- Timestamp:
- 2016-10-18T13:04:35+02:00 (8 years ago)
- Location:
- trunk/src/org/openstreetmap/josm
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/actions/mapmode/ImproveWayAccuracyAction.java
r11082 r11144 233 233 // Non-native highlighting is used, because sometimes highlighted 234 234 // segments are covered with others, which is bad. 235 g.setStroke(SELECT_TARGET_WAY_STROKE.get()); 235 BasicStroke stroke = SELECT_TARGET_WAY_STROKE.get(); 236 g.setStroke(stroke); 236 237 237 238 List<Node> nodes = targetWay.getNodes(); 238 239 239 g.draw(new MapViewPath(mv).append(nodes, false) );240 g.draw(new MapViewPath(mv).append(nodes, false).computeClippedLine(stroke)); 240 241 241 242 } else if (state == State.IMPROVING) { … … 301 302 } 302 303 } 303 g.draw(b );304 g.draw(b.computeClippedLine(g.getStroke())); 304 305 305 306 // Highlighting candidateNode … … 313 314 drawIntersectingWayHelperLines(mv, b); 314 315 g.setStroke(MOVE_NODE_INTERSECTING_STROKE.get()); 315 g.draw(b );316 g.draw(b.computeClippedLine(g.getStroke())); 316 317 } 317 318 -
trunk/src/org/openstreetmap/josm/actions/mapmode/ParallelWayAction.java
r10875 r11144 471 471 line.moveTo(referenceSegment.getFirstNode()); 472 472 line.lineTo(referenceSegment.getSecondNode()); 473 g.draw(line );473 g.draw(line.computeClippedLine(g.getStroke())); 474 474 475 475 g.setStroke(HELPER_LINE_STROKE.get()); … … 478 478 line.moveTo(helperLineStart); 479 479 line.lineTo(helperLineEnd); 480 g.draw(line );480 g.draw(line.computeClippedLine(g.getStroke())); 481 481 } 482 482 } -
trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/StyledMapRenderer.java
r11100 r11144 451 451 } 452 452 453 private void displaySegments( Path2Dpath, Path2D orientationArrows, Path2D onewayArrows, Path2D onewayArrowsCasing,453 private void displaySegments(MapViewPath path, Path2D orientationArrows, Path2D onewayArrows, Path2D onewayArrowsCasing, 454 454 Color color, BasicStroke line, BasicStroke dashes, Color dashedColor) { 455 455 g.setColor(isInactiveMode ? inactiveColor : color); … … 457 457 g.setStroke(line); 458 458 } 459 g.draw(path );459 g.draw(path.computeClippedLine(g.getStroke())); 460 460 461 461 if (!isInactiveMode && useStrokes && dashes != null) { 462 462 g.setColor(dashedColor); 463 463 g.setStroke(dashes); 464 g.draw(path );464 g.draw(path.computeClippedLine(dashes)); 465 465 } 466 466 … … 1030 1030 * @param line line style 1031 1031 */ 1032 private void drawPathHighlight( Path2Dpath, BasicStroke line) {1032 private void drawPathHighlight(MapViewPath path, BasicStroke line) { 1033 1033 if (path == null) 1034 1034 return; -
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.