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.appariement.reseaux;
028:
029: import java.sql.Time;
030: import java.util.ArrayList;
031: import java.util.Iterator;
032: import java.util.List;
033:
034: import fr.ign.cogit.geoxygene.contrib.appariement.EnsembleDeLiens;
035: import fr.ign.cogit.geoxygene.contrib.appariement.reseaux.topologie.ArcApp;
036: import fr.ign.cogit.geoxygene.contrib.appariement.reseaux.topologie.NoeudApp;
037: import fr.ign.cogit.geoxygene.contrib.appariement.reseaux.topologie.ReseauApp;
038: import fr.ign.cogit.geoxygene.feature.FT_Feature;
039: import fr.ign.cogit.geoxygene.feature.FT_FeatureCollection;
040: import fr.ign.cogit.geoxygene.feature.Population;
041: import fr.ign.cogit.geoxygene.spatial.coordgeom.DirectPosition;
042: import fr.ign.cogit.geoxygene.spatial.coordgeom.DirectPositionList;
043: import fr.ign.cogit.geoxygene.spatial.coordgeom.GM_LineString;
044: import fr.ign.cogit.geoxygene.spatial.geomprim.GM_Point;
045: import fr.ign.cogit.geoxygene.util.index.Tiling;
046:
047: /**
048: *
049: * Méthodes d'import et export pour l'appariement sur des données géographiques quelconques
050: * (création des réseaux, lancement de l'appariement, export des résultats).
051: *
052: * @author Mustiere - IGN / Laboratoire COGIT
053: * @version 1.0
054: *
055: */
056:
057: public class AppariementIO {
058:
059: /** Lancement de l'appariement de réseaux sur des objets géographiques :
060: * 1- Transformation des données initales en deux graphes, en fonction des paramètres d'import.
061: * 2- Lancement du calcul d'appariement générique sur les deux réseaux.
062: * 3- Analyse et export des résutlats éventuellement
063: *
064: * @return
065: * L'ensemble des liens en sortie (de la classe EnsembleDeLiens).
066: *
067: * @param paramApp
068: * Les paramètres de l'appariement (seuls de distance, préparation topologique des données...)
069: *
070: * @param cartesTopo
071: * Liste en entrée/sortie qui permet de récupérer en sortie les graphes intermédiaires
072: * créés pendant le calcul (de type Reseau_App, spécialisation de CarteTopo).
073: * - Si on veut récupérer les graphes : passer une liste vide - new ArrayList() - mais non nulle.
074: * Elle contient alors en sortie 2 éléments : dans l'ordre les cartes topo de reférence et comparaison.
075: * Elle peut contenir un 3eme élément: le graphe ref recalé sur comp si cela est demandé dans les paramètres.
076: * - Si on ne veut rien récupérer : passer Null
077: */
078: public static EnsembleDeLiens AppariementDeJeuxGeo(
079: ParametresApp paramApp, List cartesTopo) {
080:
081: ReseauApp reseauRef, reseauComp;
082: EnsembleDeLiens liens, liensGeneriques;
083:
084: if (paramApp.debugAffichageCommentaires > 0)
085: System.out.println("");
086: if (paramApp.debugAffichageCommentaires > 0)
087: System.out
088: .println("######## DEBUT DE L'APPARIEMENT DE RESEAUX #########");
089: if (paramApp.debugAffichageCommentaires > 0)
090: System.out
091: .println(" (1 = les données les moins détaillées ; 2 = les données les plus détaillées)");
092: if (paramApp.debugAffichageCommentaires > 0)
093: System.out.println("");
094: ////////////////////////////////////////////////
095: // STRUCTURATION
096: if (paramApp.debugAffichageCommentaires > 0)
097: System.out.println("STRUCTURATION DES DONNEES");
098: if (paramApp.debugAffichageCommentaires > 0)
099: System.out
100: .println(" Organisation des données en réseau et prétraitements topologiques");
101: if (paramApp.debugAffichageCommentaires > 1)
102: System.out
103: .println(" DEBUT DE LA PHASE DE STRUCTURATION "
104: + (new Time(System.currentTimeMillis()))
105: .toString());
106: if (paramApp.debugAffichageCommentaires > 1)
107: System.out
108: .println(" Création du réseau correspondant au jeu 1 "
109: + (new Time(System.currentTimeMillis()))
110: .toString());
111: reseauRef = Import(paramApp, true);
112: if (cartesTopo != null)
113: cartesTopo.add(reseauRef);
114: if (paramApp.debugAffichageCommentaires > 1)
115: System.out
116: .println(" Création du réseau correspondant au jeu 2 "
117: + (new Time(System.currentTimeMillis()))
118: .toString());
119: reseauComp = Import(paramApp, false);
120: if (cartesTopo != null)
121: cartesTopo.add(reseauComp);
122:
123: // NB: l'ordre dans lequel les projections sont faites n'est pas neutre
124: if (paramApp.projeteNoeud2surReseau1) {
125: if (paramApp.debugAffichageCommentaires > 1)
126: System.out
127: .println(" Projection du réseau 2 sur le réseau 1 "
128: + (new Time(System.currentTimeMillis()))
129: .toString());
130: else
131: reseauRef
132: .projete(
133: reseauComp,
134: paramApp.projeteNoeud2surReseau1_DistanceNoeudArc,
135: paramApp.projeteNoeud2surReseau1_DistanceProjectionNoeud,
136: paramApp.projeteNoeud2surReseau1_ImpassesSeulement);
137: }
138: if (paramApp.projeteNoeuds1SurReseau2) {
139: if (paramApp.debugAffichageCommentaires > 1)
140: System.out
141: .println(" Projection du réseau 1 sur le réseau 2 "
142: + (new Time(System.currentTimeMillis()))
143: .toString());
144: else
145: reseauComp
146: .projete(
147: reseauRef,
148: paramApp.projeteNoeuds1SurReseau2_DistanceNoeudArc,
149: paramApp.projeteNoeuds1SurReseau2_DistanceProjectionNoeud,
150: paramApp.projeteNoeuds1SurReseau2_ImpassesSeulement);
151: }
152:
153: if (paramApp.debugAffichageCommentaires > 1)
154: System.out
155: .println(" Remplissage des attributs des arcs et noeuds des réseaux "
156: + (new Time(System.currentTimeMillis()))
157: .toString());
158: reseauRef.instancieAttributsNuls(paramApp);
159: reseauComp.initialisePoids();
160:
161: if (paramApp.debugAffichageCommentaires > 0)
162: System.out
163: .println(" Structuration initiale des données terminée : ");
164: if (paramApp.debugAffichageCommentaires > 0)
165: System.out.println(" Réseau 1 : "
166: + reseauRef.getPopArcs().size() + " arcs et "
167: + reseauRef.getPopNoeuds().size() + " noeuds.");
168: if (paramApp.debugAffichageCommentaires > 0)
169: System.out.println(" Réseau 2 : "
170: + reseauComp.getPopArcs().size() + " arcs et "
171: + reseauComp.getPopNoeuds().size() + " noeuds.");
172: if (paramApp.debugAffichageCommentaires > 1)
173: System.out
174: .println(" FIN DE LA PHASE DE STRUCTURATION "
175: + (new Time(System.currentTimeMillis()))
176: .toString());
177:
178: ////////////////////////////////////////////////
179: // APPARIEMENT
180: if (paramApp.debugAffichageCommentaires > 0)
181: System.out.println("");
182: if (paramApp.debugAffichageCommentaires > 0)
183: System.out.println("APPARIEMENT DES RESEAUX");
184: if (paramApp.debugAffichageCommentaires > 1)
185: System.out
186: .println(" DEBUT DE LA PHASE D'APPARIEMENT DES RESEAUX "
187: + (new Time(System.currentTimeMillis()))
188: .toString());
189: liens = Appariement.appariementReseaux(reseauRef, reseauComp,
190: paramApp);
191: if (paramApp.debugAffichageCommentaires > 0)
192: System.out.println(" Appariement des réseaux terminé ");
193: if (paramApp.debugAffichageCommentaires > 0)
194: System.out
195: .println(" "
196: + liens.size()
197: + " liens d'appariement ont été trouvés (dans la structure de travail)");
198: if (paramApp.debugAffichageCommentaires > 1)
199: System.out
200: .println(" FIN DE LA PHASE D'APPARIEMENT DES RESEAUX "
201: + (new Time(System.currentTimeMillis()))
202: .toString());
203:
204: ////////////////////////////////////////////////
205: // EXPORT
206: if (paramApp.debugAffichageCommentaires > 0)
207: System.out.println("");
208: if (paramApp.debugAffichageCommentaires > 0)
209: System.out.println("BILAN ET EXPORT DES RESULTATS ");
210: if (paramApp.debugAffichageCommentaires > 1)
211: System.out
212: .println(" DEBUT DE LA PHASE D'EXPORT "
213: + (new Time(System.currentTimeMillis()))
214: .toString());
215: if (paramApp.debugBilanSurObjetsGeo == false) {
216: if (paramApp.debugAffichageCommentaires > 1)
217: System.out
218: .println(" Affectation d'une géométrie aux liens "
219: + (new Time(System.currentTimeMillis()))
220: .toString());
221: liensGeneriques = LienReseaux.exportAppCarteTopo(liens,
222: paramApp);
223: } else {
224: if (paramApp.debugAffichageCommentaires > 1)
225: System.out
226: .println(" Transformation des liens de réseaux en liens génériques "
227: + (new Time(System.currentTimeMillis()))
228: .toString());
229: liensGeneriques = LienReseaux.exportLiensAppariement(liens,
230: reseauRef, paramApp);
231: }
232:
233: if (paramApp.debugAffichageCommentaires > 1)
234: System.out
235: .println(" Nettoyage des réseaux (destruction des liens temporaires créés...) "
236: + (new Time(System.currentTimeMillis()))
237: .toString());
238: Appariement.nettoyageLiens(reseauRef, reseauComp);
239: if (paramApp.debugAffichageCommentaires > 1)
240: System.out
241: .println(" Fin du nettoyage "
242: + (new Time(System.currentTimeMillis()))
243: .toString());
244:
245: if (paramApp.debugAffichageCommentaires > 0)
246: System.out.println(" Bilan et export terminés ");
247: if (paramApp.debugAffichageCommentaires > 0)
248: System.out
249: .println(" "
250: + liensGeneriques.size()
251: + " liens d'appariement ont été exportés (dans la structure finale)");
252: if (paramApp.debugAffichageCommentaires > 1)
253: System.out
254: .println(" FIN DE LA PHASE D'EXPORT "
255: + (new Time(System.currentTimeMillis()))
256: .toString());
257: if (paramApp.debugAffichageCommentaires > 0)
258: System.out.println("");
259: if (paramApp.debugAffichageCommentaires > 0)
260: System.out
261: .println("######## FIN DE L'APPARIEMENT DE RESEAUX #########");
262:
263: return liensGeneriques;
264: }
265:
266: //////////////////////////////////////////////////////////////////////
267: // METHODES D'IMPORT //
268: //////////////////////////////////////////////////////////////////////
269: /** Création d'une carte topo à partir des objets géographiques initiaux.
270: * *
271: * @return
272: * Le réseau créé.
273: *
274: * @param paramApp
275: * Les paramètres de l'appariement (seuls de distance, préparation topologique des données...)
276: *
277: * @param paramApp
278: * true = on traite le réseau de référence
279: * false = on traite le réseau de comparaison
280: */
281: private static ReseauApp Import(ParametresApp paramApp, boolean ref) {
282: ReseauApp reseau;
283: Iterator itPopArcs, itPopNoeuds, itElements;
284: FT_FeatureCollection popGeo;
285: Population popArcApp, popNoeudApp;
286: FT_Feature element;
287: ArcApp arc;
288: NoeudApp noeud;
289:
290: if (ref)
291: reseau = new ReseauApp("Réseau de référence");
292: else
293: reseau = new ReseauApp("Réseau de comparaison");
294: popArcApp = reseau.getPopArcs();
295: popNoeudApp = reseau.getPopNoeuds();
296:
297: ///////////////////////////
298: // import des arcs
299: if (ref)
300: itPopArcs = paramApp.populationsArcs1.iterator();
301: else
302: itPopArcs = paramApp.populationsArcs2.iterator();
303: while (itPopArcs.hasNext()) {
304: popGeo = (FT_FeatureCollection) itPopArcs.next();
305: //import d'une population d'arcs
306: itElements = popGeo.getElements().iterator();
307: while (itElements.hasNext()) {
308: element = (FT_Feature) itElements.next();
309: arc = (ArcApp) popArcApp.nouvelElement();
310: GM_LineString ligne = new GM_LineString(
311: (DirectPositionList) element.getGeom().coord()
312: .clone());
313: arc.setGeometrie(ligne);
314: if (paramApp.populationsArcsAvecOrientationDouble)
315: arc.setOrientation(2);
316: else
317: arc.setOrientation(1);
318: arc.addCorrespondant(element);
319:
320: // Le code ci-dessous permet un import plus fin mais a été réalisé
321: // pour des données spécifiques et n'est pas encore codé très générique.
322: // Il est donc commenté dans cette version du code.
323: // element = (FT_Feature)itElements.next();
324: // if ( ref && paramApp.filtrageRef ) {
325: // if ( filtrageTroncon(element) ) continue;
326: // }
327: // if ( !ref && paramApp.filtrageComp ) {
328: // if ( filtrageTroncon(element) ) continue;
329: // }
330: // arc = (Arc_App)popArcApp.nouvelElement();
331: // GM_LineString ligne = new GM_LineString((DirectPositionList)element.getGeom().coord().clone());
332: // arc.setGeometrie(ligne);
333: // if ( paramApp.orientationConstante) {
334: // if (paramApp.orientationDouble) arc.setOrientation(2);
335: // else arc.setOrientation(1);
336: // }
337: // else arc.setOrientation(orientationTroncon(element));
338: // arc.addCorrespondant(element);
339: }
340: }
341:
342: ///////////////////////////
343: // import des noeuds
344: if (ref)
345: itPopNoeuds = paramApp.populationsNoeuds1.iterator();
346: else
347: itPopNoeuds = paramApp.populationsNoeuds2.iterator();
348: while (itPopNoeuds.hasNext()) {
349: popGeo = (Population) itPopNoeuds.next();
350: //import d'une population de noeuds
351: itElements = popGeo.getElements().iterator();
352: while (itElements.hasNext()) {
353: element = (FT_Feature) itElements.next();
354: noeud = (NoeudApp) popNoeudApp.nouvelElement();
355: //noeud.setGeometrie((GM_Point)element.getGeom());
356: noeud.setGeometrie(new GM_Point(
357: (DirectPosition) ((GM_Point) element.getGeom())
358: .getPosition().clone()));
359: noeud.addCorrespondant(element);
360: noeud.setTaille(paramApp.distanceNoeudsMax);
361: // Le code ci-dessous permet un import plus fin mais a été réalisé
362: // pour des données spécifiques et n'est pas encore codé très générique.
363: // Il est donc commenté dans cette version du code.
364: // if ( paramApp.distanceNoeudsConstante ) noeud.setTaille(paramApp.distanceNoeuds);
365: // else noeud.setTaille(tailleNoeud(element, paramApp));
366: }
367: }
368:
369: /////////////////////////////
370: // Indexation spatiale des arcs et noeuds
371: // On crée un dallage régulier avec en moyenne 20 objets par case
372: if (paramApp.debugAffichageCommentaires > 1)
373: System.out
374: .println(" Indexation spatiale des arcs et des noeuds "
375: + (new Time(System.currentTimeMillis()))
376: .toString());
377: int nb = (int) Math.sqrt(reseau.getPopArcs().size() / 20);
378: if (nb == 0)
379: nb = 1;
380: reseau.getPopArcs().initSpatialIndex(Tiling.class, true, nb);
381: reseau.getPopNoeuds().initSpatialIndex(
382: reseau.getPopArcs().getSpatialIndex());
383:
384: /////////////////////////////
385: // Instanciation de la topologie
386:
387: // 1- Création de la topologie arcs-noeuds, rendu du graphe planaire
388: if ((ref && paramApp.topologieGraphePlanaire1)
389: || (!ref && paramApp.topologieGraphePlanaire2)) { // cas où on veut une topologie planaire
390: if (paramApp.debugAffichageCommentaires > 1)
391: System.out
392: .println(" Rendu du graphe planaire et instanciation de la topologie arcs-noeuds "
393: + (new Time(System.currentTimeMillis()))
394: .toString());
395: reseau.filtreArcsDoublons();
396: //reseau.creeTopologieArcsNoeuds(0);
397: reseau.rendPlanaire(0);
398: reseau.filtreDoublons(0);
399: } else { // cas où on ne veut pas nécessairement rendre planaire la topologie
400: if (paramApp.debugAffichageCommentaires > 1)
401: System.out.println(" Instanciation de la topologie "
402: + (new Time(System.currentTimeMillis()))
403: .toString());
404: reseau.creeNoeudsManquants(0);
405: reseau.filtreDoublons(0);
406: reseau.creeTopologieArcsNoeuds(0);
407: }
408:
409: // 2- On fusionne les noeuds proches
410: if (ref) {
411: if (paramApp.topologieSeuilFusionNoeuds1 >= 0) {
412: if (paramApp.debugAffichageCommentaires > 1)
413: System.out.println(" Fusion des noeuds proches "
414: + (new Time(System.currentTimeMillis()))
415: .toString());
416: reseau
417: .fusionNoeuds(paramApp.topologieSeuilFusionNoeuds1);
418: }
419: if (paramApp.topologieSurfacesFusionNoeuds1 != null) {
420: if (paramApp.debugAffichageCommentaires > 1)
421: System.out
422: .println(" Fusion des noeuds dans une même surface "
423: + (new Time(System
424: .currentTimeMillis()))
425: .toString());
426: reseau
427: .fusionNoeuds(paramApp.topologieSurfacesFusionNoeuds1);
428: }
429: } else {
430: if (paramApp.topologieSeuilFusionNoeuds2 >= 0) {
431: if (paramApp.debugAffichageCommentaires > 1)
432: System.out.println(" Fusion des noeuds proches "
433: + (new Time(System.currentTimeMillis()))
434: .toString());
435: reseau
436: .fusionNoeuds(paramApp.topologieSeuilFusionNoeuds2);
437: }
438: if (paramApp.topologieSurfacesFusionNoeuds2 != null) {
439: if (paramApp.debugAffichageCommentaires > 1)
440: System.out
441: .println(" Fusion des noeuds dans une même surface "
442: + (new Time(System
443: .currentTimeMillis()))
444: .toString());
445: reseau
446: .fusionNoeuds(paramApp.topologieSurfacesFusionNoeuds2);
447: }
448: }
449:
450: // 3- On enlève les noeuds isolés
451: if (paramApp.debugAffichageCommentaires > 1)
452: System.out
453: .println(" Filtrage des noeuds isolés "
454: + (new Time(System.currentTimeMillis()))
455: .toString());
456: reseau.filtreNoeudsIsoles();
457:
458: // 4- On filtre les noeuds simples (avec 2 arcs incidents)
459: if ((ref && paramApp.topologieElimineNoeudsAvecDeuxArcs1)
460: || (!ref && paramApp.topologieElimineNoeudsAvecDeuxArcs2)) {
461: if (paramApp.debugAffichageCommentaires > 1)
462: System.out
463: .println(" Filtrage des noeuds avec seulement 2 arcs incidents "
464: + (new Time(System.currentTimeMillis()))
465: .toString());
466: reseau.filtreNoeudsSimples();
467: }
468:
469: // 5- On fusionne des arcs en double
470: if (ref && paramApp.topologieFusionArcsDoubles1) {
471: if (paramApp.debugAffichageCommentaires > 1)
472: System.out.println(" Filtrage des arcs en double "
473: + (new Time(System.currentTimeMillis()))
474: .toString());
475: reseau.filtreArcsDoublons();
476: }
477: if (!ref && paramApp.topologieFusionArcsDoubles2) {
478: if (paramApp.debugAffichageCommentaires > 1)
479: System.out.println(" Filtrage des arcs en double "
480: + (new Time(System.currentTimeMillis()))
481: .toString());
482: reseau.filtreArcsDoublons();
483: }
484:
485: // 6 - On crée la topologie de faces
486: if (!ref && paramApp.varianteChercheRondsPoints) {
487: if (paramApp.debugAffichageCommentaires > 1)
488: System.out
489: .println(" Création de la topologie de faces");
490: reseau.creeTopologieFaces();
491: }
492:
493: // 7 - On double la taille de recherche pour les impasses
494: if (paramApp.distanceNoeudsImpassesMax >= 0) {
495: if (ref) {
496: if (paramApp.debugAffichageCommentaires > 1)
497: System.out
498: .println(" Doublage du rayon de recherche des noeuds aux impasses");
499: Iterator itNoeuds = reseau.getPopNoeuds().getElements()
500: .iterator();
501: while (itNoeuds.hasNext()) {
502: NoeudApp noeud2 = (NoeudApp) itNoeuds.next();
503: if (noeud2.arcs().size() == 1)
504: noeud2
505: .setTaille(paramApp.distanceNoeudsImpassesMax);
506: }
507: }
508: }
509:
510: return reseau;
511: }
512:
513: //////////////////////////////////////////////////////////////////////
514: // METHODES D'EXPORT //
515: //////////////////////////////////////////////////////////////////////
516:
517: /** Methode utile principalement pour analyser les résultats d'un appariement,
518: * qui découpe un réseau en plusieurs réseaux selon les valeurs de l'attribut
519: * "Resultat_Appariement" des arcs et noeuds du réseau apparié.
520: */
521: public static List scindeSelonValeursResultatsAppariement(
522: ReseauApp reseauRef, List valeursClassement) {
523: List cartesTopoClassees = new ArrayList();
524: Iterator itArcs = reseauRef.getPopArcs().getElements()
525: .iterator();
526: Iterator itNoeuds = reseauRef.getPopNoeuds().getElements()
527: .iterator();
528: ArcApp arc, arcClasse;
529: NoeudApp noeud, noeudClasse;
530: int i;
531:
532: for (i = 0; i < valeursClassement.size(); i++) {
533: cartesTopoClassees.add(new ReseauApp("Eval "
534: + valeursClassement.get(i)));
535: }
536: while (itArcs.hasNext()) {
537: arc = (ArcApp) itArcs.next();
538: for (i = 0; i < valeursClassement.size(); i++) {
539: if (arc.getResultatAppariement() == null)
540: continue;
541: if (arc.getResultatAppariement().startsWith(
542: (String) valeursClassement.get(i))) {
543: arcClasse = (ArcApp) ((ReseauApp) cartesTopoClassees
544: .get(i)).getPopArcs().nouvelElement();
545: arcClasse.setGeom(arc.getGeom());
546: arcClasse.setResultatAppariement(arc
547: .getResultatAppariement());
548: }
549: }
550: }
551: while (itNoeuds.hasNext()) {
552: noeud = (NoeudApp) itNoeuds.next();
553: for (i = 0; i < valeursClassement.size(); i++) {
554: if (noeud.getResultatAppariement() == null)
555: continue;
556: if (noeud.getResultatAppariement().startsWith(
557: (String) valeursClassement.get(i))) {
558: noeudClasse = (NoeudApp) ((ReseauApp) cartesTopoClassees
559: .get(i)).getPopNoeuds().nouvelElement();
560: noeudClasse.setGeom(noeud.getGeom());
561: noeudClasse.setResultatAppariement(noeud
562: .getResultatAppariement());
563: }
564: }
565: }
566: return cartesTopoClassees;
567: }
568: }
|