Statistics
| Revision:

gvsig-lrs / 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 @ 27

History | View | Annotate | Download (56.2 KB)

1
/* gvSIG. Desktop Geographic Information System.
2
 *
3
 * Copyright ? 2007-2015 gvSIG Association
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License
7
 * as published by the Free Software Foundation; either version 2
8
 * of the License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18
 * MA  02110-1301, USA.
19
 *
20
 * For any additional information, do not hesitate to contact us
21
 * at info AT gvsig.com, or visit our website www.gvsig.com.
22
 */
23
package org.gvsig.lrs.lib.impl;
24

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

    
35
import org.apache.commons.lang3.mutable.MutableInt;
36
import org.gvsig.fmap.dal.feature.EditableFeature;
37
import org.gvsig.fmap.dal.feature.Feature;
38
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
39
import org.gvsig.fmap.dal.feature.FeatureReference;
40
import org.gvsig.fmap.dal.feature.FeatureSelection;
41
import org.gvsig.fmap.dal.feature.FeatureSet;
42
import org.gvsig.fmap.dal.feature.FeatureStore;
43
import org.gvsig.fmap.dal.feature.NewFeatureStoreParameters;
44
import org.gvsig.fmap.geom.Geometry;
45
import org.gvsig.fmap.geom.Geometry.DIMENSIONS;
46
import org.gvsig.fmap.geom.GeometryLocator;
47
import org.gvsig.fmap.geom.GeometryManager;
48
import org.gvsig.fmap.geom.aggregate.MultiLine;
49
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
50
import org.gvsig.fmap.geom.exception.CreateGeometryException;
51
import org.gvsig.fmap.geom.operation.GeometryOperationException;
52
import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException;
53
import org.gvsig.fmap.geom.primitive.Envelope;
54
import org.gvsig.fmap.geom.primitive.Line;
55
import org.gvsig.fmap.geom.primitive.Point;
56
import org.gvsig.lrs.lib.api.LrsAlgorithm;
57
import org.gvsig.lrs.lib.api.LrsAlgorithmParams;
58
import org.gvsig.lrs.lib.api.LrsCoordinatesPriority;
59
import org.gvsig.lrs.lib.api.LrsCreateRouteAlgorithmParams;
60
import org.gvsig.lrs.lib.api.LrsSourceOfMeasures;
61
import org.gvsig.lrs.lib.api.exceptions.LrsCreateRouteException;
62
import org.gvsig.lrs.lib.api.exceptions.LrsException;
63
import org.gvsig.tools.ToolsLocator;
64
import org.gvsig.tools.dataTypes.DataType;
65
import org.gvsig.tools.exception.BaseException;
66
import org.gvsig.tools.i18n.I18nManager;
67
import org.gvsig.tools.locator.LocatorException;
68
import org.gvsig.tools.service.Manager;
69
import org.gvsig.tools.task.SimpleTaskStatus;
70
import org.gvsig.tools.visitor.VisitCanceledException;
71
import org.gvsig.tools.visitor.Visitor;
72
import org.omg.CosNaming.IstringHelper;
73
import org.slf4j.Logger;
74
import org.slf4j.LoggerFactory;
75

    
76
/**
77
 * @author fdiaz
78
 *
79
 */
