3
@c This file is part of the 3DLDF User and Reference Manual.
4
@c Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 The Free Software Foundation
5
@c See the section "GNU Free Documentation License" in the file
6
@c fdl.texi for copying conditions.
9
@node Picture Reference, Point Reference, Label Reference, Top
10
@chapter Picture Reference
14
Class @code{Picture} is defined in @file{pictures.web}.
17
* Picture Data Members::
18
* Picture Global Variables::
19
* Picture Constructors::
21
* Affine Transformations for Pictures::
22
* Modifying Pictures::
24
* Outputting Pictures::
27
@node Picture Data Members, Picture Global Variables, Picture Reference, Picture Reference
30
@deftypevr {Private variable} Transform transform
31
Applied to the @code{Shapes} on the @code{Picture} when the latter is
32
output. It is initialized as the identity @code{Transform}, and can be
33
modified by the transformation functions, by
34
@code{Picture::operator*=(const Transform&)}
35
(@pxref{Picture Operators,,Picture Reference; Operators}), and by
36
@code{Picture::set_transform()}
37
(@pxref{Modifying Pictures,,Picture Reference; Modifying}).
40
@deftypevr {Private variable} {vector<Shape*>} shapes
41
Contains pointers to the @code{Shapes} on the @code{Picture}.
42
When a drawing or filling function is invoked for a @code{Shape}, a copy
43
is dynamically allocated and a pointer to the copy is placed onto
47
@deftypevr {Private variable} vector<Label*> labels
48
Contains pointers to the @code{Labels} on the @code{Picture}. When a
49
@code{Point} is labelled, either directly or through a call to
50
@code{label()} or @code{dotlabel()} for another type of
51
@code{Shape}@footnote{@code{label()} and @code{dotlabel()}
52
are currently only defined for @code{Point} and @code{Path} (and the
53
latter's derived classes), i.e., not for @code{Solid} and its derived
56
a @code{Label} is dynamically allocated, the @code{Point} is copied to
57
@code{*Label::pt}, and a pointer to the @code{Label} is placed onto
61
@deftypevr {Private variable} bool do_labels
62
Used for enabling or disabling output of @code{Labels} when outputting a
63
@code{Picture}. The default value is @code{true}. It is set to
64
@code{false} by using @code{suppress_labels()} and can be reset to
65
@code{true} by using @code{unsuppress_labels()}.
66
@xref{Picture Output Functions, , Picture Reference; Output Functions}.
68
Often, when a @code{Picture} is copied, transformed, and output again in
69
a single figure, it's undesirable to have the @code{Labels} output again
70
in their new positions. To avoid this, use @code{suppress_labels()}
71
after outputting the @code{Picture} the first time.
74
@node Picture Global Variables, Picture Constructors, Picture Data Members, Picture Reference
75
@section Global Variables
77
@deftypevar Variable Picture current_picture
78
The @code{Picture} used as the default by the drawing and filling
83
@node Picture Constructors, Picture Operators, Picture Global Variables, Picture Reference
86
@c !! Change text for all default constructors, as below.
87
@deftypefn {Default constructor} void Picture (void)
88
Creates an empty @code{Picture}.
91
@deftypefn {Copy constructor} void Picture ({const Picture&} @var{p})
92
Creates a copy of @code{Picture} @var{p}.
97
current_picture.output(Projections::PARALLEL_X_Z);
98
Picture new_picture(current_picture);
100
new_picture.output(Projections::PARALLEL_X_Z);
107
\immediate\write\examples{Circle c(origin, 3);}
108
\immediate\write\examples{c.draw();}
109
\immediate\write\examples{Picture new_picture(current_picture);}
110
\immediate\write\examples{new_picture.shift(2);}
111
\immediate\write\examples{new_picture.output(Projections::PARALLEL_X_Z);}
113
\immediate\write\examples{Point p1(c.get_point(8));}
114
\immediate\write\examples{Point p0(p1);}
115
\immediate\write\examples{p0.shift(-1);}
116
\immediate\write\examples{p0.dotlabel("current@UBAR picture", "ulft");}
117
\immediate\write\examples{p0.drawarrow(p1);}
118
\immediate\write\examples{Point p2(c.get_point(0));}
119
\immediate\write\examples{p2.shift(2);} %% This shift must be the same as the
120
%% shift applied to new_picture above!
121
\immediate\write\examples{Point p3(p2); p3.shift(1);}
122
\immediate\write\examples{p3.drawarrow(p2);}
123
\immediate\write\examples{p3.dotlabel("new@UBAR picture", "urt");}
124
\OEX{Projections::PARALLEL_X_Z}
135
<img src="./graphics/png/3DLDF77.png"
136
alt="[Figure 77. Not displayed.]"
147
[Figure 77 not displayed.]
152
@node Picture Operators, Affine Transformations for Pictures, Picture Constructors, Picture Reference
155
@deftypefn {Assignment operator} void operator= ({const Picture&} @var{p})
156
Makes @code{*this} a copy of @var{p}, destroying the old contents of @code{*this}.
159
@deftypefn {Operator} void operator+= ({const Picture&} @var{p})
160
Adds the contents of @var{p} to @code{*this}. @var{p} remains unchanged.
165
@deftypefn {Operator} void operator+= (Shape* @var{s})
166
Puts @var{s} onto @code{shapes}. Note that the pointer @var{s}
167
itself is put onto @code{shapes}, so any allocation and copying must be
168
performed first. This is a low-level function that users normally won't
169
need to use directly.
173
@deftypefn {Operator} void operator+= (Label* @var{label})
174
Puts @var{label} onto @code{labels}.
175
Note that the pointer @var{label}
176
itself is put onto @code{labels}, so any allocation and copying must be
177
performed first. This is a low-level function that users normally won't
178
need to invoke directly.
181
@deftypefn Operator Transform operator*= ({const Transform&} @var{t})
182
Multiplies @code{transform} by @var{t}. This has the effect of
183
transforming all of the @code{Shapes} on @code{shapes} and all of
184
the @code{Points} of the @code{Labels} on @code{labels} by @var{t} upon
191
Reg_Polygon pl(origin, 5, 3, 90);
194
current_picture.output(Projections::PARALLEL_X_Y);
195
current_picture *= t;
196
current_picture.output(Projections::PARALLEL_X_Y);
203
\immediate\write\examples{Transform t;}
204
\immediate\write\examples{t.rotate(0, 0, 180);}
205
\immediate\write\examples{t.shift(5);}
206
\immediate\write\examples{Reg_Polygon pl(origin, 5, 3, 90);^^Jpl.draw();}
207
\immediate\write\examples{pl.label();}
208
\OEX{Projections::PARALLEL_X_Y}
209
\immediate\write\examples{current_picture *= t;}
210
\OEX{Projections::PARALLEL_X_Y}
221
<img src="./graphics/png/3DLDF78.png"
222
alt="[Figure 78. Not displayed.]"
233
[Figure 78 not displayed.]
239
@node Affine Transformations for Pictures, Modifying Pictures, Picture Operators, Picture Reference
240
@section Affine Transformations
241
The functions in this section all operate on the @code{transform} data
242
member of the @code{Picture} and return a @code{Transform} representing the
243
transformation---@emph{not} @code{transform}.
246
@deftypefun Transform scale (real @var{x}, [real @var{y} = 1, [real @var{z} = 1]])
247
Performs @code{transform.scale(@var{x}, @var{y}, @var{z})} and returns
248
the result. This has the effect of scaling
249
all of the elements of @code{shapes} and @code{labels}.
252
@deftypefun Transform shift (real @var{}x, [real @var{y} = 0, [real @var{z} = 0]])
253
Performs @code{transform.shift(@var{x}, @var{y}, @var{z})} and returns
254
the result. This has the effect of shifting
255
all of the @code{Shapes} and @code{Labels} on the @code{Picture}.
258
@deftypefun Transform shift ({const Point&} @var{p})
259
Performs @code{transform.shift(@var{p})} and returns
260
the result. This has the effect of shifting
261
all of the @code{Shapes} and @code{Labels} on the @code{Picture} by the
262
x, y, and z-coordinates of @var{p}.
265
@deftypefun Transform rotate ({const real} @var{x}, [{const real} @var{y} = 0, [{const real} @var{z} = 0]])
266
Performs @code{transform.rotate(@var{x}, @var{y}, @var{z})} and returns
267
the result. This has the effect of rotating
268
all of the elements of @code{shapes} and @code{labels}.
271
@deftypefun Transform rotate ({const Point&} @var{p0}, {const Point&} @var{p1}, [{const real} @var{angle} = 180]);
272
Performs @code{transform.rotate(@var{p0}, @var{p1}, @var{angle})} and returns
273
the result. This has the effect of rotating
274
all of the elements of @code{shapes} and @code{labels} about the line
277
$\overrightarrow{p_0p_1}$.
282
from @math{p_0} to @math{p_1}.
287
@node Modifying Pictures, Showing Pictures, Affine Transformations for Pictures, Picture Reference
290
@deftypefun void clear (void)
291
Destroys the @code{Shapes} and @code{Labels} on the
292
@code{Picture} and removes all the @code{Shape} pointers from
293
@code{shapes} and the @code{Label} pointers from @code{labels}.
294
All dynamically allocated objects are deallocated, namely the
295
@code{Shapes}, the @code{Labels}, and the @code{Points} belonging to the
296
@code{Labels}. @code{transform} is reset to the identity @code{Transform}.
299
@deftypefun void reset_transform (void)
300
Resets @code{transform} to the identity @code{Transform}.
303
@deftypefun Transform set_transform ({const Transform&} @var{t})
304
Sets @code{transform} to @code{t} and returns @code{t}.
307
@deftypefun void kill_labels (void)
308
Removes the @code{Labels} from the @code{Picture}.
311
@node Showing Pictures, Outputting Pictures, Modifying Pictures, Picture Reference
314
@deftypefun void show ([string @var{text} = "", [bool @var{stop} = @code{false}]])
315
Prints information about the @code{Picture} to standard output.
317
@code{show()} first prints the string @code{"Showing Picture:"} to
318
standard output, followed by @var{text}, if the latter is not the empty
319
string (@code{""})@footnote{Actually, it's printed to standard output
320
even if it is the empty string, you just don't see it.}.
322
Then it calls @code{transform.show()}, prints the size of @code{shapes} and
323
@code{labels}, and the value of @code{do_labels}. Then it calls
324
@code{show()} on each of the @code{Shapes} on @code{shapes}. Since
325
@code{show()} is a @code{virtual} function in @code{class Shape}, the
326
appropriate @code{show()} is called for each @code{Shape}, i.e.,
327
@code{Point::show()} for a @code{Point}, @code{Path::show()} for a
328
@code{Path}, etc. If @var{stop} is @code{true}, execution stops and the
329
user is requested to type <RETURN> to continue. Finally, the string
330
@code{"Done showing picture."} is printed to standard output.
333
@deftypefun void show_transform ([string @var{text} = "Transform from Picture:"])
334
Calls @code{transform.show()}, passing @var{text} as the argument to the
338
@node Outputting Pictures, , Showing Pictures, Picture Reference
342
* Picture Output Namespaces::
343
* Picture Output Functions::
346
@node Picture Output Namespaces, Picture Output Functions, Outputting Pictures, Outputting Pictures
347
@subsection Namespaces
350
* Namespace Projections::
351
* Namespace Sorting::
354
@node Namespace Projections, Namespace Sorting, Picture Output Namespaces, Picture Output Namespaces
355
@subsubsection Namespace Projections
357
The namespace @code{Projections} is defined in @file{pictures.web}.
359
@deftypevr {Constant} {const unsigned short} PERSP
360
@deftypevrx {Constant} {const unsigned short} PARALLEL_X_Y
361
@deftypevrx {Constant} {const unsigned short} PARALLEL_X_Z
362
@deftypevrx {Constant} {const unsigned short} PARALLEL_Z_Y
363
@deftypevrx {Constant} {const unsigned short} AXON
364
@deftypevrx {Constant} {const unsigned short} ISO
365
These constants can be used for the @var{projection} argument in
366
@code{Picture::output()}, described in
367
@ref{Picture Output Functions,,Picture Reference; Outputting; Functions},
371
@node Namespace Sorting, , Namespace Projections, Picture Output Namespaces
372
@subsubsection Namespace Sorting
374
The namespace @code{Sorting} is defined in @file{pictures.web}.
376
@deftypevr {Constant} {const unsigned short} NO_SORT
377
@deftypevrx {Constant} {const unsigned short} MAX_Z
378
@deftypevrx {Constant} {const unsigned short} MIN_Z
379
@deftypevrx {Constant} {const unsigned short} MEAN_Z
380
These constants can be used for the @var{sort_value} argument in
381
@code{Picture::output()}, described in
382
@ref{Picture Output Functions,,Picture Reference; Outputting; Functions},
386
@node Picture Output Functions, , Picture Output Namespaces, Outputting Pictures
387
@subsection Output Functions
388
@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]]]]]]]]]])
390
@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]]]]]]]]]])
392
These functions create a two-dimensional projection of the objects on the
393
@code{Picture} and write MetaPost code to @code{out_stream} for
400
@item @code{const Focus&} @var{f}
401
The @code{Focus} used for projection, also known as the center of
402
projection, or the camera.
403
This argument is used in the first version only.
404
The second version, without a @code{const Focus&} @var{f} argument,
405
merely calls the first version and passes it the global variable
406
@code{default_focus} as its first argument, so @code{default_focus} is
407
effectively the default for @var{f}. Defining two versions in this way makes it
409
@code{output()} with @code{projection} as its first (and possibly only)
410
argument. If instead, @var{f} were an optional argument with
411
@code{default_focus} as its default, this wouldn't have been possible. It
412
also wouldn't be possible to have @var{f} have a default in the first
413
version, and to retain the second version, because the compiler wouldn't
414
be able to resolve a call to @code{output()} with no arguments.
416
@item @code{const unsigned short} @var{projection}
417
Default: @code{Projections::PERSP}.
418
The type of projection. Valid values are @code{const unsigned shorts}
419
defined in @code{namespace Projections}
420
(@pxref{Namespace Projections}):@*
421
@code{PERSP} for the perspective projection,@*
422
@code{PARALLEL_X_Y} for parallel projection onto the x-y plane,@*
423
@code{PARALLEL_X_Z} for parallel projection onto the x-z plane, and@*
424
@code{PARALLEL_Z_Y} for parallel projection onto the z-y plane.
426
I plan to add isometric and axionometric projections soon.
429
@item @code{real} @var{factor}
431
Passed from @code{output()} to
432
@code{extract()} and from there to @code{project()}. The
433
@code{world_coordinates} of the @code{Points} that are projected are
434
multiplied by @var{factor}, which enlarges or shrinks the projected
435
image without altering the @code{Picture} itself. @var{factor}
436
is probably most useful for parallel projections, where the @code{Focus}
437
@var{f} isn't used; with a perspective projection, the parameters of
438
the @code{Focus} can be used to influence the size of the projected
441
@item @code{const unsigned short} @var{sort_value}
442
Default: @code{Sorting::MAX_Z}.
443
The value used should be one of the constants defined in
444
@code{namespace Sorting}, @xref{Namespace Sorting}, above.
445
If @code{MAX_Z} (the default) is used, the @code{Shapes} on the
446
@code{Picture} are sorted according to the maximum z-value of the
447
@code{projective_extremes} of the @code{Points} belonging to the
448
@code{Shape}. If @code{MIN_Z} is used,
449
they are sorted according to the minimum z-value, and
450
if @code{MEAN_Z} is used, they are sorted according to the mean of
451
the maximum and minimum z-values. If @code{NO_SORT} is used, the
452
@code{Shapes} are output in the order in which they were put onto the
456
The surface hiding algorithm
457
implemented in 3DLDF is quite primitive, and doesn't always work right.
458
For @code{Shapes} that intersect, it @emph{can't} work right.
460
I plan to work on improving the surface hiding algorithm soon. This is
461
not a trivial problem. To solve it properly, each @code{Shape} on a
462
@code{Picture} must be tested for intersection with every other
463
@code{Shape} on the @code{Picture}. If two or more @code{Shapes} intersect,
464
they must be broken up into smaller objects until there are no more
465
intersections. I don't expect to have a proper solution soon, but I
466
expect that I will be able to make some improvements.
467
@xref{Surface Hiding}.
469
@item @code{const bool} @var{do_warnings}
470
Default: @code{true}. If @code{true}, @code{output()} issues warnings
471
to @code{stderr} (standard error output) if a @code{Shape} cannot be
472
output because it lies
473
outside the limits set by the following arguments. Sometimes, a user
474
may only want to project a portion of a @code{Picture}, in which case
475
such warnings would not be helpful. In this case, @var{do_warnings}
476
should be @code{false}.
478
@item @code{const real} @var{min_x_proj}
479
Default: -40. The minimum x-coordinate of the projection of a
480
@code{Shape} such that the @code{Shape} can be output.
481
If @code{projective_coordinates[0]} of any @code{Point} on a
482
@code{Shape} is less than @var{min_x_proj}, the @code{Shape} will not be
485
@item @code{const real} @var{max_x_proj}
487
The maximum x-coordinate of the projection of a
488
@code{Shape} such that the @code{Shape} can be output.
489
If @code{projective_coordinates[0]} of any @code{Point} on a
490
@code{Shape} is greater than @var{max_x_proj}, the @code{Shape} will not be
493
@item @code{const real} @var{min_y_proj}
495
The minimum y-coordinate of the projection of a
496
@code{Shape} such that the @code{Shape} can be output.
497
If @code{projective_coordinates[1]} of any @code{Point} on a
498
@code{Shape} is less than @var{min_y_proj}, the @code{Shape} will not be
501
@item @code{const real} @var{max_y_proj}
503
The maximum y-coordinate of the projection of a
504
@code{Shape} such that the @code{Shape} can be output.
505
If @code{projective_coordinates[1]} of any @code{Point} on a
506
@code{Shape} is greater than @var{max_y_proj}, the @code{Shape} will not be
510
@item @code{const real} @var{min_z_proj}
512
The minimum z-coordinate of the projection of a
513
@code{Shape} such that the @code{Shape} can be output.
514
If @code{projective_coordinates[2]} of any @code{Point} on a
515
@code{Shape} is less than @var{min_z_proj}, the @code{Shape} will not be
518
@item @code{const real} @var{max_z_proj}
520
The maximum z-coordinate of the projection of a
521
@code{Shape} such that the @code{Shape} can be output.
522
If @code{projective_coordinates[2]} of any @code{Point} on a
523
@code{Shape} is greater than @var{max_z_proj}, the @code{Shape} will not be
528
@deftypefun void suppress_labels (void)
529
Suppresses output of the @code{Labels} on a @code{Picture} when
530
@code{output()} is called. This can be useful when a @code{Picture} is
531
output, transformed, and output again, one or more times, in a single figure.
532
Usually, it will not be desirable to have the @code{Labels} output more
535
In @NEXTFIG{}, @code{current_picture} is output three times, but the
536
@code{Labels} on it are only output once.
539
Ellipse e(origin, 3, 5);
548
pt0.dotlabel("0", "lft");
549
pt1.dotlabel("1", "rt");
550
pt2.dotlabel("2", "bot");
552
current_picture.output(Projections::PARALLEL_X_Z);
553
current_picture.rotate(0, 60);
554
current_picture.suppress_labels();
555
current_picture.output(Projections::PARALLEL_X_Z);
556
current_picture.rotate(0, 60);
557
current_picture.output(Projections::PARALLEL_X_Z);
564
\immediate\write\examples{Ellipse e(origin, 3, 5);}
565
\immediate\write\examples{e.label();}
566
\immediate\write\examples{e.draw();}
567
\immediate\write\examples{Point pt0(-3);}
568
\immediate\write\examples{Point pt1(3);}
569
\immediate\write\examples{pt0.draw(pt1);}
570
\immediate\write\examples{Point pt2(0, 0, -4);}
571
\immediate\write\examples{Point pt3(0, 0, 4);}
572
\immediate\write\examples{pt2.draw(pt3);}
573
\immediate\write\examples{pt0.dotlabel("0", "lft");}
574
\immediate\write\examples{pt1.dotlabel("1", "rt");}
575
\immediate\write\examples{pt2.dotlabel("2", "bot");}
576
\immediate\write\examples{pt3.dotlabel("3");}
577
\immediate\write\examples{current_picture.output(Projections::PARALLEL_X_Z);}
578
\immediate\write\examples{current_picture.rotate(0, 60);}
579
\immediate\write\examples{current_picture.suppress_labels();}
580
\immediate\write\examples{current_picture.output(Projections::PARALLEL_X_Z);}
581
\immediate\write\examples{current_picture.rotate(0, 60);}
582
\immediate\write\examples{current_picture.output(Projections::PARALLEL_X_Z);}
584
%% LDF 2003.01.19. !! I neglected to unsuppress the labels at first.
585
%% It took me maybe 45 minutes to find out why my labels in the next
586
%% example weren't being printed!
588
\immediate\write\examples{current_picture.unsuppress_labels();}
599
<img src="./graphics/png/3DLDF79.png"
600
alt="[Figure 79. Not displayed.]"
611
[Figure 79 not displayed.]
616
@deftypefn {Inline function} void unsuppress_labels (void)
617
Sets @code{do_labels} to @code{true}. If a @code{Picture} contains
618
@code{Labels}, @code{unsuppress_labels()} ensures that they will be
619
output, when @code{Picture::output()} is called, so long as there is no
620
intervening call to @code{suppress_labels()} or @code{kill_labels()}.