@c picture.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: picture.texi,v 1.6 2004/01/12 18:40:10 lfinsto1 Exp lfinsto1 $
  
@node Picture Reference, Point Reference, Label Reference, Top
@chapter Picture Reference


@tindex Picture
Class @code{Picture} is defined in @file{pictures.web}.

@menu
* Picture Data Members::        
* Picture Global Variables::    
* Picture Constructors::        
* Picture Operators::           
* Affine Transformations for Pictures::  
* Modifying Pictures::          
* Showing Pictures::            
* Outputting Pictures::         
@end menu

@node Picture Data Members, Picture Global Variables, Picture Reference, Picture Reference
@section Data Members

@deftypevr {Private variable} Transform transform
Applied to the @code{Shapes} on the @code{Picture} when the latter is
output.  It is initialized as the identity @code{Transform}, and can be
modified by the transformation functions, by 
@code{Picture::operator*=(const Transform&)}
(@pxref{Picture Operators,,Picture Reference; Operators}), and by
@code{Picture::set_transform()} 
(@pxref{Modifying Pictures,,Picture Reference; Modifying}).  
@end deftypevr

@deftypevr {Private variable} {vector<Shape*>} shapes
Contains pointers to the @code{Shapes} on the @code{Picture}. 
When a drawing or filling function is invoked for a @code{Shape}, a copy
is dynamically allocated and a pointer to the copy is placed onto
@code{shapes}.  
@end deftypevr