80
public class LrsCreateRouteAlgorithm implements LrsAlgorithm {
81

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

    
85
    private LrsCreateRouteAlgorithmParams parameters;
86

    
87
    /**
88
     *
89
     */
90
    public LrsCreateRouteAlgorithm(LrsCreateRouteAlgorithmParams parameters) {
91
        this.parameters = parameters;
92

    
93
    }
94

    
95
    /*
96
     * (non-Javadoc)
97
     *
98
     * @see org.gvsig.tools.service.Service#getManager()
99
     */
100
    public Manager getManager() {
101
        return null;
102
    }
103

    
104
    /*
105
     * (non-Javadoc)
106
     *
107
     * @see org.gvsig.lrs.lib.api.LrsAlgorithm#getParams()
108
     */
109
    public LrsAlgorithmParams getParams() {
110
        return this.parameters;
111
    }
112

    
113
    /*
114
     * (non-Javadoc)
115
     *
116
     * @see org.gvsig.lrs.lib.api.LrsAlgorithm#execute(org.gvsig.tools.task.
117
     * SimpleTaskStatus)
118
     */
119
    public void execute(SimpleTaskStatus taskStatus) throws LrsException {
120
        NewFeatureStoreParameters newFeatureStoreParameters =
121
            parameters.getNewFeatureStoreParameters();
122
        FeatureStore sourceFeatureStore = parameters.getSourceFeatureStore();
123
        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();
135

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

    
138
        taskStatus.setTitle(parameters.getName());
139
        I18nManager i18nManager = ToolsLocator.getI18nManager();
140
        taskStatus.message(i18nManager.getTranslation("grouping_features"));
141

    
142
        try {
143
            final String routeFieldName = idRouteField.getName();
144
            final String fromFieldName;
145
            final DataType fromDataType;
146
            final DataType toDataType;
147
            if (fromMeasureField != null) {
148
                fromFieldName = fromMeasureField.getName();
149
                fromDataType = fromMeasureField.getDataType();
150
            } else {
151
                fromFieldName = null;
152
                fromDataType = null;
153
            }
154
            final String toFieldName;
155
            if (toMeasureField != null) {
156
                toFieldName = toMeasureField.getName();
157
                toDataType = toMeasureField.getDataType();
158
            } else {
159
                toFieldName = null;
160
                toDataType = null;
161
            }
162

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

    
166
            FeatureSet sourceFeatures;
167
            if (sourceFeatureStore.getFeatureSelection().getSize() > 0) {
168
                sourceFeatures = sourceFeatureStore.getFeatureSelection();
169
            } else {
170
                sourceFeatures = sourceFeatureStore.getFeatureSet();
171
            }
172

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

    
178
                public void visit(Object obj)
179
                    throws VisitCanceledException, BaseException {
180
                    Feature feature = (Feature) obj;
181
                    String routeName = (String) feature.get(routeFieldName);
182
                    Geometry originalGeometry = feature.getDefaultGeometry();
183
                    Object objFrom = null;
184
                    Object objTo = null;
185
                    if (fromFieldName != null) {
186
                        objFrom = feature.get(fromFieldName);
187
                    }
188
                    if (toFieldName != null) {
189
                        objTo = feature.get(toFieldName);
190
                    }
191
                    if (!featuresMap.containsKey(routeName)) {
192
                        featuresMap.put(routeName, new ArrayList<MStructure>());
193
                    }
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();
202
                    contId.increment();
203
                    mList.add(mStructure);
204
                    featuresMap.put(routeName, mList);
205
                }
206
            });
207
            taskStatus.setRangeOfValues(0, featuresMap.size());
208
            int taskCount = 0;
209

    
210
            newFeatureStore.edit(FeatureStore.MODE_FULLEDIT);
211

    
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()) {
232
                String routeName = entry.getKey();
233
                List<MStructure> mList = entry.getValue();
234

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

    
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
                newFeatureStore.update(newFeature);
268

    
269
                taskCount++;
270
                taskStatus.setCurValue(taskCount);
271

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

    
276
        } catch (Exception e1) {
277
            taskStatus.abort();
278
            throw new LrsCreateRouteException("Error creating routes", e1);
279
        }
280

    
281
        taskStatus.terminate();
282

    
283
    }
284

    
285
    private Geometry createGeometryRoute(List<MStructure> mList)
286
        throws CreateGeometryException, GeometryOperationNotSupportedException,
287
        GeometryOperationException {
288
        LrsSourceOfMeasures sourceOfMeasures = parameters.getSourceOfMeasures();
289
        Geometry geometryResult = null;
290
        simplifyMultilines(mList);
291
        switch (sourceOfMeasures) {
292
        case ONE_FIELD:
293
            geometryResult = calculateGeometryByOneField(mList);
294
            break;
295
        case TWO_FIELDS:
296
            geometryResult = calculateGeometryByTwoField(mList);
297
            break;
298
        case LENGTH:
299
        default:
300
            geometryResult = calculateGeometryByLength(mList);
301
            break;
302
        }
303
        geometryResult = simplifyMultiline(geometryResult);
304
        geometryResult = applyOffset(geometryResult);
305
        return geometryResult;
306
    }
307

    
308
    private Geometry calculateGeometryByLength(List<MStructure> mList)
309
        throws CreateGeometryException, GeometryOperationNotSupportedException,
310
        GeometryOperationException {
311
        boolean ignoreSpatialGaps = parameters.ignoreSpatialGaps();
312
        for (MStructure mStructure : mList) {
313
            mStructure.fromField =
314
                getGeometryLength(mStructure.geometry, ignoreSpatialGaps);
315
        }
316
        return calculateGeometryByOneField(mList);
317
    }
318

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

    
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;
336

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

    
343
            if (!ignoreSpatialGaps) {
344
                gapBetweenGeometries = calculateGap(lastPoint, geometry);
345
                lastMValueGeometry+=gapBetweenGeometries;
346
            }
347
            Double previouslyCalculatedMValue= getCalculatedMValueForFirstPoint(mGeometry,geometry);
348
            if (previouslyCalculatedMValue!=null){
349
                lastPoint=null;
350
                lastMValueGeometry=previouslyCalculatedMValue;
351
            }
352

    
353
            Double geometryMFirstPoint = lastMValueGeometry;
