Changeset 11147 in josm


Ignore:
Timestamp:
2016-10-19T15:28:45+02:00 (5 months ago)
Author:
michael2402
Message:

Fix 13636: Use line clipping for computing the one way arrows, too.

Location:
trunk/src/org/openstreetmap/josm
Files:
2 edited

Legend:

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

    r11144 r11147  
    14491449        MapViewPath path = new MapViewPath(mapState);
    14501450        MapViewPath orientationArrows = showOrientation ? new MapViewPath(mapState) : null;
    1451         MapViewPath onewayArrows = showOneway ? new MapViewPath(mapState) : null;
    1452         MapViewPath onewayArrowsCasing = showOneway ? new MapViewPath(mapState) : null;
     1451        MapViewPath onewayArrows;
     1452        MapViewPath onewayArrowsCasing;
    14531453        Rectangle bounds = g.getClipBounds();
    14541454        if (bounds != null) {
     
    14571457        }
    14581458
    1459         boolean initialMoveToNeeded = true;
    14601459        List<Node> wayNodes = way.getNodes();
    14611460        if (wayNodes.size() < 2) return;
     
    14821481        double wayLength = 0;
    14831482        Iterator<MapViewPoint> it = new OffsetIterator(wayNodes, offset);
     1483        boolean initialMoveToNeeded = true;
    14841484        while (it.hasNext()) {
    14851485            MapViewPoint p = it.next();
     
    15031503                    final double segmentLength = p1.distanceToInView(p2);
    15041504                    if (segmentLength != 0) {
    1505                         final double nx = (p2.getInViewX() - p1.getInViewX()) / segmentLength;
    1506                         final double ny = (p2.getInViewY() - p1.getInViewY()) / segmentLength;
    1507 
    1508                         final double interval = 60;
    1509                         // distance from p1
    1510                         double dist = interval - (wayLength % interval);
    1511 
    1512                         while (dist < segmentLength) {
    1513                             appenOnewayPath(onewayReversed, p1, nx, ny, dist, 3d, onewayArrowsCasing);
    1514                             appenOnewayPath(onewayReversed, p1, nx, ny, dist, 2d, onewayArrows);
    1515                             dist += interval;
    1516                         }
    15171505                    }
    15181506                    wayLength += segmentLength;
     
    15211509            lastPoint = p;
    15221510        }
     1511        if (showOneway) {
     1512            onewayArrows = new MapViewPath(mapState);
     1513            onewayArrowsCasing = new MapViewPath(mapState);
     1514            double interval = 60;
     1515
     1516            path.visitClippedLine(0, 60, (inLineOffset, start, end, startIsOldEnd) -> {
     1517                double segmentLength = start.distanceToInView(end);
     1518                if (segmentLength > 0.001) {
     1519                    final double nx = (end.getInViewX() - start.getInViewX()) / segmentLength;
     1520                    final double ny = (end.getInViewY() - start.getInViewY()) / segmentLength;
     1521
     1522                    // distance from p1
     1523                    double dist = interval - (inLineOffset % interval);
     1524
     1525                    while (dist < segmentLength) {
     1526                        appenOnewayPath(onewayReversed, start, nx, ny, dist, 3d, onewayArrowsCasing);
     1527                        appenOnewayPath(onewayReversed, start, nx, ny, dist, 2d, onewayArrows);
     1528                        dist += interval;
     1529                    }
     1530                }
     1531            });
     1532        } else {
     1533            onewayArrows = null;
     1534            onewayArrowsCasing = null;
     1535        }
     1536
    15231537        if (way.isHighlighted()) {
    15241538            drawPathHighlight(path, line);
  • trunk/src/org/openstreetmap/josm/gui/draw/MapViewPath.java

    r11145 r11147  
    178178     * @param stroke The stroke to compute the line for.
    179179     * @return The new line shape.
     180     * @since 11147
    180181     */
    181182    public Shape computeClippedLine(Stroke stroke) {
     183        MapPath2D clamped = new MapPath2D();
     184        if (visitClippedLine(stroke, (inLineOffset, start, end, startIsOldEnd) -> {
     185            if (!startIsOldEnd) {
     186                clamped.moveTo(start);
     187            }
     188            clamped.lineTo(end);
     189        })) {
     190            return clamped;
     191        } else {
     192            // could not clip the path.
     193            return this;
     194        }
     195    }
     196
     197    /**
     198     * Visits all straight segments of this path. The segments are clamped to the view.
     199     * If they are clamped, the start points are aligned with the pattern.
     200     * @param stroke The stroke to take the dash information from.
     201     * @param consumer The consumer to call for each segment
     202     * @return false if visiting the path failed because there e.g. were non-straight segments.
     203     * @since 11147
     204     */
     205    public boolean visitClippedLine(Stroke stroke, PathSegmentConsumer consumer) {
    182206        if (stroke instanceof BasicStroke && ((BasicStroke) stroke).getDashArray() != null) {
    183207            float length = 0;
     
    185209                length += f;
    186210            }
    187             return computeClippedLine(((BasicStroke) stroke).getDashPhase(), length);
     211            return visitClippedLine(((BasicStroke) stroke).getDashPhase(), length, consumer);
    188212        } 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 {
     213            return visitClippedLine(0, 0, consumer);
     214        }
     215    }
     216
     217    /**
     218     * Visits all straight segments of this path. The segments are clamped to the view.
     219     * If they are clamped, the start points are aligned with the pattern.
     220     * @param strokeOffset The initial offset of the pattern
     221     * @param strokeLength The dash pattern length. 0 to use no pattern.
     222     * @param consumer The consumer to call for each segment
     223     * @return false if visiting the path failed because there e.g. were non-straight segments.
     224     * @since 11147
     225     */
     226    public boolean visitClippedLine(double strokeOffset, double strokeLength, PathSegmentConsumer consumer) {
     227        return new ClampingPathVisitor(state.getViewClipRectangle(), strokeOffset, strokeLength, consumer)
     228            .visit(this);
     229    }
     230
     231
     232    /**
     233     * This class is used to visit the segments of this path.
     234     * @author Michael Zangl
     235     * @since 11147
     236     */
     237    public interface PathSegmentConsumer {
     238
     239        /**
     240         * Add a line segment between two points
     241         * @param inLineOffset The offset of start in the line
     242         * @param start The start point
     243         * @param end The end point
     244         * @param startIsOldEnd If the start point equals the last end point.
     245         */
     246        void addLineBetween(double inLineOffset, MapViewPoint start, MapViewPoint end, boolean startIsOldEnd);
     247
     248    }
     249
     250    private class ClampingPathVisitor {
    204251        private final MapViewRectangle clip;
    205         private double strokeProgress;
     252        private final PathSegmentConsumer consumer;
     253        protected double strokeProgress;
    206254        private final double strokeLength;
    207255        private MapViewPoint lastMoveTo;
     
    210258        private boolean cursorIsActive = false;
    211259
    212         ClampingPathVisitor(MapViewRectangle clip, double strokeOffset, double strokeLength) {
     260        /**
     261         * Create a new {@link ClampingPathVisitor}
     262         * @param clip View clip rectangle
     263         * @param strokeOffset Initial stroke offset
     264         * @param strokeLength Total length of a stroke sequence
     265         * @param consumer The consumer to notify of the path segments.
     266         */
     267        ClampingPathVisitor(MapViewRectangle clip, double strokeOffset, double strokeLength, PathSegmentConsumer consumer) {
    213268            this.clip = clip;
    214269            this.strokeProgress = Math.min(strokeLength - strokeOffset, 0);
    215270            this.strokeLength = strokeLength;
     271            this.consumer = consumer;
    216272        }
    217273
    218274        /**
    219275         * Append a path to this one. The path is clipped to the current view.
    220          * @param it The iterator
     276         * @param mapViewPath The iterator
    221277         * @return true if adding the path was successful.
    222278         */
    223         public boolean visit(PathIterator it) {
     279        public boolean visit(MapViewPath mapViewPath) {
    224280            double[] coords = new double[8];
     281            PathIterator it = mapViewPath.getPathIterator(null);
    225282            while (!it.isDone()) {
    226283                int type = it.currentSegment(coords);
     
    252309            lastMoveTo = point;
    253310            cursor = point;
     311            cursorIsActive = false;
    254312        }
    255313
     
    264322                if (!cursorIsActive || !entry.equals(cursor)) {
    265323                    entry = alignStrokeOffset(entry, cursor);
    266                     moveTo(entry);
    267324                }
    268                 lineTo(exit);
     325                consumer.addLineBetween(strokeProgress + cursor.distanceToInView(entry), entry, exit, cursorIsActive);
    269326                cursorIsActive = exit.equals(next);
    270327            }
     
    273330            cursor = next;
    274331        }
     332
    275333
    276334        private MapViewPoint alignStrokeOffset(MapViewPoint entry, MapViewPoint originalStart) {
Note: See TracChangeset for help on using the changeset viewer.