Package org.bzdev.p3d

Class Model3D

java.lang.Object
org.bzdev.p3d.Model3D
All Implemented Interfaces:
Shape3D, Model3DOps<Model3D.Triangle>

public class Model3D extends Object implements Shape3D, Model3DOps<Model3D.Triangle>
Three-dimensional model class. This class represents a 3D model of an object as a set of triangles. It can produce an STL file, which is commonly supported by 3D printers.

As an example of its use, the statements


 Model3D m3d = new Model3D();
 m3d.setStackTraceMode(true);
 m3d.addTriangle(...);
 ...
 m3d.addTriangle(...);
 if (m3d.notPrintable(System.out)) System.exit(1);
 m3d.writeSTL("model test", "model.stl");
 System.exit(0);
 
will create a model, test it to verify that it is printable on a 3D printer, and if it is printable, create an STL file. The call to setStackTraceMode will configure the model so that each triangle the model creates with an explicitly specified tag is tagged with a stack trace created when the triangle was created. Please see setStackTraceMode(boolean) for the procedure for setting this permission when the scrunner command is used to run a script.

The triangles in a model are expected to follow the same rules used by STL files: the right-hand rule determines the triangle's orientation and an edge of a triangle must intersect another triangle at a vertex. While one can create triangles explicitly, one can also add the objects in another instance of Model3D.

The simplest way to create an image showing the model is to use the method createImageSequence(OutputStream,String,int,int):


  Model3D m3d = new Model3D();
  ...
  m3d.addTriangle(...);
  ...
  m3d.createImageSequence(new FileOutputStream("model.isq"), "png", 8, 4);
 

The file model.isq is a ZIP file with a manifest describing various image parameters, and a with a sequence of image files showing the model in various orientations.

The following code creates an image, using the* low-level API:


 int WIDTH = 800;
 int HEIGHT = 800;
 ...
 Model3D m3d = new Model3D();
 ...
 m3d.addTriangle(...);
 ...
 Model3D.Image image =
    new Model3D.Image(WIDTH, HEIGHT, BufferedImage.TYPE_INT_ARGB_PRE);
 image.setCoordRotation(...);
 image.setBacksideColor(Color.RED);
 image.setEdgeColor(Color.GREEN);
 Graphics2D g2d = image.createGraphics();
 g2d.setColor(Color.BLUE);
 g2d.fillRect(0, 0, WIDTH, HEIGHT);
 g2d.dispose();
 m3d.setImageParameters(image);
 m3d.render(image);
 image.write("png", "modeltest.png");
 

To create an animation showing the model from different orientations use the following code:


 Model3D m3d = new Model3D();
 ...
 m3d.addTriangle(...);
 ...
 Animation2D a2d = new Animation2D(...);
 a2d.setBackgroundColor(Color.BLUE.dargker().darker());
 Model3DViewFactory = new Model3DViewFactory(a2d);
 factory.setModel(m3d);
 // configure factory
 ...
 factory.createObject(view);
 // clear directory tmp
 ...
 int maxframes = a2d.estimateFrameCount(ANIMATION_LENGTH);
 a2d.initFrames(maxFrames, "tmp/img-", "png")
 a2d.scheduleFrames(0, maxframes);
 a2d.run();
 
The documentation for Model3DViewFactory describes how to configure this factory.

When a triangle is created, the coordinates of each vertex are rounded to the nearest single-precision floating-point number, but stored as a double-precision floating-point number. In addition, any value that differs from 0 by less than one part in 1010 will be treated as 0.0. This is done for two reasons:

  1. to prevent round-off errors from turning what should be a common vertex for multiple triangles into multiple vertices.
  2. So that area and volume computations will use the coordinates of vertices as those would be stored in an STL file.
Although an STL file can contain a normal vector for a triangle, the models create the normal vector from the vertices directly: the computed vector is more accurate.

Two types of transformations can be applied when a model is being created:

  • One may call pushParms(), followed by setObjectTranslation, setObjectTranslation, and setObjectRotation in order to change the position and orientation the triangles that will be created. This is intended for the case where an object needs to have a particular orientation to be printed or when multiple copies of the object are needed.
  • One may call pushTransform(Transform3D) to modify an object. The transform can be an arbitrary one. For example, one could create a set of triangles that represents a disk, increase its height with increasing radius, and then stretch that object in the Y direction in order to create an elliptical bowl.
Calls to popParms() and popTransform() will remove the transforms that were created, leaving the ones previously in place.

Because Model3D was designed for 3D printing, coordinate values are rounded to single-precision floating point numbers and very small values (those with absolute values less than the value produced by the Java expression Math.ulp(1.0F)) are rounded to 0.0. This rounding is not performed by Surface3D and its subclasses.

