Skip to content

Commit

Permalink
Geo: fixes circle radius calculation
Browse files Browse the repository at this point in the history
This change fixes the creation circle shapes o it calculates it correctly instead of essentially using the diameter as the radius.  The radius has to be converted into degrees but calculating the ratio of the desired radius to the circumference of the earth and then multiplying it by 360 (number of degrees around the earths circumference).  This issue here was that it was only multiplied by 180 making the result out by a factor of 2.  Also made the test for circles actually check to make sure it has the correct centre and radius.

Closes #7301
  • Loading branch information
colings86 committed Aug 20, 2014
1 parent c55d9ce commit 6812a9c
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 8 deletions.
Expand Up @@ -19,12 +19,12 @@

package org.elasticsearch.common.geo.builders;

import com.spatial4j.core.shape.Circle;
import com.vividsolutions.jts.geom.Coordinate;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.common.unit.DistanceUnit.Distance;
import org.elasticsearch.common.xcontent.XContentBuilder;

import com.spatial4j.core.shape.Circle;
import com.vividsolutions.jts.geom.Coordinate;
import java.io.IOException;

public class CircleBuilder extends ShapeBuilder {
Expand Down Expand Up @@ -109,7 +109,7 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws

@Override
public Circle build() {
return SPATIAL_CONTEXT.makeCircle(center.x, center.y, 180 * radius / unit.getEarthCircumference());
return SPATIAL_CONTEXT.makeCircle(center.x, center.y, 360 * radius / unit.getEarthCircumference());
}

@Override
Expand Down
29 changes: 24 additions & 5 deletions src/test/java/org/elasticsearch/common/geo/ShapeBuilderTests.java
Expand Up @@ -19,9 +19,11 @@

package org.elasticsearch.common.geo;

import com.spatial4j.core.shape.Circle;
import com.spatial4j.core.shape.Point;
import com.spatial4j.core.shape.Rectangle;
import com.spatial4j.core.shape.Shape;
import com.spatial4j.core.shape.impl.PointImpl;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.Polygon;
Expand Down Expand Up @@ -161,11 +163,28 @@ public void testPolygonSelfIntersection() {

@Test
public void testGeoCircle() {
ShapeBuilder.newCircleBuilder().center(0, 0).radius("100m").build();
ShapeBuilder.newCircleBuilder().center(+180, 0).radius("100m").build();
ShapeBuilder.newCircleBuilder().center(-180, 0).radius("100m").build();
ShapeBuilder.newCircleBuilder().center(0, 90).radius("100m").build();
ShapeBuilder.newCircleBuilder().center(0, -90).radius("100m").build();
double earthCircumference = 40075016.69;
Circle circle = ShapeBuilder.newCircleBuilder().center(0, 0).radius("100m").build();
assertEquals((360 * 100) / earthCircumference, circle.getRadius(), 0.00000001);
assertEquals((Point) new PointImpl(0, 0, ShapeBuilder.SPATIAL_CONTEXT), circle.getCenter());
circle = ShapeBuilder.newCircleBuilder().center(+180, 0).radius("100m").build();
assertEquals((360 * 100) / earthCircumference, circle.getRadius(), 0.00000001);
assertEquals((Point) new PointImpl(180, 0, ShapeBuilder.SPATIAL_CONTEXT), circle.getCenter());
circle = ShapeBuilder.newCircleBuilder().center(-180, 0).radius("100m").build();
assertEquals((360 * 100) / earthCircumference, circle.getRadius(), 0.00000001);
assertEquals((Point) new PointImpl(-180, 0, ShapeBuilder.SPATIAL_CONTEXT), circle.getCenter());
circle = ShapeBuilder.newCircleBuilder().center(0, 90).radius("100m").build();
assertEquals((360 * 100) / earthCircumference, circle.getRadius(), 0.00000001);
assertEquals((Point) new PointImpl(0, 90, ShapeBuilder.SPATIAL_CONTEXT), circle.getCenter());
circle = ShapeBuilder.newCircleBuilder().center(0, -90).radius("100m").build();
assertEquals((360 * 100) / earthCircumference, circle.getRadius(), 0.00000001);
assertEquals((Point) new PointImpl(0, -90, ShapeBuilder.SPATIAL_CONTEXT), circle.getCenter());
double randomLat = (randomDouble() * 180) - 90;
double randomLon = (randomDouble() * 360) - 180;
double randomRadius = randomIntBetween(1, (int) earthCircumference / 4);
circle = ShapeBuilder.newCircleBuilder().center(randomLon, randomLat).radius(randomRadius + "m").build();
assertEquals((360 * randomRadius) / earthCircumference, circle.getRadius(), 0.00000001);
assertEquals((Point) new PointImpl(randomLon, randomLat, ShapeBuilder.SPATIAL_CONTEXT), circle.getCenter());
}

@Test
Expand Down

0 comments on commit 6812a9c

Please sign in to comment.