Circles of given radius through two points: Difference between revisions

Line 1,484:
No circles can be drawn through (0.1234, 0.9876)</pre>
 
=={{header|Scala}}==
<lang scala>import org.scalatest.FunSuite
import math._
 
case class V2(x: Double, y: Double) {
val distance = hypot(x, y)
def /(other: V2) = V2((x+other.x) / 2.0, (y+other.y) / 2.0)
def -(other: V2) = V2(x-other.x,y-other.y)
override def equals(other: Any) = other match {
case p: V2 => abs(x-p.x) < 0.0001 && abs(y-p.y) < 0.0001
case _ => false
}
override def toString = f"($x%.4f, $y%.4f)"
}
 
case class Circle(center: V2, radius: Double)
 
class PointTest extends FunSuite {
println(" p1 p2 r result")
Seq(
(V2(0.1234, 0.9876), V2(0.8765, 0.2345), 2.0, Seq(Circle(V2(1.8631, 1.9742), 2.0), Circle(V2(-0.8632, -0.7521), 2.0))),
(V2(0.0000, 2.0000), V2(0.0000, 0.0000), 1.0, Seq(Circle(V2(0.0, 1.0), 1.0))),
(V2(0.1234, 0.9876), V2(0.1234, 0.9876), 2.0, "coincident points yields infinite circles"),
(V2(0.1234, 0.9876), V2(0.8765, 0.2345), 0.5, "radius is less then the distance between points"),
(V2(0.1234, 0.9876), V2(0.1234, 0.9876), 0.0, "radius of zero yields no circles")
) foreach { v =>
print(s"${v._1} ${v._2} ${v._3}: ")
circles(v._1, v._2, v._3) match {
case Right(list) => println(list mkString ",")
assert(list == v._4)
case Left(error) => println(error)
assert(error === v._4)
}
}
 
def circles(p1: V2, p2: V2, radius: Double) = if (radius == 0.0) {
Left("radius of zero yields no circles")
} else if (p1 == p2) {
Left("coincident points yields infinite circles")
} else if (radius * 2 < (p1-p2).distance) {
Left("radius is less then the distance between points")
} else {
Right(circlesThruPoints(p1, p2, radius))
} ensuring { result =>
result.isLeft || result.right.get.nonEmpty
}
 
def circlesThruPoints(p1: V2, p2: V2, radius: Double): Seq[Circle] = {
val diff = p2 - p1
val d = pow(pow(radius, 2) - pow(diff.distance / 2, 2), 0.5)
val mid = p1 / p2
Seq(
Circle(V2(mid.x - d * diff.y / diff.distance, mid.y + d * diff.x / diff.distance), abs(radius)),
Circle(V2(mid.x + d * diff.y / diff.distance, mid.y - d * diff.x / diff.distance), abs(radius))).distinct
}
}</lang>
{{out}}
<pre> p1 p2 r result
(0.1234, 0.9876) (0.8765, 0.2345) 2.0: Circle((1.8631, 1.9742),2.0),Circle((-0.8632, -0.7521),2.0)
(0.0000, 2.0000) (0.0000, 0.0000) 1.0: Circle((0.0000, 1.0000),1.0)
(0.1234, 0.9876) (0.1234, 0.9876) 2.0: coincident points yields infinite circles
(0.1234, 0.9876) (0.8765, 0.2345) 0.5: radius is less then the distance between points
(0.1234, 0.9876) (0.1234, 0.9876) 0.0: radius of zero yields no circlesEmpty test suite.</pre>
=={{header|Seed7}}==
<lang seed7>$ include "seed7_05.s7i";
Anonymous user