Changeset 10887 in josm for trunk/src/org/openstreetmap/josm


Ignore:
Timestamp:
2016-08-24T00:35:23+02:00 (8 years ago)
Author:
Don-vip
Message:

fix #13385 - rendering artifacts (patch by Gerd Petermann)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/StyledMapRenderer.java

    r10875 r10887  
    110110        /* 'prev0' is a point that has distance 'offset' from 'prev' and the
    111111         * line from 'prev' to 'prev0' is perpendicular to the way segment from
    112          * 'prev' to the next point.
     112         * 'prev' to the current point.
    113113         */
    114114        private double xPrev0;
     
    138138            }
    139139
     140            double xCurrent = current.getInViewX();
     141            double yCurrent = current.getInViewY();
    140142            if (idx == nodes.size() - 1) {
    141143                ++idx;
    142144                if (prev != null) {
    143                     return mapState.getForView(xPrev0 + current.getInViewX() - prev.getInViewX(),
    144                                                yPrev0 + current.getInViewY() - prev.getInViewY());
     145                    return mapState.getForView(xPrev0 + xCurrent - prev.getInViewX(),
     146                                               yPrev0 + yCurrent - prev.getInViewY());
    145147                } else {
    146148                    return current;
     
    149151
    150152            MapViewPoint next = getForIndex(idx + 1);
    151 
    152             double dxNext = next.getInViewX() - current.getInViewX();
    153             double dyNext = next.getInViewY() - current.getInViewY();
     153            double dxNext = next.getInViewX() - xCurrent;
     154            double dyNext = next.getInViewY() - yCurrent;
    154155            double lenNext = Math.sqrt(dxNext*dxNext + dyNext*dyNext);
    155156
    156             if (lenNext < 1e-3) {
     157            if (lenNext < 1e-11) {
    157158                lenNext = 1; // value does not matter, because dy_next and dx_next is 0
    158159            }
    159160
    160             double xCurrent0 = current.getInViewX() + offset * dyNext / lenNext;
    161             double yCurrent0 = current.getInViewY() - offset * dxNext / lenNext;
     161            // calculate the position of the translated current point
     162            double om = offset / lenNext;
     163            double xCurrent0 = xCurrent + om * dyNext;
     164            double yCurrent0 = yCurrent - om * dxNext;
    162165
    163166            if (idx == 0) {
     
    168171                return mapState.getForView(xCurrent0, yCurrent0);
    169172            } else {
    170                 double dxPrev = current.getInViewX() - prev.getInViewX();
    171                 double dyPrev = current.getInViewY() - prev.getInViewY();
    172 
     173                double dxPrev = xCurrent - prev.getInViewX();
     174                double dyPrev = yCurrent - prev.getInViewY();
    173175                // determine intersection of the lines parallel to the two segments
    174176                double det = dxNext*dyPrev - dxPrev*dyNext;
    175 
    176                 if (Utils.equalsEpsilon(det, 0)) {
     177                double m = dxNext*(yCurrent0 - yPrev0) - dyNext*(xCurrent0 - xPrev0);
     178
     179                if (Utils.equalsEpsilon(det, 0) || Math.signum(det) != Math.signum(m)) {
    177180                    ++idx;
    178181                    prev = current;
     
    182185                }
    183186
    184                 double m = dxNext*(yCurrent0 - yPrev0) - dyNext*(xCurrent0 - xPrev0);
    185 
    186                 double cx = xPrev0 + m * dxPrev / det;
    187                 double cy = yPrev0 + m * dyPrev / det;
     187                double f = m / det;
     188                if (f < 0) {
     189                    ++idx;
     190                    prev = current;
     191                    xPrev0 = xCurrent0;
     192                    yPrev0 = yCurrent0;
     193                    return mapState.getForView(xCurrent0, yCurrent0);
     194                }
     195                // the position of the intersection or intermittent point
     196                double cx = xPrev0 + f * dxPrev;
     197                double cy = yPrev0 + f * dyPrev;
     198
     199                if (f > 1) {
     200                    // check if the intersection point is too far away, this will happen for sharp angles
     201                    double dxI = cx - xCurrent;
     202                    double dyI = cy - yCurrent;
     203                    double lenISq = dxI * dxI + dyI * dyI;
     204
     205                    if (lenISq > Math.abs(2 * offset * offset)) {
     206                        // intersection point is too far away, calculate intermittent points for capping
     207                        double dxPrev0 = xCurrent0 - xPrev0;
     208                        double dyPrev0 = yCurrent0 - yPrev0;
     209                        double lenPrev0 = Math.sqrt(dxPrev0 * dxPrev0 + dyPrev0 * dyPrev0);
     210                        f = 1 + Math.abs(offset / lenPrev0);
     211                        double cxCap = xPrev0 + f * dxPrev;
     212                        double cyCap = yPrev0 + f * dyPrev;
     213                        xPrev0 = cxCap;
     214                        yPrev0 = cyCap;
     215                        // calculate a virtual prev point which lies on a line that goes through current and
     216                        // is perpendicular to the line that goes through current and the intersection
     217                        // so that the next capping point is calculated with it.
     218                        double lenI = Math.sqrt(lenISq);
     219                        double xv = xCurrent + dyI / lenI;
     220                        double yv = yCurrent - dxI / lenI;
     221
     222                        prev = mapState.getForView(xv, yv);
     223                        return mapState.getForView(cxCap, cyCap);
     224                    }
     225                }
    188226                ++idx;
    189227                prev = current;
Note: See TracChangeset for help on using the changeset viewer.