@c plane.texi

     
@c This file is part of the 3DLDF User and Reference Manual.
@c Copyright (C) 2003, 2004 Laurence D. Finston 
@c See the section "GNU Free Documentation License" in the file 
@c fdl.texi for copying conditions.

@c $Id: plane.texi,v 1.6 2004/01/12 18:40:18 lfinsto1 Exp lfinsto1 $
 
@node Plane Reference, Path Reference, Line Reference, Top
@chapter Plane Reference

@tindex Plane
The @code{struct Plane}  is defined in @file{planes.web}. 
@code{Planes} are not @code{Shapes}.  They are used for
performing vector operations.  A @code{Plane} is defined by a
@code{Point} representing a point on the plane, a @code{Point}
representing the normal to the plane, and the distance of the plane from
the origin. 

The most common use of @code{Planes} is to represent the 
plane in which an existing plane figure lies.  Therefore, they  
most likely to be created by using @code{Path::get_plane()}.
@xref{Querying Paths,, Path Reference; Querying}.  However, @code{class
Plane} does have constructors for creating @code{Planes} directly, if
desired.
@xref{Planes Constructors,,Planes Reference; Constructors}. 

@menu
* Planes Data Members::         
* Planes Global Constants::     
* Planes Constructors::         
* Planes Operators::            
* Planes Returning Information::  
* Plane Intersections::         
* Planes Showing::              
@end menu
 
@node Planes Data Members, Planes Global Constants, Plane Reference, Plane Reference
@section Data Members

Because the main purpose of @code{Plane} is to 
provide information about @code{Shapes}, its data members are all
@code{public}. 

@deftypevr {Public variable} Point point
Represents a point on the plane.
@end deftypevr

@deftypevr {Public variable}  Point normal
Represents the normal to the plane.
@end deftypevr

@deftypevr {Public variable} real distance
The distance of the plane from the origin.
@end deftypevr 

@node Planes Global Constants, Planes Constructors, Planes Data Members, Plane Reference
@section Global Constants

@deftypevr {Constant} {const Plane} INVALID_PLANE
A @code{Plane} with @code{point} @equiv{} @code{normal}, and
@code{distance} @equiv{} @code{INVALID_REAL}.  

@code{INVALID_PLANE} is returned from @code{Path::get_plane()}, if the 
@code{Path} is not planar.  @xref{Querying Paths,, Path Reference; Querying}. 
@end deftypevr 

@node Planes Constructors, Planes Operators, Planes Global Constants, Plane Reference
@section Constructors




@deftypefn {Default constructor} void Plane (void)
Creates a degenerate @code{Plane} with
@code{point} @equiv{} @code{normal} @equiv{} @code{origin}, and
@code{distance} @equiv{} 0.  

@code{Planes} constructed using this constructor will probably be set
using the assignment operator 
or @code{Path::get_plane()}
immediately, or
very soon after being declared. 
@xref{Planes Operators,,Planes Reference; Operators}, and 
@ref{Querying Paths,,Paths Reference; Querying}.
@end deftypefn 


@deftypefn {Copy constructor} void Plane ({const Plane& p})
Creates a new @code{Plane}, making it a copy of @var{p}.
@end deftypefn 

@deftypefn {Constructor} void Plane ({const Point&} @var{p}, {const Point&} @var{n})
If @var{p} is not equal to @var{n}, this constructor creates a
@code{Plane} and sets @code{point} to @var{p}.  @code{normal} 
is set to @var{n}, and made a unit vector.  
@code{distance} is calculated according to the following formula:
@c
Let @math{n} stand for @code{normal}, @math{p} for @code{point}, and @math{d} for
@code{distance}: 
@iftex
@tex
$d = -p\cdot n$.  
@end tex
@end iftex
@c
@ifnottex 
@math{d = -p \dot n}.  
@end ifnottex 
@c
If @math{d = 0}, @code{origin}
lies in the @code{Plane}.  If @math{d > 0}, @code{origin} lies on the side of the
@code{Plane} that @code{normal} points to, considered to be ``outside''.
If @math{d<0}, @code{origin} lies on the side of the
@code{Plane} that @code{normal} does not point to, considered to be
``inside''. 


However, if @var{p} @equiv{} @var{n}, @code{point} and @code{normal} are
both set to @code{INVALID_POINT}, and @code{distance} is set to
@code{INVALID_REAL}, i.e., @code{*this} will be equal to
@code{INVALID_PLANE} 
(@pxref{Planes Global Constants,,Planes Reference; Global Constants}).  

@example
Point P(1, 1, 1);
Point N(0, 1);
N.rotate(-35, 30, 20);
N.show("N:");
@print{} N: (-0.549659, 0.671664, 0.496732)
Plane q(P, N);
cout << q.distance;
@print{} -0.618736
@end example


@c
@iftex
@tex
\medskip
\ifmakeexamples
\BEX
\BGRP
\immediate\write\examples{default_focus.set(4, 3, -10, 0, 3, 10, 10);}
\immediate\write\examples{Circle c(origin, 5);}
\immediate\write\examples{Point N(0, 1);}
\immediate\write\examples{c *= N.rotate(-35, 30, 20);}
\immediate\write\examples{N.label("$N$");}
\immediate\write\examples{Point N_save(N);}
\immediate\write\examples{Point P(1, 1, 1);}
\immediate\write\examples{Plane q(P, N);}
\immediate\write\examples{P.dotlabel("$P$", "lrt"); }
\immediate\write\examples{c *= N.shift(P);}
\immediate\write\examples{N.label("$@DBKS{vec}@OCB n@CCB$");}
\immediate\write\examples{c.filldraw(black, light_gray, "evenly");}
\immediate\write\examples{Point pt[7];}
\immediate\write\examples{P.drawarrow(N);}
\immediate\write\examples{pt[0] = c.get_center();}
\immediate\write\examples{for (int i = 0; i < 16; i+=2)}
\immediate\write\examples{  @OCB}
\immediate\write\examples{    pt[1] = c.get_point(i);}
\immediate\write\examples{    pt[2] =  pt[1]- pt[0];}
\immediate\write\examples{    pt[2] *= .5;}
\immediate\write\examples{    pt[2].shift(pt[1]);}
\immediate\write\examples{    pt[0].drawarrow(pt[2], black, "evenly");}
\immediate\write\examples{  @CCB}
\immediate\write\examples{pt[3] = c.get_center().mediate(c.get_point(15), .667);}
\immediate\write\examples{pt[4] = c.get_center().mediate(c.get_point(0), .667);}
\immediate\write\examples{pt[5] = pt[3].mediate(pt[4]);}
\immediate\write\examples{pt[5].label("$q$");}
\immediate\write\examples{pt[6].shift(0, -.1);} 
\immediate\write\examples{draw_axes(0,"d","d","d",black,"","",0,0,pt[6]);}
\immediate\write\examples{origin.drawarrow(N_save);}
\immediate\write\examples{current_picture.output(default_focus, Projections::PERSP, 1, Sorting::NO_SORT);}
\EGRP
\EEX 1
\fi
\PEX
@end tex
@end iftex

@ifhtml
@html
<p align="center">
<br>
<img src="./graphics/png/3DLDFmp.105.png"
alt="[Figure 105. Not displayed.]"
/>
<br>
<br>
Fig. 105.
<br>
</p>
@end html
@end ifhtml

@ifinfo
[Figure 105 not displayed.]
@end ifinfo

@c
@end deftypefn 


@node Planes Operators, Planes Returning Information, Planes Constructors, Plane Reference
@section Operators

@deftypefn {Assignment operator} {const Plane&} operator= ({const Plane&} @var{p})
Sets @code{point} to @var{p}.@code{point}, @code{normal} to
@var{p}.@code{normal}, and @code{distance} to @var{p}.@code{distance}.  
The return value is @var{p}, so that invocations of this function can be 
chained.

@example
Point pt(2, 2.3, 6);
Point norm(-1, 12, -36);
Plane A(pt, norm);
Plane B;
Plane C;
B = C = A;
A.show("A:");
@print{} A:
   normal: (-0.0263432, 0.316118, -0.948354)
   point: (2, 2.3, 6)
   distance == 5.01574
cout << (A == B && A == C && B == C);
@print{} 1
@end example
@end deftypefn 

