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 |
} |