Skip to content
Snippets Groups Projects
Geometry.scala 1.63 KiB
Newer Older
Martin Ring's avatar
Martin Ring committed
case class Point(
  x: Double,
  y: Double
):
  def +(that: Point) = Point(this.x + that.x, this.y + that.y)
  def unary_- : Point = Point(-x,-y)
  def -(that: Point) = this + (- that)
  def *(scalar: Double) = Point(x*scalar,y*scalar)
  def magnitude: Double = Math.sqrt(Math.pow(x,2) + Math.pow(y,2))
  def phi: Double = Math.atan2(y,x)
  def normalized: Point = Point(Math.cos(phi),Math.sin(phi))

object Point:
  def distance(a: Point, b: Point): Double = (a - b).magnitude

case class Path(
  color: String,
  width: Int,
  points: Vector[Point]
):
  def append(x: Double, y: Double): Path = {
    if (points.length > 1 && Point.distance(points.last,points.init.last) <= width * 2)
      copy(points = points.init :+ Point(x,y))
    else
      copy(points = points :+ Point(x,y))
  }

  val scale = 0.5

  lazy val controlPoints: Seq[Point] = (for (i <- 0 until points.length) yield {
    if (i == 0) {
      val p1 = points(i)
      val p2 = points(i+1)
      val tangent = p2 - p1;
      val q1 = p1 + tangent * scale;
      Seq(p1,q1)
    } else if (i == points.length - 1) {
      val p0 = points(i - 1)
      val p1 = points(i)
      val tangent = (p1 - p0);
      val q0 = p1 - tangent * scale;
      Seq(q0,p1)
    } else {
      val p0 = points(i - 1)
      val p1 = points(i)
      val p2 = points(i + 1)
      val tangent = (p2 - p0).normalized;
      val q0 = p1 - tangent * scale * (p1 - p0).magnitude;
      val q1 = p1 + tangent * scale * (p2 - p1).magnitude;
      Seq(q0,p1,q1)
    }
  }).flatten

  def hits(x: Double, y: Double): Boolean = points.exists(p => Point.distance(p,Point(x,y)) <= width)

  def isEmpty: Boolean = points.length < 2