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

History | View | Annotate | Download (5.25 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
        MultiPoint intersections =
75
            (MultiPoint) arcToBeSplitted.intersection(splitter);
76

    
77
        if (intersections == null) {
78
            return geometryToBeSplitted;
79
        }
80

    
81
        // Arc#getCenterPoint can return null if two points of arc are the same
82
        Point tmpCenter = arcToBeSplitted.getCenterPoint();
83
        if (tmpCenter == null) {
84
            // If center is null, we use this "trick". Get center of arc
85
            // envelope.
86
            tmpCenter =
87
                SplitOperationUtils.createPoint(arcToBeSplitted.getEnvelope()
88
                    .getCenter(0), arcToBeSplitted.getEnvelope().getCenter(1),
89
                    subtype);
90
        }
91
        final Point center = tmpCenter;
92

    
93
        double radius = center.distance(arcToBeSplitted.getEndPoint());
94

    
95
        // Order intersection points by angle to create arcs correctly
96
        List<Point> orderedIntersectionPoints = new ArrayList<Point>();
97
        for (int i = 0; i < intersections.getPrimitivesNumber(); i++) {
98
            orderedIntersectionPoints.add(intersections.getPointAt(i));
99
        }
100

    
101
        // Sort by angle
102
        Collections.sort(orderedIntersectionPoints, new Comparator<Point>() {
103

    
104
            public int compare(Point p1, Point p2) {
105
                double angle1 = 0;
106
                double angle2 = 0;
107
                try {
108
                    angle1 = SplitOperationUtils.getAngle(center, p1);
109
                    angle2 = SplitOperationUtils.getAngle(center, p2);
110
                } catch (BaseException e) {
111
                    logger.warn("Problems getting angle between center and"
112
                        + " one intersection point");
113
                    return 0;
114
                }
115
                return Double.compare(angle1, angle2);
116
            }
117
        });
118

    
119
        MultiCurve splittedArcs = geoManager.createMultiCurve(subtype);
120

    
121
        for (int i = 0; i < orderedIntersectionPoints.size(); i++) {
122
            Point intersecctionPoint = orderedIntersectionPoints.get(i);
123
            Point nextIntersecctionPoint;
124

    
125
            if (i + 1 >= orderedIntersectionPoints.size()) {
126
                nextIntersecctionPoint = orderedIntersectionPoints.get(0);
127
            } else {
128
                nextIntersecctionPoint = orderedIntersectionPoints.get(i + 1);
129
            }
130

    
131
            double angle1 =
132
                SplitOperationUtils.getAngle(center, intersecctionPoint);
133
            double angle2 =
134
                SplitOperationUtils.getAngle(center, nextIntersecctionPoint);
135

    
136
            Arc arc = (Arc) geoManager.create(Geometry.TYPES.ARC, subtype);
137

    
138
            arc.setPointsStartEnd(center, radius, angle1, angle2);
139
            splittedArcs.addCurve(arc);
140
        }
141

    
142
        return splittedArcs;
143
    }
144
}