@c rcpcurve.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: rcpcurve.texi,v 1.6 2004/01/12 18:40:41 lfinsto1 Exp lfinsto1 $
 
@node Regular Closed Plane Curve Reference, Ellipse Reference, Rectangle Reference, Top
@chapter Regular Closed Plane Curve Reference

@tindex Reg_Cl_Plane_Curve
Class @code{Reg_Cl_Plane_Curve} is defined in @file{curves.web}.
It is derived from @code{Path} using @code{public} derivation. 

@code{Reg_Cl_Plane_Curve} is not called
``@code{Regular_Closed_Plane_Curve}'' because the longer name 
causes too many ``Overfull boxes''@c
@c
@footnote{If you don't
know what ``overfull boxes'' are, don't worry about it.  It has to do with 
@TeX{}'s line and page breaking algorithms.  If you want to know more,
see Knuth, Donald E., @cite{The @TeX{}book}.}
@c
in the CWEAVE output of the program code.
@xref{CWEB Documentation}. 

@code{Reg_Cl_Plane_Curve} is meant to be used as a base class;  no
objects should be declared of type @code{Reg_Cl_Plane_Curve}.
Currently, @code{class Ellipses} is derived from
@code{Reg_Cl_Plane_Curve} and @code{class Circle} is derived from
@code{Ellipse}.  

At present, I have no fixed definition of what constitutes
``regularity'' as far as @code{Reg_Cl_Plane_Curves} are concerned.
Ellipses and circles are ``regular'' in the sense that they have axes of
symmetry.  There must be an equation for a @code{Reg_Cl_Plane_Curve},
such as 
@math{x^2 + y^2 = r^2} 
for a circle.
A derived class should have a @code{solve()} function that uses this
equation.  @code{Reg_Cl_Plane_Curve::intersection_points()} in turn uses
@code{solve()} to find the intersection points of a line with the
@code{Reg_Cl_Plane_Curve}.  This way, the derived classes don't need
their own functions for finding their intersections with a line.
However, such functions can be added, if desired.

It is assumed that classes derived from @code{Reg_Cl_Plane_Curve} are
fillable, which implies that they must be closed @code{Paths}.
@code{Reg_Cl_Plane_Curves} inherit their drawing and filling functions
from @code{Path}.

The constructors and setting functions of classes derived from
@code{Reg_Cl_Plane_Curve} must ensure that the resulting geometric
figures are planar, convex, and that the number of @code{Points} they contain is
a multiple of 4.  The latter assumption is of importance in 
@code{intersection_points()}, @code{segment()}, @code{half()}, and
@code{quarter()}.
@xref{Regular Closed Plane Curve Intersections,,
Regular Closed Plane Curve Reference; Intersections}, and
@ref{Regular Closed Plane Curve Segments,,
Regular Closed Plane Curve Reference; Segments}.

@menu
* Regular Closed Plane Curve Data Members::  
* Querying Regular Closed Plane Curves::  
* Regular Closed Plane Curve Intersections::  
* Regular Closed Plane Curve Segments::  
@end menu
 
@node Regular Closed Plane Curve Data Members, Querying Regular Closed Plane Curves, Regular Closed Plane Curve Reference, Regular Closed Plane Curve Reference
@section Data Members

@deftypevr {Protected variable} {Point} center
The center of the @code{Reg_Cl_Plane_Curve}, if it has one.
@end deftypevr 

@deftypevr {Protected variable} {unsigned short} number_of_points
The number of @code{Points} on @code{points} in a
@code{Reg_Cl_Plane_Curve}. 
@end deftypevr 

@node Querying Regular Closed Plane Curves, Regular Closed Plane Curve Intersections, Regular Closed Plane Curve Data Members, Regular Closed Plane Curve Reference
@section Querying 
  
@deftypefn {@code{const} inline virtual functions} bool is_quadratic (void)
@deftypefnx {} bool is_cubic (void)
@deftypefnx {} bool is_quartic (void)
These functions all return @code{false}.  They are intended to be
overloaded by member functions of derived classes.
@end deftypefn 


@deftypefn {@code{const} inline virtual function} real_triple get_coefficients (real @var{Slope}, real @var{v_intercept})
Returns a @code{real_triple} with all three values @equiv{}
@code{INVALID_REAL}.  Intended to be overloaded by member functions of
derived classes.
@end deftypefn 

