RosettaCodeData/Task/Ray-casting-algorithm/Scala/ray-casting-algorithm.scala

48 lines
2.0 KiB
Scala

package scala.ray_casting
case class Edge(_1: (Double, Double), _2: (Double, Double)) {
import Math._
import Double._
def raySegI(p: (Double, Double)): Boolean = {
if (_1._2 > _2._2) return Edge(_2, _1).raySegI(p)
if (p._2 == _1._2 || p._2 == _2._2) return raySegI((p._1, p._2 + epsilon))
if (p._2 > _2._2 || p._2 < _1._2 || p._1 > max(_1._1, _2._1))
return false
if (p._1 < min(_1._1, _2._1)) return true
val blue = if (abs(_1._1 - p._1) > MinValue) (p._2 - _1._2) / (p._1 - _1._1) else MaxValue
val red = if (abs(_1._1 - _2._1) > MinValue) (_2._2 - _1._2) / (_2._1 - _1._1) else MaxValue
blue >= red
}
final val epsilon = 0.00001
}
case class Figure(name: String, edges: Seq[Edge]) {
def contains(p: (Double, Double)) = edges.count(_.raySegI(p)) % 2 != 0
}
object Ray_casting extends App {
val figures = Seq(Figure("Square", Seq(((0.0, 0.0), (10.0, 0.0)), ((10.0, 0.0), (10.0, 10.0)),
((10.0, 10.0), (0.0, 10.0)),((0.0, 10.0), (0.0, 0.0)))),
Figure("Square hole", Seq(((0.0, 0.0), (10.0, 0.0)), ((10.0, 0.0), (10.0, 10.0)),
((10.0, 10.0), (0.0, 10.0)), ((0.0, 10.0), (0.0, 0.0)), ((2.5, 2.5), (7.5, 2.5)),
((7.5, 2.5), (7.5, 7.5)),((7.5, 7.5), (2.5, 7.5)), ((2.5, 7.5), (2.5, 2.5)))),
Figure("Strange", Seq(((0.0, 0.0), (2.5, 2.5)), ((2.5, 2.5), (0.0, 10.0)),
((0.0, 10.0), (2.5, 7.5)), ((2.5, 7.5), (7.5, 7.5)), ((7.5, 7.5), (10.0, 10.0)),
((10.0, 10.0), (10.0, 0.0)), ((10.0, 0.0), (2.5, 2.5)))),
Figure("Exagon", Seq(((3.0, 0.0), (7.0, 0.0)), ((7.0, 0.0), (10.0, 5.0)), ((10.0, 5.0), (7.0, 10.0)),
((7.0, 10.0), (3.0, 10.0)), ((3.0, 10.0), (0.0, 5.0)), ((0.0, 5.0), (3.0, 0.0)))))
val points = Seq((5.0, 5.0), (5.0, 8.0), (-10.0, 5.0), (0.0, 5.0), (10.0, 5.0), (8.0, 5.0), (10.0, 10.0))
println("points: " + points)
for (f <- figures) {
println("figure: " + f.name)
println(" " + f.edges)
println("result: " + (points map f.contains))
}
private implicit def to_edge(p: ((Double, Double), (Double, Double))): Edge = Edge(p._1, p._2)
}