Search in sources :

Example 56 with Point

use of com.revolsys.geometry.model.Point in project com.revolsys.open by revolsys.

the class LineMergeGraph method addEdge.

/**
 * Adds an Edge, DirectedEdges, and Nodes for the given LineString representation
 * of an edge.
 * Empty lines or lines with all coordinates equal are not added.
 *
 * @param line the linestring to add to the graph
 */
public void addEdge(final LineString line) {
    if (line.isEmpty()) {
        return;
    }
    final LineString points = line.removeDuplicatePoints();
    final int vertexCount = points.getVertexCount();
    if (vertexCount > 1) {
        final Point fromPoint = points.getPoint(0);
        final Point toPoint = points.getPoint(vertexCount - 1);
        final Node startNode = getNode(fromPoint);
        final Node endNode = getNode(toPoint);
        final DirectedEdge directedEdge0 = new LineMergeDirectedEdge(startNode, endNode, points.getPoint(1).newPoint(), true);
        final DirectedEdge directedEdge1 = new LineMergeDirectedEdge(endNode, startNode, points.getPoint(vertexCount - 2).newPoint(), false);
        final Edge edge = new LineMergeEdge(line);
        edge.setDirectedEdges(directedEdge0, directedEdge1);
        add(edge);
    }
}
Also used : DirectedEdge(com.revolsys.geometry.planargraph.DirectedEdge) LineString(com.revolsys.geometry.model.LineString) Node(com.revolsys.geometry.planargraph.Node) Point(com.revolsys.geometry.model.Point) DirectedEdge(com.revolsys.geometry.planargraph.DirectedEdge) Edge(com.revolsys.geometry.planargraph.Edge) Point(com.revolsys.geometry.model.Point)

Example 57 with Point

use of com.revolsys.geometry.model.Point in project com.revolsys.open by revolsys.

the class LineSequencer method isSequenced.

/**
 * Tests whether a {@link Geometry} is sequenced correctly.
 * {@link LineString}s are trivially sequenced.
 * {@link Lineal}s are checked for correct sequencing.
 * Otherwise, <code>isSequenced</code> is defined
 * to be <code>true</code> for geometries that are not lineal.
 *
 * @param geom the geometry to test
 * @return <code>true</code> if the geometry is sequenced or is not lineal
 */
public static boolean isSequenced(final Geometry geom) {
    if (!(geom instanceof Lineal) || geom instanceof LineString) {
        return true;
    }
    final Lineal lineal = (Lineal) geom;
    // the nodes in all subgraphs which have been completely scanned
    final Set prevSubgraphNodes = new TreeSet();
    Point lastNode = null;
    final List currNodes = new ArrayList();
    for (int i = 0; i < lineal.getGeometryCount(); i++) {
        final LineString line = (LineString) lineal.getGeometry(i);
        final Point startNode = line.getPoint(0);
        final Point endNode = line.getPoint(line.getVertexCount() - 1);
        /**
         * If this linestring is connected to a previous subgraph, geom is not sequenced
         */
        if (prevSubgraphNodes.contains(startNode)) {
            return false;
        }
        if (prevSubgraphNodes.contains(endNode)) {
            return false;
        }
        if (lastNode != null) {
            if (!startNode.equals(lastNode)) {
                // start new connected sequence
                prevSubgraphNodes.addAll(currNodes);
                currNodes.clear();
            }
        }
        currNodes.add(startNode);
        currNodes.add(endNode);
        lastNode = endNode;
    }
    return true;
}
Also used : Set(java.util.Set) TreeSet(java.util.TreeSet) Lineal(com.revolsys.geometry.model.Lineal) LineString(com.revolsys.geometry.model.LineString) TreeSet(java.util.TreeSet) ArrayList(java.util.ArrayList) ArrayList(java.util.ArrayList) List(java.util.List) LinkedList(java.util.LinkedList) Point(com.revolsys.geometry.model.Point) Point(com.revolsys.geometry.model.Point)

Example 58 with Point

use of com.revolsys.geometry.model.Point in project com.revolsys.open by revolsys.

the class OffsetSegmentGenerator method addInsideTurn.

/**
 * Adds the offset points for an inside (concave) turn.
 *
 * @param orientation
 * @param addStartPoint
 */
