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: Planes Returning Information,  Next: Plane Intersections,  Prev: Planes Operators,  Up: Plane Reference

Returning Information
=====================

 - `const' function: real_short get_distance (const Point& P)
 - `const' function: real_short get_distance (void)
     The version of this function taking a `Point' argument returns a
     `real_short' R, whose `real' part (R.`first') represents the
     distance of P from the `Plane'.  This value is always positive.
     R.`second' can take on three values:

    0
          If the `Point' lies in the `Plane'.

    1
          If it lies on the side of the `Plane' pointed at by the
          normal to the `Plane', considered to be the "outside".

    -1
          If it lies on the side of the `Plane' _not_ pointed at by the
          normal to the `Plane', considered to be the "inside".

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

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

          Point N(0, 1);
          N.rotate(-10, 20, 20);
          Point P(1, 1, 1);
          Plane q(P, N);
          Point A(4, -2, 4);
          Point B(-1, 3, 2);
          Point C = q.intersection_point(A, B).pt;
          real_short bp;
          
          bp = q.get_distance();
          cout << bp.first;
          -| 0.675646
          cout << bp.second
          -| -1
          
          bp = q.get_distance(A)
          cout << bp.first;
          -| 3.40368
          cout << bp.second;
          -|  -1
          
          bp = q.get_distance(B)
          cout << bp.first;
          -| 2.75865
          cout << bp.second;
          -| 1
          
          bp = q.get_distance(C)
          cout << bp.first;
          -| 0
          cout << bp.second;
          -| 0

     [Figure 106 not displayed.]



File: 3DLDF.info,  Node: Plane Intersections,  Next: Planes Showing,  Prev: Planes Returning Information,  Up: Plane Reference

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

 - `const' function: bool_point intersection_point (const Point& P0,
          const Point& P1)
 - `const' function: bool_point intersection_point (const Path& P)
     These functions find the intersection point of the `Plane' and a
     line.  In the first version, the line is defined by the two
     `Point' arguments.  In the second version, the `Path' P must be
     linear, i.e., P.`is_linear()' must be `true'.

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

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

     [Figure 107 not displayed.]


 - `const' function: Line intersection_line (const Plane& P)
     Returns a `Line' L.  representing the line of intersection of two
     `Planes'.  *Note Line Reference::.

     In [next figure] , `intersection_line()' is used to find the line
     of intersection of the `Planes' derived from the `Rectangles' r_0
     and r_1 using `get_plane()' (*note Paths Reference; Querying:
     Querying Paths.).  Please note that there is no guarantee that
     L.`position' will be in a convenient place for your drawing.  A
     bit of fiddling was needed to find the `Points' P_2 and P_3.  I
     plan to add functions for finding the intersection lines of plane
     figures, but haven't done so yet.

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

     [Figure 108 not displayed.]



File: 3DLDF.info,  Node: Planes Showing,  Prev: Plane Intersections,  Up: Plane Reference

Showing
=======

 - `const' function: void show ([string TEXT = ""])
     Prints information about the `Plane' to standard output.  If TEXT
     is not the empty `string', it is printed to the standard output.
     Otherwise, `Plane:' is printed.  Following this, if the `Plane' is
     equal to `INVALID_PLANE' (*note Planes Reference; Global
     Constants: Planes Global Constants.), a message to this effect is
     printed to standard output.  Otherwise, `normal' and `point' are
     shown using `Point::show()' (*note Point Reference; Showing:
     Showing Points.).  Finally, `distance' is printed.

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



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

Path Reference
**************

   Class `Path' is defined in `paths.web'.  It is derived from `Shape'
using `protected' derivation.

* Menu:

* Path Data Members::
* Path Constructors and Setting Functions::
* Path Destructor::
* Path Operators::
* Appending to Paths ::
* Copying Paths::
* Clearing Paths ::
* Modifying Paths ::
* Affine Transformations for Paths::
* Aligning Paths with an Axis::
* Applying Transformations to Paths::
* Drawing and Filling Paths::
* Labelling Paths::
* Showing Paths::
* Querying Paths::
* Outputting Paths::
* Path Intersections::


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

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

 - Protected variable: bool line_switch
     `true' if the `Path' was created using the constructor `Path(const
     Point& p0, const Point& p1)', directly or indirectly.  *Note Path
     Reference; Constructors and Setting Functions: Path Constructors
     and Setting Functions.

          Point p0;
          Point p1(1, 1);
          Point p2(2, 3);
          Path q0(p0, p1);
          cout << q0.get_line_switch();
          -| 1
          Path q1;
          q1 = q0;
          cout << q1.get_line_switch();
          -| 1
          Path q2 = p0.draw(p1);
          cout << q2.get_line_switch();
          -| 1
          Path q3("..", false, &p1, &p2, &p0, 0);
          cout << q3.get_line_switch();
          -| 0

     [Figure 109 not displayed.]

     Some `Path' functions only work on _linear `Paths'_, so it's
     necessary to be able to distinguish them from non-linear ones.
     The function `is_linear()' should be enough to ensure that all of
     these functions work, so I plan to make `line_switch' obsolete
     soon.  However, at the moment, it's still needed.  *Note Path
     Reference; Querying: Querying Paths.

 - Protected variable: bool cycle_switch
     `true' if the `Path' is cyclical, otherwise `false'.

 - Protected variable: bool on_free_store
     `true' if the `Path' was dynamically allocated on the free store.
     Otherwise `false'.  Set to `true' only in `create_new<Path>()',
     which should be the only way `Paths' are ever dynamically
     allocated.  *Note Path Reference; Constructors and Setting
     Functions: Path Constructors and Setting Functions.

 - Protected variable: bool do_output
     Used in `Picture::output()'.  Set to `false' if the `Path' isn't
     projectable using the arguments passed to `Picture::output()'.
     *Note Picture Reference; Outputting: Outputting Pictures.

 - Protected variable: signed short fill_draw_value
     Set in the drawing and filling functions, and used in
     `Path::output()', to determine what MetaPost code to write to
     `out_stream'.  *Note Path Reference; Drawing and Filling: Drawing
     and Filling Paths, and *Note Path Reference; Outputting:
     Outputting Paths.

 - Protected variable: const Color* draw_color
     Pointer to the `Color' used if the `Path' is drawn.

 - Protected variable: const Color* fill_color
     Pointer to the `Color' used if the `Path' is filled.

 - Protected variable: string dashed
     String written to `out_stream' for the "dash pattern" in a
     MetaPost `draw' or `undraw' command.  If and only if `dashed' is
     not the empty string, "`dashed' <_dash pattern_>" is written to
     `out_stream'.

     Dash patterns have no meaning inside 3DLDF;  `dashed', if
     non-empty, is written unchanged to `out_stream'.  I may change this
     in the future.

 - Protected variable: string pen
     String written to `out_stream' for the `pen' to be used in a
     MetaPost `draw', `undraw', `filldraw', or `unfilldraw' command.
     If and only if `pen' is not the empty string, "`withpen' <...>" is
     written to `out_stream'.

     Pens have no meaning inside 3DLDF;  `pen', if non-empty, is
     written unchanged to `out_stream'.  I may change this in the
     future.

 - Protected variable: bool arrow
     Indicates whether an arrow should be drawn when outputting a
     `Path'.  Set to `true' on a `Path' created on the free store and
     put onto a `Picture' by `drawarrow()'.

 - Protected variable: valarray<real> projective_extremes
     Contains the maxima and minima of the x, y, and z-coordinates of
     the _projections_ of `Points' on a `Path' using a particular
     `Focus'.  Set in `set_extremes()' and used in `Picture::output()'
     for surface hiding.

 - Protected variable: vector<Point*> points
     Pointers to the `Points' on the `Path'.

 - Protected variable: vector<string> connectors
     The connectors between the `Points' on the `Path'.  Connectors are
     simply `strings' in 3DLDF, they are written unchanged to
     `out_stream'.

 - Public static variable: const Color* help_color
     Pointer to a `const Color', which becomes the default for
     `draw_help()'.  *Note Path Reference; Drawing and Filling: Drawing
     and Filling Paths.

     Please note that `help_color' is a pointer to a `const Color', not
     a `const' pointer to a `Color' or a `const' pointer to a `const
     Color'!  It's easy to get confused by the syntax for these types
     of pointers.(1)

 - Public static variable: string help_dash_pattern
     The default dash pattern for `draw_help()'.

 - Public static variable: bool do_help_lines
     `true' if help lines should be output, otherwise `false'.  If
     `false', a call to `draw_help()' does not cause a copy of the
     `Path' to be created and put onto a `Picture'.  *Note Path
     Reference; Drawing and Filling: Drawing and Filling Paths.

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

   (1) Stroustrup, `The C++  Programming Language', p. 96.


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

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

 - Default constructor: void Path (void)
     Creates an empty `Path' with no `Points' and no connectors.

 - Constructor: void Path (const Point& P0, const Point& P1)
     Creates a line (more precisely, a line segment) between P0 and P1.
     The single connector between the two `Points' is set to `"--"'
     and the data member `line_switch' (of type `bool') is set to
     `true'.  There are certain operations on `Paths' that are only
     applicable to lines, so it's necessary to store the information
     that a `Path' is a line.(1)

          Point A(-2, -2.5, -1);
          Point B(3, 2, 2.5)
          Path p(A, B);
          p.show("p:");
          -| p:
             (-2, -2.5, -1) -- (3, 2, 2.5);

     [Figure 110 not displayed.]


 - Setting function: void set (const Point& P0, const Point& P1)
     Corresponds to the constructor above.

          Point P0(1, 2, 3);
          Point P1(3.5, -12, 75);
          Path q;
          q.set(P0, P1);
          q.show("q:");
          -| q:
             (1, 2, 3) -- (3.5, -12, 75);


 - Constructor: void Path (string CONNECTOR, bool CYCLE, Point* P,
          [...], 0)
     For `Paths' with an arbitrary number of `Points' and one type of
     connector.

     CONNECTOR is passed unchanged to `out_file', so it must be a valid
     connector in MetaPost.

     CYCLE indicates whether the `Path' is a cycle or not.
     `cycle_switch' is set to CYCLE.  *Note Path Reference; Data
     Members: Path Data Members.  The filling and unfilling functions
     only work for `Paths' that are cycles.  *Note Path Reference;
     Drawing and Filling: Drawing and Filling Paths.  If a `Path' is a
     cycle, it is up to the user to make sure that it has sensible
     `Point' and connector values;  3DLDF doesn't check them.  If they
     are not sensible, for instance, if the `Path' crosses itself, and
     you try to fill it, this will cause an error in MetaPost.  It is
     possible that a `Path' will be "sensible" in some projections and
     not in others, although I have not tested this.

     P is a pointer to the first `Point' that should go onto the `Path'.
     The ellipsis points (`...') represent an arbitrary number of
     pointers to `Points' that should go onto the `Path'.  The final
     argument must be `0', which is interpreted by the C++  compiler as
     the null pointer.(2)

     It is admittedly a bit awkward to have to type "`&p0'" rather than
     "`p0'", and I have frequently forgotten to do it, which causes a
     compiler error, but all of the arguments must be pointers in order
     to be able to use 0 to indicate the end of the argument list.
     Convenience in typing function calls is not a high priority in
     3DLDF, because once I've written an input routine, these function
     calls should be generated automatically.  It will be more
     important to define a convenient syntax for the input routine.

          Point P0;
          Point P1(2);
          Point P2(2,2);
          Point P3(0,2);
          Path p("..", true, &P0, &P1, &P2, &P3, 0);
          p.draw();

     [Figure 111 not displayed.]


 - Setting function: void set (string CONNECTOR, bool CYCLE, Point* P,
          [...], 0)
     Corresponds to the constructor above.

          Point P[4];
          P[0].set(2, 1, 3);
          P[3] = P[2] =  P[1] = P[0];
          P[3] *= P[2] *=  P[1].rotate(3, 12, 18);
          P[3] *= P[2].shift(-2, -1, 3);
          P[3].shear(1.5, .5, 3.5);
          Path q("...", false, &P[0], &P[1], &P[2], &P[3], 0);
          q.show("q:");
          -| q:
             (2, 1, 3) ... (0.92139, 1.51449, 3.29505) ...
             (-1.07861, 0.514487, 6.29505) ... (2.84065, -3.26065, 6.29505);

     [Figure 112 not displayed.]


 - Constructor: void Path (Point* FIRST_POINT_PTR, char* S, Point* P,
          [...], 0)
     Constructor for `Paths' with an arbitrary number of `Points' and
     connectors.  The first, required, argument is a pointer to a
     `Point', followed by pointers to `char' alternating with pointers
     to `Points'.(3) The last argument must be 0, i.e., the null
     pointer.

     There is no need to indicate by means of an argument whether the
     `Path' is a cycle or not:  If it is, the last argument before the 0
     will be a `char*' (pointer to `char'), if not, it will be a
     `Point*'.  The data member `cycle_switch' (of type `bool') will be
     set to `true' or `false' accordingly.

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

     [Figure 113 not displayed.]


 - Setting function: void set (Point *FIRST_POINT_PTR, string S, Point
          *P, [...], 0)
     Corresponds to the constructor above.

 - Copy constructor: void Path (const Path& P)
     Creates a new `Path', making it a copy of P.

 - Template specializations: Path* create_new<Path> (const Path* P)
 - : Path* create_new<Path> (const Path& P)
     Pseudo-constructors for dynamic allocation of `Paths'.  They
     create a `Path' on the free store and allocate memory for it using
     `new(Path)'.  They return a pointer to the new `Path'.

     If P is a non-zero pointer or a reference, the new `Path' will be
     a copy of P.  If the new object is not meant to be a copy of an
     existing one, `0' must be passed to `create_new<Path>()' as its
     argument.  *Note Dynamic Allocation of Shapes::, for more
     information.

     `create_new<Path>()' is used in the drawing and filling functions
     for copying a `Path' and putting the copy onto a `Picture'.  *Note
     Path Reference; Drawing and Filling: Drawing and Filling Paths.

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

   (1) It isn't sufficient to check whether a `Path' consists of only
two `Points' to determine whether it is a line or not, since a
connector with "`curl'" could cause it to be non-linear.  On the other
hand, `Paths' containing only colinear `Points' and the connector
`"--"' are perfectly legitimate lines.  I'm in the process of changing
all of the code that tests for linearity by checking the value of
`line_switch', so that it uses `is_linear()' instead.  When I've done
this, it may be possible to eliminate `line_switch'.  *Note Path
Reference; Data Members: Path Data Members, and *Note Path Reference;
Querying: Querying Paths.

   (2) Stroustrup, `The C++  Programming Language', p. 88.

   (3) Where possible, I prefer to use the C++  data type `string'
rather than `char*', however it was necessary to use `char*' here
because 0 is not a valid `string', even though `string' may be
implemented as `char*', and 0 must be a valid argument, since it is
needed to indicate the end of the argument list.


File: 3DLDF.info,  Node: Path Destructor,  Next: Path Operators,  Prev: Path Constructors and Setting Functions,  Up: Path Reference

Destructor
==========

 - `virtual' Destructor: void ~Path (`void')
     All of the `Points' on a `Path' are created by
     `create_new<Point>()', which allocates them dynamically on the
     free store.  Therefore, the destructor calls `delete()' on all of
     the pointers on `points'.  Following this, it calls
     `points.clear()' and `connectors.clear()'.  `draw_color' and
     `fill_color' may or may not have been allocated on the free store,
     so `~Path()' checks this first, and deletes them, if they were.
     Then, it sets them to 0.


File: 3DLDF.info,  Node: Path Operators,  Next: Appending to Paths,  Prev: Path Destructor,  Up: Path Reference

Operators
=========

 - Virtual function: Transform operator*= (const Transform& T)
     Calls `Point::operator*=(T)' on each of the `Points' on the `Path'.
     *Note Point Reference; Operators: Point Operators.  This has the
     effect of transforming the entire `Path' by T.  Please note that
     `Path' does not have a `transform' data member of its own.

 - Function: void operator+= (const Point& PT)
     Copies PT and pushes a pointer to the copy onto `points'.  The
     last connector in the `Path' will be used to connect the new
     `Point' and the previous one.

          Point A(1, 2, 3);
          Point B(3, 4, 5);
          Path q;
          q += A;
          q += B;
          q.show("q:");
          -| q:
             (1, 2, 3) -- (3, 4, 5);


 - `const' function: Path operator+ (const Point& PT)
     Copies the `Path' and PT, and pushes a pointer to the copy of PT
     onto `points' in the new `Path'.  The last connector in the new
     `Path' will be used to connect the new `Point' and the previous
     one.  The `Path' remains unchanged.

 - Function: void operator&= (const Path& PA)
     Concatenates two `Paths'.  The result is assigned to `*this'.
     Neither `*this' nor PA may be cyclical, i.e., `cycle_switch' must
     be `false' for both `Paths'.

 - `const' function: Path operator& (const Path& PA)
     Returns a `Path' representing the concatenation of `*this' and PA.
     `*this' remains unchanged.  Neither `*this' nor PA may be
     cyclical, i.e., `cycle_switch' must be `false' for both `Paths'.

 - Function: void operator+= (const string S)
     Pushes S onto `connectors'.


File: 3DLDF.info,  Node: Appending to Paths,  Next: Copying Paths,  Prev: Path Operators,  Up: Path Reference

Appending
=========

 - Function: Path append (const Path& PA, [string CONNECTOR = "--",
          [bool ASSIGN = `true']])
     Appends PA to `*this' using CONNECTOR to join them and returns the
     resulting `Path'.  If ASSIGN == `true', then the return value is
     assigned to `*this', otherwise, `*this' remains unchanged.

     If necessary, a `const' version could be added, for `const Paths'.

          Point A(-2, 2);
          Point B(-2, -2);
          Point C(2, -2);
          Point D(2, 2);
          Path q("--", false, &A, &B, &C, &D, 0);
          Point E(1, 2);
          Point F(0, 4);
          Point G(-.5, 3);
          Path r("..", false, &E, &F, &G, 0);
          q.append(r, "..", true);
          q += "..";
          q += "--";
          q.set_cycle();
          q.show("q:");
          -| q:
             (-2, 2, 0) -- (-2, -2, 0) --
             (2, -2, 0) -- (2, 2, 0) ..
             (1, 2, 0) .. (0, 4, 0) ..
             (-0.5, 3, 0) -- cycle;

     [Figure 114 not displayed.]