354
            lastMValueGeometry+=mStructure.fromField;
355
            Double geometryMLastPoint=lastMValueGeometry;
356

    
357
            Double distance=Double.valueOf(0);;
358
            for (Line line:geometryLines){
359
                Double gapBetweenLines = Double.valueOf(0);
360
                Double lineLength=getLineLength(line);
361
                if (!ignoreSpatialGaps&&!firstLineInGeometry) {
362
                    gapBetweenLines = calculateGap(lastPoint, line);
363
                    distance+=gapBetweenLines;
364
                    firstLineInGeometry=false;
365
                }
366

    
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);
375
            }
376
        }
377
        return mGeometry;
378

    
379

    
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);
404
//                }
405
//            }
406
//        }
407
//        return mGeometry;
408
    }
409

    
410
    private Double getCalculatedMValueForFirstPoint(Geometry mGeometry,Geometry geometry){
411
        List<Point> mPoints=extractPoints(mGeometry);
412
        Point point=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);
417
            }
418
        }
419
        return null;
420
    }
421

    
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);
428

    
429
        for (MStructure mStructure : mList) {
430
            Geometry geometry = mStructure.geometry;
431
            List<Line> geometryLines=extractLines(geometry);
432
            Double geometryLength=getGeometryLength(geometry);
433

    
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=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);
447
            }
448
        }
449

    
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);
458
//            }
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
//        }
468

    
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;
500
//            }
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
//        }
509
//        return lines;
510
//    }
511

    
512
    private Line lineToMLine(Line line, Double minMValue, Double maxMValue)
513
        throws CreateGeometryException, GeometryOperationNotSupportedException,
514
        GeometryOperationException {
515
        GeometryManager geomanager = GeometryLocator.getGeometryManager();
516
        Double lineLength = getLineLength(line);
517
        Line lineM = (Line) geomanager.create(Geometry.TYPES.LINE,
518
            Geometry.SUBTYPES.GEOM2DM);
519
        Double inLineDistance = Double.valueOf(0);
520
        for (int i = 0; i < line.getNumVertices(); i++) {
521
            Point vertex = line.getVertex(i);
522
            Point mVertex = (Point) geomanager.create(Geometry.TYPES.POINT,
523
                Geometry.SUBTYPES.GEOM2DM);
524
            mVertex.setX(vertex.getX());
525
            mVertex.setY(vertex.getY());
526

    
527
            Double mValue;
528
            if (i == 0)
529
                mValue = minMValue;
530
            else if (i == line.getNumVertices() - 1)
531
                mValue = maxMValue;
532
            else {
533
                Point previousVertex = line.getVertex(i - 1);
534
                inLineDistance += vertex.distance(previousVertex);
535
                mValue = calculateM(maxMValue, minMValue, inLineDistance,
536
                    lineLength);
537
            }
538

    
539
            mVertex.setCoordinateAt(mVertex.getDimension() - 1, mValue);
540
            lineM.addVertex(mVertex);
541
        }
542
        return lineM;
543
    }
544

    
545
    private Double calculateM(Double maxValue, Double minValue,
546
        Double relativeDistance, Double totalLength) {
547
        // mValue=((newMax-newMin)*(mCoordinate-oldMin)/(oldMax-oldMin))+newMin;
548
        if (totalLength.equals(Double.valueOf(0)))
549
            return Double.POSITIVE_INFINITY;
550
        return ((maxValue - minValue) * (relativeDistance) / (totalLength))
551
            + minValue;
552
    }
553

    
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);
560
        }
561
        mList = simplifiedMList;
562
    }
563

    
564
    private Geometry simplifyMultiline(Geometry geometry) throws CreateGeometryException, LocatorException{
565
        if (geometry instanceof MultiLine) {
566
            MultiLine multiline = (MultiLine) geometry;
567

    
568
            if (multiline.getPrimitivesNumber() == 1) {
569
                return multiline.getPrimitiveAt(0);
570
            } else {
571
                List<Line> simplifiedLines = new ArrayList<Line>();
572
                List<Line> complexLines = new ArrayList<Line>();
573
                for (int i = 0; i < multiline.getPrimitivesNumber(); i++) {
574
                    complexLines.add((Line) multiline.getPrimitiveAt(i));
575
                }
576

    
577
                Line line = null;
578
                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
                        }
587
                        Line unitedLine = unionAdjacentLines(line, auxLine);
588
                        if (unitedLine != null) {
589
                            line = unitedLine;
590
                            complexLines.remove(i);
591
                            i=0;
592
                        }else{
593
                            i++;
594
                        }
595
                    }
596
                    simplifiedLines.add(line);
597
                }
