@Test
  public void testCopy() {
    Graph g = initUnsorted(createGraph());
    EdgeIteratorState eb = g.edge(6, 5, 11, true);
    eb.setWayGeometry(Helper.createPointList(12, 10, -1, 3));
    LevelGraph lg = new GraphBuilder(encodingManager).levelGraphCreate();
    GHUtility.copyTo(g, lg);
    eb = lg.getEdgeProps(eb.getEdge(), 6);
    assertEquals(Helper.createPointList(-1, 3, 12, 10), eb.getWayGeometry());
    assertEquals(0, lg.getLevel(0));
    assertEquals(0, lg.getLevel(1));
    assertEquals(0, lg.getLatitude(0), 1e-6);
    assertEquals(1, lg.getLongitude(0), 1e-6);
    assertEquals(2.5, lg.getLatitude(1), 1e-6);
    assertEquals(4.5, lg.getLongitude(1), 1e-6);
    assertEquals(9, lg.getNodes());
    EdgeIterator iter = lg.createEdgeExplorer().setBaseNode(8);
    iter.next();
    assertEquals(2.05, iter.getDistance(), 1e-6);
    assertEquals("11", BitUtil.toBitString(iter.getFlags(), 2));
    iter.next();
    assertEquals(0.5, iter.getDistance(), 1e-6);
    assertEquals("11", BitUtil.toBitString(iter.getFlags(), 2));

    iter = lg.createEdgeExplorer().setBaseNode(7);
    iter.next();
    assertEquals(2.1, iter.getDistance(), 1e-6);
    assertEquals("01", BitUtil.toBitString(iter.getFlags(), 2));
    assertTrue(iter.next());
    assertEquals(0.7, iter.getDistance(), 1e-6);
  }
  @Test
  public void testGetAllEdges() {
    graph = createGraph();
    graph.edge(0, 1, 2, true);
    graph.edge(3, 1, 1, false);
    graph.edge(3, 2, 1, false);

    EdgeIterator iter = graph.getAllEdges();
    assertTrue(iter.next());
    int edgeId = iter.getEdge();
    assertEquals(0, iter.getBaseNode());
    assertEquals(1, iter.getAdjNode());
    assertEquals(2, iter.getDistance(), 1e-6);

    assertTrue(iter.next());
    int edgeId2 = iter.getEdge();
    assertEquals(1, edgeId2 - edgeId);
    assertEquals(1, iter.getBaseNode());
    assertEquals(3, iter.getAdjNode());

    assertTrue(iter.next());
    assertEquals(2, iter.getBaseNode());
    assertEquals(3, iter.getAdjNode());

    assertFalse(iter.next());
  }
  /** Finds shortcuts, does not change the underlying graph. */
  void findShortcuts(ShortcutHandler sch) {
    long tmpDegreeCounter = 0;
    EdgeIterator incomingEdges = vehicleInExplorer.setBaseNode(sch.getNode());
    // collect outgoing nodes (goal-nodes) only once
    while (incomingEdges.next()) {
      int u_fromNode = incomingEdges.getAdjNode();
      // accept only uncontracted nodes
      if (g.getLevel(u_fromNode) != 0) continue;

      double v_u_weight = incomingEdges.getDistance();
      int skippedEdge1 = incomingEdges.getEdge();
      int incomingEdgeOrigCount = getOrigEdgeCount(skippedEdge1);
      // collect outgoing nodes (goal-nodes) only once
      EdgeIterator outgoingEdges = vehicleOutExplorer.setBaseNode(sch.getNode());
      // force fresh maps etc as this cannot be determined by from node alone (e.g. same from node
      // but different avoidNode)
      algo.clear();
      tmpDegreeCounter++;
      while (outgoingEdges.next()) {
        int w_toNode = outgoingEdges.getAdjNode();
        // add only uncontracted nodes
        if (g.getLevel(w_toNode) != 0 || u_fromNode == w_toNode) {
          continue;
        }

        // Limit weight as ferries or forbidden edges can increase local search too much.
        // If we decrease the correct weight we only explore less and introduce more shortcuts.
        // I.e. no change to accuracy is made.
        double existingDirectWeight = v_u_weight + outgoingEdges.getDistance();
        algo.setLimitWeight(existingDirectWeight)
            .setLimitVisitedNodes((int) meanDegree * 100)
            .setEdgeFilter(levelEdgeFilter.setAvoidNode(sch.getNode()));

        dijkstraSW.start();
        dijkstraCount++;
        int endNode = algo.findEndNode(u_fromNode, w_toNode);
        dijkstraSW.stop();

        // compare end node as the limit could force dijkstra to finish earlier
        if (endNode == w_toNode && algo.getWeight(endNode) <= existingDirectWeight)
          // FOUND witness path, so do not add shortcut
          continue;

        sch.foundShortcut(
            u_fromNode,
            w_toNode,
            existingDirectWeight,
            outgoingEdges,
            skippedEdge1,
            incomingEdgeOrigCount);
      }
    }
    if (sch instanceof AddShortcutHandler) {
      // sliding mean value when using "*2" => slower changes
      meanDegree = (meanDegree * 2 + tmpDegreeCounter) / 3;
      // meanDegree = (meanDegree + tmpDegreeCounter) / 2;
    }
  }
  @Test
  public void testSimpleDelete2() {
    graph = createGraph();
    NodeAccess na = graph.getNodeAccess();
    assertEquals(-1, getIdOf(graph, 12));
    na.setNode(9, 9, 1);
    assertEquals(-1, getIdOf(graph, 12));

    na.setNode(11, 11, 1);
    na.setNode(12, 12, 1);

    // mini subnetwork which gets completely removed:
    graph.edge(5, 10, 510, true);
    graph.markNodeRemoved(5);
    graph.markNodeRemoved(10);

    PointList pl = new PointList();
    pl.add(1, 2, Double.NaN);
    pl.add(1, 3, Double.NaN);
    graph.edge(9, 11, 911, true).setWayGeometry(pl);
    graph.edge(9, 12, 912, true).setWayGeometry(pl);

    assertEquals(13, graph.getNodes());
    assertEquals(Arrays.<String>asList(), GHUtility.getProblems(graph));

    // perform deletion
    graph.optimize();

    assertEquals(11, graph.getNodes());
    assertEquals(Arrays.<String>asList(), GHUtility.getProblems(graph));

    int id11 = getIdOf(graph, 11); // is now 10
    int id12 = getIdOf(graph, 12); // is now 5
    int id9 = getIdOf(graph, 9); // is now 9
    assertEquals(
        GHUtility.asSet(id12, id11), GHUtility.getNeighbors(carAllExplorer.setBaseNode(id9)));
    assertEquals(GHUtility.asSet(id9), GHUtility.getNeighbors(carAllExplorer.setBaseNode(id11)));
    assertEquals(GHUtility.asSet(id9), GHUtility.getNeighbors(carAllExplorer.setBaseNode(id12)));

    EdgeIterator iter = carAllExplorer.setBaseNode(id9);
    assertTrue(iter.next());
    assertEquals(id12, iter.getAdjNode());
    assertEquals(2, iter.fetchWayGeometry(0).getLongitude(0), 1e-7);

    assertTrue(iter.next());
    assertEquals(id11, iter.getAdjNode());
    assertEquals(2, iter.fetchWayGeometry(0).getLongitude(0), 1e-7);
  }
  @Test
  public void testDetachEdge() {
    graph = createGraph();
    graph.edge(0, 1, 2, true);
    long flags = carEncoder.setProperties(10, true, false);
    graph.edge(0, 2, 2, true).setWayGeometry(Helper.createPointList(1, 2, 3, 4)).setFlags(flags);
    graph.edge(1, 2, 2, true);

    EdgeIterator iter = graph.createEdgeExplorer().setBaseNode(0);
    try {
      // currently not possible to detach without next, without introducing a new property inside
      // EdgeIterable
      iter.detach(false);
      assertTrue(false);
    } catch (Exception ex) {
    }

    iter.next();
    EdgeIteratorState edgeState2 = iter.detach(false);
    assertEquals(2, iter.getAdjNode());
    assertEquals(1, edgeState2.fetchWayGeometry(0).getLatitude(0), 1e-1);
    assertEquals(2, edgeState2.getAdjNode());
    assertTrue(carEncoder.isBool(edgeState2.getFlags(), FlagEncoder.K_FORWARD));

    EdgeIteratorState edgeState3 = iter.detach(true);
    assertEquals(0, edgeState3.getAdjNode());
    assertEquals(2, edgeState3.getBaseNode());
    assertEquals(3, edgeState3.fetchWayGeometry(0).getLatitude(0), 1e-1);
    assertFalse(carEncoder.isBool(edgeState3.getFlags(), FlagEncoder.K_FORWARD));
    assertEquals(GHUtility.getEdge(graph, 0, 2).getFlags(), edgeState2.getFlags());
    assertEquals(GHUtility.getEdge(graph, 2, 0).getFlags(), edgeState3.getFlags());

    iter.next();
    assertEquals(1, iter.getAdjNode());
    assertEquals(2, edgeState2.getAdjNode());
    assertEquals(2, edgeState3.getBaseNode());

    assertEquals(0, iter.fetchWayGeometry(0).size());
    assertEquals(1, edgeState2.fetchWayGeometry(0).getLatitude(0), 1e-1);
    assertEquals(3, edgeState3.fetchWayGeometry(0).getLatitude(0), 1e-1);

    // #162 a directed self referencing edge should be able to reverse its state too
    graph.edge(3, 3, 2, true).setFlags(flags);
    EdgeIterator iter2 = graph.createEdgeExplorer().setBaseNode(3);
    iter2.next();
    assertEquals(edgeState2.getFlags(), iter2.detach(false).getFlags());
    assertEquals(edgeState3.getFlags(), iter2.detach(true).getFlags());
  }
  /** Sets up all parameters with target Graph target */
  public MoleculeParameters(Molecule target) {
    // automatically set initial individuals size range
    int vertices = target.getVerticesSize();
    verticesInterval.set(Math.max(2, vertices / 2), vertices * 2);
    cyclesInterval.set(0, target.getNumberOfCycles() * 2);

    // insure that all possible vertex and edge types are in initial population in roughly equal
    // quantities
    java.util.Hashtable elements = new java.util.Hashtable();
    for (VertexIterator v = target.getVertexIterator(); v.more(); v.next()) {
      String s = v.vertex().toString();
      if (!elements.containsKey(s)) {
        elements.put(s, s);
        try {
          provider.add((Vertex) v.vertex().clone());
        } catch (CloneNotSupportedException e) {
          Error.fatal("can't clone vertex: " + e);
        }
      }
    }
    for (EdgeIterator e = target.getEdgeIterator(); e.more(); e.next()) {
      String s = e.edge().toString();
      if (!elements.containsKey(s)) {
        elements.put(s, s);
        try {
          provider.add((Edge) e.edge().clone());
        } catch (CloneNotSupportedException ee) {
          Error.fatal("can't clone edge: " + ee);
        }
      }
    }
    setParameters(target);
  }
 public boolean containsLatitude(Graph g, EdgeIterator iter, double latitude) {
   NodeAccess na = g.getNodeAccess();
   while (iter.next()) {
     if (Math.abs(na.getLatitude(iter.getAdjNode()) - latitude) < 1e-4) return true;
   }
   return false;
 }
 public static int count(EdgeIterator iter) {
   int counter = 0;
   while (iter.next()) {
     ++counter;
   }
   return counter;
 }
  @Test
  public void testFlags() {
    graph = createGraph();
    graph.edge(0, 1).setDistance(10).setFlags(carEncoder.setProperties(100, true, true));
    graph.edge(2, 3).setDistance(10).setFlags(carEncoder.setProperties(10, true, false));

    EdgeIterator iter = carAllExplorer.setBaseNode(0);
    assertTrue(iter.next());
    assertEquals(carEncoder.setProperties(100, true, true), iter.getFlags());

    iter = carAllExplorer.setBaseNode(2);
    assertTrue(iter.next());
    assertEquals(carEncoder.setProperties(10, true, false), iter.getFlags());

    try {
      graph.edge(0, 1).setDistance(-1);
      assertTrue(false);
    } catch (IllegalArgumentException ex) {
    }
  }
  public static boolean contains(EdgeIterator iter, int... locs) {
    TIntHashSet set = new TIntHashSet();

    while (iter.next()) {
      set.add(iter.node());
    }
    for (int l : locs) {
      if (!set.contains(l)) return false;
    }
    return true;
  }
 /** note/todo: this methods counts edges twice if both directions are available */
 public static int countEdges(Graph g) {
   int counter = 0;
   int nodes = g.getNodes();
   for (int i = 0; i < nodes; i++) {
     EdgeIterator iter = g.getOutgoing(i);
     while (iter.next()) {
       counter++;
     }
   }
   return counter;
 }
  @Test
  public void testUnidirectionalEdgeFilter() {
    graph = createGraph();

    graph.edge(1, 2, 12, false);
    graph.edge(1, 11, 12, false);
    graph.edge(11, 1, 12, false);
    graph.edge(1, 12, 12, false);
    graph.edge(3, 2, 112, false);
    EdgeIterator i = carOutExplorer.setBaseNode(2);
    assertFalse(i.next());

    assertEquals(4, GHUtility.count(carAllExplorer.setBaseNode(1)));

    assertEquals(1, GHUtility.count(carInExplorer.setBaseNode(1)));
    assertEquals(2, GHUtility.count(carInExplorer.setBaseNode(2)));
    assertEquals(0, GHUtility.count(carInExplorer.setBaseNode(3)));

    assertEquals(3, GHUtility.count(carOutExplorer.setBaseNode(1)));
    assertEquals(0, GHUtility.count(carOutExplorer.setBaseNode(2)));
    assertEquals(1, GHUtility.count(carOutExplorer.setBaseNode(3)));
    i = carOutExplorer.setBaseNode(3);
    i.next();
    assertEquals(2, i.getAdjNode());

    i = carOutExplorer.setBaseNode(1);
    assertTrue(i.next());
    assertEquals(12, i.getAdjNode());
    assertTrue(i.next());
    assertEquals(11, i.getAdjNode());
    assertTrue(i.next());
    assertEquals(2, i.getAdjNode());
    assertFalse(i.next());
  }
  protected void checkGraph(Graph g) {
    NodeAccess na = g.getNodeAccess();
    assertTrue(na.is3D());
    assertTrue(g.getBounds().isValid());

    assertEquals(new BBox(10, 20, 10, 12, 0, 1), g.getBounds());
    assertEquals(10, na.getLatitude(0), 1e-2);
    assertEquals(10, na.getLongitude(0), 1e-2);
    EdgeExplorer explorer = g.createEdgeExplorer(carOutFilter);
    assertEquals(2, GHUtility.count(explorer.setBaseNode(0)));
    assertEquals(GHUtility.asSet(2, 1), GHUtility.getNeighbors(explorer.setBaseNode(0)));

    EdgeIterator iter = explorer.setBaseNode(0);
    assertTrue(iter.next());
    assertEquals(Helper.createPointList3D(3.5, 4.5, 0, 5, 6, 0), iter.fetchWayGeometry(0));

    assertTrue(iter.next());
    assertEquals(Helper.createPointList3D(1.5, 1, 0, 2, 3, 0), iter.fetchWayGeometry(0));
    assertEquals(Helper.createPointList3D(10, 10, 0, 1.5, 1, 0, 2, 3, 0), iter.fetchWayGeometry(1));
    assertEquals(Helper.createPointList3D(1.5, 1, 0, 2, 3, 0, 11, 20, 1), iter.fetchWayGeometry(2));

    assertEquals(11, na.getLatitude(1), 1e-2);
    assertEquals(20, na.getLongitude(1), 1e-2);
    assertEquals(2, GHUtility.count(explorer.setBaseNode(1)));
    assertEquals(GHUtility.asSet(2, 0), GHUtility.getNeighbors(explorer.setBaseNode(1)));

    assertEquals(12, na.getLatitude(2), 1e-2);
    assertEquals(12, na.getLongitude(2), 1e-2);
    assertEquals(1, GHUtility.count(explorer.setBaseNode(2)));

    assertEquals(GHUtility.asSet(0), GHUtility.getNeighbors(explorer.setBaseNode(2)));

    EdgeIteratorState eib = GHUtility.getEdge(g, 1, 2);
    assertEquals(Helper.createPointList3D(), eib.fetchWayGeometry(0));
    assertEquals(Helper.createPointList3D(11, 20, 1), eib.fetchWayGeometry(1));
    assertEquals(Helper.createPointList3D(12, 12, 0.4), eib.fetchWayGeometry(2));
    assertEquals(GHUtility.asSet(0), GHUtility.getNeighbors(explorer.setBaseNode(2)));
  }
 boolean prepareEdges() {
   // In CH the setProperties (speed) are ignored as calculating the new setProperties for a
   // shortcut is often not possible.
   // Also several shortcuts would be necessary with the different modes (e.g. fastest and
   // shortest)
   // So calculate the weight and store this as weight, then use only weight instead of calcWeight
   EdgeIterator iter = g.getAllEdges();
   int c = 0;
   while (iter.next()) {
     c++;
     iter.setDistance(prepareWeighting.calcWeight(iter));
     setOrigEdgeCount(iter.getEdge(), 1);
   }
   return c > 0;
 }
  @Test
  public void testCreateDuplicateEdges() {
    graph = createGraph();
    graph.edge(2, 1, 12, true);
    graph.edge(2, 3, 12, true);
    graph.edge(2, 3, 13, false);
    assertEquals(3, GHUtility.count(carOutExplorer.setBaseNode(2)));

    // no exception
    graph.getEdgeProps(1, 3);

    // raise exception
    try {
      graph.getEdgeProps(4, 3);
      assertTrue(false);
    } catch (Exception ex) {
    }
    try {
      graph.getEdgeProps(-1, 3);
      assertTrue(false);
    } catch (Exception ex) {
    }

    EdgeIterator iter = carOutExplorer.setBaseNode(2);
    assertTrue(iter.next());
    EdgeIteratorState oneIter = graph.getEdgeProps(iter.getEdge(), 3);
    assertEquals(13, oneIter.getDistance(), 1e-6);
    assertEquals(2, oneIter.getBaseNode());
    assertTrue(carEncoder.isBool(oneIter.getFlags(), FlagEncoder.K_FORWARD));
    assertFalse(carEncoder.isBool(oneIter.getFlags(), FlagEncoder.K_BACKWARD));

    oneIter = graph.getEdgeProps(iter.getEdge(), 2);
    assertEquals(13, oneIter.getDistance(), 1e-6);
    assertEquals(3, oneIter.getBaseNode());
    assertFalse(carEncoder.isBool(oneIter.getFlags(), FlagEncoder.K_FORWARD));
    assertTrue(carEncoder.isBool(oneIter.getFlags(), FlagEncoder.K_BACKWARD));

    graph.edge(3, 2, 14, true);
    assertEquals(4, GHUtility.count(carOutExplorer.setBaseNode(2)));
  }
  /** @throws could throw exception if uncatched problems like index out of bounds etc */
  public static List<String> getProblems(Graph g) {
    List<String> problems = new ArrayList<String>();
    int nodes = g.getNodes();
    for (int i = 0; i < nodes; i++) {
      double lat = g.getLatitude(i);
      if (lat > 90 || lat < -90) problems.add("latitude is not within its bounds " + lat);
      double lon = g.getLongitude(i);
      if (lon > 180 || lon < -180) problems.add("longitude is not within its bounds " + lon);
      int incom = count(g.getIncoming(i));
      int out = count(g.getOutgoing(i));
      int e = count(g.getEdges(i));
      if (Math.max(out, incom) > e)
        problems.add(
            "count incoming or outgoing edges should be maximum "
                + e
                + " but were:"
                + incom
                + "(in), "
                + out
                + "(out)");

      EdgeIterator iter = g.getEdges(i);
      while (iter.next()) {
        if (iter.node() >= nodes)
          problems.add(
              "edge of " + i + " has a node " + iter.node() + " greater or equal to getNodes");
        if (iter.node() < 0) problems.add("edge of " + i + " has a negative node " + iter.node());
      }
    }

    //        for (int i = 0; i < nodes; i++) {
    //            new XFirstSearch().start(g, i, false);
    //        }

    return problems;
  }
  @Test
  public void testUpdateUnidirectional() {
    graph = createGraph();

    graph.edge(1, 2, 12, false);
    graph.edge(3, 2, 112, false);
    EdgeIterator i = carOutExplorer.setBaseNode(2);
    assertFalse(i.next());
    i = carOutExplorer.setBaseNode(3);
    assertTrue(i.next());
    assertEquals(2, i.getAdjNode());
    assertFalse(i.next());

    graph.edge(2, 3, 112, false);
    i = carOutExplorer.setBaseNode(2);
    assertTrue(i.next());
    assertEquals(3, i.getAdjNode());
    i = carOutExplorer.setBaseNode(3);
    i.next();
    assertEquals(2, i.getAdjNode());
    assertFalse(i.next());
  }
