Skip to content

Commit

Permalink
Initial commit of Point, Polygon, Distance and Within (2D)
Browse files Browse the repository at this point in the history
  • Loading branch information
craigtaverner committed Apr 15, 2018
1 parent 1dd128a commit d74e1ed
Show file tree
Hide file tree
Showing 15 changed files with 1,768 additions and 0 deletions.
64 changes: 64 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Created by .ignore support plugin (hsz.mobi)
### Java template
# Compiled class file
*.class

# Log file
*.log

# BlueJ files
*.ctxt

# Mobile Tools for Java (J2ME)
.mtj.tmp/

# Package Files #
*.jar
*.war
*.ear
*.zip
*.tar.gz
*.rar

# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*

docs/guides
classes
*.patch
dependency-reduced-pom.xml
derby*
.gradle
gradle.properties
build/
*~
\#*
target
out
.project
.classpath
.settings
.externalToolBuilders/
.scala_dependencies
.factorypath
.cache
.cache-main
.cache-tests
*.iws
*.ipr
*.iml
.idea
.DS_Store
.shell_history
.mailmap
.java-version
.cache-main
.cache-tests
Thumbs.db
.cache-main
.cache-tests
bin
*.cache
*.jfr
devenv.local
*~
674 changes: 674 additions & 0 deletions LICENSE

Large diffs are not rendered by default.

109 changes: 109 additions & 0 deletions algo/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>org.amanzi</groupId>
<artifactId>spatial-3d-parent</artifactId>
<version>1.0.0</version>
</parent>

<artifactId>spatial-3d-algo</artifactId>
<name>Spatial 3D :: Algo</name>
<description>Utilities and Algorithms for 3D Spatial Analysis</description>
<packaging>jar</packaging>

<dependencies>

<dependency>
<groupId>org.amanzi</groupId>
<artifactId>spatial-3d-core</artifactId>
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j</artifactId>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>net.biville.florent</groupId>
<artifactId>neo4j-sproc-compiler</artifactId>
<scope>provided</scope>
<optional>true</optional>
</dependency>

<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-kernel</artifactId>
<type>test-jar</type>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-io</artifactId>
<type>test-jar</type>
<scope>test</scope>
</dependency>

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>

<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-library</artifactId>
</dependency>

