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 @ 496

History | View | Annotate | Download (6.43 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.Comparator;
30
import java.util.List;
31

    
32
import org.slf4j.Logger;
33
import org.slf4j.LoggerFactory;
34

    
35
import org.gvsig.fmap.geom.Geometry;
36
import org.gvsig.fmap.geom.GeometryLocator;
37
import org.gvsig.fmap.geom.GeometryManager;
38
import org.gvsig.fmap.geom.aggregate.MultiCurve;
39
import org.gvsig.fmap.geom.aggregate.MultiPoint;
40
import org.gvsig.fmap.geom.exception.CreateGeometryException;
41
import org.gvsig.fmap.geom.operation.GeometryOperationException;
42
import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException;
43
import org.gvsig.fmap.geom.primitive.Arc;
44
import org.gvsig.fmap.geom.primitive.Point;
45
import org.gvsig.tools.exception.BaseException;
46

    
47
/**
48
 * @author llmarques
49
 *
50
 */
51
public class ArcSplitOperation implements SplitOperation {
52

    
53
    private static Logger logger = LoggerFactory
54
        .getLogger(ArcSplitOperation.class);
55

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

    
69
        int subtype = geometryToBeSplitted.getGeometryType().getSubType();
70
        GeometryManager geoManager = GeometryLocator.getGeometryManager();
71

    
72
        Arc arcToBeSplitted = (Arc) geometryToBeSplitted;
73

    
74
        Geometry intersections = arcToBeSplitted.intersection(splitter);
75

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

    
89
            // Two or more intersection points
90
            MultiPoint multiIntersection = (MultiPoint) intersections;
91

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

    
105
            double radius = center.distance(arcToBeSplitted.getEndPoint());
106

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

    
113
            // Sort by angle
114
            Collections.sort(orderedIntersectionPoints,
115
                new Comparator<Point>() {
116

    
117
                    public int compare(Point p1, Point p2) {
118
                        double angle1 = 0;
119
                        double angle2 = 0;
120
                        try {
121
                            angle1 = SplitOperationUtils.getAngle(center, p1);
122
                            angle2 = SplitOperationUtils.getAngle(center, p2);
123
                        } catch (BaseException e) {
124
                            logger
125
                                .warn("Problems getting angle between center and"
126
                                    + " one intersection point");
127
                            return 0;
128
                        }
129
                        return Double.compare(angle1, angle2);
130
                    }
131
                });
132

    
133
            MultiCurve splittedArcs = geoManager.createMultiCurve(subtype);
134

    
135
            for (int i = 0; i < orderedIntersectionPoints.size(); i++) {
136
                Point intersecctionPoint = orderedIntersectionPoints.get(i);
137
                Point nextIntersecctionPoint;
138

    
139
                if (i + 1 >= orderedIntersectionPoints.size()) {
140
                    nextIntersecctionPoint = orderedIntersectionPoints.get(0);
141
                } else {
142
                    nextIntersecctionPoint =
143
                        orderedIntersectionPoints.get(i + 1);
144
                }
145

    
146
                double angle1 =
147
                    SplitOperationUtils.getAngle(center, intersecctionPoint);
148
                double angle2 =
149
                    SplitOperationUtils
150
                        .getAngle(center, nextIntersecctionPoint);
151

    
152
                Arc arc = (Arc) geoManager.create(Geometry.TYPES.ARC, subtype);
153

    
154
                arc.setPointsStartEnd(center, radius, angle1, angle2);
155
                splittedArcs.addCurve(arc);
156
            }
157

    
158
            return splittedArcs;
159
        }
160
        return arcToBeSplitted;
161
    }
162

    
163
    private boolean isClosed(Arc arc) {
164
       
165
        Point initPoint = arc.getInitPoint();
166
        Point endPoint = arc.getEndPoint();
167
        Point centerPoint = arc.getCenterPoint();
168
        
169
        if(initPoint.equals(endPoint) || centerPoint == null){
170
            return true;
171
        }
172
        return false;
173
    }
174
}