Changeset 11144 in josm for trunk/src/org/openstreetmap/josm/gui
- Timestamp:
- 2016-10-18T13:04:35+02:00 (9 years ago)
- Location:
- trunk/src/org/openstreetmap/josm/gui
- Files:
-
- 2 edited
-
MapViewState.java (modified) (1 diff)
-
draw/MapViewPath.java (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/gui/MapViewState.java
r11141 r11144 553 553 * @since 10874 554 554 */ 555 public MapViewPoint interpolate(MapViewPoint p1, inti) {555 public MapViewPoint interpolate(MapViewPoint p1, double i) { 556 556 return new MapViewViewPoint((1 - i) * getInViewX() + i * p1.getInViewX(), (1 - i) * getInViewY() + i * p1.getInViewY()); 557 557 } -
trunk/src/org/openstreetmap/josm/gui/draw/MapViewPath.java
r11026 r11144 2 2 package org.openstreetmap.josm.gui.draw; 3 3 4 import java.awt.geom.Point2D; 5 import java.text.MessageFormat; 4 import java.awt.BasicStroke; 5 import java.awt.Shape; 6 import java.awt.Stroke; 7 import java.awt.geom.PathIterator; 6 8 7 9 import org.openstreetmap.josm.data.coor.EastNorth; … … 12 14 import org.openstreetmap.josm.gui.MapViewState.MapViewRectangle; 13 15 16 14 17 /** 15 18 * This is a version of a java Path2D that allows you to add points to it by simply giving their east/north, lat/lon or node coordinates. 16 19 * <p> 17 * Paths far outside the view area are automatically clipped to increase performance. 20 * It is possible to clip the part of the path that is outside the view. This is useful when drawing dashed lines. Those lines use up a lot of 21 * performance if the zoom level is high and the part outside the view is long. See {@link #computeClippedLine(Stroke)}. 18 22 * @author Michael Zangl 19 23 * @since 10875 … … 91 95 @Override 92 96 public MapViewPath lineTo(MapViewPoint p) { 93 Point2D currentPoint = getCurrentPoint(); 94 if (currentPoint == null) { 95 throw new IllegalStateException("Path not started yet."); 96 } 97 MapViewPoint current = state.getForView(currentPoint.getX(), currentPoint.getY()); 98 MapViewPoint end = p; 99 100 MapViewRectangle clip = state.getViewClipRectangle(); 101 MapViewPoint entry = clip.getLineEntry(current, end); 102 if (entry == null) { 103 // skip this one - outside the view. 104 super.moveTo(end); 105 } else { 106 if (!entry.equals(current)) { 107 super.moveTo(entry); 108 } 109 MapViewPoint exit = clip.getLineEntry(end, current); 110 if (exit == null) { 111 throw new AssertionError(MessageFormat.format( 112 "getLineEntry produces wrong results when doing the reverse lookup. Attempt: {0}->{1}", 113 end.getEastNorth(), current.getEastNorth())); 114 } 115 super.lineTo(exit); 116 if (!exit.equals(end)) { 117 super.moveTo(end); 118 } 119 } 97 super.lineTo(p); 120 98 return this; 121 99 } … … 191 169 } 192 170 } 171 172 /** 173 * Compute a line that is similar to the current path expect for that parts outside the screen are skipped using moveTo commands. 174 * 175 * The line is computed in a way that dashes stay in their place when moving the view. 176 * 177 * The resulting line is not intended to fill areas. 178 * @param stroke The stroke to compute the line for. 179 * @return The new line shape. 180 */ 181 public Shape computeClippedLine(Stroke stroke) { 182 if (stroke instanceof BasicStroke && ((BasicStroke) stroke).getDashArray() != null) { 183 float length = 0; 184 for (float f : ((BasicStroke) stroke).getDashArray()) { 185 length += f; 186 } 187 return computeClippedLine(((BasicStroke) stroke).getDashPhase(), length); 188 } else { 189 return computeClippedLine(0, 0); 190 } 191 } 192 193 private Shape computeClippedLine(double strokeOffset, double strokeLength) { 194 ClampingPathVisitor path = new ClampingPathVisitor(state.getViewClipRectangle(), strokeOffset, strokeLength); 195 if (path.visit(getPathIterator(null))) { 196 return path; 197 } else { 198 // could not clip the path. 199 return this; 200 } 201 } 202 203 private class ClampingPathVisitor extends MapPath2D { 204 private final MapViewRectangle clip; 205 private double strokeOffset; 206 private final double strokeLength; 207 private MapViewPoint lastMoveTo; 208 209 private MapViewPoint cursor; 210 private boolean cursorIsActive = false; 211 212 ClampingPathVisitor(MapViewRectangle clip, double strokeOffset, double strokeLength) { 213 this.clip = clip; 214 this.strokeOffset = strokeOffset; 215 this.strokeLength = strokeLength; 216 } 217 218 /** 219 * Append a path to this one. The path is clipped to the current view. 220 * @param it The iterator 221 * @return true if adding the path was successful. 222 */ 223 public boolean visit(PathIterator it) { 224 double[] coords = new double[8]; 225 while (!it.isDone()) { 226 int type = it.currentSegment(coords); 227 switch (type) { 228 case PathIterator.SEG_CLOSE: 229 visitClose(); 230 break; 231 case PathIterator.SEG_LINETO: 232 visitLineTo(coords[0], coords[1]); 233 break; 234 case PathIterator.SEG_MOVETO: 235 visitMoveTo(coords[0], coords[1]); 236 break; 237 default: 238 // cannot handle this shape - this should be very rare. We let Java2D do the clipping. 239 return false; 240 } 241 it.next(); 242 } 243 return true; 244 } 245 246 void visitClose() { 247 drawLineTo(lastMoveTo); 248 } 249 250 void visitMoveTo(double x, double y) { 251 MapViewPoint point = state.getForView(x, y); 252 lastMoveTo = point; 253 cursor = point; 254 } 255 256 void visitLineTo(double x, double y) { 257 drawLineTo(state.getForView(x, y)); 258 } 259 260 private void drawLineTo(MapViewPoint next) { 261 MapViewPoint entry = clip.getLineEntry(cursor, next); 262 if (entry != null) { 263 MapViewPoint exit = clip.getLineEntry(next, cursor); 264 if (!cursorIsActive || !entry.equals(cursor)) { 265 entry = alignStrokeOffset(entry, cursor); 266 moveTo(entry); 267 } 268 lineTo(exit); 269 cursorIsActive = exit.equals(next); 270 } 271 strokeOffset += cursor.distanceToInView(next); 272 273 cursor = next; 274 } 275 276 private MapViewPoint alignStrokeOffset(MapViewPoint entry, MapViewPoint originalStart) { 277 double distanceSq = entry.distanceToInViewSq(originalStart); 278 if (distanceSq < 0.01 || strokeLength <= 0.001) { 279 // don't move if there is nothing to move. 280 return entry; 281 } 282 283 double distance = Math.sqrt(distanceSq); 284 double offset = ((strokeOffset + distance)) % strokeLength; 285 if (offset < 0.01) { 286 return entry; 287 } 288 289 return entry.interpolate(originalStart, offset / distance); 290 } 291 292 } 193 293 }
Note:
See TracChangeset
for help on using the changeset viewer.
