Statistics
| Revision:

root / branches / v2_0_0_prep / extensions / extEditing / src / org / gvsig / editing / gui / cad / tools / split / SplitEdgeStar.java @ 29685

History | View | Annotate | Download (7.65 KB)

1
/* Spatial Operations & Editing Tools for uDig
2
 * 
3
 * Axios Engineering under a funding contract with: 
4
 *      Diputación Foral de Gipuzkoa, Ordenación Territorial 
5
 *
6
 *      http://b5m.gipuzkoa.net
7
 *      http://www.axios.es 
8
 *
9
 * (C) 2006, Diputación Foral de Gipuzkoa, Ordenación Territorial (DFG-OT). 
10
 * DFG-OT agrees to licence under Lesser General Public License (LGPL).
11
 * 
12
 * You can redistribute it and/or modify it under the terms of the 
13
 * GNU Lesser General Public License as published by the Free Software 
14
 * Foundation; version 2.1 of the License.
15
 *
16
 * This library is distributed in the hope that it will be useful,
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19
 * Lesser General Public License for more details.
20
 */
21
package org.gvsig.editing.gui.cad.tools.split;
22

    
23
import java.util.ArrayList;
24
import java.util.Iterator;
25
import java.util.List;
26

    
27
import com.vividsolutions.jts.algorithm.Angle;
28
import com.vividsolutions.jts.algorithm.CGAlgorithms;
29
import com.vividsolutions.jts.geom.Coordinate;
30
import com.vividsolutions.jts.geomgraph.DirectedEdge;
31
import com.vividsolutions.jts.geomgraph.DirectedEdgeStar;
32
import com.vividsolutions.jts.geomgraph.EdgeEnd;
33
import com.vividsolutions.jts.util.Assert;
34

    
35
/**
36
 * A {@link DirectedEdgeStar} for the {@link SplitGraphNode nodes} in a {@link SplitGraph}
37
 * 
38
 * @author Gabriel Roldán, Axios Engineering
39
 * @author Mauricio Pazos, Axios Engineering
40
 * @since 1.1.0
41
 */
