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: Returning Information for Points,  Next: Modifying Points,  Prev: Returning Coordinates,  Up: Point Reference

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

 - Static function: real epsilon (void)
     Returns the positive `real' value of smallest magnitude \epsilon
     that should be used as a coordinate value in a `Point'.  A
     coordinate of a `Point' may also contain -\epsilon.

     The value \epsilon is used for testing the equality of `Points' in
     `Point::operator==()' (*note Point Reference; Operators: Point
     Operators.):

     Let \epsilon be the value returned by `epsilon()', P and Q be
     `Points', and P_x, Q_x, P_y, Q_y, P_z, and Q_z the updated x, y,
     and z-coordinates of P and Q, respectively.  If and only if ||P_x|
     - |Q_x|| < \epsilon, ||P_y| - |Q_y|| < \epsilon, and ||P_z| -
     |Q_z|| < \epsilon, then P = Q.

     `epsilon()' returns different values, depending on whether `real'
     is `float' or `double': If `real' is `float' (the default),
     `epsilon()' returns 0.00001.  If `real' is `double', it returns
     0.000000001.

     Please note:  I haven't tested whether 0.000000001 is a good value
     yet, so users should be aware of this if they set `real' to
     `double'!(1) The way to test this is to start with two `Points' P
     and Q at different locations.  Then they should be transformed
     using different rotations in such a way that they should end up at
     the same location.  Let \epsilon stand for the value returned by
     `epsilon()', and let x, y, and y stand for the `world_coordinates'
     of the `Points' after `apply_transform()' has been called on them.
     If x_P = x_Q, y_P = y_Q, and z_P = z_Q, \epsilon is a good value.

     Rotation causes a significant loss of precision to due to the use
     of the `sin()' and `cos()' functions.  Therefore, neither
     `Point::epsilon()' nor `Transform::epsilon()' (*note Tranform
     Reference; Returning Information: Returning Information for
     Transforms.)  can be as small as I'd like them to be.  If they are
     two small, operations that test for equality of `Transforms' and
     `Points' will return `false' for objects that should be equal.

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

   (1) For that matter, I haven't really tested whether 0.00001 is a
good value when `real' is `float'.


File: 3DLDF.info,  Node: Modifying Points,  Next: Affine Transformations for Points,  Prev: Returning Information for Points,  Up: Point Reference

