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.coordgeom;
028:
029: import java.util.ArrayList;
030: import java.util.List;
031:
032: import fr.ign.cogit.geoxygene.spatial.geomprim.GM_Curve;
033: import fr.ign.cogit.geoxygene.spatial.geomprim.GM_OrientableCurve;
034: import fr.ign.cogit.geoxygene.spatial.geomprim.GM_Ring;
035: import fr.ign.cogit.geoxygene.spatial.geomprim.GM_Surface;
036: import fr.ign.cogit.geoxygene.spatial.geomprim.GM_SurfaceBoundary;
037:
038: /**
039: * Polygone : morceau de surface plan (les arêtes constituant la frontière sont coplanaires).
040: * L'attribut interpolation vaut "planar" par défaut.
041: *
042: * @author Thierry Badard & Arnaud Braun
043: * @version 1.0
044: *
045: */
046:
047: public class GM_Polygon extends GM_SurfacePatch {
048:
049: //////////////////////////////////////////////////////////////////////////////////////////////
050: //// modele original ISO abandonne pour simplification ///////////////////////////////////////
051: //////////////////////////////////////////////////////////////////////////////////////////////
052:
053: /** Stocke la frontière constituant le polygone. */
054: //protected GM_SurfaceBoundary boundary;
055: /** Renvoie la frontière. */
056: //public GM_SurfaceBoundary getBoundary () {return this.boundary;}
057: /** Optionnel. */
058: //protected GM_Surface spanningSurface;
059: /** Renvoie la spanning surface. */
060: //public GM_Surface getSpanningSurface () {return this.spanningSurface;}
061:
062: //////////////////////////////////////////////////////////////////////////////////////////////
063: //// frontiere du polygone ///////////////////////////////////////////////////////////////////
064: //////////////////////////////////////////////////////////////////////////////////////////////
065: /** Anneau extérieur. */
066: protected GM_Ring exterior;
067:
068: /** Renvoie l'anneau extérieur */
069: public GM_Ring getExterior() {
070: return this .exterior;
071: }
072:
073: /** Affecte une valeur à l'anneau extérieur */
074: protected void setExterior(GM_Ring value) {
075: this .exterior = value;
076: }
077:
078: /** Renvoie 1 si l'anneau extérieur est affecté, 0 sinon.
079: * Il paraît qu'il existe des cas où on peut avoir une surface avec que des frontières intérieures. */
080: public int sizeExterior() {
081: if (this .exterior == null)
082: return 0;
083: else
084: return 1;
085: }
086:
087: /** Anneau(x) intérieur(s) en cas de trou(s) : liste de GM_Ring */
088: protected List interior = new ArrayList();
089:
090: /** Renvoie la liste des anneaux intérieurs */
091: public List getInterior() {
092: return this .interior;
093: }
094:
095: /** Renvoie l'anneau intérieur de rang i */
096: public GM_Ring getInterior(int i) {
097: return (GM_Ring) this .interior.get(i);
098: }
099:
100: /** Affecte un GM_Ring au rang i */
101: public void setInterior(int i, GM_Ring value) {
102: this .interior.set(i, value);
103: }
104:
105: /** Ajoute un GM_Ring en fin de liste */
106: public void addInterior(GM_Ring value) {
107: this .interior.add(value);
108: }
109:
110: /** Ajoute un GM_ring au rang i */
111: public void addInterior(int i, GM_Ring value) {
112: this .interior.add(i, value);
113: }
114:
115: /** Efface le (ou les) GM_Ring passé en paramètre */
116: public void removeInterior(GM_Ring value) {
117: this .interior.remove(value);
118: }
119:
120: /** Efface le GM_Ring de rang i */
121: public void removeInterior(int i) {
122: this .interior.remove(i);
123: }
124:
125: /** Nombre d'anneaux intérieurs */
126: public int sizeInterior() {
127: return this .interior.size();
128: }
129:
130: ////////////////////////////////////////////////////////////////////////////////////////////////
131: //// Constructeurs /////////////////////////////////////////////////////////////////////////////
132: ////////////////////////////////////////////////////////////////////////////////////////////////
133:
134: /** Constructeur par défaut */
135: public GM_Polygon() {
136: super ();
137: this .patch.add(this );
138: interpolation = "planar";
139: }
140:
141: /** NON IMPLEMENTE.
142: * Constructeur à partir d'une frontière et d'une surface. */
143: public GM_Polygon(GM_SurfaceBoundary boundary, GM_Surface spanSurf) {
144: super ();
145: this .patch.add(this );
146: interpolation = "planar";
147: }
148:
149: /** Constructeur à partir d'une frontière. */
150: public GM_Polygon(GM_SurfaceBoundary bdy) {
151: super ();
152: this .patch.add(this );
153: interpolation = "planar";
154: this .exterior = bdy.getExterior();
155: this .interior = bdy.getInterior();
156: }
157:
158: /** Constructeur à partir d'une GM_LineString fermée sans vérifier la fermeture.
159: * ATTENTION : ne vérifie pas la fermeture. */
160: public GM_Polygon(GM_LineString ls) {
161: super ();
162: this .patch.add(this );
163: interpolation = "planar";
164: GM_Ring ring = new GM_Ring(ls);
165: this .exterior = ring;
166: }
167:
168: /** Constructeur à partir d'une GM_LineString fermée en vérifiant la fermeture.
169: * Vérifie la fermeture (d'où le paramètre tolérance), sinon exception. */
170: public GM_Polygon(GM_LineString ls, double tolerance)
171: throws Exception {
172: super ();
173: this .patch.add(this );
174: interpolation = "planar";
175: try {
176: GM_Ring ring = new GM_Ring(ls, tolerance);
177: this .exterior = ring;
178: } catch (Exception e) {
179: throw new Exception(
180: "Tentative de créer un polygone avec une LineString non fermée.");
181: }
182: }
183:
184: /** Constructeur à partir d'une GM_Curve fermée sans vérifier la fermeture.
185: * ATTENTION : ne vérifie pas la fermeture. */
186: public GM_Polygon(GM_Curve curve) {
187: super ();
188: this .patch.add(this );
189: interpolation = "planar";
190: GM_Ring ring = new GM_Ring(curve);
191: this .exterior = ring;
192: }
193:
194: /** Constructeur à partir d'une GM_Curve fermée en vérifiant la fermeture.
195: * Vérifie la fermeture (d'où le paramètre tolérance), sinon exception. */
196: public GM_Polygon(GM_Curve curve, double tolerance)
197: throws Exception {
198: super ();
199: this .patch.add(this );
200: interpolation = "planar";
201: try {
202: GM_Ring ring = new GM_Ring(curve, tolerance);
203: this .exterior = ring;
204: } catch (Exception e) {
205: throw new Exception(
206: "Tentative de créer un polygone avec une GM_Curve non fermée.");
207: }
208: }
209:
210: /** Constructeur à partir d'un GM_Ring. */
211: public GM_Polygon(GM_Ring ring) {
212: super ();
213: this .patch.add(this );
214: interpolation = "planar";
215: this .exterior = ring;
216: }
217:
218: /** Constructeur à partir d'une enveloppe (2D). */
219: public GM_Polygon(GM_Envelope env) {
220: super ();
221: this .patch.add(this );
222: interpolation = "planar";
223: GM_LineString ls = new GM_LineString();
224: boolean flag3D = true;
225: DirectPosition dp;
226: Double D = new Double(env.getLowerCorner().getZ());
227: if (D.isNaN())
228: flag3D = false;
229: ls.getControlPoint().add(env.getLowerCorner());
230: if (flag3D)
231: dp = new DirectPosition(env.getUpperCorner().getX(), env
232: .getLowerCorner().getY(), 0.0);
233: else
234: dp = new DirectPosition(env.getUpperCorner().getX(), env
235: .getLowerCorner().getY());
236: ls.getControlPoint().add(dp);
237: ls.getControlPoint().add(env.getUpperCorner());
238: if (flag3D)
239: dp = new DirectPosition(env.getLowerCorner().getX(), env
240: .getUpperCorner().getY(), 0.0);
241: else
242: dp = new DirectPosition(env.getLowerCorner().getX(), env
243: .getUpperCorner().getY());
244: ls.getControlPoint().add(dp);
245: ls.getControlPoint().add(env.getLowerCorner());
246: GM_Ring ring = new GM_Ring(ls);
247: this .exterior = ring;
248: }
249:
250: ////////////////////////////////////////////////////////////////////////////////////////////////
251: //// Methode implementant une methode de GM_SurfacePatch ///////////////////////////////////////
252: ////////////////////////////////////////////////////////////////////////////////////////////////
253:
254: /** Renvoie un GM_Polygon en "retournant" la frontière (inverse l'ordre du trace des points).*/
255: // Implémentation d'une méthode abstraite de GM_SurfacePatch.
256: public GM_SurfacePatch reverse() {
257: GM_Ring oldRing = this .getExterior();
258: GM_Ring newRing = new GM_Ring();
259: int n = oldRing.sizeGenerator();
260: for (int i = 0; i < n; i++) {
261: GM_OrientableCurve oriCurve = oldRing.getGenerator(n - i
262: - 1);
263: if (oriCurve.getOrientation() == +1)
264: newRing.addGenerator((GM_OrientableCurve) oriCurve
265: .getNegative());
266: else if (oriCurve.getOrientation() == -1)
267: newRing.addGenerator((GM_OrientableCurve) oriCurve
268: .getPositive());
269: }
270: GM_SurfaceBoundary newBdy = new GM_SurfaceBoundary(newRing);
271: int m = this .sizeInterior();
272: if (m > 0)
273: for (int j = 0; j < m; j++) {
274: oldRing = this .getInterior(j);
275: n = oldRing.sizeGenerator();
276: newRing = new GM_Ring();
277: for (int i = 0; i < n; i++) {
278: GM_OrientableCurve oriCurve = oldRing
279: .getGenerator(n - i - 1);
280: if (oriCurve.getOrientation() == +1)
281: newRing
282: .addGenerator((GM_OrientableCurve) oriCurve
283: .getNegative());
284: else if (oriCurve.getOrientation() == -1)
285: newRing
286: .addGenerator((GM_OrientableCurve) oriCurve
287: .getPositive());
288: }
289: newBdy.addInterior(newRing);
290: }
291: GM_Polygon result = new GM_Polygon(newBdy);
292: return result;
293: }
294:
295: }
|