private void addInsideTurn(final int orientation, final boolean addStartPoint) {
    final double x00 = this.offset0.getX(0);
    final double y00 = this.offset0.getY(0);
    final double x01 = this.offset0.getX(1);
    final double y01 = this.offset0.getY(1);
    final double x10 = this.offset1.getX(0);
    final double y10 = this.offset1.getY(0);
    final double x11 = this.offset1.getX(1);
    final double y11 = this.offset1.getY(1);
    /**
     * add intersection point of offset segments (if any)
     */
    this.li.computeIntersection(x00, y00, x01, y01, x10, y10, x11, y11);
    if (this.li.hasIntersection()) {
        final Point intersection = this.li.getIntersection(0);
        final double intersectionX = intersection.getX();
        final double intersectionY = intersection.getY();
        this.segList.addPoint(intersectionX, intersectionY);
    } else {
        /**
         * If no intersection is detected,
         * it means the angle is so small and/or the offset so
         * large that the offsets segments don't intersect.
         * In this case we must
         * add a "closing segment" to make sure the buffer curve is continuous,
         * fairly smooth (e.g. no sharp reversals in direction)
         * and tracks the buffer correctly around the corner. The curve connects
         * the endpoints of the segment offsets to points
         * which lie toward the centre point of the corner.
         * The joining curve will not appear in the final buffer outline, since it
         * is completely internal to the buffer polygon.
         *
         * In complex buffer cases the closing segment may cut across many other
         * segments in the generated offset curve.  In order to improve the
         * performance of the noding, the closing segment should be kept as short as possible.
         * (But not too short, since that would defeat its purpose).
         * This is the purpose of the closingSegFactor heuristic value.
         */
        /**
         * The intersection test above is vulnerable to robustness errors; i.e. it
         * may be that the offsets should intersect very close to their endpoints,
         * but aren't reported as such due to rounding. To handle this situation
         * appropriately, we use the following test: If the offset points are very
         * close, don't add closing segments but simply use one of the offset
         * points
         */
        this.hasNarrowConcaveAngle = true;
        if (MathUtil.distance(x01, y01, x10, y10) < this.distance * INSIDE_TURN_VERTEX_SNAP_DISTANCE_FACTOR) {
            this.segList.addPoint(x01, y01);
        } else {
            // add endpoint of this segment offset
            this.segList.addPoint(x01, y01);
            /**
             * Add "closing segment" of required length.
             */
            if (this.closingSegLengthFactor > 0) {
                final double midX0 = (this.closingSegLengthFactor * x01 + this.s1X) / (this.closingSegLengthFactor + 1);
                final double midY0 = (this.closingSegLengthFactor * y01 + this.s1Y) / (this.closingSegLengthFactor + 1);
                this.segList.addPoint(midX0, midY0);
                final double midX1 = (this.closingSegLengthFactor * x10 + this.s1X) / (this.closingSegLengthFactor + 1);
                final double midY1 = (this.closingSegLengthFactor * y10 + this.s1Y) / (this.closingSegLengthFactor + 1);
                this.segList.addPoint(midX1, midY1);
            } else {
                /**
                 * This branch is not expected to be used except for testing purposes.
                 * It is equivalent to the JTS 1.9 logic for closing segments
                 * (which results in very poor performance for large buffer distances)
                 */
                this.segList.addPoint(this.s1X, this.s1Y);
            }
            // */
            // add start point of next segment offset
            this.segList.addPoint(x10, y10);
        }
    }
}
Also used : Point(com.revolsys.geometry.model.Point)

Example 59 with Point

use of com.revolsys.geometry.model.Point in project com.revolsys.open by revolsys.

the class OffsetSegmentGenerator method addLimitedMitreJoin.

/**
 * Adds a limited mitre join connecting the two reflex offset segments.
 * A limited mitre is a mitre which is beveled at the distance
 * determined by the mitre ratio limit.
 *
 * @param offset0 the first offset segment
 * @param offset1 the second offset segment
 * @param distance the offset distance
 * @param mitreLimit the mitre limit ratio
 */
