public class SemiVirtualIncrementalTin extends Object implements IIncrementalTin
The IncrementalTin class uses an implementation of the quad-edge structure popularized by Guibas and Stolfi. While this structure leads to elegant code, the nature of the Java language (and object-oriented coding in general) results in relatively expensive memory requirements, approximately 244 bytes per vertex inserted into the TIN (counting the storage for both edges and vertices). Since it is common for lidar data sets to include multiple-millions of points, that memory use adds up fast.
This implementation reduces memory requirements by representing the edge-link relationships with internal integer arrays and numerical indexing rather than object references. By keeping the edge relationship data in "virtual form", the implementation reduces the memory use for the edges to about 120 bytes per vertex. The implementation is "semi-virtual" in that all data is still kept in core, but the amount of memory is reduced by a virtual representation of the edge structures.
Unfortunately, this reduction comes with a cost. In testing, the virtual implementation requires approximately 60 percent more runtime to process vertices than the direct implementation. Both implementations experience a degradation of throughput when the memory use approaches the maximum allowed by the JVM (specified on the command line using the -Xmx#### option). But since the virtual implementation uses half the memory of the direct implementation, the onset of degraded conditions when working with a fixed memory size can be pushed back considerably using the virtual implementation.
This class also dramatically reduces the number of objects that are used to represent the TIN. The IncrementalTIN class uses about 7.005 objects per vertex (including vertices and edges) while the virtual implementation uses only about 1.012. This reduction can be valuable in reducing the impact of garbage collection when processing large data sets.
The Bower-Watson algorithm for point insertion is discussed in Cheng, Siu-Wing; Dey, T.; Shewchuk, J. (2013) "Delaunay mesh generation", CRC Press, Boca Raton, FL. This is a challenging book that provides an overview of both 2D and solid TIN models. Jonathan Shewchuk is pretty much the expert on Delaunay Triangulations and his writings were a valuable resource in the creation of this class. You can also read Bowyer's and Watson's original papers both of which famously appeared in the same issue of the same journal in 1981. See Bowyer, A. (1981) "Computing Dirichlet tesselations", The Computer Journal" Vol 24, No 2., p. 162-166. and Watson, D. (1981) "Computing the N-dimensional tesselation with application to Voronoi Diagrams", The Computer Journal" Vol 24, No 2., p. 167-172.
The point-removal algorithm is due to Devillers. See Devillers, O. (2002), "On deletion in delaunay triangulations", International Journal of Computational Geometry & Applications 12.3 p. 123-2005.
The QuadEdge concept is based on the structure popularized by Guibas, L. and Stolfi, J. (1985) "Primitives for the manipulation of subdivisions and the computation of Voronoi diagrams" ACM Transactions on Graphics, 4(2), 1985, p. 75-123.
| Constructor and Description |
|---|
SemiVirtualIncrementalTin()
Constructs an incremental TIN using numerical thresholds appropriate
for the default nominal point spacing of 1 unit.
|
SemiVirtualIncrementalTin(double nominalPointSpacing)
Constructs an incremental TIN using numerical thresholds appropriate
for the specified nominal point spacing.
|
| Modifier and Type | Method and Description |
|---|---|
boolean |
add(List<Vertex> list,
IMonitorWithCancellation monitor)
Inserts a list of vertices into the collection of vertices managed by the
TIN.
|
boolean |
add(Vertex v)
Insert a vertex into the collection of vertices managed by
the TIN.
|
void |
addConstraints(List<IConstraint> constraints,
boolean restoreConformity)
Adds constraints to the TIN.
|
void |
clear()
Clears all internal state data of the TIN, preparing any allocated
resources for re-use.
|
TriangleCount |
countTriangles()
Performs a survey of the TIN to gather statistics about the triangle
formed during its construction.
|
void |
dispose()
Nullifies all internal data and references, preparing the
instance for garbage collection.
|
Iterable<IQuadEdge> |
edges()
Provides a convenience implementation of a wrapper class
that can be used in a Java enhanced-loop statement.
|
Rectangle2D |
getBounds()
Gets the bounds of the TIN.
|
IConstraint |
getConstraint(int index)
Gets the constraint associated with the index, or a null if
no such constraint exists.
|
List<IConstraint> |
getConstraints()
Gets a shallow copy of the list of constraints currently
stored in the TIN.
|
Iterator<IQuadEdge> |
getEdgeIterator()
Gets an iterator for stepping through the collection of edges
currently stored in the TIN.
|
List<IQuadEdge> |
getEdges()
Gets a list of edges currently allocated by an instance.
|
IIntegrityCheck |
getIntegrityCheck()
Gets an implementation of the integrity check interface suitable for
the referenced TIN implementation.
|
int |
getMaximumEdgeAllocationIndex()
Gets the maximum index of the currently allocated edges.
|
INeighborEdgeLocator |
getNeighborEdgeLocator()
Gets a new instance of the INeighborEdgeLocator interface.
|
INeighborhoodPointsCollector |
getNeighborhoodPointsCollector()
Gets a new instance of a neighborhood points collector.
|
double |
getNominalPointSpacing()
Gets the nominal point spacing used to determine numerical thresholds
for various proximity and inclusion tests.
|
List<IQuadEdge> |
getPerimeter()
Gets a list of edges currently defining the perimeter of the TIN.
|
SemiVirtualEdge |
getStartingEdge()
Obtains an arbitrary edge to serve as the
start of a search or traversal operation.
|
int |
getSyntheticVertexCount()
Gets the number of synthetic vertices added to the TIN.
|
Thresholds |
getThresholds()
Gets the Thresholds object that is associated with this instance.
|
List<Vertex> |
getVertices()
Gets a list of vertices currently stored in the TIN.
|
boolean |
isBootstrapped()
Indicates whether the instance contains sufficient information
to represent a TIN.
|
boolean |
isPointInsideTin(double x,
double y)
Determines whether the point is inside the convex polygon boundary
of the TIN.
|
void |
preAllocateEdges(int nVertices)
Allocates a number of vertices roughly sufficient to represent a TIN
containing the specified number of vertices.
|
void |
printDiagnostics(PrintStream ps)
Print statistics and diagnostic information collected during the
TIN construction process.
|
void |
printEdges(PrintStream ps)
Provides a diagnostic print out of the edges comprising the TIN.
|
boolean |
remove(Vertex vRemove)
Removes the specified vertex from the TIN.
|
void |
setResolutionRuleForMergedVertices(VertexMergerGroup.ResolutionRule resolutionRule)
Specifies a rule for interpreting the Z value of a group of vertices that
were merged due to being coincident, or nearly coincident.
|
public SemiVirtualIncrementalTin()
public SemiVirtualIncrementalTin(double nominalPointSpacing)
Lidar applications sometimes refer to the point-spacing concept as "nominal pulse spacing", a term that reflects the origin of the data in a laser-based measuring system.
nominalPointSpacing - the nominal distance between points.public boolean add(Vertex v)
add in interface IIncrementalTinv - a valid vertexpublic boolean add(List<Vertex> list, IMonitorWithCancellation monitor)
In the bootstrap phase, three points are chosen at random from the vertex list to create the initial triangle for insertion. The initialization will make a small number of selection attempts and select the triangle with the largest number. In the event that this process does not find three points that are not a suitable choice (as when they are collinear or nearly collinear), the process will be repeated until a valid initial triangle is selected.
Thus, there is a small performance advantage in supplying the vertices using a list that can be accessed efficiently in a random order (see the discussion of the Java API for the List and java.util.RandomAccess interfaces). Once the initial triangle is established, the list will be traversed sequentially to build the TIN and random access considerations will no longer apply.
add in interface IIncrementalTinlist - a valid list of vertices to be added to the TIN.monitor - an optional instance of a monitoring implementation;
null if not usedpublic void preAllocateEdges(int nVertices)
preAllocateEdges in interface IIncrementalTinnVertices - the number of vertices expected to be added to the TIN.public Rectangle2D getBounds()
getBounds in interface IIncrementalTinpublic void printEdges(PrintStream ps)
printEdges in interface IIncrementalTinps - A valid print stream.public TriangleCount countTriangles()
countTriangles in interface IIncrementalTinpublic List<IQuadEdge> getPerimeter()
Warning: For efficiency purposes, the edges return by this routine are the same objects as those currently being used in the instance. Any modification of the edge objects will damage the TIN. Therefore, applications must not modify the edges returned by this method.
getPerimeter in interface IIncrementalTinpublic void printDiagnostics(PrintStream ps)
printDiagnostics in interface IIncrementalTinps - A valid instance of a PrintStream to receive the output.public List<IQuadEdge> getEdges()
Warning: For efficiency purposes, the edges return by this routine are the same objects as those currently being used in the instance. Any modification of the edge objects will damage the TIN. Therefore, applications must not modify the edges returned by this method.
getEdges in interface IIncrementalTinpublic Iterator<IQuadEdge> getEdgeIterator()
IIncrementalTinWarning: For efficiency purposes, the edges returned by this routine are the same objects as those currently being used in the instance. Any modification of the edge objects will damage the TIN. Therefore, applications must not modify the edges returned by this method. Caution: For reasons of efficiency, the iterator does not offer any protection against concurrent modification. Therefore applications using this iterator must never modify the TIN during iteration.
getEdgeIterator in interface IIncrementalTinpublic Iterable<IQuadEdge> edges()
IIncrementalTin
IIncremntal tin = // some implementation
for(IQuadEdge e: tin.edges(){
// some processing logic
}
Please see the API documentation for getEdgeIterator() for cautions regarding the use of this method.
edges in interface IIncrementalTinpublic int getMaximumEdgeAllocationIndex()
IIncrementalTinInternally, Tinfour uses edge index values to manage edges in memory. The while there can be small gaps in the indexing sequence, this method provides a way of obtaining the absolute maximum value of currently allocated edges.
getMaximumEdgeAllocationIndex in interface IIncrementalTinpublic double getNominalPointSpacing()
Lidar applications sometimes refer to the point-spacing concept as "nominal pulse spacing", a term that reflects the origin of the data in a laser-based measuring system.
getNominalPointSpacing in interface IIncrementalTinpublic Thresholds getThresholds()
IIncrementalTingetThresholds in interface IIncrementalTinpublic void dispose()
IIncrementalTindispose in interface IIncrementalTinpublic void clear()
IIncrementalTinclear in interface IIncrementalTinpublic boolean isBootstrapped()
isBootstrapped in interface IIncrementalTinpublic boolean remove(Vertex vRemove)
At this time, this method does not handle the case where all vertices are removed from the TIN.
remove in interface IIncrementalTinvRemove - the vertex to be removedpublic SemiVirtualEdge getStartingEdge()
public void setResolutionRuleForMergedVertices(VertexMergerGroup.ResolutionRule resolutionRule)
setResolutionRuleForMergedVertices in interface IIncrementalTinresolutionRule - The rule to be used for interpreting merged vertices.public List<Vertex> getVertices()
getVertices in interface IIncrementalTinpublic INeighborEdgeLocator getNeighborEdgeLocator()
IIncrementalTingetNeighborEdgeLocator in interface IIncrementalTinpublic INeighborhoodPointsCollector getNeighborhoodPointsCollector()
IIncrementalTingetNeighborhoodPointsCollector in interface IIncrementalTinpublic IIntegrityCheck getIntegrityCheck()
IIncrementalTingetIntegrityCheck in interface IIncrementalTinpublic boolean isPointInsideTin(double x,
double y)
IIncrementalTinisPointInsideTin in interface IIncrementalTinx - The x coordinate of interesty - THe y coordinate of interestpublic void addConstraints(List<IConstraint> constraints, boolean restoreConformity)
IIncrementalTinUsing Constraints
There are a number of important restrictions to the use of constraints. Constraints must only be added to the TIN once, after all other vertices have already been added. Furthermore, the addConstraint method can only be called once. Logic is implemented as a safety measure to ensure that these restrictions are not accidentally violated.
There are also important restrictions on the geometry of constraints. Most importantly, constraints must never intersect each other except at the endpoints of the segments that define them (i.e. segments in constraints must never cross each other). Due to the high cost of processing required to check that this restriction is observed, it is not directly enforced by the Tinfour implementations.
Restoring Conformity
When constraints are added to a Delaunay triangulation, they often violate the Delaunay criterion and result in a non-conforming mesh. The addConstraint method can optionally restore conformity by inserting synthetic points into the the constraint edges. The cost of this process is additional processing time and an increase in the number of points in the TIN.
When points are synthesized, it is necessary to interpolate a value for the z-coordinate. At this time, the specific interpolation process is undefined. The current Tinfour implementations use linear interpolation between constraint points. While no viable alternative approach is currently under consideration, the choice of interpolation method is subject to change in the future.
addConstraints in interface IIncrementalTinconstraints - a valid, potentially empty list.restoreConformity - restores conformitypublic List<IConstraint> getConstraints()
IIncrementalTingetConstraints in interface IIncrementalTinpublic IConstraint getConstraint(int index)
IIncrementalTingetConstraint in interface IIncrementalTinindex - an arbitrary integer indexpublic int getSyntheticVertexCount()
IIncrementalTingetSyntheticVertexCount in interface IIncrementalTinCopyright © 2019. All rights reserved.