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

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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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.