598

    
599
                if (simplifiedLines.size() == 1) {
600
                    geometry = simplifiedLines.get(0);
601
                } else {
602
                    MultiLine simplifiedMultiLine =
603
                        (MultiLine) GeometryLocator.getGeometryManager()
604
                            .create(multiline.getGeometryType());
605
                    for (Line simpleLine : simplifiedLines) {
606
                        simplifiedMultiLine.addPrimitive(simpleLine);
607
                    }
608
                    return simplifiedMultiLine;
609
                }
610
            }
611
        }
612
        return geometry;
613
    }
614

    
615
    private Line unionAdjacentLines(Line line1, Line line2) {
616
        if (line1 == null || line2 == null) {
617
            return null;
618
        }
619
        Line resultLine;
620
        try {
621
            resultLine = (Line) GeometryLocator.getGeometryManager()
622
                .create(line1.getGeometryType());
623
        } catch (Exception e) {
624
            return null;
625
        }
626

    
627
        Point firstPointL1 = line1.getVertex(0);
628
        Point lastPointL1 = line1.getVertex(line1.getNumVertices() - 1);
629
        Point firstPointL2 = line2.getVertex(0);
630
        Point lastPointL2 = line2.getVertex(line2.getNumVertices() - 1);
631
        if (lastPointL1.equals(firstPointL2)) {
632
            resultLine = (Line) line1.cloneGeometry();
633
            for (int i = 1; i < line2.getNumVertices(); i++) {
634
                resultLine
635
                    .addVertex((Point) line2.getVertex(i).cloneGeometry());
636
            }
637
            return resultLine;
638
        }
639
        if (lastPointL2.equals(firstPointL1)) {
640
            resultLine = (Line) line2.cloneGeometry();
641
            for (int i = 1; i < line1.getNumVertices(); i++) {
642
                resultLine
643
                    .addVertex((Point) line1.getVertex(i).cloneGeometry());
644
            }
645
            return resultLine;
646
        }
647
        if (firstPointL1.equals(firstPointL2)) {
648
            for (int i = line1.getNumVertices() - 1; i >= 0; i--) {
649
                resultLine
650
                    .addVertex((Point) line1.getVertex(i).cloneGeometry());
651
            }
652
            for (int i = 1; i < line2.getNumVertices(); i++) {
653
                resultLine
654
                    .addVertex((Point) line2.getVertex(i).cloneGeometry());
655
            }
656
            return resultLine;
657
        }
658
        if (lastPointL1.equals(lastPointL2)) {
659
            resultLine = (Line) line1.cloneGeometry();
660
            for (int i = line2.getNumVertices() - 2; i >= 0; i--) {
661
                resultLine
662
                    .addVertex((Point) line2.getVertex(i).cloneGeometry());
663
            }
664
            return resultLine;
665
        }
666
        return null;
667
    }
668

    
669

    
670
//    private Double calculateGap(Point lastPoint, Line line)
671
//        throws GeometryOperationNotSupportedException,
672
//        GeometryOperationException {
673
//        Double gap = new Double(0);
674
//        if (lastPoint != null) {
675
//            Point firstPoint = line.getVertex(0);
676
//            gap = firstPoint.distance(lastPoint);
677
//        }
678
//        return gap;
679
//    }
680

    
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();
708
        GeometryManager geomanager = GeometryLocator.getGeometryManager();
709
        Envelope envelope = geomanager.createEnvelope(Geometry.SUBTYPES.GEOM2D);
710
        for (MStructure mStructure : mList) {
711
            envelope.add(mStructure.geometry.getEnvelope());
712
        }
713
        Point origin = envelope.getLowerCorner();
714
        switch (coordinatePriority) {
715
        case DOWN_LEFT:
716
            break;
717
        case DOWN_RIGHT:
718
            Double maxX = envelope.getMaximum(DIMENSIONS.X);
719
            origin.setX(maxX);
720
            break;
721
        case UP_LEFT:
722
            Double maxY = envelope.getMaximum(DIMENSIONS.Y);
723
            origin.setY(maxY);
724
            break;
725
        case UP_RIGHT:
726
            origin = envelope.getUpperCorner();
727
            break;
728
        default:
729
            break;
730
        }
731

    
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

    
796
    }
797

    
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);
810
            }
811
            initialPoint=route.finalPoint;
812
        }
813
        return orderedMList;
814
    }
815

    
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;
820

    
821
        if (!point.equals(originPoint)){
822
            if (isTriplePoint(mList, point)){
823
                point=originPoint;
824
            }
825
        }
826

    
827
        for (Route route:routes){
828
            Double initialDistance=point.distance(route.initialPoint);
829
            if(initialDistance<minDistance){
830
                minDistance = initialDistance;
831
                nearestRoute = route;
832
            }
833
            Double finalDistance=point.distance(route.finalPoint);
834
            if(finalDistance<minDistance){
835
                minDistance = finalDistance;
836
                nearestRoute = route;
837
            }
838
        }
