Changeset 5671 in josm for trunk/src/org


Ignore:
Timestamp:
2013-01-26T16:49:29+01:00 (12 years ago)
Author:
Don-vip
Message:

Improve validator layer painting performance (major slowdown seen with #3346 test file)

Location:
trunk/src/org/openstreetmap/josm
Files:
1 added
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/data/validation/TestError.java

    r4672 r5671  
    22package org.openstreetmap.josm.data.validation;
    33
    4 import java.awt.Color;
    5 import java.awt.Graphics;
    6 import java.awt.Point;
     4import java.util.ArrayList;
    75import java.util.Collection;
    86import java.util.Collections;
    97import java.util.List;
    108import java.util.TreeSet;
    11 import java.util.ArrayList;
    129
    1310import org.openstreetmap.josm.command.Command;
     
    1714import org.openstreetmap.josm.data.osm.Way;
    1815import org.openstreetmap.josm.data.osm.WaySegment;
    19 import org.openstreetmap.josm.data.osm.visitor.AbstractVisitor;
    20 import org.openstreetmap.josm.gui.MapView;
    2116
    2217/**
     
    3631    /** The affected primitives */
    3732    private Collection<? extends OsmPrimitive> primitives;
    38     /** The primitives to be highlighted */
     33    /** The primitives or way segments to be highlighted */
    3934    private Collection<?> highlighted;
    4035    /** The tester that raised this error */
     
    5045     * @param severity The severity of this error
    5146     * @param message The error message
    52      * @param primitive The affected primitive
    5347     * @param primitives The affected primitives
    5448     * @param code The test error reference code
     
    246240
    247241    /**
    248      * Paints the error on affected primitives
    249      *
    250      * @param g The graphics
    251      * @param mv The MapView
    252      */
    253     public void paint(Graphics g, MapView mv) {
    254         if (!ignored) {
    255             PaintVisitor v = new PaintVisitor(g, mv);
    256             visitHighlighted(v);
    257         }
     242     * Sets the selection flag of this error
     243     * @param selected if this error is selected
     244     */
     245    public void setSelected(boolean selected) {
     246        this.selected = selected;
    258247    }
    259248
     
    272261
    273262    /**
    274      * Visitor that highlights the primitives affected by this error
    275      * @author frsantos
    276      */
    277     class PaintVisitor extends AbstractVisitor implements ValidatorVisitor {
    278         /** The graphics */
    279         private final Graphics g;
    280         /** The MapView */
    281         private final MapView mv;
    282 
    283         /**
    284          * Constructor
    285          * @param g The graphics
    286          * @param mv The Mapview
    287          */
    288         public PaintVisitor(Graphics g, MapView mv) {
    289             this.g = g;
    290             this.mv = mv;
    291         }
    292 
    293         @Override
    294         public void visit(OsmPrimitive p) {
    295             if (p.isUsable()) {
    296                 p.visit(this);
    297             }
    298         }
    299 
    300         /**
    301          * Draws a circle around the node
    302          * @param n The node
    303          * @param color The circle color
    304          */
    305         public void drawNode(Node n, Color color) {
    306             Point p = mv.getPoint(n);
    307             g.setColor(color);
    308             if (selected) {
    309                 g.fillOval(p.x - 5, p.y - 5, 10, 10);
    310             } else {
    311                 g.drawOval(p.x - 5, p.y - 5, 10, 10);
    312             }
    313         }
    314 
    315         public void drawSegment(Point p1, Point p2, Color color) {
    316             g.setColor(color);
    317 
    318             double t = Math.atan2(p2.x - p1.x, p2.y - p1.y);
    319             double cosT = Math.cos(t);
    320             double sinT = Math.sin(t);
    321             int deg = (int) Math.toDegrees(t);
    322             if (selected) {
    323                 int[] x = new int[] { (int) (p1.x + 5 * cosT), (int) (p2.x + 5 * cosT),
    324                                       (int) (p2.x - 5 * cosT), (int) (p1.x - 5 * cosT) };
    325                 int[] y = new int[] { (int) (p1.y - 5 * sinT), (int) (p2.y - 5 * sinT),
    326                                       (int) (p2.y + 5 * sinT), (int) (p1.y + 5 * sinT) };
    327                 g.fillPolygon(x, y, 4);
    328                 g.fillArc(p1.x - 5, p1.y - 5, 10, 10, deg, 180);
    329                 g.fillArc(p2.x - 5, p2.y - 5, 10, 10, deg, -180);
    330             } else {
    331                 g.drawLine((int) (p1.x + 5 * cosT), (int) (p1.y - 5 * sinT),
    332                            (int) (p2.x + 5 * cosT), (int) (p2.y - 5 * sinT));
    333                 g.drawLine((int) (p1.x - 5 * cosT), (int) (p1.y + 5 * sinT),
    334                            (int) (p2.x - 5 * cosT), (int) (p2.y + 5 * sinT));
    335                 g.drawArc(p1.x - 5, p1.y - 5, 10, 10, deg, 180);
    336                 g.drawArc(p2.x - 5, p2.y - 5, 10, 10, deg, -180);
    337             }
    338         }
    339 
    340         /**
    341          * Draws a line around the segment
    342          *
    343          * @param s The segment
    344          * @param color The color
    345          */
    346         public void drawSegment(Node n1, Node n2, Color color) {
    347             drawSegment(mv.getPoint(n1), mv.getPoint(n2), color);
    348         }
    349 
    350         /**
    351          * Draw a small rectangle.
    352          * White if selected (as always) or red otherwise.
    353          *
    354          * @param n The node to draw.
    355          */
    356         @Override
    357         public void visit(Node n) {
    358             if (isNodeVisible(n)) {
    359                 drawNode(n, severity.getColor());
    360             }
    361         }
    362 
    363         @Override
    364         public void visit(Way w) {
    365             visit(w.getNodes());
    366         }
    367 
    368         @Override
    369         public void visit(WaySegment ws) {
    370             if (ws.lowerIndex < 0 || ws.lowerIndex + 1 >= ws.way.getNodesCount())
    371                 return;
    372             Node a = ws.way.getNodes().get(ws.lowerIndex), b = ws.way.getNodes().get(ws.lowerIndex + 1);
    373             if (isSegmentVisible(a, b)) {
    374                 drawSegment(a, b, severity.getColor());
    375             }
    376         }
    377 
    378         @Override
    379         public void visit(Relation r) {
    380             /* No idea how to draw a relation. */
    381         }
    382 
    383         /**
    384          * Checks if the given node is in the visible area.
    385          * @param n The node to check for visibility
    386          * @return true if the node is visible
    387          */
    388         protected boolean isNodeVisible(Node n) {
    389             Point p = mv.getPoint(n);
    390             return !((p.x < 0) || (p.y < 0) || (p.x > mv.getWidth()) || (p.y > mv.getHeight()));
    391         }
    392 
    393         /**
    394          * Checks if the given segment is in the visible area.
    395          * NOTE: This will return true for a small number of non-visible
    396          *       segments.
    397          * @param ls The segment to check
    398          * @return true if the segment is visible
    399          */
    400         protected boolean isSegmentVisible(Node n1, Node n2) {
    401             Point p1 = mv.getPoint(n1);
    402             Point p2 = mv.getPoint(n2);
    403             if ((p1.x < 0) && (p2.x < 0))
    404                 return false;
    405             if ((p1.y < 0) && (p2.y < 0))
    406                 return false;
    407             if ((p1.x > mv.getWidth()) && (p2.x > mv.getWidth()))
    408                 return false;
    409             if ((p1.y > mv.getHeight()) && (p2.y > mv.getHeight()))
    410                 return false;
    411             return true;
    412         }
    413 
    414         @Override
    415         public void visit(List<Node> nodes) {
    416             Node lastN = null;
    417             for (Node n : nodes) {
    418                 if (lastN == null) {
    419                     lastN = n;
    420                     continue;
    421                 }
    422                 if (n.isDrawable() && isSegmentVisible(lastN, n)) {
    423                     drawSegment(lastN, n, severity.getColor());
    424                 }
    425                 lastN = n;
    426             }
    427         }
    428     }
    429 
    430     /**
    431      * Sets the selection flag of this error
    432      * @param selected if this error is selected
    433      */
    434     public void setSelected(boolean selected) {
    435         this.selected = selected;
     263     * Returns the selection flag of this error
     264     * @return true if this error is selected
     265     * @since 5671
     266     */
     267    public boolean isSelected() {
     268        return selected;
     269    }
     270
     271    /**
     272     * Returns The primitives or way segments to be highlighted
     273     * @return The primitives or way segments to be highlighted
     274     * @since 5671
     275     */
     276    public Collection<?> getHighlighted() {
     277        return highlighted;
    436278    }
    437279}
  • trunk/src/org/openstreetmap/josm/data/validation/ValidatorVisitor.java

    r3669 r5671  
    99
    1010public interface ValidatorVisitor {
     11    void visit(TestError error);
    1112    void visit(OsmPrimitive p);
    1213    void visit(WaySegment ws);
  • trunk/src/org/openstreetmap/josm/gui/dialogs/ValidatorDialog.java

    r5631 r5671  
    335335            return;
    336336        ValidatorBoundingXYVisitor bbox = new ValidatorBoundingXYVisitor();
    337         popupMenuError.visitHighlighted(bbox);
     337        bbox.visit(popupMenuError);
    338338        if (bbox.getBounds() == null)
    339339            return;
     
    523523            for (Node n: nodes) {
    524524                visit(n);
     525            }
     526        }
     527
     528        @Override
     529        public void visit(TestError error) {
     530            if (error != null) {
     531                error.visitHighlighted(this);
    525532            }
    526533        }
  • trunk/src/org/openstreetmap/josm/gui/layer/ValidatorLayer.java

    r3674 r5671  
    1717import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
    1818import org.openstreetmap.josm.data.validation.OsmValidator;
     19import org.openstreetmap.josm.data.validation.PaintVisitor;
    1920import org.openstreetmap.josm.data.validation.Severity;
    2021import org.openstreetmap.josm.data.validation.TestError;
     
    3536    private int updateCount = -1;
    3637
     38    /**
     39     * Constructs a new Validator layer
     40     */
    3741    public ValidatorLayer() {
    3842        super(tr("Validation errors"));
     
    6064        if (root == null || root.getChildCount() == 0)
    6165            return;
     66       
     67        PaintVisitor paintVisitor = new PaintVisitor(g, mv);
    6268
    6369        DefaultMutableTreeNode severity = (DefaultMutableTreeNode) root.getLastChild();
     
    6773                Object tn = errorMessages.nextElement().getUserObject();
    6874                if (tn instanceof TestError) {
    69                     ((TestError) tn).paint(g, mv);
     75                    paintVisitor.visit(((TestError) tn));
    7076                }
    7177            }
     
    7480            severity = severity.getPreviousSibling();
    7581        }
     82       
     83        paintVisitor.clearPaintedObjects();
    7684    }
    7785
Note: See TracChangeset for help on using the changeset viewer.