private void addLimitedMitreJoin(final LineSegment offset0, final LineSegment offset1, final double distance, final double mitreLimit) {
    final double basePtX = this.s1X;
    final double basePtY = this.s1Y;
    final double ang0 = Angle.angle2d(basePtX, basePtY, this.s0X, this.s0Y);
    final double ang2 = Angle.angle2d(basePtX, basePtY, this.s2X, this.s2Y);
    // oriented angle between segments
    final double angDiff = Angle.angleBetweenOriented(ang0, ang2);
    // half of the interior angle
    final double angDiffHalf = angDiff / 2;
    // angle for bisector of the interior angle between the segments
    final double midAng = Angle.normalize(ang0 + angDiffHalf);
    // rotating this by PI gives the bisector of the reflex angle
    final double mitreMidAng = Angle.normalize(midAng + Math.PI);
    // the miterLimit determines the distance to the mitre bevel
    final double mitreDist = mitreLimit * distance;
    // the bevel delta is the difference between the buffer distance
    // and half of the length of the bevel segment
    final double bevelDelta = mitreDist * Math.abs(Math.sin(angDiffHalf));
    final double bevelHalfLen = distance - bevelDelta;
    // compute the midpoint of the bevel segment
    final double bevelMidX = basePtX + mitreDist * Math.cos(mitreMidAng);
    final double bevelMidY = basePtY + mitreDist * Math.sin(mitreMidAng);
    // compute the mitre midline segment from the corner point to the bevel
    // segment midpoint
    final LineSegment mitreMidLine = new LineSegmentDouble(2, basePtX, basePtY, bevelMidX, bevelMidY);
    // finally the bevel segment endpoints are computed as offsets from
    // the mitre midline
    final Point bevelEndLeft = mitreMidLine.pointAlongOffset(1.0, bevelHalfLen);
    final Point bevelEndRight = mitreMidLine.pointAlongOffset(1.0, -bevelHalfLen);
    if (this.side == Position.LEFT) {
        this.segList.addPoint(bevelEndLeft);
        this.segList.addPoint(bevelEndRight);
    } else {
        this.segList.addPoint(bevelEndRight);
        this.segList.addPoint(bevelEndLeft);
    }
}
Also used : LineSegmentDouble(com.revolsys.geometry.model.segment.LineSegmentDouble) Point(com.revolsys.geometry.model.Point) LineSegment(com.revolsys.geometry.model.segment.LineSegment)

Example 60 with Point

use of com.revolsys.geometry.model.Point in project com.revolsys.open by revolsys.

the class OffsetSegmentGenerator method addMitreJoin.

/**
 * Adds a mitre join connecting the two reflex offset segments.
 * The mitre will be beveled if it exceeds the mitre ratio limit.
 *
 * @param offset0 the first offset segment
 * @param offset1 the second offset segment
 * @param distance the offset distance
 */
private void addMitreJoin(final double x, final double y, final LineSegment offset0, final LineSegment offset1, final double distance) {
    boolean isMitreWithinLimit = true;
    double intPtX = 0;
    double intPtY = 0;
    /**
     * This computation is unstable if the offset segments are nearly collinear.
     * Howver, this situation should have been eliminated earlier by the check for
     * whether the offset segment endpoints are almost coincident
     */
    try {
        final double line1x1 = offset0.getX(0);
        final double line1y1 = offset0.getY(0);
        final double line1x2 = offset0.getX(1);
        final double line1y2 = offset0.getY(1);
        final double line2x1 = offset1.getX(0);
        final double line2y1 = offset1.getY(0);
        final double line2x2 = offset1.getX(1);
        final double line2y2 = offset1.getY(1);
        final Point intersection = HCoordinate.intersection(line1x1, line1y1, line1x2, line1y2, line2x1, line2y1, line2x2, line2y2);
        intPtX = intersection.getX();
        intPtY = intersection.getY();
        final double mitreRatio;
        if (distance <= 0.0) {
            mitreRatio = 1;
        } else {
            mitreRatio = MathUtil.distance(intPtX, intPtY, x, y) / Math.abs(distance);
        }
        if (mitreRatio > this.bufParams.getMitreLimit()) {
            isMitreWithinLimit = false;
        }
    } catch (final NotRepresentableException ex) {
        isMitreWithinLimit = false;
    }
    if (isMitreWithinLimit) {
        this.segList.addPoint(intPtX, intPtY);
    } else {
        addLimitedMitreJoin(offset0, offset1, distance, this.bufParams.getMitreLimit());
    }
}
Also used : NotRepresentableException(com.revolsys.geometry.algorithm.NotRepresentableException) Point(com.revolsys.geometry.model.Point)

Aggregations

Point (com.revolsys.geometry.model.Point)669 LineString (com.revolsys.geometry.model.LineString)130 GeometryFactory (com.revolsys.geometry.model.GeometryFactory)103 Geometry (com.revolsys.geometry.model.Geometry)95 PointDoubleXY (com.revolsys.geometry.model.impl.PointDoubleXY)90 ArrayList (java.util.ArrayList)79 BoundingBox (com.revolsys.geometry.model.BoundingBox)51 Polygon (com.revolsys.geometry.model.Polygon)42 LineSegment (com.revolsys.geometry.model.segment.LineSegment)34 List (java.util.List)28 LinearRing (com.revolsys.geometry.model.LinearRing)26 PointDouble (com.revolsys.geometry.model.impl.PointDouble)22 PointDoubleXYZ (com.revolsys.geometry.model.impl.PointDoubleXYZ)19 Edge (com.revolsys.geometry.graph.Edge)18 Test (org.junit.Test)17 Punctual (com.revolsys.geometry.model.Punctual)16 Segment (com.revolsys.geometry.model.segment.Segment)15 Vertex (com.revolsys.geometry.model.vertex.Vertex)15 Record (com.revolsys.record.Record)15 Lineal (com.revolsys.geometry.model.Lineal)14