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.geomprim;
028:
029: import fr.ign.cogit.geoxygene.spatial.coordgeom.DirectPositionList;
030: import fr.ign.cogit.geoxygene.spatial.coordgeom.GM_Polygon;
031:
032: //import datatools.Geodatabase;
033:
034: /**
035: * Surface orientée. A de l'intérêt pour traiter les trous : un trou est une surface orientée négativement.
036: * A aussi de l'intérêt en 3D.
037: * Une surface orientée positivement à sa frontière dans le sens direct (la surface est à gauche de la frontière).
038: * Une surface orientée négativement à sa frontière dans le sens des aiguilles d'une montre (la surface est à droite de la frontière).
039: * En 3D, on peut représenter un vecteur normal à la surface avec la règle du tire-bouchon.
040: * Si l'orientation est +1, alors self est une GM_Surface, de primitive elle-même.
041: * Si l'orientation est -1, alors self est une GM_OrientableSurface, de primitive une GM_Surface renversée par rapport à la surface positive.
042: *
043: * @author Thierry Badard & Arnaud Braun
044: * @version 1.0
045: *
046: */
047:
048: public class GM_OrientableSurface extends GM_OrientablePrimitive {
049:
050: /** Primitive */
051: public GM_Surface primitive;
052:
053: /** Renvoie la primitive de self */
054: public GM_Surface getPrimitive() {
055: return this .primitive;
056: }
057:
058: /** Attribut stockant les primitives orientées de cette primitive.
059: * Proxy[0] est celle orientée positivement.
060: * Proxy[1] est celle orientée négativement.
061: * On accède aux primitives orientées par getPositive() et getNegative(). */
062: public GM_OrientableSurface[] proxy = new GM_OrientableSurface[2];
063:
064: /** Renvoie la primitive orientée positivement correspondant à self. */
065: public GM_OrientableSurface getPositive() {
066: return proxy[0];
067: }
068:
069: /** Renvoie la primitive orientée négativement correspondant à self. */
070: // on recalcule en dynamique la primitive de la primitive orientee negativement, qui est "renversee"
071: // par rapport a la primitive orientee positivement.
072: public GM_OrientableSurface getNegative() {
073: GM_Surface proxy1prim = (GM_Surface) proxy[1].primitive;
074: proxy1prim.getPatch().clear();
075: GM_Surface proxy0 = (GM_Surface) proxy[1].proxy[0];
076: int n = proxy0.sizePatch();
077: if (n > 0)
078: for (int i = 0; i < n; i++)
079: proxy1prim.addPatch(proxy0.getPatch(n - 1 - i)
080: .reverse());
081: return proxy[1];
082: }
083:
084: /** Redéfinition de l'opérateur "boundary" sur GM_Object. Renvoie une GM_SurfaceBoundary, c'est-à-dire un GM_Ring pour
085: * représenter l'extérieur, et éventuellement des GM_Ring pour représenter les trous.
086: * ATTENTION ne fonctionne que pour les surfaces composées d'un seul patch, qui est un polygone. */
087: public GM_SurfaceBoundary boundary() {
088: GM_Surface s = (GM_Surface) this .getPrimitive();
089: int n = s.sizePatch();
090: if (n == 1) {
091: GM_Polygon poly = (GM_Polygon) s.getPatch(0);
092: GM_SurfaceBoundary bdy = new GM_SurfaceBoundary();
093: bdy.exterior = poly.getExterior();
094: bdy.interior = poly.getInterior();
095: return bdy;
096: } else {
097: System.out
098: .println("GM_OrientableSurface::boundary() : cette méthode ne fonctionne que pour les surfaces composées d'un et d'un seul patch.");
099: return null;
100: }
101: }
102:
103: /** EXPERIMENTAL. Méthode "boundary" à utiliser dans le cas des surfaces en plusieurs morceaux
104: * En effet, dans ce cas, on fait appel à Oracle, d'où le paramètre data. */
105: // A REVOIR : valeur de la tolérance.
106: /* public GM_SurfaceBoundary boundary(Geodatabase data) throws Exception {
107: GM_Surface s = (GM_Surface)this.getPrimitive();
108: int n = s.sizePatch();
109: if (n == 1) {
110: GM_Polygon poly = (GM_Polygon)s.getPatch(0);
111: GM_SurfaceBoundary bdy = new GM_SurfaceBoundary();
112: bdy.exterior = poly.getExterior();
113: bdy.interior = poly.getInterior();
114: return bdy;
115: }
116: else if (n == 0) {
117: System.out.println("GM_OrientableSurface::boundary() : la surface est vide ");
118: return null;
119: }
120: else {
121: // Dans le cas des polygones composes de plusieurs patchs, on va utiliser Oracle pour calculer la frontiere
122: // On convertit les patchs en surface et on va en calculer l'union.
123: // Puis on renvoie la frontiere de cette union.
124: GM_Surface union = new GM_Surface(((GM_Surface)this.getPrimitive()).getPatch(0));
125: for (int i=1; i<n; i++) {
126: GM_Surface surf = new GM_Surface(((GM_Surface)this.getPrimitive()).getPatch(i));
127: union = (GM_Surface)union.union(data,0.0000000001,surf);
128: }
129: return union.boundary();
130: }
131: }*/
132:
133: /** Renvoie les coordonnees de la primitive. */
134: public DirectPositionList coord() {
135: return getPrimitive().coord();
136: }
137:
138: }
|