Skip to content

Commit

Permalink
Add OffsetCurve class (#810)
Browse files Browse the repository at this point in the history
* Add OffsetCurve and related code

Signed-off-by: Martin Davis <[email protected]>
  • Loading branch information
dr-jts authored Dec 3, 2021
1 parent 66483c3 commit 149b389
Show file tree
Hide file tree
Showing 13 changed files with 878 additions and 42 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
import org.locationtech.jts.operation.buffer.BufferOp;
import org.locationtech.jts.operation.buffer.BufferParameters;
import org.locationtech.jts.operation.buffer.OffsetCurveBuilder;
import org.locationtech.jts.operation.buffer.OffsetCurveSetBuilder;
import org.locationtech.jts.operation.buffer.BufferCurveSetBuilder;
import org.locationtech.jts.operation.buffer.VariableBuffer;
import org.locationtech.jts.operation.buffer.validate.BufferResultValidator;
import org.locationtech.jtstest.geomfunction.Metadata;
Expand Down Expand Up @@ -108,10 +108,9 @@ public static Geometry bufferCurveWithParams(Geometry g,
private static Geometry buildCurveSet(Geometry g, double dist, BufferParameters bufParams)
{
// --- now construct curve
OffsetCurveBuilder ocb = new OffsetCurveBuilder(
BufferCurveSetBuilder ocsb = new BufferCurveSetBuilder(g, dist,
g.getFactory().getPrecisionModel(),
bufParams);
OffsetCurveSetBuilder ocsb = new OffsetCurveSetBuilder(g, dist, ocb);
List curves = ocsb.getCurves();

List lines = new ArrayList();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,29 @@

import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.operation.buffer.BufferParameters;
import org.locationtech.jts.operation.buffer.OffsetCurveBuilder;
import org.locationtech.jts.geom.LineString;
import org.locationtech.jts.geom.util.GeometryCombiner;
import org.locationtech.jts.operation.buffer.OffsetCurve;

public class OffsetCurveFunctions {

public static Geometry offsetCurve(Geometry geom, double distance)
{
BufferParameters bufParams = new BufferParameters();
OffsetCurveBuilder ocb = new OffsetCurveBuilder(
geom.getFactory().getPrecisionModel(), bufParams
);
Coordinate[] pts = ocb.getOffsetCurve(geom.getCoordinates(), distance);
return OffsetCurve.getCurve(geom, distance);
}

public static Geometry offsetCurveBoth(Geometry geom, double distance)
{
Geometry curve1 = OffsetCurve.getCurve(geom, distance);
Geometry curve2 = OffsetCurve.getCurve(geom, -distance);
return GeometryCombiner.combine(curve1, curve2);
}

public static Geometry rawCurve(Geometry geom, double distance)
{
Coordinate[] pts = OffsetCurve.rawOffset((LineString) geom, distance);
Geometry curve = geom.getFactory().createLineString(pts);
return curve;
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,24 @@ public LineSegment project(LineSegment seg)
return new LineSegment(newp0, newp1);
}

/**
* Computes the {@link LineSegment} that is offset from
* the segment by a given distance.
* The computed segment is offset to the left of the line if the offset distance is
* positive, to the right if negative.
*
* @param offsetDistance the distance the point is offset from the segment
* (positive is to the left, negative is to the right)
* @return a line segment offset by the specified distance
*
* @throws IllegalStateException if the segment has zero length
*/
public LineSegment offset(double offsetDistance) {
Coordinate offset0 = pointAlongOffset(0, offsetDistance);
Coordinate offset1 = pointAlongOffset(1, offsetDistance);
return new LineSegment(offset0, offset1);
}

/**
* Computes the reflection of a point in the line defined
* by this line segment.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,19 +65,76 @@ public static Collection map(Collection geoms, MapOp op)
}

/**
* An interface for geometry functions used for mapping.
* Maps the atomic elements of a {@link Geometry}
* (which may be atomic or composite)
* using a {@link MapOp} mapping operation
* into an atomic <tt>Geometry</tt> or a flat collection
* of the most specific type.
* <tt>null</tt> and empty values returned from the mapping operation
* are discarded.
*
* @param geom the geometry to map
* @param emptyDim the dimension of empty geometry to create
* @param op the mapping operation
* @return the mapped result
*/
public static Geometry flatMap(Geometry geom, int emptyDim, MapOp op)
{
List<Geometry> mapped = new ArrayList<Geometry>();
flatMap(geom, op, mapped);

if (mapped.size() == 0) {
return geom.getFactory().createEmpty(emptyDim);
}
if (mapped.size() == 1)
return mapped.get(0);
return geom.getFactory().buildGeometry(mapped);
}

private static void flatMap(Geometry geom, MapOp op, List<Geometry> mapped)
{
for (int i = 0; i < geom.getNumGeometries(); i++) {
Geometry g = geom.getGeometryN(i);
if (g instanceof GeometryCollection) {
flatMap(g, op, mapped);
}
else {
Geometry res = op.map(g);
if (res != null && ! res.isEmpty()) {
addFlat(res, mapped);
}
}
}
}

private static void addFlat(Geometry geom, List<Geometry> geomList) {
if (geom.isEmpty()) return;
if (geom instanceof GeometryCollection) {
for (int i = 0; i < geom.getNumGeometries(); i++) {
addFlat(geom.getGeometryN(i), geomList);
}
}
else {
geomList.add(geom);
}
}

/**
* An interface for geometry functions that map a geometry input to a geometry output.
* The output may be <tt>null</tt> if there is no valid output value for
* the given input value.
*
* @author Martin Davis
*
*/
public interface MapOp
{
/**
* Computes a new geometry value.
* Maps a geometry value into another value.
*
* @param g the input geometry
* @param geom the input geometry
* @return a result geometry
*/
Geometry map(Geometry g);
Geometry map(Geometry geom);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -137,9 +137,7 @@ public Geometry buffer(Geometry g, double distance)
// factory must be the same as the one used by the input
geomFact = g.getFactory();

OffsetCurveBuilder curveBuilder = new OffsetCurveBuilder(precisionModel, bufParams);

OffsetCurveSetBuilder curveSetBuilder = new OffsetCurveSetBuilder(g, distance, curveBuilder);
BufferCurveSetBuilder curveSetBuilder = new BufferCurveSetBuilder(g, distance, precisionModel, bufParams);
curveSetBuilder.setInvertOrientation(isInvertOrientation);

List bufferSegStrList = curveSetBuilder.getCurves();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import org.locationtech.jts.geom.Point;
import org.locationtech.jts.geom.Polygon;
import org.locationtech.jts.geom.Position;
import org.locationtech.jts.geom.PrecisionModel;
import org.locationtech.jts.geom.Triangle;
import org.locationtech.jts.geomgraph.Label;
import org.locationtech.jts.noding.NodedSegmentString;
Expand All @@ -44,7 +45,7 @@
*
* @version 1.7
*/
public class OffsetCurveSetBuilder {
public class BufferCurveSetBuilder {

private Geometry inputGeom;
private double distance;
Expand All @@ -54,14 +55,15 @@ public class OffsetCurveSetBuilder {

private boolean isInvertOrientation = false;

public OffsetCurveSetBuilder(
public BufferCurveSetBuilder(
Geometry inputGeom,
double distance,
OffsetCurveBuilder curveBuilder)
PrecisionModel precisionModel,
BufferParameters bufParams)
{
this.inputGeom = inputGeom;
this.distance = distance;
this.curveBuilder = curveBuilder;
this.curveBuilder = new OffsetCurveBuilder(precisionModel, bufParams);
}

/**
Expand Down
Loading

0 comments on commit 149b389

Please sign in to comment.