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 / LrsCalibrateRouteAlgorithm.java @ 53

History | View | Annotate | Download (34.6 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.HashMap;
27
import java.util.List;
28
import java.util.Map;
29
import java.util.Map.Entry;
30

    
31
import org.cresques.cts.IProjection;
32
import org.gvsig.fmap.dal.feature.EditableFeature;
33
import org.gvsig.fmap.dal.feature.Feature;
34
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
35
import org.gvsig.fmap.dal.feature.FeatureSet;
36
import org.gvsig.fmap.dal.feature.FeatureStore;
37
import org.gvsig.fmap.dal.feature.NewFeatureStoreParameters;
38
import org.gvsig.fmap.geom.Geometry;
39
import org.gvsig.fmap.geom.GeometryLocator;
40
import org.gvsig.fmap.geom.GeometryManager;
41
import org.gvsig.fmap.geom.exception.CreateGeometryException;
42
import org.gvsig.fmap.geom.operation.GeometryOperationException;
43
import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException;
44
import org.gvsig.fmap.geom.primitive.Line;
45
import org.gvsig.fmap.geom.primitive.Point;
46
import org.gvsig.lrs.lib.api.DistanceUnits;
47
import org.gvsig.lrs.lib.api.LrsAlgorithm;
48
import org.gvsig.lrs.lib.api.LrsAlgorithmParams;
49
import org.gvsig.lrs.lib.api.LrsCalibrateRouteAlgorithmParams;
50
import org.gvsig.lrs.lib.api.LrsCreateRouteAlgorithmParams;
51
import org.gvsig.lrs.lib.api.LrsMeasureCalculationMethods;
52
import org.gvsig.lrs.lib.api.exceptions.LrsCalibrateRouteException;
53
import org.gvsig.lrs.lib.api.exceptions.LrsException;
54
import org.gvsig.tools.ToolsLocator;
55
import org.gvsig.tools.exception.BaseException;
56
import org.gvsig.tools.i18n.I18nManager;
57
import org.gvsig.tools.service.Manager;
58
import org.gvsig.tools.task.SimpleTaskStatus;
59
import org.gvsig.tools.visitor.VisitCanceledException;
60
import org.gvsig.tools.visitor.Visitor;
61
import org.slf4j.Logger;
62
import org.slf4j.LoggerFactory;
63

    
64
/**
65
 * @author dmartinez
66
 *
67
 */
68
public class LrsCalibrateRouteAlgorithm implements LrsAlgorithm {
69

    
70
    private static final Logger logger = LoggerFactory.getLogger(LrsCalibrateRouteAlgorithm.class);
71

    
72
    private LrsCalibrateRouteAlgorithmParams parameters;
73

    
74
    /**
75
     *
76
     */
77
    public LrsCalibrateRouteAlgorithm(LrsCalibrateRouteAlgorithmParams parameters) {
78
        this.parameters = parameters;
79

    
80
    }
81

    
82
    /*
83
     * (non-Javadoc)
84
     *
85
     * @see org.gvsig.tools.service.Service#getManager()
86
     */
87
    public Manager getManager() {
88
        return null;
89
    }
90

    
91
    /*
92
     * (non-Javadoc)
93
     *
94
     * @see org.gvsig.lrs.lib.api.LrsAlgorithm#getParams()
95
     */
96
    public  LrsAlgorithmParams getParams() {
97
        return this.parameters;
98
    }
99

    
100
    /* (non-Javadoc)
101
     * @see org.gvsig.lrs.lib.api.LrsAlgorithm#setParams(org.gvsig.lrs.lib.api.LrsAlgorithmParams)
102
     */
103
    public void setParams(LrsAlgorithmParams params) throws IllegalArgumentException {
104
        if(!(params instanceof LrsCreateRouteAlgorithmParams)){
105
            throw new IllegalArgumentException("params should be LrsCalibrateRouteAlgorithmParams type.");
106
        }
107
        // TODO Auto-generated method stub
108
    }
109

    
110
    /*
111
     * (non-Javadoc)
112
     * @see org.gvsig.lrs.lib.api.LrsAlgorithm#execute(org.gvsig.tools.task.SimpleTaskStatus)
113
     */
114
    public void execute(final SimpleTaskStatus taskStatus) throws LrsException {
115
        NewFeatureStoreParameters newFeatureStoreParameters =
116
            parameters.getNewFeatureStoreParameters();
117
        FeatureStore sourceFeatureStore = parameters.getSourceFeatureStore();
118
        FeatureAttributeDescriptor idRouteField = parameters.getIdRouteField();
119
        FeatureStore calibratePointFeatureStore= parameters.getCalibratePointFeatureStore();
120
        FeatureAttributeDescriptor idRouteCalibratePointField =parameters.getCalibratePointIdRouteField();
121
        FeatureAttributeDescriptor fromMeasureField = parameters.getFromMeasureField();
122
        final boolean includeAll=parameters.includeAll();
123

    
124
        logger.info(parameters.toString());
125

    
126
        taskStatus.setTitle(parameters.getName());
127
        I18nManager i18nManager = ToolsLocator.getI18nManager();
128
        taskStatus.message(i18nManager.getTranslation("grouping_features"));
129

    
130
        try {
131
            final String routeFieldName = idRouteField.getName();
132
            final String routeCalibratePointFieldName=idRouteCalibratePointField.getName();
133
            final String measureFieldName=fromMeasureField.getName();
134
            final Double convertedSearchRadius=calculateConvertedSearchRadius();
135

    
136
            FeatureStore newFeatureStore = LrsAlgorithmUtils
137
                .createNewDataStore(newFeatureStoreParameters, idRouteField);
138

    
139
            FeatureSet sourceFeatures;
140
            if (sourceFeatureStore.getFeatureSelection().getSize() > 0) {
141
                sourceFeatures = sourceFeatureStore.getFeatureSelection();
142
            } else {
143
                sourceFeatures = sourceFeatureStore.getFeatureSet();
144
            }
145

    
146
            final Map<String, Object[]> featuresMap =
147
                new HashMap<String, Object[]>();
148
            sourceFeatures.accept(new Visitor() {
149

    
150
                public void visit(Object obj)
151
                    throws VisitCanceledException, BaseException {
152
                    Feature feature = (Feature) obj;
153
                    String routeName = (String) feature.get(routeFieldName);
154
                    List<Point> points = new ArrayList<Point>();
155
                    Object[] valueObject=new Object[2];
156
                    valueObject[0]=feature.getDefaultGeometry();
157
                    valueObject[1]=points;
158

    
159
                    featuresMap.put(routeName, valueObject);
160
                }
161
            });
162

    
163
            FeatureSet pointFeatures=calibratePointFeatureStore.getFeatureSet();
164
            pointFeatures.accept(new Visitor() {
165

    
166
                public void visit(Object obj) throws VisitCanceledException, BaseException {
167
                    Feature feature = (Feature) obj;
168
                    String routeName = (String) feature.get(routeCalibratePointFieldName);
169
                    Double measure= (Double) feature.get(measureFieldName);
170
                    Geometry geomPoint=(Point)feature.getDefaultGeometry();
171

    
172
                    if (geomPoint instanceof Point){
173
                        Point point=(Point) geomPoint;
174
                        Object valueObject=featuresMap.get(routeName);
175
                        if (valueObject!=null && valueObject instanceof Object[]){
176
                            Object[] objArray=(Object[])valueObject;
177
                            if (objArray[1] instanceof List){
178
                                List<Point> points=(List<Point>)objArray[1];
179
                                if (feature.getDefaultGeometry() instanceof Point){
180
                                    Geometry geometry=(Geometry)objArray[0];
181
                                    if (isValidPoint(point,geometry, convertedSearchRadius)){
182
                                        try {
183
                                            Point mPoint= pointToMPoint(geometry,point, measure);
184
                                            points.add(mPoint);
185
                                        } catch (Exception e) {
186
                                            logger.debug("Error adding point",e);
187
                                        }
188
                                    }
189
                                }
190
                            }
191
                        }
192
                    }
193
                }
194
            });
195

    
196
            taskStatus.setRangeOfValues(0, featuresMap.size());
197
            int taskCount = 0;
198

    
199
            newFeatureStore.edit(FeatureStore.MODE_FULLEDIT);
200

    
201
            for (Entry<String, Object[]> entry : featuresMap
202
                .entrySet()) {
203
                String routeName = entry.getKey();
204
                Object valueObject = entry.getValue();
205
                List<Point> points=null;
206
                Geometry geometry=null;
207

    
208
                if (valueObject!=null && valueObject instanceof Object[]){
209
                    Object[] objArray=(Object[])valueObject;
210
                    if (objArray[0] instanceof Geometry){
211
                        geometry=(Geometry)objArray[0];
212
                    }
213
                    if (objArray[1] instanceof List){
214
                        points=(List<Point>)objArray[1];
215
                    }
216
                }
217
                if (!points.isEmpty()){
218
                    EditableFeature newFeature =
219
                        newFeatureStore.createNewFeature(true);
220
                    newFeature.set(routeFieldName, routeName);
221
                    Geometry calibratedRoute = calibrateRoute(geometry,points);
222
                    newFeature.setDefaultGeometry(calibratedRoute);
223
                    newFeatureStore.update(newFeature);
224
                }else{
225
                    if (includeAll){
226
                        EditableFeature newFeature =
227
                            newFeatureStore.createNewFeature(true);
228
                        newFeature.set(routeFieldName, routeName);
229
                        newFeature.setDefaultGeometry(geometry);
230
                        newFeatureStore.update(newFeature);
231
                    }
232
                }
233
                taskCount++;
234
                taskStatus.setCurValue(taskCount);
235
            }
236
            newFeatureStore.finishEditing();
237
        } catch (Exception e1) {
238
            taskStatus.abort();
239
            throw new LrsCalibrateRouteException("Error calibrating routes", e1);
240
        }
241

    
242
        taskStatus.terminate();
243
    }
244

    
245

    
246
    private Point pointToMPoint(Geometry geometry,Point point, Double measure) throws CreateGeometryException, GeometryOperationNotSupportedException, GeometryOperationException{
247
        GeometryManager geomanager = GeometryLocator.getGeometryManager();
248

    
249
        Point[] pointsInLine=(Point[])geometry.closestPoints(point);
250
        Point pointInLine=pointsInLine[0];
251

    
252
        Point mPoint = (Point) geomanager
253
            .create(Geometry.TYPES.POINT, Geometry.SUBTYPES.GEOM2DM);
254
        mPoint.setX(pointInLine.getX());
255
        mPoint.setY(pointInLine.getY());
256
        int mDimension=mPoint.getDimension()-1;
257
        mPoint.setCoordinateAt(mDimension, measure);
258

    
259
        return mPoint;
260
    }
261

    
262
    private Double calculateConvertedSearchRadius(){
263
        Double searchRadius=parameters.getSearchRadius();
264
        DistanceUnits measureUnits = parameters.getMeasureUnits();
265
        FeatureStore sourceFeatureStore = parameters.getSourceFeatureStore();
266

    
267
        IProjection projection;
268
        try {
269
            projection = sourceFeatureStore.getDefaultFeatureType().getDefaultSRS();
270

    
271
            Double searchRadiusInMeters=searchRadius*measureUnits.getTransToMeter();
272
            //TODO
273
            //DistanceUnits projectionDistanceUnits=getProjectionDistanceUnits(projection);
274
            //return searchRadiusInMeters/projectionDistanceUnits.getTransToMeter();
275
            return searchRadiusInMeters;
276
        } catch (Exception e) {
277
            return new Double(0);
278
        }
279
    }
280

    
281
    private boolean isValidPoint(Point point,Geometry geometry, Double convertedSearchRadius){
282
        try {
283
            return geometry.isWithinDistance(point, convertedSearchRadius);
284
        } catch (Exception e) {
285
            return false;
286
        }
287
    }
288

    
289
    private Geometry calibrateRoute(Geometry geometry, List<Point> points) {
290
        LrsMeasureCalculationMethods calculationMethod= parameters.getMeasureCalculationMethods();
291
        boolean ignoreSpatialGaps = parameters.ignoreSpatialGaps();
292
        boolean interpolateBetweenCalibrationPoints=parameters.interpolateBetweenCalibrationPoints();
293
        boolean extrapolateBeforeCalibrationPoints=parameters.extrapolateBeforeCalibrationPoints();
294
        boolean extrapolateAfterCalibrationPoints=parameters.extrapolateAfterCalibrationPoints();
295

    
296
        if (points.isEmpty()){
297
            return geometry;
298
        }
299
        ExpandedRoute expandedRoute=new ExpandedRoute(geometry, ignoreSpatialGaps);
300

    
301

    
302
        switch (calculationMethod) {
303
        case DISTANCE:
304
            if (extrapolateBeforeCalibrationPoints||interpolateBetweenCalibrationPoints||extrapolateAfterCalibrationPoints){
305
                expandedRoute.resetMeasuresToDistances();
306
            }
307
        case MEASURES:
308
        default:
309
            expandedRoute.addFixedPoints(points);
310
            expandedRoute.calculateCalibrationPoints(extrapolateBeforeCalibrationPoints,interpolateBetweenCalibrationPoints,extrapolateAfterCalibrationPoints);
311
            return expandedRoute.getRoute();
312
        }
313

    
314
    }
315

    
316

    
317

    
318
    class ExpandedRoute{
319
        private Geometry route;
320
        private List<Boolean> isFixedPoint;
321
        private List<Double> distances;
322
        private List<Double>oldMValues;
323
        private List<Point> vertices;
324
        private List<Integer> lineIndexes;
325
        private int MDIMENSION;
326

    
327
        private final Double PRECISION=new Double(1.0e-5);
328

    
329
        public Geometry getRoute(){
330
            return route;
331
        }
332

    
333
        public ExpandedRoute(Geometry geometry, boolean ignoreSpatialGaps){
334
            isFixedPoint=new ArrayList<Boolean>();
335
            distances=new ArrayList<Double>();
336
            oldMValues=new ArrayList<Double>();
337
            vertices=new ArrayList<Point>();
338
            lineIndexes=new ArrayList<Integer>();
339
            route=geometry.cloneGeometry();
340

    
341
            double distance = 0;
342
            List<Line> lines=LrsAlgorithmUtils.extractLines(geometry);
343
            Point previousVertex=null;
344
            for (int i=0; i<lines.size();i++){
345
                Line line=lines.get(i);
346
                for (int j=0; j<line.getNumVertices();j++){
347
                    Point vertex=line.getVertex(j);
348
                    if(j==0){
349
                       if (previousVertex==null){
350
                           //First point in geometry
351
                           MDIMENSION=vertex.getDimension()-1;
352
                           distance=0;
353
                       }
354
                       Integer visitedIndex = getIndexVisitedVertex(vertex);
355
                       if (visitedIndex!=null){
356
                           previousVertex=vertices.get(visitedIndex);
357
                           distance=distances.get(visitedIndex);
358
                       }else{
359
                           if (previousVertex!=null){
360
                               try {
361
                                   if(!LrsAlgorithmUtils.equalPoints(vertex, previousVertex)){
362
                                       Integer nearestVertexPos=getIndexNearestVisitedVertex(vertex);
363
                                       if (ignoreSpatialGaps){
364
                                           distance=distances.get(nearestVertexPos);
365
                                       }else{
366
                                           Point nearestVertex=vertices.get(nearestVertexPos);
367
                                           distance=distances.get(nearestVertexPos);
368
                                           distance+=vertex.distance(nearestVertex);
369
                                       }
370
                                   }
371
                               } catch (Exception e) {
372
                                   distance=Double.NaN;
373
                               }
374
                           }
375
                       }
376
                    }else{
377
                        try {
378
                            distance+=vertex.distance(previousVertex);
379
                        } catch (Exception e) {
380
                            distance=Double.NaN;
381
                        }
382
                    }
383
                    Double mValue=vertex.getCoordinateAt(MDIMENSION);
384

    
385
                    isFixedPoint.add(false);
386
                    vertices.add(vertex);
387
                    distances.add(distance);
388
                    oldMValues.add(mValue);
389
                    lineIndexes.add(i);
390

    
391
                    previousVertex = vertex;
392
                }
393
            }
394
        }
395

    
396
        private Integer getIndexNearestVisitedVertex(Point vertex) throws GeometryOperationNotSupportedException, GeometryOperationException{
397
            double nearestDistance = Double.POSITIVE_INFINITY;
398
            Integer nearestPointPos=null;
399
            for (int i=0;i<vertices.size();i++){
400
                Double distance=vertex.distance(vertices.get(i));
401
                if(nearestDistance>distance && distance>Double.valueOf(0)){
402
                    nearestDistance=distance;
403
                    nearestPointPos=i;
404
                }
405
            }
406
            return nearestPointPos;
407
        }
408

    
409
        private Integer getIndexVisitedVertex(Point point){
410
            double distance = Double.NEGATIVE_INFINITY;
411
            Integer index = null;
412
            for(int i =0; i<vertices.size(); i++){
413
                if (LrsAlgorithmUtils.equalPoints(point, vertices.get(i))){
414
                    if(this.distances.get(i)>distance){
415
                        distance = this.distances.get(i);
416
                        index = i;
417
                    }
418
                }
419
            }
420
            return index;
421
        }
422

    
423
        private void addFixedPoints(List<Point> fixedPoints){
424
            Double minMValue=null;
425
            Double maxMValue=null;
426
            for (Point fixedPoint:fixedPoints){
427
                Double length=Double.valueOf(0);
428
                int index = 0;
429
                List<Line> lines=LrsAlgorithmUtils.extractLines(route);
430
                List<Integer>insertAtList=new ArrayList<Integer>();
431
                List<Double>lengths=new ArrayList<Double>();
432
                List<Double>oldValues=new ArrayList<Double>();
433
                List<Integer>lineReference=new ArrayList<Integer>();
434
                for (int i=0; i<lines.size();i++){
435
                    Line line=lines.get(i);
436
                    try{
437
                        //FIXME
438
                        //if (line.intersects(fixedPoint)){
439
                        if (line.isWithinDistance(fixedPoint, PRECISION)){
440
                            length=distances.get(index);
441
                            for (int j=0;j<line.getNumVertices();j++){
442
                                Point vertex=line.getVertex(j);
443
                                Point nextVertex;
444
                                if (j+1<line.getNumVertices()){
445
                                    nextVertex=line.getVertex(j+1);
446
                                }else{
447
                                    nextVertex=null;
448
                                }
449
                                if(LrsAlgorithmUtils.equalPoints(vertex, fixedPoint)||vertex.distance(fixedPoint)<=PRECISION){
450
                                    oldMValues.set(index, vertex.getCoordinateAt(MDIMENSION));
451
                                    Double mValue=fixedPoint.getCoordinateAt(MDIMENSION);
452
                                    vertex.setCoordinateAt(MDIMENSION, mValue);
453
                                    isFixedPoint.set(index, true);
454
                                    vertices.set(index, vertex);
455
                                }else{
456
                                    if (nextVertex!=null
457
                                        && !LrsAlgorithmUtils.equalPoints(nextVertex, fixedPoint)
458
                                        && vertex.distance(fixedPoint)>PRECISION){
459

    
460
                                        GeometryManager geomanager = GeometryLocator.getGeometryManager();
461
                                        Line segment= (Line) geomanager
462
                                            .create(Geometry.TYPES.LINE, Geometry.SUBTYPES.GEOM2DM);
463
                                        segment.addVertex(vertex);
464
                                        segment.addVertex(nextVertex);
465
                                        //FIXME
466
                                        //if (line.intersects(fixedPoint)){
467
                                        if (segment.isWithinDistance(fixedPoint, PRECISION)){
468
                                            length+=vertex.distance(fixedPoint);
469
                                            Double oldMValue=LrsAlgorithmUtils.straightLineThroughTwoPointsEquation(
470
                                                vertex.getCoordinateAt(MDIMENSION),
471
                                                nextVertex.getCoordinateAt(MDIMENSION),
472
                                                distances.get(index),
473
                                                distances.get(index+1),
474
                                                length);
475
                                            insertAtList.add(index+1);
476
                                            lengths.add(length);
477
                                            oldValues.add(oldMValue);
478
                                            lineReference.add(i);
479
                                        }
480
                                    }
481
                                }
482
                                index++;
483
                            }
484
                        }else{
485
                            index+=line.getNumVertices();
486
                        }
487
                    }catch(Exception e){
488
                        logger.warn("Error inserting point "+fixedPoint.toString(),e);
489
                    }
490
                }
491
                int pos=0;
492
                for (Integer insertAt:insertAtList){
493
                    Double distance=lengths.get(pos);
494
                    Double oldMValue=oldValues.get(pos);
495
                    Integer linePos=lineReference.get(pos);
496
                    int correctedPosition=insertAt+pos;
497
                    route=LrsAlgorithmUtils.insertVertex(route, fixedPoint, correctedPosition);
498
                    isFixedPoint.add(correctedPosition, true);
499
                    distances.add(correctedPosition, distance);
500
                    oldMValues.add(correctedPosition, oldMValue);
501
                    lineIndexes.add(correctedPosition, linePos);
502
                    vertices.add(correctedPosition, fixedPoint);
503
                    pos++;
504
                }
505
            }
506
        }
507

    
508

    
509

    
510
        public void resetMeasuresToDistances(){
511
             List<Point> points=LrsAlgorithmUtils.extractPoints(route);
512
             for (int i=0;i<points.size();i++){
513
                 if (!isFixedPoint.get(i)){
514
                     points.get(i).setCoordinateAt(MDIMENSION, distances.get(i));
515
                     vertices.get(i).setCoordinateAt(MDIMENSION, distances.get(i));
516
                     oldMValues.set(i, distances.get(i));
517
                 }
518
             }
519
        }
520

    
521
//        public void interpolateBetweenCalibrationPoints(){
522
//            Double newMValueBeforePoint=Double.NaN;
523
//            Double oldMValueBeforePoint=Double.NaN;
524
//            Double calibrationRatio=Double.NaN;
525
//            for (int i=firstFixedPointPos; i<=lastFixedPointPos-1;i++){
526
//                if (isFixedPoint.get(i)){
527
//                    int pointBeforePos=i;
528
//                    int pointAfterPos=getNextPosFixedPoint(i);
529
//
530
//                    newMValueBeforePoint=vertices.get(pointBeforePos).getCoordinateAt(MDIMENSION);
531
//                    Double newMValueAfterPoint=vertices.get(pointAfterPos).getCoordinateAt(MDIMENSION);
532
//
533
//                    oldMValueBeforePoint=oldMValues.get(pointBeforePos);
534
//                    Double oldMValueAfterPoint=oldMValues.get(pointAfterPos);
535
//
536
//                    Double distanceBetweenFixedPoints=newMValueAfterPoint-newMValueBeforePoint;
537
//                    Double distanceBetweenOldFixedPoints=oldMValueAfterPoint-oldMValueBeforePoint;
538
//
539
//                    calibrationRatio=distanceBetweenOldFixedPoints/distanceBetweenFixedPoints;
540
//                }else{
541
//                    Double valueToRecalculate=vertices.get(i).getCoordinateAt(MDIMENSION);
542
//                    Double distanceBetween=valueToRecalculate-oldMValueBeforePoint;
543
//                    Double mValue=newMValueBeforePoint+(distanceBetween/calibrationRatio);
544
//                    refreshMValueGeometryVertex(i,mValue);
545
//                }
546
//            }
547
//        }
548

    
549
        public void calculateCalibrationPoints(boolean before, boolean between, boolean after){
550
            for (int i=0; i<vertices.size();i++){
551
                if(!isFixedPoint.get(i)){
552
                    Integer prevFixedPointPos=getPreviousPosFixedPoint(i);
553
                    Integer nextFixedPointPos=getNextPosFixedPoint(i);
554

    
555
                    if (prevFixedPointPos==null && nextFixedPointPos!=null  && before){
556
                        //TODO
557
                        //extrapolateBeforeCalibrationPoints(nextFixedPointPos,i);
558
                    }
559
                    if (prevFixedPointPos!=null && nextFixedPointPos!=null && between){
560
                        calculateMValue(prevFixedPointPos,nextFixedPointPos,i);
561
                    }
562
                    if (prevFixedPointPos!=null && nextFixedPointPos==null && after){
563
                        //TODO
564
                        //extrapolateAfterCalibrationPoints(prevFixedPointPos,i);
565
                    }
566
                }
567
            }
568
        }
569

    
570
        public void calculateMValue(int prevFixedPointPos,int nextFixedPointPos,int pos){
571
            Double newMValueBeforePoint=vertices.get(prevFixedPointPos).getCoordinateAt(MDIMENSION);
572
            Double newMValueAfterPoint=vertices.get(nextFixedPointPos).getCoordinateAt(MDIMENSION);
573

    
574
            Double oldMValueBeforePoint=oldMValues.get(prevFixedPointPos);
575
            Double oldMValueAfterPoint=oldMValues.get(nextFixedPointPos);
576

    
577
            Double distanceBetweenFixedPoints=newMValueAfterPoint-newMValueBeforePoint;
578
            Double distanceBetweenOldFixedPoints=oldMValueAfterPoint-oldMValueBeforePoint;
579

    
580
            Double calibrationRatio=distanceBetweenOldFixedPoints/distanceBetweenFixedPoints;
581

    
582
            Double valueToRecalculate=vertices.get(pos).getCoordinateAt(MDIMENSION);
583
            Double distanceBetween=valueToRecalculate-oldMValueBeforePoint;
584
            Double mValue=newMValueBeforePoint+(distanceBetween/calibrationRatio);
585
            refreshMValueGeometryVertex(pos,mValue);
586
        }
587

    
588

    
589
//        public void extrapolateBeforeCalibrationPoints(){
590
//            Integer nextFixedPointPos=getNextPosFixedPoint(firstFixedPointPos);
591
//            if (nextFixedPointPos!=null){
592
//                Double newMValueFirstPoint=vertices.get(firstFixedPointPos).getCoordinateAt(MDIMENSION);
593
//                Double newMValueSecondPoint=vertices.get(nextFixedPointPos).getCoordinateAt(MDIMENSION);
594
//
595
//                Double oldMValueFirstPoint=oldMValues.get(firstFixedPointPos);
596
//                Double oldMValueSecondPoint=oldMValues.get(nextFixedPointPos);
597
//
598
//                Double distanceBetweenFixedPoints=newMValueSecondPoint-newMValueFirstPoint;
599
//                Double distanceBetweenOldFixedPoints=oldMValueSecondPoint-oldMValueFirstPoint;
600
//
601
//                Double calibrationRatio=distanceBetweenOldFixedPoints/distanceBetweenFixedPoints;
602
//                for (int i=0; i<firstFixedPointPos;i++){
603
//                    Double valueToRecalculate=vertices.get(i).getCoordinateAt(MDIMENSION);
604
//                    Double distanceBetween=oldMValueFirstPoint-valueToRecalculate;
605
//                    Double mValue=newMValueFirstPoint-(distanceBetween/calibrationRatio);
606
//                    refreshMValueGeometryVertex(i,mValue);
607
//                }
608
//            }
609
//        }
610
//
611
//        public void extrapolateAfterCalibrationPoints(){
612
//            Integer prevFixedPointPos=getPreviousPosFixedPoint(lastFixedPointPos);
613
//            if (prevFixedPointPos!=null){
614
//                Double newMValueLastPoint=vertices.get(lastFixedPointPos).getCoordinateAt(MDIMENSION);
615
//                Double newMValuePrevPoint=vertices.get(prevFixedPointPos).getCoordinateAt(MDIMENSION);
616
//
617
//                Double oldMValueLastPoint=oldMValues.get(lastFixedPointPos);
618
//                Double oldMValuePrevPoint=oldMValues.get(prevFixedPointPos);
619
//
620
//                Double distanceBetweenFixedPoints=newMValueLastPoint-newMValuePrevPoint;
621
//                Double distanceBetweenOldFixedPoints=oldMValueLastPoint-oldMValuePrevPoint;
622
//
623
//                Double calibrationRatio=distanceBetweenOldFixedPoints/distanceBetweenFixedPoints;
624
//                for (int i=lastFixedPointPos+1; i<vertices.size();i++){
625
//                    Double valueToRecalculate=vertices.get(i).getCoordinateAt(MDIMENSION);
626
//                    Double distanceBetween=valueToRecalculate-oldMValueLastPoint;
627
//                    Double mValue=newMValueLastPoint+(distanceBetween/calibrationRatio);
628
//                    refreshMValueGeometryVertex(i,mValue);
629
//                }
630
//            }
631
//        }
632
//
633
//        private Integer getNextPosFixedPoint(int pos){
634
//            for (int i=pos+1;i<isFixedPoint.size();i++){
635
//                if (isFixedPoint.get(i)){
636
//                    if( !distances.get(pos).equals(distances.get(i)) ){
637
//                        return i;
638
//                    }
639
//                }
640
//            }
641
//            return null;
642
//        }
643

    
644

    
645

    
646
        private Integer getNextPosFixedPoint(int pos){
647
            Integer nextFixedPointPos= findNextFixedPointInLine(pos);
648
            if (nextFixedPointPos!=null){
649
                return nextFixedPointPos;
650
            }else{
651
                int lastPositionInLine=getLastPositionInLine(pos);
652
                nextFixedPointPos=findNextFixedPointInNextLines(lastPositionInLine,new ArrayList<Integer>());
653
                if (nextFixedPointPos!=null){
654
                    return nextFixedPointPos;
655
                }
656
                try{
657
                    Integer nearestVertex=findNearestNextPoint(lastPositionInLine);
658
                    return getNextPosFixedPoint(nearestVertex);
659
                }catch (Exception e){
660
                    return null;
661
                }
662
            }
663
        }
664

    
665
        private Integer getLastPositionInLine (int pos){
666
            Integer lineVisited=lineIndexes.get(pos);
667
            for (int i=pos+1;i<vertices.size();i++){
668
                if (!lineVisited.equals(lineIndexes.get(i))){
669
                    return i-1;
670
                }
671
            }
672
            return vertices.size()-1;
673
        }
674

    
675
        private Integer findNextFixedPointInNextLines(int pos,List<Integer> visitedLines){
676
            Integer nextFixedPointPos= findNextFixedPointInLine(pos);
677
            if (nextFixedPointPos!=null){
678
                return nextFixedPointPos;
679
            }else{
680
                Integer lineIndex=lineIndexes.get(pos);
681
                visitedLines.add(lineIndex);
682
                int lastPositionInLine=getLastPositionInLine(pos);
683
                Point lastVertexInLine=vertices.get(lastPositionInLine);
684
                for (int i=pos+1;i<vertices.size();i++){
685
                    if (LrsAlgorithmUtils.equalPoints(lastVertexInLine, vertices.get(i))){
686
                        if (!visitedLines.contains(lineIndexes.get(i))){
687
                            findNextFixedPointInNextLines(i,visitedLines);
688
                        }
689
                    }
690
                }
691
            }
692
            return null;
693
        }
694

    
695
        private Integer findNextFixedPointInLine(int vertexPos){
696
            int lineIndex=lineIndexes.get(vertexPos);
697
            for (int i=vertexPos;i<vertices.size();i++){
698
                if(!lineIndexes.get(i).equals(lineIndex)){
699
                    return null;
700
                }
701
                if (isFixedPoint.get(i)){
702
                    return i;
703
                }
704
            }
705
            return null;
706
        }
707

    
708

    
709
        private Integer findNearestNextPoint(int vertexPos) throws GeometryOperationNotSupportedException, GeometryOperationException{
710
            Point vertex=vertices.get(vertexPos);
711
            double nearestDistance = Double.POSITIVE_INFINITY;
712
            Integer nearestPointPos=null;
713
            for (int i=vertexPos+1;i<vertices.size();i++){
714
                Double distance=vertex.distance(vertices.get(i));
715
                if(nearestDistance>distance && distance>Double.valueOf(0)){
716
                    nearestDistance=distance;
717
                    nearestPointPos=i;
718
                }
719
            }
720
            return nearestPointPos;
721
        }
722

    
723

    
724
        private Integer getPreviousPosFixedPoint(int pos){
725
            Integer prevFixedPointPos= findPrevFixedPointInLine(pos);
726
            if (prevFixedPointPos!=null){
727
                return prevFixedPointPos;
728
            }else{
729
                Integer lineVisited=lineIndexes.get(pos);
730
                for (int i=pos-1;i>=0;i--){
731
                    if (!lineVisited.equals(lineIndexes.get(i))){//Line has changed
732
                        int lastPositionInLine=i+1;
733
                        for (int j=lastPositionInLine;j>=0;j--){
734
                            if (LrsAlgorithmUtils.equalPoints(vertices.get(lastPositionInLine), vertices.get(j))){
735
                                if (isFixedPoint.get(j)){
736
                                    return j;
737
                                }
738
                            }
739
                        }
740
                        try{
741
                            return findNearestPrevFixedPoint(lastPositionInLine);
742
                        }catch (Exception e){
743
                            return null;
744
                        }
745
                    }
746
                }
747
            }
748
            return null;
749
        }
750
        private Integer findPrevFixedPointInLine(int vertexPos){
751
            int lineIndex=lineIndexes.get(vertexPos);
752
            for (int i=vertexPos;i>=0;i--){
753
                if(!lineIndexes.get(i).equals(lineIndex)){
754
                    return null;
755
                }
756
                if (isFixedPoint.get(i)){
757
                    return i;
758
                }
759
            }
760
            return null;
761
        }
762
        private Integer findNearestPrevFixedPoint(int vertexPos) throws GeometryOperationNotSupportedException, GeometryOperationException{
763
            Point vertex=vertices.get(vertexPos);
764
            double nearestDistance = Double.POSITIVE_INFINITY;
765
            Integer nearestPointPos=null;
766
            for (int i=vertexPos-1;i>=0;i--){
767
                if (isFixedPoint.get(i)){
768
                    Double distance=vertex.distance(vertices.get(i));
769
                    if(nearestDistance>distance){
770
                        nearestDistance=distance;
771
                        nearestPointPos=i;
772
                    }
773
                }
774
            }
775
            return nearestPointPos;
776
        }
777

    
778

    
779
        private void refreshMValueGeometryVertex(int i, Double mValue){
780
            List<Point> points=LrsAlgorithmUtils.extractPoints(route);
781
            vertices.get(i).setCoordinateAt(MDIMENSION, mValue);
782
            points.get(i).setCoordinateAt(MDIMENSION,mValue);
783
            isFixedPoint.set(i, true);
784
        }
785

    
786
    }
787

    
788

    
789
}
790

    
791

    
792

    
793