Changeset 11696 in josm for trunk/src/org
- Timestamp:
- 2017-03-07T19:51:27+01:00 (8 years ago)
- Location:
- trunk/src/org/openstreetmap/josm/data/osm/visitor/paint
- Files:
-
- 1 added
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/StyledMapRenderer.java
r11674 r11696 34 34 import java.util.List; 35 35 import java.util.Map; 36 import java.util.NoSuchElementException;37 36 import java.util.Optional; 38 37 import java.util.concurrent.ForkJoinPool; … … 97 96 98 97 /** 99 * Iterates over a list of Way Nodes and returns screen coordinates that100 * represent a line that is shifted by a certain offset perpendicular101 * to the way direction.102 *103 * There is no intention, to handle consecutive duplicate Nodes in a104 * perfect way, but it should not throw an exception.105 */106 private class OffsetIterator implements Iterator<MapViewPoint> {107 108 private final List<Node> nodes;109 private final double offset;110 private int idx;111 112 private MapViewPoint prev;113 /* 'prev0' is a point that has distance 'offset' from 'prev' and the114 * line from 'prev' to 'prev0' is perpendicular to the way segment from115 * 'prev' to the current point.116 */117 private double xPrev0;118 private double yPrev0;119 120 OffsetIterator(List<Node> nodes, double offset) {121 this.nodes = nodes;122 this.offset = offset;123 idx = 0;124 }125 126 @Override127 public boolean hasNext() {128 return idx < nodes.size();129 }130 131 @Override132 public MapViewPoint next() {133 if (!hasNext())134 throw new NoSuchElementException();135 136 MapViewPoint current = getForIndex(idx);137 138 if (Math.abs(offset) < 0.1d) {139 idx++;140 return current;141 }142 143 double xCurrent = current.getInViewX();144 double yCurrent = current.getInViewY();145 if (idx == nodes.size() - 1) {146 ++idx;147 if (prev != null) {148 return mapState.getForView(xPrev0 + xCurrent - prev.getInViewX(),149 yPrev0 + yCurrent - prev.getInViewY());150 } else {151 return current;152 }153 }154 155 MapViewPoint next = getForIndex(idx + 1);156 double dxNext = next.getInViewX() - xCurrent;157 double dyNext = next.getInViewY() - yCurrent;158 double lenNext = Math.sqrt(dxNext*dxNext + dyNext*dyNext);159 160 if (lenNext < 1e-11) {161 lenNext = 1; // value does not matter, because dy_next and dx_next is 0162 }163 164 // calculate the position of the translated current point165 double om = offset / lenNext;166 double xCurrent0 = xCurrent + om * dyNext;167 double yCurrent0 = yCurrent - om * dxNext;168 169 if (idx == 0) {170 ++idx;171 prev = current;172 xPrev0 = xCurrent0;173 yPrev0 = yCurrent0;174 return mapState.getForView(xCurrent0, yCurrent0);175 } else {176 double dxPrev = xCurrent - prev.getInViewX();177 double dyPrev = yCurrent - prev.getInViewY();178 // determine intersection of the lines parallel to the two segments179 double det = dxNext*dyPrev - dxPrev*dyNext;180 double m = dxNext*(yCurrent0 - yPrev0) - dyNext*(xCurrent0 - xPrev0);181 182 if (Utils.equalsEpsilon(det, 0) || Math.signum(det) != Math.signum(m)) {183 ++idx;184 prev = current;185 xPrev0 = xCurrent0;186 yPrev0 = yCurrent0;187 return mapState.getForView(xCurrent0, yCurrent0);188 }189 190 double f = m / det;191 if (f < 0) {192 ++idx;193 prev = current;194 xPrev0 = xCurrent0;195 yPrev0 = yCurrent0;196 return mapState.getForView(xCurrent0, yCurrent0);197 }198 // the position of the intersection or intermittent point199 double cx = xPrev0 + f * dxPrev;200 double cy = yPrev0 + f * dyPrev;201 202 if (f > 1) {203 // check if the intersection point is too far away, this will happen for sharp angles204 double dxI = cx - xCurrent;205 double dyI = cy - yCurrent;206 double lenISq = dxI * dxI + dyI * dyI;207 208 if (lenISq > Math.abs(2 * offset * offset)) {209 // intersection point is too far away, calculate intermittent points for capping210 double dxPrev0 = xCurrent0 - xPrev0;211 double dyPrev0 = yCurrent0 - yPrev0;212 double lenPrev0 = Math.sqrt(dxPrev0 * dxPrev0 + dyPrev0 * dyPrev0);213 f = 1 + Math.abs(offset / lenPrev0);214 double cxCap = xPrev0 + f * dxPrev;215 double cyCap = yPrev0 + f * dyPrev;216 xPrev0 = cxCap;217 yPrev0 = cyCap;218 // calculate a virtual prev point which lies on a line that goes through current and219 // is perpendicular to the line that goes through current and the intersection220 // so that the next capping point is calculated with it.221 double lenI = Math.sqrt(lenISq);222 double xv = xCurrent + dyI / lenI;223 double yv = yCurrent - dxI / lenI;224 225 prev = mapState.getForView(xv, yv);226 return mapState.getForView(cxCap, cyCap);227 }228 }229 ++idx;230 prev = current;231 xPrev0 = xCurrent0;232 yPrev0 = yCurrent0;233 return mapState.getForView(cx, cy);234 }235 }236 237 private MapViewPoint getForIndex(int i) {238 return mapState.getPointFor(nodes.get(i));239 }240 241 @Override242 public void remove() {243 throw new UnsupportedOperationException();244 }245 }246 247 /**248 98 * This stores a style and a primitive that should be painted with that style. 249 99 */ … … 840 690 int dy2 = dy1 + imgHeight; 841 691 842 OffsetIterator it = new OffsetIterator(way.getNodes(), offset); 692 OffsetIterator it = new OffsetIterator(mapState, way.getNodes(), offset); 843 693 MapViewPath path = new MapViewPath(mapState); 844 694 if (it.hasNext()) { … … 1509 1359 1510 1360 MapViewPoint lastPoint = null; 1511 Iterator<MapViewPoint> it = new OffsetIterator(wayNodes, offset); 1361 Iterator<MapViewPoint> it = new OffsetIterator(mapState, wayNodes, offset); 1512 1362 boolean initialMoveToNeeded = true; 1513 1363 while (it.hasNext()) {
Note:
See TracChangeset
for help on using the changeset viewer.