GeometryUtils: fix clockwise calculation (#704)
This commit is contained in:
parent
1051aacc7c
commit
271cab1212
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user