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

History | View | Annotate | Download (35.2 KB)

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

    
25
import java.util.ArrayList;
26
import java.util.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.slf4j.Logger;
33
import org.slf4j.LoggerFactory;
34

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

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

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

    
73
    private LrsCalibrateRouteAlgorithmParams parameters;
74

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

    
81
    }
82

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

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

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

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

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

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

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

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

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

    
147
            final Map<String, RouteAndPoints> featuresMap =
148
                new HashMap<String, RouteAndPoints>();
149
            sourceFeatures.accept(new Visitor() {
150

    
151
                public void visit(Object obj)
152
                    throws VisitCanceledException, BaseException {
153
                    Feature feature = (Feature) obj;
154
                    String routeName = (String) feature.get(routeFieldName);
155
                    RouteAndPoints routeAndPoints = new RouteAndPoints(feature.getDefaultGeometry(), new ArrayList<Point>());
156

    
157
                    featuresMap.put(routeName, routeAndPoints);
158
                }
159
            });
160

    
161
            FeatureSet pointFeatures=calibratePointFeatureStore.getFeatureSet();
162
            pointFeatures.accept(new Visitor() {
163

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

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

    
194
            taskStatus.setRangeOfValues(0, featuresMap.size());
195
            int taskCount = 0;
196

    
197
            newFeatureStore.edit(FeatureStore.MODE_FULLEDIT);
198

    
199
            for (Entry<String, RouteAndPoints> entry : featuresMap.entrySet()) {
200
                String routeName = entry.getKey();
201
                Object valueObject = entry.getValue();
202
                List<Point> points=null;
203
                Geometry geometry=null;
204

    
205
                if (valueObject!=null && valueObject instanceof RouteAndPoints){
206
                    RouteAndPoints routeAndPoints=(RouteAndPoints)valueObject;
207
                        geometry=routeAndPoints.getRoute();
208
                        points=routeAndPoints.getPoints();
209
                }
210
                if (!points.isEmpty()){
211
                    EditableFeature newFeature =
212
                        newFeatureStore.createNewFeature(true);
213
                    newFeature.set(routeFieldName, routeName);
214
                    Geometry calibratedRoute = calibrateRoute(geometry,points);
215
                    newFeature.setDefaultGeometry(calibratedRoute);
216
                    newFeatureStore.update(newFeature);
217
                } else if (includeAll) {
218
                    EditableFeature newFeature = newFeatureStore.createNewFeature(true);
219
                    newFeature.set(routeFieldName, routeName);
220
                    newFeature.setDefaultGeometry(geometry);
221
                    newFeatureStore.update(newFeature);
222
                }
223
                taskCount++;
224
                taskStatus.setCurValue(taskCount);
225
            }
226
            newFeatureStore.finishEditing();
227
        } catch (Exception e1) {
228
            taskStatus.abort();
229
            throw new LrsCalibrateRouteException("Error calibrating routes", e1);
230
        }
231

    
232
        taskStatus.terminate();
233
    }
234

    
235

    
236
    private Point pointToMPoint(Geometry geometry,Point point, Double measure) throws CreateGeometryException, GeometryOperationNotSupportedException, GeometryOperationException{
237
        GeometryManager geomanager = GeometryLocator.getGeometryManager();
238

    
239
        Point[] pointsInLine=(Point[])geometry.closestPoints(point);
240
        Point pointInLine=pointsInLine[0];
241

    
242
        Point mPoint = (Point) geomanager
243
            .create(Geometry.TYPES.POINT, Geometry.SUBTYPES.GEOM2DM);
244
        mPoint.setX(pointInLine.getX());
245
        mPoint.setY(pointInLine.getY());
246
        int mDimension=mPoint.getDimension()-1;
247
        mPoint.setCoordinateAt(mDimension, measure);
248

    
249
        return mPoint;
250
    }
