/*
* 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.revolsys.geometry.geomgraph;
import com.revolsys.geometry.model.Location;
/**
* A <code>Label</code> indicates the topological relationship of a component
* of a topology graph to a given <code>Geometry</code>.
* This class supports labels for relationships to two <code>Geometry</code>s,
* which is sufficient for algorithms for binary operations.
* <P>
* Topology graphs support the concept of labeling nodes and edges in the graph.
* The label of a node or edge specifies its topological relationship to one or
* more geometries. (In fact, since JTS operations have only two arguments labels
* are required for only two geometries). A label for a node or edge has one or
* two elements, depending on whether the node or edge occurs in one or both of the
* input <code>Geometry</code>s. Elements contain attributes which categorize the
* topological location of the node or edge relative to the parent
* <code>Geometry</code>; that is, whether the node or edge is in the interior,
* boundary or exterior of the <code>Geometry</code>. Attributes have a value
* from the set <code>{Interior, Boundary, Exterior}</code>. In a node each
* element has a single attribute <code><On></code>. For an edge each element has a
* triplet of attributes <code><Left, On, Right></code>.
* <P>
* It is up to the client code to associate the 0 and 1 <code>TopologyLocation</code>s
* with specific geometries.
* @version 1.7
*
*/
public class Label {
// converts a Label to a Line label (that is, one with no side Locations)
public static Label toLineLabel(final Label label) {
final Label lineLabel = new Label(Location.NONE);
for (int i = 0; i < 2; i++) {
lineLabel.setLocation(i, label.getLocation(i));
}
return lineLabel;
}
TopologyLocation elt[] = new TopologyLocation[2];
/**
* Construct a Label with a single location for both Geometries.
* Initialize the location for the Geometry index.
*/
public Label(final int geomIndex, final Location onLoc) {
this.elt[0] = new TopologyLocation(Location.NONE);
this.elt[1] = new TopologyLocation(Location.NONE);
this.elt[geomIndex].setLocation(onLoc);
}
/**
* Construct a Label with On, Left and Right locations for both Geometries.
* Initialize the locations for the given Geometry index.
*/
public Label(final int geomIndex, final Location onLoc, final Location leftLoc,
final Location rightLoc) {
this.elt[0] = new TopologyLocation(Location.NONE, Location.NONE, Location.NONE);
this.elt[1] = new TopologyLocation(Location.NONE, Location.NONE, Location.NONE);
this.elt[geomIndex].setLocations(onLoc, leftLoc, rightLoc);
}
/**
* Construct a Label with the same values as the argument Label.
*/
public Label(final Label lbl) {
this.elt[0] = new TopologyLocation(lbl.elt[0]);
this.elt[1] = new TopologyLocation(lbl.elt[1]);
}
/**
* Construct a Label with a single location for both Geometries.
* Initialize the locations to Null
*/
public Label(final Location onLoc) {
this.elt[0] = new TopologyLocation(onLoc);
this.elt[1] = new TopologyLocation(onLoc);
}
/**
* Construct a Label with On, Left and Right locations for both Geometries.
* Initialize the locations for both Geometries to the given values.
*/
public Label(final Location onLoc, final Location leftLoc, final Location rightLoc) {
this.elt[0] = new TopologyLocation(onLoc, leftLoc, rightLoc);
this.elt[1] = new TopologyLocation(onLoc, leftLoc, rightLoc);
}
public boolean allPositionsEqual(final int geomIndex, final Location loc) {
return this.elt[geomIndex].allPositionsEqual(loc);
}
public void flip() {
this.elt[0].flip();
this.elt[1].flip();
}
public int getGeometryCount() {
int count = 0;
if (!this.elt[0].isNull()) {
count++;
}
if (!this.elt[1].isNull()) {
count++;
}
return count;
}
public Location getLocation(final int geomIndex) {
return this.elt[geomIndex].get(Position.ON);
}
public Location getLocation(final int geomIndex, final int posIndex) {
return this.elt[geomIndex].get(posIndex);
}
public boolean isAnyNull(final int geomIndex) {
return this.elt[geomIndex].isAnyNull();
}
public boolean isArea() {
return this.elt[0].isArea() || this.elt[1].isArea();
}
public boolean isArea(final int geomIndex) {
/*
* Testing if (elt[0].getLocations().length != elt[1].getLocations().length) {
* System.out.println(this); }
*/
return this.elt[geomIndex].isArea();
}
public boolean isEqualOnSide(final Label lbl, final int side) {
return this.elt[0].isEqualOnSide(lbl.elt[0], side)
&& this.elt[1].isEqualOnSide(lbl.elt[1], side);
}
public boolean isLine(final int geomIndex) {
return this.elt[geomIndex].isLine();
}
public boolean isNull(final int geomIndex) {
return this.elt[geomIndex].isNull();
}
/**
* Merge this label with another one.
* Merging updates any null attributes of this label with the attributes from lbl
*/
public void merge(final Label lbl) {
for (int i = 0; i < 2; i++) {
if (this.elt[i] == null && lbl.elt[i] != null) {
this.elt[i] = new TopologyLocation(lbl.elt[i]);
} else {
this.elt[i].merge(lbl.elt[i]);
}
}
}
public void setAllLocations(final int geomIndex, final Location location) {
this.elt[geomIndex].setAllLocations(location);
}
public void setAllLocationsIfNull(final int geomIndex, final Location location) {
this.elt[geomIndex].setAllLocationsIfNull(location);
}
public void setAllLocationsIfNull(final Location location) {
setAllLocationsIfNull(0, location);
setAllLocationsIfNull(1, location);
}
public void setLocation(final int geomIndex, final int posIndex, final Location location) {
this.elt[geomIndex].setLocation(posIndex, location);
}
public void setLocation(final int geomIndex, final Location location) {
this.elt[geomIndex].setLocation(Position.ON, location);
}
/**
* Converts one GeometryLocation to a Line location
*/
public void toLine(final int geomIndex) {
if (this.elt[geomIndex].isArea()) {
this.elt[geomIndex] = new TopologyLocation(this.elt[geomIndex].location[0]);
}
}
@Override
public String toString() {
final StringBuilder buf = new StringBuilder();
if (this.elt[0] != null) {
buf.append("A:");
buf.append(this.elt[0].toString());
}
if (this.elt[1] != null) {
buf.append(" B:");
buf.append(this.elt[1].toString());
}
return buf.toString();
}
}