Modifying
=========

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

 - Function: void clear (void)
     Sets all of the coordinates in all of the sets of coordinates
     (i.e., `world_coordinates', `user_coordinates',
     `view_coordinates', and `projective_coordinates') to 0 and resets
     `transform'

 - Function: void clean ([int FACTOR = 1])
     Calls `apply_transform()' and sets the values of
     `world_coordinates' to 0, whose absolute values are less than
     `epsilon()' * FACTOR .

 - Function: void reset_transform (void)
     Sets `Transform' to the identity `Transform'.  Performed in
     `apply_transform()', after the latter updates `world_coordinates'.
     *Note Point Reference; Applying Transformations: Applying
     Transformations to Points.


File: 3DLDF.info,  Node: Affine Transformations for Points,  Next: Applying Transformations to Points,  Prev: Modifying Points,  Up: Point Reference

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

 - Function: Transform rotate (const real X, [const real Y = 0, [const
          real Z = 0]])
 - Function: Transform rotate (const Point& P0, const Point& P1, [const
          real ANGLE = 180])
 - Function: Transform rotate (const Path& P, [const real ANGLE = 180])
     Each of these functions calls the corresponding version of
     `Transform::rotate()', and returns its return value, namely, a
     `Transform' representing the rotation only.

     In the first version, taking three `real' arguments, the `Point'
     is rotated X degrees around the x-axis, Y degrees around the
     y-axis, and Z degrees around the z-axis in that order.

          Point p0(1, 0, 2);
          p0.rotate(90);
          p0.show("p0:")
          -| p0: (1, 2, 0)
          Point p1(-1, 1, 1);
          p1.rotate(-90, 90, 90);
          p1.show("pt1:");
          -| p1: (1, -1, -1)

     [Figure 81 not displayed.]

     Please note that rotations are not commutative operations.  Nor
     are they commutative with other transformations.  So, if you want
     to rotate a `Point' about the x, y and z-axes in that order, you
     can do so with a single invocation of `rotate()', as in the
     previous example.  However, if you want to rotate a `Point' first
     about the y-axis and then about the x-axis, you must invoke
     `rotate()' twice.

          Point pt0(1, 1, 1);
          pt0.rotate(0, 45);
          pt0.rotate(45);
          pt0.show("pt0:");
          -| pt0: (0, 1.70711, 0.292893)

     In the version taking two `Point' arguments P0 and P1, and a
     `real' argument ANGLE, the `Point' is rotated `angle' degrees
     around the axis determined by P0 and P1, 180 degrees  by default.

          Point P(2, 0, 0);
          Point A;
          Point B(2, 2, 2);
          P.rotate(A, B, 180);

     [Figure 82 not displayed.]


 - Function: Transform scale (real X, [real Y = 1, [real Z = 1]])
     Calls `transform.scale(X, Y, Z)' and returns its return value,
     namely, a `Transform' representing the scaling operation only.

     Scaling causes the x-coordinate of the `Point' to be multiplied by
     X, the y-coordinate of the `Point' to be multiplied by Y, and the
     z-coordinate of the `Point' to be multiplied by Z.

          Point p0(1, 0, 3);
          p0.scale(4);
          p0.show("p0:");
          -| p0: (4, 0, 3)
          Point p1(-2, -1, -2);
          p1.scale(-2, -3, -4);
          p1.show("p1:");
          -| p1: (4, 3, 8)

     [Figure 83 not displayed.]


 - Function: Transform shear (real XY, [real XZ = 0, [real YX = 0,
          [real YZ = 0, [real ZX = 0, [real ZY = 0]]]]])
     Calls `transform.shear()' with the same arguments and returns its
     return value, namely, a `Transform' representing the shearing
     operation only.

     Shearing modifies each coordinate of a `Point' proportionately to
     the values of the other two coordinates.  Let x_0, y_0, and z_0
     stand for the coordinates of a `Point' P before `P.shear('\alpha,
     \beta, \gamma, \delta, \epsilon, \zeta `)', and x_1, y_1, and z_1
     for its coordinates afterwards.

          x_1 == x_0 + \alpha y + \beta z
          y_1 == y_0 + \gamma x + \delta z
          z_1 == z_0 + \epsilon x + \zeta y

     [next figure]  demonstrates the effect of shearing the four
     `Points' of a 3 * 3

     `Rectangle' (i.e., a square) r in the x-y plane using only an XY
     argument, making it non-rectangular.

          Point P0;
          Point P1(3);
          Point P2(3, 3);
          Point P3(0, 3);
          Rectangle r(p0, p1, p2, p3);
          r.draw();
          r.shear(1.5);
          r.draw(black, "evenly");

     [Figure 84 not displayed.]


 - Function: Transform shift (real X, [real Y = 0, [real Z = 0]])
 - Function: Transform shift (const Point& P)
     Each of these functions calls the corresponding version of
     `Transform::shift()' on `transform', and returns its return value,
     namely, a `Transform' representing the shifting operation only.

     The `Point' is shifted X units in the direction of the positive
     x-axis, Y units in the direction of the positive y-axis, and Z
     units in the direction of the positive z-axis.

          p0(1, 2, 3);
          p0.shift(2, 3, 5);
          p0.show("p0:");
          -| p0: (3, 5, 8)


 - Function: Transform shift_times (real X, [real Y = 1, [real Z = 1]])
 - Function: Transform shift_times (const Point& P)
     Each of these functions calls the corresponding version of
     `Transform::shift_times()' on `transform' and returns its return
     value, namely the new value of `transform'.

     `shift_times()' makes it possible to increase the magnitude of a
     shift applied to a `Point', while maintaining its direction.
     Please note that `shift_times()' will only have an effect if it's
     called after a call to `shift()' and before `transform' is reset.
     This is performed by `reset_transform()', which is called in
     `apply_transform()', and can also be called directly.  *Note
     Transform Reference; Resetting: Resetting Transforms, and *Note
     Point Reference; Applying Transformations: Applying
     Transformations to Points.

          Point P;
          P.drawdot();
          P.shift(1, 1, 1);
          P.drawdot();
          P.shift_times(2, 2, 2);
          P.drawdot();
          P.shift_times(2, 2, 2);
          P.drawdot();
          P.shift_times(2, 2, 2);
          P.drawdot();

     [Figure 85 not displayed.]



File: 3DLDF.info,  Node: Applying Transformations to Points,  Next: Projecting Points,  Prev: Affine Transformations for Points,  Up: Point Reference

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

 - Function: void apply_transform (void)
     Updates `world_coordinates' by multiplying it by `transform',
     which is subsequently reset to the identity `Transform'.


File: 3DLDF.info,  Node: Projecting Points,  Next: Vector Operations,  Prev: Applying Transformations to Points,  Up: Point Reference

Projecting
==========

 - Function: bool project (const Focus& F, [const unsigned short PROJ =
          Projections::PERSP, [real FACTOR = 1]])
 - Function: bool project ([const unsigned short& PROJ =
          Projections::PERSP, [real FACTOR = 1]])
     These functions calculate `projective_coordinates'.  PROJ
     indicates which projection is to be performed.  If it is
     `Projections::PERSP', then F indicates which `Focus' is to be used
     (in the first version), or the global variable `default_focus' is
     used (in the second).  If `Projections::PARALLEL_X_Y',
     `Projections::PARALLEL_X_Z', or `Projections::PARALLEL_Z_Y' is
     used, F is ignored, since these projections don't use a `Focus'.
     Currently, no other projections are defined.  The x and y
     coordinates in `projective_coordinates' are multiplied by FACTOR
     with the default being 1.


File: 3DLDF.info,  Node: Vector Operations,  Next: Points and Lines,  Prev: Projecting Points,  Up: Point Reference

Vector Operations
=================

   Mathematically speaking, vectors and points are not the same.
However, they can both be represented as triples of real numbers (in a
three-dimensional Cartesian space).  It is sometimes convenient to treat
points as though they were vectors, and vice versa.  In particular, it
is convenient to use the same data type, namely `class Point', to
represent both points and vectors in 3DLDF.

 - `const' function: real dot_product (Point P)
     Returns the dot or scalar product of `*this' and P.

     If P and Q are `Points',
          P \dot Q = x_P * x_Q + y_P * y_Q + z_P * z_Q = |P||Q| * cos(\theta)
     where  |P| and |Q| are the magnitudes of P and Q, respectively,
     and \theta is the angle between P and Q.

     Since
          \theta = arccos(P \dot Q / |P||Q|),
     the dot product can be used for finding the angle between two
     vectors.

          Point P(1, -1, -1);
          Point Q(3, 2, 5);
          cout << P.angle(Q);
          -| 112.002
          cout << P.dot_product(Q);
          -| -4
          real P_Q_angle = (180.0 / PI)
                           * acos(P.dot_product(Q)
                           / (P.magnitude() * Q.magnitude()));
          cout << P_Q_angle;
          -| 112.002

     [Figure 86 not displayed.]

     If the angle \theta between two vectors P and Q is 90 degrees ,
     then \cos(\theta) is 0, so P \dot Q will also be 0.  Therefore,
     `dot_product()' can be used as a test for the orthogonality of
     vectors.

          Point P(2);
          Point Q(P);
          Point Q0(P0);
          Q0 *= Q.rotate(0, 0, 90);
          P *= Q.rotate(0, 45, 45);
          P *= Q.rotate(45);
          cout << P.angle(Q);
          -| 90
          cout << P.dot_product(Q);
          -| 0

     [Figure 87 not displayed.]


 - `const' function: Point cross_product (Point P)
     Returns the cross or vector product of `*this' and P.

     If P and Q are `Points',

          P * Q = ((y_P * z_Q - z_P * y_Q), (z_P * x_Q - x_P * z_Q),
          (x_P * y_Q - y_P * x_Q)) = |P||Q| * sin(\theta) * n,

     where |P| and |Q| are the magnitudes of P and Q, respectively,
     \theta is the angle between P and Q, and n is a unit vector
     perpendicular to both P and Q in the direction of a right-hand
     screw from P towards Q.  Therefore, `cross_product()' can be used
     to find the normals to planes.

          Point P(2, 2, 2);
          Point Q(-2, 2, 2);
          Point n = P.cross_product(Q);
          n.show("n:");
          -| n: (0, -8, 8)
          real theta = (PI / 180.0) * P.angle(Q);
          cout << theta;
          -| 1.23096
          real n_mag = P.magnitude() * Q.magnitude() * sin(theta);
          cout << n_mag;
          -| 11.3137
          n /= n_mag;
          cout << n.magnitude();
          -| 1

     [Figure 88 not displayed.]

     If \theta = 0 degrees or 180 degrees, \sin(\theta) will be 0, and
     P * Q  will be (0, 0, 0).  The cross product thus provides a test
     for parallel vectors.

          Point P(1, 2, 1);
          Point Q(P);
          Point R;
          R *= Q.shift(-3, -1, 1);
          Point s(Q - R);
          Point n = P.cross_product(s);
          n.show("n:");
          -| n: (0, 0, 0)

     [Figure 89 not displayed.]


 - `const' function: real magnitude (void)
     Returns the magnitude of the `Point'.  This is its distance from
     `origin' and is equal to sqrt(x^2 + y^2 + z^2).

          Point P(13, 15.7, 22);
          cout << P.magnitude();
          -| 29.9915

 - `const' function: real angle (Point P)
     Returns the angle in degrees between two `Points'.

          Point P(3.75, -1.25, 6.25);
          Point Q(-5, 2.5, 6.25);
          real angle = P.angle(Q);
          cout << angle;
          -| 73.9084
          Point n = origin.get_normal(P, Q);
          n.show("n:");
          -| n: (0.393377, 0.91788, -0.0524503)

     [Figure 90 not displayed.]


 - Function: Point unit_vector (const bool ASSIGN, [const bool SILENT =
          FALSE])
 - `const' function: Point unit_vector (void)
     These functions return a `Point' with the x, y, and z-coordinates
     of `world_coordinates' divided by the magnitude of the `Point'.
     The magnitude of the resulting `Point' is thus 1.  The first
     version assigns the result to `*this' and should only ever be
     called with ASSIGN = `true'.  Calling it with the argument `false'
     is equivalent to calling the `const' version, with no assignment.
     If `unit_vector()' is called with ASSIGN and SILENT both `false',
     it issues a warning message is issued and the `const' version is
     called.  If SILENT is `true', the message is suppressed.

          Point P(21, 45.677, 91);
          Point Q = P.unit_vector();
          Q.show("Q:");
          -| Q: (0.201994, 0.439357, 0.875308)
          P.rotate(30, 25, 10);
          P.show("P:");
          P: (-19.3213, 82.9627, 59.6009)
          cout << P.magnitude();
          -| 103.963
          P.unit_vector(true);
          P.show("P:");
          -| P: (-0.185847, 0.797999, 0.573287)
          cout << P.magnitude();
          -| 1



File: 3DLDF.info,  Node: Points and Lines,  Next: Point Intersections,  Prev: Vector Operations,  Up: Point Reference

Points and Lines
================

 - `const' function: Line get_line (const Point& P)
     Returns the `Line' L corresponding to the line from `*this' to P.
     L.`position' will be `*this', and L.`direction' will be P -
     `*this'.  *Note Line Reference::.

 - `const' function: real slope (Point P, [char M = 'x', [char N =
          'y']])
     Returns a `real' number representing the slope of the _trace_ of
     the line defined by `*this' and P on the plane indicated by the
     arguments M and N.

          Point p0(3, 4, 5);
          Point p1(2, 7, 12);
          real r = p0.slope(p1, 'x', 'y');
          => r == -3
          r = p0.slope(p1, 'x', 'z');
          => r == -7
          r = p0.slope(p1, 'z', 'y');
          => r == 0.428571

 - Function: bool_real is_on_segment (Point P0, Point P1)
 - `const' function: bool_real is_on_segment (const Point& P0, const
          Point& P1)
     These functions return a `bool_real', where the `bool' part is
     `true', if the `Point' lies on the line segment between P0 and P1,
     otherwise `false'.  If the `Point' lies on the line segment, the
     `real' part is a value r such that 0 <= r <= 1 indicating how far
     the `Point' is along the way from P0 to P1.  For example, if the
     `Point' is half of the way from P0 to P1, r will be .5.  If the
     `Point' does not lie on the line segment, but on the _line_
     passing through P0 and P1, r will be <0 or >1.

     If the `Point' doesn't lie on the line passing through P0 and P1,
     r will be `INVALID_REAL'.

          Point p0(-1, -2, 1);
          Point p1(3, 2, 5);
          Point p2(p0.mediate(p1, .75));
          Point p3(p0.mediate(p1, 1.5));
          Point p4(p2);
          p4.shift(-2, 1, -1);
          bool_real br = p2.is_on_segment(p0, p1);
          cout << br.first;
          -| 1
          cout << br.second;
          -| 0.75
          bool_real br = p3.is_on_segment(p0, p1);
          cout << br.first;
          -| 0
          cout << br.second;
          -| 1.5
          bool_real br = p4.is_on_segment(p0, p1);
          cout << br.first;
          -| 0
          cout << br.second;
          -| 3.40282e+38
          cout << (br.second == INVALID_REAL)
          -| 1

     [Figure 91 not displayed.]


 - `const' function: bool_real is_on_line (const Point& P0, const
          Point& P1)
     Returns a `bool_real' where the `bool' part is `true', if the
     `Point' lies on the line passing through P0 and P1, otherwise
     `false'.  If the `Point' lies on the line, the `real' part is a
     value r indicating how how far the `Point' is along the way from
     P0 to P1, otherwise `INVALID_REAL'.  The following values of r are
     possible for a call to `P.is_on_line(A, B)', where the `Point' P
     lies on the line AB:

          P == A ---> r== 0.
          
          P == B ---> r== 1.
          
          P lies on the opposite side of A from B ---> r < 0.
          
          P lies between A and B ---> 0 <  r < 1.
          
          P lies on the opposite side of A from B ---> r > 1

          Point A(-1, -2);
          Point B(2, 3);
          Point C(B.mediate(A, 1.25));
          bool_real br = C.is_on_line(A, B);
          Point D(A.mediate(B));
          br = D.is_on_line(A, B);
          Point E(A.mediate(B, 1.25));
          br = E.is_on_line(A, B);
          Point F(D);
          F.shift(-1, 1);
          br = F.is_on_line(A, B);

     [Figure 92 not displayed.]


 - `const' function: Point mediate (Point P, [const real R = .5])
     Returns a `Point' R of the way from `*this' to P.

          Point p0(-1, 0, -1);
          Point p1(10, 0, 10);
          Point p2(5, 5, 5);
          Point p3 = p0.mediate(p1, 1.5);
          p3.show("p3:");
          -| p3: (15.5, 0, 15.5)
          Point p4 = p0.mediate(p2, 1/3.0);
          p4.show("p4:");
          -| p4: (1, 1.66667, 1)

     [Figure 93 not displayed.]



