001: /*
002: * This file is part of the GeOxygene project source files.
003: *
004: * GeOxygene aims at providing an open framework which implements OGC/ISO specifications for
005: * the development and deployment of geographic (GIS) applications. It is a open source
006: * contribution of the COGIT laboratory at the Institut Géographique National (the French
007: * National Mapping Agency).
008: *
009: * See: http://oxygene-project.sourceforge.net
010: *
011: * Copyright (C) 2005 Institut Géographique National
012: *
013: * This library is free software; you can redistribute it and/or modify it under the terms
014: * of the GNU Lesser General Public License as published by the Free Software Foundation;
015: * either version 2.1 of the License, or any later version.
016: *
017: * This library is distributed in the hope that it will be useful, but WITHOUT ANY
018: * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
019: * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
020: *
021: * You should have received a copy of the GNU Lesser General Public License along with
022: * this library (see file LICENSE if present); if not, write to the Free Software
023: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
024: *
025: */
026:
027: package fr.ign.cogit.geoxygene.spatial.topoprim;
028:
029: import java.util.List;
030:
031: /**
032: * Brin topologique orienté. Supporte la classe TP_Edge pour les TP_Expression.
033: * Dans notre implémentation, l'identifiant d'un TP_DirectedTopo est celui de sa primitive avec le signe de l'orientation.
034: * EXPLIQUER QUE C'EST PAS PERSISTANT et que A PRIORI ca n'a pas de GEOMETRIE
035: *
036: * @author Thierry Badard, Arnaud Braun & Audrey Simon
037: * @version 1.0
038: *
039: */
040:
041: public class TP_DirectedEdge extends TP_DirectedTopo {
042:
043: /////////////////////////////////////////////////////////////////////////////////////
044: // constructeur /////////////////////////////////////////////////////////////////////
045: /////////////////////////////////////////////////////////////////////////////////////
046: /** Constructeur par défaut. */
047: public TP_DirectedEdge() {
048: }
049:
050: /////////////////////////////////////////////////////////////////////////////////////
051: // topo /////////////////////////////////////////////////////////////////////////////
052: /////////////////////////////////////////////////////////////////////////////////////
053: /** Primitive de this. */
054: protected TP_Edge topo;
055:
056: /** Primitive de this. */
057: public TP_Edge topo() {
058: return topo;
059: }
060:
061: /////////////////////////////////////////////////////////////////////////////////////
062: // negate ///////////////////////////////////////////////////////////////////////////
063: /////////////////////////////////////////////////////////////////////////////////////
064: /** Renvoie le TP_DirectedEdge d'orientation opposée. */
065: public TP_DirectedEdge negate() {
066: if (orientation < 0)
067: return topo.proxy[0];
068: else
069: return topo.proxy[1];
070: }
071:
072: /////////////////////////////////////////////////////////////////////////////////////
073: // boundary /////////////////////////////////////////////////////////////////////////
074: /////////////////////////////////////////////////////////////////////////////////////
075: /** Renvoie les TP_DirectedNode frontière du TP_DirectedEdge, structurés en TP_EdgeBoundary.
076: * Un peut lourd à utiliser, mieux d'utiliser directement getEndnode() et getStartnode().*/
077: public TP_EdgeBoundary boundary() {
078: if (orientation == +1)
079: return this .topo().boundary();
080: // si le brin est négatif on retourne tout
081: else if (orientation == -1) {
082: TP_EdgeBoundary boundary = (TP_EdgeBoundary) this .topo()
083: .boundary();
084: TP_DirectedNode startNode = (TP_DirectedNode) boundary
085: .getStartnode().negate();
086: TP_DirectedNode endNode = (TP_DirectedNode) boundary
087: .getEndnode().negate();
088: TP_EdgeBoundary result = new TP_EdgeBoundary(endNode,
089: startNode);
090: return result;
091: } else
092: return null;
093: }
094:
095: /** Renvoie directement le endNode (qui est orienté positivement). */
096: public TP_DirectedNode endNode() {
097: TP_EdgeBoundary bdy = this .boundary();
098: TP_DirectedNode theNode = bdy.getEndnode();
099: return theNode;
100: }
101:
102: /** Renvoie directement le startNode (qui est orienté négativemnt). */
103: public TP_DirectedNode startNode() {
104: TP_EdgeBoundary bdy = this .boundary();
105: TP_DirectedNode theNode = bdy.getStartnode();
106: return theNode;
107: }
108:
109: /////////////////////////////////////////////////////////////////////////////////////
110: // coboundary ///////////////////////////////////////////////////////////////////////
111: /////////////////////////////////////////////////////////////////////////////////////
112: /** Renvoie les TP_DirectedFace associés au TP_DirectedEdge. */
113: public List coBoundary() {
114: if (orientation == +1)
115: return this .topo().coBoundary();
116: // si le brin est négatif on retourne tout
117: else if (orientation == -1) {
118: List coBoundary = this .topo().coBoundary();
119: for (int i = 0; i < coBoundary.size(); i++) {
120: TP_DirectedFace directedFace1 = (TP_DirectedFace) coBoundary
121: .get(i);
122: TP_DirectedFace directedFace2 = (TP_DirectedFace) directedFace1
123: .negate();
124: coBoundary.set(i, directedFace2);
125: }
126: return coBoundary;
127: } else
128: return null;
129: }
130:
131: /** Renvoie la face gauche (orientée du même signe que le TP_DirectedEdge). */
132: public TP_DirectedFace leftFace() {
133: List cobdy = this .coBoundary();
134: if (cobdy.size() > 0) {
135: TP_DirectedFace dface1 = (TP_DirectedFace) cobdy.get(0);
136: TP_DirectedFace dface2 = (TP_DirectedFace) cobdy.get(1);
137: if (dface1.getOrientation() == this .getOrientation())
138: return dface1;
139: else
140: return dface2;
141: } else
142: return null;
143: }
144:
145: /** Renvoie la face droite (orientée du signe opposé au TP_DirectedEdge). */
146: public TP_DirectedFace rightFace() {
147: List cobdy = this .coBoundary();
148: if (cobdy.size() > 0) {
149: TP_DirectedFace dface1 = (TP_DirectedFace) cobdy.get(0);
150: TP_DirectedFace dface2 = (TP_DirectedFace) cobdy.get(1);
151: if (dface1.getOrientation() == -this .getOrientation())
152: return dface1;
153: else
154: return dface2;
155: } else
156: return null;
157: }
158:
159: /////////////////////////////////////////////////////////////////////////////////////
160: // brin suivant /////////////////////////////////////////////////////////////////////
161: /////////////////////////////////////////////////////////////////////////////////////
162: /** La liste ordonnee dans le sens trigo des brins suivants. Les entrants sont orientés négativement,
163: les sortants positivement. */
164: public List nextEdgesList() {
165: TP_DirectedNode endNode = this .endNode();
166: List coBdy = endNode.coBoundary();
167:
168: // il faut les retourner car coBoundary renvoie des entrants + et des sortant - (on veut le contraire)
169: for (int i = 0; i < coBdy.size(); i++) {
170: TP_DirectedEdge dirEdge = (TP_DirectedEdge) coBdy.get(i);
171: TP_DirectedEdge dirEdgeNeg = (TP_DirectedEdge) dirEdge
172: .negate();
173: coBdy.set(i, dirEdgeNeg);
174: }
175:
176: // on enleve this de la liste
177: for (int i = 0; i < coBdy.size(); i++) {
178: TP_DirectedEdge dirEdge = (TP_DirectedEdge) coBdy.get(i);
179: if (dirEdge.getId() == -1 * this .getId()) {
180: coBdy.remove(i);
181: break;
182: }
183:
184: }
185: return coBdy;
186: }
187:
188: /** Le brin orienté suivant (= celui partageant la même face gauche). */
189: public TP_DirectedEdge nextEdge() {
190: TP_DirectedNode endNode = this .endNode();
191: List coBdy = endNode.coBoundary();
192: // dans coBdy, comme ils sont orientes dans le sens trigo, c'est le brin juste avant this
193: TP_DirectedEdge result = null;
194: // cas particulier : pas de brin suivant reel. On renvoie l'oppose de this
195: if (coBdy.size() == 0)
196: result = (TP_DirectedEdge) this .negate();
197:
198: else {
199: TP_DirectedEdge dirEdge = (TP_DirectedEdge) coBdy.get(0);
200: if (dirEdge.equalsID(this ))
201: result = (TP_DirectedEdge) coBdy.get(coBdy.size() - 1);
202: else
203: for (int i = 1; i < coBdy.size(); i++) {
204: dirEdge = (TP_DirectedEdge) coBdy.get(i);
205: if (dirEdge.equalsID(this )) {
206: result = (TP_DirectedEdge) coBdy.get(i - 1);
207: break;
208: }
209: }
210: }
211: // il faut le retourner car coBoundary renvoie des entrants + et des sortant -
212: result = (TP_DirectedEdge) result.negate();
213: return result;
214: }
215:
216: /////////////////////////////////////////////////////////////////////////////////////
217: // brin precedent ///////////////////////////////////////////////////////////////////
218: /////////////////////////////////////////////////////////////////////////////////////
219: /** La liste ordonnee dans le sens trigo des brins précédents. Les entrants sont orientés négativement,
220: les sortants positivement. This n'appartient pas à la liste. */
221: public List previousEdgesList() {
222: TP_DirectedNode startNode = this .startNode();
223: List coBdy = startNode.coBoundary();
224:
225: // il faut les retourner car coBoundary renvoie des entrants - et des sortant +
226: // car startNode est négatif
227: for (int i = 0; i < coBdy.size(); i++) {
228: TP_DirectedEdge dirEdge = (TP_DirectedEdge) coBdy.get(i);
229: TP_DirectedEdge dirEdgeNeg = (TP_DirectedEdge) dirEdge
230: .negate();
231: coBdy.set(i, dirEdgeNeg);
232: }
233:
234: // on enleve this de la liste
235: for (int i = 0; i < coBdy.size(); i++) {
236: TP_DirectedEdge dirEdge = (TP_DirectedEdge) coBdy.get(i);
237: if (dirEdge.getId() == -1 * this .getId()) {
238: coBdy.remove(i);
239: break;
240: }
241: }
242: return coBdy;
243: }
244:
245: /** Le brin orienté précédent (= celui partageant la même face gauche). */
246: public TP_DirectedEdge previousEdge() {
247: TP_DirectedNode startNode = this .startNode();
248: List coBdy = startNode.coBoundary();
249: // dans coBdy, comme ils sont orientes dans le sens trigo, c'est le brin juste apres this
250: TP_DirectedEdge result = null;
251:
252: // cas particulier : pas de brin precedent reel. On renvoie l'oppose de this
253: if (coBdy.size() == 0)
254: result = (TP_DirectedEdge) this .negate();
255:
256: else {
257: TP_DirectedEdge dirEdge = (TP_DirectedEdge) coBdy.get(coBdy
258: .size() - 1);
259: if (dirEdge.equalsID(this ))
260: result = (TP_DirectedEdge) coBdy.get(0);
261: else
262: for (int i = 0; i < coBdy.size() - 1; i++) {
263: dirEdge = (TP_DirectedEdge) coBdy.get(i);
264: if (dirEdge.equalsID(this )) {
265: result = (TP_DirectedEdge) coBdy.get(i + 1);
266: break;
267: }
268: }
269: }
270: // il faut le retourner car coBoundary renvoie des entrants - et des sortant +
271: // (car startNode est negatif)
272: result = (TP_DirectedEdge) result.negate();
273: return result;
274: }
275:
276: /////////////////////////////////////////////////////////////////////////////////////
277: // cycle ////////////////////////////////////////////////////////////////////////////
278: /////////////////////////////////////////////////////////////////////////////////////
279: /** Tous les TP_DirectedEdge partageant la même face gauche. */
280: public TP_Ring cycle() {
281: TP_Ring ring = new TP_Ring();
282: TP_DirectedEdge suivant1 = (TP_DirectedEdge) this .clone();
283: TP_DirectedEdge suivant2 = new TP_DirectedEdge(); // suivant2 a un identifiant 0 est une orientation 0
284: while (!suivant2.equalsID(this)) {
285: suivant2 = suivant1.nextEdge();
286: suivant1 = suivant2;
287: ring.addTerm(suivant1);
288: }
289: return ring;
290: }
291:
292: }
|