de.jreality.geometry

## Class ThickenedSurfaceFactory

• ```public class ThickenedSurfaceFactory
extends Object```
This factory class allows you to create a thickened surface from a given surface (given as an instance of `IndexedFaceSet`. The result is a closed surface with a well-defined interior and exterior.

The first step is that a copy of the surface is created by moving the original vertices along the vertex normal direction until they are a distance thickness from the original vertices. For convenience, call the original surface the bottom surface and this new surface the top surface.

The second step is to find all edges which only appear once in the combinatorics of the indexed face set. These edges are assumed to be boundary edges; to each such edge a new quadrilateral is created which joins the edge to its translated image under step one. If face colors are provided for the original surface, then the face color of these new boundary faces is inherited from the unique face to which the boundary edge belongs.

The third step is to (optionally) generate holes in the thickened surface, one for each face of the original surface. To be exact, a hole are introduced into each face of the bottom surface and its corresponding face in the top surface. A tube is then constructed joining the two holes together. The tube is constructed as a product surface. Currently, any cross section of the tube parallel to the two faces is a scaled version of a special curve inscribed in this face; to be exact, it is a quadric curve tangent to the midpoints of the faces of the face. And the cross section of the tube by a plane passing through the center of the hole and perpendicular to the original face is determined by the profile curve parameter.

A typical invocation of an instance of this class looks like:

``````                surface = SphereUtility.tessellatedIcosahedronSphere(1);
tsf = new ThickenedSurfaceFactory(surface);             // constructor requires a surface
tsf.setThickness(.1);                           // distance between top and bottom
tsf.setMakeHoles(true);                         // boolean
tsf.setHoleFactor(.5);                          // values smaller than one make the holes bigger
tsf.setStepsPerEdge(6);                         // each original edge is replaced by 6 segments
// profile curve describes the cross-section of the hole
tsf.setProfileCurve(new double[][]{{0,0}, {.333,.5},{.666, .5},{1,0}});
tsf.update();
IndexedFaceSet thickSurface = tsf.getThickenedSurface();

``````

Note: the case of a non-orientable surface represents special difficulties for the thicken factory. Some remarks:

• If a single vertex borders on two faces with opposite-facing normals, the factory will produce incorrect results, in which the two sides of the thickened surface cross each other.
• If duplicate vertices are present on two face with opposite-facing normals, there is hope. Call the the method `setMergeDuplicateBoundaryVerts(boolean)` with the value `true`. The factory will then attempt to find such vertices and do surgery on the thickened surface to avoid the crossing.

Author:
Charles Gunn
• ### Constructor Summary

Constructors
Constructor and Description
`ThickenedSurfaceFactory(IndexedFaceSet ifs)`
• ### Method Summary

All Methods
Modifier and Type Method and Description
`double` `getHoleFactor()`
`int` `getMetric()`
`double[][]` `getProfileCurve()`
`double` `getShiftAlongNormal()`
`int` `getStepsPerEdge()`
`IndexedFaceSet` `getSurface()`
`IndexedFaceSet` `getThickenedSurface()`
This returns the thickened surface.
`double` `getThickness()`
`boolean` `isConstantWidth()`
`boolean` `isCurvedEdges()`
`boolean` `isKeepFaceColors()`
`boolean` `isLinearHole()`
`boolean` `isMakeHoles()`
`boolean` `isMergeDuplicateBoundaryVerts()`
`boolean` `isThickenAlongFaceNormals()`
`void` `processBoundary()`
`void` `setConstantWidth(boolean constantWidth)`
`void` `setCurvedEdges(boolean curvedEdges)`
`void` `setHoleFactor(double holeFactor)`
This parameter is an additional parameter controlling the size of the hole.
`void` `setKeepFaceColors(boolean keepFaceColors)`
Set this to true to retain the original face colors of the input surface in the thickened surface.
`void` `setLinearHole(boolean linearHole)`
`void` `setMakeHoles(boolean makeHoles)`
Determines whether holes are generated in the thickened surface or not.
`void` `setMergeDuplicateBoundaryVerts(boolean b)`
`void` `setMetric(int metric)`
For working in non-euclidean geometries, set this.
`void` `setProfileCurve(double[][] profileCurve)`
This set of number pairs controls the cross-section of the hole when I cut it with a plane passing through the center of the hole parallel to the normal direction of the original surface.
`void` `setShiftAlongNormal(double shiftAlongNormal)`
`void` `setStepsPerEdge(int stepsPerEdge)`
The refinement of the geometry created to represent a hole is controlled by this parameter.
`void` `setSurface(IndexedFaceSet theSurface)`
`void` `setThickenAlongFaceNormals(boolean thickedAlongFaceNormals)`
`void` `setThickness(double thickness)`
This parameter controls how far apart the top and bottom surfaces are.
`void` `update()`
This has to be called after each set of edits to the state of the factory, in order to update the result.
• ### Methods inherited from class java.lang.Object

`equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`
• ### Constructor Detail

• #### ThickenedSurfaceFactory

`public ThickenedSurfaceFactory(IndexedFaceSet ifs)`
• ### Method Detail

• #### getSurface

`public IndexedFaceSet getSurface()`
• #### setSurface

`public void setSurface(IndexedFaceSet theSurface)`
• #### isMakeHoles

`public boolean isMakeHoles()`
• #### setMakeHoles

`public void setMakeHoles(boolean makeHoles)`
Determines whether holes are generated in the thickened surface or not. Default: false;
Parameters:
`makeHoles` -
• #### getProfileCurve

`public double[][] getProfileCurve()`
• #### setProfileCurve

`public void setProfileCurve(double[][] profileCurve)`
This set of number pairs controls the cross-section of the hole when I cut it with a plane passing through the center of the hole parallel to the normal direction of the original surface. to be precise, they are weights used with a bilinear interpolation scheme.

The first coordinate of each pair controls the mixture of the top and bottom surfaces and the second coordinate controls the mixture of the center point and the peripheral point (point on the original edge).

For example, the triple `{{0,0},{.5,1},{1,0}}` results in a profile curve that begins on the bottom surface (x = 0) at the original edge (y=0), moves to the middle between top and bottom (x = .5) at the center of the hole (y=1), and ends at the top surface (x = 0) at the original edge there (y = 0). examples.put("borromean ring",surface);

Parameters:
`profileCurve` -
• #### getStepsPerEdge

`public int getStepsPerEdge()`
• #### setStepsPerEdge

`public void setStepsPerEdge(int stepsPerEdge)`
The refinement of the geometry created to represent a hole is controlled by this parameter. Default: 3
Parameters:
`stepsPerEdge` -
• #### getThickness

`public double getThickness()`
• #### setThickness

`public void setThickness(double thickness)`
This parameter controls how far apart the top and bottom surfaces are.
Parameters:
`thickness` -
• #### getHoleFactor

`public double getHoleFactor()`
• #### setHoleFactor

`public void setHoleFactor(double holeFactor)`
This parameter is an additional parameter controlling the size of the hole. It basically is used as a scale factor on the y-coordinate of the profile curve; larger values make the hole smaller, while smaller ones make the whole bigger. Negative values are discouraged. Default: 1.0
Parameters:
`holeFactor` -
• #### isKeepFaceColors

`public boolean isKeepFaceColors()`
• #### getMetric

`public int getMetric()`
• #### setMetric

`public void setMetric(int metric)`
For working in non-euclidean geometries, set this. Default: `Pn.EUCLIDEAN`. Warning: currently ignored.
Parameters:
`metric` -
• #### setKeepFaceColors

`public void setKeepFaceColors(boolean keepFaceColors)`
Set this to true to retain the original face colors of the input surface in the thickened surface.
Parameters:
`keepFaceColors` -
• #### isCurvedEdges

`public boolean isCurvedEdges()`
• #### setCurvedEdges

`public void setCurvedEdges(boolean curvedEdges)`
• #### isLinearHole

`public boolean isLinearHole()`
• #### setLinearHole

`public void setLinearHole(boolean linearHole)`
• #### getShiftAlongNormal

`public double getShiftAlongNormal()`
• #### setShiftAlongNormal

`public void setShiftAlongNormal(double shiftAlongNormal)`
• #### isThickenAlongFaceNormals

`public boolean isThickenAlongFaceNormals()`
• #### setThickenAlongFaceNormals

`public void setThickenAlongFaceNormals(boolean thickedAlongFaceNormals)`
• #### isConstantWidth

`public boolean isConstantWidth()`
• #### setConstantWidth

`public void setConstantWidth(boolean constantWidth)`
• #### getThickenedSurface

`public IndexedFaceSet getThickenedSurface()`
This returns the thickened surface. This remains the same for the life of the factory.
Returns:
• #### update

`public void update()`
This has to be called after each set of edits to the state of the factory, in order to update the result.
• #### processBoundary

`public void processBoundary()`
• #### isMergeDuplicateBoundaryVerts

`public boolean isMergeDuplicateBoundaryVerts()`
• #### setMergeDuplicateBoundaryVerts

`public void setMergeDuplicateBoundaryVerts(boolean b)`