You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@commons.apache.org by GitBox <gi...@apache.org> on 2020/07/11 20:07:05 UTC
[GitHub] [commons-geometry] darkma773r opened a new pull request #97: GEOMETRY-100: Spherical centroids of small areas
darkma773r opened a new pull request #97:
URL: https://github.com/apache/commons-geometry/pull/97
Adding special cases for centroid computations for very small areas.
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [commons-geometry] darkma773r commented on a change in pull request #97: GEOMETRY-100: Spherical centroids of small areas
Posted by GitBox <gi...@apache.org>.
darkma773r commented on a change in pull request #97:
URL: https://github.com/apache/commons-geometry/pull/97#discussion_r454072077
##########
File path: commons-geometry-spherical/src/main/java/org/apache/commons/geometry/spherical/twod/ConvexArea2S.java
##########
@@ -132,35 +139,167 @@ public Point2S getCentroid() {
return weighted == null ? null : Point2S.from(weighted);
}
- /** Returns the weighted vector for the centroid. This vector is computed by scaling the
- * pole vector of the great circle of each boundary arc by the size of the arc and summing
- * the results. By combining the weighted centroid vectors of multiple areas, a single
- * centroid can be computed for the whole group.
+ /** Return the weighted centroid vector of the area. The returned vector points in the direction of the
+ * centroid point on the surface of the unit sphere with the length of the vector proportional to the
+ * effective mass of the area at the centroid. By adding the weighted centroid vectors of multiple
+ * convex areas, a single centroid can be computed for the combined area.
* @return weighted centroid vector.
* @see <a href="https://archive.org/details/centroidinertiat00broc">
* <em>The Centroid and Inertia Tensor for a Spherical Triangle</em> - John E. Brock</a>
*/
Vector3D getWeightedCentroidVector() {
final List<GreatArc> arcs = getBoundaries();
- switch (arcs.size()) {
+ final int numBoundaries = arcs.size();
+
+ switch (numBoundaries) {
case 0:
// full space; no centroid
return null;
case 1:
- // hemisphere; centroid is the pole of the hemisphere
- final GreatArc singleArc = arcs.get(0);
- return singleArc.getCircle().getPole().withNorm(singleArc.getSize());
+ // hemisphere
+ return computeHemisphereWeightedCentroidVector(arcs.get(0));
+ case 2:
+ // lune
+ return computeLuneWeightedCentroidVector(arcs.get(0), arcs.get(1));
default:
- // 2 or more sides; use an extension of the approach outlined here:
- // https://archive.org/details/centroidinertiat00broc
- // In short, the centroid is the sum of the pole vectors of each side
- // multiplied by their arc lengths.
- Vector3D centroid = Vector3D.ZERO;
- for (final GreatArc arc : getBoundaries()) {
- centroid = centroid.add(arc.getCircle().getPole().withNorm(arc.getSize()));
+ // triangle or other convex polygon
+ final double arcLengthSum = arcs.stream()
+ .mapToDouble(GreatArc::getSize)
+ .sum();
+
+ if (arcLengthSum < TRIANGLE_FAN_CENTROID_COMPUTE_THRESHOLD) {
+ return computeTriangleFanWeightedCentroidVector(arcs);
+ }
+
+ return computeArcPoleWeightedCentroidVector(arcs);
+ }
+ }
+
+ /** Compute the weighted centroid vector for the hemisphere formed by the given arc.
+ * @param arc arc defining the hemisphere
+ * @return the weighted centroid vector for the hemisphere
+ * @see #getWeightedCentroidVector()
+ */
+ private Vector3D computeHemisphereWeightedCentroidVector(final GreatArc arc) {
Review comment:
Sounds good.
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [commons-geometry] darkma773r commented on a change in pull request #97: GEOMETRY-100: Spherical centroids of small areas
Posted by GitBox <gi...@apache.org>.
darkma773r commented on a change in pull request #97:
URL: https://github.com/apache/commons-geometry/pull/97#discussion_r454984107
##########
File path: commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/twod/RegionBSPTree2STest.java
##########
@@ -838,6 +843,48 @@ public void testCircleToPolygonBoundarySize() {
Assert.assertEquals("Clockwise boundary size", boundary, cw.getBoundarySize(), 1.0e-7);
}
+ @Test
+ public void testSmallCircleToPolygon() {
+ // arrange
+ final double radius = 5.0e-8;
+ final Point2S center = Point2S.of(0.5, 1.5);
+ final int numPts = 100;
+
+ // act
+ final RegionBSPTree2S circle = circleToPolygon(center, radius, numPts, false);
+
+ // assert
+ // https://en.wikipedia.org/wiki/Spherical_cap
+ final double area = 4.0 * PlaneAngleRadians.PI * Math.pow(Math.sin(radius / 2.0), 2.0);
+ final double boundary = PlaneAngleRadians.TWO_PI * Math.sin(radius);
+
+ SphericalTestUtils.assertPointsEq(center, circle.getCentroid(), TEST_EPS);
+ Assert.assertEquals(area, circle.getSize(), TEST_EPS);
+ Assert.assertEquals(boundary, circle.getBoundarySize(), TEST_EPS);
Review comment:
The difference between the actual and expected boundary sizes is 4.937270541285221E-11 so any epsilon less than that will cause a failure. TEST_EPS is set to 1e-10.
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [commons-geometry] singhbaljit commented on a change in pull request #97: GEOMETRY-100: Spherical centroids of small areas
Posted by GitBox <gi...@apache.org>.
singhbaljit commented on a change in pull request #97:
URL: https://github.com/apache/commons-geometry/pull/97#discussion_r453927651
##########
File path: commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/twod/RegionBSPTree2STest.java
##########
@@ -975,7 +1022,13 @@ private static double rightTriangleArea(final double a, final double b) {
return angleA + angleB - (0.5 * PlaneAngleRadians.PI);
}
- private static RegionBSPTree2S circleToPolygon(final Point2S center, final double radius, final int numPts, final boolean clockwise) {
+ private static RegionBSPTree2S circleToPolygon(final Point2S center, final double radius, final int numPts,
Review comment:
Any reason for this method? I think its easy enough to inline `circleToPolygon(center, radius, numPts, clockwise, TEST_PRECISION)`.
##########
File path: commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/twod/RegionBSPTree2STest.java
##########
@@ -838,6 +843,48 @@ public void testCircleToPolygonBoundarySize() {
Assert.assertEquals("Clockwise boundary size", boundary, cw.getBoundarySize(), 1.0e-7);
}
+ @Test
+ public void testSmallCircleToPolygon() {
+ // arrange
+ final double radius = 5.0e-8;
+ final Point2S center = Point2S.of(0.5, 1.5);
+ final int numPts = 100;
+
+ // act
+ final RegionBSPTree2S circle = circleToPolygon(center, radius, numPts, false);
+
+ // assert
+ // https://en.wikipedia.org/wiki/Spherical_cap
+ final double area = 4.0 * PlaneAngleRadians.PI * Math.pow(Math.sin(radius / 2.0), 2.0);
+ final double boundary = PlaneAngleRadians.TWO_PI * Math.sin(radius);
+
+ SphericalTestUtils.assertPointsEq(center, circle.getCentroid(), TEST_EPS);
+ Assert.assertEquals(area, circle.getSize(), TEST_EPS);
+ Assert.assertEquals(boundary, circle.getBoundarySize(), TEST_EPS);
+ }
+
+ @Test
+ public void testSmallGeographicalRectangle() {
+ // arrange
+ final double[][] vertices = {
+ {42.656216727628696, -70.61919768884546},
+ {42.65612858998112, -70.61938607250165},
+ {42.65579098923594, -70.61909615581666},
+ {42.655879126692355, -70.61890777301083}
+ };
+
+ // act
+ final RegionBSPTree2S rectangle = latLongToTree(TEST_PRECISION, vertices);
+
+ // assert
+ // approximate the centroid as average of vertices
+ final double avgLat = Stream.of(vertices).mapToDouble(v -> v[0]).average().getAsDouble();
+ final double avgLon = Stream.of(vertices).mapToDouble(v -> v[1]).average().getAsDouble();
+ final Point2S centroid = latLongToPoint(avgLat, avgLon);
+
+ SphericalTestUtils.assertPointsEq(centroid, rectangle.getCentroid(), TEST_EPS);
Review comment:
We should add tests for size and boundary size.
##########
File path: commons-geometry-spherical/src/main/java/org/apache/commons/geometry/spherical/twod/ConvexArea2S.java
##########
@@ -132,35 +139,167 @@ public Point2S getCentroid() {
return weighted == null ? null : Point2S.from(weighted);
}
- /** Returns the weighted vector for the centroid. This vector is computed by scaling the
- * pole vector of the great circle of each boundary arc by the size of the arc and summing
- * the results. By combining the weighted centroid vectors of multiple areas, a single
- * centroid can be computed for the whole group.
+ /** Return the weighted centroid vector of the area. The returned vector points in the direction of the
+ * centroid point on the surface of the unit sphere with the length of the vector proportional to the
+ * effective mass of the area at the centroid. By adding the weighted centroid vectors of multiple
+ * convex areas, a single centroid can be computed for the combined area.
* @return weighted centroid vector.
* @see <a href="https://archive.org/details/centroidinertiat00broc">
* <em>The Centroid and Inertia Tensor for a Spherical Triangle</em> - John E. Brock</a>
*/
Vector3D getWeightedCentroidVector() {
final List<GreatArc> arcs = getBoundaries();
- switch (arcs.size()) {
+ final int numBoundaries = arcs.size();
+
+ switch (numBoundaries) {
case 0:
// full space; no centroid
return null;
case 1:
- // hemisphere; centroid is the pole of the hemisphere
- final GreatArc singleArc = arcs.get(0);
- return singleArc.getCircle().getPole().withNorm(singleArc.getSize());
+ // hemisphere
+ return computeHemisphereWeightedCentroidVector(arcs.get(0));
+ case 2:
+ // lune
+ return computeLuneWeightedCentroidVector(arcs.get(0), arcs.get(1));
default:
- // 2 or more sides; use an extension of the approach outlined here:
- // https://archive.org/details/centroidinertiat00broc
- // In short, the centroid is the sum of the pole vectors of each side
- // multiplied by their arc lengths.
- Vector3D centroid = Vector3D.ZERO;
- for (final GreatArc arc : getBoundaries()) {
- centroid = centroid.add(arc.getCircle().getPole().withNorm(arc.getSize()));
+ // triangle or other convex polygon
+ final double arcLengthSum = arcs.stream()
+ .mapToDouble(GreatArc::getSize)
+ .sum();
+
+ if (arcLengthSum < TRIANGLE_FAN_CENTROID_COMPUTE_THRESHOLD) {
+ return computeTriangleFanWeightedCentroidVector(arcs);
+ }
+
+ return computeArcPoleWeightedCentroidVector(arcs);
+ }
+ }
+
+ /** Compute the weighted centroid vector for the hemisphere formed by the given arc.
+ * @param arc arc defining the hemisphere
+ * @return the weighted centroid vector for the hemisphere
+ * @see #getWeightedCentroidVector()
+ */
+ private Vector3D computeHemisphereWeightedCentroidVector(final GreatArc arc) {
+ return arc.getCircle().getPole().withNorm(HALF_SIZE);
+ }
+
+ /** Compute the weighted centroid vector for the lune formed by the given arcs.
+ * @param a first arc for the lune
+ * @param b second arc for the lune
+ * @return the weighted centroid vector for the lune
+ * @see #getWeightedCentroidVector()
+ */
+ private Vector3D computeLuneWeightedCentroidVector(final GreatArc a, final GreatArc b) {
+ final Point2S aMid = a.getCentroid();
+ final Point2S bMid = b.getCentroid();
+
+ // compute the centroid vector as the exact center of the lune to avoid inaccurate
+ // results with very small regions
+ final Vector3D.Unit centroid = aMid.slerp(bMid, 0.5).getVector();
+
+ // compute the weight using the reverse of the algorithm from computeArcPoleWeightedCentroidVector()
+ final double weight =
+ (a.getSize() * centroid.dot(a.getCircle().getPole())) +
+ (b.getSize() * centroid.dot(b.getCircle().getPole()));
+
+ return centroid.withNorm(weight);
+ }
+
+ /** Compute the weighted centroid vector for the triangle or polygon formed by the given arcs
+ * by adding together the arc pole vectors multiplied by their respective arc lengths. This
+ * algorithm is described in the paper <a href="https://archive.org/details/centroidinertiat00broc">
+ * <em>The Centroid and Inertia Tensor for a Spherical Triangle</em></a> by John E Brock.
+ *
+ * <p>Note: This algorithm works well in general but is susceptible to floating point errors
+ * on very small areas. In these cases, the computed centroid may not be in the expected location
+ * and may even be outside of the area. The {@link #computeTriangleFanWeightedCentroidVector(List)}
+ * method can produce more accurate results in these cases.</p>
+ * @param arcs boundary arcs for the area
+ * @return the weighted centroid vector for the area
+ * @see #computeTriangleFanWeightedCentroidVector(List)
+ */
+ private Vector3D computeArcPoleWeightedCentroidVector(final List<GreatArc> arcs) {
+ Vector3D centroid = Vector3D.ZERO;
+
+ Vector3D arcContribution;
Review comment:
Any reason to declare this outside the loop?
##########
File path: commons-geometry-spherical/src/main/java/org/apache/commons/geometry/spherical/twod/RegionBSPTree2S.java
##########
@@ -171,16 +171,32 @@ public RegionBSPTree2S toTree() {
final DoublePrecisionContext precision = ((GreatArc) getRoot().getCut()).getPrecision();
double sizeSum = 0;
- Vector3D centroidVector = Vector3D.ZERO;
+ Vector3D centroidVectorSum = Vector3D.ZERO;
+
+ Vector3D centroidVector;
+ double maxCentroidVectorWeightSq = 0.0;
for (final ConvexArea2S area : areas) {
sizeSum += area.getSize();
- centroidVector = centroidVector.add(area.getWeightedCentroidVector());
+
+ centroidVector = area.getWeightedCentroidVector();
+ maxCentroidVectorWeightSq = Math.max(maxCentroidVectorWeightSq, centroidVector.normSq());
+
+ centroidVectorSum = centroidVectorSum.add(centroidVector);
}
- final Point2S centroid = centroidVector.eq(Vector3D.ZERO, precision) ?
- null :
- Point2S.from(centroidVector);
+ // Convert the weighted centroid vector to a point on the sphere surface. If the centroid vector
Review comment:
I think you'll disagree with usage of `Optional`, but thought I recommend it anyways. 😃
```java
final Point2S centroid = Optional.of(centroidVectorSum)
.filter(v -> !(v.normSq() < maxCentroidVectorWeightSq && v.eq(Vector3D.ZERO, precision)))
.map(Point2S::from)
.orElse(null);
```
##########
File path: commons-geometry-spherical/src/main/java/org/apache/commons/geometry/spherical/twod/RegionBSPTree2S.java
##########
@@ -171,16 +171,32 @@ public RegionBSPTree2S toTree() {
final DoublePrecisionContext precision = ((GreatArc) getRoot().getCut()).getPrecision();
double sizeSum = 0;
- Vector3D centroidVector = Vector3D.ZERO;
+ Vector3D centroidVectorSum = Vector3D.ZERO;
+
+ Vector3D centroidVector;
Review comment:
Any reason the declaration is not inside the loop? It doesn't look to be used elsewhere.
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [commons-geometry] singhbaljit commented on a change in pull request #97: GEOMETRY-100: Spherical centroids of small areas
Posted by GitBox <gi...@apache.org>.
singhbaljit commented on a change in pull request #97:
URL: https://github.com/apache/commons-geometry/pull/97#discussion_r454491164
##########
File path: commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/twod/RegionBSPTree2STest.java
##########
@@ -838,6 +843,48 @@ public void testCircleToPolygonBoundarySize() {
Assert.assertEquals("Clockwise boundary size", boundary, cw.getBoundarySize(), 1.0e-7);
}
+ @Test
+ public void testSmallCircleToPolygon() {
+ // arrange
+ final double radius = 5.0e-8;
+ final Point2S center = Point2S.of(0.5, 1.5);
+ final int numPts = 100;
+
+ // act
+ final RegionBSPTree2S circle = circleToPolygon(center, radius, numPts, false);
+
+ // assert
+ // https://en.wikipedia.org/wiki/Spherical_cap
+ final double area = 4.0 * PlaneAngleRadians.PI * Math.pow(Math.sin(radius / 2.0), 2.0);
+ final double boundary = PlaneAngleRadians.TWO_PI * Math.sin(radius);
+
+ SphericalTestUtils.assertPointsEq(center, circle.getCentroid(), TEST_EPS);
+ Assert.assertEquals(area, circle.getSize(), TEST_EPS);
+ Assert.assertEquals(boundary, circle.getBoundarySize(), TEST_EPS);
Review comment:
Not sure how this is passing here. Seems like its failing for me. I'm using radius of 4.78E-8 (which is about 1 foot geographically). I'm using `EpsilonDoublePrecisionContext[epsilon= 1.5696101377226165E-12]`
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [commons-geometry] singhbaljit commented on a change in pull request #97: GEOMETRY-100: Spherical centroids of small areas
Posted by GitBox <gi...@apache.org>.
singhbaljit commented on a change in pull request #97:
URL: https://github.com/apache/commons-geometry/pull/97#discussion_r454469867
##########
File path: commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/twod/RegionBSPTree2STest.java
##########
@@ -838,6 +843,48 @@ public void testCircleToPolygonBoundarySize() {
Assert.assertEquals("Clockwise boundary size", boundary, cw.getBoundarySize(), 1.0e-7);
}
+ @Test
+ public void testSmallCircleToPolygon() {
+ // arrange
+ final double radius = 5.0e-8;
+ final Point2S center = Point2S.of(0.5, 1.5);
+ final int numPts = 100;
+
+ // act
+ final RegionBSPTree2S circle = circleToPolygon(center, radius, numPts, false);
+
+ // assert
+ // https://en.wikipedia.org/wiki/Spherical_cap
+ final double area = 4.0 * PlaneAngleRadians.PI * Math.pow(Math.sin(radius / 2.0), 2.0);
+ final double boundary = PlaneAngleRadians.TWO_PI * Math.sin(radius);
+
+ SphericalTestUtils.assertPointsEq(center, circle.getCentroid(), TEST_EPS);
+ Assert.assertEquals(area, circle.getSize(), TEST_EPS);
+ Assert.assertEquals(boundary, circle.getBoundarySize(), TEST_EPS);
+ }
+
+ @Test
+ public void testSmallGeographicalRectangle() {
+ // arrange
+ final double[][] vertices = {
+ {42.656216727628696, -70.61919768884546},
+ {42.65612858998112, -70.61938607250165},
+ {42.65579098923594, -70.61909615581666},
+ {42.655879126692355, -70.61890777301083}
+ };
+
+ // act
+ final RegionBSPTree2S rectangle = latLongToTree(TEST_PRECISION, vertices);
+
+ // assert
+ // approximate the centroid as average of vertices
+ final double avgLat = Stream.of(vertices).mapToDouble(v -> v[0]).average().getAsDouble();
+ final double avgLon = Stream.of(vertices).mapToDouble(v -> v[1]).average().getAsDouble();
+ final Point2S centroid = latLongToPoint(avgLat, avgLon);
+
+ SphericalTestUtils.assertPointsEq(centroid, rectangle.getCentroid(), TEST_EPS);
Review comment:
If you remove the radius scaling, then the expected values are (without rounding):
Area = 1.997213869978027E-11
Boundary size = 1.9669710464585642E-5
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [commons-geometry] singhbaljit commented on a change in pull request #97: GEOMETRY-100: Spherical centroids of small areas
Posted by GitBox <gi...@apache.org>.
singhbaljit commented on a change in pull request #97:
URL: https://github.com/apache/commons-geometry/pull/97#discussion_r454456153
##########
File path: commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/twod/RegionBSPTree2STest.java
##########
@@ -838,6 +843,48 @@ public void testCircleToPolygonBoundarySize() {
Assert.assertEquals("Clockwise boundary size", boundary, cw.getBoundarySize(), 1.0e-7);
}
+ @Test
+ public void testSmallCircleToPolygon() {
+ // arrange
+ final double radius = 5.0e-8;
+ final Point2S center = Point2S.of(0.5, 1.5);
+ final int numPts = 100;
+
+ // act
+ final RegionBSPTree2S circle = circleToPolygon(center, radius, numPts, false);
+
+ // assert
+ // https://en.wikipedia.org/wiki/Spherical_cap
+ final double area = 4.0 * PlaneAngleRadians.PI * Math.pow(Math.sin(radius / 2.0), 2.0);
+ final double boundary = PlaneAngleRadians.TWO_PI * Math.sin(radius);
+
+ SphericalTestUtils.assertPointsEq(center, circle.getCentroid(), TEST_EPS);
+ Assert.assertEquals(area, circle.getSize(), TEST_EPS);
+ Assert.assertEquals(boundary, circle.getBoundarySize(), TEST_EPS);
+ }
+
+ @Test
+ public void testSmallGeographicalRectangle() {
+ // arrange
+ final double[][] vertices = {
+ {42.656216727628696, -70.61919768884546},
+ {42.65612858998112, -70.61938607250165},
+ {42.65579098923594, -70.61909615581666},
+ {42.655879126692355, -70.61890777301083}
+ };
+
+ // act
+ final RegionBSPTree2S rectangle = latLongToTree(TEST_PRECISION, vertices);
+
+ // assert
+ // approximate the centroid as average of vertices
+ final double avgLat = Stream.of(vertices).mapToDouble(v -> v[0]).average().getAsDouble();
+ final double avgLon = Stream.of(vertices).mapToDouble(v -> v[1]).average().getAsDouble();
+ final Point2S centroid = latLongToPoint(avgLat, avgLon);
+
+ SphericalTestUtils.assertPointsEq(centroid, rectangle.getCentroid(), TEST_EPS);
Review comment:
Tests for area and boundary are passing with this branch locally in my test environment. I used GeographicLib, but the result are also close to Euclidean value (A = pi*r^2, etc.)
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [commons-geometry] singhbaljit commented on a change in pull request #97: GEOMETRY-100: Spherical centroids of small areas
Posted by GitBox <gi...@apache.org>.
singhbaljit commented on a change in pull request #97:
URL: https://github.com/apache/commons-geometry/pull/97#discussion_r453944699
##########
File path: commons-geometry-spherical/src/main/java/org/apache/commons/geometry/spherical/twod/ConvexArea2S.java
##########
@@ -132,35 +139,167 @@ public Point2S getCentroid() {
return weighted == null ? null : Point2S.from(weighted);
}
- /** Returns the weighted vector for the centroid. This vector is computed by scaling the
- * pole vector of the great circle of each boundary arc by the size of the arc and summing
- * the results. By combining the weighted centroid vectors of multiple areas, a single
- * centroid can be computed for the whole group.
+ /** Return the weighted centroid vector of the area. The returned vector points in the direction of the
+ * centroid point on the surface of the unit sphere with the length of the vector proportional to the
+ * effective mass of the area at the centroid. By adding the weighted centroid vectors of multiple
+ * convex areas, a single centroid can be computed for the combined area.
* @return weighted centroid vector.
* @see <a href="https://archive.org/details/centroidinertiat00broc">
* <em>The Centroid and Inertia Tensor for a Spherical Triangle</em> - John E. Brock</a>
*/
Vector3D getWeightedCentroidVector() {
final List<GreatArc> arcs = getBoundaries();
- switch (arcs.size()) {
+ final int numBoundaries = arcs.size();
+
+ switch (numBoundaries) {
case 0:
// full space; no centroid
return null;
case 1:
- // hemisphere; centroid is the pole of the hemisphere
- final GreatArc singleArc = arcs.get(0);
- return singleArc.getCircle().getPole().withNorm(singleArc.getSize());
+ // hemisphere
+ return computeHemisphereWeightedCentroidVector(arcs.get(0));
+ case 2:
+ // lune
+ return computeLuneWeightedCentroidVector(arcs.get(0), arcs.get(1));
default:
- // 2 or more sides; use an extension of the approach outlined here:
- // https://archive.org/details/centroidinertiat00broc
- // In short, the centroid is the sum of the pole vectors of each side
- // multiplied by their arc lengths.
- Vector3D centroid = Vector3D.ZERO;
- for (final GreatArc arc : getBoundaries()) {
- centroid = centroid.add(arc.getCircle().getPole().withNorm(arc.getSize()));
+ // triangle or other convex polygon
+ final double arcLengthSum = arcs.stream()
+ .mapToDouble(GreatArc::getSize)
+ .sum();
+
+ if (arcLengthSum < TRIANGLE_FAN_CENTROID_COMPUTE_THRESHOLD) {
+ return computeTriangleFanWeightedCentroidVector(arcs);
+ }
+
+ return computeArcPoleWeightedCentroidVector(arcs);
+ }
+ }
+
+ /** Compute the weighted centroid vector for the hemisphere formed by the given arc.
+ * @param arc arc defining the hemisphere
+ * @return the weighted centroid vector for the hemisphere
+ * @see #getWeightedCentroidVector()
+ */
+ private Vector3D computeHemisphereWeightedCentroidVector(final GreatArc arc) {
Review comment:
Should be `static`...along with other `compute*` methods.
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [commons-geometry] darkma773r commented on a change in pull request #97: GEOMETRY-100: Spherical centroids of small areas
Posted by GitBox <gi...@apache.org>.
darkma773r commented on a change in pull request #97:
URL: https://github.com/apache/commons-geometry/pull/97#discussion_r454981185
##########
File path: commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/twod/RegionBSPTree2STest.java
##########
@@ -838,6 +843,48 @@ public void testCircleToPolygonBoundarySize() {
Assert.assertEquals("Clockwise boundary size", boundary, cw.getBoundarySize(), 1.0e-7);
}
+ @Test
+ public void testSmallCircleToPolygon() {
+ // arrange
+ final double radius = 5.0e-8;
+ final Point2S center = Point2S.of(0.5, 1.5);
+ final int numPts = 100;
+
+ // act
+ final RegionBSPTree2S circle = circleToPolygon(center, radius, numPts, false);
+
+ // assert
+ // https://en.wikipedia.org/wiki/Spherical_cap
+ final double area = 4.0 * PlaneAngleRadians.PI * Math.pow(Math.sin(radius / 2.0), 2.0);
+ final double boundary = PlaneAngleRadians.TWO_PI * Math.sin(radius);
+
+ SphericalTestUtils.assertPointsEq(center, circle.getCentroid(), TEST_EPS);
+ Assert.assertEquals(area, circle.getSize(), TEST_EPS);
+ Assert.assertEquals(boundary, circle.getBoundarySize(), TEST_EPS);
Review comment:
The test doesn't pass on your machine?
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [commons-geometry] darkma773r commented on a change in pull request #97: GEOMETRY-100: Spherical centroids of small areas
Posted by GitBox <gi...@apache.org>.
darkma773r commented on a change in pull request #97:
URL: https://github.com/apache/commons-geometry/pull/97#discussion_r454054904
##########
File path: commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/twod/RegionBSPTree2STest.java
##########
@@ -838,6 +843,48 @@ public void testCircleToPolygonBoundarySize() {
Assert.assertEquals("Clockwise boundary size", boundary, cw.getBoundarySize(), 1.0e-7);
}
+ @Test
+ public void testSmallCircleToPolygon() {
+ // arrange
+ final double radius = 5.0e-8;
+ final Point2S center = Point2S.of(0.5, 1.5);
+ final int numPts = 100;
+
+ // act
+ final RegionBSPTree2S circle = circleToPolygon(center, radius, numPts, false);
+
+ // assert
+ // https://en.wikipedia.org/wiki/Spherical_cap
+ final double area = 4.0 * PlaneAngleRadians.PI * Math.pow(Math.sin(radius / 2.0), 2.0);
+ final double boundary = PlaneAngleRadians.TWO_PI * Math.sin(radius);
+
+ SphericalTestUtils.assertPointsEq(center, circle.getCentroid(), TEST_EPS);
+ Assert.assertEquals(area, circle.getSize(), TEST_EPS);
+ Assert.assertEquals(boundary, circle.getBoundarySize(), TEST_EPS);
+ }
+
+ @Test
+ public void testSmallGeographicalRectangle() {
+ // arrange
+ final double[][] vertices = {
+ {42.656216727628696, -70.61919768884546},
+ {42.65612858998112, -70.61938607250165},
+ {42.65579098923594, -70.61909615581666},
+ {42.655879126692355, -70.61890777301083}
+ };
+
+ // act
+ final RegionBSPTree2S rectangle = latLongToTree(TEST_PRECISION, vertices);
+
+ // assert
+ // approximate the centroid as average of vertices
+ final double avgLat = Stream.of(vertices).mapToDouble(v -> v[0]).average().getAsDouble();
+ final double avgLon = Stream.of(vertices).mapToDouble(v -> v[1]).average().getAsDouble();
+ final Point2S centroid = latLongToPoint(avgLat, avgLon);
+
+ SphericalTestUtils.assertPointsEq(centroid, rectangle.getCentroid(), TEST_EPS);
Review comment:
That would be good but I'm not sure what the exact answers should be. Google maps' distance calculator gives a boundary size of 124.51 m and an area of 799.78 m^2. The test here returns values between 125.45 m and 812.42 m^2 (with an earth radius of 6378 km) and 125.04 m and 807.08 m^2 (with an earth radius of 6357 km). Those seem pretty close in general but I have no idea what goes into Google's distance calculation so I don't know if it's reasonable to assert that we're close to those numbers.
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [commons-geometry] darkma773r commented on a change in pull request #97: GEOMETRY-100: Spherical centroids of small areas
Posted by GitBox <gi...@apache.org>.
darkma773r commented on a change in pull request #97:
URL: https://github.com/apache/commons-geometry/pull/97#discussion_r454979080
##########
File path: commons-geometry-spherical/src/main/java/org/apache/commons/geometry/spherical/twod/ConvexArea2S.java
##########
@@ -132,35 +139,167 @@ public Point2S getCentroid() {
return weighted == null ? null : Point2S.from(weighted);
}
- /** Returns the weighted vector for the centroid. This vector is computed by scaling the
- * pole vector of the great circle of each boundary arc by the size of the arc and summing
- * the results. By combining the weighted centroid vectors of multiple areas, a single
- * centroid can be computed for the whole group.
+ /** Return the weighted centroid vector of the area. The returned vector points in the direction of the
+ * centroid point on the surface of the unit sphere with the length of the vector proportional to the
+ * effective mass of the area at the centroid. By adding the weighted centroid vectors of multiple
+ * convex areas, a single centroid can be computed for the combined area.
* @return weighted centroid vector.
* @see <a href="https://archive.org/details/centroidinertiat00broc">
* <em>The Centroid and Inertia Tensor for a Spherical Triangle</em> - John E. Brock</a>
*/
Vector3D getWeightedCentroidVector() {
final List<GreatArc> arcs = getBoundaries();
- switch (arcs.size()) {
+ final int numBoundaries = arcs.size();
+
+ switch (numBoundaries) {
case 0:
// full space; no centroid
return null;
case 1:
- // hemisphere; centroid is the pole of the hemisphere
- final GreatArc singleArc = arcs.get(0);
- return singleArc.getCircle().getPole().withNorm(singleArc.getSize());
+ // hemisphere
+ return computeHemisphereWeightedCentroidVector(arcs.get(0));
+ case 2:
+ // lune
+ return computeLuneWeightedCentroidVector(arcs.get(0), arcs.get(1));
default:
- // 2 or more sides; use an extension of the approach outlined here:
- // https://archive.org/details/centroidinertiat00broc
- // In short, the centroid is the sum of the pole vectors of each side
- // multiplied by their arc lengths.
- Vector3D centroid = Vector3D.ZERO;
- for (final GreatArc arc : getBoundaries()) {
- centroid = centroid.add(arc.getCircle().getPole().withNorm(arc.getSize()));
+ // triangle or other convex polygon
+ final double arcLengthSum = arcs.stream()
+ .mapToDouble(GreatArc::getSize)
+ .sum();
+
+ if (arcLengthSum < TRIANGLE_FAN_CENTROID_COMPUTE_THRESHOLD) {
+ return computeTriangleFanWeightedCentroidVector(arcs);
+ }
+
+ return computeArcPoleWeightedCentroidVector(arcs);
+ }
+ }
+
+ /** Compute the weighted centroid vector for the hemisphere formed by the given arc.
+ * @param arc arc defining the hemisphere
+ * @return the weighted centroid vector for the hemisphere
+ * @see #getWeightedCentroidVector()
+ */
+ private Vector3D computeHemisphereWeightedCentroidVector(final GreatArc arc) {
Review comment:
Done.
##########
File path: commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/twod/RegionBSPTree2STest.java
##########
@@ -975,7 +1022,13 @@ private static double rightTriangleArea(final double a, final double b) {
return angleA + angleB - (0.5 * PlaneAngleRadians.PI);
}
- private static RegionBSPTree2S circleToPolygon(final Point2S center, final double radius, final int numPts, final boolean clockwise) {
+ private static RegionBSPTree2S circleToPolygon(final Point2S center, final double radius, final int numPts,
Review comment:
Done.
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [commons-geometry] singhbaljit commented on a change in pull request #97: GEOMETRY-100: Spherical centroids of small areas
Posted by GitBox <gi...@apache.org>.
singhbaljit commented on a change in pull request #97:
URL: https://github.com/apache/commons-geometry/pull/97#discussion_r455040420
##########
File path: commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/twod/RegionBSPTree2STest.java
##########
@@ -838,6 +843,48 @@ public void testCircleToPolygonBoundarySize() {
Assert.assertEquals("Clockwise boundary size", boundary, cw.getBoundarySize(), 1.0e-7);
}
+ @Test
+ public void testSmallCircleToPolygon() {
+ // arrange
+ final double radius = 5.0e-8;
+ final Point2S center = Point2S.of(0.5, 1.5);
+ final int numPts = 100;
+
+ // act
+ final RegionBSPTree2S circle = circleToPolygon(center, radius, numPts, false);
+
+ // assert
+ // https://en.wikipedia.org/wiki/Spherical_cap
+ final double area = 4.0 * PlaneAngleRadians.PI * Math.pow(Math.sin(radius / 2.0), 2.0);
+ final double boundary = PlaneAngleRadians.TWO_PI * Math.sin(radius);
+
+ SphericalTestUtils.assertPointsEq(center, circle.getCentroid(), TEST_EPS);
+ Assert.assertEquals(area, circle.getSize(), TEST_EPS);
+ Assert.assertEquals(boundary, circle.getBoundarySize(), TEST_EPS);
Review comment:
The boundary size calculation is seems to be different on my library (consuming this library as dependency). Running units tests of this library on my machine works fine. Must be something on my end. I don't see anything odd here.
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [commons-geometry] singhbaljit commented on a change in pull request #97: GEOMETRY-100: Spherical centroids of small areas
Posted by GitBox <gi...@apache.org>.
singhbaljit commented on a change in pull request #97:
URL: https://github.com/apache/commons-geometry/pull/97#discussion_r454457994
##########
File path: commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/twod/RegionBSPTree2STest.java
##########
@@ -838,6 +843,48 @@ public void testCircleToPolygonBoundarySize() {
Assert.assertEquals("Clockwise boundary size", boundary, cw.getBoundarySize(), 1.0e-7);
}
+ @Test
+ public void testSmallCircleToPolygon() {
+ // arrange
+ final double radius = 5.0e-8;
+ final Point2S center = Point2S.of(0.5, 1.5);
+ final int numPts = 100;
+
+ // act
+ final RegionBSPTree2S circle = circleToPolygon(center, radius, numPts, false);
+
+ // assert
+ // https://en.wikipedia.org/wiki/Spherical_cap
+ final double area = 4.0 * PlaneAngleRadians.PI * Math.pow(Math.sin(radius / 2.0), 2.0);
+ final double boundary = PlaneAngleRadians.TWO_PI * Math.sin(radius);
+
+ SphericalTestUtils.assertPointsEq(center, circle.getCentroid(), TEST_EPS);
+ Assert.assertEquals(area, circle.getSize(), TEST_EPS);
+ Assert.assertEquals(boundary, circle.getBoundarySize(), TEST_EPS);
+ }
+
+ @Test
+ public void testSmallGeographicalRectangle() {
+ // arrange
+ final double[][] vertices = {
+ {42.656216727628696, -70.61919768884546},
+ {42.65612858998112, -70.61938607250165},
+ {42.65579098923594, -70.61909615581666},
+ {42.655879126692355, -70.61890777301083}
+ };
+
+ // act
+ final RegionBSPTree2S rectangle = latLongToTree(TEST_PRECISION, vertices);
+
+ // assert
+ // approximate the centroid as average of vertices
+ final double avgLat = Stream.of(vertices).mapToDouble(v -> v[0]).average().getAsDouble();
+ final double avgLon = Stream.of(vertices).mapToDouble(v -> v[1]).average().getAsDouble();
+ final Point2S centroid = latLongToPoint(avgLat, avgLon);
+
+ SphericalTestUtils.assertPointsEq(centroid, rectangle.getCentroid(), TEST_EPS);
Review comment:
I used GeographicLib for comparison. Tests for area and boundary sizes are passing. I get 810.664m^2 and 125.316m for size and boundary size, with radius using authalic radius (6371007.18m).
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [commons-geometry] singhbaljit commented on a change in pull request #97: GEOMETRY-100: Spherical centroids of small areas
Posted by GitBox <gi...@apache.org>.
singhbaljit commented on a change in pull request #97:
URL: https://github.com/apache/commons-geometry/pull/97#discussion_r454457994
##########
File path: commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/twod/RegionBSPTree2STest.java
##########
@@ -838,6 +843,48 @@ public void testCircleToPolygonBoundarySize() {
Assert.assertEquals("Clockwise boundary size", boundary, cw.getBoundarySize(), 1.0e-7);
}
+ @Test
+ public void testSmallCircleToPolygon() {
+ // arrange
+ final double radius = 5.0e-8;
+ final Point2S center = Point2S.of(0.5, 1.5);
+ final int numPts = 100;
+
+ // act
+ final RegionBSPTree2S circle = circleToPolygon(center, radius, numPts, false);
+
+ // assert
+ // https://en.wikipedia.org/wiki/Spherical_cap
+ final double area = 4.0 * PlaneAngleRadians.PI * Math.pow(Math.sin(radius / 2.0), 2.0);
+ final double boundary = PlaneAngleRadians.TWO_PI * Math.sin(radius);
+
+ SphericalTestUtils.assertPointsEq(center, circle.getCentroid(), TEST_EPS);
+ Assert.assertEquals(area, circle.getSize(), TEST_EPS);
+ Assert.assertEquals(boundary, circle.getBoundarySize(), TEST_EPS);
+ }
+
+ @Test
+ public void testSmallGeographicalRectangle() {
+ // arrange
+ final double[][] vertices = {
+ {42.656216727628696, -70.61919768884546},
+ {42.65612858998112, -70.61938607250165},
+ {42.65579098923594, -70.61909615581666},
+ {42.655879126692355, -70.61890777301083}
+ };
+
+ // act
+ final RegionBSPTree2S rectangle = latLongToTree(TEST_PRECISION, vertices);
+
+ // assert
+ // approximate the centroid as average of vertices
+ final double avgLat = Stream.of(vertices).mapToDouble(v -> v[0]).average().getAsDouble();
+ final double avgLon = Stream.of(vertices).mapToDouble(v -> v[1]).average().getAsDouble();
+ final Point2S centroid = latLongToPoint(avgLat, avgLon);
+
+ SphericalTestUtils.assertPointsEq(centroid, rectangle.getCentroid(), TEST_EPS);
Review comment:
I used GeographicLib for comparison. Tests for area and boundary sizes are passing.
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [commons-geometry] singhbaljit commented on a change in pull request #97: GEOMETRY-100: Spherical centroids of small areas
Posted by GitBox <gi...@apache.org>.
singhbaljit commented on a change in pull request #97:
URL: https://github.com/apache/commons-geometry/pull/97#discussion_r454457994
##########
File path: commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/twod/RegionBSPTree2STest.java
##########
@@ -838,6 +843,48 @@ public void testCircleToPolygonBoundarySize() {
Assert.assertEquals("Clockwise boundary size", boundary, cw.getBoundarySize(), 1.0e-7);
}
+ @Test
+ public void testSmallCircleToPolygon() {
+ // arrange
+ final double radius = 5.0e-8;
+ final Point2S center = Point2S.of(0.5, 1.5);
+ final int numPts = 100;
+
+ // act
+ final RegionBSPTree2S circle = circleToPolygon(center, radius, numPts, false);
+
+ // assert
+ // https://en.wikipedia.org/wiki/Spherical_cap
+ final double area = 4.0 * PlaneAngleRadians.PI * Math.pow(Math.sin(radius / 2.0), 2.0);
+ final double boundary = PlaneAngleRadians.TWO_PI * Math.sin(radius);
+
+ SphericalTestUtils.assertPointsEq(center, circle.getCentroid(), TEST_EPS);
+ Assert.assertEquals(area, circle.getSize(), TEST_EPS);
+ Assert.assertEquals(boundary, circle.getBoundarySize(), TEST_EPS);
+ }
+
+ @Test
+ public void testSmallGeographicalRectangle() {
+ // arrange
+ final double[][] vertices = {
+ {42.656216727628696, -70.61919768884546},
+ {42.65612858998112, -70.61938607250165},
+ {42.65579098923594, -70.61909615581666},
+ {42.655879126692355, -70.61890777301083}
+ };
+
+ // act
+ final RegionBSPTree2S rectangle = latLongToTree(TEST_PRECISION, vertices);
+
+ // assert
+ // approximate the centroid as average of vertices
+ final double avgLat = Stream.of(vertices).mapToDouble(v -> v[0]).average().getAsDouble();
+ final double avgLon = Stream.of(vertices).mapToDouble(v -> v[1]).average().getAsDouble();
+ final Point2S centroid = latLongToPoint(avgLat, avgLon);
+
+ SphericalTestUtils.assertPointsEq(centroid, rectangle.getCentroid(), TEST_EPS);
Review comment:
I used GeographicLib for comparison. Tests for area and boundary sizes are passing. I get 810.664m^2 and 125.316m for size and boundary size, using authalic radius (6371007.18m).
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [commons-geometry] darkma773r commented on a change in pull request #97: GEOMETRY-100: Spherical centroids of small areas
Posted by GitBox <gi...@apache.org>.
darkma773r commented on a change in pull request #97:
URL: https://github.com/apache/commons-geometry/pull/97#discussion_r454979306
##########
File path: commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/twod/RegionBSPTree2STest.java
##########
@@ -838,6 +843,48 @@ public void testCircleToPolygonBoundarySize() {
Assert.assertEquals("Clockwise boundary size", boundary, cw.getBoundarySize(), 1.0e-7);
}
+ @Test
+ public void testSmallCircleToPolygon() {
+ // arrange
+ final double radius = 5.0e-8;
+ final Point2S center = Point2S.of(0.5, 1.5);
+ final int numPts = 100;
+
+ // act
+ final RegionBSPTree2S circle = circleToPolygon(center, radius, numPts, false);
+
+ // assert
+ // https://en.wikipedia.org/wiki/Spherical_cap
+ final double area = 4.0 * PlaneAngleRadians.PI * Math.pow(Math.sin(radius / 2.0), 2.0);
+ final double boundary = PlaneAngleRadians.TWO_PI * Math.sin(radius);
+
+ SphericalTestUtils.assertPointsEq(center, circle.getCentroid(), TEST_EPS);
+ Assert.assertEquals(area, circle.getSize(), TEST_EPS);
+ Assert.assertEquals(boundary, circle.getBoundarySize(), TEST_EPS);
+ }
+
+ @Test
+ public void testSmallGeographicalRectangle() {
+ // arrange
+ final double[][] vertices = {
+ {42.656216727628696, -70.61919768884546},
+ {42.65612858998112, -70.61938607250165},
+ {42.65579098923594, -70.61909615581666},
+ {42.655879126692355, -70.61890777301083}
+ };
+
+ // act
+ final RegionBSPTree2S rectangle = latLongToTree(TEST_PRECISION, vertices);
+
+ // assert
+ // approximate the centroid as average of vertices
+ final double avgLat = Stream.of(vertices).mapToDouble(v -> v[0]).average().getAsDouble();
+ final double avgLon = Stream.of(vertices).mapToDouble(v -> v[1]).average().getAsDouble();
+ final Point2S centroid = latLongToPoint(avgLat, avgLon);
+
+ SphericalTestUtils.assertPointsEq(centroid, rectangle.getCentroid(), TEST_EPS);
Review comment:
I added assertions with those values.
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [commons-geometry] singhbaljit commented on a change in pull request #97: GEOMETRY-100: Spherical centroids of small areas
Posted by GitBox <gi...@apache.org>.
singhbaljit commented on a change in pull request #97:
URL: https://github.com/apache/commons-geometry/pull/97#discussion_r454081205
##########
File path: commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/twod/RegionBSPTree2STest.java
##########
@@ -838,6 +843,48 @@ public void testCircleToPolygonBoundarySize() {
Assert.assertEquals("Clockwise boundary size", boundary, cw.getBoundarySize(), 1.0e-7);
}
+ @Test
+ public void testSmallCircleToPolygon() {
+ // arrange
+ final double radius = 5.0e-8;
+ final Point2S center = Point2S.of(0.5, 1.5);
+ final int numPts = 100;
+
+ // act
+ final RegionBSPTree2S circle = circleToPolygon(center, radius, numPts, false);
+
+ // assert
+ // https://en.wikipedia.org/wiki/Spherical_cap
+ final double area = 4.0 * PlaneAngleRadians.PI * Math.pow(Math.sin(radius / 2.0), 2.0);
+ final double boundary = PlaneAngleRadians.TWO_PI * Math.sin(radius);
+
+ SphericalTestUtils.assertPointsEq(center, circle.getCentroid(), TEST_EPS);
+ Assert.assertEquals(area, circle.getSize(), TEST_EPS);
+ Assert.assertEquals(boundary, circle.getBoundarySize(), TEST_EPS);
+ }
+
+ @Test
+ public void testSmallGeographicalRectangle() {
+ // arrange
+ final double[][] vertices = {
+ {42.656216727628696, -70.61919768884546},
+ {42.65612858998112, -70.61938607250165},
+ {42.65579098923594, -70.61909615581666},
+ {42.655879126692355, -70.61890777301083}
+ };
+
+ // act
+ final RegionBSPTree2S rectangle = latLongToTree(TEST_PRECISION, vertices);
+
+ // assert
+ // approximate the centroid as average of vertices
+ final double avgLat = Stream.of(vertices).mapToDouble(v -> v[0]).average().getAsDouble();
+ final double avgLon = Stream.of(vertices).mapToDouble(v -> v[1]).average().getAsDouble();
+ final Point2S centroid = latLongToPoint(avgLat, avgLon);
+
+ SphericalTestUtils.assertPointsEq(centroid, rectangle.getCentroid(), TEST_EPS);
Review comment:
Thoughts on using [GeographicLib](https://geographiclib.sourceforge.io) as reference? Using flattening of `0` means perfect sphere.
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [commons-geometry] singhbaljit commented on a change in pull request #97: GEOMETRY-100: Spherical centroids of small areas
Posted by GitBox <gi...@apache.org>.
singhbaljit commented on a change in pull request #97:
URL: https://github.com/apache/commons-geometry/pull/97#discussion_r454456153
##########
File path: commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/twod/RegionBSPTree2STest.java
##########
@@ -838,6 +843,48 @@ public void testCircleToPolygonBoundarySize() {
Assert.assertEquals("Clockwise boundary size", boundary, cw.getBoundarySize(), 1.0e-7);
}
+ @Test
+ public void testSmallCircleToPolygon() {
+ // arrange
+ final double radius = 5.0e-8;
+ final Point2S center = Point2S.of(0.5, 1.5);
+ final int numPts = 100;
+
+ // act
+ final RegionBSPTree2S circle = circleToPolygon(center, radius, numPts, false);
+
+ // assert
+ // https://en.wikipedia.org/wiki/Spherical_cap
+ final double area = 4.0 * PlaneAngleRadians.PI * Math.pow(Math.sin(radius / 2.0), 2.0);
+ final double boundary = PlaneAngleRadians.TWO_PI * Math.sin(radius);
+
+ SphericalTestUtils.assertPointsEq(center, circle.getCentroid(), TEST_EPS);
+ Assert.assertEquals(area, circle.getSize(), TEST_EPS);
+ Assert.assertEquals(boundary, circle.getBoundarySize(), TEST_EPS);
+ }
+
+ @Test
+ public void testSmallGeographicalRectangle() {
+ // arrange
+ final double[][] vertices = {
+ {42.656216727628696, -70.61919768884546},
+ {42.65612858998112, -70.61938607250165},
+ {42.65579098923594, -70.61909615581666},
+ {42.655879126692355, -70.61890777301083}
+ };
+
+ // act
+ final RegionBSPTree2S rectangle = latLongToTree(TEST_PRECISION, vertices);
+
+ // assert
+ // approximate the centroid as average of vertices
+ final double avgLat = Stream.of(vertices).mapToDouble(v -> v[0]).average().getAsDouble();
+ final double avgLon = Stream.of(vertices).mapToDouble(v -> v[1]).average().getAsDouble();
+ final Point2S centroid = latLongToPoint(avgLat, avgLon);
+
+ SphericalTestUtils.assertPointsEq(centroid, rectangle.getCentroid(), TEST_EPS);
Review comment:
Tests for area and boundary are passing with this branch locally in my test environment.
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [commons-geometry] darkma773r commented on a change in pull request #97: GEOMETRY-100: Spherical centroids of small areas
Posted by GitBox <gi...@apache.org>.
darkma773r commented on a change in pull request #97:
URL: https://github.com/apache/commons-geometry/pull/97#discussion_r454071335
##########
File path: commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/twod/RegionBSPTree2STest.java
##########
@@ -975,7 +1022,13 @@ private static double rightTriangleArea(final double a, final double b) {
return angleA + angleB - (0.5 * PlaneAngleRadians.PI);
}
- private static RegionBSPTree2S circleToPolygon(final Point2S center, final double radius, final int numPts, final boolean clockwise) {
+ private static RegionBSPTree2S circleToPolygon(final Point2S center, final double radius, final int numPts,
Review comment:
Nope. I'll update.
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [commons-geometry] singhbaljit commented on a change in pull request #97: GEOMETRY-100: Spherical centroids of small areas
Posted by GitBox <gi...@apache.org>.
singhbaljit commented on a change in pull request #97:
URL: https://github.com/apache/commons-geometry/pull/97#discussion_r454491164
##########
File path: commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/twod/RegionBSPTree2STest.java
##########
@@ -838,6 +843,48 @@ public void testCircleToPolygonBoundarySize() {
Assert.assertEquals("Clockwise boundary size", boundary, cw.getBoundarySize(), 1.0e-7);
}
+ @Test
+ public void testSmallCircleToPolygon() {
+ // arrange
+ final double radius = 5.0e-8;
+ final Point2S center = Point2S.of(0.5, 1.5);
+ final int numPts = 100;
+
+ // act
+ final RegionBSPTree2S circle = circleToPolygon(center, radius, numPts, false);
+
+ // assert
+ // https://en.wikipedia.org/wiki/Spherical_cap
+ final double area = 4.0 * PlaneAngleRadians.PI * Math.pow(Math.sin(radius / 2.0), 2.0);
+ final double boundary = PlaneAngleRadians.TWO_PI * Math.sin(radius);
+
+ SphericalTestUtils.assertPointsEq(center, circle.getCentroid(), TEST_EPS);
+ Assert.assertEquals(area, circle.getSize(), TEST_EPS);
+ Assert.assertEquals(boundary, circle.getBoundarySize(), TEST_EPS);
Review comment:
Not sure how this is passing here. Seems like its failing for me. I'm using radius of 4.78E-8 (which is about 1 foot geographically).
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [commons-geometry] asfgit merged pull request #97: GEOMETRY-100: Spherical centroids of small areas
Posted by GitBox <gi...@apache.org>.
asfgit merged pull request #97:
URL: https://github.com/apache/commons-geometry/pull/97
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org