Package org.openstreetmap.josm.data.osm.visitor

Source Code of org.openstreetmap.josm.data.osm.visitor.MapPaintVisitor

/* License: GPL. Copyright 2007 by Immanuel Scholz and others */
package org.openstreetmap.josm.data.osm.visitor;

/* To enable debugging or profiling remove the double / signs */

import static org.openstreetmap.josm.tools.I18n.marktr;
import static org.openstreetmap.josm.tools.I18n.tr;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.Stroke;
import java.awt.geom.GeneralPath;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;

import javax.swing.ImageIcon;

import org.openstreetmap.josm.Main;
import org.openstreetmap.josm.data.coor.EastNorth;
import org.openstreetmap.josm.data.coor.LatLon;
import org.openstreetmap.josm.data.osm.DataSet;
import org.openstreetmap.josm.data.osm.Node;
import org.openstreetmap.josm.data.osm.OsmPrimitive;
import org.openstreetmap.josm.data.osm.Relation;
import org.openstreetmap.josm.data.osm.RelationMember;
import org.openstreetmap.josm.data.osm.Way;
import org.openstreetmap.josm.gui.NavigatableComponent;
import org.openstreetmap.josm.gui.mappaint.AreaElemStyle;
import org.openstreetmap.josm.gui.mappaint.ElemStyle;
import org.openstreetmap.josm.gui.mappaint.ElemStyles;
import org.openstreetmap.josm.gui.mappaint.IconElemStyle;
import org.openstreetmap.josm.gui.mappaint.LineElemStyle;
import org.openstreetmap.josm.gui.mappaint.MapPaintStyles;
import org.openstreetmap.josm.tools.ImageProvider;

import es.emergya.ui.gis.RotatableView;

public class MapPaintVisitor extends SimplePaintVisitor {
  protected boolean useRealWidth;
  protected boolean zoomLevelDisplay;
  protected int fillAreas;
  protected boolean drawMultipolygon;
  protected boolean drawRestriction;
  protected boolean leftHandTraffic;
  // protected boolean restrictionDebug;
  protected int showNames;
  protected int showIcons;
  protected int useStrokes;
  protected int fillAlpha;
  protected Color untaggedColor;
  protected Color textColor;
  protected float[] currentDashed = new float[0];
  protected Color currentDashedColor;
  protected int currentWidth = 0;
  protected Stroke currentStroke = null;
  protected Font orderFont;
  protected ElemStyles.StyleSet styles;
  protected double circum;
  protected double dist;
  protected Collection<String> regionalNameOrder;
  protected Boolean selectedCall;
  protected Boolean useStyleCache;
  private static int paintid = 0;
  private static int viewid = 0;
  private EastNorth minEN;
  private EastNorth maxEN;

  // protected int profilerVisibleNodes;
  // protected int profilerVisibleWays;
  // protected int profilerVisibleAreas;
  // protected int profilerSegments;
  // protected int profilerVisibleSegments;
  // protected boolean profilerOmitDraw;

  protected boolean isZoomOk(ElemStyle e) {
    if (!zoomLevelDisplay) /* show everything if the user wishes so */
      return true;

    if (e == null) /*
             * the default for things that don't have a rule (show,
             * if scale is smaller than 1500m)
             */
      return (circum < 1500);

    /*
     * formula to calculate a map scale: natural size / map size = scale
     * example: 876000mm (876m as displayed) / 22mm (roughly estimated
     * screen size of legend bar) = 39818
     *
     * so the exact "correcting value" below depends only on the screen size
     * and resolution XXX - do we need a Preference setting for this (if
     * things vary widely)?
     */
    return !(circum >= e.maxScale / 22 || circum < e.minScale / 22);
  }

  public ElemStyle getPrimitiveStyle(OsmPrimitive osm) {
    if (!useStyleCache)
      return (styles != null) ? styles.get(osm) : null;

    if (osm.mappaintStyle == null && styles != null) {
      osm.mappaintStyle = styles.get(osm);
      if (osm instanceof Way)
        ((Way) osm).isMappaintArea = styles.isArea(osm);
    }
    return osm.mappaintStyle;
  }

  public IconElemStyle getPrimitiveNodeStyle(OsmPrimitive osm) {
    if (!useStyleCache)
      return (styles != null) ? styles.getIcon(osm) : null;

    if (osm.mappaintStyle == null && styles != null)
      osm.mappaintStyle = styles.getIcon(osm);

    return (IconElemStyle) osm.mappaintStyle;
  }

  public boolean isPrimitiveArea(Way osm) {
    if (!useStyleCache)
      return styles.isArea(osm);

    if (osm.mappaintStyle == null && styles != null) {
      osm.mappaintStyle = styles.get(osm);
      osm.isMappaintArea = styles.isArea(osm);
    }
    return osm.isMappaintArea;
  }

  /**
   * Draw a small rectangle. White if selected (as always) or red otherwise.
   *
   * @param n
   *            The node to draw.
   */
  public void visit(Node n) {
    /* check, if the node is visible at all */
    if ((n.getEastNorth().east() > maxEN.east())
        || (n.getEastNorth().north() > maxEN.north())
        || (n.getEastNorth().east() < minEN.east())
        || (n.getEastNorth().north() < minEN.north())) {
      n.mappaintVisibleCode = viewid;
      return;
    }
    n.mappaintVisibleCode = 0;

    IconElemStyle nodeStyle = (IconElemStyle) getPrimitiveStyle(n);

    // if(profilerOmitDraw)
    // return;

    if (nodeStyle != null && isZoomOk(nodeStyle) && showIcons > dist)
      drawNode(n, nodeStyle.icon, nodeStyle.annotate, n.selected);
    else if (n.highlighted)
      drawNode(n, highlightColor, selectedNodeSize, selectedNodeRadius,
          fillSelectedNode);
    else if (n.selected)
      drawNode(n, selectedColor, selectedNodeSize, selectedNodeRadius,
          fillSelectedNode);
    else if (n.isTagged())
      drawNode(n, nodeColor, taggedNodeSize, taggedNodeRadius,
          fillUnselectedNode);
    else
      drawNode(n, nodeColor, unselectedNodeSize, unselectedNodeRadius,
          fillUnselectedNode);
  }

  /**
   * Draw a line for all segments, according to tags.
   *
   * @param w
   *            The way to draw.
   */
  public void visit(Way w) {
    if (w.nodes.size() < 2) {
      w.mappaintVisibleCode = viewid;
      return;
    }

    /* check, if the way is visible at all */
    double minx = 10000;
    double maxx = -10000;
    double miny = 10000;
    double maxy = -10000;

    for (Node n : w.nodes) {
      if (n.getEastNorth().east() > maxx)
        maxx = n.getEastNorth().east();
      if (n.getEastNorth().north() > maxy)
        maxy = n.getEastNorth().north();
      if (n.getEastNorth().east() < minx)
        minx = n.getEastNorth().east();
      if (n.getEastNorth().north() < miny)
        miny = n.getEastNorth().north();
    }

    if ((minx > maxEN.east()) || (miny > maxEN.north())
        || (maxx < minEN.east()) || (maxy < minEN.north())) {
      w.mappaintVisibleCode = viewid;
      return;
    }

    ElemStyle wayStyle = getPrimitiveStyle(w);

    if (!isZoomOk(wayStyle)) {
      w.mappaintVisibleCode = viewid;
      return;
    }

    w.mappaintVisibleCode = 0;
    if (fillAreas > dist)
      w.clearErrors();

    if (wayStyle == null) {
      /* way without style */
      // profilerVisibleWays++;
      // if(!profilerOmitDraw)
      drawWay(w, null, untaggedColor, w.selected);
    } else if (wayStyle instanceof LineElemStyle) {
      /* way with line style */
      // profilerVisibleWays++;
      // if(!profilerOmitDraw)
      drawWay(w, (LineElemStyle) wayStyle, untaggedWayColor, w.selected);
    } else if (wayStyle instanceof AreaElemStyle) {
      AreaElemStyle areaStyle = (AreaElemStyle) wayStyle;
      /* way with area style */
      // if(!profilerOmitDraw)
      // {
      if (fillAreas > dist && (!areaStyle.closed || w.isClosed())) {
        // profilerVisibleAreas++;
        drawArea(w, w.selected ? selectedColor : areaStyle.color);
        if (!w.isClosed())
          w.putError(tr("Area style way is not closed."), true);
      }
      drawWay(w, areaStyle.line, areaStyle.color, w.selected);
      // }
    }
  }

  public void drawWay(Way w, LineElemStyle l, Color color, Boolean selected) {
    /*
     * show direction arrows, if draw.segment.relevant_directions_only is
     * not set, the way is tagged with a direction key (even if the tag is
     * negated as in oneway=false) or the way is selected
     */
    boolean showDirection = w.selected
        || ((!useRealWidth) && (showDirectionArrow && (!showRelevantDirectionsOnly || w
            .hasDirectionKeys())));
    /*
     * head only takes over control if the option is true, the direction
     * should be shown at all and not only because it's selected
     */
    boolean showOnlyHeadArrowOnly = showDirection && !w.selected
        && showHeadArrowOnly;
    int width = defaultSegmentWidth;
    int realWidth = 0; /* the real width of the element in meters */
    float dashed[] = new float[0];
    Color dashedColor = null;
    Node lastN;

    if (l != null) {
      if (l.color != null)
        color = l.color;
      width = l.width;
      realWidth = l.realWidth;
      dashed = l.dashed;
      dashedColor = l.dashedColor;
    }
    if (selected)
      color = selectedColor;
    if (realWidth > 0 && useRealWidth && !showDirection) {
      int tmpWidth = (int) (100 / (float) (circum / realWidth));
      if (tmpWidth > width)
        width = tmpWidth;

      /* if we have a "width" tag, try use it */
      /*
       * (this might be slow and could be improved by caching the value in
       * the Way, on the other hand only used if "real width" is enabled)
       */
      String widthTag = w.get("width");
      if (widthTag == null) {
        widthTag = w.get("est_width");
      }
      if (widthTag != null) {
        try {
          width = Integer.parseInt(widthTag);
        } catch (NumberFormatException nfe) {
        }
      }
    }

    if (w.highlighted)
      color = highlightColor;
    else if (w.selected)
      color = selectedColor;

    /* draw overlays under the way */
    if (l != null && l.overlays != null) {
      for (LineElemStyle s : l.overlays) {
        if (!s.over) {
          lastN = null;
          for (Node n : w.nodes) {
            if (lastN != null) {
              drawSeg(lastN, n,
                  s.color != null && !w.selected ? s.color
                      : color, false, s.getWidth(width),
                  s.dashed, s.dashedColor);
            }
            lastN = n;
          }
        }
      }
    }

    /* draw the way */
    lastN = null;
    Iterator<Node> it = w.nodes.iterator();
    while (it.hasNext()) {
      Node n = it.next();
      if (lastN != null)
        drawSeg(lastN, n, color, showOnlyHeadArrowOnly ? !it.hasNext()
            : showDirection, width, dashed, dashedColor);
      lastN = n;
    }

    /* draw overlays above the way */
    if (l != null && l.overlays != null) {
      for (LineElemStyle s : l.overlays) {
        if (s.over) {
          lastN = null;
          for (Node n : w.nodes) {
            if (lastN != null) {
              drawSeg(lastN, n,
                  s.color != null && !w.selected ? s.color
                      : color, false, s.getWidth(width),
                  s.dashed, s.dashedColor);
            }
            lastN = n;
          }
        }
      }
    }

    if (showOrderNumber) {
      int orderNumber = 0;
      lastN = null;
      for (Node n : w.nodes) {
        if (lastN != null) {
          orderNumber++;
          drawOrderNumber(lastN, n, orderNumber);
        }
        lastN = n;
      }
    }
    displaySegments();
  }

  public Collection<Way> joinWays(Collection<Way> join, OsmPrimitive errs) {
    Collection<Way> res = new LinkedList<Way>();
    Object[] joinArray = join.toArray();
    int left = join.size();
    while (left != 0) {
      Way w = null;
      Boolean selected = false;
      ArrayList<Node> n = null;
      Boolean joined = true;
      while (joined && left != 0) {
        joined = false;
        for (int i = 0; i < joinArray.length && left != 0; ++i) {
          if (joinArray[i] != null) {
            Way c = (Way) joinArray[i];
            if (w == null) {
              w = c;
              selected = w.selected;
              joinArray[i] = null;
              --left;
            } else {
              int mode = 0;
              int cl = c.nodes.size() - 1;
              int nl;
              if (n == null) {
                nl = w.nodes.size() - 1;
                if (w.nodes.get(nl) == c.nodes.get(0))
                  mode = 21;
                else if (w.nodes.get(nl) == c.nodes.get(cl))
                  mode = 22;
                else if (w.nodes.get(0) == c.nodes.get(0))
                  mode = 11;
                else if (w.nodes.get(0) == c.nodes.get(cl))
                  mode = 12;
              } else {
                nl = n.size() - 1;
                if (n.get(nl) == c.nodes.get(0))
                  mode = 21;
                else if (n.get(0) == c.nodes.get(cl))
                  mode = 12;
                else if (n.get(0) == c.nodes.get(0))
                  mode = 11;
                else if (n.get(nl) == c.nodes.get(cl))
                  mode = 22;
              }
              if (mode != 0) {
                joinArray[i] = null;
                joined = true;
                if (c.selected)
                  selected = true;
                --left;
                if (n == null)
                  n = new ArrayList<Node>(w.nodes);
                n.remove((mode == 21 || mode == 22) ? nl : 0);
                if (mode == 21)
                  n.addAll(c.nodes);
                else if (mode == 12)
                  n.addAll(0, c.nodes);
                else if (mode == 22) {
                  for (Node node : c.nodes)
                    n.add(nl, node);
                } else /* mode == 11 */
                {
                  for (Node node : c.nodes)
                    n.add(0, node);
                }
              }
            }
          }
        } /* for(i = ... */
      } /* while(joined) */
      if (n != null) {
        w = new Way(w);
        w.nodes.clear();
        w.nodes.addAll(n);
        w.selected = selected;
      }
      if (!w.isClosed()) {
        if (errs != null) {
          errs.putError(tr("multipolygon way ''{0}'' is not closed.",
              w.getName()), true);
        }
      }
      res.add(w);
    } /* while(left != 0) */

    return res;
  }

  public void drawSelectedMember(OsmPrimitive osm, ElemStyle style,
      Boolean area, Boolean areaselected) {
    if (osm instanceof Way) {
      if (style instanceof AreaElemStyle) {
        Way way = (Way) osm;
        AreaElemStyle areaStyle = (AreaElemStyle) style;
        drawWay(way, areaStyle.line, selectedColor, true);
        if (area && (!areaStyle.closed || way.isClosed()))
          drawArea(way, areaselected ? selectedColor
              : areaStyle.color);
      } else {
        drawWay((Way) osm, (LineElemStyle) style, selectedColor, true);
      }
    } else if (osm instanceof Node) {
      if (style != null && isZoomOk(style))
        drawNode((Node) osm, ((IconElemStyle) style).icon,
            ((IconElemStyle) style).annotate, true);
      else
        drawNode((Node) osm, selectedColor, selectedNodeSize,
            selectedNodeRadius, fillSelectedNode);
    }
    osm.mappaintDrawnCode = paintid;
  }

  public void visit(Relation r) {

    r.mappaintVisibleCode = 0;

    /* TODO: is it possible to do this like the nodes/ways code? */
    // if(profilerOmitDraw)
    // return;
    if (selectedCall) {
      for (RelationMember m : r.members) {
        if (m.member != null && !m.member.incomplete
            && !m.member.deleted && m.member instanceof Node) {
          drawSelectedMember(
              m.member,
              styles != null ? getPrimitiveStyle(m.member) : null,
              true, true);
        }
      }
      return;
    } else if (drawMultipolygon && r.keys != null
        && "multipolygon".equals(r.keys.get("type"))) {
      if (drawMultipolygon(r))
        return;
    } else if (drawRestriction && r.keys != null
        && "restriction".equals(r.keys.get("type"))) {
      drawRestriction(r);
    }

    if (r.selected) /* draw ways */
    {
      for (RelationMember m : r.members) {
        if (m.member != null && !m.member.incomplete
            && !m.member.deleted && m.member instanceof Way) /*
                                     * nodes
                                     * drawn
                                     * on
                                     * second
                                     * call
                                     */
        {
          drawSelectedMember(
              m.member,
              styles != null ? getPrimitiveStyle(m.member) : null,
              true, true);
        }
      }
    }
  }

