Changeset 36056 in osm for applications/editors
- Timestamp:
- 2023-02-23T21:45:50+01:00 (21 months ago)
- Location:
- applications/editors/josm/plugins/FastDraw
- Files:
-
- 8 added
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
applications/editors/josm/plugins/FastDraw/src/org/openstreetmap/josm/plugins/fastdraw/DrawnPolyLine.java
r35978 r36056 13 13 import org.openstreetmap.josm.data.coor.LatLon; 14 14 import org.openstreetmap.josm.gui.MapView; 15 15 import org.openstreetmap.josm.tools.Logging; 16 17 /** 18 * A holder for how the polyline has been drawn 19 */ 16 20 public class DrawnPolyLine { 17 21 MapView mv; 18 private LinkedList<LatLon> points = new LinkedList<>();22 private final LinkedList<LatLon> points = new LinkedList<>(); 19 23 private LinkedList<LatLon> simplePoints = new LinkedList<>(); 20 24 private Set<LatLon> used; 21 private Set<LatLon> fixed = new HashSet<>();25 private final Set<LatLon> fixed = new HashSet<>(); 22 26 23 27 private int lastIdx; 24 28 private boolean closedFlag; 25 29 30 /** 31 * Create a new object 32 */ 26 33 public DrawnPolyLine() { 27 34 clear(); … … 57 64 58 65 boolean wasSimplified() { 59 return (simplePoints != null && simplePoints.size() > 0);66 return (simplePoints != null && !simplePoints.isEmpty()); 60 67 } 61 68 … … 85 92 86 93 void undo() { 87 //if (points.size() > 0) points.removeLast();88 94 if (lastIdx > 0 && lastIdx < points.size()) { 89 95 points.remove(lastIdx); … … 114 120 } 115 121 } else { 116 // insert point into mid lle of the line122 // insert point into middle of the line 117 123 if (points.isEmpty() || !coor.equals(points.get(lastIdx))) { 118 points.add(lastIdx +1, coor);124 points.add(lastIdx + 1, coor); 119 125 lastIdx++; 120 126 } … … 137 143 /** 138 144 * Increase epsilon to fit points count in maxPKM point per 1 km 145 * @param initEpsilon min point-to line distance in pixels (tolerance, initial) 146 * @param ekf The multiplier against the epsilon for the next round, until the max points per km is reached 147 * @param k see {@link #getNodesPerKm(int)} 148 * @param maxPKM The maximum nodes per km 149 * @return The final epsilon value used 139 150 */ 140 151 double autoSimplify(double initEpsilon, double ekf, int k, double maxPKM) { 141 152 double e = initEpsilon; 142 153 if (e < 1e-3) e = 1e-3; 143 if (ekf < 1 +1e-2) ekf = 1.01;154 if (ekf < 1 + 1e-2) ekf = 1.01; 144 155 simplify(e); 145 156 while (getNodesPerKm(k) > maxPKM && e < 1e3) { 146 e = e *ekf;157 e = e * ekf; 147 158 simplify(e); 148 //System.out.printf("eps=%f n=%d\n", e,simplePoints.size());159 Logging.trace("DrawnPolyLine: eps={0} n={1}", e, simplePoints.size()); 149 160 } 150 161 return e; … … 153 164 /** 154 165 * Simplified drawn line, not touching the nodes includes in "fixed" set. 166 * @param epsilon min point-to line distance in pixels (tolerance) 155 167 */ 156 168 void simplify(double epsilon) { 157 //System.out.println("Simplify polyline...");169 Logging.trace("DrawnPolyLine: Simplify polyline..."); 158 170 int n = points.size(); 159 171 if (n < 3) return; … … 173 185 simplePoints.addAll(points); 174 186 simplePoints.retainAll(used); 175 //Main.map.mapView.repaint();176 187 used = null; 177 188 } … … 179 190 /** 180 191 * Simplification of the line specified by "points" field. 181 * Remainin points are included to "used" set.192 * Remaining points are included to "used" set. 182 193 * @param start - starting index 183 194 * @param end - ending index … … 190 201 LatLon first = points.get(start); 191 202 LatLon last = points.get(end); 192 Point first p= getPoint(first);193 Point last p= getPoint(last);203 Point firstP = getPoint(first); 204 Point lastP = getPoint(last); 194 205 used.add(first); 195 206 used.add(last); … … 197 208 if (end - start < 2) return; 198 209 199 int farthest_node = -1; 200 double farthest_dist = 0; 201 202 double d = 0; 210 int farthestNode = -1; 211 double farthestDist = 0; 203 212 204 213 for (int i = start + 1; i < end; i++) { 205 d = pointLineDistance(getPoint(points.get(i)), firstp, lastp); 206 if (d > farthest_dist) { 207 farthest_dist = d; 208 farthest_node = i; 209 } 210 } 211 212 if (farthest_dist > epsilon) { 213 douglasPeucker(start, farthest_node, epsilon, depth + 1); 214 douglasPeucker(farthest_node, end, epsilon, depth + 1); 215 } 216 } 217 218 /** Modfified funclion from LakeWalker 214 double d = pointLineDistance(getPoint(points.get(i)), firstP, lastP); 215 if (d > farthestDist) { 216 farthestDist = d; 217 farthestNode = i; 218 } 219 } 220 221 if (farthestDist > epsilon) { 222 douglasPeucker(start, farthestNode, epsilon, depth + 1); 223 douglasPeucker(farthestNode, end, epsilon, depth + 1); 224 } 225 } 226 227 /** 228 * Modified function from LakeWalker 219 229 * Gets distance from point p1 to line p2-p3 230 * @param p1 The originating point 231 * @param p2 An end of the line 232 * @param p3 The other end of the line 233 * @return The distance from point p1 to the line p2-p3 220 234 */ 221 235 public double pointLineDistance(Point p1, Point p2, Point p3) { … … 240 254 241 255 void deleteNode(int idx) { 242 if (idx <= lastIdx) lastIdx--; 256 final boolean isClosed = isClosed(); 257 final LatLon point = points.get(idx); 258 if (isClosed) { 259 if (idx == 0) idx = getPointCount() - 1; 260 if (idx == getPointCount() - 1) closedFlag = false; 261 } 262 if (idx <= lastIdx && lastIdx != 0) lastIdx--; 243 263 fixed.remove(points.get(idx)); 244 264 points.remove(idx); 265 if (isClosed && points.size() == 1 && points.get(0) == point) { 266 this.deleteNode(0); 267 } 245 268 } 246 269 … … 280 303 } 281 304 282 /** find starting point of the polyline line fragment close to p 305 /** 306 * find starting point of the polyline line fragment close to p 283 307 * line fragment = segments between two fixed (green) nodes 308 * @param p The point to find the segment for 309 * @return the LatLon of the start of the segment 284 310 */ 285 311 LatLon findBigSegment(Point p) { … … 288 314 Iterator<LatLon> it2 = points.listIterator(1); 289 315 Point p1, p2; 290 LatLon pp1, pp2, start = null;316 LatLon pp1, pp2, start; 291 317 start = points.getFirst(); 292 318 do { … … 306 332 } 307 333 308 private double pointSegmentDistance(Point p, Point p1, Point p2) { 309 double a, b, x, y, l, kt, kn, dist; 310 x = p.x-p1.x; 311 y = p.y-p1.y; 312 a = p2.x-p1.x; 313 b = p2.y-p1.y; 314 l = Math.hypot(a, b); 315 if (l == 0) return Math.hypot(x, y); // p1 = p2 316 kt = (x*a+y*b)/l; 317 kn = Math.abs((-x*b+y*a)/l); 334 private static double pointSegmentDistance(Point p, Point p1, Point p2) { 335 final int x = p.x - p1.x; 336 final int y = p.y - p1.y; 337 final int a = p2.x - p1.x; 338 final int b = p2.y - p1.y; 339 final double l = Math.hypot(a, b); 340 if (l == 0) { 341 return Math.hypot(x, y); // p1 = p2 342 } 343 final double kt = (x * a + y * b)/l; 344 final double kn = Math.abs((-x * b + y * a)/l); 345 double dist; 318 346 if (kt >= 0 && kt < l) dist = kn; else { 319 dist = Math.min(Math.hypot(x, y), Math.hypot( x-a, y-b));347 dist = Math.min(Math.hypot(x, y), Math.hypot((double) x - a, (double) y - b)); 320 348 } 321 349 return dist; … … 360 388 * max((k-1) / (L(i,i+1)+L(i+1,i+2)+...+L(i+k-1,i+k))) [ i=1..n-k ] 361 389 * @param k - window size (number of points to average points per km 390 * @return The maximum number of <i>simplified</i> line points divided by the segment length 362 391 */ 363 392 public double getNodesPerKm(int k) { … … 369 398 if (k > n) k = n; 370 399 371 ILatLon pp1, pp2 = null;400 ILatLon pp1, pp2; 372 401 Iterator<LatLon> it1, it2; 373 402 it1 = pts.listIterator(0); … … 376 405 for (int i = 0; i < n-1; i++) { 377 406 pp1 = it1.next(); 378 //p1 = getPoint(pp1);379 407 pp2 = it2.next(); 380 //p2 =sa getPoint(pp2);381 408 lens[i] = pp1.greatCircleDistance(pp2); 382 409 } 383 410 double pkm = 0, maxpkm = 0; 384 411 double len = 0; 385 int seg = 0; // averaged segments counts412 int seg; // averaged segments counts 386 413 for (int i = 1; i < n; i++) { 387 414 len += lens[i-1]; // add next next point … … 395 422 // len is length of points[i-windowSize] .. points[i] 396 423 if (len > 0) pkm = seg / len * 1000; 397 //System.out.println("i="+i+" pkm="+len+" pkm="+pkm);424 Logging.trace("DrawnPolyLine: i={0} len={1} pkm={2}", i, len, pkm); 398 425 if (pkm > maxpkm) maxpkm = pkm; 399 426 }
Note:
See TracChangeset
for help on using the changeset viewer.