File: 3DLDF.info,  Node: Copying Paths,  Next: Clearing Paths,  Prev: Appending to Paths,  Up: Path Reference

Copying
=======

 - `const' virtual function: Shape* get_copy (void)
     Creates a copy of the `Path' using `create_new<Path>()', which
     returns a pointer to `Path'.  `get_copy()' then casts this pointer
     to a pointer to `Shape' and returns it.

     This function is used when copying `Pictures' and in
     `Solid::output()', where objects of types derived from `Shape'
     must be handled in the same way, without their actual types being
     known.


File: 3DLDF.info,  Node: Clearing Paths,  Next: Modifying Paths,  Prev: Copying Paths,  Up: Path Reference

Clearing
========

 - Virtual function: void clear (void)
     Does the same thing the destructor `~Path()' does: Calls
     `delete()' on the pointers to `Points' on `points', clears
     `points' and `connectors', deletes `draw_color' and `fill_color',
     if they point to `Colors' that were allocated on the free store,
     and sets them to 0.

     `clear()' is a pure virtual function in `class Shape', so `Path'
     must be have a `clear()' function.  It is needed, because it is
     sometimes called through a pointer to `Shape', so that `~Path()'
     cannot be accessed.  At least, so far I haven't found a way to
     call a destructor through the virtual function facility.