251

    
252
    private Double calculateConvertedSearchRadius(){
253
        Double searchRadius=parameters.getSearchRadius();
254
        DistanceUnits measureUnits = parameters.getMeasureUnits();
255
        FeatureStore sourceFeatureStore = parameters.getSourceFeatureStore();
256

    
257
        try {
258
            IProjection projection = sourceFeatureStore.getDefaultFeatureType().getDefaultSRS();
259

    
260
            Double searchRadiusInMeters=searchRadius*measureUnits.getTransToMeter();
261
            //TODO
262
//            DistanceUnits projectionDistanceUnits=getProjectionDistanceUnits(projection);
263
            //return searchRadiusInMeters/projectionDistanceUnits.getTransToMeter();
264
            return searchRadiusInMeters;
265
        } catch (Exception e) {
266
            return new Double(0);
267
        }
268
    }
269

    
270
    private boolean isValidPoint(Point point,Geometry geometry, Double convertedSearchRadius){
271
        try {
272
            return geometry.isWithinDistance(point, convertedSearchRadius);
273
        } catch (Exception e) {
274
            return false;
275
        }
276
    }
277

    
278
    private Geometry calibrateRoute(Geometry geometry, List<Point> points) {
279
        LrsMeasureCalculationMethods calculationMethod= parameters.getMeasureCalculationMethods();
280
        boolean ignoreSpatialGaps = parameters.ignoreSpatialGaps();
281
        boolean interpolateBetweenCalibrationPoints=parameters.interpolateBetweenCalibrationPoints();
282
        boolean extrapolateBeforeCalibrationPoints=parameters.extrapolateBeforeCalibrationPoints();
283
        boolean extrapolateAfterCalibrationPoints=parameters.extrapolateAfterCalibrationPoints();
284

    
285
        if (points.isEmpty()){
286
            return geometry;
287
        }
288
        ExpandedRoute expandedRoute=new ExpandedRoute(geometry, ignoreSpatialGaps);
289

    
290

    
291
        switch (calculationMethod) {
292
        case DISTANCE:
293
            if (extrapolateBeforeCalibrationPoints||interpolateBetweenCalibrationPoints||extrapolateAfterCalibrationPoints){
294
                expandedRoute.resetMeasuresToDistances();
295
            }
296
        case MEASURES:
297
        default:
298
            expandedRoute.addFixedPoints(points);
299
            expandedRoute.calculateCalibrationPoints(extrapolateBeforeCalibrationPoints,interpolateBetweenCalibrationPoints,extrapolateAfterCalibrationPoints);
300
            return expandedRoute.getRoute();
301
        }
302

    
303
    }
304

    
305

    
306

    
307
    class ExpandedRoute{
308
        private Geometry route;
309
        private List<Boolean> isFixedPoint;
310
        private List<Double> distances;
311
        private List<Double>oldMValues;
312
        private List<Point> vertices;
313
        private List<Integer> lineIndexes;
314
        private int MDIMENSION;
315

    
316
        private final Double PRECISION=new Double(1.0e-5);
317

    
318
        public Geometry getRoute(){
319
            return route;
320
        }
321

    
322
        public ExpandedRoute(Geometry geometry, boolean ignoreSpatialGaps){
323
            isFixedPoint=new ArrayList<Boolean>();
324
            distances=new ArrayList<Double>();
325
            oldMValues=new ArrayList<Double>();
326
            vertices=new ArrayList<Point>();
327
            lineIndexes=new ArrayList<Integer>();
328
            route=geometry.cloneGeometry();
329

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

    
374
                    isFixedPoint.add(false);
375
                    vertices.add(vertex);
376
                    distances.add(distance);
377
                    oldMValues.add(mValue);
378
                    lineIndexes.add(i);
379

    
380
                    previousVertex = vertex;
381
                }
382
            }
383
        }
384

    
385
        private Integer getIndexNearestVisitedVertex(Point vertex) throws GeometryOperationNotSupportedException, GeometryOperationException{
386
            double nearestDistance = Double.POSITIVE_INFINITY;
387
            Integer nearestPointPos=null;
388
            for (int i=0;i<vertices.size();i++){
389
                Double distance=vertex.distance(vertices.get(i));
390
                if(nearestDistance>distance && distance>Double.valueOf(0)){
391
                    nearestDistance=distance;
392
                    nearestPointPos=i;
393
                }
394
            }
395
            return nearestPointPos;
396
        }
397

    
398
        private Integer getIndexVisitedVertex(Point point){
399
            double distance = Double.NEGATIVE_INFINITY;
400
            Integer index = null;
401
            for(int i =0; i<vertices.size(); i++){
402
                if (LrsAlgorithmUtils.equalPoints(point, vertices.get(i))){
403
                    if(this.distances.get(i)>distance){
404
                        distance = this.distances.get(i);
405
                        index = i;
406
                    }
407
                }
408
            }
409
            return index;
410
        }
411

    
412
        private void addFixedPoints(List<Point> fixedPoints){
413
            Double minMValue=null;
414
            Double maxMValue=null;
415
            for (Point fixedPoint:fixedPoints){
416
                Double length=Double.valueOf(0);
417
                int index = 0;
418
                List<Line> lines=LrsAlgorithmUtils.extractLines(route);
419
                List<Integer>insertAtList=new ArrayList<Integer>();
420
                List<Double>lengths=new ArrayList<Double>();
421
                List<Double>oldValues=new ArrayList<Double>();
422
                List<Integer>lineReference=new ArrayList<Integer>();
423
                for (int i=0; i<lines.size();i++){
424
                    Line line=lines.get(i);
425
                    try{
426
                        if (line.isWithinDistance(fixedPoint, PRECISION)){
427
                            length=distances.get(index);
428
                            for (int j=0;j<line.getNumVertices();j++){
429
                                Point vertex=line.getVertex(j);
430
                                Point nextVertex;
431
                                if (j+1<line.getNumVertices()){
432
                                    nextVertex=line.getVertex(j+1);
433
                                }else{
434
                                    nextVertex=null;
435
                                }
436
                                if(LrsAlgorithmUtils.equalPoints(vertex, fixedPoint)||vertex.distance(fixedPoint)<=PRECISION){
437
                                    oldMValues.set(index, vertex.getCoordinateAt(MDIMENSION));
438
                                    Double mValue=fixedPoint.getCoordinateAt(MDIMENSION);
439
                                    vertex.setCoordinateAt(MDIMENSION, mValue);
440
                                    isFixedPoint.set(index, true);
441
//                                    vertices.set(index, vertex);
442
                                }else{
443
                                    if (nextVertex!=null
444
                                        && !LrsAlgorithmUtils.equalPoints(nextVertex, fixedPoint)
445
                                        && vertex.distance(fixedPoint)>PRECISION){
446

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

    
495

    
496

    
497
        public void resetMeasuresToDistances(){
498
             List<Point> points=LrsAlgorithmUtils.extractPoints(route);
499
             for (int i=0;i<points.size();i++){
500
                 if (!isFixedPoint.get(i)){
501
                     points.get(i).setCoordinateAt(MDIMENSION, distances.get(i));
502
                     vertices.get(i).setCoordinateAt(MDIMENSION, distances.get(i));
503
                     oldMValues.set(i, distances.get(i));
504
                 }
505
             }
506
        }
507

    
508
//        public void interpolateBetweenCalibrationPoints(){
509
//            Double newMValueBeforePoint=Double.NaN;
510
//            Double oldMValueBeforePoint=Double.NaN;
511
//            Double calibrationRatio=Double.NaN;
512
//            for (int i=firstFixedPointPos; i<=lastFixedPointPos-1;i++){
513
//                if (isFixedPoint.get(i)){
514
//                    int pointBeforePos=i;
515
//                    int pointAfterPos=getNextPosFixedPoint(i);
516
//
517
//                    newMValueBeforePoint=vertices.get(pointBeforePos).getCoordinateAt(MDIMENSION);
518
//                    Double newMValueAfterPoint=vertices.get(pointAfterPos).getCoordinateAt(MDIMENSION);
519
//
520
//                    oldMValueBeforePoint=oldMValues.get(pointBeforePos);
521
//                    Double oldMValueAfterPoint=oldMValues.get(pointAfterPos);
522
//
523
//                    Double distanceBetweenFixedPoints=newMValueAfterPoint-newMValueBeforePoint;
524
//                    Double distanceBetweenOldFixedPoints=oldMValueAfterPoint-oldMValueBeforePoint;
525
//
526
//                    calibrationRatio=distanceBetweenOldFixedPoints/distanceBetweenFixedPoints;
527
//                }else{
528
//                    Double valueToRecalculate=vertices.get(i).getCoordinateAt(MDIMENSION);
529
//                    Double distanceBetween=valueToRecalculate-oldMValueBeforePoint;
530
//                    Double mValue=newMValueBeforePoint+(distanceBetween/calibrationRatio);
531
//                    refreshMValueGeometryVertex(i,mValue);
532
//                }
533
//            }
534
//        }
535

    
536
        public void calculateCalibrationPoints(boolean before, boolean between, boolean after){
537
            for (int i=0; i<vertices.size();i++){
538
                if(!isFixedPoint.get(i)){
539
                    Integer prevFixedPointPos=getPreviousPosFixedPoint(i);
540
                    Integer nextFixedPointPos=getNextPosFixedPoint(i);
541

    
542
                    if (prevFixedPointPos==null && nextFixedPointPos!=null  && before){
543
                        //TODO
544
                        //extrapolateBeforeCalibrationPoints(nextFixedPointPos,i);
545
                    }
546
                    if (prevFixedPointPos!=null && nextFixedPointPos!=null && between){
547
                        calculateMValue(prevFixedPointPos,nextFixedPointPos,i);
548
                    }
549
                    if (prevFixedPointPos!=null && nextFixedPointPos==null && after){
550
                        //TODO
551
                        //extrapolateAfterCalibrationPoints(prevFixedPointPos,i);
552
                    }
553
                }
554
            }
555
        }
556

    
557
        public void calculateMValue(int prevFixedPointPos,int nextFixedPointPos,int pos){
558
            Double newMValueBeforePoint=vertices.get(prevFixedPointPos).getCoordinateAt(MDIMENSION);
559
            Double newMValueAfterPoint=vertices.get(nextFixedPointPos).getCoordinateAt(MDIMENSION);
560

    
561
            Double oldMValueBeforePoint=oldMValues.get(prevFixedPointPos);
562
            Double oldMValueAfterPoint=oldMValues.get(nextFixedPointPos);
563

    
564
            Double distanceBetweenFixedPoints=newMValueAfterPoint-newMValueBeforePoint;
565
            Double distanceBetweenOldFixedPoints=oldMValueAfterPoint-oldMValueBeforePoint;
566

    
567
            Double calibrationRatio=distanceBetweenOldFixedPoints/distanceBetweenFixedPoints;
568

    
569
            Double valueToRecalculate=vertices.get(pos).getCoordinateAt(MDIMENSION);
570
            Double distanceBetween=valueToRecalculate-oldMValueBeforePoint;
571
            Double mValue=newMValueBeforePoint+(distanceBetween/calibrationRatio);
572
            refreshMValueGeometryVertex(pos,mValue);
573
        }
574

    
575

    
576
//        public void extrapolateBeforeCalibrationPoints(){
577
//            Integer nextFixedPointPos=getNextPosFixedPoint(firstFixedPointPos);
578
//            if (nextFixedPointPos!=null){
579
//                Double newMValueFirstPoint=vertices.get(firstFixedPointPos).getCoordinateAt(MDIMENSION);
580
//                Double newMValueSecondPoint=vertices.get(nextFixedPointPos).getCoordinateAt(MDIMENSION);
581
//
582
//                Double oldMValueFirstPoint=oldMValues.get(firstFixedPointPos);
583
//                Double oldMValueSecondPoint=oldMValues.get(nextFixedPointPos);
584
//
585
//                Double distanceBetweenFixedPoints=newMValueSecondPoint-newMValueFirstPoint;
586
//                Double distanceBetweenOldFixedPoints=oldMValueSecondPoint-oldMValueFirstPoint;
587
//
588
//                Double calibrationRatio=distanceBetweenOldFixedPoints/distanceBetweenFixedPoints;
589
//                for (int i=0; i<firstFixedPointPos;i++){
590
//                    Double valueToRecalculate=vertices.get(i).getCoordinateAt(MDIMENSION);
591
//                    Double distanceBetween=oldMValueFirstPoint-valueToRecalculate;
592
//                    Double mValue=newMValueFirstPoint-(distanceBetween/calibrationRatio);
593
//                    refreshMValueGeometryVertex(i,mValue);
594
//                }
595
//            }
596
//        }
597
//
598
//        public void extrapolateAfterCalibrationPoints(){
599
//            Integer prevFixedPointPos=getPreviousPosFixedPoint(lastFixedPointPos);
600
//            if (prevFixedPointPos!=null){
601
//                Double newMValueLastPoint=vertices.get(lastFixedPointPos).getCoordinateAt(MDIMENSION);
602
//                Double newMValuePrevPoint=vertices.get(prevFixedPointPos).getCoordinateAt(MDIMENSION);
603
//
604
//                Double oldMValueLastPoint=oldMValues.get(lastFixedPointPos);
605
//                Double oldMValuePrevPoint=oldMValues.get(prevFixedPointPos);
606
//
607
//                Double distanceBetweenFixedPoints=newMValueLastPoint-newMValuePrevPoint;
608
//                Double distanceBetweenOldFixedPoints=oldMValueLastPoint-oldMValuePrevPoint;
609
//
610
//                Double calibrationRatio=distanceBetweenOldFixedPoints/distanceBetweenFixedPoints;
611
//                for (int i=lastFixedPointPos+1; i<vertices.size();i++){
612
//                    Double valueToRecalculate=vertices.get(i).getCoordinateAt(MDIMENSION);
613
//                    Double distanceBetween=valueToRecalculate-oldMValueLastPoint;
614
//                    Double mValue=newMValueLastPoint+(distanceBetween/calibrationRatio);
615
//                    refreshMValueGeometryVertex(i,mValue);
616
//                }
617
//            }
618
//        }
619
//
620
//        private Integer getNextPosFixedPoint(int pos){
621
//            for (int i=pos+1;i<isFixedPoint.size();i++){
622
//                if (isFixedPoint.get(i)){
623
//                    if( !distances.get(pos).equals(distances.get(i)) ){
624
//                        return i;
625
//                    }
626
//                }
627
//            }
628
//            return null;
629
//        }
630

    
631

    
632

    
633
        private Integer getNextPosFixedPoint(int pos){
634
            Integer nextFixedPointPos= findNextFixedPointInLine(pos);
635
            if (nextFixedPointPos!=null){
636
                return nextFixedPointPos;
637
            }else{
638
                int lastPositionInLine=getLastPositionInLine(pos);
639
                        nextFixedPointPos=findNextFixedPointInNextLines(lastPositionInLine,new ArrayList<Integer>());
640
                        if (nextFixedPointPos!=null){
641
                            return nextFixedPointPos;
642
                        }
643
                        try{
644
                    Integer nearestVertex=findNearestNextPoint(lastPositionInLine);
645
                    return getNextPosFixedPoint(nearestVertex);
646
                        }catch (Exception e){
647
                            return null;
648
                        }
649
                    }
650
                }
651

    
652
        private Integer getLastPositionInLine (int pos){
653
            Integer lineVisited=lineIndexes.get(pos);
654
            for (int i=pos+1;i<vertices.size();i++){
655
                if (!lineVisited.equals(lineIndexes.get(i))){
656
                    return i-1;
657
            }
658
        }
659
            return vertices.size()-1;
660
        }
661

    
662
        private Integer findNextFixedPointInNextLines(int pos,List<Integer> visitedLines){
663
            Integer nextFixedPointPos= findNextFixedPointInLine(pos);
664
            if (nextFixedPointPos!=null){
665
                return nextFixedPointPos;
666
            }else{
667
                Integer lineIndex=lineIndexes.get(pos);
668
                visitedLines.add(lineIndex);
669
                int lastPositionInLine=getLastPositionInLine(pos);
670
                Point lastVertexInLine=vertices.get(lastPositionInLine);
671
                for (int i=pos+1;i<vertices.size();i++){
672
                    if (LrsAlgorithmUtils.equalPoints(lastVertexInLine, vertices.get(i))){
673
                        if (!visitedLines.contains(lineIndexes.get(i))){
674
                            findNextFixedPointInNextLines(i,visitedLines);
675
                        }
676
                    }
677
                }
678
            }
679
            return null;
680
        }
681

    
682
        private Integer findNextFixedPointInLine(int vertexPos){
683
            int lineIndex=lineIndexes.get(vertexPos);
684
            for (int i=vertexPos;i<vertices.size();i++){
685
                if(!lineIndexes.get(i).equals(lineIndex)){
686
                    return null;
687
                }
688
                if (isFixedPoint.get(i)){
689
                    return i;
690
                }
691
            }
692
            return null;
693
        }
694

    
695

    
696
        private Integer findNearestNextPoint(int vertexPos) throws GeometryOperationNotSupportedException, GeometryOperationException{
697
            Point vertex=vertices.get(vertexPos);
698
            double nearestDistance = Double.POSITIVE_INFINITY;
699
            Integer nearestPointPos=null;
700
            for (int i=vertexPos+1;i<vertices.size();i++){
701
                    Double distance=vertex.distance(vertices.get(i));
702
                if(nearestDistance>distance && distance>Double.valueOf(0)){
703
                        nearestDistance=distance;
704
                        nearestPointPos=i;
705
                    }
706
                }
707
            return nearestPointPos;
708
        }
709

    
710

    
711
        private Integer getPreviousPosFixedPoint(int pos){
712
            Integer prevFixedPointPos= findPrevFixedPointInLine(pos);
713
            if (prevFixedPointPos!=null){
714
                return prevFixedPointPos;
715
            }else{
716
                Integer lineVisited=lineIndexes.get(pos);
717
                for (int i=pos-1;i>=0;i--){
718
                    if (!lineVisited.equals(lineIndexes.get(i))){//Line has changed
719
                        int lastPositionInLine=i+1;
720
                        for (int j=lastPositionInLine;j>=0;j--){
721
                            if (LrsAlgorithmUtils.equalPoints(vertices.get(lastPositionInLine), vertices.get(j))){
722
                                if (isFixedPoint.get(j)){
723
                                    return j;
724
                                }
725
                            }
726
                        }
727
                        try{
728
                            return findNearestPrevFixedPoint(lastPositionInLine);
729
                        }catch (Exception e){
730
                            return null;
731
                        }
732
                    }
733
                }
734
            }
735
            return null;
736
        }
737
        private Integer findPrevFixedPointInLine(int vertexPos){
738
            int lineIndex=lineIndexes.get(vertexPos);
739
            for (int i=vertexPos;i>=0;i--){
740
                if(!lineIndexes.get(i).equals(lineIndex)){
741
                    return null;
742
                }
743
                if (isFixedPoint.get(i)){
744
                    return i;
745
                }
746
            }
747
            return null;
748
        }
749
        private Integer findNearestPrevFixedPoint(int vertexPos) throws GeometryOperationNotSupportedException, GeometryOperationException{
750
            Point vertex=vertices.get(vertexPos);
751
            double nearestDistance = Double.POSITIVE_INFINITY;
752
            Integer nearestPointPos=null;
753
            for (int i=vertexPos-1;i>=0;i--){
754
                if (isFixedPoint.get(i)){
755
                    Double distance=vertex.distance(vertices.get(i));
756
                    if(nearestDistance>distance){
757
                        nearestDistance=distance;
758
                        nearestPointPos=i;
759
                    }
760
                }
761
            }
762
            return nearestPointPos;
763
        }
764

    
765

    
766
        private void refreshMValueGeometryVertex(int i, Double mValue){
767
            List<Point> points=LrsAlgorithmUtils.extractPoints(route);
768
            vertices.get(i).setCoordinateAt(MDIMENSION, mValue);
769
            points.get(i).setCoordinateAt(MDIMENSION,mValue);
770
            isFixedPoint.set(i, true);
771
        }
772

    
773
    }
774

    
775
    private class RouteAndPoints {
776
        private Geometry route;
777
        private List<Point> points;
778

    
779

    
780
        /**
781
         *
782
         */
783
        public RouteAndPoints(Geometry route, List<Point> points) {
784
            this.setRoute(route);
785
            this.setPoints(points);
786
        }
787

    
788

    
789
        /**
790
         * @return the route
791
         */
792
        public Geometry getRoute() {
793
            return route;
794
        }
795

    
796

    
797
        /**
798
         * @param route the route to set
799
         */
800
        public void setRoute(Geometry route) {
801
            this.route = route;
802
        }
803

    
804

    
805
        /**
806
         * @return the points
807
         */
808
        public List<Point> getPoints() {
809
            return points;
810
        }
811

    
812

    
813
        /**
814
         * @param points the points to set
815
         */
816
        public void setPoints(List<Point> points) {
817
            this.points = points;
818
        }
819

    
820
    }
821
}
822

    
823

    
824

    
825