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 @ 17

History | View | Annotate | Download (48.3 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.awt.Dimension;
26
import java.awt.geom.Point2D;
27
import java.io.File;
28
import java.sql.Array;
29
import java.util.ArrayList;
30
import java.util.Arrays;
31
import java.util.Comparator;
32
import java.util.HashMap;
33
import java.util.Iterator;
34
import java.util.List;
35
import java.util.Map;
36
import java.util.Map.Entry;
37

    
38
import javax.xml.transform.Source;
39

    
40
import org.apache.commons.lang3.mutable.MutableDouble;
41
import org.gvsig.fmap.dal.DALLocator;
42
import org.gvsig.fmap.dal.DataManager;
43
import org.gvsig.fmap.dal.DataServerExplorer;
44
import org.gvsig.fmap.dal.DataServerExplorerParameters;
45
import org.gvsig.fmap.dal.DataStore;
46
import org.gvsig.fmap.dal.DataTypes;
47
import org.gvsig.fmap.dal.exception.DataException;
48
import org.gvsig.fmap.dal.feature.EditableFeature;
49
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
50
import org.gvsig.fmap.dal.feature.EditableFeatureType;
51
import org.gvsig.fmap.dal.feature.Feature;
52
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
53
import org.gvsig.fmap.dal.feature.FeatureReference;
54
import org.gvsig.fmap.dal.feature.FeatureSelection;
55
import org.gvsig.fmap.dal.feature.FeatureSet;
56
import org.gvsig.fmap.dal.feature.FeatureStore;
57
import org.gvsig.fmap.dal.feature.NewFeatureStoreParameters;
58
import org.gvsig.fmap.dal.store.shp.SHPNewStoreParameters;
59
import org.gvsig.fmap.geom.Geometry;
60
import org.gvsig.fmap.geom.Geometry.DIMENSIONS;
61
import org.gvsig.fmap.geom.GeometryException;
62
import org.gvsig.fmap.geom.GeometryLocator;
63
import org.gvsig.fmap.geom.GeometryManager;
64
import org.gvsig.fmap.geom.aggregate.MultiLine;
65
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
66
import org.gvsig.fmap.geom.exception.CreateGeometryException;
67
import org.gvsig.fmap.geom.operation.GeometryOperationException;
68
import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException;
69
import org.gvsig.fmap.geom.primitive.Envelope;
70
import org.gvsig.fmap.geom.primitive.Line;
71
import org.gvsig.fmap.geom.primitive.Point;
72
import org.gvsig.fmap.geom.type.GeometryType;
73
import org.gvsig.lrs.lib.api.LrsAlgorithm;
74
import org.gvsig.lrs.lib.api.LrsAlgorithmParams;
75
import org.gvsig.lrs.lib.api.LrsCoordinatesPriority;
76
import org.gvsig.lrs.lib.api.LrsCreateRouteAlgorithmParams;
77
import org.gvsig.lrs.lib.api.LrsSourceOfMeasures;
78
import org.gvsig.lrs.lib.api.exceptions.LrsCreateRouteException;
79
import org.gvsig.lrs.lib.api.exceptions.LrsException;
80
import org.gvsig.tools.ToolsLocator;
81
import org.gvsig.tools.dataTypes.DataType;
82
import org.gvsig.tools.exception.BaseException;
83
import org.gvsig.tools.i18n.I18nManager;
84
import org.gvsig.tools.service.Manager;
85
import org.gvsig.tools.task.SimpleTaskStatus;
86
import org.gvsig.tools.visitor.VisitCanceledException;
87
import org.gvsig.tools.visitor.Visitor;
88
import org.slf4j.Logger;
89
import org.slf4j.LoggerFactory;
90

    
91
/**
92
 * @author fdiaz
93
 *
94
 */
95
public class LrsCreateRouteAlgorithm implements LrsAlgorithm {
96

    
97
    private static final Logger logger = LoggerFactory.getLogger(LrsCreateRouteAlgorithm.class);
98

    
99
    private LrsCreateRouteAlgorithmParams parameters;
100

    
101

    
102
    /**
103
     *
104
     */
105
    public LrsCreateRouteAlgorithm(LrsCreateRouteAlgorithmParams parameters) {
106
        this.parameters = parameters;
107

    
108
    }
109

    
110
    /*
111
     * (non-Javadoc)
112
     *
113
     * @see org.gvsig.tools.service.Service#getManager()
114
     */
115
    public Manager getManager() {
116
        return null;
117
    }
118

    
119
    /*
120
     * (non-Javadoc)
121
     *
122
     * @see org.gvsig.lrs.lib.api.LrsAlgorithm#getParams()
123
     */
124
    public  LrsAlgorithmParams getParams() {
125
        return this.parameters;
126
    }
127

    
128
    /*
129
     * (non-Javadoc)
130
     * @see org.gvsig.lrs.lib.api.LrsAlgorithm#execute(org.gvsig.tools.task.SimpleTaskStatus)
131
     */
132
    public void execute(SimpleTaskStatus taskStatus) throws LrsException {
133
        NewFeatureStoreParameters newFeatureStoreParameters = parameters.getNewFeatureStoreParameters();
134
        FeatureStore sourceFeatureStore = parameters.getSourceFeatureStore();
135
        FeatureAttributeDescriptor idRouteField = parameters.getIdRouteField();
136
        //LrsCoordinatesPriority coordinatePriority = parameters.getCoordinatePriority();
137
        //LrsSourceOfMeasures sourceOfMeasures = parameters.getSourceOfMeasures();
138
        FeatureAttributeDescriptor fromMeasureField = parameters.getFromMeasureField();
139
        FeatureAttributeDescriptor toMeasureField = parameters.getToMeasureField();
140
        //double measureFactor = parameters.getMeasureFactor();
141
        //double measureOffset = parameters.getMeasureOffset();
142
        //boolean ignoreSpatialGaps = parameters.ignoreSpatialGaps();
143

    
144
        logger.info(parameters.toString());
145

    
146
        taskStatus.setTitle(parameters.getName());
147
        I18nManager i18nManager = ToolsLocator.getI18nManager();
148
        taskStatus.message(i18nManager.getTranslation("grouping_features"));
149

    
150
        try {
151
            final String routeFieldName=idRouteField.getName();
152
            final String fromFieldName;
153
            final DataType fromDataType;
154
            final DataType toDataType;
155
            if (fromMeasureField!=null){
156
                fromFieldName=fromMeasureField.getName();
157
                fromDataType=fromMeasureField.getDataType();
158
            }else{
159
                fromFieldName=null;
160
                fromDataType=null;
161
            }
162
            final String toFieldName;
163
            if (toMeasureField!=null){
164
                toFieldName=toMeasureField.getName();
165
                toDataType=toMeasureField.getDataType();
166
            }else{
167
                toFieldName=null;
168
                toDataType=null;
169
            }
170

    
171
            FeatureStore newFeatureStore=LrsAlgorithmUtils.createNewDataStore(newFeatureStoreParameters,idRouteField);
172

    
173
            FeatureSet sourceFeatures;
174
            if (sourceFeatureStore.getFeatureSelection().getSize()>0){
175
                sourceFeatures=sourceFeatureStore.getFeatureSelection();
176
            }else{
177
                sourceFeatures=sourceFeatureStore.getFeatureSet();
178
            }
179

    
180
            final Map<String,List<MStructure>> featuresMap=new HashMap<String, List<MStructure>>();
181
            sourceFeatures.accept(new Visitor() {
182

    
183
                public void visit(Object obj) throws VisitCanceledException, BaseException {
184
                    Feature feature=(Feature)obj;
185
                    String routeName=(String)feature.get(routeFieldName);
186
                    Geometry originalGeometry=feature.getDefaultGeometry();
187
                    Object objFrom=null;
188
                    Object objTo=null;
189
                    if (fromFieldName!=null){
190
                        objFrom=feature.get(fromFieldName);
191
                    }
192
                    if (toFieldName!=null){
193
                        objTo=feature.get(toFieldName);
194
                    }
195
                    if (!featuresMap.containsKey(routeName)){
196
                        featuresMap.put(routeName, new ArrayList<MStructure>());
197
                    }
198
                    List<MStructure> mList=featuresMap.get(routeName);
199
                    MStructure mStructure=new MStructure();
200
                    mStructure.geometry=originalGeometry;
201
                    mStructure.fromField=LrsAlgorithmUtils.getAsDouble(objFrom,fromDataType);
202
                    mStructure.toField=LrsAlgorithmUtils.getAsDouble(objTo,toDataType);
203
                    mList.add(mStructure);
204
                    featuresMap.put(routeName, mList);
205
                }
206
            });
207

    
208
            taskStatus.setRangeOfValues(0, featuresMap.size());
209
            int taskCount=0;
210

    
211
            newFeatureStore.edit(FeatureStore.MODE_FULLEDIT);
212

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

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

    
227
            for(Entry<String, List<MStructure>> entry : featuresMap.entrySet()) {
228
                String routeName = entry.getKey();
229
                List<MStructure> mList = entry.getValue();
230

    
231
                EditableFeature newFeature = newFeatureStore.createNewFeature(true);
232
                newFeature.set(routeFieldName, routeName);
233
                Geometry route = createGeometryRoute(mList);
234
                newFeature.setDefaultGeometry(route);
235

    
236

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

    
259
                //END of Test addition
260

    
261

    
262
                newFeatureStore.update(newFeature);
263

    
264
                taskCount++;
265
                taskStatus.setCurValue(taskCount);
266

    
267
            }
268
            logger.debug(resultDebug.toString());
269
            newFeatureStore.finishEditing();
270

    
271
        } catch (Exception e1) {
272
            taskStatus.abort();
273
            throw new LrsCreateRouteException("Error creating routes", e1);
274
        }
275

    
276

    
277
        taskStatus.terminate();
278

    
279

    
280
//        FeatureSelection selection;
281
//        try {
282
//            outputFeatureStore.edit(FeatureStore.MODE_FULLEDIT);
283
//            selection = sourceFeatureStore.getFeatureSelection();
284
//            if (selection == null || selection.isEmpty()) {
285
//                selection = sourceFeatureStore.createFeatureSelection();
286
//                selection.selectAll();
287
//            }
288
//            taskStatus.message("Grouping features");
289
//            Map<Object, List<FeatureReference>> groupedReferences = getGroupedReferences(selection, idRouteField);
290
//
291
//            taskStatus.message("Creating routes");
292
//
293
//            Set<Object> keys = groupedReferences.keySet();
294
//            taskStatus.setRangeOfValues(0, keys.size());
295
//            int i=0;
296
//            for (Iterator iterator = keys.iterator(); iterator.hasNext();) {
297
//                taskStatus.setCurValue(i++);
298
//                Object key = (Object) iterator.next();
299
//                EditableFeature newFeature = outputFeatureStore.createNewFeature(true);
300
//                newFeature.set(idRouteField.getName(), key);
301
//
302
//                List<FeatureReference> references = groupedReferences.get(key);
303
//                Geometry route = createRoute(references, coordinatePriority, sourceOfMeasures, fromMeasureField, toMeasureField, measureFactor, measureOffset, ignoreSpatialGaps);
304
//                route = calibrateRoute(route);
305
//                newFeature.setDefaultGeometry(route);
306
//                outputFeatureStore.update(newFeature);
307
//            }
308
//            outputFeatureStore.finishEditing();
309
//            taskStatus.terminate();
310
//
311
//        } catch (DataException e) {
312
//            // TODO Auto-generated catch block
313
//            e.printStackTrace();
314
//        } catch (BaseException e) {
315
//            // TODO Auto-generated catch block
316
//            e.printStackTrace();
317
//        }
318
    }
319

    
320
    private Geometry createGeometryRoute(List<MStructure> mList) throws CreateGeometryException, GeometryOperationNotSupportedException, GeometryOperationException {
321
        LrsSourceOfMeasures sourceOfMeasures =parameters.getSourceOfMeasures();
322
        Geometry geometryResult=null;
323
        switch (sourceOfMeasures) {
324
        case ONE_FIELD:
325
            geometryResult= calculateGeometryByOneField(mList);
326
            break;
327
        case TWO_FIELDS:
328
            geometryResult= calculateGeometryByTwoField(mList);
329
            break;
330
        case LENGTH:
331
        default:
332
            geometryResult= calculateGeometryByLength(mList);
333
            break;
334
        }
335
        geometryResult=applyOffset(geometryResult);
336
        return geometryResult;
337
    }
338

    
339
    private Geometry calculateGeometryByLength(List<MStructure> mList) throws CreateGeometryException, GeometryOperationNotSupportedException, GeometryOperationException{
340
        return null;
341
    }
342

    
343
    private Geometry calculateGeometryByOneField(List<MStructure> mList) throws CreateGeometryException, GeometryOperationNotSupportedException, GeometryOperationException {
344
        boolean ignoreSpatialGaps = parameters.ignoreSpatialGaps();
345
        GeometryManager geomanager= GeometryLocator.getGeometryManager();
346
        try {
347
            sortMList(mList);
348
        } catch (Exception e) {
349
            logger.warn("Geometries couldn't be ordered");
350
        }
351
        MultiLine mGeometry= (MultiLine)geomanager.create(Geometry.TYPES.MULTILINE, Geometry.SUBTYPES.GEOM2DM);
352
        MutableDouble lastMValue=new MutableDouble(0);
353
        Double gap=Double.valueOf(0);
354
        Point lastPoint=null;
355
        for (MStructure mStructure:mList){
356
            Geometry geometry=mStructure.geometry;
357
            if(!ignoreSpatialGaps){
358
                gap=calculateGap(lastPoint, geometry);
359
                lastMValue.add(gap);
360
            }
361
            Double fromDistance=lastMValue.getValue();
362
            lastMValue.add(mStructure.fromField);
363
            Double toDistance=lastMValue.getValue();
364

    
365
            if (geometry instanceof Line){
366
                Line line=(Line) geometry;
367
                Line lineM=lineToMLine(line, fromDistance, toDistance);
368
                mGeometry.addPrimitive(lineM);
369
                lastPoint=lineM.getVertex(lineM.getNumVertices()-1);
370
            }
371
            if (geometry instanceof MultiLine){
372
                MultiLine multiLine =(MultiLine) geometry;
373
                Line[] lines=multilineToMlines(multiLine, fromDistance, toDistance,ignoreSpatialGaps);
374
                for (Line lineM:lines){
375
                    mGeometry.addPrimitive(lineM);
376
                    lastPoint=lineM.getVertex(lineM.getNumVertices()-1);
377
                }
378
            }
379
        }
380
        return mGeometry;
381
    }
382

    
383
    private Double calculateGap(Point lastPoint, Geometry geometry) throws GeometryOperationNotSupportedException, GeometryOperationException{
384
        Double gap=new Double(0);
385
        if (geometry instanceof Line){
386
            Line line=(Line) geometry;
387
            if (lastPoint!=null){
388
                Point firstPoint=line.getVertex(0);
389
                gap=firstPoint.distance(lastPoint);
390
            }
391
        }
392
        if (geometry instanceof MultiLine){
393
            MultiLine multiLine =(MultiLine) geometry;
394
            if (lastPoint!=null){
395
                Line line=(Line) multiLine.getPrimitiveAt(0);
396
                Point firstPoint=line.getVertex(0);
397
                gap=firstPoint.distance(lastPoint);
398
            }
399
        }
400
        return gap;
401
    }
402

    
403
    private void sortMList(List<MStructure> mList) throws CreateEnvelopeException, GeometryOperationNotSupportedException, GeometryOperationException {
404
        LrsCoordinatesPriority coordinatePriority = parameters.getCoordinatePriority();
405
        GeometryManager geomanager= GeometryLocator.getGeometryManager();
406
        Envelope envelope = geomanager.createEnvelope(Geometry.SUBTYPES.GEOM2D);
407
        for (MStructure mStructure:mList){
408
            envelope.add(mStructure.geometry.getEnvelope());
409
        }
410
        Point origin=envelope.getLowerCorner();
411
        switch (coordinatePriority) {
412
        case DOWN_LEFT:
413
            break;
414
        case DOWN_RIGHT:
415
            Double maxX =envelope.getMaximum(DIMENSIONS.X);
416
            origin.setX(maxX);
417
            break;
418
        case UP_LEFT:
419
            Double maxY =envelope.getMaximum(DIMENSIONS.Y);
420
            origin.setY(maxY);
421
            break;
422
        case UP_RIGHT:
423
            origin=envelope.getUpperCorner();
424
            break;
425
        default:
426
            break;
427
        }
428
        GeometryDistanceToPointComparator comaparatorMList=new GeometryDistanceToPointComparator(origin);
429
        MStructure[] orderedMStruct=(MStructure[])mList.toArray();
430
        Arrays.sort(orderedMStruct, comaparatorMList);
431
        mList=new ArrayList<MStructure>(Arrays.asList(orderedMStruct));
432

    
433
        for (MStructure mStructure:mList){
434
            Geometry geometry=mStructure.geometry;
435
            if (geometry instanceof Line){
436
                Line line=(Line)geometry;
437
                Double firstPointDistance=origin.distance(line.getVertex(0));
438
                Double lastPointDistance=origin.distance(line.getVertex(line.getNumVertices()-1));
439
                if (lastPointDistance<firstPointDistance){
440
                    geometry.flip();
441
                }
442
            }
443
            if (geometry instanceof MultiLine){
444
                MultiLine multiLine=(MultiLine)geometry;
445
                Line firstLine=(Line)multiLine.getPrimitiveAt(0);
446
                Line lastLine=(Line)multiLine.getPrimitiveAt(multiLine.getPrimitivesNumber()-1);
447
                Double firstPointDistance=origin.distance(firstLine.getVertex(0));
448
                Double lastPointDistance=origin.distance(lastLine.getVertex(lastLine.getNumVertices()-1));
449
                if (lastPointDistance<firstPointDistance){
450
                    geometry.flip();
451
                }
452
            }
453
            mStructure.geometry=geometry;
454
        }
455
    }
456

    
457
    private Geometry applyOffset(Geometry geometry){
458
        double measureFactor = parameters.getMeasureFactor();
459
        double measureOffset = parameters.getMeasureOffset();
460
        if (geometry instanceof Line){
461
            Line line=(Line) geometry;
462
            for (int i=0;i<line.getNumVertices();i++){
463
                Point mVertex=line.getVertex(i);
464
                Double mValue=mVertex.getCoordinateAt(mVertex.getDimension()-1);
465
                Double newMValue=(mValue*measureFactor)+measureOffset;
466
                mVertex.setCoordinateAt(mVertex.getDimension()-1, newMValue);
467
                line.setVertex(i, mVertex);
468
            }
469
        }
470
        if (geometry instanceof MultiLine){
471
            MultiLine multiLine =(MultiLine) geometry;
472
            for (int i=0;i<multiLine.getPrimitivesNumber();i++){
473
                Line line=(Line) multiLine.getPrimitiveAt(i);
474
                for (int j=0;j<line.getNumVertices();j++){
475
                    Point mVertex=line.getVertex(j);
476
                    Double mValue=mVertex.getCoordinateAt(mVertex.getDimension()-1);
477
                    Double newMValue=(mValue*measureFactor)+measureOffset;
478
                    mVertex.setCoordinateAt(mVertex.getDimension()-1, newMValue);
479
                    line.setVertex(j, mVertex);
480
                }
481
            }
482
        }
483
        return geometry;
484
    }
485

    
486
    private Geometry calculateGeometryByTwoField(List<MStructure> mList) throws CreateGeometryException, GeometryOperationNotSupportedException, GeometryOperationException{
487
        GeometryManager geomanager= GeometryLocator.getGeometryManager();
488
        MultiLine mGeometry= (MultiLine)geomanager.create(Geometry.TYPES.MULTILINE, Geometry.SUBTYPES.GEOM2DM);
489
        for (MStructure mStructure:mList){
490
            Geometry geometry=mStructure.geometry;
491
            Double fromDistance=mStructure.fromField;
492
            Double toDistance=mStructure.toField;
493
            if (geometry instanceof Line){
494
                Line line=(Line) geometry;
495
                Line lineM=lineToMLine(line, fromDistance, toDistance);
496
                mGeometry.addPrimitive(lineM);
497
            }
498
            if (geometry instanceof MultiLine){
499
                MultiLine multiLine =(MultiLine) geometry;
500
                Line[] lines=multilineToMlines(multiLine, fromDistance, toDistance);
501
                for (Line lineM:lines){
502
                    mGeometry.addPrimitive(lineM);
503
                }
504
            }
505
        }
506

    
507
        return mGeometry;
508
    }
509
    private Line[] multilineToMlines(MultiLine multiLine,Double fromDistance, Double toDistance) throws GeometryOperationNotSupportedException, GeometryOperationException, CreateGeometryException{
510
        return multilineToMlines(multiLine,fromDistance, toDistance,true);
511
    }
512
    private Line[] multilineToMlines(MultiLine multiLine,Double fromDistance, Double toDistance,boolean ignoreSpatialGaps) throws GeometryOperationNotSupportedException, GeometryOperationException, CreateGeometryException{
513

    
514
        Line[] lines=new Line[multiLine.getPrimitivesNumber()];
515
        Double multiLineLength=getMultiLineLength(multiLine,ignoreSpatialGaps);
516
        Double mFirstPoint=fromDistance;
517
        Double mLastPoint=null;
518
        Double distance=Double.valueOf(0);
519
        Point lastPoint=null;
520
        for (int i=0;i<multiLine.getPrimitivesNumber();i++){
521

    
522
            Line line=(Line) multiLine.getPrimitiveAt(i);
523
            Double lineLength=getLineLength(line);
524
            Double gap=Double.valueOf(0);
525

    
526
            if (!ignoreSpatialGaps&&lastPoint!=null){
527
                Point firstPoint=line.getVertex(0);
528
                gap=firstPoint.distance(lastPoint);
529
                distance+=gap;
530
            }
531
            mFirstPoint=calculateM(toDistance,fromDistance, distance, multiLineLength);
532
            distance+=lineLength;
533
            mLastPoint=calculateM(toDistance,fromDistance, distance, multiLineLength);
534
            lines[i]=lineToMLine(line, mFirstPoint, mLastPoint);
535
            lastPoint=lines[i].getVertex(line.getNumVertices()-1);
536
        }
537
        return lines;
538
    }
539

    
540
    private Line lineToMLine(Line line,Double minMValue, Double maxMValue) throws CreateGeometryException, GeometryOperationNotSupportedException, GeometryOperationException{
541
        GeometryManager geomanager= GeometryLocator.getGeometryManager();
542
        Double lineLength=getLineLength(line);
543
        Line lineM=(Line)geomanager.create(Geometry.TYPES.LINE, Geometry.SUBTYPES.GEOM2DM);
544
        Double inLineDistance=Double.valueOf(0);
545
        for (int i=0;i<line.getNumVertices();i++){
546
            Point vertex=line.getVertex(i);
547
            Point mVertex=(Point)geomanager.create(Geometry.TYPES.POINT, Geometry.SUBTYPES.GEOM2DM);
548
            mVertex.setX(vertex.getX());
549
            mVertex.setY(vertex.getY());
550

    
551
            Double mValue;
552
            if (i==0)mValue=minMValue;
553
            else if (i==line.getNumVertices()-1) mValue=maxMValue;
554
            else{
555
                Point previousVertex=line.getVertex(i-1);
556
                inLineDistance+=vertex.distance(previousVertex);
557
                mValue=calculateM(maxMValue,minMValue, inLineDistance, lineLength);
558
            }
559

    
560
            mVertex.setCoordinateAt(mVertex.getDimension()-1, mValue);
561
            lineM.addVertex(mVertex);
562
        }
563
        return lineM;
564
    }
565

    
566
    private Double calculateM(Double maxValue, Double minValue, Double relativeDistance, Double totalLength){
567
        //mValue=((newMax-newMin)*(mCoordinate-oldMin)/(oldMax-oldMin))+newMin;
568
        if (totalLength.equals(Double.valueOf(0) )) return Double.POSITIVE_INFINITY;
569
        return ((maxValue-minValue)*(relativeDistance)/(totalLength))+minValue;
570
    }
571

    
572
//    private Line lineToMLine(Line line,Point previousVertex, MutableDouble distance) throws CreateGeometryException{
573
//        GeometryManager geomanager= GeometryLocator.getGeometryManager();
574
//        Line lineM=(Line)geomanager.create(Geometry.TYPES.LINE, Geometry.SUBTYPES.GEOM2DM);
575
//        for (int i=0;i<line.getNumVertices();i++){
576
//            Point vertex=line.getVertex(i);
577
//            Point mVertex=(Point)geomanager.create(Geometry.TYPES.POINT, Geometry.SUBTYPES.GEOM2DM);
578
//            mVertex.setX(vertex.getX());
579
//            mVertex.setY(vertex.getY());
580
//
581
//            if (previousVertex==null){
582
//                previousVertex=vertex;
583
//            }else{
584
//                try {
585
//                    distance.setValue(distance.getValue()+vertex.distance(previousVertex));
586
//                    previousVertex=vertex;
587
//                } catch (Exception e) {
588
//                    previousVertex=vertex;
589
//                    distance.setValue(Double.NaN);
590
//                }
591
//            }
592
//            mVertex.setCoordinateAt(mVertex.getDimension()-1, distance.getValue());
593
//            lineM.addVertex(mVertex);
594
//        }
595
//        return lineM;
596
//    }
597

    
598

    
599
    /**
600
     * @param route
601
     * @return
602
     */
603
    private Geometry calibrateRoute(Geometry route) {
604
        // TODO Auto-generated method stub
605
        return route;
606
    }
607

    
608
    private Map<Object, List<FeatureReference>> getGroupedReferences(FeatureSelection selection, final FeatureAttributeDescriptor idRouteField) throws BaseException {
609
        final Map<Object, List<FeatureReference>> refs = new HashMap<Object, List<FeatureReference>>();
610
        selection.accept(new Visitor() {
611

    
612
            public void visit(Object obj) throws VisitCanceledException, BaseException {
613
                Feature feature = (Feature) obj;
614
                Object id = feature.getFeature(idRouteField.getName());
615
                FeatureReference reference = feature.getReference();
616
                List<FeatureReference> references = refs.get(id);
617
                if (references == null) {
618
                    references = new ArrayList<FeatureReference>();
619
                }
620
                references.add(reference);
621
                refs.put(id, references);
622
            }
623
        });
624
        return refs;
625
    }
626

    
627
//    private MultiLine createRoute(List<FeatureReference> references, LrsCoordinatesPriority coordinatePriority, LrsSourceOfMeasures sourceOfMeasures, FeatureAttributeDescriptor fromMeasureField,FeatureAttributeDescriptor toMeasureField, double measureFactor, double measureOffset, boolean ignoreSpatialGaps) throws CreateGeometryException, DataException, CreateEnvelopeException, GeometryOperationNotSupportedException, GeometryOperationException{
628
//
629
//        Envelope envelope = getEnvelope(references);
630
//        Point p = getOriginPointAccordingPriorityCoordinates(envelope, coordinatePriority);
631
//        GeometryManager geometryManager = GeometryLocator.getGeometryManager();
632
//
633
//        //FIXME: cuando est? esto tendr? que ser GEOM2DM o incluso GEOM3DM
634
//        MultiLine route = geometryManager.createMultiLine(Geometry.SUBTYPES.GEOM2D);
635
//        double m = 0;
636
//        Point previousVertex = null;
637
//        List<FeatureReference> orderedReferences = getOrderedReferences(references, (Point)p.cloneGeometry());
638
//        for (Iterator iterator = orderedReferences.iterator(); iterator.hasNext();) {
639
//            FeatureReference featureReference = (FeatureReference) iterator.next();
640
//            Feature feature = featureReference.getFeature();
641
//            Geometry geometry = feature.getDefaultGeometry();
642
//            if (geometry instanceof Line) {
643
//                Line line = (Line) geometry;
644
//                Point firstVertex = line.getVertex(0);
645
//                Point lastVertex = line.getVertex(line.getNumVertices() - 1);
646
//                boolean ascendantOrder = isAscendantOrder(p, firstVertex, lastVertex);
647
//                //FIXME: cuando est? disponible esto deber? ser GEOM2DM (?o incluso GEOM3DM?)
648
//                Line tramo = geometryManager.createLine(Geometry.SUBTYPES.GEOM3D);
649
//                double lineLength = getLineLength(line);
650
//                for(int i=0; i<line.getNumVertices(); i++){
651
//                    Point vertex = getNextVertex(line, ascendantOrder, i);
652
//
653
//                    switch (sourceOfMeasures) {
654
//                    case ONE_FIELD:
655
//                        m = calculateMByOneField(m, previousVertex, i, vertex, feature.getDouble(fromMeasureField.getName()), lineLength, measureFactor, measureOffset, ignoreSpatialGaps);
656
//                        break;
657
//                    case TWO_FIELDS:
658
//                        m = calculateMByTwoField(m, previousVertex, i, vertex, feature.getDouble(fromMeasureField.getName()), feature.getDouble(toMeasureField.getName()), lineLength, measureFactor, measureOffset);
659
//                        break;
660
//                    case LENGTH:
661
//                    default:
662
//                        m = calculateMByLength(m, previousVertex, i, vertex, ignoreSpatialGaps, measureFactor, measureOffset);
663
//                        break;
664
//                    }
665
//                    // FIXME: cuando est? disponible esto deber? ser GEOM2DM (?o incluso GEOM3DM?)
666
//                    Point mvertex = geometryManager.createPoint(vertex.getX(), vertex.getY(), Geometry.SUBTYPES.GEOM3D);
667
//                    mvertex.setCoordinateAt(2, m);
668
//                    tramo.addVertex(mvertex);
669
//                    previousVertex = vertex;
670
//                    p = vertex;
671
//                }
672
//                route.addPrimitive(tramo);
673
//            } else if (geometry instanceof MultiLine) {
674
//                MultiLine multiLine = (MultiLine)geometry;
675
//                double multiLineLength = getMultiLineLength(multiLine);
676
//                MultiLine orderedMultiLine = getOrderedMultiLine(multiLine, previousVertex, coordinatePriority);
677
//                for (int j = 0; j < orderedMultiLine.getPrimitivesNumber(); j++) {
678
//                    Line line = (Line) orderedMultiLine.getPrimitiveAt(j);
679
//                    Point firstVertex = line.getVertex(0);
680
//                    Point lastVertex = line.getVertex(line.getNumVertices() - 1);
681
//                    boolean ascendantOrder = isAscendantOrder(p, firstVertex, lastVertex);
682
//                    //FIXME: cuando est? disponible esto deber? ser GEOM2DM (?o incluso GEOM3DM?)
683
//                    Line tramo = geometryManager.createLine(Geometry.SUBTYPES.GEOM3D);
684
//                    for(int i=0; i<line.getNumVertices(); i++){
685
//                        Point vertex = getNextVertex(line, ascendantOrder, i);
686
//                        switch (sourceOfMeasures) {
687
//                        case ONE_FIELD:
688
//                            m = calculateMByOneField(m, previousVertex, i, vertex, feature.getDouble(toMeasureField.getName()), multiLineLength, multiLineLength, multiLineLength, ascendantOrder);
689
//                            break;
690
//                        case TWO_FIELDS:
691
//                            //Este caso tal vez no se d? nunca, pero por si acaso
692
//                            m = calculateMByTwoField(m, previousVertex, i, vertex, feature.getDouble(fromMeasureField.getName()), feature.getDouble(toMeasureField.getName()), multiLineLength, measureFactor, measureOffset);
693
//                            break;
694
//                        case LENGTH:
695
//                        default:
696
//                            m = calculateMByLength(m, previousVertex, i, vertex, ignoreSpatialGaps, measureFactor, measureOffset);
697
//                            break;
698
//                        }
699
//
700
//                        // FIXME: cuando est? disponible esto deber? ser GEOM2DM (?o incluso GEOM3DM?)
701
//                        Point mvertex = geometryManager.createPoint(vertex.getX(), vertex.getY(), Geometry.SUBTYPES.GEOM3D);
702
//                        mvertex.setCoordinateAt(2, m);
703
//                        tramo.addVertex(mvertex);
704
//                        previousVertex = vertex;
705
//                        p = vertex;
706
//                    }
707
//                    route.addPrimitive(tramo);
708
//                }
709
//            }
710
//        }
711
//
712
//        return route;
713
//    }
714

    
715
    /**
716
     * @param multiLine
717
     * @param previousVertex
718
     * @param coordinatePriority2
719
     * @return
720
     * @throws CreateGeometryException
721
     * @throws GeometryOperationException
722
     * @throws GeometryOperationNotSupportedException
723
     */
724
    private MultiLine getOrderedMultiLine(MultiLine multiLine, Point previousVertex, LrsCoordinatesPriority coordinatePriority) throws CreateGeometryException, GeometryOperationNotSupportedException, GeometryOperationException {
725
        GeometryManager geometryManager = GeometryLocator.getGeometryManager();
726
        MultiLine orderedMultiLine = geometryManager.createMultiLine(multiLine.getGeometryType().getSubType());
727
        Point p = null;
728
        if(previousVertex!=null){
729
            previousVertex.cloneGeometry();
730
        } else {
731
            Envelope envelope = multiLine.getEnvelope();
732
            p = getOriginPointAccordingPriorityCoordinates(envelope, coordinatePriority);
733
        }
734

    
735
        Point newPoint = (Point) p.cloneGeometry();
736
        Integer nearestPrimitive = null;
737
        double nearestDistance = Double.POSITIVE_INFINITY;
738
        List<Integer> addedPrimitives = new ArrayList<Integer>();
739
        boolean changed = true;
740
        while (changed) {
741
            changed = false;
742
            nearestDistance = Double.POSITIVE_INFINITY;
743

    
744
            for (int i = 0; i < multiLine.getPrimitivesNumber(); i++) {
745
                if(!addedPrimitives.contains(i)){
746
                    Line line = (Line)multiLine.getPrimitiveAt(i);
747
                    Point firstVertex = line.getVertex(0);
748
                    Point lastVertex = line.getVertex(line.getNumVertices() - 1);
749
                    double distanceFirstVertex = p.distance(firstVertex);
750
                    double distanceLastVertex = p.distance(lastVertex);
751
                    double distance = Math.min(distanceFirstVertex, distanceLastVertex);
752
                    if (distance < nearestDistance) {
753
                        if(distanceFirstVertex<distanceLastVertex){
754
                            newPoint = lastVertex;
755
                        } else {
756

    
757
                        }
758
                        nearestPrimitive = i;
759
                        nearestDistance = distance;
760
                        changed = true;
761
                    }
762

    
763
                }
764
            }
765
            if (changed) {
766
                addedPrimitives.add(nearestPrimitive);
767
                p = (Point) newPoint.cloneGeometry();
768
            }
769
        }
770
        p = (Point) previousVertex.cloneGeometry();
771
        for (Iterator iterator = addedPrimitives.iterator(); iterator.hasNext();) {
772
            Integer integer = (Integer) iterator.next();
773
            Line line = (Line)multiLine.getPrimitiveAt(integer);
774
            Line auxLine;
775
            if(isAscendantOrder(p, line.getVertex(0), line.getVertex(line.getNumVertices()-1))){
776
                auxLine = (Line) line.cloneGeometry();
777
            } else {
778
                auxLine = geometryManager.createLine(line.getGeometryType().getSubType());
779
                for (int i = line.getNumVertices(); i >=0 ; --i) {
780
                    auxLine.addVertex(line.getVertex(i));
781
                }
782
            }
783
            orderedMultiLine.addPrimitive(auxLine);
784
        }
785
        return orderedMultiLine;
786
    }
787

    
788
    private Point getOriginPointAccordingPriorityCoordinates(Envelope envelope, LrsCoordinatesPriority coordinatePriority) throws CreateGeometryException {
789
        GeometryManager geometryManager = GeometryLocator.getGeometryManager();
790
        Point p;
791
        switch (coordinatePriority) {
792
        case DOWN_LEFT:
793
            p = geometryManager.createPoint(envelope.getMinimum(0), envelope.getMaximum(1), Geometry.SUBTYPES.GEOM2D);
794
            break;
795
        case UP_RIGHT:
796
            p = geometryManager.createPoint(envelope.getMinimum(0), envelope.getMinimum(1), Geometry.SUBTYPES.GEOM2D);
797
            break;
798
        case DOWN_RIGHT:
799
            p = geometryManager.createPoint(envelope.getMaximum(0), envelope.getMaximum(1), Geometry.SUBTYPES.GEOM2D);
800
            break;
801
        case UP_LEFT:
802
        default:
803
            p = geometryManager.createPoint(envelope.getMaximum(0), envelope.getMinimum(1), Geometry.SUBTYPES.GEOM2D);
804
            break;
805
        }
806
        return p;
807
    }
808

    
809
    /**
810
     * @param line
811
     * @return lenght
812
     * @throws GeometryOperationException
813
     * @throws GeometryOperationNotSupportedException
814
     */
815
    private double getLineLength(Line line) throws GeometryOperationNotSupportedException, GeometryOperationException {
816
        double lenght = 0;
817
        Point previousVertex = null;
818
        for(int i=0; i<line.getNumVertices(); i++){
819
            Point vertex = line.getVertex(i);
820
            if(previousVertex!=null){
821
                lenght+=previousVertex.distance(vertex);
822
            }
823
            previousVertex = vertex;
824
        }
825
        return lenght;
826
    }
827

    
828
    /**
829
     * @param multiLine
830
     * @return lenght
831
     * @throws GeometryOperationException
832
     * @throws GeometryOperationNotSupportedException
833
     */
834
    private double getMultiLineLength(MultiLine multiLine,boolean ignoreSpatialGaps) throws GeometryOperationNotSupportedException, GeometryOperationException{
835
        double lenght = 0;
836
        Point previousVertex = null;
837
        for (int j = 0; j < multiLine.getPrimitivesNumber(); j++) {
838
            Line line = (Line) multiLine.getPrimitiveAt(j);
839
            if (ignoreSpatialGaps){
840
                previousVertex = null;
841
            }
842
            for(int i=0; i<line.getNumVertices(); i++){
843
                Point vertex = line.getVertex(i);
844
                if(previousVertex!=null){
845
                    lenght+=previousVertex.distance(vertex);
846
                }
847
                previousVertex = vertex;
848
            }
849
        }
850
        return lenght;
851
    }
852

    
853
    private double calculateM(double m, Point previousVertex, int i, Point vertex, Double from, Double to, boolean ignoreSpatialGaps, double measureFactor, double measureOffset)
854
        throws GeometryOperationNotSupportedException, GeometryOperationException {
855
        if (i == 0) {
856
            if (previousVertex != null && !ignoreSpatialGaps) {
857
                m += (previousVertex.distance(vertex)*measureFactor)+measureOffset;
858
            }
859
        } else {
860
            if(previousVertex!=null){
861
                m += (previousVertex.distance(vertex)*measureFactor)+measureOffset;
862
            }
863
        }
864
        return m;
865
    }
866

    
867
    private double calculateMByLength(double m, Point previousVertex, int i, Point vertex, boolean ignoreSpatialGaps, double measureFactor, double measureOffset)
868
        throws GeometryOperationNotSupportedException, GeometryOperationException {
869
        if (i == 0) {
870
            if (previousVertex != null && !ignoreSpatialGaps) {
871
                m += (previousVertex.distance(vertex)*measureFactor)+measureOffset;
872
            }
873
        } else {
874
            if(previousVertex!=null){
875
                m += (previousVertex.distance(vertex)*measureFactor)+measureOffset;
876
            }
877
        }
878
        return m;
879
    }
880

    
881
    private double calculateMByOneField(double m, Point previousVertex, int i, Point vertex, Double length, double totalGeometricLength, double measureFactor, double measureOffset, boolean ignoreSpatialGaps)
882
        throws GeometryOperationNotSupportedException, GeometryOperationException {
883
        if (i == 0) {
884
            if (previousVertex != null && !ignoreSpatialGaps) {
885
                m += (previousVertex.distance(vertex)*length/totalGeometricLength*measureFactor)+measureOffset;
886
            }
887
        } else {
888
            if(previousVertex!=null){
889
                m += (previousVertex.distance(vertex)*length/totalGeometricLength*measureFactor)+measureOffset;
890
            }
891
        }
892
        return m;
893
    }
894

    
895
    private double calculateMByTwoField(double m, Point previousVertex, int i, Point vertex, Double from, Double to, double totalGeometricLength, double measureFactor, double measureOffset)
896
        throws GeometryOperationNotSupportedException, GeometryOperationException {
897
        if (i == 0) {
898
            m = from;
899
        } else {
900
            if(previousVertex!=null){
901
                m += (previousVertex.distance(vertex)*(to-from)/totalGeometricLength*measureFactor)+measureOffset;
902
            }
903
        }
904
        return m;
905
    }
906

    
907
    private Point getNextVertex(Line line, boolean ascendantOrder, int i) {
908
        Point vertex = null;
909
        if(ascendantOrder){
910
            vertex = line.getVertex(i);
911
        } else {
912
            vertex = line.getVertex(line.getNumVertices()-i);
913
        }
914
        return vertex;
915
    }
916

    
917
    private boolean isAscendantOrder(Point p, Point firstVertex, Point lastVertex)
918
        throws GeometryOperationNotSupportedException, GeometryOperationException {
919
        double distanceFirstVertex = p.distance(firstVertex);
920
        double distanceLastVertex = p.distance(lastVertex);
921
        boolean ascendantOrder = (distanceFirstVertex<=distanceLastVertex);
922
        return ascendantOrder;
923
    }
924

    
925
    private List<FeatureReference> getOrderedReferences(List<FeatureReference> references, Point point)
926
        throws CreateEnvelopeException, DataException, CreateGeometryException, GeometryOperationNotSupportedException,
927
        GeometryOperationException {
928

    
929
        Point p = (Point) point.cloneGeometry();
930
        List<FeatureReference> orderedReferences = new ArrayList<FeatureReference>();
931

    
932
        FeatureReference nearestFeatureReference = null;
933
        double nearestDistance = Double.POSITIVE_INFINITY;
934
        boolean changed = true;
935
        Point newPoint = (Point) p.cloneGeometry();
936

    
937
        while (changed) {
938
            changed = false;
939
            nearestDistance = Double.POSITIVE_INFINITY;
940
            for (Iterator iterator = references.iterator(); iterator.hasNext();) {
941
                FeatureReference featureReference = (FeatureReference) iterator.next();
942
                if (!orderedReferences.contains(featureReference)) {
943
                    Geometry geometry = featureReference.getFeature().getDefaultGeometry();
944
                    if (geometry instanceof Line) {
945
                        Line line = (Line) geometry;
946
                        Point firstVertex = line.getVertex(0);
947
                        Point lastVertex = line.getVertex(line.getNumVertices() - 1);
948
                        double distanceFirstVertex = p.distance(firstVertex);
949
                        double distanceLastVertex = p.distance(lastVertex);
950
                        double distance = Math.min(distanceFirstVertex, distanceLastVertex);
951
                        if (distance < nearestDistance) {
952
                            if(distanceFirstVertex<distanceLastVertex){
953
                                newPoint = lastVertex;
954
                            }
955
                            nearestFeatureReference = featureReference;
956
                            nearestDistance = distance;
957
                            changed = true;
958
                        }
959
                    } else if (geometry instanceof MultiLine) {
960
                        MultiLine multiLine = (MultiLine) geometry;
961
                        for(int i=0; i<multiLine.getPrimitivesNumber(); i++){
962
                            Line line = (Line)multiLine.getPrimitiveAt(i);
963
                            Point firstVertex = line.getVertex(0);
964
                            Point lastVertex = line.getVertex(line.getNumVertices() - 1);
965
                            double distanceFirstVertex = p.distance(firstVertex);
966
                            double distanceLastVertex = p.distance(lastVertex);
967
                            double distance = Math.min(distanceFirstVertex, distanceLastVertex);
968
                            if (distance < nearestDistance) {
969
                                if(distanceFirstVertex<distanceLastVertex){
970
                                    newPoint = lastVertex;
971
                                }
972
                                nearestFeatureReference = featureReference;
973
                                nearestDistance = distance;
974
                                changed = true;
975
                                break;
976
                            }
977
                        }
978
                    }
979
                }
980
            }
981
            if (changed) {
982
                orderedReferences.add(nearestFeatureReference);
983
                p = (Point) newPoint.cloneGeometry();
984
            }
985
        }
986
        return orderedReferences;
987
    }
988

    
989
    private Envelope getEnvelope(List<FeatureReference> references) throws CreateEnvelopeException, DataException{
990
        GeometryManager geometryManager = GeometryLocator.getGeometryManager();
991
        Envelope envelope = geometryManager.createEnvelope(Geometry.SUBTYPES.GEOM2D);
992
        for (Iterator iterator = references.iterator(); iterator.hasNext();) {
993
            FeatureReference featureReference = (FeatureReference) iterator.next();
994
            Geometry geometry = featureReference.getFeature().getDefaultGeometry();
995
            envelope.add(geometry.getEnvelope());
996
        }
997
        return envelope;
998
    }
999

    
1000
    /* (non-Javadoc)
1001
     * @see org.gvsig.lrs.lib.api.LrsAlgorithm#setParams(org.gvsig.lrs.lib.api.LrsAlgorithmParams)
1002
     */
1003
    public void setParams(LrsAlgorithmParams params) throws IllegalArgumentException {
1004
        if(!(params instanceof LrsCreateRouteAlgorithmParams)){
1005
            throw new IllegalArgumentException("params should be LrsCreateRouteAlgorithmParams type.");
1006
        }
1007
        // TODO Auto-generated method stub
1008

    
1009
    }
1010

    
1011
    class MStructure implements Comparable<MStructure>{
1012
        Geometry geometry;
1013
        Double fromField;
1014
        Double toField;
1015

    
1016
        public int compareTo(MStructure o) {
1017
            // TODO Auto-generated method stub
1018
            return 0;
1019
        }
1020
    }
1021

    
1022

    
1023
    class GeometryDistanceToPointComparator implements Comparator<MStructure> {
1024

    
1025
        private Point referencePoint;
1026

    
1027
        public GeometryDistanceToPointComparator(Point referencePoint) {
1028
            this.referencePoint = referencePoint;
1029
        }
1030

    
1031
        public int compare(MStructure mStruct1, MStructure mStruct2) {
1032
            Double distance1=nearestPointDistance(mStruct1.geometry);
1033
            Double distance2=nearestPointDistance(mStruct2.geometry);
1034
            return distance1.compareTo(distance2);
1035
        }
1036

    
1037
        private Double nearestPointDistance(Geometry geometry){
1038
            if (geometry instanceof Line){
1039
                return nearestPointDistanceToLine((Line)geometry);
1040
            }
1041
            if (geometry instanceof MultiLine){
1042
                MultiLine multiLine=(MultiLine)geometry;
1043
                Line firstLine=(Line)multiLine.getPrimitiveAt(0);
1044
                Line lastLine=(Line)multiLine.getPrimitiveAt(multiLine.getPrimitivesNumber()-1);
1045

    
1046
                Double distanceFirstPoint;
1047
                Double distanceLastPoint;
1048
                try {
1049
                    distanceFirstPoint = referencePoint.distance(firstLine.getVertex(0));
1050
                } catch (Exception e) {
1051
                    distanceFirstPoint=Double.MAX_VALUE;
1052
                }
1053
                try {
1054
                    distanceLastPoint=referencePoint.distance(lastLine.getVertex(lastLine.getNumVertices()-1));
1055
                } catch (Exception e) {
1056
                    distanceLastPoint=Double.MAX_VALUE;
1057
                }
1058

    
1059
                if (distanceFirstPoint<distanceLastPoint) return distanceFirstPoint;
1060
                else return distanceLastPoint;
1061
            }
1062
            return Double.MAX_VALUE;
1063
        }
1064

    
1065
        private Double nearestPointDistanceToLine(Line line){
1066
            Double distanceFirstPoint;
1067
            Double distanceLastPoint;
1068
            try {
1069
                distanceFirstPoint = referencePoint.distance(line.getVertex(0));
1070
            } catch (Exception e) {
1071
                distanceFirstPoint=Double.MAX_VALUE;
1072
            }
1073
            try {
1074
                distanceLastPoint=referencePoint.distance(line.getVertex(line.getNumVertices()-1));
1075
            } catch (Exception e) {
1076
                distanceLastPoint=Double.MAX_VALUE;
1077
            }
1078

    
1079
            if (distanceFirstPoint<distanceLastPoint) return distanceFirstPoint;
1080
            else return distanceLastPoint;
1081
        }
1082

    
1083
    }
1084

    
1085
}
1086

    
1087

    
1088

    
1089