@deftypefn {@code{const} operator} bool operator== ({const Plane&} @var{p})
Equality operator.  Compares @code{*this} and @var{p}, and returns
@code{true}, if @code{point} @equiv{} @var{p}.@code{point},
@code{normal} @equiv{} @var{p}.@code{normal}, and 
@code{distance} @equiv{} @var{p}.@code{distance},
otherwise @code{false}.
@end deftypefn 

@deftypefn {@code{const} operator} bool operator!= ({const Plane&} @var{p})
Inequality operator.  Compares @code{*this} and @var{p} and returns
@code{true}, if @code{point} @NEQ{} @var{p}.@code{point}, or 
@code{normal} @NEQ{} @var{p}.@code{normal}, or
@code{distance} @NEQ{} @var{p}.@code{distance}.
Otherwise, it returns @code{false}.
@end deftypefn 

@node Planes Returning Information, Plane Intersections, Planes Operators, Plane Reference
@section Returning Information


@deftypefn {@code{const} function} real_short get_distance ({const Point&} @var{p})
@deftypefnx {@code{const} function} real_short get_distance (void)
The version of this function taking a @code{Point} argument returns 
a @code{real_short} @var{r}, whose @code{real} part
(@var{r}.@code{first}) represents
the distance of @var{p} from the @code{Plane}.  This value is always
positive.  @var{r}.@code{second} can take on three values:

@table @asis
@item 0 
If the @code{Point} lies in the @code{Plane}.

@item 1 
If it lies on the side of the @code{Plane} pointed at by the
normal to the @code{Plane}, considered to be the ``outside''.

@item -1 
If it lies on the side of the @code{Plane} @emph{not} pointed at
by the normal to the @code{Plane}, considered to be the ``inside''.
@end table

The version taking no argument returns 
the absolute of the data member @code{distance} and its sign, i.e., the
distance of @code{origin} to the @code{Plane}, and which side of the
@code{Plane} it lies on.

It would have been possible to use @code{origin} as the default for an
optional @code{Point} argument, but I've chosen to overload this
function, because of problems that may arise, when I implement
@code{user_coordinates} and @code{view_coordinates} 
(@pxref{Point Data Members,,Point Reference; Data Members}).

@example
Point N(0, 1);
N.rotate(-10, 20, 20);
Point P(1, 1, 1);
Plane q(P, N);
Point A(4, -2, 4);
Point B(-1, 3, 2);
Point C = q.intersection_point(A, B).pt;
real_short bp;

bp = q.get_distance();
cout << bp.first;
@print{} 0.675646
cout << bp.second
@print{} -1

bp = q.get_distance(A)
cout << bp.first;
@print{} 3.40368
cout << bp.second;
@print{}  -1

bp = q.get_distance(B)
cout << bp.first;
@print{} 2.75865
cout << bp.second;
@print{} 1

bp = q.get_distance(C)
cout << bp.first;
@print{} 0
cout << bp.second;
@print{} 0
@end example

