Skip to content

Commit

Permalink
Merge pull request #10 from ngageoint/develop
Browse files Browse the repository at this point in the history
1.0.4 release
  • Loading branch information
bosborn authored Nov 20, 2017
2 parents 7e3fe46 + faf06cf commit 3a0e5d3
Show file tree
Hide file tree
Showing 5 changed files with 207 additions and 4 deletions.
5 changes: 3 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ Adheres to [Semantic Versioning](http://semver.org/).

---

## 1.0.4 (TBD)
## [1.0.4](https://github.com/ngageoint/geopackage-wkb-java/releases/tag/1.0.4) (11-20-2017)

* TBD
* Douglas Peucker algorithm for geometry simplification
* maven-gpg-plugin version 1.6

## [1.0.3](https://github.com/ngageoint/geopackage-wkb-java/releases/tag/1.0.3) (06-12-2017)

Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,14 @@ writer.close();

### Installation ###

Pull from the [Maven Central Repository](http://search.maven.org/#artifactdetails|mil.nga|wkb|1.0.3|jar) (JAR, POM, Source, Javadoc)
Pull from the [Maven Central Repository](http://search.maven.org/#artifactdetails|mil.nga|wkb|1.0.4|jar) (JAR, POM, Source, Javadoc)

```xml

<dependency>
<groupId>mil.nga</groupId>
<artifactId>wkb</artifactId>
<version>1.0.3</version>
<version>1.0.4</version>
</dependency>

```
Expand Down
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<id>sign-artifacts</id>
Expand Down
126 changes: 126 additions & 0 deletions src/main/java/mil/nga/wkb/util/GeometryUtils.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package mil.nga.wkb.util;

import java.util.ArrayList;
import java.util.List;

import mil.nga.wkb.geom.CircularString;
Expand Down Expand Up @@ -479,4 +480,129 @@ private static void normalize(PolyhedralSurface polyhedralSurface,
}
}

/**
* Simplify the ordered points (representing a line, polygon, etc) using the
* Douglas Peucker algorithm to create a similar curve with fewer points.
* Points should be in a meters unit type projection. The tolerance is the
* minimum tolerated distance between consecutive points.
*
* @param points
* geometry points
* @param tolerance
* minimum tolerance in meters for consecutive points
* @return simplified points
* @since 1.0.4
*/
public static List<Point> simplifyPoints(List<Point> points,
double tolerance) {
return simplifyPoints(points, tolerance, 0, points.size() - 1);
}

/**
* Simplify the ordered points (representing a line, polygon, etc) using the
* Douglas Peucker algorithm to create a similar curve with fewer points.
* Points should be in a meters unit type projection. The tolerance is the
* minimum tolerated distance between consecutive points.
*
* @param points
* geometry points
* @param tolerance
* minimum tolerance in meters for consecutive points
* @param startIndex
* start index
* @param endIndex
* end index
* @return simplified points
*/
private static List<Point> simplifyPoints(List<Point> points,
double tolerance, int startIndex, int endIndex) {

List<Point> result = null;

double dmax = 0.0;
int index = 0;

Point startPoint = points.get(startIndex);
Point endPoint = points.get(endIndex);

for (int i = startIndex + 1; i < endIndex; i++) {
Point point = points.get(i);

double d = perpendicularDistance(point, startPoint, endPoint);

if (d > dmax) {
index = i;
dmax = d;
}
}

if (dmax > tolerance) {

List<Point> recResults1 = simplifyPoints(points, tolerance,
startIndex, index);
List<Point> recResults2 = simplifyPoints(points, tolerance, index,
endIndex);

result = recResults1.subList(0, recResults1.size() - 1);
result.addAll(recResults2);

} else {
result = new ArrayList<Point>();
result.add(startPoint);
result.add(endPoint);
}

return result;
}

/**
* Calculate the perpendicular distance between the point and the line
* represented by the start and end points. Points should be in a meters
* unit type projection.
*
* @param point
* point
* @param lineStart
* point representing the line start
* @param lineEnd
* point representing the line end
* @return distance in meters
* @since 1.0.4
*/
public static double perpendicularDistance(Point point, Point lineStart,
Point lineEnd) {

double x = point.getX();
double y = point.getY();
double startX = lineStart.getX();
double startY = lineStart.getY();
double endX = lineEnd.getX();
double endY = lineEnd.getY();

double vX = endX - startX;
double vY = endY - startY;
double wX = x - startX;
double wY = y - startY;
double c1 = wX * vX + wY * vY;
double c2 = vX * vX + vY * vY;

double x2;
double y2;
if (c1 <= 0) {
x2 = startX;
y2 = startY;
} else if (c2 <= c1) {
x2 = endX;
y2 = endY;
} else {
double b = c1 / c2;
x2 = startX + b * vX;
y2 = startY + b * vY;
}

double distance = Math.sqrt(Math.pow(x2 - x, 2) + Math.pow(y2 - y, 2));

return distance;
}

}
75 changes: 75 additions & 0 deletions src/test/java/mil/nga/wkb/test/GeometryUtilsTest.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package mil.nga.wkb.test;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import junit.framework.TestCase;
Expand Down Expand Up @@ -326,4 +328,77 @@ public void testCopyMinimizeAndNormalize() {

}

@Test
public void testSimplifyPoints() {

final double halfWorldWidth = 20037508.342789244;

List<Point> points = new ArrayList<>();
List<Double> distances = new ArrayList<>();

double x = (Math.random() * halfWorldWidth * 2) - halfWorldWidth;
double y = (Math.random() * halfWorldWidth * 2) - halfWorldWidth;
Point point = new Point(x, y);
points.add(point);

for (int i = 1; i < 100; i++) {

double xChange = 100000.0 * Math.random()
* (Math.random() < .5 ? 1 : -1);
x += xChange;

double yChange = 100000.0 * Math.random()
* (Math.random() < .5 ? 1 : -1);
y += yChange;
if (y > halfWorldWidth || y < -halfWorldWidth) {
y -= 2 * yChange;
}

Point previousPoint = point;
point = new Point(x, y);
points.add(point);

double distance = GeometryUtils.distance(previousPoint, point);
distances.add(distance);

}

List<Double> sortedDistances = new ArrayList<>(distances);
Collections.sort(sortedDistances);
double tolerance = sortedDistances.get(sortedDistances.size() / 2);

List<Point> simplifiedPoints = GeometryUtils.simplifyPoints(points,
tolerance);
TestCase.assertTrue(simplifiedPoints.size() <= points.size());

Point firstPoint = points.get(0);
Point lastPoint = points.get(points.size() - 1);
Point firstSimplifiedPoint = simplifiedPoints.get(0);
Point lastSimplifiedPoint = simplifiedPoints.get(simplifiedPoints
.size() - 1);

TestCase.assertEquals(firstPoint.getX(), firstSimplifiedPoint.getX());
TestCase.assertEquals(firstPoint.getY(), firstSimplifiedPoint.getY());
TestCase.assertEquals(lastPoint.getX(), lastSimplifiedPoint.getX());
TestCase.assertEquals(lastPoint.getY(), lastSimplifiedPoint.getY());

int pointIndex = 0;
for (int i = 1; i < simplifiedPoints.size(); i++) {
Point simplifiedPoint = simplifiedPoints.get(i);
double simplifiedDistance = GeometryUtils.distance(
simplifiedPoints.get(i - 1), simplifiedPoint);
TestCase.assertTrue(simplifiedDistance >= tolerance);

for (pointIndex++; pointIndex < points.size(); pointIndex++) {
Point newPoint = points.get(pointIndex);
if (newPoint.getX() == simplifiedPoint.getX()
&& newPoint.getY() == simplifiedPoint.getY()) {
break;
}
}
TestCase.assertTrue(pointIndex < points.size());
}

}

}

0 comments on commit 3a0e5d3

Please sign in to comment.