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 / LrsAlgorithmUtils.java @ 89

History | View | Annotate | Download (19.9 KB)

1
/*
2
 * Copyright 2015 DiSiD Technologies S.L.L. All rights reserved.
3
 *
4
 * Project  : DiSiD org.gvsig.lrs.lib.impl
5
 * SVN Id   : $Id$
6
 */
7
package org.gvsig.lrs.lib.impl;
8

    
9
import java.io.File;
10
import java.util.ArrayList;
11
import java.util.List;
12

    
13
import org.gvsig.fmap.dal.DALLocator;
14
import org.gvsig.fmap.dal.DataManager;
15
import org.gvsig.fmap.dal.DataServerExplorer;
16
import org.gvsig.fmap.dal.DataServerExplorerParameters;
17
import org.gvsig.fmap.dal.DataStore;
18
import org.gvsig.fmap.dal.DataTypes;
19
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
20
import org.gvsig.fmap.dal.feature.EditableFeatureType;
21
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
22
import org.gvsig.fmap.dal.feature.FeatureStore;
23
import org.gvsig.fmap.dal.feature.NewFeatureStoreParameters;
24
import org.gvsig.fmap.dal.store.shp.SHPNewStoreParameters;
25
import org.gvsig.fmap.geom.Geometry;
26
import org.gvsig.fmap.geom.GeometryLocator;
27
import org.gvsig.fmap.geom.GeometryManager;
28
import org.gvsig.fmap.geom.aggregate.MultiLine;
29
import org.gvsig.fmap.geom.exception.CreateGeometryException;
30
import org.gvsig.fmap.geom.operation.GeometryOperationException;
31
import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException;
32
import org.gvsig.fmap.geom.primitive.Line;
33
import org.gvsig.fmap.geom.primitive.Point;
34
import org.gvsig.fmap.geom.type.GeometryType;
35
import org.gvsig.lrs.lib.api.exceptions.LrsCreateRouteException;
36
import org.gvsig.tools.dataTypes.DataType;
37
import org.gvsig.tools.locator.LocatorException;
38

    
39
/**
40
 * @author fdiaz
41
 *
42
 */