  /*
   * this current experimental implementation will only work for standard
   * restrictions: from(Way) / via(Node) / to(Way)
   */
  public void drawRestriction(Relation r) {
    // if(restrictionDebug)
    // System.out.println("Restriction: " + r.keys.get("name") +
    // " restriction " + r.keys.get("restriction"));

    r.clearErrors();

    Way fromWay = null;
    Way toWay = null;
    OsmPrimitive via = null;

    /* find the "from", "via" and "to" elements */
    for (RelationMember m : r.members) {
      // if(restrictionDebug)
      // System.out.println("member " + m.member + " selected " +
      // r.selected);

      if (m.member == null)
        r.putError(tr("Empty member in relation."), true);
      else if (m.member.deleted)
        r.putError(tr("Deleted member ''{0}'' in relation.", m.member
            .getName()), true);
      else if (m.member.incomplete) {
        return;
      } else {
        if (m.member instanceof Way) {
          Way w = (Way) m.member;
          if (w.nodes.size() < 2) {
            r.putError(tr("Way ''{0}'' with less than two points.",
                w.getName()), true);
          } else if ("from".equals(m.role)) {
            if (fromWay != null)
              r.putError(tr("More than one \"from\" way found."),
                  true);
            else {
              fromWay = w;
            }
          } else if ("to".equals(m.role)) {
            if (toWay != null)
              r.putError(tr("More than one \"to\" way found."),
                  true);
            else {
              toWay = w;
            }
          } else if ("via".equals(m.role)) {
            if (via != null)
              r
                  .putError(
                      tr("More than one \"via\" found."),
                      true);
            else
              via = w;
          } else
            r.putError(tr("Unknown role ''{0}''.", m.role), true);
        } else if (m.member instanceof Node) {
          Node n = (Node) m.member;
          if ("via".equals(m.role)) {
            if (via != null)
              r
                  .putError(
                      tr("More than one \"via\" found."),
                      true);
            else
              via = n;
          } else
            r.putError(tr("Unknown role ''{0}''.", m.role), true);
        } else
          r.putError(tr("Unknown member type for ''{0}''.", m.member
              .getName()), true);
      }
    }

    if (fromWay == null) {
      r.putError(tr("No \"from\" way found."), true);
      return;
    }
    if (toWay == null) {
      r.putError(tr("No \"to\" way found."), true);
      return;
    }
    if (via == null) {
      r.putError(tr("No \"via\" node or way found."), true);
      return;
    }

    Node viaNode;
    if (via instanceof Node) {
      viaNode = (Node) via;
      if (!fromWay.isFirstLastNode(viaNode)) {
        r
            .putError(
                tr("The \"from\" way doesn't start or end at a \"via\" node."),
                true);
        return;
      }
      if (!toWay.isFirstLastNode(viaNode))
        r
            .putError(
                tr("The \"to\" way doesn't start or end at a \"via\" node."),
                true);
    } else {
      Way viaWay = (Way) via;
      Node firstNode = viaWay.firstNode();
      Node lastNode = viaWay.lastNode();
      if (fromWay.isFirstLastNode(firstNode))
        viaNode = firstNode;
      else if (fromWay.isFirstLastNode(lastNode))
        viaNode = firstNode;
      else {
        r
            .putError(
                tr("The \"from\" way doesn't start or end at the \"via\" way."),
                true);
        return;
      }
      if (!toWay.isFirstLastNode(viaNode == firstNode ? lastNode
          : firstNode))
        r
            .putError(
                tr("The \"to\" way doesn't start or end at the \"via\" way."),
                true);
    }

    /* find the "direct" nodes before the via node */
    Node fromNode = null;
    if (fromWay.firstNode() == via) {
      // System.out.println("From way heading away from via");
      fromNode = fromWay.nodes.get(1);
    } else {
      // System.out.println("From way heading towards via");
      fromNode = fromWay.nodes.get(fromWay.nodes.size() - 2);
    }

    Point pFrom = nc.getPoint(fromNode.getEastNorth());
    Point pVia = nc.getPoint(viaNode.getEastNorth());

    // if(restrictionDebug) {
    /* find the "direct" node after the via node */
    // Node toNode = null;
    // if(toWay.firstNode() == via) {
    // System.out.println("To way heading away from via");
    // toNode = toWay.nodes.get(1);
    // } else {
    // System.out.println("To way heading towards via");
    // toNode = toWay.nodes.get(toWay.nodes.size()-2);
    // }
    // Point pTo = nc.getPoint(toNode.eastNorth);
    // /* debug output of interesting nodes */
    // System.out.println("From: " + fromNode);
    // drawNode(fromNode, selectedColor, selectedNodeSize,
    // selectedNodeRadius, fillSelectedNode);
    // System.out.println("Via: " + via);
    // drawNode(via, selectedColor, selectedNodeSize, selectedNodeRadius,
    // fillSelectedNode);
    // System.out.println("To: " + toNode);
    // drawNode(toNode, selectedColor, selectedNodeSize, selectedNodeRadius,
    // fillSelectedNode);
    // System.out.println("From X: " + pFrom.x + " Y " + pFrom.y);
    // System.out.println("Via  X: " + pVia.x + " Y " + pVia.y);
    // System.out.println("To   X: " + pTo.x + " Y " + pTo.y);
    // }
    /*
     * starting from via, go back the "from" way a few pixels (calculate the
     * vector vx/vy with the specified length and the direction away from
     * the "via" node along the first segment of the "from" way)
     */
    double distanceFromVia = 14;
    double dx = (pFrom.x >= pVia.x) ? (pFrom.x - pVia.x)
        : (pVia.x - pFrom.x);
    double dy = (pFrom.y >= pVia.y) ? (pFrom.y - pVia.y)
        : (pVia.y - pFrom.y);

    double fromAngle;
    if (dx == 0.0) {
      fromAngle = Math.PI / 2;
    } else {
      fromAngle = Math.atan(dy / dx);
    }
    double fromAngleDeg = Math.toDegrees(fromAngle);

    double vx = distanceFromVia * Math.cos(fromAngle);
    double vy = distanceFromVia * Math.sin(fromAngle);

    if (pFrom.x < pVia.x)
      vx = -vx;
    if (pFrom.y < pVia.y)
      vy = -vy;

    // if(restrictionDebug)
    // System.out.println("vx " + vx + " vy " + vy);

    /*
     * go a few pixels away from the way (in a right angle) (calculate the
     * vx2/vy2 vector with the specified length and the direction 90degrees
     * away from the first segment of the "from" way)
     */
    double distanceFromWay = 10;
    double vx2 = 0;
    double vy2 = 0;
    double iconAngle = 0;

    if (pFrom.x >= pVia.x && pFrom.y >= pVia.y) {
      if (!leftHandTraffic) {
        vx2 = distanceFromWay
            * Math.cos(Math.toRadians(fromAngleDeg - 90));
        vy2 = distanceFromWay
            * Math.sin(Math.toRadians(fromAngleDeg - 90));
      } else {
        vx2 = distanceFromWay
            * Math.cos(Math.toRadians(fromAngleDeg + 90));
        vy2 = distanceFromWay
            * Math.sin(Math.toRadians(fromAngleDeg + 90));
      }
      iconAngle = 270 + fromAngleDeg;
    }
    if (pFrom.x < pVia.x && pFrom.y >= pVia.y) {
      if (!leftHandTraffic) {
        vx2 = distanceFromWay * Math.sin(Math.toRadians(fromAngleDeg));
        vy2 = distanceFromWay * Math.cos(Math.toRadians(fromAngleDeg));
      } else {
        vx2 = distanceFromWay
            * Math.sin(Math.toRadians(fromAngleDeg + 180));
        vy2 = distanceFromWay
            * Math.cos(Math.toRadians(fromAngleDeg + 180));
      }
      iconAngle = 90 - fromAngleDeg;
    }
    if (pFrom.x < pVia.x && pFrom.y < pVia.y) {
      if (!leftHandTraffic) {
        vx2 = distanceFromWay
            * Math.cos(Math.toRadians(fromAngleDeg + 90));
        vy2 = distanceFromWay
            * Math.sin(Math.toRadians(fromAngleDeg + 90));
      } else {
        vx2 = distanceFromWay
            * Math.cos(Math.toRadians(fromAngleDeg - 90));
        vy2 = distanceFromWay
            * Math.sin(Math.toRadians(fromAngleDeg - 90));
      }
      iconAngle = 90 + fromAngleDeg;
    }
    if (pFrom.x >= pVia.x && pFrom.y < pVia.y) {
      if (!leftHandTraffic) {
        vx2 = distanceFromWay
            * Math.sin(Math.toRadians(fromAngleDeg + 180));
        vy2 = distanceFromWay
            * Math.cos(Math.toRadians(fromAngleDeg + 180));
      } else {
        vx2 = distanceFromWay * Math.sin(Math.toRadians(fromAngleDeg));
        vy2 = distanceFromWay * Math.cos(Math.toRadians(fromAngleDeg));
      }
      iconAngle = 270 - fromAngleDeg;
    }

    IconElemStyle nodeStyle = getPrimitiveNodeStyle(r);

    if (nodeStyle == null) {
      r.putError(tr("Style for restriction {0} not found.", r.keys
          .get("restriction")), true);
      return;
    }

    /* rotate icon with direction last node in from to */
    // if(restrictionDebug)
    // System.out.println("Deg1 " + fromAngleDeg + " Deg2 " + (fromAngleDeg
    // + 180) + " Icon " + iconAngle);
    ImageIcon rotatedIcon = ImageProvider.createRotatedImage(
        null /* icon2 */, nodeStyle.icon, iconAngle);

    /* scale down icon to 16*16 pixels */
    ImageIcon smallIcon = new ImageIcon(rotatedIcon.getImage()
        .getScaledInstance(16, 16, Image.SCALE_SMOOTH));
    int w = smallIcon.getIconWidth(), h = smallIcon.getIconHeight();
    smallIcon.paintIcon(Main.map.mapView, g, (int) (pVia.x + vx + vx2) - w
        / 2, (int) (pVia.y + vy + vy2) - h / 2);

    if (r.selected) {
      g.setColor(selectedColor);
      g.drawRect((int) (pVia.x + vx + vx2) - w / 2 - 2, (int) (pVia.y
          + vy + vy2)
          - h / 2 - 2, w + 4, h + 4);
    }
  }

