Revision 33

View differences:

org.gvsig.lrs/trunk/org.gvsig.lrs/org.gvsig.lrs.lib/org.gvsig.lrs.lib.impl/src/main/java/org/gvsig/lrs/lib/impl/LrsCreateRouteAlgorithm.java
24 24

  
25 25
import java.util.ArrayList;
26 26
import java.util.Collections;
27
import java.util.Comparator;
28
import java.util.HashMap;
27
import java.util.Iterator;
29 28
import java.util.List;
30
import java.util.Map;
31 29
import java.util.Map.Entry;
32 30
import java.util.SortedMap;
33 31
import java.util.TreeMap;
34 32

  
35 33
import org.apache.commons.lang3.mutable.MutableInt;
34
import org.slf4j.Logger;
35
import org.slf4j.LoggerFactory;
36

  
36 37
import org.gvsig.fmap.dal.feature.EditableFeature;
37 38
import org.gvsig.fmap.dal.feature.Feature;
38 39
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
39
import org.gvsig.fmap.dal.feature.FeatureReference;
40
import org.gvsig.fmap.dal.feature.FeatureSelection;
41 40
import org.gvsig.fmap.dal.feature.FeatureSet;
42 41
import org.gvsig.fmap.dal.feature.FeatureStore;
43 42
import org.gvsig.fmap.dal.feature.NewFeatureStoreParameters;
......
69 68
import org.gvsig.tools.task.SimpleTaskStatus;
70 69
import org.gvsig.tools.visitor.VisitCanceledException;
71 70
import org.gvsig.tools.visitor.Visitor;
72
import org.omg.CosNaming.IstringHelper;
73
import org.slf4j.Logger;
74
import org.slf4j.LoggerFactory;
75 71

  
76 72
/**
77 73
 * @author fdiaz
......
79 75
 */
80 76
public class LrsCreateRouteAlgorithm implements LrsAlgorithm {
81 77

  
82
    private static final Logger logger =
83
        LoggerFactory.getLogger(LrsCreateRouteAlgorithm.class);
78
    private static final Logger logger = LoggerFactory.getLogger(LrsCreateRouteAlgorithm.class);
84 79

  
85 80
    private LrsCreateRouteAlgorithmParams parameters;
86 81

  
......
117 112
     * SimpleTaskStatus)
118 113
     */
119 114
    public void execute(SimpleTaskStatus taskStatus) throws LrsException {
120
        NewFeatureStoreParameters newFeatureStoreParameters =
121
            parameters.getNewFeatureStoreParameters();
115
        NewFeatureStoreParameters newFeatureStoreParameters = parameters.getNewFeatureStoreParameters();
122 116
        FeatureStore sourceFeatureStore = parameters.getSourceFeatureStore();
123 117
        FeatureAttributeDescriptor idRouteField = parameters.getIdRouteField();
124
        // LrsCoordinatesPriority coordinatePriority =
125
        // parameters.getCoordinatePriority();
126
        // LrsSourceOfMeasures sourceOfMeasures =
127
        // parameters.getSourceOfMeasures();
128
        FeatureAttributeDescriptor fromMeasureField =
129
            parameters.getFromMeasureField();
130
        FeatureAttributeDescriptor toMeasureField =
131
            parameters.getToMeasureField();
132
        // double measureFactor = parameters.getMeasureFactor();
133
        // double measureOffset = parameters.getMeasureOffset();
134
        // boolean ignoreSpatialGaps = parameters.ignoreSpatialGaps();
118
        FeatureAttributeDescriptor fromMeasureField = parameters.getFromMeasureField();
119
        FeatureAttributeDescriptor toMeasureField = parameters.getToMeasureField();
135 120

  
136 121
        logger.info(parameters.toString());
137 122

  
......
160 145
                toDataType = null;
161 146
            }
162 147

  
163
            FeatureStore newFeatureStore = LrsAlgorithmUtils
164
                .createNewDataStore(newFeatureStoreParameters, idRouteField);
148
            FeatureStore newFeatureStore =
149
                LrsAlgorithmUtils.createNewDataStore(newFeatureStoreParameters, idRouteField);
165 150

  
166 151
            FeatureSet sourceFeatures;
167 152
            if (sourceFeatureStore.getFeatureSelection().getSize() > 0) {
......
170 155
                sourceFeatures = sourceFeatureStore.getFeatureSet();
171 156
            }
172 157

  
173
            final SortedMap<String, List<MStructure>> featuresMap =
174
                new TreeMap<String, List<MStructure>>();
175
            final MutableInt contId=new MutableInt(0);
158
            final SortedMap<String, List<MSegment>> featuresMap = new TreeMap<String, List<MSegment>>();
159
            final MutableInt contId = new MutableInt(0);
