Task: Circles of given radius through two points



C#: using System;
public class CirclesOfGivenRadiusThroughTwoPoints
{
    public static void Main()
    {
        double[][] values = new double[][] {
            new [] { 0.1234, 0.9876, 0.8765, 0.2345,   2 },
            new [] { 0.0,       2.0,    0.0,    0.0,   1 },
            new [] { 0.1234, 0.9876, 0.1234, 0.9876,   2 },
            new [] { 0.1234, 0.9876, 0.8765, 0.2345, 0.5 },
            new [] { 0.1234, 0.9876, 0.1234, 0.9876,   0 }
        };
		
        foreach (var a in values) {
            var p = new Point(a[0], a[1]);
            var q = new Point(a[2], a[3]);
            Console.WriteLine($"Points {p} and {q} with radius {a[4]}:");
            try {
                var centers = FindCircles(p, q, a[4]);
                Console.WriteLine("\t" + string.Join(" and ", centers));
            } catch (Exception ex) {
                Console.WriteLine("\t" + ex.Message);
            }
        }
    }
	
    static Point[] FindCircles(Point p, Point q, double radius) {
        if(radius < 0) throw new ArgumentException("Negative radius.");
        if(radius == 0) {
            if(p == q) return new [] { p };
            else throw new InvalidOperationException("No circles.");
        }
        if (p == q) throw new InvalidOperationException("Infinite number of circles.");
		
        double sqDistance = Point.SquaredDistance(p, q);
        double sqDiameter = 4 * radius * radius;
        if (sqDistance > sqDiameter) throw new InvalidOperationException("Points are too far apart.");
		
        Point midPoint = new Point((p.X + q.X) / 2, (p.Y + q.Y) / 2);
        if (sqDistance == sqDiameter) return new [] { midPoint };
		
        double d = Math.Sqrt(radius * radius - sqDistance / 4);
        double distance = Math.Sqrt(sqDistance);
        double ox = d * (q.X - p.X) / distance, oy = d * (q.Y - p.Y) / distance;
        return new [] {
            new Point(midPoint.X - oy, midPoint.Y + ox),
            new Point(midPoint.X + oy, midPoint.Y - ox)
        };
    }
	
    public struct Point
    {
        public Point(double x, double y) : this() {
            X = x;
            Y = y;
        }
	
        public double X { get; }
        public double Y { get; }
	
        public static bool operator ==(Point p, Point q) => p.X == q.X && p.Y == q.Y;
        public static bool operator !=(Point p, Point q) => p.X != q.X || p.Y != q.Y;
	
        public static double SquaredDistance(Point p, Point q) {
            double dx = q.X - p.X, dy = q.Y - p.Y;
            return dx * dx + dy * dy;
        }
		
        public override string ToString() => $"({X}, {Y})";
		
    }	
}


Go: package main

import (
    "fmt"
    "math"
)

var (
    Two  = "Two circles."
    R0   = "R==0.0 does not describe circles."
    Co   = "Coincident points describe an infinite number of circles."
    CoR0 = "Coincident points with r==0.0 describe a degenerate circle."
    Diam = "Points form a diameter and describe only a single circle."
    Far  = "Points too far apart to form circles."
)

type point struct{ x, y float64 }

func circles(p1, p2 point, r float64) (c1, c2 point, Case string) {
    if p1 == p2 {
        if r == 0 {
            return p1, p1, CoR0
        }
        Case = Co
        return
    }
    if r == 0 {
        return p1, p2, R0
    }
    dx := p2.x - p1.x
    dy := p2.y - p1.y
    q := math.Hypot(dx, dy)
    if q > 2*r {
        Case = Far
        return
    }
    m := point{(p1.x + p2.x) / 2, (p1.y + p2.y) / 2}
    if q == 2*r {
        return m, m, Diam
    }
    d := math.Sqrt(r*r - q*q/4)
    ox := d * dx / q
    oy := d * dy / q
    return point{m.x - oy, m.y + ox}, point{m.x + oy, m.y - ox}, Two
}

var td = []struct {
    p1, p2 point
    r      float64
}{
    {point{0.1234, 0.9876}, point{0.8765, 0.2345}, 2.0},
    {point{0.0000, 2.0000}, point{0.0000, 0.0000}, 1.0},
    {point{0.1234, 0.9876}, point{0.1234, 0.9876}, 2.0},
    {point{0.1234, 0.9876}, point{0.8765, 0.2345}, 0.5},
    {point{0.1234, 0.9876}, point{0.1234, 0.9876}, 0.0},
}

func main() {
    for _, tc := range td {
        fmt.Println("p1: ", tc.p1)
        fmt.Println("p2: ", tc.p2)
        fmt.Println("r: ", tc.r)
        c1, c2, Case := circles(tc.p1, tc.p2, tc.r)
        fmt.Println("  ", Case)
        switch Case {
        case CoR0, Diam:
            fmt.Println("   Center: ", c1)
        case Two:
            fmt.Println("   Center 1: ", c1)
            fmt.Println("   Center 2: ", c2)
        }
        fmt.Println()
    }
}