/** * 利用广度优先搜索进行路径判断 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; }
/* * (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; }
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++; } }