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.split / src / main / java / org / gvsig / vectorediting / lib / prov / split / operation / ArcSplitOperation.java @ 2616

History | View | Annotate | Download (6.17 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright ? 2007-2014 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.split.operation;
26

    
27
import java.util.ArrayList;
28
import java.util.Collections;
29
import java.util.List;
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.aggregate.MultiPoint;
35
import org.gvsig.fmap.geom.exception.CreateGeometryException;
36
import org.gvsig.fmap.geom.operation.GeometryOperationException;
37
import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException;
38
import org.gvsig.fmap.geom.primitive.Arc;
39
import org.gvsig.fmap.geom.primitive.Point;
40
import org.gvsig.tools.exception.BaseException;
41
import org.slf4j.Logger;
42
import org.slf4j.LoggerFactory;
43

    
44
/**
45
 * @author llmarques
46
 *
47
 */
48
public class ArcSplitOperation implements SplitOperation {
49

    
50
    private static final Logger LOGGER =  LoggerFactory
51
        .getLogger(ArcSplitOperation.class);
52

    
53
    /*
54
     * Strategy:
55
     * 
56
     * 1. Get intersection points.
57
     * 2. Get center and radius
58
     * 3. Order intersections points by angle
59
     * 4. Iterate over ordered intersection points and create splitted arcs.
60
     * Stop iteration when all intersections points have been iterated.
61
     */
62
    @Override
63
    public Geometry split(Geometry geometryToBeSplitted, Geometry splitter)
64
        throws GeometryOperationNotSupportedException,
65
        GeometryOperationException, CreateGeometryException {
66

    
67
        int subtype = geometryToBeSplitted.getGeometryType().getSubType();
68
        GeometryManager geoManager = GeometryLocator.getGeometryManager();
69

    
70
        Arc arcToBeSplitted = (Arc) geometryToBeSplitted;
71

    
72
        Geometry intersections = arcToBeSplitted.intersection(splitter);
73

    
74
        if (intersections == null) {
75
            return geometryToBeSplitted;
76
        } else if (intersections instanceof Point) {
77
            
78
            if(isClosed(arcToBeSplitted)){ // Closed arcs can be splitted by one point
79
                return arcToBeSplitted;
80
            } else {
81
                return arcToBeSplitted.difference(splitter);
82
            }
83
            
84
            
85
        } else if (intersections instanceof MultiPoint) {
86

    
87
            // Two or more intersection points
88
            MultiPoint multiIntersection = (MultiPoint) intersections;
89

    
90
            // Arc#getCenterPoint can return null if two points of arc are the
91
            // same
92
            Point tmpCenter = arcToBeSplitted.getCenterPoint();
93
            if (tmpCenter == null) {
94
                // If center is null, we use this "trick". Get center of arc
95
                // envelope.
96
                tmpCenter =
97
                    SplitOperationUtils.createPoint(arcToBeSplitted
98
                        .getEnvelope().getCenter(0), arcToBeSplitted
99
                        .getEnvelope().getCenter(1), subtype);
100
            }
101
            final Point center = tmpCenter;
102

    
103
            double radius = center.distance(arcToBeSplitted.getEndPoint());
104

    
105
            // Order intersection points by angle to create arcs correctly
106
            List<Point> orderedIntersectionPoints = new ArrayList<>();
107
            for (int i = 0; i < multiIntersection.getPrimitivesNumber(); i++) {
108
                orderedIntersectionPoints.add(multiIntersection.getPointAt(i));
109
            }
110

    
111
            // Sort by angle
112
            Collections.sort(orderedIntersectionPoints, (Point p1, Point p2) -> {
113
                double angle1;
114
                double angle2;
115
                try {
116
                    angle1 = SplitOperationUtils.getAngle(center, p1);
117
                    angle2 = SplitOperationUtils.getAngle(center, p2);
118
                } catch (BaseException e) {
119
                    LOGGER
120
                            .warn("Problems getting angle between center and"
121
                                    + " one intersection point");
122
                    return 0;
123
                }
124
                return Double.compare(angle1, angle2);
125
            });
126

    
127
            MultiCurve splittedArcs = geoManager.createMultiCurve(subtype);
128

    
129
            for (int i = 0; i < orderedIntersectionPoints.size(); i++) {
130
                Point intersecctionPoint = orderedIntersectionPoints.get(i);
131
                Point nextIntersecctionPoint;
132

    
133
                if (i + 1 >= orderedIntersectionPoints.size()) {
134
                    nextIntersecctionPoint = orderedIntersectionPoints.get(0);
135
                } else {
136
                    nextIntersecctionPoint =
137
                        orderedIntersectionPoints.get(i + 1);
138
                }
139

    
140
                double angle1 =
141
                    SplitOperationUtils.getAngle(center, intersecctionPoint);
142
                double angle2 =
143
                    SplitOperationUtils
144
                        .getAngle(center, nextIntersecctionPoint);
145

    
146
                Arc arc = (Arc) geoManager.create(Geometry.TYPES.ARC, subtype);
147

    
148
                arc.setPointsStartEnd(center, radius, angle1, angle2);
149
                splittedArcs.addCurve(arc);
150
            }
151

    
152
            return splittedArcs;
153
        }
154
        return arcToBeSplitted;
155
    }
156

    
157
    private boolean isClosed(Arc arc) {
158
       
159
        Point initPoint = arc.getInitPoint();
160
        Point endPoint = arc.getEndPoint();
161
        Point centerPoint = arc.getCenterPoint();
162
        
163
        return initPoint.equals(endPoint) || centerPoint == null;
164
    }
165
}