@deftypefn {@code{const} inline virtual function} {pair<real, real>} solve (char @var{axis_unknown}, real @var{known})
Returns a @code{pair<real, real>} with @code{first} @math{=}
@code{second} @math{=} @code{INVALID_REAL}.  
Intended to be overloaded by member functions of
derived classes.
@end deftypefn 

@deftypefn {@code{const} virtual function} {signed short} location (Point @var{ref_pt}, Point @var{p})
Returns a @code{signed short} indicating the location of @var{p} with
respect to the @code{Reg_Cl_Plane_Curve}, which must be planar.  
The @code{Reg_Cl_Plane_Curve} constructors should ensure that 
@code{Reg_Cl_Plane_Curves} are, but there is no guarantee that they will
not have been manipulated into a non-planar state, by shearing, for
example.  

The argument @var{ref_pt} is used within the function for
shifting a copy of the @code{Reg_Cl_Plane_Curve} to a convenient
position.  It need not be the |center| of the @code{Reg_Cl_Plane_Curve},
however, classes derived from @code{Reg_Cl_Plane_Curve} will probably 
have their own versions of @code{location()}, which will pass @code{center}
as the @var{ref_pt} argument to this function.
@code{Reg_Cl_Plane_Curves} need not have a meaningful |center|.  

@code{location()} returns the following values:
@table @asis

@item -1
@var{p} and @code{*this} are coplanar, and @var{p} lies 
outside the perimeter of @code{*this}.

@item 0
@var{p} and @code{*this} are coplanar, and @var{p} lies on the perimeter
of @code{*this}.

@item 1   
@var{p} and @code{*this} are coplanar, and @var{p} lies inside
the perimeter of @code{*this}.

@item -2
@var{p} and @code{*this} are not coplanar.

@item -3
Something has gone terribly wrong.

@item -4 
The normal to @code{*this} has 0 magnitude, i.e., the
|Points| on @code{*this} are colinear.

@item -5
An error occurred in putting @code{*this} in one of
the major planes.
@end table
@end deftypefn 

@deftypefn {Virtual function} Point angle_point (real @var{angle})
Returns @code{INVALID_POINT}.  Intended to be overloaded by member functions of
derived classes.
@end deftypefn 

@node Regular Closed Plane Curve Intersections, Regular Closed Plane Curve Segments, Querying Regular Closed Plane Curves, Regular Closed Plane Curve Reference
@section Intersections

@deftypefn {@code{const} function} bool_point_pair intersection_points (Point @var{ref_pt}, Point @var{p0}, Point @var{p1}) 
@deftypefnx {@code{const} function} bool_point_pair intersection_points ({const Point&} @var{ref_pt}, {const Path&} @var{p})
@c
The version of this function taking @code{Point} arguments finds the
intersection points, if any, of the 
@code{Reg_Cl_Plane_Curve} and the line  
@math{p}
that passes through the @code{Points} 
@math{p_0}
and
@math{p_1}.
In the other version, the @code{Path} argument must be a linear
@code{Path}, and its first and last @code{Points} are passed to the
first version of this function as @var{p0} and @var{p1}, respectively.

Let 
@math{C}
be the @code{Reg_Cl_Plane_Curve}.
@math{C} and @math{p} can intersect at at most two intersection points
@math{i_1} and @math{i_2}.
Let @code{bpp} be the return
value of this function.  
The intersection points need not be on the @emph{line segment}
between @code{pt0} and @code{pt1}.  
@code{bpp.first.pt} will be set
to the first intersection point if it exists, or @code{INVALID_POINT} if
it doesn't.  If the first intersection point exists and is on the line
segment between @code{pt0} and @code{pt1}

In @NEXTFIG{}, the line @OVERRTARROW{AB} is normal to the
@code{Ellipse} @math{e}, or, to put it another way, @OVERRTARROW{AB} is
perpendicular to the plane of @math{e}.  The intersection point @math{i_0} lies
within the perimeter of @math{e}.  

The line @OVERRTARROW{DE} is skew to the plane of @math{e}, and
intersects @math{e} at @math{i_1}, on the perimeter of @math{e}.

