/**
   * 利用广度优先搜索进行路径判断 p -> q 是否有路径
   *
   * @return
   */
  private static boolean pathOrderCheckBFS(GraphNode<Integer> p, GraphNode<Integer> q) {
    IQueue<GraphNode<Integer>> queue = new Queue<GraphNode<Integer>>();

    if (!p.visited && p.equals(q)) {
      return true;
    }

    p.visited = true;
    queue.enqueue(p);

    while (!queue.isEmpty()) {
      List<GraphNode<Integer>> neighbors = queue.dequeue().neighborList;
      for (int i = 0; i < neighbors.size(); i++) {
        GraphNode<Integer> neighbor = neighbors.get(i);

        if (!neighbor.visited && neighbor.equals(q)) {
          return true;
        }
        neighbor.visited = true;
        queue.enqueue(neighbor);
      }
    }

    return false;
  }
  /**
   * 利用深度优先搜索进行路径判断 p -> q 是否有路径
   *
   * @return
   */
  private static boolean pathOrderCheckDFS(GraphNode<Integer> p, GraphNode<Integer> q) {
    if (p.equals(q)) {
      return true;
    }

    boolean isFound = false;
    List<GraphNode<Integer>> pNeighborList = p.neighborList;
    for (int i = 0; i < pNeighborList.size(); i++) {
      GraphNode<Integer> neighbor = pNeighborList.get(i);
      if (!neighbor.visited) {
        neighbor.visited = true;
        if (neighbor.equals(q)) {
          return true;
        }

        isFound = isFound || pathOrderCheckDFS(neighbor, q);
      }
    }

    return isFound;
  }
Ejemplo n.º 3
0
 /*
  * (non-Javadoc)
  *
  * @see java.util.AbstractSet#equals(java.lang.Object)
  */
 @Override
 public boolean equals(Object o) {
   if (o instanceof GraphCycle) {
     GraphCycle gc = (GraphCycle) o;
     if (gc.size() != size()) return false;
     for (int i = 0; i < size(); i++) {
       GraphNode n1 = (GraphNode) toArray()[i];
       GraphNode n2 = (GraphNode) gc.toArray()[i];
       if (!n1.equals(n2)) return false;
     }
     return true;
   }
   return false;
 }
