Exploring Analyic Geometry with Mathematica®

Home Contents Commands Packages Explorations Reference
Tour Lines Circles Conics Analysis Tangents

D2DTangentLines2D

The package D2DTangentLines2D provides functions for computing lines that are tangent to curves using a variety of defining conditions.

Initialization

BeginPackage["D2DTangentLines2D`", {"D2DCircle2D`", "D2DConic2D`", "D2DEllipse2D`", "D2DEquations2D`", "D2DExpressions2D`", "D2DGeometry2D`", "D2DHyperbola2D`", "D2DLine2D`", "D2DMaster2D`", "D2DParabola2D`", "D2DPoint2D`", "D2DQuadratic2D`", "D2DSegment2D`", "D2DSolve2D`", "D2DTangentPoints2D`", "D2DTransform2D`"}];

D2DTangentLines2D::usage=
   "D2DTangentLines2D is a package for constructing tangent lines and line segments.";

TangentEquation2D::usage=
   "TangentEquation2D[line, quad] constructs an equation involving the coefficients of a line and a quadratic constraining the line to be tangent to the quadratic.";

TangentLines2D::usage=
   "TangentLines2D[point, curve] constructs a list of lines through a point and tangent to a second-degree curve; TangentLines2D[line, curve, Parallel2D] constructs a list of tangent lines parallel to a given line;  TangentLines2D[line, curve, Perpendicular2D] constructs a list of tangent lines perpendicular to a given line; TangentLines2D[curve, curve] constructs a list of lines tangent to two curves.";

TangentSegments2D::usage=
   "TangentSegments2D[curve,curve] constructs a list of line segments tangent to two curves.";

Begin["`Private`"];

Tangent Equation

Line Tangent to a Quadratic

Format: TangentEquation2D[line,quad]
Forms an equation between the coefficients of a line and a quadratic constraining the line to be tangent to the quadratic.

TangentEquation2D[Line2D[p_,q_,r_],
                  Quadratic2D[a_,b_,c_,d_,e_,f_]] :=
   ((4*c*f-e^2)*p^2+(4*a*f-d^2)*q^2+(4*a*c-b^2)*r^2+
   2*(b*d-2*a*e)*q*r+2*(b*e-2*c*d)*p*r+2*(d*e-2*b*f)*p*q)==0;

Line Construction

Lines Through a Point Tangent to a Circle

Format: TangentLines2D[point,circle]
Constructs a list containing up to two lines through a point and tangent to a circle.

TangentLines2D[Point2D[{x1_,y1_}],Circle2D[{h2_,k2_},r2_]] :=
   Union[TangentLine$2D[{x1,y1},0,{h2,k2},r2,1]];

Lines Through a Point Tangent to a Curve

Format: TangentLines2D[point,curve]
Constructs a list containing up to two lines through a point and tangent to a curve or quadratic.