Exemple #18
0
  @Override
  public BufferedImage renderTile(final int x, final int y, final int zoom) {
    ProfileMapCombination debugCurrent;
    EdgeBasedGraph debugEbg;
    Weights debugWeights;
    ArcFlags debugAF;
    if (DEBUG_VIS != 0) {
      debugCurrent = ProfileMapManager.getInstance().getCurrentCombination();
      debugEbg = debugCurrent.getStreetMap().getEdgeBasedGraph();
      debugWeights = debugCurrent.getWeights();
      debugAF = debugCurrent.getArcFlags();
    }
    GraphIndex index = graph.getIndex(zoom);

    final Set<Integer> edges = getEdgesOnTile(x, y, zoom, index);

    final BufferedImage tile = new BufferedImage(256, 256, BufferedImage.TYPE_INT_RGB);
    final Graphics2D g = tile.createGraphics();
    g.setColor(new Color(210, 210, 210));
    g.fillRect(0, 0, 256, 256);
    g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    g.setRenderingHint(
        RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
    final Stroke oldStroke = g.getStroke();
    // Draw border
    EdgeIterator it = new EdgeIterator(edges.iterator(), zoom, x, y, index);
    while (it.next()) {
      g.setColor(getMainStreetColor(it.p.getType(), true));
      g.setStroke(
          new BasicStroke(
              getStreetWidth(zoom, it.p) + 4, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
      g.drawLine(it.xstart, it.ystart, it.xtarget, it.ytarget);
    }

    // Draw street
    it = new EdgeIterator(edges.iterator(), zoom, x, y, index);
    while (it.next()) {
      g.setColor(getMainStreetColor(it.p.getType(), false));
      g.setStroke(
          new BasicStroke(
              getStreetWidth(zoom, it.p), BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
      g.drawLine(it.xstart, it.ystart, it.xtarget, it.ytarget);
    }

    g.setStroke(oldStroke);

    // Draw name of street – must be above all streets
    final Font font = new Font(Font.SANS_SERIF, 0, 12);
    g.setColor(Color.BLACK);
    g.setFont(font);
    it = new EdgeIterator(edges.iterator(), zoom, x, y, index);
    while (it.next()) {
      final String name = getName(it.edge);
      final double streetLength =
          Math.sqrt(Math.pow((it.xtarget - it.xstart), 2) + Math.pow((it.ytarget - it.ystart), 2));

      if (DEBUG_VIS != 0) {
        String debugData;
        int tturn = debugEbg.getOutgoingTurns(it.edge).iterator().next();
        if (DEBUG_VIS == 1) {
          debugData = Integer.toHexString(debugAF.getFlag(tturn));
        } else if (DEBUG_VIS == 4) {
          debugData = Integer.toString(it.edge);
        } else { // 2,3
          debugData =
              Integer.toString(
                  DEBUG_VIS == 2
                      ? debugWeights.getWeight(tturn)
                      : graph.getEdgeProperties(it.edge).getMaxSpeed(debugCurrent.getProfile()));
        }
        g.drawString(debugData, (it.xstart + it.xtarget) / 2, (it.ystart + it.ytarget) / 2);
      }
      if (name != null && (it.xstart != -1) && getStreetWidth(zoom, it.p) > 7) {
        final AffineTransform old = g.getTransform();

        final Rectangle2D r = font.getStringBounds(name, g.getFontRenderContext());
        double angle = getAngle(it.xstart, it.ystart, it.xtarget, it.ytarget, streetLength);

        // Pfeil <-
        if (zoom > 15 && streetLength > 40) {
          if (graph.getCorrespondingEdge(it.edge) == -1) {
            g.setColor(Color.LIGHT_GRAY);
            double angle2 = angle;
            if (it.xtarget < it.xstart || (it.xstart == it.xtarget && it.ystart > it.ytarget)) {
              angle2 -= Math.PI;
            }
            AffineTransform rotateInstance =
                AffineTransform.getRotateInstance(angle2, it.xstart, it.ystart);
            rotateInstance.translate(15 + it.xstart, it.ystart);
            g.setTransform(rotateInstance);
            drawArrow(zoom, g);
            g.setColor(Color.BLACK);
          }
        }

        int xstart;
        int ystart;
        if (it.xstart < it.xtarget || (it.xstart == it.xtarget && it.ystart < it.ytarget)) {
          xstart = it.xstart;
          ystart = it.ystart;
        } else {
          xstart = it.xtarget;
          ystart = it.ytarget;
        }
        final AffineTransform at = AffineTransform.getRotateInstance(angle, xstart, ystart);
        g.setTransform(at);
        if (r.getWidth() + 5 * space < streetLength) {
          g.drawString(
              name,
              (int) (xstart + streetLength / 2 - r.getWidth() / 2),
              (int) (ystart - r.getY() / 2 - r.getY() - r.getHeight()) + 1);
        }
        g.setTransform(old);
      }
    }
    return tile;
  }
 public static EdgeIterator until(EdgeIterator edges, int i) {
   while (edges.next()) {
     if (edges.node() == i) return edges;
   }
   return EdgeIterator.EMPTY;
 }
  @Test
  public void testPillarNodes() {
    graph = createGraph();
    NodeAccess na = graph.getNodeAccess();
    na.setNode(0, 0.01, 0.01);
    na.setNode(4, 0.4, 0.4);
    na.setNode(14, 0.14, 0.14);
    na.setNode(10, 0.99, 0.99);

    PointList pointList = Helper.createPointList(1, 1, 1, 2, 1, 3);
    graph
        .edge(0, 4)
        .setDistance(100)
        .setFlags(carEncoder.setProperties(10, true, false))
        .setWayGeometry(pointList);
    pointList = Helper.createPointList(1, 5, 1, 6, 1, 7, 1, 8, 1, 9);
    graph
        .edge(4, 10)
        .setDistance(100)
        .setFlags(carEncoder.setProperties(10, true, false))
        .setWayGeometry(pointList);
    pointList = Helper.createPointList(1, 13, 1, 12, 1, 11);
    graph
        .edge(14, 0)
        .setDistance(100)
        .setFlags(carEncoder.setProperties(10, true, false))
        .setWayGeometry(pointList);

    EdgeIterator iter = carAllExplorer.setBaseNode(0);
    assertTrue(iter.next());
    assertEquals(14, iter.getAdjNode());
    assertPList(Helper.createPointList(1, 11, 1, 12, 1, 13.0), iter.fetchWayGeometry(0));
    assertPList(
        Helper.createPointList(0.01, 0.01, 1, 11, 1, 12, 1, 13.0), iter.fetchWayGeometry(1));
    assertPList(
        Helper.createPointList(1, 11, 1, 12, 1, 13.0, 0.14, 0.14), iter.fetchWayGeometry(2));
    assertPList(
        Helper.createPointList(0.01, 0.01, 1, 11, 1, 12, 1, 13.0, 0.14, 0.14),
        iter.fetchWayGeometry(3));

    assertTrue(iter.next());
    assertEquals(4, iter.getAdjNode());
    assertPList(Helper.createPointList(1, 1, 1, 2, 1, 3), iter.fetchWayGeometry(0));
    assertPList(Helper.createPointList(0.01, 0.01, 1, 1, 1, 2, 1, 3), iter.fetchWayGeometry(1));
    assertPList(Helper.createPointList(1, 1, 1, 2, 1, 3, 0.4, 0.4), iter.fetchWayGeometry(2));
    assertPList(
        Helper.createPointList(0.01, 0.01, 1, 1, 1, 2, 1, 3, 0.4, 0.4), iter.fetchWayGeometry(3));

    assertFalse(iter.next());

    iter = carOutExplorer.setBaseNode(0);
    assertTrue(iter.next());
    assertEquals(4, iter.getAdjNode());
    assertPList(Helper.createPointList(1, 1, 1, 2, 1, 3), iter.fetchWayGeometry(0));
    assertFalse(iter.next());

    iter = carInExplorer.setBaseNode(10);
    assertTrue(iter.next());
    assertEquals(4, iter.getAdjNode());
    assertPList(Helper.createPointList(1, 9, 1, 8, 1, 7, 1, 6, 1, 5), iter.fetchWayGeometry(0));
    assertPList(
        Helper.createPointList(0.99, 0.99, 1, 9, 1, 8, 1, 7, 1, 6, 1, 5), iter.fetchWayGeometry(1));
    assertPList(
        Helper.createPointList(1, 9, 1, 8, 1, 7, 1, 6, 1, 5, 0.4, 0.4), iter.fetchWayGeometry(2));
    assertPList(
        Helper.createPointList(0.99, 0.99, 1, 9, 1, 8, 1, 7, 1, 6, 1, 5, 0.4, 0.4),
        iter.fetchWayGeometry(3));
    assertFalse(iter.next());
  }