Skip to content

Commit

Permalink
Fix Angle#interiorAngle method (#721) (#723)
Browse files Browse the repository at this point in the history
Signed-off-by: grimsa <gediminas.rimsa@gmail.com>
  • Loading branch information
grimsa committed May 21, 2021
1 parent e570d57 commit 480301f
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 11 deletions.
1 change: 1 addition & 0 deletions doc/JTS_Version_History.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ Distributions for older JTS versions can be obtained at the
* Fix `HalfEdge.prev()` method (#703)
* Fix `BufferOp` to remove invalid elements caused by inverted ring curves (#706)
* Fix `IsSimpleOp` duplicate lines bug (#716)
* Fix `Angle.interiorAngle` to produce interior angle correctly (#721)

<!-- ================================================================ -->

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ public static double interiorAngle(Coordinate p0, Coordinate p1, Coordinate p2)
{
double anglePrev = Angle.angle(p1, p0);
double angleNext = Angle.angle(p1, p2);
return Math.abs(angleNext - anglePrev);
return normalizePositive(angleNext - anglePrev);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,15 @@

import junit.framework.TestCase;
import junit.textui.TestRunner;
import org.locationtech.jts.geom.CoordinateSequenceFactory;
import org.locationtech.jts.geom.CoordinateSequences;
import org.locationtech.jts.geom.CoordinateXY;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.Polygon;
import org.locationtech.jts.shape.random.RandomPointsBuilder;


import java.util.Arrays;

/**
* @version 1.7
Expand All @@ -32,7 +39,7 @@ public static void main(String args[]) {

public AngleTest(String name) { super(name); }

public void testAngle() throws Exception
public void testAngle()
{
assertEquals(Angle.angle(new Coordinate(10,0)), 0.0, TOLERANCE);
assertEquals(Angle.angle(new Coordinate(10,10)), Math.PI/4, TOLERANCE);
Expand All @@ -43,7 +50,7 @@ public void testAngle() throws Exception
assertEquals(Angle.angle(new Coordinate(-10,-10)), -0.75*Math.PI, TOLERANCE);
}

public void testIsAcute() throws Exception
public void testIsAcute()
{
assertEquals(Angle.isAcute(new Coordinate(10,0), new Coordinate(0,0), new Coordinate(5,10)), true);
assertEquals(Angle.isAcute(new Coordinate(10,0), new Coordinate(0,0), new Coordinate(5,-10)), true);
Expand All @@ -52,11 +59,9 @@ public void testIsAcute() throws Exception

assertEquals(Angle.isAcute(new Coordinate(10,0), new Coordinate(0,0), new Coordinate(-5,10)), false);
assertEquals(Angle.isAcute(new Coordinate(10,0), new Coordinate(0,0), new Coordinate(-5,-10)), false);


}

public void testNormalizePositive() throws Exception
public void testNormalizePositive()
{
assertEquals(Angle.normalizePositive(0.0), 0.0, TOLERANCE);

Expand All @@ -75,10 +80,9 @@ public void testNormalizePositive() throws Exception
assertEquals(Angle.normalizePositive(2.5*Math.PI), 0.5*Math.PI, TOLERANCE);
assertEquals(Angle.normalizePositive(3*Math.PI), Math.PI, TOLERANCE);
assertEquals(Angle.normalizePositive(4 * Math.PI), 0.0, TOLERANCE);

}

public void testNormalize() throws Exception
public void testNormalize()
{
assertEquals(Angle.normalize(0.0), 0.0, TOLERANCE);

Expand All @@ -97,9 +101,52 @@ public void testNormalize() throws Exception
assertEquals(Angle.normalize(2.5*Math.PI), 0.5*Math.PI, TOLERANCE);
assertEquals(Angle.normalize(3*Math.PI), Math.PI, TOLERANCE);
assertEquals(Angle.normalize(4 * Math.PI), 0.0, TOLERANCE);


}

public void testInteriorAngle() {
Coordinate p1 = new CoordinateXY(1, 2);
Coordinate p2 = new CoordinateXY(3, 2);
Coordinate p3 = new CoordinateXY(2, 1);

// Tests all interior angles of a triangle "POLYGON ((1 2, 3 2, 2 1, 1 2))"
assertEquals(45, Math.toDegrees(Angle.interiorAngle(p1, p2, p3)), 0.01);
assertEquals(90, Math.toDegrees(Angle.interiorAngle(p2, p3, p1)), 0.01);
assertEquals(45, Math.toDegrees(Angle.interiorAngle(p3, p1, p2)), 0.01);
// Tests interior angles greater than 180 degrees
assertEquals(315, Math.toDegrees(Angle.interiorAngle(p3, p2, p1)), 0.01);
assertEquals(270, Math.toDegrees(Angle.interiorAngle(p1, p3, p2)), 0.01);
assertEquals(315, Math.toDegrees(Angle.interiorAngle(p2, p1, p3)), 0.01);
}

/**
* Tests interior angle calculation using a number of random triangles
*/
public void testInteriorAngle_randomTriangles() {
GeometryFactory geometryFactory = new GeometryFactory();
CoordinateSequenceFactory coordinateSequenceFactory = geometryFactory.getCoordinateSequenceFactory();
for (int i = 0; i < 100; i++){
RandomPointsBuilder builder = new RandomPointsBuilder();
builder.setNumPoints(3);
Geometry threeRandomPoints = builder.getGeometry();
Polygon triangle = geometryFactory.createPolygon(
CoordinateSequences.ensureValidRing(
coordinateSequenceFactory,
coordinateSequenceFactory.create(threeRandomPoints.getCoordinates())
)
);
// Triangle coordinates in clockwise order
Coordinate[] c = Orientation.isCCW(triangle.getCoordinates())
? triangle.reverse().getCoordinates()
: triangle.getCoordinates();
double sumOfInteriorAngles = Angle.interiorAngle(c[0], c[1], c[2])
+ Angle.interiorAngle(c[1], c[2], c[0])
+ Angle.interiorAngle(c[2], c[0], c[1]);
assertEquals(
i + ": The sum of the angles of a triangle is not equal to two right angles for points: " + Arrays.toString(c),
Math.PI,
sumOfInteriorAngles,
0.01
);
}
}
}

0 comments on commit 480301f

Please sign in to comment.