All Downloads are FREE. Search and download functionalities are using the official Maven repository.

doodle.image.examples.Windswept.scala Maven / Gradle / Ivy

There is a newer version: 0.27.0
Show newest version
/*
 * Copyright 2015 Creative Scala
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package doodle
package image
package examples

import cats.syntax.all.*
import doodle.core.*
import doodle.random.*
import doodle.syntax.all.*

object Windswept {
  import PathElement.*

  def randomColor(meanHue: Angle) =
    for {
      hue <- Random.normal(meanHue.toDegrees, 10.0) map (_.degrees)
    } yield Color.hsl(hue, 0.8, 0.6)

  val leafGreen: Random[Color] = randomColor(80.degrees)
  val emeraldGreen: Random[Color] = randomColor(110.degrees)

  def square(fill: Color): Image =
    Image.rectangle(25, 25) fillColor fill strokeWidth 0.0

  def randomSquare(fill: Random[Color]): Random[Image] =
    (fill, fill, fill, fill) mapN { (f1, f2, f3, f4) =>
      (square(f1) beside square(f2)) above (square(f3) beside square(f4))
    }

  val leafSquare = randomSquare(leafGreen)
  val emeraldSquare = randomSquare(emeraldGreen)

  def randomColumn(
      one: Random[Image],
      two: Random[Image],
      three: Random[Image],
      four: Random[Image],
      five: Random[Image]
  ): Random[Image] =
    (one, two, three, four, five) mapN { _ above _ above _ above _ above _ }

  val columnOne =
    randomColumn(
      emeraldSquare,
      emeraldSquare,
      emeraldSquare,
      emeraldSquare,
      emeraldSquare
    )

  val columnTwo =
    randomColumn(
      emeraldSquare,
      emeraldSquare,
      leafSquare,
      emeraldSquare,
      emeraldSquare
    )

  val columnThree =
    randomColumn(
      emeraldSquare,
      leafSquare,
      emeraldSquare,
      leafSquare,
      emeraldSquare
    )

  val columnFour =
    randomColumn(
      leafSquare,
      emeraldSquare,
      emeraldSquare,
      emeraldSquare,
      leafSquare
    )

  val singleRepeat: Random[Image] =
    (
      columnOne,
      columnTwo,
      columnThree,
      columnFour,
      columnThree,
      columnTwo
    ) mapN {
      _ beside _ beside _ beside _ beside _ beside _
    }

  val pattern: Random[Image] =
    (singleRepeat, singleRepeat, singleRepeat, columnOne) mapN {
      _ beside _ beside _ beside _
    }

  def randomPoint(x: Random[Double], y: Random[Double]): Random[Point] =
    (x, y) mapN { (x, y) =>
      Point.cartesian(x, y)
    }

  def normalPoint(point: Point, stdDev: Double = 50): Random[Point] =
    randomPoint(Random.normal(point.x, stdDev), Random.normal(point.y, stdDev))

  def randomBezier(
      cp1: Point,
      cp2: Point,
      end: Point,
      stdDev: Double
  ): Random[BezierCurveTo] = {
    (
      normalPoint(cp1, stdDev),
      normalPoint(cp2, stdDev),
      normalPoint(end, stdDev)
    ) mapN { (cp1, cp2, end) =>
      BezierCurveTo(cp1, cp2, end)
    }
  }

  val tendril: Random[Image] =
    for {
      stroke <- randomColor(25.degrees) map (_.fadeOut(0.4.normalized))
      offset = -425
      start = Point.cartesian(offset.toDouble, 0)
      end <- Random.normal(800, 30)
    } yield Image.path(
      OpenPath.empty.moveTo(start).lineTo(Point.cartesian(end + offset, 0))
    ) strokeColor stroke strokeWidth 1.0

  val tendrils: Random[Image] =
    (-50 to 50).foldLeft(tendril) { (randomImage, i) =>
      for {
        accum <- randomImage
        t <- tendril
      } yield (t.at(0, i.toDouble)).on(accum)
    }

  def image =
    (for {
      t1 <- tendrils
      t2 <- tendrils
      t3 <- tendrils
      p1 <- pattern
      p2 <- pattern
      p3 <- pattern
    } yield (t1 on p1) above (t2 on p2) above (t3 on p3)).run
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy