Revision 2228

View differences:

org.gvsig.vectorediting/trunk/org.gvsig.vectorediting/org.gvsig.vectorediting.app/org.gvsig.vectorediting.app.mainplugin/src/main/resources-plugin/i18n/text.properties
159 159
sweep_angle = \u00c1ngulo de barrido
160 160
center_point = Centro
161 161
_graphic_distance = Distancia gr\u00e1fica
162
geometry_to_extend_to=Geometr\u00eda hasta la que extender
162
geometry_to_extend_to=Geometr\u00eda hasta la que extender
163
geometry_to_trim_with=Geometr\u00eda con la que recortar
164
shearing_point=Punto de recorte
org.gvsig.vectorediting/trunk/org.gvsig.vectorediting/org.gvsig.vectorediting.app/org.gvsig.vectorediting.app.mainplugin/src/main/resources-plugin/i18n/text_en.properties
157 157
sweep_angle = Sweep angle
158 158
center_point = Center point
159 159
_graphic_distance = Graphic distance
160
geometry_to_extend_to= Geometry to extend to
160
geometry_to_extend_to= Geometry to extend to
161
geometry_to_trim_with=Geometry to trim with
162
shearing_point=Shearing point
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/TrimLineOperation.java
26 26

  
27 27
import org.gvsig.fmap.dal.exception.DataException;
28 28
import org.gvsig.fmap.dal.feature.FeatureSelection;
29
import org.gvsig.fmap.geom.Geometry;
29 30
import org.gvsig.fmap.geom.aggregate.MultiCurve;
30 31
import org.gvsig.fmap.geom.exception.CreateGeometryException;
31 32
import org.gvsig.fmap.geom.operation.GeometryOperationException;
......
43 44
public interface TrimLineOperation {
44 45

  
45 46
    /**
47
     * Trim line, taking as cutting edges the shears received as
48
     * parameters.Inserted point is the point inserted by user.It is used to determinate
49
 what segment of curve it must trimmed.If curveToBeExtended does not intersect with any geometry, the geometry
50
 will not be modified.
51
     * 
52
     * 
53
     * @param curveToTrim
54
     *            Curve to trim
55
     * @param shearingPoint
56
     *            Point inserted by user to determinate what side of curve must
57
     *            be extended.
58
     * @param shears
59
     *            If curveToBeExtended intersects with some shears, it will
60
     *            be cutted to it. If there are several shears that
61
     *            intersects with curveToTrim, it will be cutted to
62
     *            nearest point.
63
     * @return Trimmed line
64
     * @throws org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException
65
     * @throws org.gvsig.fmap.geom.operation.GeometryOperationException
66
     * @throws org.gvsig.fmap.dal.exception.DataException
67
     * @throws org.gvsig.fmap.geom.exception.CreateGeometryException
68
     */
69
    public MultiCurve trimLine(Curve curveToTrim, Point shearingPoint,
70
        FeatureSelection shears)
71
        throws GeometryOperationNotSupportedException,
72
        GeometryOperationException, DataException, CreateGeometryException,
73
        LocatorException;
74

  
75
    
76
        /**
46 77
     * Trim line, taking as cutting edges the boundary objects received as
47
     * parameters.
78
     * parameters.Inserted point is the point inserted by user.It is used to determinate
79
 what segment of curve it must trimmed.If curveToBeExtended does not intersect with any geometry, the geometry
80
 will not be modified.
48 81
     * 
49
     * Inserted point is the point inserted by user. It is used to determinate
50
     * what segment of curve it must trimmed.
51 82
     * 
52
     * If curveToBeExtended does not intersect with any geometry, the geometry
53
     * will not be modified.
54
     * 
55 83
     * @param curveToTrim
56 84
     *            Curve to trim
57
     * @param insertedPoint
85
     * @param shearingPoint
58 86
     *            Point inserted by user to determinate what side of curve must
59 87
     *            be extended.
60
     * @param boundaryObjects
88
     * @param shears
61 89
     *            If curveToBeExtended intersects with some boundary object, it
62 90
     *            will
63 91
     *            be extend to it. If there are several boundary objects that
......
65 93
     *            nearest
66 94
     *            point.
67 95
     * @return Trimmed line
96
     * @throws org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException
97
     * @throws org.gvsig.fmap.geom.operation.GeometryOperationException
98
     * @throws org.gvsig.fmap.dal.exception.DataException
99
     * @throws org.gvsig.fmap.geom.exception.CreateGeometryException
68 100
     */
69
    public MultiCurve trimLine(Curve curveToTrim, Point insertedPoint,
70
        FeatureSelection boundaryObjects)
101
    public MultiCurve trimLine(Curve curveToTrim, Point shearingPoint,
102
        Geometry shears)
71 103
        throws GeometryOperationNotSupportedException,
72 104
        GeometryOperationException, DataException, CreateGeometryException,
73 105
        LocatorException;
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/TrimLineOperationUtils.java
26 26

  
27 27
import java.util.HashMap;
28 28
import java.util.Map;
29

  
29
import org.gvsig.fmap.geom.Geometry;
30 30
import org.gvsig.fmap.geom.Geometry.TYPES;
31 31
import org.gvsig.fmap.geom.GeometryLocator;
32
import org.gvsig.fmap.geom.GeometryManager;
33
import org.gvsig.fmap.geom.GeometryUtils;
34
import org.gvsig.fmap.geom.aggregate.MultiLine;
32 35
import org.gvsig.fmap.geom.exception.CreateGeometryException;
33 36
import org.gvsig.fmap.geom.operation.GeometryOperationException;
34 37
import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException;
35 38
import org.gvsig.fmap.geom.primitive.Arc;
36 39
import org.gvsig.fmap.geom.primitive.Curve;
40
import org.gvsig.fmap.geom.primitive.Line;
37 41
import org.gvsig.fmap.geom.primitive.Point;
38 42
import org.gvsig.fmap.geom.primitive.Primitive;
39 43
import org.gvsig.tools.locator.LocatorException;
......
56 60

  
57 61
    private static Map<Integer, TrimLineOperation> operations =
58 62
        new HashMap<Integer, TrimLineOperation>();
63
    
64
    public static final double SNAP_TOLERANCE = 0.1;
59 65

  
66

  
60 67
    public TrimLineOperationUtils() {
61 68
    }
62 69

  
......
72 79
        return operation;
73 80
    }
74 81

  
75
    // FIXME: remove this method when geometry library has this utility method
76
    public static double getAngle(Point start, Point end)
77
        throws GeometryOperationNotSupportedException,
78
        GeometryOperationException {
79
        double angle = Math.acos((end.getX() - start.getX()) / start.distance(end));
80

  
81
        if (start.getY() > end.getY()) {
82
            angle = -angle;
83
        }
84

  
85
        if (angle < 0) {
86
            angle += (2 * Math.PI);
87
        }
88

  
89
        return angle;
90
    }
91
    
92 82
    public static Arc createArc(Point center, double radius, Point initPoint,
93 83
        Point endPoint, int subtype) throws CreateGeometryException,
94 84
        LocatorException, GeometryOperationNotSupportedException,
......
98 88
            (Arc) GeometryLocator.getGeometryManager().create(TYPES.ARC,
99 89
                subtype);
100 90

  
101
        double startAngle = TrimLineOperationUtils.getAngle(center, initPoint);
102
        double endAngle = TrimLineOperationUtils.getAngle(center, endPoint);
91
        double startAngle = GeometryUtils.calculateAngle(center, initPoint);
92
        double endAngle = GeometryUtils.calculateAngle(center, endPoint);
103 93

  
104 94
        arc.setPointsStartEnd(center, radius, startAngle, endAngle);
105 95
        return arc;
......
113 103

  
114 104
        return curve.buffer(tolerance).intersects(projectedPoint);
115 105
    }
106
    
107
    
108
    public static Double getSide(Geometry geometry, Point point) throws GeometryOperationNotSupportedException, GeometryOperationException, CreateGeometryException{
109
        GeometryManager geomManager= GeometryLocator.getGeometryManager();
110
        int subtype = geometry.getGeometryType().getSubType();
111
        Geometry[] closestPoints = geometry.closestPoints(point);
112
        if(geometry instanceof Line) {
113
            Line line = (Line)geometry;
114
            int index = 0;
115
            Point previousVertex = null;
116
            for (Point vertex : line) {
117
                if(index < line.getNumVertices()-1){
118
                    Point nextVertex = line.getVertex(index+1);
119
                    Line segment = geomManager.createLine(subtype);
120
                    segment.addVertex(vertex);
121
                    segment.addVertex(nextVertex);
122
                    Geometry p = closestPoints[0];
123
                    double coef = TrimLineOperationUtils.getSide(vertex, nextVertex, point);
124
                    if(segment.isWithinDistance(p, SNAP_TOLERANCE)) {
125
                        if(vertex.isWithinDistance(p, SNAP_TOLERANCE) && previousVertex != null){
126
                            double previousCoef = TrimLineOperationUtils.getSide(previousVertex, vertex, point);
127
                            if(previousCoef == coef){
128
                                return coef;
129
                            } else {
130
                                return Double.NaN;
131
                            }
132
                        } else if(nextVertex.isWithinDistance(p, SNAP_TOLERANCE) && index < line.getNumVertices()-2){
133
                            Point nextNextVertex = line.getVertex(index+2);
134
                            double nextCoef = TrimLineOperationUtils.getSide(nextVertex, nextNextVertex, point);
135
                            if(nextCoef == coef){
136
                                return coef;
137
                            } else {
138
                                return Double.NaN;
139
                            }
140
                        }
141
                        return coef;
142
                    }
143
                    previousVertex = vertex;
144
                }
145
                index++;
146
            }
147
        } else if (geometry instanceof MultiLine) {
148
            double minDistance = Double.POSITIVE_INFINITY;
149
            MultiLine multiline = (MultiLine)geometry;
150
            Geometry nearestComponent = null;
151
            for (Geometry component : multiline) {
152
                double distance = component.distance(point);
153
                if(distance < minDistance){
154
                    nearestComponent = component;
155
                    minDistance = distance;
156
                }
157
            }
158
            if(nearestComponent != null) {
159
                return TrimLineOperationUtils.getSide(nearestComponent, point);
160
            }
161
        }
162
        return Double.NaN;
163
    }
164
    
165
    public static double getSide(Point a, Point b, Point c) {
166
        if (a == null || b == null || c == null || a.equals(b) || a.equals(c) || b.equals(c)) {
167
            throw new IllegalArgumentException("Points must be different and not null.");
168
        }
169
        return Math.signum((b.getX() - a.getX()) * (c.getY() - a.getY()) - (b.getY() - a.getY()) * (c.getX() - a.getX()));
170
    }