42
class SplitEdgeStar extends DirectedEdgeStar {
43

    
44
    /**
45
     * Adds a DirectedEdge to the list of incident edges on this star
46
     * 
47
     * @param de non null directed edge to insert on this node star
48
     */
49
    public void insert( DirectedEdge de ) {
50
        if (de == null) {
51
            throw new NullPointerException();
52
        }
53
        insertEdgeEnd(de, de);
54
    }
55

    
56
    /**
57
     * Overrides {@link DirectedEdgeStar#insert(EdgeEnd)} just to delegate to
58
     * {@link #insert(DirectedEdge)} forcing the argument type
59
     */
60
    @Override
61
    public void insert( EdgeEnd ee ) {
62
        insert((DirectedEdge) ee);
63
    }
64

    
65
    /**
66
     * Removes the given edge from this edge star
67
     * 
68
     * @param edge
69
     * @throws IllegalArgumentException if <code>edge</code> is not one of this star's edges
70
     */
71
    public void remove( DirectedEdge edge ) {
72
        if (edge == null) {
73
            throw new NullPointerException("edge");
74
        }
75
        int degree = getDegree();
76
        Object removed = edgeMap.remove(edge);
77
        int afterDegree = getDegree();
78
        Assert.isTrue(afterDegree == degree - 1);
79
        if (edge != removed) {
80
            throw new IllegalArgumentException(
81
                                               "Tried to remove an edge not registered in this edge star: "
82
                                                       + edge);
83
        }
84
        edgeList = null; // edge list has changed - clear the cache
85
    }
86

    
87
    /**
88
     * Returns the list of Directed edges whose direction is outgoing from this star's node. That
89
     * is, for all the DirectedEdges in the star, if the edge's start point is coincident whith the
90
     * edge star node, returns the same DirectedNode, otherwise returns the edge's
91
     * {@link DirectedEdge#getSym() symmetric edge}.
92
     * 
93
     * @return
94
     */
95
    private List getOutgoingEdges() {
96
        final Coordinate nodeCoord = getCoordinate();
97
        final List edges = getEdges();
98
        final List outgoingEdges = new ArrayList(edges.size());
99
        for( Iterator it = edges.iterator(); it.hasNext(); ) {
100
            DirectedEdge edge = (DirectedEdge) it.next();
101
            if (!nodeCoord.equals2D(edge.getCoordinate())) {
102
                edge = edge.getSym();
103
            }
104
            assert nodeCoord.equals2D(edge.getCoordinate());
105
            outgoingEdges.add(edge);
106
        }
107
        return outgoingEdges;
108
    }
109

    
110
    /**
111
     * Finds the first edge to the passed in in the <code>searchDrirection</code> direction.
112
     * 
113
     * @param searchDirection one of {@link CGAlgorithms#CLOCKWISE},
114
     *        {@link CGAlgorithms#COUNTERCLOCKWISE}
115
     * @return the edge forming the acutest angle with <code>edge</code> in the
116
     *         <code>prefferredDirection</code> or <code>null</code> if there are no edges in
117
     *         the prefferred direction.
118
     */
119
    public DirectedEdge findClosestEdgeInDirection( DirectedEdge edge, final int searchDirection ) {
120
        if (edge == null) {
121
            throw new NullPointerException("edge");
122
        }
123
        if (CGAlgorithms.CLOCKWISE != searchDirection
124
                && CGAlgorithms.COUNTERCLOCKWISE != searchDirection) {
125
            throw new IllegalArgumentException("Allowed values for for searchDirection "
126
                    + "are CGAlgorithms.CLOCKWISE and CGAlgorithms.COUNTERCLOCKWISE: "
127
                    + searchDirection);
128
        }
129

    
130
        // ensure we're using the node's outgoing edge
131
        if (super.findIndex(edge) == -1) {
132
            edge = edge.getSym();
133
            if (super.findIndex(edge) == -1) {
134
                throw new IllegalArgumentException("Edge does not belongs to this edgestar");
135
            }
136
        }
137
        final int degree = getDegree();
138
        if (degree < 2) {
139
            throw new IllegalStateException("there must be at least two edges in the edge star");
140
        }
141
        final Coordinate nodeCoord = getCoordinate();
142

    
143
        assert nodeCoord.equals2D(edge.getCoordinate());
144

    
145
        double acutestAngle = Double.MAX_VALUE;
146
        DirectedEdge acutest = null;
147
        DirectedEdge adjacentEdge = null;
148

    
149
        final Coordinate tip1 = edge.getDirectedCoordinate();
150
        final Coordinate tail = nodeCoord;
151

    
152
        // ensure we're using outgoing edges
153
        final List outgoingEdges = getOutgoingEdges();
154
        for( Iterator it = outgoingEdges.iterator(); it.hasNext(); ) {
155
            adjacentEdge = (DirectedEdge) it.next();
156

    
157
            if (adjacentEdge == edge) {
158
                continue;
159
            }
160

    
161
            Coordinate tip2 = adjacentEdge.getDirectedCoordinate();
162

    
163
            double angle = computeAngleInDirection(tip1, tail, tip2, searchDirection);
164

    
165
            if (angle < acutestAngle) {
166
                acutestAngle = angle;
167
                acutest = adjacentEdge;
168
            }
169
        }
170

    
171
        return acutest;
172
    }
173

    
174
    /**
175
     * Computes the angle comprised between the vector <code>tail:tip1</code> looking in the
176
     * specified <code>direction</code> to the vector <code>tail:tip2</code>
177
     * 
178
     * @param tip1
179
     * @param tail
180
     * @param tip2
181
     * @param direction one of {@link CGAlgorithms#CLOCKWISE},
182
     *        {@link CGAlgorithms#COUNTERCLOCKWISE}
183
     * @return the angle in radians defined by the vectors tail-tip1:tail-tip2 calculated in the
184
     *         specified <code>direction</code> from tail-tip1
185
     */
186
    public double computeAngleInDirection( Coordinate tip1, Coordinate tail, Coordinate tip2,
187
                                           int direction ) {
188
        final int orientation = CGAlgorithms.computeOrientation(tail, tip1, tip2);
189

    
190
        // minimal angle (non oriented)
191
        double angle = Angle.angleBetween(tip1, tail, tip2);
192
        if (orientation != direction) {
193
            angle = Angle.PI_TIMES_2 - angle;
194
        }
195
        return angle;
196
    }
197

    
198
    public String toString() {
199
        StringBuffer sb = new StringBuffer("SplitEdgeStar[degree: ");
200
        sb.append(getDegree()).append(", edges: ");
201
        for( Iterator it = getEdges().iterator(); it.hasNext(); ) {
202
            DirectedEdge de = (DirectedEdge) it.next();
203
            sb.append("DirectedEdge[");
204
            sb.append(de.getEdge()).append(" ");
205
            sb.append("]");
206
        }
207
        sb.append("]");
208
        return sb.toString();
209
    }
210

    
211
}