root / org.gvsig.toolbox / trunk / org.gvsig.toolbox / org.gvsig.toolbox.algorithm / src / main / java / es / unex / sextante / tin / linearIsolinesFromTin / LinearContourLines.java @ 59
History | View | Annotate | Download (11.4 KB)
1 | 59 | nbrodin | /**
|
---|---|---|---|
2 | * @author Josef Bezdek, ZCU Plzen
|
||
3 | * @version 1.0
|
||
4 | * @since JDK1.5
|
||
5 | */
|
||
6 | |||
7 | package es.unex.sextante.tin.linearIsolinesFromTin; |
||
8 | |||
9 | import java.util.ArrayList; |
||
10 | import java.util.Iterator; |
||
11 | import java.util.LinkedList; |
||
12 | import java.util.TreeMap; |
||
13 | |||
14 | import com.vividsolutions.jts.geom.Coordinate; |
||
15 | |||
16 | public class LinearContourLines { |
||
17 | |||
18 | ArrayList finalIsolines = null; |
||
19 | double elevatedStep;
|
||
20 | double clusterTol;
|
||
21 | double minIso;
|
||
22 | double maxIso;
|
||
23 | int numberOfIsolines;
|
||
24 | TreeMap treeIndex;
|
||
25 | |||
26 | |||
27 | /******************************************************************************************************************************
|
||
28 | * Constructor
|
||
29 | *
|
||
30 | * @param equidistance -
|
||
31 | * equidistance between isolines
|
||
32 | * @param clusterTol -
|
||
33 | * minimum diference in X,Y coordinates between points where the points are indetical
|
||
34 | */
|
||
35 | public LinearContourLines(final double equiDistance, |
||
36 | double clusterTol) {
|
||
37 | elevatedStep = equiDistance; |
||
38 | int coeficient = 1; |
||
39 | while (clusterTol < 1) { |
||
40 | coeficient *= 10;
|
||
41 | clusterTol *= 10;
|
||
42 | //System.out.println(clusterTol);
|
||
43 | } |
||
44 | this.clusterTol = coeficient * 10; |
||
45 | finalIsolines = new ArrayList(); |
||
46 | treeIndex = new TreeMap<Integer, BinaryTree>(); |
||
47 | } |
||
48 | |||
49 | |||
50 | /******************************************************************************************************************************
|
||
51 | * Private function which generetes izolines from triangle with defined elevated Step
|
||
52 | *
|
||
53 | * @param T -
|
||
54 | * triangle
|
||
55 | */
|
||
56 | private void trianglesIsoLines(final Coordinate[] triangle) { |
||
57 | Double minZ = new Double(0); |
||
58 | Double maxZ = new Double(0); |
||
59 | Coordinate startIZO = null;
|
||
60 | Coordinate stopIZO = null;
|
||
61 | double elev = Double.NEGATIVE_INFINITY; |
||
62 | |||
63 | //TEST OF SINGULAR POINTS
|
||
64 | if (triangle[0].z / elevatedStep == (int) (triangle[0].z / elevatedStep)) { |
||
65 | triangle[0].z = triangle[0].z + elevatedStep * 0.01;//Float.MIN_VALUE; |
||
66 | } |
||
67 | if (triangle[1].z / elevatedStep == (int) (triangle[1].z / elevatedStep)) { |
||
68 | triangle[1].z = triangle[1].z + elevatedStep * 0.01;//Float.MIN_VALUE; |
||
69 | } |
||
70 | if (triangle[2].z / elevatedStep == (int) (triangle[2].z / elevatedStep)) { |
||
71 | triangle[2].z = triangle[2].z + elevatedStep * 0.01;//Float.MIN_VALUE; |
||
72 | } |
||
73 | |||
74 | minZ = triangle[0].z;
|
||
75 | maxZ = triangle[0].z;
|
||
76 | if (minZ > triangle[1].z) { |
||
77 | minZ = triangle[1].z;
|
||
78 | } |
||
79 | if (minZ > triangle[2].z) { |
||
80 | minZ = triangle[2].z;
|
||
81 | } |
||
82 | if (maxZ < triangle[1].z) { |
||
83 | maxZ = triangle[1].z;
|
||
84 | } |
||
85 | if (maxZ < triangle[2].z) { |
||
86 | maxZ = triangle[2].z;
|
||
87 | } |
||
88 | if (minZ >= 0) { |
||
89 | elev = ((int) (minZ / elevatedStep + 1)) * elevatedStep; |
||
90 | } |
||
91 | else {
|
||
92 | elev = ((int) (minZ / elevatedStep)) * elevatedStep;
|
||
93 | } |
||
94 | |||
95 | if (elev <= minZ) {
|
||
96 | elev += elevatedStep; |
||
97 | } |
||
98 | |||
99 | while (elev < maxZ) {
|
||
100 | if (((triangle[0].z < elev) & (triangle[1].z > elev)) || ((triangle[0].z > elev) & (triangle[1].z < elev))) { |
||
101 | startIZO = solveLinearInterpolation(triangle[0], triangle[1], elev); |
||
102 | } |
||
103 | if (((triangle[0].z < elev) & (triangle[2].z > elev)) || ((triangle[0].z > elev) & (triangle[2].z < elev))) { |
||
104 | if (startIZO == null) { |
||
105 | startIZO = solveLinearInterpolation(triangle[0], triangle[2], elev); |
||
106 | } |
||
107 | else {
|
||
108 | stopIZO = solveLinearInterpolation(triangle[0], triangle[2], elev); |
||
109 | } |
||
110 | } |
||
111 | if (((triangle[1].z < elev) & (triangle[2].z > elev)) || ((triangle[1].z > elev) & (triangle[2].z < elev))) { |
||
112 | if (startIZO == null) { |
||
113 | startIZO = solveLinearInterpolation(triangle[1], triangle[2], elev); |
||
114 | } |
||
115 | if (stopIZO == null) { |
||
116 | stopIZO = solveLinearInterpolation(triangle[1], triangle[2], elev); |
||
117 | } |
||
118 | } |
||
119 | |||
120 | startIZO.x = Math.round(startIZO.x * clusterTol) / clusterTol;
|
||
121 | startIZO.y = Math.round(startIZO.y * clusterTol) / clusterTol;
|
||
122 | stopIZO.x = Math.round(stopIZO.x * clusterTol) / clusterTol;
|
||
123 | stopIZO.y = Math.round(stopIZO.y * clusterTol) / clusterTol;
|
||
124 | |||
125 | if (!startIZO.equals2D(stopIZO)) {
|
||
126 | sortIsolines(startIZO, stopIZO, elev); //
|
||
127 | } |
||
128 | |||
129 | startIZO = null;
|
||
130 | stopIZO = null;
|
||
131 | elev += elevatedStep; |
||
132 | |||
133 | } |
||
134 | |||
135 | } |
||
136 | |||
137 | |||
138 | /******************************************************************************************************************************
|
||
139 | * Private function which computes point on line, (Linear interpolation)
|
||
140 | *
|
||
141 | * @param A -
|
||
142 | * start point of line
|
||
143 | * @param B -
|
||
144 | * end point of line
|
||
145 | * @param elev -
|
||
146 | * defined elevation
|
||
147 | * @return - coordinate of point with definied elevation
|
||
148 | */
|
||
149 | private Coordinate solveLinearInterpolation(final Coordinate A, |
||
150 | final Coordinate B,
|
||
151 | final double elev) { |
||
152 | final double koef; |
||
153 | double rate;
|
||
154 | if (B.z > A.z) {
|
||
155 | rate = (elev - A.z) / (B.z - A.z); |
||
156 | return new Coordinate((A.x + (B.x - A.x) * rate), (A.y + (B.y - A.y) * rate), elev); |
||
157 | } |
||
158 | else {
|
||
159 | rate = (elev - B.z) / (A.z - B.z); |
||
160 | return new Coordinate((B.x + (A.x - B.x) * rate), (B.y + (A.y - B.y) * rate), elev); |
||
161 | } |
||
162 | } |
||
163 | |||
164 | |||
165 | /******************************************************************************************************************************
|
||
166 | * The method for counting isolines from TIN
|
||
167 | *
|
||
168 | * @param triangles -
|
||
169 | * array of vertexes of triangles
|
||
170 | */
|
||
171 | public void countIsolines(final Coordinate[][] triangles) { |
||
172 | for (int i = 0; i < triangles.length; i++) { |
||
173 | trianglesIsoLines(triangles[i]); |
||
174 | triangles[i] = null;
|
||
175 | } |
||
176 | } |
||
177 | |||
178 | |||
179 | /******************************************************************************************************************************
|
||
180 | * The method gets list of isolines
|
||
181 | *
|
||
182 | * @return ArrayList of isolines
|
||
183 | */
|
||
184 | public ArrayList getIsolines() { |
||
185 | return finalIsolines;
|
||
186 | } |
||
187 | |||
188 | |||
189 | /******************************************************************************************************************************
|
||
190 | * The method sorts segment of isoline to LineString
|
||
191 | *
|
||
192 | * @param coordA -
|
||
193 | * start vertex of isoline's segment
|
||
194 | * @param coordB -
|
||
195 | * stop vertex of isoline's segment
|
||
196 | * @param elevation -
|
||
197 | * elevation of isoline's segment
|
||
198 | */
|
||
199 | private void sortIsolines(final Coordinate coordA, |
||
200 | final Coordinate coordB,
|
||
201 | final double elevation) { |
||
202 | DVertex izoA = null;
|
||
203 | DVertex izoB = null;
|
||
204 | int indexA = 0; |
||
205 | int indexB = 0; |
||
206 | BinaryTree tree = null;
|
||
207 | |||
208 | final int elevIndex = new Double((elevation - minIso) / elevatedStep).intValue(); |
||
209 | |||
210 | if (treeIndex.containsKey(elevIndex)) {
|
||
211 | tree = (BinaryTree) treeIndex.get(elevIndex); |
||
212 | } |
||
213 | else {
|
||
214 | tree = new BinaryTree();
|
||
215 | treeIndex.put(elevIndex, tree); |
||
216 | } |
||
217 | |||
218 | izoA = (DVertex) tree.search(coordA); |
||
219 | izoB = (DVertex) tree.search(coordB); |
||
220 | |||
221 | if (izoA != null) { |
||
222 | indexA = 1;
|
||
223 | } |
||
224 | if (izoB != null) { |
||
225 | indexB = 2;
|
||
226 | } |
||
227 | |||
228 | switch (indexA + indexB) {
|
||
229 | case 0: { |
||
230 | final LinkedList izoList = new LinkedList(); |
||
231 | izoList.add(coordA); |
||
232 | izoList.add(coordB); |
||
233 | |||
234 | tree.insert(coordA, new Integer(finalIsolines.size())); |
||
235 | tree.insert(coordB, new Integer(finalIsolines.size())); |
||
236 | finalIsolines.add(finalIsolines.size(), izoList); |
||
237 | break;
|
||
238 | } |
||
239 | case 1: { |
||
240 | final LinkedList izoList = (LinkedList) finalIsolines.get(izoA.data); |
||
241 | if (izoList == null) { |
||
242 | break;
|
||
243 | } |
||
244 | tree.remove(coordA); |
||
245 | if (((Coordinate) izoList.getFirst()).equals2D(coordA)) {
|
||
246 | izoList.addFirst(coordB); |
||
247 | tree.insert(coordB, izoA.data); |
||
248 | } |
||
249 | else {
|
||
250 | |||
251 | izoList.addLast(coordB); |
||
252 | tree.insert(coordB, izoA.data); |
||
253 | } |
||
254 | break;
|
||
255 | } |
||
256 | case 2: { |
||
257 | final LinkedList izoList = (LinkedList) finalIsolines.get(izoB.data); |
||
258 | if (izoList == null) { |
||
259 | break;
|
||
260 | } |
||
261 | tree.remove(coordB); |
||
262 | if (((Coordinate) izoList.getFirst()).equals2D(coordB)) {
|
||
263 | izoList.addFirst(coordA); |
||
264 | tree.insert(coordA, izoB.data); |
||
265 | |||
266 | } |
||
267 | else {
|
||
268 | izoList.addLast(coordA); |
||
269 | tree.insert(coordA, izoB.data); |
||
270 | } |
||
271 | break;
|
||
272 | } |
||
273 | case 3: { |
||
274 | final LinkedList izoList = (LinkedList) finalIsolines.get(izoA.data); |
||
275 | if (izoList == null) { |
||
276 | break;
|
||
277 | } |
||
278 | if ((izoA.data.intValue() == izoB.data.intValue())) {
|
||
279 | tree.remove(coordA); |
||
280 | tree.remove(coordB); |
||
281 | if (((Coordinate) izoList.getFirst()).equals2D(coordA)) {
|
||
282 | izoList.addLast(coordA); |
||
283 | } |
||
284 | else {
|
||
285 | izoList.addFirst(coordA); |
||
286 | } |
||
287 | } |
||
288 | else {
|
||
289 | final LinkedList izoListB = (LinkedList) finalIsolines.get(izoB.data); |
||
290 | if (izoListB == null) { |
||
291 | break;
|
||
292 | } |
||
293 | if (((Coordinate) izoList.getFirst()).equals2D(coordA)) {
|
||
294 | if (((Coordinate) izoListB.getFirst()).equals2D(coordB)) {
|
||
295 | final Iterator iterIzoB = izoListB.iterator(); |
||
296 | while (iterIzoB.hasNext()) {
|
||
297 | izoList.addFirst(iterIzoB.next()); |
||
298 | } |
||
299 | } |
||
300 | else {
|
||
301 | final Iterator iterIzoB = izoListB.descendingIterator(); |
||
302 | while (iterIzoB.hasNext()) {
|
||
303 | izoList.addFirst(iterIzoB.next()); |
||
304 | } |
||
305 | } |
||
306 | } |
||
307 | else {
|
||
308 | if (((Coordinate) izoListB.getFirst()).equals2D(coordB)) {
|
||
309 | final Iterator iterIzoB = izoListB.iterator(); |
||
310 | while (iterIzoB.hasNext()) {
|
||
311 | izoList.addLast(iterIzoB.next()); |
||
312 | } |
||
313 | } |
||
314 | else {
|
||
315 | final Iterator iterIzoB = izoListB.descendingIterator(); |
||
316 | while (iterIzoB.hasNext()) {
|
||
317 | izoList.addLast(iterIzoB.next()); |
||
318 | } |
||
319 | } |
||
320 | |||
321 | } |
||
322 | finalIsolines.set(izoB.data, null);
|
||
323 | ((DVertex) tree.search((Coordinate) izoList.getLast())).data = izoA.data; |
||
324 | ((DVertex) tree.search((Coordinate) izoList.getFirst())).data = izoA.data; |
||
325 | |||
326 | } |
||
327 | tree.remove(coordA); |
||
328 | tree.remove(coordB); |
||
329 | |||
330 | } |
||
331 | } |
||
332 | |||
333 | } |
||
334 | |||
335 | } |