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.ArrayList;
030: import java.util.List;
031:
032: /**
033: * Représente des TP_DirectedEdge connectés en un cycle.
034: * L'anneau doit être orienté pour que la face soit à sa gauche.
035: *
036: * @author Thierry Badard & Arnaud Braun
037: * @version 1.0
038: *
039: */
040:
041: public class TP_Ring extends TP_Expression {
042:
043: /** Constructeur par défaut. */
044: public TP_Ring() {
045: term = new ArrayList();
046: }
047:
048: /** Constructeur à partir de plusieurs TP_DirectedEdge. La liste doit contenir au moins 1 element.
049: * Le constructeur réorganise la liste pour que les brins orientés soient chaînés. Il renvoie une exception si ça ne boucle pas. */
050: public TP_Ring(List sdt) throws Exception {
051: term = new ArrayList();
052: int compteur; // nombre d'arc en contact avec l'arc courant
053:
054: TP_DirectedEdge dt0 = (TP_DirectedEdge) sdt.get(0);
055: TP_DirectedEdge dtref = null;
056:
057: // probleme si on commence par un arc pendant, dans ce cas on en prend un autre
058: if (!dt0.topo().getLeftface().equals(dt0.topo().getRightface())) {
059: term.add(dt0);
060: sdt.remove(0);
061: } else {
062: if (sdt.size() > 1) {
063: for (int i = 1; i < sdt.size(); i++) {
064: dt0 = (TP_DirectedEdge) sdt.get(i);
065: if (!dt0.topo().getLeftface().equals(
066: dt0.topo().getRightface())) {
067: term.add(dt0);
068: sdt.remove(i);
069: break;
070: }
071: }
072: }
073: }
074:
075: int IDEndNode = dt0.endNode().topo().getId();
076: int theIDStartNode = dt0.startNode().topo().getId();
077:
078: while (sdt.size() > 0) {
079: compteur = 0;
080: // on cherche le nombre d'arc en contact avec l'arc courant
081: for (int j = 0; j < sdt.size(); j++) {
082: TP_DirectedEdge dt = (TP_DirectedEdge) sdt.get(j);
083: int IDStartNode = dt.startNode().topo().getId();
084: if (IDEndNode == IDStartNode) {
085: compteur++;
086: dtref = dt;
087: }
088: }
089:
090: // probleme ! ca ne chaine pas
091: if (compteur == 0) {
092: throw new Exception("Les brins ne sont pas chainés.");
093: }
094:
095: // pas de probleme !
096: else if (compteur == 1) {
097: term.add(dtref);
098: IDEndNode = dtref.endNode().topo().getId();
099: dt0 = dtref;
100: sdt.remove(dtref);
101:
102: // if compteur > 1 : presence d'arc pendant (caracterise par left face = right face)
103: } else {
104: // c'est ceux la qu'on met en premier dans la liste, pour revenir au point initial
105: for (int j = 0; j < sdt.size(); j++) {
106: TP_DirectedEdge dt = (TP_DirectedEdge) sdt.get(j);
107: int IDStartNode = dt.startNode().topo().getId();
108: TP_Edge dttopo = dt.topo();
109: if ((IDEndNode == IDStartNode)
110: && (dttopo.getLeftface().equals(dttopo
111: .getRightface()))) {
112: boolean flag = true;
113: if (dt.topo().equals(dt0.topo())) { // cas particulier : il faut verifier qu'il n'y a pas d'autre candidat
114: for (int k = j + 1; k < sdt.size(); k++) {
115: TP_DirectedEdge dt1 = (TP_DirectedEdge) sdt
116: .get(k);
117: IDStartNode = dt1.startNode().topo()
118: .getId();
119: TP_Edge dt1topo = dt1.topo();
120: if ((IDEndNode == IDStartNode)
121: && (dt1topo.getLeftface()
122: .equals(dt1topo
123: .getRightface()))) {
124: term.add(dt1);
125: IDEndNode = dt1.endNode().topo()
126: .getId();
127: dt0 = dt1;
128: sdt.remove(dt1);
129: flag = false;
130: break;
131: }
132: }
133: }
134: if (flag) { // pas d'autre candidat trouve : on rebrousse chemin
135: term.add(dt);
136: IDEndNode = dt.endNode().topo().getId();
137: dt0 = dt;
138: sdt.remove(dt);
139: }
140: break;
141: }
142: }
143: }
144: }
145:
146: // ultime verification du bouclage
147: if (theIDStartNode != IDEndNode)
148: throw new Exception("Les brins ne sont pas chainés.");
149:
150: }
151:
152: }
|