Exploring Analyic Geometry with Mathematica®

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

D2DQuadratic2D

The package D2DQuadratic2D implements the Quadratic2D object.

Initialization

BeginPackage["D2DQuadratic2D`", {"D2DEquations2D`", "D2DExpressions2D`", "D2DLine2D`", "D2DLoci2D`", "D2DMaster2D`", "D2DNumbers2D`", "D2DPoint2D`", "D2DSketch2D`", "D2DTransform2D`"}];

D2DQuadratic2D::usage=
   "D2DQuadratic2D is a package providing support for the quadratic object.";

Quadratic2D::usage=
   "Quadratic2D[a,b,c,d,e,f] represents the polynomial a*x^2+b*x*y+c*y^2+d*x+e*y+f.";

Begin["`Private`"];

Description

Representation

Format:  Quadratic2D[a,b,c,d,e,f]
A quadratic is used to represent a quadratic polynomial in two unknowns.  Quadratic2D[a,b,c,d,e,f] represents "D2DQuadratic2D_1.gif".

Graphics

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

SetDisplay2D[
   Quadratic2D[a_,b_,c_,d_,e_,f_],
   Loci2D[Quadratic2D[a,b,c,d,e,f]]];

Validation

Format: Quadratic2D[a,b,c,d,e,f]
Detects a quadratic with imaginary coefficients and returns the $Failed symbol.  If the imaginary parts are insignificant, they are removed.

Quadratic2D::imaginary=
   "An invalid quadratic of the form 'Quadratic2D[`1`, `2`, `3`, `4`, `5`, `6`]' has been detected; the arguments cannot be imaginary.";

Quadratic2D[a_,b_,c_,d_,e_,f_] :=
   (Quadratic2D @@ ChopImaginary2D[Quadratic$2D[a,b,c,d,e,f]]) /;
(FreeQ[{a,b,c,d,e,f},_Pattern] && IsTinyImaginary2D[{a,b,c,d,e,f}]);

Quadratic2D[a_,b_,c_,d_,e_,f_] :=
   (Message[Quadratic2D::imaginary,a,b,c,d,e,f];$Failed) /;
(FreeQ[{a,b,c,d,e,f},_Pattern] && IsComplex2D[{a,b,c,d,e,f},0]);

Format: Quadratic2D[a,b,c,d,e,f]
Returns the $Failed symbol when an invalid quadratic is detected (the first five coefficients are zero).  Also, normalizes quadratics with tiny coefficients to improve numerical stability.

Quadratic2D::invalid=
   "An invalid quadratic of the form 'Quadratic2D[`1`, `2`, `3`, `4`, `5`, `6`]' was encountered; at least one of the first five coefficients must be non-zero.";

Quadratic2D[a_,b_,c_,d_,e_,f_] :=
   (Message[Quadratic2D::invalid,a,b,c,d,e,f];$Failed) /;
(FreeQ[{a,b,c,d,e,f},_Pattern] && IsZero2D[{a,b,c,d,e},And,0]);

Quadratic2D[a_,b_,c_,d_,e_,f_] :=
   (Quadratic2D @@ ({a,b,c,d,e,f}/Sqrt[a^2+b^2+c^2+d^2+e^2])) /;
(FreeQ[{a,b,c,d,e,f},_Pattern] && IsZero2D[{a,b,c,d,e},And]);

Format: IsValid2D[quad]
Verifies that a quadratic is valid.

IsValid2D[
   Quadratic2D[a_?IsScalar2D,b_?IsScalar2D,
               c_?IsScalar2D,d_?IsScalar2D,
               e_?IsScalar2D,f_?IsScalar2D]] := True;

Transformations

Reflect

Format: Reflect2D[quad,line]
Reflects a 'quadratic' in a line.

Reflect2D[Q:Quadratic2D[a_,b_,c_,d_,e_,f_],L:Line2D[p_,q_,r_]] :=
   Module[{eq1,eq2,x,y},
      eq1=Equation2D[Q,{x,y}];
      eq2=Reflect2D[eq1,{x,y},L];
      Quadratic2D[eq2,{x,y}] ];

Rotate

Format: Rotate2D[quad,θ,coords]
Rotates a quadratic 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[Q:Quadratic2D[a_,b_,c_,d_,e_,f_],theta_?IsScalar2D,
         {h_?IsScalar2D,k_?IsScalar2D}] :=
   Module[{eq1,eq2,x,y},
      eq1=Equation2D[Q,{x,y}];
      eq2=Rotate2D[eq1,{x,y},theta,{h,k}];
      Quadratic2D[eq2,{x,y}] ];

Scale

Format: Scale2D[quad,s,coords]
Scales a quadratic from a position given by coordinates.  If the third argument is omitted, it defaults to the origin (see D2DTransform2D.html).

Scale2D[Q:Quadratic2D[a_,b_,c_,d_,e_,f_],s_?IsScalar2D,
        {h_?IsScalar2D,k_?IsScalar2D}] :=
   Module[{eq1,eq2,x,y},
      eq1=Equation2D[Q,{x,y}];
      eq2=Scale2D[eq1,{x,y},s,{h,k}];
      Quadratic2D[eq2,{x,y}] ] /;
Not[IsZeroOrNegative2D[s]];

Translate

Format: Translate2D[quad,{u,v}]
Translates a quadratic delta distance.

Translate2D[Quadratic2D[a_,b_,c_,d_,e_,f_],
          {u_?IsScalar2D,v_?IsScalar2D}] :=
   Quadratic2D[a,b,c,d-2*a*u-b*v,e-2*c*v-b*u,
               a*u^2+b*u*v+c*v^2-u*d-v*e+f];

Quadratic Construction

Simplify and FullSimplify

Format: Simplify[quad] and FullSimplify[quad]
Extends the Mathematica Simplify and FullSimplify commands to simplify the coefficients of a quadratic by factoring out common factors.  Executed when the package is loaded.

protected=Unprotect[Simplify];
Simplify[expr_?(!FreeQ[#,Quadratic2D[a_,b_,c_,d_,e_,f_]]&),
         opts___] :=
   Simplify[expr /. Quadratic2D[a_,b_,c_,d_,e_,f_] :>
              (Quadratic$2D @@
                  SimplifyCoefficients2D[{a,b,c,d,e,f}]),
            opts] /. Quadratic$2D->Quadratic2D;
Protect[Evaluate[protected]];

protected=Unprotect[FullSimplify];
FullSimplify[expr_?(!FreeQ[#,Quadratic2D[a_,b_,c_,d_,e_,f_]]&),
             opts___] :=
   FullSimplify[expr /. Quadratic2D[a_,b_,c_,d_,e_,f_] :>
                 (Quadratic$2D @@
                     SimplifyCoefficients2D[{a,b,c,d,e,f}]),
            opts] /. Quadratic$2D->Quadratic2D;
Protect[Evaluate[protected]];

Normalize

Format: Quadratic2D[quad]
Normalizes the coefficients of a quadratic in two unknowns so that the sum of the squares of the first five coefficients equals one.

Quadratic2D[Quadratic2D[a_,b_,c_,d_,e_,f_]] :=
   (Quadratic2D @@ ({a,b,c,d,e,f}/Sqrt[a^2+b^2+c^2+d^2+e^2]));

Quadratic from Equation/Polynomial

Format: Quadratic2D[expr,{x,y}]
Forms a quadratic from a polynomial or equation in two unknowns.  For example, when the expression is "D2DQuadratic2D_2.gif" will return Quadratic2D[a,n,c,d,e,f]; the polynomial   "D2DQuadratic2D_3.gif"  will also return Quadratic2D[a,n,c,d,e,f. The x and y arguments are assumed to be the names of the variables.

Quadratic2D::noPoly=
   "The expression `1` cannot be recognized as a quadratic polynomial or equation in variables `2` and `3`.";

Quadratic2D[expr_,{x_,y_}] :=
   Module[{eqn,a,b,c,d,e,f},
      eqn=If[Head[expr]===Equal,
             expr[[1]]-expr[[2]],
             expr] //Expand;
      a=Coefficient[eqn,x^2];
      b=Coefficient[eqn,x*y];
      c=Coefficient[eqn,y^2];
      d=Coefficient[Expand[eqn /. {x*y->0}],x];
      e=Coefficient[Expand[eqn /. {x*y->0}],y];
      f=(eqn /. {x->0,y->0}) //Expand;
      If[IsZero2D[a*x^2+b*x*y+c*y^2+d*x+e*y+f-eqn],
         Quadratic2D[a,b,c,d,e,f],
         Message[Quadratic2D::noPoly,expr,x,y];$Failed] ];

Quadratic from Coordinates

Format: Quadratic2D[coords]
Forms a (degenerate) quadratic from a point given by a coordinate list (a point circle).

Quadratic2D[{x_?IsScalar2D,y_?IsScalar2D}] :=
   Quadratic2D[1,0,1,-2*x,-2*y,x^2+y^2];

Quadratic Through Three Points

Format: Quadratic2D[point,point,point]
Constructs a quadratic (circle) that passes through three points.

Quadratic2D[Point2D[{x1_,y1_}],Point2D[{x2_,y2_}],Point2D[{x3_,y3_}]] :=
   Module[{eqn,x,y},
      eqn=Det[{{ x^2+ y^2, x, y,1},
               {x1^2+y1^2,x1,y1,1},
               {x2^2+y2^2,x2,y2,1},
               {x3^2+y3^2,x3,y3,1}}];
      Quadratic2D[eqn,{x,y}] ];

Quadratic Through Five Points

Format: Quadratic2D[point,point,point,point,point]
Constructs a quadratic that passes through five points.

Quadratic2D[Point2D[{x1_,y1_}],Point2D[{x2_,y2_}],Point2D[{x3_,y3_}],
            Point2D[{x4_,y4_}],Point2D[{x5_,y5_}]] :=
   Module[{full,a,b,c,d,e,f},
      full={{x1^2, x2^2, x3^2, x4^2, x5^2},
            {x1*y1,x2*y2,x3*y3,x4*y4,x5*y5},
            {y1^2, y2^2, y3^2, y4^2, y5^2},
            {x1,   x2,   x3,   x4,   x5},
            {y1,   y2,   y3,   y4,   y5},
            {1,    1,    1,    1,    1}};
      {a,b,c,d,e,f}=Map[Det[Transpose[Drop[full,{#}]]]&,{1,2,3,4,5,6}];
      Quadratic2D[a,-b,c,-d,e,-f] ];

Quadratic Tangent to Five Lines

Format: Quadratic2D[line,line,line,line,line]
Constructs a quadratic tangent to five lines.  The private function Reciprocal$2D constructs the reciprocal of a conic with respect to the unit circle "D2DQuadratic2D_4.gif".  If any of the lines pass through the origin, the entire configuration is transformed to avoid the infinities involved.

Reciprocal$2D[Quadratic2D[a_,b_,c_,d_,e_,f_]] :=
   Quadratic2D[4*c*f-e^2,2*d*e-4*b*f,4*a*f-d^2,
               4*c*d-2*b*e,4*a*e-2*d*b,4*a*c-b^2];

Quadratic2D[L1:Line2D[a1_,b1_,c1_],L2:Line2D[a2_,b2_,c2_],
            L3:Line2D[a3_,b3_,c3_],L4:Line2D[a4_,b4_,c4_],
            L5:Line2D[a5_,b5_,c5_]] :=
   Module[{u,v,lns,Q},
      {u,v}=RandomInteger[{-5, 5}, 2];
      lns=Translate2D[{L1,L2,L3,L4,L5},{u,v}];
      Q=Quadratic2D[lns];
      Translate2D[Q,{-u,-v}] ] /;
IsZero2D[{c1,c2,c3,c4,c5},Or];

Quadratic2D[Line2D[a1_,b1_,c1_],Line2D[a2_,b2_,c2_],
            Line2D[a3_,b3_,c3_],Line2D[a4_,b4_,c4_],
            Line2D[a5_,b5_,c5_]] :=
   Reciprocal$2D[
      Quadratic2D[
         Point2D[{-a1/c1,-b1/c1}],Point2D[{-a2/c2,-b2/c2}],
         Point2D[{-a3/c3,-b3/c3}],Point2D[{-a4/c4,-b4/c4}],
         Point2D[{-a5/c5,-b5/c5}]]] /;
Not[IsZero2D[{c1,c2,c3,c4,c5},Or]];

Quadratic from Two Lines

Format: Quadratic2D[line,line]
Constructs a quadratic representing two lines multiplied together.

Quadratic2D[Line2D[a1_,b1_,c1_],Line2D[a2_,b2_,c2_]] :=
   Quadratic2D[a1*a2,a1*b2+a2*b1,b1*b2,a1*c2+a2*c1,b1*c2+b2*c1,c1*c2];

Quadratic from Focus/Directrix/Eccentricity

Format: Quadratic2D[point,line,e]
Constructs a quadratic from a focus point, directrix line and eccentricity.

Quadratic2D::eccentricity=
   "The eccentricity `1` is invalid; the eccentricity must be positive.";

Quadratic2D[Point2D[{x1_,y1_}],L2:Line2D[a2_,b2_,c2_],e_?IsScalar2D] :=
   Module[{l,m,r},
      If[IsZeroOrNegative2D[e],
         Message[Quadratic2D::eccentricity,e];$Failed,
         {p,q,r}=List @@ Line2D[L2];
         Quadratic2D[e^2*p^2-1, 2*e^2*p*q, e^2*q^2-1,
                     2*(x1+e^2*p*r), 2*(y1+e^2*q*r),e^2*r^2-x1^2-y1^2]] ];

Quadratic Vertex Equation

Format: Quadratic2D[point,fcLen,e,θ]
Constructs a quadratic from the vertex point, focal length, eccentricity and rotation angle.  If the rotation angle is omitted, it defaults to zero.

Quadratic2D::invLen=
   "A non-positive focal chord length, `1`, is invalid; no valid quadratic can be constructed.";

Quadratic2D::invEcc=
   "A negative eccentricity, `1`, is invalid; no valid quadratic can be constructed.";

Quadratic2D[P1:Point2D[{x1_,y1_}],fcLen_?IsScalar2D,e_?IsScalar2D] :=
   Quadratic2D[P1,fcLen,e,0];

Quadratic2D[Point2D[{x1_,y1_}],fcLen_?IsScalar2D,
            e_?IsScalar2D,theta_?IsScalar2D] :=
   Module[{eqn,x,y},
      Which[
         IsZeroOrNegative2D[fcLen],
            Message[Quadratic2D::invLen,fcLen];$Failed,
         IsNegative2D[e],
            Message[Quadratic2D::invEcc,e];$Failed,
         True,
            eqn=(y-y1)^2==fcLen*(x-x1)-(1-e^2)(x-x1)^2;
            Rotate2D[Quadratic2D[eqn,{x,y}],theta,{x1,y1}]] ];

Epilogue

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


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