43
public class LrsAlgorithmUtils {
44

    
45
    static protected FeatureStore createNewDataStore(NewFeatureStoreParameters newFeatureStoreParameters,
46
        FeatureAttributeDescriptor idRouteField) throws Exception {
47
        return createNewDataStore(newFeatureStoreParameters, idRouteField, Geometry.TYPES.MULTILINE);
48
    }
49

    
50
    static protected FeatureStore createNewDataStore(NewFeatureStoreParameters newFeatureStoreParameters,
51
        FeatureAttributeDescriptor idRouteField, int type) throws Exception {
52
        try {
53
            SHPNewStoreParameters shapeStoreParams = (SHPNewStoreParameters) newFeatureStoreParameters;
54
            File file = shapeStoreParams.getFile();
55
            String filePath = file.getPath().substring(0, file.getPath().lastIndexOf(File.separator));
56

    
57
            DataManager dataManager = DALLocator.getDataManager();
58
            DataServerExplorerParameters serverParams =
59
                dataManager.createServerExplorerParameters("FilesystemExplorer");
60
            serverParams.setDynValue("initialpath", filePath);
61
            DataServerExplorer serverExplorer =
62
                dataManager.openServerExplorer(serverParams.getExplorerName(), serverParams);
63

    
64
            EditableFeatureType featureType = (EditableFeatureType) shapeStoreParams.getDefaultFeatureType();
65
            featureType.add(idRouteField.getName(), idRouteField.getType(), idRouteField.getSize());
66
            EditableFeatureAttributeDescriptor geometryField = featureType.add("Geometry", DataTypes.GEOMETRY);
67
            GeometryType geometryType =
68
                GeometryLocator.getGeometryManager().getGeometryType(type, Geometry.SUBTYPES.GEOM2DM);
69
            geometryField.setGeometryType(geometryType);
70

    
71
            featureType.setDefaultGeometryAttributeName("Geometry");
72

    
73
            shapeStoreParams.setDefaultFeatureType(featureType);
74
            serverExplorer.add("Shape", shapeStoreParams, true);
75

    
76
            DataStore store = dataManager.createStore(shapeStoreParams);
77

    
78
            return (FeatureStore) store;
79

    
80
        } catch (Exception e) {
81
            throw new LrsCreateRouteException("Error creating new dataStore", e);
82
        }
83
    }
84

    
85
    static protected Double getAsDouble(Object obj, DataType dataType) {
86
        if (obj == null || dataType == null) {
87
            return null;
88
        }
89
        Double result = Double.NaN;
90
        if (dataType.equals(DataTypes.DOUBLE)) {
91
            result = (Double) obj;
92
        } else if (dataType.isNumeric()) {
93
            result = Double.valueOf(String.valueOf(obj));
94
        }
95
        return result;
96
    }
97

    
98
    static List<Point> getPointsWithM(Geometry geom, double m) throws CreateGeometryException, LocatorException {
99

    
100
        List<Point> points = new ArrayList<Point>();
101

    
102
        if (geom instanceof Line) {
103
            Line line = (Line) geom;
104
            for (int i = 0; i < line.getNumVertices() - 1; i++) {
105
                Point currentVertex = line.getVertex(i);
106
                Point nextVertex = line.getVertex(i + 1);
107
                Point point = getPointWithMBetweenTwoMPoints(m, currentVertex, nextVertex);
108
                if (point != null && !points.contains(point)) {
109
                    points.add(point);
110
                }
111
            }
112
        } else if (geom instanceof MultiLine) {
113
            MultiLine multiLine = (MultiLine) geom;
114
            for (int p = 0; p < multiLine.getPrimitivesNumber(); p++) {
115
                Line line = (Line) multiLine.getPrimitiveAt(p);
116
                for (int i = 0; i < line.getNumVertices() - 1; i++) {
117
                    Point point = getPointWithMBetweenTwoMPoints(m, line.getVertex(i), line.getVertex(i + 1));
118
                    if (point != null && !points.contains(point)) {
119
                        points.add(point);
120
                    }
121
                }
122
            }
123
        }
124
        return points;
125
    }
126

    
127
    private static boolean isInRange(double v, double r1, double r2) {
128
        if (r1 < r2) {
129
            return v >= r1 && v <= r2;
130
        } else if (r1 > r2) {
131
            return v >= r2 && v <= r1;
132
        } else {
133
            return v == r1;
134
        }
135
    }
136

    
137
    static MultiLine getLinesBetweenTwoM(Geometry geom, double m1, double m2) throws CreateGeometryException,
138
        LocatorException {
139
        GeometryManager geomManager = GeometryLocator.getGeometryManager();
140

    
141
        MultiLine lines = null;
142
        if (geom instanceof Line) {
143
            lines = getLinesBetweenTwoM((Line) geom, m1, m2);
144
        } else if (geom instanceof MultiLine) {
145
            lines = (MultiLine) geomManager.create(Geometry.TYPES.MULTILINE, geom.getGeometryType().getSubType());
146
            MultiLine multiLine = (MultiLine) geom;
147
            for (int i = 0; i < multiLine.getPrimitivesNumber(); i++) {
148
                MultiLine auxMultiLine = getLinesBetweenTwoM(multiLine.getPrimitiveAt(i), m1, m2);
149
                for (int j = 0; j < auxMultiLine.getPrimitivesNumber(); j++) {
150
                    lines.addPrimitive(auxMultiLine.getPrimitiveAt(j));
151
                }
152
            }
153
        }
154
        return lines;
155
    }
156

    
157
    static private MultiLine getLinesBetweenTwoM(Line line, double m1, double m2) throws CreateGeometryException {
158
        GeometryManager geomManager = GeometryLocator.getGeometryManager();
159
        MultiLine lines = (MultiLine) geomManager.create(Geometry.TYPES.MULTILINE, line.getGeometryType().getSubType());
160
        Line auxLine = (Line) geomManager.create(Geometry.TYPES.LINE, line.getGeometryType().getSubType());
161

    
162
        boolean inSegment = false;
163
        if (line.getNumVertices() > 0) {
164
            int ivertex = 0;
165
            Point previousVertex = null;
166
            while (ivertex < line.getNumVertices()) {
167
                if (!inSegment) { // NO ESTAMOS EN UN SEGMENTO VALIDO
168
                    Point vertex = line.getVertex(ivertex);
169
                    double m = vertex.getCoordinateAt(vertex.getDimension() - 1);
170
                    if (isInRange(m, m1, m2)) {
171
                        // Si la m del vertice actual entra en el rango:
172
                        if (previousVertex == null) {
173
                            // Si no hay previousVertex, este debe ser el primer
174
                            // vertice, entonces
175
                            // - a?adimos el v?rtice a la linea
176
                            // - marcamos que estamos en un segmento valido
177
                            // - nos guardamos el vertice como previousVertex
178
                            // - aumentamos el indice para coger el siguiente
179
                            // v?rtice en la pr?xima iteraci?n
180
                            auxLine.addVertex(vertex);
181
                            previousVertex = vertex;
182
                            inSegment = true;
183
                            ivertex++;
184
                        } else {
185
                            // - Calculamos qu? punto habr?a iniciado el
186
                            // segmento v?lido
187
                            double previousM = previousVertex.getCoordinateAt(previousVertex.getDimension() - 1);
188
                            // FIXME: Esta comprobaci?n se podr?a quitar
189
                            if (isInRange(m1, previousM, m) || isInRange(m2, previousM, m)) {
190
                                Point point = getPointWithMBetweenTwoMPoints(m1, previousVertex, vertex);
191
                                if (point == null) {
192
                                    point = getPointWithMBetweenTwoMPoints(m2, previousVertex, vertex);
193
                                }
194
                                if (point != null) {
195
                                    // - A?adimos el punto a la linea auxiliar
196
                                    // - Marcamos que estamos en un segmento v?lido
197
                                    // - nos guardamos el punto como previousVertex
198
                                    // - y NO aumentamos el indice
199
                                    auxLine.addVertex(point);
200
                                    inSegment = true;
201
                                    previousVertex = point;
202
                                } else {
203
                                    // Nunca deber?a pasar por aqu?
204
                                }
205
                            }
206
                        }
207
                    } else {
208
                        // Cabe la posibilidad de que entre un vertice y otro se
209
                        // entre y se salga del rango
210
                        if (previousVertex != null) {
211
                            double previousM = previousVertex.getCoordinateAt(previousVertex.getDimension() - 1);
212
                            if (isInRange(m1, previousM, m) && isInRange(m2, previousM, m)) {
213
                                Point point1 = getPointWithMBetweenTwoMPoints(m1, previousVertex, vertex);
214
                                Point point2 = getPointWithMBetweenTwoMPoints(m2, previousVertex, vertex);
215
                                auxLine.addVertex(point1);
216
                                auxLine.addVertex(point2);
217
                                lines.addPrimitive(auxLine);
218
                            }
219
                        }
220

    
221
                        // Si la m del v?rtice actual no entra en el rango:
222
                        // - nos guardamos el vertice como previousVertex
223
                        // - aumentamos el indice para coger el siguiente
224
                        // v?rtice en la pr?xima iteraci?n
225
                        previousVertex = vertex;
226
                        ivertex++;
227
                    }
228
                } else { // ESTAMOS EN UN SEGMENTO VALIDO
229
                    Point vertex = line.getVertex(ivertex);
230
                    double m = vertex.getCoordinateAt(previousVertex.getDimension() - 1);
231
                    if (isInRange(m, m1, m2)) {
232
                        // Si la m del vertice actual entra en el rango:
233
                        // - a?adimos el v?rtice a la linea
234
                        // - aumentamos el indice para coger el siguiente
235
                        // v?rtice en la pr?xima iteraci?n
236
                        auxLine.addVertex(vertex);
237
                        previousVertex = vertex;
238
                        ivertex++;
239
                    } else {
240
                        // Si la m del v?rtice actual no entra en el rango:
241
                        // - Calculamos el punto que habr?a finalizado el
242
                        // segmento v?lido entre el vertice anterior y el actual
243
                        Point point = getPointWithMBetweenTwoMPoints(m1, previousVertex, vertex);
244
                        if (point == null) {
245
                            point = getPointWithMBetweenTwoMPoints(m2, previousVertex, vertex);
246
                        }
247
                        if (point != null) {
248
                            // - A?adimos el punto a la linea auxiliar
249
                            // - a?adimos la linea y creamos una nueva
250
                            // - Marcamos que NO estamos en un segmento v?lido
251
                            // - nos guardamos el punto como previousVertex
252
                            // - y NO aumentamos el indice
253
                            auxLine.addVertex(point);
254
                            lines.addPrimitive(auxLine);
255
                            auxLine =
256
                                (Line) geomManager.create(Geometry.TYPES.LINE, line.getGeometryType().getSubType());
257
                            inSegment = false;
258
                            previousVertex = point;
259
                        } else {
260
                            // Nunca deber?a pasar por aqu?
261
                        }
262
                    }
263
                }
264
            }
265
        }
266
        if (inSegment && auxLine.getNumVertices() > 0) {
267
            lines.addPrimitive(auxLine);
268
        }
269
        return lines;
270
    }
271

    
272
    /*
273
     *
274
     */
275
    private static Point getPointWithMBetweenTwoMPoints(double m, Point p1, Point p2) throws CreateGeometryException,
276
        LocatorException {
277
        double x;
278
        double y;
279
        double m1 = p1.getCoordinateAt(p1.getDimension() - 1);
280
        double m2 = p2.getCoordinateAt(p2.getDimension() - 1);
281

    
282
        if (m1 <= m2) {
283
            if (m < m1 || m > m2) {
284
                return null;
285
            }
286
        } else {
287
            if (m < m2 || m > m1) {
288
                return null;
289
            }
290
        }
291

    
292
        double x1 = p1.getX();
293
        double x2 = p2.getX();
294
        double y1 = p1.getY();
295
        double y2 = p2.getY();
296
        if (x1 == x2) {
297
            x = x1;
298
        } else {
299
            x = ((x2 - x1) * (m - m1) / (m2 - m1)) + x1;
300
        }
301
        if (y1 == y2) {
302
            y = y1;
303
        } else {
304
            y = ((y2 - y1) * (m - m1) / (m2 - m1)) + y1;
305
        }
306

    
307
        Point point = (Point) GeometryLocator.getGeometryManager().create(p1.getGeometryType());
308
        point.setX(x);
309
        point.setY(y);
310
        point.setCoordinateAt(point.getDimension() - 1, m);
311
        return point;
312
    }
313

    
314

    
315

    
316
    /**
317
     * Returns geometry length without gaps
318
     * @param geometry
319
     * @return
320
     * @throws GeometryOperationNotSupportedException
321
     * @throws GeometryOperationException
322
     */
323
    static protected Double getGeometryLength(Geometry geometry) throws GeometryOperationNotSupportedException, GeometryOperationException{
324
        return getGeometryLength(geometry, true);
325
    }
326

    
327
    /**
328
     * Returns geometry length without gaps with the option to not ignore spatial gaps.
329
     * @param geometry
330
     * @param ignoreSpatialGaps
331
     * @return
332
     * @throws GeometryOperationNotSupportedException
333
     * @throws GeometryOperationException
334
     */
335
    static protected Double getGeometryLength(Geometry geometry,
336
        boolean ignoreSpatialGaps)
337
            throws GeometryOperationNotSupportedException,
338
            GeometryOperationException {
339
        if (geometry instanceof Line) {
340
            Line line = (Line) geometry;
341
            return getLineLength(line);
342
        }
343
        if (geometry instanceof MultiLine) {
344
            MultiLine multiLine = (MultiLine) geometry;
345
            return getMultiLineLength(multiLine, ignoreSpatialGaps);
346
        }
347
        return Double.NaN;
348
    }
349

    
350
    /**
351
     * @param line
352
     * @return lenght
353
     * @throws GeometryOperationException
354
     * @throws GeometryOperationNotSupportedException
355
     */
356
    static protected double getLineLength(Line line)
357
        throws GeometryOperationNotSupportedException,
358
        GeometryOperationException {
359
        double lenght = 0;
360
        Point previousVertex = null;
361
        for (int i = 0; i < line.getNumVertices(); i++) {
362
            Point vertex = line.getVertex(i);
363
            if (previousVertex != null) {
364
                lenght += previousVertex.distance(vertex);
365
            }
366
            previousVertex = vertex;
367
        }
368
        return lenght;
369
    }
370

    
371
    /**
372
     * @param multiLine
373
     * @return lenght
374
     * @throws GeometryOperationException
375
     * @throws GeometryOperationNotSupportedException
376
     */
377
    static protected double getMultiLineLength(MultiLine multiLine,
378
        boolean ignoreSpatialGaps)
379
            throws GeometryOperationNotSupportedException,
380
            GeometryOperationException {
381
        double length = 0;
382
        Point previousVertex = null;
383
        for (int j = 0; j < multiLine.getPrimitivesNumber(); j++) {
384
            Line line = (Line) multiLine.getPrimitiveAt(j);
385
            if (ignoreSpatialGaps) {
386
                previousVertex = null;
387
            }
388
            for (int i = 0; i < line.getNumVertices(); i++) {
389
                Point vertex = line.getVertex(i);
390
                if (previousVertex != null) {
391
                    length += previousVertex.distance(vertex);
392
                }
393
                previousVertex = vertex;
394
            }
395
        }
396
        return length;
397
    }
398

    
399
    /**
400
     * Extracts the lines in a Line or Multiline
401
     * @param geometry
402
     * @return
403
     */
404
    static protected List<Line> extractLines(Geometry geometry){
405
        List<Line> lines=new ArrayList<Line>();
406
        if (geometry instanceof  Line){
407
            lines.add((Line) geometry);
408
        }
409
        if (geometry instanceof MultiLine){
410
            MultiLine multiline=(MultiLine)geometry;
411
            for (int i=0;i<multiline.getPrimitivesNumber();i++){
412
                lines.add((Line) multiline.getPrimitiveAt(i));
413
            }
414
        }
415
        return lines;
416
    }
417

    
418
    static protected List<Point> extractPoints(Geometry geometry){
419
        List<Point> points=new ArrayList<Point>();
420
        List<Line> lines=LrsAlgorithmUtils.extractLines(geometry);
421
        for (Line line: lines){
422
            for (int i=0;i<line.getNumVertices();i++){
423
                points.add(line.getVertex(i));
424
            }
425
        }
426
        return points;
427
    }
428

    
429

    
430
    static protected Point extractFirstPoint(Geometry geometry){
431
        Point firstPoint=null;
432
        List<Line> lines= LrsAlgorithmUtils.extractLines(geometry);
433
        if (lines!=null && !lines.isEmpty()){
434
            firstPoint=lines.get(0).getVertex(0);
435
        }
436
        return firstPoint;
437
    }
438

    
439
    static protected boolean equalPoints(Point point1, Point point2){
440
        if ( point1.getX()==point2.getX() && point1.getY()==point2.getY()){
441
            return true;
442
        }
443
        return false;
444
    }
445

    
446
    static protected Geometry insertVertex(Geometry geometry, Point vertex, int index){
447
        if (geometry instanceof Line){
448
            Line line=(Line)geometry;
449
            line.insertVertex(index, vertex);
450
        }
451
        if (geometry instanceof MultiLine){
452
            List<Line> lines=extractLines(geometry);
453
            for(Line line:lines){
454
                if (index<=line.getNumVertices()){
455
                    line.insertVertex(index, vertex);
456
                    return geometry;
457
                }else{
458
                    index-=line.getNumVertices();
459
                }
460

    
461
            }
462
        }
463
        return geometry;
464
    }
465

    
466
    /**
467
     * Reduced versi?n of straight line through two points equation to calculate M's
468
     *
469
     * @param totalLength
470
     * @param minValue
471
     * @param maxValue
472
     * @param relativeDistance
473
     * @return
474
     */
475
    static protected double calculateM(Double totalLength, Double minValue, Double maxValue, Double relativeDistance) {
476
        return LrsAlgorithmUtils.straightLineThroughTwoPointsEquation(0, totalLength, minValue, maxValue, relativeDistance);
477
    }
478

    
479
    /**
480
     * Straight line through two points equation.
481
     *
482
     * @param x1
483
     * @param x2
484
     * @param y1
485
     * @param y2
486
     * @param x
487
     * @return
488
     */
489
    static protected double straightLineThroughTwoPointsEquation(double x1, double x2, double y1, double y2, double x) {
490
        if (x2 - x1 == 0.0) {
491
            return Double.POSITIVE_INFINITY;
492
        }
493
        return ((y2 - y1) * (x - x1) / (x2 - x1)) + y1;
494
    }
495

    
496
}