Revision 81

View differences:

org.gvsig.lrs/tags/org.gvsig.lrs-1.0.3/org.gvsig.lrs.lib/org.gvsig.lrs.lib.impl/pom.xml
1
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
2
  <modelVersion>4.0.0</modelVersion>
3
  <parent>
4
    <groupId>org.gvsig</groupId>
5
    <artifactId>org.gvsig.lrs.lib</artifactId>
6
    <version>1.0.3</version>
7
  </parent>
8
  <groupId>org.gvsig</groupId>
9
  <artifactId>org.gvsig.lrs.lib.impl</artifactId>
10
  <version>1.0.3</version>
11
  <name>org.gvsig.lrs.lib.impl</name>
12
  <dependencies>
13
    <dependency>
14
      <groupId>org.gvsig</groupId>
15
      <artifactId>org.gvsig.lrs.lib.api</artifactId>
16
    </dependency>
17
    <dependency>
18
      <groupId>org.gvsig</groupId>
19
      <artifactId>org.gvsig.fmap.dal.api</artifactId>
20
    </dependency>
21
    <dependency>
22
     <groupId>org.gvsig</groupId>
23
     <artifactId>org.gvsig.fmap.dal.file.shp</artifactId>
24
    </dependency>
25
  </dependencies>
26
</project>
org.gvsig.lrs/tags/org.gvsig.lrs-1.0.3/org.gvsig.lrs.lib/org.gvsig.lrs.lib.impl/src/main/resources/META-INF/services/org.gvsig.tools.library.Library
1
org.gvsig.lrs.lib.impl.DefaultLrsAlgorithmsLibrary
0 2

  
org.gvsig.lrs/tags/org.gvsig.lrs-1.0.3/org.gvsig.lrs.lib/org.gvsig.lrs.lib.impl/src/main/java/org/gvsig/lrs/lib/impl/DefaultLrsEditRouteCalibrationSelectIdRouteAlgorithmParams.java
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 org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
26
import org.gvsig.fmap.dal.feature.FeatureStore;
27
import org.gvsig.fmap.dal.feature.NewFeatureStoreParameters;
28
import org.gvsig.lrs.lib.api.DistanceUnits;
29
import org.gvsig.lrs.lib.api.LrsCalibrateRouteAlgorithmParams;
30
import org.gvsig.lrs.lib.api.LrsEditRouteCalibrationSelectIdRouteAlgorithmParams;
31
import org.gvsig.lrs.lib.api.LrsMeasureCalculationMethods;
32

  
33

  
34
/**
35
 * @author dmartinez
36
 *
37
 */
38
public class DefaultLrsEditRouteCalibrationSelectIdRouteAlgorithmParams implements LrsEditRouteCalibrationSelectIdRouteAlgorithmParams {
39

  
40
    private FeatureAttributeDescriptor idRouteField;
41
    private final String NAME = "LrsEditRouteCalibrationSelectIdRouteAlgorithm";
42
    private final String DESCRIPTION = "Algorithm to select id route to edit calibration with linear reference system.";
43

  
44

  
45
    /* (non-Javadoc)
46
     * @see org.gvsig.lrs.lib.api.LrsAlgorithmParams#getName()
47
     */
48
    public String getName() {
49
        return NAME;
50
    }
51

  
52
    /* (non-Javadoc)
53
     * @see org.gvsig.lrs.lib.api.LrsAlgorithmParams#getDescription()
54
     */
55
    public String getDescription() {
56
        return DESCRIPTION;
57
    }
58

  
59
    /*
60
     * (non-Javadoc)
61
     * @see org.gvsig.lrs.lib.api.LrsCreateRouteAlgorithmParams#getIdRouteField()
62
     */
63
    public FeatureAttributeDescriptor getIdRouteField() {
64
        return idRouteField;
65
    }
66

  
67
    /*
68
     * (non-Javadoc)
69
     * @see org.gvsig.lrs.lib.api.LrsCreateRouteAlgorithmParams#setIdRouteField(org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor)
70
     */
71
    public void setIdRouteField(FeatureAttributeDescriptor idRouteField) {
72
        this.idRouteField = idRouteField;
73
    }
74

  
75
}
org.gvsig.lrs/tags/org.gvsig.lrs-1.0.3/org.gvsig.lrs.lib/org.gvsig.lrs.lib.impl/src/main/java/org/gvsig/lrs/lib/impl/DefaultLrsAlgorithmsManager.java
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 org.gvsig.lrs.lib.api.MeasuresCalculator;
26

  
27
import java.util.List;
28

  
29
import org.apache.commons.lang3.StringUtils;
30
import org.cresques.cts.IProjection;
31

  
32
import org.gvsig.fmap.dal.DALLocator;
33
import org.gvsig.fmap.dal.DataManager;
34
import org.gvsig.fmap.dal.DataServerExplorer;
35
import org.gvsig.fmap.dal.DataServerExplorerParameters;
36
import org.gvsig.fmap.dal.DataStoreParameters;
37
import org.gvsig.fmap.dal.exception.DataException;
38
import org.gvsig.fmap.dal.exception.InitializeException;
39
import org.gvsig.fmap.dal.exception.ProviderNotRegisteredException;
40
import org.gvsig.fmap.dal.exception.ValidateDataParametersException;
41
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
42
import org.gvsig.fmap.dal.feature.EditableFeatureType;
43
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
44
import org.gvsig.fmap.dal.feature.FeatureStore;
45
import org.gvsig.fmap.dal.feature.FeatureType;
46
import org.gvsig.fmap.dal.feature.NewFeatureStoreParameters;
47
import org.gvsig.fmap.geom.DataTypes;
48
import org.gvsig.fmap.geom.Geometry;
49
import org.gvsig.fmap.geom.GeometryLocator;
50
import org.gvsig.fmap.geom.GeometryManager;
51
import org.gvsig.fmap.geom.exception.CreateGeometryException;
52
import org.gvsig.fmap.geom.operation.GeometryOperationException;
53
import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException;
54
import org.gvsig.fmap.geom.primitive.Line;
55
import org.gvsig.fmap.geom.primitive.Point;
56
import org.gvsig.fmap.geom.type.GeometryType;
57
import org.gvsig.fmap.geom.type.GeometryTypeNotSupportedException;
58
import org.gvsig.fmap.geom.type.GeometryTypeNotValidException;
59
import org.gvsig.lrs.lib.api.LrsAlgorithm;
60
import org.gvsig.lrs.lib.api.LrsAlgorithmParams;
61
import org.gvsig.lrs.lib.api.LrsAlgorithmsManager;
62
import org.gvsig.lrs.lib.api.LrsCalibrateRouteAlgorithmParams;
63
import org.gvsig.lrs.lib.api.LrsCreateRouteAlgorithmParams;
64
import org.gvsig.lrs.lib.api.LrsEditRouteCalibrationAlgorithmParams;
65
import org.gvsig.lrs.lib.api.LrsEditRouteCalibrationSelectIdRouteAlgorithmParams;
66
import org.gvsig.lrs.lib.api.LrsGenerateDynamicSegmentationAlgorithmParams;
67
import org.gvsig.lrs.lib.api.LrsShowMeasuresAlgorithmParams;
68
import org.gvsig.tools.dynobject.DynObject;
69
import org.gvsig.tools.locator.LocatorException;
70
import org.gvsig.tools.service.Service;
71
import org.gvsig.tools.service.ServiceException;
72

  
73

  
74
/**
75
 * @author fdiaz
76
 *
77
 */