Ejemplo n.º 4
0
  public void read(DB mapDb, String adminLevel) throws IOException, ClassNotFoundException {
    List<Relation> relations = new ArrayList<Relation>();

    Map<Long, Relation> relationStore = mapDb.getTreeMap("relationStore");
    int totalRelCounter = 0;

    for (Long id : relationStore.keySet()) {
      totalRelCounter++;
      if (totalRelCounter % 10000 == 0)
        log.info(
            "Rel counter: "
                + totalRelCounter
                + ", adminLevels added="
                + relations.size() /*+relations.size()*/);

      Relation rel = relationStore.get(id);
      if (adminLevel.equals(rel.tags.get("admin_level"))) relations.add(rel);
    }

    log.info("Found " + relations.size() + " relations. Processing...");

    //	log.info();
    FileWriter out = new FileWriter("states.txt");
    Map<String, FileWriter> countryPolyFiles = new HashMap<String, FileWriter>();
    for (Relation rel : relations) {

      String name = rel.tags.get("name");

      int totalNodes = 0;

      for (Member m : rel.members) {
        if (m.member instanceof Way) {
          totalNodes += ((Way) m.member).numNodes();
        }
      }

      int ways = 0, nodes = 0;
      Set<String> roles = new HashSet<String>();

      List<List<Node>> multipoly = new ArrayList<List<Node>>();
      List<String> rolesList = new ArrayList<String>();

      List<GraphNode> graphNodes = new ArrayList<GraphNode>();
      List<GraphEdge> graphEdges = new ArrayList<GraphEdge>();

      for (Member m : rel.members) {
        if (m.member instanceof Way) {
          ways++;
          roles.add(m.role);

          Way way = (Way) m.member;

          // log.info(way.nodes.get(0)+"->"+way.nodes.get(way.nodes.size()-1));
          GraphNode src = new GraphNode(Arrays.toString(way.getNode(0)));
          GraphNode dest = new GraphNode(Arrays.toString(way.getNode(way.numNodes() - 1)));

          log.debug(src + "->" + dest + ", size=" + way.numNodes());
          /*for (int i=0; i<way.numNodes(); i++) {
            log.info("Way point "+i+": "+Arrays.toString(way.getNode(i)));
          }*/

          if (graphNodes.contains(src)) src = graphNodes.get(graphNodes.indexOf(src));
          else graphNodes.add(src);
          if (graphNodes.contains(dest)) dest = graphNodes.get(graphNodes.indexOf(dest));
          else graphNodes.add(dest);

          float[] reversedWayNodes = way.getPointsReversed();
          float[] wayNodes = way.getPoints();

          if (src.equals(dest)) {
            src.selfPath = wayNodes;
            dest.selfPath = wayNodes;
          }

          GraphEdge to = new GraphEdge(src, dest, wayNodes, "" + way.id);
          GraphEdge from = new GraphEdge(dest, src, reversedWayNodes, "" + way.id);

          // log.info("ALL: "+to+", id="+to.id);
          //          if (way.id.equals("219576421"))
          //            log.info("219576421: "+to.path);

          // if(src.edges.contains(to)==false)
          src.edges.add(to);
          // if(dest.edges.contains(from)==false)
          dest.edges.add(from);

          graphEdges.add(to);
          graphEdges.add(from);

        } else if (m.member instanceof Node) {
          nodes++;
        }
      }

      List<List<GraphNode>> loops = GraphProcessor.traverse(graphNodes);

      for (List<GraphNode> loop : loops) {
        List<Node> poly = new ArrayList<Node>();
        if (loop.size() == 1) {
          log.debug("Self loop came: " + loop);
          poly.addAll(Utils.nodesFromPoints(loop.get(0).selfPath));
        } else
          for (int i = 1; i < loop.size(); i++) {
            GraphNode prev = loop.get(i - 1);
            GraphNode cur = loop.get(i);
            if (prev.equals(cur)) {
              // poly.addAll(prev.selfPath);
              continue;
            } else {
              /*GraphEdge tmpEdge = new GraphEdge(prev, cur, null);
              GraphEdge actualEdge = graphEdges.get(loops.indexOf(tmpEdge));*/
              GraphEdge actualEdge = null;
              for (GraphEdge e : prev.edges) if (e.dest.equals(cur)) actualEdge = e;
              if (actualEdge == null) {
                System.err.println(
                    "ERROR: Prev: " + prev + ", cur=" + cur + ", prev.edges: " + prev.edges);
              } else {
                poly.addAll(Utils.nodesFromPoints(actualEdge.path));
              }
            }
          }
        if (poly.size() > 0) multipoly.add(poly);
      }

      // log.info("Max size poly = "+maxSizePoly);
      int processedNodes = 0;
      for (List<Node> poly : multipoly) processedNodes += poly.size();
      if (totalNodes > 0)
        log.info(
            name
                + ": "
                + processedNodes
                + "/"
                + totalNodes
                + " ("
                + (processedNodes * 100 / totalNodes)
                + "%), polygons="
                + multipoly.size());

      if (multipoly.size() > 0 && rel.tags.containsKey("name")) {
        places.add(new AdminPolygon(rel.id, rel.tags, rolesList, multipoly));

        // log.info(rel.tags.get("name")+": "+ways+", "+nodes+", roles="+roles+",
        // Multipoly="+multipoly.size()+", RolesList="+rolesList.size());
        // log.info("isin: "+rel.tags.get("is_in:country_code"));
        // log.info(rel.tags);
      }
      // }
      // }
    }
    out.close();
    for (String c : countryPolyFiles.keySet()) countryPolyFiles.get(c).close();
  }
  @Override
  public void generate(
      Vector<GraphNode> nodes,
      Vector<GraphEdge> edges,
      int nodesNum,
      int gridWidth,
      int gridHeight,
      int cellWidth,
      int minNodeWeight,
      int maxNodeWeight,
      int minEdgeCost,
      int maxEdgeCost,
      Random random,
      int randomWeight,
      int gradientWeight,
      int optimaWeight,
      int blurIterations,
      int optimaPercentage) {

    //		Random random = new Random(randomSeed);

    // prepare for generating only half the required nodes in one half of the grid
    int oldGridWidth = gridWidth;
    nodesNum /= 2;
    gridWidth /= 2;

    // get the maximal distance to the grid's center
    double maxDistance =
        Math.sqrt(Math.pow(gridWidth * cellWidth / 2, 2) + Math.pow(gridHeight * cellWidth / 2, 2));
    int centerX = (oldGridWidth + 1) * cellWidth / 2;
    int centerY = (gridHeight + 1) * cellWidth / 2;

    int i = 0;
    while (nodes.size() < nodesNum) {

      int gridX = random.nextInt(gridWidth + 1);
      int gridY = random.nextInt(gridHeight + 1);
      int x = gridX * cellWidth + cellWidth / 2; // + random.nextInt(10) - 5;
      int y = gridY * cellWidth + cellWidth / 2; // + random.nextInt(10) - 5;

      double distance = Math.sqrt(Math.pow(centerX - x, 2) + Math.pow(centerY - y, 2));

      double percentage = distance / (maxDistance / 100);

      double d = 1 - percentage / 100;

      double a = 1 + minNodeWeight + Math.ceil((maxNodeWeight - minNodeWeight - 1) * d);

      int b = minNodeWeight + random.nextInt(maxNodeWeight - minNodeWeight + 1);

      //			int weight = minNodeWeight + random.nextInt(maxNodeWeight - minNodeWeight);

      int weight = (int) (((100 - randomWeight) * a + randomWeight * b) / 100);
      if (weight > maxNodeWeight) {
        weight = maxNodeWeight;
      } else if (weight < minNodeWeight) {
        weight = minNodeWeight;
      }

      GraphNode n = new GraphNode(i, weight, gridX, gridY, x, y);

      if (!nodes.contains(n)) {
        nodes.add(n);
        i++;
      }
    }

    int c = 4;
    double limit =
        c
            * Math.sqrt(
                Math.pow(
                        ((double) (cellWidth * gridHeight)
                            / Math.sqrt(
                                ((double) gridHeight / (double) gridWidth) * (double) nodesNum)),
                        2)
                    + Math.pow(
                        ((double) (cellWidth * gridWidth)
                            / Math.sqrt(
                                ((double) gridWidth / (double) gridHeight) * (double) nodesNum)),
                        2));

    // create a full graph... the edges will be sorted by length
    Vector<GraphEdge> edgesFullSorted = new Vector<GraphEdge>();
    for (int a = 0; a < nodes.size(); a++) {

      for (int b = a + 1; b < nodes.size(); b++) {

        GraphNode n1 = nodes.elementAt(a);
        GraphNode n2 = nodes.elementAt(b);

        int weight = minEdgeCost + random.nextInt(maxEdgeCost - minEdgeCost);
        GraphEdge e = new GraphEdge(weight, n1, n2);
        // edgesFull.add(e);

        // only add if shorter than some value
        if (e.getLength() < limit) {
          edgesFullSorted.add(e);
        }
      }
    }

    Collections.sort(
        edgesFullSorted,
        new Comparator<GraphEdge>() {
          @Override
          public int compare(GraphEdge o1, GraphEdge o2) {
            if (o1.getLength() < o2.getLength()) {
              return 1;
            } else if (o1.getLength() > o2.getLength()) {
              return -1;
            } else {
              return 0;
            }
          }
        });

    // filter remaining edges
    Vector<GraphEdge> remove = new Vector<GraphEdge>();
    for (int a = 0; a < edgesFullSorted.size(); a++) {

      // should be sorted descending
      if (a + 1 != edgesFullSorted.size())
        assert edgesFullSorted.get(a).getLength() >= edgesFullSorted.get(a + 1).getLength();

      // if intersects remove edge
      for (int b = a + 1; b < edgesFullSorted.size(); b++) {

        // do not intersect adjacent edges
        GraphNode id1 = edgesFullSorted.get(a).node1;
        GraphNode id2 = edgesFullSorted.get(a).node2;
        GraphNode id3 = edgesFullSorted.get(b).node1;
        GraphNode id4 = edgesFullSorted.get(b).node2;

        if (id1.equals(id3)) {
          if (checkSameLine(id1, id2, id4)) {
            remove.add(edgesFullSorted.get(a));
            break; // stop looking for intersections
          } else {
            continue;
          }
        }
        if (id1.equals(id4)) {
          if (checkSameLine(id1, id2, id3)) {
            remove.add(edgesFullSorted.get(a));
            break; // stop looking for intersections
          } else {
            continue;
          }
        }
        if (id2.equals(id3)) {
          if (checkSameLine(id2, id1, id4)) {
            remove.add(edgesFullSorted.get(a));
            break; // stop looking for intersections
          } else {
            continue;
          }
        }
        if (id2.equals(id4)) {
          if (checkSameLine(id2, id1, id3)) {
            remove.add(edgesFullSorted.get(a));
            break; // stop looking for intersections
          } else {
            continue;
          }
        }

        // intersection algorithm stolen from:
        // http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/
        double x1 = id1.x;
        double y1 = id1.y;
        double x2 = id2.x;
        double y2 = id2.y;
        double x3 = id3.x;
        double y3 = id3.y;
        double x4 = id4.x;
        double y4 = id4.y;

        double ua =
            ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3))
                / ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1));
        double ub =
            ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3))
                / ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1));

        boolean intersect = ua > 0.0f && ua < 1.0f && ub > 0.0f && ub < 1.0f;

        if (intersect) {

          remove.add(edgesFullSorted.get(a));
          break; // stop looking for intersections
        }
      }
    }

    // remaining edges are the triangulation
    for (GraphEdge e : edgesFullSorted) {

      if (!remove.contains(e)) {
        edges.add(e);
      }
    }

    // mirror everything at one vertical axis
    Vector<GraphNode> mirroredNodes = new Vector<GraphNode>();
    // store every single node's counterpart to easily assign the edges later
    counterparts = new HashMap<GraphNode, GraphNode>();
    // store the nodes at the right edge so that they can be linked to their counterparts
    HashMap<Integer, GraphNode> boundaryNodes = new HashMap<Integer, GraphNode>();

    for (GraphNode n : nodes) {

      GraphNode mirroredNode =
          new GraphNode(
              i,
              n.weight,
              oldGridWidth - n.gridX,
              n.gridY,
              (oldGridWidth + 1) * cellWidth - n.x,
              n.y);
      if (!nodes.contains(mirroredNode)) {
        mirroredNodes.add(mirroredNode);
        counterparts.put(n, mirroredNode);
        i++;
        // update the boundary nodes
        if (!boundaryNodes.containsKey(n.gridY)) {
          boundaryNodes.put(n.gridY, n);
        } else {
          if (boundaryNodes.get(n.gridY).gridX < n.gridX) {
            boundaryNodes.put(n.gridY, n);
          }
        }
      } else {
        counterparts.put(n, n);
      }
    }

    nodes.addAll(mirroredNodes);

    Vector<GraphEdge> mirroredEdges = new Vector<GraphEdge>();
    for (GraphEdge e : edges) {

      GraphEdge newEdge =
          new GraphEdge(e.weight, counterparts.get(e.node1), counterparts.get(e.node2));
      mirroredEdges.add(newEdge);
    }
    edges.addAll(mirroredEdges);

    Vector<GraphEdge> connectingEdges = new Vector<GraphEdge>();
    // connect both halves
    for (GraphNode n : boundaryNodes.values()) {
      if (n != counterparts.get(n)) {
        int weight = minEdgeCost + random.nextInt(maxEdgeCost - minEdgeCost);
        GraphEdge newEdge = new GraphEdge(weight, n, counterparts.get(n));
        connectingEdges.add(newEdge);
      }
    }

    // check the new edges for possible intersections
    for (GraphEdge e1 : connectingEdges) {

      boolean add = true;

      for (GraphEdge e2 : edges) {

        GraphNode id1 = e1.node1;
        GraphNode id2 = e1.node2;
        GraphNode id3 = e2.node1;
        GraphNode id4 = e2.node2;

        double x1 = id1.x;
        double y1 = id1.y;
        double x2 = id2.x;
        double y2 = id2.y;
        double x3 = id3.x;
        double y3 = id3.y;
        double x4 = id4.x;
        double y4 = id4.y;

        double ua =
            ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3))
                / ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1));
        double ub =
            ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3))
                / ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1));

        boolean intersect = ua > 0.0f && ua < 1.0f && ub > 0.0f && ub < 1.0f;

        if (intersect) {
          add = false;
          break;
        }
      }

      if (add) {
        edges.add(e1);
      }
    }

    // shuffle nodes to assign new "names"
    Collections.shuffle(nodes, random);
    int j = 0;
    for (GraphNode n : nodes) {
      n.name = GraphNode.NODE_NAME_PREFIX + j;
      j++;
    }
  }