  public Boolean drawMultipolygon(Relation r) {
    Collection<Way> inner = new LinkedList<Way>();
    Collection<Way> outer = new LinkedList<Way>();
    Collection<Way> innerclosed = new LinkedList<Way>();
    Collection<Way> outerclosed = new LinkedList<Way>();
    Boolean incomplete = false;
    Boolean drawn = false;

    r.clearErrors();

    for (RelationMember m : r.members) {
      if (m.member == null)
        r.putError(tr("Empty member in relation."), true);
      else if (m.member.deleted)
        r.putError(tr("Deleted member ''{0}'' in relation.", m.member
            .getName()), true);
      else if (m.member.incomplete)
        incomplete = true;
      else {
        if (m.member instanceof Way) {
          Way w = (Way) m.member;
          if (w.nodes.size() < 2) {
            r.putError(tr("Way ''{0}'' with less than two points.",
                w.getName()), true);
          } else if ("inner".equals(m.role))
            inner.add(w);
          else if ("outer".equals(m.role))
            outer.add(w);
          else {
            r.putError(tr(
                "No useful role ''{0}'' for Way ''{1}''.",
                m.role == null ? "" : m.role, w.getName()),
                true);
            if (m.role == null || m.role.length() == 0)
              outer.add(w);
            else if (r.selected)
              drawSelectedMember(
                  m.member,
                  styles != null ? getPrimitiveStyle(m.member)
                      : null, true, true);
          }
        } else {
          r.putError(tr("Non-Way ''{0}'' in multipolygon.", m.member
              .getName()), true);
        }
      }
    }

    ElemStyle wayStyle = styles != null ? getPrimitiveStyle(r) : null;
    if (styles != null
        && (wayStyle == null || !(wayStyle instanceof AreaElemStyle))) {
      for (Way w : outer) {
        if (wayStyle == null || !(wayStyle instanceof AreaElemStyle))
          wayStyle = styles.get(w);
      }
      r.mappaintStyle = wayStyle;
    }

    if (wayStyle != null && wayStyle instanceof AreaElemStyle) {
      Boolean zoomok = isZoomOk(wayStyle);
      Boolean visible = false;
      Collection<Way> join = new LinkedList<Way>();

      drawn = true;
      for (Way w : outer) {
        if (w.isClosed())
          outerclosed.add(w);
        else
          join.add(w);
      }
      if (join.size() != 0) {
        for (Way w : joinWays(join, incomplete ? null : r))
          outerclosed.add(w);
      }

      join.clear();
      for (Way w : inner) {
        if (w.isClosed())
          innerclosed.add(w);
        else
          join.add(w);
      }
      if (join.size() != 0) {
        for (Way w : joinWays(join, incomplete ? null : r))
          innerclosed.add(w);
      }

      if (outerclosed.size() == 0) {
        r.putError(tr("No outer way for multipolygon ''{0}''.", r
            .getName()), true);
        visible = true; /* prevent killing remaining ways */
      } else if (zoomok) {
        class PolyData {
          public Polygon poly = new Polygon();
          public Way way;
          private Point p = null;
          private Collection<Polygon> inner = null;

          PolyData(Way w) {
            way = w;
            for (Node n : w.nodes) {
              p = nc.getPoint(n.getEastNorth());
              poly.addPoint(p.x, p.y);
            }
          }

          public int contains(Polygon p) {
            int contains = p.npoints;
            for (int i = 0; i < p.npoints; ++i) {
              if (poly.contains(p.xpoints[i], p.ypoints[i]))
                --contains;
            }
            if (contains == 0)
              return 1;
            if (contains == p.npoints)
              return 0;
            return 2;
          }

          public void addInner(Polygon p) {
            if (inner == null)
              inner = new ArrayList<Polygon>();
            inner.add(p);
          }

          public boolean isClosed() {
            return (poly.npoints >= 3
                && poly.xpoints[0] == poly.xpoints[poly.npoints - 1] && poly.ypoints[0] == poly.ypoints[poly.npoints - 1]);
          }

          public Polygon get() {
            if (inner != null) {
              for (Polygon pp : inner) {
                for (int i = 0; i < pp.npoints; ++i)
                  poly.addPoint(pp.xpoints[i], pp.ypoints[i]);
                poly.addPoint(p.x, p.y);
              }
              inner = null;
            }
            return poly;
          }
        }
        LinkedList<PolyData> poly = new LinkedList<PolyData>();
        for (Way w : outerclosed) {
          poly.add(new PolyData(w));
        }
        for (Way wInner : innerclosed) {
          Polygon polygon = new Polygon();

          for (Node n : wInner.nodes) {
            Point pInner = nc.getPoint(n.getEastNorth());
            polygon.addPoint(pInner.x, pInner.y);
          }
          if (!wInner.isClosed()) {
            Point pInner = nc.getPoint(wInner.nodes.get(0)
                .getEastNorth());
            polygon.addPoint(pInner.x, pInner.y);
          }
          PolyData o = null;
          for (PolyData pd : poly) {
            Integer c = pd.contains(polygon);
            if (c >= 1) {
              if (c > 1 && pd.way.isClosed()) {
                r
                    .putError(
                        tr(
                            "Intersection between ways ''{0}'' and ''{1}''.",
                            pd.way.getName(),
                            wInner.getName()), true);
              }
              if (o == null || o.contains(pd.poly) > 0)
                o = pd;
            }
          }
          if (o == null) {
            if (!incomplete) {
              r.putError(tr("Inner way ''{0}'' is outside.",
                  wInner.getName()), true);
            }
            o = poly.get(0);
          }
          o.addInner(polygon);
        }
        AreaElemStyle areaStyle = (AreaElemStyle) wayStyle;
        for (PolyData pd : poly) {
          Polygon p = pd.get();
          if (isPolygonVisible(p)
              && (!areaStyle.closed || pd.isClosed())) {
            drawAreaPolygon(p,
                (pd.way.selected || r.selected) ? selectedColor
                    : areaStyle.color);
            visible = true;
          }
        }
      }
      if (!visible) /* nothing visible, so disable relation and all its ways */
      {
        r.mappaintVisibleCode = viewid;
        for (Way wInner : inner)
          wInner.mappaintVisibleCode = viewid;
        for (Way wOuter : outer)
          wOuter.mappaintVisibleCode = viewid;
        return drawn;
      }
      for (Way wInner : inner) {
        ElemStyle innerStyle = getPrimitiveStyle(wInner);
        if (innerStyle == null) {
          if (zoomok
              && (wInner.mappaintDrawnCode != paintid || outer
                  .size() == 0)) {
            drawWay(wInner, ((AreaElemStyle) wayStyle).line,
                ((AreaElemStyle) wayStyle).color,
                wInner.selected || r.selected);
          }
          wInner.mappaintDrawnCode = paintid;
        } else {
          if (r.selected) {
            drawSelectedMember(wInner, innerStyle, !wayStyle
                .equals(innerStyle), wInner.selected);
          }
          if (wayStyle.equals(innerStyle)) {
            r
                .putError(
                    tr(
                        "Style for inner way ''{0}'' equals multipolygon.",
                        wInner.getName()), false);
            if (!r.selected)
              wInner.mappaintDrawnAreaCode = paintid;
          }
        }
      }
      for (Way wOuter : outer) {
        ElemStyle outerStyle = getPrimitiveStyle(wOuter);
        if (outerStyle == null) {
          if (zoomok) {
            drawWay(wOuter, ((AreaElemStyle) wayStyle).line,
                ((AreaElemStyle) wayStyle).color,
                wOuter.selected || r.selected);
          }
          wOuter.mappaintDrawnCode = paintid;
        } else {
          if (outerStyle instanceof AreaElemStyle
              && !wayStyle.equals(outerStyle)) {
            r.putError(tr(
                "Style for outer way ''{0}'' mismatches.",
                wOuter.getName()), true);
          }
          if (r.selected) {
            drawSelectedMember(wOuter, outerStyle, false, false);
          } else if (outerStyle instanceof AreaElemStyle)
            wOuter.mappaintDrawnAreaCode = paintid;
        }
      }
    }
    return drawn;
  }