@deftypevr {Private variable} vector<Label*> labels
Contains pointers to the @code{Labels} on the @code{Picture}.  When a
@code{Point} is labelled, either directly or through a call to
@code{label()} or @code{dotlabel()} for another type of 
@code{Shape}@footnote{@code{label()} and @code{dotlabel()}
are currently only defined for @code{Point} and @code{Path} (and the
latter's derived classes), i.e., not for @code{Solid} and its derived
classes.},
@c 
a @code{Label} is dynamically allocated, the @code{Point} is copied to 
@code{*Label::pt}, and a pointer to the @code{Label} is placed onto 
@code{labels}.
@end deftypevr

@deftypevr {Private variable} bool do_labels
Used for enabling or disabling output of @code{Labels} when outputting a
@code{Picture}.  The default value is @code{true}.  It is set to
@code{false} by using @code{suppress_labels()} and can be reset to
@code{true} by using @code{unsuppress_labels()}.  
@xref{Picture Output Functions, , Picture Reference; Output Functions}.  

Often, when a @code{Picture} is copied, transformed, and output again in
a single figure, it's undesirable to have the @code{Labels} output again
in their new positions.  To avoid this, use @code{suppress_labels()}
after outputting the @code{Picture} the first time.
@end deftypevr

@node Picture Global Variables, Picture Constructors, Picture Data Members, Picture Reference
@section Global Variables

@deftypevar Variable Picture current_picture
The @code{Picture} used as the default by the drawing and filling
functions. 
@end deftypevar 


@node Picture Constructors, Picture Operators, Picture Global Variables, Picture Reference
@section Constructors

@c !! Change text for all default constructors, as below.
@deftypefn {Default constructor} void Picture (void)
Creates an empty @code{Picture}.
@end deftypefn

@deftypefn {Copy constructor} void Picture ({const Picture&} @var{p})
Creates a copy of @code{Picture} @var{p}.

@example
Circle c(origin, 3);
c.draw();
current_picture.output(Projections::PARALLEL_X_Z);
Picture new_picture(current_picture);
new_picture.shift(2);
new_picture.output(Projections::PARALLEL_X_Z);
@end example

@iftex
@tex
\ifmakeexamples
\BEX
\immediate\write\examples{Circle c(origin, 3);} 
\immediate\write\examples{c.draw();}
\immediate\write\examples{Picture new_picture(current_picture);}
\immediate\write\examples{new_picture.shift(2);}
\immediate\write\examples{new_picture.output(Projections::PARALLEL_X_Z);}
%% Labels.
\immediate\write\examples{Point p1(c.get_point(8));}
\immediate\write\examples{Point p0(p1);}
\immediate\write\examples{p0.shift(-1);}
\immediate\write\examples{p0.dotlabel("current@UBAR picture", "ulft");}
\immediate\write\examples{p0.drawarrow(p1);}
\immediate\write\examples{Point p2(c.get_point(0));}
\immediate\write\examples{p2.shift(2);}  %% This shift must be the same as the
                              %% shift applied to new_picture above!
\immediate\write\examples{Point p3(p2); p3.shift(1);} 
\immediate\write\examples{p3.drawarrow(p2);} 
\immediate\write\examples{p3.dotlabel("new@UBAR picture", "urt");} 
\OEX{Projections::PARALLEL_X_Z}
\EEX 1
\fi
\PEX
@end tex
@end iftex

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

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

@end deftypefn

@node Picture Operators, Affine Transformations for Pictures, Picture Constructors, Picture Reference
@section Operators

@deftypefn {Assignment operator} void operator= ({const Picture&} @var{p})
Makes @code{*this} a copy of @var{p}, destroying the old contents of @code{*this}.
@end deftypefn

@deftypefn {Operator} void operator+= ({const Picture&} @var{p})
Adds the contents of @var{p} to @code{*this}.  @var{p} remains unchanged.
@end deftypefn



@deftypefn {Operator} void operator+= (Shape* @var{s})
Puts @var{s} onto @code{shapes}.  Note that the pointer @var{s}
itself is put onto @code{shapes}, so any allocation and copying must be
performed first.  This is a low-level function that users normally won't
need to use directly.
@end deftypefn


@deftypefn {Operator} void operator+= (Label* @var{label})
Puts @var{label} onto @code{labels}.
Note that the pointer @var{label}
itself is put onto @code{labels}, so any allocation and copying must be
performed first.  This is a low-level function that users normally won't
need to invoke directly.
@end deftypefn

@deftypefn Operator Transform operator*= ({const Transform&} @var{t}) 
Multiplies @code{transform} by @var{t}.  This has the effect of
transforming all of the @code{Shapes} on @code{shapes} and all of
the @code{Points} of the @code{Labels} on @code{labels} by @var{t} upon
output. 

@example
Transform t;
t.rotate(0, 0, 180);
t.shift(3);
Reg_Polygon pl(origin, 5, 3, 90);
pl.draw();
pl.label();
current_picture.output(Projections::PARALLEL_X_Y);
current_picture *= t;
current_picture.output(Projections::PARALLEL_X_Y);
@end example

@iftex
@tex
\ifmakeexamples
\BEX
\immediate\write\examples{Transform t;}
\immediate\write\examples{t.rotate(0, 0, 180);}
\immediate\write\examples{t.shift(5);}
\immediate\write\examples{Reg_Polygon pl(origin, 5, 3, 90);^^Jpl.draw();}
\immediate\write\examples{pl.label();} 
\OEX{Projections::PARALLEL_X_Y}
\immediate\write\examples{current_picture *= t;} 
\OEX{Projections::PARALLEL_X_Y}
\EEX 1
\fi
\PEX
@end tex
@end iftex

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

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

@end deftypefn


@node Affine Transformations for Pictures, Modifying Pictures, Picture Operators, Picture Reference
@section Affine Transformations 
The functions in this section all operate on the @code{transform} data
member of the @code{Picture} and return a @code{Transform} representing the
transformation---@emph{not} @code{transform}.


@deftypefun Transform scale (real @var{x}, [real @var{y} = 1, [real @var{z} = 1]])
Performs @code{transform.scale(@var{x}, @var{y}, @var{z})} and returns 
the result.  This has the effect of scaling 
all of the elements of @code{shapes} and @code{labels}.
@end deftypefun

@deftypefun Transform shift (real @var{}x, [real @var{y} = 0, [real @var{z} = 0]])
Performs @code{transform.shift(@var{x}, @var{y}, @var{z})} and returns 
the result.  This has the effect of shifting
all of the @code{Shapes} and @code{Labels} on the @code{Picture}.
@end deftypefun

@deftypefun Transform shift ({const Point&} @var{p})
Performs @code{transform.shift(@var{p})} and returns 
the result.  This has the effect of shifting
all of the @code{Shapes} and @code{Labels} on the @code{Picture} by the
x, y, and z-coordinates of @var{p}.
@end deftypefun

@deftypefun Transform rotate ({const real} @var{x}, [{const real} @var{y} = 0, [{const real} @var{z} = 0]])
Performs @code{transform.rotate(@var{x}, @var{y}, @var{z})} and returns 
the result.  This has the effect of rotating
all of the elements of @code{shapes} and @code{labels}.
@end deftypefun

@deftypefun Transform rotate ({const Point&} @var{p0}, {const Point&} @var{p1}, [{const real} @var{angle} = 180]);
Performs @code{transform.rotate(@var{p0}, @var{p1}, @var{angle})} and returns 
the result.  This has the effect of rotating
all of the elements of @code{shapes} and @code{labels} about the line 
@iftex
@tex
$\overrightarrow{p_0p_1}$.
@end tex
@end iftex
@c
@ifnottex 
from @math{p_0} to @math{p_1}.
@end ifnottex 
@c
@end deftypefun

@node Modifying Pictures, Showing Pictures, Affine Transformations for Pictures, Picture Reference
@section Modifying

@deftypefun void clear (void)
Destroys the @code{Shapes} and @code{Labels} on the
@code{Picture} and removes all the @code{Shape} pointers from
@code{shapes} and the @code{Label} pointers from @code{labels}.  
All dynamically allocated objects are deallocated, namely the
@code{Shapes}, the @code{Labels}, and the @code{Points} belonging to the
@code{Labels}. @code{transform} is reset to the identity @code{Transform}.  
@end deftypefun

@deftypefun void reset_transform (void)
Resets @code{transform} to the identity @code{Transform}.  
@end deftypefun

@deftypefun Transform set_transform ({const Transform&} @var{t})
Sets @code{transform} to @code{t} and returns @code{t}.  
@end deftypefun

@deftypefun void kill_labels (void)
Removes the @code{Labels} from the @code{Picture}.  
@end deftypefun 

@node Showing Pictures, Outputting Pictures, Modifying Pictures, Picture Reference
@section Showing 

@deftypefun void show ([string @var{text} = "", [bool @var{stop} = @code{false}]])
Prints information about the @code{Picture} to standard output.

@code{show()} first prints the string @code{"Showing Picture:"} to
standard output, followed by @var{text}, if the latter is not the empty 
string (@code{""})@footnote{Actually, it's printed to standard output
even if it is the empty string, you just don't see it.}.
@c
Then it calls @code{transform.show()}, prints the size of @code{shapes} and
@code{labels}, and the value of @code{do_labels}.  Then it calls
@code{show()} on each of the @code{Shapes} on @code{shapes}.  Since
@code{show()} is a @code{virtual} function in @code{class Shape}, the
appropriate @code{show()} is called for each @code{Shape}, i.e.,
@code{Point::show()} for a @code{Point}, @code{Path::show()} for a
@code{Path}, etc.  If @var{stop} is @code{true}, execution stops and the
user is requested to type <RETURN> to continue.  Finally, the string
@code{"Done showing picture."} is printed to standard output.
@end deftypefun

@deftypefun void show_transform ([string @var{text} = "Transform from Picture:"])
Calls @code{transform.show()}, passing @var{text} as the argument to the
latter function.
@end deftypefun

@node Outputting Pictures,  , Showing Pictures, Picture Reference
@section Outputting 

@menu
* Picture Output Namespaces::   
* Picture Output Functions::    
@end menu

@node Picture Output Namespaces, Picture Output Functions, Outputting Pictures, Outputting Pictures
@subsection Namespaces

@menu
* Namespace Projections::       
* Namespace Sorting::           
@end menu
 
@node Namespace Projections, Namespace Sorting, Picture Output Namespaces, Picture Output Namespaces
@subsubsection Namespace Projections

The namespace @code{Projections} is defined in @file{pictures.web}.  

@deftypevr  {Constant} {const unsigned short} PERSP
@deftypevrx {Constant} {const unsigned short} PARALLEL_X_Y
@deftypevrx {Constant} {const unsigned short} PARALLEL_X_Z
@deftypevrx {Constant} {const unsigned short} PARALLEL_Z_Y
@deftypevrx {Constant} {const unsigned short} AXON
@deftypevrx {Constant} {const unsigned short} ISO 
These constants can be used for the @var{projection} argument in
@code{Picture::output()}, described in 
@ref{Picture Output Functions,,Picture Reference; Outputting; Functions}, 
below.  
@end deftypevr

@node Namespace Sorting,  , Namespace Projections, Picture Output Namespaces
@subsubsection Namespace Sorting

The namespace @code{Sorting} is defined in @file{pictures.web}.  

@deftypevr   {Constant} {const unsigned short} NO_SORT
@deftypevrx  {Constant} {const unsigned short} MAX_Z  
@deftypevrx  {Constant} {const unsigned short} MIN_Z  
@deftypevrx  {Constant} {const unsigned short} MEAN_Z 
These constants can be used for the @var{sort_value} argument in
@code{Picture::output()}, described in 
@ref{Picture Output Functions,,Picture Reference; Outputting; Functions}, 
below.
@end deftypevr

@node Picture Output Functions,  , Picture Output Namespaces, Outputting Pictures
@subsection Output Functions
@deftypefun void output ({const Focus&} @var{f}, [{const unsigned short} @var{projection} = @code{Projections::PERSP}, [real @var{factor} = 1, [{const unsigned short} @var{sort_value} = @code{Sorting::MAX_Z}, [{const bool} @var{do_warnings} = @code{true}, [{const real} @var{min_x_proj} = -40, [{const real} @var{max_x_proj} = 40, [{const real} @var{min_y_proj} = -40, [{const real} @var{max_y_proj} = 40, [{const real} @var{min_z_proj} = -40, [{const real} @var{max_z_proj} = 40]]]]]]]]]])
@c
@deftypefunx void output ([{const unsigned short} @var{projection} = @code{Projections::PERSP}, [real @var{factor} = 1, [{const unsigned short} @var{sort_value} = @code{Sorting::MAX_Z}, [{const bool} @var{do_warnings} = @code{true}, [{const real} @var{min_x_proj} = -40, [{const real} @var{max_x_proj} = 40, [{const real} @var{min_y_proj} = -40, [{const real} @var{max_y_proj} = 40, [{const real} @var{min_z_proj} = -40, [{const real} @var{max_z_proj} = 40]]]]]]]]]])
@c
These functions create a two-dimensional projection of the objects on the
@code{Picture} and write MetaPost code to @code{out_stream} for
drawing it.


The arguments:

@table @asis
@item @code{const Focus&} @var{f}
The @code{Focus} used for projection, also known as the center of
projection, or the camera.
This argument is used in the first version only.
The second version, without a @code{const Focus&} @var{f} argument,
merely calls the first version and passes it the global variable
@code{default_focus} as its first argument, so @code{default_focus} is
effectively the default for @var{f}.  Defining two versions in this way makes it
possible to call 
@code{output()} with @code{projection} as its first (and possibly only)
argument.  If instead, @var{f} were an optional argument with
@code{default_focus} as its default, this wouldn't have been possible.  It
also wouldn't be possible to have @var{f} have a default in the first
version, and to retain the second version, because the compiler wouldn't
be able to resolve a call to @code{output()} with no arguments.

@item @code{const unsigned short} @var{projection}
Default: @code{Projections::PERSP}.
The type of projection.  Valid values are @code{const unsigned shorts}
defined in @code{namespace Projections} 
(@pxref{Namespace Projections}):@*
@code{PERSP} for the perspective projection,@* 
@code{PARALLEL_X_Y} for parallel projection onto the x-y plane,@*
@code{PARALLEL_X_Z} for parallel projection onto the x-z plane, and@*
@code{PARALLEL_Z_Y} for parallel projection onto the z-y plane.
%% !! TO DO:  
I plan to add isometric and axionometric projections soon.


@item @code{real} @var{factor}
Default: 1.
Passed from @code{output()} to
@code{extract()} and from there to @code{project()}.  The
@code{world_coordinates} of the @code{Points} that are projected are 
multiplied by @var{factor}, which enlarges or shrinks the projected
image without altering the @code{Picture} itself.  @var{factor}
is probably most useful for parallel projections, where the @code{Focus}
@var{f} isn't used;  with a perspective projection, the parameters of
the @code{Focus} can be used to influence the size of the projected
image. 

@item @code{const unsigned short} @var{sort_value}
Default: @code{Sorting::MAX_Z}.
The value used should be one of the constants defined in 
@code{namespace Sorting}, @xref{Namespace Sorting}, above.
If @code{MAX_Z} (the default) is used, the @code{Shapes} on the
@code{Picture} are sorted according to the maximum z-value of the
@code{projective_extremes} of the @code{Points} belonging to the
@code{Shape}.  If @code{MIN_Z} is used, 
they are sorted according to the minimum z-value, and 
if @code{MEAN_Z} is used, they are sorted according to the  mean of 
the maximum and minimum z-values.  If @code{NO_SORT} is used, the
@code{Shapes} are output in the order in which they were put onto the
@code{Picture}. 


The surface hiding algorithm
implemented in 3DLDF is quite primitive, and doesn't always work right.
For @code{Shapes} that intersect, it @emph{can't} work right.  
@c !! TO DO: 
I plan to work on improving the surface hiding algorithm soon.  This is
not a trivial problem.  To solve it properly, each @code{Shape} on a
@code{Picture} must be tested for intersection with every other
@code{Shape} on the @code{Picture}.  If two or more @code{Shapes} intersect,
they must be broken up into smaller objects until there are no more 
intersections.  I don't expect to have a proper solution soon, but I
expect that I will be able to make some improvements.
@xref{Surface Hiding}.

@item @code{const bool} @var{do_warnings}
Default: @code{true}.  If @code{true}, @code{output()} issues warnings
to @code{stderr} (standard error output) if a @code{Shape} cannot be
output because it lies 
outside the limits set by the following arguments.  Sometimes, a user
may only want to project a portion of a @code{Picture}, in which case
such warnings would not be helpful.  In this case, @var{do_warnings}
should be @code{false}.

@item @code{const real} @var{min_x_proj}
Default: -40.  The minimum x-coordinate of the projection of a
@code{Shape} such that the @code{Shape} can be output.  
If @code{projective_coordinates[0]} of any @code{Point} on a 
@code{Shape} is less than @var{min_x_proj}, the @code{Shape} will not be
projected at all. 

@item @code{const real} @var{max_x_proj}
Default: 40. 
The maximum x-coordinate of the projection of a
@code{Shape} such that the @code{Shape} can be output.  
If @code{projective_coordinates[0]} of any @code{Point} on a 
@code{Shape} is greater than @var{max_x_proj}, the @code{Shape} will not be
projected at all.

@item @code{const real} @var{min_y_proj}
Default: -40.
The minimum y-coordinate of the projection of a
@code{Shape} such that the @code{Shape} can be output.  
If @code{projective_coordinates[1]} of any @code{Point} on a 
@code{Shape} is less than @var{min_y_proj}, the @code{Shape} will not be
projected at all.

@item @code{const real} @var{max_y_proj}
Default: 40.
The maximum y-coordinate of the projection of a
@code{Shape} such that the @code{Shape} can be output.  
If @code{projective_coordinates[1]} of any @code{Point} on a 
@code{Shape} is greater than @var{max_y_proj}, the @code{Shape} will not be
projected at all.


@item @code{const real} @var{min_z_proj}
Default: -40.
The minimum z-coordinate of the projection of a
@code{Shape} such that the @code{Shape} can be output.  
If @code{projective_coordinates[2]} of any @code{Point} on a 
@code{Shape} is less than @var{min_z_proj}, the @code{Shape} will not be
projected at all.

@item @code{const real} @var{max_z_proj}
Default: 40.
The maximum z-coordinate of the projection of a
@code{Shape} such that the @code{Shape} can be output.  
If @code{projective_coordinates[2]} of any @code{Point} on a 
@code{Shape} is greater than @var{max_z_proj}, the @code{Shape} will not be
projected at all.
@end table
@end deftypefun

@deftypefun void suppress_labels (void)
Suppresses output of the @code{Labels} on a @code{Picture} when
@code{output()} is called.  This can be useful when a @code{Picture} is
output, transformed, and output again, one or more times, in a single figure.
Usually, it will not be desirable to have the @code{Labels} output more
than once.

In @NEXTFIG{}, @code{current_picture} is output three times, but the
@code{Labels} on it are only output once.

@example
Ellipse e(origin, 3, 5);
e.label();
e.draw();
Point pt0(-3);
Point pt1(3);
pt0.draw(pt1);
Point pt2(0, 0, -4);
Point pt3(0, 0, 4);
pt2.draw(pt3);
pt0.dotlabel("0", "lft");
pt1.dotlabel("1", "rt");
pt2.dotlabel("2", "bot");
pt3.dotlabel("3");
current_picture.output(Projections::PARALLEL_X_Z);
current_picture.rotate(0, 60);
current_picture.suppress_labels();
current_picture.output(Projections::PARALLEL_X_Z);
current_picture.rotate(0, 60);
current_picture.output(Projections::PARALLEL_X_Z);
@end example

@iftex
@tex 
\ifmakeexamples
\BEX
\immediate\write\examples{Ellipse e(origin, 3, 5);}
\immediate\write\examples{e.label();}
\immediate\write\examples{e.draw();}
\immediate\write\examples{Point pt0(-3);}
\immediate\write\examples{Point pt1(3);}
\immediate\write\examples{pt0.draw(pt1);}
\immediate\write\examples{Point pt2(0, 0, -4);}
\immediate\write\examples{Point pt3(0, 0, 4);}
\immediate\write\examples{pt2.draw(pt3);}
\immediate\write\examples{pt0.dotlabel("0", "lft");}
\immediate\write\examples{pt1.dotlabel("1", "rt");}
\immediate\write\examples{pt2.dotlabel("2", "bot");}
\immediate\write\examples{pt3.dotlabel("3");}
\immediate\write\examples{current_picture.output(Projections::PARALLEL_X_Z);}
\immediate\write\examples{current_picture.rotate(0, 60);}
\immediate\write\examples{current_picture.suppress_labels();}
\immediate\write\examples{current_picture.output(Projections::PARALLEL_X_Z);}
\immediate\write\examples{current_picture.rotate(0, 60);}
\immediate\write\examples{current_picture.output(Projections::PARALLEL_X_Z);}
%%
%% LDF 2003.01.19.  !! I neglected to unsuppress the labels at first.
%% It took me maybe 45 minutes to find out why my labels in the next
%% example weren't being printed!
%%
\immediate\write\examples{current_picture.unsuppress_labels();} 
\EEX 1
\fi
\PEX  
@end tex
@end iftex

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

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

@end deftypefun

@deftypefn {Inline function} void unsuppress_labels (void)
Sets @code{do_labels} to @code{true}.  If a @code{Picture} contains
@code{Labels}, @code{unsuppress_labels()} ensures that they will be
output, when @code{Picture::output()} is called, so long as there is no
intervening call to @code{suppress_labels()} or @code{kill_labels()}.  
@end deftypefn


