Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.plugin / org.gvsig.editing.app / org.gvsig.editing.app.mainplugin / src / main / java / org / gvsig / editing / gui / cad / tools / split / SplitEdgeStar.java @ 40557

History | View | Annotate | Download (8.59 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 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 3
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
/* Spatial Operations & Editing Tools for uDig
25
 * 
26
 * Axios Engineering under a funding contract with: 
27
 *      Diputación Foral de Gipuzkoa, Ordenación Territorial 
28
 *
29
 *      http://b5m.gipuzkoa.net
30
 *      http://www.axios.es 
31
 *
32
 * (C) 2006, Diputación Foral de Gipuzkoa, Ordenación Territorial (DFG-OT). 
33
 * DFG-OT agrees to licence under Lesser General Public License (LGPL).
34
 * 
35
 * You can redistribute it and/or modify it under the terms of the 
36
 * GNU Lesser General Public License as published by the Free Software 
37
 * Foundation; version 2.1 of the License.
38
 *
39
 * This library is distributed in the hope that it will be useful,
40
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
41
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
42
 * Lesser General Public License for more details.
43
 */
44
package org.gvsig.editing.gui.cad.tools.split;
45

    
46
import java.util.ArrayList;
47
import java.util.Iterator;
48
import java.util.List;
49

    
50
import com.vividsolutions.jts.algorithm.Angle;
51
import com.vividsolutions.jts.algorithm.CGAlgorithms;
52
import com.vividsolutions.jts.geom.Coordinate;
53
import com.vividsolutions.jts.geomgraph.DirectedEdge;
54
import com.vividsolutions.jts.geomgraph.DirectedEdgeStar;
55
import com.vividsolutions.jts.geomgraph.EdgeEnd;
56
import com.vividsolutions.jts.util.Assert;
57

    
58
/**
59
 * A {@link DirectedEdgeStar} for the {@link SplitGraphNode nodes} in a {@link SplitGraph}
60
 * 
61
 * @author Gabriel Roldán, Axios Engineering
62
 * @author Mauricio Pazos, Axios Engineering
63
 * @since 1.1.0
64
 */
65
class SplitEdgeStar extends DirectedEdgeStar {
66

    
67
    /**
68
     * Adds a DirectedEdge to the list of incident edges on this star
69
     * 
70
     * @param de non null directed edge to insert on this node star
71
     */
72
    public void insert( DirectedEdge de ) {
73
        if (de == null) {
74
            throw new NullPointerException();
75
        }
76
        insertEdgeEnd(de, de);
77
    }
78

    
79
    /**
80
     * Overrides {@link DirectedEdgeStar#insert(EdgeEnd)} just to delegate to
81
     * {@link #insert(DirectedEdge)} forcing the argument type
82
     */
83
    @Override
84
    public void insert( EdgeEnd ee ) {
85
        insert((DirectedEdge) ee);
86
    }
87

    
88
    /**
89
     * Removes the given edge from this edge star
90
     * 
91
     * @param edge
92
     * @throws IllegalArgumentException if <code>edge</code> is not one of this star's edges
93
     */
94
    public void remove( DirectedEdge edge ) {
95
        if (edge == null) {
96
            throw new NullPointerException("edge");
97
        }
98
        int degree = getDegree();
99
        Object removed = edgeMap.remove(edge);
100
        int afterDegree = getDegree();
101
        Assert.isTrue(afterDegree == degree - 1);
102
        if (edge != removed) {
103
            throw new IllegalArgumentException(
104
                                               "Tried to remove an edge not registered in this edge star: "
105
                                                       + edge);
106
        }
107
        edgeList = null; // edge list has changed - clear the cache
108
    }
109

    
110
    /**
111
     * Returns the list of Directed edges whose direction is outgoing from this star's node. That
112
     * is, for all the DirectedEdges in the star, if the edge's start point is coincident whith the
113
     * edge star node, returns the same DirectedNode, otherwise returns the edge's
114
     * {@link DirectedEdge#getSym() symmetric edge}.
115
     * 
116
     * @return
117
     */
118
    private List getOutgoingEdges() {
119
        final Coordinate nodeCoord = getCoordinate();
120
        final List edges = getEdges();
121
        final List outgoingEdges = new ArrayList(edges.size());
122
        for( Iterator it = edges.iterator(); it.hasNext(); ) {
123
            DirectedEdge edge = (DirectedEdge) it.next();
124
            if (!nodeCoord.equals2D(edge.getCoordinate())) {
125
                edge = edge.getSym();
126
            }
127
            assert nodeCoord.equals2D(edge.getCoordinate());
128
            outgoingEdges.add(edge);
129
        }
130
        return outgoingEdges;
131
    }
132

    
133
    /**
134
     * Finds the first edge to the passed in in the <code>searchDrirection</code> direction.
135
     * 
136
     * @param searchDirection one of {@link CGAlgorithms#CLOCKWISE},
137
     *        {@link CGAlgorithms#COUNTERCLOCKWISE}
138
     * @return the edge forming the acutest angle with <code>edge</code> in the
139
     *         <code>prefferredDirection</code> or <code>null</code> if there are no edges in
140
     *         the prefferred direction.
141
     */
142
    public DirectedEdge findClosestEdgeInDirection( DirectedEdge edge, final int searchDirection ) {
143
        if (edge == null) {
144
            throw new NullPointerException("edge");
145
        }
146
        if (CGAlgorithms.CLOCKWISE != searchDirection
147
                && CGAlgorithms.COUNTERCLOCKWISE != searchDirection) {
148
            throw new IllegalArgumentException("Allowed values for for searchDirection "
149
                    + "are CGAlgorithms.CLOCKWISE and CGAlgorithms.COUNTERCLOCKWISE: "
150
                    + searchDirection);
151
        }
152

    
153
        // ensure we're using the node's outgoing edge
154
        if (super.findIndex(edge) == -1) {
155
            edge = edge.getSym();
156
            if (super.findIndex(edge) == -1) {
157
                throw new IllegalArgumentException("Edge does not belongs to this edgestar");
158
            }
159
        }
160
        final int degree = getDegree();
161
        if (degree < 2) {
162
            throw new IllegalStateException("there must be at least two edges in the edge star");
163
        }
164
        final Coordinate nodeCoord = getCoordinate();
165

    
166
        assert nodeCoord.equals2D(edge.getCoordinate());
167

    
168
        double acutestAngle = Double.MAX_VALUE;
169
        DirectedEdge acutest = null;
170
        DirectedEdge adjacentEdge = null;
171

    
172
        final Coordinate tip1 = edge.getDirectedCoordinate();
173
        final Coordinate tail = nodeCoord;
174

    
175
        // ensure we're using outgoing edges
176
        final List outgoingEdges = getOutgoingEdges();
177
        for( Iterator it = outgoingEdges.iterator(); it.hasNext(); ) {
178
            adjacentEdge = (DirectedEdge) it.next();
179

    
180
            if (adjacentEdge == edge) {
181
                continue;
182
            }
183

    
184
            Coordinate tip2 = adjacentEdge.getDirectedCoordinate();
185

    
186
            double angle = computeAngleInDirection(tip1, tail, tip2, searchDirection);
187

    
188
            if (angle < acutestAngle) {
189
                acutestAngle = angle;
190
                acutest = adjacentEdge;
191
            }
192
        }
193

    
194
        return acutest;
195
    }
196

    
197
    /**
198
     * Computes the angle comprised between the vector <code>tail:tip1</code> looking in the
199
     * specified <code>direction</code> to the vector <code>tail:tip2</code>
200
     * 
201
     * @param tip1
202
     * @param tail
203
     * @param tip2
204
     * @param direction one of {@link CGAlgorithms#CLOCKWISE},
205
     *        {@link CGAlgorithms#COUNTERCLOCKWISE}
206
     * @return the angle in radians defined by the vectors tail-tip1:tail-tip2 calculated in the
207
     *         specified <code>direction</code> from tail-tip1
208
     */
209
    public double computeAngleInDirection( Coordinate tip1, Coordinate tail, Coordinate tip2,
210
                                           int direction ) {
211
        final int orientation = CGAlgorithms.computeOrientation(tail, tip1, tip2);
212

    
213
        // minimal angle (non oriented)
214
        double angle = Angle.angleBetween(tip1, tail, tip2);
215
        if (orientation != direction) {
216
            angle = Angle.PI_TIMES_2 - angle;
217
        }
218
        return angle;
219
    }
220

    
221
    public String toString() {
222
        StringBuffer sb = new StringBuffer("SplitEdgeStar[degree: ");
223
        sb.append(getDegree()).append(", edges: ");
224
        for( Iterator it = getEdges().iterator(); it.hasNext(); ) {
225
            DirectedEdge de = (DirectedEdge) it.next();
226
            sb.append("DirectedEdge[");
227
            sb.append(de.getEdge()).append(" ");
228
            sb.append("]");
229
        }
230
        sb.append("]");
231
        return sb.toString();
232
    }
233

    
234
}