78
public class DefaultLrsAlgorithmsManager implements LrsAlgorithmsManager {
79

  
80
    /* (non-Javadoc)
81
     * @see org.gvsig.tools.service.Manager#createServiceParameters(java.lang.String)
82
     */
83
    public DynObject createServiceParameters(String serviceName) throws ServiceException {
84
        // TODO Auto-generated method stub
85
        return null;
86
    }
87

  
88
    /* (non-Javadoc)
89
     * @see org.gvsig.tools.service.Manager#getService(org.gvsig.tools.dynobject.DynObject)
90
     */
91
    public Service getService(DynObject parameters) throws ServiceException {
92
        // TODO Auto-generated method stub
93
        return null;
94
    }
95

  
96
    /* (non-Javadoc)
97
     * @see org.gvsig.lrs.lib.api.LrsAlgorithmsManager#createLrsAlgorithm(org.gvsig.lrs.lib.api.LrsAlgorithmParams)
98
     */
99
    public LrsAlgorithm createLrsAlgorithm(LrsAlgorithmParams params) {
100
        if(params instanceof LrsCreateRouteAlgorithmParams){
101
            return new LrsCreateRouteAlgorithm((LrsCreateRouteAlgorithmParams)params);
102
        }
103
        if(params instanceof LrsCalibrateRouteAlgorithmParams){
104
            return new LrsCalibrateRouteAlgorithm((LrsCalibrateRouteAlgorithmParams)params);
105
        }
106
        if(params instanceof LrsGenerateDynamicSegmentationAlgorithmParams){
107
            return new LrsGenerateDynamicSegmentationAlgorithm((LrsGenerateDynamicSegmentationAlgorithmParams)params);
108
        }
109
        return null;
110
    }
111

  
112
    /* (non-Javadoc)
113
     * @see org.gvsig.lrs.lib.api.LrsAlgorithmsManager#createLrsCreateRouteAlgorithmParams()
114
     */
115
    public LrsCreateRouteAlgorithmParams createLrsCreateRouteAlgorithmParams() {
116
        return new DefaultLrsCreateRouteAlgorithmParams();
117
    }
118

  
119
    /* (non-Javadoc)
120
     * @see org.gvsig.lrs.lib.api.LrsAlgorithmsManager#createLrsCalibrateRouteAlgorithmParams()
121
     */
122
    public LrsCalibrateRouteAlgorithmParams createLrsCalibrateRouteAlgorithmParams() {
123
        return new DefaultLrsCalibrateRouteAlgorithmParams();
124
    }
125

  
126
    /* (non-Javadoc)
127
     * @see org.gvsig.lrs.lib.api.LrsAlgorithmsManager#createLrsEditRouteCalibrationAlgorithmParams()
128
     */
129
    public LrsEditRouteCalibrationAlgorithmParams createLrsEditRouteCalibrationAlgorithmParams() {
130
        return new DefaultLrsEditRouteCalibrationAlgorithmParams();
131
    }
132

  
133
    /* (non-Javadoc)
134
     * @see org.gvsig.lrs.lib.api.LrsAlgorithmsManager#createLrsEditRouteCalibrationSelectIdRouteAlgorithmParams()
135
     */
136
    public LrsEditRouteCalibrationSelectIdRouteAlgorithmParams createLrsEditRouteCalibrationSelectIdRouteAlgorithmParams() {
137
        return new DefaultLrsEditRouteCalibrationSelectIdRouteAlgorithmParams();
138
    }
139

  
140
    /* (non-Javadoc)
141
     * @see org.gvsig.lrs.lib.api.LrsAlgorithmsManager#createLrsShowMeasuresAlgorithmParams()
142
     */
143
    public LrsShowMeasuresAlgorithmParams createLrsShowMeasuresAlgorithmParams() {
144
        return new DefaultLrsShowMeasuresAlgorithmParams();
145
    }
146

  
147

  
148
    /* (non-Javadoc)
149
     * @see org.gvsig.lrs.lib.api.LrsAlgorithmsManager#createLrsGenerateDynamicSegmentationAlgorithmParams()
150
     */
151
    public LrsGenerateDynamicSegmentationAlgorithmParams createLrsGenerateDynamicSegmentationAlgorithmParams() {
152
        return new DefaultLrsGenerateDynamicSegmentationAlgorithmParams();
153
    }
154

  
155

  
156
    public void createNewShape(FeatureType sourceFeatureType,
157
        int outputLayerType, String outputLayerPath, IProjection projection) throws ValidateDataParametersException, DataException, GeometryTypeNotSupportedException, GeometryTypeNotValidException {
158

  
159
        DataManager dataManager = DALLocator.getDataManager();
160
        DataServerExplorerParameters eparams =
161
            dataManager.createServerExplorerParameters("FilesystemExplorer");
162
        eparams.setDynValue("initialpath", "/data");
163
        DataServerExplorer serverExplorer =
164
            dataManager.openServerExplorer(eparams.getExplorerName(), eparams);
165

  
166
        NewFeatureStoreParameters sparams =
167
            (NewFeatureStoreParameters) serverExplorer
168
                .getAddParameters("Shape");
169

  
170
        EditableFeatureType newEditableFeatureType =
171
            (EditableFeatureType) sparams.getDefaultFeatureType();
172

  
173
        // Iterate over feature type. Don't add geometry fields.
174
        for (int i = 0; i < sourceFeatureType.size(); i++) {
175
            String fieldName =
176
                sourceFeatureType.getAttributeDescriptor(i).getName();
177
            int fieldType =
178
                sourceFeatureType.getAttributeDescriptor(i).getType();
179
            if (fieldType != DataTypes.GEOMETRY) {
180
                newEditableFeatureType.add(fieldName, fieldType);
181
            }
182
        }
183

  
184
        // Add new geometry field with new geometry type
185
        FeatureAttributeDescriptor geometryAttribute =
186
            (FeatureAttributeDescriptor) sourceFeatureType
187
                .get(sourceFeatureType.getDefaultGeometryAttributeName());
188
        EditableFeatureAttributeDescriptor newGeometryAttribute =
189
            newEditableFeatureType.add(geometryAttribute.getName(),
190
                geometryAttribute.getType(), geometryAttribute.getSize());
191

  
192
        GeometryManager geoManager = GeometryLocator.getGeometryManager();
193
        GeometryType sourceLayerGeomType =
194
            sourceFeatureType.getDefaultGeometryAttribute().getGeomType();
195
        GeometryType outputLayerGeomType =
196
            geoManager.getGeometryType(outputLayerType,
197
                sourceLayerGeomType.getSubType());
198

  
199
        newGeometryAttribute.setGeometryType(outputLayerGeomType);
200
        newGeometryAttribute.setPrecision(geometryAttribute.getPrecision());
201
        newGeometryAttribute.setDefaultValue(geometryAttribute
202
            .getDefaultValue());
203

  
204
        newEditableFeatureType
205
            .setDefaultGeometryAttributeName(geometryAttribute.getName());
206

  
207
        if(!StringUtils.endsWithIgnoreCase(outputLayerPath, ".shp")){
208
            outputLayerPath = new StringBuilder().append(outputLayerPath).append(".shp").toString();
209
        }
210

  
211
        sparams.setDynValue("geometryType", null);
212
        sparams.setDynValue("shpfile", outputLayerPath);
213
        sparams.setDynValue("CRS", projection);
214
        sparams.setDynValue("useNullGeometry", false);
215
        sparams.setDefaultFeatureType(newEditableFeatureType);
216
        sparams.validate();
217

  
218
        serverExplorer.add("Shape", sparams, true);
219
    }
220

  
221
    public FeatureStore getFeatureStore(String outputLayerPath,
222
        IProjection projection) throws InitializeException, ProviderNotRegisteredException, ValidateDataParametersException{
223

  
224
        DataManager dataManager = DALLocator.getDataManager();
225
        DataStoreParameters dataStoreParams =
226
            dataManager.createStoreParameters("Shape");
227
        dataStoreParams.setDynValue("shpfile", outputLayerPath);
228
        dataStoreParams.setDynValue("CRS", projection);
229
        dataStoreParams.setDynValue("useNullGeometry", false);
230
        dataStoreParams.validate();
231

  
232
        return (FeatureStore) dataManager.openStore("Shape", dataStoreParams);
233
    }
234

  
235
    public MeasuresCalculator createMeasuresCalculator(Geometry geometry, boolean ignoreSpatialGaps) {
236
        return new DefaultMeasuresCalculator(geometry, ignoreSpatialGaps);
237
    }
238

  
239
    @Override
240
    public Point getMPointFromGeometry(Geometry geom, double m) throws CreateGeometryException, LocatorException {
241
        List<Point> points = LrsAlgorithmUtils.getPointsWithM( geom,  m);
242
        if (points!=null && !points.isEmpty()){
243
            return points.get(0);
244
        }
245
        return null;
246
    }
247

  
248
    /**
249
     * Given a point without m in a M-Geometry, returns the point with the m-value
250
     * @param geom
251
     * @param pointNoM
252
     * @return
253
     * @throws GeometryOperationException
254
     * @throws GeometryOperationNotSupportedException
255
     * @throws CreateGeometryException
256
     */
257
    @Override
258
    public Point getMPointFromGeometry(Geometry geom, Point pointNoM) throws CreateGeometryException, GeometryOperationNotSupportedException, GeometryOperationException{
259
        final Double PRECISION = new Double(1.0e-5);
260
        final int MDIMENSION = geom.getDimension() - 1;
261

  
262
        List<Line> lines = LrsAlgorithmUtils.extractLines(geom);
263
        for (int i = 0; i < lines.size(); i++) {
264
            Line line = lines.get(i);
265

  
266
            if (line.isWithinDistance(pointNoM, PRECISION)) {
267
                for (int j = 0; j < line.getNumVertices(); j++) {
268
                    Point vertex = line.getVertex(j);
269
                    Point nextVertex;
270
                    if (j + 1 < line.getNumVertices()) {
271
                        nextVertex = line.getVertex(j + 1);
272
                    } else {
273
                        nextVertex = null;
274
                    }
275
                    //The point and the first vertex are the same
276
                    if (LrsAlgorithmUtils.equalPoints(vertex, pointNoM) || vertex.distance(pointNoM) <= PRECISION) {
277
                        Double m=vertex.getCoordinateAt(MDIMENSION);
278
                        GeometryManager geomanager = GeometryLocator.getGeometryManager();
279
                        Point mPoint = (Point) geomanager
280
                                .create(Geometry.TYPES.POINT, Geometry.SUBTYPES.GEOM2DM);
281
                        mPoint.setX(pointNoM.getX());
282
                        mPoint.setY(pointNoM.getY());
283
                        mPoint.setCoordinateAt(MDIMENSION, m);
284
                        return mPoint;
285
                    }else{
286
                        if (nextVertex != null
287
                            && !LrsAlgorithmUtils.equalPoints(nextVertex, pointNoM)
288
                            && vertex.distance(pointNoM) > PRECISION
289
                            && nextVertex.distance(pointNoM) > PRECISION) {
290

  
291
                            GeometryManager geomanager = GeometryLocator.getGeometryManager();
292
                            Line segment = (Line) geomanager
293
                                    .create(Geometry.TYPES.LINE, Geometry.SUBTYPES.GEOM2DM);
294
                            segment.addVertex(vertex);
295
                            segment.addVertex(nextVertex);
296
                            if (segment.isWithinDistance(pointNoM, PRECISION)) {
297
                                double distanceFirstVertex = 0;
298
                                double distanceNextVertex = nextVertex.distance(vertex);
299
                                double distanceToFixedPoint = vertex.distance(pointNoM);
300

  
301
                                Double m = LrsAlgorithmUtils.straightLineThroughTwoPointsEquation(
302
                                    distanceFirstVertex,
303
                                    distanceNextVertex,
304
                                    vertex.getCoordinateAt(MDIMENSION),
305
                                    nextVertex.getCoordinateAt(MDIMENSION),
306
                                    distanceToFixedPoint);
307

  
308
                                Point mPoint = (Point) geomanager
309
                                        .create(Geometry.TYPES.POINT, Geometry.SUBTYPES.GEOM2DM);
310
                                mPoint.setX(pointNoM.getX());
311
                                mPoint.setY(pointNoM.getY());
312
                                mPoint.setCoordinateAt(MDIMENSION, m);
313
                                return mPoint;
314
                            }
315
                        }
316
                    }
317
                }
318
            }
319

  
320
        }
321
        return null;
322

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

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

  
33
import org.apache.commons.lang3.mutable.MutableInt;
34
import org.slf4j.Logger;
35
import org.slf4j.LoggerFactory;
36

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

  
72
/**
73
 * @author fdiaz
74
 *
75
 */
76
public class LrsCreateRouteAlgorithm implements LrsAlgorithm {
77

  
78
    private static final Logger logger = LoggerFactory.getLogger(LrsCreateRouteAlgorithm.class);
79

  
80
    private LrsCreateRouteAlgorithmParams parameters;
81

  
82
    /**
83
     *
84
     */
85
    public LrsCreateRouteAlgorithm(LrsCreateRouteAlgorithmParams parameters) {
86
        this.parameters = parameters;
87

  
88
    }
89

  
90
    /*
91
     * (non-Javadoc)
92
     *
93
     * @see org.gvsig.tools.service.Service#getManager()
94
     */
95
    public Manager getManager() {
96
        return null;
97
    }
98

  
99
    /*
100
     * (non-Javadoc)
101
     *
102
     * @see org.gvsig.lrs.lib.api.LrsAlgorithm#getParams()
103
     */
104
    public LrsAlgorithmParams getParams() {
105
        return this.parameters;
106
    }
107

  
108
    /*
109
     * (non-Javadoc)
110
     *
111
     * @see org.gvsig.lrs.lib.api.LrsAlgorithm#execute(org.gvsig.tools.task.
112
     * SimpleTaskStatus)
113
     */
114
    public void execute(SimpleTaskStatus taskStatus) throws LrsException {
115
        NewFeatureStoreParameters newFeatureStoreParameters = parameters.getNewFeatureStoreParameters();
116
        FeatureStore sourceFeatureStore = parameters.getSourceFeatureStore();
117
        FeatureAttributeDescriptor idRouteField = parameters.getIdRouteField();
118
        FeatureAttributeDescriptor fromMeasureField = parameters.getFromMeasureField();
119
        FeatureAttributeDescriptor toMeasureField = parameters.getToMeasureField();
120

  
121
        logger.info(parameters.toString());
122

  
123
        taskStatus.setTitle(parameters.getName());
124
        I18nManager i18nManager = ToolsLocator.getI18nManager();
125
        taskStatus.message(i18nManager.getTranslation("grouping_features"));
126

  
127
        try {
128
            final String routeFieldName = idRouteField.getName();
129
            final String fromFieldName;
130
            final DataType fromDataType;
131
            final DataType toDataType;
132
            if (fromMeasureField != null) {
133
                fromFieldName = fromMeasureField.getName();
134
                fromDataType = fromMeasureField.getDataType();
135
            } else {
136
                fromFieldName = null;
137
                fromDataType = null;
138
            }
139
            final String toFieldName;
140
            if (toMeasureField != null) {
141
                toFieldName = toMeasureField.getName();
142
                toDataType = toMeasureField.getDataType();
143
            } else {
144
                toFieldName = null;
145
                toDataType = null;
146
            }
147

  
148
            FeatureStore newFeatureStore =
149
                LrsAlgorithmUtils.createNewDataStore(newFeatureStoreParameters, idRouteField);
150

  
151
            FeatureSet sourceFeatures;
152
            if (sourceFeatureStore.getFeatureSelection().getSize() > 0) {
153
                sourceFeatures = sourceFeatureStore.getFeatureSelection();
154
            } else {
155
                sourceFeatures = sourceFeatureStore.getFeatureSet();
156
            }
157

  
158
            final SortedMap<String, List<MSegment>> featuresMap = new TreeMap<String, List<MSegment>>();
159
            final MutableInt contId = new MutableInt(0);
160
            sourceFeatures.accept(new Visitor() {
161

  
162
                public void visit(Object obj) throws VisitCanceledException, BaseException {
163
                    Feature feature = (Feature) obj;
164
                    String routeName = (String) feature.get(routeFieldName);
165
                    Object objFrom = null;
166
                    Object objTo = null;
167
                    if (fromFieldName != null) {
168
                        objFrom = feature.get(fromFieldName);
169
                    }
170
                    if (toFieldName != null) {
171
                        objTo = feature.get(toFieldName);
172
                    }
173
                    if (!featuresMap.containsKey(routeName)) {
174
                        featuresMap.put(routeName, new ArrayList<MSegment>());
175
                    }
176
                    List<MSegment> mList = featuresMap.get(routeName);
177
                    MSegment mSegment = new MSegment();
178
                    mSegment.geometry = feature.getDefaultGeometry().cloneGeometry();
179
                    mSegment.fromValue = LrsAlgorithmUtils.getAsDouble(objFrom, fromDataType);
180
                    mSegment.toValue = LrsAlgorithmUtils.getAsDouble(objTo, toDataType);
181
                    mSegment.id = contId.getValue();
182
                    contId.increment();
183
                    mList.add(mSegment);
184
                    featuresMap.put(routeName, mList);
185
                }
186
            });
187

  
188
            taskStatus.setRangeOfValues(0, featuresMap.size());
189
            int taskCount = 0;
190

  
191
            newFeatureStore.edit(FeatureStore.MODE_FULLEDIT);
192

  
193
            for (Entry<String, List<MSegment>> entry : featuresMap.entrySet()) {
194
                String routeName = entry.getKey();
195
                List<MSegment> mList = entry.getValue();
196

  
197
                EditableFeature newFeature = newFeatureStore.createNewFeature(true);
198
                newFeature.set(routeFieldName, routeName);
199
                Geometry route = createGeometryRoute(mList);
200
                newFeature.setDefaultGeometry(route);
201

  
202
                newFeatureStore.update(newFeature);
203

  
204
                taskCount++;
205
                taskStatus.setCurValue(taskCount);
206

  
207
            }
208
            newFeatureStore.finishEditing();
209

  
210
        } catch (Exception e1) {
211
            taskStatus.abort();
212
            throw new LrsCreateRouteException("Error creating routes", e1);
213
        }
214

  
215
        taskStatus.terminate();
216

  
217
    }
218

  
219
    private Geometry createGeometryRoute(List<MSegment> mList) throws CreateGeometryException,
220
        GeometryOperationNotSupportedException, GeometryOperationException, CreateEnvelopeException {
221
        LrsSourceOfMeasures sourceOfMeasures = parameters.getSourceOfMeasures();
222
        Geometry geometryResult = null;
223
        simplifyMultilines(mList);
224
        switch (sourceOfMeasures) {
225
        case ONE_FIELD:
226
            geometryResult = calculateGeometryByOneField(mList);
227
            break;
228
        case TWO_FIELDS:
229
            geometryResult = calculateGeometryByTwoField(mList);
230
            break;
231
        case LENGTH:
232
        default:
233
            geometryResult = calculateGeometryByLength(mList);
234
            break;
235
        }
236
        geometryResult = applyOffsetAndFactor(geometryResult);
237
        return geometryResult;
238
    }
239

  
240
    private Geometry calculateGeometryByLength(List<MSegment> mList) throws CreateGeometryException,
241
        GeometryOperationNotSupportedException, GeometryOperationException, CreateEnvelopeException {
242
        boolean ignoreSpatialGaps = parameters.ignoreSpatialGaps();
243
        for (MSegment mSegment : mList) {
244
            mSegment.fromValue = LrsAlgorithmUtils.getGeometryLength(mSegment.geometry, ignoreSpatialGaps);
245
        }
246
        return calculateGeometryByOneField(mList);
247
    }
248

  
249
    private Geometry calculateGeometryByOneField(List<MSegment> mList) throws CreateGeometryException,
250
        GeometryOperationNotSupportedException, GeometryOperationException, CreateEnvelopeException {
251
        boolean ignoreSpatialGaps = parameters.ignoreSpatialGaps();
252
        GeometryManager gmanager = GeometryLocator.getGeometryManager();
253
        try {
254
            mList = sortMList(mList);
255
        } catch (Exception e) {
256
            logger.warn("Geometries couldn't be ordered");
257
        }
258

  
259
        MultiLine auxMultiLine = (MultiLine) gmanager.create(Geometry.TYPES.MULTILINE, Geometry.SUBTYPES.GEOM2DM);
260

  
261
        Point previousPoint = null;
262
        double previousM = 0.0;
263
        for (MSegment mSegment : mList) {
264
            Geometry geom = mSegment.geometry;
265
            Double geometryLength = mSegment.getLength(ignoreSpatialGaps);
266
            if (geom instanceof Line) {
267
                Line line = (Line) geom;
268
                Line auxLine = (Line) gmanager.create(Geometry.TYPES.LINE, Geometry.SUBTYPES.GEOM2DM);
269
                double distance = 0.0;
270
                double firstM = previousM;
271
                for (int i = 0; i < line.getNumVertices(); i++) {
272
                    Point vertex = line.getVertex(i);
273
                    Point point = (Point) gmanager.create(Geometry.TYPES.POINT, Geometry.SUBTYPES.GEOM2DM);
274
                    point.setX(vertex.getX());
275
                    point.setY(vertex.getY());
276
                    if (i == 0 && previousPoint != null) {
277
                        boolean gap = false;
278
                        if (areInSame2DLocation(previousPoint, vertex)) {
279
                            // Buscamos si ha sido una bifurcaci?n
280
                            Point fork = getPossibleFork(auxMultiLine, vertex);
281
                            if(fork!=null){
282
                                previousPoint = fork;
283
                                // OJO, aqu? previousPoint pasa a ser 2DM
284
                            }
285
                        } else {
286
                            // En caso de salto, calculamos el previousPoint
287
                            // buscando el v?rtice m?s cercano
288
                            previousPoint = getClosestVertex(auxMultiLine, vertex);
289
                            // OJO, aqu? previousPoint pasa a ser 2DM
290
                            gap = true;
291
                        }
292
                        previousM = previousPoint.getCoordinateAt(previousPoint.getDimension() - 1);
293
                        if (i == 0) {
294
                            firstM = previousM;
295
                        }
296
                        if (gap && !ignoreSpatialGaps) {
297
                            Point previousVertex = getPreviousVertexToPoint(auxMultiLine, previousPoint);
298
                            if(areInSame2DLocation(previousPoint,previousVertex)){
299
                                Point nextVertex = getNextVertexToPoint(auxMultiLine, previousPoint);
300
                                double distanceToNextPoint = nextVertex.distance(previousPoint);
301
                                previousM = LrsAlgorithmUtils.straightLineThroughTwoPointsEquation(0, distanceToNextPoint,
302
                                    previousM, nextVertex.getCoordinateAt(previousVertex.getDimension() - 1),
303
                                        previousPoint.distance(point));
304
                            } else {
305
                                double distanceToPreviousPoint = previousVertex.distance(previousPoint);
306
                                previousM = LrsAlgorithmUtils.straightLineThroughTwoPointsEquation(0, distanceToPreviousPoint,
307
                                        previousVertex.getCoordinateAt(previousVertex.getDimension() - 1), previousM,
308
                                        distanceToPreviousPoint + previousPoint.distance(point));
309
                            }
310
                            firstM = previousM;
311
                        }
312
                    }
313
                    if (i != 0) {
314
                        distance += previousPoint.distance(vertex);
315
                    }
316
                    double m =
317
                        LrsAlgorithmUtils.straightLineThroughTwoPointsEquation(0, geometryLength, firstM, firstM + mSegment.fromValue,
318
                            distance);
319
                    point.setCoordinateAt(point.getDimension() - 1, m);
320
                    auxLine.addVertex(point);
321
                    previousM = m;
322
                    previousPoint = vertex;
323
                }
324
                auxMultiLine.addPrimitive(auxLine);
325
            } else if (geom instanceof MultiLine) {
326
                MultiLine multiline = (MultiLine) geom;
327
                for (int i = 0; i < multiline.getPrimitivesNumber(); i++) {
328
                    Line line = (Line) multiline.getPrimitiveAt(i);
329
                    Line auxLine = (Line) gmanager.create(Geometry.TYPES.LINE, Geometry.SUBTYPES.GEOM2DM);
330
                    double distance = 0.0;
331
                    double firstM = previousM;
332
                    for (int j = 0; j < line.getNumVertices(); j++) {
333
                        Point vertex = line.getVertex(j);
334
                        Point point = (Point) gmanager.create(Geometry.TYPES.POINT, Geometry.SUBTYPES.GEOM2DM);
335
                        point.setX(vertex.getX());
336
                        point.setY(vertex.getY());
337
                        if (j == 0 && previousPoint != null) {
338
                            boolean gap = false;
339
                            if (areInSame2DLocation(previousPoint, vertex)) {
340
                                // Buscamos si ha sido una bifurcaci?n
341
                                previousPoint = getPossibleFork(auxMultiLine, vertex);
342
                                // OJO, aqu? previousPoint pasa a ser 2DM
343
                            } else {
344
                                // En caso de salto, calculamos el previousPoint
345
                                // buscando el v?rtice m?s cercano
346
                                previousPoint = getClosestVertex(auxMultiLine, vertex);
347
                                // OJO, aqu? previousPoint pasa a ser 2DM
348
                                gap = true;
349
                            }
350
                            previousM = previousPoint.getCoordinateAt(previousPoint.getDimension() - 1);
351
                            if (j == 0) {
352
                                firstM = previousM;
353
                            }
354
                            if (gap && !ignoreSpatialGaps) {
355
                                Point previousVertex = getPreviousVertexToPoint(auxMultiLine, previousPoint);
356
                                previousVertex.getCoordinateAt(previousVertex.getDimension() - 1);
357
                                previousM =
358
                                    LrsAlgorithmUtils.straightLineThroughTwoPointsEquation(0, previousVertex.distance(previousPoint),
359
                                        previousVertex.getCoordinateAt(previousVertex.getDimension() - 1), previousM,
360
                                        previousVertex.distance(previousPoint) + previousPoint.distance(point));
361
                                firstM = previousM;
362
                            }
363
                        }
364
                        if (j != 0) {
365
                            distance += previousPoint.distance(vertex);
366
                        }
367
                        double m =
368
                            LrsAlgorithmUtils.straightLineThroughTwoPointsEquation(0, geometryLength, firstM, firstM + mSegment.fromValue,
369
                                distance);
370
                        point.setCoordinateAt(point.getDimension() - 1, m);
371
                        auxLine.addVertex(point);
372
                        previousM = m;
373
                        previousPoint = vertex;
374
                    }
375
                    multiline.addPrimitive(auxLine);
376
                }
377
            } else {
378
                // NO deber?a entrar por aqu?
379
                logger.warn("A not LINE nor MULTILINE geometry found in CreateRoute process");
380
            }
381
        }
382

  
383
        return compactMultiLine(auxMultiLine);
384
    }
385

  
386
    /**
387
     * Joins consecutive adjacent lines into the multiLine that are not involved in a fork
388
     *
389
     * @param auxMultiLine
390
     * @return
391
     * @throws CreateGeometryException
392
     * @throws GeometryOperationException
393
     * @throws GeometryOperationNotSupportedException
394
     */
395
    private MultiLine compactMultiLine(MultiLine multiLine) throws CreateGeometryException, GeometryOperationNotSupportedException, GeometryOperationException {
396
        GeometryManager geomManager = GeometryLocator.getGeometryManager();
397
        MultiLine result =  (MultiLine) geomManager.create(multiLine.getGeometryType());
398

  
399
        int primitivesNumber = multiLine.getPrimitivesNumber();
400
        List<Line> lines = new ArrayList<Line>(primitivesNumber);
401
        for(int i = 0; i < primitivesNumber; i++){
402
            lines.add((Line)multiLine.getPrimitiveAt(i).cloneGeometry());
403
        }
404
        if (lines.size() > 0) {
405
            Line line = lines.get(0);
406
            while (lines.size() > 1) {
407
                Point lastVertex = line.getVertex(line.getNumVertices() - 1);
408
                lines.remove(0);
409
                // Borramos la primera linea de la lista ==> lines.get(0) es la siguiente
410
                Line line2 = lines.get(0);
411
                // Si el ultimo punto de la primera
412
                if (lastVertex.equals(line2.getVertex(0)) && !bifurcation(lastVertex, lines)) {
413
                    for(int i = 1; i<line2.getNumVertices(); i++){
414
                        line.addVertex(line2.getVertex(i));
415
                    }
416
                } else {
417
                    result.addPrimitive(line);
418
                    line = line2;
419
                }
420
            }
421
            result.addPrimitive(line);
422
        }
423
        return result;
424
    }
425

  
426
    /**
427
     * Checks if a bifurcation occurs at one point.
428
     *
429
     * @param point
430
     * @param lines
431
     * @return
432
     */
433
    private boolean bifurcation(Point point, List<org.gvsig.fmap.geom.primitive.Line> lines) {
434
        // Saltamos la primera linea
435
        for(int i = 1; i<lines.size(); i++){
436
            if(point.equals(lines.get(i).getVertex(0))){
437
                return true;
438
            }
439
        }
440
        return false;
441
    }
442

  
443
    /**
444
     * Returns the previous vertex to a point.
445
     *
446
     * @param auxMultiLine
447
     * @param previousPoint
448
     * @return
449
     * @throws GeometryOperationException
450
     * @throws GeometryOperationNotSupportedException
451
     * @throws CreateGeometryException
452
     */
453
    private Point getPreviousVertexToPoint(MultiLine multiLine, Point point) throws CreateGeometryException,
454
        GeometryOperationNotSupportedException, GeometryOperationException {
455
        GeometryManager geomManager = GeometryLocator.getGeometryManager();
456
        for (int i = 0; i < multiLine.getPrimitivesNumber(); i++) {
457
            Line line = (Line) multiLine.getPrimitiveAt(i);
458
            if (line.intersects(point)) {
459
                for (int j = 0; j < line.getNumVertices() - 1; j++) {
460
                    if (point.equals(line.getVertex(j + 1))) {
461
                        return line.getVertex(j);
462
                    }
463
                    Line auxLine = (Line) geomManager.create(Geometry.TYPES.LINE, Geometry.SUBTYPES.GEOM2DM);
464
                    auxLine.addVertex(line.getVertex(j));
465
                    auxLine.addVertex(line.getVertex(j + 1));
466
                    if (auxLine.intersects(point)) {
467
                        return line.getVertex(j);
468
                    }
469
                }
470
            }
471
        }
472
        return null;
473
    }
474

  
475
    /**
476
     * Returns the next vertex to a point.
477
     *
478
     * @param auxMultiLine
479
     * @param previousPoint
480
     * @return
481
     * @throws GeometryOperationException
482
     * @throws GeometryOperationNotSupportedException
483
     * @throws CreateGeometryException
484
     */
485
    private Point getNextVertexToPoint(MultiLine multiLine, Point point) throws CreateGeometryException,
486
        GeometryOperationNotSupportedException, GeometryOperationException {
487
        GeometryManager geomManager = GeometryLocator.getGeometryManager();
488
        for (int i = 0; i < multiLine.getPrimitivesNumber(); i++) {
489
            Line line = (Line) multiLine.getPrimitiveAt(i);
490
            if (line.intersects(point)) {
491
                for (int j = 0; j < line.getNumVertices() - 1; j++) {
492
                    if (point.equals(line.getVertex(j))) {
493
                        return line.getVertex(j+1);
494
                    }
495
                    Line auxLine = (Line) geomManager.create(Geometry.TYPES.LINE, Geometry.SUBTYPES.GEOM2DM);
496
                    auxLine.addVertex(line.getVertex(j));
497
                    auxLine.addVertex(line.getVertex(j + 1));
498
                    if (auxLine.intersects(point)) {
499
                        return line.getVertex(j+1);
500
                    }
501
                }
502
            }
503
        }
504
        return null;
505
    }
506

  
507
    /**
508
     * Checks if a bifurcation occurs at one point and return the vertex with maximum M
509
     *
510
     * @param multiLine
511
     * @param vertex
512
     * @return
513
     */
514
    private Point getPossibleFork(MultiLine multiLine, Point point) {
515

  
516
        List<Point> vertices = new ArrayList<Point>();
517
        for (int i = 0; i < multiLine.getPrimitivesNumber(); i++) {
518
            Line line = (Line) multiLine.getPrimitiveAt(i);
519
            for (int j = 0; j < line.getNumVertices(); j++) {
520
                Point vertex = line.getVertex(j);
521
                if (areInSame2DLocation(vertex, point)) {
522
                    vertices.add(vertex);
523
                }
524
            }
525
        }
526
        if (vertices.size() > 0) {
527
            Double maxM = Double.NEGATIVE_INFINITY;
528
            Point forked = null;
529
            for (Iterator<Point> iterator = vertices.iterator(); iterator.hasNext();) {
530
                Point vertex = (Point) iterator.next();
531
                double m = vertex.getCoordinateAt(vertex.getDimension() - 1);
532
                if (m > maxM) {
533
                    maxM = m;
534
                    forked = vertex;
535
                }
536
            }
537
            return forked;
538
        }
539
        return null;
540
    }
541

  
542
    /**
543
     * Compares x & y coordinates of a point.
544
     *
545
     * @param p1
546
     * @param p2
547
     * @return
548
     */
549
    private boolean areInSame2DLocation(Point p1, Point p2) {
550
        return ((p1.getX() == p2.getX()) && (p1.getY() == p2.getY()));
551
    }
552

  
553
    /**
554
     * Returns the vertex of the multiline closest to a point
555
     *
556
     * @param mGeometry
557
     * @param vertex
558
     * @return
559
     * @throws GeometryOperationException
560
     * @throws GeometryOperationNotSupportedException
561
     * @throws CreateEnvelopeException
562
     */
563
    private Point getClosestVertex(MultiLine multiLine, Point point) throws CreateEnvelopeException,
564
        GeometryOperationNotSupportedException, GeometryOperationException {
565
        Point result = null;
566
        double minDistance = Double.POSITIVE_INFINITY;
567

  
568
        for (int i = 0; i < multiLine.getPrimitivesNumber(); i++) {
569
            Line line = (Line) multiLine.getPrimitiveAt(i);
570
            for (int j = 0; j < line.getNumVertices(); j++) {
571
                Point vertex = line.getVertex(j);
572
                double distance = point.distance(vertex);
573
                if (distance <= minDistance) {
574
                    minDistance = distance;
575
                    result = vertex;
576
                }
577
            }
578
        }
579

  
580
        return result;
581
    }
582

  
583
    /**
584
     * Returns a multiline calculate by two field method
585
     *
586
     * @param mList
587
     * @return
588
     * @throws CreateGeometryException
589
     * @throws GeometryOperationNotSupportedException
590
     * @throws GeometryOperationException
591
     */
592
    private MultiLine calculateGeometryByTwoField(List<MSegment> mList) throws CreateGeometryException,
593
        GeometryOperationNotSupportedException, GeometryOperationException {
594
        GeometryManager geomanager = GeometryLocator.getGeometryManager();
595
        MultiLine mGeometry = (MultiLine) geomanager.create(Geometry.TYPES.MULTILINE, Geometry.SUBTYPES.GEOM2DM);
596

  
597
        for (MSegment mSegment : mList) {
598
            Geometry geometry = mSegment.geometry;
599
            List<Line> geometryLines = extractLines(geometry);
600
            Double geometryLength = LrsAlgorithmUtils.getGeometryLength(geometry);
601

  
602
            Double geometryMFirstPoint = mSegment.fromValue;
603
            Double geometryMLastPoint = mSegment.toValue;
604

  
605
            Double distance = Double.valueOf(0);
606
            for (Line line : geometryLines) {
607
                Double lineLength = getLineLength(line);
608
                Double mFirstPoint = LrsAlgorithmUtils.calculateM(geometryLength, geometryMFirstPoint, geometryMLastPoint, distance);
609
                distance += lineLength;
610
                Double mLastPoint = LrsAlgorithmUtils.calculateM(geometryLength, geometryMFirstPoint, geometryMLastPoint, distance);
611
                Line mLine = lineToMLine(line, mFirstPoint, mLastPoint);
612
                mGeometry.addPrimitive(mLine);
613
            }
614
        }
615

  
616
        return mGeometry;
617
    }
618

  
619
    /**
620
     * Converts a Line2D in a Line2DM filled it with proportional calculated M's
621
     *
622
     * @param line
623
     * @param minMValue
624
     * @param maxMValue
625
     * @return
626
     * @throws CreateGeometryException
627
     * @throws GeometryOperationNotSupportedException
628
     * @throws GeometryOperationException
629
     */
630
    private Line lineToMLine(Line line, Double minMValue, Double maxMValue) throws CreateGeometryException,
631
        GeometryOperationNotSupportedException, GeometryOperationException {
632
        GeometryManager geomanager = GeometryLocator.getGeometryManager();
633
        Double lineLength = getLineLength(line);
634
        Line lineM = (Line) geomanager.create(Geometry.TYPES.LINE, Geometry.SUBTYPES.GEOM2DM);
635
        Double inLineDistance = Double.valueOf(0);
636
        for (int i = 0; i < line.getNumVertices(); i++) {
637
            Point vertex = line.getVertex(i);
638
            Point mVertex = (Point) geomanager.create(Geometry.TYPES.POINT, Geometry.SUBTYPES.GEOM2DM);
639
            mVertex.setX(vertex.getX());
640
            mVertex.setY(vertex.getY());
641

  
642
            Double mValue;
643
            if (i == 0)
644
                mValue = minMValue;
645
            else if (i == line.getNumVertices() - 1)
646
                mValue = maxMValue;
647
            else {
648
                Point previousVertex = line.getVertex(i - 1);
649
                inLineDistance += vertex.distance(previousVertex);
650
                mValue = LrsAlgorithmUtils.calculateM(lineLength, minMValue, maxMValue, inLineDistance);
651
            }
652

  
653
            mVertex.setCoordinateAt(mVertex.getDimension() - 1, mValue);
654
            lineM.addVertex(mVertex);
655
        }
656
        return lineM;
657
    }
658

  
659

  
660
    /**
661
     * Simplify the multilines in mList calling simplifyMultiline method
662
     *
663
     * @param mList
664
     * @throws CreateGeometryException
665
     * @throws LocatorException
666
     */
667
    private void simplifyMultilines(List<MSegment> mList) throws CreateGeometryException, LocatorException {
668
        for (MSegment mSegment : mList) {
669
            mSegment.geometry = simplifyMultiline(mSegment.geometry);
670
        }
671
    }
672

  
673
    /**
674
     * Simplify a Multiline ordering and joining her lines if can.
675
     *
676
     * @param geometry
677
     * @return
678
     * @throws CreateGeometryException
679
     * @throws LocatorException
680
     */
681
    private Geometry simplifyMultiline(Geometry geometry) throws CreateGeometryException, LocatorException {
682
        if (geometry instanceof MultiLine) {
683
            MultiLine multiline = (MultiLine) geometry;
684

  
685
            if (multiline.getPrimitivesNumber() == 1) {
686
                return multiline.getPrimitiveAt(0);
687
            } else {
688
                List<Line> simplifiedLines = new ArrayList<Line>();
689
                List<Line> complexLines = new ArrayList<Line>();
690
                for (int i = 0; i < multiline.getPrimitivesNumber(); i++) {
691
                    complexLines.add((Line) multiline.getPrimitiveAt(i));
692
                }
693

  
694
                Line line = null;
695
                while (complexLines.size() > 0) {
696
                    line = complexLines.remove(0);
697
                    int i = 0;
698
                    while (i < complexLines.size()) {
699
                        Line auxLine = complexLines.get(i);
700
                        Line unitedLine = unionAdjacentLines(line, auxLine);
701
                        if (unitedLine != null) {
702
                            line = unitedLine;
703
                            complexLines.remove(i);
704
                            i = 0;
705
                        } else {
706
                            i++;
707
                        }
708
                    }
709
                    simplifiedLines.add(line);
710
                }
711

  
712
                if (simplifiedLines.size() == 1) {
713
                    geometry = simplifiedLines.get(0);
714
                } else {
715
                    MultiLine simplifiedMultiLine =
716
                        (MultiLine) GeometryLocator.getGeometryManager().create(multiline.getGeometryType());
717
                    for (Line simpleLine : simplifiedLines) {
718
                        simplifiedMultiLine.addPrimitive(simpleLine);
719
                    }
720
                    return simplifiedMultiLine;
721
                }
722
            }
723
        }
724
        return geometry;
725
    }
726

  
727
    /**
728
     * Join two adjacent lines flipping it if necessary
729
     *
730
     * @param line1
731
     * @param line2
732
     * @return
733
     */
734
    private Line unionAdjacentLines(Line line1, Line line2) {
735
        if (line1 == null || line2 == null) {
736
            return null;
737
        }
738
        Line resultLine;
739
        try {
740
            resultLine = (Line) GeometryLocator.getGeometryManager().create(line1.getGeometryType());
741
        } catch (Exception e) {
742
            return null;
743
        }
744

  
745
        Point firstPointL1 = line1.getVertex(0);
746
        Point lastPointL1 = line1.getVertex(line1.getNumVertices() - 1);
747
        Point firstPointL2 = line2.getVertex(0);
748
        Point lastPointL2 = line2.getVertex(line2.getNumVertices() - 1);
749
        if (lastPointL1.equals(firstPointL2)) {
750
            resultLine = (Line) line1.cloneGeometry();
751
            for (int i = 1; i < line2.getNumVertices(); i++) {
752
                resultLine.addVertex((Point) line2.getVertex(i).cloneGeometry());
753
            }
754
            return resultLine;
755
        }
756
        if (lastPointL2.equals(firstPointL1)) {
757
            resultLine = (Line) line2.cloneGeometry();
758
            for (int i = 1; i < line1.getNumVertices(); i++) {
759
                resultLine.addVertex((Point) line1.getVertex(i).cloneGeometry());
760
            }
761
            return resultLine;
762
        }
763
        if (firstPointL1.equals(firstPointL2)) {
764
            for (int i = line1.getNumVertices() - 1; i >= 0; i--) {
765
                resultLine.addVertex((Point) line1.getVertex(i).cloneGeometry());
766
            }
767
            for (int i = 1; i < line2.getNumVertices(); i++) {
768
                resultLine.addVertex((Point) line2.getVertex(i).cloneGeometry());
769
            }
770
            return resultLine;
771
        }
772
        if (lastPointL1.equals(lastPointL2)) {
773
            resultLine = (Line) line1.cloneGeometry();
774
            for (int i = line2.getNumVertices() - 2; i >= 0; i--) {
775
                resultLine.addVertex((Point) line2.getVertex(i).cloneGeometry());
776
            }
777
            return resultLine;
778
        }
779
        return null;
780
    }
781

  
782
    /**
783
     * Sorts mList
784
     *
785
     * @param mList
786
     * @return
787
     * @throws CreateEnvelopeException
788
     * @throws GeometryOperationNotSupportedException
789
     * @throws GeometryOperationException
790
     */
791
    private List<MSegment> sortMList(List<MSegment> mList) throws CreateEnvelopeException,
792
        GeometryOperationNotSupportedException, GeometryOperationException {
793
        LrsCoordinatesPriority coordinatePriority = parameters.getCoordinatePriority();
794
        GeometryManager geomanager = GeometryLocator.getGeometryManager();
795
        Envelope envelope = geomanager.createEnvelope(Geometry.SUBTYPES.GEOM2D);
796
        for (MSegment mSegment : mList) {
797
            envelope.add(mSegment.geometry.getEnvelope());
798
        }
799
        Point origin = envelope.getLowerCorner();
800
        switch (coordinatePriority) {
801
        case DOWN_LEFT:
802
            break;
803
        case DOWN_RIGHT:
804
            Double maxX = envelope.getMaximum(DIMENSIONS.X);
805
            origin.setX(maxX);
806
            break;
807
        case UP_LEFT:
808
            Double maxY = envelope.getMaximum(DIMENSIONS.Y);
809
            origin.setY(maxY);
810
            break;
811
        case UP_RIGHT:
812
            origin = envelope.getUpperCorner();
813
            break;
814
        default:
815
            break;
816
        }
817

  
818
        List<Stretch> stretches = createStretches(mList, origin);
819
        stretches = sortStretches(stretches, origin);
820
        return extractSegmentsFromStretches(stretches);
821
    }
822

  
823
    /**
824
     * Extracts segment from stretches and returns a list of segment.
825
     *
826
     * @param stretches
827
     * @return
828
     */
829
    private List<MSegment> extractSegmentsFromStretches(List<Stretch> stretches) {
830
        List<MSegment> result = new ArrayList<MSegment>();
831
        for (Stretch stretch : stretches) {
832
            for (int i = 0; i < stretch.getSegmentNumber(); i++) {
833
                result.add(stretch.getSegment(i));
834
            }
835
        }
836
        return result;
837
    }
838

  
839
    /**
840
     * Sort the stretches
841
     *
842
     * @param stretches
843
     * @param origin
844
     * @return
845
     * @throws GeometryOperationNotSupportedException
846
     * @throws GeometryOperationException
847
     */
848
    private List<Stretch> sortStretches(List<Stretch> stretches, Point origin)
849
        throws GeometryOperationNotSupportedException, GeometryOperationException {
850
        List<Stretch> result = new ArrayList<Stretch>();
851

  
852
        Point originPoint = origin;
853
        while (result.size() < stretches.size()) {
854
            // Buscamos tramos que sean adyacentes al origin
855
            if (result.size() == 0) {
856
                addUnvisitedAdjacentStretches(stretches, result, originPoint);
857
            }
858
            if (result.size() == 0) {
859
                result.add(getNearestUnvisitedStretch(stretches, originPoint, result));
860
            }
861

  
862
            boolean addedAdjacentStretches = true;
863
            while (addedAdjacentStretches) {
864
                addedAdjacentStretches = false;
865
                int visitedNumber = result.size();
866
                for (int i = 0; i < visitedNumber; i++) {
867
                    Stretch visited = result.get(i);
868
                    addUnvisitedAdjacentStretches(stretches, result, visited.getFinalPoint());
869
                }
870
                addedAdjacentStretches = (visitedNumber < result.size());
871
            }
872

  
873
            int visitedNumber = result.size();
874
            Stretch nearest = null;
875
            for (int i = visitedNumber - 1; i >= 0; i--) {
876
                if(nearest!=null){
877
                    break;
878
                }
879
                Stretch visited = result.get(i);
880
                for (int j=0; j<visited.getSegmentNumber(); j++) {
881
                    if(nearest!=null){
882
                        break;
883
                    }
884
                    MSegment segment = visited.getSegment(j);
885
                    Geometry geom = segment.geometry;
886
                    if(geom instanceof Line){
887
                        Line line = (Line)geom;
888
                        for (int k=0; k<line.getNumVertices(); k++){
889
                            nearest = getNearestUnvisitedStretch(stretches, line.getVertex(k), result);
890
                            if (nearest != null) {
891
                                result.add(nearest);
892
                                break;
893
                            }
894
                        }
895
                    } else { //geom is multiline
896
                        MultiLine multiline = (MultiLine)geom;
897
                        for (int l=0; l<multiline.getPrimitivesNumber(); l++){
898
                            if(nearest!=null){
899
                                break;
900
                            }
901
                            Line line = (Line)multiline.getPrimitiveAt(l);
902
                            for (int k=0; k<line.getNumVertices(); k++){
903
                                nearest = getNearestUnvisitedStretch(stretches, line.getVertex(k), result);
904
                                if (nearest != null) {
905
                                    result.add(nearest);
906
                                    break;
907
                                }
908
                            }
909

  
910
                        }
911
                    }
912
                }
913
            }
914
        }
915
        return result;
916
    }
917

  
918
    /**
919
     * Adds unvisited adjacent stretches to the visited list
920
     *
921
     * @param stretches
922
     * @param visited
923
     * @param originPoint
924
     * @throws GeometryOperationNotSupportedException
925
     * @throws GeometryOperationException
926
     */
927
    private void addUnvisitedAdjacentStretches(List<Stretch> stretches, List<Stretch> visited, Point originPoint)
928
        throws GeometryOperationNotSupportedException, GeometryOperationException {
929
        for (Stretch stretch : stretches) {
930
            if (!visited.contains(stretch)) {
931
                if (areInSame2DLocation(stretch.getInitialPoint(), originPoint)) {
932
                    visited.add(stretch);
933
                } else if (areInSame2DLocation(stretch.getFinalPoint(), originPoint)) {
934
                    visited.add(stretch.flip());
935
                }
936
            }
937
        }
938
    }
939

  
940
    /**
941
     * Returns the unvisited stretch nearest to a point
942
     *
943
     * @param stretches
944
     * @param origin
945
     * @param visited
946
     * @return
947
     * @throws GeometryOperationNotSupportedException
948
     * @throws GeometryOperationException
949
     */
950
    private Stretch getNearestUnvisitedStretch(List<Stretch> stretches, Point origin, List<Stretch> visited)
951
        throws GeometryOperationNotSupportedException, GeometryOperationException {
952

  
953
        double minDistance = Double.POSITIVE_INFINITY;
954
        Stretch nearest = null;
955
        boolean needFlip = false;
956
        for (Stretch stretch : stretches) {
957
            if (!visited.contains(stretch)) {
958
                Double initialDistance = origin.distance(stretch.getInitialPoint());
959
                if (initialDistance < minDistance) {
960
                    minDistance = initialDistance;
961
                    nearest = stretch;
962
                    needFlip = false;
963
                }
964
                Double finalDistance = origin.distance(stretch.getFinalPoint());
965
                if (finalDistance < minDistance) {
966
                    minDistance = finalDistance;
967
                    nearest = stretch;
968
                    needFlip = true;
969
                }
970
            }
971
        }
972
        if (needFlip && nearest != null) {
973
            nearest.flip();
974
        }
975
        return nearest;
976
    }
977

  
978
    /**
979
     * Creates stretches from mList and returns a list of stretches
980
     *
981
     * @param mList
982
     * @param origin
983
     * @return
984
     * @throws GeometryOperationNotSupportedException
985
     * @throws GeometryOperationException
986
     */
987
    private List<Stretch> createStretches(List<MSegment> mList, Point origin)
988
        throws GeometryOperationNotSupportedException, GeometryOperationException {
989

  
990
        List<MSegment> addedMSegment = new ArrayList<LrsCreateRouteAlgorithm.MSegment>();
991
        List<Stretch> stretches = new ArrayList<Stretch>();
992
        while (addedMSegment.size() < mList.size()) {
993
            for (MSegment mSegment : mList) {
994
                if (!addedMSegment.contains(mSegment)) {
995
                    Stretch stretch = new Stretch();
996
                    stretches.add(stretch);
997
                    stretch.addSegment(mSegment);
998
                    addedMSegment.add(mSegment);
999

  
1000
                    List<MSegment> initialNextSegments =
1001
                        mSegment.searchNextSegments(stretch.getInitialPoint(), mList);
1002
                    do {
1003
                        if (initialNextSegments.size() == 1) {
1004
                            MSegment previousSegment = initialNextSegments.get(0);
1005
                            if (!addedMSegment.contains(previousSegment)) {
1006
                                if (!previousSegment.getFinalPoint().equals(stretch.getInitialPoint())) {
1007
                                    previousSegment.flip();
1008
                                }
1009
                                stretch.addSegment(0, previousSegment);
1010
                                addedMSegment.add(previousSegment);
1011
                                initialNextSegments =
1012
                                    previousSegment.searchNextSegments(stretch.getInitialPoint(), mList);
1013
                            } else {
1014
                                break;
1015
                            }
1016
                        } else {
1017
                            break;
1018
                        }
1019
                    } while (initialNextSegments.size() == 1);
1020

  
1021
                    List<MSegment> finalNextSegments =
1022
                        mSegment.searchNextSegments(stretch.getFinalPoint(), mList);
1023
                    do {
1024
                        if (finalNextSegments.size() == 1) {
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff