Martin,

For my case (near enough right angled corners) it works quite well.
Performance isn't too much of an issue as it only gets run a few times
and comparing that with downloading extra data from the DB it's negligible.

I just knocked together some code below to test it out, feel free to use
any of this, there are a bunch of utility methods and a class to visit
each segment of the line strings.

Paul

  public static Polygon getMitredBuffer(final Polygon polygon,
    final double distance) {
    Geometry buffer = polygon;
    LineString exteriorRing = polygon.getExteriorRing();
    Geometry exteriorBuffer = getMitredBuffer(exteriorRing, distance);
    buffer = buffer.union(exteriorBuffer);
    for (int i = 0; i < polygon.getNumInteriorRing(); i++) {
      LineString ring = polygon.getInteriorRingN(i);
      Geometry bufferedRing = getMitredBuffer(ring, distance);
      buffer = buffer.union(bufferedRing);
    }
    return (Polygon)buffer;
  }

  public static Polygon getMitredBuffer(final LineString lineString,
    final double distance) {
    LineStringMitredBuffer visitor = new LineStringMitredBuffer(distance);
    visitLineSegments(lineString.getCoordinateSequence(), visitor);
    return visitor.getBuffer();
  }

  public static Polygon getMitredBuffer(final LineSegment segment,
    final double distance) {

    double angle = segment.angle();
    LineSegment extendedSegment = addLength(segment, distance, distance);
    LineSegment clockwiseSegment = offset(extendedSegment, distance, 
Angle.CLOCKWISE);
    LineSegment counterClockwiseSegment = offset(extendedSegment, distance,
      Angle.COUNTERCLOCKWISE);

    Coordinate[] coords = new Coordinate[] {
      clockwiseSegment.p0, clockwiseSegment.p1, counterClockwiseSegment.p1,
      counterClockwiseSegment.p0, clockwiseSegment.p0
    };
    GeometryFactory factory = new GeometryFactory();
    LinearRing exteriorRing = factory.createLinearRing(coords);
    return factory.createPolygon(exteriorRing, null);
  }


  public static LineSegment offset(final LineSegment line,
    final double distance, final int orientation) {
    double angle = line.angle();
    if (orientation == Angle.CLOCKWISE) {
      angle -= Angle.PI_OVER_2;
    } else {
      angle += Angle.PI_OVER_2;
    }
    Coordinate c1 = offset(line.p0, angle, distance);
    Coordinate c2 = offset(line.p1, angle, distance);
    return new LineSegment(c1, c2);
  }

  public static Coordinate offset(final Coordinate coordinate,
    final double angle, final double distance) {
    double newX = coordinate.x + distance * Math.cos(angle);
    double newY = coordinate.y + distance * Math.sin(angle);
    Coordinate newCoordinate = new Coordinate(newX, newY);
    return newCoordinate;

  }

  public static LineSegment addLength(final LineSegment line,
    final double startDistance, final double endDistance) {
    double angle = line.angle();
    Coordinate c1 = offset(line.p0, angle, -startDistance);
    Coordinate c2 = offset(line.p1, angle, endDistance);
    return new LineSegment(c1, c2);

  }


  public static void visitLineSegments(final CoordinateSequence coords,
    final LineSegmentVistor visitor) {
    Coordinate previousCoordinate = coords.getCoordinate(0);
    for (int i = 1; i < coords.size(); i++) {
      Coordinate coordinate = coords.getCoordinate(i);
      LineSegment segment = new LineSegment(previousCoordinate, coordinate);
      if (segment.getLength() > 0) {
        if (!visitor.visit(segment)) {
          return;
        }
      }
      previousCoordinate = coordinate;
    }
  }


public class LineStringMitredBuffer implements LineSegmentVistor {
  private Polygon buffer;

  private double distance;

  public LineStringMitredBuffer(double distance) {
    this.distance = distance;
  }

  public boolean visit(LineSegment segment) {
    Polygon segmentBuffer = JtsGeometryUtil.getMitredBuffer(segment, distance);
    if (buffer == null) {
      buffer = segmentBuffer;
    } else {
      buffer = (Polygon)buffer.union(segmentBuffer);
    }
    return true;
  }

  /**
   * @return the buffer
   */
  public Polygon getBuffer() {
    return buffer;
  }

}




Martin Davis wrote:
> Paul,
>
> Actually on second thought this might not give you what you want.  The
> problem will be when you union two line segments which aren't at right
> angles to each other - the square ends won't match up smoothly.
>
> I'd try it manually in JUMP first, anyway, just to see what's going to
> happen.
>
> I'm going to try and look at how easy this would be to add to the code
> base - it shouldn't be too hard to implement.
>
> Paul Austin wrote:

_______________________________________________
jts-devel mailing list
[email protected]
http://lists.refractions.net/mailman/listinfo/jts-devel

Reply via email to