001:
002: /*
003: * The JTS Topology Suite is a collection of Java classes that
004: * implement the fundamental operations required to validate a given
005: * geo-spatial data set to a known topological specification.
006: *
007: * Copyright (C) 2001 Vivid Solutions
008: *
009: * This library is free software; you can redistribute it and/or
010: * modify it under the terms of the GNU Lesser General Public
011: * License as published by the Free Software Foundation; either
012: * version 2.1 of the License, or (at your option) any later version.
013: *
014: * This library is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
017: * Lesser General Public License for more details.
018: *
019: * You should have received a copy of the GNU Lesser General Public
020: * License along with this library; if not, write to the Free Software
021: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
022: *
023: * For more information, contact:
024: *
025: * Vivid Solutions
026: * Suite #1A
027: * 2328 Government Street
028: * Victoria BC V8T 5G5
029: * Canada
030: *
031: * (250)385-6040
032: * www.vividsolutions.com
033: */
034: package com.vividsolutions.jts.geomgraph;
035:
036: import com.vividsolutions.jts.geom.Location;
037:
038: /**
039: * A <code>Label</code> indicates the topological relationship of a component
040: * of a topology graph to a given <code>Geometry</code>.
041: * This class supports labels for relationships to two <code>Geometry</code>s,
042: * which is sufficient for algorithms for binary operations.
043: * <P>
044: * Topology graphs support the concept of labeling nodes and edges in the graph.
045: * The label of a node or edge specifies its topological relationship to one or
046: * more geometries. (In fact, since JTS operations have only two arguments labels
047: * are required for only two geometries). A label for a node or edge has one or
048: * two elements, depending on whether the node or edge occurs in one or both of the
049: * input <code>Geometry</code>s. Elements contain attributes which categorize the
050: * topological location of the node or edge relative to the parent
051: * <code>Geometry</code>; that is, whether the node or edge is in the interior,
052: * boundary or exterior of the <code>Geometry</code>. Attributes have a value
053: * from the set <code>{Interior, Boundary, Exterior}</code>. In a node each
054: * element has a single attribute <code><On></code>. For an edge each element has a
055: * triplet of attributes <code><Left, On, Right></code>.
056: * <P>
057: * It is up to the client code to associate the 0 and 1 <code>TopologyLocation</code>s
058: * with specific geometries.
059: * @version 1.7
060: *
061: */
062: public class Label {
063:
064: // converts a Label to a Line label (that is, one with no side Locations)
065: public static Label toLineLabel(Label label) {
066: Label lineLabel = new Label(Location.NONE);
067: for (int i = 0; i < 2; i++) {
068: lineLabel.setLocation(i, label.getLocation(i));
069: }
070: return lineLabel;
071: }
072:
073: TopologyLocation elt[] = new TopologyLocation[2];
074:
075: /**
076: * Construct a Label with a single location for both Geometries.
077: * Initialize the locations to Null
078: */
079: public Label(int onLoc) {
080: elt[0] = new TopologyLocation(onLoc);
081: elt[1] = new TopologyLocation(onLoc);
082: }
083:
084: /**
085: * Construct a Label with a single location for both Geometries.
086: * Initialize the location for the Geometry index.
087: */
088: public Label(int geomIndex, int onLoc) {
089: elt[0] = new TopologyLocation(Location.NONE);
090: elt[1] = new TopologyLocation(Location.NONE);
091: elt[geomIndex].setLocation(onLoc);
092: }
093:
094: /**
095: * Construct a Label with On, Left and Right locations for both Geometries.
096: * Initialize the locations for both Geometries to the given values.
097: */
098: public Label(int onLoc, int leftLoc, int rightLoc) {
099: elt[0] = new TopologyLocation(onLoc, leftLoc, rightLoc);
100: elt[1] = new TopologyLocation(onLoc, leftLoc, rightLoc);
101: }
102:
103: /**
104: * Construct a Label with On, Left and Right locations for both Geometries.
105: * Initialize the locations for the given Geometry index.
106: */
107: public Label(int geomIndex, int onLoc, int leftLoc, int rightLoc) {
108: elt[0] = new TopologyLocation(Location.NONE, Location.NONE,
109: Location.NONE);
110: elt[1] = new TopologyLocation(Location.NONE, Location.NONE,
111: Location.NONE);
112: elt[geomIndex].setLocations(onLoc, leftLoc, rightLoc);
113: }
114:
115: /**
116: * Construct a Label with the same values as the argument Label.
117: */
118: public Label(Label lbl) {
119: elt[0] = new TopologyLocation(lbl.elt[0]);
120: elt[1] = new TopologyLocation(lbl.elt[1]);
121: }
122:
123: public void flip() {
124: elt[0].flip();
125: elt[1].flip();
126: }
127:
128: public int getLocation(int geomIndex, int posIndex) {
129: return elt[geomIndex].get(posIndex);
130: }
131:
132: public int getLocation(int geomIndex) {
133: return elt[geomIndex].get(Position.ON);
134: }
135:
136: public void setLocation(int geomIndex, int posIndex, int location) {
137: elt[geomIndex].setLocation(posIndex, location);
138: }
139:
140: public void setLocation(int geomIndex, int location) {
141: elt[geomIndex].setLocation(Position.ON, location);
142: }
143:
144: public void setAllLocations(int geomIndex, int location) {
145: elt[geomIndex].setAllLocations(location);
146: }
147:
148: public void setAllLocationsIfNull(int geomIndex, int location) {
149: elt[geomIndex].setAllLocationsIfNull(location);
150: }
151:
152: public void setAllLocationsIfNull(int location) {
153: setAllLocationsIfNull(0, location);
154: setAllLocationsIfNull(1, location);
155: }
156:
157: /**
158: * Merge this label with another one.
159: * Merging updates any null attributes of this label with the attributes from lbl
160: */
161: public void merge(Label lbl) {
162: for (int i = 0; i < 2; i++) {
163: if (elt[i] == null && lbl.elt[i] != null) {
164: elt[i] = new TopologyLocation(lbl.elt[i]);
165: } else {
166: elt[i].merge(lbl.elt[i]);
167: }
168: }
169: }
170:
171: public int getGeometryCount() {
172: int count = 0;
173: if (!elt[0].isNull())
174: count++;
175: if (!elt[1].isNull())
176: count++;
177: return count;
178: }
179:
180: public boolean isNull(int geomIndex) {
181: return elt[geomIndex].isNull();
182: }
183:
184: public boolean isAnyNull(int geomIndex) {
185: return elt[geomIndex].isAnyNull();
186: }
187:
188: public boolean isArea() {
189: return elt[0].isArea() || elt[1].isArea();
190: }
191:
192: public boolean isArea(int geomIndex) {
193: return elt[geomIndex].isArea();
194: }
195:
196: public boolean isLine(int geomIndex) {
197: return elt[geomIndex].isLine();
198: }
199:
200: public boolean isEqualOnSide(Label lbl, int side) {
201: return this .elt[0].isEqualOnSide(lbl.elt[0], side)
202: && this .elt[1].isEqualOnSide(lbl.elt[1], side);
203: }
204:
205: public boolean allPositionsEqual(int geomIndex, int loc) {
206: return elt[geomIndex].allPositionsEqual(loc);
207: }
208:
209: /**
210: * Converts one GeometryLocation to a Line location
211: */
212: public void toLine(int geomIndex) {
213: if (elt[geomIndex].isArea())
214: elt[geomIndex] = new TopologyLocation(
215: elt[geomIndex].location[0]);
216: }
217:
218: public String toString() {
219: StringBuffer buf = new StringBuffer();
220: if (elt[0] != null) {
221: buf.append("a:");
222: buf.append(elt[0].toString());
223: }
224: if (elt[1] != null) {
225: buf.append(" b:");
226: buf.append(elt[1].toString());
227: }
228: return buf.toString();
229: }
230: }
|