Exploring Analyic Geometry with Mathematica®

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

D2DLine2D

The package D2DLine2D implements the Line2D object.

Initialization

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

D2DLine2D::usage=
   "D2DLine2D is a package that implements the Line2D object.";

Angle2D::usage=
   "Angle2D[line] gives the between the +x-axis and a line; Angle2D[line,line] gives the angle measured counter-clockwise from the first line to the second line. Angle2D[conic] gives the angle of rotation of a conic.";

Line2D::usage=
  "Line2D[A,B,C] is the standard form of a line with the equation Ax+By+C=0.";

Parallel2D::usage=
   "Parallel2D is the keyword required in Line2D[point, line, Parallel2D].";

Perpendicular2D::usage=
   "Perpendicular2D is the keyword required in Line2D[point, point, Perpendicular2D]; it is also required in Line2D[point, line, Perpendicular2D].";

Slope2D::usage=
   "Slope2D[line] gives the slope of a line. Slope[lnseg] gives the slope of a line segment.";

Begin["`Private`"];

Description

Representation

Format: Line2D[A,B,C]
Standard representation of a line in Descarta2D. The three arguments are the coefficients of the line in general form, A x+B y+C=0.  The normal form of a line, cos(θ) x+sin(θ)y-ρ=0, is also by provided by using the form Line2D[cos(θ),sin(θ),], where θ is the angle the normal to the line makes with the +x-axis, and ρ is the distance of the line from the origin.

Equations

Format: Line2D[expr,{x,y}]
Constructs a line from a linear polynomial in two unknowns.  For example, the polynomial a x+b y+c will return Line2D[a,b,c]; the equation a x+b y+c==0 will also return Line2D[a,b,c].  The {x,y} arguments are assumed to be the names of the variables.

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

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

Evaluation

Format: Line2D[A,B,C][t]
Evaluates a parameter, t, on a line.  Returns a coordinate list {x,y}.  The point nearest the origin is at parameter t=0.  Other points are parameterized by distance along the line.

Line2D[a1_,b1_,c1_][t_?IsScalar2D] :=
   Module[{a,b,c},
      {a,b,c}={a1,b1,c1}/Sqrt[a1^2+b1^2];
      -{a*c,b*c}+{b,-a}*t ];

Graphics

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

SetDisplay2D[
   Line2D[a_,b_,c_][{t1_?IsScalar2D,t2_?IsScalar2D}],
   Line[{Line2D[a,b,c][t1],
         Line2D[a,b,c][t2]}] ];

SetDisplay2D[
   Line2D[a_,b_,c_],
   Line[{Line2D[a,b,c][-AskCurveLength2D[ ]/2],
         Line2D[a,b,c][ AskCurveLength2D[ ]/2]}] ];

Validation

Format: Line2D[A,B,C]
Detects a line with imaginary coefficients and returns the $Failed symbol.  If the imaginary parts are insignificant, they are removed.

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

Line2D[a_,b_,c_] :=
   (Line2D @@ ChopImaginary2D[Line$2D[a,b,c]]) /;
(FreeQ[{a,b,c},_Pattern] && IsTinyImaginary2D[{a,b,c}]);

Line2D[a_,b_,c_] :=
   (Message[Line2D::imaginary,a,b,c];$Failed) /;
(FreeQ[{a,b,c},_Pattern] && IsComplex2D[{a,b,c},0]);

Format: Line2D[A,B,C]
Returns the $Failed symbol when an invalid line is detected (the first two coefficients are zero).  Also, normalizes lines with tiny coefficients to improve numerical stability.

Line2D::invalid=
   "An invalid line of the form 'Line2D[`1`, `2`, `3`]' was encountered; at least one of the first two coefficients must be non-zero.";

Line2D[a_,b_,c_] :=
   (Message[Line2D::invalid,a,b,c];$Failed) /;
(FreeQ[{a,b,c},_Pattern] && IsZero2D[{a,b},And,0]);

Line2D[a_,b_,c_] :=
   (Line2D @@ ({a,b,c}/Sqrt[a^2+b^2])) /;
(FreeQ[{a,b,c},_Pattern] && IsZero2D[{a,b},And]);

Format: IsValid2D[line]
Verifies that a line is syntactically valid.

IsValid2D[Line2D[a_?IsScalar2D,b_?IsScalar2D,c_?IsScalar2D]] := True;

Simplify and FullSimplify

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

protected=Unprotect[Simplify];
Simplify[expr_?(!FreeQ[#,Line2D[a_,b_,c_]]&),opts___] :=
   Simplify[expr /. Line2D[a_,b_,c_] :>
               (Line$2D @@ SimplifyCoefficients2D[{a,b,c}]),
            opts] /. Line$2D->Line2D;
Protect[Evaluate[protected]];

protected=Unprotect[FullSimplify];
FullSimplify[expr_?(!FreeQ[#,Line2D[a_,b_,c_]]&),
             opts___] :=
   FullSimplify[expr /. Line2D[a_,b_,c_] :>
                   (Line$2D @@ SimplifyCoefficients2D[{a,b,c}]),
                opts] /. Line$2D->Line2D;
Protect[Evaluate[protected]];

Scalars

Angle of a Line

Format: Angle2D[line]
Computes the angle measured counter-clockwise from the +x-axis to a line.  The result is returned in radians.

Angle2D[Line2D[a_,b_,c_]] :=
   PrimaryAngle2D[If[IsZero2D[b],Pi/2,ArcTan[-a/b]],Pi];

Angle between Two Lines

Format: Angle2D[line,line]
Computes the angle measured counter-clockwise from the first line to the second line.  The result is returned in radians.

Angle2D[L1:Line2D[a1_,b1_,c1_],L2:Line2D[a2_,b2_,c2_]] :=
   PrimaryAngle2D[(Angle2D[L2]-Angle2D[L1]),Pi];

Distance from a Point to a Line

Format: Distance2D[point,line]
Computes the distance between a point and a line.

Distance2D[Point2D[{x1_,y1_}],Line2D[a2_,b2_,c2_]] :=
   Sqrt[(a2*x1+b2*y1+c2)^2/(a2^2+b2^2)];

Slope of a Line

Format: Slope2D[line]
Computes the slope of a line.

Slope2D[Line2D[a_,b_,c_]] := If[IsZero2D[b],Infinity,-a/b];

Transformations

Reflect

Format: Reflect2D[line,line]
Reflects the first line in the second line.

Reflect2D[Line2D[a1_,b1_,c1_],Line2D[a2_,b2_,c2_]] :=
   Module[{a,b,c},
      a=a1*(b2^2-a2^2)-2*b1*a2*b2;
      b=b1*(a2^2-b2^2)-2*a1*a2*b2;
      c=c1*(a2^2+b2^2)-2*c2*(a1*a2+b1*b2);
      Line2D[a,b,c] ];

Rotate

Format: Rotate2D[line,θ,coords]
Rotates a line by an angle θ about a position given by coordinates.  If the third argument is omitted, it defaults to the origin (see D2DTransform2D.html).

Rotate2D[Line2D[a_,b_,c_],theta_?IsScalar2D,
         {h_?IsScalar2D,k_?IsScalar2D}] :=
   Line2D[a*Cos[theta]-b*Sin[theta],
          b*Cos[theta]+a*Sin[theta],
          a*h+b*k+c-Cos[theta]*(a*h+b*k)-Sin[theta]*(a*k-b*h)];

Scale

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

Scale2D[Line2D[a_,b_,c_],s_?IsScalar2D,{h_?IsScalar2D,k_?IsScalar2D}] :=
   Line2D[a,b,a*(s-1)*h+b*(s-1)*k+c*s] /;
Not[IsZeroOrNegative2D[s]];

Translate

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

Translate2D[Line2D[a_,b_,c_],
            {u_?IsScalar2D,v_?IsScalar2D}] :=
   Line2D[a,b,-a*u-b*v+c];

Line Construction

Normalize a Line

Format: Line2D[line]
Constructs a line with normalized coefficients

Line2D[Line2D[a_,b_,c_]] :=
   If[IsZeroOrNegative2D[c],
      Apply[Line2D, {a,b,c}/Sqrt[a^2+b^2]],
      Apply[Line2D,-{a,b,c}/Sqrt[a^2+b^2]] ];

Line Through a Point with a Given Slope

Format: Line2D[point,m]
Constructs a line through a point with a given slope.  If the slope m is the symbol Infinity then a vertical line is returned.

Line2D[Point2D[{x0_,y0_}],Infinity] := Line2D[1,0,-x0];

Line2D[Point2D[{x0_,y0_}],m_?IsScalar2D] := Line2D[m,-1,-m*x0+y0];

Offset Line

Format: Line2D[line,d]
Constructs a line offset a given distance from a given line.  The offset distance may be positive or negative to produce the two possible offset lines.

Line2D[Line2D[a_,b_,c_],d_?IsScalar2D] :=
   Line2D[a,b,c-d*Sqrt[a^2+b^2]];

Line Through Two Coordinates

Format: Line2D[coords,coords]
Constructs a line through two points given as coordinates.  Also, using Line2D[{a,0},{0,b}] provides a construction of the intercept form of a line, x/a+y/b=1.

Line2D::sameCoords=
   "The coordinates `1` and `2` are coincident; no valid line can be constructed.";

Line2D[{x1_?IsScalar2D,y1_?IsScalar2D},{x2_?IsScalar2D,y2_?IsScalar2D}] :=
   If[IsCoincident2D[{x1,y1},{x2,y2}],
      Message[Line2D::sameCoords,{x1,y1},{x2,y2}];$Failed,
      Line2D[-(y2-y1),(x2-x1),(x1*y2-x2*y1)] ];

Line Through Two Points

Format: Line2D[point,point]
Constructs a line through two points.

Line2D[Point2D[{x1_,y1_}],Point2D[{x2_,y2_}]] := Line2D[{x1,y1},{x2,y2}];

Line Equidistant from Two Points

Format: Line2D[point,point,Perpendicular2D]
Constructs a line equidistant from two points (the perpendicular bisector of the line segment joining the two points).

Line2D[Point2D[{x1_,y1_}],Point2D[{x2_,y2_}],Perpendicular2D] :=
   If[IsCoincident2D[{x1,y1},{x2,y2}],
      Message[Line2D::sameCoords,{x1,y1},{x2,y2}];$Failed,
      Line2D[x1-x2,y1-y2,-((x1^2+y1^2)-(x2^2+y2^2))/2] ];

Line Perpendicular to a Line Through a Point

Format: Line2D[point,line,Perpendicular2D]
Constructs a line perpendicular to a given line through a given point.  The keyword Perpendicular2D is optional and may be omitted.

Line2D[P1:Point2D[{x1_,y1_}],L2:Line2D[a2_,b2_,c2_]] :=
   Line2D[P1,L2,Perpendicular2D];

Line2D[Point2D[{x1_,y1_}],Line2D[a2_,b2_,c2_],Perpendicular2D] :=
   Line2D[b2,-a2,-x1*b2+y1*a2];

Line Parallel to a Line Through a Point

Format: Line2D[point,line,Parallel2D]
Constructs a line parallel to a given line through a given point.

Line2D[Point2D[{x1_,y1_}],Line2D[a2_,b2_,c2_],Parallel2D] :=
   Line2D[-a2,-b2,x1*a2+y1*b2];

Polar Line of a Quadratic

Format: Line2D[point,quad]
Constructs a polar (line) of a quadratic with respect to a pole (point).  If the point is on the quadratic then the line is the tangent at the point.

Line2D::noPolar=
   "Since `1` is at the center of the conic, no polar line exists.";

Line2D[P1:Point2D[{x1_,y1_}],Q2:Quadratic2D[a_,b_,c_,d_,e_,f_]] :=
   Module[{p,q,r},
      p=2*a*x1+b*y1+d; q=b*x1+2*c*y1+e; r=d*x1+e*y1+2*f;
      If[IsZero2D[{p,q},And],
         Message[Line2D::noPolar,P1,Q2];$Failed,
         Line2D[p,q,r]] ];

Epilogue

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


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