public class RobustPreds
extends java.lang.Object
In general, the methods will first perform the query using regular
double-precision arithmetic. If this is insufficient to yield a correct
answer, the query is reevaluated using "robust" predicates involving
adaptive precision arithmetic (Jonathan Shewchuck, "Adaptive precision
floating-point arithmetic and fast robust geometric predicates", Discrete
&
Computational Geometry, 1997).
If the computation is exactly degenerate (i.e., an edge exactly intersects a triangle vertex or edge, then a whether or not an intersection occurs is determined using tie-breaking rules as described in Edelsbrunner and Peter, "Simulation of simplicity: a technique to cope with degenerate cases in geometric algorithms", ACM Transactions on Graphics, 1990, and as implemented by Aftosmis et al., "Robust and efficient Cartesian mesh generation for component-based geometry", AIAA journal, 1998. These tie-breaking rules require assigning unique indices to all primitive vertices, and making sure that these remain the same across all the calculations. In cases where all queries involve triangles and faces from two triangular meshes, we can determine such unique indices using the mesh-specific vertex indices. For the vertices on the first mesh, we use mesh indices verbatim, while for the second mesh we use the mesh indices plus the number of vertices on the first mesh.
The robust predicates used by this class are supported using a native code library.
Modifier and Type | Field and Description |
---|---|
static int |
DEGENERACY_MASK |
static int |
E01_ON_SEGMENT
triangle edge 01 is on the segment, according to exact arithmetic
|
static int |
E12_ON_SEGMENT
triangle edge 12 is on the segment, according to exact arithmetic
|
static int |
E20_ON_SEGMENT
triangle edge 20 is on the segment, according to exact arithmetic
|
static int |
HEAD_ON_TRIANGLE
head segment point is on the triangle plane, according to exact arithmetic
|
static int |
INTERSECTS
segment and triangle intersect
|
static int |
TAIL_ON_TRIANGLE
tail segment point is on the triangle plane, according to exact arithmetic
|
static int |
TAIL_OUTSIDE
tail segment point is outside the (counterclockwise) triangle, according to
tie-breaking rules
|
static int |
V0_ON_SEGMENT
triangle vertex 0 is on the segment, according to exact arithmetic
|
static int |
V1_ON_SEGMENT
triangle vertex 1 is on the segment, according to exact arithmetic
|
static int |
V2_ON_SEGMENT
triangle vertex 2 is on the segment, according to exact arithmetic
|
Constructor and Description |
---|
RobustPreds() |
Modifier and Type | Method and Description |
---|---|
static int |
closestIntersection(Face faceC,
HalfEdge edge,
Face faceD)
Assuming that
faceC and faceD both intersect
edge , determines which intersection point comes irst. |
static int |
intersectEdgeTriangle(Point3d ipnt,
HalfEdge edge,
Face face,
double maxlen,
boolean edgeOnMesh0,
boolean worldCoords)
Tests for the intersection of an edge and a triangle described by a
face.
|
static int |
intersectSegmentTriangle(Point3d ipnt,
int it,
Vector3d pt,
int ih,
Vector3d ph,
int i0,
Vector3d p0,
int i1,
Vector3d p1,
int i2,
Vector3d p2)
Tests for the intersection of a line segment and a triangle.
|
static int |
intersectSegmentTriangle(Point3d ipnt,
Point3d pt,
Point3d ph,
Face face,
double maxlen,
boolean worldCoords)
Tests for the intersection of a line segment and a triangle described by
a face.
|
static int |
intersectSegmentTriangleFast(Point3d ipnt,
Point3d pt,
Point3d ph,
Point3d p0,
Point3d p1,
Point3d p2,
double maxlen)
Tests for the intersection of a line segment and a triangle described by
a face using double precision arithmetic.
|
static boolean |
orient3d(Vertex3d v0,
Vertex3d v1,
Vertex3d v2,
Vertex3d v3,
boolean v3OnMesh0,
boolean worldCoords)
Returns
true if v3 is "below", or "inside" the plane formed
by the counterclockwise triangle v0, v1, v2. |
static double |
orient3dFast(Vector3d p0,
Vector3d p1,
Vector3d p2,
Vector3d p3,
double maxlen)
Fast test to see if p3 is "below", or "inside" the plane formed by the
counterclockwise triangle p0, p1, p2.
|
static void |
printIntersectEdgeFace(HalfEdge edge,
Face face,
boolean edgeOnMesh0)
For debugging - prints out arguments sent to jniIntersectSegmentTriangle().
|
public static final int INTERSECTS
public static final int TAIL_OUTSIDE
public static final int TAIL_ON_TRIANGLE
public static final int HEAD_ON_TRIANGLE
public static final int E01_ON_SEGMENT
public static final int E12_ON_SEGMENT
public static final int E20_ON_SEGMENT
public static final int V0_ON_SEGMENT
public static final int V1_ON_SEGMENT
public static final int V2_ON_SEGMENT
public static final int DEGENERACY_MASK
public static boolean orient3d(Vertex3d v0, Vertex3d v1, Vertex3d v2, Vertex3d v3, boolean v3OnMesh0, boolean worldCoords)
true
if v3 is "below", or "inside" the plane formed
by the counterclockwise triangle v0, v1, v2.
The computation first performs a quick numeric calculation to see if the intersection can be determined within regular double precision tolerances. If it cannot, then a more detailed calculation is performed using robust predicates.
If tie-breaking is needed, then this is done using "Simulation of
Simplicity", as described in the class header, by assigning unique
indices to each vertex based on their underlying mesh indices. If the
meshes are different, then if v3OnMesh0
is
true
, we increment the triangle vertex indices by the number
of vertices on the v3 mesh, while if it is false
we
increment the v3 vertex index by the number of vertices on the triangle
mesh.
v0
- first triangle vertexv1
- second triangle vertexv2
- third vertexv3
- vertex to testv3OnMesh0
- used to determine vertex indices for tie-breaking,
as described aboveworldCoords
- if true
, computes the intersection in
world coordinates. Otherwise, mesh local coordinates are used.true
if v3 is inside the trianglepublic static void printIntersectEdgeFace(HalfEdge edge, Face face, boolean edgeOnMesh0)
public static int closestIntersection(Face faceC, HalfEdge edge, Face faceD)
faceC
and faceD
both intersect
edge
, determines which intersection point comes irst.
Specifically, let c and d be the intersection of faceC
and
faceD
with edge
. Then this method returns: 1 if
d is closer to the edge's tail, -1 if c is closer to the edge's tail, and
0 if they are equidistant. This method uses adaptive arithmetic to
determine an exact solution.faceC
- first face to testedge
- edge to tectfaceD
- second face to testpublic static int intersectEdgeTriangle(Point3d ipnt, HalfEdge edge, Face face, double maxlen, boolean edgeOnMesh0, boolean worldCoords)
INTERSECTS
(always set if there is an
intersection), TAIL_OUTSIDE
, TAIL_ON_TRIANGLE
, HEAD_ON_TRIANGLE
, E01_ON_SEGMENT
, E12_ON_SEGMENT
, and
E20_ON_SEGMENT
. If there is an intersection, and
ipnt
is non-null
, then the intersection point
is computed and returned in ipnt
.
If maxlen > 0
, the method first performs a quick numeric
calculation to see if the intersection can be determined within to
tolerance based on maxlen
. If it cannot, then a more
detailed calculation is performed using robust predicates. In order to
work properly, maxlen
must be >=
the length of the
edge and any of the face edges. If maxlen
= 0, then the
robust predicates are called directly.
If tie-breaking is needed, then this is done using "Simulation of
Simplicity", as described in the class header, by assigning unique
indices to each vertex based on their underlying mesh indices. If the
meshes are different, then if edgeOnMesh0
is
true
, we increment the face vertex indices by the number of
vertices on the edge mesh, while if it is false
we increment
the edge vertex indices by the number of vertices on the face mesh.
ipnt
- if non-null
and if the edge and face intersect,
returns the intersection pointedge
- edge to test for intersectionface
- face to test for intersectionmaxlen
- if > 0
, specifies an upper bound for the length of
the edge and face edges which is used to see if the intersection can be
determined using regular double precisionedgeOnMesh0
- used to determine vertex indices for tie-breaking,
as described aboveworldCoords
- if true
, computes the intersection
in world coordinates. Otherwise, mesh local coordinates are used.public static int intersectSegmentTriangle(Point3d ipnt, Point3d pt, Point3d ph, Face face, double maxlen, boolean worldCoords)
INTERSECTS
(always set if there
is an intersection), TAIL_OUTSIDE
, TAIL_ON_TRIANGLE
,
HEAD_ON_TRIANGLE
, E01_ON_SEGMENT
, E12_ON_SEGMENT
, and E20_ON_SEGMENT
. If there is an
intersection, and ipnt
is non-null
, then the
intersection point is computed and returned in ipnt
.
If maxlen > 0
, the method first performs a quick numeric
calculation to see if the intersection can be determined within to
tolerance based on maxlen
. If it cannot, then a more
detailed calculation is performed using robust predicates. In order to
work properly, maxlen
must be >=
the length of the
segment and any of the face edges. If maxlen
= 0, then the
robust predicates are called directly.
If tie-breaking is needed, then this is done using "Simulation of
Simplicity", as described in the class header, by assigning unique
indices to each vertex based on their underlying mesh indices. Vertices
for the line segment end points (pt
and ph
) are
assigned 0 and 1, while for the face vertices indices are assigned using
their underlying mesh vertices plus 2.
For tie-breaking purposes, it is assumed that the line segment is a
stand-alone primitive and independent of the face mesh. If multiple
queries are performed with the same line segment and different faces from
the same mesh, then pt
and ph
should always
refer to the same segment end points.
ipnt
- if non-null
and if the segment and face
intersect, returns the intersection pointpt
- tail point of the line segmentph
- head point of the line segmentface
- face to test for intersectionmaxlen
- if > 0
, specifies an upper bound for the length of
the edge and face edges which is used to see if the intersection can be
determined using regular double precisionworldCoords
- if true
, computes the intersection
in world coordinates. Otherwise, mesh local coordinates are used.public static double orient3dFast(Vector3d p0, Vector3d p1, Vector3d p2, Vector3d p3, double maxlen)
maxlen
may be
used; this should be >=
the maximum length of all edges
associated with the calculation. If maxlen
is given as zero, then
it is computed automatically from the edges of the tetrahedron.p0
- first triangle pointp1
- second triangle pointp2
- third triangle pointp3
- point to testmaxlen
- optional; if > 0
, should be the maximum length
of all edges associated with the calculationpublic static int intersectSegmentTriangleFast(Point3d ipnt, Point3d pt, Point3d ph, Point3d p0, Point3d p1, Point3d p2, double maxlen)
INTERSECTS
(always set if there is an intersection),
and TAIL_OUTSIDE
if the tail of the segment is outside the
triangle (in a counterclockwise sense). If there is an intersection, and
ipnt
is non-null
, then the intersection point
is computed and returned in ipnt
.ipnt
- if non-null
and if the segment and face
intersect, returns the intersection pointpt
- tail point of the line segmentph
- head point of the line segmentp0
- first face vertex pointp1
- second face vertex pointp2
- third face vertex pointmaxlen
- maximum length used to determine if the computation can be
done using double precision arithmetic. Should be >=
the length
of the segment and any of the face edges.public static int intersectSegmentTriangle(Point3d ipnt, int it, Vector3d pt, int ih, Vector3d ph, int i0, Vector3d p0, int i1, Vector3d p1, int i2, Vector3d p2)
INTERSECTS
(always set if there is an
intersection), TAIL_OUTSIDE
, TAIL_ON_TRIANGLE
, HEAD_ON_TRIANGLE
, E01_ON_SEGMENT
, E12_ON_SEGMENT
, and
E20_ON_SEGMENT
. If there is an intersection, and
ipnt
is non-null
, then the intersection point
is computed and returned in ipnt
.
The computation first performs a quick numeric calculation to see if the intersection can be determined within regular double precision tolerances. If it cannot, then a more detailed calculation is performed using robust predicates.
If tie-breaking is needed, then this is done using "Simulation of Simplicity", as described in the class header, using the indices supplied for each vertex. These should be unique to each vertex across all queries.
ipnt
- if non-null
and if the edge and triangle
intersect, returns the intersection pointit
- tie-breaking index for tail segment vertexpt
- position of tail segment vertexih
- tie-breaking index for head segment vertexph
- position of head segment vertexi0
- tie-breaking index for first face vertexp0
- position of first face vertexi1
- tie-breaking index for second face vertexp1
- position of second face vertexi2
- tie-breaking index for third face vertexp2
- position of third face vertex