But I need help on this one. Please tell me if I m wrong:
1) When the centers are located in the same point there are only two possible answers : "-1" and "0"
2) Otherwise there are 5 different cases: 0 -> 1 -> 2 -> 3 -> 4. The number of tangents depends on the distance between the centers.
I WOULD ALSO APPRECIATE SOME TESTDATA!!!
![:-?](./images/smilies/icon_confused.gif)
[pascal]
{$N+}
Program tangents;
Const eps = 0.000000001;
Type Vect = Record
X, Y : extended;
End;
Var x1,x2,y1,y2,r1,r2,L,C,l1,c1 : extended;
V,PV : Vect;
Inversed : Boolean;
P1,P2 : Vect;
Ans : array [1..5,1..5] of extended;
i,j,k,NAns : longint;
Procedure Z(e1,e2,e3,e4,e5 : extended);
Begin
Inc(NAns);
Ans[Nans,1]:=e1; Ans[Nans,2]:=e2;
Ans[Nans,3]:=e3; Ans[Nans,4]:=e4; Ans[Nans,5]:=e5;
End;
Function Dist(var v1,v2 : vect) : extended;
Begin
Dist := sqrt((v1.x-v2.x)*(v1.x-v2.x)+(v1.y-v2.y)*(v1.y-v2.y));
End;
Function D(v1, v2 : extended) : extended;
Begin
D:=abs(v1-v2);
End;
Procedure Do_Outer;
Begin
C:=(R2-R1)*r2/L;
V.X:=(x1-x2)/L; V.Y:=(Y1-Y2)/L;
PV.X:=V.Y; PV.Y:=-V.X;
P2.X:=X2+V.X*C+PV.X*sqrt(r2*r2-c*c);
P2.y:=y2+V.y*C+PV.y*sqrt(r2*r2-c*c);
P1.X:=X1+V.X*(r1/r2)*C+PV.X*sqrt(r2*r2-c*c)*(r1/r2);
P1.y:=y1+V.y*C*(r1/r2)+PV.y*sqrt(r2*r2-c*c)*(r1/r2);
IF Inversed then
Z(P2.x, P2.Y, P1.X, P1.Y, Dist(P1,P2))
Else Z(P1.x, P1.Y, P2.X, P2.Y, Dist(P1,P2));
P2.X:=X2+V.X*C-PV.X*sqrt(r2*r2-c*c);
P2.y:=y2+V.y*C-PV.y*sqrt(r2*r2-c*c);
P1.X:=X1+V.X*(r1/r2)*C-PV.X*sqrt(r2*r2-c*c)*(r1/r2);
P1.y:=y1+V.y*C*(r1/r2)-PV.y*sqrt(r2*r2-c*c)*(r1/r2);
IF Inversed then
Z(P2.x, P2.Y, P1.X, P1.Y, Dist(P1,P2))
Else Z(P1.x, P1.Y, P2.X, P2.Y, Dist(P1,P2));
End;
Procedure Do_Inner;
Begin
l1:=L*r1/(r1+r2);
c1:=r1*r1/l1;
V.x:=(X2-x1)/L; V.y:=(y2-y1)/L;
PV.X:=V.Y; PV.Y:=-V.X;
P1.X:=x1+V.X*c1+Pv.X*sqrt(r1*r1-c1*c1);
P1.Y:=y1+V.y*c1+Pv.y*sqrt(r1*r1-c1*c1);
P2.X:=x2-V.X*c1*(r2/r1)-Pv.X*sqrt(r1*r1-c1*c1)*(r2/r1);
P2.Y:=Y2-V.Y*c1*(r2/r1)-Pv.Y*sqrt(r1*r1-c1*c1)*(r2/r1);
IF Inversed then
Z(P2.x, P2.Y, P1.X, P1.Y, Dist(P1,P2))
Else Z(P1.x, P1.Y, P2.X, P2.Y, Dist(P1,P2));
P1.X:=x1+V.X*c1-Pv.X*sqrt(r1*r1-c1*c1);
P1.Y:=y1+V.y*c1-Pv.y*sqrt(r1*r1-c1*c1);
P2.X:=x2-V.X*c1*(r2/r1)+Pv.X*sqrt(r1*r1-c1*c1)*(r2/r1);
P2.Y:=Y2-V.Y*c1*(r2/r1)+Pv.Y*sqrt(r1*r1-c1*c1)*(r2/r1);
IF Inversed then
Z(P2.x, P2.Y, P1.X, P1.Y, Dist(P1,P2))
Else Z(P1.x, P1.Y, P2.X, P2.Y, Dist(P1,P2));
End;
Begin
NAns:=0;
While true do Begin
For i:=1 to NAns do
For j:=1 to NAns-1 do
If ((Ans[j,1]-Ans[j+1,1]>Eps) OR ((D(Ans[j,1],Ans[j+1,1])<Eps) AND (Ans[j,2]>Ans[j+1,2]))) then
For k:=1 to 5 do Begin
l:=Ans[j,k]; Ans[j,k]:=Ans[j+1,k]; Ans[j+1,k]:=l;
End;
For i:=1 to NAns do Begin
For j:=1 to 5 do Begin
Write(Ans[i,j]:0:5);
write(' ');
End;
Writeln;
End;
NAns:=0;
Read(x1, y1, r1, x2, y2, r2);
If (D(x1,0.0)+D(x2,0.0)+D(y1,0.0)+D(y2,0.0)+D(r1,0.0)+D(r2,0.0) < eps )
Then Halt(0);
Inversed := False;
If R1>R2 then Begin
Inversed := TRUE;
L:=r1; r1:=r2; r2:=l; L:=x1; x1:=x2; x2:=l; L:=y1; y1:=y2; y2:=l;
End;
L:=sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
If (L<Eps) then Begin
If D(r1,r2)<eps then Begin writeln('-1'); Continue; End
Else Begin Writeln('0'); Continue; End;
End;
{I}
If (R2-L-R1) > Eps Then Begin Writeln('0'); Continue; End;
{II}
If (R1+L-R2<Eps) then Begin
Writeln('1');
V.x:=(x1-x2)*(R2-R1)/L; V.y:=(y1-y2)*(R2-R1)/L;
Z(x1+V.x, y1+V.Y, x1+V.x, y1+V.Y, 0.0);
Continue;
End;
{III}
If (R1+R2-L>Eps) Then Begin
Writeln('2');
Do_Outer;
Continue;
End;
{IV}
If (R1+R2-L>-Eps) then Begin
Writeln('3');
V.x:=(x2-x1)*r1/(r1+r2); V.y:=(y2-y1)*r1/(r1+r2);
z(x1+V.x, y1+V.Y, x1+V.x, y1+V.Y, 0.0 );
Do_Outer;
Continue;
End;
{V}
If (L-R1-R2>Eps) Then Begin
Writeln('4');
Do_Outer;
Do_Inner;
Continue;
End;
End;
End.
[/pascal]