com.hazelcast.shaded.org.locationtech.jts.geomgraph.EdgeRing Maven / Gradle / Ivy
/*
* Copyright (c) 2016 Vivid Solutions.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* and Eclipse Distribution License v. 1.0 which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v20.html
* and the Eclipse Distribution License is available at
*
* http://www.eclipse.org/org/documents/edl-v10.php.
*/
package com.hazelcast.shaded.org.locationtech.jts.geomgraph;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import com.hazelcast.shaded.org.locationtech.jts.algorithm.Orientation;
import com.hazelcast.shaded.org.locationtech.jts.algorithm.PointLocation;
import com.hazelcast.shaded.org.locationtech.jts.geom.Coordinate;
import com.hazelcast.shaded.org.locationtech.jts.geom.Envelope;
import com.hazelcast.shaded.org.locationtech.jts.geom.GeometryFactory;
import com.hazelcast.shaded.org.locationtech.jts.geom.LinearRing;
import com.hazelcast.shaded.org.locationtech.jts.geom.Location;
import com.hazelcast.shaded.org.locationtech.jts.geom.Polygon;
import com.hazelcast.shaded.org.locationtech.jts.geom.Position;
import com.hazelcast.shaded.org.locationtech.jts.geom.TopologyException;
import com.hazelcast.shaded.org.locationtech.jts.util.Assert;
/**
* @version 1.7
*/
public abstract class EdgeRing {
protected DirectedEdge startDe; // the directed edge which starts the list of edges for this EdgeRing
private int maxNodeDegree = -1;
private List edges = new ArrayList(); // the DirectedEdges making up this EdgeRing
private List pts = new ArrayList();
private Label label = new Label(Location.NONE); // label stores the locations of each geometry on the face surrounded by this ring
private LinearRing ring; // the ring created for this EdgeRing
private boolean isHole;
private EdgeRing shell; // if non-null, the ring is a hole and this EdgeRing is its containing shell
private ArrayList holes = new ArrayList(); // a list of EdgeRings which are holes in this EdgeRing
protected GeometryFactory geometryFactory;
public EdgeRing(DirectedEdge start, GeometryFactory geometryFactory) {
this.geometryFactory = geometryFactory;
computePoints(start);
computeRing();
}
public boolean isIsolated()
{
return (label.getGeometryCount() == 1);
}
public boolean isHole()
{
//computePoints();
return isHole;
}
public Coordinate getCoordinate(int i) { return (Coordinate) pts.get(i); }
public LinearRing getLinearRing() { return ring; }
public Label getLabel() { return label; }
public boolean isShell() { return shell == null; }
public EdgeRing getShell() { return shell; }
public void setShell(EdgeRing shell)
{
this.shell = shell;
if (shell != null) shell.addHole(this);
}
public void addHole(EdgeRing ring) { holes.add(ring); }
public Polygon toPolygon(GeometryFactory geometryFactory)
{
LinearRing[] holeLR = new LinearRing[holes.size()];
for (int i = 0; i < holes.size(); i++) {
holeLR[i] = ((EdgeRing) holes.get(i)).getLinearRing();
}
Polygon poly = geometryFactory.createPolygon(getLinearRing(), holeLR);
return poly;
}
/**
* Compute a LinearRing from the point list previously collected.
* Test if the ring is a hole (i.e. if it is CCW) and set the hole flag
* accordingly.
*/
public void computeRing()
{
if (ring != null) return; // don't compute more than once
Coordinate[] coord = new Coordinate[pts.size()];
for (int i = 0; i < pts.size(); i++) {
coord[i] = (Coordinate) pts.get(i);
}
ring = geometryFactory.createLinearRing(coord);
isHole = Orientation.isCCW(ring.getCoordinates());
//Debug.println( (isHole ? "hole - " : "shell - ") + WKTWriter.toLineString(new CoordinateArraySequence(ring.getCoordinates())));
}
abstract public DirectedEdge getNext(DirectedEdge de);
abstract public void setEdgeRing(DirectedEdge de, EdgeRing er);
/**
* Returns the list of DirectedEdges that make up this EdgeRing
*
* @return List of DirectedEdges
*/
public List getEdges() { return edges; }
/**
* Collect all the points from the DirectedEdges of this ring into a contiguous list
*/
protected void computePoints(DirectedEdge start)
{
//System.out.println("buildRing");
startDe = start;
DirectedEdge de = start;
boolean isFirstEdge = true;
do {
// Assert.isTrue(de != null, "found null Directed Edge");
if (de == null)
throw new TopologyException("Found null DirectedEdge");
if (de.getEdgeRing() == this)
throw new TopologyException("Directed Edge visited twice during ring-building at " + de.getCoordinate());
edges.add(de);
//Debug.println(de);
//Debug.println(de.getEdge());
Label label = de.getLabel();
Assert.isTrue(label.isArea());
mergeLabel(label);
addPoints(de.getEdge(), de.isForward(), isFirstEdge);
isFirstEdge = false;
setEdgeRing(de, this);
de = getNext(de);
} while (de != startDe);
}
public int getMaxNodeDegree()
{
if (maxNodeDegree < 0) computeMaxNodeDegree();
return maxNodeDegree;
}
private void computeMaxNodeDegree()
{
maxNodeDegree = 0;
DirectedEdge de = startDe;
do {
Node node = de.getNode();
int degree = ((DirectedEdgeStar) node.getEdges()).getOutgoingDegree(this);
if (degree > maxNodeDegree) maxNodeDegree = degree;
de = getNext(de);
} while (de != startDe);
maxNodeDegree *= 2;
}
public void setInResult()
{
DirectedEdge de = startDe;
do {
de.getEdge().setInResult(true);
de = de.getNext();
} while (de != startDe);
}
protected void mergeLabel(Label deLabel)
{
mergeLabel(deLabel, 0);
mergeLabel(deLabel, 1);
}
/**
* Merge the RHS label from a DirectedEdge into the label for this EdgeRing.
* The DirectedEdge label may be null. This is acceptable - it results
* from a node which is NOT an intersection node between the Geometries
* (e.g. the end node of a LinearRing). In this case the DirectedEdge label
* does not contribute any information to the overall labelling, and is simply skipped.
*/
protected void mergeLabel(Label deLabel, int geomIndex)
{
int loc = deLabel.getLocation(geomIndex, Position.RIGHT);
// no information to be had from this label
if (loc == Location.NONE) return;
// if there is no current RHS value, set it
if (label.getLocation(geomIndex) == Location.NONE) {
label.setLocation(geomIndex, loc);
return;
}
}
protected void addPoints(Edge edge, boolean isForward, boolean isFirstEdge)
{
Coordinate[] edgePts = edge.getCoordinates();
if (isForward) {
int startIndex = 1;
if (isFirstEdge) startIndex = 0;
for (int i = startIndex; i < edgePts.length; i++) {
pts.add(edgePts[i]);
}
}
else { // is backward
int startIndex = edgePts.length - 2;
if (isFirstEdge) startIndex = edgePts.length - 1;
for (int i = startIndex; i >= 0; i--) {
pts.add(edgePts[i]);
}
}
}
/**
* This method will cause the ring to be computed.
* It will also check any holes, if they have been assigned.
*
* @param p point
* @return true of ring contains point
*/
public boolean containsPoint(Coordinate p)
{
LinearRing shell = getLinearRing();
Envelope env = shell.getEnvelopeInternal();
if (! env.contains(p)) return false;
if (! PointLocation.isInRing(p, shell.getCoordinates()) ) return false;
for (Iterator i = holes.iterator(); i.hasNext(); ) {
EdgeRing hole = (EdgeRing) i.next();
if (hole.containsPoint(p) )
return false;
}
return true;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy