Statistics
| Revision:

gvsig-vectorediting / org.gvsig.vectorediting / trunk / org.gvsig.vectorediting / org.gvsig.vectorediting.lib / org.gvsig.vectorediting.lib.prov / org.gvsig.vectorediting.lib.prov.trimline / src / main / java / org / gvsig / vectorediting / lib / prov / trimline / operation / CurveTrimLineOperation.java @ 2616

History | View | Annotate | Download (10 KB)

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

    
25
package org.gvsig.vectorediting.lib.prov.trimline.operation;
26

    
27
import org.gvsig.fmap.dal.exception.DataException;
28
import org.gvsig.fmap.dal.feature.Feature;
29
import org.gvsig.fmap.dal.feature.FeatureSelection;
30
import org.gvsig.fmap.geom.Geometry;
31
import org.gvsig.fmap.geom.GeometryLocator;
32
import org.gvsig.fmap.geom.GeometryManager;
33
import org.gvsig.fmap.geom.aggregate.MultiCurve;
34
import org.gvsig.fmap.geom.exception.CreateGeometryException;
35
import org.gvsig.fmap.geom.operation.GeometryOperationException;
36
import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException;
37
import org.gvsig.fmap.geom.primitive.Curve;
38
import org.gvsig.fmap.geom.primitive.Line;
39
import org.gvsig.fmap.geom.primitive.Point;
40
import org.gvsig.tools.dispose.DisposableIterator;
41
import org.gvsig.tools.locator.LocatorException;
42
import org.slf4j.Logger;
43
import org.slf4j.LoggerFactory;
44

    
45
/**
46
 * Operation to trim curves.
47
 * 
48
 * @author llmarques
49
 */
