Mercurial > dive4elements > gnv-client
comparison gnv-artifacts/src/main/java/de/intevation/gnv/utils/IndexBuffer.java @ 349:555483213f78
Added buffer creator in index (i, j) space.
gnv-artifacts/trunk@419 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Mon, 14 Dec 2009 14:36:43 +0000 |
parents | |
children | b1f5f2a8840f |
comparison
equal
deleted
inserted
replaced
348:ec95d3248576 | 349:555483213f78 |
---|---|
1 package de.intevation.gnv.utils; | |
2 | |
3 import java.awt.geom.Point2D; | |
4 | |
5 import java.awt.Point; | |
6 | |
7 import java.util.List; | |
8 | |
9 /** | |
10 * Create buffers around integer pairs (i_1..n), j_1..n). | |
11 * | |
12 * @author Sascha L. Teichmann (sascha.teichmann@intevation.de) | |
13 */ | |
14 public class IndexBuffer | |
15 { | |
16 public static final double EPSILON = 1e-6d; | |
17 public static final double OFFSET = 1.0d; | |
18 | |
19 public static final String I_COLUMN = "IPOSITION"; | |
20 public static final String J_COLUMN = "JPOSITION"; | |
21 | |
22 public static final class Segment { | |
23 | |
24 private Segment next; | |
25 | |
26 private Point2D.Double n; | |
27 private double d1; | |
28 private double d2; | |
29 | |
30 private int iMin; | |
31 private int iMax; | |
32 | |
33 private int jMin; | |
34 private int jMax; | |
35 | |
36 public Segment(Point a, Point b, Segment next) { | |
37 | |
38 this.next = next; | |
39 | |
40 iMin = Math.min(a.x, b.x)-1; | |
41 iMax = Math.max(a.x, b.x)+1; | |
42 | |
43 jMin = Math.min(a.y, b.y)-1; | |
44 jMax = Math.max(a.y, b.y)+1; | |
45 | |
46 if (a.x > b.x) { | |
47 Point p = a; a = b; b = p; | |
48 } | |
49 | |
50 Point2D.Double p1, p2, p3; | |
51 | |
52 if (a.y < b.y) { | |
53 p1 = new Point2D.Double(a.x - OFFSET, a.y + 1 + OFFSET); | |
54 p2 = new Point2D.Double(b.x - OFFSET, b.y + 1 + OFFSET); | |
55 p3 = new Point2D.Double(a.x + 1 + OFFSET, a.y - OFFSET); | |
56 } | |
57 else { | |
58 p1 = new Point2D.Double(a.x + 1 + OFFSET, a.y + 1 + OFFSET); | |
59 p2 = new Point2D.Double(b.x + 1 + OFFSET, b.y + 1 + OFFSET); | |
60 p3 = new Point2D.Double(b.x - OFFSET, b.y - OFFSET); | |
61 } | |
62 | |
63 n = normalize(orthogonal(sub(p1, p2))); | |
64 | |
65 d1 = dot(n, p1); | |
66 d2 = dot(n, p3); | |
67 | |
68 if (d1 > d2) { | |
69 double d = d1; | |
70 d1 = d2; | |
71 d2 = d; | |
72 } | |
73 } | |
74 | |
75 public boolean check(int i, int j) { | |
76 if (i < iMin || i > iMax || j < jMin || j > jMax) { | |
77 return false; | |
78 } | |
79 double v = dot(n, i, j); | |
80 return v >= d1 && v <= d2; | |
81 } | |
82 | |
83 public void toWhereClause(StringBuilder sb, String iColumn, String jColumn) { | |
84 sb.append('(') | |
85 .append(iColumn).append(" >= ").append(iMin).append(" AND ") | |
86 .append(iColumn).append(" <= ").append(iMax).append(" AND ") | |
87 .append(jColumn).append(" >= ").append(jMin).append(" AND ") | |
88 .append(jColumn).append(" <= ").append(jMax).append(" AND (") | |
89 .append(n.x).append('*').append(iColumn).append(" + ") | |
90 .append(n.y).append('*').append(jColumn) | |
91 .append(") BETWEEN ").append(d1).append(" AND ").append(d2).append(')'); | |
92 } | |
93 } // class Segment | |
94 | |
95 protected Segment head; | |
96 | |
97 protected String iColumn; | |
98 protected String jColumn; | |
99 | |
100 public IndexBuffer(List<? extends Point> points) { | |
101 this(points, I_COLUMN, J_COLUMN); | |
102 } | |
103 | |
104 public IndexBuffer(List<? extends Point> points, String iColumn, String jColumn) { | |
105 this.iColumn = iColumn; | |
106 this.jColumn = jColumn; | |
107 | |
108 for (int i = 1, N = points.size(); i < N; ++i) { | |
109 Point p1 = (Point)points.get(i-1); | |
110 Point p2 = (Point)points.get(i); | |
111 head = new Segment(p1, p2, head); | |
112 } | |
113 } | |
114 | |
115 public boolean check(int i, int j) { | |
116 | |
117 Segment current = head; | |
118 while (current != null) { | |
119 if (current.check(i, j)) { | |
120 return true; | |
121 } | |
122 current = current.next; | |
123 } | |
124 return false; | |
125 } | |
126 | |
127 public String toWhereClause() { | |
128 | |
129 StringBuilder sb = new StringBuilder(); | |
130 | |
131 Segment current = head; | |
132 | |
133 while (current != null) { | |
134 if (current != head) { | |
135 sb.append(" OR "); | |
136 } | |
137 current.toWhereClause(sb, iColumn, jColumn); | |
138 current = current.next; | |
139 } | |
140 | |
141 return sb.toString(); | |
142 } | |
143 | |
144 public static Point2D.Double sub(Point2D.Double p1, Point2D.Double p2) { | |
145 return new Point2D.Double(p1.x - p2.x, p1.y - p2.y); | |
146 } | |
147 | |
148 public static final double dot(Point2D.Double p1, Point2D.Double p2) { | |
149 return p1.x*p2.x + p1.y*p2.y; | |
150 } | |
151 | |
152 public static final double dot(Point2D.Double p1, double x, double y) { | |
153 return p1.x*x + p1.y*y; | |
154 } | |
155 | |
156 public static final Point2D.Double scale(Point2D.Double p, double s) { | |
157 return new Point2D.Double(s*p.x, s*p.y); | |
158 } | |
159 | |
160 public static final Point2D.Double normalize(Point2D.Double p) { | |
161 double len2 = Math.sqrt(dot(p, p)); | |
162 return len2 > EPSILON ? scale(p, 1d/len2) : p; | |
163 } | |
164 | |
165 public static final Point2D.Double orthogonal(Point2D.Double p) { | |
166 return new Point2D.Double(p.y, -p.x); | |
167 } | |
168 } | |
169 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8: |