GeometryUtils: fix clockwise calculation (#704)
This commit is contained in:
parent
1051aacc7c
commit
271cab1212
@ -8,9 +8,10 @@ public class GeometryTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testIsTrisClockwise() {
|
public void testIsTrisClockwise() {
|
||||||
|
// Coordinate system is LHS
|
||||||
float[] pA = new float[]{0, 0};
|
float[] pA = new float[]{0, 0};
|
||||||
float[] pB = new float[]{1, 1};
|
float[] pB = new float[]{1, 0};
|
||||||
float[] pC = new float[]{1, 0};
|
float[] pC = new float[]{1, 1};
|
||||||
|
|
||||||
float area = GeometryUtils.isTrisClockwise(pA, pB, pC);
|
float area = GeometryUtils.isTrisClockwise(pA, pB, pC);
|
||||||
Assert.assertTrue(area > 0);
|
Assert.assertTrue(area > 0);
|
||||||
@ -21,12 +22,13 @@ public class GeometryTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testIsClockwise() {
|
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);
|
float area = GeometryUtils.isClockwise(points, points.length);
|
||||||
Assert.assertTrue(area > 0);
|
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);
|
area = GeometryUtils.isClockwise(points, points.length);
|
||||||
Assert.assertTrue(area < 0);
|
Assert.assertTrue(area < 0);
|
||||||
}
|
}
|
||||||
|
@ -479,12 +479,16 @@ public class GeometryBuffer {
|
|||||||
* Calculates geometry area, only polygon outer ring is taken into account.
|
* Calculates geometry area, only polygon outer ring is taken into account.
|
||||||
*
|
*
|
||||||
* @return unsigned polygon area, 0 for other geometries
|
* @return unsigned polygon area, 0 for other geometries
|
||||||
|
* @see GeometryUtils#area(float[], int)
|
||||||
*/
|
*/
|
||||||
public float area() {
|
public float area() {
|
||||||
float area = isClockwise();
|
float area = isClockwise();
|
||||||
return area < 0 ? -area : area;
|
return area < 0 ? -area : area;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see GeometryUtils#isClockwise(float[], int).
|
||||||
|
*/
|
||||||
public float isClockwise() {
|
public float isClockwise() {
|
||||||
if (isPoint() || isLine() || getNumPoints() < 3)
|
if (isPoint() || isLine() || getNumPoints() < 3)
|
||||||
return 0f;
|
return 0f;
|
||||||
|
@ -155,7 +155,7 @@ public class BuildingLayer extends Layer implements TileLoaderThemeHook, ZoomLim
|
|||||||
mBuildings.put(tile.hashCode(), buildingElements);
|
mBuildings.put(tile.hashCode(), buildingElements);
|
||||||
}
|
}
|
||||||
element = new MapElement(element); // Deep copy, because element will be cleared
|
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)
|
// Buildings must be counter clockwise in VTM (mirrored to OSM)
|
||||||
element.reverse();
|
element.reverse();
|
||||||
}
|
}
|
||||||
|
@ -700,7 +700,7 @@ public final class S3DBUtils {
|
|||||||
if (Arrays.equals(ridgePoints.get(k), ridgePoints.get(secIndex)))
|
if (Arrays.equals(ridgePoints.get(k), ridgePoints.get(secIndex)))
|
||||||
ridgeSkipFaceIndex.add(k);
|
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
|
// TODO Improve handling of counter clockwise faces and support multiple faces
|
||||||
isTessellateAble = false;
|
isTessellateAble = false;
|
||||||
break;
|
break;
|
||||||
@ -845,7 +845,7 @@ public final class S3DBUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Scale of normal vec
|
// Scale of normal vec
|
||||||
maxDist = -Math.signum(GeometryUtils.isTrisClockwise(
|
maxDist = Math.signum(GeometryUtils.isTrisClockwise(
|
||||||
pL,
|
pL,
|
||||||
GeometryUtils.sumVec(pL, vL),
|
GeometryUtils.sumVec(pL, vL),
|
||||||
splitLinePoint)) * (maxDist / 2);
|
splitLinePoint)) * (maxDist / 2);
|
||||||
@ -861,7 +861,7 @@ public final class S3DBUtils {
|
|||||||
List<float[]> elementPoints2 = new ArrayList<>();
|
List<float[]> elementPoints2 = new ArrayList<>();
|
||||||
float[] secSplitPoint = GeometryUtils.sumVec(splitLinePoint, vL);
|
float[] secSplitPoint = GeometryUtils.sumVec(splitLinePoint, vL);
|
||||||
float sideLastPoint = Math.signum(GeometryUtils.isTrisClockwise(splitLinePoint, secSplitPoint, point3Fs.get(groundSize - 1)));
|
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<>();
|
List<Integer> intersection1 = new ArrayList<>(), intersection2 = new ArrayList<>();
|
||||||
for (int k = 0; k < groundSize; k++) {
|
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
|
// 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.
|
* 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) {
|
public static float area(float[] points, int size) {
|
||||||
float area = isClockwise(points, n);
|
float area = isClockwise(points, size);
|
||||||
return area < 0 ? -area : area;
|
return area < 0 ? -area : area;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -311,33 +312,35 @@ public final class GeometryUtils {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Is polygon clockwise.
|
* Is polygon clockwise.
|
||||||
|
* Note that the coordinate system is left hand side.
|
||||||
*
|
*
|
||||||
* @param points the points array
|
* @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
|
* @return the signed area of the polygon
|
||||||
* positive: clockwise
|
* positive: clockwise
|
||||||
* negative: counter-clockwise
|
* negative: counter-clockwise
|
||||||
* 0: collinear
|
* 0: collinear
|
||||||
*/
|
*/
|
||||||
public static float isClockwise(float[] points, int n) {
|
public static float isClockwise(float[] points, int size) {
|
||||||
float area = 0f;
|
float area = 0f;
|
||||||
for (int i = 0; i < n - 2; i += 2) {
|
for (int i = 0; i < size - 2; i += 2) {
|
||||||
area += (points[i + 1] * points[i + 2]) - (points[i] * points[i + 3]);
|
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;
|
return 0.5f * area;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates the turn of tris pA-pB-pC.
|
* Indicates the turn of tris pA-pB-pC.
|
||||||
|
* Note that the coordinate system is left hand side.
|
||||||
*
|
*
|
||||||
* @return positive: clockwise
|
* @return positive: clockwise
|
||||||
* negative: counter-clockwise
|
* negative: counter-clockwise
|
||||||
* 0: collinear
|
* 0: collinear
|
||||||
*/
|
*/
|
||||||
public static float isTrisClockwise(float[] pA, float[] pB, float[] pC) {
|
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