@example
@group
Point p0(2, 2, 3);
Ellipse e(p0, 3, 4, 30, -60, -5.2);
Point p1 = p0.mediate(e.get_point(11), .5);
Point A = e.get_normal();
A *= 2.5;
A.shift(p1);
Point B = A.mediate(p1, 2);
bool_point_pair bpp = e.intersection_points(A, B);
Point C(0, 2, 0);
Point D(0, -3.5, 0);
C *= D.rotate(2, 0, -5);
C *= D.shift(e.get_point(4));
bpp = e.intersection_points(C, D);
@end group
@end example

@c
@iftex
@tex
\ifmakeexamples
\BEX
\BGRP
\immediate\write\examples{Point p0(2, 2, 3);}
\immediate\write\examples{p0.label("$e$", "");}
\immediate\write\examples{Ellipse e(p0, 3, 4, 30, -60, -5.2);}
\immediate\write\examples{e.draw();}
\immediate\write\examples{Point p1 = p0.mediate(e.get_point(11), .5);}
\immediate\write\examples{Point A = e.get_normal();}
\immediate\write\examples{A *= 2.5;}
\immediate\write\examples{A.shift(p1);}
\immediate\write\examples{A.dotlabel("$A$"); }
\immediate\write\examples{Point B = A.mediate(p1, 2);}
\immediate\write\examples{B.dotlabel("$B$", "bot");}
\immediate\write\examples{A.draw(B, black, "evenly");}
\immediate\write\examples{bool_point_pair bpp = e.intersection_points(A, B);}
\immediate\write\examples{bpp.first.pt.dotlabel("$i_0$", "rt"); }
\immediate\write\examples{Point C(0, 2, 0);}
\immediate\write\examples{Point D(0, -3.5, 0);}
\immediate\write\examples{C *= D.rotate(2, 0, -5);}
\immediate\write\examples{C *= D.shift(e.get_point(4));}
\immediate\write\examples{C.dotlabel("$C$"); }
\immediate\write\examples{D.dotlabel("$D$", "bot"); }
\immediate\write\examples{C.draw(D, black, "evenly");}
\immediate\write\examples{bpp = e.intersection_points(C, D);}
\immediate\write\examples{bpp.first.pt.dotlabel("$i_1$", "rt"); }
\OEX{}
\EEX 1
\fi
\PEX
@end tex
@end iftex

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

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

@c

In @NEXTFIG{}, @math{q} and @math{e} are coplanar.  In this case, 
only the intersections of @math{q} with the perimeter of @math{e} are returned by
@code{intersection_points()}.

@example
@group 
A = p0.mediate(e.get_point(3), 1.5);
B = p0.mediate(e.get_point(11), 1.5);
Path q(A, B);
bpp = e.intersection_points(q);
@end group
@end example

@c
@iftex
@tex
\ifmakeexamples
\BEX
\immediate\write\examples{e.draw();}
\immediate\write\examples{p0.label("$e$");}
\immediate\write\examples{A = p0.mediate(e.get_point(3), 1.5);}
\immediate\write\examples{B = p0.mediate(e.get_point(11), 1.5);}
\immediate\write\examples{Path q(A, B);} 
\immediate\write\examples{q.get_point(0).dotlabel("$q_0$", "rt"); }
\immediate\write\examples{q.get_point(1).dotlabel("$q_1$", "lft"); }
\immediate\write\examples{q.draw(black, "evenly");}
\immediate\write\examples{bpp = e.intersection_points(q);} 
\immediate\write\examples{bpp.first.pt.dotlabel("$i_0$"); }
\immediate\write\examples{bpp.second.pt.dotlabel("$i_1$", "ulft"); }
\OEX{}
\EGRP
\EEX 1
\fi
\PEX
@end tex
@end iftex

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

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

@c

@end deftypefn


@node Regular Closed Plane Curve Segments,  , Regular Closed Plane Curve Intersections, Regular Closed Plane Curve Reference
@section Segments

@deftypefn {@code{const} function} Path segment ({unsigned int} @var{factor}, [real @var{angle} = 0, [bool @var{closed} = @code{true}]])
Returns a @code{Path} representing a segment of the @code{Reg_Cl_Plane_Curve}.
@var{factor} must be 
@math{>1} and @math{<=} @code{number_of_points}.  If it is not, an error message is
issued and an empty @code{Path} is returned.

