
Given two points on a plane and a radius, usually two circles of given radius can be drawn through the points.

Exceptions

 r==0.0 should be treated as never describing circles (except in the case where the points are coincident).
 If the points are coincident then an infinite number of circles with the point on their circumference can be drawn, unless r==0.0 as well which then collapses the circles to a point.
 If the points form a diameter then return two identical circles or return a single circle, according to which is the most natural mechanism for the implementation language.
 If the points are too far apart then no circles can be drawn.


Task detail

 Write a function/subroutine/method/... that takes two points and a radius and returns the two circles through those points, or some indication of special cases where two, possibly equal, circles cannot be returned.
 Show here the output for the following inputs:
      p1                p2           r
0.1234, 0.9876    0.8765, 0.2345    2.0
0.0000, 2.0000    0.0000, 0.0000    1.0
0.1234, 0.9876    0.1234, 0.9876    2.0
0.1234, 0.9876    0.8765, 0.2345    0.5
0.1234, 0.9876    0.1234, 0.9876    0.0



Related task

   Total circles area.


See also

   Finding the Center of a Circle from 2 Points and Radius from Math forum @ Drexel


$ include "seed7_05.s7i";
  include "float.s7i";
  include "math.s7i";
 
const type: point is new struct
    var float: x is 0.0;
    var float: y is 0.0;
  end struct;
 
const func point: point (in float: x, in float: y) is func
  result
    var point: aPoint is point.value;
  begin
    aPoint.x := x;
    aPoint.y := y;
  end func;
 
const func float: distance (in point: p1, in point: p2) is
  return sqrt((p1.x - p2.x) ** 2 + (p1.y - p2.y) ** 2);
 
const proc: findCircles (in point: p1, in point: p2, in float: radius) is func
  local
    var float: separation is 0.0;
    var float: mirrorDistance is 0.0;
  begin
    separation := distance(p1, p2);
    if separation = 0.0 then
      if radius = 0.0 then
        write("Radius of zero. No circles can be drawn through (");
      else
        write("Infinitely many circles can be drawn through (");
      end if;
      writeln(p1.x digits 4 <& ", " <& p1.y digits 4 <& ")");
    elsif separation = 2.0 * radius then
      writeln("Given points are opposite ends of a diameter of the circle with center (" <&
              (p1.x + p2.x) / 2.0 digits 4 <& ", " <& (p1.y + p2.y) / 2.0 digits 4 <& ") and radius " <&
              radius digits 4); 
    elsif separation > 2.0 * radius then
      writeln("Given points are farther away from each other than a diameter of a circle with radius " <&
              radius digits 4);
    else
      mirrorDistance := sqrt(radius ** 2 - (separation / 2.0) ** 2);
      writeln("Two circles are possible.");
      writeln("Circle C1 with center (" <&
              (p1.x + p2.x) / 2.0 + mirrorDistance*(p1.y - p2.y) / separation digits 4 <& ", " <&
              (p1.y + p2.y) / 2.0 + mirrorDistance*(p2.x - p1.x) / separation digits 4 <& "), radius " <&
              radius digits 4);
      writeln("Circle C2 with center (" <&
              (p1.x + p2.x) / 2.0 - mirrorDistance*(p1.y - p2.y) / separation digits 4 <& ", " <&
              (p1.y + p2.y) / 2.0 - mirrorDistance*(p2.x - p1.x) / separation digits 4 <& "), radius " <&
              radius digits 4);
    end if;
  end func;
 
const proc: main is func
  local
    const array array float: cases is [] (
        [] (0.1234, 0.9876, 0.8765, 0.2345, 2.0),
        [] (0.0000, 2.0000, 0.0000, 0.0000, 1.0),
        [] (0.1234, 0.9876, 0.1234, 0.9876, 2.0),
        [] (0.1234, 0.9876, 0.8765, 0.2345, 0.5),
        [] (0.1234, 0.9876, 0.1234, 0.9876, 0.0));
    var integer: index is 0;
  begin
    for index range 1 to 5 do
      writeln("Case " <& index <& ":");
      findCircles(point(cases[index][1], cases[index][2]),
                  point(cases[index][3], cases[index][4]), cases[index][5]);
    end for;
  end func;