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`" *)