Changeset 33085 in osm


Ignore:
Timestamp:
2016-11-25T23:29:59+01:00 (8 years ago)
Author:
donvip
Message:

checkstyle

Location:
applications/editors/josm/plugins/turnlanes
Files:
2 added
27 edited

Legend:

Unmodified
Added
Removed
  • applications/editors/josm/plugins/turnlanes/.project

    r32286 r33085  
    1616                        </arguments>
    1717                </buildCommand>
     18                <buildCommand>
     19                        <name>net.sf.eclipsecs.core.CheckstyleBuilder</name>
     20                        <arguments>
     21                        </arguments>
     22                </buildCommand>
    1823        </buildSpec>
    1924        <natures>
    2025                <nature>org.eclipse.jdt.core.javanature</nature>
     26                <nature>net.sf.eclipsecs.core.CheckstyleNature</nature>
    2127        </natures>
    2228</projectDescription>
  • applications/editors/josm/plugins/turnlanes/src/org/openstreetmap/josm/plugins/turnlanes/CollectionUtils.java

    r30737 r33085  
     1// License: GPL. For details, see LICENSE file.
    12package org.openstreetmap.josm.plugins.turnlanes;
    23
     
    910import java.util.Set;
    1011
    11 public class CollectionUtils {
     12public final class CollectionUtils {
     13
     14    private CollectionUtils() {
     15        // Hide default constructor for utilities classes
     16    }
     17
    1218    public static <E> Iterable<E> reverse(final List<E> list) {
    1319        return new Iterable<E>() {
     
    1521            public Iterator<E> iterator() {
    1622                final ListIterator<E> it = list.listIterator(list.size());
    17                
     23
    1824                return new Iterator<E>() {
    1925                    @Override
     
    2127                        return it.hasPrevious();
    2228                    }
    23                    
     29
    2430                    @Override
    2531                    public E next() {
    2632                        return it.previous();
    2733                    }
    28                    
     34
    2935                    @Override
    3036                    public void remove() {
     
    3541        };
    3642    }
    37    
     43
    3844    public static <E> Set<E> toSet(Iterable<? extends E> iterable) {
    3945        final Set<E> set = new HashSet<>();
    40        
     46
    4147        for (E e : iterable) {
    4248            set.add(e);
    4349        }
    44        
     50
    4551        return Collections.unmodifiableSet(set);
    4652    }
    47    
     53
    4854    public static <E> List<E> toList(Iterable<? extends E> iterable) {
    4955        final List<E> list = new ArrayList<>();
    50        
     56
    5157        for (E e : iterable) {
    5258            list.add(e);
    5359        }
    54        
     60
    5561        return Collections.unmodifiableList(list);
    5662    }
  • applications/editors/josm/plugins/turnlanes/src/org/openstreetmap/josm/plugins/turnlanes/TurnLanesPlugin.java

    r26154 r33085  
     1// License: GPL. For details, see LICENSE file.
    12package org.openstreetmap.josm.plugins.turnlanes;
    23
  • applications/editors/josm/plugins/turnlanes/src/org/openstreetmap/josm/plugins/turnlanes/gui/GuiContainer.java

    r30737 r33085  
     1// License: GPL. For details, see LICENSE file.
    12package org.openstreetmap.josm.plugins.turnlanes.gui;
    23
     
    2728    static final Color RED = new Color(234, 66, 108);
    2829    static final Color GREEN = new Color(66, 234, 108);
    29    
     30
    3031    private static final GuiContainer EMPTY = new GuiContainer(ModelContainer.empty());
    31    
     32
    3233    public static GuiContainer empty() {
    3334        return EMPTY;
    3435    }
    35    
     36
    3637    private final ModelContainer mc;
    37    
     38
    3839    private final Point2D translation;
    3940    /**
     
    4344    private final double scale;
    4445    private final double laneWidth;
    45    
     46
    4647    private final Map<Junction, JunctionGui> junctions = new HashMap<>();
    4748    private final Map<Road, RoadGui> roads = new HashMap<>();
    48    
     49
    4950    private final Stroke connectionStroke;
    50    
    51     public GuiContainer(ModelContainer mc) {
     51
     52    GuiContainer(ModelContainer mc) {
    5253        final Point2D origin = avgOrigin(locs(mc.getPrimaryJunctions()));
    53        
     54
    5455        final LatLon originCoor = Main.getProjection().eastNorth2latlon(new EastNorth(origin.getX(), origin.getY()));
    5556        final LatLon relCoor = Main.getProjection().eastNorth2latlon(
    5657                new EastNorth(origin.getX() + 1, origin.getY() + 1));
    57        
     58
    5859        // meters per source unit
    5960        final double mpsu = relCoor.greatCircleDistance(originCoor) / sqrt(2);
    60        
     61
    6162        this.mc = mc;
    6263        this.translation = new Point2D.Double(-origin.getX(), -origin.getY());
     
    6465        this.scale = mpsu / mpp;
    6566        this.laneWidth = 2 / mpp;
    66        
     67
    6768        this.connectionStroke = new BasicStroke((float) (laneWidth / 4), BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
    68        
     69
    6970        for (Junction j : mc.getPrimaryJunctions()) {
    7071            getGui(j);
    7172        }
    7273    }
    73    
     74
    7475    private static Point2D avgOrigin(List<Point2D> locs) {
    7576        if (locs.isEmpty()) {
    7677            return new Point2D.Double(0, 0);
    7778        }
    78        
     79
    7980        double x = 0;
    8081        double y = 0;
    81        
     82
    8283        for (Point2D l : locs) {
    8384            x += l.getX();
    8485            y += l.getY();
    8586        }
    86        
     87
    8788        return new Point2D.Double(x / locs.size(), y / locs.size());
    8889    }
    89    
     90
    9091    public JunctionGui getGui(Junction j) {
    9192        final JunctionGui existing = junctions.get(j);
     
    9394            return existing;
    9495        }
    95        
     96
    9697        return new JunctionGui(this, j);
    9798    }
    98    
     99
    99100    void register(JunctionGui j) {
    100101        if (junctions.put(j.getModel(), j) != null) {
     
    102103        }
    103104    }
    104    
     105
    105106    public RoadGui getGui(Road r) {
    106107        final RoadGui gui = roads.get(r);
    107        
     108
    108109        if (gui == null) {
    109110            final RoadGui newGui = new RoadGui(this, r);
     
    111112            return newGui;
    112113        }
    113        
     114
    114115        return gui;
    115116    }
    116    
     117
    117118    Point2D translateAndScale(Point2D loc) {
    118119        return new Point2D.Double((loc.getX() + translation.getX()) * scale, (loc.getY() + translation.getY()) * scale);
    119120    }
    120    
     121
    121122    /**
    122123     * @return meters per pixel
     
    125126        return mpp;
    126127    }
    127    
     128
    128129    public double getScale() {
    129130        return scale;
    130131    }
    131    
     132
    132133    public double getLaneWidth() {
    133134        return laneWidth;
    134135    }
    135    
     136
    136137    public Stroke getConnectionStroke() {
    137138        return connectionStroke;
    138139    }
    139    
     140
    140141    public LaneGui getGui(Lane lane) {
    141142        final RoadGui roadGui = roads.get(lane.getRoad());
    142        
     143
    143144        for (LaneGui l : roadGui.getLanes()) {
    144145            if (l.getModel().equals(lane)) {
     
    146147            }
    147148        }
    148        
     149
    149150        throw new IllegalArgumentException(tr("No such lane."));
    150151    }
    151    
     152
    152153    public ModelContainer getModel() {
    153154        return mc;
    154155    }
    155    
     156
    156157    public Rectangle2D getBounds() {
    157158        if (isEmpty()) {
    158159            return new Rectangle2D.Double(-1, -1, 2, 2);
    159160        }
    160        
     161
    161162        final List<Junction> primaries = new ArrayList<>(mc.getPrimaryJunctions());
    162163        final List<Double> top = new ArrayList<>();
     
    164165        final List<Double> right = new ArrayList<>();
    165166        final List<Double> bottom = new ArrayList<>();
    166        
     167
    167168        for (Junction j : primaries) {
    168169            final JunctionGui g = getGui(j);
    169170            final Rectangle2D b = g.getBounds();
    170            
     171
    171172            top.add(b.getMinY());
    172173            left.add(b.getMinX());
     
    174175            bottom.add(b.getMaxY());
    175176        }
    176        
     177
    177178        final double t = Collections.min(top);
    178179        final double l = Collections.min(left);
    179180        final double r = Collections.max(right);
    180181        final double b = Collections.max(bottom);
    181        
     182
    182183        return new Rectangle2D.Double(l, t, r - l, b - t);
    183184    }
    184    
     185
    185186    public GuiContainer recalculate() {
    186187        return new GuiContainer(mc.recalculate());
    187188    }
    188    
     189
    189190    public Iterable<RoadGui> getRoads() {
    190191        return roads.values();
    191192    }
    192    
     193
    193194    public Iterable<JunctionGui> getJunctions() {
    194195        return junctions.values();
    195196    }
    196    
     197
    197198    public boolean isEmpty() {
    198199        return mc.isEmpty();
  • applications/editors/josm/plugins/turnlanes/src/org/openstreetmap/josm/plugins/turnlanes/gui/GuiUtil.java

    r30737 r33085  
     1// License: GPL. For details, see LICENSE file.
    12package org.openstreetmap.josm.plugins.turnlanes.gui;
    23
     
    1617import org.openstreetmap.josm.plugins.turnlanes.model.Junction;
    1718
    18 class GuiUtil {
     19final class GuiUtil {
     20
     21    private GuiUtil() {
     22        // Hide default constructor for utilities classes
     23    }
     24
    1925    static double normalize(double a) {
    2026        while (a < 0) {
     
    2632        return a;
    2733    }
    28    
     34
    2935    // control point factor for curves (circle segment of angle a)
    3036    static double cpf(double a, double scale) {
    3137        return 4.0 / 3 * Math.tan(min(abs(a), PI - 0.001) / 4) * scale;
    3238    }
    33    
     39
    3440    static Point2D intersection(Line2D a, Line2D b) {
    3541        final double aa = GuiUtil.angle(a);
    3642        final double ab = GuiUtil.angle(b);
    37        
     43
    3844        // less than 1/2 degree => no intersection
    3945        if (Math.abs(Math.PI - abs(minAngleDiff(aa, ab))) < PI / 360) {
    4046            return null;
    4147        }
    42        
     48
    4349        final double d = (a.getX1() - a.getX2()) * (b.getY1() - b.getY2()) - (a.getY1() - a.getY2())
    4450            * (b.getX1() - b.getX2());
    45        
     51
    4652        final double x = ((b.getX1() - b.getX2()) * (a.getX1() * a.getY2() - a.getY1() * a.getX2()) - (a.getX1() - a
    4753            .getX2()) * (b.getX1() * b.getY2() - b.getY1() * b.getX2()))
     
    5056            .getY2()) * (b.getX1() * b.getY2() - b.getY1() * b.getX2()))
    5157            / d;
    52        
     58
    5359        return new Point2D.Double(x, y);
    5460    }
    55    
     61
    5662    static Point2D closest(Line2D l, Point2D p) {
    5763        final Point2D lv = vector(l.getP1(), l.getP2());
    5864        final double numerator = dot(vector(l.getP1(), p), lv);
    59        
     65
    6066        if (numerator < 0) {
    6167            return l.getP1();
    6268        }
    63        
     69
    6470        final double denominator = dot(lv, lv);
    6571        if (numerator >= denominator) {
    6672            return l.getP2();
    6773        }
    68        
     74
    6975        final double r = numerator / denominator;
    7076        return new Point2D.Double(l.getX1() + r * lv.getX(), l.getY1() + r * lv.getY());
    7177    }
    72    
     78
    7379    private static double dot(Point2D a, Point2D b) {
    7480        return a.getX() * b.getX() + a.getY() * b.getY();
    7581    }
    76    
     82
    7783    private static Point2D vector(Point2D from, Point2D to) {
    7884        return new Point2D.Double(to.getX() - from.getX(), to.getY() - from.getY());
    7985    }
    80    
     86
    8187    public static double angle(Point2D from, Point2D to) {
    8288        final double dx = to.getX() - from.getX();
    8389        final double dy = -(to.getY() - from.getY());
    84        
     90
    8591        return normalize(Math.atan2(dy, dx));
    8692    }
    87    
     93
    8894    public static Point2D relativePoint(Point2D p, double r, double a) {
    89         return new Point2D.Double( //
    90             p.getX() + r * Math.cos(a), //
    91             p.getY() - r * Math.sin(a) //
     95        return new Point2D.Double(
     96            p.getX() + r * Math.cos(a),
     97            p.getY() - r * Math.sin(a)
    9298        );
    9399    }
    94    
     100
    95101    public static Line2D relativeLine(Line2D l, double r, double a) {
    96102        final double dx = r * Math.cos(a);
    97103        final double dy = -r * Math.sin(a);
    98        
    99         return new Line2D.Double( //
    100             l.getX1() + dx, //
    101             l.getY1() + dy, //
    102             l.getX2() + dx, //
    103             l.getY2() + dy //
     104
     105        return new Line2D.Double(
     106            l.getX1() + dx,
     107            l.getY1() + dy,
     108            l.getX2() + dx,
     109            l.getY2() + dy
    104110        );
    105111    }
    106    
     112
    107113    public static double angle(Line2D l) {
    108114        return angle(l.getP1(), l.getP2());
    109115    }
    110    
     116
    111117    public static double minAngleDiff(double a1, double a2) {
    112118        final double d = normalize(a2 - a1);
    113        
     119
    114120        return d > Math.PI ? -(2 * Math.PI - d) : d;
    115121    }
    116    
    117     public static final Point2D middle(Point2D a, Point2D b) {
     122
     123    public static Point2D middle(Point2D a, Point2D b) {
    118124        return relativePoint(a, a.distance(b) / 2, angle(a, b));
    119125    }
    120    
    121     public static final Point2D middle(Line2D l) {
     126
     127    public static Point2D middle(Line2D l) {
    122128        return middle(l.getP1(), l.getP2());
    123129    }
    124    
     130
    125131    public static Line2D line(Point2D p, double a) {
    126132        return new Line2D.Double(p, relativePoint(p, 1, a));
    127133    }
    128    
     134
    129135    public static Point2D loc(Node node) {
    130136        final EastNorth loc = Main.getProjection().latlon2eastNorth(node.getCoor());
    131137        return new Point2D.Double(loc.getX(), -loc.getY());
    132138    }
    133    
     139
    134140    public static List<Point2D> locs(Iterable<Junction> junctions) {
    135141        final List<Point2D> locs = new ArrayList<>();
    136        
     142
    137143        for (Junction j : junctions) {
    138144            locs.add(loc(j.getNode()));
    139145        }
    140        
     146
    141147        return locs;
    142148    }
    143    
     149
    144150    static void area(Path2D area, Path inner, Path outer) {
    145151        area.append(inner.getIterator(), false);
  • applications/editors/josm/plugins/turnlanes/src/org/openstreetmap/josm/plugins/turnlanes/gui/InteractiveElement.java

    r26154 r33085  
     1// License: GPL. For details, see LICENSE file.
    12package org.openstreetmap.josm.plugins.turnlanes.gui;
    23
     
    1314        Type VIA_CONNECTOR = new Type() {};
    1415    }
    15    
     16
    1617    public void paintBackground(Graphics2D g2d, State state) {}
    17    
     18
    1819    abstract void paint(Graphics2D g2d, State state);
    19    
     20
    2021    abstract boolean contains(Point2D p, State state);
    21    
     22
    2223    abstract Type getType();
    23    
     24
    2425    State activate(State old) {
    2526        return old;
    2627    }
    27    
     28
    2829    boolean beginDrag(double x, double y) {
    2930        return false;
    3031    }
    31    
     32
    3233    State drag(double x, double y, InteractiveElement target, State old) {
    3334        return old;
    3435    }
    35    
     36
    3637    State drop(double x, double y, InteractiveElement target, State old) {
    3738        return old;
    3839    }
    39    
     40
    4041    abstract int getZIndex();
    41    
     42
    4243    State click(State old) {
    4344        return old;
  • applications/editors/josm/plugins/turnlanes/src/org/openstreetmap/josm/plugins/turnlanes/gui/JunctionGui.java

    r30737 r33085  
     1// License: GPL. For details, see LICENSE file.
    12package org.openstreetmap.josm.plugins.turnlanes.gui;
    23
     
    3940    private final class TurnConnection extends InteractiveElement {
    4041        private final Turn turn;
    41        
     42
    4243        private Point2D dragBegin;
    4344        private double dragOffsetX = 0;
    4445        private double dragOffsetY = 0;
    45        
    46         public TurnConnection(Turn turn) {
     46
     47        TurnConnection(Turn turn) {
    4748            this.turn = turn;
    4849        }
    49        
     50
    5051        @Override
    5152        void paint(Graphics2D g2d, State state) {
     
    5859            }
    5960        }
    60        
     61
    6162        private Path2D getPath() {
    6263            final Path2D path = new Path2D.Double();
    63            
     64
    6465            final LaneGui laneGui = getContainer().getGui(turn.getFrom());
    6566            final RoadGui roadGui = getContainer().getGui(turn.getTo().getRoad());
    66            
     67
    6768            path.moveTo(laneGui.outgoing.getCenter().getX(), laneGui.outgoing.getCenter().getY());
    68            
     69
    6970            Junction j = laneGui.getModel().getOutgoingJunction();
    7071            for (Road v : turn.getVia()) {
     
    7778                    j = v.getFromEnd().getJunction();
    7879                }
    79                
     80
    8081                path.append(it, true);
    8182            }
    82            
     83
    8384            path.lineTo(roadGui.getConnector(turn.getTo()).getCenter().getX(), roadGui.getConnector(turn.getTo()).getCenter()
    8485                .getY());
    85            
     86
    8687            return path;
    8788        }
    88        
     89
    8990        private boolean isVisible(State state) {
    9091            if (state instanceof State.AllTurns) {
     
    9596                return turn.getTo().equals(((State.IncomingActive) state).getRoadEnd());
    9697            }
    97            
     98
    9899            return false;
    99100        }
    100        
     101
    101102        @Override
    102103        boolean contains(Point2D p, State state) {
     
    104105                return false;
    105106            }
    106            
     107
    107108            final PathIterator it = new FlatteningPathIterator(getPath().getPathIterator(null), 0.05 / getContainer()
    108109                .getMpp());
     
    113114                if (it.currentSegment(coords) == PathIterator.SEG_LINETO) {
    114115                    final Point2D closest = closest(new Line2D.Double(lastX, lastY, coords[0], coords[1]), p);
    115                    
     116
    116117                    if (p.distance(closest) <= strokeWidth() / 2) {
    117118                        return true;
    118119                    }
    119120                }
    120                
     121
    121122                lastX = coords[0];
    122123                lastY = coords[1];
    123124                it.next();
    124125            }
    125            
     126
    126127            return false;
    127128        }
    128        
     129
    129130        private double strokeWidth() {
    130131            final BasicStroke stroke = (BasicStroke) getContainer().getConnectionStroke();
    131132            return stroke.getLineWidth();
    132133        }
    133        
     134
    134135        @Override
    135136        Type getType() {
    136137            return Type.TURN_CONNECTION;
    137138        }
    138        
     139
    139140        @Override
    140141        int getZIndex() {
    141142            return 0;
    142143        }
    143        
     144
    144145        @Override
    145146        boolean beginDrag(double x, double y) {
     
    149150            return true;
    150151        }
    151        
     152
    152153        @Override
    153154        State drag(double x, double y, InteractiveElement target, State old) {
     
    156157            return old;
    157158        }
    158        
     159
    159160        @Override
    160161        State drop(double x, double y, InteractiveElement target, State old) {
    161162            drag(x, y, target, old);
    162            
     163
    163164            if (isRemoveDragOffset()) {
    164165                turn.remove();
    165166            }
    166            
     167
    167168            dragBegin = null;
    168169            dragOffsetX = 0;
     
    170171            return new State.Dirty(old);
    171172        }
    172        
     173
    173174        private boolean isRemoveDragOffset() {
    174175            final double r = getContainer().getGui(turn.getFrom().getRoad()).connectorRadius;
     
    177178        }
    178179    }
    179    
     180
    180181    private final class Corner {
    181182        final double x1;
    182183        final double y1;
    183        
     184
    184185        final double cx1;
    185186        final double cy1;
    186        
     187
    187188        final double cx2;
    188189        final double cy2;
    189        
     190
    190191        final double x2;
    191192        final double y2;
    192        
    193         public Corner(Point2D c1, Point2D cp1, Point2D cp2, Point2D c2) {
     193
     194        Corner(Point2D c1, Point2D cp1, Point2D cp2, Point2D c2) {
    194195            this.x1 = c1.getX();
    195196            this.y1 = c1.getY();
     
    201202            this.y2 = c2.getY();
    202203        }
    203        
     204
    204205        @Override
    205206        public String toString() {
     
    208209        }
    209210    }
    210    
     211
    211212    private final class Linkage implements Comparable<Linkage> {
    212213        final RoadGui roadGui;
    213214        final Road.End roadEnd;
    214215        final double angle;
    215        
     216
    216217        double lTrim;
    217218        double rTrim;
    218        
    219         public Linkage(Road.End roadEnd) {
     219
     220        Linkage(Road.End roadEnd) {
    220221            this.roadGui = getContainer().getGui(roadEnd.getRoad());
    221222            this.roadEnd = roadEnd;
    222223            this.angle = normalize(roadGui.getAngle(roadEnd) + PI);
    223            
     224
    224225            roads.put(angle, this);
    225226        }
    226        
     227
    227228        @Override
    228229        public int compareTo(Linkage o) {
    229230            return Double.compare(angle, o.angle);
    230231        }
    231        
     232
    232233        public void trimLeft(Linkage right) {
    233234            right.trimRight(this);
    234            
     235
    235236            final Line2D leftCurb = roadGui.getLeftCurb(roadEnd);
    236237            final Line2D rightCurb = right.roadGui.getRightCurb(right.roadEnd);
    237            
     238
    238239            final double leftAngle = angle(leftCurb);
    239240            final double rightAngle = angle(rightCurb);
    240            
     241
    241242            final Point2D isect;
    242243            if (abs(PI - normalize(rightAngle - leftAngle)) > PI / 12) {
     
    245246                isect = GuiUtil.relativePoint(leftCurb.getP1(), roadGui.getWidth(roadEnd) / 2, angle);
    246247            }
    247            
     248
    248249            if (Math.abs(leftAngle - angle(leftCurb.getP1(), isect)) < 0.1) {
    249250                lTrim = leftCurb.getP1().distance(isect);
    250251            }
    251252        }
    252        
     253
    253254        private void trimRight(Linkage left) {
    254255            final Line2D rightCurb = roadGui.getRightCurb(roadEnd);
    255256            final Line2D leftCurb = left.roadGui.getLeftCurb(left.roadEnd);
    256            
     257
    257258            final double rightAngle = angle(rightCurb);
    258259            final double leftAngle = angle(leftCurb);
    259            
     260
    260261            final Point2D isect;
    261262            if (abs(PI - normalize(rightAngle - leftAngle)) > PI / 12) {
     
    264265                isect = GuiUtil.relativePoint(rightCurb.getP1(), roadGui.getWidth(roadEnd) / 2, angle);
    265266            }
    266            
     267
    267268            if (Math.abs(rightAngle - angle(rightCurb.getP1(), isect)) < 0.1) {
    268269                rTrim = rightCurb.getP1().distance(isect);
    269270            }
    270271        }
    271        
     272
    272273        public void trimAdjust() {
    273274            final double MAX_TAN = tan(PI / 2 - MAX_ANGLE);
    274            
     275
    275276            final double sin = roadGui.getWidth(roadEnd);
    276277            final double cos = abs(lTrim - rTrim);
    277278            final double tan = sin / cos;
    278            
     279
    279280            if (tan < MAX_TAN) {
    280281                lTrim = max(lTrim, rTrim - sin / MAX_TAN);
    281282                rTrim = max(rTrim, lTrim - sin / MAX_TAN);
    282283            }
    283            
     284
    284285            lTrim += container.getLaneWidth() / 2;
    285286            rTrim += container.getLaneWidth() / 2;
    286287        }
    287288    }
    288    
     289
    289290    // max angle between corners
    290291    private static final double MAX_ANGLE = Math.toRadians(30);
    291    
     292
    292293    private final GuiContainer container;
    293294    private final Junction junction;
    294    
     295
    295296    final double x;
    296297    final double y;
    297    
     298
    298299    private final NavigableMap<Double, Linkage> roads = new TreeMap<>();
    299    
     300
    300301    private final Path2D area = new Path2D.Double();
    301    
    302     public JunctionGui(GuiContainer container, Junction j) {
     302
     303    JunctionGui(GuiContainer container, Junction j) {
    303304        this.container = container;
    304305        this.junction = j;
    305        
     306
    306307        container.register(this);
    307        
     308
    308309        final Point2D loc = container.translateAndScale(loc(j.getNode()));
    309310        this.x = loc.getX();
    310311        this.y = loc.getY();
    311        
     312
    312313        final Set<Road> done = new HashSet<>();
    313314        for (Road r : j.getRoads()) {
    314315            if (!done.contains(r)) {
    315316                done.add(r);
    316                
     317
    317318                if (r.getFromEnd().getJunction().equals(j)) {
    318319                    new Linkage(r.getFromEnd());
     
    323324            }
    324325        }
    325        
     326
    326327        recalculate();
    327328    }
    328    
     329
    329330    void recalculate() {
    330331        for (Linkage l : roads.values()) {
     
    332333            l.rTrim = 0;
    333334        }
    334        
     335
    335336        area.reset();
    336337        if (roads.size() < 2) {
    337338            return;
    338339        }
    339        
     340
    340341        Linkage last = roads.lastEntry().getValue();
    341342        for (Linkage l : roads.values()) {
     
    346347            l.trimAdjust();
    347348        }
    348        
     349
    349350        boolean first = true;
    350351        for (Corner c : corners()) {
     
    355356                area.lineTo(c.x1, c.y1);
    356357            }
    357            
     358
    358359            area.curveTo(c.cx1, c.cy1, c.cx2, c.cy2, c.x2, c.y2);
    359360        }
    360        
     361
    361362        area.closePath();
    362363    }
    363    
     364
    364365    private Iterable<Corner> corners() {
    365366        final List<Corner> result = new ArrayList<>(roads.size());
    366        
     367
    367368        Linkage last = roads.lastEntry().getValue();
    368369        for (Linkage l : roads.values()) {
     
    370371            last = l;
    371372        }
    372        
     373
    373374        return result;
    374375    }
    375    
     376
    376377    private Corner corner(Linkage right, Linkage left) {
    377378        final Line2D rightCurb = right.roadGui.getRightCurb(right.roadEnd);
    378379        final Line2D leftCurb = left.roadGui.getLeftCurb(left.roadEnd);
    379        
     380
    380381        final double rightAngle = angle(rightCurb);
    381382        final double leftAngle = angle(leftCurb);
    382        
     383
    383384        final double delta = normalize(leftAngle - rightAngle);
    384        
     385
    385386        final boolean wide = delta > PI;
    386387        final double a = wide ? max(0, delta - (PI + 2 * MAX_ANGLE)) : delta;
    387        
     388
    388389        final double cpf1 = cpf(a, container.getLaneWidth() / 2 + (wide ? right.roadGui.getWidth(right.roadEnd) : 0));
    389390        final double cpf2 = cpf(a, container.getLaneWidth() / 2 + (wide ? left.roadGui.getWidth(left.roadEnd) : 0));
    390        
     391
    391392        final Point2D c1 = relativePoint(rightCurb.getP1(), cpf1, right.angle + PI);
    392393        final Point2D c2 = relativePoint(leftCurb.getP1(), cpf2, left.angle + PI);
    393        
     394
    394395        return new Corner(rightCurb.getP1(), c1, c2, leftCurb.getP1());
    395396    }
    396    
     397
    397398    public Set<RoadGui> getRoads() {
    398399        final Set<RoadGui> result = new HashSet<>();
    399        
     400
    400401        for (Linkage l : roads.values()) {
    401402            result.add(l.roadGui);
    402403        }
    403        
     404
    404405        return Collections.unmodifiableSet(result);
    405406    }
    406    
     407
    407408    double getLeftTrim(Road.End end) {
    408409        return getLinkage(end).lTrim;
    409410    }
    410    
     411
    411412    private Linkage getLinkage(Road.End end) {
    412413        final double a = normalize(getContainer().getGui(end.getRoad()).getAngle(end) + PI);
     
    414415        return e != null ? e.getValue() : null;
    415416    }
    416    
     417
    417418    double getRightTrim(Road.End end) {
    418419        return getLinkage(end).rTrim;
    419420    }
    420    
     421
    421422    Point2D getPoint() {
    422423        return new Point2D.Double(x, y);
    423424    }
    424    
     425
    425426    public GuiContainer getContainer() {
    426427        return container;
    427428    }
    428    
     429
    429430    public Junction getModel() {
    430431        return junction;
    431432    }
    432    
     433
    433434    public List<InteractiveElement> paint(Graphics2D g2d) {
    434435        g2d.setColor(new Color(96, 96, 96));
    435436        g2d.fill(area);
    436        
     437
    437438        final List<InteractiveElement> result = new ArrayList<>();
    438        
     439
    439440        if (getModel().isPrimary()) {
    440441            for (Road.End r : new HashSet<>(getModel().getRoadEnds())) {
     
    444445            }
    445446        }
    446        
     447
    447448        return result;
    448449    }
    449    
     450
    450451    public Rectangle2D getBounds() {
    451452        return area.getBounds2D();
  • applications/editors/josm/plugins/turnlanes/src/org/openstreetmap/josm/plugins/turnlanes/gui/JunctionPane.java

    r30737 r33085  
     1// License: GPL. For details, see LICENSE file.
    12package org.openstreetmap.josm.plugins.turnlanes.gui;
    23
     
    3940        private int originY;
    4041        private int button;
    41        
     42
     43        @Override
    4244        public void mousePressed(MouseEvent e) {
    4345            JunctionPane.this.requestFocus();
    44            
     46
    4547            button = e.getButton();
    46            
     48
    4749            if (button == MouseEvent.BUTTON1) {
    4850                final Point2D mouse = translateMouseCoords(e);
     
    5557                }
    5658            }
    57            
     59
    5860            originX = e.getX();
    5961            originY = e.getY();
    6062        }
    61        
     63
    6264        @Override
    6365        public void mouseReleased(MouseEvent e) {
     
    6668                setState(dragging.drop(mouse.getX(), mouse.getY(), dropTarget(mouse), state));
    6769            }
    68            
     70
    6971            dragging = null;
    7072            repaint();
    7173        }
    72        
     74
    7375        private InteractiveElement dropTarget(Point2D mouse) {
    7476            for (InteractiveElement ie : interactives()) {
     
    7779                }
    7880            }
    79            
     81
    8082            return null;
    8183        }
    82        
     84
    8385        @Override
    8486        public void mouseClicked(MouseEvent e) {
     
    9395            }
    9496        }
    95        
     97
     98        @Override
    9699        public void mouseDragged(MouseEvent e) {
    97100            if (button == MouseEvent.BUTTON1) {
    98101                final Point2D mouse = translateMouseCoords(e);
    99                
     102
    100103                if (dragging == null) {
    101104                    final Point2D origin = translateCoords(originX, originY);
     
    105108                                dragging = ie;
    106109                            }
    107                            
     110
    108111                            break;
    109112                        }
    110113                    }
    111114                }
    112                
     115
    113116                if (dragging != null) {
    114117                    setState(dragging.drag(mouse.getX(), mouse.getY(), dropTarget(mouse), state));
     
    116119            } else if (button == MouseEvent.BUTTON3) {
    117120                translate(e.getX() - originX, e.getY() - originY);
    118                
     121
    119122                originX = e.getX();
    120123                originY = e.getY();
    121124            }
    122125        }
    123        
     126
    124127        @Override
    125128        public void mouseWheelMoved(MouseWheelEvent e) {
    126129            scale(e.getX(), e.getY(), Math.pow(0.8, e.getWheelRotation()));
    127130        }
    128        
     131
    129132        private Point2D translateMouseCoords(MouseEvent e) {
    130133            return translateCoords(e.getX(), e.getY());
    131134        }
    132        
     135
    133136        private Point2D translateCoords(int x, int y) {
    134137            final double c = Math.cos(-rotation);
    135138            final double s = Math.sin(-rotation);
    136            
     139
    137140            final double x2 = -translationX + x / scale;
    138141            final double y2 = -translationY + y / scale;
    139            
     142
    140143            return new Point2D.Double(x2 * c - y2 * s, x2 * s + y2 * c);
    141144        }
    142145    }
    143    
     146
    144147    private static final long serialVersionUID = 6917061040674799271L;
    145    
     148
    146149    private static final Color TRANSPARENT = new Color(0, 0, 0, 0);
    147    
     150
    148151    private final MouseInputProcessor mip = new MouseInputProcessor();
    149    
     152
    150153    private GuiContainer container;
    151    
     154
    152155    private final JLabel error = new JLabel("");
    153    
     156
    154157    private int width = 0;
    155158    private int height = 0;
     
    161164    private BufferedImage passive;
    162165    private BufferedImage interactive;
    163    
     166
    164167    private final NavigableMap<Integer, List<InteractiveElement>> interactives = new TreeMap<>();
    165168    private State state;
    166169    private InteractiveElement dragging;
    167    
    168     public JunctionPane(GuiContainer container) {
     170
     171    JunctionPane(GuiContainer container) {
    169172        setJunction(container);
    170        
     173
    171174        setLayout(new GridBagLayout());
    172175        error.setOpaque(false);
    173176        add(error, new GridBagConstraints(0, 0, 1, 1, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH,
    174177                new Insets(8, 8, 8, 8), 0, 0));
    175        
     178
    176179        setFocusable(true);
    177        
     180
    178181        getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_F5, 0), "refresh");
    179182        getActionMap().put("refresh", new AbstractAction() {
    180183            private static final long serialVersionUID = 1L;
    181            
     184
    182185            @Override
    183186            public void actionPerformed(ActionEvent e) {
     
    185188            }
    186189        });
    187        
     190
    188191        getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_PLUS, 0), "zoomIn");
    189192        getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ADD, 0), "zoomIn");
    190193        getActionMap().put("zoomIn", new AbstractAction() {
    191194            private static final long serialVersionUID = 1L;
    192            
     195
    193196            @Override
    194197            public void actionPerformed(ActionEvent e) {
     
    196199            }
    197200        });
    198        
     201
    199202        getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_MINUS, 0), "zoomOut");
    200203        getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_SUBTRACT, 0), "zoomOut");
    201204        getActionMap().put("zoomOut", new AbstractAction() {
    202205            private static final long serialVersionUID = 1L;
    203            
     206
    204207            @Override
    205208            public void actionPerformed(ActionEvent e) {
     
    207210            }
    208211        });
    209        
     212
    210213        getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0), "center");
    211214        getActionMap().put("center", new AbstractAction() {
    212215            private static final long serialVersionUID = 1L;
    213            
     216
    214217            @Override
    215218            public void actionPerformed(ActionEvent e) {
     
    217220            }
    218221        });
    219        
     222
    220223        getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_A, InputEvent.CTRL_DOWN_MASK), "toggleAllTurns");
    221224        getActionMap().put("toggleAllTurns", new AbstractAction() {
    222225            private static final long serialVersionUID = 1L;
    223            
     226
    224227            @Override
    225228            public void actionPerformed(ActionEvent e) {
     
    227230            }
    228231        });
    229        
     232
    230233        getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_L, InputEvent.CTRL_DOWN_MASK), "rotateLeft");
    231234        getActionMap().put("rotateLeft", new AbstractAction() {
    232235            private static final long serialVersionUID = 1L;
    233            
     236
    234237            @Override
    235238            public void actionPerformed(ActionEvent e) {
     
    238241            }
    239242        });
    240        
     243
    241244        getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_R, InputEvent.CTRL_DOWN_MASK), "rotateRight");
    242245        getActionMap().put("rotateRight", new AbstractAction() {
    243246            private static final long serialVersionUID = 1L;
    244            
     247
    245248            @Override
    246249            public void actionPerformed(ActionEvent e) {
     
    249252            }
    250253        });
    251        
     254
    252255        getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), "delete");
    253256        getActionMap().put("delete", new AbstractAction() {
    254257            private static final long serialVersionUID = 1L;
    255            
     258
    256259            @Override
    257260            public void actionPerformed(ActionEvent e) {
     
    260263        });
    261264    }
    262    
     265
    263266    public void setJunction(GuiContainer container) {
    264267        removeMouseListener(mip);
     
    267270        this.interactives.clear();
    268271        this.dragging = null;
    269        
     272
    270273        this.container = container;
    271274        center();
    272275        setState(new State.Invalid(new State.Default()));
    273        
     276
    274277        addMouseListener(mip);
    275278        addMouseMotionListener(mip);
    276279        addMouseWheelListener(mip);
    277280    }
    278    
     281
    279282    private void center() {
    280283        final Rectangle2D bounds = container.getBounds();
    281        
     284
    282285        rotation = 0;
    283        
     286
    284287        scale = Math.min(getHeight() / 2 / bounds.getHeight(), getWidth() / 2 / bounds.getWidth());
    285        
     288
    286289        translationX = -bounds.getCenterX();
    287290        translationY = -bounds.getCenterY();
    288        
     291
    289292        translate(getWidth() / 2d, getHeight() / 2d);
    290293    }
    291    
     294
    292295    private void toggleAllTurns() {
    293296        if (state instanceof State.AllTurns) {
     
    297300        }
    298301    }
    299    
     302
    300303    private void setState(State state) {
    301304        error.setText("");
    302        
     305
    303306        if (state instanceof State.AllTurns) {
    304307            dirty = true;
     
    307310            dirty = true;
    308311            setState(((State.Invalid) state).unwrap());
    309            
     312
    310313            try {
    311314                final GuiContainer old = container;
    312                
     315
    313316                container = container.recalculate();
    314                
     317
    315318                if (old.isEmpty() != container.isEmpty()) {
    316319                    center();
     
    327330            this.state = state.carryOver(container);
    328331        }
    329        
     332
    330333        repaint();
    331334    }
    332    
     335
    333336    private void displayError(UnexpectedDataException e) {
    334337        if (e.getKind() == UnexpectedDataException.Kind.MISSING_TAG
    335338                && UnexpectedDataException.Kind.MISSING_TAG.format("lanes").equals(e.getMessage())) {
    336            
     339
    337340            error.setText(tr("<html>The number of lanes is not specified for one or more roads;"
    338341                    + " please add missing lanes tags.</html>"));
     
    341344        }
    342345    }
    343    
     346
    344347    private void displayError(RuntimeException e) {
    345348        error.setText(tr("<html>An error occurred while constructing the model."
     
    347350                + "<br><br>Error: {0}</html>", e.getMessage()));
    348351    }
    349    
     352
    350353    void scale(int x, int y, double scale) {
    351354        this.scale *= scale;
    352        
     355
    353356        final double w = getWidth();
    354357        final double h = getHeight();
    355        
     358
    356359        translationX -= (w * (scale - 1)) / (2 * this.scale);
    357360        translationY -= (h * (scale - 1)) / (2 * this.scale);
    358        
     361
    359362        dirty = true;
    360363        repaint();
    361364    }
    362    
     365
    363366    void scale(double scale) {
    364367        scale(getWidth() / 2, getHeight() / 2, scale);
    365368    }
    366    
     369
    367370    void translate(double x, double y) {
    368371        translationX += x / scale;
    369372        translationY += y / scale;
    370        
     373
    371374        dirty = true;
    372375        repaint();
    373376    }
    374    
     377
    375378    @Override
    376379    protected void paintComponent(Graphics g) {
     
    379382            width = getWidth();
    380383            height = getHeight();
    381            
     384
    382385            // translate already set dirty flag
    383386            passive = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
    384387            interactive = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
    385388        }
    386        
     389
    387390        if (dirty) {
    388391            paintPassive((Graphics2D) passive.getGraphics());
     
    390393        }
    391394        paintInteractive((Graphics2D) interactive.getGraphics());
    392        
     395
    393396        final Graphics2D g2d = (Graphics2D) g;
    394        
     397
    395398        g2d.drawImage(passive, 0, 0, getWidth(), getHeight(), null);
    396399        g2d.drawImage(interactive, 0, 0, getWidth(), getHeight(), null);
    397        
     400
    398401        paintChildren(g);
    399402    }
    400    
     403
    401404    private void paintInteractive(Graphics2D g2d) {
    402405        g2d.setBackground(TRANSPARENT);
     
    405408        g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
    406409        g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
    407        
     410
    408411        g2d.scale(scale, scale);
    409412        g2d.translate(translationX, translationY);
    410413        g2d.rotate(rotation);
    411        
     414
    412415        g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC, 0.7f));
    413        
     416
    414417        for (Map.Entry<Integer, List<InteractiveElement>> e : interactives.entrySet()) {
    415418            for (InteractiveElement ie : e.getValue()) {
     
    421424        }
    422425    }
    423    
     426
    424427    private List<InteractiveElement> interactives() {
    425428        final List<InteractiveElement> result = new ArrayList<>();
    426        
     429
    427430        for (List<InteractiveElement> ies : interactives.descendingMap().values()) {
    428431            result.addAll(ies);
    429432        }
    430        
     433
    431434        return result;
    432435    }
    433    
     436
    434437    private void paintPassive(Graphics2D g2d) {
    435438        interactives.clear();
    436        
     439
    437440        g2d.setBackground(new Color(100, 160, 240));
    438441        g2d.clearRect(0, 0, getWidth(), getHeight());
    439        
     442
    440443        g2d.scale(scale, scale);
    441444        g2d.translate(translationX, translationY);
    442445        g2d.rotate(rotation);
    443        
     446
    444447        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    445        
     448
    446449        g2d.setColor(Color.GRAY);
    447450        for (RoadGui r : container.getRoads()) {
    448451            addAllInteractives(r.paint(g2d));
    449452        }
    450        
     453
    451454        for (JunctionGui j : container.getJunctions()) {
    452455            addAllInteractives(j.paint(g2d));
     
    454457        }
    455458    }
    456    
     459
    457460    private void addAllInteractives(List<InteractiveElement> ies) {
    458461        for (InteractiveElement ie : ies) {
    459462            final List<InteractiveElement> existing = interactives.get(ie.getZIndex());
    460            
     463
    461464            final List<InteractiveElement> list;
    462465            if (existing == null) {
     
    466469                list = existing;
    467470            }
    468            
     471
    469472            list.add(ie);
    470473        }
    471474    }
    472    
     475
    473476    static void dot(Graphics2D g2d, Point2D p, double r, Color c) {
    474477        final Color old = g2d.getColor();
    475        
     478
    476479        g2d.setColor(c);
    477480        g2d.fill(new Ellipse2D.Double(p.getX() - r, p.getY() - r, 2 * r, 2 * r));
    478        
     481
    479482        g2d.setColor(old);
    480483    }
    481    
     484
    482485    static void dot(Graphics2D g2d, Point2D p, double r) {
    483486        dot(g2d, p, r, Color.RED);
    484487    }
    485    
     488
    486489    void refresh() {
    487490        setState(new State.Invalid(state));
  • applications/editors/josm/plugins/turnlanes/src/org/openstreetmap/josm/plugins/turnlanes/gui/LaneGui.java

    r30737 r33085  
     1// License: GPL. For details, see LICENSE file.
    12package org.openstreetmap.josm.plugins.turnlanes.gui;
    23
     
    2930        private final Point2D center = new Point2D.Double();
    3031        private final Ellipse2D circle = new Ellipse2D.Double();
    31        
     32
    3233        private Point2D dragDelta;
    33        
     34
    3435        private LengthSlider() {}
    35        
     36
    3637        @Override
    3738        public void paint(Graphics2D g2d, State state) {
     
    3940                g2d.setColor(Color.BLUE);
    4041                g2d.fill(circle);
    41                
     42
    4243                final String len = METER_FORMAT.format(getLength() * getRoad().getContainer().getMpp());
    4344                final Rectangle2D bounds = circle.getBounds2D();
     
    4647            }
    4748        }
    48        
     49
    4950        private boolean isVisible(State state) {
    5051            if (state instanceof State.OutgoingActive) {
    5152                return LaneGui.this.equals(((State.OutgoingActive) state).getLane());
    5253            }
    53            
     54
    5455            return false;
    5556        }
    56        
     57
    5758        @Override
    5859        public boolean contains(Point2D p, State state) {
    5960            return isVisible(state) && circle.contains(p);
    6061        }
    61        
     62
    6263        @Override
    6364        public Type getType() {
    6465            return Type.INCOMING_CONNECTOR;
    6566        }
    66        
     67
    6768        @Override
    6869        boolean beginDrag(double x, double y) {
     
    7071            return true;
    7172        }
    72        
     73
    7374        @Override
    7475        State drag(double x, double y, InteractiveElement target, State old) {
     
    7677            return new State.Dirty(old);
    7778        }
    78        
     79
    7980        @Override
    8081        State drop(double x, double y, InteractiveElement target, State old) {
     
    8283            return old;
    8384        }
    84        
     85
    8586        void move(double x, double y, boolean updateModel) {
    8687            final double r = getRoad().connectorRadius;
    87            
     88
    8889            final double offset = getRoad().getOffset(x, y);
    8990            final double newLength = getModel().getOutgoingRoadEnd().isFromEnd() ? offset : getRoad().getLength()
    9091                    - offset;
    9192            final double adjustedLength = min(max(newLength, 0.1), getRoad().getLength());
    92            
     93
    9394            length = adjustedLength;
    9495            if (updateModel) {
    9596                getModel().setLength(adjustedLength * getRoad().getContainer().getMpp());
    9697            }
    97            
     98
    9899            center.setLocation(x, y);
    99100            circle.setFrame(x - r, y - r, 2 * r, 2 * r);
    100101        }
    101        
     102
    102103        public void move(Point2D loc) {
    103104            final double x = loc.getX();
    104105            final double y = loc.getY();
    105106            final double r = getRoad().connectorRadius;
    106            
     107
    107108            center.setLocation(x, y);
    108109            circle.setFrame(x - r, y - r, 2 * r, 2 * r);
    109110        }
    110        
     111
    111112        @Override
    112113        int getZIndex() {
     
    114115        }
    115116    }
    116    
     117
    117118    final class OutgoingConnector extends InteractiveElement {
    118119        private final Point2D center = new Point2D.Double();
    119120        private final Ellipse2D circle = new Ellipse2D.Double();
    120        
     121
    121122        private Point2D dragLocation;
    122123        private IncomingConnector dropTarget;
    123        
     124
    124125        private OutgoingConnector() {}
    125        
     126
    126127        @Override
    127128        public void paintBackground(Graphics2D g2d, State state) {
     
    129130                final Composite old = g2d.getComposite();
    130131                g2d.setComposite(((AlphaComposite) old).derive(0.2f));
    131                
     132
    132133                g2d.setColor(new Color(255, 127, 31));
    133134                LaneGui.this.fill(g2d);
    134                
     135
    135136                g2d.setComposite(old);
    136137            }
    137            
     138
    138139            if (dragLocation != null) {
    139140                final State.Connecting s = (State.Connecting) state;
    140141                final Path2D path = new Path2D.Double();
    141142                path.moveTo(center.getX(), center.getY());
    142                
     143
    143144                final List<RoadGui.ViaConnector> vias = s.getViaConnectors();
    144145                for (int i = 0; i < vias.size() - 1; i += 2) {
     
    151152                    path.lineTo(last.getCenter().getX(), last.getCenter().getY());
    152153                }
    153                
     154
    154155                if (dropTarget == null) {
    155156                    g2d.setColor(GuiContainer.RED);
     
    159160                    path.lineTo(dropTarget.getCenter().getX(), dropTarget.getCenter().getY());
    160161                }
    161                
     162
    162163                g2d.setStroke(getContainer().getConnectionStroke());
    163164                g2d.draw(path);
    164165            }
    165166        }
    166        
     167
    167168        @Override
    168169        public void paint(Graphics2D g2d, State state) {
     
    172173                    g2d.setComposite(((AlphaComposite) old).derive(1f));
    173174                }
    174                
     175
    175176                g2d.setColor(Color.WHITE);
    176177                g2d.fill(circle);
     
    178179            }
    179180        }
    180        
     181
    181182        private boolean isActive(State state) {
    182183            return state instanceof State.OutgoingActive
    183184                    && LaneGui.this.equals(((State.OutgoingActive) state).getLane());
    184185        }
    185        
     186
    186187        private boolean isVisible(State state) {
    187188            if (state instanceof State.Connecting) {
    188189                return ((State.Connecting) state).getLane().equals(getModel());
    189190            }
    190            
     191
    191192            return !getRoad().getModel().isPrimary() && getModel().getOutgoingJunction().isPrimary();
    192193        }
    193        
     194
    194195        @Override
    195196        public boolean contains(Point2D p, State state) {
    196197            return isVisible(state) && (circle.contains(p) || LaneGui.this.contains(p));
    197198        }
    198        
     199
    199200        @Override
    200201        public Type getType() {
    201202            return Type.OUTGOING_CONNECTOR;
    202203        }
    203        
     204
    204205        @Override
    205206        public State activate(State old) {
    206207            return new State.OutgoingActive(LaneGui.this);
    207208        }
    208        
     209
    209210        @Override
    210211        boolean beginDrag(double x, double y) {
    211212            return circle.contains(x, y);
    212213        }
    213        
     214
    214215        @Override
    215216        State.Connecting drag(double x, double y, InteractiveElement target, State old) {
    216217            dragLocation = new Point2D.Double(x, y);
    217218            dropTarget = null;
    218            
     219
    219220            if (!(old instanceof State.Connecting)) {
    220221                return new State.Connecting(getModel());
    221222            }
    222            
     223
    223224            final State.Connecting s = (State.Connecting) old;
    224225            if (target != null && target.getType() == Type.INCOMING_CONNECTOR) {
    225226                dropTarget = (IncomingConnector) target;
    226                
     227
    227228                return (s.getViaConnectors().size() & 1) == 0 ? s : s.pop();
    228229            } else if (target != null && target.getType() == Type.VIA_CONNECTOR) {
    229230                return s.next((RoadGui.ViaConnector) target);
    230231            }
    231            
     232
    232233            return s;
    233234        }
    234        
     235
    235236        @Override
    236237        State drop(double x, double y, InteractiveElement target, State old) {
     
    240241                return activate(old);
    241242            }
    242            
     243
    243244            final List<Road> via = new ArrayList<>();
    244245            assert (s.getViaConnectors().size() & 1) == 0;
     
    249250                via.add(a.getRoadEnd().getRoad());
    250251            }
    251            
     252
    252253            getModel().addTurn(via, dropTarget.getRoadEnd());
    253254            dropTarget = null;
    254255            return new State.Dirty(activate(old));
    255256        }
    256        
     257
    257258        public Point2D getCenter() {
    258259            return (Point2D) center.clone();
    259260        }
    260        
     261
    261262        void move(double x, double y) {
    262263            final double r = getRoad().connectorRadius;
    263            
     264
    264265            center.setLocation(x, y);
    265266            circle.setFrame(x - r, y - r, 2 * r, 2 * r);
    266267        }
    267        
     268
    268269        @Override
    269270        int getZIndex() {
     
    271272        }
    272273    }
    273    
     274
    274275    static final NumberFormat METER_FORMAT = new DecimalFormat("0.0m");
    275    
     276
    276277    private final RoadGui road;
    277278    private final Lane lane;
    278    
     279
    279280    final Path2D area = new Path2D.Double();
    280    
     281
    281282    final OutgoingConnector outgoing = new OutgoingConnector();
    282283    final LengthSlider lengthSlider;
    283    
     284
    284285    private Shape clip;
    285286    private double length;
    286    
    287     public LaneGui(RoadGui road, Lane lane) {
     287
     288    LaneGui(RoadGui road, Lane lane) {
    288289        this.road = road;
    289290        this.lane = lane;
     
    291292        this.length = lane.isExtra() ? lane.getLength() / road.getContainer().getMpp() : Double.NaN;
    292293    }
    293    
     294
    294295    public double getLength() {
    295296        return lane.isExtra() ? length : road.getLength();
    296297    }
    297    
     298
    298299    public Lane getModel() {
    299300        return lane;
    300301    }
    301    
     302
    302303    public RoadGui getRoad() {
    303304        return road;
    304305    }
    305    
     306
    306307    public GuiContainer getContainer() {
    307308        return getRoad().getContainer();
    308309    }
    309    
     310
    310311    public Path recalculate(Path inner, Path2D innerLine) {
    311312        area.reset();
    312        
     313
    313314        final double W = getContainer().getLaneWidth();
    314315        final double L = getLength();
    315        
     316
    316317        final double WW = 3 / getContainer().getMpp();
    317        
     318
    318319        final LaneGui left = left();
    319320        final Lane leftModel = left == null ? null : left.getModel();
     
    321322                || !leftModel.getOutgoingRoadEnd().equals(getModel().getOutgoingRoadEnd()) ? Double.NEGATIVE_INFINITY
    322323                : leftModel.getKind() == Lane.Kind.EXTRA_LEFT ? left.getLength() : L;
    323        
     324
    324325        final Path outer;
    325326        if (getModel().getKind() == Lane.Kind.EXTRA_LEFT) {
    326327            final double AL = 30 / getContainer().getMpp();
    327328            final double SL = max(L, leftLength + AL);
    328            
     329
    329330            outer = inner.offset(W, SL, SL + AL, 0);
    330331            area(area, inner.subpath(0, L, true), outer.subpath(0, L + WW, true));
    331            
     332
    332333            lengthSlider.move(inner.getPoint(L, true));
    333            
     334
    334335            if (L > leftLength) {
    335336                innerLine.append(inner.subpath(leftLength + WW, L, true).getIterator(), leftLength >= 0
     
    341342            outer = inner.offset(W, L, L + WW, 0);
    342343            area(area, inner.subpath(0, L + WW, true), outer.subpath(0, L, true));
    343            
     344
    344345            lengthSlider.move(outer.getPoint(L, true));
    345346        } else {
    346347            outer = inner.offset(W, -1, -1, W);
    347348            area(area, inner, outer);
    348            
     349
    349350            if (leftLength < L) {
    350351                innerLine.append(inner.subpath(leftLength + WW, L, true).getIterator(), leftLength >= 0
     
    352353            }
    353354        }
    354        
     355
    355356        return outer;
    356357    }
    357    
     358
    358359    private LaneGui left() {
    359360        final List<LaneGui> lanes = getRoad().getLanes(getModel().getOutgoingRoadEnd());
     
    361362        return i > 0 ? lanes.get(i - 1) : null;
    362363    }
    363    
     364
    364365    public void fill(Graphics2D g2d) {
    365366        final Shape old = g2d.getClip();
     
    368369        g2d.setClip(old);
    369370    }
    370    
     371
    371372    public void setClip(Shape clip) {
    372373        this.clip = clip;
    373374    }
    374    
     375
    375376    public boolean contains(Point2D p) {
    376377        return area.contains(p) && clip.contains(p);
  • applications/editors/josm/plugins/turnlanes/src/org/openstreetmap/josm/plugins/turnlanes/gui/Path.java

    r26316 r33085  
     1// License: GPL. For details, see LICENSE file.
    12package org.openstreetmap.josm.plugins.turnlanes.gui;
    23
     
    2223 * A path that allows constructing offset curves/parallel curves with a somewhat crude straight
    2324 * skeleton implementation.
    24  * 
     25 *
    2526 * @author Ben Schulz
    2627 */
     
    2829    private static final class SimplePathIterator implements PathIterator {
    2930        private final SimplePathIterator previous;
    30        
     31
    3132        private final int type;
    3233        private final double[] coords;
    33        
     34
    3435        private boolean done = false;
    35        
    36         public SimplePathIterator(SimplePathIterator previous, int type, double... coords) {
     36
     37        SimplePathIterator(SimplePathIterator previous, int type, double... coords) {
    3738            this.previous = previous;
    3839            this.type = type;
    3940            this.coords = coords;
    4041        }
    41        
    42         public SimplePathIterator(int type, double... coords) {
     42
     43        SimplePathIterator(int type, double... coords) {
    4344            this(null, type, coords);
    4445        }
    45        
     46
    4647        @Override
    4748        public int getWindingRule() {
    4849            return WIND_NON_ZERO;
    4950        }
    50        
     51
    5152        @Override
    5253        public boolean isDone() {
    5354            return done;
    5455        }
    55        
     56
    5657        @Override
    5758        public void next() {
     
    6263            }
    6364        }
    64        
     65
    6566        @Override
    6667        public int currentSegment(float[] coords) {
     
    7071                throw new NoSuchElementException("Iterator is already done.");
    7172            }
    72            
     73
    7374            for (int i = 0; i < 6; ++i) {
    7475                coords[i] = (float) this.coords[i];
    7576            }
    76            
     77
    7778            return type;
    7879        }
    79        
     80
    8081        @Override
    8182        public int currentSegment(double[] coords) {
     
    8586                throw new NoSuchElementException("Iterator is already done.");
    8687            }
    87            
     88
    8889            for (int i = 0; i < 6; ++i) {
    8990                coords[i] = this.coords[i];
    9091            }
    91            
     92
    9293            return type;
    9394        }
    94        
    95     }
    96    
     95
     96    }
     97
    9798    private static final class Line extends Path {
    9899        private final Path previous;
    99        
     100
    100101        private final double endX;
    101102        private final double endY;
    102        
     103
    103104        private final double angle;
    104        
     105
    105106        private final double length;
    106        
    107         public Line(Path previous, double x, double y, double length) {
     107
     108        Line(Path previous, double x, double y, double length) {
    108109            this.previous = previous;
    109            
     110
    110111            this.endX = x;
    111112            this.endY = y;
    112            
     113
    113114            this.angle = angle(previous.getEnd(), getEnd());
    114            
     115
    115116            this.length = length;
    116117        }
    117        
     118
    118119        @Override
    119120        public Point2D getStart() {
    120121            return previous.getStart();
    121122        }
    122        
     123
    123124        @Override
    124125        public Point2D getEnd() {
    125126            return new Point2D.Double(endX, endY);
    126127        }
    127        
     128
    128129        @Override
    129130        public double getEndAngle() {
    130131            return angle;
    131132        }
    132        
     133
    133134        @Override
    134135        public double getLength() {
    135136            return previous.getLength() + length;
    136137        }
    137        
     138
    138139        @Override
    139140        public Path offset(double ws, double m1, double m2, double we) {
    140141            return offsetInternal(ws, m1, m2, we, angle);
    141142        }
    142        
     143
    143144        @Override
    144145        Path offsetInternal(double ws, double m1, double m2, double we, double endAngle) {
    145146            final double PL = previous.getLength();
    146147            final double ML = PL + length;
    147            
     148
    148149            final Path prev = previous.offsetInternal(ws, m1, m2, we, angle);
    149            
     150
    150151            final double wStart = PL <= m1 ? ws : m2 <= PL ? we : ws + (PL - m1) * (we - ws) / (m2 - m1);
    151152            final Point2D from = prev.getEnd();
    152153            final Point2D to = offsetEnd(wStart, endAngle);
    153            
     154
    154155            if (abs(minAngleDiff(angle, angle(from, to))) > PI / 100) {
    155156                return previous.offsetInternal(ws, m1, m2, we, endAngle);
    156157            }
    157            
     158
    158159            if (ML <= m1) {
    159160                return simpleOffset(prev, ws, endAngle);
     
    161162                return simpleOffset(prev, we, endAngle);
    162163            }
    163            
     164
    164165            final double LL = from.distance(to);
    165            
     166
    166167            final Point2D m1o = PL <= m1 ? relativePoint(prev.getEnd(), LL * (m1 - PL) / length, angle) : null;
    167168            final Point2D m2t = m2 <= ML ? relativePoint(getEnd(), LL * (ML - m2) / length, angle + PI) : null;
    168169            final Point2D m2o = m2t == null ? null : relativePoint(m2t, we, (angle + endAngle - PI) / 2);
    169            
     170
    170171            if (m1o != null && m2o != null) {
    171172                final Line l1 = new Line(prev, m1o.getX(), m1o.getY(), m1 - PL);
    172173                final Line l2 = new Line(l1, m2o.getX(), m2o.getY(), m2 - m1);
    173                
     174
    174175                final Point2D end = offsetEnd(we, endAngle);
    175                
     176
    176177                return new Line(l2, end.getX(), end.getY(), ML - m2);
    177178            } else if (m1o != null) {
    178179                final Line l1 = new Line(prev, m1o.getX(), m1o.getY(), m1 - PL);
    179                
     180
    180181                final double w = ws + (ML - m1) * (we - ws) / (m2 - m1);
    181182                final Point2D end = offsetEnd(w, endAngle);
    182                
     183
    183184                return new Line(l1, end.getX(), end.getY(), ML - m1);
    184185            } else if (m2o != null) {
    185186                final Line l2 = new Line(prev, m2o.getX(), m2o.getY(), m2 - PL);
    186                
     187
    187188                final Point2D end = offsetEnd(we, endAngle);
    188                
     189
    189190                return new Line(l2, end.getX(), end.getY(), ML - m2);
    190191            } else {
     
    194195            }
    195196        }
    196        
     197
    197198        private Path simpleOffset(Path prev, double w, double endAngle) {
    198199            final Point2D offset = offsetEnd(w, endAngle);
    199200            return new Line(prev, offset.getX(), offset.getY(), length);
    200201        }
    201        
     202
    202203        private Point2D offsetEnd(double w, double endAngle) {
    203204            final double da2 = minAngleDiff(angle, endAngle) / 2;
    204205            final double hypotenuse = w / cos(da2);
    205            
     206
    206207            return relativePoint(getEnd(), hypotenuse, angle + PI / 2 + da2);
    207208        }
    208        
     209
    209210        @Override
    210211        public SimplePathIterator getIterator() {
     
    212213                    0, 0, 0);
    213214        }
    214        
     215
    215216        @Override
    216217        public Path subpath(double from, double to) {
    217218            final double PL = previous.getLength();
    218219            final double ML = PL + length;
    219            
     220
    220221            if (from > ML) {
    221222                throw new IllegalArgumentException("from > length");
     
    223224                throw new IllegalArgumentException("to > length");
    224225            }
    225            
     226
    226227            if (to < PL) {
    227228                return previous.subpath(from, to);
    228229            }
    229            
     230
    230231            final Point2D end = to < ML ? getPoint(to) : new Point2D.Double(endX, endY);
    231            
     232
    232233            final double EL = min(ML, to);
    233234            if (PL <= from) {
     
    238239            }
    239240        }
    240        
     241
    241242        @Override
    242243        public Point2D getPoint(double offset) {
    243244            final double PL = previous.getLength();
    244245            final double ML = PL + length;
    245            
     246
    246247            if (offset > ML) {
    247248                throw new IllegalArgumentException("offset > length");
    248249            }
    249            
     250
    250251            if (offset <= ML && offset >= PL) {
    251252                final double LL = previous.getEnd().distance(getEnd());
     
    255256            }
    256257        }
    257        
     258
    258259        @Override
    259260        SimplePathIterator getIteratorInternal(double endAngle) {
     
    261262        }
    262263    }
    263    
     264
    264265    // TODO curves are still somewhat broken
    265266    private static class Curve extends Path {
    266267        private final Path previous;
    267        
     268
    268269        private final double height;
    269        
     270
    270271        private final double centerX;
    271272        private final double centerY;
    272273        private final double centerToFromAngle;
    273        
     274
    274275        private final double endX;
    275276        private final double endY;
    276        
     277
    277278        private final double fromAngle;
    278279        private final double fromRadius;
    279280        private final double toRadius;
    280281        private final double angle;
    281        
     282
    282283        private final double length;
    283        
     284
    284285        private Curve(Path previous, double r1, double r2, double a, double length, double fromAngle) {
    285286            this.previous = previous;
     
    289290            this.angle = a;
    290291            this.length = length;
    291            
     292
    292293            final Point2D from = previous.getEnd();
    293294            this.centerToFromAngle = fromAngle - signum(a) * PI / 2;
    294295            final Point2D center = relativePoint(from, r1, centerToFromAngle + PI);
    295            
     296
    296297            final double toAngle = centerToFromAngle + a;
    297298            this.endX = center.getX() + r2 * cos(toAngle);
    298299            this.endY = center.getY() - r2 * sin(toAngle);
    299            
     300
    300301            this.centerX = center.getX();
    301302            this.centerY = center.getY();
    302            
     303
    303304            final double y = new Line2D.Double(center, from).ptLineDist(endX, endY);
    304305            this.height = y / sin(angle);
    305306        }
    306        
    307         public Curve(Path previous, double r1, double r2, double a, double length) {
     307
     308        Curve(Path previous, double r1, double r2, double a, double length) {
    308309            this(previous, r1, r2, a, length, previous.getEndAngle());
    309310        }
    310        
     311
     312        @Override
    311313        public Point2D getStart() {
    312314            return previous.getStart();
    313315        }
    314        
     316
    315317        @Override
    316318        public Point2D getEnd() {
    317319            return new Point2D.Double(endX, endY);
    318320        }
    319        
     321
    320322        @Override
    321323        public double getEndAngle() {
    322324            return fromAngle + angle;
    323325        }
    324        
     326
    325327        @Override
    326328        public double getLength() {
    327329            return previous.getLength() + length;
    328330        }
    329        
     331
    330332        @Override
    331333        public Path offset(double ws, double m1, double m2, double we) {
    332334            return offsetInternal(ws, m1, m2, we, previous.getEndAngle() + angle);
    333335        }
    334        
     336
    335337        @Override
    336338        Path offsetInternal(double ws, double m1, double m2, double we, double endAngle) {
    337339            final double PL = previous.getLength();
    338340            final double ML = PL + length;
    339            
     341
    340342            final Path prev = previous.offsetInternal(ws, m1, m2, we, fromAngle);
    341            
     343
    342344            if (ML <= m1) {
    343345                return simpleOffset(prev, ws);
     
    345347                return simpleOffset(prev, we);
    346348            }
    347            
     349
    348350            final double s = signum(angle);
    349            
     351
    350352            if (PL < m1 && m2 < ML) {
    351353                final double l1 = m1 - PL;
    352354                final double a1 = angle(l1);
    353355                final double r1 = radius(a1) - s * ws;
    354                
     356
    355357                final Curve c1 = new Curve(prev, fromRadius - ws, r1, offsetAngle(prev, a1), l1, fromAngle);
    356                
     358
    357359                final double l2 = m2 - m1;
    358360                final double a2 = angle(l2);
    359361                final double r2 = radius(a2) - s * we;
    360                
     362
    361363                final Curve c2 = new Curve(c1, r1, r2, a2 - a1, l2);
    362                
     364
    363365                return new Curve(c2, r2, toRadius - s * we, angle - a2, ML - m2);
    364366            } else if (PL < m1) {
     
    366368                final double a1 = angle(l1);
    367369                final double r1 = radius(a1) - s * ws;
    368                
     370
    369371                final Curve c1 = new Curve(prev, fromRadius - s * ws, r1, offsetAngle(prev, a1), l1, fromAngle);
    370                
     372
    371373                final double w = ws + (ML - m1) * (we - ws) / (m2 - m1);
    372                
     374
    373375                return new Curve(c1, r1, toRadius - s * w, angle - a1, ML - m1);
    374376            } else if (m2 < ML) {
    375377                final double w = ws + (PL - m1) * (we - ws) / (m2 - m1);
    376                
     378
    377379                final double l2 = m2 - PL;
    378380                final double a2 = angle(l2);
    379381                final double r2 = radius(a2) - s * we;
    380                
     382
    381383                final Curve c2 = new Curve(prev, fromRadius - s * w, r2, offsetAngle(prev, a2), l2, fromAngle);
    382                
     384
    383385                return new Curve(c2, r2, toRadius - s * we, angle - a2, ML - m2);
    384386            } else {
    385387                final double w1 = ws + (PL - m1) * (we - ws) / (m2 - m1);
    386388                final double w2 = we - (m2 - ML) * (we - ws) / (m2 - m1);
    387                
     389
    388390                return new Curve(prev, fromRadius - s * w1, toRadius - s * w2, offsetAngle(prev, angle), length,
    389391                        fromAngle);
    390392            }
    391393        }
    392        
     394
    393395        private double angle(double l) {
    394396            return l * angle / length;
    395397        }
    396        
     398
    397399        private double radius(double a) {
    398400            return hypot(fromRadius * cos(a), height * sin(a));
    399401        }
    400        
     402
    401403        private double offsetAngle(Path prev, double a) {
    402             return a;// + GuiUtil.normalize(previous.getEndAngle()
     404            return a; // + GuiUtil.normalize(previous.getEndAngle()
    403405            // - prev.getEndAngle());
    404406        }
    405        
     407
    406408        private Path simpleOffset(Path prev, double w) {
    407409            final double s = signum(angle);
    408410            return new Curve(prev, fromRadius - s * w, toRadius - s * w, offsetAngle(prev, angle), length, fromAngle);
    409411        }
    410        
     412
    411413        @Override
    412414        public SimplePathIterator getIterator() {
    413415            return getIteratorInternal(previous.getEndAngle() + angle);
    414416        }
    415        
     417
    416418        @Override
    417419        public Path subpath(double from, double to) {
    418420            final double PL = previous.getLength();
    419421            final double ML = PL + length;
    420            
     422
    421423            if (from > ML) {
    422424                throw new IllegalArgumentException("from > length");
     
    424426                throw new IllegalArgumentException("to > length");
    425427            }
    426            
     428
    427429            if (to < PL) {
    428430                return previous.subpath(from, to);
    429431            }
    430            
     432
    431433            final double toA = to < ML ? angle(to - PL) : angle;
    432434            final double toR = to < ML ? radius(toA) : toRadius;
    433            
     435
    434436            final double fromA = from > PL ? angle(from - PL) : 0;
    435437            final double fromR = from > PL ? radius(fromA) : fromRadius;
    436            
     438
    437439            final double a = toA - fromA;
    438440            final double l = min(ML, to) - max(PL, from);
    439            
     441
    440442            if (from >= PL) {
    441443                final Point2D start = getPoint(from);
    442444                final double fa = fromAngle + fromA;
    443                
     445
    444446                return new Curve(new Start(start.getX(), start.getY(), fa), fromR, toR, a, l, fa);
    445447            } else {
     
    447449            }
    448450        }
    449        
     451
    450452        @Override
    451453        public Point2D getPoint(double offset) {
    452454            final double PL = previous.getLength();
    453455            final double ML = PL + length;
    454            
     456
    455457            if (offset <= ML && offset >= PL) {
    456458                final double a = abs(angle(offset - PL));
    457459                final double w = fromRadius * cos(a);
    458460                final double h = -height * sin(a);
    459                
     461
    460462                final double r = centerToFromAngle; // rotation angle
    461463                final double x = w * cos(r) + h * sin(r);
    462464                final double y = -w * sin(r) + h * cos(r);
    463                
     465
    464466                return new Point2D.Double(centerX + x, centerY + y);
    465467            } else {
     
    467469            }
    468470        }
    469        
     471
    470472        @Override
    471473        SimplePathIterator getIteratorInternal(double endAngle) {
    472474            final Point2D cp1 = relativePoint(previous.getEnd(), cpf(angle, fromRadius), previous.getEndAngle());
    473475            final Point2D cp2 = relativePoint(getEnd(), cpf(angle, toRadius), endAngle + PI);
    474            
     476
    475477            return new SimplePathIterator(previous.getIteratorInternal(getEndAngle()), PathIterator.SEG_CUBICTO, //
    476478                    cp1.getX(), cp1.getY(), cp2.getX(), cp2.getY(), endX, endY //
    477479            );
    478            
    479         }
    480     }
    481    
     480
     481        }
     482    }
     483
    482484    private static class Start extends Path {
    483485        private final double x;
    484486        private final double y;
    485        
     487
    486488        private final double endAngle;
    487        
    488         public Start(double x, double y, double endAngle) {
     489
     490        Start(double x, double y, double endAngle) {
    489491            this.x = x;
    490492            this.y = y;
    491493            this.endAngle = endAngle;
    492494        }
    493        
    494         public Start(double x, double y) {
     495
     496        Start(double x, double y) {
    495497            this(x, y, Double.NaN);
    496498        }
    497        
     499
     500        @Override
    498501        public Point2D getStart() {
    499502            return new Point2D.Double(x, y);
    500503        }
    501        
     504
     505        @Override
    502506        public Point2D getEnd() {
    503507            return new Point2D.Double(x, y);
    504508        }
    505        
     509
    506510        @Override
    507511        public double getEndAngle() {
     
    509513                throw new UnsupportedOperationException();
    510514            }
    511            
     515
    512516            return endAngle;
    513517        }
    514        
     518
    515519        @Override
    516520        public double getLength() {
    517521            return 0;
    518522        }
    519        
     523
    520524        @Override
    521525        public Path offset(double ws, double m1, double m2, double we) {
    522526            throw new UnsupportedOperationException();
    523527        }
    524        
     528
    525529        @Override
    526530        Path offsetInternal(double ws, double m1, double m2, double we, double endAngle) {
     
    528532            return new Start(offset.getX(), offset.getY(), endAngle);
    529533        }
    530        
     534
    531535        @Override
    532536        public SimplePathIterator getIterator() {
    533537            return new SimplePathIterator(PathIterator.SEG_MOVETO, x, y, 0, 0, 0, 0);
    534538        }
    535        
     539
    536540        @Override
    537541        public Path subpath(double from, double to) {
     
    542546                throw new IllegalArgumentException("from < 0");
    543547            }
    544            
     548
    545549            return this;
    546550        }
    547        
     551
    548552        @Override
    549553        public Point2D getPoint(double offset) {
     
    554558            }
    555559        }
    556        
     560
    557561        @Override
    558562        SimplePathIterator getIteratorInternal(double endAngle) {
     
    560564        }
    561565    }
    562    
     566
    563567    public static Path create(double x, double y) {
    564568        return new Start(x, y);
    565569    }
    566    
     570
    567571    public Path lineTo(double x, double y, double length) {
    568572        return new Line(this, x, y, length);
    569573    }
    570    
     574
    571575    public Path curveTo(double r1, double r2, double a, double length) {
    572576        return new Curve(this, r1, r2, a, length);
    573577    }
    574    
     578
    575579    public abstract Path offset(double ws, double m1, double m2, double we);
    576    
     580
    577581    abstract Path offsetInternal(double ws, double m1, double m2, double we, double endAngle);
    578    
     582
    579583    public abstract double getLength();
    580    
     584
    581585    public abstract double getEndAngle();
    582    
     586
    583587    public abstract Point2D getStart();
    584    
     588
    585589    public abstract Point2D getEnd();
    586    
     590
    587591    public abstract SimplePathIterator getIterator();
    588    
     592
    589593    abstract SimplePathIterator getIteratorInternal(double endAngle);
    590    
     594
    591595    public abstract Path subpath(double from, double to);
    592    
     596
    593597    public Path subpath(double from, double to, boolean fixArgs) {
    594598        if (fixArgs) {
     
    596600            to = min(max(to, 0), getLength());
    597601        }
    598        
     602
    599603        return subpath(from, to);
    600604    }
    601    
     605
    602606    public abstract Point2D getPoint(double offset);
    603    
     607
    604608    public Point2D getPoint(double offset, boolean fixArgs) {
    605609        if (fixArgs) {
    606610            offset = min(max(offset, 0), getLength());
    607611        }
    608        
     612
    609613        return getPoint(offset);
    610614    }
  • applications/editors/josm/plugins/turnlanes/src/org/openstreetmap/josm/plugins/turnlanes/gui/ReversePathIterator.java

    r26154 r33085  
     1// License: GPL. For details, see LICENSE file.
    12package org.openstreetmap.josm.plugins.turnlanes.gui;
    23
     
    67/**
    78 * Path iterator which reverses the path of a given iterator.
    8  * 
     9 *
    910 * <p>
    1011 * The given (unreversed) iterator must start with a {@code PathIterator.SEG_MOVETO} and must not
     
    1213 * returned by {@code Path.getIterator} which has exactly those properties.
    1314 * </p>
    14  * 
     15 *
    1516 * @author Ben Schulz
    1617 */
    17 class ReversePathIterator implements PathIterator {
     18final class ReversePathIterator implements PathIterator {
    1819    private static final int[] COUNTS = {
    1920        2, // SEG_MOVETO = 0
     
    2324        0, // SEG_CLOSE = 4
    2425    };
    25    
     26
    2627    public static ReversePathIterator reverse(PathIterator it) {
    2728        return new ReversePathIterator(it);
    2829    }
    29    
     30
    3031    private static int[] reverseTypes(int[] types, int length) {
    3132        if (length > 0 && types[0] != SEG_MOVETO) {
     
    3334            throw new IllegalArgumentException("Can not reverse path without initial SEG_MOVETO.");
    3435        }
    35        
     36
    3637        final int[] result = new int[length];
    37        
     38
    3839        result[0] = SEG_MOVETO;
    39        
     40
    4041        int lower = 1;
    4142        int upper = length - 1;
    42        
     43
    4344        while (lower <= upper) {
    4445            result[lower] = types[upper];
    4546            result[upper] = types[lower];
    46            
     47
    4748            ++lower;
    4849            --upper;
    4950        }
    50        
     51
    5152        return result;
    5253    }
    53    
     54
    5455    private static double[] reverseCoords(double[] coords, int length) {
    5556        final double[] result = new double[length];
    56        
     57
    5758        int lower = 0;
    5859        int upper = length - 2;
    59        
     60
    6061        while (lower <= upper) {
    6162            result[lower] = coords[upper];
     
    6364            result[upper] = coords[lower];
    6465            result[upper + 1] = coords[lower + 1];
    65            
     66
    6667            lower += 2;
    6768            upper -= 2;
    6869        }
    69        
     70
    7071        return result;
    7172    }
    72    
     73
    7374    private final int winding;
    74    
     75
    7576    private final int[] types;
    7677    private int typesIndex = 0;
    77    
     78
    7879    private final double[] coords;
    7980    private int coordsIndex = 0;
    80    
     81
    8182    private ReversePathIterator(PathIterator it) {
    8283        this.winding = it.getWindingRule();
    83        
     84
    8485        double[] tmpCoords = new double[62];
    8586        int[] tmpTypes = new int[11];
    86        
     87
    8788        int tmpCoordsI = 0;
    8889        int tmpTypesI = 0;
    89        
     90
    9091        while (!it.isDone()) {
    9192            if (tmpTypesI >= tmpTypes.length) {
    9293                tmpTypes = Arrays.copyOf(tmpTypes, 2 * tmpTypes.length);
    9394            }
    94            
     95
    9596            final double[] cs = new double[6];
    9697            final int t = it.currentSegment(cs);
    9798            tmpTypes[tmpTypesI++] = t;
    9899            final int count = COUNTS[t];
    99            
     100
    100101            if (tmpCoordsI + count > tmpCoords.length) {
    101102                tmpCoords = Arrays.copyOf(tmpCoords, 2 * tmpCoords.length);
     
    103104            System.arraycopy(cs, 0, tmpCoords, tmpCoordsI, count);
    104105            tmpCoordsI += count;
    105            
     106
    106107            it.next();
    107108        }
    108        
     109
    109110        this.types = reverseTypes(tmpTypes, tmpTypesI);
    110111        this.coords = reverseCoords(tmpCoords, tmpCoordsI);
    111112    }
    112    
     113
    113114    @Override
    114115    public int getWindingRule() {
    115116        return winding;
    116117    }
    117    
     118
    118119    @Override
    119120    public boolean isDone() {
    120121        return typesIndex >= types.length;
    121122    }
    122    
     123
    123124    @Override
    124125    public void next() {
     
    126127        ++typesIndex;
    127128    }
    128    
     129
    129130    @Override
    130131    public int currentSegment(float[] coords) {
    131132        final double[] tmp = new double[6];
    132133        final int type = currentSegment(tmp);
    133        
     134
    134135        coords[0] = (float) tmp[0];
    135136        coords[1] = (float) tmp[1];
     
    138139        coords[4] = (float) tmp[4];
    139140        coords[5] = (float) tmp[5];
    140        
     141
    141142        return type;
    142143    }
    143    
     144
    144145    @Override
    145146    public int currentSegment(double[] coords) {
  • applications/editors/josm/plugins/turnlanes/src/org/openstreetmap/josm/plugins/turnlanes/gui/RoadGui.java

    r30737 r33085  
     1// License: GPL. For details, see LICENSE file.
    12package org.openstreetmap.josm.plugins.turnlanes.gui;
    23
     
    4344    final class ViaConnector extends InteractiveElement {
    4445        private final Road.End end;
    45        
     46
    4647        private final Line2D line;
    4748        private final float strokeWidth;
    48        
    49         public ViaConnector(Road.End end) {
     49
     50        ViaConnector(Road.End end) {
    5051            this.end = end;
    5152            this.line = new Line2D.Double(getLeftCorner(end), getRightCorner(end));
    5253            this.strokeWidth = (float) (3 * getContainer().getLaneWidth() / 4);
    5354        }
    54        
     55
    5556        @Override
    5657        void paint(Graphics2D g2d, State state) {
     
    6162            }
    6263        }
    63        
     64
    6465        @Override
    6566        boolean contains(Point2D p, State state) {
     
    6768                return false;
    6869            }
    69            
     70
    7071            final Point2D closest = closest(line, p);
    7172            return p.distance(closest) <= strokeWidth / 2;
    7273        }
    73        
     74
    7475        private boolean isVisible(State state) {
    7576            if (!(state instanceof State.Connecting)) {
    7677                return false;
    7778            }
    78            
     79
    7980            final State.Connecting s = (State.Connecting) state;
    80            
     81
    8182            if (s.getJunction().equals(end.getJunction()) || equals(s.getBacktrackViaConnector())) {
    8283                return true;
     
    8586                return true;
    8687            }
    87            
     88
    8889            return false;
    8990        }
    90        
     91
    9192        private Road getRoadModel() {
    9293            return getModel();
    9394        }
    94        
     95
    9596        public RoadGui getRoad() {
    9697            return RoadGui.this;
    9798        }
    98        
     99
    99100        @Override
    100101        Type getType() {
    101102            return Type.VIA_CONNECTOR;
    102103        }
    103        
     104
    104105        @Override
    105106        int getZIndex() {
    106107            return 1;
    107108        }
    108        
     109
    109110        public Road.End getRoadEnd() {
    110111            return end;
    111112        }
    112        
     113
    113114        public Point2D getCenter() {
    114115            return relativePoint(line.getP1(), line.getP1().distance(line.getP2()) / 2, angle(line.getP1(), line.getP2()));
    115116        }
    116117    }
    117    
     118
    118119    private final class Extender extends InteractiveElement {
    119120        private final Road.End end;
    120121        private final Way way;
    121        
     122
    122123        private final Line2D line;
    123        
    124         public Extender(Road.End end, Way way, double angle) {
     124
     125        Extender(Road.End end, Way way, double angle) {
    125126            this.end = end;
    126127            this.way = way;
    127128            this.line = new Line2D.Double(a.getPoint(), relativePoint(a.getPoint(), getContainer().getLaneWidth() * 4, angle));
    128129        }
    129        
     130
    130131        @Override
    131132        void paint(Graphics2D g2d, State state) {
     
    134135            g2d.draw(line);
    135136        }
    136        
     137
    137138        @Override
    138139        boolean contains(Point2D p, State state) {
    139140            final BasicStroke stroke = (BasicStroke) getContainer().getConnectionStroke();
    140141            final double strokeWidth = stroke.getLineWidth();
    141            
     142
    142143            final Point2D closest = closest(line, p);
    143144            return p.distance(closest) <= strokeWidth / 2;
    144145        }
    145        
     146
    146147        @Override
    147148        State click(State old) {
     
    149150            return new State.Invalid(old);
    150151        }
    151        
     152
    152153        @Override
    153154        Type getType() {
    154155            return Type.EXTENDER;
    155156        }
    156        
     157
    157158        @Override
    158159        int getZIndex() {
     
    160161        }
    161162    }
    162    
     163
    163164    private final class LaneAdder extends InteractiveElement {
    164165        private final Road.End end;
    165166        private final Lane.Kind kind;
    166        
     167
    167168        private final Point2D center;
    168169        private final Ellipse2D background;
    169        
    170         public LaneAdder(Road.End end, Lane.Kind kind) {
     170
     171        LaneAdder(Road.End end, Lane.Kind kind) {
    171172            this.end = end;
    172173            this.kind = kind;
    173            
     174
    174175            final double a = getAngle(end) + PI;
    175176            final Point2D lc = getLeftCorner(end);
    176177            final Point2D rc = getRightCorner(end);
    177            
     178
    178179            final double r = connectorRadius;
    179180            final double cx;
     
    182183                final JunctionGui j = getContainer().getGui(end.getJunction());
    183184                final Point2D i = intersection(line(j.getPoint(), a), new Line2D.Double(lc, rc));
    184                
     185
    185186                cx = i.getX() + 21d / 16 * r * (2 * cos(a) + cos(a - PI / 2));
    186187                cy = i.getY() - 21d / 16 * r * (2 * sin(a) + sin(a - PI / 2));
     
    189190                cy = rc.getY() - 21d / 16 * r * (2 * sin(a) + sin(a + PI / 2));
    190191            }
    191            
     192
    192193            center = new Point2D.Double(cx, cy);
    193194            background = new Ellipse2D.Double(cx - r, cy - r, 2 * r, 2 * r);
    194195        }
    195        
     196
    196197        @Override
    197198        void paint(Graphics2D g2d, State state) {
     
    199200                return;
    200201            }
    201            
     202
    202203            g2d.setColor(Color.DARK_GRAY);
    203204            g2d.fill(background);
    204            
     205
    205206            final double l = 2 * connectorRadius / 3;
    206207            final Line2D v = new Line2D.Double(center.getX(), center.getY() - l, center.getX(), center.getY() + l);
    207208            final Line2D h = new Line2D.Double(center.getX() - l, center.getY(), center.getX() + l, center.getY());
    208            
     209
    209210            g2d.setStroke(new BasicStroke((float) (connectorRadius / 5)));
    210211            g2d.setColor(Color.WHITE);
     
    212213            g2d.draw(h);
    213214        }
    214        
     215
    215216        private boolean isVisible(State state) {
    216217            return end.getJunction().isPrimary();
    217218        }
    218        
     219
    219220        @Override
    220221        boolean contains(Point2D p, State state) {
    221222            return isVisible(state) && background.contains(p);
    222223        }
    223        
     224
    224225        @Override
    225226        Type getType() {
    226227            return Type.LANE_ADDER;
    227228        }
    228        
     229
    229230        @Override
    230231        int getZIndex() {
    231232            return 2;
    232233        }
    233        
     234
    234235        @Override
    235236        public State click(State old) {
     
    238239        }
    239240    }
    240    
     241
    241242    final class IncomingConnector extends InteractiveElement {
    242243        private final Road.End end;
    243244        private final List<LaneGui> lanes;
    244        
     245
    245246        private final Point2D center = new Point2D.Double();
    246247        private final Ellipse2D circle = new Ellipse2D.Double();
    247        
     248
    248249        private IncomingConnector(Road.End end) {
    249250            this.end = end;
    250            
     251
    251252            final List<LaneGui> lanes = new ArrayList<>(end.getLanes().size());
    252253            for (Lane l : end.getOppositeEnd().getLanes()) {
     
    255256            this.lanes = Collections.unmodifiableList(lanes);
    256257        }
    257        
     258
    258259        @Override
    259260        public void paintBackground(Graphics2D g2d, State state) {
     
    261262                final Composite old = g2d.getComposite();
    262263                g2d.setComposite(((AlphaComposite) old).derive(0.2f));
    263                
     264
    264265                g2d.setColor(new Color(255, 127, 31));
    265                
     266
    266267                for (LaneGui l : lanes) {
    267268                    l.fill(g2d);
    268269                }
    269                
     270
    270271                g2d.setComposite(old);
    271272            }
    272273        }
    273        
     274
    274275        @Override
    275276        public void paint(Graphics2D g2d, State state) {
     
    279280                    g2d.setComposite(((AlphaComposite) old).derive(1f));
    280281                }
    281                
     282
    282283                g2d.setColor(Color.LIGHT_GRAY);
    283284                g2d.fill(circle);
    284                
     285
    285286                g2d.setComposite(old);
    286287            }
    287288        }
    288        
     289
    289290        private boolean isActive(State state) {
    290291            if (!(state instanceof State.IncomingActive)) {
    291292                return false;
    292293            }
    293            
     294
    294295            final Road.End roadEnd = ((State.IncomingActive) state).getRoadEnd();
    295            
     296
    296297            return roadEnd.equals(getRoadEnd());
    297298        }
    298        
     299
    299300        private boolean isVisible(State state) {
    300301            if (getModel().isPrimary() || !getRoadEnd().getJunction().isPrimary()
     
    302303                return false;
    303304            }
    304            
     305
    305306            if (state instanceof State.Connecting) {
    306307                return ((State.Connecting) state).getJunction().equals(getRoadEnd().getJunction());
    307308            }
    308            
     309
    309310            return true;
    310311        }
    311        
     312
    312313        @Override
    313314        public boolean contains(Point2D p, State state) {
     
    317318                return true;
    318319            }
    319            
     320
    320321            for (LaneGui l : lanes) {
    321322                if (l.contains(p)) {
     
    323324                }
    324325            }
    325            
     326
    326327            return false;
    327328        }
    328        
     329
    329330        @Override
    330331        public Type getType() {
    331332            return Type.INCOMING_CONNECTOR;
    332333        }
    333        
     334
    334335        @Override
    335336        public State activate(State old) {
    336337            return new State.IncomingActive(getRoadEnd());
    337338        }
    338        
     339
    339340        public Point2D getCenter() {
    340341            return (Point2D) center.clone();
    341342        }
    342        
     343
    343344        void move(double x, double y) {
    344345            final double r = connectorRadius;
    345            
     346
    346347            center.setLocation(x, y);
    347348            circle.setFrame(x - r, y - r, 2 * r, 2 * r);
    348349        }
    349        
     350
    350351        public Road.End getRoadEnd() {
    351352            return end;
    352353        }
    353        
     354
    354355        public List<LaneGui> getLanes() {
    355356            return lanes;
    356357        }
    357        
     358
    358359        @Override
    359360        int getZIndex() {
    360361            return 1;
    361362        }
    362        
     363
    363364        public void add(LaneGui lane) {
    364365            lanes.add(lane);
    365366        }
    366367    }
    367    
     368
    368369    // TODO rework to be a SegmentGui (with getModel())
    369370    private final class Segment {
    370371        final Point2D to;
    371372        final Point2D from;
    372        
     373
    373374        final Segment prev;
    374375        final Segment next;
    375        
     376
    376377        final double length;
    377378        final double angle;
    378        
    379         public Segment(Segment next, List<Point2D> bends, JunctionGui a) {
     379
     380        Segment(Segment next, List<Point2D> bends, JunctionGui a) {
    380381            final Point2D head = (Point2D) bends.get(0).clone();
    381382            final List<Point2D> tail = bends.subList(1, bends.size());
    382            
     383
    383384            this.next = next;
    384385            this.to = head;
     
    387388            this.length = from.distance(to);
    388389            this.angle = angle(from, to);
    389            
     390
    390391            // TODO create a factory method for the segments list and pass it to
    391392            // the constructor(s)
    392393            segments.add(this);
    393394        }
    394        
    395         public Segment(JunctionGui b, List<Point2D> bends, JunctionGui a) {
     395
     396        Segment(JunctionGui b, List<Point2D> bends, JunctionGui a) {
    396397            this((Segment) null, prepended(bends, (Point2D) b.getPoint().clone()), a);
    397398        }
    398        
     399
    399400        private double getFromOffset() {
    400401            return prev == null ? 0 : prev.getFromOffset() + prev.length;
    401402        }
    402        
     403
    403404        public double getOffset(double x, double y) {
    404405            return getOffsetInternal(new Point2D.Double(x, y), -1, Double.POSITIVE_INFINITY);
    405406        }
    406        
     407
    407408        private double getOffsetInternal(Point2D p, double offset, double quality) {
    408409            final Point2D closest = closest(new Line2D.Double(from, to), p);
    409410            final double myQuality = closest.distance(p);
    410            
     411
    411412            if (myQuality < quality) {
    412413                quality = myQuality;
    413                
     414
    414415                final Line2D normal = line(p, angle + PI / 2);
    415416                final Point2D isect = intersection(normal, new Line2D.Double(from, to));
    416417                final double d = from.distance(isect);
    417418                final boolean negative = Math.abs(angle(from, isect) - angle) > 1;
    418                
     419
    419420                offset = getFromOffset() + (negative ? -1 : 1) * d;
    420421            }
    421            
     422
    422423            return next == null ? offset : next.getOffsetInternal(p, offset, quality);
    423424        }
    424        
     425
    425426        public Path append(Path path, boolean forward, double offset) {
    426427            if (ROUND_CORNERS) {
     
    428429                final Point2D s = forward ? to : from;
    429430                final Point2D e = forward ? from : to;
    430                
     431
    431432                if (n == null) {
    432433                    return path.lineTo(e.getX(), e.getY(), length - offset);
    433434                }
    434                
     435
    435436                final double a = minAngleDiff(angle, n.angle);
    436437                final double d = 3 * outerMargin + getWidth(getModel().getToEnd(), (forward && a < 0) || (!forward && a > 0));
    437438                final double l = d * tan(abs(a));
    438                
     439
    439440                if (length - offset < l / 2 || n.length < l / 2) {
    440441                    return n.append(path.lineTo(e.getX(), e.getY(), length - offset), forward, 0);
    441442                } else {
    442443                    final Point2D p = relativePoint(e, l / 2, angle(e, s));
    443                    
     444
    444445                    final Path line = path.lineTo(p.getX(), p.getY(), length - l / 2 - offset);
    445446                    final Path curve = line.curveTo(d, d, a, l);
    446                    
     447
    447448                    return n.append(curve, forward, l / 2);
    448449                }
     
    456457        }
    457458    }
    458    
     459
    459460    /**
    460461     * This should become a setting, but rounding is (as of yet) still slightly buggy and a low
     
    462463     */
    463464    private static final boolean ROUND_CORNERS = false;
    464    
    465     private static final List<Point2D> prepended(List<Point2D> bends, Point2D point) {
     465
     466    private static List<Point2D> prepended(List<Point2D> bends, Point2D point) {
    466467        final List<Point2D> result = new ArrayList<>(bends.size() + 1);
    467468        result.add(point);
     
    469470        return result;
    470471    }
    471    
     472
    472473    private final GuiContainer container;
    473474    private final double innerMargin;
    474475    private final double outerMargin;
    475    
     476
    476477    private final float lineWidth;
    477478    private final Stroke regularStroke;
    478479    private final Stroke dashedStroke;
    479    
     480
    480481    private final JunctionGui a;
    481482    private final JunctionGui b;
    482483    private final double length;
    483    
     484
    484485    private final IncomingConnector incomingA;
    485486    private final IncomingConnector incomingB;
    486    
     487
    487488    private final Road road;
    488489    private final List<Segment> segments = new ArrayList<>();
    489    
     490
    490491    final double connectorRadius;
    491    
    492     public RoadGui(GuiContainer container, Road road) {
     492
     493    RoadGui(GuiContainer container, Road road) {
    493494        this.container = container;
    494        
     495
    495496        this.road = road;
    496        
     497
    497498        this.a = container.getGui(road.getFromEnd().getJunction());
    498499        this.b = container.getGui(road.getToEnd().getJunction());
    499        
     500
    500501        this.incomingA = new IncomingConnector(road.getFromEnd());
    501502        this.incomingB = new IncomingConnector(road.getToEnd());
    502        
     503
    503504        final List<Point2D> bends = new ArrayList<>();
    504505        final List<Node> nodes = road.getRoute().getNodes();
     
    506507            bends.add(container.translateAndScale(loc(nodes.get(i))));
    507508        }
    508        
     509
    509510        // they add themselves to this.segments
    510511        new Segment(b, bends, a);
     
    514515        }
    515516        this.length = l;
    516        
     517
    517518        this.innerMargin = !incomingA.getLanes().isEmpty() && !incomingB.getLanes().isEmpty() ? 1 * container
    518519            .getLaneWidth() / 15 : 0;
     
    525526        }, 0);
    526527    }
    527    
     528
    528529    public JunctionGui getA() {
    529530        return a;
    530531    }
    531    
     532
    532533    public JunctionGui getB() {
    533534        return b;
    534535    }
    535    
     536
    536537    public Line2D getLeftCurb(Road.End end) {
    537538        return GuiUtil.line(getCorner(end, true), getAngle(end) + PI);
    538539    }
    539    
     540
    540541    public Line2D getRightCurb(Road.End end) {
    541542        return GuiUtil.line(getCorner(end, false), getAngle(end) + PI);
    542543    }
    543    
     544
    544545    private Point2D getLeftCorner(Road.End end) {
    545546        return getCorner(end, true);
    546547    }
    547    
     548
    548549    private Point2D getRightCorner(Road.End end) {
    549550        return getCorner(end, false);
    550551    }
    551    
     552
    552553    private Point2D getCorner(Road.End end, boolean left) {
    553554        final JunctionGui j = end.isFromEnd() ? a : b;
     
    556557        final double a = getAngle(end) + PI;
    557558        final double t = left ? j.getLeftTrim(end) : j.getRightTrim(end);
    558        
     559
    559560        final double dx = s * cos(PI / 2 - a) * w + cos(a) * t;
    560561        final double dy = s * sin(PI / 2 - a) * w - sin(a) * t;
    561        
     562
    562563        return new Point2D.Double(j.x + dx, j.y + dy);
    563564    }
    564    
     565
    565566    private double getWidth(Road.End end, boolean left) {
    566567        if (!end.getRoad().equals(road)) {
    567568            throw new IllegalArgumentException();
    568569        }
    569        
     570
    570571        final int lcForward = incomingA.getLanes().size();
    571572        final int lcBackward = incomingB.getLanes().size();
    572        
     573
    573574        final double LW = getContainer().getLaneWidth();
    574575        final double M = innerMargin + outerMargin;
    575        
     576
    576577        if (end.isToEnd()) {
    577578            return (left ? lcBackward : lcForward) * LW + M;
     
    580581        }
    581582    }
    582    
     583
    583584    List<InteractiveElement> paint(Graphics2D g2d) {
    584585        final List<InteractiveElement> result = new ArrayList<>();
    585        
     586
    586587        result.addAll(paintLanes(g2d));
    587        
     588
    588589        if (getModel().isPrimary()) {
    589590            result.add(new ViaConnector(getModel().getFromEnd()));
     
    594595            result.addAll(extenders(getModel().getToEnd()));
    595596        }
    596        
     597
    597598        g2d.setColor(Color.RED);
    598599        for (Segment s : segments) {
    599600            g2d.fill(new Ellipse2D.Double(s.from.getX() - 1, s.from.getY() - 1, 2, 2));
    600601        }
    601        
     602
    602603        return result;
    603604    }
    604    
     605
    605606    private List<LaneAdder> laneAdders() {
    606607        final List<LaneAdder> result = new ArrayList<>(4);
    607        
     608
    608609        if (!incomingA.getLanes().isEmpty()) {
    609610            result.add(new LaneAdder(getModel().getToEnd(), Lane.Kind.EXTRA_LEFT));
    610611            result.add(new LaneAdder(getModel().getToEnd(), Lane.Kind.EXTRA_RIGHT));
    611612        }
    612        
     613
    613614        if (!incomingB.getLanes().isEmpty()) {
    614615            result.add(new LaneAdder(getModel().getFromEnd(), Lane.Kind.EXTRA_LEFT));
    615616            result.add(new LaneAdder(getModel().getFromEnd(), Lane.Kind.EXTRA_RIGHT));
    616617        }
    617        
     618
    618619        return result;
    619620    }
    620    
     621
    621622    private List<Extender> extenders(Road.End end) {
    622623        if (!end.isExtendable()) {
    623624            return Collections.emptyList();
    624625        }
    625        
     626
    626627        final List<Extender> result = new ArrayList<>();
    627        
     628
    628629        final Node n = end.getJunction().getNode();
    629630        for (Way w : OsmPrimitive.getFilteredList(n.getReferrers(), Way.class)) {
     
    634635            }
    635636        }
    636        
     637
    637638        return result;
    638639    }
    639    
     640
    640641    public Road getModel() {
    641642        return road;
    642643    }
    643    
     644
    644645    public IncomingConnector getConnector(Road.End end) {
    645646        return end.isFromEnd() ? incomingA : incomingB;
    646647    }
    647    
     648
    648649    private List<InteractiveElement> paintLanes(Graphics2D g2d) {
    649650        final Path2D middleLines = new Path2D.Double();
    650        
     651
    651652        g2d.setStroke(regularStroke);
    652        
     653
    653654        final boolean forward = !incomingA.getLanes().isEmpty();
    654655        final boolean backward = !incomingB.getLanes().isEmpty();
    655        
     656
    656657        final Path2D middleArea;
    657658        if (forward && backward) {
    658659            paintLanes(g2d, middleLines, true);
    659660            paintLanes(g2d, middleLines, false);
    660            
     661
    661662            middleLines.closePath();
    662663            middleArea = middleLines;
     
    664665        } else if (forward || backward) {
    665666            paintLanes(g2d, middleLines, forward);
    666            
     667
    667668            middleArea = new Path2D.Double();
    668669            middleArea.append(middleLines.getPathIterator(null), false);
     
    673674            throw new AssertionError();
    674675        }
    675        
     676
    676677        g2d.fill(middleArea);
    677678        g2d.setColor(Color.WHITE);
    678679        g2d.draw(middleLines);
    679        
     680
    680681        final List<InteractiveElement> result = new ArrayList<>();
    681        
     682
    682683        moveIncoming(getModel().getFromEnd());
    683684        moveIncoming(getModel().getToEnd());
    684685        result.add(incomingA);
    685686        result.add(incomingB);
    686        
     687
    687688        for (IncomingConnector c : Arrays.asList(incomingA, incomingB)) {
    688689            int offset = 0;
    689690            for (LaneGui l : c.getLanes()) {
    690691                moveOutgoing(l, offset++);
    691                
     692
    692693                result.add(l.outgoing);
    693694                if (l.getModel().isExtra()) {
     
    696697            }
    697698        }
    698        
     699
    699700        return result;
    700701    }
    701    
     702
    702703    private void paintLanes(Graphics2D g2d, Path2D middleLines, boolean forward) {
    703704        final Shape clip = clip();
    704705        g2d.clip(clip);
    705        
     706
    706707        final Path middle = middlePath(forward);
    707        
     708
    708709        Path innerPath = middle.offset(innerMargin, -1, -1, innerMargin);
    709710        final List<Path> linePaths = new ArrayList<>();
    710711        linePaths.add(innerPath);
    711        
     712
    712713        for (LaneGui l : forward ? incomingA.getLanes() : incomingB.getLanes()) {
    713714            l.setClip(clip);
     
    715716            linePaths.add(innerPath);
    716717        }
    717        
     718
    718719        final Path2D area = new Path2D.Double();
    719720        area(area, middle, innerPath.offset(outerMargin, -1, -1, outerMargin));
    720721        g2d.setColor(Color.GRAY);
    721722        g2d.fill(area);
    722        
     723
    723724        g2d.setColor(Color.WHITE);
    724725        final Path2D lines = new Path2D.Double();
    725726        lines.append(innerPath.getIterator(), false);
    726727        g2d.draw(lines);
    727        
     728
    728729        // g2d.setColor(new Color(32, 128, 192));
    729730        g2d.setColor(Color.WHITE);
     
    735736        }
    736737        g2d.setStroke(regularStroke);
    737        
     738
    738739        // g2d.setColor(new Color(32, 128, 192));
    739740        // lines.reset();
    740741        // lines.append(middle.getIterator(), false);
    741742        // g2d.draw(lines);
    742        
     743
    743744        g2d.setClip(null);
    744745    }
    745    
     746
    746747    private Shape clip() {
    747748        final Area clip = new Area(new Rectangle2D.Double(-100000, -100000, 200000, 200000));
    748749        clip.subtract(new Area(negativeClip(true)));
    749750        clip.subtract(new Area(negativeClip(false)));
    750        
     751
    751752        return clip;
    752753    }
    753    
     754
    754755    private Shape negativeClip(boolean forward) {
    755756        final Road.End end = forward ? getModel().getToEnd() : getModel().getFromEnd();
    756757        final JunctionGui j = forward ? b : a;
    757        
     758
    758759        final Line2D lc = getLeftCurb(end);
    759760        final Line2D rc = getRightCurb(end);
    760        
     761
    761762        final Path2D negativeClip = new Path2D.Double();
    762        
     763
    763764        final double d = rc.getP1().distance(j.getPoint()) + lc.getP1().distance(j.getPoint());
    764        
     765
    765766        final double cm = 0.01 / getContainer().getMpp(); // 1 centimeter
    766767        final double rca = angle(rc) + PI;
     
    770771        final Point2D l1 = relativePoint(relativePoint(lc.getP1(), 1, angle(rc.getP1(), lc.getP1())), cm, lca);
    771772        final Point2D l2 = relativePoint(l1, d, lca);
    772        
     773
    773774        negativeClip.moveTo(r1.getX(), r1.getY());
    774775        negativeClip.lineTo(r2.getX(), r2.getY());
     
    776777        negativeClip.lineTo(l1.getX(), l1.getY());
    777778        negativeClip.closePath();
    778        
     779
    779780        return negativeClip;
    780781    }
    781    
     782
    782783    public Path getLaneMiddle(boolean forward) {
    783784        final Path mid = middlePath(!forward);
    784785        final double w = getWidth(forward ? getModel().getFromEnd() : getModel().getToEnd(), true);
    785786        final double o = (w - outerMargin) / 2;
    786        
     787
    787788        return o > 0 ? mid.offset(-o, -1, -1, -o) : mid;
    788789    }
    789    
     790
    790791    private Path middlePath(boolean forward) {
    791792        final Path path = forward ? Path.create(b.x, b.y) : Path.create(a.x, a.y);
    792793        final Segment first = forward ? segments.get(segments.size() - 1) : segments.get(0);
    793        
     794
    794795        return first.append(path, forward, 0);
    795796    }
    796    
     797
    797798    private void moveIncoming(Road.End end) {
    798799        final Point2D lc = getLeftCorner(end);
    799800        final Point2D rc = getRightCorner(end);
    800801        final Line2D cornerLine = new Line2D.Double(lc, rc);
    801        
     802
    802803        final double a = getAngle(end);
    803804        final Line2D roadLine = line(getContainer().getGui(end.getJunction()).getPoint(), a);
    804        
     805
    805806        final Point2D i = intersection(roadLine, cornerLine);
    806807        // TODO fix depending on angle(i, lc)
    807808        final double offset = innerMargin + (getWidth(end, true) - innerMargin - outerMargin) / 2;
    808809        final Point2D loc = relativePoint(i, offset, angle(i, lc));
    809        
     810
    810811        getConnector(end).move(loc.getX(), loc.getY());
    811812    }
    812    
     813
    813814    private void moveOutgoing(LaneGui lane, int offset) {
    814815        final Road.End end = lane.getModel().getOutgoingRoadEnd();
    815        
     816
    816817        final Point2D lc = getLeftCorner(end);
    817818        final Point2D rc = getRightCorner(end);
    818819        final Line2D cornerLine = new Line2D.Double(lc, rc);
    819        
     820
    820821        final double a = getAngle(end);
    821822        final Line2D roadLine = line(getContainer().getGui(end.getJunction()).getPoint(), a);
    822        
     823
    823824        final Point2D i = intersection(roadLine, cornerLine);
    824825        // TODO fix depending on angle(i, rc)
    825826        final double d = innerMargin + (2 * offset + 1) * getContainer().getLaneWidth() / 2;
    826827        final Point2D loc = relativePoint(i, d, angle(i, rc));
    827        
     828
    828829        lane.outgoing.move(loc.getX(), loc.getY());
    829830    }
    830    
     831
    831832    public JunctionGui getJunction(Road.End end) {
    832833        if (!getModel().equals(end.getRoad())) {
    833834            throw new IllegalArgumentException();
    834835        }
    835        
     836
    836837        return end.isFromEnd() ? getA() : getB();
    837838    }
    838    
     839
    839840    public double getAngle(Road.End end) {
    840841        if (!getModel().equals(end.getRoad())) {
    841842            throw new IllegalArgumentException();
    842843        }
    843        
     844
    844845        if (end.isToEnd()) {
    845846            return segments.get(segments.size() - 1).angle;
     
    849850        }
    850851    }
    851    
     852
    852853    public double getWidth(Road.End end) {
    853854        return getWidth(end, true) + getWidth(end, false);
    854855    }
    855    
     856
    856857    public double getLength() {
    857858        return length;
    858859    }
    859    
     860
    860861    public double getOffset(double x, double y) {
    861862        return segments.get(0).getOffset(x, y);
    862863    }
    863    
     864
    864865    public GuiContainer getContainer() {
    865866        return container;
    866867    }
    867    
     868
    868869    public List<LaneGui> getLanes() {
    869870        final List<LaneGui> result = new ArrayList<>();
    870        
     871
    871872        result.addAll(incomingB.getLanes());
    872873        result.addAll(incomingA.getLanes());
    873        
     874
    874875        return Collections.unmodifiableList(result);
    875876    }
    876    
     877
    877878    public List<LaneGui> getLanes(Road.End end) {
    878879        return getConnector(end.getOppositeEnd()).getLanes();
  • applications/editors/josm/plugins/turnlanes/src/org/openstreetmap/josm/plugins/turnlanes/gui/State.java

    r30737 r33085  
     1// License: GPL. For details, see LICENSE file.
    12package org.openstreetmap.josm.plugins.turnlanes.gui;
    23
     
    1415    static class AllTurns extends State {
    1516        private final State wrapped;
    16        
    17         public AllTurns(State wrapped) {
     17
     18        AllTurns(State wrapped) {
    1819            this.wrapped = wrapped;
    1920        }
    20        
     21
    2122        public State unwrap() {
    2223            return wrapped;
    2324        }
    24        
     25
    2526        @Override
    2627        State carryOver(GuiContainer newContainer) {
     
    2829        }
    2930    }
    30    
     31
    3132    static class Connecting extends State {
    3233        private final Lane lane;
    3334        private final List<RoadGui.ViaConnector> vias;
    34        
    35         public Connecting(Lane lane) {
    36             this(lane, Collections.<RoadGui.ViaConnector> emptyList());
    37         }
    38        
    39         public Connecting(Lane lane, List<ViaConnector> vias) {
     35
     36        Connecting(Lane lane) {
     37            this(lane, Collections.<RoadGui.ViaConnector>emptyList());
     38        }
     39
     40        Connecting(Lane lane, List<ViaConnector> vias) {
    4041            this.lane = lane;
    4142            this.vias = vias;
    4243        }
    43        
     44
    4445        public Connecting next(RoadGui.ViaConnector via) {
    4546            if (vias.isEmpty()) {
    4647                return new Connecting(lane, Collections.unmodifiableList(Arrays.asList(via)));
    4748            }
    48            
     49
    4950            final List<RoadGui.ViaConnector> tmp = new ArrayList<>(vias.size() + 1);
    5051            final boolean even = (vias.size() & 1) == 0;
    5152            final RoadGui.ViaConnector last = vias.get(vias.size() - 1);
    52            
     53
    5354            if (last.equals(via) || !even && last.getRoadEnd().getJunction().equals(via.getRoadEnd().getJunction())) {
    5455                return pop().next(via);
    5556            }
    56            
     57
    5758            if (vias.size() >= 2) {
    5859                if (lane.getOutgoingJunction().equals(via.getRoadEnd().getJunction())) {
     
    6263                }
    6364            }
    64            
     65
    6566            for (RoadGui.ViaConnector v : vias) {
    6667                tmp.add(v);
    67                
     68
    6869                if (!(even && v.equals(last)) && v.getRoadEnd().getJunction().equals(via.getRoadEnd().getJunction())) {
    6970                    return new Connecting(lane, Collections.unmodifiableList(tmp));
    7071                }
    7172            }
    72            
     73
    7374            tmp.add(via);
    7475            return new Connecting(lane, Collections.unmodifiableList(tmp));
    7576        }
    76        
     77
    7778        public Junction getJunction() {
    7879            return vias.isEmpty() ? lane.getOutgoingJunction() : vias.get(vias.size() - 1).getRoadEnd().getJunction();
    7980        }
    80        
     81
    8182        public RoadGui.ViaConnector getBacktrackViaConnector() {
    8283            return vias.size() < 2 ? null : vias.get(vias.size() - 2);
    8384        }
    84        
     85
    8586        public List<RoadGui.ViaConnector> getViaConnectors() {
    8687            return vias;
    8788        }
    88        
     89
    8990        public Lane getLane() {
    9091            return lane;
    9192        }
    92        
     93
    9394        public Connecting pop() {
    9495            return new Connecting(lane, vias.subList(0, vias.size() - 1));
    9596        }
    9697    }
    97    
     98
    9899    static class Invalid extends State {
    99100        private final State wrapped;
    100        
    101         public Invalid(State wrapped) {
     101
     102        Invalid(State wrapped) {
    102103            this.wrapped = wrapped;
    103104        }
    104        
     105
    105106        public State unwrap() {
    106107            return wrapped;
    107108        }
    108109    }
    109    
     110
    110111    static class Dirty extends State {
    111112        private final State wrapped;
    112        
    113         public Dirty(State wrapped) {
     113
     114        Dirty(State wrapped) {
    114115            this.wrapped = wrapped;
    115116        }
    116        
     117
    117118        public State unwrap() {
    118119            return wrapped;
    119120        }
    120        
     121
    121122        @Override
    122123        State carryOver(GuiContainer newContainer) {
     
    124125        }
    125126    }
    126    
     127
    127128    static class Default extends State {
    128         public Default() {}
    129     }
    130    
     129        Default() {}
     130    }
     131
    131132    static class IncomingActive extends State {
    132133        private final Road.End roadEnd;
    133        
    134         public IncomingActive(Road.End roadEnd) {
     134
     135        IncomingActive(Road.End roadEnd) {
    135136            this.roadEnd = roadEnd;
    136137        }
    137        
     138
    138139        public Road.End getRoadEnd() {
    139140            return roadEnd;
    140141        }
    141        
     142
    142143        @Override
    143144        State carryOver(GuiContainer newContainer) {
     
    145146                return this;
    146147            }
    147            
     148
    148149            final Junction newJunction = newContainer.getModel().getJunction(roadEnd.getJunction().getNode());
    149            
     150
    150151            for (Road.End e : newJunction.getRoadEnds()) {
    151152                if (e.isToEnd() && e.getWay().equals(roadEnd.getWay())) {
     
    153154                }
    154155            }
    155            
     156
    156157            return new Default();
    157158        }
    158159    }
    159    
     160
    160161    static class OutgoingActive extends State {
    161162        private final LaneGui lane;
    162        
    163         public OutgoingActive(LaneGui lane) {
     163
     164        OutgoingActive(LaneGui lane) {
    164165            this.lane = lane;
    165166        }
    166        
     167
    167168        public LaneGui getLane() {
    168169            return lane;
    169170        }
    170        
     171
    171172        @Override
    172173        State delete() {
     
    174175                return this;
    175176            }
    176            
     177
    177178            lane.getModel().remove();
    178            
     179
    179180            return new Invalid(this);
    180181        }
    181        
     182
    182183        @Override
    183184        State carryOver(GuiContainer newContainer) {
     
    185186                return this;
    186187            }
    187            
     188
    188189            final Lane model = lane.getModel();
    189190            final Junction newJunction = newContainer.getModel().getJunction(model.getOutgoingJunction().getNode());
    190            
     191
    191192            for (Road.End e : newJunction.getRoadEnds()) {
    192193                if (e.isToEnd() && e.getWay().equals(model.getOutgoingRoadEnd().getWay())) {
     
    196197                        }
    197198                    }
    198                    
     199
    199200                    break;
    200201                }
    201202            }
    202            
     203
    203204            return new Default();
    204205        }
    205206    }
    206    
     207
    207208    State delete() {
    208209        return this;
    209210    }
    210    
     211
    211212    State carryOver(GuiContainer newContainer) {
    212213        return this;
  • applications/editors/josm/plugins/turnlanes/src/org/openstreetmap/josm/plugins/turnlanes/gui/TurnLanesDialog.java

    r32458 r33085  
     1// License: GPL. For details, see LICENSE file.
    12package org.openstreetmap.josm.plugins.turnlanes.gui;
    23
     
    4243    private class EditAction extends JosmAction {
    4344        private static final long serialVersionUID = 4114119073563457706L;
    44        
    45         public EditAction() {
     45
     46        EditAction() {
    4647            super(tr("Edit"), "dialogs/edit", tr("Edit turn relations and lane lengths for selected node."), null,
    4748                    false);
    4849        }
    49        
     50
    5051        @Override
    5152        public void actionPerformed(ActionEvent e) {
     
    5758        }
    5859    }
    59    
     60
    6061    private class ValidateAction extends JosmAction {
    6162        private static final long serialVersionUID = 7510740945725851427L;
    62        
    63         public ValidateAction() {
     63
     64        ValidateAction() {
    6465            super(tr("Validate"), "dialogs/validator", tr("Validate turn- and lane-length-relations for consistency."),
    6566                    null, false);
    6667        }
    67        
     68
    6869        @Override
    6970        public void actionPerformed(ActionEvent e) {
     
    7475        }
    7576    }
    76    
     77
    7778    private final DataSetListener dataSetListener = new DataSetListener() {
    7879        @Override
     
    8081            refresh();
    8182        }
    82        
     83
    8384        @Override
    8485        public void tagsChanged(TagsChangedEvent event) {
    8586            refresh();
    86            
    87         }
    88        
     87
     88        }
     89
    8990        @Override
    9091        public void relationMembersChanged(RelationMembersChangedEvent event) {
    9192            refresh();
    9293        }
    93        
     94
    9495        @Override
    9596        public void primitivesRemoved(PrimitivesRemovedEvent event) {
    9697            refresh();
    9798        }
    98        
     99
    99100        @Override
    100101        public void primitivesAdded(PrimitivesAddedEvent event) {
    101102            refresh();
    102103        }
    103        
     104
    104105        @Override
    105106        public void otherDatasetChange(AbstractDatasetChangedEvent event) {
    106107            refresh();
    107108        }
    108        
     109
    109110        @Override
    110111        public void nodeMoved(NodeMovedEvent event) {
    111112            refresh();
    112113        }
    113        
     114
    114115        @Override
    115116        public void dataChanged(DataChangedEvent event) {
    116117            refresh();
    117118        }
    118        
     119
    119120        private void refresh() {
    120121            if (editing) {
     
    123124        }
    124125    };
    125    
     126
    126127    private final JosmAction editAction = new EditAction();
    127128    private final JosmAction validateAction = new ValidateAction();
    128    
     129
    129130    private static final long serialVersionUID = -1998375221636611358L;
    130    
     131
    131132    private static final String CARD_EDIT = "EDIT";
    132133    private static final String CARD_VALIDATE = "VALIDATE";
    133    
     134
    134135    private final JPanel body = new JPanel();
    135136    private final JunctionPane junctionPane = new JunctionPane(GuiContainer.empty());
    136    
     137
    137138    private final JToggleButton editButton = new JToggleButton(editAction);
    138139    private final JToggleButton validateButton = new JToggleButton(validateAction);
    139    
     140
    140141    private final Set<OsmPrimitive> selected = new HashSet<>();
    141    
     142
    142143    private boolean editing = true;
    143144    private boolean wasShowing = false;
    144    
     145
    145146    public TurnLanesDialog() {
    146147        super(tr("Turn Lanes"), "turnlanes.png", tr("Edit turn lanes"), null, 200);
    147        
     148
    148149        Main.getLayerManager().addActiveLayerChangeListener(this);
    149150        DataSet.addSelectionListener(this);
    150        
     151
    151152        final JPanel buttonPanel = new JPanel(new GridLayout(1, 2, 4, 4));
    152153        final ButtonGroup group = new ButtonGroup();
     
    155156        buttonPanel.add(editButton);
    156157        buttonPanel.add(validateButton);
    157        
     158
    158159        body.setLayout(new CardLayout(4, 4));
    159        
     160
    160161        add(buttonPanel, BorderLayout.SOUTH);
    161162        add(body, BorderLayout.CENTER);
    162        
     163
    163164        body.add(junctionPane, CARD_EDIT);
    164165        body.add(new ValidationPanel(), CARD_VALIDATE);
    165        
     166
    166167        editButton.doClick();
    167168    }
    168    
     169
    169170    @Override
    170171    protected void stateChanged() {
     
    174175        wasShowing = isShowing;
    175176    }
    176    
     177
    177178    void refresh() {
    178179        if (isShowing && editing) {
     
    180181            final List<Node> nodes = OsmPrimitive.getFilteredList(s, Node.class);
    181182            final List<Way> ways = OsmPrimitive.getFilteredList(s, Way.class);
    182            
     183
    183184            final ModelContainer mc = nodes.isEmpty() ? ModelContainer.empty() : ModelContainer
    184185                    .createEmpty(nodes, ways);
    185            
     186
    186187            junctionPane.setJunction(new GuiContainer(mc));
    187188        }
  • applications/editors/josm/plugins/turnlanes/src/org/openstreetmap/josm/plugins/turnlanes/gui/ValidationPanel.java

    r32458 r33085  
     1// License: GPL. For details, see LICENSE file.
    12package org.openstreetmap.josm.plugins.turnlanes.gui;
    23
     
    2627class ValidationPanel extends JPanel {
    2728    private static final long serialVersionUID = -1585778734201458665L;
    28    
     29
    2930    private static final String[] COLUMN_NAMES = {
    3031        tr("Description"), tr("Type"), tr("Quick-Fix")
    3132    };
    32    
     33
    3334    private final Action refreshAction = new JosmAction(tr("Refresh"), "dialogs/refresh",
    3435        tr("Revalidate all turnlanes-relations."), null, false) {
    3536        private static final long serialVersionUID = -8110599654128234810L;
    36        
     37
    3738        @Override
    3839        public void actionPerformed(ActionEvent e) {
     
    4041        }
    4142    };
    42    
     43
    4344    private final Action fixAction = new JosmAction(tr("Fix"), "dialogs/fix", tr("Automatically fixes the issue."), null,
    4445        false) {
    4546        private static final long serialVersionUID = -8110599654128234810L;
    46        
     47
    4748        @Override
    4849        public void actionPerformed(ActionEvent e) {
     
    5455        }
    5556    };
    56    
     57
    5758    private final Action selectAction = new JosmAction(tr("Select"), "dialogs/select",
    5859        tr("Selects the offending relation."), null, false) {
    5960        private static final long serialVersionUID = -8110599654128234810L;
    60        
     61
    6162        @Override
    6263        public void actionPerformed(ActionEvent e) {
     
    6869        }
    6970    };
    70    
     71
    7172    private final SideButton refreshButton = new SideButton(refreshAction);
    7273    private final SideButton fixButton = new SideButton(fixAction);
    7374    private final SideButton selectButton = new SideButton(selectAction);
    74    
     75
    7576    private final DefaultTableModel issueModel = new DefaultTableModel(COLUMN_NAMES, 0);
    7677    private final List<Issue> issues = new ArrayList<>();
    7778    private final JTable issueTable = new JTable(issueModel) {
    7879        private static final long serialVersionUID = 6323348290180585298L;
    79        
     80
     81        @Override
    8082        public boolean isCellEditable(int row, int column) {
    8183            return false;
    82         };
     84        }
    8385    };
    84    
     86
    8587    private Issue selected;
    86    
    87     public ValidationPanel() {
     88
     89    ValidationPanel() {
    8890        super(new BorderLayout(4, 4));
    89        
     91
    9092        final JPanel buttonPanel = new JPanel(new GridLayout(1, 3, 4, 4));
    91        
     93
    9294        buttonPanel.add(refreshButton);
    9395        buttonPanel.add(fixButton);
    9496        buttonPanel.add(selectButton);
    95        
     97
    9698        add(buttonPanel, BorderLayout.NORTH);
    9799        add(new JScrollPane(issueTable), BorderLayout.CENTER);
    98        
     100
    99101        issueTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    100102        issueTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
     
    103105                final int i = issueTable.getSelectedRow();
    104106                final Issue issue = i >= 0 ? issues.get(i) : null;
    105                
     107
    106108                setSelected(issue);
    107109            }
    108110        });
    109        
     111
    110112        setSelected(null);
    111113    }
    112    
     114
    113115    private void setIssues(List<Issue> issues) {
    114116        issueModel.setRowCount(0);
    115117        this.issues.clear();
    116        
     118
    117119        for (Issue i : issues) {
    118120            final String[] row = {
     
    125127        }
    126128    }
    127    
     129
    128130    private void setSelected(Issue selected) {
    129131        this.selected = selected;
    130        
     132
    131133        if (selected == null) {
    132134            fixButton.setEnabled(false);
  • applications/editors/josm/plugins/turnlanes/src/org/openstreetmap/josm/plugins/turnlanes/model/Constants.java

    r26154 r33085  
     1// License: GPL. For details, see LICENSE file.
    12package org.openstreetmap.josm.plugins.turnlanes.model;
    23
     
    78    String SPLIT_REGEX = "\\p{Zs}*[,:;]\\p{Zs}*";
    89    Pattern SPLIT_PATTERN = Pattern.compile(SPLIT_REGEX);
    9    
     10
    1011    String TYPE_LENGTHS = "turnlanes:lengths";
    11    
     12
    1213    String LENGTHS_KEY_LENGTHS_LEFT = "lengths:left";
    1314    String LENGTHS_KEY_LENGTHS_RIGHT = "lengths:right";
    14    
     15
    1516    String TYPE_TURNS = "turnlanes:turns";
    16    
     17
    1718    String TURN_ROLE_VIA = "via";
    1819    String TURN_ROLE_FROM = "from";
    1920    String TURN_ROLE_TO = "to";
    20    
     21
    2122    String TURN_KEY_LANES = "lanes";
    2223    String TURN_KEY_EXTRA_LANES = "lanes:extra";
    2324    String LENGTHS_ROLE_END = "end";
    2425    String LENGTHS_ROLE_WAYS = "ways";
    25    
     26
    2627}
  • applications/editors/josm/plugins/turnlanes/src/org/openstreetmap/josm/plugins/turnlanes/model/GenericCommand.java

    r30737 r33085  
     1// License: GPL. For details, see LICENSE file.
    12package org.openstreetmap.josm.plugins.turnlanes.model;
    23
     
    1718        final PrimitiveData before;
    1819        final AbstractPrimitive after;
    19        
    20         public BeforeAfter(PrimitiveData before, AbstractPrimitive after) {
     20
     21        BeforeAfter(PrimitiveData before, AbstractPrimitive after) {
    2122            this.before = before;
    2223            this.after = after;
    2324        }
    24        
     25
    2526        public OsmPrimitive afterPrimitive() {
    2627            return (OsmPrimitive) after;
    2728        }
    28        
     29
    2930        public PrimitiveData afterData() {
    3031            return (PrimitiveData) after;
    3132        }
    3233    }
    33    
     34
    3435    private final DataSet dataSet;
    3536    private final String description;
    3637    private final Map<OsmPrimitive, BeforeAfter> beforeAfters = new HashMap<>();
    37    
     38
    3839    public GenericCommand(DataSet dataSet, String description) {
    3940        this.dataSet = dataSet;
    4041        this.description = description;
    4142    }
    42    
     43
    4344    void add(OsmPrimitive p) {
    4445        beforeAfters.put(p, new BeforeAfter(null, p));
    4546    }
    46    
     47
    4748    AbstractPrimitive backup(OsmPrimitive p) {
    4849        final BeforeAfter ba = beforeAfters.get(p);
    49        
     50
    5051        if (ba == null) {
    5152            final BeforeAfter newBa = new BeforeAfter(p.save(), p.save());
     
    5657        }
    5758    }
    58    
     59
    5960    @Override
    6061    public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted,
    6162            Collection<OsmPrimitive> added) {}
    62    
     63
    6364    @Override
    6465    public String getDescriptionText() {
    6566        return description;
    6667    }
    67    
     68
    6869    @Override
    6970    public boolean executeCommand() {
     
    7778        return true;
    7879    }
    79    
     80
    8081    @Override
    8182    public void undoCommand() {
     
    8889        }
    8990    }
    90    
     91
    9192    @Override
    9293    public PrimitiveData getOrig(OsmPrimitive osm) {
    9394        return beforeAfters.get(osm).before;
    9495    }
    95    
     96
    9697    @Override
    9798    public Collection<? extends OsmPrimitive> getParticipatingPrimitives() {
  • applications/editors/josm/plugins/turnlanes/src/org/openstreetmap/josm/plugins/turnlanes/model/Issue.java

    r30737 r33085  
     1// License: GPL. For details, see LICENSE file.
    12package org.openstreetmap.josm.plugins.turnlanes.model;
    23
     
    1112import org.openstreetmap.josm.data.osm.Relation;
    1213
    13 public class Issue {
     14public final class Issue {
    1415    public enum Severity {
    1516        INFO,
     
    1718        ERROR;
    1819    }
    19    
    20     public static abstract class QuickFix {
     20
     21    public abstract static class QuickFix {
    2122        public static final QuickFix NONE = new QuickFix(tr("None")) {
    22            
     23
    2324            @Override
    2425            public boolean perform() {
     
    2627            }
    2728        };
    28        
     29
    2930        private final String description;
    30        
     31
    3132        public QuickFix(String description) {
    3233            this.description = description;
    3334        }
    34        
     35
    3536        public String getDescription() {
    3637            return description;
    3738        }
    38        
     39
    3940        public abstract boolean perform();
    4041    }
    41    
     42
    4243    private final Severity severity;
    4344    private final Relation relation;
     
    4546    private final String description;
    4647    private final QuickFix quickFix;
    47    
     48
    4849    private Issue(Severity severity, Relation relation, List<? extends OsmPrimitive> primitives, String description,
    4950        QuickFix quickFix) {
     
    5455        this.quickFix = quickFix;
    5556    }
    56    
     57
    5758    public static Issue newError(Relation relation, List<? extends OsmPrimitive> primitives, String description,
    5859        QuickFix quickFix) {
    5960        return new Issue(Severity.ERROR, relation, primitives, description, quickFix);
    6061    }
    61    
     62
    6263    public static Issue newError(Relation relation, List<? extends OsmPrimitive> primitives, String description) {
    6364        return newError(relation, primitives, description, QuickFix.NONE);
    6465    }
    65    
     66
    6667    public static Issue newError(Relation relation, OsmPrimitive primitive, String description) {
    6768        return newError(relation, Arrays.asList(primitive), description, QuickFix.NONE);
    6869    }
    69    
     70
    7071    public static Issue newError(Relation relation, String description) {
    71         return newError(relation, Collections.<OsmPrimitive> emptyList(), description, QuickFix.NONE);
     72        return newError(relation, Collections.<OsmPrimitive>emptyList(), description, QuickFix.NONE);
    7273    }
    73    
     74
    7475    public static Issue newWarning(List<OsmPrimitive> primitives, String description) {
    7576        return new Issue(Severity.WARN, null, primitives, description, QuickFix.NONE);
    7677    }
    77    
     78
    7879    public Severity getSeverity() {
    7980        return severity;
    8081    }
    81    
     82
    8283    public String getDescription() {
    8384        return description;
    8485    }
    85    
     86
    8687    public Relation getRelation() {
    8788        return relation;
    8889    }
    89    
     90
    9091    public List<OsmPrimitive> getPrimitives() {
    9192        return primitives;
    9293    }
    93    
     94
    9495    public QuickFix getQuickFix() {
    9596        return quickFix;
  • applications/editors/josm/plugins/turnlanes/src/org/openstreetmap/josm/plugins/turnlanes/model/Junction.java

    r30737 r33085  
     1// License: GPL. For details, see LICENSE file.
    12package org.openstreetmap.josm.plugins.turnlanes.model;
    23
     
    1112public class Junction {
    1213    private final ModelContainer container;
    13    
     14
    1415    private final Node node;
    1516    private final Set<Way> roads = new HashSet<>();
    16    
     17
    1718    Junction(ModelContainer container, Node n) {
    1819        this.container = container;
    1920        this.node = n;
    2021    }
    21    
     22
    2223    public boolean isPrimary() {
    2324        return getContainer().isPrimary(this);
    2425    }
    25    
     26
    2627    public Node getNode() {
    2728        return node;
    2829    }
    29    
     30
    3031    public List<Road> getRoads() {
    3132        final List<Road> result = new ArrayList<>(roads.size());
    32        
     33
    3334        for (Way w : roads) {
    3435            result.add(container.getRoad(w));
    3536        }
    36        
     37
    3738        return result;
    3839    }
    39    
     40
    4041    public List<Road.End> getRoadEnds() {
    4142        final List<Road.End> result = new ArrayList<>(roads.size());
    42        
     43
    4344        for (Way w : roads) {
    4445            result.add(getRoadEnd(w));
    4546        }
    46        
     47
    4748        return result;
    4849    }
    49    
     50
    5051    void addRoad(Way w) {
    5152        roads.add(w);
    5253    }
    53    
     54
    5455    Road.End getRoadEnd(Way w) {
    5556        final Road r = getContainer().getRoad(w);
    56        
     57
    5758        if (r.getRoute().getSegments().size() == 1) {
    5859            final boolean starts = r.getRoute().getStart().equals(node);
    5960            final boolean ends = r.getRoute().getEnd().equals(node);
    60            
     61
    6162            if (starts && ends) {
    6263                throw new IllegalArgumentException("Ambiguous: The way starts and ends at the junction node.");
     
    7172            return r.getToEnd();
    7273        }
    73        
     74
    7475        throw new IllegalArgumentException("While there exists a road for the given way, the way neither "
    7576                + "starts nor ends at the junction node.");
    7677    }
    77    
     78
    7879    public ModelContainer getContainer() {
    7980        return container;
  • applications/editors/josm/plugins/turnlanes/src/org/openstreetmap/josm/plugins/turnlanes/model/Lane.java

    r30737 r33085  
     1// License: GPL. For details, see LICENSE file.
    12package org.openstreetmap.josm.plugins.turnlanes.model;
    23
     
    2021        EXTRA_RIGHT,
    2122        REGULAR;
    22        
     23
    2324        public boolean isExtra() {
    2425            return this == EXTRA_LEFT || this == EXTRA_RIGHT;
    2526        }
    2627    }
    27    
     28
    2829    static List<Lane> load(Road.End roadEnd) {
    2930        final List<Lane> result = new ArrayList<>();
    3031        int i;
    31        
     32
    3233        i = 0;
    3334        for (double l : roadEnd.getLengths(Kind.EXTRA_LEFT)) {
     
    3536        }
    3637        Collections.reverse(result);
    37        
     38
    3839        final int regulars = getRegularCount(roadEnd.getWay(), roadEnd.getJunction().getNode());
    3940        for (i = 1; i <= regulars; ++i) {
    4041            result.add(new Lane(roadEnd, i));
    4142        }
    42        
     43
    4344        i = 0;
    4445        for (double l : roadEnd.getLengths(Kind.EXTRA_RIGHT)) {
    4546            result.add(new Lane(roadEnd, ++i, Kind.EXTRA_RIGHT, l));
    4647        }
    47        
     48
    4849        return result;
    4950    }
    50    
     51
    5152    static List<Double> loadLengths(Relation r, String key, double lengthBound) {
    5253        final List<Double> result = new ArrayList<>();
    53        
     54
    5455        if (r != null && r.get(key) != null) {
    5556            for (String s : Constants.SPLIT_PATTERN.split(r.get(key))) {
     
    5758                // a unit (m))
    5859                final Double length = Double.parseDouble(s.trim());
    59                
     60
    6061                if (length >= lengthBound) {
    6162                    result.add(length);
     
    6364            }
    6465        }
    65        
     66
    6667        return result;
    6768    }
    68    
     69
    6970    static int getRegularCount(Way w, Node end) {
    7071        final int count = Utils.parseIntTag(w, "lanes");
    7172        final boolean forward = w.lastNode().equals(end);
    72        
     73
    7374        if (w.hasDirectionKeys()) {
    7475            return getRegularCountOneWay(w, forward, count);
     
    7778        }
    7879    }
    79    
     80
    8081    private static int getRegularCountOneWay(Way w, boolean forward, final int count) {
    8182        if (forward ^ "-1".equals(w.get("oneway"))) {
     
    8586        }
    8687    }
    87    
     88
    8889    private static int getRegularCountTwoWay(Way w, boolean forward, final int count) {
    8990        if (w.get("lanes:backward") != null) {
     
    9192            return forward ? count - backwardCount : backwardCount;
    9293        }
    93        
     94
    9495        if (w.get("lanes:forward") != null) {
    9596            final int forwardCount = Utils.parseIntTag(w, "lanes:forward");
    9697            return forward ? forwardCount : count - forwardCount;
    9798        }
    98        
     99
    99100        // default: round up in forward direction...
    100101        return forward ? (count + 1) / 2 : count / 2;
    101102    }
    102    
     103
    103104    private final Road.End roadEnd;
    104105    private final int index;
    105106    private final Kind kind;
    106    
     107
    107108    private Set<Turn> turns;
    108109    private double length = -1;
    109    
     110
    110111    public Lane(Road.End roadEnd, int index) {
    111112        this.roadEnd = roadEnd;
     
    113114        this.kind = Kind.REGULAR;
    114115    }
    115    
     116
    116117    public Lane(Road.End roadEnd, int index, Kind kind, double length) {
    117118        assert kind == Kind.EXTRA_LEFT || kind == Kind.EXTRA_RIGHT;
    118        
     119
    119120        this.roadEnd = roadEnd;
    120121        this.index = index;
    121122        this.kind = kind;
    122123        this.length = length;
    123        
     124
    124125        if (length <= 0) {
    125126            throw new IllegalArgumentException("Length must be positive");
    126127        }
    127128    }
    128    
     129
    129130    public Road getRoad() {
    130131        return roadEnd.getRoad();
    131132    }
    132    
     133
    133134    public Kind getKind() {
    134135        return kind;
    135136    }
    136    
     137
    137138    public double getLength() {
    138139        return isExtra() ? length : getRoad().getLength();
    139140    }
    140    
     141
    141142    public void setLength(double length) {
    142143        if (!isExtra()) {
     
    145146            throw new IllegalArgumentException("Length must positive.");
    146147        }
    147        
     148
    148149        this.length = length;
    149        
     150
    150151        // TODO if needed, increase length of other lanes
    151152        getOutgoingRoadEnd().updateLengths();
    152153    }
    153    
     154
    154155    public boolean isExtra() {
    155156        return getKind() != Kind.REGULAR;
    156157    }
    157    
     158
    158159    public int getIndex() {
    159160        return index;
    160161    }
    161    
     162
    162163    public Junction getOutgoingJunction() {
    163164        return getOutgoingRoadEnd().getJunction();
    164165    }
    165    
     166
    166167    public Junction getIncomingJunction() {
    167168        return getIncomingRoadEnd().getJunction();
    168169    }
    169    
     170
    170171    public Road.End getOutgoingRoadEnd() {
    171172        return roadEnd;
    172173    }
    173    
     174
    174175    public Road.End getIncomingRoadEnd() {
    175176        return roadEnd.getOppositeEnd();
    176177    }
    177    
     178
    178179    public ModelContainer getContainer() {
    179180        return getRoad().getContainer();
    180181    }
    181    
     182
    182183    public void addTurn(List<Road> via, Road.End to) {
    183184        final GenericCommand cmd = new GenericCommand(getOutgoingJunction().getNode().getDataSet(), tr("Add turn"));
    184        
     185
    185186        Relation existing = null;
    186187        for (Turn t : to.getTurns()) {
     
    190191                    return;
    191192                }
    192                
     193
    193194                existing = t.getRelation();
    194195            }
    195196        }
    196        
     197
    197198        final Relation r;
    198199        if (existing == null) {
    199200            r = new Relation();
    200201            r.put("type", Constants.TYPE_TURNS);
    201            
     202
    202203            r.addMember(new RelationMember(Constants.TURN_ROLE_FROM, getOutgoingRoadEnd().getWay()));
    203204            if (via.isEmpty()) {
     
    209210            }
    210211            r.addMember(new RelationMember(Constants.TURN_ROLE_TO, to.getWay()));
    211            
     212
    212213            cmd.add(r);
    213214        } else {
    214215            r = existing;
    215216        }
    216        
     217
    217218        final String key = isExtra() ? Constants.TURN_KEY_EXTRA_LANES : Constants.TURN_KEY_LANES;
    218219        final List<Integer> lanes = Turn.indices(r, key);
    219220        lanes.add(getIndex());
    220221        cmd.backup(r).put(key, Turn.join(lanes));
    221        
     222
    222223        Main.main.undoRedo.add(cmd);
    223224    }
    224    
     225
    225226    public Set<Turn> getTurns() {
    226227        return turns;
    227228    }
    228    
     229
    229230    public void remove() {
    230231        if (!isExtra()) {
    231232            throw new UnsupportedOperationException();
    232233        }
    233        
     234
    234235        final GenericCommand cmd = new GenericCommand(getOutgoingJunction().getNode().getDataSet(), tr("Delete lane."));
    235        
     236
    236237        for (Turn t : getTurns()) {
    237238            t.remove(cmd);
    238239        }
    239        
     240
    240241        getOutgoingRoadEnd().removeLane(cmd, this);
    241        
     242
    242243        Main.main.undoRedo.add(cmd);
    243244    }
    244    
     245
    245246    void initialize() {
    246247        final Set<Turn> turns = Turn.load(getContainer(), Constants.TURN_ROLE_FROM, getOutgoingRoadEnd().getWay());
    247        
     248
    248249        final Iterator<Turn> it = turns.iterator();
    249250        while (it.hasNext()) {
    250251            final Turn t = it.next();
    251            
     252
    252253            if (!t.getFrom().equals(this)) {
    253254                it.remove();
    254255            }
    255256        }
    256        
     257
    257258        this.turns = Collections.unmodifiableSet(turns);
    258259    }
  • applications/editors/josm/plugins/turnlanes/src/org/openstreetmap/josm/plugins/turnlanes/model/ModelContainer.java

    r30737 r33085  
     1// License: GPL. For details, see LICENSE file.
    12package org.openstreetmap.josm.plugins.turnlanes.model;
    23
     
    1920import org.openstreetmap.josm.tools.Pair;
    2021
    21 public class ModelContainer {
    22     private static final ModelContainer EMPTY = new ModelContainer(Collections.<Node> emptySet(),
    23             Collections.<Way> emptySet(), false);
    24    
     22public final class ModelContainer {
     23    private static final ModelContainer EMPTY = new ModelContainer(Collections.<Node>emptySet(),
     24            Collections.<Way>emptySet(), false);
     25
    2526    public static ModelContainer create(Iterable<Node> primaryNodes, Iterable<Way> primaryWays) {
    2627        return new ModelContainer(new HashSet<>(CollectionUtils.toList(primaryNodes)), new HashSet<>(
    2728                CollectionUtils.toList(primaryWays)), false);
    2829    }
    29    
     30
    3031    public static ModelContainer createEmpty(Iterable<Node> primaryNodes, Iterable<Way> primaryWays) {
    3132        return new ModelContainer(new HashSet<>(CollectionUtils.toList(primaryNodes)), new HashSet<>(
    3233                CollectionUtils.toList(primaryWays)), true);
    3334    }
    34    
     35
    3536    public static ModelContainer empty() {
    3637        return EMPTY;
    3738    }
    38    
     39
    3940    private static void close(Set<Node> closedNodes, Set<Way> closedWays) {
    4041        boolean closed = false;
    41        
     42
    4243        while (!closed) {
    4344            closed = true;
    44            
     45
    4546            for (Node n : new ArrayList<>(closedNodes)) {
    4647                for (Way w : Utils.filterRoads(n.getReferrers())) {
     
    4950                    }
    5051                }
    51                
     52
    5253                for (Way w : new ArrayList<>(closedWays)) {
    5354                    closed &= close(closedNodes, closedWays, w);
     
    5657        }
    5758    }
    58    
     59
    5960    private static boolean close(Set<Node> closedNodes, Set<Way> closedWays, Way w) {
    6061        boolean closed = true;
    61        
     62
    6263        for (Relation r : OsmPrimitive.getFilteredList(w.getReferrers(), Relation.class)) {
    6364            if (!r.get("type").equals(Constants.TYPE_TURNS)) {
    6465                continue;
    6566            }
    66            
     67
    6768            for (RelationMember m : r.getMembers()) {
    6869                if (m.getRole().equals(Constants.TURN_ROLE_VIA) && m.getMember().equals(w)) {
     
    7172            }
    7273        }
    73        
     74
    7475        return closed;
    7576    }
    76    
     77
    7778    private static boolean close(Set<Node> closedNodes, Set<Way> closedWays, Relation r) {
    7879        boolean closed = true;
    79        
     80
    8081        final List<Way> via = new ArrayList<>();
    8182        for (RelationMember m : Utils.getMembers(r, Constants.TURN_ROLE_VIA)) {
     
    8788            }
    8889        }
    89        
     90
    9091        if (!via.isEmpty()) {
    9192            final Way from = Utils.getMemberWay(r, Constants.TURN_ROLE_FROM);
    9293            final Way to = Utils.getMemberWay(r, Constants.TURN_ROLE_TO);
    93            
     94
    9495            closed &= !closedNodes.add(Utils.lineUp(from, via.get(0)));
    9596            closed &= !closedNodes.add(Utils.lineUp(via.get(via.size() - 1), to));
    9697        }
    97        
     98
    9899        return closed;
    99100    }
    100    
     101
    101102    private static <E extends OsmPrimitive, C extends Collection<E>> C filterUsables(C collection) {
    102103        final Iterator<E> it = collection.iterator();
    103        
     104
    104105        while (it.hasNext()) {
    105106            final E e = it.next();
    106            
     107
    107108            if (e.getDataSet() == null || !e.isUsable()) {
    108109                it.remove();
    109110            }
    110111        }
    111        
     112
    112113        return collection;
    113114    }
    114    
     115
    115116    private final Map<Node, Junction> junctions = new HashMap<>();
    116117    private final Map<Way, Road> roads = new HashMap<>();
    117    
     118
    118119    private final Set<Node> primaryNodes;
    119120    private final Set<Way> primaryWays;
    120    
     121
    121122    private final boolean empty;
    122    
     123
    123124    private ModelContainer(Set<Node> primaryNodes, Set<Way> primaryWays, boolean empty) {
    124125        if (empty) {
     
    129130            final Set<Node> closedNodes = filterUsables(new HashSet<>(primaryNodes));
    130131            final Set<Way> closedWays = filterUsables(new HashSet<>(primaryWays));
    131            
     132
    132133            close(closedNodes, closedWays);
    133            
     134
    134135            this.primaryNodes = Collections.unmodifiableSet(closedNodes);
    135136            this.primaryWays = Collections.unmodifiableSet(closedWays);
    136            
     137
    137138            for (Pair<Way, Junction> w : createPrimaryJunctions()) {
    138139                if (!this.primaryWays.contains(w.a)) {
     
    140141                }
    141142            }
    142            
     143
    143144            for (Route r : Utils.orderWays(this.primaryWays, this.primaryNodes)) {
    144145                addRoad(new Road(this, r));
    145146            }
    146            
     147
    147148            for (Road r : roads.values()) {
    148149                r.initialize();
    149150            }
    150            
     151
    151152            this.empty = junctions.isEmpty();
    152153        }
    153154    }
    154    
     155
    155156    private Set<Pair<Way, Junction>> createPrimaryJunctions() {
    156157        final Set<Pair<Way, Junction>> roads = new HashSet<>();
    157        
     158
    158159        for (Node n : primaryNodes) {
    159160            final List<Way> ws = new ArrayList<>();
     
    163164                }
    164165            }
    165            
     166
    166167            if (ws.size() > 1) {
    167168                final Junction j = register(new Junction(this, n));
     
    171172            }
    172173        }
    173        
     174
    174175        return roads;
    175176    }
    176    
     177
    177178    Junction getOrCreateJunction(Node n) {
    178179        final Junction existing = junctions.get(n);
    179        
     180
    180181        if (existing != null) {
    181182            return existing;
    182183        }
    183        
     184
    184185        return register(new Junction(this, n));
    185186    }
    186    
     187
    187188    public Junction getJunction(Node n) {
    188189        Junction j = junctions.get(n);
    189        
     190
    190191        if (j == null) {
    191192            throw new IllegalArgumentException();
    192193        }
    193        
     194
    194195        return j;
    195196    }
    196    
     197
    197198    Road getRoad(Way w) {
    198199        final Road r = roads.get(w);
    199        
     200
    200201        if (r == null) {
    201202            throw new IllegalArgumentException("There is no road containing the given way.");
    202203        }
    203        
     204
    204205        return r;
    205206    }
    206    
     207
    207208    private void addRoad(Road newRoad, Road mergedA, Road mergedB) {
    208209        assert (mergedA == null) == (mergedB == null);
    209        
     210
    210211        for (Route.Segment s : newRoad.getRoute().getSegments()) {
    211212            final Road oldRoad = roads.put(s.getWay(), newRoad);
    212            
     213
    213214            if (oldRoad != null) {
    214215                if (mergedA == null) {
     
    220221        }
    221222    }
    222    
     223
    223224    private void addRoad(Road newRoad) {
    224225        addRoad(newRoad, null, null);
    225226    }
    226    
     227
    227228    private Road mergeRoads(Road a, Road b) {
    228229        final String ERR_ILLEGAL_ARGS = "The given roads can not be merged into one.";
    229        
     230
    230231        final List<Way> ws = new ArrayList<>(CollectionUtils.toList(CollectionUtils.reverse(a.getRoute().getWays())));
    231232        final List<Way> bws = b.getRoute().getWays();
    232        
     233
    233234        int i = -1;
    234235        for (Way w : ws) {
     
    239240            }
    240241        }
    241        
     242
    242243        if (i < 0) {
    243244            throw new IllegalArgumentException(ERR_ILLEGAL_ARGS);
    244245        }
    245246        ws.addAll(bws.subList(i + 1, bws.size()));
    246        
     247
    247248        final Route mergedRoute = Route.create(ws, a.getRoute().getLastSegment().getEnd());
    248249        return new Road(this, mergedRoute);
    249250    }
    250    
     251
    251252    private Junction register(Junction j) {
    252253        if (junctions.put(j.getNode(), j) != null) {
    253254            throw new IllegalStateException();
    254255        }
    255        
     256
    256257        return j;
    257258    }
    258    
     259
    259260    public Set<Junction> getPrimaryJunctions() {
    260261        if (empty) {
    261262            return Collections.emptySet();
    262263        }
    263        
     264
    264265        final Set<Junction> pjs = new HashSet<>();
    265266        for (Node n : primaryNodes) {
     
    268269        return pjs;
    269270    }
    270    
     271
    271272    public Set<Road> getPrimaryRoads() {
    272273        if (empty) {
    273274            return Collections.emptySet();
    274275        }
    275        
     276
    276277        final Set<Road> prs = new HashSet<>();
    277278        for (Way w : primaryWays) {
     
    280281        return prs;
    281282    }
    282    
     283
    283284    public ModelContainer recalculate() {
    284285        return new ModelContainer(primaryNodes, primaryWays, false);
    285286    }
    286    
     287
    287288    public boolean isPrimary(Junction j) {
    288289        return primaryNodes.contains(j.getNode());
    289290    }
    290    
     291
    291292    public boolean isPrimary(Road r) {
    292293        return primaryWays.contains(r.getRoute().getFirstSegment().getWay());
    293294    }
    294    
     295
    295296    public boolean isEmpty() {
    296297        return empty;
    297298    }
    298    
     299
    299300    public boolean hasRoad(Way w) {
    300301        return roads.containsKey(w);
    301302    }
    302    
     303
    303304    public boolean hasJunction(Node n) {
    304305        return junctions.containsKey(n);
  • applications/editors/josm/plugins/turnlanes/src/org/openstreetmap/josm/plugins/turnlanes/model/Road.java

    r30737 r33085  
     1// License: GPL. For details, see LICENSE file.
    12package org.openstreetmap.josm.plugins.turnlanes.model;
    23
     
    2324
    2425public class Road {
    25     public class End {
     26    public final class End {
    2627        private final boolean from;
    2728        private final Junction junction;
    28        
     29
    2930        private final Relation lengthsLeft;
    3031        private final Relation lengthsRight;
    31        
     32
    3233        private final double extraLengthLeft;
    3334        private final double extraLengthRight;
    34        
     35
    3536        private final List<Lane> lanes;
    3637        private Set<Turn> turns;
    37        
     38
    3839        private End(boolean from, Junction junction, Relation lengthsLeft, Relation lengthsRight) {
    3940            this.from = from;
     
    4445            this.extraLengthRight = lengthsRight == null ? 0 : Route.load(lengthsRight).getLengthFrom(getWay());
    4546            this.lanes = Lane.load(this);
    46            
     47
    4748            junction.addRoad(getWay());
    4849        }
    49        
     50
    5051        private End(boolean from, Junction junction) {
    5152            this.from = from;
     
    5657            this.extraLengthRight = 0;
    5758            this.lanes = Lane.load(this);
    58            
     59
    5960            junction.addRoad(getWay());
    6061        }
    61        
     62
    6263        public Road getRoad() {
    6364            return Road.this;
    6465        }
    65        
     66
    6667        public Way getWay() {
    6768            return isFromEnd() ? getRoute().getFirstSegment().getWay() : getRoute().getLastSegment().getWay();
    6869        }
    69        
     70
    7071        public Junction getJunction() {
    7172            return junction;
    7273        }
    73        
     74
    7475        public boolean isFromEnd() {
    7576            return from;
    7677        }
    77        
     78
    7879        public boolean isToEnd() {
    7980            return !isFromEnd();
    8081        }
    81        
     82
    8283        public End getOppositeEnd() {
    8384            return isFromEnd() ? toEnd : fromEnd;
    8485        }
    85        
     86
    8687        /**
    8788         * @return the turns <em>onto</em> this road at this end
     
    9091            return turns;
    9192        }
    92        
     93
    9394        public void addLane(Lane.Kind kind) {
    9495            if (kind == Lane.Kind.REGULAR) {
    9596                throw new IllegalArgumentException("Only extra lanes can be added.");
    9697            }
    97            
     98
    9899            double length = Double.POSITIVE_INFINITY;
    99100            for (Lane l : lanes) {
     
    102103                }
    103104            }
    104            
     105
    105106            if (Double.isInfinite(length)) {
    106107                length = Math.min(20, 3 * getLength() / 4);
    107108            }
    108            
     109
    109110            addLane(kind, length);
    110111        }
    111        
     112
    112113        private void addLane(Lane.Kind kind, double length) {
    113114            assert kind == Lane.Kind.EXTRA_LEFT || kind == Lane.Kind.EXTRA_RIGHT;
    114            
     115
    115116            final GenericCommand cmd = new GenericCommand(getJunction().getNode().getDataSet(), "Add lane");
    116            
     117
    117118            final boolean left = kind == Lane.Kind.EXTRA_LEFT;
    118119            final Relation rel = left ? lengthsLeft : lengthsRight;
    119120            final Relation other = left ? lengthsRight : lengthsLeft;
    120121            final Node n = getJunction().getNode();
    121            
     122
    122123            final String lengthStr = toLengthString(length);
    123124            final Relation target;
     
    131132                target = rel;
    132133            }
    133            
     134
    134135            final String key = left ? Constants.LENGTHS_KEY_LENGTHS_LEFT : Constants.LENGTHS_KEY_LENGTHS_RIGHT;
    135136            final String old = target.get(key);
     
    139140                cmd.backup(target).put(key, old + Constants.SEPARATOR + lengthStr);
    140141            }
    141            
     142
    142143            Main.main.undoRedo.add(cmd);
    143144        }
    144        
     145
    145146        private Relation createLengthsRelation() {
    146147            final Node n = getJunction().getNode();
    147            
     148
    148149            final Relation r = new Relation();
    149150            r.put("type", Constants.TYPE_LENGTHS);
    150            
     151
    151152            r.addMember(new RelationMember(Constants.LENGTHS_ROLE_END, n));
    152153            for (Route.Segment s : isFromEnd() ? route.getSegments() : CollectionUtils.reverse(route.getSegments())) {
    153154                r.addMember(new RelationMember(Constants.LENGTHS_ROLE_WAYS, s.getWay()));
    154155            }
    155            
     156
    156157            n.getDataSet().addPrimitive(r);
    157            
     158
    158159            return r;
    159160        }
    160        
     161
    161162        void updateLengths() {
    162163            final GenericCommand cmd = new GenericCommand(getJunction().getNode().getDataSet(), "Change lane length");
    163            
     164
    164165            for (final boolean left : Arrays.asList(true, false)) {
    165166                final Lane.Kind kind = left ? Lane.Kind.EXTRA_LEFT : Lane.Kind.EXTRA_RIGHT;
    166167                final Relation r = left ? lengthsLeft : lengthsRight;
    167168                final double extra = left ? extraLengthLeft : extraLengthRight;
    168                
     169
    169170                if (r == null) {
    170171                    continue;
    171172                }
    172                
     173
    173174                final StringBuilder lengths = new StringBuilder(32);
    174175                for (Lane l : left ? CollectionUtils.reverse(lanes) : lanes) {
     
    177178                    }
    178179                }
    179                
     180
    180181                lengths.setLength(lengths.length() - Constants.SEPARATOR.length());
    181182                cmd.backup(r).put(left ? Constants.LENGTHS_KEY_LENGTHS_LEFT : Constants.LENGTHS_KEY_LENGTHS_RIGHT,
    182183                        lengths.toString());
    183184            }
    184            
     185
    185186            Main.main.undoRedo.add(cmd);
    186187        }
    187        
     188
    188189        public List<Lane> getLanes() {
    189190            return lanes;
    190191        }
    191        
     192
    192193        public Lane getLane(Lane.Kind kind, int index) {
    193194            for (Lane l : lanes) {
     
    196197                }
    197198            }
    198            
     199
    199200            throw new IllegalArgumentException("No such lane.");
    200201        }
    201        
     202
    202203        public Lane getExtraLane(int index) {
    203204            return index < 0 ? getLane(Lane.Kind.EXTRA_LEFT, index) : getLane(Lane.Kind.EXTRA_RIGHT, index);
    204205        }
    205        
     206
    206207        public boolean isExtendable() {
    207208            final End o = getOppositeEnd();
    208209            return (lengthsLeft == null && lengthsRight == null) && (o.lengthsLeft != null || o.lengthsRight != null);
    209210        }
    210        
     211
    211212        public void extend(Way way) {
    212213            if (!isExtendable()) {
    213214                throw new IllegalStateException();
    214215            }
    215            
     216
    216217            final End o = getOppositeEnd();
    217218            if (o.lengthsLeft != null) {
     
    222223            }
    223224        }
    224        
     225
    225226        public List<Double> getLengths(Lane.Kind kind) {
    226227            switch (kind) {
     
    233234            }
    234235        }
    235        
     236
    236237        void removeLane(GenericCommand cmd, Lane lane) {
    237238            assert lane.getKind() == Lane.Kind.EXTRA_LEFT || lane.getKind() == Lane.Kind.EXTRA_RIGHT;
    238            
     239
    239240            final boolean left = lane.getKind() == Lane.Kind.EXTRA_LEFT;
    240241            final Relation rel = left ? lengthsLeft : lengthsRight;
    241            
     242
    242243            for (Turn t : Turn.load(getContainer(), Constants.TURN_ROLE_FROM, getWay())) {
    243244                t.fixReferences(cmd, left, lane.getIndex());
    244245            }
    245            
     246
    246247            final double extraLength = left ? extraLengthLeft : extraLengthRight;
    247248            final List<Double> newLengths = new ArrayList<>();
     
    255256                }
    256257            }
    257            
     258
    258259            final AbstractPrimitive bRel = cmd.backup(rel);
    259260            bRel.put(key, join(newLengths));
    260            
     261
    261262            if (bRel.get(Constants.LENGTHS_KEY_LENGTHS_LEFT) == null
    262263                    && bRel.get(Constants.LENGTHS_KEY_LENGTHS_RIGHT) == null) {
     
    264265            }
    265266        }
    266        
     267
    267268        void initialize() {
    268269            this.turns = Collections.unmodifiableSet(Turn.load(getContainer(), Constants.TURN_ROLE_TO, getWay()));
    269            
     270
    270271            for (Lane l : lanes) {
    271272                l.initialize();
     
    273274        }
    274275    }
    275    
     276
    276277    private static Pair<Relation, Relation> getLengthRelations(Way w, Node n) {
    277278        final List<Relation> left = new ArrayList<>();
    278279        final List<Relation> right = new ArrayList<>();
    279        
     280
    280281        for (OsmPrimitive p : w.getReferrers()) {
    281282            if (p.getType() != OsmPrimitiveType.RELATION) {
    282283                continue;
    283284            }
    284            
     285
    285286            Relation r = (Relation) p;
    286            
     287
    287288            if (Constants.TYPE_LENGTHS.equals(r.get("type")) && isRightDirection(r, w, n)) {
    288                
     289
    289290                if (r.get(Constants.LENGTHS_KEY_LENGTHS_LEFT) != null) {
    290291                    left.add(r);
    291292                }
    292                
     293
    293294                if (r.get(Constants.LENGTHS_KEY_LENGTHS_RIGHT) != null) {
    294295                    right.add(r);
     
    296297            }
    297298        }
    298        
     299
    299300        if (left.size() > 1) {
    300301            throw new IllegalArgumentException("Way is in " + left.size()
    301302                    + " lengths relations for given direction, both specifying left lane lengths.");
    302303        }
    303        
     304
    304305        if (right.size() > 1) {
    305306            throw new IllegalArgumentException("Way is in " + right.size()
    306307                    + " lengths relations for given direction, both specifying right lane lengths.");
    307308        }
    308        
    309         return new Pair<>( //
    310                 left.isEmpty() ? null : left.get(0), //
    311                 right.isEmpty() ? null : right.get(0) //
     309
     310        return new Pair<>(
     311                left.isEmpty() ? null : left.get(0),
     312                right.isEmpty() ? null : right.get(0)
    312313        );
    313314    }
    314    
     315
    315316    /**
    316317     * @param r
     
    328329            }
    329330        }
    330        
     331
    331332        return false;
    332333    }
    333    
     334
    334335    private final ModelContainer container;
    335336    private final Route route;
    336337    private final End fromEnd;
    337338    private final End toEnd;
    338    
     339
    339340    Road(ModelContainer container, Way w, Junction j) {
    340341        final Node n = j.getNode();
     
    343344        }
    344345        final Pair<Relation, Relation> lengthsRelations = getLengthRelations(w, n);
    345        
     346
    346347        this.container = container;
    347348        this.route = lengthsRelations.a == null && lengthsRelations.b == null ? Route.create(Arrays.asList(w), n)
     
    350351        this.toEnd = new End(false, j, lengthsRelations.a, lengthsRelations.b);
    351352    }
    352    
     353
    353354    Road(ModelContainer container, Route route) {
    354355        this.container = container;
     
    357358        this.toEnd = new End(false, container.getJunction(route.getEnd()));
    358359    }
    359    
     360
    360361    public End getFromEnd() {
    361362        return fromEnd;
    362363    }
    363    
     364
    364365    public End getToEnd() {
    365366        return toEnd;
    366367    }
    367    
     368
    368369    public Route getRoute() {
    369370        return route;
    370371    }
    371    
     372
    372373    public double getLength() {
    373374        return route.getLength();
    374375    }
    375    
     376
    376377    private static String join(List<Double> list) {
    377378        if (list.isEmpty()) {
    378379            return null;
    379380        }
    380        
     381
    381382        final StringBuilder builder = new StringBuilder(list.size() * (4 + Constants.SEPARATOR.length()));
    382        
     383
    383384        for (double e : list) {
    384385            builder.append(toLengthString(e)).append(Constants.SEPARATOR);
    385386        }
    386        
     387
    387388        builder.setLength(builder.length() - Constants.SEPARATOR.length());
    388389        return builder.toString();
    389390    }
    390    
     391
    391392    private static String toLengthString(double length) {
    392393        final DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance();
     
    396397        return nf.format(length);
    397398    }
    398    
     399
    399400    public ModelContainer getContainer() {
    400401        return container;
    401402    }
    402    
     403
    403404    public boolean isPrimary() {
    404405        return getContainer().isPrimary(this);
    405406    }
    406    
     407
    407408    void initialize() {
    408409        fromEnd.initialize();
  • applications/editors/josm/plugins/turnlanes/src/org/openstreetmap/josm/plugins/turnlanes/model/Route.java

    r30737 r33085  
     1// License: GPL. For details, see LICENSE file.
    12package org.openstreetmap.josm.plugins.turnlanes.model;
    23
     
    910import org.openstreetmap.josm.data.osm.Way;
    1011
    11 public class Route {
     12public final class Route {
    1213    public static final class Segment {
    1314        private final Node start;
    1415        private final Way way;
    1516        private final Node end;
    16        
     17
    1718        private final List<Node> nodes;
    18        
     19
    1920        Segment(Node start, Way way, Node end) {
    2021            this.start = start;
    2122            this.way = way;
    2223            this.end = end;
    23            
     24
    2425            final List<Node> ns = way.getNodes();
    2526            if (way.lastNode().equals(start)) {
    2627                Collections.reverse(ns);
    2728            }
    28            
     29
    2930            this.nodes = Collections.unmodifiableList(ns);
    3031        }
    31        
     32
    3233        public Node getStart() {
    3334            return start;
    3435        }
    35        
     36
    3637        public Way getWay() {
    3738            return way;
    3839        }
    39        
     40
    4041        public Node getEnd() {
    4142            return end;
    4243        }
    43        
     44
    4445        public List<Node> getNodes() {
    4546            return nodes;
    4647        }
    47        
     48
    4849        public double getLength() {
    4950            double length = 0;
    50            
     51
    5152            Node last = nodes.get(0);
    5253            for (Node n : nodes.subList(1, nodes.size())) {
     
    5455                last = n;
    5556            }
    56            
     57
    5758            return length;
    5859        }
    59        
     60
    6061        @Override
    6162        public int hashCode() {
     
    6768            return result;
    6869        }
    69        
     70
    7071        @Override
    7172        public boolean equals(Object obj) {
     
    9596        }
    9697    }
    97    
     98
    9899    public static Route load(Relation r) {
    99100        final Node end = Utils.getMemberNode(r, Constants.LENGTHS_ROLE_END);
    100101        final List<Way> ws = Utils.getMemberWays(r, Constants.LENGTHS_ROLE_WAYS);
    101        
     102
    102103        return create(ws, end);
    103104    }
    104    
     105
    105106    public static Route load(Relation left, Relation right, Way w) {
    106107        left = left == null ? right : left;
    107108        right = right == null ? left : right;
    108        
     109
    109110        if (left == null) {
    110111            throw new IllegalArgumentException("At least one relation must not be null.");
    111112        }
    112        
     113
    113114        final Route leftRoute = load(left);
    114115        final Route rightRoute = load(right);
    115        
     116
    116117        int iLeft = 0;
    117118        while (!w.equals(leftRoute.getSegments().get(iLeft++).getWay()))
    118119            ;
    119        
     120
    120121        int iRight = 0;
    121122        while (!w.equals(rightRoute.getSegments().get(iRight++).getWay()))
    122123            ;
    123        
     124
    124125        final int min = Math.min(iLeft, iRight);
    125        
     126
    126127        final List<Segment> leftSegments = leftRoute.getSegments().subList(iLeft - min, iLeft);
    127128        final List<Segment> rightSegments = rightRoute.getSegments().subList(iRight - min, iRight);
    128        
     129
    129130        if (!leftSegments.equals(rightSegments)) {
    130131            throw new IllegalArgumentException("Routes are split across different ways.");
    131132        }
    132        
     133
    133134        return new Route(iLeft == min ? rightSegments : leftSegments);
    134135    }
    135    
     136
    136137    public static Route create(List<Way> ws, Node end) {
    137138        final List<Segment> segments = new ArrayList<>(ws.size());
    138        
     139
    139140        for (Way w : ws) {
    140141            if (!w.isFirstLastNode(end)) {
    141142                throw new IllegalArgumentException("Ways must be ordered.");
    142143            }
    143            
     144
    144145            final Node start = Utils.getOppositeEnd(w, end);
    145146            segments.add(0, new Segment(start, w, end));
    146147            end = start;
    147148        }
    148        
     149
    149150        return new Route(segments);
    150151    }
    151    
     152
    152153    private final List<Segment> segments;
    153    
     154
    154155    private Route(List<Segment> segments) {
    155156        this.segments = Collections.unmodifiableList(new ArrayList<>(segments));
    156157    }
    157    
     158
    158159    public List<Segment> getSegments() {
    159160        return segments;
    160161    }
    161    
     162
    162163    public List<Node> getNodes() {
    163164        final List<Node> ns = new ArrayList<>();
    164        
     165
    165166        ns.add(segments.get(0).getStart());
    166167        for (Segment s : segments) {
    167168            ns.addAll(s.getNodes().subList(1, s.getNodes().size()));
    168169        }
    169        
     170
    170171        return Collections.unmodifiableList(ns);
    171172    }
    172    
     173
    173174    public double getLengthFrom(Way w) {
    174175        double length = Double.NEGATIVE_INFINITY;
    175        
     176
    176177        for (Segment s : getSegments()) {
    177178            length += s.getLength();
    178            
     179
    179180            if (w.equals(s.getWay())) {
    180181                length = 0;
    181182            }
    182183        }
    183        
     184
    184185        if (length < 0) {
    185186            throw new IllegalArgumentException("Way must be part of the route.");
    186187        }
    187        
     188
    188189        return length;
    189190    }
    190    
     191
    191192    public double getLength() {
    192193        double length = 0;
    193        
     194
    194195        for (Segment s : getSegments()) {
    195196            length += s.getLength();
    196197        }
    197        
     198
    198199        return length;
    199200    }
    200    
     201
    201202    public Node getStart() {
    202203        return getFirstSegment().getStart();
    203204    }
    204    
     205
    205206    public Node getEnd() {
    206207        return getLastSegment().getEnd();
    207208    }
    208    
     209
    209210    public Segment getFirstSegment() {
    210211        return getSegments().get(0);
    211212    }
    212    
     213
    213214    public Segment getLastSegment() {
    214215        return getSegments().get(getSegments().size() - 1);
    215216    }
    216    
     217
    217218    public Route subRoute(int fromIndex, int toIndex) {
    218219        return new Route(segments.subList(fromIndex, toIndex));
    219220    }
    220    
     221
    221222    public List<Way> getWays() {
    222223        final List<Way> ws = new ArrayList<>();
    223        
     224
    224225        for (Segment s : segments) {
    225226            ws.add(s.getWay());
    226227        }
    227        
     228
    228229        return Collections.unmodifiableList(ws);
    229230    }
  • applications/editors/josm/plugins/turnlanes/src/org/openstreetmap/josm/plugins/turnlanes/model/Turn.java

    r30737 r33085  
     1// License: GPL. For details, see LICENSE file.
    12package org.openstreetmap.josm.plugins.turnlanes.model;
    23
     
    2223    static Set<Turn> load(ModelContainer c, String role, OsmPrimitive primitive) {
    2324        final Set<Turn> result = new HashSet<>();
    24        
     25
    2526        for (Relation r : OsmPrimitive.getFilteredList(primitive.getReferrers(), Relation.class)) {
    2627            if (!r.isUsable() || !r.get("type").equals(Constants.TYPE_TURNS)) {
    2728                continue;
    2829            }
    29            
     30
    3031            for (RelationMember m : r.getMembers()) {
    3132                if (m.getRole().equals(role) && m.getMember().equals(primitive)) {
     
    3435            }
    3536        }
    36        
    37         return result;
    38     }
    39    
     37
     38        return result;
     39    }
     40
    4041    static Set<Turn> load(ModelContainer c, Relation r) {
    4142        for (RelationMember m : r.getMembers()) {
     
    4849            }
    4950        }
    50        
     51
    5152        throw new IllegalArgumentException("No via node or way(s).");
    5253    }
    53    
     54
    5455    private static Set<Turn> loadWithViaWays(ModelContainer c, Relation r) {
    5556        final Way from = Utils.getMemberWay(r, Constants.TURN_ROLE_FROM);
    5657        final Way to = Utils.getMemberWay(r, Constants.TURN_ROLE_TO);
    57        
     58
    5859        if (!c.hasRoad(from) || !c.hasRoad(to)) {
    5960            return Collections.emptySet();
    6061        }
    61        
     62
    6263        final List<Way> tmp = Utils.getMemberWays(r, Constants.TURN_ROLE_VIA);
    6364        final LinkedList<Road> via = new LinkedList<>();
    64        
     65
    6566        final Road.End fromRoadEnd = c.getJunction(Utils.lineUp(from, tmp.get(0))).getRoadEnd(from);
    66        
     67
    6768        Node n = fromRoadEnd.getJunction().getNode();
    6869        final Iterator<Way> it = tmp.iterator();
     
    7273                return Collections.emptySet();
    7374            }
    74            
     75
    7576            final Road v = c.getRoad(w);
    7677            via.add(v);
    7778            n = Utils.getOppositeEnd(w, n);
    78            
     79
    7980            if (!v.isPrimary()) {
    8081                throw new IllegalStateException("The road is not part of the junction.");
    8182            }
    82            
     83
    8384            final Iterator<Route.Segment> it2 = (v.getRoute().getFirstSegment().getWay().equals(w) ? v.getRoute()
    8485                    .getSegments() : CollectionUtils.reverse(v.getRoute().getSegments())).iterator();
    8586            it2.next(); // first is done
    86            
     87
    8788            while (it2.hasNext()) {
    8889                final Way w2 = it2.next().getWay();
    8990                n = Utils.getOppositeEnd(w2, n);
    90                
     91
    9192                if (!it.hasNext() || !w2.equals(it.next())) {
    9293                    throw new IllegalStateException("The via ways of the relation do not form a road.");
     
    9697        final Road.End toRoadEnd = c.getJunction(n).getRoadEnd(to);
    9798        n = Utils.getOppositeEnd(to, n);
    98        
     99
    99100        final Set<Turn> result = new HashSet<>();
    100101        for (int i : indices(r, Constants.TURN_KEY_LANES)) {
     
    106107        return result;
    107108    }
    108    
     109
    109110    static List<Integer> indices(Relation r, String key) {
    110111        final String joined = r.get(key);
    111        
     112
    112113        if (joined == null) {
    113114            return new ArrayList<>(1);
    114115        }
    115        
     116
    116117        final List<Integer> result = new ArrayList<>();
    117118        for (String lane : Constants.SPLIT_PATTERN.split(joined)) {
    118119            result.add(Integer.parseInt(lane));
    119120        }
    120        
    121         return result;
    122     }
    123    
     121
     122        return result;
     123    }
     124
    124125    private static Set<Turn> loadWithViaNode(ModelContainer c, Relation r) {
    125126        final Way from = Utils.getMemberWay(r, Constants.TURN_ROLE_FROM);
    126127        final Node via = Utils.getMemberNode(r, Constants.TURN_ROLE_VIA);
    127128        final Way to = Utils.getMemberWay(r, Constants.TURN_ROLE_TO);
    128        
     129
    129130        if (!c.hasRoad(from) || !c.hasJunction(via) || !c.hasRoad(to)) {
    130131            return Collections.emptySet();
    131132        }
    132        
     133
    133134        final Junction j = c.getJunction(via);
    134        
     135
    135136        final Road.End fromRoadEnd = j.getRoadEnd(from);
    136137        final Road.End toRoadEnd = j.getRoadEnd(to);
    137        
     138
    138139        final Set<Turn> result = new HashSet<>();
    139140        for (int i : indices(r, Constants.TURN_KEY_LANES)) {
    140             result.add(new Turn(r, fromRoadEnd.getLane(Lane.Kind.REGULAR, i), Collections.<Road> emptyList(), toRoadEnd));
     141            result.add(new Turn(r, fromRoadEnd.getLane(Lane.Kind.REGULAR, i), Collections.<Road>emptyList(), toRoadEnd));
    141142        }
    142143        for (int i : indices(r, Constants.TURN_KEY_EXTRA_LANES)) {
    143             result.add(new Turn(r, fromRoadEnd.getExtraLane(i), Collections.<Road> emptyList(), toRoadEnd));
    144         }
    145         return result;
    146     }
    147    
     144            result.add(new Turn(r, fromRoadEnd.getExtraLane(i), Collections.<Road>emptyList(), toRoadEnd));
     145        }
     146        return result;
     147    }
     148
    148149    static String join(List<Integer> list) {
    149150        if (list.isEmpty()) {
    150151            return null;
    151152        }
    152        
     153
    153154        final StringBuilder builder = new StringBuilder(list.size() * (2 + Constants.SEPARATOR.length()));
    154        
     155
    155156        for (int e : list) {
    156157            builder.append(e).append(Constants.SEPARATOR);
    157158        }
    158        
     159
    159160        builder.setLength(builder.length() - Constants.SEPARATOR.length());
    160161        return builder.toString();
    161162    }
    162    
     163
    163164    private final Relation relation;
    164    
     165
    165166    private final Lane from;
    166167    private final List<Road> via;
    167168    private final Road.End to;
    168    
     169
    169170    public Turn(Relation relation, Lane from, List<Road> via, Road.End to) {
    170171        this.relation = relation;
     
    173174        this.to = to;
    174175    }
    175    
     176
    176177    public Lane getFrom() {
    177178        return from;
    178179    }
    179    
     180
    180181    public List<Road> getVia() {
    181182        return via;
    182183    }
    183    
     184
    184185    public Road.End getTo() {
    185186        return to;
    186187    }
    187    
     188
    188189    Relation getRelation() {
    189190        return relation;
    190191    }
    191    
     192
    192193    public void remove() {
    193194        final GenericCommand cmd = new GenericCommand(relation.getDataSet(), tr("Delete turn."));
    194        
     195
    195196        remove(cmd);
    196        
     197
    197198        Main.main.undoRedo.add(cmd);
    198199    }
    199    
     200
    200201    void remove(GenericCommand cmd) {
    201202        final List<Integer> lanes = indices(relation, Constants.TURN_KEY_LANES);
    202203        final List<Integer> extraLanes = indices(relation, Constants.TURN_KEY_EXTRA_LANES);
    203        
     204
    204205        // TODO understand & document
    205206        if (lanes.size() + extraLanes.size() == 1 && (from.isExtra() ^ !lanes.isEmpty())) {
     
    211212            lanes.remove(Integer.valueOf(from.getIndex()));
    212213        }
    213        
     214
    214215        cmd.backup(relation).put(Constants.TURN_KEY_LANES, lanes.isEmpty() ? null : join(lanes));
    215216        cmd.backup(relation).put(Constants.TURN_KEY_EXTRA_LANES, extraLanes.isEmpty() ? null : join(extraLanes));
    216217    }
    217    
     218
    218219    void fixReferences(GenericCommand cmd, boolean left, int index) {
    219220        final List<Integer> fixed = new ArrayList<>();
     
    225226            }
    226227        }
    227        
     228
    228229        cmd.backup(relation).put(Constants.TURN_KEY_EXTRA_LANES, join(fixed));
    229230    }
  • applications/editors/josm/plugins/turnlanes/src/org/openstreetmap/josm/plugins/turnlanes/model/UnexpectedDataException.java

    r26154 r33085  
     1// License: GPL. For details, see LICENSE file.
    12package org.openstreetmap.josm.plugins.turnlanes.model;
    23
     
    78public final class UnexpectedDataException extends RuntimeException {
    89    private static final long serialVersionUID = 7430280313889494242L;
    9    
     10
    1011    public enum Kind {
    1112        NO_MEMBER("No member with role \"{0}\".", 1),
     
    1415        INVALID_TAG_FORMAT("The tag \"{0}\" has an invalid format: {1}", 2),
    1516        MISSING_TAG("The tag \"{0}\" is missing.", 1);
    16        
     17
    1718        private final String message;
    1819        private final int params;
    19        
    20         private Kind(String message, int params) {
     20
     21        Kind(String message, int params) {
    2122            this.message = message;
    2223            this.params = params;
    2324        }
    24        
     25
    2526        public UnexpectedDataException chuck(Object... args) {
    2627            throw new UnexpectedDataException(this, format(args));
    2728        }
    28        
     29
    2930        public String format(Object... args) {
    3031            if (args.length != params) {
    3132                throw new IllegalArgumentException("Wrong argument count for " + this + ": " + Arrays.toString(args));
    3233            }
    33            
     34
    3435            return tr(message, args);
    3536        }
    3637    }
    37    
     38
    3839    private final Kind kind;
    39    
     40
    4041    public UnexpectedDataException(Kind kind, String message) {
    4142        super(message);
    42        
     43
    4344        this.kind = kind;
    4445    }
    45    
     46
    4647    public Kind getKind() {
    4748        return kind;
  • applications/editors/josm/plugins/turnlanes/src/org/openstreetmap/josm/plugins/turnlanes/model/Utils.java

    r30737 r33085  
     1// License: GPL. For details, see LICENSE file.
    12package org.openstreetmap.josm.plugins.turnlanes.model;
    23
     
    1920import org.openstreetmap.josm.plugins.turnlanes.CollectionUtils;
    2021
    21 public class Utils {
     22public final class Utils {
    2223    private static final Set<String> ROAD_HIGHWAY_VALUES = Collections.unmodifiableSet(new HashSet<>(Arrays
    2324            .asList("motorway", "motorway_link", "trunk", "trunk_link", "primary", "primary_link", "secondary",
    2425                    "secondary_link", "tertiary", "tertiary_link", "residential", "unclassified", "road", "living_street", "service",
    2526                    "track", "pedestrian", "raceway", "services")));
    26    
     27
     28    private Utils() {
     29        // Hide default constructor for utilities classes
     30    }
     31
    2732    public static boolean isRoad(Way w) {
    2833        return ROAD_HIGHWAY_VALUES.contains(w.get("highway"));
    2934    }
    30    
    31     public static final List<Way> filterRoads(List<OsmPrimitive> of) {
     35
     36    public static List<Way> filterRoads(List<OsmPrimitive> of) {
    3237        final List<Way> result = new ArrayList<>();
    33        
     38
    3439        for (OsmPrimitive p : of) {
    3540            if (p.getType() == OsmPrimitiveType.WAY && Utils.isRoad((Way) p)) {
     
    3742            }
    3843        }
    39        
    40         return result;
    41     }
    42    
     44
     45        return result;
     46    }
     47
    4348    public static Node getMemberNode(Relation r, String role) {
    4449        return getMember(r, role, OsmPrimitiveType.NODE).getNode();
    4550    }
    46    
     51
    4752    public static Way getMemberWay(Relation r, String role) {
    4853        return getMember(r, role, OsmPrimitiveType.WAY).getWay();
    4954    }
    50    
     55
    5156    public static RelationMember getMember(Relation r, String role, OsmPrimitiveType type) {
    5257        final List<RelationMember> candidates = getMembers(r, role, type);
     
    5863        return candidates.get(0);
    5964    }
    60    
     65
    6166    public static List<RelationMember> getMembers(Relation r, String role, OsmPrimitiveType type) {
    6267        final List<RelationMember> result = getMembers(r, role);
     
    6873        return result;
    6974    }
    70    
     75
    7176    public static List<RelationMember> getMembers(Relation r, String role) {
    7277        final List<RelationMember> result = new ArrayList<>();
     
    7883        return result;
    7984    }
    80    
     85
    8186    public static List<Node> getMemberNodes(Relation r, String role) {
    8287        return mapMembers(getMembers(r, role, OsmPrimitiveType.NODE), Node.class);
    8388    }
    84    
     89
    8590    public static List<Way> getMemberWays(Relation r, String role) {
    8691        return mapMembers(getMembers(r, role, OsmPrimitiveType.WAY), Way.class);
    8792    }
    88    
     93
    8994    private static <T> List<T> mapMembers(List<RelationMember> ms, Class<T> t) {
    9095        final List<T> result = new ArrayList<>(ms.size());
     
    9499        return result;
    95100    }
    96    
     101
    97102    /**
    98      * 
    99      * @param a
    100      * @param b
     103     *
     104     * @param a first way
     105     * @param b second way
    101106     * @return the node at which {@code a} and {@code b} are connected
    102107     */
     
    108113            throw new IllegalArgumentException("Ways are not connected (at their first and last nodes).");
    109114        }
    110        
     115
    111116        if (a.firstNode() == b.firstNode() || a.lastNode() == b.firstNode()) {
    112117            return b.firstNode();
     
    117122        }
    118123    }
    119    
     124
    120125    public static Node getOppositeEnd(Way w, Node n) {
    121126        final boolean first = n.equals(w.firstNode());
    122127        final boolean last = n.equals(w.lastNode());
    123        
     128
    124129        if (first && last) {
    125130            throw new IllegalArgumentException("Way starts as well as ends at the given node.");
     
    132137        }
    133138    }
    134    
     139
    135140    /**
    136141     * Orders the {@code ways} such that the combined ways out of each returned list form a path (in
    137142     * order) from one node out of {@code nodes} to another out of {@code nodes}.
    138      * 
     143     *
    139144     * <ul>
    140145     * <li>Each way is used exactly once.</li>
     
    142147     * <li>Paths contain no loops w.r.t. the ways' first and last nodes</li>
    143148     * </ul>
    144      * 
     149     *
    145150     * @param ways
    146151     *            ways to be ordered
    147152     * @param nodes
    148153     *            start/end nodes
    149      * @return
     154     * @return ordered list
    150155     * @throws IllegalArgumentException
    151156     *             if the ways can't be ordered
     
    154159        final List<Way> ws = new LinkedList<>(CollectionUtils.toList(ways));
    155160        final Set<Node> ns = new HashSet<>(CollectionUtils.toList(nodes));
    156        
     161
    157162        final List<Route> result = new ArrayList<>();
    158        
     163
    159164        while (!ws.isEmpty()) {
    160165            result.add(findPath(ws, ns));
    161166        }
    162        
    163         return result;
    164     }
    165    
     167
     168        return result;
     169    }
     170
    166171    private static Route findPath(List<Way> ws, Set<Node> ns) {
    167172        final Way w = findPathSegment(ws, ns);
    168173        final boolean first = ns.contains(w.firstNode());
    169174        final boolean last = ns.contains(w.lastNode());
    170        
     175
    171176        if (first && last) {
    172177            return Route.create(Arrays.asList(w), w.firstNode());
     
    174179            throw new AssertionError();
    175180        }
    176        
     181
    177182        final List<Way> result = new ArrayList<>();
    178183        result.add(w);
     
    182187            result.add(next);
    183188            n = getOppositeEnd(next, n);
    184            
     189
    185190            if (ns.contains(n)) {
    186191                return Route.create(result, first ? w.firstNode() : w.lastNode());
     
    188193        }
    189194    }
    190    
     195
    191196    private static Way findPathSegment(List<Way> ws, Collection<Node> ns) {
    192197        final Iterator<Way> it = ws.iterator();
    193        
     198
    194199        while (it.hasNext()) {
    195200            final Way w = it.next();
    196            
     201
    197202            if (ns.contains(w.firstNode()) || ns.contains(w.lastNode())) {
    198203                it.remove();
     
    200205            }
    201206        }
    202        
     207
    203208        throw new IllegalArgumentException("Ways can't be ordered.");
    204209    }
    205    
     210
    206211    public static Iterable<Way> flattenVia(Node start, List<Road> via, Node end) {
    207212        final List<Way> result = new ArrayList<>();
    208        
     213
    209214        Node n = start;
    210215        for (Road r : via) {
    211216            final Iterable<Route.Segment> segments = r.getRoute().getFirstSegment().getWay().isFirstLastNode(n) ? r
    212217                    .getRoute().getSegments() : CollectionUtils.reverse(r.getRoute().getSegments());
    213            
     218
    214219            for (Route.Segment s : segments) {
    215220                result.add(s.getWay());
     
    220225            throw new IllegalArgumentException("The given via ways don't end at the given node.");
    221226        }
    222        
    223         return result;
    224     }
    225    
     227
     228        return result;
     229    }
     230
    226231    public static int parseIntTag(OsmPrimitive primitive, String tag) {
    227232        final String value = primitive.get(tag);
    228        
     233
    229234        if (value != null) {
    230235            try {
     
    234239            }
    235240        }
    236        
     241
    237242        throw UnexpectedDataException.Kind.MISSING_TAG.chuck(tag);
    238243    }
  • applications/editors/josm/plugins/turnlanes/src/org/openstreetmap/josm/plugins/turnlanes/model/Validator.java

    r30737 r33085  
     1// License: GPL. For details, see LICENSE file.
    12package org.openstreetmap.josm.plugins.turnlanes.model;
    23
     
    2728            final Node junction;
    2829            final Way from;
    29            
    30             public Key(Node junction, Way from) {
     30
     31            Key(Node junction, Way from) {
    3132                this.junction = junction;
    3233                this.from = from;
    3334            }
    34            
     35
    3536            @Override
    3637            public int hashCode() {
     
    4142                return result;
    4243            }
    43            
     44
    4445            @Override
    4546            public boolean equals(Object obj) {
     
    6465            }
    6566        }
    66        
     67
    6768        final Key key;
    6869        private final int extraLeft;
     
    7071        private final int extraRight;
    7172        private final BitSet bitset;
    72        
    73         public IncomingLanes(Key key, int extraLeft, int regular, int extraRight) {
     73
     74        IncomingLanes(Key key, int extraLeft, int regular, int extraRight) {
    7475            this.key = key;
    7576            this.extraLeft = extraLeft;
     
    7879            this.bitset = new BitSet(extraLeft + regular + extraRight);
    7980        }
    80        
     81
    8182        public boolean existsRegular(int l) {
    8283            if (l > 0 && l <= regular) {
     
    8485                return true;
    8586            }
    86            
     87
    8788            return false;
    8889        }
    89        
     90
    9091        public boolean existsExtra(int l) {
    9192            if (l < 0 && Math.abs(l) <= extraLeft) {
     
    9899            return false;
    99100        }
    100        
     101
    101102        public int unreferenced() {
    102103            return extraLeft + regular + extraRight - bitset.cardinality();
    103104        }
    104105    }
    105    
     106
    106107    public List<Issue> validate(DataSet dataSet) {
    107108        final List<Relation> lenghts = new ArrayList<>();
    108109        final List<Relation> turns = new ArrayList<>();
    109        
     110
    110111        for (Relation r : OsmPrimitive.getFilteredList(dataSet.allPrimitives(), Relation.class)) {
    111112            if (!r.isUsable()) {
    112113                continue;
    113114            }
    114            
     115
    115116            final String type = r.get("type");
    116117            if (Constants.TYPE_LENGTHS.equals(type)) {
     
    120121            }
    121122        }
    122        
    123         final List<Issue> issues = new ArrayList<>();
    124        
     123
     124        final List<Issue> issues = new ArrayList<>();
     125
    125126        final Map<IncomingLanes.Key, IncomingLanes> incomingLanes = new HashMap<>();
    126127        issues.addAll(validateLengths(lenghts, incomingLanes));
    127128        issues.addAll(validateTurns(turns, incomingLanes));
    128        
     129
    129130        for (IncomingLanes lanes : incomingLanes.values()) {
    130131            if (lanes.unreferenced() > 0) {
     
    133134            }
    134135        }
    135        
     136
    136137        return issues;
    137138    }
    138    
     139
    139140    private List<Issue> validateLengths(List<Relation> lenghts, Map<IncomingLanes.Key, IncomingLanes> incomingLanes) {
    140141        final List<Issue> issues = new ArrayList<>();
    141        
     142
    142143        for (Relation r : lenghts) {
    143144            issues.addAll(validateLengths(r, incomingLanes));
    144145        }
    145        
     146
    146147        return issues;
    147148    }
    148    
     149
    149150    private List<Issue> validateLengths(Relation r, Map<IncomingLanes.Key, IncomingLanes> incomingLanes) {
    150151        final List<Issue> issues = new ArrayList<>();
    151        
     152
    152153        try {
    153154            final Node end = Utils.getMemberNode(r, Constants.LENGTHS_ROLE_END);
    154155            final Route route = validateLengthsWays(r, end, issues);
    155            
     156
    156157            if (route == null) {
    157158                return issues;
    158159            }
    159            
     160
    160161            final List<Double> left = Lane.loadLengths(r, Constants.LENGTHS_KEY_LENGTHS_LEFT, 0);
    161162            final List<Double> right = Lane.loadLengths(r, Constants.LENGTHS_KEY_LENGTHS_RIGHT, 0);
    162            
     163
    163164            int tooLong = 0;
    164165            for (Double l : left) {
     
    172173                }
    173174            }
    174            
     175
    175176            if (tooLong > 0) {
    176177                issues.add(Issue.newError(r, end, "The lengths-relation specifies " + tooLong
    177178                        + " extra-lanes which are longer than its ways."));
    178179            }
    179            
     180
    180181            putIncomingLanes(route, left, right, incomingLanes);
    181            
     182
    182183            return issues;
    183            
     184
    184185        } catch (UnexpectedDataException e) {
    185186            issues.add(Issue.newError(r, e.getMessage()));
     
    187188        }
    188189    }
    189    
     190
    190191    private void putIncomingLanes(Route route, List<Double> left, List<Double> right,
    191192            Map<IncomingLanes.Key, IncomingLanes> incomingLanes) {
    192193        final Node end = route.getLastSegment().getEnd();
    193194        final Way way = route.getLastSegment().getWay();
    194        
     195
    195196        final IncomingLanes.Key key = new IncomingLanes.Key(end, way);
    196197        final IncomingLanes lanes = new IncomingLanes(key, left.size(), Lane.getRegularCount(way, end), right.size());
    197198        final IncomingLanes old = incomingLanes.put(key, lanes);
    198        
     199
    199200        if (old != null) {
    200201            incomingLanes.put(
     
    204205        }
    205206    }
    206    
     207
    207208    private Route validateLengthsWays(Relation r, Node end, List<Issue> issues) {
    208209        final List<Way> ways = Utils.getMemberWays(r, Constants.LENGTHS_ROLE_WAYS);
    209        
     210
    210211        if (ways.isEmpty()) {
    211212            issues.add(Issue.newError(r, "A lengths-relation requires at least one member-way with role \""
     
    213214            return null;
    214215        }
    215        
     216
    216217        Node current = end;
    217218        for (Way w : ways) {
     
    219220                return orderWays(r, ways, current, issues, "ways", "lengths");
    220221            }
    221            
     222
    222223            current = Utils.getOppositeEnd(w, current);
    223224        }
    224        
     225
    225226        return Route.create(ways, end);
    226227    }
    227    
     228
    228229    private Route orderWays(final Relation r, List<Way> ways, Node end, List<Issue> issues, String role, String type) {
    229230        final List<Way> unordered = new ArrayList<>(ways);
    230231        final List<Way> ordered = new ArrayList<>(ways.size());
    231232        final Set<Node> ends = new HashSet<>(); // to find cycles
    232        
     233
    233234        Node current = end;
    234235        findNext: while (!unordered.isEmpty()) {
     
    238239                return null;
    239240            }
    240            
     241
    241242            Iterator<Way> it = unordered.iterator();
    242243            while (it.hasNext()) {
    243244                final Way w = it.next();
    244                
     245
    245246                if (w.isFirstLastNode(current)) {
    246247                    it.remove();
     
    250251                }
    251252            }
    252            
     253
    253254            issues.add(Issue.newError(r, ways, "The " + role + " of the " + type + "-relation are disconnected."));
    254255            return null;
    255256        }
    256        
     257
    257258        final QuickFix quickFix = new QuickFix(tr("Put the ways in order.")) {
    258259            @Override
     
    260261                for (int i = r.getMembersCount() - 1; i >= 0; --i) {
    261262                    final RelationMember m = r.getMember(i);
    262                    
     263
    263264                    if (m.isWay() && Constants.LENGTHS_ROLE_WAYS.equals(m.getRole())) {
    264265                        r.removeMember(i);
    265266                    }
    266267                }
    267                
     268
    268269                for (Way w : ordered) {
    269270                    r.addMember(new RelationMember(Constants.LENGTHS_ROLE_WAYS, w));
    270271                }
    271                
     272
    272273                return true;
    273274            }
    274275        };
    275        
     276
    276277        issues.add(Issue.newError(r, ways, "The ways of the lengths-relation are unordered.", quickFix));
    277        
     278
    278279        return Route.create(ordered, end);
    279280    }
    280    
     281
    281282    private List<Issue> validateTurns(List<Relation> turns, Map<IncomingLanes.Key, IncomingLanes> incomingLanes) {
    282283        final List<Issue> issues = new ArrayList<>();
    283        
     284
    284285        for (Relation r : turns) {
    285286            issues.addAll(validateTurns(r, incomingLanes));
    286287        }
    287        
     288
    288289        return issues;
    289290    }
    290    
     291
    291292    private List<Issue> validateTurns(Relation r, Map<IncomingLanes.Key, IncomingLanes> incomingLanes) {
    292293        final List<Issue> issues = new ArrayList<>();
    293        
     294
    294295        try {
    295296            final Way from = Utils.getMemberWay(r, Constants.TURN_ROLE_FROM);
    296297            final Way to = Utils.getMemberWay(r, Constants.TURN_ROLE_TO);
    297            
     298
    298299            if (from.firstNode().equals(from.lastNode())) {
    299300                issues.add(Issue.newError(r, from, "The from-way both starts as well as ends at the via-node."));
     
    305306                return issues;
    306307            }
    307            
     308
    308309            final Node fromJunctionNode;
    309310            final List<RelationMember> viaMembers = Utils.getMembers(r, Constants.TURN_ROLE_VIA);
     
    312313            } else if (viaMembers.get(0).isWay()) {
    313314                final List<Way> vias = Utils.getMemberWays(r, Constants.TURN_ROLE_VIA);
    314                
     315
    315316                fromJunctionNode = Utils.lineUp(from, vias.get(0));
    316317                Node current = fromJunctionNode;
     
    320321                        break;
    321322                    }
    322                    
     323
    323324                    current = Utils.getOppositeEnd(via, current);
    324325                }
    325326            } else {
    326327                final Node via = Utils.getMemberNode(r, Constants.TURN_ROLE_VIA);
    327                
     328
    328329                if (!from.isFirstLastNode(via)) {
    329330                    issues.add(Issue.newError(r, from, "The from-way does not start or end at the via-node."));
     
    332333                    issues.add(Issue.newError(r, to, "The to-way does not start or end at the via-node."));
    333334                }
    334                
     335
    335336                fromJunctionNode = via;
    336337            }
    337            
     338
    338339            if (!issues.isEmpty()) {
    339340                return issues;
    340341            }
    341342            final IncomingLanes lanes = get(incomingLanes, fromJunctionNode, from);
    342            
     343
    343344            for (int l : splitInts(r, Constants.TURN_KEY_LANES, issues)) {
    344345                if (!lanes.existsRegular(l)) {
     
    346347                }
    347348            }
    348            
     349
    349350            for (int l : splitInts(r, Constants.TURN_KEY_EXTRA_LANES, issues)) {
    350351                if (!lanes.existsExtra(l)) {
     
    352353                }
    353354            }
    354            
     355
    355356            return issues;
    356357        } catch (UnexpectedDataException e) {
     
    359360        }
    360361    }
    361    
     362
    362363    private List<Integer> splitInts(Relation r, String key, List<Issue> issues) {
    363364        final String ints = r.get(key);
    364        
     365
    365366        if (ints == null) {
    366367            return Collections.emptyList();
    367368        }
    368        
     369
    369370        final List<Integer> result = new ArrayList<>();
    370        
     371
    371372        for (String s : Constants.SPLIT_PATTERN.split(ints)) {
    372373            try {
     
    377378            }
    378379        }
    379        
     380
    380381        return result;
    381382    }
    382    
     383
    383384    private IncomingLanes get(Map<IncomingLanes.Key, IncomingLanes> incomingLanes, Node via, Way from) {
    384385        final IncomingLanes.Key key = new IncomingLanes.Key(via, from);
    385386        final IncomingLanes lanes = incomingLanes.get(key);
    386        
     387
    387388        if (lanes == null) {
    388389            final IncomingLanes newLanes = new IncomingLanes(key, 0, Lane.getRegularCount(from, via), 0);
Note: See TracChangeset for help on using the changeset viewer.