File: 3DLDF.info,  Node: Point Intersections,  Next: Point Drawing Functions,  Prev: Points and Lines,  Up: Point Reference

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

 - Static function: bool_point intersection_point (Point P0, Point P1,
          Point Q0, Point Q1)
 - Static function: bool_point intersection_point (Point P0, Point P1,
          Point Q0, Point Q1, const bool TRACE)
     These functions find the intersection point, if any, of the lines
     determined by P0 and P1 on the one hand, and Q0 and Q1 on the
     other.

     Let `bp' be the `bool_point' returned by `intersection_point()'.
     If an intersection point is found, the corresponding `Point' will
     be stored in `bp.pt', otherwise, `bp.pt' will be set to
     `INVALID_POINT'.  If the intersection point lies on both of the
     line segments, `bp.b' will be `true', otherwise, `false'.

     The two versions use different methods of finding the intersection
     point.  The first uses a vector calculation, the second looks for
     the intersections of the traces of the lines on the major planes.
     If the TRACE argument is used, the second version will be called,
     whether TRACE is `true' or `false'.  Ordinarily, there should be
     no need to use the trace version.

          Point A(-1, -1);
          Point B(1, 1);
          Point C(-1, 1);
          Point D(1, -1);
          bool_point bp = Point::intersection_point(A, B, C, D);
          bp.pt.dotlabel("$i$");
          cout << "bp.b == " << bp.b << endl << flush;
          -| bp.b == 1

     [Figure 94 not displayed.]

          Point A(.5, .5);
          Point B(1.5, 1.5);
          Point C(-1, 1);
          Point D(1, -1);
          bool_point bp = Point::intersection_point(A, B, C, D, true);
          bp.pt.dotlabel("$i$");
          cout << "bp.b == " << bp.b << endl << flush;
          -| bp.b == 0

     [Figure 95 not displayed.]



