Class IncrementalTin
- java.lang.Object
-
- org.tinfour.standard.IncrementalTin
-
- All Implemented Interfaces:
IIncrementalTin
public class IncrementalTin extends Object implements IIncrementalTin
Provides methods and data elements for building and maintaining a Triangulated Irregular Network (TIN) that is optimal with regard to the Delaunay criterion.The Delaunay Triangulation has several desirable properties and is well documented on the Internet. The TIN produced by this class is meets the Delaunay criterion except in cases where round-off errors due to the limits of floating point calculations result in small deviations from the optimum.
There are three major classes of algorithms for creating a Delaunay Triangulation: sweep-line algorithms, divide-and-conquer, and incremental construction. In the incremental algorithm used for this implementation, vertices are added to the TIN one-at-a time. If a vertex lies inside the convex hull of an existing TIN, it is inserted. If the vertex lies to the exterior, the bounds of the TIN is extended to include it. Delaunay optimality is maintained at each step.
Memory use and performance
This class was designed to handle cases where the input set includes a large number of vertices. In particular, terrain elevation data sets collected using laser devices (lidar) that typically include multiple millions of data points. With such large input sets, performance and memory-management are critical issues.
Naturally, memory use and performance varies by hardware, operating system, and Java Virtual Machine (HVM). In 2015, testing lidar data under Windows 7 on a computer with a 2.9 GHz Intel i7 processor, 8 gigabytes installed memory, 512 kilobytes of L2 cache memory, and Hotspot JVM, this class routinely delivered a processing rate of 1.1 million vertices per second. Time-complexity for samples smaller than 10 million was nearly linear. Memory use averaged 244 bytes per vertex.
Memory Use
About a third of the memory use by this class when running under Hotspot is due to Java object-related overhead rather than actual data. Software environments such as Java and C# provide automatic garbage collection and memory management. Doing so adds a small amount of memory overhead to each object created. Because the data-size of the objects used to build a TIN (vertices and edges) is also small, this overhead is significant. In a sufficiently large Delaunay Triangulation, the number of edges approaches three per vertex. This implementation uses one object per vertex and two per edge. Although the memory overhead for Java varies for different operating systems and Java Virtual Machines (JVMs), the Hotspot JVM for Windows uses 12 bytes per object. Thus for each vertex, it requires (1+3*2)x12 = 84 bytes of overhead.
Performance
Managing the performance cost of object construction Testing indicates that the most time-consuming part of the TIN construction operation is the construction of Java objects. As noted above, this class requires 6 edge-related objects per vertex. Although this overhead is inescapable when processing a single data set, this class does permit a TIN instance to be reused over-and-over again when processing multiple data sets. A call to the clear() method resets the TIN to an empty state, but preserves the edges already allocated so that they may be reused for the next data set. By doing so, the cost of the up-front construction of edge objects can be amortized over the entire data set, this reducing the processing time for a group of multiple input sets. Applications that do so should be able to improve on the run-time performance values quoted above.
Input geometry The worst case vertex geometry for TIN construction is a data set in which a large number of points are collinear and do not form triangles readily. Unfortunately, that is exactly the geometry of one of the most obvious classes of input: the regular grid. This class supports two different add() methods for adding vertices to the TIN. When dealing with a regular grid or similar geometries, it is advantageous to use the add() method that takes a list as an input rather than the one that accepts single vertices. Having a list of vertices gives this class more flexibility in constructing the TIN.
The process of inserting a vertex within a TIN requires fewer operations than extending the convex hull of that TIN. If a list of vertices is supplied to the initial add routine, the bootstrap process attempts pick the largest starting triangle that it can without excessive processing. Doing so improves performance and stability of the build process.
Storing the same vertex more than once The add() methods detect when the same vertex object is inserted more than once and ignore redundant inputs. For distinct vertex objects at the same or nearly same coordinates, this class maintains a "merged group" of vertices. Rules for disambiguating the values of a merged group my be specified using a call to the setResolutionRuleForMergedVertices() method.
Sequential spatial autocorrelation
Inserting a vertex into a TIN depends on identifying the triangle that contains an insertion vertex (if any). This class uses the Stochastic Lawson's Walk algorithm (SLW) that is most efficient when subsequent vertices tend to be spaced close together. Fortunately, this condition is met by many real-world data collection systems. For example, airborne-lidar systems tend to produce a sequence of samples that are closely spaced in terms of horizontal coordinates because they collect measurements using scanning lasers and storing them in the order they are taken.
Other data sources may not be compliant. Randomly generated data points, in particular, may be problematic. For such data, there may be a performance benefit in using the HilbertSort class to pre-order points before insertion so that sequential spatial autocorrelation is provided by the input data.
One way to judge the degree of sequential spacial autocorrelation in a set of vertices is to view the output of the printDiagnostics() method after building a TIN. Under the entry for the SLW statistics, the "average steps to completion" indicates how many comparisons were needed to locate vertices. If this number is larger than 7 or 8, it may be useful to try using the HilbertSort and see if it improves processing times.
Cleaning up when finished
Because of the complex relationships between objects in a TIN, Java garbage collection may require an above-average number of passes to clean up memory when an instance of this class goes out-of-scope. The dispose() method can be used to expedite garbage collection. Once the dispose() method is called on a TIN, it cannot be reused. Do not confuse dispose() with clear().
Running nude
Because of the unusually demanding performance considerations related to the use of this class, object instances are frequently reused and, thus, are subject to change. Consequently, this implementation provides little protection against improper method calls by applications accessing its data. In particular, applications must never modify an object (such as an edge) obtained from instances of this class. Furthermore, they must assume that any addition or removal of vertices to the TIN may change the internal state of any objects previously obtained.
To better understand the re-use strategy, consider that each time a vertex is added to or removed from a TIN, the set of edges that link vertices changes. Some edges may be removed, others added. Testing with lidar data sets indicates that the present implementation re-uses each edge in the collection a average about 7.5 times while the TIN is being constructed. If the application were to treat edges as immutable, it would have to construct new objects each time a vertex was inserted and many of those edge objects would have to be discarded (and garbage collected) before the entire vertex set was processed. Doing so would substantially degrade the performance of this class.
Multi-Threading and Concurrency The process of creating a Delaunay Triangulation (TIN) using an incremental-insertion technique is inherently serial. Therefore, application code that creates a TIN should not attempt to access the "add" methods for this class in parallel threads. However, this API is designed so that once a TIN is complete, it can be accessed by multiple threads on a read-only basis. Multi-threaded access is particularly useful when performing surface-interpolation operations to construct raster (grid) representations of data.
Methods and References
A good review of point location using a stochastic Lawson's walk is provided by Soukal, R.; Málková, Kolingerová (2012) "Walking algorithms for point location in TIN models", Computational Geoscience 16:853-869.
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.
The logic for adding constraints to the TIN was adapted from Sloan, S.W. (1993) "A Fast Algorithm for Generating Constrained Delaunay Triangulations", Computers & Structures Vol 47. No 3, 1993, p. 441-450.
-
-
Constructor Summary
Constructors Constructor Description IncrementalTin()Constructs an incremental TIN using numerical thresholds appropriate for the default nominal point spacing of 1 unit.IncrementalTin(double estimatedPointSpacing)Constructs an incremental TIN using numerical thresholds appropriate for the specified nominal point spacing.
-
Method Summary
All Methods Instance Methods Concrete Methods Modifier and Type Method Description booleanadd(List<Vertex> list, IMonitorWithCancellation monitor)Inserts a list of vertices into the collection of vertices managed by the TIN.booleanadd(Vertex v)Insert a vertex into the collection of vertices managed by the TIN.voidaddConstraints(List<IConstraint> constraints, boolean restoreConformity)Adds constraints to the TIN.voidclear()Clears all internal state data of the TIN, preparing any allocated resources for re-use.TriangleCountcountTriangles()Performs a survey of the TIN to gather statistics about the triangle formed during its construction.voiddispose()Nullifies all internal data and references, preparing the instance for garbage collection.Iterable<IQuadEdge>edges()Provides a convenience implementation that can be used with a Java enhanced-loop statement to access the set of edges that form the structure of the incremental TIN.Iterable<IQuadEdge>edgesAndDuals()Provides a convenience implementation that can be used with a Java enhanced-loop statement to access both sides of each edge in the incremental TIN.Rectangle2DgetBounds()Gets the bounds of the TIN.IConstraintgetConstraint(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.IIntegrityCheckgetIntegrityCheck()Gets an implementation of the integrity check interface suitable for the referenced TIN implementation.IConstraintgetLinearConstraint(IQuadEdge edge)Gets the linear constraint associated with the edge, if any.intgetMaximumEdgeAllocationIndex()Gets the maximum index of the currently allocated edges.IIncrementalTinNavigatorgetNavigator()Gets a new instance of the IIncrementalTinNavigator interface.INeighborEdgeLocatorgetNeighborEdgeLocator()Gets a new instance of a neighbor edge locator implementation.INeighborhoodPointsCollectorgetNeighborhoodPointsCollector()Gets a new instance of a neighborhood points collector.doublegetNominalPointSpacing()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.IConstraintgetRegionConstraint(IQuadEdge edge)Gets the region constraint associated with the edge, if any.QuadEdgegetStartingEdge()Obtains an arbitrary edge to serve as the start of a search or traversal operation.intgetSyntheticVertexCount()Gets the number of synthetic vertices added to the TIN.ThresholdsgetThresholds()Gets the Thresholds object that is associated with this instance.List<Vertex>getVertices()Gets a list of vertices currently stored in the TIN.booleanisBootstrapped()Indicates whether the instance contains sufficient information to represent a TIN.booleanisConformant()Indicates whether the triangulated mesh conforms to the Delaunay criterion.voidpreAllocateEdges(int nVertices)Allocates a number of vertices roughly sufficient to represent a TIN containing the specified number of vertices.voidprintDiagnostics(PrintStream ps)Print statistics and diagnostic information collected during the TIN construction process.voidprintEdges(PrintStream ps)Provides a diagnostic print out of the edges comprising the TIN.booleanremove(Vertex vRemove)Removes the specified vertex from the TIN.voidsetResolutionRuleForMergedVertices(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.voidsetVertexAdjustmentEnabled(boolean status)Sets an option allowing or disabling Tinfour's ability to make small adjustments in the position of a vertex when constructing a Delaunay triangulation.VertexsplitEdge(IQuadEdge eInput, double t, double zSplit)Splits the edge at parameter t measured from A toward B. t is clamped to (ε, 1-ε) to avoid zero-length subedges.VertexsplitEdge(IQuadEdge eInput, double t, double zSplit, boolean restoreConformity)Splits an existing edge into two at parametric position t measured from the edge’s origin (A) toward its destination (B).Iterable<SimpleTriangle>triangles()Provides a convenience implementation that can be used with a Java enhanced-loop statement to access the set of SimpleTriangles implicit in the structure of the incremental TIN.Iterable<Vertex>vertices()Provides a convenience implementation that can be used with a Java enhanced-loop statement to access the set of vertices stored in an incremental TIN.-
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
-
Methods inherited from interface org.tinfour.common.IIncrementalTin
splitEdge
-
-
-
-
Constructor Detail
-
IncrementalTin
public IncrementalTin()
Constructs an incremental TIN using numerical thresholds appropriate for the default nominal point spacing of 1 unit.
-
IncrementalTin
public IncrementalTin(double estimatedPointSpacing)
Constructs an incremental TIN using numerical thresholds appropriate for the specified nominal point spacing. This value is an estimated spacing used for determining numerical thresholds for various proximity and inclusion tests. For best results, it should be within one to two orders of magnitude of the actual value for the samples. In practice, this value is usually chosen to be close to the mean point spacing for a sample. But for samples with varying density, a mean value from the set of smaller point spacings may be used.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.
- Parameters:
estimatedPointSpacing- the estimated nominal distance between points.
-
-
Method Detail
-
add
public boolean add(Vertex v)
Insert a vertex into the collection of vertices managed by the TIN. If the TIN is not yet bootstrapped, the vertex will be retained in a simple list until enough vertices are received in order to bootstrap the TIN.- Specified by:
addin interfaceIIncrementalTin- Parameters:
v- a valid vertex- Returns:
- true if the TIN is bootstrapped; otherwise false
-
add
public boolean add(List<Vertex> list, IMonitorWithCancellation monitor)
Inserts a list of vertices into the collection of vertices managed by the TIN. If the TIN is not yet bootstrapped, the vertices will be retained in a simple list until enough vertices are received in order to bootstrap the TIN.Performance Consideration Related to List
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.
Performance Consideration Related to Location of Vertices The performance of the insertion process is sensitive to the relative location of vertices. An input data set based on purely random vertex positions represents one of the worst-case input sets in terms of processing time.
Ordinarily, the most computationally expensive operation for inserting a vertex into the Delaunay triangulation is locating the triangle that contains its coordinates. But Tinfour implements logic to expedite this search operation by taking advantage of a characteristic that occurs in many data sets: the location of one vertex in a sequence is usually close to the location of the vertex that preceded it. By starting each search at the position in the triangulation where a vertex was most recently inserted, the time-to-search can be reduced dramatically. Unfortunately, in vertices generated by a random process, this assumption of sequential proximity (i.e. "spatial autocorrelation") is not true.
To assist in the case of random or poorly correlated vertex geometries, application can take advantage of the HilbertSort class which is supplied as part of the Core Tinfour module. In the example shown below, the use of the HilbertSort yields a factor of 100 improvement in the time to perform the .add() method.
int nVertices = 1_000_000; List<Vertex> vertices = new ArrayList<>(); for (int i = 0; i < nVertices; i++) { double x = Math.random() * 1000; double y = Math.random() * 1000; vertices.add(new Vertex(x, y, 0)); } HilbertSort hs = new HilbertSort(); hs.sort(vertices); IIncrementalTin tin = new IncrementalTin(); tin.add(vertices, null);- Specified by:
addin interfaceIIncrementalTin- Parameters:
list- a valid list of vertices to be added to the TIN.monitor- an optional instance of a monitoring implementation; null if not used- Returns:
- true if the TIN is bootstrapped; otherwise false
-
preAllocateEdges
public void preAllocateEdges(int nVertices)
Allocates a number of vertices roughly sufficient to represent a TIN containing the specified number of vertices. This method serves as a diagnostic tool, allowing a test-application to separate the portion of processing time consumed by Java object construction from that spent processing the vertex data.- Specified by:
preAllocateEdgesin interfaceIIncrementalTin- Parameters:
nVertices- the number of vertices expected to be added to the TIN.
-
getBounds
public Rectangle2D getBounds()
Gets the bounds of the TIN. If the TIN is not initialized (bootstrapped), this method returns a null.- Specified by:
getBoundsin interfaceIIncrementalTin- Returns:
- if available, a valid rectangle giving the bounds of the TIN; otherwise, a null
-
printEdges
public void printEdges(PrintStream ps)
Provides a diagnostic print out of the edges comprising the TIN.- Specified by:
printEdgesin interfaceIIncrementalTin- Parameters:
ps- A valid print stream.
-
countTriangles
public TriangleCount countTriangles()
Performs a survey of the TIN to gather statistics about the triangle formed during its construction.- Specified by:
countTrianglesin interfaceIIncrementalTin- Returns:
- A valid instance of the TriangleCount class.
-
getPerimeter
public List<IQuadEdge> getPerimeter()
Gets a list of edges currently defining the perimeter of the TIN. The list may be empty if the TIN is not initialized (bootstrapped).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.
- Specified by:
getPerimeterin interfaceIIncrementalTin- Returns:
- a valid, potentially empty list.
-
printDiagnostics
public void printDiagnostics(PrintStream ps)
Print statistics and diagnostic information collected during the TIN construction process. This information will be removed and reset by a call to the clear() method.- Specified by:
printDiagnosticsin interfaceIIncrementalTin- Parameters:
ps- A valid instance of a PrintStream to receive the output.
-
getEdges
public List<IQuadEdge> getEdges()
Gets a list of edges currently allocated by an instance. The list may be empty if the TIN is not initialized (bootstrapped).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.
- Specified by:
getEdgesin interfaceIIncrementalTin- Returns:
- a valid, potentially empty list.
-
getEdgeIterator
public Iterator<IQuadEdge> getEdgeIterator()
Description copied from interface:IIncrementalTinGets an iterator for stepping through the collection of edges currently stored in the TIN.Note that this loop produces only the "base side" of each edge. To access the counterpart (the side of the edge in the other direction), an application needs to access its dual using the edge's getDual() method.
Warning: 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.
- Specified by:
getEdgeIteratorin interfaceIIncrementalTin- Returns:
- a valid iterator.
-
edges
public Iterable<IQuadEdge> edges()
Description copied from interface:IIncrementalTinProvides a convenience implementation that can be used with a Java enhanced-loop statement to access the set of edges that form the structure of the incremental TIN. The edges produced by this Iterator are filtered so that the fictitious edges (ghost edges) are not produced by the iteration.For example, this method could be used in the following manner:
IIncremntal tin = // some implementation for(IQuadEdge e: tin.edges(){ // some processing logic }Note that this loop produces only the "base side" of each edge. To access the counterpart (the side of the edge in the other direction), an application needs to access its dual using the edge's getDual() method.
Please see the API documentation for getEdgeIterator() for cautions regarding the use of this method.
- Specified by:
edgesin interfaceIIncrementalTin- Returns:
- a valid instance.
-
edgesAndDuals
public Iterable<IQuadEdge> edgesAndDuals()
Description copied from interface:IIncrementalTinProvides a convenience implementation that can be used with a Java enhanced-loop statement to access both sides of each edge in the incremental TIN. This method is similar to theedges()iterator except that it produces both sides of each edge. The edges produced by this Iterator are filtered so that the fictitious edges (ghost edges) are not produced by the iteration.For example, this method could be used in the following manner:
IIncremntal tin = // some implementation for(IQuadEdge e: tin.halfEdges(){ // some processing logic }Note that this loop produces both the "base side" and the "dual" of each edge.
Please see the API documentation for getEdgeIterator() for cautions regarding the use of this method.
- Specified by:
edgesAndDualsin interfaceIIncrementalTin- Returns:
- a valid instance.
-
getMaximumEdgeAllocationIndex
public int getMaximumEdgeAllocationIndex()
Description copied from interface:IIncrementalTinGets the maximum index of the currently allocated edges. This method can be used in support of applications that require the need to survey the edge set and maintain a parallel array or collection instance that tracks information about the edges. In such cases, the maximum edge index provides a way of knowing how large to size the array or collection.Internally, 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.
- Specified by:
getMaximumEdgeAllocationIndexin interfaceIIncrementalTin- Returns:
- a positive value or zero if the TIN is not bootstrapped.
-
getNominalPointSpacing
public double getNominalPointSpacing()
Gets the nominal point spacing used to determine numerical thresholds for various proximity and inclusion tests. For best results, it should be within one to two orders of magnitude of the actual value for the samples. In practice, this value is usually chosen to be close to the mean point spacing for a sample. But for samples with varying density, a mean value from the set of smaller point spacings may be used.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.
- Specified by:
getNominalPointSpacingin interfaceIIncrementalTin- Returns:
- a positive floating-point value greater than zero.
-
getThresholds
public Thresholds getThresholds()
Description copied from interface:IIncrementalTinGets the Thresholds object that is associated with this instance. Because all elements in Thresholds are declared final (immutable), it can be shared safely between multiple threads or other classes.- Specified by:
getThresholdsin interfaceIIncrementalTin- Returns:
- a valid instance
-
dispose
public void dispose()
Description copied from interface:IIncrementalTinNullifies all internal data and references, preparing the instance for garbage collection. Because of the complex relationships between objects in a TIN, Java garbage collection may require an above average number of passes to clean up memory when an instance of this class goes out-of-scope. The dispose() method can be used to expedite garbage collection. Do not confuse the dispose() method with the clear() method. The clear() method prepares a TIN instance for reuse. The dispose() method prepares a TIN instance for garbage collection. Once the dispose() method is called on a TIN, it cannot be reused.- Specified by:
disposein interfaceIIncrementalTin
-
clear
public void clear()
Description copied from interface:IIncrementalTinClears all internal state data of the TIN, preparing any allocated resources for re-use. When processing multiple sets of input data the clear() method has an advantage in that it can be used to reduce the overhead related to multiple edge object implementation.- Specified by:
clearin interfaceIIncrementalTin
-
isBootstrapped
public boolean isBootstrapped()
Indicates whether the instance contains sufficient information to represent a TIN. Bootstrapping requires the input of at least three distinct, non-collinear vertices. If the TIN is not bootstrapped methods that access its content may return empty or null results.- Specified by:
isBootstrappedin interfaceIIncrementalTin- Returns:
- true if the TIN is successfully initialized; otherwise, false.
-
remove
public boolean remove(Vertex vRemove)
Removes the specified vertex from the TIN. If the vertex is part of a merged-group, it is removed from the group by the structure of the TIN is unchanged.At this time, this method does not handle the case where all vertices are removed from the TIN.
- Specified by:
removein interfaceIIncrementalTin- Parameters:
vRemove- the vertex to be removed- Returns:
- true if the vertex was found in the TIN and removed.
-
getStartingEdge
public QuadEdge getStartingEdge()
Obtains an arbitrary edge to serve as the start of a search or traversal operation.- Returns:
- An ordinary (non-ghost) edge.
-
getNeighborEdgeLocator
public INeighborEdgeLocator getNeighborEdgeLocator()
Gets a new instance of a neighbor edge locator implementation. Instances observe the contract of the IProcessUsingTin interface in that they access the TIN on a readonly basis and may be used in parallel threads provided that the TIN is not modified.- Specified by:
getNeighborEdgeLocatorin interfaceIIncrementalTin- Returns:
- an edge locator tied to this TIN.
-
getNavigator
public IIncrementalTinNavigator getNavigator()
Description copied from interface:IIncrementalTinGets a new instance of the IIncrementalTinNavigator interface. The navigator implementations provide utilities to perform geometry-based queries on the TIN. These queries include tests to see if a coordinate point lies within the TIN, tests to get neighboring edges, etc.Instances observe the contract of the IProcessUsingTin interface in that they access the TIN on a read-only basis and may be used in parallel threads provided that the TIN is not modified.
- Specified by:
getNavigatorin interfaceIIncrementalTin- Returns:
- an valid navigator instance or a null if the TIN is not properly bootstrapped.
-
getNeighborhoodPointsCollector
public INeighborhoodPointsCollector getNeighborhoodPointsCollector()
Gets a new instance of a neighborhood points collector. Instances observe the contract of the IProcessUsingTin interface in that they access the TIN on a readonly basis and may be used in parallel threads provided that the TIN is not modified.- Specified by:
getNeighborhoodPointsCollectorin interfaceIIncrementalTin- Returns:
- an points collector tied to this TIN.
-
getIntegrityCheck
public IIntegrityCheck getIntegrityCheck()
Description copied from interface:IIncrementalTinGets an implementation of the integrity check interface suitable for the referenced TIN implementation.- Specified by:
getIntegrityCheckin interfaceIIncrementalTin- Returns:
- a valid integrity check implementation.
-
setResolutionRuleForMergedVertices
public 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.- Specified by:
setResolutionRuleForMergedVerticesin interfaceIIncrementalTin- Parameters:
resolutionRule- The rule to be used for interpreting merged vertices.
-
getVertices
public List<Vertex> getVertices()
Gets a list of vertices currently stored in the TIN. This list of objects is not necessarily equivalent to the set of objects that were input because some vertices may have been incorporated into one or more vertex-merger groups. Note that the list of vertices is not sorted and will usually not be returned in the same order as the original input set.- Specified by:
getVerticesin interfaceIIncrementalTin- Returns:
- a valid list of vertices, potentially empty if the TIN has not been initialized.
-
addConstraints
public void addConstraints(List<IConstraint> constraints, boolean restoreConformity)
Description copied from interface:IIncrementalTinAdds constraints to the TIN.Using Constraints
There are a number of important restrictions to the use of constraints. Constraints must only be added to the TIN once, preferably after non-constraint 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.
Finally, there is a limit to the number of constraint objects that can be added to the incremental TIN. At this time, the total number of constraint objects is limited to 8190 (2^13-2). A constraint object may contain multiple edges, so the total number of edges is only limited by available memory and processing time. The reason for this restriction is that Tinfour attempts to conserve the amount of memory dedicated to edges and allows only a single 32-bit integer to store constraint references and state data.
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.
- Specified by:
addConstraintsin interfaceIIncrementalTin- Parameters:
constraints- a valid, potentially empty list.restoreConformity- restores conformity
-
getConstraints
public List<IConstraint> getConstraints()
Description copied from interface:IIncrementalTinGets a shallow copy of the list of constraints currently stored in the TIN.- Specified by:
getConstraintsin interfaceIIncrementalTin- Returns:
- a valid, potentially empty list of constraint instances.
-
getConstraint
public IConstraint getConstraint(int index)
Description copied from interface:IIncrementalTinGets the constraint associated with the index, or a null if no such constraint exists. Note that there is no out-of-bounds range for the input index. An invalid index simply yields a null reference.- Specified by:
getConstraintin interfaceIIncrementalTin- Parameters:
index- an arbitrary integer index- Returns:
- if found, a valid constraint; otherwise a null.
-
getRegionConstraint
public IConstraint getRegionConstraint(IQuadEdge edge)
Description copied from interface:IIncrementalTinGets the region constraint associated with the edge, if any. If the edge is on the border of a region, this method will return the constraint to its immediate left side.- Specified by:
getRegionConstraintin interfaceIIncrementalTin- Parameters:
edge- a valid edge instance.- Returns:
- if a region constraint is associated with the edge, a valid instance; otherwise, a null.
-
getLinearConstraint
public IConstraint getLinearConstraint(IQuadEdge edge)
Description copied from interface:IIncrementalTinGets the linear constraint associated with the edge, if any. In some cases, a linear constraint may lie within a constrained region, but it will not lie on the border of a constrained region.- Specified by:
getLinearConstraintin interfaceIIncrementalTin- Parameters:
edge- a valid edge instance.- Returns:
- if a linear constraint is associated with the edge, a valid instance; otherwise, a null.
-
getSyntheticVertexCount
public int getSyntheticVertexCount()
Description copied from interface:IIncrementalTinGets the number of synthetic vertices added to the TIN. Vertices can be synthesized as part of the Delaunay restoration process when adding constraints. Future implementations of additional functions (such as Delaunay refinement) may also add synthetic points.- Specified by:
getSyntheticVertexCountin interfaceIIncrementalTin- Returns:
- a positive integer, potentially zero.
-
splitEdge
public Vertex splitEdge(IQuadEdge eInput, double t, double zSplit, boolean restoreConformity)
Description copied from interface:IIncrementalTinSplits an existing edge into two at parametric position t measured from the edge’s origin (A) toward its destination (B).The inserted vertex inherits the constraint status of the edge; if the input edge is constrained, the new vertex is marked as a constraint vertex and the edge is subdivided into two constrained edges.
Implementations may clamp t to an open interval (ε, 1−ε) to avoid creation of zero-length subedges. The z coordinate of the inserted vertex is taken from the supplied
zSplit. If an implementation does not support restoring Delaunay conformance at split time, therestoreConformityflag may be ignored.- Specified by:
splitEdgein interfaceIIncrementalTin- Parameters:
eInput- a valid edge belonging to this TIN instancet- the split parameter in [0,1], measured from A toward B; values at or near the endpoints may be clamped by the implementationzSplit- the z coordinate for the new vertexrestoreConformity- obsolete, no longer used- Returns:
- the insertion vertex (never null if the split succeeds)
-
splitEdge
public Vertex splitEdge(IQuadEdge eInput, double t, double zSplit)
Splits the edge at parameter t measured from A toward B. t is clamped to (ε, 1-ε) to avoid zero-length subedges.- Specified by:
splitEdgein interfaceIIncrementalTin- Parameters:
eInput- a valid edge belonging to this TIN instancet- the split parameter in [0,1], measured from A toward B; values at or near the endpoints may be clamped by the implementationzSplit- the z coordinate for the new vertex- Returns:
- the insertion vertex (never null if the split succeeds)
-
triangles
public Iterable<SimpleTriangle> triangles()
Description copied from interface:IIncrementalTinProvides a convenience implementation that can be used with a Java enhanced-loop statement to access the set of SimpleTriangles implicit in the structure of the incremental TIN. This iterable will produce all SimpleTriangles in the collection with no repeats or omissions.For example, this method could be used in the following manner:
IIncremntal tin = // a valid instance for(SimpleTriangle t: tin.triangles(){ // some processing logic }Please see the API documentation for SimpleTriangleIterator for cautions regarding the use of this method.
- Specified by:
trianglesin interfaceIIncrementalTin- Returns:
- a valid instance.
-
vertices
public Iterable<Vertex> vertices()
Description copied from interface:IIncrementalTinProvides a convenience implementation that can be used with a Java enhanced-loop statement to access the set of vertices stored in an incremental TIN. This iterable will produce all vertices in the collection with no repeats or omissions.For example, this method could be used in the following manner:
IIncremntal tin = // a valid instance for(Vertex v: tin.verticess(){ // some processing logic }Please see the API documentation for VertexIterator for cautions regarding the use of this method.
- Specified by:
verticesin interfaceIIncrementalTin- Returns:
- a valid instance.
-
isConformant
public boolean isConformant()
Indicates whether the triangulated mesh conforms to the Delaunay criterion. This value is set to true when the triangulated irregular network (TIN) is successfully bootstrapped. This value is set to false when constraints are added to the mesh without the restore-conformity option being enabled.- Specified by:
isConformantin interfaceIIncrementalTin- Returns:
- true if the TIN conforms to the Delaunay criterion; otherwise, false.
-
setVertexAdjustmentEnabled
public void setVertexAdjustmentEnabled(boolean status)
Description copied from interface:IIncrementalTinSets an option allowing or disabling Tinfour's ability to make small adjustments in the position of a vertex when constructing a Delaunay triangulation. This option allows the triangulation to avoid cases where the input vertex set would result in undesirable characteristics. When a vertex position is adjusted, it is wrapped in an instance of the VertexAdjustment class which is stored in the triangulation.By default, vertex adjustments are enabled.
At this time, Tinfour only implements one special case where an adjustment is constructed. When a vertex is inserted very close to a constrained segment, its position can be moved onto to the segment. This adjustment avoids a case where restoring Delaunay conformity would require the creation of a large number of densely spaced vertices in the neighborhood of the insertion.
- Specified by:
setVertexAdjustmentEnabledin interfaceIIncrementalTin- Parameters:
status- true if adjustments are enabled; otherwise false.
-
-