public class TubeFactory extends Object
Example: in euclidean space, a tube around a line is an infinite cylinder. And, a tube around a line segment is a finite cylinder.
Complications arise in calculating tubes in various ways, some of which this class attempts to take into account:
If the curve is considered to be discrete, then the tubing problem is not well-posed near the joints of the curve, since there the curvature approaches infinity and any finite tube will intersect itself.
This factory provides the basic foundation. It does not provide any geometry output;
it is useful mainly on account of the method #makeFrameField(double[][], int, int)
. See its
documentation for a more precise statement of the mathematical implementation.
Subclassses which generate actual geometric tubes can take different strategies
to the challenges posed above, working with the same basic data provided in this class.
The basic data which determine the tube are:
Pn
)These data are set using the instance methods below.
Calling update()
will update the current state of the factory to the
values set since the last call to update()
. This is mostly of interest in the subclasses.
TODO adjust the parameter which determines how the profile at the vertices of the curve are "pulled back" towards the mid-segment profiles.
Modifier and Type | Field and Description |
---|---|
boolean |
closedCurve |
double[][] |
crossSection |
double[][] |
edgeColors |
boolean |
extendAtEnds |
FrameFieldType |
frameFieldType |
boolean |
framesDirty |
boolean |
generateTextureCoordinates |
int |
metric |
double[] |
radii |
double |
radius |
double[][] |
theCurve |
int |
twists |
double[][] |
userBinormals |
double[][] |
userTangents |
double[][] |
vertexColors |
boolean |
vertexColorsEnabled |
Constructor and Description |
---|
TubeFactory() |
TubeFactory(double[][] curve) |
Modifier and Type | Method and Description |
---|---|
TubeUtility.FrameInfo[] |
getFrameField() |
SceneGraphComponent |
getFramesSceneGraphRepresentation() |
double[] |
getInitialBinormal() |
static SceneGraphComponent |
getSceneGraphRepresentation(TubeUtility.FrameInfo[] frames) |
static SceneGraphComponent |
getSceneGraphRepresentation(TubeUtility.FrameInfo[] frames,
double scale) |
double[][] |
getTangents() |
double[][] |
getUserBinormals() |
static SceneGraphComponent |
getXYZAxes() |
boolean |
isArcLengthTextureCoordinates() |
boolean |
isExtendAtEnds() |
boolean |
isGenerateEdges() |
boolean |
isGenerateTextureCoordinates() |
boolean |
isMatchClosedTwist() |
boolean |
isRemoveDuplicates() |
TubeUtility.FrameInfo[] |
makeFrameField(double[][] polygon,
FrameFieldType type,
int metric)
The primary method in the tube-generating process.
|
void |
setArcLengthTextureCoordinates(boolean arcLengthTextureCoordinates)
If true, force the generated v- texture coordinates to run from 0 to 1 proportional
to the (discrete) arc length of the curve.
|
void |
setClosed(boolean closedCurve)
Set whether the curve should be considered a closed loop.
|
void |
setCrossSection(double[][] crossSection)
A 2D curve in the (x,y) plane (with 3D coordinates!) to be used as the
cross section of the tube.
|
void |
setEdgeColors(double[][] edgeColors)
Apply colors to faces of output tube, one for each tube segment.
|
void |
setExtendAtEnds(boolean extendAtEnds) |
void |
setFrameField(TubeUtility.FrameInfo[] frames) |
void |
setFrameFieldType(FrameFieldType frameFieldType)
Should the underlying frame field be generated by
TubeUtility#PARALLEL or
TubeUtility#FRENET displacement? Default: TubeUtility#PARALLEL |
void |
setGenerateEdges(boolean generateEdges) |
void |
setGenerateTextureCoordinates(boolean generateTextureCoordinates)
Whether the output geometry should have automatic texture coordinates.
|
void |
setInitialBinormal(double[] initialBinormal) |
void |
setMatchClosedTwist(boolean matchClosedTwist) |
void |
setMetric(int metric)
Set the metric of the ambient space.
|
void |
setRadii(double[] radii) |
void |
setRadius(double radius)
Set the radius of the tube.
|
void |
setRemoveDuplicates(boolean removeDuplicates) |
void |
setTangents(double[][] tangents) |
void |
setTwists(int twists)
Set an integer number of twists to apply to the cross section as it is
swept along the curve.
|
void |
setUserBinormals(double[][] userBinormals) |
void |
setVertexColors(double[][] vertexColors)
Apply colors to vertices of output tube, one for each tube cross section.
|
void |
setVertexColorsEnabled(boolean vertexColorsEnabled)
Whether to apply vertex colors to the output tube.
|
void |
update() |
void |
updateFrames() |
public double[][] theCurve
public double[][] userTangents
public double[][] userBinormals
public double[][] vertexColors
public double[][] edgeColors
public double[][] crossSection
public double[] radii
public double radius
public FrameFieldType frameFieldType
public int metric
public int twists
public boolean generateTextureCoordinates
public boolean extendAtEnds
public boolean framesDirty
public boolean closedCurve
public boolean vertexColorsEnabled
public TubeFactory()
public TubeFactory(double[][] curve)
public void updateFrames()
public TubeUtility.FrameInfo[] getFrameField()
public void setClosed(boolean closedCurve)
closedCurve
- public void setCrossSection(double[][] crossSection)
crossSection
- public double[][] getTangents()
public void setTangents(double[][] tangents)
public double[][] getUserBinormals()
public void setUserBinormals(double[][] userBinormals)
public void setFrameField(TubeUtility.FrameInfo[] frames)
public void setFrameFieldType(FrameFieldType frameFieldType)
TubeUtility#PARALLEL
or
TubeUtility#FRENET
displacement? Default: TubeUtility#PARALLEL
frameFieldType
- public void setRadius(double radius)
radius
- public void setRadii(double[] radii)
public void setMetric(int metric)
Pn
.metric
- public void setTwists(int twists)
twists
- public void setVertexColorsEnabled(boolean vertexColorsEnabled)
setVertexColors(double[][])
.vertexColorsEnabled
- public void setEdgeColors(double[][] edgeColors)
edgeColors
- double[n][] where n is number of segments in curvepublic void setVertexColors(double[][] vertexColors)
vertexColors
- double[n][] where n is number of vertices in curvepublic boolean isGenerateTextureCoordinates()
public void setGenerateTextureCoordinates(boolean generateTextureCoordinates)
setArcLengthTextureCoordinates(boolean)
public boolean isArcLengthTextureCoordinates()
public void setArcLengthTextureCoordinates(boolean arcLengthTextureCoordinates)
arcLengthTextureCoordinates
- public boolean isExtendAtEnds()
public void setExtendAtEnds(boolean extendAtEnds)
public boolean isRemoveDuplicates()
public void setRemoveDuplicates(boolean removeDuplicates)
public boolean isGenerateEdges()
public void setGenerateEdges(boolean generateEdges)
public boolean isMatchClosedTwist()
public void setMatchClosedTwist(boolean matchClosedTwist)
public double[] getInitialBinormal()
public void setInitialBinormal(double[] initialBinormal)
public SceneGraphComponent getFramesSceneGraphRepresentation()
public void update()
public TubeUtility.FrameInfo[] makeFrameField(double[][] polygon, FrameFieldType type, int metric)
This is an instance method, since there is quite a bit of state which is expensive to compute and so can be saved in the instance.
The code is complicated by dealing with euclidean, hyperbolic, and elliptic cases simultaneously and But at the same time the code is a interesting example of how euclidean objects can be generalized to non-euclidean setting.
Explanation of the algorithm: Assume that polygon is an array of length n
The input curve polygon is assumed to have an initial and terminal point with the following properties: 1) if the curve is closed, polygon[0]=polygon[n-2] and polygon[n-1]=polygon[1] 2) if the curve is not closed, then polygon[0] is the mirror of polygon[2] wrt polygon[1], similarly for polygon[n-1]. The tubing factories perform this setup automatically before calling this method, but if you want to use this method directly, you'll need to do this setup yourself.
The returned frame array (of type TubeUtility.FrameInfo
is of length n-2.
The input curve can consist of either 3- or 4-d vectors; in the latter case they are assumed to be homogeneous projective coordinates.
The basic idea is: first calculate the Frenet frame for the curve. That is, in the best case, a simple matter at each point P[i] of the curve:
polygon
- the curve to frame (as array of 3- or 4-d points)type
- TubeUtility.PARALLEL
or {TubeUtility.FRENET}metric
- the metric metric Pn
TubeUtility.FrameInfo
containing an orthonormal frame for each internal point in the initial polygon array.public static SceneGraphComponent getSceneGraphRepresentation(TubeUtility.FrameInfo[] frames)
public static SceneGraphComponent getSceneGraphRepresentation(TubeUtility.FrameInfo[] frames, double scale)
public static SceneGraphComponent getXYZAxes()