diff --git a/dist/Tinfour-1.0.jar b/dist/Tinfour-1.0.jar
index c8577b79..7a2d3188 100644
Binary files a/dist/Tinfour-1.0.jar and b/dist/Tinfour-1.0.jar differ
diff --git a/dist/TinfourViewer-1.0.jar b/dist/TinfourViewer-1.0.jar
index 7a4523d9..c14151da 100644
Binary files a/dist/TinfourViewer-1.0.jar and b/dist/TinfourViewer-1.0.jar differ
diff --git a/src/main/java/tinfour/voronoi/BoundedVoronoiBuildOptions.java b/src/main/java/tinfour/voronoi/BoundedVoronoiBuildOptions.java
index 17d1d0ad..e05197b9 100644
--- a/src/main/java/tinfour/voronoi/BoundedVoronoiBuildOptions.java
+++ b/src/main/java/tinfour/voronoi/BoundedVoronoiBuildOptions.java
@@ -36,7 +36,7 @@
*/
public class BoundedVoronoiBuildOptions {
- protected boolean enableAdjustments = false;
+ protected boolean enableAdjustments;
// The default adjustment value of 30 was chosen through trial and error.
// A round number was chosen to reflect the fact that it is an arbitrary
diff --git a/src/main/java/tinfour/voronoi/BoundedVoronoi.java b/src/main/java/tinfour/voronoi/BoundedVoronoiDiagram.java
similarity index 94%
rename from src/main/java/tinfour/voronoi/BoundedVoronoi.java
rename to src/main/java/tinfour/voronoi/BoundedVoronoiDiagram.java
index e5876f4b..bc64c822 100644
--- a/src/main/java/tinfour/voronoi/BoundedVoronoi.java
+++ b/src/main/java/tinfour/voronoi/BoundedVoronoiDiagram.java
@@ -57,8 +57,6 @@
import tinfour.common.Vertex;
import tinfour.edge.EdgePool;
import tinfour.edge.QuadEdge;
-import tinfour.semivirtual.SemiVirtualIncrementalTin;
-import tinfour.standard.IncrementalTin;
import tinfour.utils.TinInstantiationUtility;
import tinfour.utils.VertexColorizerKempe6;
@@ -71,7 +69,7 @@
* This class is under development and is subject to minor
* changes in its API and behavior.
*/
-public class BoundedVoronoi {
+public class BoundedVoronoiDiagram {
/**
* The overall domain of the structure
@@ -95,7 +93,7 @@ public class BoundedVoronoi {
private double maxRadius = -1;
- private BoundedVoronoi() {
+ private BoundedVoronoiDiagram() {
// a private constructor to deter applications from
// invoking the default constructor
sampleBounds = null;
@@ -111,7 +109,7 @@ private BoundedVoronoi() {
* null to use defaults.
*
*/
- public BoundedVoronoi(List vertexList, BoundedVoronoiBuildOptions options) {
+ public BoundedVoronoiDiagram(List vertexList, BoundedVoronoiBuildOptions options) {
if (vertexList == null) {
throw new IllegalArgumentException(
"Null input not allowed for constructor");
@@ -176,7 +174,7 @@ public BoundedVoronoi(List vertexList, BoundedVoronoiBuildOptions option
* @param delaunayTriangulation a valid instance of a Delaunay Triangulation
* implementation.
*/
- public BoundedVoronoi(IIncrementalTin delaunayTriangulation) {
+ public BoundedVoronoiDiagram(IIncrementalTin delaunayTriangulation) {
if (delaunayTriangulation == null) {
throw new IllegalArgumentException(
"Null input is not allowed for TIN");
@@ -316,8 +314,8 @@ private IQuadEdge liangBarsky(Vertex v0, Vertex v1) {
} else {
x = x0 + t0 * xDelta;
y = y0 + t0 * yDelta;
- z = computeZ(iBorder0, x, y);
- p0 = new Vertex(x, y, z, v0.getIndex());
+ z = computePerimeterParameter(iBorder0, x, y);
+ p0 = new PerimeterVertex(x, y, z, v0.getIndex());
p0.setSynthetic(true);
}
@@ -326,8 +324,8 @@ private IQuadEdge liangBarsky(Vertex v0, Vertex v1) {
} else {
x = x0 + t1 * xDelta;
y = y0 + t1 * yDelta;
- z = computeZ(iBorder1, x, y);
- p1 = new Vertex(x, y, z, v1.getIndex());
+ z = computePerimeterParameter(iBorder1, x, y);
+ p1 = new PerimeterVertex(x, y, z, v1.getIndex());
p1.setSynthetic(true);
}
@@ -335,7 +333,7 @@ private IQuadEdge liangBarsky(Vertex v0, Vertex v1) {
}
@SuppressWarnings("PMD.CollapsibleIfStatements")
- private double computeZ(double x, double y) {
+ private double computePerimeterParameter(double x, double y) {
if (y == ymin) {
// bottom border range 0 to 1
if (xmin <= x && x <= xmax) {
@@ -360,7 +358,7 @@ private double computeZ(double x, double y) {
return Double.NaN;
}
- private double computeZ(int iBoarder, double x, double y) {
+ private double computePerimeterParameter(int iBoarder, double x, double y) {
switch (iBoarder) {
case 0:
return (x - xmin) / (xmax - xmin);
@@ -451,14 +449,14 @@ private void buildPerimeterRay(IQuadEdge e, Vertex[] center, IQuadEdge[] part) {
y = t * uY + cY;
if (t >= 0 && y0 <= y && y <= y1) {
z = 4 - (y - y0) / (y1 - y0); // the left side, descending, z in [3,4]
- Vertex v = new Vertex(x0, y, z, -vCenter.getIndex());
+ Vertex v = new PerimeterVertex(x0, y, z, -vCenter.getIndex());
nBuild = insertRayVertex(nBuild, vBuild, tBuild, t, v);
}
t = (x1 - cX) / uX;
y = t * uY + cY;
if (t >= 0 && y0 <= y && y <= y1) {
z = 1 + (y - y0) / (y1 - y0); // right side, ascending, z in [1,2]
- Vertex v = new Vertex(x1, y, z, -vCenter.getIndex());
+ Vertex v = new PerimeterVertex(x1, y, z, -vCenter.getIndex());
nBuild = insertRayVertex(nBuild, vBuild, tBuild, t, v);
}
}
@@ -468,7 +466,7 @@ private void buildPerimeterRay(IQuadEdge e, Vertex[] center, IQuadEdge[] part) {
x = t * uX + cX;
if (t >= 0 && x0 <= x && x <= x1) {
z = (x - x0) / (x1 - x0); // bottom side, ascending, z in [0,1]
- Vertex v = new Vertex(x, y0, z, -vCenter.getIndex());
+ Vertex v = new PerimeterVertex(x, y0, z, -vCenter.getIndex());
nBuild = insertRayVertex(nBuild, vBuild, tBuild, t, v);
}
@@ -476,7 +474,7 @@ private void buildPerimeterRay(IQuadEdge e, Vertex[] center, IQuadEdge[] part) {
x = t * uX + cX;
if (t >= 0 && x0 <= x && x <= x1) {
z = 3 - (x - x0) / (x1 - x0); // top side, descending, z in [2,3]
- Vertex v = new Vertex(x, y1, z, -vCenter.getIndex());
+ Vertex v = new PerimeterVertex(x, y1, z, -vCenter.getIndex());
nBuild = insertRayVertex(nBuild, vBuild, tBuild, t, v);
}
}
@@ -574,8 +572,16 @@ private void buildCenter(Circumcircle cCircle, IQuadEdge e, Vertex[] centers) {
}
double x = cCircle.getX();
double y = cCircle.getY();
- double z = computeZ(x, y);
- Vertex v = new Vertex(x, y, z, mindex(e, f, r));
+ // there is a low, but non-zero, probability that the center
+ // will lie on one of the perimeter edges.
+ double z = computePerimeterParameter(x, y);
+ Vertex v;
+ if (Double.isNaN(z)) {
+ v = new Vertex(x, y, z, mindex(e, f, r));
+ } else {
+ v = new PerimeterVertex(x, y, z, mindex(e, f, r));
+ }
+
centers[e.getIndex()] = v;
centers[f.getIndex()] = v;
centers[r.getIndex()] = v;
@@ -594,15 +600,18 @@ private void buildStructure(
IIncrementalTin tin,
BoundedVoronoiBuildOptions pOptions) {
- if (pOptions.enableAdjustments) {
- if (tin instanceof IncrementalTin) {
- ((IncrementalTin) tin).collaspsePerimeterTriangles(
- pOptions.adjustmentThreshold);
- } else if (tin instanceof SemiVirtualIncrementalTin) {
- ((SemiVirtualIncrementalTin) tin).collaspsePerimeterTriangles(
- pOptions.adjustmentThreshold);
- }
- }
+
+ // The TIN classes' adjustment logic has a flaw, so it is supressed here
+ // pending a fix or permanent removal
+ //if (pOptions.enableAdjustments) {
+ // if (tin instanceof IncrementalTin) {
+ // ((IncrementalTin) tin).collaspsePerimeterTriangles(
+ // pOptions.adjustmentThreshold);
+ // } else if (tin instanceof SemiVirtualIncrementalTin) {
+ // ((SemiVirtualIncrementalTin) tin).collaspsePerimeterTriangles(
+ // pOptions.adjustmentThreshold);
+ // }
+ //}
// The visited array tracks which of the TIN edges were
// visited for various processes. It is used more than once.
diff --git a/src/main/java/tinfour/voronoi/BoundedVoronoiDrawingUtility.java b/src/main/java/tinfour/voronoi/BoundedVoronoiDrawingUtility.java
index c376067b..479c50e3 100644
--- a/src/main/java/tinfour/voronoi/BoundedVoronoiDrawingUtility.java
+++ b/src/main/java/tinfour/voronoi/BoundedVoronoiDrawingUtility.java
@@ -60,7 +60,7 @@
@SuppressWarnings("PMD.AvoidInstantiatingObjectsInLoops")
public class BoundedVoronoiDrawingUtility {
- private final BoundedVoronoi diagram;
+ private final BoundedVoronoiDiagram diagram;
private final AffineTransform af;
private final Rectangle2D bounds;
@@ -100,7 +100,7 @@ public class BoundedVoronoiDrawingUtility {
* defaults are to be used.
*/
public BoundedVoronoiDrawingUtility(
- BoundedVoronoi diagram,
+ BoundedVoronoiDiagram diagram,
int width,
int height,
int pad,
diff --git a/src/main/java/tinfour/voronoi/BoundedVoronoiIntegrityCheck.java b/src/main/java/tinfour/voronoi/BoundedVoronoiIntegrityCheck.java
index 981cc6d6..7e2fc35b 100644
--- a/src/main/java/tinfour/voronoi/BoundedVoronoiIntegrityCheck.java
+++ b/src/main/java/tinfour/voronoi/BoundedVoronoiIntegrityCheck.java
@@ -41,14 +41,14 @@
public class BoundedVoronoiIntegrityCheck {
String message;
- BoundedVoronoi lmv;
+ BoundedVoronoiDiagram lmv;
/**
* Constructs an instance of the integrity checker tied to the
* specified instance.
* @param BoundedVoronoi a valid, correctly populated instance
*/
- public BoundedVoronoiIntegrityCheck(BoundedVoronoi BoundedVoronoi) {
+ public BoundedVoronoiIntegrityCheck(BoundedVoronoiDiagram BoundedVoronoi) {
lmv = BoundedVoronoi;
message = null;
}
diff --git a/src/main/java/tinfour/voronoi/PerimeterVertex.java b/src/main/java/tinfour/voronoi/PerimeterVertex.java
new file mode 100644
index 00000000..aa932904
--- /dev/null
+++ b/src/main/java/tinfour/voronoi/PerimeterVertex.java
@@ -0,0 +1,76 @@
+/* --------------------------------------------------------------------
+ * Copyright 2018 Gary W. Lucas.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0A
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ---------------------------------------------------------------------
+ */
+
+ /*
+ * -----------------------------------------------------------------------
+ *
+ * Revision History:
+ * Date Name Description
+ * ------ --------- -------------------------------------------------
+ * 09/2018 G. Lucas Initial implementation
+ *
+ * Notes:
+ *
+ * -----------------------------------------------------------------------
+ */
+package tinfour.voronoi;
+
+import tinfour.common.Vertex;
+
+/**
+ * Extends the Vertex class to add perimeter parameter.
+ */
+class PerimeterVertex extends Vertex {
+ /**
+ * The perimeter parameter
+ */
+ final double p;
+
+ /**
+ * Construct a vertex at the specified horizontal Cartesian coordinates with
+ * a z value indicating the parameterized position along the rectangular
+ * bounds of the Voronoi Diagram. The parameter is a value in the
+ * range 0 ≤ z < 4.
+ * @param x the x Cartesian coordinate of the vertex
+ * @param y the y Cartesian coordinate of the vertex
+ * @param z the parameterized position, in range 0 to 4.
+ * @param index an arbitrary index value
+ */
+ public PerimeterVertex(double x, double y, double z, int index){
+ super(x, y, z, index);
+ this.p = z;
+ }
+
+ /**
+ * Gets the perimeter parameter value for vertex.
+ * @return a valid double-precision value
+ */
+ @Override
+ public double getZ(){
+ return p;
+ }
+
+ @Override
+ public String toString() {
+ if (this.isSynthetic()) {
+ return String.format("Pv %11.9f", p);
+ } else {
+ // the rare case of a circumcenter lying on the perimeter
+ return String.format("Pcc %11.9f, center %d", p, getIndex());
+ }
+ }
+}
diff --git a/src/main/java/tinfour/voronoi/ThiessenPolygon.java b/src/main/java/tinfour/voronoi/ThiessenPolygon.java
index d056f83a..3ad670cf 100644
--- a/src/main/java/tinfour/voronoi/ThiessenPolygon.java
+++ b/src/main/java/tinfour/voronoi/ThiessenPolygon.java
@@ -99,7 +99,7 @@ public double getArea() {
}
/**
- * Gets the central vertex of the polygon.
+ * Gets the defining vertex of the polygon.
*
* @return the vertex
*/
@@ -142,6 +142,20 @@ public boolean isPointInPolygon(double x, double y) {
public boolean isOpen(){
return open;
}
+
+ /**
+ * Gets the index element of the defining vertex for this polygon.
+ * The vertex index is under the control of the calling application
+ * and is not modified by the Voronoi classes. Note that the
+ * index of a vertex is not necessarily unique but left to the
+ * requirements of the application that constructs it.
+ * @return an integer value
+ */
+ public int getIndex(){
+ return vertex.getIndex();
+ }
+
+
@Override
public String toString() {
return String.format("ThiessenPolygon vertex=%s", vertex.getLabel());
diff --git a/src/test/java/tinfour/test/shapefile/ShapefileReader.java b/src/test/java/tinfour/test/shapefile/ShapefileReader.java
index 13455193..7432fb68 100644
--- a/src/test/java/tinfour/test/shapefile/ShapefileReader.java
+++ b/src/test/java/tinfour/test/shapefile/ShapefileReader.java
@@ -76,8 +76,8 @@ public ShapefileReader(File file) throws IOException {
}
minX = raf.readDouble();
- maxX = raf.readDouble();
minY = raf.readDouble();
+ maxX = raf.readDouble();
maxY = raf.readDouble();
minZ = raf.readDouble();
maxZ = raf.readDouble();
@@ -196,6 +196,19 @@ record = new ShapefileRecord();
+ ", expected " + shapefileType.getTypeCode());
}
switch (shapefileType) {
+ case Point:
+ // simple case, but we populate other record items for consistency
+ record.setSizes(1,1);
+ record.nParts = 1;
+ record.nPoints = 1;
+ record.partStart[1] = 1;
+ record.x0 = raf.readDouble();
+ record.y0 = raf.readDouble();
+ record.x1 = record.x0;
+ record.y1 = record.y0;
+ record.xyz[0] = record.x0;
+ record.xyz[1] = record.y0;
+ break;
case PolyLineZ:
case PolygonZ: {
record.x0 = raf.readDouble();