Mercurial > dive4elements > river
comparison flys-artifacts/src/main/java/de/intevation/flys/artifacts/geom/Polygon2D.java @ 1794:2ad7ba85a2b3
Work in progress: Added polygon to help creating 'Raum/Flaeche' renderers.
flys-artifacts/trunk@3117 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Fri, 28 Oct 2011 16:59:03 +0000 |
parents | |
children | fe7f9264a2ed |
comparison
equal
deleted
inserted
replaced
1793:1636686070f7 | 1794:2ad7ba85a2b3 |
---|---|
1 package de.intevation.flys.geom; | |
2 | |
3 import gnu.trove.TDoubleArrayList; | |
4 | |
5 import java.io.Serializable; | |
6 | |
7 import java.awt.Shape; | |
8 | |
9 import java.awt.geom.Path2D; | |
10 import java.awt.geom.Point2D; | |
11 | |
12 import java.util.ArrayList; | |
13 import java.util.List; | |
14 import java.util.Arrays; | |
15 import java.util.Comparator; | |
16 import java.util.Collections; | |
17 | |
18 public class Polygon2D | |
19 implements Serializable | |
20 { | |
21 public static final Comparator<Point2D> POINT_X_CMP = | |
22 new Comparator<Point2D>() { | |
23 public int compare(Point2D a, Point2D b) { | |
24 double d = a.getX() - b.getX(); | |
25 if (d < 0d) return -1; | |
26 return d > 0d ? + 1 : 0; | |
27 } | |
28 }; | |
29 | |
30 public static final Comparator<Point2D []> FIRST_POINT_X = | |
31 new Comparator<Point2D []>() { | |
32 public int compare(Point2D [] a, Point2D [] b) { | |
33 if (a.length == 0) return -1; // should not happen. | |
34 if (b.length == 0) return +1; // should not happen. | |
35 double d = a[0].getX() - b[0].getX(); | |
36 if (d < 0d) return -1; | |
37 return d > 0d ? + 1 : 0; | |
38 } | |
39 }; | |
40 | |
41 protected TDoubleArrayList xs; | |
42 protected TDoubleArrayList ys; | |
43 | |
44 public Polygon2D() { | |
45 xs = new TDoubleArrayList(); | |
46 ys = new TDoubleArrayList(); | |
47 } | |
48 | |
49 public void add(double x, double y) { | |
50 xs.add(x); | |
51 ys.add(y); | |
52 } | |
53 | |
54 public double area() { | |
55 double area = 0d; | |
56 | |
57 for (int i = 0, N = xs.size(); i < N; ++i) { | |
58 int j = (i + 1) % N; | |
59 area += xs.getQuick(i)*ys.getQuick(j); | |
60 area -= xs.getQuick(j)*ys.getQuick(i); | |
61 } | |
62 | |
63 return 0.5d*area; | |
64 } | |
65 | |
66 public Shape toShape() { | |
67 Path2D.Double path = new Path2D.Double(); | |
68 | |
69 int N = xs.size(); | |
70 | |
71 if (N > 0) { | |
72 path.moveTo(xs.getQuick(0), ys.getQuick(0)); | |
73 for (int i = 1; i < N; ++i) { | |
74 path.lineTo(xs.getQuick(i), ys.getQuick(i)); | |
75 } | |
76 path.closePath(); | |
77 } | |
78 | |
79 return path; | |
80 } | |
81 | |
82 protected static List<Point2D []> splitByNaNs( | |
83 double [] xs, | |
84 double [] ys | |
85 ) { | |
86 List<Point2D []> parts = new ArrayList<Point2D []>(); | |
87 | |
88 List<Point2D> tmp = new ArrayList<Point2D>(xs.length); | |
89 | |
90 for (int i = 0; i < xs.length; ++i) { | |
91 double x = xs[i]; | |
92 double y = ys[i]; | |
93 | |
94 if (Double.isNaN(x) || Double.isNaN(y)) { | |
95 if (!tmp.isEmpty()) { | |
96 Point2D [] part = new Point2D[tmp.size()]; | |
97 parts.add(tmp.toArray(part)); | |
98 tmp.clear(); | |
99 } | |
100 } | |
101 else { | |
102 tmp.add(new Point2D.Double(x, y)); | |
103 } | |
104 } | |
105 | |
106 if (!tmp.isEmpty()) { | |
107 Point2D [] part = new Point2D[tmp.size()]; | |
108 parts.add(tmp.toArray(part)); | |
109 } | |
110 | |
111 return parts; | |
112 } | |
113 | |
114 public static void createPolygons( | |
115 double [] xAs, double [] yAs, | |
116 double [] xBs, double [] yBs, | |
117 List<Polygon2D> positives, | |
118 List<Polygon2D> negatives | |
119 ) { | |
120 if (xAs.length == 0 || xBs.length == 0) { | |
121 return; | |
122 } | |
123 | |
124 List<Point2D []> splAs = splitByNaNs(xAs, yAs); | |
125 List<Point2D []> splBs = splitByNaNs(xBs, yBs); | |
126 | |
127 // They feeded us with NaNs only. | |
128 if (splAs.isEmpty() || splBs.isEmpty()) { | |
129 return; | |
130 } | |
131 | |
132 // Sort each part by x to ensure that the first | |
133 // is the smallest. | |
134 for (Point2D [] splA: splAs) { | |
135 Arrays.sort(splA, POINT_X_CMP); | |
136 } | |
137 | |
138 for (Point2D [] splB: splBs) { | |
139 Arrays.sort(splB, POINT_X_CMP); | |
140 } | |
141 | |
142 // Now sort all parts by there first elements. | |
143 // Should be good enough to find overlapping regions. | |
144 Collections.sort(splAs, FIRST_POINT_X); | |
145 Collections.sort(splBs, FIRST_POINT_X); | |
146 | |
147 // Check if the two series intersect at all. | |
148 // If no then there will be no area between them. | |
149 | |
150 Point2D [] p1 = splAs.get(0); | |
151 Point2D [] p2 = splBs.get(splBs.size()-1); | |
152 | |
153 // First of As greater than last of Bs. | |
154 if (POINT_X_CMP.compare(p1[0], p2[p2.length-1]) > 0) { | |
155 return; | |
156 } | |
157 | |
158 p2 = splAs.get(splAs.size()-1); | |
159 p1 = splBs.get(0); | |
160 | |
161 // First of Bs greater than last of As. | |
162 if (POINT_X_CMP.compare(p1[0], p2[p2.length-1]) > 0) { | |
163 return; | |
164 } | |
165 | |
166 // TODO: Intersect/split the two series parts. | |
167 | |
168 } | |
169 } | |
170 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : |