Exploring Analyic Geometry with Mathematica®

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

D2DConicArc2D

The package D2DConicArc2D implements the ConicArc2D object.

Initialization

BeginPackage["D2DConicArc2D`",{"D2DCircle2D`", "D2DEllipse2D`", "D2DEquations2D`", "D2DExpressions2D`", "D2DGeometry2D`", "D2DHyperbola2D`", "D2DIntersect2D`", "D2DLine2D`", "D2DLoci2D`", "D2DMaster2D`", "D2DNumbers2D`", "D2DParabola2D`", "D2DPoint2D`", "D2DQuadratic2D`", "D2DSketch2D`", "D2DTransform2D`"}];

D2DConicArc2D::usage=
   "D2DConicArc2D is a package providing the conic arc object.";

Apex2D::usage=
   "Apex2D is a keyword used in Point2D[cnarc,Apex2D] to construct the apex control point of a conic arc.";

ConicArc2D::usage=
   "ConicArc2D[{x0,y0},{xA,yA},{x1,y1},p] is the standard form of conic arc with start point (x0,y0), end point (x1,y1), apex point (xA,yA) and projective discriminant 'p'.";

Rho2D::usage=
   "Rho2D[cnarc] returns the rho value of a conic arc; 0<rho<1/2 is an ellipse; rho=1/2 is a parabola; 1/2<rho<1 is a hyperbola.";

Begin["`Private`"];

Description

Representation

Format: ConicArc2D[{"D2DConicArc2D_1.gif","D2DConicArc2D_2.gif"},{"D2DConicArc2D_3.gif","D2DConicArc2D_4.gif"},{"D2DConicArc2D_5.gif","D2DConicArc2D_6.gif"},ρ]
Standard representation of a conic arc in Descarta2D.  The first and third arguments are the coordinates of the start and end points of the conic arc, respectively.  The second argument is the coordinates of the apex point of the conic arc (the apex point is the intersection of the start/end point tangents).  The fourth argument is a scalar representing the rho value of the conic arc (0<ρ<1/2, ellipse; ρ=1/2, parabola; 1/2<ρ<1, hyperbola).

Equation

Format: Quadratic2D[cnarc]
Constructs a quadratic representing the equation of the curve associated with a conic arc.

Quadratic2D[ConicArc2D[{x0_,y0_},{xA_,yA_},{x1_,y1_},p_]] :=
   Module[{eqn,a,b,k,x,y},
      eqn=a*b==k*(1-a-b)^2 /.
         {k->(1-p)^2/(4*p^2),
          a->(( y-yA)*(x1-xA)-( x-xA)*(y1-yA))/
             ((y0-yA)*(x1-xA)-(x0-xA)*(y1-yA)),
          b->(( y-yA)*(x0-xA)-( x-xA)*(y0-yA))/
             ((y1-yA)*(x0-xA)-(x1-xA)*(y0-yA))};
      Quadratic2D[eqn,{x,y}] ];
      

Evaluation

Format: ConicArc2D[{"D2DConicArc2D_7.gif","D2DConicArc2D_8.gif"},{"D2DConicArc2D_9.gif","D2DConicArc2D_10.gif"},{"D2DConicArc2D_11.gif","D2DConicArc2D_12.gif"},ρ][t]
Evaluates a conic arc at a parameter, t, and returns a list of coordinates {x,y}.  Parameter values in the range 0≤t≤1 cover the complete span of the conic arc.

ConicArc2D[p0:{x0_,y0_},pA:{xA_,yA_},p1:{x1_,y1_},p_][t_?IsScalar2D] :=
   Module[{b0,b1,b2},
      b0=(1-t)^2; b1=2*t*(1-t); b2=t^2;
      (b0*(1-p)*p0+b1*p*pA+b2*(1-p)*p1)/(b0*(1-p)+b1*p+b2*(1-p))];

Graphics

Provides graphics primitives for a conic arc by extending the Mathematica Display command. Executed when the package is loaded.

SetDisplay2D[
   ConicArc2D[{x0_,y0_},{xA_,yA_},
              {x1_,y1_},p_][{t1_?IsScalar2D,t2_?IsScalar2D}],
   MakePrimitives2D[
      ConicArc2D[{x0,y0},{xA,yA},{x1,y1},p],{t1,t2}] ];

SetDisplay2D[
   ConicArc2D[{x0_,y0_},{xA_,yA_},{x1_,y1_},p_],
   MakePrimitives2D[
      ConicArc2D[{x0,y0},{xA,yA},{x1,y1},p],{0,1}] ];

Validation

Format: ConicArc2D[{"D2DConicArc2D_13.gif","D2DConicArc2D_14.gif"},{"D2DConicArc2D_15.gif","D2DConicArc2D_16.gif"},{"D2DConicArc2D_17.gif","D2DConicArc2D_18.gif"},ρ]
Detects a conic arc with imaginary arguments and returns the $Failed symbol.  If the imaginary parts are insignificant, they are removed.

ConicArc2D::imaginary=
   "An invalid conic arc of the form 'ConicArc2D[`1`, `2`, `3`, `4`]' has been detected; the arguments cannot be imaginary.";

ConicArc2D[p0:{x0_,y0_},pA:{xA_,yA_},p1:{x1_,y1_},p_] :=
   (ConicArc2D @@ ChopImaginary2D[ConicArc$2D[p0,pA,p1,p]]) /;
(FreeQ[{p0,pA,p1,p},_Pattern] && IsTinyImaginary2D[{p0,pA,p1,p}]);

ConicArc2D[p0:{x0_,y0_},pA:{xA_,yA_},p1:{x1_,y1_},p_] :=
   (Message[ConicArc2D::imaginary,p0,pA,p1,p];$Failed) /;
(FreeQ[{p0,pA,p1,p},_Pattern] && IsComplex2D[{p0,pA,p1,p},0]);

Format: ConicArc2D[{"D2DConicArc2D_19.gif","D2DConicArc2D_20.gif"},{"D2DConicArc2D_21.gif","D2DConicArc2D_22.gif"},{"D2DConicArc2D_23.gif","D2DConicArc2D_24.gif"},ρ]
Detects a conic arc with collinear control points and returns the $Failed symbol.

ConicArc2D::points=
   "An invalid conic arc of the form 'ConicArc2D[`1`, `2`, `3`, `4`]' has been detected; the control points cannot be collinear.";

ConicArc2D[p0:{x0_,y0_},pA:{xA_,yA_},p1:{x1_,y1_},p_] :=
   (Message[ConicArc2D::points,p0,pA,p1,p];$Failed) /;
(FreeQ[{p0,pA,p1,p},_Pattern] &&
IsCollinear2D[Point2D[p0],Point2D[pA],Point2D[p1]]);

Format: ConicArc2D[{"D2DConicArc2D_25.gif","D2DConicArc2D_26.gif"},{"D2DConicArc2D_27.gif","D2DConicArc2D_28.gif"},{"D2DConicArc2D_29.gif","D2DConicArc2D_30.gif"},ρ]
Detects a conic arc with an invalid ρ value and returns the $Failed symbol.

ConicArc2D::rho=
   "An invalid conic arc of the form 'ConicArc2D[`1`, `2`, `3`, `4`]' has been detected; the value of rho must be in the range 0<rho<1.";

ConicArc2D[p0:{x0_,y0_},pA:{xA_,yA_},p1:{x1_,y1_},p_] :=
   (Message[ConicArc2D::rho,p0,pA,p1,p];$Failed) /;
(FreeQ[{p0,pA,p1,p},_Pattern] &&
(IsZeroOrNegative2D[p,0] || IsZeroOrNegative2D[1-p,0]));

Format: IsValid2D[cnarc]
Verifies that a conic arc is syntactically valid.

IsValid2D[
   ConicArc2D[{x0_?IsScalar2D,y0_?IsScalar2D},
              {xA_?IsScalar2D,yA_?IsScalar2D},
              {x1_?IsScalar2D,y1_?IsScalar2D},p_?IsScalar2D]] := True;

Scalars

Rho

Format: Rho2D[cnarc]
Returns the ρ value of a conic arc.

Rho2D[ConicArc2D[{x0_,y0_},{xA_,yA_},{x1_,y1_},p_]] := p;

Transformations

Reflect

Format: Reflect2D[cnarc,line]
Reflects a conic arc in a line.

Reflect2D[ConicArc2D[{x0_,y0_},{xA_,yA_},{x1_,y1_},p_],
          L:Line2D[A2_,B2_,C2_]] :=
   ConicArc2D[Reflect2D[{x0,y0},L],
              Reflect2D[{xA,yA},L],
              Reflect2D[{x1,y1},L],p];

Rotate

Format: Rotate2D[cnarc,θ,coords]
Rotates a conic arc by an angle θ about a position specified by a coordinate list.  If the third argument is omitted, it defaults to the origin (see D2DTransform2D.html).

Rotate2D[ConicArc2D[{x0_,y0_},{xA_,yA_},{x1_,y1_},p_],
         theta_?IsScalar2D,
         {h_?IsScalar2D,k_?IsScalar2D}] :=
   ConicArc2D[Rotate2D[{x0,y0},theta,{h,k}],
              Rotate2D[{xA,yA},theta,{h,k}],
              Rotate2D[{x1,y1},theta,{h,k}],p];

Scale

Format: Scale2D[cnarc,s,coords]
Scales a conic arc by ascale factor, s, from a position given by coordinates.  If the position is omitted, it defaults to the origin (see D2DTransform2D.html).

Scale2D[ConicArc2D[{x0_,y0_},{xA_,yA_},{x1_,y1_},p_],
        s_?IsScalar2D,
        {h_?IsScalar2D,k_?IsScalar2D}] :=
   ConicArc2D[Scale2D[{x0,y0},s,{h,k}],
              Scale2D[{xA,yA},s,{h,k}],
              Scale2D[{x1,y1},s,{h,k}],p] /;
