Circles of given radius through two points: Difference between revisions

Content added Content deleted
(Add Swift)
Line 3,383: Line 3,383:
2 | .9876 .9876 |
2 | .9876 .9876 |
+-----------------+</lang>
+-----------------+</lang>

=={{header|Swift}}==

{{trans|F#}}

<lang swift>import Foundation

struct Point: Equatable {
var x: Double
var y: Double
}

struct Circle {
var center: Point
var radius: Double

public static func circleBetween(
_ p1: Point,
_ p2: Point,
withRadius radius: Double
) -> (Circle, Circle?)? {
func applyPoint(_ p1: Point, _ p2: Point, op: (Double, Double) -> Double) -> Point {
return Point(x: op(p1.x, p2.x), y: op(p1.y, p2.y))
}

func mul2(_ p: Point, mul: Double) -> Point {
return Point(x: p.x * mul, y: p.y * mul)
}

func div2(_ p: Point, div: Double) -> Point {
return Point(x: p.x / div, y: p.y / div)
}

func norm(_ p: Point) -> Point {
return div2(p, div: (p.x * p.x + p.y * p.y).squareRoot())
}

guard radius != 0, p1 != p2 else {
return nil
}

let diameter = 2 * radius
let pq = applyPoint(p1, p2, op: -)
let magPQ = (pq.x * pq.x + pq.y * pq.y).squareRoot()

guard diameter >= magPQ else {
return nil
}

let midpoint = div2(applyPoint(p1, p2, op: +), div: 2)
let halfPQ = magPQ / 2
let magMidC = abs(radius * radius - halfPQ * halfPQ).squareRoot()
let midC = mul2(norm(Point(x: -pq.y, y: pq.x)), mul: magMidC)
let center1 = applyPoint(midpoint, midC, op: +)
let center2 = applyPoint(midpoint, midC, op: -)

if center1 == center2 {
return (Circle(center: center1, radius: radius), nil)
} else {
return (Circle(center: center1, radius: radius), Circle(center: center2, radius: radius))
}
}
}

let testCases = [
(Point(x: 0.1234, y: 0.9876), Point(x: 0.8765, y: 0.2345), 2.0),
(Point(x: 0.0000, y: 2.0000), Point(x: 0.0000, y: 0.0000), 1.0),
(Point(x: 0.1234, y: 0.9876), Point(x: 0.1234, y: 0.9876), 2.0),
(Point(x: 0.1234, y: 0.9876), Point(x: 0.8765, y: 0.2345), 0.5),
(Point(x: 0.1234, y: 0.9876), Point(x: 0.1234, y: 0.9876), 0.0)
]

for testCase in testCases {
switch Circle.circleBetween(testCase.0, testCase.1, withRadius: testCase.2) {
case nil:
print("No ans")
case (let circle1, nil)?:
print("One ans: \(circle1)")
case (let circle1, let circle2?)?:
print("Two ans: \(circle1) \(circle2)")
}
}

</lang>

{{out}}

<pre>Two ans: Circle(center: Point(x: -0.8632118016581896, y: -0.7521118016581892), radius: 2.0) Circle(center: Point(x: 1.8631118016581893, y: 1.974211801658189), radius: 2.0)
One ans: Circle(center: Point(x: 0.0, y: 1.0), radius: 1.0)
No ans
No ans
No ans</pre>


=={{header|Tcl}}==
=={{header|Tcl}}==