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: /**
030: * Rectangle englobant minimum en 2D, ou pave englobant minimium en 3D.
031: * Un GM_envelope est parallele aux axes.
032: *
033: * @author Thierry Badard & Arnaud Braun
034: * @version 1.0
035: *
036: */
037:
038: public class GM_Envelope {
039:
040: ////////////////////////////////////////////////////////////////////////////////////////////////
041: // Attributs et accesseurs /////////////////////////////////////////////////////////////////////
042: ////////////////////////////////////////////////////////////////////////////////////////////////
043:
044: /** Coin superieur : Xmax, Ymax, (Zmax).*/
045: protected DirectPosition upperCorner;
046:
047: /** Affecte le coin superieur. */
048: public void setUpperCorner(DirectPosition UpperCorner) {
049: upperCorner = (DirectPosition) UpperCorner.clone();
050: }
051:
052: /** Renvoie le coin superieur. */
053: public DirectPosition getUpperCorner() {
054: return this .upperCorner;
055: }
056:
057: /** Coin inferieur : Xmin, Ymin, (Zmin). */
058: protected DirectPosition lowerCorner;
059:
060: /** Affecte le coin inferieur. */
061: public void setLowerCorner(DirectPosition LowerCorner) {
062: lowerCorner = (DirectPosition) LowerCorner.clone();
063: }
064:
065: /** Renvoie le coin inferieur. */
066: public DirectPosition getLowerCorner() {
067: return this .lowerCorner;
068: }
069:
070: ////////////////////////////////////////////////////////////////////////////////////////////////
071: // Constructeurs ///////////////////////////////////////////////////////////////////////////////
072: ////////////////////////////////////////////////////////////////////////////////////////////////
073:
074: /** Constructeur par defaut (initialise des points 3D par defaut). */
075: public GM_Envelope() {
076: upperCorner = new DirectPosition();
077: lowerCorner = new DirectPosition();
078: }
079:
080: /** Constructeur a partir des 2 coins. Attention a l'ordre des points.*/
081: public GM_Envelope(DirectPosition UpperCorner,
082: DirectPosition LowerCorner) {
083: upperCorner = UpperCorner;
084: lowerCorner = LowerCorner;
085: }
086:
087: /** Constructeur a partir de coordonnees (2D). */
088: public GM_Envelope(double Xmin, double Xmax, double Ymin,
089: double Ymax) {
090: upperCorner = new DirectPosition(Xmax, Ymax);
091: lowerCorner = new DirectPosition(Xmin, Ymin);
092: }
093:
094: /** Constructeur a partir de coordonnees (3D). */
095: public GM_Envelope(double Xmin, double Xmax, double Ymin,
096: double Ymax, double Zmin, double Zmax) {
097: upperCorner = new DirectPosition(Xmax, Ymax, Zmax);
098: lowerCorner = new DirectPosition(Xmin, Ymin, Zmin);
099: }
100:
101: /** Construit un carre dont P est le centre, de cote d. */
102: public GM_Envelope(DirectPosition P, double d) {
103: double c = d / 2;
104: upperCorner = new DirectPosition(P.getX() + c, P.getY() + c, P
105: .getZ()
106: + c);
107: lowerCorner = new DirectPosition(P.getX() - c, P.getY() - c, P
108: .getZ()
109: - c);
110: }
111:
112: ////////////////////////////////////////////////////////////////////////////////////////////////
113: // Divers get //////////////////////////////////////////////////////////////////////////////////
114: ////////////////////////////////////////////////////////////////////////////////////////////////
115:
116: /** Renvoie la dimension (3D). */
117: public int getDimension() {
118: if (upperCorner.getDimension() == lowerCorner.getDimension())
119: return upperCorner.getDimension();
120: else {
121: System.out
122: .println("GM_Enveloppe::getDimension() : Les points upperCorner et lowerCorner n'ont pas la même dimension.");
123: return 0;
124: }
125: }
126:
127: /** Renvoie la difference des X. */
128: public double width() {
129: return upperCorner.getX() - lowerCorner.getX();
130: }
131:
132: /** Renvoie la difference des Y. */
133: public double length() {
134: return upperCorner.getY() - lowerCorner.getY();
135: }
136:
137: /** Renvoie la difference des Z. */
138: public double height() {
139: return upperCorner.getZ() - lowerCorner.getZ();
140: }
141:
142: /** Renvoie le X max. */
143: public double maxX() {
144: return upperCorner.getX();
145: }
146:
147: /** Renvoie le X min. */
148: public double minX() {
149: return lowerCorner.getX();
150: }
151:
152: /** Renvoie le Y max. */
153: public double maxY() {
154: return upperCorner.getY();
155: }
156:
157: /** Renvoie le Y min. */
158: public double minY() {
159: return lowerCorner.getY();
160: }
161:
162: /** Renvoie le Z max. */
163: public double maxZ() {
164: return upperCorner.getZ();
165: }
166:
167: /** Renvoie le Z min. */
168: public double minZ() {
169: return lowerCorner.getZ();
170: }
171:
172: /** Renvoie le centre de l'enveloppe. */
173: public DirectPosition center() {
174: int n = this .getDimension();
175: DirectPosition result = new DirectPosition();
176: for (int i = 0; i < n; i++) {
177: double theMin = lowerCorner.getCoordinate(i);
178: double theMax = upperCorner.getCoordinate(i);
179: result.setCoordinate(i, theMin + (theMax - theMin) / 2);
180: }
181: return result;
182: }
183:
184: ////////////////////////////////////////////////////////////////////////////////////////////////
185: // Methodes contains ///////////////////////////////////////////////////////////////////////////
186: ////////////////////////////////////////////////////////////////////////////////////////////////
187:
188: /** Indique si self contient le point passe en parametre, fonctionne en 2D uniquement. */
189: public boolean contains(DirectPosition thePoint) {
190: // int n = this.getDimension();
191: int n = 2;
192: for (int i = 0; i < n; i++) {
193: double theCoord = thePoint.getCoordinate(i);
194: double theMin = lowerCorner.getCoordinate(i);
195: double theMax = upperCorner.getCoordinate(i);
196: if (theCoord > theMax)
197: return false;
198: if (theCoord < theMin)
199: return false;
200: }
201: return true;
202: }
203:
204: /** Indique si self contient le point de coordonnees x,y passees en parametre (2D). */
205: public boolean contains(double x, double y) {
206: double Xmin = lowerCorner.getX();
207: double Xmax = upperCorner.getX();
208: double Ymin = lowerCorner.getY();
209: double Ymax = upperCorner.getY();
210: if (x < Xmin)
211: return false;
212: if (x > Xmax)
213: return false;
214: if (y < Ymin)
215: return false;
216: if (y > Ymax)
217: return false;
218: return true;
219: }
220:
221: /** Indique si self contient le point de coordonnees x,y,z passees en parametre (3D). */
222: public boolean contains(double x, double y, double z) {
223: double Xmin = lowerCorner.getX();
224: double Xmax = upperCorner.getX();
225: double Ymin = lowerCorner.getY();
226: double Ymax = upperCorner.getY();
227: double Zmin = lowerCorner.getZ();
228: double Zmax = upperCorner.getZ();
229: if (x < Xmin)
230: return false;
231: if (x > Xmax)
232: return false;
233: if (y < Ymin)
234: return false;
235: if (y > Ymax)
236: return false;
237: if (z < Zmin)
238: return false;
239: if (z > Zmax)
240: return false;
241: return true;
242: }
243:
244: /** Indique si self contient entierement l'enveloppe passee en parametre. */
245: public boolean contains(GM_Envelope env) {
246: if (!this .contains(env.getLowerCorner()))
247: return false;
248: if (!this .contains(env.getUpperCorner()))
249: return false;
250: return true;
251: }
252:
253: /** Indique si self et l'enveloppe passee en parametre se recouvrent, en 2D. */
254: public boolean overlaps(GM_Envelope env) {
255: if (this .getUpperCorner().getX() < env.getLowerCorner().getX())
256: return false;
257: if (this .getLowerCorner().getX() > env.getUpperCorner().getX())
258: return false;
259: if (this .getUpperCorner().getY() < env.getLowerCorner().getY())
260: return false;
261: if (this .getLowerCorner().getY() > env.getUpperCorner().getY())
262: return false;
263: return true;
264: }
265:
266: ////////////////////////////////////////////////////////////////////////////////////////////////
267: // Methodes expand /////////////////////////////////////////////////////////////////////////////
268: ////////////////////////////////////////////////////////////////////////////////////////////////
269:
270: /** Agrandit l'enveloppe pour contenir le point en entree. Si le point est deja dans l'enveloppe, ne fait rien. */
271: public void expand(DirectPosition thePoint) {
272: if (!this .contains(thePoint)) {
273: int n = this .getDimension();
274: for (int i = 0; i < n; i++) {
275: double theCoord = thePoint.getCoordinate(i);
276: double theMin = lowerCorner.getCoordinate(i);
277: double theMax = upperCorner.getCoordinate(i);
278: if (theCoord > theMax)
279: upperCorner.setCoordinate(i, theCoord);
280: else if (theCoord < theMin)
281: lowerCorner.setCoordinate(i, theCoord);
282: }
283: }
284: }
285:
286: /** Agrandit l'enveloppe pour contenir le point en entree. Si le point est deja dans l'enveloppe, ne fait rien. */
287: public void expand(double x, double y) {
288: if (!this .contains(x, y)) {
289: double Xmin = lowerCorner.getX();
290: double Xmax = upperCorner.getX();
291: double Ymin = lowerCorner.getY();
292: double Ymax = upperCorner.getY();
293: if (y > Ymax)
294: upperCorner.setY(y);
295: else if (y < Ymin)
296: lowerCorner.setY(y);
297: if (x > Xmax)
298: upperCorner.setX(x);
299: else if (x < Xmin)
300: lowerCorner.setX(x);
301: }
302: }
303:
304: /** Agrandit l'enveloppe pour contenir le point en entree. Si le point est deja dans l'enveloppe, ne fait rien. */
305: public void expand(double x, double y, double z) {
306: if (!this .contains(x, y, z)) {
307: double Xmin = lowerCorner.getX();
308: double Xmax = upperCorner.getX();
309: double Ymin = lowerCorner.getY();
310: double Ymax = upperCorner.getY();
311: double Zmin = lowerCorner.getZ();
312: double Zmax = upperCorner.getZ();
313: if (z > Zmax)
314: upperCorner.setZ(z);
315: else if (z < Zmin)
316: lowerCorner.setZ(z);
317: if (y > Ymax)
318: upperCorner.setY(y);
319: else if (y < Ymin)
320: lowerCorner.setY(y);
321: if (x > Xmax)
322: upperCorner.setX(x);
323: else if (x < Xmin)
324: lowerCorner.setX(x);
325: }
326: }
327:
328: /** Agrandit l'enveloppe pour contenir l'enveloppe en entree. Si elle est deja contenue, ne fait rien. */
329: public void expand(GM_Envelope env) {
330: if (!this .contains(env)) {
331: this .expand(env.getUpperCorner());
332: this .expand(env.getLowerCorner());
333: }
334: }
335:
336: /** Effectue une homothetie de facteur h sur l'enveloppe. */
337: public void expandBy(double h) {
338: DirectPosition theCenter = this .center();
339: int n = this .getDimension();
340: for (int i = 0; i < n; i++) {
341: double center = theCenter.getCoordinate(i);
342: double delta = upperCorner.getCoordinate(i) - center;
343: upperCorner.setCoordinate(i, center + h * delta);
344: lowerCorner.setCoordinate(i, center - h * delta);
345: }
346: }
347:
348: /** Effectue une homothetie de w sur l'axe des X et de l sur l'axe des Y. */
349: public void expandBy(double w, double l) {
350: DirectPosition theCenter = this .center();
351: double centerX = theCenter.getX();
352: double deltaX = this .maxX() - centerX;
353: upperCorner.setX(centerX + w * deltaX);
354: lowerCorner.setX(centerX - w * deltaX);
355:
356: double centerY = theCenter.getY();
357: double deltaY = this .maxY() - centerY;
358: upperCorner.setY(centerY + l * deltaY);
359: lowerCorner.setY(centerY - l * deltaY);
360: }
361:
362: /** Effectue une homothetie de w sur l'axe des X, de l sur l'axe des Y, et de h sur l'axe des Z. */
363: public void expandBy(double w, double l, double h) {
364: DirectPosition theCenter = this .center();
365: double centerX = theCenter.getX();
366: double deltaX = this .maxX() - centerX;
367: upperCorner.setX(centerX + w * deltaX);
368: lowerCorner.setX(centerX - w * deltaX);
369:
370: double centerY = theCenter.getY();
371: double deltaY = this .maxY() - centerY;
372: upperCorner.setY(centerY + l * deltaY);
373: lowerCorner.setY(centerY - l * deltaY);
374:
375: double centerZ = theCenter.getZ();
376: double deltaZ = this .maxZ() - centerZ;
377: upperCorner.setZ(centerZ + h * deltaZ);
378: lowerCorner.setZ(centerZ - h * deltaZ);
379: }
380:
381: ////////////////////////////////////////////////////////////////////////////////////////////////
382: // Divers //////////////////////////////////////////////////////////////////////////////////////
383: ////////////////////////////////////////////////////////////////////////////////////////////////
384:
385: /** Renvoie True si l'enveloppe est vide, c'est-a-dire : les coordonnees du lowerCorner
386: sont plus grandes que celles du upperCorner. */
387: public boolean isEmpty() {
388: int n = this .getDimension();
389: for (int i = 0; i < n; i++) {
390: double theMin = lowerCorner.getCoordinate(i);
391: double theMax = upperCorner.getCoordinate(i);
392: if (theMin > theMax)
393: return true;
394: }
395: return false;
396: }
397:
398: /** Clone l'enveloppe. */
399: public Object clone() {
400: DirectPosition up = (DirectPosition) upperCorner.clone();
401: DirectPosition low = (DirectPosition) lowerCorner.clone();
402: return new GM_Envelope(up, low);
403: }
404:
405: /** Affiche les coordonnees */
406: public String toString() {
407: return samplePoint().toString();
408: }
409:
410: /** Renvoie la liste des DirectPosition de l'objet. */
411: public DirectPositionList samplePoint() {
412: DirectPositionList dpl = new DirectPositionList();
413: DirectPosition dp;
414: dpl.add(lowerCorner);
415: if (!Double.isNaN(lowerCorner.getZ()))
416: dp = new DirectPosition(upperCorner.getX(), lowerCorner
417: .getY(), lowerCorner.getZ()); // a revoir
418: else
419: dp = new DirectPosition(upperCorner.getX(), lowerCorner
420: .getY());
421: dpl.add(dp);
422: dpl.add(upperCorner);
423: if (!Double.isNaN(upperCorner.getZ()))
424: dp = new DirectPosition(lowerCorner.getX(), upperCorner
425: .getY(), upperCorner.getZ()); // a revoir
426: else
427: dp = new DirectPosition(lowerCorner.getX(), upperCorner
428: .getY());
429: dpl.add(dp);
430:
431: return dpl;
432: }
433:
434: }
|