839
        Double initialDistance=point.distance(nearestRoute.initialPoint);
840
        Double finalDistance=point.distance(nearestRoute.finalPoint);
841

    
842
        if (finalDistance<initialDistance){
843
            Collections.reverse(nearestRoute.structures);
844
            for (MStructure structure :nearestRoute.structures){
845
                structure.geometry.flip();
846
            }
847
        }
848
        return nearestRoute;
849
    }
850

    
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;
859
                }
860
                i++;
861
            }
862
        }
863
    }
864

    
865

    
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=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
                    }
884

    
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;
895
                        }
896
                        boolean lineAdded=false;
897
                        MStructure mStructureAdded=mList.get(i);
898
                        Geometry geometryAdded=mStructureAdded.geometry;
899
                        List<Line> linesAdded=extractLines(geometryAdded);
900
                        for (Line addedLine:linesAdded){
901
                            if (!isAddedLine(routes,addedLine)){
902

    
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;
942
                                        if (distanceAddedPoint<initialPointDistance){
943
                                            lowPriority=true;
944
                                        }
945
                                        if (!lowPriority||insertLowPriority){
946
                                            finalPointDistance=distanceAddedPoint;
947
                                            route.finalPoint=finalPoint;
948
                                            route.structures.add(mStructureAddedOrdered);
949
                                            route.lines.add(addedLine);
950
                                            lineAdded=true;
951
                                        }
952
                                    }
953
                                }else if ( route.finalPoint.equals(finalPoint) ){
954
                                    if (!isTriplePoint(mList,finalPoint)){
955
                                        Double distanceAddedPoint=origin.distance(initialPoint);
956
                                        boolean lowPriority=false;
957
                                        if (distanceAddedPoint<finalPointDistance){
958
                                            lowPriority=true;
959
                                        }
960
                                        if (!lowPriority||insertLowPriority){
961
                                            finalPointDistance=distanceAddedPoint;
962
                                            mStructureAddedOrdered.geometry.flip();
963
                                            route.finalPoint=initialPoint;
964
                                            route.structures.add(mStructureAddedOrdered);
965
                                            route.lines.add(addedLine);
966
                                            lineAdded=true;
967
                                        }
968
                                    }
969
                                }
970
                            }
971
                        }
972
                        if (lineAdded){
973
                            i=0;
974
                        }else{
975
                            i++;
976
                        }
977
                    }
978
                }
979
            }
980

    
981
        }
982
        return routes;
983
    }
984

    
985
    private boolean isTriplePoint(List <MStructure> mList,Point point){
986
        List <Point> points=new ArrayList<Point>();
987
        for (MStructure structure:mList){
988
            points.addAll(extractPoints(structure.geometry));
989
        }
990

    
991
        int cont=0;
992
        for (int i=0;i<points.size();i++){
993
            if (points.get(i).equals(point)){
994
                cont++;
995
            }
996
            if (cont==3){
997
                return true;
998
            }
999
        }
1000
        return false;
1001
    }
1002

    
1003
    private Point extractFirstPoint(Geometry geometry){
1004
        Point firstPoint=null;
1005
        List<Line> lines= extractLines(geometry);
1006
        if (lines!=null && !lines.isEmpty()){
1007
            firstPoint=lines.get(0).getVertex(0);
1008
        }
1009
        return firstPoint;
1010
    }
1011

    
1012
    private List<Point> extractPoints(Geometry geometry){
1013
        List<Point> points=new ArrayList<Point>();
1014
        List<Line> lines=extractLines(geometry);
1015
        for (Line line: lines){
1016
            for (int i=0;i<line.getNumVertices();i++){
1017
                points.add(line.getVertex(i));
1018
            }
1019
        }
1020
        return points;
1021
    }
1022

    
1023
    private List<Line> extractLines(Geometry geometry){
1024
        List<Line> lines=new ArrayList<Line>();
1025
        if (geometry instanceof  Line){
1026
            lines.add((Line) geometry);
1027
        }
1028
        if (geometry instanceof MultiLine){
1029
            MultiLine multiline=(MultiLine)geometry;
1030
            for (int i=0;i<multiline.getPrimitivesNumber();i++){
1031
                lines.add((Line) multiline.getPrimitiveAt(i));
1032
            }
1033
        }
1034
        return lines;
1035
    }
1036

    
1037
    private boolean isAddedLine(List<Route> routes,Line line){
1038
        for (Route route:routes){
1039
            if (route.lines.contains(line)){
1040
                return true;
1041
            }
1042
        }
1043
        return false;
1044
    }