50
public class CurveTrimLineOperation implements TrimLineOperation {
51

    
52
    private static final Logger LOGGER = LoggerFactory
53
        .getLogger(CurveTrimLineOperation.class);
54
        
55
    /*
56
     * Strategy:
57
     * 
58
     * 1. Get arc segments between curve and shears.
59
     * 2. Determinate what segment of curve must be deleted
60
     * 3. Rebuild curve taking into account the segment that must be deleted
61
     */
62
    @Override
63
    public MultiCurve trimLine(Curve curveToTrim, Point shearingPoint,
64
        FeatureSelection shears)
65
        throws GeometryOperationNotSupportedException,
66
        GeometryOperationException, DataException, CreateGeometryException,
67
        LocatorException {
68

    
69
        GeometryManager geometryManager = GeometryLocator.getGeometryManager();
70
        int subType = curveToTrim.getGeometryType().getSubType();
71

    
72
        DisposableIterator it = shears.fastIterator();
73
        MultiCurve segmentedLine = geometryManager.createMultiCurve(subType);
74
        segmentedLine.addCurve(curveToTrim);
75

    
76
        while (it.hasNext()) {
77
            Feature feature = (Feature) it.next();
78
            Geometry geometry = feature.getDefaultGeometry();
79

    
80
            Geometry tmpDifference = segmentedLine.difference(geometry);
81
            if (tmpDifference instanceof MultiCurve) {
82
                segmentedLine = (MultiCurve) tmpDifference;
83
            } else if(tmpDifference instanceof Curve) {
84
                // Sometimes line to split and splitter are so close ( distance
85
                // between geometries < 0.00000000001 ). In this cases, we try
86
                // to do an enhance difference.
87
                // If the result is instance of Curve, it is considered that
88
                // lines don't intersect.
89
                // If the result is instance of Multicurve, lines are so close
90
                // and it is considered that lines intersect.
91
                Geometry enchancedGeometry = enhancedDifference(geometry, (Curve) tmpDifference);
92
                if(enchancedGeometry instanceof MultiCurve){
93
                    segmentedLine = (MultiCurve) enchancedGeometry;
94
                } 
95
            }
96
        }
97

    
98
        if (segmentedLine.getPrimitivesNumber() == 1) {
99
            return segmentedLine;
100
        }
101

    
102
        int index = 0;
103
        Curve curve;
104
        double minDistance = Double.POSITIVE_INFINITY;
105
        for (int i = 0; i < segmentedLine.getPrimitivesNumber(); i++) {
106
            curve = segmentedLine.getCurveAt(i);
107
            double distance = curve.distance(shearingPoint);
108
            if (distance < minDistance) {
109
                index = i;
110
                minDistance = distance;
111
            }
112
        }
113

    
114
        MultiCurve trimmedCurve = geometryManager.createMultiCurve(subType);
115

    
116
        Curve tmpCurve = null;
117
        for (int i = 0; i < segmentedLine.getPrimitivesNumber(); i++) {
118

    
119
            if (i == index) {
120
                if (tmpCurve != null) {
121
                    trimmedCurve.addCurve(tmpCurve);
122
                    tmpCurve = null;
123
                }
124
                continue;
125
            }
126

    
127
            if (tmpCurve != null) {
128
                tmpCurve = union(tmpCurve, segmentedLine.getCurveAt(i));
129
            } else {
130
                tmpCurve = segmentedLine.getCurveAt(i);
131
            }
132
        }
133
        if (tmpCurve != null) {
134
            trimmedCurve.addCurve(tmpCurve);
135
        }
136

    
137
        return trimmedCurve;
138
    }
139

    
140
    private Curve union(Curve firstCurve, Curve secondCurve)
141
        throws CreateGeometryException, LocatorException,
142
        GeometryOperationNotSupportedException, GeometryOperationException {
143

    
144
        int subtype1 = firstCurve.getGeometryType().getSubType();
145
        int subtype2 = secondCurve.getGeometryType().getSubType();
146

    
147
        if (subtype1 == subtype2) {
148
            Curve union =
149
                GeometryLocator.getGeometryManager().createLine(subtype1);
150

    
151
            for (int i = 0; i < firstCurve.getNumVertices() - 1; i++) {
152
                union.addVertex(firstCurve.getVertex(i));
153
            }
154

    
155
            Point lastVertex =
156
                firstCurve.getVertex(firstCurve.getNumVertices() - 2);
157
            for (int i = 0; i < secondCurve.getNumVertices(); i++) {
158

    
159
                if (i == 0) {
160
                    Line tmpLine =
161
                        GeometryLocator.getGeometryManager().createLine(
162
                            subtype1);
163
                    tmpLine.setPoints(lastVertex, secondCurve.getVertex(1));
164
                    if (TrimLineOperationUtils.intersects(tmpLine,
165
                        secondCurve.getVertex(0))) {
166
                        continue;
167
                    }
168
                }
169
                union.addVertex(secondCurve.getVertex(i));
170
            }
171

    
172
            return union;
173
        }
174
        return null;
175
    }
176
    
177
    private Geometry enhancedDifference(Geometry splitter, Curve curve)
178
        throws GeometryOperationNotSupportedException,
179
        GeometryOperationException {
180
        Geometry snapTo = curve.snapTo(splitter, TrimLineOperationUtils.SNAP_TOLERANCE);
181
        return snapTo.difference(splitter);
182
    }
183

    
184

    
185
    /*
186
     * Strategy:
187
     * 
188
     * 1. Get line segments between curve and shears
189
     * 2. Determinate what segment of curve must be deleted
190
     * 3. Rebuild curve taking into account the segment that must be deleted
191
     */
192
    @Override
193
    public MultiCurve trimLine(Curve curveToTrim, Point shearingPoint,
194
        Geometry shears)
195
        throws GeometryOperationNotSupportedException,
196
        GeometryOperationException, DataException, CreateGeometryException,
197
        LocatorException {
198

    
199
        GeometryManager geometryManager = GeometryLocator.getGeometryManager();
200
        int subType = curveToTrim.getGeometryType().getSubType();
201

    
202
        MultiCurve segmentedLine = geometryManager.createMultiCurve(subType);
203
        segmentedLine.addCurve(curveToTrim);
204

    
205
        Geometry tmpDifference = segmentedLine.difference(shears);
206
        if (tmpDifference instanceof MultiCurve) {
207
            segmentedLine = (MultiCurve) tmpDifference;
208
        } else if(tmpDifference instanceof Curve) {
209
            // Sometimes line to split and splitter are so close ( distance
210
            // between geometries < 0.00000000001 ). In this cases, we try
211
            // to do an enhance difference.
212
            // If the result is instance of Curve, it is considered that
213
            // lines don't intersect.
214
            // If the result is instance of Multicurve, lines are so close
215
            // and it is considered that lines intersect.
216
            Geometry enchancedGeometry = enhancedDifference(shears, (Curve) tmpDifference);
217
            if(enchancedGeometry instanceof MultiCurve){
218
                segmentedLine = (MultiCurve) enchancedGeometry;
219
            } 
220
        }
221

    
222
        if (segmentedLine.getPrimitivesNumber() == 1) {
223
            return segmentedLine;
224
        }
225

    
226
        double side = TrimLineOperationUtils.getSide(shears, shearingPoint);
227
        
228
        int index = -1;
229
        if(!Double.isNaN(side)){
230
            Curve curve;
231
            double minDistance = Double.POSITIVE_INFINITY;
232
            for (int i = 0; i < segmentedLine.getPrimitivesNumber(); i++) {
233
                curve = segmentedLine.getCurveAt(i);
234
                double distance = curve.distance(shearingPoint);
235
                if (distance < minDistance) {
236
                    Double segmentSide = TrimLineOperationUtils.getSide(shears, curve);
237
                    if(segmentSide == side){
238
                        index = i;
239
                        minDistance = distance;
240
                    }
241
                }
242
            }
243
        }
244

    
245
        MultiCurve trimmedCurve = geometryManager.createMultiCurve(subType);
246

    
247
        Curve tmpCurve = null;
248
        for (int i = 0; i < segmentedLine.getPrimitivesNumber(); i++) {
249
            
250
            if (i == index) {
251
                if (tmpCurve != null) {
252
                    trimmedCurve.addCurve(tmpCurve);
253
                    tmpCurve = null;
254
                }
255
                continue;
256
            }
257

    
258
            if (tmpCurve != null) {
259
                tmpCurve = union(tmpCurve, segmentedLine.getCurveAt(i));
260
            } else {
261
                tmpCurve = segmentedLine.getCurveAt(i);
262
            }
263
        }
264
        if (tmpCurve != null) {
265
            trimmedCurve.addCurve(tmpCurve);
266
        }
267

    
268
        return trimmedCurve;
269
    }
270
    
271

    
272

    
273
}