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.geomcomp;
028:
029: import java.util.ArrayList;
030: import java.util.List;
031:
032: import fr.ign.cogit.geoxygene.spatial.coordgeom.DirectPosition;
033: import fr.ign.cogit.geoxygene.spatial.coordgeom.GM_CurveSegment;
034: import fr.ign.cogit.geoxygene.spatial.geomprim.GM_Curve;
035: import fr.ign.cogit.geoxygene.spatial.geomprim.GM_CurveBoundary;
036: import fr.ign.cogit.geoxygene.spatial.geomprim.GM_OrientableCurve;
037:
038: /**
039: * Complexe ayant toutes les propriétés géométriques d'une courbe.
040: * C'est une liste de courbes orientées (GM_OrientableCurve) de telle manière que le noeud final d'une courbe correspond au noeud initial de la courbe suivante dans la liste.
041: * Hérite de GM_OrientableCurve, mais le lien n'apparaît pas explicitement (problème de double héritage en java). Les méthodes et attributs ont été reportés.
042: *
043: *<P> ATTENTION : normalement, il faudrait remplir le set "element" (contrainte : toutes les primitives du generateur
044: * sont dans le complexe). Ceci n'est pas implémenté pour le moment.
045: *<P> A FAIRE AUSSI : iterateur sur "generator"
046: *
047: * @author Thierry Badard & Arnaud Braun
048: * @version 1.0
049: *
050: */
051:
052: public class GM_CompositeCurve extends GM_Composite {
053:
054: ////////////////////////////////////////////////////////////////////////
055: ////////////////////////////////////////////////////////////////////////
056: // Attribut "generator" et méthodes pour le traiter ////////////////////
057: ////////////////////////////////////////////////////////////////////////
058: ////////////////////////////////////////////////////////////////////////
059: /** Les GM_OrientableCurve constituant self. */
060: protected List generator;
061:
062: /** Renvoie la liste des GM_OrientableCurve */
063: public List getGenerator() {
064: return generator;
065: }
066:
067: /** Renvoie la GM_OrientableCurve de rang i */
068: public GM_OrientableCurve getGenerator(int i) {
069: return (GM_OrientableCurve) this .generator.get(i);
070: }
071:
072: /** Affecte une GM_OrientableCurve au rang i. Attention : aucun contrôle de continuité n'est effectué. */
073: public void setGenerator(int i, GM_OrientableCurve value) {
074: this .generator.set(i, value);
075: }
076:
077: /** Ajoute une GM_OrientableCurve en fin de liste. Attention : aucun contrôle de continuité n'est effectué. */
078: public void addGenerator(GM_OrientableCurve value) {
079: this .generator.add(value);
080: }
081:
082: /** Ajoute une GM_OrientableCurve en fin de liste avec un contrôle de continuité avec la tolérance passée en paramètre.
083: * Envoie une exception en cas de problème. */
084: public void addGenerator(GM_OrientableCurve value, double tolerance)
085: throws Exception {
086: DirectPosition pt1;
087: DirectPosition pt2;
088: if (generator.size() > 0) {
089: GM_OrientableCurve laDerniereCourbe = this
090: .getGenerator(generator.size() - 1);
091: pt1 = ((GM_CurveBoundary) laDerniereCourbe.boundary())
092: .getEndPoint().getPosition();
093: pt2 = ((GM_CurveBoundary) value.boundary()).getStartPoint()
094: .getPosition();
095: if (pt1.equals(pt2, tolerance))
096: this .generator.add(value);
097: else
098: throw new Exception(
099: "Rupture de chaînage avec la courbe passée en paramètre.");
100: } else
101: this .generator.add(value);
102: }
103:
104: /** Ajoute une GM_OrientableCurve en fin de liste avec un contrôle de continuité avec la tolérance passée en paramètre.
105: * Eventuellement change le sens d'orientation de la courbe pour assurer la continuite.
106: * Envoie une exception en cas de problème. */
107: public void addGeneratorTry(GM_OrientableCurve value,
108: double tolerance) throws Exception {
109: try {
110: this .addGenerator(value, tolerance);
111: } catch (Exception e1) {
112: try {
113: this .addGenerator((GM_OrientableCurve) value
114: .getNegative(), tolerance);
115: } catch (Exception e2) {
116: throw new Exception(
117: "Rupture de chaînage avec la courbe passée en paramètre(après avoir essayé les 2 orientations)");
118: }
119: }
120: }
121:
122: /** Ajoute une GM_OrientableCurve au rang i. Attention : aucun contrôle de continuité n'est effectué. */
123: public void addGenerator(int i, GM_OrientableCurve value) {
124: this .generator.add(i, value);
125: }
126:
127: /** Efface la (ou les) GM_OrientableCurve passé en paramètre. Attention : aucun contrôle de continuité n'est effectué. */
128: public void removeGenerator(GM_OrientableCurve value)
129: throws Exception {
130: if (this .generator.size() == 1)
131: throw new Exception(
132: "Il n'y a qu'un objet dans l'association.");
133: else
134: this .generator.remove(value);
135: }
136:
137: /** Efface la GM_OrientableCurve de rang i. Attention : aucun contrôle de continuité n'est effectué. */
138: public void removeGenerator(int i) throws Exception {
139: if (this .generator.size() == 1)
140: throw new Exception(
141: "Il n'y a qu'un objet dans l'association.");
142: else
143: this .generator.remove(i);
144: }
145:
146: /** Nombre de GM_OrientableCurve constituant self */
147: public int sizeGenerator() {
148: return this .generator.size();
149: }
150:
151: ////////////////////////////////////////////////////////////////////////
152: ////////////////////////////////////////////////////////////////////////
153: // Constructeurs ///////////////////////////////////////////////////////
154: ////////////////////////////////////////////////////////////////////////
155: ////////////////////////////////////////////////////////////////////////
156: // les constructeurs sont calques sur ceux de GM_Curve
157: /** Constructeur par défaut */
158: public GM_CompositeCurve() {
159: generator = new ArrayList();
160: primitive = new GM_Curve();
161: proxy[0] = (GM_Curve) primitive;
162: GM_OrientableCurve proxy1 = new GM_OrientableCurve();
163: proxy1.orientation = -1;
164: proxy1.proxy[0] = (GM_Curve) primitive;
165: proxy1.proxy[1] = proxy1;
166: proxy1.primitive = new GM_Curve((GM_Curve) primitive);
167: proxy[1] = proxy1;
168: }
169:
170: /** Constructeur à partir d'une et d'une seule GM_OrientableCurve.
171: * L'orientation vaut +1. */
172: public GM_CompositeCurve(GM_OrientableCurve oCurve) {
173: generator = new ArrayList();
174: generator.add(oCurve);
175: primitive = new GM_Curve();
176: this .simplifyPrimitive();
177: proxy[0] = (GM_Curve) primitive;
178: GM_OrientableCurve proxy1 = new GM_OrientableCurve();
179: proxy1.orientation = -1;
180: proxy1.proxy[0] = (GM_Curve) primitive;
181: proxy1.proxy[1] = proxy1;
182: proxy1.primitive = new GM_Curve((GM_Curve) primitive);
183: proxy[1] = proxy1;
184: }
185:
186: ////////////////////////////////////////////////////////////////////////
187: ////////////////////////////////////////////////////////////////////////
188: // Attributs et méthodes héritées de GM_OrientableCurve ////////////////
189: ////////////////////////////////////////////////////////////////////////
190: ////////////////////////////////////////////////////////////////////////
191: // On simule l'heritage du modele en reportant les attributs et methodes
192: // de GM_OrientableCurve
193: // On n'a pas repris l'attribut "orientation" qui ne sert a rien ici.
194:
195: /** Primitive. Elle doit etre recalculée à chaque modification de self : fait dans getPrimitive(). */
196: protected GM_Curve primitive;
197:
198: /** Renvoie la primitive de self. */
199: // le calcul est fait en dynamique dans la methode privee simplifyPrimitve.
200: public GM_Curve getPrimitive() {
201: this .simplifyPrimitive();
202: return this .primitive;
203: }
204:
205: /**
206: * Attribut stockant les primitives orientées de cette primitive.
207: * Proxy[0] est celle orientée positivement.
208: * Proxy[1] est celle orientée négativement.
209: * On accède aux primitives orientées par getPositive() et getNegative().
210: */
211: protected GM_OrientableCurve[] proxy = new GM_OrientableCurve[2];
212:
213: /** Renvoie la primitive orientée positivement. */
214: public GM_OrientableCurve getPositive() {
215: this .simplifyPrimitive();
216: return this .primitive; // equivaut a return this.proxy[0]
217: }
218:
219: /** Renvoie la primitive orientée négativement. */
220: public GM_OrientableCurve getNegative() {
221: this .simplifyPrimitive();
222: return this .primitive.getNegative();
223: }
224:
225: /** Redéfinition de l'opérateur "boundary" sur GM_OrientableCurve. Renvoie une GM_CurveBoundary, c'est-à-dire deux GM_Point. */
226: public GM_CurveBoundary boundary() {
227: this .simplifyPrimitive();
228: return this .primitive.boundary();
229: }
230:
231: ////////////////////////////////////////////////////////////////////////
232: ////////////////////////////////////////////////////////////////////////
233: // Méthodes "validate" /////////////////////////////////////////////////
234: ////////////////////////////////////////////////////////////////////////
235: ////////////////////////////////////////////////////////////////////////
236: // cette méthode n'est pas dans la norme.
237: /** Vérifie le chaînage des composants. Renvoie TRUE s'ils sont chaînés, FALSE sinon. */
238: public boolean validate(double tolerance) {
239: for (int i = 0; i < generator.size() - 1; i++) {
240: GM_OrientableCurve oCurve1 = (GM_OrientableCurve) generator
241: .get(i);
242: GM_Curve prim1 = (GM_Curve) oCurve1.getPrimitive();
243: GM_OrientableCurve oCurve2 = (GM_OrientableCurve) generator
244: .get(i + 1);
245: GM_Curve prim2 = (GM_Curve) oCurve2.getPrimitive();
246: DirectPosition pt1 = prim1.endPoint();
247: DirectPosition pt2 = prim2.startPoint();
248: if (!pt1.equals(pt2, tolerance))
249: return false;
250: }
251: return true;
252: }
253:
254: ////////////////////////////////////////////////////////////////////////
255: ////////////////////////////////////////////////////////////////////////
256: // Méthodes privées pour usage interne /////////////////////////////////
257: ////////////////////////////////////////////////////////////////////////
258: ////////////////////////////////////////////////////////////////////////
259: /** Calcule la primitive se self. */
260: private void simplifyPrimitive() {
261: int n = generator.size();
262: if (n > 0) {
263: // vidage de la primitive
264: GM_Curve prim = (GM_Curve) this .primitive;
265: while (prim.sizeSegment() > 0)
266: prim.removeSegment(0);
267: for (int i = 0; i < n; i++) {
268: GM_OrientableCurve oCurve = (GM_OrientableCurve) generator
269: .get(i);
270: GM_Curve thePrimitive = (GM_Curve) oCurve
271: .getPrimitive();
272: for (int j = 0; j < thePrimitive.sizeSegment(); j++) {
273: GM_CurveSegment theSegment = thePrimitive
274: .getSegment(j);
275: ((GM_Curve) this.primitive).addSegment(theSegment);
276: }
277: }
278: }
279: }
280:
281: }
|