@c
@iftex
@tex
\ifmakeexamples
\BEX
\BGRP
\immediate\write\examples{default_focus.set(-3, 4, -10, -3, 4, 10, 10);}
\immediate\write\examples{Circle c(origin, 5);}
\immediate\write\examples{Point N(0, 1);}
\immediate\write\examples{c *= N.rotate(-10, 20, 20);}
\immediate\write\examples{Point P(1, 1, 1);}
\immediate\write\examples{Plane q(P, N);}
\immediate\write\examples{P.dotlabel("$P$", "lrt"); }
\immediate\write\examples{c *= N.shift(P);}
\immediate\write\examples{N.label("$@DBKS{vec}@OCB n@CCB$", "rt");}
\immediate\write\examples{c.filldraw(black, light_gray, "evenly");}
\immediate\write\examples{Point pt[7];}
\immediate\write\examples{P.drawarrow(N);}
\immediate\write\examples{pt[0] = c.get_center();}
\immediate\write\examples{for (int i = 0; i < 16; i+=2)}
\immediate\write\examples{ @OCB}
\immediate\write\examples{ pt[1] = c.get_point(i);}
\immediate\write\examples{ pt[2] = pt[1]- pt[0];}
\immediate\write\examples{ pt[2] *= .5;}
\immediate\write\examples{ pt[2].shift(pt[1]);}
\immediate\write\examples{ pt[0].drawarrow(pt[2], black, "evenly");}
\immediate\write\examples{ @CCB}
\immediate\write\examples{pt[3] = c.get_point(12).mediate(c.get_point(14), .4);}
\immediate\write\examples{pt[4] = pt[0].mediate(pt[3], .8);}
\immediate\write\examples{pt[4].label("$q$", "");}
\immediate\write\examples{pt[6].shift(0, -.1);}
\immediate\write\examples{Point A(4, -2, 4);}
\immediate\write\examples{Point B(-1, 3, 2);}
\immediate\write\examples{A.dotlabel("$A$", "bot"); }
\immediate\write\examples{B.dotlabel("$B$"); }
\immediate\write\examples{A.draw(B, black, "evenly");}
\immediate\write\examples{Point C = q.intersection_point(A, B).pt;}
\immediate\write\examples{C.dotlabel("$C$", "bot"); }
\immediate\write\examples{real_short bp;}
\immediate\write\examples{draw_axes(0,"d","d","d",black,"","",0,0,pt[6]);}
\immediate\write\examples{current_picture.output(default_focus, Projections::PERSP, 1, Sorting::NO_SORT);}
\EGRP
\EEX 1
\fi
\PEX
@end tex
@end iftex

@ifhtml
@html
<p align="center">
<br>
<img src="./graphics/png/3DLDFmp.106.png"
alt="[Figure 106. Not displayed.]"
/>
<br>
<br>
Fig. 106.
<br>
</p>
@end html
@end ifhtml

@ifinfo
[Figure 106 not displayed.]
@end ifinfo

@c


@end deftypefn 

@node Plane Intersections, Planes Showing, Planes Returning Information, Plane Reference
@section Intersections
@deftypefn {@code{const} function} bool_point intersection_point ({const Point&} @var{p0}, {const Point&} @var{p1})
@deftypefnx {@code{const} function} bool_point intersection_point ({const Path&} @var{p})
These functions find the intersection point of the @code{Plane} and a
line.  In the first version, the
line is defined by the two @code{Point} arguments.  In the second
version, the @code{Path} @var{p} must be linear, i.e.,
@var{p}.@code{is_linear()} must be @code{true}.

Both versions of @code{intersection_point()} return a @code{bool_point} 
@var{bp}, where  @var{bp}.@code{pt} is the intersection point, or
@code{INVALID_POINT}, if there is none.  If an intersection point is
found, @var{bp}.@code{b} will be @code{true}, otherwise @code{false}.
Returning a @code{bool_point} makes it possible to test for success
without comparing the @code{Point} returned against @code{INVALID_POINT}.

@example
Point center(2, 2, 3.5);
Reg_Polygon h(center, 6, 4, 80, 30, 10);
Plane q = h.get_plane();
Point P0 = center.mediate(h.get_point(2));
P0.shift(5 * (N - center));
Point P1(P0);
P1.rotate(h.get_point(1), h.get_point(4));
P1 = 3 * (P1 - P0);
P1.shift(P0);
P1.shift(3, -.5, -2);
bool_point bp = q.intersection_point(P0, P1);
Point i_P = bp.pt;
Point P4 = h.get_point(3).mediate(h.get_point(0), .75);
P4.shift(N - center);
Point P5(P4);
P5.rotate(h.get_point(3), h.get_point(0));
P4.shift(-1, 2);
Path theta(P4, P5);
bp = q.intersection_point(theta);
Point i_theta = bp.pt;
draw_axes();
@end example