1045

    
1046
    private boolean isFlippedLine(Line line,Point origin) throws GeometryOperationNotSupportedException, GeometryOperationException{
1047
        Point initialPoint=line.getVertex(0);
1048
        Point finalPoint=line.getVertex(line.getNumVertices()-1);
1049
        Double distance1=origin.distance(initialPoint);
1050
        Double distance2=origin.distance(finalPoint);
1051
        if (distance1>distance2){
1052
            return true;
1053
        }else {
1054
            return false;
1055
        }
1056
    }
1057

    
1058

    
1059
//    private List<Point> getExtremePoints(List<MStructure> mList,Point origin){
1060
//        List<Point> pointsInExtremes=new ArrayList<Point>();
1061
//        for (MStructure mStructure: mList){
1062
//            Geometry geometry=mStructure.geometry;
1063
//            if (geometry instanceof Line){
1064
//                Line line=(Line)geometry;
1065
//                pointsInExtremes.add(line.getVertex(0));
1066
//                pointsInExtremes.add(line.getVertex(line.getNumVertices()-1));
1067
//            }
1068
//            if (geometry instanceof MultiLine){
1069
//                MultiLine multiline=(MultiLine)geometry;
1070
//                for (int i=0;i<multiline.getPrimitivesNumber();i++){
1071
//                    Line line=(Line)multiline.getPrimitiveAt(i);
1072
//                    pointsInExtremes.add(line.getVertex(0));
1073
//                    pointsInExtremes.add(line.getVertex(line.getNumVertices()-1));
1074
//                }
1075
//            }
1076
//
1077
//            PointToReferencePointComparator pointComparator= new PointToReferencePointComparator(origin);
1078
//            Collections.sort(pointsInExtremes, pointComparator);
1079
//
1080
//            List<Point> orderedExtremePoints=new ArrayList<Point>();
1081
//            while ( !pointsInExtremes.isEmpty() ){
1082
//                Point extremePoint=pointsInExtremes.get(0);
1083
//                if ( isLoopOrUnique(mList, extremePoint) ){
1084
//                    orderedExtremePoints.add(extremePoint);
1085
//                }
1086
//                while (pointsInExtremes.contains(extremePoint)){
1087
//                    pointsInExtremes.remove(extremePoint);
1088
//                }
1089
//            }
1090
//        }
1091
//
1092
//        return orderedExtremePoints;
1093
//    }
1094

    
1095
//    private boolean isLoopOrUnique(List<MStructure> mList, Point extremePoint){
1096
//        boolean repeated=false;
1097
//        boolean loop=false;
1098
//
1099
//        int i=0;
1100
//        boolean firstAparition=false;
1101
//        while( !repeated && !loop){
1102
//            if (geometry instanceof Line){
1103
//                Line line=(Line)geometry;
1104
//                pointsInExtremes.add(line.getVertex(0));
1105
//                pointsInExtremes.add(line.getVertex(line.getNumVertices()-1));
1106
//            }
1107
//            if (geometry instanceof MultiLine){
1108
//                MultiLine multiline=(MultiLine)geometry;
1109
//                for (int i=0;i<multiline.getPrimitivesNumber();i++){
1110
//                    Line line=(Line)multiline.getPrimitiveAt(i);
1111
//                    pointsInExtremes.add(line.getVertex(0));
1112
//                    pointsInExtremes.add(line.getVertex(line.getNumVertices()-1));
1113
//                }
1114
//            }
1115
//        }
1116
//
1117
//        return loop&&!repeated;
1118
//    }
1119

    
1120
    private Geometry applyOffset(Geometry geometry) {
1121
        double measureFactor = parameters.getMeasureFactor();
1122
        double measureOffset = parameters.getMeasureOffset();
1123
        if (geometry instanceof Line) {
1124
            Line line = (Line) geometry;
1125
            for (int i = 0; i < line.getNumVertices(); i++) {
1126
                Point mVertex = line.getVertex(i);
1127
                Double mValue =
1128
                    mVertex.getCoordinateAt(mVertex.getDimension() - 1);
1129
                Double newMValue = (mValue * measureFactor) + measureOffset;
1130
                mVertex.setCoordinateAt(mVertex.getDimension() - 1, newMValue);
1131
                line.setVertex(i, mVertex);
1132
            }
1133
        }
1134
        if (geometry instanceof MultiLine) {
1135
            MultiLine multiLine = (MultiLine) geometry;
1136
            for (int i = 0; i < multiLine.getPrimitivesNumber(); i++) {
1137
                Line line = (Line) multiLine.getPrimitiveAt(i);
1138
                for (int j = 0; j < line.getNumVertices(); j++) {
1139
                    Point mVertex = line.getVertex(j);
1140
                    Double mValue =
1141
                        mVertex.getCoordinateAt(mVertex.getDimension() - 1);
1142
                    Double newMValue = (mValue * measureFactor) + measureOffset;
1143
                    mVertex.setCoordinateAt(mVertex.getDimension() - 1,
1144
                        newMValue);
1145
                    line.setVertex(j, mVertex);
1146
                }
1147
            }
1148
        }
1149
        return geometry;
1150
    }