TangentLines2D[P1:Point2D[{x1_,y1_}],crv2_] :=
   Module[{pts},
      pts=TangentPoints2D[P1,crv2];
      Which[
         pts=={},        {},
         Length[pts]==1, {Line2D[P1,crv2]},
         True,           Map[Line2D[P1,#]&,pts]] ] /;
Is2D[crv2,{Ellipse2D,Hyperbola2D,Parabola2D,Quadratic2D}];

Parallel or Perpendicular Tangent Lines

Format: TangentLines2D[line,curve,Parallel2D | Perpendicular2D]
Constructs a list containing up to two lines which are parallel or perpendicular to a given line and tangent to a conic curve or quadratic.  If the Parallel2D | Perpendicular2D keyword is omitted, the default is Parallel2D.

TangentLines2D[L:Line2D[p_,q_,r_],Q:Quadratic2D[a_,b_,c_,d_,e_,f_],
               Parallel2D] :=
   Module[{z,eq1,R,ans},
      z=R*(-b^2+4*a*c)+q*(b*d-2*a*e)+p*(-2*c*d+b*e);
      If[IsZero2D[z],{},
         eq1=TangentEquation2D[Line2D[p,q,R],Q];
         ans=Select[Solve2D[{eq1},{R}],
                    Not[IsComplex2D[R /. #]]&];
         Map[Line2D[p,q,(R /. #)]&,ans]] ];

TangentLines2D[L:Line2D[a_,b_,c_],crv_,Parallel2D] :=
   TangentLines2D[L,Quadratic2D[crv],Parallel2D] /;
Is2D[crv,{Circle2D,Ellipse2D,Hyperbola2D,Parabola2D}];

TangentLines2D[L:Line2D[a_,b_,c_],crv_] :=
   TangentLines2D[L,crv,Parallel2D] /;
Is2D[crv,{Circle2D,Ellipse2D,Hyperbola2D,Parabola2D,Quadratic2D}];

TangentLines2D[Line2D[a_,b_,c_],crv_,Perpendicular2D] :=
   TangentLines2D[Line2D[-b,a,c],crv,Parallel2D] /;
Is2D[crv,{Circle2D,Ellipse2D,Hyperbola2D,Parabola2D,Quadratic2D}];

Lines Tangent to Two Circles

Format: TangentLines2D[circle,circle]
Constructs a list containing up to four lines which are tangent to two circles.  The first two lines in the list are the external tangents; the last two lines (if present) are the internal tangents.  The private function TangentLine$2D implements the mathematics.

TangentLines2D[Circle2D[{h1_,k1_},r1_],Circle2D[{h2_,k2_},r2_]] :=
   Flatten[{Map[Union[TangentLine$2D[{h1,k1},r1,{h2,k2},r2,#]]&,{-1,1}]}];

TangentLine$2D[{h1_,k1_},r1_,{h2_,k2_},r2_,s_] :=
  Module[{H=h1-h2,K=k1-k2,R=r1+s*r2,L,A2,B2,C2,lns,sv1,sv2},
    L=H^2+K^2;
    A2=A1*H-B1*K; B2=B1*H+A1*K; C2 =L*r1-h1*A2-k1*B2;
    sv1=Head[Line2D::imaginary];Off[Line2D::imaginary];
    sv2=Head[Line2D::invalid];Off[Line2D::invalid];
    lns=Map[(Line2D[A2, B2, C2] /. #)&,
            {{A1->R, B1-> If[IsZero2D[L-R^2],0,Sqrt[L-R^2]]},
             {A1->R, B1->-If[IsZero2D[L-R^2],0,Sqrt[L-R^2]]}}];
    If[sv1===String,On[Line2D::imaginary]];
    If[sv2===String,On[Line2D::invalid]];
    Select[lns,IsValid2D]];

Lines Tangent to Two Quadratics

Format: TangentLines2D[quad,quad]
Constructs a list containing up to four lines tangent to two quadratics.  The private function TanLn$2D computes the candidate tangent lines, and the private function DeleteCoincident$2D removes coincident solutions.

TanLn$2D[Q1:Quadratic2D[a1_,b1_,c1_,d1_,e1_,f1_],
          Q2:Quadratic2D[a2_,b2_,c2_,d2_,e2_,f2_]] :=
   Module[{L,p,q,r,ans,lns,svMsg1,svMsg2},
      L=Line2D[p,q,r];
      ans=Solve2D[{TangentEquation2D[L,Q1],
                   TangentEquation2D[L,Q2],
                   p^2+q^2==1},{p,q,r}];
      svMsg1=Head[Line2D::imaginary];Off[Line2D::imaginary];
      svMsg2=Head[Line2D::invalid];Off[Line2D::invalid];
      lns=Map[(L /. #)&,ans];
      If[svMsg1===String,On[Line2D::imaginary]];
      If[svMsg2===String,On[Line2D::invalid]];
      Select[lns,IsValid2D] ];

DeleteCoincident$2D[{s1___,
      L1:Line2D[a1_,b1_,c1_],s2___,
      L2:Line2D[a2_,b2_,c2_],s3___}]:=
   DeleteCoincident$2D[{s1,L1,s2,s3}] /;
IsCoincident2D[L1,L2];

DeleteCoincident$2D[lns_List]:=lns;

TangentLines2D[Q1:Quadratic2D[a1_,b1_,c1_,d1_,e1_,f1_],
               Q2:Quadratic2D[a2_,b2_,c2_,d2_,e2_,f2_]] :=
   If[IsCoincident2D[Q1,Q2],{},
      DeleteCoincident$2D[TanLn$2D[Q1,Q2]]];

Lines Tangent to Two Conics

Format: TangentLines2D[curve,curve]
Constructs a list containing up to four lines tangent to two conic curves (circles, ellipses, hyperbolas, parabolas or quadratics).

TangentLines2D[crv1_,crv2_] :=
   Module[{Q1,Q2},
      Q1=If[Is2D[crv1,{Quadratic2D}],crv1,Quadratic2D[crv1]];
      Q2=If[Is2D[crv2,{Quadratic2D}],crv2,Quadratic2D[crv2]];
      TangentLines2D[Q1,Q2]] /;
Is2D[crv1,{Circle2D,Ellipse2D,Hyperbola2D,Parabola2D,Quadratic2D}] &&
Is2D[crv2,{Circle2D,Ellipse2D,Hyperbola2D,Parabola2D,Quadratic2D}];

Line Segments Tangent to Two Curves

Format: TangentSegments2D[curve,curve]
Constructs a list containing up to four line segments tangent to two curves (circles, ellipses, hyperbolas, parabola or quadratics).

TangentSegments2D[crv1_,crv2_] :=
   Module[{lns,svMsg1,svMsg2},
      lns=TangentLines2D[crv1,crv2];
      svMsg1=Head[Segment2D::imaginary];Off[Segment2D::imaginary];
      svMsg2=Head[Segment2D::invalid];Off[Segment2D::invalid];
      lns=Map[Segment2D[Point2D[#,crv1],Point2D[#,crv2]]&,lns];
      If[svMsg1===String,On[Segment2D::imaginary]];
      If[svMsg2===String,On[Segment2D::invalid]];
      Select[lns,IsValid2D] ] /;
Is2D[crv1,{Circle2D,Ellipse2D,Hyperbola2D,Parabola2D,Quadratic2D}] &&
Is2D[crv2,{Circle2D,Ellipse2D,Hyperbola2D,Parabola2D,Quadratic2D}];

Epilogue

End[ ]; (* end of "`Private" *)
EndPackage[ ]; (* end of "D2DTangentLines2D`" *)


Copyright © 1999-2007 Donald L. Vossler, Descarta2D Publishing
www.Descarta2D.com