com.vividsolutions.jts.operation.relate.EdgeEndBundle Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of JTSplus Show documentation
Show all versions of JTSplus Show documentation
JTS Topology Suite 1.14 with additional functions for GeoSpark
/*
* The JTS Topology Suite is a collection of Java classes that
* implement the fundamental operations required to validate a given
* geo-spatial data set to a known topological specification.
*
* Copyright (C) 2001 Vivid Solutions
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* For more information, contact:
*
* Vivid Solutions
* Suite #1A
* 2328 Government Street
* Victoria BC V8T 5G5
* Canada
*
* (250)385-6040
* www.vividsolutions.com
*/
package com.vividsolutions.jts.operation.relate;
import java.io.PrintStream;
import java.util.*;
import com.vividsolutions.jts.geom.*;
import com.vividsolutions.jts.geomgraph.*;
import com.vividsolutions.jts.util.Assert;
import com.vividsolutions.jts.algorithm.BoundaryNodeRule;
/**
* A collection of {@link EdgeEnd}s which obey the following invariant:
* They originate at the same node and have the same direction.
*
* @version 1.7
*/
public class EdgeEndBundle
extends EdgeEnd
{
// private BoundaryNodeRule boundaryNodeRule;
private List edgeEnds = new ArrayList();
public EdgeEndBundle(BoundaryNodeRule boundaryNodeRule, EdgeEnd e)
{
super(e.getEdge(), e.getCoordinate(), e.getDirectedCoordinate(), new Label(e.getLabel()));
insert(e);
/*
if (boundaryNodeRule != null)
this.boundaryNodeRule = boundaryNodeRule;
else
boundaryNodeRule = BoundaryNodeRule.OGC_SFS_BOUNDARY_RULE;
*/
}
public EdgeEndBundle(EdgeEnd e)
{
this(null, e);
}
public Label getLabel() { return label; }
public Iterator iterator() { return edgeEnds.iterator(); }
public List getEdgeEnds() { return edgeEnds; }
public void insert(EdgeEnd e)
{
// Assert: start point is the same
// Assert: direction is the same
edgeEnds.add(e);
}
/**
* This computes the overall edge label for the set of
* edges in this EdgeStubBundle. It essentially merges
* the ON and side labels for each edge. These labels must be compatible
*/
public void computeLabel(BoundaryNodeRule boundaryNodeRule)
{
// create the label. If any of the edges belong to areas,
// the label must be an area label
boolean isArea = false;
for (Iterator it = iterator(); it.hasNext(); ) {
EdgeEnd e = (EdgeEnd) it.next();
if (e.getLabel().isArea()) isArea = true;
}
if (isArea)
label = new Label(Location.NONE, Location.NONE, Location.NONE);
else
label = new Label(Location.NONE);
// compute the On label, and the side labels if present
for (int i = 0; i < 2; i++) {
computeLabelOn(i, boundaryNodeRule);
if (isArea)
computeLabelSides(i);
}
}
/**
* Compute the overall ON location for the list of EdgeStubs.
* (This is essentially equivalent to computing the self-overlay of a single Geometry)
* edgeStubs can be either on the boundary (eg Polygon edge)
* OR in the interior (e.g. segment of a LineString)
* of their parent Geometry.
* In addition, GeometryCollections use a {@link BoundaryNodeRule} to determine
* whether a segment is on the boundary or not.
* Finally, in GeometryCollections it can occur that an edge is both
* on the boundary and in the interior (e.g. a LineString segment lying on
* top of a Polygon edge.) In this case the Boundary is given precendence.
*
* These observations result in the following rules for computing the ON location:
*
* - if there are an odd number of Bdy edges, the attribute is Bdy
*
- if there are an even number >= 2 of Bdy edges, the attribute is Int
*
- if there are any Int edges, the attribute is Int
*
- otherwise, the attribute is NULL.
*
*/
private void computeLabelOn(int geomIndex, BoundaryNodeRule boundaryNodeRule)
{
// compute the ON location value
int boundaryCount = 0;
boolean foundInterior = false;
for (Iterator it = iterator(); it.hasNext(); ) {
EdgeEnd e = (EdgeEnd) it.next();
int loc = e.getLabel().getLocation(geomIndex);
if (loc == Location.BOUNDARY) boundaryCount++;
if (loc == Location.INTERIOR) foundInterior = true;
}
int loc = Location.NONE;
if (foundInterior) loc = Location.INTERIOR;
if (boundaryCount > 0) {
loc = GeometryGraph.determineBoundary(boundaryNodeRule, boundaryCount);
}
label.setLocation(geomIndex, loc);
}
/**
* Compute the labelling for each side
*/
private void computeLabelSides(int geomIndex)
{
computeLabelSide(geomIndex, Position.LEFT);
computeLabelSide(geomIndex, Position.RIGHT);
}
/**
* To compute the summary label for a side, the algorithm is:
* FOR all edges
* IF any edge's location is INTERIOR for the side, side location = INTERIOR
* ELSE IF there is at least one EXTERIOR attribute, side location = EXTERIOR
* ELSE side location = NULL
*
* Note that it is possible for two sides to have apparently contradictory information
* i.e. one edge side may indicate that it is in the interior of a geometry, while
* another edge side may indicate the exterior of the same geometry. This is
* not an incompatibility - GeometryCollections may contain two Polygons that touch
* along an edge. This is the reason for Interior-primacy rule above - it
* results in the summary label having the Geometry interior on both sides.
*/
private void computeLabelSide(int geomIndex, int side)
{
for (Iterator it = iterator(); it.hasNext(); ) {
EdgeEnd e = (EdgeEnd) it.next();
if (e.getLabel().isArea()) {
int loc = e.getLabel().getLocation(geomIndex, side);
if (loc == Location.INTERIOR) {
label.setLocation(geomIndex, side, Location.INTERIOR);
return;
}
else if (loc == Location.EXTERIOR)
label.setLocation(geomIndex, side, Location.EXTERIOR);
}
}
}
/**
* Update the IM with the contribution for the computed label for the EdgeStubs.
*/
void updateIM(IntersectionMatrix im)
{
Edge.updateIM(label, im);
}
public void print(PrintStream out)
{
out.println("EdgeEndBundle--> Label: " + label);
for (Iterator it = iterator(); it.hasNext(); ) {
EdgeEnd ee = (EdgeEnd) it.next();
ee.print(out);
out.println();
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy