GeometryUtils: fix clockwise calculation (#704)

This commit is contained in:
Gustl22 2019-03-19 18:47:05 +01:00 committed by Emux
parent 1051aacc7c
commit 271cab1212
No known key found for this signature in database
GPG Key ID: 64ED9980896038C3
5 changed files with 26 additions and 17 deletions

View File

@ -8,9 +8,10 @@ public class GeometryTest {
@Test
public void testIsTrisClockwise() {
// Coordinate system is LHS
float[] pA = new float[]{0, 0};
float[] pB = new float[]{1, 1};
float[] pC = new float[]{1, 0};
float[] pB = new float[]{1, 0};
float[] pC = new float[]{1, 1};
float area = GeometryUtils.isTrisClockwise(pA, pB, pC);
Assert.assertTrue(area > 0);
@ -21,12 +22,13 @@ public class GeometryTest {
@Test
public void testIsClockwise() {
float[] points = new float[]{0, 0, 1, 1, 1, 0};
// Coordinate system is LHS
float[] points = new float[]{0, 0, 1, 0, 1, 1};
float area = GeometryUtils.isClockwise(points, points.length);
Assert.assertTrue(area > 0);
points = new float[]{0, 0, 1, 0, 1, 1};
points = new float[]{0, 0, 1, 1, 1, 0};
area = GeometryUtils.isClockwise(points, points.length);
Assert.assertTrue(area < 0);
}

View File

@ -479,12 +479,16 @@ public class GeometryBuffer {
* Calculates geometry area, only polygon outer ring is taken into account.
*
* @return unsigned polygon area, 0 for other geometries
* @see GeometryUtils#area(float[], int)
*/
public float area() {
float area = isClockwise();
return area < 0 ? -area : area;
}
/**
* @see GeometryUtils#isClockwise(float[], int).
*/
public float isClockwise() {
if (isPoint() || isLine() || getNumPoints() < 3)
return 0f;

View File

@ -155,7 +155,7 @@ public class BuildingLayer extends Layer implements TileLoaderThemeHook, ZoomLim
mBuildings.put(tile.hashCode(), buildingElements);
}
element = new MapElement(element); // Deep copy, because element will be cleared
if (RAW_DATA && element.isClockwise() > 0) {
if (RAW_DATA && element.isClockwise() < 0) {
// Buildings must be counter clockwise in VTM (mirrored to OSM)
element.reverse();
}

View File

@ -700,7 +700,7 @@ public final class S3DBUtils {
if (Arrays.equals(ridgePoints.get(k), ridgePoints.get(secIndex)))
ridgeSkipFaceIndex.add(k);
}
if (isClockwise < 0 && IMPROVE_RIDGE_CALCULATION) {
if (isClockwise > 0 && IMPROVE_RIDGE_CALCULATION) {
// TODO Improve handling of counter clockwise faces and support multiple faces
isTessellateAble = false;
break;
@ -845,7 +845,7 @@ public final class S3DBUtils {
}
}
// Scale of normal vec
maxDist = -Math.signum(GeometryUtils.isTrisClockwise(
maxDist = Math.signum(GeometryUtils.isTrisClockwise(
pL,
GeometryUtils.sumVec(pL, vL),
splitLinePoint)) * (maxDist / 2);
@ -861,7 +861,7 @@ public final class S3DBUtils {
List<float[]> elementPoints2 = new ArrayList<>();
float[] secSplitPoint = GeometryUtils.sumVec(splitLinePoint, vL);
float sideLastPoint = Math.signum(GeometryUtils.isTrisClockwise(splitLinePoint, secSplitPoint, point3Fs.get(groundSize - 1)));
degreeNormL = sideLastPoint < 0 ? degreeNormL : (degreeNormL + 180f) % 360; // Correct angle
degreeNormL = sideLastPoint > 0 ? degreeNormL : (degreeNormL + 180f) % 360; // Correct angle
List<Integer> intersection1 = new ArrayList<>(), intersection2 = new ArrayList<>();
for (int k = 0; k < groundSize; k++) {
// If point is not on the same side as the previous point, the split line intersect and can calc split point

View File

@ -69,10 +69,11 @@ public final class GeometryUtils {
/**
* Returns the unsigned area of polygon.
*
* @param n number of points
* @param size the number of point coordinates
* @return unsigned polygon area
*/
public static float area(float[] points, int n) {
float area = isClockwise(points, n);
public static float area(float[] points, int size) {
float area = isClockwise(points, size);
return area < 0 ? -area : area;
}
@ -311,33 +312,35 @@ public final class GeometryUtils {
/**
* Is polygon clockwise.
* Note that the coordinate system is left hand side.
*
* @param points the points array
* @param n the number of points
* @param size the number of point coordinates
* @return the signed area of the polygon
* positive: clockwise
* negative: counter-clockwise
* 0: collinear
*/
public static float isClockwise(float[] points, int n) {
public static float isClockwise(float[] points, int size) {
float area = 0f;
for (int i = 0; i < n - 2; i += 2) {
area += (points[i + 1] * points[i + 2]) - (points[i] * points[i + 3]);
for (int i = 0; i < size - 2; i += 2) {
area += (points[i] * points[i + 3]) - (points[i + 1] * points[i + 2]);
}
area += (points[n - 1] * points[0]) - (points[n - 2] * points[1]);
area += (points[size - 2] * points[1]) - (points[size - 1] * points[0]);
return 0.5f * area;
}
/**
* Indicates the turn of tris pA-pB-pC.
* Note that the coordinate system is left hand side.
*
* @return positive: clockwise
* negative: counter-clockwise
* 0: collinear
*/
public static float isTrisClockwise(float[] pA, float[] pB, float[] pC) {
return (pB[1] - pA[1]) * (pC[0] - pA[0]) - (pB[0] - pA[0]) * (pC[1] - pA[1]);
return (pB[0] - pA[0]) * (pC[1] - pA[1]) - (pB[1] - pA[1]) * (pC[0] - pA[0]);
}
/**