If @var{angle} is non-zero, the segment @code{Path} is rotated by
@var{angle} about a line from @code{center} in the direction of the
normal to the plane of the @code{Reg_Cl_Plane_Curve}.  
Please note, that a @code{Reg_Cl_Plane_Curve} must have a meaningful
@code{center}, in order for rotation to work.
If the absolute value of
@var{angle} @math{>360}, a warning is issued, and 
@code{fmod(@var{angle}, 360)} is used.

If @var{closed} is @code{true}, the @code{Path} will be a cycle, with
the ends of the curved segment joined using the connector @samp{--}.
The curved segment is joined to the line using @samp{&} on each side.

@example
Circle c(origin, 4, 30, 30, 30);
Path p = c.segment(3, 130);
p.show("p:");
@print{} p:
points.size() == 8
connectors.size() == 8(-0.00662541, -0.888379, -1.79185) .. 
(0.741088, -0.673392, -1.73128) ..  
(1.37598, -0.355887, -1.40714) .. 
(1.80139, 0.0157987, -0.868767) .. 
(1.95255, 0.385079, -0.198137) .. (1.80646, 0.695735, 0.502658) & 
(1.80646, 0.695735, 0.502658) -- 
(-0.00662541, -0.888379, -1.79185) & cycle;
@end example

@c
@iftex
@tex
\ifmakeexamples
\BEX
\BGRP
\immediate\write\examples{default_focus.set(2, 5, -10, 2, 5, 10, 10); }
\immediate\write\examples{Circle c(origin, 4, 30, 30, 30);}
\immediate\write\examples{c.draw();}
\immediate\write\examples{origin.label("$c$", "");}
\immediate\write\examples{Path p = c.segment(3, 130);}
\immediate\write\examples{(.75 * p.get_point(2)).label("$p$", "rt");}
\immediate\write\examples{p.filldraw(black, light_gray, "", "pencircle scaled .75mm");}
\OEX{}
\EGRP
\EEX 1
\fi
\PEX
@end tex
@end iftex

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

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

@c
@end deftypefn 

@deftypefn {@code{const} inline function} Path half ([real @var{angle} = 0, [bool @var{closed} = true]])
Returns a @code{Path} using half of the @code{Points} on the
@code{Reg_Cl_Plane_Curve}.
The effect of the arguments @var{angle} and @var{closed} is similar to
that in @code{segment()}, above.

@example
Ellipse e(origin, 3, 5, 20, 15, 12.5);
Path p = e.half(0, false);
@end example

@c
@iftex
@tex
\ifmakeexamples
\BEX
\BGRP
\immediate\write\examples{default_focus.set(3, 5, -10, 3, 3, 10, 10); }
\immediate\write\examples{Ellipse e(origin, 3, 5, 20, 15, 12.5);}
\immediate\write\examples{e.fill(light_gray);}
\immediate\write\examples{origin.label("$e$", "");}
\immediate\write\examples{Path p = e.half(0, false);}
\immediate\write\examples{p.get_point(p.get_size() / 2).label("$p$");}
\immediate\write\examples{p.draw(black, "", "pencircle scaled .75mm");}
\OEX{}
\EGRP
\EEX 1
\fi
\PEX
@end tex
@end iftex

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

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

@c

@end deftypefn 

@deftypefn {@code{const} inline function} Path quarter ([real @var{angle} = 0, [bool @var{closed} = @code{true}]])
Returns a @code{Path} using a quarter of the @code{Points} on the
@code{Reg_Cl_Plane_Curve}.
The effect of the arguments @var{angle} and @var{closed} is similar to
that in @code{segment()}, above.

@example
Ellipse e(origin, 3, 5, 60, 5, 2.5);
Path p = e.quarter(180, false);
@end example

@c
@iftex
@tex
\ifmakeexamples
\BEX
\BGRP
\immediate\write\examples{default_focus.set(3, 5, -10, 3, 3, 10, 10); }
\immediate\write\examples{Ellipse e(origin, 3, 5, 60, 5, 2.5);}
\immediate\write\examples{e.fill(light_gray);}
\immediate\write\examples{origin.label("$e$", "");}
\immediate\write\examples{Path p = e.quarter(180, false);}
\immediate\write\examples{p.get_point(p.get_size() / 2).label("$p$", "llft");}
\immediate\write\examples{p.draw(black, "", "pencircle scaled .75mm");}
\OEX{} 
\EGRP
\EEX 1
\fi
\PEX  
@end tex
@end iftex

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

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

@c
@end deftypefn 