@c
@iftex
@tex
\ifmakeexamples
\BEX
\BGRP  
\immediate\write\examples{default_focus.set(3, 2, -10, 3, 2, 10, 10);}
\immediate\write\examples{Point center(2, 2, 3.5);}
\immediate\write\examples{center.drawdot();}
\immediate\write\examples{Reg_Polygon h(center, 6, 4, 80, 30, 10);}
\immediate\write\examples{h.draw();}
\immediate\write\examples{Plane q = h.get_plane();}
\immediate\write\examples{Point N = q.normal;}
\immediate\write\examples{N.shift(center);}
\immediate\write\examples{Point N_temp(N);}
\immediate\write\examples{N_temp *= 1.1;}
\immediate\write\examples{center.drawarrow(N_temp);}
\immediate\write\examples{N_temp.label("$@DBKS{vec}@OCB n@CCB$", "rt");}
\immediate\write\examples{Point P0 = center.mediate(h.get_point(2));}
\immediate\write\examples{P0.shift(5 * (N - center));}
\immediate\write\examples{P0.dotlabel("$P_0$"); }
\immediate\write\examples{Point P1(P0);}
\immediate\write\examples{P1.rotate(h.get_point(1), h.get_point(4));}
\immediate\write\examples{P1 = 3 * (P1 - P0);}
\immediate\write\examples{P1.shift(P0);}
\immediate\write\examples{P1.shift(3, -.5, -2);}
\immediate\write\examples{P1.dotlabel("$P_1$"); }
\immediate\write\examples{bool_point bp = q.intersection_point(P0, P1);}
\immediate\write\examples{Point i_P = bp.pt;}
\immediate\write\examples{i_P.dotlabel("$i_P$", "bot"); }
\immediate\write\examples{P0.draw(P1, black, "evenly");}
\immediate\write\examples{Point P4 = h.get_point(3).mediate(h.get_point(0), .75);}
\immediate\write\examples{P4.shift(N - center);}
\immediate\write\examples{Point P5(P4);}
\immediate\write\examples{P5.rotate(h.get_point(3), h.get_point(0));}
\immediate\write\examples{P4.shift(-1, 2);}
\immediate\write\examples{Path theta(P4, P5);}
\immediate\write\examples{P4.drawdot(black, "pencircle scaled .75mm");}
\immediate\write\examples{theta.get_point(0).mediate(theta.get_point(1), .1).label("$@DBKS{theta}$", "rt"); }
\immediate\write\examples{theta.drawarrow(black);}
\immediate\write\examples{bp = q.intersection_point(theta);}
\immediate\write\examples{Point i_theta = bp.pt;}
\immediate\write\examples{i_theta.dotlabel("$i_@DBKS{theta}$", "rt"); }
\immediate\write\examples{draw_axes();}
\immediate\write\examples{current_picture.output(default_focus, Projections::PERSP, 1, Sorting::NO_SORT);}
\EGRP
\EEX 1
\fi
\PEX
@end tex
@end iftex

@ifhtml
@html
<p align="center">
<br>
<img src="./graphics/png/3DLDFmp.107.png"
alt="[Figure 107. Not displayed.]"
/>
<br>
<br>
Fig. 107.
<br>
</p>
@end html
@end ifhtml

@ifinfo
[Figure 107 not displayed.]
@end ifinfo

@c



@end deftypefn

@deftypefn {@code{const} function} Line intersection_line ({const Plane&} @var{p})
Returns a @code{Line} @var{l}.  representing the line of intersection of two
@code{Planes}.  @xref{Line Reference}.

In @NEXTFIG{}, @code{intersection_line()} is used to find the line of
intersection of the @code{Planes} derived from the @code{Rectangles} 
@math{r_0} and @math{r_1} using @code{get_plane()} 
(@pxref{Querying Paths,,Paths Reference; Querying}).
Please note that there is no guarantee that @var{l}.@code{position} will
be in a convenient place for your drawing.  A bit of fiddling was
needed to find the @code{Points} @math{P_2} and @math{P_3}.  
@c !! TO DO: 
I plan to add functions for finding the intersection lines of plane
figures, but haven't done so yet.


@example
Rectangle r0(origin, 5, 5, 10, 15, 6);
Rectangle r1(origin, 5, 5, 90, 50, 10);
r1 *= r0.rotate(30, 30, 30);
r1 *= r0.shift(1, -1, 3);
Plane q0 = r0.get_plane();
Plane q1 = r1.get_plane();
Line l = q0.intersection_line(q1);
l.show("l:");
@print{} l:
   position: (0, 11.2193, 20.0759)
   direction: (0.0466595, -0.570146, -0.796753)