  protected Polygon getPolygon(Way w) {
    Polygon polygon = new Polygon();

    for (Node n : w.nodes) {
      Point p = nc.getPoint(n.getEastNorth());
      polygon.addPoint(p.x, p.y);
    }
    return polygon;
  }

  protected void drawArea(Way w, Color color) {
    Polygon polygon = getPolygon(w);

    /* set the opacity (alpha) level of the filled polygon */
    g.setColor(new Color(color.getRed(), color.getGreen(), color.getBlue(),
        fillAlpha));
    g.fillPolygon(polygon);
  }

  protected void drawAreaPolygon(Polygon polygon, Color color) {
    /* set the opacity (alpha) level of the filled polygon */
    g.setColor(new Color(color.getRed(), color.getGreen(), color.getBlue(),
        fillAlpha));
    g.fillPolygon(polygon);
  }

  protected void drawNode(Node n, ImageIcon icon, boolean annotate,
      Boolean selected) {
    Point p = nc.getPoint(n.getEastNorth());
    if ((p.x < 0) || (p.y < 0) || (p.x > nc.getWidth())
        || (p.y > nc.getHeight()))
      return;

    // profilerVisibleNodes++;

    int w = icon.getIconWidth(), h = icon.getIconHeight();
    icon.paintIcon(Main.map.mapView, g, p.x - w / 2, p.y - h / 2);
    if (showNames > dist) {
      String name = getNodeName(n);
      if (name != null && annotate) {
        g.setColor(textColor);
        Font defaultFont = g.getFont();
        g.setFont(orderFont);
        g.drawString(name, p.x + w / 2 + 2, p.y + h / 2 + 2);
        g.setFont(defaultFont);
      }
    }
    if (selected) {
      g.setColor(selectedColor);
      g.drawRect(p.x - w / 2 - 2, p.y - h / 2 - 2, w + 4, h + 4);
    }
  }

  protected String getNodeName(Node n) {
    String name = null;
    if (n.keys != null) {
      for (String rn : regionalNameOrder) {
        name = n.keys.get(rn);
        if (name != null)
          break;
      }
    }
    return name;
  }

  private void drawSeg(Node n1, Node n2, Color col, boolean showDirection,
      int width, float dashed[], Color dashedColor) {
    // profilerSegments++;
    if (col != currentColor || width != currentWidth
        || !Arrays.equals(dashed, currentDashed)
        || dashedColor != currentDashedColor) {
      displaySegments(col, width, dashed, dashedColor);
    }
    Point p1 = nc.getPoint(n1.getEastNorth());
    Point p2 = nc.getPoint(n2.getEastNorth());

    if (!isSegmentVisible(p1, p2)) {
      return;
    }
    // profilerVisibleSegments++;
    currentPath.moveTo(p1.x, p1.y);
    currentPath.lineTo(p2.x, p2.y);

    if (showDirection) {
      double t = Math.atan2(p2.y - p1.y, p2.x - p1.x) + Math.PI;
      currentPath.lineTo((int) (p2.x + 10 * Math.cos(t - PHI)),
          (int) (p2.y + 10 * Math.sin(t - PHI)));
      currentPath.moveTo((int) (p2.x + 10 * Math.cos(t + PHI)),
          (int) (p2.y + 10 * Math.sin(t + PHI)));
      currentPath.lineTo(p2.x, p2.y);
    }
  }

  protected void displaySegments() {
    displaySegments(null, 0, new float[0], null);
  }

