This is 3DLDF.info, produced by makeinfo version 4.5 from 3DLDF.texi.

This is the 3DLDF User and Reference Manual, edition 1.1.5 for 3DLDF
1.1.5.  This manual was last updated on 14 January 2004.  3DLDF is a
GNU package for three-dimensional drawing with MetaPost output.  The
author is Laurence D. Finston.

   Copyright (C) 2003, 2004 Laurence D. Finston.

     Permission is granted to copy, distribute and/or modify this
     document under the terms of the GNU Free Documentation License,
     Version 1.2 or any later version published by the Free Software
     Foundation; with no Invariant Sections, no Front-Cover Texts, and
     no Back-Cover Texts.  A copy of the license is included in the
     section entitled "GNU Free Documentation License".
   
INFO-DIR-SECTION GNU packages
START-INFO-DIR-ENTRY
* 3DLDF: (3DLDF).            3D drawing with MetaPost output.
END-INFO-DIR-ENTRY


File: 3DLDF.info,  Node: Drawing and Filling Paths,  Next: Labelling Paths,  Prev: Applying Transformations to Paths,  Up: Path Reference

Drawing and Filling
===================

 - `const' virtual function: void draw ([const Color& DDRAW_COLOR =
          `*Colors::default_color', [const string DDASHED = "", [const
          string PPEN = "", [Picture& PICTURE = `current_picture']]]])
 - `const' Virtual function: void draw (Picture& PICTURE, [const Color&
          DDRAW_COLOR = *Colors::default_color, [string DDASHED = "",
          [string PPEN = ""]]])
     Allocates a copy of the `Path' on the free store, puts a pointer to
     the copy on PICTURE.`shapes', sets its `fill_draw_value' to
     `DRAW', and the values of its `draw_color', `dashed', and `pen'
     according to the arguments.

     The second version is convenient for passing a `Picture' argument
     without having to specify all of the other arguments.

     All of the arguments to `draw()' are optional, so it can be invoked
     as follows:

          Point A;
          Point B(2);
          Point C(3, 3);
          Point D(1, 2);
          Point E(-1, 1);
          Path p("..", true, &A, &B, &C, &D, &E, 0);
          p.draw();

     [Figure 120 not displayed.]

     The arguments:

    DDRAW_COLOR
          Used to specify a color for the `Path'.  DDRAW_COLOR is a
          reference to a `Color'.  Colors are described in *Note Color
          Reference::.

          The most basic `Colors' are predefined in 3DLDF (in the
          `namespace Colors'), and users may create new `Colors' and
          specify their red-green-blue values.

          The `Path p' could be drawn in red by calling
          `p.draw(Colors::red)'. This manual isn't intended to be
          printed in color, so there's no figure to demonstrate this.
          However, gray values can be printed on non-color printers.

               using namespace Colors;
               p.draw(gray, "", "pencircle scaled .25mm");

          [Figure 121 not displayed.]

    DDASHED
          A `string' representing a "dash pattern", as defined in
          MetaPost(1).  Dash patterns have no meaning in 3DLDF, they
          are simply `strings' that are written unchanged to
          `out_stream'.

               p.draw(black, "evenly");

          [Figure 122 not displayed.]

    PPEN
          A `string' representing a "pen", as defined in Metafont and
          MetaPost(2).  Pens have no meaning in 3DLDF, they are simply
          `strings' that are written unchanged to `out_stream'.

               p.draw(black, "", "pensquare xscaled 3mm
                      yscaled .25mm scaled .5mm");

          [Figure 123 not displayed.]

    PICTURE
          Indicates the `Picture' on which the `Path' should be drawn.

          The two versions of `draw()' differ in the position of the
          PICTURE argument:  In the first version, it's the last
          argument, while in the second version, it's the first
          argument.  If a PICTURE argument is used, it's often more
          convenient to use the second version.

          The following example puts `Path p' onto `temp_picture'.  It
          also demonstrates how the labels are put onto `temp_picture',
          and how `temp_picture' is output.  In the previous examples,
          the commands for making the labels and outputting
          `current_picture' were left out in order to reduce clutter.
          *Note Point Reference; Labelling: Labelling Points, and *Note
          Picture Reference; Outputting; Output Functions: Picture
          Output Functions.

               Picture temp_picture;
               p.draw(temp_picture);
               A.dotlabel("A", "bot", temp_picture);
               B.dotlabel("B", "bot", temp_picture);
               C.dotlabel("C", "top", temp_picture);
               D.dotlabel("D", "top", temp_picture);
               E.dotlabel("E", "lft", temp_picture);
               temp_picture.output(Projections::PARALLEL_X_Y);

          [Figure 124 not displayed.]


 - `const' function: void draw_help ([const Color& DDRAW_COLOR =
          *help_color, [string DDASHED = help_dash_pattern, [string
          PPEN = "", [Picture& PICTURE = `current_picture']]]])
 - `const' function: void draw_help (Picture& PICTURE, [const Color&
          DDRAW_COLOR = `*help_color', [string DDASHED =
          `help_dash_pattern', [string PPEN = ""]]])
     This functions are for drawing help lines.  They are like
     `draw()', except that `draw_help()' returns immediately, if
     `do_help_lines' (a static data member in `Path') is `false'.
     Also, the defaults for DDRAW_COLOR and DDASHED differ from those
     for `draw()'.

 - `const' virtual function: void drawarrow ([const Color& DDRAW_COLOR
          = `*Colors::default_color', [string DDASHED = "", [string
          PPEN = "", [Picture& PICTURE = `current_picture']]]])
 - `const' virtual function: void drawarrow (Picture& PICTURE, [const
          Color& DDRAW_COLOR = `*Colors::default_color', [string
          DDASHED = "", [string PPEN = ""]]])
     Like `draw()', except that the MetaPost command `drawarrow' is
     written to `out_stream' when `picture' is output.  The second
     version is convenient for passing a `Picture' argument without
     having to specify all of the other arguments.

          Point m;
          Point n(2, 2);
          m.dotlabel("$m$", "bot");
          n.dotlabel("$n$");
          m.drawarrow(n);

     [Figure 125 not displayed.]


 - Non-member function: void draw_axes ([real DIST = 2.5, [string POS_X
          = "bot", [string POS_Y = "lft", [string POS_Z = "bot", [const
          Color& DDRAW_COLOR = `*Colors::default_color', [const string
          DDASHED = "", [const string PPEN = "", [const Point& SHIFT_X
          = `origin', [const Point& SHIFT_Y = `origin', [const Point&
          SHIFT_Z = `origin', [Picture& PICTURE =
          `current_picture']]]]]]]]]]])
 - Non-member function: void draw_axes (const Color& DDRAW_COLOR, [real
          DIST = 2.5, [string POS_X = "bot", [string POS_Y = "lft",
          [string POS_Z = "bot", [const string DDASHED = "", [const
          string PPEN = "", [const Point& SHIFT_X = `origin', [const
          Point& SHIFT_Y = `origin', [const Point& SHIFT_Z = `origin',
          [Picture& PICTURE = `current_picture']]]]]]]]]])
     These functions draw lines centered on the origin, and ending in
     arrows in the directions of the positive x, y, and z-axes, and
     labels them with the appropriate letters.  `draw_axes()' is used in
     many of the figures in this handbook.  It can be helpful in
     determining whether a `Focus' has a good "`up'" direction.  *Note
     Focus Reference; Data Members: Focus Data Members.

     In the first version, all of the arguments are optional.  In the
     second version, DDRAW_COLOR is required and has been moved to the
     front of the argument list.  This version is often convenient,
     when a `Color' other than the default is desired.

     The arguments:
    DIST
          The length of the lines drawn.  The default is 2.5.  The
          value 0 can be used as a dummy argument, if the default for
          DIST is desired, but other arguments must be specified.


    POS_X
    POS_Y
    POS_Z
          The position arguments for the labelling commands for each of
          the axes.  The defaults are `"bot"' for the x and z-axes, and
          `"lft"' for the y-axis.  The usual `strings' for the position
          of labels can be used, namely: `"top"', `"bot"', `"lft"',
          `"rt"', `"ulft"', `"urt"', `"llft"', `"lrt"', and `""'.  If
          `""' is used, that axis is not drawn.  This can be useful for
          parallel projections onto one of the major planes(3).  In
          addition, `"d"' can be used to indicate that the default
          should be used for that label.  This can be useful if one
          needs a placeholder, but doesn't remember what the default is
          for that label.

               draw_axes(0, "bot", "rt", "");
               current_picture.output(Projections::PARALLEL_X_Y);

          [Figure 126 not displayed.]

          In addition, the arguments SHIFT_X, SHIFT_Y, and SHIFT_Z can
          be used to adjust the positions of the labels further (see
          below).

    DDRAW_COLOR
    DDASHED
    PPEN
          Arguments for the `drawarrow()' command, described above, in
          this section.

    SHIFT_X
    SHIFT_Y
    SHIFT_Z
          Offsets for the labels.  These arguments make it possible to
          adjust the positions of the labels.  The defaults are
          `origin', so no shifting takes place, if they are used.  In
          [next figure] , `draw_axes' is called without any arguments,
          so the defaults are used.

               draw_axes();

          [Figure 127 not displayed.]

          In [next figure] , the `Point P' is used to shift the labels.
          Please note that placeholders must be used for the first
          arguments.

               Point P(.5, .5, .5);
               draw_axes(0, "d", "d", "d", black, "", "", P, -P, P);

          [Figure 128 not displayed.]

          Please note that the `Points' used for placing the labels are
          three-dimensional `Points', whether the SHIFT_X, SHIFT_Y,
          and/or SHIFT_Z arguments are used or not.  It is not
          currently possible to adjust the positions of the labels on
          the two-dimensional projection itself.  This would probably
          be more useful, but would require changing the way
          `Picture::output()' functions.

    PICTURE
          The `Picture', onto which the `Paths' and `Labels' are put.

 - `const' function: void fill ([const Color& FFILL_COLOR =
          `*Colors::default_color', [Picture& PICTURE =
          `current_picture']])
 - Function: void fill (Picture& PICTURE, [const Color& FFILL_COLOR =
          `*Colors::default_color'])
     Allocates a copy of the `Path' on the free store, puts a pointer to
     it onto PICTURE.`shapes', sets its `fill_draw_value' to `FILL', and
     its `fill_color' to `*FFILL_COLOR'.

     The second version is convenient for passing a `Picture' argument
     without having to specify all of the other arguments.

     The arguments are similar to those of `draw()', except that the
     `Color' argument is called FFILL_COLOR instead of DDRAW_COLOR.

          p.fill(gray);

     [Figure 129 not displayed.]


 - `const' function: void filldraw ([const Color& DDRAW_COLOR =
          `*Colors::default_color', [const Color& FFILL_COLOR =
          `*Colors::background_color', [string DDASHED = "", [string
          PPEN = "", [Picture& PICTURE = `current_picture']]]]])
 - `const' function: void filldraw (Picture& PICTURE, [const Color&
          DDRAW_COLOR = `*Colors::default_color', [const Color&
          FFILL_COLOR = `*Colors::background_color', [string DDASHED =
          "", [string PPEN = ""]]]])
     Allocates a copy of the `Path' on the free store, puts a pointer to
     the copy onto PICTURE.`shapes', sets its `fill_draw_value' to
     `FILLDRAW', its `draw_color' and `fill_color' to `*DDRAW_COLOR'
     and `*FFILL_COLOR', respectively, its `dashed' to DDASHED, and its
     `pen' to PPEN.

     The second version is convenient for passing a `Picture' argument
     without having to specify all of the other arguments.

     The arguments are similar to those of `draw()' and `fill()',
     except that both DDRAW_COLOR and FFILL_COLOR are used.

     3DLDF's `filldraw()' differs from Metafont's and MetaPost's
     `filldraw' commands:  In Metafont and MetaPost, `filldrawing' is
     equivalent to filling a `path' and then drawing its border using
     the `pen'.  Metafont does not have colors.  While MetaPost does,
     its `filldraw' command does not foresee the use of different
     colors for drawing and filling.

          p.filldraw(black, gray, "", "pencircle scaled 2mm");

     [Figure 130 not displayed.]

     It can often be useful to draw the outline of a `Path', but to have
     it hide objects that lie behind it.  This is why the default for
     FFILL_COLOR is `*Colors::background_color'.

          default_focus.set(3, 0, -10, 3, 10, 10, 10);
          Point p[8];
          p[0] = p[1] = p[2] = p[3] = p[4]
               = p[5] = p[6] = p[7].set(-1,-1, 5);
          p[1] *= p[2] *= p[3] *= p[4] *= p[5]
               *= p[6] *= p[7].rotate(0, 0, 45);
          p[2] *= p[3] *= p[4]
               *= p[5] *= p[6] *= p[7].rotate(0, 0, 45);
          p[3] *= p[4] *= p[5] *= p[6]
               *= p[7].rotate(0, 0, 45);
          p[4] *= p[5] *= p[6] *= p[7].rotate(0, 0, 45);
          p[5] *= p[6] *= p[7].rotate(0, 0, 45);
          p[6] *= p[7].rotate(0, 0, 45);
          p[7].rotate(0, 0, 45);
          Path r0("..", true, &p[0], &p[1], &p[2],
                  &p[3], &p[4], &p[5], &p[6], &p[7], 0);
          r0.filldraw(black, light_gray);
          r0.scale(2, .5);
          r0.shift(0, 0, -2.5);
          r0.filldraw(black, gray);
          r0.scale(.25, 3);
          r0.shift(0, 0, -2.5);
          r0.filldraw();

     [Figure 131 not displayed.]


 - Function: void undraw ([string DDASHED = "", [string PPEN = "",
          [Picture& PICTURE = `current_picture']]])
 - Function: void undraw (Picture& PICTURE, [string DDASHED = "",
          [string PPEN = ""]])
     Allocates a copy of the `Path' on the free store, puts a pointer to
     it on PICTURE.`shapes', sets its `fill_draw_value' to `UNDRAW', and
     the values of its `dashed' and `pen' according to the arguments.

     The second version is convenient for passing a `Picture' argument
     without having to specify all of the other arguments.

     This function "undraws" a `Path'.  This is equivalent to drawing
     the `Path' using the background color
     (`*Colors::background_color').

     Undrawing is useful for removing a portion of a `Path'.

          Point P0(1, 1);
          Point P1(2, 1);
          Point P2(2, 3);
          Point P3(-1, 1);
          Path p("--", false, &origin, &P0, &P1, &P2, &P3, 0);
          p.draw(black, "", "pencircle scaled 3mm");
          p.undraw("", "pencircle scaled 1mm");

     [Figure 132 not displayed.]


 - Function: void unfill ([Picture& PICTURE = `current_picture'])
     Allocates a copy of the `Path' on the free store, puts a pointer to
     it on PICTURE.`shapes' and sets its `fill_draw_value' to `UNFILL'

     This function is useful for removing a portion of a filled region.

          Point pt[4];
          pt[0].set(-2, -2);
          pt[1].set(2, -2);
          pt[2].set(2, 2);
          pt[3].set(-2, 2);
          Path p("--", true, &pt[0], &pt[1], &pt[2], &pt[3], 0);
          p.draw();
          p.dotlabel();
          p.filldraw(black, gray);
          p.scale(.5, .5);
          p.unfill();

     [Figure 133 not displayed.]


 - Function: void unfilldraw ([const Color& DDRAW_COLOR =
          `*Colors::background_color', [string DDASHED = "", [string
          PPEN = "", [Picture& PICTURE = current_picture]]]])
 - Function: void unfilldraw (Picture& PICTURE, [const Color&
          DDRAW_COLOR = `*Colors::background_color', [string DDASHED =
          "", [string PPEN = ""]]])
     Allocates a copy of the `Path' on the free store, puts a pointer to
     it on PICTURE.`shapes', sets its `fill_draw_value' to
     `UNFILLDRAW', and the values of its `draw_color', `dashed', and
     `pen' according to the arguments.  While the default for
     DDRAW_COLOR is `*Colors::background_color', any other `Color' can
     be used, so that `unfilldraw()' can unfill a `Path' and draw an
     outline around it.

     The second version is convenient for passing a `Picture' argument
     without having to specify all of the other arguments.

     This function is similar to `unfill()' (*note Path Reference;
     Drawing and Filling: Drawing and Filling Paths.), except that the
     outline of the `Path' will be "undrawn" using the pen specified
     with the PPEN argument, or MetaPost's `currentpen', if no PPEN
     argument is specified.  In addition, the `Path' will be drawn
     using the `Color' specified in the DDRAW_COLOR argument.  Since
     the default is `*Colors::background_color', the `Path' will be
     "undrawn" unless a different `Color' is specified.

          Point pt[6];
          pt[0].set(-2, -2);
          pt[1].set(0, -3);
          pt[2].set(2, -2);
          pt[3].set(2, 2);
          pt[4].set(0, 3);
          pt[5].set(-2, 2);
          Path p("--", true, &pt[0], &pt[1], &pt[2],
                 &pt[3], &pt[4], &pt[5], 0);
          p.fill(gray);
          p.scale(.5, .5);
          p.unfilldraw(black, "", "pensquare xscaled 3mm");

     [Figure 134 not displayed.]


   ---------- Footnotes ----------

   (1) Hobby, `A User's Manual for MetaPost', p. 32.

   (2) Knuth, `The METAFONTbook', Chapter 4, p. 21ff.  Hobby, `A User's
Manual for MetaPost', p. 32.

   (3) The usual interpretation of `""' as a position argument to a
labelling command would be to put it directly onto `*(Label.pt)', which
in this case would put it onto the arrowhead.  Since this will probably
never be desirable, I've decided to use `""' to suppress drawing axes.
Formerly, `draw_axes()' used three additional arguments for this
purpose.


File: 3DLDF.info,  Node: Labelling Paths,  Next: Showing Paths,  Prev: Drawing and Filling Paths,  Up: Path Reference

Labelling
=========

 - `const' function: void label ([unsigned int I = 0, [string
          POSITION_STRING = "top", [short TEXT_SHORT = 0, [bool DOT =
          `false', [Picture& PICTURE = `current_picture']]]]])
 - `const' function: void label (Picture& PICTURE, [unsigned int I = 0,
          [string POSITION_STRING = "top", [short TEXT_SHORT = 0, [bool
          DOT = `false']]]])
     Calls `Point::label()' on all of the `Points' on `points'.  They
     are numbered consecutively starting with I.  The other arguments
     are used for all of the `Points', so it's not possible to specify
     different positions for the labels for different `Points'.  DOT
     will normally not be specified, unless a PICTURE argument is used
     in the first version.  `dotlabel()' calls `label()' with DOT =
     `true'.

     The second version is convenient for passing a `Picture' argument
     without having to specify all of the other arguments.

 - `const' function: void dotlabel ([unsigned int I = 0, [string
          POSITION_STRING = "top", [short TEXT_SHORT = 0, Picture&
          PICTURE = `current_picture']]])
 - `const' function: void dotlabel (Picture& PICTURE, [unsigned int I =
          0, [string POSITION_STRING = "top", [short TEXT_SHORT = 0]]])
     Like `label()', except that the `Points' are dotted.


File: 3DLDF.info,  Node: Showing Paths,  Next: Querying Paths,  Prev: Labelling Paths,  Up: Path Reference

Showing
=======

 - `const' function: void show ([string TEXT = "", [char COORDS = 'w',
          [const bool DO_PERSP = `true', [const bool DO_APPLY = `true',
          [Focus* F = 0, [const unsigned short PROJ =
          `Projections::PERSP', [const real FACTOR = 1]]]]]]])
     Prints information about the `Path' to standard output (`stdout').
     TEXT is simply printed out, unless it's the empty string, in
     which case `"Path:"' is printed out.  COORDS indicates which set
     of coordinates should be shown.  Valid values are `'w'' for the
     `world_coordinates', `'p'' for the `projective_coordinates', `'u''
     for the `user_coordinates', and `'v'' for the `view_coordinates',
     whereby the latter two are currently not in use (*note Point
     Reference; Data Members: Point Data Members.).  If DO_APPLY is
     `true', `apply_transform()' is called on each `Point', updating
     its `world_coordinates' and resetting its `transform'.  Otherwise,
     it's not.  The arguments DO_PERSP, F, PROJ, and FACTOR are only
     relevant when showing `projective_coordinates'.  If `do_persp' is
     `true', the `Points' are projected using the values of F, PROJ,
     and FACTOR (*note Path Reference; Outputting: Outputting Paths.).
     Otherwise, the values currently stored in `projective_coordinates'
     are shown.  The `Points' and connectors are printed out
     alternately to standard output, followed by the word "cycle", if
     `cycle_switch = true'.(1)

          default_focus.set(0, 3, -10, 0, 3, 10, 10);
          Reg_Polygon r(origin, 5, 3, 45);
          r.fill(gray);
          Point p[10];
          for (int i = 0; i < 5; ++i)
              p[i] = r.get_point(i);
          p[5] = Point::intersection_point(p[4], p[0], p[2], p[1]).pt;
          p[6] = Point::intersection_point(p[0], p[1], p[2], p[3]).pt;
          p[7] = Point::intersection_point(p[1], p[2], p[4], p[3]).pt;
          p[8] = Point::intersection_point(p[2], p[3], p[0], p[4]).pt;
          p[9] = Point::intersection_point(p[3], p[4], p[0], p[1]).pt;
          Path q("--", true, &p[0], &p[5], &p[1], &p[6], &p[2], &p[7],
                 &p[3], &p[8], &p[4], &p[9], 0);
          q.draw();
          q.show("q:");
          -| q:
          fill_draw_value == 0
          (0, 1.06066, 1.06066)
          -- (-2.30826, 2.24651, 2.24651)
          -- (-1.42658, 0.327762, 0.327762)
          -- (-3.73485, -0.858092, -0.858092)
          -- (-0.881678, -0.858092, -0.858092)
          -- (4.92996e-07, -2.77684, -2.77684)
          -- (0.881678, -0.858092, -0.858092)
          -- (3.73485, -0.858092, -0.858092)
          -- (1.42658, 0.327762, 0.327762)
          -- (2.30826, 2.24651, 2.24651) -- cycle;
          q.show("q:", 'p');
          -| q:
          fill_draw_value == 0
          Projective coordinates.
          (0, -1.75337, 0.0958948)
          -- (-1.88483, -0.615265, 0.183441)
          -- (-1.38131, -2.58743, 0.031736)
          -- (-4.08541, -4.22023, -0.0938636)
          -- (-0.964435, -4.22023, -0.0938636)
          -- (0, -7.99767, -0.384436)
          -- (0.964436, -4.22023, -0.0938636)
          -- (4.08541, -4.22023, -0.0938636)
          -- (1.38131, -2.58743, 0.031736)
          -- (1.88483, -0.615266, 0.183441) -- cycle;

     [Figure 135 not displayed.]


 - Function: void show_colors ([bool  = `false'])
     Shows the values of `draw_color' and `fill_color'.  These will
     normally be 0, unless the `Path' is on a `Picture'.

   ---------- Footnotes ----------

   (1) The following example shows only one `Point' per line.  In
actual use, two `Points' are shown, but this causes overfull boxes in
Texinfo.


File: 3DLDF.info,  Node: Querying Paths,  Next: Outputting Paths,  Prev: Showing Paths,  Up: Path Reference

Querying
========

 - `const' function: bool is_on_free_store (void)
     Returns `true', if the `Path' was dynamically allocated on the
     free store, otherwise `false'.

 - `const' virtual function: bool is_planar ([const bool VERBOSE =
          `false', [string TEXT = ""]])
     Uses `get_normal()' to determine whether the `Path' is planar or
     not.  Returns `true', if it is, otherwise `false'.  If VERBOSE is
     `true', TEXT is written to standard output, or "Path:", if TEXT is
     the empty string, followed by a message saying whether the `Path'
     is planar or not.

 - `const' function: bool is_linear ([const bool VERBOSE = `false',
          [string TEXT = ""]])
     Returns `true', if `line_switch' is `true'.  Otherwise,
     `is_linear()' uses `get_normal()' to determine whether the `Path'
     is linear.  If it is, `is_linear()' returns `true', otherwise
     `false'.

 - Inline `const' function: bool is_cycle (void)
     Returns `true' if the `Path' is cyclical, i.e., `cycle_switch =
     true', otherwise `false'.  Only cyclical `Paths' are fillable.

 - Inline function: int size (void)
     Returns the number of `Points' on `points', i.e., `points.size()'.

 - Inline `const' function: bool get_line_switch (void)
     Returns the value of `line_switch'.  `line_switch' is only true,
     if the `Path' was created, directly or indirectly, using the
     constructor taking two `Point' arguments only.  *Note Path
     Reference; Constructors and Setting Functions: Path Constructors
     and Setting Functions.

 - Function: real slope ([char A = 'x', [char B = 'y']])
     Returns the slope of the `Path' in the plane indicated by the
     arguments, if `is_linear()' returns `true'.  Otherwise, `slope()'
     issues an error message and returns `INVALID_REAL'.

 - `const' function: Path subpath (size_t START, size_t END, [const
          bool CYCLE = false, [const string CONNECTOR = ""]])
     Returns a new `Path' using `points[START]' through `points[END -
     1]'.  If CYCLE is `true', then the new `Path' will be a cycle,
     whether `*this' is or not.  One optional connector argument can be
     used.  If it is, it will be the only connector.  Otherwise, the
     appropriate connectors from `*this' are used.

     START must be < END.  It is not possible to have START > END, even
     if `*this' is a cycle.

 - `const' function: const Point& get_point (const unsigned short A)
     Returns the `Point' `*points[A]', if A < `points.size()' and the
     `Path' is non-empty, otherwise `INVALID_POINT'.

 - `const' function: const Point& get_last_point (void)
     Returns the `Point' pointed to by the last pointer on `points'.
     Equivalent to  `get_point(get_size() - 1)', but more convenient to
     type.  Returns `INVALID_POINT', if the `Path' is empty.

 - `const' inline virtual function: size_t get_size (void)
     Returns `points.size()'.

 - `const' function: Line get_line (void)
     Returns a `Line' corresponding to the `Path', if the latter is
     linear.  Otherwise, `INVALID_LINE' is returned.  *Note Line
     Reference::.

 - `const' virtual function: Point get_normal (void)
     Returns a `Point' representing a unit vector in the direction of
     the normal to the plane of the `Path', or `INVALID_POINT', if the
     `Path' is non-planar.

          Point P(1, 1, 1);
          Rectangle r(P, 4, 4, 30, 30, 30);
          Point N = r.get_normal();

     [Figure 136 not displayed.]

     In 3DLDF, plane figures generally have constructors taking a
     |Point| argument for the center, a variable number of |real|
     arguments for the dimensions, and three |real| arguments for the
     rotation about the major axes.  The object is first created in the
     x-z plane, and the `Points' are generated to be traversed in the
     counter-clockwise direction, when seen from a `Point' with a
     positive y-coordinate.  If no rotation is specified, the normal
     will point in the direction of the positive y-axis.  If non-zero
     arguments are used for rotation, the normal will be rotated
     accordingly.  This direction considered to be "outside".  However,
     according to Huw Jones, `Computer Graphics Through Key
     Mathematics', p. 197, "outside" is considered to be the side of a
     plane, where the `Points' are meant to be traversed in the
     clockwise direction.  I hope that no problems arise from this
     discrepancy!

 - `const' virtual function: Plane get_plane (void)
     Creates and returns a `Plane' P corresponding to the `Path', if
     the latter is planar, otherwise `INVALID_PLANE'.  If the `Path' is
     planar, P.`point' will be the `Point' pointed to by
     `this->points[0]'.  *Note Plane Reference::.

          Point P(1, 1, 1);
          Rectangle r(P, 4, 4, 45, 20, 15);
          Plane q = r.get_plane();
          q.show("q:");
          -| q:
             normal: (0.0505914, 0.745607, -0.664463)
             point: (0.0178869, -0.727258, -1.01297)
             distance == -0.131735

     [Figure 137 not displayed.]


 - Function: void set_cycle ([const bool C = `true'])
     Sets `cycle_switch' to C.

 - Function: Path reverse (bool ASSIGN)
 - `const' function: Path reverse (void)
     These functions return a `Path' with the same `Points' and
     connectors as `*this', but in reversed order.  `reverse()' can
     only be applied to non-cyclical `Paths'.  If `*this' is a cycle,
     `reverse()' issues an error message and returns `*this' unreversed.

     If the first version is called with ASSIGN = `true', `*this'
     itself is reversed.  If `*this' should remain unchanged, the
     `const' version without an argument should be called.  If, on the
     other hand, the first version is called with ASSIGN = `false', a
     warning message is issued, but the reversed `Path' is returned
     just the same, leaving `*this' unchanged.



File: 3DLDF.info,  Node: Outputting Paths,  Next: Path Intersections,  Prev: Querying Paths,  Up: Path Reference

Outputting
==========

 - Function: bool project (const Focus& F, const unsigned short PROJ,
          real FACTOR)
     Calls `Point::project(F, PROJ, FACTOR)' on the `Points' on the
     `Path'.  If `Point::project()' fails (i.e., returns `false'), for
     any of the `Points', this function returns `false'.  Otherwise, it
     returns `true'.

 - Function: vector<Shape*> extract (const Focus& F, const unsigned
          short PROJ, real FACTOR)
     Checks that the `Points' on `points' can be projected using the
     values for F, PROJ, and FACTOR.  If they can, a `vector<Shape*>'
     containing only `this' is returned.  Called in `Picture::output()'.

 - Virtual function: bool set_extremes (void)
     Sets the appropriate elements in `projective_extremes' to the
     minimum and maximum values of the x, y, and z-coordinates of the
     `Points' on the `Path'.  Used in `Picture::output()' for
     determining whether a `Path' can be output using the arguments
     passed to `Picture::output()'.

 - Inline `const' virtual function: const valarray<real> get_extremes
          (void)
     Returns `projective_extremes'.  Used in `Picture::output()'.

 - `const' virtual function: real get_minimum_z (void)
 - `const' virtual function: real get_mean_z (void)
 - `const' virtual function: real get_maximum_z (void)
     These functions return the minimum, mean, or maximum value,
     respectively, of the z-coordinates of the `Points' on the `Path'.
     Used in the surface hiding algorithm in `Picture::output()'.

 - Virtual function: void suppress_output (void)
     Called in `Picture::output()'.  Sets `do_output' to `false', if
     the `Path' cannot  be output using the arguments passed to
     `Picture::output()'.

 - Virtual function: void unsuppress_output (void)
     Called in `Picture::output()'.  Resets `do_output' to `true' after
     `output()' is called on the `Shapes' on `shapes' in a `Picture',
     so that the `Path' can be output if `Picture::output()' is called
     again, with arguments that allow the `Path' to be output.

 - Virtual function: void output (void)
     Called in `Picture::output()'.  Writes the MetaPost code to
     `out_stream' for drawing, filling, filldrawing, undrawing,
     unfilling, or unfilldrawing the `Path', if the latter was
     projectable using the arguments passed to `Picture::output()'.


File: 3DLDF.info,  Node: Path Intersections,  Prev: Outputting Paths,  Up: Path Reference

Intersections
=============

 - Function: bool_point intersection_point (const Path& P, const bool
          TRACE)
     Finds the intersection point, if any, of two linear `Paths'.  Let
     `bp' be the `bool_point' returned by this function.  `bp.pt' will
     contains the intersection point, if it exists.  If not, it will
     contain `INVALID_POINT'.  If the intersection point exists and
     lies on both of the line segments represented by the `Path' and
     `p', `bp.b' will be `true', otherwise, `false'.

     This function calls `Point::intersection_points()', passing the
     first and last `Points' on `*this' and P as its arguments.  If the
     TRACE argument is `false', the version of
     `Point::intersection_points()' that finds the intersection point by
     means of a vector calculation is used.  If it's `true', the version
     that finds the intersection point of the traces of the lines on the
     major planes is used.  *Note Point Reference; Intersections: Point
     Intersections.

          Point A(-1, -1, -1);
          Point B(1, 1, 1);
          Path p0(A, B);
          Point C(-2, 1, 1);
          Point D(1.75, 0.25, 0.25);
          Path p1(C, D);
          bool_point bp = p0.intersection_point(p1);
          bp.pt.dotlabel("$i$");
          bp.pt.show("bp.pt:");
          -| bp.pt: (0.5, 0.5, 0.5)

     [Figure 138 not displayed.]



File: 3DLDF.info,  Node: Polygon Reference,  Next: Regular Polygon Reference,  Prev: Path Reference,  Up: Top

Polygon Reference
*****************

   Class `Polygon' is defined in `polygons.web', and is derived from
`Path', using public derivation.

   `Polygon' is mainly intended for use as a base class for more
specialized kinds of polygons.  Currently, the classes `Reg_Polygon'
(regular polygon) and `Rectangle' are defined.  *Note Regular Polygon
Reference::, and *Note Rectangle Reference::.

* Menu:

* Polygon Data Members::
* Polygon Operators::
* Querying Polygons::
* Affine Transformations for Polygons::
* Polygon Intersections::


File: 3DLDF.info,  Node: Polygon Data Members,  Next: Polygon Operators,  Prev: Polygon Reference,  Up: Polygon Reference

Data Members
============

 - Private variable: Point center
     The center of the `Polygon', if it has one.  However, a `Polygon'
     need not have a `center'.  If it doesn't, `center' should be set
     to `INVALID_POINT'.


File: 3DLDF.info,  Node: Polygon Operators,  Next: Querying Polygons,  Prev: Polygon Data Members,  Up: Polygon Reference

Operators
=========

 - Virtual operator: Transform operator*= (const Transform& T)
     Multiplies a `Polygon' by the `Transform' T.  Similar to
     `Path::operator*=(const Transform& t)', except that `center' is
     transformed as well.  *Note Path Reference; Operators: Path
     Operators.


File: 3DLDF.info,  Node: Querying Polygons,  Next: Affine Transformations for Polygons,  Prev: Polygon Operators,  Up: Polygon Reference

Querying
========

 - Virtual function: const Point& get_center (void)
 - `const' function: Point get_center (void)
     These functions return `center'.  If the `Polygon' doesn't contain
     any `Points', a warning is issued, and `INVALID_POINT' is returned.


File: 3DLDF.info,  Node: Affine Transformations for Polygons,  Next: Polygon Intersections,  Prev: Querying Polygons,  Up: Polygon Reference

Affine Transformations
======================

 - Virtual function: Transform rotate (const real X, [const real Y = 0,
          [const real Z = 0]])
 - Virtual function: Transform rotate (const Point& P0, const Point&
          P1, [const real ANGLE = 180])
 - Virtual function: Transform rotate (const Path& P, [const real ANGLE
          = 180])
 - Virtual function: Transform scale (real X, [real Y = 1, [real Z =
          1]])
 - Virtual function: Transform shear (real XY, [real XZ = 0, [real YX =
          0, [real YZ = 0, [real ZX = 0, [real ZY = 0]]]]])
 - Virtual function: Transform shift (real X, [real Y = 0, [real Z =
          0]])
 - Virtual function: Transform shift (const Point& P)
 - Virtual function: void shift_times (real X, [real Y = 1, [real Z =
          1]])
 - Virtual function: void shift_times (const Point& P)
     The affine transformation functions for `Polygon' differ from the
     `Path' versions only in that `center' is transformed as well.
     *Note Path Reference; Affine Transformations: Affine
     Transformations for Paths.

     Please note, that the classes currently derived from `Polygon',
     namely `Reg_Polygon' and `Rectangle', currently inherit these
     functions from `Polygon'.  The problem with this is, that they have
     data members, which are not recalculated when a `Reg_Polygon' or
     `Rectangle' is transformed.  I plan to do something about this
     soon!  It will also be necessary to add the function
     `Reg_Polygon::is_reg_polygonal()', in order to test whether
     operations on a `Reg_Polygon' have caused it to become irregular
     and/or non-polygonal.  Similarly, the function
     `Rectangle::is_rectangular()' must be added, to test whether
     operations on a `Rectangle' has caused it to become
     non-rectangular.  *Note Regular Polygon Reference; Data Members:
     Regular Polygon Data Members, and *Note Rectangle Reference; Data
     Members: Rectangle Data Members.


File: 3DLDF.info,  Node: Polygon Intersections,  Prev: Affine Transformations for Polygons,  Up: Polygon Reference

Intersections
=============

 - `const' function: bool_point_pair intersection_points (const Point&
          P0, const Point& P1)
 - `const' function: bool_point_pair intersection_points (const Path& P)
     These functions find the intersections of the `Polygon' and a line.
     In the first version, the `Point' arguments are the end points of
     the line.  The argument to the second version must be a linear
     `Path'.

     A line and a regular polygon or rectangle(1) can intersect at two
     points at most.  Let `b' be a `bool_point_pair' returned by
     `intersection_points()'.  If no intersection points are found,
     `b.first.pt' and `b.second.pt' will be `INVALID_POINT', and
     `b.first.b' and `b.second.b' will be `false'.  If a single
     intersection point is found, the corresponding `Point' will be
     stored in `b.first.pt'.  If the `Point' is on the line segment
     p_0p_1 , `b.first.b' will be `true', otherwise `false'.  If a
     second intersection point is found, it will be stored in
     `b.second.pt', and `b.second.b' is set analogously to `b.first.b'.

     When the `Point' arguments and the `Reg_Polygon' are coplanar, as
     in [next figure] , two intersection points are possible.  In this
     case, only intersection points of the line with an edge of the
     `Reg_Polygon' are returned in the `bool_point_pair'.

          Point A(1, 1, 1);
          Reg_Polygon r(origin, 5, 3);
          Transform t;
          t.rotate(15, 12, 11);
          t.shift(A);
          Point P(-2, 0, -1);
          Point Q(2, 0, 1);
          P *= Q *= r *= t;
          bool_point_pair bpp = r.intersection_points(P, Q);
          bpp.first.pt.dotlabel("$f$", "rt");
          bpp.second.pt.dotlabel("$s$");

     [Figure 139 not displayed.]

     In [next figure] , the lines BC  and PQ

     are not coplanar with the `Reg_Polygon' r.  In each case, only one
     intersection point is possible, and it can be either an
     intersection with an edge of the `Reg_Polygon', or lie within its
     perimeter.

          Point B(r.get_point(3).mediate(r.get_point(4)));
          Point C(B);
          B.shift(0, 2, .5);
          C.shift(0, -2, -.5);
          Point P(-1, -2, -1);
          Point Q(0, 2, 1);
          B *= C *= P *= Q *= r *= t;
          bool_point_pair bpp = r.intersection_points(B, C);
          bpp.first.pt.dotlabel("$i_0$", "rt");
          bpp = r.intersection_points(P, Q);
          bpp.first.pt.dotlabel("$i_1$", "rt");

     [Figure 140 not displayed.]

     In [next figure] , the intersection point of r with the line PQ

     does not lie on the line _segment_ PQ.

          bpp = r.intersection_points(P, Q);
          bpp.first.pt.dotlabel("$i$", "rt");
          cout << "bpp.first.b == " << bpp.first.b << endl << flush;
          -| bpp.first.b == 0

     [Figure 141 not displayed.]


 - `const' function: vector<Point> intersection_points (const Polygon&
          R)
     Finds the intersection points of two `Polygons'.  Let v be the
     `vector<Point>' returned by `intersection_points()'.  If the
     `Polygons' are coplanar, v will contain the intersection points of
     the edges of the `Polygons', as in [next figure] .

          Rectangle r(origin, 4, 4);
          Reg_Polygon rp(origin, 5, 5, 0, 36);
          rp.shift(0, 0, .25);
          vector <Point> v = r.intersection_points(rp);

     [Figure 142 not displayed.]

     If the `Polygons' lie in parallel planes, there can be no
     intersection points.  If they lie in non-parallel, non-coplanar
     planes, `intersection_points()' first finds the intersection line
     of the two planes.  Then it finds the intersection points of this
     line with the two `Polygons', if they exist.  There can no more
     than four intersection points, in this case.  v[0] and v[1] will
     be the intersection points of the line with `*this', while v[2] and
     v[3] will be the intersection points of the line with R.  If one
     or more of the intersection points doesn't exist, the corresponding
     member of v will contain `INVALID_POINT' as a placeholder.

          Point A(1, 1, 1);
          Rectangle r(A, 4, 4);
          Reg_Polygon p(A, 5, 5);
          p.rotate(90, 30);
          p.shift(2, 0, 3);
          vector <Point> v = r.intersection_points(p);

     [Figure 143 not displayed.]

     In [next figure] , the `Rectangle' r and the `Reg_Polygon' p don't
     overlap at all, nor does the intersection line of the two planes
     intersect with p.  However, it does intersect with p at the
     labelled `Points'.

          Point A(1, 1, 1);
          Rectangle r(A, 4, 4);
          Reg_Polygon p(A, 5, 5);
          p.rotate(90, 30);
          p.shift(4, 3, 3);
          vector <Point> v = r.intersection_points(p);
          int i = 0;
          for (vector<Point>::iterator iter = v.begin();
           iter != v.end(); ++iter)
           iter->dotlabel(i++, "bot");

     [Figure 144 not displayed.]


   ---------- Footnotes ----------

   (1) `Reg_Polygon' and `Rectangle' are currently the only classes
derived from `Polygon'.


File: 3DLDF.info,  Node: Regular Polygon Reference,  Next: Rectangle Reference,  Prev: Polygon Reference,  Up: Top

Regular Polygon Reference
*************************

   Class `Reg_Polygon' is defined in `polygons.web', and is derived
from `Polygon', using public derivation.

   As noted above in *Note Polygon Reference; Affine Transformations:
Affine Transformations for Polygons, `class Reg_Polygon', like `class
Rectangle', currently inherits its transformation functions and
`operator*=(const Transform&)' from `Polygon'.  Consequently, the data
members of a `Reg_Polygon', except for `center', are not recalculated
when it's transformed.  I plan to change this soon!  It will also be
necessary to add the function `Reg_Polygon::is_reg_polygonal()', in
order to test whether a `Reg_Polygon' is still regular and polygonal.

* Menu:

* Regular Polygon Data Members::
* Regular Polygon Constructors and Setting Functions::
* Regular Polygon Operators::
* Querying Regular Polygons::
* Circles for Regular Polygons::


File: 3DLDF.info,  Node: Regular Polygon Data Members,  Next: Regular Polygon Constructors and Setting Functions,  Prev: Regular Polygon Reference,  Up: Regular Polygon Reference

Data Members
============

 - Private variable: real internal_angle
     The angle at the center of the `Reg_Polygon' of the triangle formed
     by the center and two adjacent corners.  If n is the number of
     sides of a `Reg_Polygon', `internal_angle' will be 360.0/n, so
     `internal_angle' will be 120 for a regular triangle, 90 for a
     square, 72 for a pentagon, etc.

 - Private variable: real radius
     The radius of the surrounding circle for a `Reg_Polygon' (Umkreis).

 - Private variable: unsigned short sides
     The number of sides of a `Reg_Polygon'.

 - Private variable: bool on_free_store
     `true', if the `Reg_Polygon' was dynamically allocated on the free
     store, otherwise `false'.  Dynamic allocation of `Reg_Polygons'
     should only be performed by `create_new<Reg_Polygon>()', which sets
     `on_free_store' to `true'.


File: 3DLDF.info,  Node: Regular Polygon Constructors and Setting Functions,  Next: Regular Polygon Operators,  Prev: Regular Polygon Data Members,  Up: Regular Polygon Reference

Constructors and Setting Functions
==================================

 - Default constructor: void Reg_Polygon (void)
     Creates an empty `Reg_Polygon'.

 - Constructor: void Reg_Polygon (const Point& CCENTER, const unsigned
          short SSIDES, const real DDIAMETER, [const real ANGLE_X = 0,
          [const real ANGLE_Y = 0, [const real ANGLE_Z = 0]]])
     Creates a `Reg_Polygon' in the x-z plane, centered at the origin,
     with the number of sides specified by SSIDES and with `radius' =
     DDIAMETER / 2.

     The `Reg_Polygon' is rotated about the x, y, and z-axes in that
     order by the angles given by ANGLE_X, ANGLE_Y, and ANGLE_Z,
     respectively, if any one of them is non-zero.  Finally, the
     `Reg_Polygon' is shifted such that its center is located at
     CCENTER.

          Reg_Polygon r(origin, 3, 2.75, 10, 15, 12.5);
          r.draw();

     [Figure 145 not displayed.]


 - Setting function: void set (const Point& CCENTER, const unsigned
          short SSIDES, const real DDIAMETER, [const real ANGLE_X = 0,
          [const real ANGLE_Y = 0, [const real ANGLE_Z = 0]]])
     Corresponds to the constructor above.

     A `Reg_Polygon' can theoretically have any number of sides, however
     I haven't tested it for unreasonably large values.  The following
     example demonstrates that `set()' can be used to change a
     `Reg_Polygon'.

          Reg_Polygon r;
          real j = .5;
          for (int i = 3; i <= 16; ++i)
            {
              r.set(origin, i, j);
              r.draw();
              j += .5;
            }

     [Figure 146 not displayed.]


 - Template specializations: Reg_Polygon* create_new<Reg_Polygon>
          (const Reg_Polygon* R)
 - : Reg_Polygon* create_new<Reg_Polygon> (const Reg_Polygon& R)
     Pseudo-constructors for dynamic allocation of `Reg_Polygons'.
     They create a `Reg_Polygon' on the free store and allocate memory
     for it using `new(Reg_Polygon)'.  They return a pointer to the new
     `Reg_Polygon'.  If R is a non-zero pointer or a reference, the new
     `Reg_Polygon' will be a copy of R.  If the new object is not meant
     to be a copy of an existing one, `0' must be passed to
     `create_new<Reg_Polygon>()' as its argument.  *Note Dynamic
     Allocation of Shapes::, for more information.


File: 3DLDF.info,  Node: Regular Polygon Operators,  Next: Querying Regular Polygons,  Prev: Regular Polygon Constructors and Setting Functions,  Up: Regular Polygon Reference

Operators
=========

 - Operator: const Reg_Polygon& operator= (const Reg_Polygon& P)
     Makes the `Reg_Polygon' a copy of P.


File: 3DLDF.info,  Node: Querying Regular Polygons,  Next: Circles for Regular Polygons,  Prev: Regular Polygon Operators,  Up: Regular Polygon Reference

Querying
========

 - `const' inline function: real get_radius (void)
     Returns `radius'.


File: 3DLDF.info,  Node: Circles for Regular Polygons,  Prev: Querying Regular Polygons,  Up: Regular Polygon Reference

Circles
=======

 - `const' function: Circle in_circle (void)
     Returns the enclosed `Circle' of the `Reg_Polygon'.

          Point P(0, -1, 1);
          Reg_Polygon h(P, 6, 4, 15, 12, 11.5);
          h.filldraw(black, gray);
          Circle c = h.in_circle();
          c.unfilldraw(black);

     [Figure 147 not displayed.]


 - `const' function: Circle draw_in_circle ([const Color& DDRAW_COLOR =
          `*Colors::default_color', [const string DDASHED = "", [const
          string] PPEN = "", [Picture& PICTURE = `current_picture']]])
 - `const' function: Circle draw_in_circle ([Picture& PICTURE =
          `current_picture', [const Color& DDRAW_COLOR =
          `*Colors::default_color', [const string DDASHED = "", [const
          string] PPEN = ""]]])
     Draws and returns the enclosed `Circle' of the `Reg_Polygon'.

          Point P(0, 1, 1);
          Reg_Polygon h(P, 7, 4, 80, 2, 5);
          h.draw(black, "evenly");
          h.draw_in_circle();

     [Figure 148 not displayed.]


 - `const' function: Circle out_circle (void)
     Returns the surrounding `Circle' of the `Reg_Polygon'.

          Point P(0, -1, 1);
          Reg_Polygon h(P, 6, 4, 15, 12, 11.5);
          Circle c = h.out_circle();
          c.filldraw(black, gray);
          h.unfilldraw(black);

     [Figure 149 not displayed.]


 - `const' function: Circle draw_out_circle ([const Color& DDRAW_COLOR
          = `*Colors::default_color', [const string DDASHED = "",
          [const string] PPEN = "", [Picture& PICTURE =
          `current_picture']]])
 - `const' function: Circle draw_out_circle ([Picture& PICTURE =
          `current_picture', [const Color& DDRAW_COLOR =
          `*Colors::default_color', [const string DDASHED = "", [const
          string] PPEN = ""]]])
     Draws and returns the surrounding `Circle' of the `Reg_Polygon'.

          Point P(0, 1, 1);
          Reg_Polygon h(P, 7, 4, 80, 2, 5);
          h.draw(black, "evenly");
          h.draw_out_circle();

     [Figure 150 not displayed.]


