Changeset 3565 in josm for trunk/src/org/openstreetmap
- Timestamp:
- 2010-09-25T16:35:08+02:00 (14 years ago)
- Location:
- trunk/src/org/openstreetmap/josm/data/osm/visitor/paint
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/LineClip.java
r2987 r3565 7 7 import static java.awt.geom.Rectangle2D.OUT_BOTTOM; 8 8 import java.awt.Point; 9 import java.awt.Rectangle; 9 10 10 11 /** 11 12 * Computes the part of a line that is visible in a given rectangle. 12 13 * Using int leads to overflow, so we need long int. 13 * http://en.wikipedia.org/wiki/Cohen-Sutherland14 14 */ 15 15 public class LineClip { 16 16 private Point p1, p2; 17 private final Rectangle clipBounds; 18 19 public LineClip(Point p1, Point p2, Rectangle clipBounds) { 20 this.p1 = p1; 21 this.p2 = p2; 22 this.clipBounds = clipBounds; 23 } 17 24 18 25 /** 19 * The outcode of the point.20 * We cannot use Rectangle.outcode since it does not work with long ints.26 * run the clipping algorithm 27 * @return true if the some parts of the line lies within the clip bounds 21 28 */ 22 public int computeOutCode (long x, long y, long xmin, long ymin, long xmax, long ymax) { 23 int code = 0; 24 if (y > ymax) { 25 code |= OUT_TOP; 26 } 27 else if (y < ymin) { 28 code |= OUT_BOTTOM; 29 } 30 if (x > xmax) { 31 code |= OUT_RIGHT; 32 } 33 else if (x < xmin) { 34 code |= OUT_LEFT; 35 } 36 return code; 29 public boolean execute() { 30 return cohenSutherland(p1.x, p1.y, p2.x, p2.y, clipBounds.x , clipBounds.y, clipBounds.x + clipBounds.width, clipBounds.y + clipBounds.height); 37 31 } 38 32 39 public boolean cohenSutherland( long x1, long y1, long x2, long y2, long xmin, long ymin, long xmax, long ymax) 33 /** 34 * @return start point of the clipped line 35 */ 36 public Point getP1() 37 { 38 return p1; 39 } 40 41 /** 42 * @return end point of the clipped line 43 */ 44 public Point getP2() 45 { 46 return p2; 47 } 48 49 /** 50 * see http://en.wikipedia.org/wiki/Cohen-Sutherland 51 */ 52 private boolean cohenSutherland( long x1, long y1, long x2, long y2, long xmin, long ymin, long xmax, long ymax) 40 53 { 41 54 int outcode0, outcode1, outcodeOut; … … 94 107 } 95 108 96 public Point getP1() 97 { 98 return p1; 99 } 100 101 public Point getP2() 102 { 103 return p2; 109 /** 110 * The outcode of the point. 111 * We cannot use Rectangle.outcode since it does not work with long ints. 112 */ 113 private static int computeOutCode (long x, long y, long xmin, long ymin, long xmax, long ymax) { 114 int code = 0; 115 if (y > ymax) { 116 code |= OUT_TOP; 117 } 118 else if (y < ymin) { 119 code |= OUT_BOTTOM; 120 } 121 if (x > xmax) { 122 code |= OUT_RIGHT; 123 } 124 else if (x < xmin) { 125 code |= OUT_LEFT; 126 } 127 return code; 104 128 } 105 129 } -
trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/MapPainter.java
r3398 r3565 54 54 private final Collection<String> regionalNameOrder; 55 55 56 private static final double PHI = Math.toRadians(20); 57 private static final double cosPHI = Math.cos(PHI); 58 private static final double sinPHI = Math.sin(PHI); 59 56 60 public MapPainter(MapPaintSettings settings, Graphics2D g, boolean inactive, NavigatableComponent nc, boolean virtual, double dist, double circum) { 57 61 this.g = g; … … 85 89 86 90 GeneralPath path = new GeneralPath(); 91 GeneralPath arrows = new GeneralPath(); 92 Rectangle bounds = g.getClipBounds(); 93 bounds.grow(100, 100); // avoid arrow heads at the border 87 94 88 95 Point lastPoint = null; 96 boolean initialMoveToNeeded = true; 89 97 Iterator<Node> it = way.getNodes().iterator(); 90 98 while (it.hasNext()) { … … 92 100 Point p = nc.getPoint(n); 93 101 if(lastPoint != null) { 94 drawSegment(path, lastPoint, p, showHeadArrowOnly ? !it.hasNext() : showDirection, reversedDirection); 102 Point p1 = lastPoint; 103 Point p2 = p; 104 105 /** 106 * Do custom clipping to work around openjdk bug. It leads to 107 * drawing artefacts when zooming in a lot. (#4289, #4424) 108 * (Looks like int overflow.) 109 */ 110 LineClip clip = new LineClip(p1, p2, bounds); 111 if (clip.execute()) { 112 if (!p1.equals(clip.getP1())) { 113 p1 = clip.getP1(); 114 path.moveTo(p1.x, p1.y); 115 } else if (initialMoveToNeeded) { 116 initialMoveToNeeded = false; 117 path.moveTo(p1.x, p1.y); 118 } 119 p2 = clip.getP2(); 120 path.lineTo(p2.x, p2.y); 121 122 /* draw arrow */ 123 if (showHeadArrowOnly ? !it.hasNext() : showDirection) { 124 if (reversedDirection) { 125 Point tmp = p1; 126 p1 = p2; 127 p2 = tmp; 128 } 129 final double l = 10. / p1.distance(p2); 130 131 final double sx = l * (p1.x - p2.x); 132 final double sy = l * (p1.y - p2.y); 133 134 arrows.moveTo(p2.x, p2.y); 135 arrows.lineTo (p2.x + (int) Math.round(cosPHI * sx - sinPHI * sy), p2.y + (int) Math.round(sinPHI * sx + cosPHI * sy)); 136 arrows.moveTo (p2.x + (int) Math.round(cosPHI * sx + sinPHI * sy), p2.y + (int) Math.round(- sinPHI * sx + cosPHI * sy)); 137 arrows.lineTo(p2.x, p2.y); 138 } 139 } 95 140 } 96 141 lastPoint = p; 97 142 } 98 displaySegments(path, color, width, dashed, dashedColor);99 } 100 101 private void displaySegments(GeneralPath path, Color color, int width, float dashed[], Color dashedColor) {143 displaySegments(path, arrows, color, width, dashed, dashedColor); 144 } 145 146 private void displaySegments(GeneralPath path, GeneralPath arrows, Color color, int width, float dashed[], Color dashedColor) { 102 147 g.setColor(inactive ? inactiveColor : color); 103 148 if (useStrokes) { … … 109 154 } 110 155 g.draw(path); 156 g.draw(arrows); 111 157 112 158 if(!inactive && useStrokes && dashedColor != null) { … … 122 168 } 123 169 g.draw(path); 170 g.draw(arrows); 124 171 } 125 172 126 173 if(useStrokes) { 127 174 g.setStroke(new BasicStroke()); 128 }129 }130 131 private static final double PHI = Math.toRadians(20);132 private static final double cosPHI = Math.cos(PHI);133 private static final double sinPHI = Math.sin(PHI);134 135 private void drawSegment(GeneralPath path, Point p1, Point p2, boolean showDirection, boolean reversedDirection) {136 boolean drawIt = false;137 if (Main.isOpenjdk) {138 /**139 * Work around openjdk bug. It leads to drawing artefacts when zooming in a lot. (#4289, #4424)140 * (It looks like int overflow when clipping.) We do custom clipping.141 */142 Rectangle bounds = g.getClipBounds();143 bounds.grow(100, 100); // avoid arrow heads at the border144 LineClip clip = new LineClip();145 drawIt = clip.cohenSutherland(p1.x, p1.y, p2.x, p2.y, bounds.x, bounds.y, bounds.x+bounds.width, bounds.y+bounds.height);146 p1 = clip.getP1();147 p2 = clip.getP2();148 } else {149 drawIt = isSegmentVisible(p1, p2);150 }151 if (drawIt) {152 /* draw segment line */153 path.moveTo(p1.x, p1.y);154 path.lineTo(p2.x, p2.y);155 156 /* draw arrow */157 if (showDirection) {158 Point q1 = p1;159 Point q2 = p2;160 if (reversedDirection) {161 q1 = p2;162 q2 = p1;163 path.moveTo(q2.x, q2.y);164 }165 final double l = 10. / q1.distance(q2);166 167 final double sx = l * (q1.x - q2.x);168 final double sy = l * (q1.y - q2.y);169 170 path.lineTo (q2.x + (int) Math.round(cosPHI * sx - sinPHI * sy), q2.y + (int) Math.round(sinPHI * sx + cosPHI * sy));171 path.moveTo (q2.x + (int) Math.round(cosPHI * sx + sinPHI * sy), q2.y + (int) Math.round(- sinPHI * sx + cosPHI * sy));172 path.lineTo(q2.x, q2.y);173 }174 175 } 175 176 } -
trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/SimplePaintVisitor.java
r3398 r3565 481 481 Rectangle bounds = g.getClipBounds(); 482 482 bounds.grow(100, 100); // avoid arrow heads at the border 483 LineClip clip = new LineClip( );484 drawIt = clip. cohenSutherland(p1.x, p1.y, p2.x, p2.y, bounds.x, bounds.y, bounds.x+bounds.width, bounds.y+bounds.height);483 LineClip clip = new LineClip(p1, p2, bounds); 484 drawIt = clip.execute(); 485 485 p1 = clip.getP1(); 486 486 p2 = clip.getP2();
Note:
See TracChangeset
for help on using the changeset viewer.