@Override
  public void addEdgeToGraph(GeoGraph targetGraph, GeoObj startPoint, GeoObj endPoint) {

    // add an edge:
    if (startPoint != null) {
      MeshComponent edgeMesh = getEdgeMesh(targetGraph, startPoint, endPoint);
      if (edgeMesh != null) {
        Log.d(LOG_TAG, "Adding edge from " + startPoint + " to " + endPoint);
        GeoObj edge = targetGraph.addEdge(startPoint, endPoint, edgeMesh);
        edge.getGraphicsComponent().setColor(newNotJetWalkedColor());
      }
    }
  }
  /**
   * This method returns the best match for a specified position. It could for example be used to
   * calculate the closest address to your current location.
   *
   * @param location
   * @return the closest address to the {@link GeoObj}
   */
  public Address getBestAddressForLocation(GeoObj location) {
    try {
      List<Address> locations =
          myGeoCoder.getFromLocation(location.getLatitude(), location.getLongitude(), 1);
      if (locations.size() > 0) {
        return locations.get(0);
      }

    } catch (IOException e) {
      e.printStackTrace();
    }
    return null;
  }
  /**
   * Returns the position of an specified address (Streetname e.g.)
   *
   * @param address
   * @return null if the address could not be found
   */
  public GeoObj getBestLocationForAddress(String address) {
    try {
      List<Address> addresses = myGeoCoder.getFromLocationName(address, 5);
      if (addresses.size() > 0) {
        GeoObj g = new GeoObj(addresses.get(0));
        g.getInfoObject().setShortDescr(address + " (" + g.getInfoObject().getShortDescr() + ")");
        return g;
      }

    } catch (IOException e) {
      e.printStackTrace();
    }
    return null;
  }
  private void setToNextWayPoint(GeoGraph graph, GeoObj justCheckedNode) {

    EfficientList<GeoObj> followers = graph.getFollowingNodesOf(justCheckedNode);
    if (followers != null) {
      for (int i = 0; i < followers.myLength; i++) {
        GeoObj followingNode = followers.get(i);
        followingNode.setComp(newProxiSensor(graph));
        setHighlightNodeTransformations(followingNode.getGraphicsComponent());
        setHighlightEdgeTransformation(graph.getEdge(justCheckedNode, followingNode));
      }
    } else {
      Log.d(LOG_TAG, justCheckedNode + " has no following nodes");
    }
  }
 private void setHighlightEdgeTransformation(GeoObj edge) {
   if (edge != null) {
     edge.getGraphicsComponent().removeAllAnimations();
     edge.getGraphicsComponent()
         .addAnimation(new AnimationColorMorph(BLENDING_TIME, newPathHighlightColor()));
   }
 }
 private String generateUrl(GeoObj startPos, GeoObj destPos, boolean byWalk) {
   // build the url string:
   StringBuilder urlString = new StringBuilder();
   urlString.append("http://maps.google.com/maps?f=d&hl=en");
   if (byWalk) {
     urlString.append("&dirflg=w");
   }
   urlString.append("&saddr="); // from
   urlString.append(Double.toString(startPos.getLatitude()));
   urlString.append(",");
   urlString.append(Double.toString(startPos.getLongitude()));
   urlString.append("&daddr="); // to
   urlString.append(Double.toString(destPos.getLatitude()));
   urlString.append(",");
   urlString.append(Double.toString(destPos.getLongitude()));
   urlString.append("&;ie=UTF8&0&om=0&output=kml");
   return urlString.toString();
 }
  @Override
  public boolean addNodeToGraph(final GeoGraph targetGraph, GeoObj newNode) {
    newNode.setComp(getNodeMesh());

    /*
     * its a geoObj so the diamond will automatically surrounded by a
     * mesh-group. change the color of this group:
     */
    setNormalTransformations(newNode.getGraphicsComponent());

    Log.d(
        LOG_TAG,
        "Adding obj "
            + newNode
            + " to graph with number of nodes="
            + targetGraph.getAllItems().myLength);

    return targetGraph.add(newNode);
  }
  @Override
  public boolean addFirstNodeToGraph(final GeoGraph targetGraph, GeoObj newNode) {
    newNode.setComp(getNodeMesh());
    newNode.setComp(newProxiSensor(targetGraph));

    setNormalTransformations(newNode.getGraphicsComponent());

    Log.d(LOG_TAG, "First node will be added now..");

    Log.d(
        LOG_TAG,
        "Adding obj "
            + newNode
            + " to graph with number of nodes="
            + targetGraph.getAllItems().myLength);

    Log.d(LOG_TAG, "Setting special props for first node.");
    setHighlightNodeTransformations(newNode.getGraphicsComponent());

    return targetGraph.add(newNode);
  }
  /**
   * Uses google maps to calculate the way from the start pos to the destination pos
   *
   * @param startPos
   * @param destPos
   * @param byWalk
   * @param nodeListener
   * @param edgeListener
   * @return
   */
  public GeoGraph getPathFromAtoB(
      GeoObj startPos,
      GeoObj destPos,
      boolean byWalk,
      NodeListener nodeListener,
      EdgeListener edgeListener) {

    if (startPos == null || destPos == null) {
      Log.d(LOG_TAG, "Gmap getPathFromAtoB error: startPoint or target were null");
      return null;
    }

    // try to open the url:
    try {
      String url = generateUrl(startPos, destPos, byWalk);

      // kml does not work anymore, see a solution in
      // http://stackoverflow.com/questions/11745314/why-retrieving-google-directions-for-android-using-kml-data-is-not-working-anymo/11745316#11745316
      //			Document kml = getDocumentFromUrl(url);

      DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
      DocumentBuilder db = dbf.newDocumentBuilder();
      Document kml = db.parse(url);

      if (kml.getElementsByTagName("GeometryCollection").getLength() > 0) {

        String path =
            kml.getElementsByTagName("GeometryCollection")
                .item(0)
                .getFirstChild()
                .getFirstChild()
                .getFirstChild()
                .getNodeValue();

        final String[] pairs = path.split(" ");
        GeoGraph result = new GeoGraph();
        result
            .getInfoObject()
            .setShortDescr("Resulting graph for " + destPos.getInfoObject().getShortDescr());
        result.setIsPath(true);
        result.setNonDirectional(false);

        if (nodeListener != null) {
          nodeListener.addFirstNodeToGraph(result, startPos);
        } else {
          defaultNEListener.addFirstNodeToGraph(result, startPos);
        }

        GeoObj lastPoint = startPos;
        for (int i = 1; i < pairs.length; i++) {
          String[] geoCords = pairs[i].split(",");

          GeoObj currentPoint =
              new GeoObj(
                  Double.parseDouble(geoCords[1]),
                  Double.parseDouble(geoCords[0]),
                  Double.parseDouble(geoCords[2]));

          if (!currentPoint.hasSameCoordsAs(lastPoint)) {
            if (nodeListener != null) {
              nodeListener.addNodeToGraph(result, currentPoint);
            } else {
              defaultNEListener.addNodeToGraph(result, currentPoint);
            }
            if (edgeListener != null) {
              edgeListener.addEdgeToGraph(result, lastPoint, currentPoint);
            } else {
              defaultNEListener.addEdgeToGraph(result, lastPoint, currentPoint);
            }
            Log.d(LOG_TAG, "     + adding Waypoint:" + pairs[i]);
            lastPoint = currentPoint;
          }
        }
        if (lastPoint != null && !lastPoint.hasSameCoordsAs(destPos)) {

          /*
           * add the egde to the past point:
           */
          if (edgeListener != null) {
            edgeListener.addEdgeToGraph(result, lastPoint, destPos);
          } else {
            defaultNEListener.addEdgeToGraph(result, lastPoint, destPos);
          }
        }

        if (nodeListener != null) {
          nodeListener.addNodeToGraph(result, destPos);
        } else {
          defaultNEListener.addNodeToGraph(result, destPos);
        }

        /*
         * an alternative for adding the edges would be to call
         * result.addEdgesToCreatePath(); but this would be a bit
         * slower..
         */

        return result;
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
    return null;
  }