1

I'm trying to get all street segments out of osm2po graph, given a geo point and a certain radius. Right now I just do a breadth first search out of the street that's closest to my point, but is there a better way?

class AreaIterator implements Iterator<DirectedStreet> {
    private Set<Integer> visited = new HashSet<>();
    private List<Integer> queue = new LinkedList<>();
    private final Graph graph;
    private final GeoPoint center;
    private final float radius;
    private final boolean twoSided;

    public AreaIterator(Graph graph, GeoPoint center, float radius) {
        this.graph = graph;
        this.center = center;
        this.radius = radius;
        List<Integer> edges = getEdgesForPoint((float) center.lat(), (float) center.lon(), graph);
        queue.addAll(edges);
    }

    private int step() {
        int edgeIdx = 0;
        if (!queue.isEmpty()) {
            edgeIdx = queue.remove(0);
            DirectedStreet street = getDirectedStreetFromEdgeIdx(graph, edgeIdx);
            if (!visited.contains(edgeIdx)) {
                visited.add(edgeIdx);

                if (street.getGeom().distance(center.getGeom()) <= radius)  {
                    int sourceId = graph.getEdgeSourceIds()[edgeIdx];
                    int targetId = graph.getEdgeTargetIds()[edgeIdx];
                    int [] next = graph.findOutgoingEdges(targetId);
                    int [] in1 = graph.findIncomingEdges(targetId);
                    int [] in2 = graph.findIncomingEdges(sourceId);

                    queueAll(next);
                    queueAll(in1);
                    queueAll(in2);
                }
            }
        }

        return edgeIdx;
    }

    private void queueAll(int[] in) {
        for (int edgeIdx : in) {
            queue.add(edgeIdx);
        }
    }

    @Override
    public boolean hasNext() {
        return !queue.isEmpty();
    }

    @Override
    public DirectedStreet next() {
        return getDirectedStreetFromEdgeIdx(graph, step());
    }
}

1 Answer 1

1

No, there is no direct method for it.

If you only need the reachability, then just calculate the route and limit the search radius by using the maxCost-Parameter:

int[] findPath(Graph graph, int sourceId, int targetId,
        float maxCost, Properties params);

If you are going to draw sth. (osm2po is no drawing basis though) - regardless whether streets are part of the connected network or not, you'll have to dig deeper into the API.

Use this constructor:

public Graph(final File graphFile, final Log log, final int supports,
        final boolean async, final byte... excludedExtensionClazzes)
  • Set the third parameter to at least SUPPORT_RASTER_EDGE | SUPPORT_LATLON
  • Use getEdgeRasterBag() which returns a geo-grid of streets
  • The key is a zone denoted by an Id and the value the edgeIdx
  • The size of a cell/zone is 0.01 x 0.01 degrees.

Nevertheless, you'll have to collect the zoneIds before filtering to a circle radius. Therefore you'll need to understand the formula behind this magic Id - it's pretty simple and straight forward:

public static int createZoneId(double lat, double lon) {
    int ilat = ((int)(lat * 100d)) + 9000;
    int ilon = ((int)(lon * 100d)) + 18000;
    return ilat << 16 | ilon;
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.