171

  
172
    public static Double getSide(Geometry geometry, Curve curve) throws GeometryOperationNotSupportedException, GeometryOperationException, CreateGeometryException {
173
        GeometryManager geomManager= GeometryLocator.getGeometryManager();
174
        Double segmentSide = Double.NaN;
175
        if (curve.getNumVertices() == 1) {
176
            //
177
            segmentSide = TrimLineOperationUtils.getSide(geometry, curve.getVertex(0));
178
        } if (curve.getNumVertices() == 2) {
179
            int steps = 100;
180
            //We skip the first and last points because 
181
            //they can coincide with the geometry and give wrong results
182
            for(int t=1; t<steps; t++){
183
                double xLen = curve.getVertex(1).getX() - curve.getVertex(0).getX();
184
                double yLen = curve.getVertex(1).getY() - curve.getVertex(0).getY();
185
                double diffX = xLen/steps;
186
                double diffY = yLen/steps;
187
                
188
                Point anyPoint = geomManager.createPoint(
189
                        curve.getVertex(0).getX() + t*diffX,
190
                        curve.getVertex(0).getY() + t*diffY,
191
                        geometry.getGeometryType().getSubType());
192
                segmentSide = TrimLineOperationUtils.getSide(geometry, anyPoint);
193
                if (!segmentSide.isNaN()) {
194
                    break;
195
                }
196
            }
197
            
198
        } else {
199
            //We skip the first and last points because 
200
            //they can coincide with the geometry and give wrong results
201
            for (int j = 1; j < curve.getNumVertices()-1; j++) {
202
                Point anyPoint = curve.getVertex(j);
203
                segmentSide = TrimLineOperationUtils.getSide(geometry, anyPoint);
204
                if (!segmentSide.isNaN()) {
205
                    break;
206
                }
207
            }
208
        }
209
        return segmentSide;
210
    }
211

  
116 212
}
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
39 39
import org.gvsig.fmap.geom.primitive.Point;
40 40
import org.gvsig.tools.dispose.DisposableIterator;
41 41
import org.gvsig.tools.locator.LocatorException;
42
import org.slf4j.Logger;
43
import org.slf4j.LoggerFactory;
42 44

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

  
52
    private static final Logger LOGGER = LoggerFactory
53
        .getLogger(CurveTrimLineOperation.class);
54
        
50 55
    /*
51 56
     * Strategy:
52 57
     * 
53
     * 1. Get arc segments between curve and boundary objects.
58
     * 1. Get arc segments between curve and shears.
54 59
     * 2. Determinate what segment of curve must be deleted
55 60
     * 3. Rebuild curve taking into account the segment that must be deleted
56 61
     */
57
    public MultiCurve trimLine(Curve curveToTrim, Point insertedPoint,
58
        FeatureSelection boundaryObjects)
62
    public MultiCurve trimLine(Curve curveToTrim, Point shearingPoint,
63
        FeatureSelection shears)
59 64
        throws GeometryOperationNotSupportedException,
60 65
        GeometryOperationException, DataException, CreateGeometryException,
61 66
        LocatorException {
......
63 68
        GeometryManager geometryManager = GeometryLocator.getGeometryManager();
64 69
        int subType = curveToTrim.getGeometryType().getSubType();
65 70

  
66
        DisposableIterator it = boundaryObjects.fastIterator();
71
        DisposableIterator it = shears.fastIterator();
67 72
        MultiCurve segmentedLine = geometryManager.createMultiCurve(subType);
68 73
        segmentedLine.addCurve(curveToTrim);
69 74

  
......
98 103
        double minDistance = Double.POSITIVE_INFINITY;
99 104
        for (int i = 0; i < segmentedLine.getPrimitivesNumber(); i++) {
100 105
            curve = segmentedLine.getCurveAt(i);
101
            double distance = curve.distance(insertedPoint);
106
            double distance = curve.distance(shearingPoint);
102 107
            if (distance < minDistance) {
103 108
                index = i;
104 109
                minDistance = distance;
......
171 176
    private Geometry enhancedDifference(Geometry splitter, Curve curve)
172 177
        throws GeometryOperationNotSupportedException,
173 178
        GeometryOperationException {
174
        Geometry snapTo = curve.snapTo(splitter, 0.1);
179
        Geometry snapTo = curve.snapTo(splitter, TrimLineOperationUtils.SNAP_TOLERANCE);
175 180
        return snapTo.difference(splitter);
176 181
    }
182

  
183

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

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

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

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

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

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

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

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

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

  
267
        return trimmedCurve;
268
    }
269
    
270

  
271

  
177 272
}
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/ArcTrimLineOperation.java
55 55
     * 2. Determinate what segment of arc must be deleted
56 56
     * 3. Rebuild arc taking into account the segment that must be deleted
57 57
     */
58
    public MultiCurve trimLine(Curve curveToTrim, Point insertedPoint,
59
        FeatureSelection boundaryObjects)
58
    public MultiCurve trimLine(Curve curveToTrim, Point shearsPoint,
59
        FeatureSelection shearingObjects)
60 60
        throws GeometryOperationNotSupportedException,
61 61
        GeometryOperationException, DataException, CreateGeometryException,
62 62
        LocatorException {
......
69 69
        MultiCurve segmentedArc = geoManager.createMultiCurve(subtype);
70 70
        segmentedArc.addCurve(curveToTrim);
71 71

  
72
        DisposableIterator it = boundaryObjects.fastIterator();
72
        DisposableIterator it = shearingObjects.fastIterator();
73 73

  
74 74
        while (it.hasNext()) {
75 75
            Feature feature = (Feature) it.next();
......
86 86
        double minDistance = Double.POSITIVE_INFINITY;
87 87
        for (int i = 0; i < segmentedArc.getPrimitivesNumber(); i++) {
88 88
            arc = segmentedArc.getCurveAt(i);
89
            double distance = arc.distance(insertedPoint);
89
            double distance = arc.distance(shearsPoint);
90 90
            if (distance < minDistance) {
91 91
                index = i;
92 92
                minDistance = distance;
......
138 138
        int subtype1 = curveA.getGeometryType().getSubType();
139 139
        int subtype2 = curveB.getGeometryType().getSubType();
140 140

  
141
        Arc arc1 =
141
        Arc arc1 = null;
142
        if(curveA instanceof Arc){
143
            arc1 = (Arc)curveA;
144
        } else {
145
            arc1 =
142 146
            TrimLineOperationUtils.createArc(center, radius,
143 147
                curveA.getVertex(0),
144 148
                curveA.getVertex(curveA.getNumVertices() - 1), subtype1);
145
        Arc arc2 =
146
            TrimLineOperationUtils.createArc(center, radius,
149
        }
150
        Arc arc2 = null;
151
        if(curveB instanceof Arc){
152
            arc2 = (Arc)curveB;
153
        } else {
154
            arc2 = TrimLineOperationUtils.createArc(center, radius,
147 155
                curveB.getVertex(0),
148 156
                curveB.getVertex(curveB.getNumVertices() - 1), subtype1);
157
        }
149 158

  
150 159
        if (subtype1 == subtype2) {
151 160

  
......
168 177
        }
169 178
        return null;
170 179
    }
180

  
181

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

  
196
        GeometryManager geomManager = GeometryLocator.getGeometryManager();
197
        Arc arcToTrim = (Arc) curveToTrim;
198
        if(!arcToTrim.isCCW()) {
199
            Arc tmpArcToTrim = (Arc)geomManager.create(arcToTrim.getGeometryType());
200
            tmpArcToTrim.setPoints(arcToTrim.getEndPoint(), arcToTrim.getMiddlePoint(), arcToTrim.getInitPoint());
201
            arcToTrim = tmpArcToTrim;
202
        }
203

  
204
        GeometryManager geoManager = GeometryLocator.getGeometryManager();
205
        int subtype = arcToTrim.getGeometryType().getSubType();
206

  
207
        MultiCurve segmentedArc = geoManager.createMultiCurve(subtype);
208
        segmentedArc.addCurve(arcToTrim);
209

  
210
        Geometry geometry = boundaryObject;
211

  
212
        Geometry tmpDifference = segmentedArc.difference(geometry);
213
        if (tmpDifference instanceof MultiCurve) {
214
            segmentedArc = (MultiCurve) tmpDifference;
215
        }
216

  
217
        double side = TrimLineOperationUtils.getSide(boundaryObject, shearingPoint);
218

  
219
        int index = -1;
220
        if(!Double.isNaN(side)){
221
            Curve curve;
222
            double minDistance = Double.POSITIVE_INFINITY;
223
            for (int i = 0; i < segmentedArc.getPrimitivesNumber(); i++) {
224
                curve = segmentedArc.getCurveAt(i);
225
                double distance = curve.distance(shearingPoint);
226
                if (distance < minDistance) {
227
                    Double segmentSide = TrimLineOperationUtils.getSide(boundaryObject, curve);
228
                    if(segmentSide == side){
229
                        index = i;
230
                        minDistance = distance;
231
                    }
232
                }
233
            }
234
        }
235

  
236
        MultiCurve trimmedArc = geoManager.createMultiCurve(subtype);
237
        Point center = arcToTrim.getCenterPoint();
238

  
239
        // If Arc#getCenter() return null, we will have to use this "trick" to
240
        // get arc center.
241
        if (center == null) {
242
            center =
243
                geoManager.createPoint(arcToTrim.getEnvelope().getCenter(0),
244
                    arcToTrim.getEnvelope().getCenter(1), subtype);
245
        }
246

  
247
        double radius = center.distance(arcToTrim.getInitPoint());
248

  
249
        Curve tmpCurve = null;
250
        for (int i = 0; i < segmentedArc.getPrimitivesNumber(); i++) {
251

  
252
            if (i == index) {
253
                if (tmpCurve != null) {
254
                    trimmedArc.addCurve(tmpCurve);
255
                    tmpCurve = null;
256
                }
257
                continue;
258
            }
259

  
260
            if (tmpCurve != null) {
261
                tmpCurve =
262
                    union(center, radius, tmpCurve, segmentedArc.getCurveAt(i));
263
            } else {
264
                tmpCurve = segmentedArc.getCurveAt(i);
265
            }
266
        }
267
        if (tmpCurve != null) {
268
            trimmedArc.addCurve(tmpCurve);
269
        }
270

  
271
        return trimmedArc;
272
    }
273

  
171 274
}
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/TrimLineEditingProvider.java
25 25
package org.gvsig.vectorediting.lib.prov.trimline;
26 26

  
27 27
import java.util.ArrayList;
28
import java.util.HashMap;
28 29
import java.util.List;
29

  
30
import org.cresques.cts.IProjection;
31

  
30
import java.util.Map;
31
import java.util.logging.Level;
32
import java.util.logging.Logger;
32 33
import org.gvsig.fmap.dal.exception.DataException;
33 34
import org.gvsig.fmap.dal.feature.EditableFeature;
34 35
import org.gvsig.fmap.dal.feature.Feature;
35
import org.gvsig.fmap.dal.feature.FeatureQuery;
36 36
import org.gvsig.fmap.dal.feature.FeatureSelection;
37
import org.gvsig.fmap.dal.feature.FeatureSet;
38 37
import org.gvsig.fmap.dal.feature.FeatureStore;
39 38
import org.gvsig.fmap.geom.Geometry;
39
import static org.gvsig.fmap.geom.Geometry.TYPES.CURVE;
40
import static org.gvsig.fmap.geom.Geometry.TYPES.MULTICURVE;
41
import org.gvsig.fmap.geom.GeometryException;
40 42
import org.gvsig.fmap.geom.GeometryLocator;
41 43
import org.gvsig.fmap.geom.GeometryManager;
42 44
import org.gvsig.fmap.geom.aggregate.MultiCurve;
43 45
import org.gvsig.fmap.geom.exception.CreateGeometryException;
44 46
import org.gvsig.fmap.geom.operation.GeometryOperationException;
45 47
import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException;
48
import org.gvsig.fmap.geom.primitive.Arc;
46 49
import org.gvsig.fmap.geom.primitive.Curve;
50
import org.gvsig.fmap.geom.primitive.Line;
47 51
import org.gvsig.fmap.geom.primitive.Point;
48 52
import org.gvsig.fmap.geom.primitive.Primitive;
49 53
import org.gvsig.fmap.geom.type.GeometryType;
50 54
import org.gvsig.fmap.mapcontext.MapContext;
51
import org.gvsig.fmap.mapcontext.layers.vectorial.SpatialEvaluatorsFactory;
52 55
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
53 56
import org.gvsig.tools.dispose.DisposableIterator;
54
import org.gvsig.tools.dispose.DisposeUtils;
55 57
import org.gvsig.tools.dynobject.DynObject;
56
import org.gvsig.tools.evaluator.Evaluator;
57 58
import org.gvsig.tools.exception.BaseException;
58 59
import org.gvsig.tools.service.spi.ProviderServices;
59 60
import org.gvsig.tools.visitor.VisitCanceledException;
......
75 76
import org.gvsig.vectorediting.lib.spi.EditingProviderFactory;
76 77
import org.gvsig.vectorediting.lib.spi.EditingProviderLocator;
77 78
import org.gvsig.vectorediting.lib.spi.EditingProviderManager;
79
import org.gvsig.vectorediting.lib.spi.EditingProviderServices;
78 80

  
79 81
/**
80 82
 * @author llmarques
......
85 87

  
86 88
    private final int TOLERANCE_PIXELS = 3;
87 89

  
88
    private Point insertedPoint;
89

  
90 90
    private final EditingServiceParameter selectionParameter;
91 91

  
92
    private final EditingServiceParameter linesToTrimParameter;
92
    private final EditingServiceParameter geometryToTrimWithParameter;
93 93

  
94
    private FeatureSelection selection;
94
    private final EditingServiceParameter shearingPointParameter;
95
    
96
    protected Map<EditingServiceParameter, Object> values;
95 97

  
96
    private FeatureSet linesToTrim;
97

  
98 98
    private final FeatureStore featureStore;
99 99

  
100 100
    private final MapContext mapContext;
......
123 123
            new DefaultEditingServiceParameter("selection", "selection",
124 124
                TYPE.SELECTION);
125 125

  
126
        this.linesToTrimParameter =
127
            new DefaultEditingServiceParameter("line_to_trim", "line_to_trim",
126
        this.geometryToTrimWithParameter =
127
            new DefaultEditingServiceParameter("geometry_to_trim_with", "geometry_to_trim_with",
128 128
                TYPE.POSITION);
129
        
130
        this.shearingPointParameter
131
                = new DefaultEditingServiceParameter("shearing_point",
132
                        "shearing_point", TYPE.POSITION);
133

  
129 134
    }
130 135

  
136
    @Override
131 137
    public EditingServiceParameter next() {
132
        if (selection == null) {
138
        if (values.get(selectionParameter) == null) {
133 139
            return selectionParameter;
134
        } else if (linesToTrim == null) {
135
            return linesToTrimParameter;
140
        } else if (values.get(geometryToTrimWithParameter) == null) {
141
            return geometryToTrimWithParameter;
142
        } else if (values.get(shearingPointParameter) == null) {
143
            return shearingPointParameter;
136 144
        }
137 145
        return null;
138 146
    }
139 147

  
148
    @Override
140 149
    public DrawingStatus getDrawingStatus(Point mousePosition)
141 150
        throws DrawServiceException {
142
        if (selection != null) {
151
        FeatureSelection selection = (FeatureSelection) values.get(selectionParameter);
152
        Geometry shears = (Geometry) values.get(geometryToTrimWithParameter);
153
        if (selection != null && shears != null) {
143 154
            DefaultDrawingStatus drawingStatus = new DefaultDrawingStatus();
144 155

  
145 156
            EditingProviderManager editingProviderManager =
......
147 158
            ISymbol lineSymbolEditing =
148 159
                editingProviderManager.getSymbol("line-symbol-editing");
149 160

  
150
            double tolerance =
151
                mapContext.getViewPort().toMapDistance(TOLERANCE_PIXELS);
152

  
153
            Geometry buffer;
154
            FeatureSet geometries;
155
            DisposableIterator it = null;
156 161
            try {
157
                // Create buffer with tolerance to get the geometry to be
158
                // extended
159
                buffer = mousePosition.buffer(tolerance);
160
                geometries = getGeometryByBuffer(buffer);
161

  
162
                it = geometries.fastIterator();
163
                while (it.hasNext()) {
164
                    Feature feature = (Feature) it.next();
165
                    if (!selection.isSelected(feature)) {
162
                
163
                DisposableIterator selectionIterator = null;
164
                selectionIterator = selection.fastIterator();
165
                while (selectionIterator.hasNext()) {
166
                    Feature feature = (Feature) selectionIterator.next();
167
                    if (feature != null) {
166 168
                        Geometry geometry = feature.getDefaultGeometry();
169
                        if(geometry != null && geometry.intersects(shears)) {
170
                            if (geometry instanceof MultiCurve) {
171
                                MultiCurve multiCurve = (MultiCurve) geometry;
167 172

  
168
                        if (geometry instanceof MultiCurve) {
169
                            MultiCurve multiCurve = (MultiCurve) geometry;
173
                                for (int i = 0; i < multiCurve
174
                                        .getPrimitivesNumber(); i++) {
170 175

  
171
                            for (int i = 0; i < multiCurve
172
                                .getPrimitivesNumber(); i++) {
176
                                    Curve curve = multiCurve.getCurveAt(i);
177
                                    MultiCurve trimmedCurve
178
                                            = trimLine(mousePosition, curve, shears);
179
                                    for (int j = 0; j < trimmedCurve
180
                                            .getPrimitivesNumber(); j++) {
181
                                        drawingStatus.addStatus(trimmedCurve.getCurveAt(j),
182
                                                lineSymbolEditing, "");
183
                                    }
184
                                }
173 185

  
174
                                Curve curve = multiCurve.getCurveAt(i);
175
                                MultiCurve extendedCurve =
176
                                    trimLine(mousePosition, curve);
186
                            } else if (geometry instanceof Curve) {
187
                                Curve curve = (Curve) geometry;
188
                                MultiCurve extendedCurve
189
                                        = trimLine(mousePosition, curve, shears);
177 190
                                for (int j = 0; j < extendedCurve
178
                                    .getPrimitivesNumber(); j++) {
191
                                        .getPrimitivesNumber(); j++) {
179 192
                                    drawingStatus.addStatus(
180
                                        extendedCurve.getCurveAt(j),
181
                                        lineSymbolEditing, "");
193
                                            extendedCurve.getCurveAt(j),
194
                                            lineSymbolEditing, "");
182 195
                                }
183 196
                            }
184

  
185
                        } else if (geometry instanceof Curve) {
186
                            Curve curve = (Curve) geometry;
187
                            MultiCurve extendedCurve =
188
                                trimLine(mousePosition, curve);
189
                            for (int j = 0; j < extendedCurve
190
                                .getPrimitivesNumber(); j++) {
191
                                drawingStatus.addStatus(
192
                                    extendedCurve.getCurveAt(j),
193
                                    lineSymbolEditing, "");
194
                            }
195 197
                        }
196 198
                    }
197 199
                }
198
            } catch (BaseException e) {
199
                throw new DrawServiceException(e);
200
            } finally {
201
                DisposeUtils.disposeQuietly(it);
200

  
201
                
202
            } catch (BaseException ex) {
203
                throw new DrawServiceException(ex);
202 204
            }
205
            
203 206
            return drawingStatus;
204 207
        }
205 208
        return null;
206 209
    }
207 210

  
208
    private MultiCurve trimLine(Point point, Curve curve)
211
    private MultiCurve trimLine(Point shearingPoint, Curve curve, Geometry shearsGeometry)
209 212
        throws GeometryOperationNotSupportedException,
210 213
        GeometryOperationException, DataException, CreateGeometryException {
211 214

  
212 215
        TrimLineOperation operation =
213 216
            TrimLineOperationUtils.getOperation((Primitive) curve);
214 217

  
215
        return operation.trimLine(curve, point, selection);
218
        return operation.trimLine(curve, shearingPoint, shearsGeometry);
216 219
    }
217 220

  
221
    @Override
218 222
    public void stop() throws StopServiceException {
219
        linesToTrim = null;
223
        values.clear();
220 224
    }
221 225

  
226
    @Override
222 227
    public List<EditingServiceParameter> getParameters() {
223 228
        List<EditingServiceParameter> parameters =
224 229
            new ArrayList<>();
225 230
        parameters.add(selectionParameter);
226
        parameters.add(linesToTrimParameter);
231
        parameters.add(geometryToTrimWithParameter);
232
        parameters.add(shearingPointParameter);
227 233
        return parameters;
228 234
    }
229 235

  
......
232 238
        validateAndInsertValue(parameter, value);
233 239
    }
234 240

  
241
    @Override
235 242
    public void setValue(Object value) throws InvalidEntryException {
236 243
        EditingServiceParameter parameter = next();
237 244
        validateAndInsertValue(parameter, value);
......
241 248
        final EditingServiceParameter parameter, Object value)
242 249
        throws InvalidEntryException {
243 250

  
244
        if (parameter == selectionParameter
245
            && value instanceof FeatureSelection) {
251
        if (parameter == selectionParameter) {
252
            if (value instanceof FeatureSelection) {
253
                FeatureSelection featureSelection = (FeatureSelection) value;
254
                if (featureSelection.getSelectedCount() > 0) {
255
                    try {
256
                        featureSelection.accept(new Visitor() {
246 257

  
247
            FeatureSelection featureSelection = (FeatureSelection) value;
258
                            public void visit(Object obj)
259
                                    throws VisitCanceledException, BaseException {
260
                                Feature feature = (Feature) obj;
261
                                Geometry geometry
262
                                        = feature.getDefaultGeometry();
248 263

  
249
            if (featureSelection.getSelectedCount() > 0) {
250
                try {
251
                    featureSelection.accept(new Visitor() {
252

  
253
                        public void visit(Object obj)
254
                            throws VisitCanceledException, BaseException {
255
                            Feature feature = (Feature) obj;
256
                            Geometry geometry = feature.getDefaultGeometry();
257
                            GeometryType geoType = geometry.getGeometryType();
258

  
259
                            if (!geoType.isTypeOf(SURFACE)
260
                                && !geoType.isTypeOf(MULTISURFACE)
261
                                && !geoType.isTypeOf(CURVE)
262
                                && !geoType.isTypeOf(MULTICURVE)) {
263
                                throw new InvalidEntryException(null);
264
                                if (!isValidGeometryToSelect(geometry)) {
265
                                    throw new InvalidEntryException(null);
266
                                }
264 267
                            }
265
                        }
266
                    });
267

  
268
                    selection = featureSelection;
269
                    return;
270
                } catch (BaseException e) {
271
                    throw new InvalidEntryException(e);
268
                        });
269
                        values.put(parameter, featureSelection);
270
                        return;
271
                    } catch (BaseException e) {
272
                        throw new InvalidEntryException(e);
273
                    }
272 274
                }
273 275
            }
274
        } else if (parameter == linesToTrimParameter && value instanceof Point) {
276
        } else if (parameter == geometryToTrimWithParameter && value instanceof Point) {
275 277

  
276
            Point point = (Point) value;
278
            if (value instanceof Point) {
279
                Point point = (Point) value;
277 280

  
278
            try {
279
                double tolerance =
280
                    mapContext.getViewPort().toMapDistance(TOLERANCE_PIXELS);
281

  
282
                // Create buffer with tolerance to get geometries to be
283
                // extended
284
                Geometry buffer = point.buffer(tolerance);
285
                FeatureSet geometries = getGeometryByBuffer(buffer);
286

  
287
                if (geometries.getSize() > 0) {
288

  
289
                    geometries.accept(new Visitor() {
290

  
291
                        public void visit(Object obj)
292
                            throws VisitCanceledException, BaseException {
293

  
294
                            Feature feature = (Feature) obj;
295
                            final Geometry geometry =
296
                                feature.getDefaultGeometry();
297
                            GeometryType geoType = geometry.getGeometryType();
298

  
299
                            if (!geoType.isTypeOf(CURVE)
300
                                && !geoType.isTypeOf(MULTICURVE)) {
301
                                throw new InvalidEntryException(null);
302
                            }
303
                        }
304
                    });
305

  
306
                    insertedPoint = point;
307
                    linesToTrim = geometries;
281
                Geometry geometry = getGeometry(point); //editingProviderServices.getGeometryOfVisibleLayers(point, featureStore, mapContext);
282
                if (geometry != null) {
283
                    try {
284
                        values.put(parameter, geometry.toLines());
285
                    } catch (GeometryException ex) {
286
                        throw new InvalidEntryException(ex);
287
                    }
308 288
                    return;
309 289
                }
310
            } catch (BaseException e) {
311
                throw new InvalidEntryException(e);
290

  
312 291
            }
292
        } else if (parameter == shearingPointParameter && value instanceof Point) {
293

  
294
            if (value instanceof Point) {
295
                Point point = (Point) value;
296
                values.put(parameter, point);
297
                return;
298
            }
313 299
        }
314 300
        throw new InvalidEntryException(null);
315 301
    }
302
    
303
    private boolean isValidGeometryToSelect(Geometry geometry) {
304
        GeometryType geoType
305
                = geometry.getGeometryType();
306
        if (!geoType.isTypeOf(CURVE)
307
                && !geoType.isTypeOf(MULTICURVE)) {
308
            return false;
309
        }
316 310

  
317
    private FeatureSet getGeometryByBuffer(Geometry buffer)
318
        throws DataException {
319
        FeatureQuery queryByGeometry = featureStore.createFeatureQuery();
311
        if (geoType.isTypeOf(CURVE)) {
312
            if (geometry instanceof Line ) {
313
                Line line = (Line) geometry;
314
                return !line.isClosed();
315
            }
316
            if (geometry instanceof Arc ) {
317
                Arc arc = (Arc) geometry;
318
                return !arc.getInitPoint().equals(arc.getEndPoint());
319
            }
320
            return false;
321
        }
320 322

  
321
        // Get default SRS of default feature type
322
        IProjection defaultSRS =
323
            this.featureStore.getDefaultFeatureType().getDefaultSRS();
323
        if (geoType.isTypeOf(MULTICURVE)) {
324
            MultiCurve multiCurve = (MultiCurve) geometry;
325
            for (Geometry geom : multiCurve) {
326
                if (!isValidGeometryToSelect(geom)) {
327
                    return false;
328
                }
329
            }
330
        }
331
        return true;
324 332

  
325
        Evaluator iee = SpatialEvaluatorsFactory.getInstance().intersects(
326
                buffer, 
327
                defaultSRS, 
328
                featureStore
329
        );
333
    }
330 334

  
331
        queryByGeometry.setFilter(iee);
332
        queryByGeometry.setAttributeNames(null);
333
        return this.featureStore.getFeatureSet(queryByGeometry);
335
    private Geometry getGeometry(Point point) {
336
        EditingProviderServices editingProviderServices = (EditingProviderServices) getProviderServices();
337
        Geometry geometry = editingProviderServices.getGeometryOfVisibleLayers(point, featureStore, mapContext);
338
        return geometry;
334 339
    }
335 340

  
341
    @Override
336 342
    public Geometry finish() throws FinishServiceException {
337 343
        return null;
338 344
    }
339 345

  
346
    @Override
340 347
    public void finishAndStore() throws FinishServiceException {
348
        
349
        FeatureSelection selection = (FeatureSelection) values.get(selectionParameter);
350
        Geometry shearsGeometry = (Geometry) values.get(geometryToTrimWithParameter);
351
        Point point = (Point) values.get(shearingPointParameter);
341 352

  
342
        if (selection != null && linesToTrim != null) {
343

  
353
        if (selection != null && shearsGeometry != null && point != null) {
344 354
            try {
345
                linesToTrim.accept(new Visitor() {
355
                
356
                
357
                DisposableIterator selectionIterator = null;
358
                selectionIterator = selection.fastIterator();
359
                while (selectionIterator.hasNext()) {
360
                    Feature feature = (Feature) selectionIterator.next();
346 361

  
347
                    public void visit(Object obj)
348
                        throws VisitCanceledException, BaseException {
349
                        Feature feature = (Feature) obj;
350
                        Geometry geometry = feature.getDefaultGeometry();
351
                        EditableFeature eFeature = feature.getEditable();
362
                    Geometry geometry = feature.getDefaultGeometry();
363
                    
364
                    EditableFeature eFeature = feature.getEditable();
352 365

  
366
                    if(geometry.intersects(shearsGeometry)){
353 367
                        if (geometry instanceof Curve) {
354 368

  
355 369
                            Curve curveToTrim = (Curve) geometry;
356 370
                            MultiCurve result =
357
                                trimLine(insertedPoint, curveToTrim);
371
                                trimLine(point, curveToTrim, shearsGeometry);
358 372
                            eFeature.setDefaultGeometry(result);
373
                            selection.update(eFeature);
359 374

  
360 375
                        } else if (geometry instanceof MultiCurve) {
361 376

  
362 377
                            int subType =
363 378
                                geometry.getGeometryType().getSubType();
364
                            MultiCurve multiCurveTrimmed =
379
                            MultiCurve trimmedMultiCurve =
365 380
                                createMultiCurve(subType);
366 381
                            MultiCurve multiCurveToTrim = (MultiCurve) geometry;
367 382

  
......
371 386
                            for (int i = 0; i < multiCurveToTrim
372 387
                                .getPrimitivesNumber(); i++) {
373 388

  
374
                                Curve curveToTrim =
389
                                Curve primitive =
375 390
                                    multiCurveToTrim.getCurveAt(i);
376 391

  
377 392
                                double distance =
378
                                    curveToTrim.distance(insertedPoint);
393
                                    primitive.distance(point);
379 394
                                if (distance < minDistance) {
380 395
                                    nearestCurveIndex = i;
381 396
                                    minDistance = distance;
......
383 398
                            }
384 399

  
385 400
                            MultiCurve result =
386
                                trimLine(insertedPoint, multiCurveToTrim
387
                                    .getCurveAt(nearestCurveIndex));
401
                                trimLine(point, multiCurveToTrim
402
                                    .getCurveAt(nearestCurveIndex), shearsGeometry);
388 403

  
389 404
                            for (int i = 0; i < result.getPrimitivesNumber(); i++) {
390
                                multiCurveTrimmed.addCurve(result.getCurveAt(i));
405
                                trimmedMultiCurve.addCurve(result.getCurveAt(i));
391 406
                            }
392 407

  
393 408
                            for (int i = 0; i < multiCurveToTrim
394 409
                                .getPrimitivesNumber(); i++) {
395 410
                                if (i != nearestCurveIndex) {
396
                                    multiCurveTrimmed.addCurve(multiCurveToTrim
411
                                    trimmedMultiCurve.addCurve(multiCurveToTrim
397 412
                                        .getCurveAt(i));
398 413
                                }
399 414
                            }
400 415

  
401
                            eFeature.setDefaultGeometry(multiCurveTrimmed);
416
                            eFeature.setDefaultGeometry(trimmedMultiCurve);
417
                            selection.update(eFeature);
418

  
402 419
                        }
403

  
404
                        linesToTrim.update(eFeature);
405 420
                    }
406
                });
407
            } catch (BaseException e) {
408
                throw new FinishServiceException(e);
421
                }  
422
            } catch (BaseException ex) {
423
                throw new FinishServiceException(ex);
409 424
            }
410 425
        }
411 426
    }
......
421 436
        return extendedMultiCurve;
422 437
    }
423 438

  
439
    @Override
424 440
    public void start() throws StartServiceException, InvalidEntryException {
425
        linesToTrim = null;
441

  
442
        this.values = new HashMap<>();
426 443
        FeatureSelection selected = null;
427
        if (featureStore != null && selection == null) {
444
        if (featureStore != null && values.get(selectionParameter) == null) {
428 445
            try {
429 446
                selected = featureStore.getFeatureSelection();
430 447
            } catch (DataException e) {
......
441 458

  
442 459
    }
443 460

  
461
    @Override
444 462
    public String getName() {
445 463
        return TrimLineEditingProviderFactory.PROVIDER_NAME;
446 464
    }

Also available in: Unified diff