File: 3DLDF.info,  Node: Point Drawing Functions,  Next: Labelling Points,  Prev: Point Intersections,  Up: Point Reference

Drawing
=======

   There are two versions for each of the drawing functions.  The second
one has the `Picture' argument PICTURE at the beginning of the argument
list, rather than at the end.  This is convenient when passing a
`picture' argument.  Where PICTURE is optional, the default is always
`current_picture'.

 - `const' function: void drawdot ([const Color& DDRAWDOT_COLOR =
          `*Colors::default_color', [const string PPEN = "", [Picture&
          PICTURE = `current_picture']]])
 - `const' function: void drawdot ([Picture& PICTURE =
          `current_picture', [const Color& DDRAWDOT_COLOR =
          `*Colors::default_color', [const string PPEN = "", ]]])
     Draws a dot on PICTURE.  If PPEN is specified, a "pen expression"
     is included in the `drawdot' command written to `out_stream'.
     Otherwise, MetaPost's `currentpen' is used.  If DDRAWDOT_COLOR is
     specified, the dot will be drawn using that `Color'.  Otherwise,
     the `Color' currently pointed to by the pointer
     `Colors::default_color' will be used.  This will normally be
     `Colors::black'.  See *Note Color Reference::, for more information
     about `Colors' and the `namespace Colors'.

     Please note that the "dot" will always be parallel to the plane of
     projection.  Even where it appears to be a surface, as in [next
     figure] , it is never put into perspective, but will always have
     the same size and shape.

          Point P(1, 1);
          P.drawdot(gray, "pensquare scaled 1cm");

     [Figure 96 not displayed.]


 - Function: void undrawdot ([string PEN = "", [Picture& PICTURE =
          `current_picture']])
 - Function: void undrawdot ([Picture& PICTURE = `current_picture',
          [string PEN = ""]])
     Undraws a dot on PICTURE.  If PPEN is specified, a "pen
     expression" is included in the `undrawdot' command written to
     `out_stream'.  Otherwise, MetaPost's `currentpen' is used.

          Point P(1, 1);
          P.drawdot(gray, "pensquare scaled 1cm");
          P.undrawdot("pencircle scaled .5cm");

     [Figure 97 not displayed.]


 - Function: void draw (const Point& P, [const Color& DDRAW_COLOR =
          `*Colors::default_color', [string DDASHED = "", [string PPEN
          = "", [Picture& PICTURE = `current_picture', [bool AARROW =
          `false']]]]])
 - Function: void draw (Picture& PICTURE = `current_picture', const
          Point& P, [const Color& DDRAW_COLOR =
          `*Colors::default_color', [string DDASHED = "", [string PPEN
          = "", [bool AARROW = `false']]]])
     Draws a line from `*this' to P.  Returns the `Path *this -- p1'.
     *Note Path Reference; Drawing and Filling: Drawing and Filling
     Paths, for more information.

          Point P(-1, -1, -1);
          Point Q(2, 3, 5);
          P.draw(Q, Colors::gray, "", "pensquare scaled .5cm");

     [Figure 98 not displayed.]


 - Function: void undraw (const Point& P, [string DDASHED = "", [string
          PPEN = "", [Picture& PICTURE = `current_picture']]])
 - Function: void undraw (Picture& PICTURE, const Point& P, [string
          DDASHED = "", [string PPEN = ""]])
     Undraws a line from `*this' to P.  Returns the `Path *this -- p1'.
     *Note Path Reference; Drawing and Filling: Drawing and Filling
     Paths, for more information.

          Point P(-1, -1, -1);
          Point Q(2, 3, 5);
          P.draw(Q, Colors::gray, "", "pensquare scaled .5cm");
          P.undraw(Q, "evenly scaled 6", "pencircle scaled .3cm");

     [Figure 99 not displayed.]


 - Function: Path draw_help (const Point& P, [const Color& DDRAW_COLOR
          = *Colors::help_color, [string DDASHED = "", [string PPEN =
          "", [Picture& PICTURE = current_picture]]]])
 - Function: Path draw_help (Picture& PICTURE, const Point& P, [const
          Color& DDRAW_COLOR = *Colors::help_color, [string DDASHED =
          "", [string PPEN = ""]]])
     Draws a "help line" from `*this to P', but only if the `static
     Path' data member `do_help_lines' is `true'.  *Note Path
     Reference; Data Members: Path Data Members.

     "Help lines" are lines that are used when constructing a drawing,
     but that should not be printed in the final version.

 - Function: Path drawarrow (const Point& P, [const Color& DDRAW_COLOR
          = `*Colors::default_color', [string DDASHED = "", [string
          PPEN = "", [Picture& PICTURE = `current_picture']]]])
 - Function: Path drawarrow (Picture& PICTURE, const Point& P, [const
          Color& DDRAW_COLOR = `*Colors::default_color', [string
          DDASHED = "", [string PPEN = ""]]])
     Draws an arrow from `*this' to P and returns the `Path' `*this --
     p'.  The second version is convenient for passing a `Picture'
     argument without having to specify all of the other arguments.

          Point P(-3, -2, 1);
          Point Q(3, 3, 5);
          P.drawarrow(Q);

     [Figure 100 not displayed.]



File: 3DLDF.info,  Node: Labelling Points,  Next: Showing Points,  Prev: Point Drawing Functions,  Up: Point Reference

Labelling
=========

   Labels make it possible to include TeX text within a drawing.
Labels are implemented by means of `class Label'.  The functions
`label()' and `dotlabel()', described in this section, create objects
of type `Label', and add them to the `Picture', which was passed to
them as an argument (`current_picture', by default).  *Note Label
Reference::, for more information.

 - `const' function: void label (const string TEXT_STR, [const string
          POSITION_STR = "top", [const bool DOT = `false', [Picture&
          PICTURE = `current_picture']]])
 - `const' function: void label (const short TEXT_SHORT, [const string
          POSITION_STR = "top", [const bool DOT = `false', [Picture&
          PICTURE = `current_picture']]])
     These functions cause a `Point' to be labelled in the drawing.
     The first argument is the text of the label. It can either be a
     `string', in the first version, or a `short', in the second.  It
     will often be the name of the `Point' in the C++  code, for
     example, `"p0"'.  It is not possible to automate this kind of
     labelling, because it is not possible to access the names of
     variables through the variables themselves in C++ .

     TEXT_STR is always placed between "`btex''' and "`etex'" in the
     MetaPost `label' command written to `out_stream'.  This makes it
     possible to include math mode material in the text of labels, as
     in the following example.

          Point p0(2, 3);
          p0.label("$p_0$");

     [Figure 101 not displayed.]

     If backslashes are needed in the text of the label, then TEXT_STR
     must contain double backslashes, so that single backslashes will
     be written to `out_stream'.

          Point P;
          Point Q(2, 2);
          Point R(P.mediate(Q));
          R.label("$\\overrightarrow{PQ}$", "ulft");

     [Figure 102 not displayed.]

     The POSITION argument indicates where the text of the label should
     be located relative to the `Point'.  The valid values are the
     strings used in MetaPost for this purpose, i.e., `top', `bot',
     `lft', `rt', `llft' (lower left), `lrt' (lower right), `ulft'
     (upper left), and `urt' (upper right).  The default is `top'.
     3DLDF does not catch the error if an invalid `position' argument
     is used; the `string' is written to the output file and an error
     will occur when MetaPost is run.

     The DOT argument is used to determine whether the label should be
     dotted or not.  The default is `false'.  The function `dotlabel()'
     calls `label()', passing `true' as the latter's DOT argument.

 - `const' function: void dotlabel ([const string TEXT_STR, [const
          string POSITION_STR = "top", [Picture& PICTURE =
          `current_picture']]])
 - `const' function: void dotlabel (const short TEXT_SHORT, [const
          string POSITION_STR = "top", [Picture& PICTURE =
          current_picture]])
     These functions are like `label()' except that they always
     produces a dot.

          Point p0(2, 3);
          p0.dotlabel("$p_0$");

     [Figure 103 not displayed.]



File: 3DLDF.info,  Node: Showing Points,  Next: Outputting Points,  Prev: Labelling Points,  Up: Point 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 TEXT followed by the values of a set of coordinates to
     standard output (`stdout').  The other arguments are similar to
     those used in the functions described in *Note Returning
     Coordinates::.

          Point P(1, 3, 5);
          P.rotate(15, 67, 98);
          P.show("P:");
          -| P: (-3.68621, -3.89112, 2.50421)

 - Function: void show_transform ([string TEXT = ""])
     Prints TEXT to standard output (`stdout'), or `"transform:"', if
     TEXT is the empty `string' (the default), and then calls
     `transform.show()'.

          Point A(-1, 1, 1);
          Point B(13, 12, 6);
          Point Q(31, 17.31, 6);
          Q.rotate(A, B, 32);
          Q.show_transform("Q.transform:");
          -| Q.transform:
             Transform:
               0.935   0.212  -0.284       0
             -0.0749   0.902   0.426       0
               0.346  -0.377   0.859       0
              -0.336   0.687  -0.569       1


File: 3DLDF.info,  Node: Outputting Points,  Prev: Showing Points,  Up: Point Reference

Outputting
==========

 - Non-member function: ostream& operator<< (ostream& O, Point& P)
     Used in `Path::output()' for writing the x and y values of the
     `projective_coordinates' of `Points' to `out_stream'.  *Note Path
     Reference; Outputting: Outputting Paths.  This is a low-level
     function that ordinary users should never have to invoke directly.

 - Function: void output (void)
     Writes the MetaPost code for drawing or undrawing a `Point' to
     `out_stream'.  Called by `Picture::output()', when a `Shape' on
     the `Picture' is a `Point'.  *Note Picture Reference; Outputting:
     Outputting Pictures.

 - Virtual function: void suppress_output (void)
     Sets `do_output' to `false', which causes a `Point' not to be
     output.  This function is called in `Picture::output()', when a
     `Point' cannot be projected.  *Note Picture Reference; Outputting:
     Outputting Pictures.

 - Virtual function: virtual void unsuppress_output (void)
     Resets `do_output' to `true', so that a `Point' can potentially be
     output, if `Picture::output()' is called again for the `Picture'
     the `Point' is on.  This function is called in `Picture::output()'.
     *Note Picture Reference; Outputting: Outputting Pictures.

 - Function: `vector<shape*>' extract (const Focus& F, const unsigned
          short PROJ, real FACTOR)
     Attempts to project the `Point' using the arguments passed to
     `Picture::output()', which calls this function.  If `extract()'
     succeeds, it returns a `vector<shape*>' containing only the
     `Point'.  Otherwise, it returns an empty `vector<shape*>'.

 - Virtual function: bool set_extremes (void)
     Sets "extreme" values for x, y, and z in `projective_coordinates'.
     This is, of course, trivial for `Points', because they only have
     one x, y and z-coordinate.  So the maxima and minima for each
     coordinate are always the same.

 - Virtual inline `const' function: `valarray <real>' get_extremes
          (void)
     Returns `projective_extremes'.

 - Virtual `const' function: real get_minimum_z (void)
 - Virtual `const' function: real get_maximum_z (void)
 - Virtual `const' function: real get_mean_z (void)
     These functions return the minimum, maximum, and mean z-value of
     the `Point'.  `get_minimum_z()' returns `projective_extremes[4]',
     `get_maximum_z()' returns `projective_extremes[5]', and
     `get_mean_z()' returns `(projective_extremes[4] +
     projective_extremes[5]) / 2'.  However, since a `Point' has only
     one z-coordinate (from `world_coordinates'), these values will all
     be the same.

     These functions are pure virtual functions in `Shape', and are
     called on `Points' through pointers to `Shape'.  Therefore, they
     must be consistent with the versions for other types derived from
     `Shape'.  *Note Shape Reference; Outputting: Outputting Shapes.


File: 3DLDF.info,  Node: Focus Reference,  Next: Line Reference,  Prev: Point Reference,  Up: Top

Focus Reference
***************

   Class `Focus' is defined in `points.web'.  `Focuses' are used when
creating a perspective projection.  They represent the center of
projection and can be thought of like a camera viewing the scene.

* Menu:

* Focus Data Members::
* Focus Global Variables::
* Focus Constructors and Setting Functions::
* Focus Operators::
* Modifying Focuses::
* Querying Focuses::
* Showing Focuses::


File: 3DLDF.info,  Node: Focus Data Members,  Next: Focus Global Variables,  Prev: Focus Reference,  Up: Focus Reference

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

 - Private variable: Point position
     The location of the `Focus' in the world coordinate system.

 - Private variable: Point direction
     The direction of view from `position' into the scene.

 - Private variable: Point up
     The direction that will be at the top of the projected drawing.

 - Private variable: real distance
     The distance of the `Focus' from the plane of projection.

 - Private variable: real angle
     Used for determining the `up' direction.

 - Private variable: char axis
     The main axis onto which the `Focus' is transformed in order to
     perform the perspective projection, z by default.

     It will normally not matter which axis is used, but it might be
     advantageous to use a particular axis in some special situations.

 - Private variable: Transform transform
     The `Transform', which will be applied to the `Shapes' on the
     `Picture', when the latter is output.  The effect of this is
     equivalent to transforming the `Focus', so that it lies on a major
     axis.

          Focus f(5, 5, -10, 2, 4, 10, 10, 180);
          =>

          `f.transform' ==
           0.989  -0.00733  -0.148  0
           0       0.999    -0.0494 0
           0.148   0.0488    0.988  0
          -3.4    -4.47      0.865  1

 - Private variable: Transform persp
     The `Transform' representing the perspective transformation for a
     particular `Focus'.  Let d stand for `distance', then
          `persp' ==
          1 0 0  0
          0 1 0  0
          0 0 0 1/d
          0 0 0  1


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

Global Variables
================

 - Variable: Focus default_focus
     Effectively, the default `Focus' in `Picture::output()'.  *Note
     Picture Reference; Outputting; Functions: Picture Output Functions.
     It's not really the default, but the version of `output()' that
     doesn't take a `Focus' argument calls another version that does
     take one, passing `default_focus' to the latter as its `Focus'
     argument.

     It's necessary to do this in such a roundabout way, because
     `Picture::output()' must be declared before `class Focus' is
     completely defined and `default_focus' is declared.

     The declaration `Focus& f = default_focus;' makes `f' a reference
     to `default_focus', i.e., it makes `f' another name for
     `default_focus'.  This may be convenient, if you don't feel like
     typing `default_focus'.


File: 3DLDF.info,  Node: Focus Constructors and Setting Functions,  Next: Focus Operators,  Prev: Focus Global Variables,  Up: Focus Reference

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

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

 - Constructor: void Focus (const real POS_X, const real POS_Y, const
          real POS_Z, const real DIR_X, const real DIR_Y, const real
          DIR_Z, const real DIST, [const real ANG = 0, [char AX = 'z']])
     Constructs a `Focus' using the first three `real' arguments as the
     x, y, and z-coordinates of `position', and the fourth through the
     sixth argument as the x, y, and z-coordinates of `direction'.  DIST
     specifies the distance of the `Focus' from the plane of
     projection, ANG the angle of rotation, which affects which
     direction is considered to be "up", and AX the major axis to which
     the `Focus' is aligned.

 - Setting function: void set (const real POS_X, const real POS_Y,
          const real POS_Z, const real DIR_X, const real DIR_Y, const
          real DIR_Z, const real DIST, [const real ANG = 0, [char AX =
          'z']])
     Resets an existing `Focus'.  Corresponds to the constructor above.

 - Constructor: void Focus (const Point& POS, const Point& DIR, const
          real DIST, [const real ANG = 0, [char AX = 'z']])
     Constructs a `Focus' using `Point' arguments for `position' and
     `direction'.  Otherwise, the arguments of this constructor
     correspond to those of the one above.

 - Setting function: void set (const Point& POS, const Point& DIR,
          const real DIST, [const real ANG = 0, [char AX = 'z']])
     Resets an existing `Focus'.  Corresponds to the constructor above.


File: 3DLDF.info,  Node: Focus Operators,  Next: Modifying Focuses,  Prev: Focus Constructors and Setting Functions,  Up: Focus Reference

Operators
=========

 - Assignment operator: const Focus& operator= (const Focus& F)
     Sets the `Focus' to F.


File: 3DLDF.info,  Node: Modifying Focuses,  Next: Querying Focuses,  Prev: Focus Operators,  Up: Focus Reference

Modifying
=========

 - Function: void reset_angle (const real ANG)
     Resets the value of `angle' and recalculates the `Transforms'
     `transform' and `persp'.


File: 3DLDF.info,  Node: Querying Focuses,  Next: Showing Focuses,  Prev: Modifying Focuses,  Up: Focus Reference

Querying
========

 - Inline `const' function: const Point& get_position (void)
     Returns `position'.

 - Inline `const' function: const Point& get_direction (void)
     Returns `direction'.

 - Inline `const' function: const real& get_distance (void)
     Returns `distance'.

 - Inline `const' function: const Point& get_up (void)
     Returns `up'.

 - Inline `const' function: const Transform& get_transform (void)
     Returns `transform'.

 - Inline `const' function: const real& get_transform_element (const
          unsigned int ROW, const unsigned int COLUMN)
     Returns an element of `transform', given two `unsigned ints' for
     the row and the column.

 - Inline `const' function: const Transform& get_persp (void)
     Returns `persp'.

 - Inline `const' function: const real& get_persp_element (const
          unsigned int ROW, const unsigned int COLUMN)
     Returns an element of `persp', given two `unsigned ints' for the
     row and the column.


File: 3DLDF.info,  Node: Showing Focuses,  Prev: Querying Focuses,  Up: Focus Reference

Showing
=======

 - `const' function: void show ([const string text_str = "Focus:",
          [const bool show_transforms = false]])
     Prints TEXT_STR to standard output (`stdout'), then calls
     `Point::show()' on `position', `direction', and `up'.  Then the
     values of `distance', `axis', and `angle' are printed to `stdout'.
     If SHOW_TRANSFORMS is `true', `transform' and `persp' are shown
     as well.


File: 3DLDF.info,  Node: Line Reference,  Next: Plane Reference,  Prev: Focus Reference,  Up: Top

Line Reference
**************

   The `struct Line' is defined in `lines.web'.  `Lines' are not
`Shapes'.  They are used for performing vector operations.  A `Line' is
defined by a `Point' representing a position vector and a `Point'
representing a direction vector.

   See also the descriptions of `Point::get_line()' in *Note Points and
Lines::, and `Path::get_line()' in *Note Path Reference; Querying:
Querying Paths.

* Menu:

* Line Data Members::
* Line Global Constants::
* Line Constructors::
* Line Operators::
* Get Path::
* Showing::


File: 3DLDF.info,  Node: Line Data Members,  Next: Line Global Constants,  Prev: Line Reference,  Up: Line Reference

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

 - Public variable: Point position
     Represents the position vector of the `Line'.

 - Public variable: Point direction
     Represents the direction vector of the `Line'.


File: 3DLDF.info,  Node: Line Global Constants,  Next: Line Constructors,  Prev: Line Data Members,  Up: Line Reference

Global Constants
================

 - Constant: const Line INVALID_LINE
     `position' and `direction' are both `INVALID_POINT'.


File: 3DLDF.info,  Node: Line Constructors,  Next: Line Operators,  Prev: Line Global Constants,  Up: Line Reference

Constructors
============

 - Default constructor: void Line (const Point& POS = `origin', const
          Point& DIR = `origin')
     Creates a `Line', setting `position' to POS, and `direction' to
     DIR.  If this function is called with no arguments, it creates a
     `Line' at the `origin' with no direction.

          Point p(2, 1, 2);
          Point d(-3, 3, 3.5);
          Line L0(p, d);
          Line L1 = p.get_line(d);

     [Figure 104 not displayed.]


 - Copy constructor: void Line (const Line& L)
     Creates a `Line', making it a copy of L.


File: 3DLDF.info,  Node: Line Operators,  Next: Get Path,  Prev: Line Constructors,  Up: Line Reference

Operators
=========

 - Assignment operator: void operator= (const Line& L)
     Sets `*this' to L.


File: 3DLDF.info,  Node: Get Path,  Next: Showing,  Prev: Line Operators,  Up: Line Reference

Get Path
========

 - `const' function: Path get_path (void)
     Returns a linear `Path' with two `Points' on the `Line'.  The
     first `Point' will be `position', and the second will be `position
     + direction'.


File: 3DLDF.info,  Node: Showing,  Prev: Get Path,  Up: Line Reference

Showing
=======

 - Function: void show ([string TEXT = ""])
     If TEXT is not the empty `string' (the default), it is printed on
     a line of its own to standard output.  Otherwise, `Line:' is
     printed.  Following this, `Point::show()' is called on `position'
     and `direction'.

          Point p(1, -2, 3);
          Point d(-12.3, 21, 36.002);
          Line L0(p, d);
          L0.show("L0:");
          -| L0:
             position: (1, -2, 3)
             direction: (-12.3, 21, 36.002)
          Line L1 = p.get_line(d);
          L1.show("L1:");
          -| L1:
             position: (1, -2, 3)
             direction: (-13.3, 23, 33.002)
          Path q = L1.get_path();
          q.show("q:");
          -| q:
             fill_draw_value == 0
             (1, -2, 3) -- (-12.3, 21, 36.002);


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

Plane Reference
***************

   The `struct Plane'  is defined in `planes.web'.  `Planes' are not
`Shapes'.  They are used for performing vector operations.  A `Plane'
is defined by a `Point' representing a point on the plane, a `Point'
representing the normal to the plane, and the distance of the plane from
the origin.

   The most common use of `Planes' is to represent the plane in which
an existing plane figure lies.  Therefore, they most likely to be
created by using `Path::get_plane()'.  *Note Path Reference; Querying:
Querying Paths.  However, `class Plane' does have constructors for
creating `Planes' directly, if desired.  *Note Planes Reference;
Constructors: Planes Constructors.

* Menu:

* Planes Data Members::
* Planes Global Constants::
* Planes Constructors::
* Planes Operators::
* Planes Returning Information::
* Plane Intersections::
* Planes Showing::


File: 3DLDF.info,  Node: Planes Data Members,  Next: Planes Global Constants,  Prev: Plane Reference,  Up: Plane Reference

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

   Because the main purpose of `Plane' is to provide information about
`Shapes', its data members are all `public'.

 - Public variable: Point point
     Represents a point on the plane.

 - Public variable: Point normal
     Represents the normal to the plane.

 - Public variable: real distance
     The distance of the plane from the origin.


File: 3DLDF.info,  Node: Planes Global Constants,  Next: Planes Constructors,  Prev: Planes Data Members,  Up: Plane Reference

Global Constants
================

 - Constant: const Plane INVALID_PLANE
     A `Plane' with `point' == `normal', and `distance' ==
     `INVALID_REAL'.

     `INVALID_PLANE' is returned from `Path::get_plane()', if the
     `Path' is not planar.  *Note Path Reference; Querying: Querying
     Paths.


File: 3DLDF.info,  Node: Planes Constructors,  Next: Planes Operators,  Prev: Planes Global Constants,  Up: Plane Reference

Constructors
============

 - Default constructor: void Plane (void)
     Creates a degenerate `Plane' with `point' == `normal' == `origin',
     and `distance' == 0.

     `Planes' constructed using this constructor will probably be set
     using the assignment operator or `Path::get_plane()' immediately,
     or very soon after being declared.  *Note Planes Reference;
     Operators: Planes Operators, and *Note Paths Reference; Querying:
     Querying Paths.

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

 - Constructor: void Plane (const Point& P, const Point& N)
     If P is not equal to N, this constructor creates a `Plane' and
     sets `point' to P.  `normal' is set to N, and made a unit vector.
     `distance' is calculated according to the following formula: Let n
     stand for `normal', p for `point', and d for `distance': d = -p
     \dot n.  If d = 0, `origin' lies in the `Plane'.  If d > 0,
     `origin' lies on the side of the `Plane' that `normal' points to,
     considered to be "outside".  If d<0, `origin' lies on the side of
     the `Plane' that `normal' does not point to, considered to be
     "inside".

     However, if P == N, `point' and `normal' are both set to
     `INVALID_POINT', and `distance' is set to `INVALID_REAL', i.e.,
     `*this' will be equal to `INVALID_PLANE' (*note Planes Reference;
     Global Constants: Planes Global Constants.).

          Point P(1, 1, 1);
          Point N(0, 1);
          N.rotate(-35, 30, 20);
          N.show("N:");
          -| N: (-0.549659, 0.671664, 0.496732)
          Plane q(P, N);
          cout << q.distance;
          -| -0.618736

     [Figure 105 not displayed.]



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

Operators
=========

 - Assignment operator: const Plane& operator= (const Plane& P)
     Sets `point' to P.`point', `normal' to P.`normal', and `distance'
     to P.`distance'.  The return value is P, so that invocations of
     this function can be chained.

          Point pt(2, 2.3, 6);
          Point norm(-1, 12, -36);
          Plane A(pt, norm);
          Plane B;
          Plane C;
          B = C = A;
          A.show("A:");
          -| A:
             normal: (-0.0263432, 0.316118, -0.948354)
             point: (2, 2.3, 6)
             distance == 5.01574
          cout << (A == B && A == C && B == C);
          -| 1

 - `const' operator: bool operator== (const Plane& P)
     Equality operator.  Compares `*this' and P, and returns `true', if
     `point' == P.`point', `normal' == P.`normal', and `distance' ==
     P.`distance', otherwise `false'.

 - `const' operator: bool operator!= (const Plane& P)
     Inequality operator.  Compares `*this' and P and returns `true',
     if `point' !=   P.`point', or `normal' !=   P.`normal', or
     `distance' !=   P.`distance'.  Otherwise, it returns `false'.