1151

    
1152

    
1153

    
1154
    private Map<Object, List<FeatureReference>> getGroupedReferences(
1155
        FeatureSelection selection,
1156
        final FeatureAttributeDescriptor idRouteField) throws BaseException {
1157
        final Map<Object, List<FeatureReference>> refs =
1158
            new HashMap<Object, List<FeatureReference>>();
1159
        selection.accept(new Visitor() {
1160

    
1161
            public void visit(Object obj)
1162
                throws VisitCanceledException, BaseException {
1163
                Feature feature = (Feature) obj;
1164
                Object id = feature.getFeature(idRouteField.getName());
1165
                FeatureReference reference = feature.getReference();
1166
                List<FeatureReference> references = refs.get(id);
1167
                if (references == null) {
1168
                    references = new ArrayList<FeatureReference>();
1169
                }
1170
                references.add(reference);
1171
                refs.put(id, references);
1172
            }
1173
        });
1174
        return refs;
1175
    }
1176

    
1177
    /**
1178
     * @param line
1179
     * @return lenght
1180
     * @throws GeometryOperationException
1181
     * @throws GeometryOperationNotSupportedException
1182
     */
1183
    private double getLineLength(Line line)
1184
        throws GeometryOperationNotSupportedException,
1185
        GeometryOperationException {
1186
        double lenght = 0;
1187
        Point previousVertex = null;
1188
        for (int i = 0; i < line.getNumVertices(); i++) {
1189
            Point vertex = line.getVertex(i);
1190
            if (previousVertex != null) {
1191
                lenght += previousVertex.distance(vertex);
1192
            }
1193
            previousVertex = vertex;
1194
        }
1195
        return lenght;
1196
    }
1197

    
1198
    private Double getGeometryLength(Geometry geometry) throws GeometryOperationNotSupportedException, GeometryOperationException{
1199
        return getGeometryLength(geometry, true);
1200
    }
1201

    
1202
    private Double getGeometryLength(Geometry geometry,
1203
        boolean ignoreSpatialGaps)
1204
            throws GeometryOperationNotSupportedException,
1205
            GeometryOperationException {
1206
        if (geometry instanceof Line) {
1207
            Line line = (Line) geometry;
1208
            return getLineLength(line);
1209
        }
1210
        if (geometry instanceof MultiLine) {
1211
            MultiLine multiLine = (MultiLine) geometry;
1212
            return getMultiLineLength(multiLine, ignoreSpatialGaps);
1213
        }
1214
        return Double.NaN;
1215
    }
1216

    
1217
    /**
1218
     * @param multiLine
1219
     * @return lenght
1220
     * @throws GeometryOperationException
1221
     * @throws GeometryOperationNotSupportedException
1222
     */
1223
    private double getMultiLineLength(MultiLine multiLine,
1224
        boolean ignoreSpatialGaps)
1225
            throws GeometryOperationNotSupportedException,
1226
            GeometryOperationException {
1227
        double lenght = 0;
1228
        Point previousVertex = null;
1229
        for (int j = 0; j < multiLine.getPrimitivesNumber(); j++) {
1230
            Line line = (Line) multiLine.getPrimitiveAt(j);
1231
            if (ignoreSpatialGaps) {
1232
                previousVertex = null;
1233
            }
1234
            for (int i = 0; i < line.getNumVertices(); i++) {
1235
                Point vertex = line.getVertex(i);
1236
                if (previousVertex != null) {
1237
                    lenght += previousVertex.distance(vertex);
1238
                }
1239
                previousVertex = vertex;
1240
            }
1241
        }
1242
        return lenght;
1243
    }
1244

    
1245
    /*
1246
     * (non-Javadoc)
1247
     *
1248
     * @see org.gvsig.lrs.lib.api.LrsAlgorithm#setParams(org.gvsig.lrs.lib.api.
1249
     * LrsAlgorithmParams)
1250
     */
1251
    public void setParams(LrsAlgorithmParams params)
1252
        throws IllegalArgumentException {
1253
        if (!(params instanceof LrsCreateRouteAlgorithmParams)) {
1254
            throw new IllegalArgumentException(
1255
                "params should be LrsCreateRouteAlgorithmParams type.");
1256
        }
1257
    }
