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.contrib.geometrie;
028:
029: import fr.ign.cogit.geoxygene.spatial.coordgeom.DirectPosition;
030: import fr.ign.cogit.geoxygene.spatial.coordgeom.GM_LineString;
031:
032: /**
033: * Classe pour le calcul avec des vecteurs (2D ou 3D).
034: * Supporte la plupart des opérations classiques.
035: * Les coordonnees des vecteurs sont stockees dans des DirectPosition.
036: * Les vecteurs 2D ont NaN comme troisieme coordonnee.
037: *
038: * English: Class for computations with vectors (either 2D or 3D).
039: * Coordinates are stored into DirectPosition. 2D vectors
040: * are given Nan As third coordinate).
041: *
042: * @author Mustière/Bonin
043: * @version 1.0
044: */
045:
046: public class Vecteur {
047: protected DirectPosition coord = null;
048:
049: public DirectPosition getCoord() {
050: return this .coord;
051: }
052:
053: public void setCoord(DirectPosition coord) {
054: this .coord = coord;
055: }
056:
057: /* Helpers pour la programmation : vecteurs nuls en 2D et 3D*/
058: public static final Vecteur vecteurNul2D = new Vecteur(
059: new DirectPosition(0, 0, Double.NaN));
060: public static final Vecteur vecteurNul3D = new Vecteur(
061: new DirectPosition(0, 0, 0));
062:
063: public Vecteur() {
064: coord = new DirectPosition();
065: }
066:
067: /** Initialise le vecteur 0 -> dp1 (a dp1) */
068: public Vecteur(DirectPosition dp1) {
069: coord = dp1;
070: }
071:
072: /** Initialise le vecteur dp1 -> dp2 (a dp2-dp1) */
073: public Vecteur(DirectPosition dp1, DirectPosition dp2) {
074: if (!Double.isNaN(dp1.getZ()) && !Double.isNaN(dp2.getZ())) {
075: coord = new DirectPosition(dp2.getX() - dp1.getX(), dp2
076: .getY()
077: - dp1.getY(), dp2.getZ() - dp1.getZ());
078: } else {
079: coord = new DirectPosition(dp2.getX() - dp1.getX(), dp2
080: .getY()
081: - dp1.getY(), Double.NaN);
082: }
083: }
084:
085: public Vecteur(double a, double b, double c) {
086: if (c != 0) {
087: coord = new DirectPosition(a, b, c);
088: } else {
089: coord = new DirectPosition(a, b, Double.NaN);
090: }
091: }
092:
093: public double getX() {
094: return this .coord.getX();
095: }
096:
097: public double getY() {
098: return this .coord.getY();
099: }
100:
101: public double getZ() {
102: return this .coord.getZ();
103: }
104:
105: public void setX(double X) {
106: this .coord.setX(X);
107: }
108:
109: public void setY(double Y) {
110: this .coord.setY(Y);
111: }
112:
113: public void setZ(double Z) {
114: this .coord.setZ(Z);
115: }
116:
117: /** Renvoie la norme de this */
118: public double norme() {
119: if (!Double.isNaN(this .getZ())) {
120: return Math.sqrt(Math.pow(this .getX(), 2)
121: + Math.pow(this .getY(), 2)
122: + Math.pow(this .getZ(), 2));
123: } else {
124: return Math.sqrt(Math.pow(this .getX(), 2)
125: + Math.pow(this .getY(), 2));
126: }
127: }
128:
129: /** Renvoie un NOUVEAU vecteur égal au vecteur normé porté par this */
130: public Vecteur vectNorme() {
131: double normev = this .norme();
132: if (!Double.isNaN(this .getZ())) {
133: return new Vecteur(new DirectPosition(this .getX() / normev,
134: this .getY() / normev, this .getZ() / normev));
135: } else {
136: return new Vecteur(new DirectPosition(this .getX() / normev,
137: this .getY() / normev, Double.NaN));
138: }
139: }
140:
141: /** Norme le vecteur this (MODIFIE le this)*/
142: public void normalise() {
143: double normev = this .norme();
144: if (!Double.isNaN(this .getZ())) {
145: this .setX((this .getX() / normev));
146: this .setY((this .getY() / normev));
147: this .setZ((this .getZ() / normev));
148: } else {
149: this .setX((this .getX() / normev));
150: this .setY((this .getY() / normev));
151: }
152: }
153:
154: /** Renvoie un NOUVEAU vecteur égal à (this + v1) */
155: public Vecteur ajoute(Vecteur v1) {
156: if (!Double.isNaN(this .getZ()) && !Double.isNaN(v1.getZ())) {
157: return new Vecteur(new DirectPosition(this .getX()
158: + v1.getX(), this .getY() + v1.getY(), this .getZ()
159: + v1.getZ()));
160: } else {
161: return new Vecteur(new DirectPosition(this .getX()
162: + v1.getX(), this .getY() + v1.getY(), Double.NaN));
163: }
164: }
165:
166: /** Renvoie un NOUVEAU vecteur égal à (this - v1) */
167: public Vecteur soustrait(Vecteur v1) {
168: if (!Double.isNaN(this .getZ()) && !Double.isNaN(v1.getZ())) {
169: return new Vecteur(new DirectPosition(this .getX()
170: - v1.getX(), this .getY() - v1.getY(), this .getZ()
171: - v1.getZ()));
172: } else {
173: return new Vecteur(new DirectPosition(this .getX()
174: - v1.getX(), this .getY() - v1.getY(), Double.NaN));
175: }
176: }
177:
178: /** Renvoie un NOUVEAU vecteur égal à (lambda.this) */
179: public Vecteur multConstante(double lambda) {
180: if (!Double.isNaN(this .getZ())) {
181: return new Vecteur(new DirectPosition(lambda * this .getX(),
182: lambda * this .getY(), lambda * this .getZ()));
183: } else {
184: return new Vecteur(new DirectPosition(lambda * this .getX(),
185: lambda * this .getY(), Double.NaN));
186: }
187: }
188:
189: /** Renvoie le point translaté de P par le vecteur this */
190: public DirectPosition translate(DirectPosition P) {
191: DirectPosition P2 = new DirectPosition();
192: P2.setX(P.getX() + this .getX());
193: P2.setY(P.getY() + this .getY());
194: if (Double.isNaN(this .getZ()) || Double.isNaN(P.getZ()))
195: P2.setZ(Double.NaN);
196: else
197: P2.setZ(P.getZ() + this .getZ());
198: return P2;
199: }
200:
201: /** Renvoie la ligne translatée de L par le vecteur this */
202: public GM_LineString translate(GM_LineString L) {
203: GM_LineString L2 = new GM_LineString();
204: for (int i = 0; i < L.sizeControlPoint(); i++) {
205: DirectPosition pt = L.getControlPoint(i);
206: L2.addControlPoint(translate(pt));
207: }
208: return L2;
209: }
210:
211: /** Renvoie le produit vectoriel this^v1 ;
212: * NB: le produit vectoriel renvoie toujours un vecteur 3D,
213: * même à partir de vecteurs 2D */
214: public Vecteur prodVectoriel(Vecteur v1) {
215: if (!Double.isNaN(this .getZ()) && !Double.isNaN(v1.getZ())) {
216: return new Vecteur(new DirectPosition(this .getY()
217: * v1.getZ() - this .getZ() * v1.getY(), this .getZ()
218: * v1.getX() - this .getX() * v1.getZ(), this .getX()
219: * v1.getY() - this .getY() * v1.getX()));
220: } else {
221: return new Vecteur(new DirectPosition(0, 0, this .getX()
222: * v1.getY() - this .getY() * v1.getX()));
223: }
224: }
225:
226: /** Renvoie le produit scalaire this.v1 */
227: public double prodScalaire(Vecteur v1) {
228: if (!Double.isNaN(this .getZ()) && !Double.isNaN(v1.getZ())) {
229: return (this .getX() * v1.getX() + this .getY() * v1.getY() + this
230: .getZ()
231: * v1.getZ());
232:
233: } else {
234: return (this .getX() * v1.getX() + this .getY() * v1.getY());
235: }
236: }
237:
238: /** Angle entre l'axe des X et le vecteur this projeté sur le plan XY */
239: public Angle direction() {
240: return new Angle(Math.atan2(this .getY(), this .getX()));
241: }
242:
243: /** Angle entre this et v1 */
244: public Angle angleVecteur(Vecteur V1) {
245: double angle = 0;
246: angle = Math.acos(this .prodScalaire(V1)
247: / (this .norme() * V1.norme()));
248: if (Double.isNaN(angle))
249: angle = 0;
250: return new Angle(angle);
251: }
252: }
|