Changeset 11696 in josm


Ignore:
Timestamp:
2017-03-07T19:51:27+01:00 (9 months ago)
Author:
michael2402
Message:

Move offset iterator to new file.

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  
    3434import java.util.List;
    3535import java.util.Map;
    36 import java.util.NoSuchElementException;
    3736import java.util.Optional;
    3837import java.util.concurrent.ForkJoinPool;
     
    9796
    9897    /**
    99      * Iterates over a list of Way Nodes and returns screen coordinates that
    100      * represent a line that is shifted by a certain offset perpendicular
    101      * to the way direction.
    102      *
    103      * There is no intention, to handle consecutive duplicate Nodes in a
    104      * 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 the
    114          * line from 'prev' to 'prev0' is perpendicular to the way segment from
    115          * '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         @Override
    127         public boolean hasNext() {
    128             return idx < nodes.size();
    129         }
    130 
    131         @Override
    132         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 0
    162             }
    163 
    164             // calculate the position of the translated current point
    165             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 segments
    179                 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 point
    199                 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 angles
    204                     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 capping
    210                         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 and
    219                         // is perpendicular to the line that goes through current and the intersection
    220                         // 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         @Override
    242         public void remove() {
    243             throw new UnsupportedOperationException();
    244         }
    245     }
    246 
    247     /**
    24898     * This stores a style and a primitive that should be painted with that style.
    24999     */
     
    840690        int dy2 = dy1 + imgHeight;
    841691
    842         OffsetIterator it = new OffsetIterator(way.getNodes(), offset);
     692        OffsetIterator it = new OffsetIterator(mapState, way.getNodes(), offset);
    843693        MapViewPath path = new MapViewPath(mapState);
    844694        if (it.hasNext()) {
     
    15091359
    15101360        MapViewPoint lastPoint = null;
    1511         Iterator<MapViewPoint> it = new OffsetIterator(wayNodes, offset);
     1361        Iterator<MapViewPoint> it = new OffsetIterator(mapState, wayNodes, offset);
    15121362        boolean initialMoveToNeeded = true;
    15131363        while (it.hasNext()) {
Note: See TracChangeset for help on using the changeset viewer.