176 160
            sourceFeatures.accept(new Visitor() {
177 161

  
178
                public void visit(Object obj)
179
                    throws VisitCanceledException, BaseException {
162
                public void visit(Object obj) throws VisitCanceledException, BaseException {
180 163
                    Feature feature = (Feature) obj;
181 164
                    String routeName = (String) feature.get(routeFieldName);
182
                    Geometry originalGeometry = feature.getDefaultGeometry();
183 165
                    Object objFrom = null;
184 166
                    Object objTo = null;
185 167
                    if (fromFieldName != null) {
......
189 171
                        objTo = feature.get(toFieldName);
190 172
                    }
191 173
                    if (!featuresMap.containsKey(routeName)) {
192
                        featuresMap.put(routeName, new ArrayList<MStructure>());
174
                        featuresMap.put(routeName, new ArrayList<MSegment>());
193 175
                    }
194
                    List<MStructure> mList = featuresMap.get(routeName);
195
                    MStructure mStructure = new MStructure();
196
                    mStructure.geometry = originalGeometry;
197
                    mStructure.fromField =
198
                        LrsAlgorithmUtils.getAsDouble(objFrom, fromDataType);
199
                    mStructure.toField =
200
                        LrsAlgorithmUtils.getAsDouble(objTo, toDataType);
201
                    mStructure.id=contId.getValue();
176
                    List<MSegment> mList = featuresMap.get(routeName);
177
                    MSegment mSegment = new MSegment();
178
                    mSegment.geometry = feature.getDefaultGeometry().cloneGeometry();
179
                    mSegment.fromValue = LrsAlgorithmUtils.getAsDouble(objFrom, fromDataType);
180
                    mSegment.toValue = LrsAlgorithmUtils.getAsDouble(objTo, toDataType);
181
                    mSegment.id = contId.getValue();
202 182
                    contId.increment();
203
                    mList.add(mStructure);
183
                    mList.add(mSegment);
204 184
                    featuresMap.put(routeName, mList);
205 185
                }
206 186
            });
187

  
207 188
            taskStatus.setRangeOfValues(0, featuresMap.size());
208 189
            int taskCount = 0;
209 190

  
210 191
            newFeatureStore.edit(FeatureStore.MODE_FULLEDIT);
211 192

  
212
            // TODO Added to facilitate Tests. Remove afterwards
213
            StringBuffer resultDebug = new StringBuffer();
214
            LrsSourceOfMeasures sourceOfMeasures =
215
                parameters.getSourceOfMeasures();
216
            boolean ignoreSpatialGaps = parameters.ignoreSpatialGaps();
217
            LrsCoordinatesPriority coordinatePriority =
218
                parameters.getCoordinatePriority();
219

  
220
            resultDebug.append(sourceOfMeasures.getName());
221
            if (!sourceOfMeasures.equals(LrsSourceOfMeasures.TWO_FIELDS)) {
222
                if (ignoreSpatialGaps)
223
                    resultDebug.append(" WITHOUT GAPS ");
224
                else
225
                    resultDebug.append(" WITH GAPS ");
226
                resultDebug.append(coordinatePriority.getName());
227
            }
228
            // END of Test addition
229

  
230
            for (Entry<String, List<MStructure>> entry : featuresMap
231
                .entrySet()) {
193
            for (Entry<String, List<MSegment>> entry : featuresMap.entrySet()) {
232 194
                String routeName = entry.getKey();
233
                List<MStructure> mList = entry.getValue();
195
                List<MSegment> mList = entry.getValue();
234 196

  
235
                EditableFeature newFeature =
236
                    newFeatureStore.createNewFeature(true);
197
                EditableFeature newFeature = newFeatureStore.createNewFeature(true);
237 198
                newFeature.set(routeFieldName, routeName);
238 199
                Geometry route = createGeometryRoute(mList);
239 200
                newFeature.setDefaultGeometry(route);
240 201

  
241
                // TODO Added to facilitate Tests. Remove afterwards
242
                String lineSeparator = System.getProperty("line.separator");
243
                resultDebug.append(lineSeparator);
244
                resultDebug.append("Route: " + routeName);
245
                resultDebug.append(lineSeparator);
246
                if (route instanceof MultiLine) {
247
                    MultiLine multiLine = (MultiLine) route;
248
                    for (int j = 0; j < multiLine.getPrimitivesNumber(); j++) {
249
                        Line line = (Line) multiLine.getPrimitiveAt(j);
250
                        resultDebug.append("Line " + j + ":[");
251
                        for (int i = 0; i < line.getNumVertices(); i++) {
252
                            Point point = line.getVertex(i);
253
                            Double x = point.getX();
254
                            Double y = point.getY();
255
                            Double m =
256
                                point.getCoordinateAt(point.getDimension() - 1);
257
                            resultDebug.append("(x=" + x.toString() + ",y="
258
                                + y.toString() + ",m=" + m.toString() + ")");
259
                        }
260
                        resultDebug.append("]");
261
                        resultDebug.append(lineSeparator);
262
                    }
263
                }
264

  
265
                // END of Test addition
266

  
267 202
                newFeatureStore.update(newFeature);
268 203

  
269 204
                taskCount++;
270 205
                taskStatus.setCurValue(taskCount);
271 206

  
272 207
            }
273
            logger.debug(resultDebug.toString());
274 208
            newFeatureStore.finishEditing();
275 209

  
276 210
        } catch (Exception e1) {
......
282 216

  
283 217
    }
284 218

  
285
    private Geometry createGeometryRoute(List<MStructure> mList)
286
        throws CreateGeometryException, GeometryOperationNotSupportedException,
287
        GeometryOperationException {
219
    private Geometry createGeometryRoute(List<MSegment> mList) throws CreateGeometryException,
220
        GeometryOperationNotSupportedException, GeometryOperationException, CreateEnvelopeException {
288 221
        LrsSourceOfMeasures sourceOfMeasures = parameters.getSourceOfMeasures();
289 222
        Geometry geometryResult = null;
290 223
        simplifyMultilines(mList);
......
300 233
            geometryResult = calculateGeometryByLength(mList);
301 234
            break;
302 235
        }
303
        geometryResult = simplifyMultiline(geometryResult);
304
        geometryResult = applyOffset(geometryResult);
236
        geometryResult = applyOffsetAndFactor(geometryResult);
305 237
        return geometryResult;
306 238
    }
307 239

  
308
    private Geometry calculateGeometryByLength(List<MStructure> mList)
309
        throws CreateGeometryException, GeometryOperationNotSupportedException,
310
        GeometryOperationException {
240
    private Geometry calculateGeometryByLength(List<MSegment> mList) throws CreateGeometryException,
241
        GeometryOperationNotSupportedException, GeometryOperationException, CreateEnvelopeException {
311 242
        boolean ignoreSpatialGaps = parameters.ignoreSpatialGaps();
312
        for (MStructure mStructure : mList) {
313
            mStructure.fromField =
314
                LrsAlgorithmUtils.getGeometryLength(mStructure.geometry, ignoreSpatialGaps);
243
        for (MSegment mSegment : mList) {
244
            mSegment.fromValue = LrsAlgorithmUtils.getGeometryLength(mSegment.geometry, ignoreSpatialGaps);
315 245
        }
316 246
        return calculateGeometryByOneField(mList);
317 247
    }
318 248

  
319
    private Geometry calculateGeometryByOneField(List<MStructure> mList)
320
        throws CreateGeometryException, GeometryOperationNotSupportedException,
321
        GeometryOperationException {
249
    private Geometry calculateGeometryByOneField(List<MSegment> mList) throws CreateGeometryException,
250
        GeometryOperationNotSupportedException, GeometryOperationException, CreateEnvelopeException {
322 251
        boolean ignoreSpatialGaps = parameters.ignoreSpatialGaps();
323
        GeometryManager geomanager = GeometryLocator.getGeometryManager();
252
        GeometryManager gmanager = GeometryLocator.getGeometryManager();
324 253
        try {
325
            mList=sortMList(mList);
254
            mList = sortMList(mList);
326 255
        } catch (Exception e) {
327 256
            logger.warn("Geometries couldn't be ordered");
328 257
        }
329 258

  
330
        MultiLine mGeometry = (MultiLine) geomanager
331
            .create(Geometry.TYPES.MULTILINE, Geometry.SUBTYPES.GEOM2DM);
332
        //MutableDouble lastMValue = new MutableDouble(0);
333
        Double lastMValueGeometry= Double.valueOf(0);
334
        Double gapBetweenGeometries = Double.valueOf(0);
335
        Point lastPoint = null;
259
        MultiLine auxMultiLine = (MultiLine) gmanager.create(Geometry.TYPES.MULTILINE, Geometry.SUBTYPES.GEOM2DM);
336 260

  
337
        for (MStructure mStructure : mList) {
338
            Geometry geometry = mStructure.geometry;
339
            List<Line> geometryLines=LrsAlgorithmUtils.extractLines(geometry);
340
            Double geometryLength=LrsAlgorithmUtils.getGeometryLength(geometry, ignoreSpatialGaps);
341
            boolean firstLineInGeometry=true;
342

  
343
            if (!ignoreSpatialGaps) {
344
                gapBetweenGeometries = calculateGap(lastPoint, geometry);
345
                lastMValueGeometry+=gapBetweenGeometries;
261
        Point previousPoint = null;
262
        double previousM = 0.0;
263
        for (MSegment mSegment : mList) {
264
            Geometry geom = mSegment.geometry;
265
            Double geometryLength = mSegment.getLength(ignoreSpatialGaps);
266
            if (geom instanceof Line) {
267
                Line line = (Line) geom;
268
                Line auxLine = (Line) gmanager.create(Geometry.TYPES.LINE, Geometry.SUBTYPES.GEOM2DM);
269
                double distance = 0.0;
270
                double firstM = previousM;
271
                for (int i = 0; i < line.getNumVertices(); i++) {
272
                    Point vertex = line.getVertex(i);
273
                    Point point = (Point) gmanager.create(Geometry.TYPES.POINT, Geometry.SUBTYPES.GEOM2DM);
274
                    point.setX(vertex.getX());
275
                    point.setY(vertex.getY());
276
                    if (i == 0 && previousPoint != null) {
277
                        boolean gap = false;
278
                        if (areInSame2DLocation(previousPoint, vertex)) {
279
                            // Buscamos si ha sido una bifurcaci?n
280
                            previousPoint = getPossibleFork(auxMultiLine, vertex);
281
                            // OJO, aqu? previousPoint pasa a ser 2DM
282
                        } else {
283
                            // En caso de salto, calculamos el previousPoint
284
                            // // y si no, buscamos el v?rtice m?s cercano
285
                            previousPoint = getClosestVertex(auxMultiLine, vertex);
286
                            // OJO, aqu? previousPoint pasa a ser 2DM
287
                            gap = true;
288
                        }
289
                        previousM = previousPoint.getCoordinateAt(previousPoint.getDimension() - 1);
290
                        if (i == 0) {
291
                            firstM = previousM;
292
                        }
293
                        if (gap && !ignoreSpatialGaps) {
294
                            Point previousVertex = getPreviousVertexToPoint(auxMultiLine, previousPoint);
295
                            previousVertex.getCoordinateAt(previousVertex.getDimension() - 1);
296
                            previousM =
297
                                strightLineThroughTwoPointsEquation(0, previousVertex.distance(previousPoint),
298
                                    previousVertex.getCoordinateAt(previousVertex.getDimension() - 1), previousM,
299
                                    previousVertex.distance(previousPoint) + previousPoint.distance(point));
300
                            firstM = previousM;
301
                        }
302
                    }
303
                    if (i != 0) {
304
                        distance += previousPoint.distance(vertex);
305
                    }
306
                    double m =
307
                        strightLineThroughTwoPointsEquation(0, geometryLength, firstM, firstM + mSegment.fromValue,
308
                            distance);
309
                    point.setCoordinateAt(point.getDimension() - 1, m);
310
                    auxLine.addVertex(point);
311
                    previousM = m;
312
                    previousPoint = vertex;
313
                }
314
                auxMultiLine.addPrimitive(auxLine);
315
            } else if (geom instanceof MultiLine) {
316
                MultiLine multiline = (MultiLine) geom;
317
                for (int i = 0; i < multiline.getPrimitivesNumber(); i++) {
318
                    Line line = (Line) multiline.getPrimitiveAt(i);
319
                    Line auxLine = (Line) gmanager.create(Geometry.TYPES.LINE, Geometry.SUBTYPES.GEOM2DM);
320
                    double distance = 0.0;
321
                    double firstM = previousM;
322
                    for (int j = 0; j < line.getNumVertices(); j++) {
323
                        Point vertex = line.getVertex(j);
324
                        Point point = (Point) gmanager.create(Geometry.TYPES.POINT, Geometry.SUBTYPES.GEOM2DM);
325
                        point.setX(vertex.getX());
326
                        point.setY(vertex.getY());
327
                        if (j == 0 && previousPoint != null) {
328
                            boolean gap = false;
329
                            if (areInSame2DLocation(previousPoint, vertex)) {
330
                                // Buscamos si ha sido una bifurcaci?n
331
                                previousPoint = getPossibleFork(auxMultiLine, vertex);
332
                                // OJO, aqu? previousPoint pasa a ser 2DM
333
                            } else {
334
                                // En caso de salto, calculamos el previousPoint
335
                                previousPoint = getClosestVertex(auxMultiLine, vertex);
336
                                // OJO, aqu? previousPoint pasa a ser 2DM
337
                                gap = true;
338
                            }
339
                            previousM = previousPoint.getCoordinateAt(previousPoint.getDimension() - 1);
340
                            if (j == 0) {
341
                                firstM = previousM;
342
                            }
343
                            if (gap && !ignoreSpatialGaps) {
344
                                Point previousVertex = getPreviousVertexToPoint(auxMultiLine, previousPoint);
345
                                previousVertex.getCoordinateAt(previousVertex.getDimension() - 1);
346
                                previousM =
347
                                    strightLineThroughTwoPointsEquation(0, previousVertex.distance(previousPoint),
348
                                        previousVertex.getCoordinateAt(previousVertex.getDimension() - 1), previousM,
349
                                        previousVertex.distance(previousPoint) + previousPoint.distance(point));
350
                                firstM = previousM;
351
                            }
352
                        }
353
                        if (j != 0) {
354
                            distance += previousPoint.distance(vertex);
355
                        }
356
                        double m =
357
                            strightLineThroughTwoPointsEquation(0, geometryLength, firstM, firstM + mSegment.fromValue,
358
                                distance);
359
                        point.setCoordinateAt(point.getDimension() - 1, m);
360
                        auxLine.addVertex(point);
361
                        previousM = m;
362
                        previousPoint = vertex;
363
                    }
364
                    multiline.addPrimitive(auxLine);
365
                }
366
            } else {
367
                // NO deber?a entrar por aqu?
368
                logger.warn("A not LINE nor MULTILINE geometry found in CreateRoute process");
346 369
            }
347
            Double previouslyCalculatedMValue= getCalculatedMValueForFirstPoint(mGeometry,geometry);
348
            if (previouslyCalculatedMValue!=null){
349
                lastPoint=null;
350
                lastMValueGeometry=previouslyCalculatedMValue;
351
            }
370
        }
352 371

  
353
            Double geometryMFirstPoint = lastMValueGeometry;
354
            lastMValueGeometry+=mStructure.fromField;
355
            Double geometryMLastPoint=lastMValueGeometry;
372
        return compactMultiLine(auxMultiLine);
373
    }
356 374

  
357
            Double distance=Double.valueOf(0);;
358
            for (Line line:geometryLines){
359
                Double gapBetweenLines = Double.valueOf(0);
360
                Double lineLength=LrsAlgorithmUtils.getLineLength(line);
361
                if (!ignoreSpatialGaps&&!firstLineInGeometry) {
362
                    gapBetweenLines = calculateGap(lastPoint, line);
363
                    distance+=gapBetweenLines;
364
                    firstLineInGeometry=false;
375
    /**
376
     * Joins consecutive adjacent lines into the multiLine that are not involved in a fork
377
     *
378
     * @param auxMultiLine
379
     * @return
380
     * @throws CreateGeometryException
381
     * @throws GeometryOperationException
382
     * @throws GeometryOperationNotSupportedException
383
     */
384
    private MultiLine compactMultiLine(MultiLine multiLine) throws CreateGeometryException, GeometryOperationNotSupportedException, GeometryOperationException {
385
        GeometryManager geomManager = GeometryLocator.getGeometryManager();
386
        MultiLine result =  (MultiLine) geomManager.create(multiLine.getGeometryType());
387

  
388
        int primitivesNumber = multiLine.getPrimitivesNumber();
389
        List<Line> lines = new ArrayList<Line>(primitivesNumber);
390
        for(int i = 0; i < primitivesNumber; i++){
391
            lines.add((Line)multiLine.getPrimitiveAt(i).cloneGeometry());
392
        }
393
        if (lines.size() > 0) {
394
            Line line = lines.get(0);
395
            while (lines.size() > 1) {
396
                Point lastVertex = line.getVertex(line.getNumVertices() - 1);
397
                lines.remove(0);
398
                // Borramos la primera linea de la lista ==> lines.get(0) es la siguiente
399
                Line line2 = lines.get(0);
400
                // Si el ultimo punto de la primera
401
                if (lastVertex.equals(line2.getVertex(0)) && !bifurcation(lastVertex, lines)) {
402
                    for(int i = 1; i<line2.getNumVertices(); i++){
403
                        line.addVertex(line2.getVertex(i));
404
                    }
405
                } else {
406
                    result.addPrimitive(line);
407
                    line = line2;
365 408
                }
409
            }
410
            result.addPrimitive(line);
411
        }
412
        return result;
413
    }
366 414

  
367
                Double mFirstPoint =
368
                    calculateM(geometryMLastPoint, geometryMFirstPoint, distance, geometryLength);
369
                distance+=lineLength;
370
                Double mLastPoint =
371
                    calculateM(geometryMLastPoint, geometryMFirstPoint, distance, geometryLength);
372
                Line mLine=lineToMLine(line, mFirstPoint, mLastPoint);
373
                mGeometry.addPrimitive(mLine);
374
                lastPoint = mLine.getVertex(mLine.getNumVertices() - 1);
415
    /**
416
     * Checks if a bifurcation occurs at one point.
417
     *
418
     * @param point
419
     * @param lines
420
     * @return
421
     */
422
    private boolean bifurcation(Point point, List<org.gvsig.fmap.geom.primitive.Line> lines) {
423
        // Saltamos la primera linea
424
        for(int i = 1; i<lines.size(); i++){
425
            if(point.equals(lines.get(i).getVertex(0))){
426
                return true;
375 427
            }
376 428
        }
377
        return mGeometry;
429
        return false;
430
    }
378 431

  
432
    /**
433
     * Returns the previous vertex to a point.
434
     *
435
     * @param auxMultiLine
436
     * @param previousPoint
437
     * @return
438
     * @throws GeometryOperationException
439
     * @throws GeometryOperationNotSupportedException
440
     * @throws CreateGeometryException
441
     */
442
    private Point getPreviousVertexToPoint(MultiLine multiLine, Point point) throws CreateGeometryException,
443
        GeometryOperationNotSupportedException, GeometryOperationException {
444
        GeometryManager geomManager = GeometryLocator.getGeometryManager();
445
        for (int i = 0; i < multiLine.getPrimitivesNumber(); i++) {
446
            Line line = (Line) multiLine.getPrimitiveAt(i);
447
            if (line.intersects(point)) {
448
                for (int j = 0; j < line.getNumVertices() - 1; j++) {
449
                    if (point.equals(line.getVertex(j + 1))) {
450
                        return line.getVertex(j);
451
                    }
452
                    Line auxLine = (Line) geomManager.create(Geometry.TYPES.LINE, Geometry.SUBTYPES.GEOM2DM);
453
                    auxLine.addVertex(line.getVertex(j));
454
                    auxLine.addVertex(line.getVertex(j + 1));
455
                    if (auxLine.intersects(point)) {
456
                        return line.getVertex(j);
457
                    }
458
                }
459
            }
460
        }
461
        return null;
462
    }
379 463

  
380
//        for (MStructure mStructure : mList) {
381
//            Geometry geometry = mStructure.geometry;
382
//
383
//            if (!ignoreSpatialGaps) {
384
//                gapBetweenLines = calculateGap(lastPoint, geometry);
385
//                lastMValue.add(gapBetweenLines);
386
//            }
387
//            Double fromDistance = lastMValue.getValue();
388
//            lastMValue.add(mStructure.fromField);
389
//            Double toDistance = lastMValue.getValue();
390
//
391
//            if (geometry instanceof Line) {
392
//                Line line = (Line) geometry;
393
//                Line lineM = lineToMLine(line, fromDistance, toDistance);
394
//                mGeometry.addPrimitive(lineM);
395
//                lastPoint = lineM.getVertex(lineM.getNumVertices() - 1);
396
//            }
397
//            if (geometry instanceof MultiLine) {
398
//                MultiLine multiLine = (MultiLine) geometry;
399
//                Line[] lines = multilineToMlines(multiLine, fromDistance,
400
//                    toDistance, ignoreSpatialGaps);
401
//                for (Line lineM : lines) {
402
//                    mGeometry.addPrimitive(lineM);
403
//                    lastPoint = lineM.getVertex(lineM.getNumVertices() - 1);
464
//    /**
465
//     * Returns the measure corresponding to the point into the geometry
466
//     *
467
//     * @param mGeometry
468
//     * @param point
469
//     * @return
470
//     * @throws GeometryOperationException
471
//     * @throws GeometryOperationNotSupportedException
472
//     * @throws CreateGeometryException
473
//     */
474
//    private double getM(MultiLine multiLine, Point point) throws GeometryOperationNotSupportedException,
475
//        GeometryOperationException, CreateGeometryException {
476
//        GeometryManager geomManager = GeometryLocator.getGeometryManager();
477
//        if (!(multiLine.getGeometryType().isSubTypeOf(Geometry.SUBTYPES.GEOM2DM))
478
//            || (multiLine.getGeometryType().isSubTypeOf(Geometry.SUBTYPES.GEOM3DM))) {
479
//            return Double.NaN;
480
//        }
481
//        if (!(point.getGeometryType().isSubTypeOf(Geometry.SUBTYPES.GEOM2DM))
482
//            || (point.getGeometryType().isSubTypeOf(Geometry.SUBTYPES.GEOM3DM))) {
483
//            return Double.NaN;
484
//        }
485
//        for (int i = 0; i < multiLine.getPrimitivesNumber(); i++) {
486
//            Line line = (Line) multiLine.getPrimitiveAt(i);
487
//            if (line.intersects(point)) {
488
//                for (int j = 0; j < line.getNumVertices() - 1; j++) {
489
//                    Point vertex1 = line.getVertex(j);
490
//                    double m1 = vertex1.getCoordinateAt(vertex1.getDimension() - 1);
491
//                    double x1 = vertex1.getX();
492
//                    double y1 = vertex1.getY();
493
//                    if (point.equals(vertex1)) {
494
//                        return m1;
495
//                    }
496
//                    Point vertex2 = line.getVertex(j + 1);
497
//                    double m2 = vertex2.getCoordinateAt(vertex2.getDimension() - 1);
498
//                    double x2 = vertex2.getX();
499
//                    double y2 = vertex2.getY();
500
//                    if (point.equals(vertex2)) {
501
//                        return m2;
502
//                    }
503
//                    Line auxLine = (Line) geomManager.create(Geometry.TYPES.LINE, Geometry.SUBTYPES.GEOM2DM);
504
//                    auxLine.addVertex(line.getVertex(j));
505
//                    auxLine.addVertex(line.getVertex(j + 1));
506
//                    if (auxLine.intersects(point)) {
507
//                        if (x1 != x2) {
508
//                            return strightLineThroughTwoPointsEquation(x1, x2, m1, m2, point.getX());
509
//                        } else {
510
//                            return strightLineThroughTwoPointsEquation(y1, y2, m1, m2, point.getY());
511
//                        }
512
//                    }
404 513
//                }
405 514
//            }
406 515
//        }
407
//        return mGeometry;
408
    }
516
//        return Double.NaN;
517
//    }
409 518

  
410
    private Double getCalculatedMValueForFirstPoint(Geometry mGeometry,Geometry geometry){
411
        List<Point> mPoints=LrsAlgorithmUtils.extractPoints(mGeometry);
412
        Point point=LrsAlgorithmUtils.extractFirstPoint(geometry);
413
        for (Point mPoint:mPoints){
414
            if ( mPoint.getX()==point.getX() && mPoint.getY()==point.getY() ){
415
                int dimensionM=mPoint.getDimension()-1;
416
                return mPoint.getCoordinateAt(dimensionM);
519
    /**
520
     * Checks if a bifurcation occurs at one point and return the vertex with maximum M
521
     *
522
     * @param multiLine
523
     * @param vertex
524
     * @return
525
     */
526
    private Point getPossibleFork(MultiLine multiLine, Point point) {
527

  
528
        List<Point> vertices = new ArrayList<Point>();
529
        for (int i = 0; i < multiLine.getPrimitivesNumber(); i++) {
530
            Line line = (Line) multiLine.getPrimitiveAt(i);
531
            for (int j = 0; j < line.getNumVertices(); j++) {
532
                Point vertex = line.getVertex(j);
533
                if (areInSame2DLocation(vertex, point)) {
534
                    vertices.add(vertex);
535
                }
417 536
            }
418 537
        }
538
        if (vertices.size() > 0) {
539
            Double maxM = Double.NEGATIVE_INFINITY;
540
            Point forked = null;
541
            for (Iterator<Point> iterator = vertices.iterator(); iterator.hasNext();) {
542
                Point vertex = (Point) iterator.next();
543
                double m = vertex.getCoordinateAt(vertex.getDimension() - 1);
544
                if (m > maxM) {
545
                    maxM = m;
546
                    forked = vertex;
547
                }
548
            }
549
            return forked;
550
        }
419 551
        return null;
420 552
    }
421 553

  
422
    private Geometry calculateGeometryByTwoField(List<MStructure> mList)
423
        throws CreateGeometryException, GeometryOperationNotSupportedException,
424
        GeometryOperationException {
425
        GeometryManager geomanager = GeometryLocator.getGeometryManager();
426
        MultiLine mGeometry = (MultiLine) geomanager
427
            .create(Geometry.TYPES.MULTILINE, Geometry.SUBTYPES.GEOM2DM);
554
    /**
555
     * Compares x & y coordinates of a point.
556
     *
557
     * @param p1
558
     * @param p2
559
     * @return
560
     */
561
    private boolean areInSame2DLocation(Point p1, Point p2) {
562
        return ((p1.getX() == p2.getX()) && (p1.getY() == p2.getY()));
563
    }
428 564

  
429
        for (MStructure mStructure : mList) {
430
            Geometry geometry = mStructure.geometry;
431
            List<Line> geometryLines=LrsAlgorithmUtils.extractLines(geometry);
432
            Double geometryLength=LrsAlgorithmUtils.getGeometryLength(geometry);
565
    /**
566
     * Returns the vertex of the multiline closest to a point
567
     *
568
     * @param mGeometry
569
     * @param vertex
570
     * @return
571
     * @throws GeometryOperationException
572
     * @throws GeometryOperationNotSupportedException
573
     * @throws CreateEnvelopeException
574
     */
575
    private Point getClosestVertex(MultiLine multiLine, Point point) throws CreateEnvelopeException,
576
        GeometryOperationNotSupportedException, GeometryOperationException {
577
        Point result = null;
578
        double minDistance = Double.POSITIVE_INFINITY;
433 579

  
434
            Double geometryMFirstPoint = mStructure.fromField;
435
            Double geometryMLastPoint=mStructure.toField;
436

  
437
            Double distance=Double.valueOf(0);
438
            for (Line line:geometryLines){
439
                Double lineLength=LrsAlgorithmUtils.getLineLength(line);
440
                Double mFirstPoint =
441
                    calculateM(geometryMLastPoint, geometryMFirstPoint, distance, geometryLength);
442
                distance+=lineLength;
443
                Double mLastPoint =
444
                    calculateM(geometryMLastPoint, geometryMFirstPoint, distance, geometryLength);
445
                Line mLine=lineToMLine(line, mFirstPoint, mLastPoint);
446
                mGeometry.addPrimitive(mLine);
580
        for (int i = 0; i < multiLine.getPrimitivesNumber(); i++) {
581
            Line line = (Line) multiLine.getPrimitiveAt(i);
582
            for (int j = 0; j < line.getNumVertices(); j++) {
583
                Point vertex = line.getVertex(j);
584
                double distance = point.distance(vertex);
585
                if (distance <= minDistance) {
586
                    minDistance = distance;
587
                    result = vertex;
588
                }
447 589
            }
448 590
        }
449 591

  
450
//        for (MStructure mStructure : mList) {
451
//            Geometry geometry = mStructure.geometry;
452
//            Double fromDistance = mStructure.fromField;
453
//            Double toDistance = mStructure.toField;
454
//            if (geometry instanceof Line) {
455
//                Line line = (Line) geometry;
456
//                Line lineM = lineToMLine(line, fromDistance, toDistance);
457
//                mGeometry.addPrimitive(lineM);
592
        return result;
593
    }
594

  
595
//    /**
596
//     * @param closestPoints
597
//     * @return
598
//     * @throws CreateEnvelopeException
599
//     * @throws GeometryOperationException
600
//     * @throws GeometryOperationNotSupportedException
601
//     */
602
//    private Point getClosestPointByCoordinatePriority(Geometry[] closestPoints) throws CreateEnvelopeException,
603
//        GeometryOperationNotSupportedException, GeometryOperationException {
604
//        LrsCoordinatesPriority coordinatePriority = parameters.getCoordinatePriority();
605
//        GeometryManager geomanager = GeometryLocator.getGeometryManager();
606
//        Envelope envelope = geomanager.createEnvelope(Geometry.SUBTYPES.GEOM2D);
607
//        for (int i = 0; i < closestPoints.length; i++) {
608
//            envelope.add(closestPoints[i]);
609
//        }
610
//        Point origin = envelope.getLowerCorner();
611
//        switch (coordinatePriority) {
612
//        case DOWN_LEFT:
613
//            break;
614
//        case DOWN_RIGHT:
615
//            Double maxX = envelope.getMaximum(DIMENSIONS.X);
616
//            origin.setX(maxX);
617
//            break;
618
//        case UP_LEFT:
619
//            Double maxY = envelope.getMaximum(DIMENSIONS.Y);
620
//            origin.setY(maxY);
621
//            break;
622
//        case UP_RIGHT:
623
//            origin = envelope.getUpperCorner();
624
//            break;
625
//        default:
626
//            break;
627
//        }
628
//        Point closestPoint = null;
629
//        double minDistance = Double.POSITIVE_INFINITY;
630
//        for (int i = 0; i < closestPoints.length; i++) {
631
//            Point point = (Point) closestPoints[i];
632
//            double distance = origin.distance(point);
633
//            if (minDistance > distance) {
634
//                minDistance = distance;
635
//                closestPoint = point;
458 636
//            }
459
//            if (geometry instanceof MultiLine) {
460
//                MultiLine multiLine = (MultiLine) geometry;
461
//                Line[] lines =
462
//                    multilineToMlines(multiLine, fromDistance, toDistance);
463
//                for (Line lineM : lines) {
464
//                    mGeometry.addPrimitive(lineM);
465
//                }
466
//            }
467 637
//        }
638
//        return closestPoint;
639
//    }
468 640

  
469
        return mGeometry;
470
    }
471

  
472
//    private Line[] multilineToMlines(MultiLine multiLine, Double fromDistance,
473
//        Double toDistance) throws GeometryOperationNotSupportedException,
474
//            GeometryOperationException, CreateGeometryException {
475
//        return multilineToMlines(multiLine, fromDistance, toDistance, true);
476
//    }
477
//
478
//    private Line[] multilineToMlines(MultiLine multiLine, Double fromDistance,
479
//        Double toDistance, boolean ignoreSpatialGaps)
480
//            throws GeometryOperationNotSupportedException,
481
//            GeometryOperationException, CreateGeometryException {
482
//
483
//        Line[] lines = new Line[multiLine.getPrimitivesNumber()];
484
//        Double multiLineLength =
485
//            getMultiLineLength(multiLine, ignoreSpatialGaps);
486
//        Double mFirstPoint = fromDistance;
487
//        Double mLastPoint = null;
488
//        Double distance = Double.valueOf(0);
489
//        Point lastPoint = null;
490
//        for (int i = 0; i < multiLine.getPrimitivesNumber(); i++) {
491
//
492
//            Line line = (Line) multiLine.getPrimitiveAt(i);
493
//            Double lineLength = getLineLength(line);
494
//            Double gap = Double.valueOf(0);
495
//
496
//            if (!ignoreSpatialGaps && lastPoint != null) {
497
//                Point firstPoint = line.getVertex(0);
498
//                gap = firstPoint.distance(lastPoint);
499
//                distance += gap;
641
//    private Double getCalculatedMValueForFirstPoint(Geometry mGeometry, Geometry geometry) {
642
//        List<Point> mPoints = extractPoints(mGeometry);
643
//        Point point = extractFirstPoint(geometry);
644
//        for (Point mPoint : mPoints) {
645
//            if (mPoint.getX() == point.getX() && mPoint.getY() == point.getY()) {
646
//                int dimensionM = mPoint.getDimension() - 1;
647
//                return mPoint.getCoordinateAt(dimensionM);
500 648
//            }
501
//            mFirstPoint =
502
//                calculateM(toDistance, fromDistance, distance, multiLineLength);
503
//            distance += lineLength;
504
//            mLastPoint =
505
//                calculateM(toDistance, fromDistance, distance, multiLineLength);
506
//            lines[i] = lineToMLine(line, mFirstPoint, mLastPoint);
507
//            lastPoint = lines[i].getVertex(line.getNumVertices() - 1);
508 649
//        }
509
//        return lines;
650
//        return null;
510 651
//    }
511 652

  
512
    private Line lineToMLine(Line line, Double minMValue, Double maxMValue)
513
        throws CreateGeometryException, GeometryOperationNotSupportedException,
514
        GeometryOperationException {
653
    /**
654
     * Returns a multiline calculate by two field method
655
     *
656
     * @param mList
657
     * @return
658
     * @throws CreateGeometryException
659
     * @throws GeometryOperationNotSupportedException
660
     * @throws GeometryOperationException
661
     */
662
    private MultiLine calculateGeometryByTwoField(List<MSegment> mList) throws CreateGeometryException,
663
        GeometryOperationNotSupportedException, GeometryOperationException {
515 664
        GeometryManager geomanager = GeometryLocator.getGeometryManager();
516
        Double lineLength = LrsAlgorithmUtils.getLineLength(line);
517
        Line lineM = (Line) geomanager.create(Geometry.TYPES.LINE,
518
            Geometry.SUBTYPES.GEOM2DM);
665
        MultiLine mGeometry = (MultiLine) geomanager.create(Geometry.TYPES.MULTILINE, Geometry.SUBTYPES.GEOM2DM);
666

  
667
        for (MSegment mSegment : mList) {
668
            Geometry geometry = mSegment.geometry;
669
            List<Line> geometryLines = extractLines(geometry);
670
            Double geometryLength = LrsAlgorithmUtils.getGeometryLength(geometry);
671

  
672
            Double geometryMFirstPoint = mSegment.fromValue;
673
            Double geometryMLastPoint = mSegment.toValue;
674

  
675
            Double distance = Double.valueOf(0);
676
            for (Line line : geometryLines) {
677
                Double lineLength = getLineLength(line);
678
                Double mFirstPoint = calculateM(geometryMLastPoint, geometryMFirstPoint, distance, geometryLength);
679
                distance += lineLength;
680
                Double mLastPoint = calculateM(geometryMLastPoint, geometryMFirstPoint, distance, geometryLength);
681
                Line mLine = lineToMLine(line, mFirstPoint, mLastPoint);
682
                mGeometry.addPrimitive(mLine);
683
            }
684
        }
685

  
686
        return mGeometry;
687
    }
688

  
689
    /**
690
     * Converts a Line2D in a Line2DM filled it with proportional calculated M's
691
     *
692
     * @param line
693
     * @param minMValue
694
     * @param maxMValue
695
     * @return
696
     * @throws CreateGeometryException
697
     * @throws GeometryOperationNotSupportedException
698
     * @throws GeometryOperationException
699
     */
700
    private Line lineToMLine(Line line, Double minMValue, Double maxMValue) throws CreateGeometryException,
701
        GeometryOperationNotSupportedException, GeometryOperationException {
702
        GeometryManager geomanager = GeometryLocator.getGeometryManager();
703
        Double lineLength = getLineLength(line);
704
        Line lineM = (Line) geomanager.create(Geometry.TYPES.LINE, Geometry.SUBTYPES.GEOM2DM);
519 705
        Double inLineDistance = Double.valueOf(0);
520 706
        for (int i = 0; i < line.getNumVertices(); i++) {
521 707
            Point vertex = line.getVertex(i);
522
            Point mVertex = (Point) geomanager.create(Geometry.TYPES.POINT,
523
                Geometry.SUBTYPES.GEOM2DM);
708
            Point mVertex = (Point) geomanager.create(Geometry.TYPES.POINT, Geometry.SUBTYPES.GEOM2DM);
524 709
            mVertex.setX(vertex.getX());
525 710
            mVertex.setY(vertex.getY());
526 711

  
......
532 717
            else {
533 718
                Point previousVertex = line.getVertex(i - 1);
534 719
                inLineDistance += vertex.distance(previousVertex);
535
                mValue = calculateM(maxMValue, minMValue, inLineDistance,
536
                    lineLength);
720
                mValue = calculateM(maxMValue, minMValue, inLineDistance, lineLength);
537 721
            }
538 722

  
539 723
            mVertex.setCoordinateAt(mVertex.getDimension() - 1, mValue);
......
542 726
        return lineM;
543 727
    }
544 728

  
545
    private Double calculateM(Double maxValue, Double minValue,
546
        Double relativeDistance, Double totalLength) {
547
        // mValue=((newMax-newMin)*(mCoordinate-oldMin)/(oldMax-oldMin))+newMin;
729
    /**
730
     * Reduced versi?n of stright line through two points equation to calculate M's
731
     *
732
     * @param maxValue
733
     * @param minValue
734
     * @param relativeDistance
735
     * @param totalLength
736
     * @return
737
     */
738
    private Double calculateM(Double maxValue, Double minValue, Double relativeDistance, Double totalLength) {
548 739
        if (totalLength.equals(Double.valueOf(0)))
549 740
            return Double.POSITIVE_INFINITY;
550
        return ((maxValue - minValue) * (relativeDistance) / (totalLength))
551
            + minValue;
741
        return ((maxValue - minValue) * (relativeDistance) / (totalLength)) + minValue;
552 742
    }
553 743

  
554
    private void simplifyMultilines(List<MStructure> mList)
555
        throws CreateGeometryException, LocatorException {
556
        List<MStructure> simplifiedMList = new ArrayList<MStructure>();
557
        for (MStructure mStructure : mList) {
558
            mStructure.geometry=simplifyMultiline(mStructure.geometry);
559
            simplifiedMList.add(mStructure);
744
    /**
745
     * Stright line through two points equation.
746
     *
747
     * @param x1
748
     * @param x2
749
     * @param y1
750
     * @param y2
751
     * @param x
752
     * @return
753
     */
754
    private double strightLineThroughTwoPointsEquation(double x1, double x2, double y1, double y2, double x) {
755
        if (x2 - x1 == 0.0) {
756
            return Double.POSITIVE_INFINITY;
560 757
        }
561
        mList = simplifiedMList;
758
        return ((y2 - y1) * (x - x1) / (x2 - x1)) + y1;
562 759
    }
563 760

  
564
    private Geometry simplifyMultiline(Geometry geometry) throws CreateGeometryException, LocatorException{
761
    /**
762
     * Simplify the multilines in mList calling simplifyMultiline method
763
     *
764
     * @param mList
765
     * @throws CreateGeometryException
766
     * @throws LocatorException
767
     */
768
    private void simplifyMultilines(List<MSegment> mList) throws CreateGeometryException, LocatorException {
769
        for (MSegment mSegment : mList) {
770
            mSegment.geometry = simplifyMultiline(mSegment.geometry);
771
        }
772
    }
773

  
774
    /**
775
     * Simplify a Multiline ordering and joining her lines if can.
776
     *
777
     * @param geometry
778
     * @return
779
     * @throws CreateGeometryException
780
     * @throws LocatorException
781
     */
782
    private Geometry simplifyMultiline(Geometry geometry) throws CreateGeometryException, LocatorException {
565 783
        if (geometry instanceof MultiLine) {
566 784
            MultiLine multiline = (MultiLine) geometry;
567 785

  
......
576 794

  
577 795
                Line line = null;
578 796
                while (complexLines.size() > 0) {
579
                    line = complexLines.get(0);
580
                    complexLines.remove(0);
581
                    int i=0;
582
                    while (i<complexLines.size()) {
583
                        Line auxLine=null;
584
                        if (complexLines.size()>0){
585
                            auxLine=complexLines.get(i);
586
                        }
797
                    line = complexLines.remove(0);
798
                    int i = 0;
799
                    while (i < complexLines.size()) {
800
                        Line auxLine = complexLines.get(i);
587 801
                        Line unitedLine = unionAdjacentLines(line, auxLine);
588 802
                        if (unitedLine != null) {
589 803
                            line = unitedLine;
590 804
                            complexLines.remove(i);
591
                            i=0;
592
                        }else{
805
                            i = 0;
806
                        } else {
593 807
                            i++;
594 808
                        }
595 809
                    }
......
600 814
                    geometry = simplifiedLines.get(0);
601 815
                } else {
602 816
                    MultiLine simplifiedMultiLine =
603
                        (MultiLine) GeometryLocator.getGeometryManager()
604
                            .create(multiline.getGeometryType());
817
                        (MultiLine) GeometryLocator.getGeometryManager().create(multiline.getGeometryType());
605 818
                    for (Line simpleLine : simplifiedLines) {
606 819
                        simplifiedMultiLine.addPrimitive(simpleLine);
607 820
                    }
......
612 825
        return geometry;
613 826
    }
614 827

  
828
    /**
829
     * Join two adjacent lines flipping it if necessary
830
     *
831
     * @param line1
832
     * @param line2
833
     * @return
834
     */
615 835
    private Line unionAdjacentLines(Line line1, Line line2) {
616 836
        if (line1 == null || line2 == null) {
617 837
            return null;
618 838
        }
619 839
        Line resultLine;
620 840
        try {
621
            resultLine = (Line) GeometryLocator.getGeometryManager()
622
                .create(line1.getGeometryType());
841
            resultLine = (Line) GeometryLocator.getGeometryManager().create(line1.getGeometryType());
623 842
        } catch (Exception e) {
624 843
            return null;
625 844
        }
......
631 850
        if (lastPointL1.equals(firstPointL2)) {
632 851
            resultLine = (Line) line1.cloneGeometry();
633 852
            for (int i = 1; i < line2.getNumVertices(); i++) {
634
                resultLine
635
                    .addVertex((Point) line2.getVertex(i).cloneGeometry());
853
                resultLine.addVertex((Point) line2.getVertex(i).cloneGeometry());
636 854
            }
637 855
            return resultLine;
638 856
        }
639 857
        if (lastPointL2.equals(firstPointL1)) {
640 858
            resultLine = (Line) line2.cloneGeometry();
641 859
            for (int i = 1; i < line1.getNumVertices(); i++) {
642
                resultLine
643
                    .addVertex((Point) line1.getVertex(i).cloneGeometry());
860
                resultLine.addVertex((Point) line1.getVertex(i).cloneGeometry());
644 861
            }
645 862
            return resultLine;
646 863
        }
647 864
        if (firstPointL1.equals(firstPointL2)) {
648 865
            for (int i = line1.getNumVertices() - 1; i >= 0; i--) {
649
                resultLine
650
                    .addVertex((Point) line1.getVertex(i).cloneGeometry());
866
                resultLine.addVertex((Point) line1.getVertex(i).cloneGeometry());
651 867
            }
652 868
            for (int i = 1; i < line2.getNumVertices(); i++) {
653
                resultLine
654
                    .addVertex((Point) line2.getVertex(i).cloneGeometry());
869
                resultLine.addVertex((Point) line2.getVertex(i).cloneGeometry());
655 870
            }
656 871
            return resultLine;
657 872
        }
658 873
        if (lastPointL1.equals(lastPointL2)) {
659 874
            resultLine = (Line) line1.cloneGeometry();
660 875
            for (int i = line2.getNumVertices() - 2; i >= 0; i--) {
661
                resultLine
662
                    .addVertex((Point) line2.getVertex(i).cloneGeometry());
876
                resultLine.addVertex((Point) line2.getVertex(i).cloneGeometry());
663 877
            }
664 878
            return resultLine;
665 879
        }
666 880
        return null;
667 881
    }
668 882

  
669

  
670
//    private Double calculateGap(Point lastPoint, Line line)
671
//        throws GeometryOperationNotSupportedException,
883
//    /**
884
//     * Calculate distance between a point and the firstPoint of the geometry
885
//     *
886
//     * @param point
887
//     * @param geometry
888
//     * @return
889
//     * @throws GeometryOperationNotSupportedException
890
//     * @throws GeometryOperationException
891
//     */
892
//    private Double calculateGap(Point point, Geometry geometry) throws GeometryOperationNotSupportedException,
672 893
//        GeometryOperationException {
673 894
//        Double gap = new Double(0);
674
//        if (lastPoint != null) {
675
//            Point firstPoint = line.getVertex(0);
676
//            gap = firstPoint.distance(lastPoint);
895
//        if (geometry instanceof Line) {
896
//            Line line = (Line) geometry;
897
//            if (point != null) {
898
//                Point firstPoint = line.getVertex(0);
899
//                gap = firstPoint.distance(point);
900
//            }
677 901
//        }
902
//        if (geometry instanceof MultiLine) {
903
//            MultiLine multiLine = (MultiLine) geometry;
904
//            if (point != null) {
905
//                Line line = (Line) multiLine.getPrimitiveAt(0);
906
//                Point firstPoint = line.getVertex(0);
907
//                gap = firstPoint.distance(point);
908
//            }
909
//        }
678 910
//        return gap;
679 911
//    }
680 912

  
681
    private Double calculateGap(Point lastPoint, Geometry geometry)
682
        throws GeometryOperationNotSupportedException,
683
        GeometryOperationException {
684
        Double gap = new Double(0);
685
        if (geometry instanceof Line) {
686
            Line line = (Line) geometry;
687
            if (lastPoint != null) {
688
                Point firstPoint = line.getVertex(0);
689
                gap = firstPoint.distance(lastPoint);
690
            }
691
        }
692
        if (geometry instanceof MultiLine) {
693
            MultiLine multiLine = (MultiLine) geometry;
694
            if (lastPoint != null) {
695
                Line line = (Line) multiLine.getPrimitiveAt(0);
696
                Point firstPoint = line.getVertex(0);
697
                gap = firstPoint.distance(lastPoint);
698
            }
699
        }
700
        return gap;
701
    }
702

  
703
    private List<MStructure> sortMList(List<MStructure> mList)
704
        throws CreateEnvelopeException, GeometryOperationNotSupportedException,
705
        GeometryOperationException {
706
        LrsCoordinatesPriority coordinatePriority =
707
            parameters.getCoordinatePriority();
913
    /**
914
     * Sorts mList
915
     *
916
     * @param mList
917
     * @return
918
     * @throws CreateEnvelopeException
919
     * @throws GeometryOperationNotSupportedException
920
     * @throws GeometryOperationException
921
     */
922
    private List<MSegment> sortMList(List<MSegment> mList) throws CreateEnvelopeException,
923
        GeometryOperationNotSupportedException, GeometryOperationException {
924
        LrsCoordinatesPriority coordinatePriority = parameters.getCoordinatePriority();
708 925
        GeometryManager geomanager = GeometryLocator.getGeometryManager();
709 926
        Envelope envelope = geomanager.createEnvelope(Geometry.SUBTYPES.GEOM2D);
710
        for (MStructure mStructure : mList) {
711
            envelope.add(mStructure.geometry.getEnvelope());
927
        for (MSegment mSegment : mList) {
928
            envelope.add(mSegment.geometry.getEnvelope());
712 929
        }
713 930
        Point origin = envelope.getLowerCorner();
714 931
        switch (coordinatePriority) {
......
729 946
            break;
730 947
        }
731 948

  
732
        List<Route> routes=createRoutes(mList,origin);
733
        mList=extractMStructures(routes,origin,mList);
734
        return mList;
735

  
736
        //SECOND ATTEMPT
737
//        List<MStructure> orderedMlist=new ArrayList<MStructure>();
738
//        while (!mList.isEmpty()){
739
//            List<Point> orderedExtremePoints=getExtremePoints(mList,origin);
740
//            while ( !orderedExtremePoints.isEmpty() ){
741
//                Point initialPoint= orderedExtremePoints.get(0);
742
//                orderedExtremePoints.remove(0);
743
//                MStructure initialMStructure=getMStructureWithExtremePoint(initialPoint);
744
//                orderMStructure(initialMStructure,origin); //Flips Geometry if it is necessary.
745
//                orderedMlist.add(initialMStructure);
746
//                mList.remove(initialMStructure);
747
//                List<Point> pointsInMStructure=getPointsInMStructure(initialMStructure);
748
//                orderedExtremePoints.removeAll(pointsInMStructure);
749
//                Point nextPoint=getNextPointInLine(initialMStructure, initialPoint);
750
//                while (nextPoint!=null){
751
//                    MStructure nextMStructure=getMStructureWithNextPoint(nextPoint);
752
//                    orderMStructure(nextMStructure,origin);
753
//                    orderedMlist.add(initialMStructure);
754
//                    mList.remove(initialMStructure);
755
//                    pointsInMStructure=getPointsInMStructure(nextMStructure);
756
//                    orderedExtremePoints.removeAll(pointsInMStructure);
757
//                    nextPoint=getNextPointInLine(nextMStructure, nextPoint);
758
//                }
759
//            }
760
//        }
761
//        mList=orderedMlist;
762

  
763

  
764
        //FIRST ATTEMPT
765
//        GeometryDistanceToPointComparator comaparatorMList =
766
//            new GeometryDistanceToPointComparator(origin);
767
//        Collections.sort(mList, comaparatorMList);
768
//
769
//        for (MStructure mStructure : mList) {
770
//            Geometry geometry = mStructure.geometry;
771
//            if (geometry instanceof Line) {
772
//                Line line = (Line) geometry;
773
//                Double firstPointDistance = origin.distance(line.getVertex(0));
774
//                Double lastPointDistance =
775
//                    origin.distance(line.getVertex(line.getNumVertices() - 1));
776
//                if (lastPointDistance < firstPointDistance) {
777
//                    geometry.flip();
778
//                }
779
//            }
780
//            if (geometry instanceof MultiLine) {
781
//                MultiLine multiLine = (MultiLine) geometry;
782
//                Line firstLine = (Line) multiLine.getPrimitiveAt(0);
783
//                Line lastLine = (Line) multiLine
784
//                    .getPrimitiveAt(multiLine.getPrimitivesNumber() - 1);
785
//                Double firstPointDistance =
786
//                    origin.distance(firstLine.getVertex(0));
787
//                Double lastPointDistance = origin.distance(
788
//                    lastLine.getVertex(lastLine.getNumVertices() - 1));
789
//                if (lastPointDistance < firstPointDistance) {
790
//                    geometry.flip();
791
//                }
792
//            }
793
//            mStructure.geometry = geometry;
794
//        }
795

  
949
        List<Stretch> stretches = createStretches(mList, origin);
950
        stretches = sortStretches(stretches, origin);
951
        return extractSegmentsFromStretches(stretches);
796 952
    }
797 953

  
798
    private List<MStructure> extractMStructures(List<Route> routes, Point origin,List<MStructure> mList) throws GeometryOperationNotSupportedException, GeometryOperationException{
799
        List<MStructure> orderedMList=new ArrayList<MStructure>();
800
        Point initialPoint=origin;
801
        while (!routes.isEmpty()){
802
            Route route=getNearestRoute(routes, initialPoint, mList,origin);
803
            routes.remove(route);
804
            int i=0;
805
            while (!route.structures.isEmpty()){
806
                MStructure structure=route.structures.get(i);
807
                route.structures.remove(i);
808
                orderedMList.add(structure);
809
                removeRepeatedStructures(routes, structure);
954
    /**
955
     * Extracts segment from stretches and returns a list of segment.
956
     *
957
     * @param stretches
958
     * @return
959
     */
960
    private List<MSegment> extractSegmentsFromStretches(List<Stretch> stretches) {
961
        List<MSegment> result = new ArrayList<MSegment>();
962
        for (Stretch stretch : stretches) {
963
            for (int i = 0; i < stretch.getSegmentNumber(); i++) {
964
                result.add(stretch.getSegment(i));
810 965
            }
811
            initialPoint=route.finalPoint;
812 966
        }
813
        return orderedMList;
967
        return result;
814 968
    }
815 969

  
816
    private Route getNearestRoute(List<Route> routes, Point point,List<MStructure> mList, Point originPoint)
817
        throws GeometryOperationNotSupportedException, GeometryOperationException{
818
        double minDistance = Double.POSITIVE_INFINITY;
819
        Route nearestRoute = null;
970
    /**
971
     * Sort the stretches
972
     *
973
     * @param stretches
974
     * @param origin
975
     * @return
976
     * @throws GeometryOperationNotSupportedException
977
     * @throws GeometryOperationException
978
     */
979
    private List<Stretch> sortStretches(List<Stretch> stretches, Point origin)
980
        throws GeometryOperationNotSupportedException, GeometryOperationException {
981
        List<Stretch> result = new ArrayList<Stretch>();
820 982

  
821
        if (!point.equals(originPoint)){
822
            if (isTriplePoint(mList, point)){
823
                point=originPoint;
983
        Point originPoint = origin;
984
        while (result.size() < stretches.size()) {
985
            // Buscamos tramos que sean adyacentes al origin
986
            if (result.size() == 0) {
987
                addUnvisitedAdjacentStretches(stretches, result, originPoint);
824 988
            }
825
        }
989
            if (result.size() == 0) {
990
                result.add(getNearestUnvisitedStretch(stretches, originPoint, result));
991
            }
826 992

  
827
        for (Route route:routes){
828
            Double initialDistance=point.distance(route.initialPoint);
829
            if(initialDistance<minDistance){
830
                minDistance = initialDistance;
831
                nearestRoute = route;
993
            boolean addedAdjacentStretches = true;
994
            while (addedAdjacentStretches) {
995
                addedAdjacentStretches = false;
996
                int visitedNumber = result.size();
997
                for (int i = 0; i < visitedNumber; i++) {
998
                    Stretch visited = result.get(i);
999
                    addUnvisitedAdjacentStretches(stretches, result, visited.getFinalPoint());
1000
                }
1001
                addedAdjacentStretches = (visitedNumber < result.size());
832 1002
            }
833
            Double finalDistance=point.distance(route.finalPoint);
834
            if(finalDistance<minDistance){
835
                minDistance = finalDistance;
836
                nearestRoute = route;
1003

  
1004
            int visitedNumber = result.size();
1005
            for (int i = visitedNumber - 1; i >= 0; i--) {
1006
                Stretch visited = result.get(i);
1007
                Stretch nearest = getNearestUnvisitedStretch(stretches, visited.getFinalPoint(), result);
1008
                if (nearest != null) {
1009
                    result.add(nearest);
1010
                    break;
1011
                }
837 1012
            }
838 1013
        }
839
        Double initialDistance=point.distance(nearestRoute.initialPoint);
840
        Double finalDistance=point.distance(nearestRoute.finalPoint);
1014
        return result;
1015
    }
841 1016

  
842
        if (finalDistance<initialDistance){
843
            Collections.reverse(nearestRoute.structures);
844
            for (MStructure structure :nearestRoute.structures){
845
                structure.geometry.flip();
1017
    /**
1018
     * Adds unvisited adjacent stretches to the visited list
1019
     *
1020
     * @param stretches
1021
     * @param visited
1022
     * @param originPoint
1023
     * @throws GeometryOperationNotSupportedException
1024
     * @throws GeometryOperationException
1025
     */
1026
    private void addUnvisitedAdjacentStretches(List<Stretch> stretches, List<Stretch> visited, Point originPoint)
1027
        throws GeometryOperationNotSupportedException, GeometryOperationException {
1028
        for (Stretch stretch : stretches) {
1029
            if (!visited.contains(stretch)) {
1030
                if (areInSame2DLocation(stretch.getInitialPoint(), originPoint)) {
1031
                    visited.add(stretch);
1032
                } else if (areInSame2DLocation(stretch.getFinalPoint(), originPoint)) {
1033
                    visited.add(stretch.flip());
1034
                }
846 1035
            }
847 1036
        }
848
        return nearestRoute;
849 1037
    }
850 1038

  
851
    private void removeRepeatedStructures(List<Route>routes, MStructure structureToRemove){
852
        for (Route route:routes){
853
            int i=0;
854
            boolean removed=false;
855
            while (i< route.structures.size()&&!removed){
856
                if (route.structures.get(i).id==structureToRemove.id){
857
                    route.structures.remove(i);
858
                    removed=true;
1039
    /**
1040
     * Returns the unvisited stretch nearest to a point
1041
     *
1042
     * @param stretches
1043
     * @param origin
1044
     * @param visited
1045
     * @return
1046
     * @throws GeometryOperationNotSupportedException
1047
     * @throws GeometryOperationException
1048
     */
1049
    private Stretch getNearestUnvisitedStretch(List<Stretch> stretches, Point origin, List<Stretch> visited)
1050
        throws GeometryOperationNotSupportedException, GeometryOperationException {
1051

  
1052
        double minDistance = Double.POSITIVE_INFINITY;
1053
        Stretch nearest = null;
1054
        boolean needFlip = false;
1055
        for (Stretch stretch : stretches) {
1056
            if (!visited.contains(stretch)) {
1057
                Double initialDistance = origin.distance(stretch.getInitialPoint());
1058
                if (initialDistance < minDistance) {
1059
                    minDistance = initialDistance;
1060
                    nearest = stretch;
1061
                    needFlip = false;
859 1062
                }
860
                i++;
1063
                Double finalDistance = origin.distance(stretch.getFinalPoint());
1064
                if (finalDistance < minDistance) {
1065
                    minDistance = finalDistance;
1066
                    nearest = stretch;
1067
                    needFlip = true;
1068
                }
861 1069
            }
862 1070
        }
1071
        if (needFlip && nearest != null) {
1072
            nearest.flip();
1073
        }
1074
        return nearest;
863 1075
    }
864 1076

  
1077
    /**
1078
     * Creates stretches from mList and returns a list of stretches
1079
     *
1080
     * @param mList
1081
     * @param origin
1082
     * @return
1083
     * @throws GeometryOperationNotSupportedException
1084
     * @throws GeometryOperationException
1085
     */
1086
    private List<Stretch> createStretches(List<MSegment> mList, Point origin)
1087
        throws GeometryOperationNotSupportedException, GeometryOperationException {
865 1088

  
866
    private List <Route> createRoutes(List<MStructure> mList, Point origin) throws GeometryOperationNotSupportedException, GeometryOperationException{
867
        List <Route> routes=new ArrayList<Route>();
868
        for (MStructure mStructure:mList){
869
            Geometry geometry=mStructure.geometry;
870
            List<Line> lines=LrsAlgorithmUtils.extractLines(geometry);
871
            for (Line initialLine:lines){
872
                if (!isAddedLine(routes,initialLine)){
873
                    Route route=new Route();
874
                    routes.add(route);
875
                    MStructure mStructureOrdered=mStructure.clone();
876
                    if (isFlippedLine(initialLine, origin)){
877
                        mStructureOrdered.geometry.flip();
878
                        route.initialPoint=initialLine.getVertex(initialLine.getNumVertices()-1);
879
                        route.finalPoint=initialLine.getVertex(0);
880
                    }else{
881
                        route.initialPoint=initialLine.getVertex(0);
882
                        route.finalPoint=initialLine.getVertex(initialLine.getNumVertices()-1);
883
                    }
1089
        List<MSegment> addedMSegment = new ArrayList<LrsCreateRouteAlgorithm.MSegment>();
1090
        List<Stretch> stretches = new ArrayList<Stretch>();
1091
        while (addedMSegment.size() < mList.size()) {
1092
            for (MSegment mSegment : mList) {
1093
                if (!addedMSegment.contains(mSegment)) {
1094
                    Stretch stretch = new Stretch();
1095
                    stretches.add(stretch);
1096
                    stretch.addSegment(mSegment);
1097
                    addedMSegment.add(mSegment);
884 1098

  
885
                    route.structures.add(mStructureOrdered);
886
                    route.lines.add(initialLine);
887
                    Double initialPointDistance=route.initialPoint.distance(origin);
888
                    Double finalPointDistance=route.finalPoint.distance(origin);
889
                    int i=0;
890
                    boolean insertLowPriority=false;
891
                    while (i<mList.size() && !insertLowPriority){
892
                        if (i>=mList.size()){
893
                            insertLowPriority=true;
894
                            i=0;
1099
                    List<MSegment> initialNextSegments =
1100
                        mSegment.searchNextSegments(stretch.getInitialPoint(), mList);
1101
                    do {
1102
                        if (initialNextSegments.size() == 1) {
1103
                            MSegment previousSegment = initialNextSegments.get(0);
1104
                            if (!addedMSegment.contains(previousSegment)) {
1105
                                if (!previousSegment.getFinalPoint().equals(stretch.getInitialPoint())) {
1106
                                    previousSegment.flip();
1107
                                }
1108
                                stretch.addSegment(0, previousSegment);
1109
                                addedMSegment.add(previousSegment);
1110
                                initialNextSegments =
1111
                                    previousSegment.searchNextSegments(stretch.getInitialPoint(), mList);
1112
                            } else {
1113
                                break;
1114
                            }
1115
                        } else {
1116
                            break;
895 1117
                        }
896
                        boolean lineAdded=false;
897
                        MStructure mStructureAdded=mList.get(i);
898
                        Geometry geometryAdded=mStructureAdded.geometry;
899
                        List<Line> linesAdded=LrsAlgorithmUtils.extractLines(geometryAdded);
900
                        for (Line addedLine:linesAdded){
901
                            if (!isAddedLine(routes,addedLine)){
1118
                    } while (initialNextSegments.size() == 1);
902 1119

  
903
                                MStructure mStructureAddedOrdered=mStructureAdded.clone();
904
                                Point initialPoint=addedLine.getVertex(0);
905
                                Point finalPoint=addedLine.getVertex(addedLine.getNumVertices()-1);
906

  
907
                                if ( route.initialPoint.equals(initialPoint) ){
908
                                    if (!isTriplePoint(mList,initialPoint)){
909
                                        Double distanceAddedPoint=origin.distance(finalPoint);
910
                                        boolean lowPriority=false;
911
                                        if (distanceAddedPoint>finalPointDistance){
912
                                            lowPriority=true;
913
                                        }
914
                                        if (!lowPriority||insertLowPriority){
915
                                            initialPointDistance=distanceAddedPoint;
916
                                            mStructureAddedOrdered.geometry.flip();
917
                                            route.initialPoint=finalPoint;
918
                                            route.structures.add(0, mStructureAddedOrdered);
919
                                            route.lines.add(addedLine);
920
                                            lineAdded=true;
921
                                        }
922
                                    }
923
                                }else if ( route.initialPoint.equals(finalPoint)  ) {
924
                                    if (!isTriplePoint(mList,finalPoint)){
925
                                        Double distanceAddedPoint=origin.distance(initialPoint);
926
                                        boolean lowPriority=false;
927
                                        if (distanceAddedPoint>initialPointDistance){
928
                                            lowPriority=true;
929
                                        }
930
                                        if (!lowPriority||insertLowPriority){
931
                                            initialPointDistance=distanceAddedPoint;
932
                                            route.initialPoint=initialPoint;
933
                                            route.structures.add(0, mStructureAddedOrdered);
934
                                            route.lines.add(addedLine);
935
                                            lineAdded=true;
936
                                        }
937
                                    }
938
                                }else if ( route.finalPoint.equals(initialPoint) ){
939
                                   if (!isTriplePoint(mList,finalPoint)){
940
                                        Double distanceAddedPoint=origin.distance(initialPoint);
941
                                        boolean lowPriority=false;
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff