Search in sources :

Example 1 with QuadEdgeSubdivision

use of com.vividsolutions.jts.triangulate.quadedge.QuadEdgeSubdivision in project OpenTripPlanner by opentripplanner.

the class ConcaveHull method concaveHull.

/**
 * Create the concave hull.
 *
 * @return
 * 		the concave hull
 */
private Geometry concaveHull() {
    // triangulation: create a DelaunayTriangulationBuilder object
    ConformingDelaunayTriangulationBuilder cdtb = new ConformingDelaunayTriangulationBuilder();
    // add geometry collection
    cdtb.setSites(this.geometries);
    QuadEdgeSubdivision qes = cdtb.getSubdivision();
    Collection<QuadEdge> quadEdges = qes.getEdges();
    List<QuadEdgeTriangle> qeTriangles = QuadEdgeTriangle.createOn(qes);
    Collection<com.vividsolutions.jts.triangulate.quadedge.Vertex> qeVertices = qes.getVertices(false);
    int iV = 0;
    for (com.vividsolutions.jts.triangulate.quadedge.Vertex v : qeVertices) {
        this.coordinates.put(v.getCoordinate(), iV);
        this.vertices.put(iV, new Vertex(iV, v.getCoordinate()));
        iV++;
    }
    // border
    List<QuadEdge> qeFrameBorder = new ArrayList<QuadEdge>();
    List<QuadEdge> qeFrame = new ArrayList<QuadEdge>();
    List<QuadEdge> qeBorder = new ArrayList<QuadEdge>();
    for (QuadEdge qe : quadEdges) {
        if (qes.isFrameBorderEdge(qe)) {
            qeFrameBorder.add(qe);
        }
        if (qes.isFrameEdge(qe)) {
            qeFrame.add(qe);
        }
    }
    // border
    for (int j = 0; j < qeFrameBorder.size(); j++) {
        QuadEdge q = qeFrameBorder.get(j);
        if (!qeFrame.contains(q)) {
            qeBorder.add(q);
        }
    }
    // deletion of exterior edges
    for (QuadEdge qe : qeFrame) {
        qes.delete(qe);
    }
    HashMap<QuadEdge, Double> qeDistances = new HashMap<QuadEdge, Double>();
    for (QuadEdge qe : quadEdges) {
        qeDistances.put(qe, qe.toLineSegment().getLength());
    }
    DoubleComparator dc = new DoubleComparator(qeDistances);
    TreeMap<QuadEdge, Double> qeSorted = new TreeMap<QuadEdge, Double>(dc);
    qeSorted.putAll(qeDistances);
    // edges creation
    int i = 0;
    for (QuadEdge qe : qeSorted.keySet()) {
        LineSegment s = qe.toLineSegment();
        s.normalize();
        Integer idS = this.coordinates.get(s.p0);
        Integer idD = this.coordinates.get(s.p1);
        Vertex oV = this.vertices.get(idS);
        Vertex eV = this.vertices.get(idD);
        Edge edge;
        if (qeBorder.contains(qe)) {
            oV.setBorder(true);
            eV.setBorder(true);
            edge = new Edge(i, s, oV, eV, true);
            if (s.getLength() < this.threshold) {
                this.shortLengths.put(i, edge);
            } else {
                this.lengths.put(i, edge);
            }
        } else {
            edge = new Edge(i, s, oV, eV, false);
        }
        this.edges.put(i, edge);
        this.segments.put(s, i);
        i++;
    }
    // hm of linesegment and hm of edges // with id as key
    // hm of triangles using hm of ls and connection with hm of edges
    i = 0;
    for (QuadEdgeTriangle qet : qeTriangles) {
        LineSegment sA = qet.getEdge(0).toLineSegment();
        LineSegment sB = qet.getEdge(1).toLineSegment();
        LineSegment sC = qet.getEdge(2).toLineSegment();
        sA.normalize();
        sB.normalize();
        sC.normalize();
        Edge edgeA = this.edges.get(this.segments.get(sA));
        Edge edgeB = this.edges.get(this.segments.get(sB));
        Edge edgeC = this.edges.get(this.segments.get(sC));
        if (edgeA == null || edgeB == null || edgeC == null)
            continue;
        Triangle triangle = new Triangle(i, qet.isBorder() ? true : false);
        triangle.addEdge(edgeA);
        triangle.addEdge(edgeB);
        triangle.addEdge(edgeC);
        edgeA.addTriangle(triangle);
        edgeB.addTriangle(triangle);
        edgeC.addTriangle(triangle);
        this.triangles.put(i, triangle);
        i++;
    }
    // add triangle neighbourood
    for (Edge edge : this.edges.values()) {
        if (edge.getTriangles().size() > 1) {
            Triangle tA = edge.getTriangles().get(0);
            Triangle tB = edge.getTriangles().get(1);
            tA.addNeighbour(tB);
            tB.addNeighbour(tA);
        }
    }
    // concave hull algorithm
    int index = 0;
    while (index != -1) {
        index = -1;
        Edge e = null;
        // find the max length (smallest id so first entry)
        int si = this.lengths.size();
        if (si != 0) {
            Entry<Integer, Edge> entry = this.lengths.firstEntry();
            int ind = entry.getKey();
            if (entry.getValue().getGeometry().getLength() > this.threshold) {
                index = ind;
                e = entry.getValue();
            }
        }
        if (index != -1) {
            Triangle triangle = e.getTriangles().get(0);
            List<Triangle> neighbours = triangle.getNeighbours();
            // irregular triangle test
            if (neighbours.size() == 1) {
                this.shortLengths.put(e.getId(), e);
                this.lengths.remove(e.getId());
            } else {
                Edge e0 = triangle.getEdges().get(0);
                Edge e1 = triangle.getEdges().get(1);
                // test if all the vertices are on the border
                if (e0.getOV().isBorder() && e0.getEV().isBorder() && e1.getOV().isBorder() && e1.getEV().isBorder()) {
                    this.shortLengths.put(e.getId(), e);
                    this.lengths.remove(e.getId());
                } else {
                    // not sure this is safe
                    if (neighbours.size() < 1)
                        continue;
                    Triangle tA = neighbours.get(0);
                    Triangle tB = neighbours.get(1);
                    // FIXME not necessarily useful
                    tA.setBorder(true);
                    // FIXME not necessarily useful
                    tB.setBorder(true);
                    this.triangles.remove(triangle.getId());
                    tA.removeNeighbour(triangle);
                    tB.removeNeighbour(triangle);
                    // new edges
                    List<Edge> ee = triangle.getEdges();
                    Edge eA = ee.get(0);
                    Edge eB = ee.get(1);
                    Edge eC = ee.get(2);
                    if (eA.isBorder()) {
                        this.edges.remove(eA.getId());
                        eB.setBorder(true);
                        eB.getOV().setBorder(true);
                        eB.getEV().setBorder(true);
                        eC.setBorder(true);
                        eC.getOV().setBorder(true);
                        eC.getEV().setBorder(true);
                        // clean the relationships with the triangle
                        eB.removeTriangle(triangle);
                        eC.removeTriangle(triangle);
                        if (eB.getGeometry().getLength() < this.threshold) {
                            this.shortLengths.put(eB.getId(), eB);
                        } else {
                            this.lengths.put(eB.getId(), eB);
                        }
                        if (eC.getGeometry().getLength() < this.threshold) {
                            this.shortLengths.put(eC.getId(), eC);
                        } else {
                            this.lengths.put(eC.getId(), eC);
                        }
                        this.lengths.remove(eA.getId());
                    } else if (eB.isBorder()) {
                        this.edges.remove(eB.getId());
                        eA.setBorder(true);
                        eA.getOV().setBorder(true);
                        eA.getEV().setBorder(true);
                        eC.setBorder(true);
                        eC.getOV().setBorder(true);
                        eC.getEV().setBorder(true);
                        // clean the relationships with the triangle
                        eA.removeTriangle(triangle);
                        eC.removeTriangle(triangle);
                        if (eA.getGeometry().getLength() < this.threshold) {
                            this.shortLengths.put(eA.getId(), eA);
                        } else {
                            this.lengths.put(eA.getId(), eA);
                        }
                        if (eC.getGeometry().getLength() < this.threshold) {
                            this.shortLengths.put(eC.getId(), eC);
                        } else {
                            this.lengths.put(eC.getId(), eC);
                        }
                        this.lengths.remove(eB.getId());
                    } else {
                        this.edges.remove(eC.getId());
                        eA.setBorder(true);
                        eA.getOV().setBorder(true);
                        eA.getEV().setBorder(true);
                        eB.setBorder(true);
                        eB.getOV().setBorder(true);
                        eB.getEV().setBorder(true);
                        // clean the relationships with the triangle
                        eA.removeTriangle(triangle);
                        eB.removeTriangle(triangle);
                        if (eA.getGeometry().getLength() < this.threshold) {
                            this.shortLengths.put(eA.getId(), eA);
                        } else {
                            this.lengths.put(eA.getId(), eA);
                        }
                        if (eB.getGeometry().getLength() < this.threshold) {
                            this.shortLengths.put(eB.getId(), eB);
                        } else {
                            this.lengths.put(eB.getId(), eB);
                        }
                        this.lengths.remove(eC.getId());
                    }
                }
            }
        }
    }
    // concave hull creation
    List<LineString> edges = new ArrayList<LineString>();
    for (Edge e : this.lengths.values()) {
        LineString l = e.getGeometry().toGeometry(this.geomFactory);
        edges.add(l);
    }
    for (Edge e : this.shortLengths.values()) {
        LineString l = e.getGeometry().toGeometry(this.geomFactory);
        edges.add(l);
    }
    // merge
    LineMerger lineMerger = new LineMerger();
    lineMerger.add(edges);
    LineString merge = (LineString) lineMerger.getMergedLineStrings().iterator().next();
    if (merge.isRing()) {
        LinearRing lr = new LinearRing(merge.getCoordinateSequence(), this.geomFactory);
        Polygon concaveHull = new Polygon(lr, null, this.geomFactory);
        return concaveHull;
    }
    return merge;
}
Also used : Vertex(org.opensphere.geometry.triangulation.model.Vertex) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) QuadEdgeTriangle(com.vividsolutions.jts.triangulate.quadedge.QuadEdgeTriangle) Triangle(org.opensphere.geometry.triangulation.model.Triangle) ConformingDelaunayTriangulationBuilder(com.vividsolutions.jts.triangulate.ConformingDelaunayTriangulationBuilder) Polygon(com.vividsolutions.jts.geom.Polygon) LineSegment(com.vividsolutions.jts.geom.LineSegment) QuadEdge(com.vividsolutions.jts.triangulate.quadedge.QuadEdge) QuadEdgeTriangle(com.vividsolutions.jts.triangulate.quadedge.QuadEdgeTriangle) DoubleComparator(org.opensphere.geometry.triangulation.DoubleComparator) TreeMap(java.util.TreeMap) QuadEdgeSubdivision(com.vividsolutions.jts.triangulate.quadedge.QuadEdgeSubdivision) Point(com.vividsolutions.jts.geom.Point) LineMerger(com.vividsolutions.jts.operation.linemerge.LineMerger) LineString(com.vividsolutions.jts.geom.LineString) LinearRing(com.vividsolutions.jts.geom.LinearRing) QuadEdge(com.vividsolutions.jts.triangulate.quadedge.QuadEdge) Edge(org.opensphere.geometry.triangulation.model.Edge)

Example 2 with QuadEdgeSubdivision

use of com.vividsolutions.jts.triangulate.quadedge.QuadEdgeSubdivision in project graphhopper by graphhopper.

the class FakeWalkNetworkBuilder method buildWalkNetwork.

static void buildWalkNetwork(Collection<GTFSFeed> feeds, GraphHopperStorage graph, PtFlagEncoder encoder, DistanceCalc distCalc) {
    Collection<ConstraintVertex> sites = new ArrayList<>();
    Map<Vertex, Integer> vertex2nodeId = new HashMap<>();
    feeds.stream().flatMap(feed -> feed.stops.values().stream()).forEach(stop -> {
        int i = graph.getNodes();
        graph.getNodeAccess().setNode(i++, stop.stop_lat, stop.stop_lon);
        ConstraintVertex site = new ConstraintVertex(new Coordinate(stop.stop_lon, stop.stop_lat));
        sites.add(site);
        vertex2nodeId.put(site, i - 1);
    });
    ConformingDelaunayTriangulator conformingDelaunayTriangulator = new ConformingDelaunayTriangulator(sites, 0.0);
    conformingDelaunayTriangulator.setConstraints(new ArrayList(), new ArrayList());
    conformingDelaunayTriangulator.formInitialDelaunay();
    QuadEdgeSubdivision tin = conformingDelaunayTriangulator.getSubdivision();
    List<QuadEdge> edges = tin.getPrimaryEdges(false);
    for (QuadEdge edge : edges) {
        EdgeIteratorState ghEdge = graph.edge(vertex2nodeId.get(edge.orig()), vertex2nodeId.get(edge.dest()));
        double distance = distCalc.calcDist(edge.orig().getY(), edge.orig().getX(), edge.dest().getY(), edge.dest().getX());
        ghEdge.setDistance(distance);
        ghEdge.setFlags(encoder.setSpeed(ghEdge.getFlags(), 5.0));
        ghEdge.setFlags(encoder.setAccess(ghEdge.getFlags(), true, true));
    }
}
Also used : GraphHopperStorage(com.graphhopper.storage.GraphHopperStorage) Coordinate(com.vividsolutions.jts.geom.Coordinate) QuadEdge(com.vividsolutions.jts.triangulate.quadedge.QuadEdge) java.util(java.util) EdgeIteratorState(com.graphhopper.util.EdgeIteratorState) ConformingDelaunayTriangulator(com.vividsolutions.jts.triangulate.ConformingDelaunayTriangulator) ConstraintVertex(com.vividsolutions.jts.triangulate.ConstraintVertex) Vertex(com.vividsolutions.jts.triangulate.quadedge.Vertex) GTFSFeed(com.conveyal.gtfs.GTFSFeed) DistanceCalc(com.graphhopper.util.DistanceCalc) QuadEdgeSubdivision(com.vividsolutions.jts.triangulate.quadedge.QuadEdgeSubdivision) ConstraintVertex(com.vividsolutions.jts.triangulate.ConstraintVertex) Vertex(com.vividsolutions.jts.triangulate.quadedge.Vertex) QuadEdge(com.vividsolutions.jts.triangulate.quadedge.QuadEdge) ConformingDelaunayTriangulator(com.vividsolutions.jts.triangulate.ConformingDelaunayTriangulator) QuadEdgeSubdivision(com.vividsolutions.jts.triangulate.quadedge.QuadEdgeSubdivision) ConstraintVertex(com.vividsolutions.jts.triangulate.ConstraintVertex) Coordinate(com.vividsolutions.jts.geom.Coordinate) EdgeIteratorState(com.graphhopper.util.EdgeIteratorState)