File: 3DLDF.info,  Node: Modifying Paths,  Next: Affine Transformations for Paths,  Prev: Clearing Paths,  Up: Path Reference

Modifying
=========

 - Virtual function: bool set_on_free_store ([bool B = `true'])
     Sets `on_free_store' to B.  This is used in the template function
     `create_new()'.  *Note Path Reference; Constructors and Setting
     Functions: Path Constructors and Setting Functions.

 - Virtual function: void set_fill_draw_value (const signed short S)
     Sets `fill_draw_value' to S, which should be one of `Shape::DRAW',
     `Shape::FILL', `Shape::FILLDRAW', `Shape::UNDRAW',
     `Shape::UNFILL', or `Shape::UNFILLDRAW'.

 - Virtual function: void set_draw_color (const Color& C)
 - Virtual function: void set_draw_color (const Color * C)
     Sets `draw_color' (a pointer to a `const Color') to &C or C,
     depending on whether the version with a reference argument or the
     version with a pointer argument is used.

     `set_draw_color()' is used in the `Solid' drawing and filling
     functions, because `Path::draw_color' is `protected', and the
     `Solid' cannot access it directly.  *Note Solid Reference; Drawing
     and Filling: Drawing and Filling Solids.

 - Virtual function: void set_fill_color (const Color& C)
 - Virtual function: void set_fill_color (const Color* C)
     Sets `fill_color' (a pointer to a `const Color') to &C or C,
     depending on whether the version with a reference argument or the
     version with a pointer argument is used.

     `set_fill_color()' is used in the `Solid' drawing and filling
     functions, because `Path::fill_color' is `protected', and the
     `Solid' cannot access it directly.  *Note Solid Reference; Drawing
     and Filling: Drawing and Filling Solids.

 - Virtual function: void set_dash_pattern ([const string S = ""])
     Sets `dashed' to S.

 - Virtual function: void set_pen ([const string S = ""])
     Sets `pen' to S.

 - Virtual function: void set_connectors ([const string S = ".."])
     Clears `connectors' and then pushes S onto it, making S the only
     connector.  Additional connectors can be added by using
     `Path::operator+=(const string)'.  *Note Path Reference;
     Operators: Path Operators.

     I plan to add a version of this function taking a vector of
     `strings' as its argument, to make it possible to set several
     connectors at one time.


File: 3DLDF.info,  Node: Affine Transformations for Paths,  Next: Aligning Paths with an Axis,  Prev: Modifying Paths,  Up: Path Reference

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

 - Virtual function: Transform rotate (const real X, [const real Y = 0,
          [const real Z = 0]])
     Creates a `Transform t' locally and calls `t.rotate(X, Y, Z)'.
     `t' is then applied to all of the `Points' on `points'.  The
     return value is `t'.

 - Function: Transform scale (real X, [real y = 1, [real z = 1]])
     Creates a `Transform t' locally and calls `t.scale(X, Y, Z)'.  `t'
     is then applied to all of the `Points' on `points'.  The return
     value is `t'.

     The `Points' on the `Path' are scaled according to the arguments:

          Point pt[8];
          pt[0] = (-1, -1);
          for (int i = 1; i < 8; ++i)
            {
              pt[i] = pt[0];
              pt[i].rotate(0, 0, i * 45);
            }
          Path p("--", true, &pt[0], &pt[1], &pt[2], &pt[3],
                 &pt[4], &pt[5], &pt[6],
                 &pt[7], 0);
          p.draw();
          p.scale(2, 2);
          p.draw();

     [Figure 115 not displayed.]


 - Function: Transform shear (real XY, [real XZ = 0, [real YX = 0,
          [real YZ = 0, [real ZX = 0, [real ZY = 0]]]]])
     Creates a `Transform t' locally and calls `t.shear(XY, XZ, YX, YZ,
     ZX, ZY)'.  `t' is then applied to all of the `Points' on `points'.
     The return value is `t'.

          Point p0;
          Point p1(1);
          Point p2(1, 1);
          Point p3(0, 1);
          Path q("--", true, &p0, &p1, &p2, &p3, 0);
          q.rotate(0, 45);
          q.shift(1);
          q.filldraw(black, light_gray);
          q.shear(1.5, 2, 2.5, 3, 3.5, 5);
          q.filldraw(black, light_gray);

     [Figure 116 not displayed.]


 - Function: Transform shift (real X, [real Y = 0, [real Z = 0]])
     Creates a `Transform t' locally and calls `t.shift(X, Y, Z)'.  `t'
     is then applied to all of the `Points' on `points'.  The return
     value is `t'.

     Shifts each of the `Points' on the `Path' according to the
     arguments.

          default_focus.set(5, 10, -10, 0, 10, 10, 10);
          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.draw();
          p.shift(3, 3, 3);
          p.draw();

     [Figure 117 not displayed.]


 - Function: Transform shift (const Point& P)
     Creates a `Transform t' locally and calls `t.shift(P)'.  `t' is
     then applied to all of the `Points' on `points'.  The return value
     is `t'.

     This version of `shift()' uses the x, y, and z-coordinates of the
     `Point' P to shift the `Path'.

          default_focus.set(5, 10, -10, 0, 10, 10, 10);
          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.draw();
          Point s(1, 1, 1);
          p.shift(s);
          p.draw();

     [Figure 118 not displayed.]


 - Virtual function: void shift_times (real X, [real Y = 1, [real Z =
          1]])
 - Virtual function: void shift_times (const Point& @var{p})
     Each of these functions calls the corresponding version of
     `Point::shift_times()' on all of the `Points' on `points'.  *Note
     Point Reference; Affine Transformations: Affine Transformations
     for Points.  The return value is `void', because there is no
     guarantee that all of the `Points' on a `Path' will have identical
     `transform' members (although it's likely).

     Please note that `shift_times()' will only have an effect on the
     `Points' on a `Path' if it's called _after_ a call to `shift()'
     and _before_ an operation is applied that causes
     `Point::apply_transform()' to be called.

 - Virtual function: Transform rotate (const Point& P0, const Point&
          P1, [const real ANGLE = 180])
     Creates a `Transform t' locally and calls `t.rotate(P0, P1,
     ANGLE)'.  `t' is then applied to all of the `Points' on `points'.
     The return value is `t'.

 - Function: Transform rotate (const Path& P, [const real ANGLE = 180])
     If `p.is_linear()' returns `true', this function creates a
     `Transform' T locally and calls `T.rotate(P, ANGLE)'.  `t' is then
     applied to all of the `Points' on `points'.  The return value is
     `t'.  Otherwise, it issues an error message and returns
     `INVALID_TRANSFORM'.


File: 3DLDF.info,  Node: Aligning Paths with an Axis,  Next: Applying Transformations to Paths,  Prev: Affine Transformations for Paths,  Up: Path Reference

Aligning with an Axis
=====================

 - `const' function: Transform align_with_axis ([const char AXIS = 'z'])
 - Function: Transform align_with_axis (bool ASSIGN, [const char AXIS =
          'z'])
 - Function: Transform align_with_axis (const Point& P0, const Point&
          P1, const char AXIS)
     These functions return the `Transform' which, if applied to the
     `Path', would align it with the major axis indicated by the AXIS
     argument.

     The first and second versions can only be called for `Paths' where
     `line_switch' is `true'.  The first version is `const', so the
     `Path' remains unchanged.  The second version should only be
     called with `ASSIGN = true', so that the `Transform' is applied to
     the `Path', actually aligning it with the axis indicated.  If the
     second version is called with `ASSIGN = false', a warning message
     is issued to the standard error output (`stderr'), since one might
     as well use the first version in this case, but it won't do any
     harm.  The third version creates a `Transform' T locally that
     would align the line from P0 to P1 with the axis indicated, and
     applies T to the `Path'.

          Point A(2, 3, 2);
          Point B(-1, 1, 3);
          Path p(A, B);
          Transform t = p.align_with_axis(true, 'z');
          t.show("t:");
          -| t:
              -0.316   0.507  -0.802       0
                   0  -0.845  -0.535       0
              -0.949  -0.169   0.267       0
                2.53    1.86    2.67       1
          p *= t;
          p.show("p:");
          -| p:
             (2.53, 1.86, 2.67) -- (-1.02, 1.23, 3.67);
          
          Point C(1);
          C *= t.inverse();
          
          Path q;
          q += "..";
          q += C;
          
          for (int i = 0; i < 15; ++i)
            {
              C.rotate(A, B, 360.0/16);
              q += C;
            }
          q.set_cycle(true);
          q.show("q:");
          -| q:
             (1.68, 3, 1.05) .. (1.9, 2.68, 1.06) ..
             (2.13, 2.4, 1.21) .. (2.35, 2.22, 1.48) ..
             (2.51, 2.15, 1.83) .. (2.59, 2.22, 2.21) ..
             (2.58, 2.4, 2.55) .. (2.49, 2.68, 2.81) ..
             (2.32, 3, 2.95) .. (2.1, 3.32, 2.94) ..
             (1.87, 3.6, 2.79) .. (1.65, 3.78, 2.52) ..
             (1.49, 3.85, 2.17) .. (1.41, 3.78, 1.79) ..
             (1.42, 3.6, 1.45) .. (1.51, 3.32, 1.19) .. cycle;
          q.align_with_axis(A, B, 'z');
          q.show("q:");
          -| q:
             (1, 0, 0) .. (0.924, 0.383, 0) ..
             (0.707, 0.707, 0) .. (0.383, 0.924, 0) ..
             (0, 1, 0) .. (-0.383, 0.924, 0) ..
             (-0.707, 0.707, 0) .. (-0.924, 0.383, 0) ..
             (-1, 0, 0) .. (-0.924, -0.383, 0) ..
             (-0.707, -0.707, 0) .. (-0.383, -0.924, 0) ..
             (0, -1, 0) .. (0.383, -0.924, 0) ..
             (0.707, -0.707, 0) .. (0.924, -0.383, 0) .. cycle;

     [Figure 119 not displayed.]



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

Applying Transformations
========================

 - Virtual function: void apply_transform (void)
     Calls `Point::apply_transform()' on all of the `Points' on
     `points'.  *Note Point Reference; Applying Transformations:
     Applying Transformations to Points.