<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-slf4j</artifactId>
<version>${neo4j.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
<configuration>
<minimizeJar>true</minimizeJar>
</configuration>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<!-- Neo4j Procedures require Java 8 -->
<compilerVersion>${javac.target}</compilerVersion>
<source>${javac.target}</source>
<target>${javac.target}</target>
<compilerArgs>
<arg>-AIgnoreContextWarnings</arg>
<arg>-AGeneratedDocumentationPath=target/generated-documentation</arg>
<arg>-ADocumentation.FieldDelimiter=¦</arg>
<arg>-ADocumentation.ExportedHeaders=qualified name¦description</arg>
<arg>-ADocumentation.QuotedFields=false</arg>
<arg>-ADocumentation.DelimitedFirstField=true</arg>
<arg>-ADocumentation.ExportGrouping=PACKAGE</arg>
</compilerArgs>
</configuration>
</plugin>
</plugins>
</build>
</project>
23 changes: 23 additions & 0 deletions algo/src/main/java/org/amanzi/spatial/algo/Distance.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package org.amanzi.spatial.algo;

import org.amanzi.spatial.core.Point;

import static java.lang.String.format;

public class Distance {

public static double distance(Point p1, Point p2) {
double[] c1 = p1.getCoordinate();
double[] c2 = p2.getCoordinate();
if (c1.length != c2.length) {
throw new IllegalArgumentException(format("Cannot calculate distance between points of different dimension: %d != %d", c1.length, c2.length));
}
double dsqr = 0;
for (int i = 0; i < c1.length; i++) {
double diff = c1[i] - c2[i];
dsqr += diff * diff;
}
return Math.sqrt(dsqr);
}

}
87 changes: 87 additions & 0 deletions algo/src/main/java/org/amanzi/spatial/algo/Within.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package org.amanzi.spatial.algo;

import org.amanzi.spatial.core.Point;
import org.amanzi.spatial.core.Polygon;
import org.apache.commons.lang3.tuple.Pair;

import java.util.ArrayList;
import java.util.Arrays;

public class Within {
public static boolean within(Polygon polygon, Point point) {
for (Polygon.SimplePolygon shell : polygon.getShells()) {
if (!within(shell, point)) {
return false;
}
}
for (Polygon.SimplePolygon hole : polygon.getShells()) {
if (within(hole, point)) {
return false;
}
}
return true;
}

public static boolean within(Polygon.SimplePolygon shell, Point point) {
int fixedDim = 0;
int compareDim = 1;
Point[] points = shell.getPoints();
ArrayList<Point[]> sides = new ArrayList<>();
for (int i = 0; i < points.length - 1; i++) {
Point p1 = points[i];
Point p2 = points[i + 1];
Integer compare1 = ternaryComparePointsIgnoringOneDimension(p1.getCoordinate(), point.getCoordinate(), fixedDim);
Integer compare2 = ternaryComparePointsIgnoringOneDimension(p2.getCoordinate(), point.getCoordinate(), fixedDim);
if (compare1 == null || compare2 == null) {
// Ignore?
} else if (compare1 * compare2 >= 0) {
// both on same side - ignore
} else {
Integer compare = ternaryComparePointsIgnoringOneDimension(p1.getCoordinate(), p2.getCoordinate(), fixedDim);
if (compare < 0) {
sides.add(new Point[]{p1, p2});
} else {
sides.add(new Point[]{p2, p1});
}
}
}
int intersections = 0;
for (Point[] side : sides) {
if (crosses(side, point, fixedDim, compareDim)) {
intersections += 1;
}
}
return intersections % 2 == 1;
}

public static boolean crosses(Point[] side, Point point, int fixedDim, int compareDim) {
double[] c = point.getCoordinate();
double[] min = new double[]{side[0].getCoordinate()[fixedDim], side[0].getCoordinate()[compareDim]};
double[] max = new double[]{side[1].getCoordinate()[fixedDim], side[1].getCoordinate()[compareDim]};
double[] diff = new double[]{max[0] - min[0], max[1] - min[1]};
double ratio = (c[1] - min[1]) / diff[1];
double offset = ratio * diff[0];
double crossingValue = min[0] + offset;
return crossingValue >= c[0];
}

public static Integer ternaryComparePointsIgnoringOneDimension(double[] c1, double[] c2, int ignoreDim) {
Integer result = null;
if (c1.length != c2.length) return null;
for (int i = 0; i < c1.length; i++) {
if (i != ignoreDim) {
double diff = c1[i] - c2[i];
int ans = (diff > 0) ? 1 : ((diff < 0) ? -1 : 0);
if (result == null) {
result = ans;
} else {
if (result != ans) {
if (result * ans != 0) return null;
else if (result == 0) result = ans;
}
}
}
}
return result;
}
}
33 changes: 33 additions & 0 deletions algo/src/test/java/org/amanzi/spatial/algo/DistanceTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package org.amanzi.spatial.algo;

import org.amanzi.spatial.core.Point;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.closeTo;

public class DistanceTest {
@Rule
public ExpectedException thrown = ExpectedException.none();

@Test
public void shouldNotWorkWithInvalidPoints() {
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("Cannot calculate distance between points of different dimension: 3 != 2");
Distance.distance(new Point(1, 2, 3), new Point(3, 4));
}

@Test
public void shouldWorkWithValid2DPoints() {
assertThat(Distance.distance(new Point(0, 0), new Point(0, 0)), equalTo(0.0));
assertThat(Distance.distance(new Point(0, 0), new Point(1, 0)), equalTo(1.0));
assertThat(Distance.distance(new Point(0, 0), new Point(0, 1)), equalTo(1.0));
assertThat(Distance.distance(new Point(1, 0), new Point(0, 0)), equalTo(1.0));
assertThat(Distance.distance(new Point(0, 1), new Point(0, 0)), equalTo(1.0));
assertThat(Distance.distance(new Point(0, 0), new Point(1, 1)), closeTo(1.414, 0.001));
assertThat(Distance.distance(new Point(-1, -1), new Point(1, 1)), closeTo(2.828, 0.001));
}
}
38 changes: 38 additions & 0 deletions algo/src/test/java/org/amanzi/spatial/algo/WithinTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package org.amanzi.spatial.algo;

import org.amanzi.spatial.core.Point;
import org.amanzi.spatial.core.Polygon;
import org.junit.Test;

import java.util.Arrays;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.MatcherAssert.assertThat;

public class WithinTest {

@Test
public void shouldBeWithinSquare() {
Polygon.SimplePolygon square = makeSquare(new double[]{-10, -10}, 20);
assertThat(Within.within(square, new Point(0, 0)), equalTo(true));
assertThat(Within.within(square, new Point(-20, 0)), equalTo(false));
assertThat(Within.within(square, new Point(20, 0)), equalTo(false));
assertThat(Within.within(square, new Point(0, -20)), equalTo(false));
assertThat(Within.within(square, new Point(0, 20)), equalTo(false));
}

private static double[] move(double[] coords, int dim, double move) {
double[] moved = Arrays.copyOf(coords, coords.length);
moved[dim] += move;
return moved;
}

private static Polygon.SimplePolygon makeSquare(double[] bottomLeftCoords, double width) {
Point bottomLeft = new Point(bottomLeftCoords);
Point bottomRight = new Point(move(bottomLeftCoords, 0, width));
Point topRight = new Point(move(bottomRight.getCoordinate(), 1, width));
Point topLeft = new Point(move(topRight.getCoordinate(), 0, -width));
return Polygon.simple(bottomLeft, bottomRight, topRight, topLeft);
}

}
24 changes: 24 additions & 0 deletions core/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.amanzi</groupId>
<artifactId>spatial-3d-parent</artifactId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>spatial-3d-core</artifactId>

<name>Spatial 3D :: Core</name>
<description>Utilities and Algorithms for 3D Spatial Analysis</description>

<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
</dependencies>

</project>
Loading

0 comments on commit d74e1ed

Please sign in to comment.