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.topoprim;
028:
029: import java.util.ArrayList;
030: import java.util.List;
031:
032: /**
033: * Permet de manipuler algébriquement les primitives, sous forme de polynomes de degré 1.
034: * Le TP_DirectedTopo représente un terme du polynome. Le TP_Expression représente tout le polynome.
035: *
036: * @author Thierry Badard & Arnaud Braun
037: * @version 1.0
038: *
039: */
040: //On n'utilise pas la classe TP_ExpressionTerm de la norme.
041:
042: public class TP_Expression {
043:
044: /** Liste des termes. */
045: protected List term;
046:
047: /** Renvoie le terme de rang i. */
048: public TP_DirectedTopo getTerm(int i) {
049: return (TP_DirectedTopo) this .term.get(i);
050: }
051:
052: /** Renvoie la liste des termes. */
053: public List getTermList() {
054: return this .term;
055: }
056:
057: /** Affecte une valeur au rang i. */
058: public void setTerm(int i, TP_DirectedTopo value) {
059: this .term.set(i, value);
060: }
061:
062: /** Ajoute un terme en fin de liste. */
063: public void addTerm(TP_DirectedTopo value) {
064: this .term.add(value);
065: }
066:
067: /** Ajoute un terme au rang i. */
068: public void addTerm(int i, TP_DirectedTopo value) {
069: this .term.add(i, value);
070: }
071:
072: /** Efface le terme de valeur "value". */
073: public void removeTerm(TP_DirectedTopo value) {
074: this .term.remove(value);
075: }
076:
077: /** Efface le terme de rang i. */
078: public void removeTerm(int i) {
079: this .term.remove(i);
080: }
081:
082: /** Renvoie le nombre de termes. */
083: public int sizeTerm() {
084: return this .term.size();
085: }
086:
087: /** Constructeur par défaut. */
088: public TP_Expression() {
089: term = new ArrayList();
090: }
091:
092: /**Constructeur à partir d'un TP_DirectedTopo.*/
093: public TP_Expression(TP_DirectedTopo dt) {
094: term = new ArrayList();
095: term.add(dt);
096: }
097:
098: /** Constructeur à partir de plusieurs TP_DirectedTopo. */
099: public TP_Expression(List sdt) {
100: term = new ArrayList();
101: for (int i = 0; i < sdt.size(); i++) {
102: TP_DirectedTopo dt = (TP_DirectedTopo) sdt.get(i);
103: term.add(dt);
104: }
105: this .simplify();
106: }
107:
108: /** Addition de 2 TP_Expression (self et le TP_Expression passé en paramètre). */
109: public TP_Expression plus(TP_Expression s) {
110: TP_Expression result = new TP_Expression();
111: result.term.addAll(this .term);
112: result.term.addAll(s.term);
113: result.simplify();
114: return result;
115: }
116:
117: /** Soustraction de 2 TP_Expression (self et le TP_Expression passé en paramètre). */
118: public TP_Expression minus(TP_Expression s) {
119: TP_Expression result = new TP_Expression();
120: result.term.addAll(this .term);
121: for (int i = 0; i < s.sizeTerm(); i++) {
122: TP_DirectedTopo dt = s.getTerm(i);
123: TP_DirectedTopo dtnegate = null;
124: // cast necessaire pour utiliser la fonction negate()
125: if (dt instanceof TP_DirectedNode)
126: dtnegate = ((TP_DirectedNode) dt).negate();
127: else if (dt instanceof TP_DirectedEdge)
128: dtnegate = ((TP_DirectedEdge) dt).negate();
129: else if (dt instanceof TP_DirectedFace)
130: dtnegate = ((TP_DirectedFace) dt).negate();
131: else if (dt instanceof TP_DirectedSolid)
132: dtnegate = ((TP_DirectedSolid) dt).negate();
133: else if (dt instanceof TP_Node)
134: dtnegate = ((TP_Node) dt).negate();
135: else if (dt instanceof TP_Edge)
136: dtnegate = ((TP_Edge) dt).negate();
137: else if (dt instanceof TP_Face)
138: dtnegate = ((TP_Face) dt).negate();
139: else if (dt instanceof TP_Solid)
140: dtnegate = ((TP_Solid) dt).negate();
141: result.term.add(dtnegate);
142: }
143: result.simplify();
144: return result;
145: }
146:
147: /** Renvoie l'opposé de self.*/
148: public TP_Expression negate() {
149: TP_Expression result = new TP_Expression();
150: int n = this .sizeTerm();
151: for (int i = 0; i < n; i++) {
152: TP_DirectedTopo dt = this .getTerm(n - i - 1);
153: TP_DirectedTopo dtnegate = null;
154: // cast necessaire pour utiliser la fonction negate()
155: if (dt instanceof TP_DirectedNode)
156: dtnegate = ((TP_DirectedNode) dt).negate();
157: else if (dt instanceof TP_DirectedEdge)
158: dtnegate = ((TP_DirectedEdge) dt).negate();
159: else if (dt instanceof TP_DirectedFace)
160: dtnegate = ((TP_DirectedFace) dt).negate();
161: else if (dt instanceof TP_DirectedSolid)
162: dtnegate = ((TP_DirectedSolid) dt).negate();
163: else if (dt instanceof TP_Node)
164: dtnegate = ((TP_Node) dt).negate();
165: else if (dt instanceof TP_Edge)
166: dtnegate = ((TP_Edge) dt).negate();
167: else if (dt instanceof TP_Face)
168: dtnegate = ((TP_Face) dt).negate();
169: else if (dt instanceof TP_Solid)
170: dtnegate = ((TP_Solid) dt).negate();
171: result.term.add(dtnegate);
172: }
173: return result;
174: }
175:
176: /** TRUE si self est un zéro polynomial.*/
177: public boolean isZero() {
178: this .simplify();
179: if (this .sizeTerm() == 0)
180: return true;
181: else
182: return false;
183: }
184:
185: /** TRUE si la frontière est zéro. */
186: public boolean isCycle() {
187: if (this .boundary().isZero())
188: return true;
189: else
190: return false;
191: }
192:
193: /** Remplace chaque boundary de chaque TP_Primitive de chaque TP_DirectedTopo, et simplifie le résultat. */
194: public TP_Expression boundary() {
195: TP_Expression result = new TP_Expression();
196: for (int i = 0; i < this .sizeTerm(); i++) {
197: TP_DirectedTopo dt = this .getTerm(i);
198: TP_Boundary dtbdy = null;
199: // cast necessaire pour utiliser la fonction boundary()
200: if (dt instanceof TP_DirectedNode)
201: dtbdy = ((TP_DirectedNode) dt).boundary();
202: else if (dt instanceof TP_DirectedEdge)
203: dtbdy = ((TP_DirectedEdge) dt).boundary();
204: else if (dt instanceof TP_DirectedFace)
205: dtbdy = ((TP_DirectedFace) dt).boundary();
206: else if (dt instanceof TP_DirectedSolid)
207: dtbdy = ((TP_DirectedSolid) dt).boundary();
208: else if (dt instanceof TP_Node)
209: dtbdy = ((TP_Node) dt).boundary();
210: else if (dt instanceof TP_Edge)
211: dtbdy = ((TP_Edge) dt).boundary();
212: else if (dt instanceof TP_Face)
213: dtbdy = ((TP_Face) dt).boundary();
214: else if (dt instanceof TP_Solid)
215: dtbdy = ((TP_Solid) dt).boundary();
216: result = result.plus(dtbdy);
217: }
218: return result;
219: }
220:
221: /** TRUE s'il y a égalité polynomiale. */
222: public boolean equals(TP_Expression s) {
223: TP_Expression this Bis = new TP_Expression();
224: TP_Expression sBis = new TP_Expression();
225: for (int i = 0; i < this .sizeTerm(); i++)
226: this Bis.addTerm(this .getTerm(i));
227: for (int i = 0; i < s.sizeTerm(); i++)
228: sBis.addTerm(s.getTerm(i));
229: this Bis.simplify();
230: sBis.simplify();
231: if (this Bis.sizeTerm() != sBis.sizeTerm())
232: return false;
233: while (this Bis.sizeTerm() > 0) {
234: TP_DirectedTopo dt1 = this Bis.getTerm(0);
235: for (int j = 0; j < sBis.sizeTerm(); j++) {
236: TP_DirectedTopo dt2 = sBis.getTerm(j);
237: if (dt1.getId() == dt2.getId()) {
238: this Bis.removeTerm(0);
239: sBis.removeTerm(j);
240: break;
241: }
242: return false;
243: }
244: }
245: return true;
246: }
247:
248: /** Cast en liste de TP_Primitive. Dans la norme, on convertit en set.*/
249: public List support() {
250: List result = new ArrayList();
251: for (int i = 0; i < this .sizeTerm(); i++) {
252: TP_DirectedTopo dt = this .getTerm(i);
253: TP_Primitive prim = null;
254: // cast necessaire pour utiliser la fonction boundary()
255: if (dt instanceof TP_DirectedNode)
256: prim = ((TP_DirectedNode) dt).topo();
257: else if (dt instanceof TP_DirectedEdge)
258: prim = ((TP_DirectedEdge) dt).topo();
259: else if (dt instanceof TP_DirectedFace)
260: prim = ((TP_DirectedFace) dt).topo();
261: else if (dt instanceof TP_DirectedSolid)
262: prim = ((TP_DirectedSolid) dt).topo();
263: else if (dt instanceof TP_Node)
264: prim = ((TP_Node) dt).topo();
265: else if (dt instanceof TP_Edge)
266: prim = ((TP_Edge) dt).topo();
267: else if (dt instanceof TP_Face)
268: prim = ((TP_Face) dt).topo();
269: else if (dt instanceof TP_Solid)
270: prim = ((TP_Solid) dt).topo();
271: result.add(prim);
272: }
273: return result;
274: }
275:
276: /** Cast chaque coBoundary de chaque TP_Primitive de chaque TP_DirectedTopo en TP_Expression, et simplifie le résultat.*/
277: public TP_Expression coBoundary() {
278: TP_Expression result = new TP_Expression();
279: for (int i = 0; i < this .sizeTerm(); i++) {
280: TP_DirectedTopo dt = this .getTerm(i);
281: List theCoBoundary = null;
282: // cast necessaire pour utiliser la fonction boundary()
283: if (dt instanceof TP_DirectedNode)
284: theCoBoundary = ((TP_DirectedNode) dt).coBoundary();
285: else if (dt instanceof TP_DirectedEdge)
286: theCoBoundary = ((TP_DirectedEdge) dt).coBoundary();
287: else if (dt instanceof TP_DirectedFace)
288: theCoBoundary = ((TP_DirectedFace) dt).coBoundary();
289: else if (dt instanceof TP_DirectedSolid)
290: theCoBoundary = ((TP_DirectedSolid) dt).coBoundary();
291: else if (dt instanceof TP_Node)
292: theCoBoundary = ((TP_Node) dt).coBoundary();
293: else if (dt instanceof TP_Edge)
294: theCoBoundary = ((TP_Edge) dt).coBoundary();
295: else if (dt instanceof TP_Face)
296: theCoBoundary = ((TP_Face) dt).coBoundary();
297: else if (dt instanceof TP_Solid)
298: theCoBoundary = ((TP_Solid) dt).coBoundary();
299: TP_Expression tpe = new TP_Expression(theCoBoundary);
300: result = result.plus(tpe);
301: }
302: return result;
303: }
304:
305: /** Cast en liste de TP_DirectedTopo. Dans la norme, on convertit en set.*/
306: public List asSet() {
307: List result = new ArrayList();
308: for (int i = 0; i < this .sizeTerm(); i++) {
309: TP_DirectedTopo dt = this .getTerm(i);
310: result.add(dt);
311: }
312: return result;
313: }
314:
315: /**= Usage interne. Simplifie le TP_Expression en annulant les termes opposés. */
316: private void simplify() {
317: int n = this .sizeTerm();
318: if (n > 1) {
319: for (int i = 0; i < n - 1; i++) {
320: TP_DirectedTopo dt1 = this .getTerm(i);
321: for (int j = i + 1; j < n; j++) {
322: TP_DirectedTopo dt2 = this .getTerm(j);
323: if (dt1.getId() == -dt2.getId()) {
324: this .removeTerm(j);
325: this .removeTerm(i);
326: n = n - 2;
327: i = i - 1;
328: break;
329: }
330: }
331: }
332: }
333: }
334:
335: }
|