Not[IsZeroOrNegative2D[s]];

Translate

Format: Translate2D[cnarc,{u,v}]
Translates a conic arc delta distance.

Translate2D[ConicArc2D[{x0_,y0_},{xA_,yA_},{x1_,y1_},p_],
            {u_?IsScalar2D,v_?IsScalar2D}] :=
   ConicArc2D[{x0+u,y0+v},{xA+u,yA+v},{x1+u,y1+v},p];

Construction

Apex Point

Format: Point2D[cnarc,Apex2D]
Constructs the apex control point of a conic arc.

Point2D[ConicArc2D[{x0_,y0_},{xA_,yA_},{x1_,y1_},p_],
        Apex2D] := Point2D[{xA,yA}];

Center Point

Format: Point2D[cnarc]
Constructs the center point of the central conic underlying a conic arc.

Point2D::notCentral1=
   "The conic underlying `1` is not a central conic; it has no center point.";

Point2D[C1:ConicArc2D[p0:{x0_,y0_},pA:{xA_,yA_},p1:{x1_,y1_},p_]] :=
   If[IsZero2D[p-1/2],
      Message[Point2D::notCentral1,C1];$Failed,
      Point2D[(-p^2*pA+(p-1)^2*(p0+p1)/2)/(1-2*p)] ];

Conic from Conic Arc

Format: Loci2D[cnarc]
Constructs a list containing the conic curve associated with a conic arc.

Loci2D[C1:ConicArc2D[{x0_,y0_},{xA_,yA_},{x1_,y1_},p_]] :=
   Loci2D[Quadratic2D[C1]];

Conic Arc from Conic

Format: ConicArc2D[line,conic]
Constructs a conic arc from a portion of a conic curve defined by a chordal line.

ConicArc2D::noChord=
   "No chord exists between `1` and `2`; a conic arc cannot be constructed.";

ConicArc2D::center=
   "The chord defined by `1` passes through the center of `2`; a conic arc cannot be constructed.";

The private function FindRho$2D[curve,point,{point,point}] computes ρ for a conic arc from the apex point and start/end points.

FindRho$2D[Parabola2D[{h_,k_},f_,theta_],
           Point2D[{xA_,yA_}],
           {Point2D[{x0_,y0_}],Point2D[{x1_,y1_}]}] := 1/2;

FindRho$2D[Circle2D[{h_,k_},r_] |
           Ellipse2D[{h_,k_},a_,b_,theta_] |
           Hyperbola2D[{h_,k_},a_,b_,theta_],
           Point2D[{xA_,yA_}],
           {Point2D[{x0_,y0_}],Point2D[{x1_,y1_}]}] :=
   Module[{xM,yM},
      {xM,yM}={x0+x1,y0+y1}/2;
      If[IsZero2D[h-xM],
         1/(1+Sqrt[k-yA]/Sqrt[k-yM]),
         1/(1+Sqrt[h-xA]/Sqrt[h-xM])] //Simplify ];

For central conics (circles, ellipses and hyperbolas) there is a restriction that the center point cannot be on the line defining the chord of the conic arc.

ConicArc2D[L1:Line2D[a1_,b1_,c1_],
           C2_ /; Is2D[C2,{Circle2D,Ellipse2D,Hyperbola2D}]] :=
If[IsOn2D[Point2D[C2],L1],
   Message[ConicArc2D::center,L1,C2];$Failed,
   CnArc$2D[L1,C2,Points2D[L1,C2]]];

Non-central conics (parabolas) have no restrictions on the position of the line defining the chord of the conic arc.

ConicArc2D[L1:Line2D[a1_,b1_,c1_],C2:Parabola2D[{h_,k_},f_,theta_]] :=
   CnArc$2D[L1,C2,Points2D[L1,C2]];

Both end points of the chord of the conic arc must be on the same branch of a hyperbola.

CnArc$2D[L1:Line2D[a1_,b1_,c1_],
         H2:Hyperbola2D[{h_,k_},a_,b_,theta_],
         {Point2D[{x0_,y0_}],Point2D[{x1_,y1_}]}] :=
   (Message[ConicArc2D::noChord,L1,H2];$Failed) /;
IsNegative2D[Polynomial2D[Quadratic2D[H2],{x0+x1,y0+y1}/2]];

The private function CnArc$2D[line,curve,{point,point}] completes the computation of the conic arc.

CnArc$2D[L1:Line2D[a1_,b1_,c1_],C2_,
         P:{Point2D[{x0_,y0_}],Point2D[{x1_,y1_}]}] :=
Module[{pt},
   pt=Point2D[L1,C2];
   ConicArc2D[{x0,y0},Coordinates2D[pt],{x1,y1},FindRho$2D[C2,pt,P]] ];

No conic arc exists if the intersection of the line and the curve does not result in two points.

CnArc$2D[L1:Line2D[a1_,b1_,c1_],C2_,pts_] :=
   (Message[ConicArc2D::noChord,L1,C2];$Failed)

Epilogue

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


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