Aggregations

QuadEdge (com.vividsolutions.jts.triangulate.quadedge.QuadEdge)2 QuadEdgeSubdivision (com.vividsolutions.jts.triangulate.quadedge.QuadEdgeSubdivision)2 GTFSFeed (com.conveyal.gtfs.GTFSFeed)1 GraphHopperStorage (com.graphhopper.storage.GraphHopperStorage)1 DistanceCalc (com.graphhopper.util.DistanceCalc)1 EdgeIteratorState (com.graphhopper.util.EdgeIteratorState)1 Coordinate (com.vividsolutions.jts.geom.Coordinate)1 LineSegment (com.vividsolutions.jts.geom.LineSegment)1 LineString (com.vividsolutions.jts.geom.LineString)1 LinearRing (com.vividsolutions.jts.geom.LinearRing)1 Point (com.vividsolutions.jts.geom.Point)1 Polygon (com.vividsolutions.jts.geom.Polygon)1 LineMerger (com.vividsolutions.jts.operation.linemerge.LineMerger)1 ConformingDelaunayTriangulationBuilder (com.vividsolutions.jts.triangulate.ConformingDelaunayTriangulationBuilder)1 ConformingDelaunayTriangulator (com.vividsolutions.jts.triangulate.ConformingDelaunayTriangulator)1 ConstraintVertex (com.vividsolutions.jts.triangulate.ConstraintVertex)1 QuadEdgeTriangle (com.vividsolutions.jts.triangulate.quadedge.QuadEdgeTriangle)1 Vertex (com.vividsolutions.jts.triangulate.quadedge.Vertex)1 java.util (java.util)1 ArrayList (java.util.ArrayList)1