Model3D provides several methods to aid in debugging. In particular,

  • Constructor Details

    • Model3D

      public Model3D()
      Constructor.
    • Model3D

      public Model3D(boolean strict)
      Constructor specifying strict mode. Strict mode (the default) requires that tests for printability require that all surfaces in a model are closed two-dimensional manifolds. When strict mode is not active, an even number of triangles can share a common edge, provided the orientations of the triangles alternate during a rotation about the common edge, switching between a clockwise and counterclockwise direction. An example is two "towers" with a triangular cross section that meet at a common edge and that share a common base:
                *-----*
                 \   /
                  \ /
                   *
                  / \
                 /   \
                *-----*
       
      If the common vertices were split into pairs, and offset by a small distance δ, the surface becomes a closed two-dimensional manifold. When δ = 0, the surface is not a closed two-dimensional manifold, but is still printable.
      Parameters:
      strict - true if strict mode is used; false otherwise
      See Also:
  • Method Details

    • xbracket

      public double[] xbracket(double x)
      Find the values allowed for tessellation that bracket a given value for an X coordinate. If setULPFactor(double) was not called or was called with a value of 0.0, the value returned will contain the constants -&infty; and &infty; (Double.NEGATIVE_INFINITY and Double.POSITIVE_INFINITY respectively) and will contain one of these if the value of x is above or below the values previously provided when segments were added to the model.

      This method is provided for debugging.

      Parameters:
      x - the value of an X coordinate
      Returns:
      an array consisting of the X coordinate below or equal to x and the X coordinate above or equal to x.
    • ybracket

      public double[] ybracket(double y)
      Find the values allowed for tessellation that bracket a given value for a Y coordinate. If setULPFactor(double) was not called or was called with a value of 0.0, the value returned will contain the constants -&infty; and &infty; (Double.NEGATIVE_INFINITY and Double.POSITIVE_INFINITY respectively) and will contain one of these if the value of y is above or below the values previously provided when segments were added to the model.

      This method is provided for debugging.

      Parameters:
      y - the value of a Y coordinate
      Returns:
      an array consisting of the Y coordinate below or equal to x and the Y coordinate above or equal to x.
    • zbracket

      public double[] zbracket(double z)
      Find the values allowed for tessellation that bracket a given value for a Z coordinate. If setULPFactor(double) was not called or was called with a value of 0.0, the value returned will contain the constants -&infty; and &infty; (Double.NEGATIVE_INFINITY and Double.POSITIVE_INFINITY respectively) and will contain one of these if the value of z is above or below the values previously provided when segments were added to the model.

      This method is provided for debugging.

      Parameters:
      z - the value of a Z coordinate
      Returns:
      an array consisting of the Z coordinate below or equal to x and the Z coordinate above or equal to x.
    • findMinULPRatio

      public double findMinULPRatio()
      Find the minimum ratio of the separation between adjacent coordinate values to the ULP value for those coordinates, treated as single-precision values. The coordinates are obtained from tables maintained when setULPFactor(double) was called with a positive argument (such an argument's value must be at least 2.0). The value returned can be used as guide for adjusting the value returned by setULPFactor(double) by providing an estimate of the closest distance between vertices before tessellation. Values much larger than 1 are an indication that tessellation in not likely to be affected by roundoff errors (assuming setULPFactor(double) has been called with a non-zero argument).
      Returns:
      the minimum ratio of the separation between adjacent coordinate values to the ULP value for those coordinates, treated as single-precision values
    • setStackTraceMode

      public void setStackTraceMode(boolean mode)
      Set stack-trace mode. When stack-trace mode is on (true), triangles without an explicit tag are tagged with a stack trace taken at the point when the triangle was created. The default value is false.
      Parameters:
      mode - true to turn on stack-trace mode; false to turn it off
    • getStackTraceMode

      public boolean getStackTraceMode()
      Get the current stack-trace mode.
      Returns:
      the stack-trace mode
    • setTessellationLevel

      public void setTessellationLevel(int level)
      Set the tessellation level of this model. A value of 0 indicates no tessellation. Adding 1 to the level quadruples the number of triangles and patches.

      It is possible to make the value of level too high for particular models as double-precision values are converted to floats (the STL format uses floats). Some corner cases involving small floating-point errors can be handled by using the method setULPFactor(double) to coalesce nearby floating-point values.

      The initial tessellation level is 0. Checking if a model is printable, well-formed, etc., can take significantly longer if the level is set to values larger than 0. In cases where the time is excessive, one may want to check the model before calling this method. Similar considerations apply to generating images of a model using methods provided by this class. An alternative for high resolution images is to create an STL or X3D file and then use applications that make use of a computer's GPU to improve the performance.

      Parameters:
      level - the tessellation level
    • getTessellationLevel

      public int getTessellationLevel()
      Get the current tessellation level.
      Returns:
      the current tessellation level
    • pushParms

      public void pushParms()
      Push object-transformation parameters. These parameters are used to change the position or orientation of an object without modifying the code used to generate the object. The parameters set by the methods setObjectTranslation, setObjectTranslation, and setObjectRotation can be pushed onto a stack and later restored. The transformations are applied in order, with the most recently defined transformation applied first. This ordering supports the following use case:
      • A method m1() calls pushParms() adds an object to the model, and then sets the object translation and rotation multiple times to add additional objects to the model so that they are placed at specific locations relative to each other, creating a composite object.
      • A method m2() also calls PushParms() and sets the object rotation and translation to place a series of objects at specific locations relative to each other. These objects are copies of the composite object obtained by calling m1().
      Note that the relative positions of the objects created by a call to m1() is independent of whether m1() is called directly or if it is called by m2(). If the transformations were applied in the opposite order, this would in general not be the case.

      Object-transformations parameters are typically used when it is desirable to include multiple independent objects in a model and position them in a way that will take advantage of the pricing rules used by various 3D printing services.

      If pushTransform(Transform3D) is also used, the tranforms provided by that method are applied before any of the transforms set using setObjectTranslation, setObjectTranslation, and setObjectRotation

      See Also:
    • popParms

      public void popParms()
      Pop object-transformation parameters. This undoes the effect of the method pushParms().
      See Also:
    • setObjectTranslation

      public void setObjectTranslation(double x2, double y2, double z2)
      Specify how to Translate new objects after rotating them about (0,0,0). After the rotation, the point at the origin will be moved to point (x2, y2, z2). THis method is equivalent to calling setObjectTranslation(0.0, 0.0, 0.0,x2, y2, z2).

      There is a stack of transformations that includes rotations and translations. The transformations are applied in order, with the most recently defined transformation applied first. Pushing this stack saves the current translations and rotations.

      There is also a list of transforms set by calling pushTransform(Transform3D). Transforms on this list are applied before the object translations and rotations.

      Parameters:
      x2 - the x coordinate for the translation
      y2 - the y coordinate for the translation
      z2 - the z coordinate for the translation
      See Also:
    • setObjectTranslation

      public void setObjectTranslation(double x1, double y1, double z1, double x2, double y2, double z2)
      Specify how to Translate an object after rotating it about a point. after a rotation about the point (x1, y1, z1), the objects will be translated so that (x1, y1, z1) moves to (x2, y2, z2). There is a stack of transformations that includes rotations and translations. The transformations are applied in order, with the most recently defined transformation applied first. Pushing this stack saves the current translations and rotations.

      There is also a list of transforms set by calling pushTransform(Transform3D). Transforms on this list are applied before the object translations and rotations.

      Parameters:
      x1 - the initial x coordinate
      y1 - the initial y coordinate
      z1 - the initial z coordinate
      x2 - the final x coordinate
      y2 - the final y coordinate
      z2 - the final z coordinate
      See Also:
    • setObjectRotation

      public void setObjectRotation(double phi, double theta, double psi)
      Rotate new objects.

      The rotation is specified by Eulerian angles. The Eulerian angles follow the convention used in Goldstein, "Classical Mechanics" but the objects are rotated instead of the coordinates. The angle phi specifies an initial rotation of objects counterclockwise about the z-axis of an origin at (x1, y1, z1) set in the last call to setObjectTranslation(x1, y1, z1, x2, y2, z2), with a default of (0,0,0) for (x1,y1,z1) and (x2,y2,z2). The angle theta specifies a second rotation about an x axis through (x1, y1, z1), again counter clockwise. The angle psi specifies a final counterclockwise rotation about the z axis. The object is then translated so that the point at (x1, y1, z1) will be at (x2, y2, z2)

      In effect, the angles have the opposite signs from the corresponding angles used by setCoordRotation.

      There is a stack of transformations that includes rotations and translations. The transformations are applied in order, with the most recently defined transformation applied first. Pushing this stack saves the current translations and rotations.

      There is also a list of transforms set by calling pushTransform(Transform3D). Transforms on this list are applied before the object translations and rotations.

      Parameters:
      phi - the Eulerian angle phi in radians
      theta - the Eulerian angle theta in radians
      psi - the Eulerian angle psi in radians
    • getBoundingBoxX

      public double getBoundingBoxX()
      Get the length parallel to the x axis for the bounding box of containing all objects.
      Returns:
      the length of the bounding box in the x direction
    • getBoundingBoxY

      public double getBoundingBoxY()
      Get the length parallel to the y axis for the bounding box of containing all objects.
      Returns:
      the length of the bounding box in the y direction
    • getBoundingBoxZ

      public double getBoundingBoxZ()
      Get the length parallel to the z axis for the bounding box of containing all objects.
      Returns:
      the length of the bounding box in the z direction
    • getMinX

      public double getMinX()
      Get the minimum x coordinate for all objects contained in a 3D model.
      Returns:
      the minimum value of the x coordinate; Double.POSITIVE_INFINITY if the model is empty
    • getMaxX

      public double getMaxX()
      Get the minimum y coordinate for all objects contained in a 3D model.
      Returns:
      the minimum value of the y coordinate; Double.NEGATIVE_INFINITY if the model is empty
    • getMinY

      public double getMinY()
      Get the minimum z coordinate for all objects contained in a 3D model.
      Returns:
      the minimum value of the z coordinate; Double.POSITIVE_INFINITY if the model is empty.
    • getMaxY

      public double getMaxY()
      Get the maximum x coordinate for all objects contained in a 3D model.
      Returns:
      the maximum value of the x coordinate; Double.NEGATIVE_INFINITY if the model is empty.
    • getMinZ

      public double getMinZ()
      Get the maximum y coordinate for all objects contained in a 3D model.
      Returns:
      the maximum value of the y coordinate; Double.POSITIVE_INFINITY if the model is empty.
    • getMaxZ

      public double getMaxZ()
      Get the maximum z coordinate for all objects contained in a 3D model.
      Returns:
      the maximum value of the z coordinate; Double.NEGATIVE_INFINITY if the model is empty.
    • getBounds

      public Rectangle3D getBounds()
      Description copied from interface: Shape3D
      Get a bounding rectangular cuboid for a 3D shape. The edges will be aligned with the X, Y and Z axes. The cuboid created may not be the smallest one possible (for example, shapes defined by Bézier surfaces may just use the control points to determine the cuboid as the convex hull for the control points includes all of the surface for parameters in the normal range [0,1]).
      Specified by:
      getBounds in interface Shape3D
      Returns:
      a bounding rectangular cuboid for this Shape3D; null if the shape does not contain any points
    • getSurfaceIterator

      public SurfaceIterator getSurfaceIterator(Transform3D tform)
      Description copied from interface: Shape3D
      Get a surface iterator for this Shape3D. The surface iterator will represent the shape as a sequence of Bézier patches, Bézier triangles, and/or planar triangles with the order of the sequence arbitrary.

      Unless the transform is an affine transform, the transformation is not exact. In this case, the patches and triangles that constitute the surface should be small enough that the transform can be approximated by an affine transform over the region containing the control points.

      Specified by:
      getSurfaceIterator in interface Shape3D
      Parameters:
      tform - a transform to apply to each control point; null for the identity transform
      Returns:
      a surface iterator
    • isOriented

      public boolean isOriented()
      Description copied from interface: Shape3D
      Determine if a surface is oriented.
      Specified by:
      isOriented in interface Shape3D
      Returns:
      true if the surface has an orientation; false if it does not
    • getBoundary

      public Path3D getBoundary()
      Description copied from interface: Shape3D
      Get the boundary for this Shape3D. For a closed surface, the boundary will be an empty path.

      Typically, a boundary will consist of a series of distinct closed subpaths. Subpaths are separated by segments whose type is {link PathIterator3D#SEG_MOVETO}. For a closed manifold, the boundary will be an empty path.

      Specified by:
      getBoundary in interface Shape3D
      Returns:
      the boundary of this surface; null if a boundary cannot be computed
      See Also:
    • isClosedManifold

      public boolean isClosedManifold()
      Description copied from interface: Shape3D
      Determine if this Shape3D is a closed two-dimensional manifold.
      Specified by:
      isClosedManifold in interface Shape3D
      Returns:
      true if the surface is a closed two-dimensional manifold; false otherwise
    • triangles

      public CollectionScanner<Model3D.Triangle> triangles()
      Get a scanner that can iterate over the planar triangles provided by this model.
      Returns:
      a CollectionScanner that can be used to iterate over the triangles associated with this model
    • trianglesAndPatches

      public CollectionScanner<Model3D.Triangle> trianglesAndPatches()
      Get a collection scanner that can iterate over planar triangles, Bézier triangles, and Bézier patches.
      Returns:
      an iterator
    • setULPFactor

      public void setULPFactor(double ulpFactor)
      Set the ULP factor for this model. When the argument provided to this method is nonzero, Model3D will attempt to coallesce nearby values to prevent inconsistencies due to floating point errors. A value x is considered close to a previously provided value if within one a multiple, equal to the argument of this method, of the single-precision ULP (Unit of Least Precision) value for x. When within this range, the value x will be replaced with a previously provided value.

      Unless the value is 0, it must be positive and no less than 2.0. The default value is 0.0.

      Parameters:
      ulpFactor - a multiple used to scale the floating-point ULP value; 0.0 to disable its use
      Throws:
      IllegalArgumentException - the argument is out of range
      IllegalStateException - this method was called after objects were added to this model
    • tessellate

      Get an iterator that will return a sequence of triangles after tessellation using the preset tessellation level
      Returns:
      an iterator

      If this method throws a Model3D.TessellationException, methods for that exception can be used to determine the source of the error.

      Throws:
      IllegalArgumentException - the tessellation level was negative
      Model3D.TessellationException - if tessellation failed
      See Also:
    • checkTessellation

      public boolean checkTessellation(PrintStream out, boolean verbose)
      Check tessellation using the default tessellation level. The default tessellation level can be set by calling setTessellationLevel(int) and is initially 0. If there is a tessellation error, the output will include the type of a surface segment and the corresponding control points listed one per line. For If an entry is shown, only the control points for a vertex or corner of the subdivided patch or triangle are shown. The order is the same as described above but without intermediate control ponts.
      Parameters:
      out - the output stream for error messages boolean verbose true if control points are to be printed with high precision; false for the default precision
      Returns:
      true on success; false on failure
    • tessellate

      Get an iterator that will return a sequence of triangles after tessellation.

      If this method throws a Model3D.TessellationException, methods for that exception can be used to determine the source of the error.

      Parameters:
      level - the tessellation level
      Returns:
      an iterator
      Throws:
      IllegalArgumentException - the tessellation level was negative
      Model3D.TessellationException - if tessellation failed
    • checkTessellation

      public boolean checkTessellation(PrintStream out, boolean verbose, int level)
      Check tessellation. If there is a tessellation error, the output will include the type of a surface segment and the corresponding control points listed one per line. For If an entry is shown, only the control points for a vertex or corner of the subdivided patch or triangle are shown. The order is the same as described above but without intermediate control ponts.
      Parameters:
      out - the output stream for error messages boolean verbose true if control points are to be printed with high precision; false for the default precision
      level - the tesselation level to check.
      Returns:
      true on success; false on failure
    • size

      public int size()
      Return the number of triangles and cubic patches in a model. The value returned is the value before any tessellation.
      Returns:
      the number of triangles and cubic patches in this model.
    • append

      public final void append(SurfaceIterator si, Object tag) throws IllegalArgumentException
      Append the surface segments specified by a surface iterator.
      Parameters:
      si - the surface iterator
      tag - a tag to label the segments added by this method
      Throws:
      IllegalArgumentException - the surface iterator returned segments from a non-oriented 3D shape
    • append

      public final void append(Shape3D surface) throws IllegalArgumentException
      Append the surface segments specified by another surface.
      Parameters:
      surface - the other surface
      Throws:
      IllegalArgumentException - the surface was not an oriented surface
    • append

      public final void append(Shape3D surface, Transform3D transform) throws IllegalArgumentException
      Append the surface segments specified by another surface after applying a transformation.
      Parameters:
      surface - the other surface
      transform - the transform to apply to a surface's control points
      Throws:
      IllegalArgumentException - the surface was not an oriented surface
    • addModel

      public void addModel(Model3DOps<?> m3d)
      Add a generalized model.

      This class implements an interface named Model3DOps that provides the operations needed to add components to a model and to implement the Shape3D interface. This method is provided so that other implementations of the Model3DOps interface can be used to create models that will be imported into the current model.

      Specified by:
      addModel in interface Model3DOps<Model3D.Triangle>
      Parameters:
      m3d - the model.
      Throws:
      IllegalArgumentException - if a model is being added to itself
    • addModel

      public void addModel(Model3DOps<?> m3d, Object tag)
      Add a generalized model, including a tag.

      This class implements an interface named Model3DOps that provides the operations needed to add components to a model and to implement the Shape3D interface. This method is provided so that other implementations of the Model3DOps interface can be used to create models that will be imported into the current model.

      Specified by:
      addModel in interface Model3DOps<Model3D.Triangle>
      Parameters:
      m3d - the model
      tag - a tag to name this call to addModel
      Throws:
      IllegalArgumentException - if a model is being added to itself
    • addModel

      public void addModel(Model3D m3d)
      Add the objects in another Model3D to this model.
      Parameters:
      m3d - a model containing objects to add
    • addModel

      public void addModel(Model3D m3d, Object tag)
      Add the objects in another Model3D to this model and tag them.
      Parameters:
      m3d - a model containing objects to add
      tag - a tag to label the objects added
      Throws:
      IllegalArgumentException - if a model is being added to itself
    • addModel

      public void addModel(Model3D m3d, boolean tessellate) throws Model3D.TessellationException
      Add a possibly tessellated 3D model to this model. When the second argument is true, only triangles are added and these are computed using argument model's tessellation level. When the second argument is false, this method is equivalent to addModel(Model3D).

      Models with multiple components may require different levels of tessellation for each. For example, some 3D printing services charge a fee per part, but count interlocking parts as a single part. Components used to tie parts together to reduce the per-part fee will be discarded after printing, and do not need as high a level of tessellation as other parts.

      If this method throws a Model3D.TessellationException, methods for that exception can be used to determine the source of the error.

      Note: if an isolated component consists of planar triangles, including ones created by using classes such as SteppedGrid, the method tessellate() will not subdivide those triangles regardless of the tessellation level.

      Parameters:
      m3d - the model to add
      tessellate - true of the model being added should be tessellated; false otherwise
      Throws:
      Model3D.TessellationException - if tessellation failed
    • pushTransform

      public void pushTransform(Transform3D transform)
      Add a transform that will be applied to a triangle when it is added to the model. The transform is applied to the triangle's vertices. The edges will still be straight. For cubic patches, triangles, and vertices, the transform is applied to each control point.

      This method can be used to create a variety of objects from existing models by distorting them. The transforms are applied in the order in which they were added. This is the opposite of the order used by pushParms(). The transforms are general transforms.

      Transforms set using pushTransform(Transform3D) are applied before the transforms set using setObjectTranslation, setObjectTranslation, setObjectRotation(double,double,double) or pushParms().

      Parameters:
      transform - the transform to apply.
      Throws:
      IllegalArgumentException - the argument was null
      See Also:
    • popTransform

      public void popTransform()
      Remove the last transform that was added.
      Throws:
      IllegalStateException - the transform stack was empty
    • addTriangle

      public Model3D.Triangle addTriangle(Model3DOps.Triangle triangle)
      Add a triangle to the model. The triangle that is stored may differ from the triangle passed as this method's argument: while the type may be different, some classes that implement Model3DOps can apply transformations and will need to create a different triangle as a result.

      Transforms that cause a modified triangle to be stored can be configured using pushTransform(Transform3D) and popTransform().

      Specified by:
      addTriangle in interface Model3DOps<Model3D.Triangle>
      Parameters:
      triangle - the triangle to add
      Returns:
      the triangle stored by this model
      See Also:
    • addTriangle

      public Model3D.Triangle addTriangle(double x1, double y1, double z1, double x2, double y2, double z2, double x3, double y3, double z3) throws IllegalArgumentException
      Description copied from interface: Model3DOps
      Add a triangle to the model, specifying the triangle by its vertices. The orientation of the triangle is determined by the right-hand rule when going from vertex 1 to vertex 2 to vertex 3.
      Specified by:
      addTriangle in interface Model3DOps<Model3D.Triangle>
      Parameters:
      x1 - the x coordinate of vertex 1
      y1 - the y coordinate of vertex 1
      z1 - the z coordinate of vertex 1
      x2 - the x coordinate of vertex 2
      y2 - the y coordinate of vertex 2
      z2 - the z coordinate of vertex 2
      x3 - the x coordinate of vertex 3
      y3 - the y coordinate of vertex 3
      z3 - the z coordinate of vertex 3
      Returns:
      the triangle stored by this model
      Throws:
      IllegalArgumentException - one of the first 9 arguments had the value Double.NaN
    • addFlippedTriangle

      public Model3D.Triangle addFlippedTriangle(double x1, double y1, double z1, double x2, double y2, double z2, double x3, double y3, double z3) throws IllegalArgumentException
      Description copied from interface: Model3DOps
      Add a flipped triangle to the model, specifying the triangle by its vertices. The orientation of the triangle is the opposite to what the right-hand rule when going from vertex 1 to vertex 2 to vertex 3 would suggest.
      Specified by:
      addFlippedTriangle in interface Model3DOps<Model3D.Triangle>
      Parameters:
      x1 - the x coordinate of vertex 1
      y1 - the y coordinate of vertex 1
      z1 - the z coordinate of vertex 1
      x2 - the x coordinate of vertex 2
      y2 - the y coordinate of vertex 2
      z2 - the z coordinate of vertex 2
      x3 - the x coordinate of vertex 3
      y3 - the y coordinate of vertex 3
      z3 - the z coordinate of vertex 3
      Returns:
      the triangle stored by this model
      Throws:
      IllegalArgumentException - one of the first 9 arguments had the value Double.NaN
    • addTriangle

      public Model3D.Triangle addTriangle(double x1, double y1, double z1, double x2, double y2, double z2, double x3, double y3, double z3, Color color) throws IllegalArgumentException
      Description copied from interface: Model3DOps
      Add a triangle to the model, specifying the triangle by its vertices and its color. The orientation of the triangle is determined by the right-hand rule when going from vertex 1 to vertex 2 to vertex 3.
      Specified by:
      addTriangle in interface Model3DOps<Model3D.Triangle>
      Parameters:
      x1 - the x coordinate of vertex 1
      y1 - the y coordinate of vertex 1
      z1 - the z coordinate of vertex 1
      x2 - the x coordinate of vertex 2
      y2 - the y coordinate of vertex 2
      z2 - the z coordinate of vertex 2
      x3 - the x coordinate of vertex 3
      y3 - the y coordinate of vertex 3
      z3 - the z coordinate of vertex 3
      color - the color of the triangle; null if none is specified
      Returns:
      the triangle stored by this model
      Throws:
      IllegalArgumentException - one of the first 9 arguments had the value Double.NaN
    • addFlippedTriangle

      public Model3D.Triangle addFlippedTriangle(double x1, double y1, double z1, double x2, double y2, double z2, double x3, double y3, double z3, Color color) throws IllegalArgumentException
      Description copied from interface: Model3DOps
      Add a flipped triangle to the model, specifying the triangle by its vertices and color. The orientation of the triangle is the opposite to what the right-hand rule when going from vertex 1 to vertex 2 to vertex 3 would suggest.
      Specified by:
      addFlippedTriangle in interface Model3DOps<Model3D.Triangle>
      Parameters:
      x1 - the x coordinate of vertex 1
      y1 - the y coordinate of vertex 1
      z1 - the z coordinate of vertex 1
      x2 - the x coordinate of vertex 2
      y2 - the y coordinate of vertex 2
      z2 - the z coordinate of vertex 2
      x3 - the x coordinate of vertex 3
      y3 - the y coordinate of vertex 3
      z3 - the z coordinate of vertex 3
      color - the color of the triangle; null if none is specified
      Returns:
      the triangle stored by this model
      Throws:
      IllegalArgumentException - one of the first 9 arguments had the value Double.NaN
    • addTriangle

      public Model3D.Triangle addTriangle(double x1, double y1, double z1, double x2, double y2, double z2, double x3, double y3, double z3, Color color, Object tag) throws IllegalArgumentException
      Description copied from interface: Model3DOps
      Add a triangle to the model, specifying the triangle by its vertices and its color, also specifying a tag. The orientation of the triangle is determined by the right-hand rule when going from vertex 1 to vertex 2 to vertex 3.
      Specified by:
      addTriangle in interface Model3DOps<Model3D.Triangle>
      Parameters:
      x1 - the x coordinate of vertex 1
      y1 - the y coordinate of vertex 1
      z1 - the z coordinate of vertex 1
      x2 - the x coordinate of vertex 2
      y2 - the y coordinate of vertex 2
      z2 - the z coordinate of vertex 2
      x3 - the x coordinate of vertex 3
      y3 - the y coordinate of vertex 3
      z3 - the z coordinate of vertex 3
      color - the color of the triangle; null if none is specified
      tag - the tag; null if there is none
      Returns:
      the triangle stored by this model
      Throws:
      IllegalArgumentException - a tag was a triangle or one of the first 9 arguments had the value Double.NaN
    • addFlippedTriangle

      public Model3D.Triangle addFlippedTriangle(double x1, double y1, double z1, double x2, double y2, double z2, double x3, double y3, double z3, Color color, Object tag) throws IllegalArgumentException
      Description copied from interface: Model3DOps
      Add a flipped triangle to the model, specifying the triangle by its vertices and color, also specifying a tag. The orientation of the triangle is the opposite to what the right-hand rule when going from vertex 1 to vertex 2 to vertex 3 would suggest.
      Specified by:
      addFlippedTriangle in interface Model3DOps<Model3D.Triangle>
      Parameters:
      x1 - the x coordinate of vertex 1
      y1 - the y coordinate of vertex 1
      z1 - the z coordinate of vertex 1
      x2 - the x coordinate of vertex 2
      y2 - the y coordinate of vertex 2
      z2 - the z coordinate of vertex 2
      x3 - the x coordinate of vertex 3
      y3 - the y coordinate of vertex 3
      z3 - the z coordinate of vertex 3
      color - the color of the triangle; null if none is specified
      tag - the tag; null if there is none
      Returns:
      the triangle stored by this model
      Throws:
      IllegalArgumentException - a tag was a triangle or one of the first 9 arguments had the value Double.NaN
    • removeTriangle

      public void removeTriangle(Object tag)
      Remove a triangle. Only triangles with tags can be removed.
      Parameters:
      tag - the triangle's tag.
    • addLineSegment

      public Model3D.LineSegment addLineSegment(Model3D.LineSegment segment)
      Add a line segment.
      Parameters:
      segment - the line segment to add.
      Returns:
      the line segment that was added
    • addLineSegment

      public Model3D.LineSegment addLineSegment(double x1, double y1, double z1, double x2, double y2, double z2)
      Add a line segment given the coordinates of its end points. The line segment is a straight line going from point p1 to another point p2.
      Parameters:
      x1 - the x coordinate of point 1
      y1 - the y coordinate of point 1
      z1 - the z coordinate of point 1
      x2 - the x coordinate of point 2
      y2 - the y coordinate of point 2
      z2 - the z coordinate of point 2
      Returns:
      the line segment that was added
    • addLineSegment

      public Model3D.LineSegment addLineSegment(double x1, double y1, double z1, double x2, double y2, double z2, Color color)
      Add a line segment given the coordinates of its end points and color. The line segment is a straight line going from point p1 to another point p2.
      Parameters:
      x1 - the x coordinate of point 1
      y1 - the y coordinate of point 1
      z1 - the z coordinate of point 1
      x2 - the x coordinate of point 2
      y2 - the y coordinate of point 2
      z2 - the z coordinate of point 2
      color - the line segment's color; null if no color is specified
      Returns:
      the line segment that was added
    • addLineSegment

      public Model3D.LineSegment addLineSegment(double x1, double y1, double z1, double x2, double y2, double z2, Color color, Object tag)
      Add a line segment given the coordinates of its end points, its color, and a tag. The line segment is a straight line going from point p1 to another point p2.
      Parameters:
      x1 - the x coordinate of point 1
      y1 - the y coordinate of point 1
      z1 - the z coordinate of point 1
      x2 - the x coordinate of point 2
      y2 - the y coordinate of point 2
      z2 - the z coordinate of point 2
      color - the line segment's color; null if no color is specified
      tag - a tag for the line segment; null if none is specified
      Returns:
      the line segment that was added
    • removeLineSegment

      public void removeLineSegment(Object tag)
      Remove a line segment.
      Parameters:
      tag - a tag naming the line segment
    • setImageParameters

      public Model3D.ImageParams setImageParameters(Model3D.ImageData idata)
      Set image parameters. The image data (idata) will be modified so that all the objects are within the border of the image.
      Parameters:
      idata - image data to read and modify
      Returns:
      the image parameters
    • setImageParameters

      public Model3D.ImageParams setImageParameters(Model3D.ImageData idata, double border)
      Set image parameters given a border. The image data (id) will be modified based on the other arguments so that all objects fit within the image and its border.
      Parameters:
      idata - image data to read and modify
      border - the minimum distance in user space from the edges of an image to the object(s) being displayed; -1 for a default
      Returns:
      the image parameters
    • setImageParameters

      public Model3D.ImageParams setImageParameters(Model3D.ImageData idata, double border, double magnification)
      Set image parameters given a border and magnification. The image data (id) will be modified based on the other arguments. The magnification field provides a factor by which an object is scaled up, so that a value of 2.0 doubles the size of the objects in an image. The fractional positions are 0.
      Parameters:
      idata - image data to read and modify
      border - the minimum distance in user space from the edges of an image to the object(s) being displayed; -1 for a default
      magnification - The magnification of the image.
      Returns:
      the image parameters
    • setImageParameters

      public Model3D.ImageParams setImageParameters(Model3D.ImageData idata, double magnification, double xfract, double yfract)
      Set image parameters given a magnification and fractional positions. The image data (id) will be modified based on the other arguments. The magnification field provides a factor by which an object is scaled up, so that a value of 2.0 doubles the size of the objects in an image. If xfract is 0.0, the minimum value of x for any object will appear at the left border. If xfract is 1.0, the maximum value of x for any object will appear at the right border. If yfract is 0, the minimum value of y for any object will appear at the bottom border. If yfract is 1.0, the maximum value of y for any object will appear at the top border. A default border will be used.
      Parameters:
      idata - image data to read and modify
      magnification - The magnification of the image.
      xfract - the fraction of the image width, excluding the borders, by which an image was shifted along the x axis, with values in the range [0.0, 1.0]
      yfract - the fraction of the image width, excluding the borders, by which an image was shifted along the y axis, with values in the range [0.0, 1.0]
      Returns:
      the image parameters
    • setImageParameters

      public Model3D.ImageParams setImageParameters(Model3D.ImageData id, double border, double magnification, double xfract, double yfract)
      Set image parameters given a border, magnification, and fractional positions. The image data (id) will be modified based on the other arguments. The magnification field provides a factor by which an object is scaled up, so that a value of 2.0 doubles the size of the objects in an image. If xfract is 0.0, the minimum value of x for any object will appear at the left border. If xfract is 1.0, the maximum value of x for any object will appear at the right border. If yfract is 0, the minimum value of y for any object will appear at the bottom border. If yfract is 1.0, the maximum value of y for any object will appear at the top border.
      Parameters:
      id - image data to read and modify
      border - the minimum distance in user space from the edges of an image to the object(s) being displayed; -1 for a default
      magnification - The magnification of the image.
      xfract - the fraction of the image width, excluding the borders, by which an image was shifted along the x axis, with values in the range [0.0, 1.0]
      yfract - the fraction of the image width, excluding the borders, by which an image was shifted along the y axis, with values in the range [0.0, 1.0]
      Returns:
      the image parameters
    • setImageParameters

      public Model3D.ImageParams setImageParameters(Model3D.ImageData id, double border, double magnification, double xfract, double yfract, boolean changeScale) throws Model3D.TessellationException
      Set image parameters given a border, magnification, fractional positions, and a scaling option The image data (id) will be modified based on the other arguments. The magnification field provides a factor by which an object is scaled up, so that a value of 2.0 doubles the size of the objects in an image. If xfract is 0.0, the minimum value of x for any object will appear at the left border. If xfract is 1.0, the maximum value of x for any object will appear at the right border. If yfract is 0, the minimum value of y for any object will appear at the bottom border. If yfract is 1.0, the maximum value of y for any object will appear at the top border.

      If this method throws a Model3D.TessellationException, methods for that exception can be used to determine the source of the error.

      Parameters:
      id - image data to read and modify
      border - the minimum distance in user space from the edges of an image to the object(s) being displayed; -1 for a default
      magnification - The magnification of the image.
      xfract - the fraction of the image width, excluding the borders, by which an image was shifted along the x axis, with values in the range [0.0, 1.0]
      yfract - the fraction of the image width, excluding the borders, by which an image was shifted along the y axis, with values in the range [0.0, 1.0]
      changeScale - true if the scale should be changed; false if not
      Returns:
      the image parameters
      Throws:
      Model3D.TessellationException - if tessellation failed
    • render

      public void render(Model3D.Image image)
      Render a model. The render list, a list of triangles sorted by stacking order, will be cleared afterwards.
      Parameters:
      image - the image which will contain the rendered model
    • render

      public void render(Model3D.Image image, boolean keep)
      Render a model, optionally preserving the render list so that additional objects can be added.
      Parameters:
      image - the image which will contain the rendered model
      keep - true if the render list should be preserved; false if not.
    • render

      public void render(Model3D.Image image, boolean keep, double tx, double ty)
      Render a model, optionally preserving the render list so that additional objects can be added and translating the coordinate system for the model.
      Parameters:
      image - the image which will contain the rendered model
      keep - true if the render list should be preserved; false if not.
      tx - the x coordinate of the new origin's location
      ty - the y coordinate of the new origin's location
    • render

      public void render(Model3D.ImageData id, Graphics2D g2d)
      Render a model given a graphics context.
      Parameters:
      id - the image data for rendered model
      g2d - the graphics context to use
    • render

      public void render(Model3D.ImageData id, Graphics2D g2d, boolean keep)
      Render a model given a graphics context and a render-list preservation flag.
      Parameters:
      id - the image data for rendered model
      g2d - the graphics context to use
      keep - true if the render list should be preserved; false if not.
    • render

      public void render(Model3D.ImageData id, Graphics2D g2d, boolean keep, double tx, double ty) throws Model3D.TessellationException
      Render a model given a graphics context and translations.

      If this method throws a Model3D.TessellationException, methods for that exception can be used to determine the source of the error.

      Parameters:
      id - the image data for rendered model
      g2d - the graphics context to use
      keep - true if the render list should be preserved; false if not.
      tx - the x coordinate of the new origin's location
      ty - the y coordinate of the new origin's location
      Throws:
      Model3D.TessellationException - if tessellation failed
    • verifyClosed2DManifold

      public List<Model3D.Edge> verifyClosed2DManifold()
      Test that the model consists of a closed 2D manifold. The orientation of a triangle is determined by using a "right hand rule" when traversing vertices. For a manifold to be two dimensional, each edge must be traversed no more than twice and to be closed, each edge must be traversed exactly twice, once in each direction. Thus, each edge must be shared by exactly two triangles. A less stringent test is useful in 3D printing: two cubes that touch on a edge but share a common base are printable, but the surface is not a manifold (although it would be if the cubes were offset from each other by a tiny amount). The constructor Model3D(boolean) allows one to specify a "strict" mode, where true requires that the surface is manifold and false allows multiple surfaces to touch at an edge.

      In addition, the rules for a valid STL file preclude partially overlapping edges.

      Returns:
      a list of edges for which the test failed; null if it succeeded
    • verifyEmbedded2DManifold

      public List<Model3D.Triangle> verifyEmbedded2DManifold()
      Test that the model's 2D manifold is embedded in a Euclidean 3 dimensional space. The model is assumed to consist only of triangles: cubic patches, cubic vertices, and cubic triangles are ignored. To test these, first create a tessellated model. Given that the manifold is represented by a set of triangles, the requirement is that triangles do not intersect.
      Returns:
      a list of triangles, each pair of which intersect each other.
    • verifyEmbedded2DManifold

      public List<Model3D.Triangle> verifyEmbedded2DManifold(double limit)
      Test that the model's 2D manifold is embedded in a Euclidean 3 dimensional space, setting a test limit. The model is assumed to consist only of triangles: cubic patches, cubic vertices, and cubic triangles are ignored. To test these, first create a tessellated model. Given that the manifold is represented by a set of triangles, the requirement is that triangles do not intersect.

      The limit (the default is Math.ulp(1F)) is a bound on how far from zero values may be and still be considered to be zero. The limit is intended to account for round-off errors. The method verifyEmbedded2DManifold() uses the default limit.

      Parameters:
      limit - the limit (a non-negative number)
      Returns:
      a list of triangles, each pair of which intersect each other.
    • numberOfComponents

      public int numberOfComponents() throws ManifoldException
      Get the number of manifold components for a model.
      Specified by:
      numberOfComponents in interface Shape3D
      Returns:
      the number of manifold components for the current model
      Throws:
      ManifoldException - the model is ill-formed and its components (the components of a manifold) cannot be computed.
    • getComponent

      public Model3D getComponent(int index) throws ManifoldException
      Get a manifold component. The components are referenced by an index, specified as an integer in the range [0,n), where n is the number of manifold components. If n is zero, no index is valid.
      Specified by:
      getComponent in interface Shape3D
      Parameters:
      index - the component's index
      Returns:
      a model containing the specified component
      Throws:
      ManifoldException - the model is ill-formed and its components (the components of a manifold) cannot be computed.
      See Also:
    • notHollow

      public boolean notHollow() throws ManifoldException
      Determine if some manifold component represents a vacant space.
      Returns:
      true if the model has no inward-facing surfaces; false if it does
      Throws:
      ManifoldException - the model is ill-formed and its components (the components of a manifold) cannot be computed.
    • notHollow

      public boolean notHollow(Appendable out) throws ManifoldException, IOException
      Determine if some manifold component represents a vacant space and optionally store a record of the results.
      Parameters:
      out - an Appendable for recording details; null for no output
      Returns:
      true if the model has no inward-facing surfaces; false if it does
      Throws:
      ManifoldException - the model is ill-formed and its components (the components of a manifold) cannot be computed.
      IOException - an error occurred during writing
    • isComponentHollow

      public boolean isComponentHollow(int index) throws ManifoldException
      Determine if a component of a 3D model is hollow. The precondition for using this method is that the model is a closed 2D manifold embedded in a Euclidean three-dimensional space.
      Parameters:
      index - the index of a component.
      Returns:
      true if the component is hollow (i.e., the normal vectors of its triangles point inwards, not outwards); false otherwise
      Throws:
      ManifoldException - the model is ill-formed and its components (the components of a manifold) cannot be computed.
    • verifyNesting

      public boolean verifyNesting()
      Test that the model compoents are properly nested.
      Returns:
      true if the components are properly nested; false otherwise
    • verifyNesting

      public boolean verifyNesting(Appendable out) throws ManifoldException
      Test that the model compoents are properly nested, and record errors.
      Parameters:
      out - the output appendable
      Returns:
      true if the components are properly nested; false otherwise
      Throws:
      ManifoldException - the model is ill-formed and its components (the components of a manifold) cannot be computed.
    • printable

      public boolean printable()
      Test if a model is printable on a 3D printer.. 3D printing technologies such as laser sintering do not allow one to print hollow objects because material would be trapped inside the object being printed. This method assumes that hollow objects are not allowed for 3D printing.

      Note: this test does not include physical constraints on dimensions. Rather it verifies that the object being printed has a surface that is a closed manifold, the it does not intersect itself, and that components are ordered correctly so that what should be the inside of an object is not the outside of that object. Specific printers will usually have constraints on a model such as minimal thicknesses for "walls" and "wires", and minimum sizes for holes for letting material be removed from cavities.

      Returns:
      true if the model can be printed; false otherwise
    • printable

      public boolean printable(Appendable out) throws IOException
      Test if a model is printable on a 3D printer, given an Appendable for error-message output. 3D printing technologies such as laser sintering do not allow one to print hollow objects because material would be trapped inside the object being printed. This method assumes that hollow objects are not allowed for 3D printing.

      Note: this test does not include physical constraints on dimensions. Rather it verifies that the object being printed has a surface that is a closed manifold, the it does not intersect itself, and that components are ordered correctly so that what should be the inside of an object is not the outside of that object. Specific printers will usually have constraints on a model such as minimal thicknesses for "walls" and "wires", and minimum sizes for holes for letting material be removed from cavities.

      Parameters:
      out - the output on which to print error messages; null if none is to be used
      Returns:
      true if the model cannot be printed; false otherwise
      Throws:
      IOException - an IO exception occurred when printing error messages
    • printable

      public boolean printable(boolean hollow)
      Test if a model is printable on a 3D printer, specifying whether hollow objects are allowed. 3D printing technologies such as laser sintering do not allow one to print hollow objects because material would be trapped inside the object being printed.

      Note: this test does not include physical constraints on dimensions. Rather it verifies that the object being printed has a surface that is a closed manifold, the it does not intersect itself, and that components are ordered correctly so that what should be the inside of an object is not the outside of that object. Specific printers will usually have constraints on a model such as minimal thicknesses for "walls" and "wires", and minimum sizes for holes for letting material be removed from cavities.

      Parameters:
      hollow - true if the printer allows hollow objects; false if not.
      Returns:
      true if the model cannot be printed; false otherwise
    • printable

      public boolean printable(boolean hollow, Appendable out) throws IOException
      Test if a model is printable on a 3D printer, given an Appendable for error-message output and specifying whether hollow objects are allowed. 3D printing technologies such as laser sintering do not allow one to print hollow objects because material would be trapped inside the object being printed.

      Note: this test does not include physical constraints on dimensions. Rather it verifies that the object being printed has a surface that is a closed manifold, the it does not intersect itself, and that components are ordered correctly so that what should be the inside of an object is not the outside of that object. Specific printers will usually have constraints on a model such as minimal thicknesses for "walls" and "wires", and minimum sizes for holes for letting material be removed from cavities.

      Parameters:
      hollow - true if the printer allows hollow objects; false if not.
      out - the output on which to print error messages; null if none is to be used
      Returns:
      true if the model cannot be printed; false otherwise
      Throws:
      IOException - an IO exception occurred when printing error messages
    • notPrintable

      public boolean notPrintable()
      Test if a model is not printable on a 3D printer.. 3D printing technologies such as laser sintering do not allow one to print hollow objects because material would be trapped inside the object being printed. This method assumes that hollow objects are not allowed for 3D printing.

      Note: this test does not include physical constraints on dimensions. Rather it verifies that the object being printed has a surface that is a closed manifold, the it does not intersect itself, and that components are ordered correctly so that what should be the inside of an object is not the outside of that object. Specific printers will usually have constraints on a model such as minimal thicknesses for "walls" and "wires", and minimum sizes for holes for letting material be removed from cavities.

      Returns:
      true if the model cannot be printed; false otherwise
    • notPrintable

      public boolean notPrintable(Appendable out) throws IOException
      Test if a model is not printable on a 3D printer, given an Appendable for error-message output. 3D printing technologies such as laser sintering do not allow one to print hollow objects because material would be trapped inside the object being printed. This method assumes that hollow objects are not allowed for 3D printing.

      Note: this test does not include physical constraints on dimensions. Rather it verifies that the object being printed has a surface that is a closed manifold, the it does not intersect itself, and that components are ordered correctly so that what should be the inside of an object is not the outside of that object. Specific printers will usually have constraints on a model such as minimal thicknesses for "walls" and "wires", and minimum sizes for holes for letting material be removed from cavities.

      Parameters:
      out - the output on which to print error messages; null if none is to be used
      Returns:
      true if the model cannot be printed; false otherwise
      Throws:
      IOException - an IO exception occurred when printing error messages
    • notPrintable

      public boolean notPrintable(boolean hollow)
      Test if a model is not printable on a 3D printer, specifying whether hollow objects are allowed. 3D printing technologies such as laser sintering do not allow one to print hollow objects because material would be trapped inside the object being printed.

      Note: this test does not include physical constraints on dimensions. Rather it verifies that the object being printed has a surface that is a closed manifold, the it does not intersect itself, and that components are ordered correctly so that what should be the inside of an object is not the outside of that object. Specific printers will usually have constraints on a model such as minimal thicknesses for "walls" and "wires", and minimum sizes for holes for letting material be removed from cavities.

      Parameters:
      hollow - true if the printer allows hollow objects; false if not.
      Returns:
      true if the model cannot be printed; false otherwise
    • notPrintable

      public boolean notPrintable(boolean hollow, Appendable out) throws IOException
      Test if a model is not printable on a 3D printer, given an Appendable for error-message output and specifying whether hollow objects are allowed. 3D printing technologies such as laser sintering do not allow one to print hollow objects because material would be trapped inside the object being printed.

      Note: this test does not include physical constraints on dimensions. Rather it verifies that the object being printed has a surface that is a closed manifold, the it does not intersect itself, and that components are ordered correctly so that what should be the inside of an object is not the outside of that object. Specific printers will usually have constraints on a model such as minimal thicknesses for "walls" and "wires", and minimum sizes for holes for letting material be removed from cavities. The test for self intersection apply only to a model's triangles. If a model contains a cubic patch, cubic vertices, or cubic triangles, a tessellated model should be created first.

      Parameters:
      hollow - true if the printer allows hollow objects; false if not.
      out - the output on which to print error messages; null if none is to be used
      Returns:
      true if the model cannot be printed; false otherwise
      Throws:
      IOException - an IO exception occurred when printing error messages
    • area

      public double area()
      Compute the surface area of a 3D model The model must be a closed manifold embedded in a two-dimensional space. The units are those used by graph-coordinate space.

      Implementation note: the result of this computation will be cached so that subsequent calls to this method will simply use the cached value (which is cleared if a triangle is added to the model).

      Returns:
      the surface area
    • volume

      public double volume()
      Compute the volume of a 3D model The model must be a closed manifold embedded in a two-dimensional space. The units are those used by graph-coordinate space. The normal vector is assumed to be in the direction implied by the right-hand rule as each triangle's vertices are traversed in the order defined. If the normal vectors for the triangles in a manifold point outwards, the volume returned will be positive; otherwise it may be negative. One can use inward pointing normal vectors to represent a cavity, but such models typically cannot be 3D printed as material will be trapped inside. A cube with x, y, and z varying from 0.0 to 1.0 will have a volume of 1.0.

      The algorithm used to compute the volume has a complexity linear in the number of triangles: the algorithm uses Gauss' theorem to turn the volume computation into a surface integral, and for each triangle, the integral can be evaluated in closed form.

      Implementation note: the result of this computation will be cached so that subsequent calls to this method will simply use the cached value (which is cleared if a triangle is added to the model).

      Returns:
      the volume
    • setSTLBase

      public void setSTLBase(boolean value)
      Set whether or not an STL base is used. An STL base provides a translation that sets the minimum x, y, and z coordinates to some value, always a positive one (STL files generally contain only positive vertex positions). The default is true. If set to false the STL-base processing is ignored, and the coordinates provided by the model (some of these coordinates may be negative or zero) are used instead.
      Parameters:
      value - true if an STL base is used; false otherwise
    • setSTLBase

      public void setSTLBase(double offset)
      Set the value of STL Base. The STL Base parameters will be set so that the minimum values of x, y and z for objects in a model are given by offset. The default is 1.0.
      Parameters:
      offset - an offset determining the STL base.
    • setSTLBase

      public void setSTLBase()
      Set the value of STL Base to a default. Equivalent to setSTLBase(1.0).
    • setUnitScaleX3D

      public void setUnitScaleX3D(double value)
      Set the unit scale factor for X3D files. The default is 0.001 so that a length of 1.0 is 1 mm.
      Parameters:
      value - the length of a unit length in meters
    • getUnitScaleX3D

      public double getUnitScaleX3D()
      Get the unit scale factor for X3D files. The value is the length in meters of a unit-length in the model.
      Returns:
      the scale factor
    • writeX3D

      public void writeX3D(String title, String description, String creator, String fname) throws IOException
      Create an X3D file from the model, given a file name. The first three parameters are strings used in meta data. The file created will use the X3D binary format if the JRE supports the fast infoset format; otherwise the format will default to the XML format. To control the format explicitly, use writeX3D(String,String,String,OutputStream,boolean).

      The XML format before a infoset is created does not have a DOCTYPE declaration: tests indicated that the corresponding DTD was not being processed appropriately. The X3D file will specify an "Interchange" profile. If the file-name extension is "x3dz" or "X3DZ", the file will be compressed.

      Parameters:
      title - the title of the file; null for a default
      description - a description of the file; null for a default
      creator - the file's author; null for a default
      fname - the name of the file
      Throws:
      IOException - an IO error occurred
    • writeX3D

      public void writeX3D(String title, String description, String creator, boolean full, String fname) throws IOException
      Create an X3D file from the model, given a file name and specifying a profile. The first three parameters are strings used in meta data. use writeX3D(String,String,String,OutputStream,boolean). If the file-name extension is "x3dz" or "X3DZ", the file will be compressed.

      The XML format before a infoset is created does not have a DOCTYPE declaration: tests indicated that the corresponding DTD was not being processed appropriately.

      Parameters:
      title - the title of the file; null for a default
      description - a description of the file; null for a default
      creator - the file's author; null for a default
      full - true if the Full X3D profile should be used; false for the Interchange profile
      fname - the name of the file
      Throws:
      IOException - an IO error occurred
    • writeSTL

      public void writeSTL(String id, String fname) throws IOException
      Create an STL file from the model, given a file name. The file created will use the X3D binary format if the JRE supports the fast infoset format; otherwise the format will default to the XML format. To control the format explicitly, use writeX3D(String,String,String,OutputStream,boolean).
      Parameters:
      id - the STL file's ID string (limited to 80 7-bit ASCII characters)
      fname - the name of the file
      Throws:
      IOException - an error occurred when opening or writing the file
    • writeSTL

      public void writeSTL(String id, File f) throws IOException
      Create an STL file from the model, given a file. The file created will use the X3D binary format if the JRE supports the fast infoset format; otherwise the format will default to the XML format. To control the format explicitly, use writeX3D(String,String,String,OutputStream,boolean).
      Parameters:
      id - the STL file's ID string (limited to 80 7-bit ASCII characters)
      f - the output file
      Throws:
      IOException - an error occurred when opening or writing the file
    • writeX3D

      public void writeX3D(String title, String description, String creator, File f) throws IOException
      Create an X3D file from the model, given a File. The first three parameters are strings used in meta data. The X3D file will specify a "Interchange" profile. If the file-name extension is "x3dz" or "X3DZ", the file will be compressed.
      Parameters:
      title - the title of the file; null for a default
      description - a description of the file; null for a default
      creator - the file's author; null for a default
      f - the file
      Throws:
      IOException - an IO error occurred
    • writeX3D

      public void writeX3D(String title, String description, String creator, boolean full, File f) throws IOException
      Create an X3D file from the model, given a File and specifying a profile. The first three parameters are strings used in meta data. If the file-name extension is "x3dz" or "X3DZ", the file will be compressed.
      Parameters:
      title - the title of the file; null for a default
      description - a description of the file; null for a default
      full - true if the Full X3D profile should be used; false for the Interchange profile
      creator - the file's author; null for a default
      f - the file
      Throws:
      IOException - an IO error occurred
    • writeSTL

      public void writeSTL(String id, OutputStream out) throws IOException
      Create an STL file from the model, given an output stream.
      Parameters:
      id - the STL file's ID string (limited to 80 7-bit ASCII characters)
      out - the output stream
      Throws:
      IOException - an error occurred when writing to the stream
    • writeX3D

      public void writeX3D(String title, String description, String creator, OutputStream os) throws IOException
      Create an X3D file from the model, given an output stream. The first three parameters are strings used in meta data. The X3D file will specify an "Interchange" profile. The file will not be compressed.
      Parameters:
      title - the title of the file; null for a default
      description - a description of the file; null for a default
      creator - the file's author; null for a default
      os - the output stream
      Throws:
      IOException - an IO error occurred
    • writeX3D

      public void writeX3D(String title, String description, String creator, boolean full, OutputStream os) throws IOException
      Create an X3D file from the model, specifying a profile and given an output stream. The first three parameters are strings used in meta data. The file will not be compressed.
      Parameters:
      title - the title of the file; null for a default
      description - a description of the file; null for a default
      creator - the file's author; null for a default
      full - true if the Full X3D profile should be used; false for the Interchange profile
      os - the output stream
      Throws:
      IOException - an IO error occurred
    • writeX3D

      public void writeX3D(String title, String description, String creator, OutputStream os, boolean compress) throws IOException
      Create an X3D file in either binary or XML format from the model, given an output stream. The first three parameters are strings used in meta data. The binary format is a fast infoset encoding of the XML file. Currently it is not supported but may be in future releases. The X3D file will specify an "Interchange" profile.
      Parameters:
      title - the title of the file; null for a default
      description - a description of the file; null for a default
      creator - the file's author; null for a default
      os - the output stream
      compress - true if the file should be compressed; false otherwise
      Throws:
      IOException - an IO error occurred
      UnsupportedOperationException - binary encoding is not supported
    • writeX3D

      public void writeX3D(String title, String description, String creator, boolean full, OutputStream os, boolean compress) throws IOException, Model3D.TessellationException
      Create an X3D file in either binary or XML format from the model, given a profile specification and an output stream. The first three parameters are strings used in meta data.

      If compressed, the output stream will be automatically closed.

      If this method throws a Model3D.TessellationException, methods for that exception can be used to determine the source of the error.

      Parameters:
      title - the title of the file; null for a default
      description - a description of the file; null for a default
      creator - the file's author; null for a default
      full - true if the Full X3D profile should be used; false for the Interchange profile
      os - the output stream
      compress - true if the file should be compressed; false for XML alone
      Throws:
      IOException - an IO error occurred
      UnsupportedOperationException - binary encoding is not supported
      Model3D.TessellationException - if tessellation failed
    • writeSTL

      Create an STL file from the model, given a writable byte channel.

      If this method throws a Model3D.TessellationException, methods for that exception can be used to determine the source of the error.

      Parameters:
      id - the STL file's ID string (limited to 80 7-bit ASCII characters)
      c - the output channel
      Throws:
      IOException - an error occurred when writing to the channel
      Model3D.TessellationException - if tessellation failed
    • createImageSequence

      public void createImageSequence(OutputStream os, String imageType, int nphi, int ntheta) throws IOException
      Create a sequence of images. The images will be created in the format supported by ImageSequenceWriter. When the number of steps is 0, only a single image will appear in the sequence. When θ is 0 or 180 degrees, $phi; will be set to 0. if nphi is 0, φ will also be set to 0. Otherwise for each value of θ φ will range from 0 to 360 in steps of 360/nphi.

      The images show the edges of triangles in green, and shows the interior side of a triangle in red. The background is a dark blue and the model is various shades of gray depending on a triangle's orientation. This is intended for visual model checking.

      Parameters:
      os - the output stream
      imageType - the image type
      nphi - the number of steps for the Eulerian angle φ
      ntheta - the number of steps for the Eulerian angle $theta;
      Throws:
      IOException - if an IO error occurred
    • createImageSequence

      public void createImageSequence(OutputStream os, String imageType, int nphi, int ntheta, double delta, double colorFactor) throws IOException
      Create a sequence of images, specifying a color factor and the maximum triangle size for rendering. The images will be created in the format supported by ImageSequenceWriter. When the number of steps is 0, only a single image will appear in the sequence. When θ is 0 or 180 degrees, $phi; will be set to 0. if nphi is 0, φ will also be set to 0. Otherwise for each value of θ φ will range from 0 to 360 in steps of 360/nphi.

      The parameters delta and colorFactor are used to fine-tune the images. A non-zero value of delta will result in triangles above a critical size being partitioned into smaller triangles for rendering in order to reduce Z-ordering problems. A non-zero color factor will cause triangles with lower Z values (after all transformations and coordinate-system rotations) to appear darker. This is useful when a model has multiple parallel surfaces with different Z values. and the user otherwise cannot distinguish them.

      The images show the edges of triangles in green, and shows the interior side of a triangle in red. The background is a dark blue and the model is various shades of gray depending on a triangle's orientation. This is intended for visual model checking.

      Parameters:
      os - the output stream
      imageType - the image type
      nphi - the number of steps for the Eulerian angle φ
      ntheta - the number of steps for the Eulerian angle $theta;
      delta - the maximum triangle size for rendering; 0.0 if this parameter should be ignored
      colorFactor - the color factor; 0.0 if this parameter should be ignored
      Throws:
      IOException - if an IO error occurred
      See Also:
    • createImageSequence

      public void createImageSequence(OutputStream os, String imageType, int nphi, int ntheta, double delta, double colorFactor, double normalFactor, boolean showEdges) throws IOException
      Create a sequence of images, specifying a color factor, normal factor and the maximum triangle size for rendering. The images will be created in the format supported by ImageSequenceWriter. When the number of steps is 0, only a single image will appear in the sequence. When θ is 0 or 180 degrees, $phi; will be set to 0. if nphi is 0, φ will also be set to 0. Otherwise for each value of θ φ will range from 0 to 360 in steps of 360/nphi.

      The parameters delta and colorFactor are used to fine-tune the images. A non-zero value of delta will result in triangles above a critical size being partitioned into smaller triangles for rendering in order to reduce Z-ordering problems. A non-zero color factor will cause triangles with lower Z values (after all transformations and coordinate-system rotations) to appear darker. This is useful when a model has multiple parallel surfaces with different Z values. and the user otherwise cannot distinguish them. The color factor is useful primarily for surfaces that are in the X-Y plane after coordinate transformations. If the the normal factor is set to a small positive value, the color factor will be effectively reduced when triangles whose normal vectors are not aligned with the Z axis are rendered. For a normal factor f, the color factor will be reduced by a factor of exp(-(1-nz)/f) where nz is the Z component of the normal vector.

      The images show the edges of triangles in green, and shows the interior side of a triangle in red. The background is a dark blue and the model is various shades of gray depending on a triangle's orientation. This is intended for visual model checking.

      Parameters:
      os - the output stream
      imageType - the image type
      nphi - the number of steps for the Eulerian angle φ
      ntheta - the number of steps for the Eulerian angle $theta;
      delta - the maximum triangle size for rendering; 0.0 if this parameter should be ignored
      colorFactor - the color factor; 0.0 if this parameter should be ignored
      normalFactor - the normal factor; 0.0 if there is none
      showEdges - true if edges of triangles and patches should be shown; false otherwise
      Throws:
      IOException - if an IO error occurred
      See Also:
    • createCrossSection

      public void createCrossSection(Graph graph, double xp, double yp, double zp, double[] normal) throws IllegalArgumentException, Model3D.TessellationException
      Generate a graph containing a cross section of this model, using the current tessellation level, where triangle edges pass through a plane that passes through the point (xp, yp, zp) and perpendicular to a normal vector.

      The orientation of the cross section is implementation dependent, but may be rotated by 90 degrees if that will result in a larger image. The triangles and edges that go through the plane will be drawn, projected onto the plane, and will be denoted by black lines. Any edges and triangles reported by the methods verifyClosed2DManifold() or verifyEmbedded2DManifold() will be denoted by red lines. After this method is called, the graph should be written or otherwise displayed. The graph will have its offsets and ranges set automatically. For example, in a test case that purposely generated an error and where notPrintable(Appendable) printed

      
       3D model's surface is not embedded in a three-dimensional space:
       Planar Triangle (-6.70000,2.30000,4.70000)-(-6.70000,6.70000,4.70000)-(-1.10000,1.90526,4.70000)
       Planar Triangle (-3.00000,3.00000,8.00000)-(3.00000,3.00000,4.00000)-(-3.00000,3.00000,4.00000)
      
       
      The code
      
       Graph graph = new Graph(700, 700);
       m3d.createCrossSection(graph, -3.0, 3.0, 4.7,
                              new double[] {0.0, 1.0, 0.0});
       graph.write("png", "fakelock.png");
       
      produced the following image (truncated and rotated for display purposes:

      3D model that looks like a lock

      thus providing a visual representation of the error.

      If this method throws a Model3D.TessellationException, methods for that exception can be used to determine the source of the error.

      Parameters:
      graph - the graph
      xp - the X coordinate of the designated point on the plane
      yp - the Y coordinate of the designated point on the plane
      zp - the Z coordinate of the designated point on the plane
      normal - the normal vector for the plane
      Throws:
      IllegalArgumentException - if the graph or normal vector are null, if the graph's size is less than 200×200, of if the normal vector's norm is 0
      Model3D.TessellationException - if tessellation failed