Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Maximum Inscribed Circle and Largest Empty Circle #530

Merged
merged 12 commits into from
Apr 9, 2020
Merged
2 changes: 2 additions & 0 deletions doc/JTS_Version_History.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ Distributions for older JTS versions can be obtained at the
* Addded `HPRtree` Hilbert Packed R-tree (#494)
* Added `VariableBuffer` class for computing varying-distance buffers (#495)
* Added `LineSegment.reflect` method (#495)
* Added `MaximumInscribedCircle` algorithm (#530)
* Added `LargestEmptyCircle` algorithm (#530)

### Performance Improvements

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.LineString;
import org.locationtech.jts.geom.Polygon;
import org.locationtech.jts.geom.Point;
import org.locationtech.jts.geom.util.GeometryMapper;
import org.locationtech.jts.geom.util.LinearComponentExtracter;
import org.locationtech.jts.geom.util.GeometryMapper.MapOp;
Expand Down Expand Up @@ -217,4 +218,11 @@ public static Geometry variableBufferMid(Geometry line,
}
return VariableBuffer.buffer(line, startDist, midDist, startDist);
}

public static Geometry bufferRadius(Geometry radiusLine) {
double distance = radiusLine.getLength();
Coordinate centrePt = radiusLine.getCoordinate();
Point centre = radiusLine.getFactory().createPoint(centrePt);
return centre.buffer(distance);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,17 @@
*/
package org.locationtech.jtstest.function;

import org.locationtech.jts.algorithm.Angle;
import org.locationtech.jts.algorithm.MinimumBoundingCircle;
import org.locationtech.jts.algorithm.MinimumDiameter;
import org.locationtech.jts.algorithm.construct.LargestEmptyCircle;
import org.locationtech.jts.algorithm.construct.MaximumInscribedCircle;
import org.locationtech.jts.densify.Densifier;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.LineString;
import org.locationtech.jts.geom.OctagonalEnvelope;
import org.locationtech.jtstest.geomfunction.Metadata;

public class ConstructionFunctions {
public static Geometry octagonalEnvelope(Geometry g) { return OctagonalEnvelope.octagonalEnvelope(g); }
Expand All @@ -40,4 +46,80 @@ public static double maximumDiameterLength(Geometry g) {

public static Geometry densify(Geometry g, double distance) { return Densifier.densify(g, distance); }

//--------------------------------------------

@Metadata(description="Constructs the Maximum Inscribed Circle of a polygonal geometry")
public static Geometry maximumInscribedCircle(Geometry g,
@Metadata(title="Distance tolerance")
double tolerance) {
MaximumInscribedCircle mic = new MaximumInscribedCircle(g, tolerance);
Coordinate center = mic.getCenter().getCoordinate();
Coordinate radiusPt = mic.getRadiusPoint().getCoordinate();
LineString radiusLine = g.getFactory().createLineString(new Coordinate[] { center, radiusPt });
return circleByRadiusLine(radiusLine, 60);
}

@Metadata(description="Constructs the center point of the Maximum Inscribed Circle of a polygonal geometry")
public static Geometry maximumInscribedCircleCenter(Geometry g,
@Metadata(title="Distance tolerance")
double tolerance) {
return MaximumInscribedCircle.getCenter(g, tolerance);
}

@Metadata(description="Constructs a radius line of the Maximum Inscribed Circle of a polygonal geometry")
public static Geometry maximumInscribedCircleRadius(Geometry g,
@Metadata(title="Distance tolerance")
double tolerance) {
MaximumInscribedCircle mic = new MaximumInscribedCircle(g, tolerance);
return mic.getRadiusLine();
}

//--------------------------------------------

@Metadata(description="Constructs the Largest Empty Circle in a set of obstacles")
public static Geometry largestEmptyCircle(Geometry g,
@Metadata(title="Distance tolerance")
double tolerance) {
LineString radiusLine = LargestEmptyCircle.getRadiusLine(g, tolerance);
return circleByRadiusLine(radiusLine, 60);
}

@Metadata(description="Computes a radius line of the Largest Empty Circle in a set of obstacles")
public static Geometry largestEmptyCircleCenter(Geometry g,
@Metadata(title="Distance tolerance")
double tolerance) {
return LargestEmptyCircle.getCenter(g, tolerance);
}

@Metadata(description="Computes a radius line of the Largest Empty Circle in a set of obstacles")
public static Geometry largestEmptyCircleRadius(Geometry g,
@Metadata(title="Distance tolerance")
double tolerance) {
return LargestEmptyCircle.getRadiusLine(g, tolerance);
}

//--------------------------------------------

@Metadata(description="Constructs an n-point circle from a 2-point line giving the radius")
public static Geometry circleByRadiusLine(Geometry radiusLine,
@Metadata(title="Number of vertices")
int nPts) {
Coordinate[] radiusPts = radiusLine.getCoordinates();
Coordinate center = radiusPts[0];
Coordinate radiusPt = radiusPts[1];
double dist = radiusPt.distance(center);

double angInc = 2 * Math.PI / (nPts - 1);
Coordinate[] circlePts = new Coordinate[nPts + 1];
circlePts[0] = radiusPt.copy();
circlePts[nPts] = radiusPt.copy();
double angStart = Angle.angle(center, radiusPt);
for (int i = 1; i < nPts; i++) {
double x = center.getX() + dist * Math.cos(angStart + i * angInc);
double y = center.getY() + dist * Math.sin(angStart + i * angInc);
circlePts[i] = new Coordinate(x,y);
}
return radiusLine.getFactory().createPolygon(circlePts);
}

}
Loading