Point P0(l.direction);
P0.shift(l.position);
P0.show("P0:");
@print{} P0: (0.0466595, 10.6491, 19.2791)
Point P1(-l.direction);
P1.shift(l.position);
Point P2(P0 - P1);
P2 *= 12.5;
P2.shift(P0);
cout << P2.is_on_plane(q0);
@print{} 1
cout << P2.is_on_plane(q1);
@print{} 1
Point P3(P0 - P1);
P3 *= 7;
P3.shift(P0);
cout << P3.is_on_plane(q0);
@print{} 1
cout << P3.is_on_plane(q1);
@print{} 1
@end example


@c
@iftex
@tex 
\ifmakeexamples
\BEX
\BGRP
\immediate\write\examples{default_focus.set(3, 2, -10, 3, 2, 10, 10);}
\immediate\write\examples{Rectangle r0(origin, 5, 5, 10, 15, 6);}
\immediate\write\examples{Rectangle r1(origin, 5, 5, 90, 50, 10);}
\immediate\write\examples{r1 *= r0.rotate(30, 30, 30);}
\immediate\write\examples{r1 *= r0.shift(1, -1, 3);}
\immediate\write\examples{r1.filldraw(black, gray);}
\immediate\write\examples{r0.draw(black, "", "pencircle scaled .5mm");}
\immediate\write\examples{r0.get_point(1).label("$r_0$"); }
\immediate\write\examples{r1.get_point(2).label("$r_1$", "lft"); }
\immediate\write\examples{Plane q0 = r0.get_plane();}
\immediate\write\examples{Plane q1 = r1.get_plane();}
\immediate\write\examples{Line l = q0.intersection_line(q1);}
\immediate\write\examples{Point P0(l.direction);}
\immediate\write\examples{P0.shift(l.position);}
\immediate\write\examples{Point P1(-l.direction);}
\immediate\write\examples{P1.shift(l.position);}
\immediate\write\examples{Point P2(P0 - P1);}
\immediate\write\examples{P2 *= 12.5;}
\immediate\write\examples{P2.shift(P0);}
\immediate\write\examples{Point P3(P0 - P1);}
\immediate\write\examples{P3 *= 7;}
\immediate\write\examples{P3.shift(P0);}
\immediate\write\examples{P2.label("$P_2$", "rt"); }
\immediate\write\examples{P3.label("$P_3$", "rt"); }
\immediate\write\examples{P2.drawarrow(P3, black, "evenly");}
\immediate\write\examples{P3.drawarrow(P2, black, "evenly");}
\immediate\write\examples{P2.mediate(P3, .8).label("$l$", "rt");}
\immediate\write\examples{draw_axes();} 
\immediate\write\examples{current_picture.output(default_focus, Projections::PERSP, 1, Sorting::NO_SORT);}
\EGRP
\EEX 1
\fi
\PEX  
@end tex
@end iftex

@ifhtml
@html
<p align="center">
<br>
<img src="./graphics/png/3DLDFmp.108.png"
alt="[Figure 108. Not displayed.]"
/>
<br>
<br>
Fig. 108.
<br>
</p>
@end html
@end ifhtml

@ifinfo
[Figure 108 not displayed.]
@end ifinfo

@c
@end deftypefn

@node Planes Showing,  , Plane Intersections, Plane Reference
@section Showing

@deftypefn {@code{const} function} void show ([string @var{text} = ""])
Prints information about the @code{Plane} to standard output.
If @var{text} is not the empty @code{string}, it is printed to the
standard output.  Otherwise, 
@samp{Plane:} is printed.  
Following this,
if the @code{Plane} is equal to @code{INVALID_PLANE} 
(@pxref{Planes Global Constants,,Planes Reference; Global Constants}),
a message to this effect is printed to standard output.  
Otherwise, @code{normal} and
@code{point} are shown using @code{Point::show()} 
(@pxref{Showing Points,,Point Reference; Showing}).  Finally,
@code{distance} is printed.

@example
Point A(1, 3, 2.5);
Rectangle r0(A, 5, 5, 10, 15, 6);
Plane p = r0.get_plane();
@print{} p:
   normal: (-0.0582432, 0.984111, -0.167731)
   point: (-0.722481, 2.38245, -0.525176)
   distance == -2.47476
@end example


@end deftypefn 