1258

    
1259
    class MStructure {
1260

    
1261
        Geometry geometry;
1262
        Double fromField;
1263
        Double toField;
1264
        int id;
1265

    
1266
        protected MStructure clone(){
1267
            MStructure otherMStructure=new MStructure();
1268
            otherMStructure.geometry=geometry.cloneGeometry();
1269
            if (fromField==null){
1270
                otherMStructure.fromField=null;
1271
            }else{
1272
                otherMStructure.fromField=new Double(fromField);
1273
            }
1274
            if (toField==null){
1275
                otherMStructure.toField=null;
1276
            }else{
1277
                otherMStructure.toField=new Double(toField);
1278
            }
1279

    
1280
            otherMStructure.id=id;
1281
            return otherMStructure;
1282
        }
1283
    }
1284

    
1285
    class Route{
1286
        public Route(){
1287
            structures=new ArrayList<MStructure>();
1288
            lines=new ArrayList<Line>();
1289
        }
1290
        List<MStructure> structures;
1291
        Point initialPoint;
1292
        Point finalPoint;
1293
        List<Line> lines;
1294
        Double distance;
1295
    }
1296

    
1297
    class PointToReferencePointComparator implements Comparator<Point>{
1298

    
1299
        private Point referencePoint;
1300

    
1301
        public PointToReferencePointComparator(Point referencePoint) {
1302
            this.referencePoint = referencePoint;
1303
        }
1304

    
1305
        public int compare(Point point1, Point point2) {
1306
            Double distance1;
1307
            try {
1308
                distance1 = point1.distance(referencePoint);
1309
            } catch (Exception e) {
1310
                distance1 = Double.MAX_VALUE;
1311
            }
1312
            Double distance2;
1313
            try {
1314
                distance2 = point2.distance(referencePoint);
1315
            } catch (Exception e) {
1316
                distance2 = Double.MAX_VALUE;
1317
            }
1318
            return distance1.compareTo(distance2);
1319
        }
1320
    }
1321

    
1322

    
1323

    
1324
//    class GeometryDistanceToPointComparator implements Comparator<MStructure> {
1325
//
1326
//        private Point referencePoint;
1327
//
1328
//        public GeometryDistanceToPointComparator(Point referencePoint) {
1329
//            this.referencePoint = referencePoint;
1330
//        }
1331
//
1332
//        public int compare(MStructure mStruct1, MStructure mStruct2) {
1333
//            Double distance1 = nearestPointDistance(mStruct1.geometry);
1334
//            Double distance2 = nearestPointDistance(mStruct2.geometry);
1335
//            return distance1.compareTo(distance2);
1336
//        }
1337
//
1338
//        private Double nearestPointDistance(Geometry geometry) {
1339
//            if (geometry instanceof Line) {
1340
//                return nearestPointDistanceToLine((Line) geometry);
1341
//            }
1342
//            if (geometry instanceof MultiLine) {
1343
//                MultiLine multiLine = (MultiLine) geometry;
1344
//                Line firstLine = (Line) multiLine.getPrimitiveAt(0);
1345
//                Line lastLine = (Line) multiLine
1346
//                    .getPrimitiveAt(multiLine.getPrimitivesNumber() - 1);
1347
//
1348
//                Double distanceFirstPoint;
1349
//                Double distanceLastPoint;
1350
//                try {
1351
//                    distanceFirstPoint =
1352
//                        referencePoint.distance(firstLine.getVertex(0));
1353
//                } catch (Exception e) {
1354
//                    distanceFirstPoint = Double.MAX_VALUE;
1355
//                }
1356
//                try {
1357
//                    distanceLastPoint = referencePoint.distance(
1358
//                        lastLine.getVertex(lastLine.getNumVertices() - 1));
1359
//                } catch (Exception e) {
1360
//                    distanceLastPoint = Double.MAX_VALUE;
1361
//                }
1362
//
1363
//                if (distanceFirstPoint < distanceLastPoint)
1364
//                    return distanceFirstPoint;
1365
//                else
1366
//                    return distanceLastPoint;
1367
//            }
1368
//            return Double.MAX_VALUE;
1369
//        }
1370
//
1371
//        private Double nearestPointDistanceToLine(Line line) {
1372
//            Double distanceFirstPoint;
1373
//            Double distanceLastPoint;
1374
//            try {
1375
//                distanceFirstPoint = referencePoint.distance(line.getVertex(0));
1376
//            } catch (Exception e) {
1377
//                distanceFirstPoint = Double.MAX_VALUE;
1378
//            }
1379
//            try {
1380
//                distanceLastPoint = referencePoint
1381
//                    .distance(line.getVertex(line.getNumVertices() - 1));
1382
//            } catch (Exception e) {
1383
//                distanceLastPoint = Double.MAX_VALUE;
1384
//            }
1385
//
1386
//            if (distanceFirstPoint <= distanceLastPoint)
1387
//                return distanceFirstPoint;
1388
//            else
1389
//                return distanceLastPoint;
1390
//        }
1391
//
1392
//    }
1393

    
1394
}