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.util.Iterator;
030: import java.util.List;
031:
032: import fr.ign.cogit.geoxygene.contrib.appariement.EnsembleDeLiens;
033: import fr.ign.cogit.geoxygene.contrib.appariement.reseaux.topologie.ArcApp;
034: import fr.ign.cogit.geoxygene.contrib.appariement.reseaux.topologie.NoeudApp;
035: import fr.ign.cogit.geoxygene.contrib.appariement.reseaux.topologie.ReseauApp;
036: import fr.ign.cogit.geoxygene.contrib.cartetopo.Arc;
037: import fr.ign.cogit.geoxygene.contrib.cartetopo.CarteTopo;
038: import fr.ign.cogit.geoxygene.contrib.geometrie.Distances;
039: import fr.ign.cogit.geoxygene.contrib.geometrie.Vecteur;
040: import fr.ign.cogit.geoxygene.spatial.coordgeom.DirectPosition;
041: import fr.ign.cogit.geoxygene.spatial.coordgeom.DirectPositionList;
042: import fr.ign.cogit.geoxygene.spatial.coordgeom.GM_LineString;
043:
044: /**
045: * Méthodes pour le recalage d'un réseau sur un autre.
046: * NB : méthodes réalisées pour un cas particulier et non retouchées pour assurer une bonne généricité.
047: * ////////////// A manier avec précaution //////////////////.
048: *
049: * @author Mustiere - IGN / Laboratoire COGIT
050: * @version 1.0
051: *
052: */
053:
054: public class Recalage {
055: /** Recale la géométrie des arcs d'un graphe sur un autre graphe
056: * une fois que ceux-ci ont été appariés.
057: *
058: * Un lien (correspondant) est gardé entre les nouveaux arcs et leurs correspondants
059: * dans le réseau de référence (accessible par arc.getCorrespondants()),
060: *
061: * IMPORTANT: ctARecaler doit être le réseau 1 dans l'appariement,
062: * et ctSurLaquelleRecaler le réseau 2.
063: *
064: * NB: méthode conçue pour les cas relativement simples qui mérite sans doute d'être affinée.
065: *
066: * @param ctARecaler
067: * Le réseau à recaler
068: *
069: * @param ctSurLaquelleRecaler
070: * Le réseau sur lequel recaler
071: *
072: * @param ctRecale
073: * Le réseau recalé (en entrée-sortie)
074: *
075: * @param liens
076: * Des liens d'appariement entre les réseaux "à recaler" et "sur lequel recaler"
077: */
078: public static CarteTopo recalage(ReseauApp ctARecaler,
079: ReseauApp ctSurLaquelleRecaler, EnsembleDeLiens liens) {
080: CarteTopo ctRecale = new CarteTopo("reseau recalé");
081: // On ajoute dans le réseau recalé les arcs sur lesquels on recale qui sont appariés.
082: Iterator itArcsSurLesquelsRecaler = ctSurLaquelleRecaler
083: .getPopArcs().getElements().iterator();
084: while (itArcsSurLesquelsRecaler.hasNext()) {
085: ArcApp arc = (ArcApp) itArcsSurLesquelsRecaler.next();
086: if (arc.getListeGroupes().size() == 0)
087: continue;
088: if (!arc.aUnCorrespondantGeneralise(liens))
089: continue;
090: Arc nouvelArc = (Arc) ctRecale.getPopArcs().nouvelElement();
091: nouvelArc.setGeometrie(arc.getGeometrie());
092: nouvelArc.setCorrespondants(arc
093: .objetsGeoRefEnCorrespondance(liens));
094: }
095:
096: // On ajoute dans le réseau recalé les arcs à recaler qui ne sont pas appariés,
097: // en modifiant la géométrie pour assurer un raccord amorti avec le reste.
098: Iterator itArcsARecaler = ctARecaler.getPopArcs().getElements()
099: .iterator();
100: while (itArcsARecaler.hasNext()) {
101: ArcApp arc = (ArcApp) itArcsARecaler.next();
102: if (arc.getLiens(liens.getElements()).size() != 0)
103: continue;
104: Arc nouvelArc = (Arc) ctRecale.getPopArcs().nouvelElement();
105: nouvelArc
106: .setGeometrie(new GM_LineString(
107: (DirectPositionList) arc.getGeom().coord()
108: .clone())); // vraie duplication de géométrie (un peu tordu, certes)
109: geometrieRecalee(arc, nouvelArc, liens);
110: }
111: return ctRecale;
112: }
113:
114: /** Methode utilisée par le recalage pour assurer le recalage.
115: * Attention : cette méthode n'est pas très générique : elle suppose que l'on recale Ref sur Comp uniquement
116: * et elle mérite des affinements.
117: */
118: private static void geometrieRecalee(ArcApp arcARecaler,
119: Arc arcRecale, EnsembleDeLiens liens) {
120: NoeudApp noeudARecalerIni = (NoeudApp) arcARecaler
121: .getNoeudIni();
122: NoeudApp noeudARecalerFin = (NoeudApp) arcARecaler
123: .getNoeudFin();
124: NoeudApp noeudRecaleIni, noeudRecaleFin;
125: List liensDuNoeudARecalerIni = noeudARecalerIni.getLiens(liens
126: .getElements());
127: List liensDuNoeudARecalerFin = noeudARecalerFin.getLiens(liens
128: .getElements());
129: GM_LineString nouvelleGeometrie = new GM_LineString(
130: (DirectPositionList) arcARecaler.getGeom().coord()
131: .clone());
132: GM_LineString geomTmp;
133: double longueur, abscisse;
134: Vecteur decalage, decalageCourant;
135: DirectPosition ptCourant;
136: int i;
137:
138: if (liensDuNoeudARecalerIni.size() == 1) {
139: // si le noeud initial de l'arc à recalé est apparié avec le réseau comp
140: if (((LienReseaux) liensDuNoeudARecalerIni.get(0))
141: .getNoeuds2().size() == 1) {
142: noeudRecaleIni = (NoeudApp) ((LienReseaux) liensDuNoeudARecalerIni
143: .get(0)).getNoeuds2().get(0);
144: nouvelleGeometrie.setControlPoint(0, noeudRecaleIni
145: .getGeometrie().getPosition());
146:
147: decalage = new Vecteur(noeudARecalerIni.getCoord(),
148: noeudRecaleIni.getCoord());
149: geomTmp = new GM_LineString(
150: (DirectPositionList) nouvelleGeometrie.coord()
151: .clone());
152: longueur = nouvelleGeometrie.length();
153: abscisse = 0;
154: for (i = 1; i < nouvelleGeometrie.coord().size() - 1; i++) {
155: ptCourant = geomTmp.coord().get(i);
156: abscisse = abscisse
157: + Distances.distance(geomTmp
158: .getControlPoint(i), geomTmp
159: .getControlPoint(i - 1));
160: decalageCourant = decalage.multConstante(1
161: - abscisse / longueur);
162: nouvelleGeometrie.setControlPoint(i,
163: decalageCourant.translate(ptCourant));
164: }
165: }
166: }
167:
168: // si le noeud final de l'arc à recalé est apparié avec le réseau comp
169: if (liensDuNoeudARecalerFin.size() == 1) {
170: if (((LienReseaux) liensDuNoeudARecalerFin.get(0))
171: .getNoeuds2().size() == 1) {
172: noeudRecaleFin = (NoeudApp) ((LienReseaux) liensDuNoeudARecalerFin
173: .get(0)).getNoeuds2().get(0);
174: nouvelleGeometrie.setControlPoint(nouvelleGeometrie
175: .coord().size() - 1, noeudRecaleFin
176: .getGeometrie().getPosition());
177:
178: decalage = new Vecteur(noeudARecalerFin.getCoord(),
179: noeudRecaleFin.getCoord());
180: geomTmp = new GM_LineString(
181: (DirectPositionList) nouvelleGeometrie.coord()
182: .clone());
183: longueur = nouvelleGeometrie.length();
184: abscisse = 0;
185: for (i = nouvelleGeometrie.coord().size() - 2; i > 0; i--) {
186: ptCourant = geomTmp.coord().get(i);
187: abscisse = abscisse
188: + Distances.distance(geomTmp
189: .getControlPoint(i), geomTmp
190: .getControlPoint(i + 1));
191: decalageCourant = decalage.multConstante(1
192: - abscisse / longueur);
193: nouvelleGeometrie.setControlPoint(i,
194: decalageCourant.translate(ptCourant));
195: }
196: }
197: }
198:
199: arcRecale.setGeom(nouvelleGeometrie);
200: }
201:
202: }
|