  protected void displaySegments(Color newColor, int newWidth,
      float newDash[], Color newDashedColor) {
    if (currentPath != null) {
      Graphics2D g2d = (Graphics2D) g;
      g2d.setColor(inactive ? inactiveColor : currentColor);
      if (currentStroke == null && useStrokes > dist) {
        if (currentDashed.length > 0) {
          try {
            g2d.setStroke(new BasicStroke(currentWidth,
                BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND,
                0, currentDashed, 0));
          } catch (IllegalArgumentException e) {
            g2d.setStroke(new BasicStroke(currentWidth,
                BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
          }
        } else
          g2d.setStroke(new BasicStroke(currentWidth,
              BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
      }
      g2d.draw(currentPath);

      if (currentDashedColor != null) {
        g2d.setColor(currentDashedColor);
        if (currentStroke == null && useStrokes > dist) {
          if (currentDashed.length > 0) {
            float[] currentDashedOffset = new float[currentDashed.length];
            System.arraycopy(currentDashed, 1, currentDashedOffset,
                0, currentDashed.length - 1);
            currentDashedOffset[currentDashed.length - 1] = currentDashed[0];
            float offset = currentDashedOffset[0];
            try {
              g2d.setStroke(new BasicStroke(currentWidth,
                  BasicStroke.CAP_BUTT,
                  BasicStroke.JOIN_ROUND, 0,
                  currentDashedOffset, offset));
            } catch (IllegalArgumentException e) {
              g2d.setStroke(new BasicStroke(currentWidth,
                  BasicStroke.CAP_ROUND,
                  BasicStroke.JOIN_ROUND));
            }
          } else
            g2d.setStroke(new BasicStroke(currentWidth,
                BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
        }
        g2d.draw(currentPath);
      }

      if (useStrokes > dist)
        g2d.setStroke(new BasicStroke(1));

      currentPath = new GeneralPath();
      currentColor = newColor;
      currentWidth = newWidth;
      currentDashed = newDash;
      currentDashedColor = newDashedColor;
      currentStroke = null;
    }
  }

  /**
   * Draw the node as small rectangle with the given color.
   *
   * @param n
   *            The node to draw.
   * @param color
   *            The color of the node.
   */
  public void drawNode(Node n, Color color, int size, int radius, boolean fill) {
    if (isZoomOk(null) && size > 1) {
      Point p = nc.getPoint(n.getEastNorth());
      if ((p.x < 0) || (p.y < 0) || (p.x > nc.getWidth())
          || (p.y > nc.getHeight()))
        return;

      // profilerVisibleNodes++;

      g.setColor(color);
      if (fill) {
        g.fillRect(p.x - radius, p.y - radius, size, size);
        g.drawRect(p.x - radius, p.y - radius, size, size);
      } else
        g.drawRect(p.x - radius, p.y - radius, size, size);

      if (showNames > dist) {
        String name = getNodeName(n);
        if (name != null /* && annotate */) {
          g.setColor(textColor);
          Font defaultFont = g.getFont();
          g.setFont(orderFont);
          g.drawString(name, p.x + radius + 2, p.y + radius + 2);
          g.setFont(defaultFont);
        }
      }
    }
  }

  public void getColors() {
    super.getColors();
    untaggedColor = Main.pref.getColor(marktr("untagged"), Color.GRAY);
    textColor = Main.pref.getColor(marktr("text"), Color.WHITE);
  }

  /* Shows areas before non-areas */
  public void visitAll(DataSet data, Boolean virtual) {

    // boolean profiler = Main.pref.getBoolean("mappaint.profiler",false);
    // profilerOmitDraw =
    // Main.pref.getBoolean("mappaint.profiler.omitdraw",false);

    useStyleCache = Main.pref.getBoolean("mappaint.cache", true);
    fillAreas = Main.pref.getInteger("mappaint.fillareas", 10000000);
    fillAlpha = Math.min(255, Math.max(0, Integer.valueOf(Main.pref
        .getInteger("mappaint.fillalpha", 50))));
    showNames = Main.pref.getInteger("mappaint.shownames", 10000000);
    showIcons = Main.pref.getInteger("mappaint.showicons", 10000000);
    useStrokes = Main.pref.getInteger("mappaint.strokes", 10000000);
    LatLon ll1 = nc.getLatLon(0, 0);
    LatLon ll2 = nc.getLatLon(100, 0);
    dist = ll1.greatCircleDistance(ll2);

    // long profilerStart = java.lang.System.currentTimeMillis();
    // long profilerLast = profilerStart;
    // int profilerN;
    // if(profiler)
    // System.out.println("Mappaint Profiler (" +
    // (useStyleCache ? "cache=true, " : "cache=false, ") +
    // "fillareas " + fillAreas + ", " +
    // "fillalpha=" + fillAlpha + "%, " +
    // "dist=" + (int)dist + "m)");

    getSettings(virtual);
    useRealWidth = Main.pref.getBoolean("mappaint.useRealWidth", false);
    zoomLevelDisplay = Main.pref.getBoolean("mappaint.zoomLevelDisplay",
        false);
    circum = ((NavigatableComponent) Main.mapView).getScale() * 100 * Main.proj.scaleFactor()
        * 40041455; /* circumference of the earth in meter */
    styles = MapPaintStyles.getStyles().getStyleSet();
    drawMultipolygon = Main.pref.getBoolean("mappaint.multipolygon", true);
    drawRestriction = Main.pref.getBoolean("mappaint.restriction", true);
    // restrictionDebug =
    // Main.pref.getBoolean("mappaint.restriction.debug",false);
    leftHandTraffic = Main.pref.getBoolean("mappaint.lefthandtraffic",
        false);
    orderFont = new Font(Main.pref.get("mappaint.font", "Helvetica"),
        Font.PLAIN, Main.pref.getInteger("mappaint.fontsize", 8));
    String[] names = { "name:" + Main.getLanguageCode(), "name",
        "int_name", "ref", "operator", "brand", "addr:housenumber" };
    regionalNameOrder = Main.pref.getCollection("mappaint.nameOrder",
        Arrays.asList(names));
    Point bl = new Point(0, nc.getHeight() - 1), tr = new Point(nc
        .getWidth() - 1, 0);
    if (nc instanceof RotatableView) {
      double angle = ((RotatableView) nc).getAngle();
      double x0 = nc.getWidth() / 2;
      double y0 = nc.getHeight() / 2;
      double cos = Math.cos(-angle), sin = Math.sin(-angle);
      // enlarge the bounding box *0.5
      bl.x -= x0;
      tr.x += x0;
      bl.y += y0;
      tr.y -= y0;
      bl = new Point((int) (x0 + cos * (bl.x - x0) - sin * (bl.y - y0)),
          (int) (y0 + sin * (bl.x - x0) + cos * (bl.y - y0)));
      tr = new Point((int) (x0 + cos * (tr.x - x0) - sin * (tr.y - y0)),
          (int) (y0 + sin * (tr.x - x0) + cos * (tr.y - y0)));
    }
    minEN = nc.getEastNorth(bl.x, bl.y);
    maxEN = nc.getEastNorth(tr.x, tr.y);

    selectedCall = false;
    ++paintid;
    viewid = nc.getViewID();

    // profilerVisibleNodes = 0;
    // profilerVisibleWays = 0;
    // profilerVisibleAreas = 0;
    // profilerSegments = 0;
    // profilerVisibleSegments = 0;

    // if(profiler)
    // {
    // System.out.format("Prepare  : %5dms\n",
    // (java.lang.System.currentTimeMillis()-profilerLast));
    // profilerLast = java.lang.System.currentTimeMillis();
    // }

    if (fillAreas > dist && styles != null && styles.hasAreas()) {
      Collection<Way> noAreaWays = new LinkedList<Way>();

      /*** RELATIONS ***/
      // profilerN = 0;
      for (final Relation osm : data.relations) {
        if (!osm.deleted && !osm.incomplete
            && osm.mappaintVisibleCode != viewid) {
          osm.visit(this);
          // profilerN++;
        }
      }

      // if(profiler)
      // {
      // System.out.format("Relations: %5dms, calls=%7d\n",
      // (java.lang.System.currentTimeMillis()-profilerLast), profilerN);
      // profilerLast = java.lang.System.currentTimeMillis();
      // }

      /*** AREAS ***/
      // profilerN = 0;
      for (final Way osm : data.ways) {
        if (!osm.incomplete && !osm.deleted
            && osm.mappaintVisibleCode != viewid
            && osm.mappaintDrawnCode != paintid) {
          if (isPrimitiveArea(osm)
              && osm.mappaintDrawnAreaCode != paintid) {
            osm.visit(this);
            // profilerN++;
          } else
            noAreaWays.add(osm);
        }
      }

      // if(profiler)
      // {
      // System.out.format("Areas    : %5dms, calls=%7d, visible=%d\n",
      // (java.lang.System.currentTimeMillis()-profilerLast), profilerN,
      // profilerVisibleAreas);
      // profilerLast = java.lang.System.currentTimeMillis();
      // }

      /*** WAYS ***/
      // profilerN = 0;
      fillAreas = 0;
      for (final OsmPrimitive osm : noAreaWays) {
        osm.visit(this);
        // profilerN++;
      }

      // if(profiler)
      // {
      // System.out.format("Ways     : %5dms, calls=%7d, visible=%d\n",
      // (java.lang.System.currentTimeMillis()-profilerLast), profilerN,
      // profilerVisibleWays);
      // profilerLast = java.lang.System.currentTimeMillis();
      // }
    } else {
      /*** WAYS (filling disabled) ***/
      // profilerN = 0;
      for (final OsmPrimitive osm : data.ways)
        if (!osm.incomplete && !osm.deleted && !osm.selected
            && osm.mappaintVisibleCode != viewid) {
          osm.visit(this);
          // profilerN++;
        }

      // if(profiler)
      // {
      // System.out.format("Ways     : %5dms, calls=%7d, visible=%d\n",
      // (java.lang.System.currentTimeMillis()-profilerLast), profilerN,
      // profilerVisibleWays);
      // profilerLast = java.lang.System.currentTimeMillis();
      // }
    }

    /*** SELECTED ***/
    selectedCall = true;
    // profilerN = 0;
    for (final OsmPrimitive osm : data.getSelected()) {
      if (!osm.incomplete && !osm.deleted && !(osm instanceof Node)
          && osm.mappaintVisibleCode != viewid
          && osm.mappaintDrawnCode != paintid) {
        osm.visit(this);
        // profilerN++;
      }
    }

    // if(profiler)
    // {
    // System.out.format("Selected : %5dms, calls=%7d\n",
    // (java.lang.System.currentTimeMillis()-profilerLast), profilerN);
    // profilerLast = java.lang.System.currentTimeMillis();
    // }

    /*** DISPLAY CACHED SEGMENTS (WAYS) NOW ***/
    displaySegments();

    /*** NODES ***/
    // profilerN = 0;
    for (final OsmPrimitive osm : data.nodes)
      if (!osm.incomplete && !osm.deleted
          && osm.mappaintVisibleCode != viewid
          && osm.mappaintDrawnCode != paintid) {
        osm.visit(this);
        // profilerN++;
      }

    // if(profiler)
    // {
    // System.out.format("Nodes    : %5dms, calls=%7d, visible=%d\n",
    // (java.lang.System.currentTimeMillis()-profilerLast), profilerN,
    // profilerVisibleNodes);
    // profilerLast = java.lang.System.currentTimeMillis();
    // }

    /*** VIRTUAL ***/
    if (virtualNodeSize != 0) {
      // profilerN = 0;
      currentColor = nodeColor;
      for (final OsmPrimitive osm : data.ways)
        if (!osm.incomplete && !osm.deleted
            && osm.mappaintVisibleCode != viewid) {
          /* TODO: move this into the SimplePaint code? */
          // if(!profilerOmitDraw)
          visitVirtual((Way) osm);
          // profilerN++;
        }

      // if(profiler)
      // {
      // System.out.format("Virtual  : %5dms, calls=%7d\n",
      // (java.lang.System.currentTimeMillis()-profilerLast), profilerN);
      // profilerLast = java.lang.System.currentTimeMillis();
      // }

      displaySegments(null);
    }

    // if(profiler)
    // {
    // System.out.format("Segments :          calls=%7d, visible=%d\n",
    // profilerSegments, profilerVisibleSegments);
    // System.out.format("All      : %5dms\n",
    // (profilerLast-profilerStart));
    // }
  }

  /**
   * Draw a number of the order of the two consecutive nodes within the
   * parents way
   */
  protected void drawOrderNumber(Node n1, Node n2, int orderNumber) {
    Point p1 = nc.getPoint(n1.getEastNorth());
    Point p2 = nc.getPoint(n2.getEastNorth());
    drawOrderNumber(p1, p2, orderNumber);
  }
}
TOP

Related Classes of org.openstreetmap.josm.data.osm.visitor.MapPaintVisitor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.