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