Ejemplo n.º 1
0
        /// <summary>
        /// Utility method for ensuring a view stays within a bounding box of geo coordinated.
        /// </summary>
        /// <param name="center">The map center we want to move to.</param>
        /// <param name="boundingBox">A GeoCoordinateBox defining the bounding box.</param>
        /// <param name="view" The current view.</param>
        /// <returns>Returns a center geo coordinate that is corrected so the view stays within the bounding box.</returns>
        public GeoCoordinate EnsureViewWithinBoundingBox(GeoCoordinate center, GeoCoordinateBox boundingBox, View2D view)
        {
            double[] mapCenterSceneCoords = this.Projection.ToPixel(center);
            double[] mapCenterPixels      = view.ToViewPort(view.Width, view.Height, mapCenterSceneCoords[0], mapCenterSceneCoords[1]);

            double[] topLeftSceneCoordinates = view.FromViewPort(view.Width,
                                                                 view.Height,
                                                                 mapCenterPixels[0] - (view.Width) / 2.0,
                                                                 mapCenterPixels[1] - (view.Height) / 2.0);
            GeoCoordinate topLeft = this.Projection.ToGeoCoordinates(topLeftSceneCoordinates[0], topLeftSceneCoordinates[1]);

            double[] bottomRightSceneCoordinates = view.FromViewPort(view.Width,
                                                                     view.Height,
                                                                     mapCenterPixels[0] + (view.Width) / 2.0,
                                                                     mapCenterPixels[1] + (view.Height) / 2.0);
            GeoCoordinate bottomRight = this.Projection.ToGeoCoordinates(bottomRightSceneCoordinates[0], bottomRightSceneCoordinates[1]);

            // Early exit when the view is inside the box.
            if (boundingBox.Contains(topLeft) && boundingBox.Contains(bottomRight))
            {
                return(center);
            }

            double viewNorth = topLeft.Latitude;
            double viewEast  = bottomRight.Longitude;
            double viewSouth = bottomRight.Latitude;
            double viewWest  = topLeft.Longitude;

            double boxNorth = boundingBox.MaxLat;
            double boxEast  = boundingBox.MaxLon;
            double boxSouth = boundingBox.MinLat;
            double boxWest  = boundingBox.MinLon;

            //TODO: Check if the view acrually fits the bounding box, if not resize the view.

            // Correct all view bounds if neccecary.
            if (viewNorth > boxNorth)
            {
                viewSouth -= viewNorth - boxNorth;
                viewNorth  = boxNorth;
            }
            if (viewEast > boxEast)
            {
                viewWest -= viewEast - boxEast;
                viewEast  = boxEast;
            }
            if (viewSouth < boxSouth)
            {
                viewNorth += boxSouth - viewSouth;
                viewSouth  = boxSouth;
            }
            if (viewWest < boxWest)
            {
                viewEast += boxWest - viewWest;
                viewWest  = boxWest;
            }

            // Compute and return corrected map center
            return(new GeoCoordinate(viewSouth + (viewNorth - viewSouth) / 2.0f, viewWest + (viewEast - viewWest) / 2.0f));
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Builds the scene.
        /// </summary>
        /// <param name="map"></param>
        /// <param name="zoomFactor"></param>
        /// <param name="center"></param>
        /// <param name="view"></param>
        private void BuildScene(Map map, float zoomFactor, GeoCoordinate center, View2D view)
        {
            // build the boundingbox.
            var viewBox = view.OuterBox;
            var box     = new GeoCoordinateBox(map.Projection.ToGeoCoordinates(viewBox.Min [0], viewBox.Min [1]),
                                               map.Projection.ToGeoCoordinates(viewBox.Max [0], viewBox.Max [1]));
            var zoomLevel = (int)map.Projection.ToZoomLevel(zoomFactor);

            if (_lastBox != null && _lastBox.Contains(box) &&
                zoomLevel == _lastZoom)
            {
                return;
            }
            _lastBox  = box;
            _lastZoom = zoomLevel;

            // reset the scene.
            if (_scene2DSimple == null)
            {
                _scene2DSimple = new Scene2DSimple();
            }
            _scene2DSimple.Clear();

            // get from the index.
            this.Scene.BackColor = SimpleColor.FromKnownColor(KnownColor.White).Value;
            lock (_sync) {
                _index.Get(_scene2DSimple, view, zoomFactor);
            }
        }
Ejemplo n.º 3
0
 /// <summary>
 /// Returns true if the coordinate is inside the polygon being filtered against.
 /// </summary>
 /// <returns></returns>
 private bool IsInsidePoly(double latitude, double longitude)
 {
     if (!_box.Contains(longitude, latitude))
     { // use the bounding box checks as a negative-first.
         return(false);
     }
     return(_poly.Contains(new GeoCoordinate(latitude, longitude)));
 }
Ejemplo n.º 4
0
 public override bool IsInside(GeoCoordinateBox box)
 {
     if (box == null)
     {
         throw new ArgumentNullException();
     }
     return(box.Contains((PointF2D)this.Coordinate));
 }
Ejemplo n.º 5
0
        /// <summary>
        /// Calculates edge data.
        /// </summary>
        /// <param name="tagsIndex"></param>
        /// <param name="tags"></param>
        /// <param name="tagsForward"></param>
        /// <param name="from"></param>
        /// <param name="to"></param>
        /// <param name="edgeInterpreter"></param>
        /// <param name="intermediates"></param>
        /// <returns></returns>
        protected override Edge CalculateEdgeData(IEdgeInterpreter edgeInterpreter, ITagsIndex tagsIndex,
                                                  TagsCollectionBase tags, bool tagsForward, GeoCoordinate from, GeoCoordinate to, List <GeoCoordinateSimple> intermediates)
        {
            if (edgeInterpreter == null)
            {
                throw new ArgumentNullException("edgeInterpreter");
            }
            if (tagsIndex == null)
            {
                throw new ArgumentNullException("tagsIndex");
            }
            if (tags == null)
            {
                throw new ArgumentNullException("tags");
            }
            if (from == null)
            {
                throw new ArgumentNullException("from");
            }
            if (to == null)
            {
                throw new ArgumentNullException("to");
            }

            uint tagsId = tagsIndex.Add(tags);

            var shapeInBox = true;

            if (intermediates != null)
            { // verify shape-in-box.
                var box = new GeoCoordinateBox(from, to);
                for (int idx = 0; idx < intermediates.Count; idx++)
                {
                    if (!box.Contains(intermediates[idx].Longitude, intermediates[idx].Latitude))
                    { // shape not in box.
                        shapeInBox = false;
                        break;
                    }
                }
            }

            return(new Edge()
            {
                Forward = tagsForward,
                Tags = tagsId,
                Distance = (float)from.DistanceEstimate(to).Value,
                ShapeInBox = shapeInBox
            });
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Returns all the arcs in the given bbox.
        /// </summary>
        /// <param name="box"></param>
        /// <returns></returns>
        public Tuple <long, long, TEdge, ICoordinateCollection>[] GetEdges(GeoCoordinateBox box)
        {
            var baseArcs = _datasource.GetEdges(box);
            var arcs     = new List <Tuple <long, long, TEdge, ICoordinateCollection> >();

            foreach (var baseArc in baseArcs)
            {
                // check if the arc was removed.
                var arc = new Arc()
                {
                    Vertex1 = baseArc.Vertex1,
                    Vertex2 = baseArc.Vertex2
                };
                if (!_removedArcs.Contains(arc))
                { // the arc was not removed, also return it.
                    arcs.Add(new Tuple <long, long, TEdge, ICoordinateCollection>(
                                 baseArc.Vertex1, baseArc.Vertex2, baseArc.EdgeData, baseArc.Intermediates));
                }
            }

            // also include new arcs.
            var inBoxNewVertices = new HashSet <long>();

            foreach (var newVertex in _newVertices)
            {
                if (box.Contains(newVertex.Value))
                {
                    inBoxNewVertices.Add(newVertex.Key);
                }
            }
            // check arcs to include.
            foreach (var newArc in _newEdges)
            {
                var arc = new Arc()
                {
                    Vertex1 = newArc.Key,
                    Vertex2 = newArc.Value.Key
                };
                if (inBoxNewVertices.Contains(arc.Vertex1) ||
                    inBoxNewVertices.Contains(arc.Vertex2))
                { // ok, vertices are contained.
                    arcs.Add(new Tuple <long, long, TEdge, ICoordinateCollection>(
                                 newArc.Key, newArc.Value.Key, newArc.Value.Value.Item1, newArc.Value.Value.Item2));
                }
            }
            return(arcs.ToArray());
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Builds the scene.
        /// </summary>
        /// <param name="map"></param>
        /// <param name="zoomFactor"></param>
        /// <param name="center"></param>
        /// <param name="view"></param>
        private void BuildScene(Map map, float zoomFactor, GeoCoordinate center, View2D view)
        {
            // build the boundingbox.
            var viewBox = view.OuterBox;
            var box     = new GeoCoordinateBox(map.Projection.ToGeoCoordinates(viewBox.Min[0], viewBox.Min[1]),
                                               map.Projection.ToGeoCoordinates(viewBox.Max[0], viewBox.Max[1]));
            var zoomLevel = (int)map.Projection.ToZoomLevel(zoomFactor);

            if (_lastBox != null && _lastBox.Contains(box) &&
                zoomLevel == _lastZoom)
            {
                return;
            }
            _lastBox  = box;
            _lastZoom = zoomLevel;

            lock (_index)
            {
                _primitives = _index.Get(view, zoomFactor);
            }
        }
        private bool IsInBB(OsmGeo osmGeo)
        {
            bool flag = false;

            switch (osmGeo.Type)
            {
            case OsmGeoType.Node:
                GeoCoordinateBox box      = this._box;
                double?          nullable = (osmGeo as Node).Latitude;
                double           latitude = nullable.Value;
                nullable = (osmGeo as Node).Longitude;
                double        longitude     = nullable.Value;
                GeoCoordinate geoCoordinate = new GeoCoordinate(latitude, longitude);
                flag = box.Contains((PointF2D)geoCoordinate);
                break;

            case OsmGeoType.Way:
                foreach (long node in (osmGeo as Way).Nodes)
                {
                    if (this._nodesIn.Contains(node))
                    {
                        flag = true;
                        break;
                    }
                }
                if (flag)
                {
                    using (List <long> .Enumerator enumerator = (osmGeo as Way).Nodes.GetEnumerator())
                    {
                        while (enumerator.MoveNext())
                        {
                            this._nodesToInclude.Add(enumerator.Current);
                        }
                        break;
                    }
                }
                else
                {
                    break;
                }

            case OsmGeoType.Relation:
                if (!this._relationsConsidered.Contains(osmGeo.Id.Value))
                {
                    foreach (RelationMember member in (osmGeo as Relation).Members)
                    {
                        switch (member.MemberType.Value)
                        {
                        case OsmGeoType.Node:
                            if (this._nodesIn.Contains(member.MemberId.Value))
                            {
                                flag = true;
                                continue;
                            }
                            continue;

                        case OsmGeoType.Way:
                            if (this._waysIn.Contains(member.MemberId.Value))
                            {
                                flag = true;
                                continue;
                            }
                            continue;

                        case OsmGeoType.Relation:
                            if (this._relationIn.Contains(member.MemberId.Value))
                            {
                                flag = true;
                                continue;
                            }
                            continue;

                        default:
                            continue;
                        }
                    }
                    if (flag)
                    {
                        using (List <RelationMember> .Enumerator enumerator = (osmGeo as Relation).Members.GetEnumerator())
                        {
                            while (enumerator.MoveNext())
                            {
                                RelationMember current = enumerator.Current;
                                switch (current.MemberType.Value)
                                {
                                case OsmGeoType.Node:
                                    this._nodesToInclude.Add(current.MemberId.Value);
                                    continue;

                                case OsmGeoType.Way:
                                    this._waysToInclude.Add(current.MemberId.Value);
                                    continue;

                                case OsmGeoType.Relation:
                                    this._relationsToInclude.Add(current.MemberId.Value);
                                    continue;

                                default:
                                    continue;
                                }
                            }
                            break;
                        }
                    }
                    else
                    {
                        break;
                    }
                }
                else
                {
                    break;
                }
            }
            return(flag);
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Adds the given node.
        /// </summary>
        /// <param name="node"></param>
        public override void AddNode(Node node)
        {
            if (!_preIndexMode)
            {
                if (_nodesToCache != null &&
                    _nodesToCache.Contains(node.Id.Value))
                { // cache this node?
                    _dataCache.AddNode(node);
                }

                if (_preIndex != null && _preIndex.Contains(node.Id.Value))
                { // only save the coordinates for relevant nodes.
                  // save the node-coordinates.
                  // add the relevant nodes.

                    if (_box == null || _box.Contains(new GeoCoordinate((float)node.Latitude.Value, (float)node.Longitude.Value)))
                    { // the coordinate is acceptable.
                        _coordinates[node.Id.Value] = new GeoCoordinateSimple()
                        {
                            Latitude  = (float)node.Latitude.Value,
                            Longitude = (float)node.Longitude.Value
                        };
                        if (_coordinates.Count == _preIndex.Count)
                        {
                            _preIndex.Clear();
                            _preIndex = null;
                        }

                        if (_bounds == null)
                        { // create bounds.
                            _bounds = new GeoCoordinateBox(
                                new GeoCoordinate(node.Latitude.Value, node.Longitude.Value),
                                new GeoCoordinate(node.Latitude.Value, node.Longitude.Value));
                        }
                        else
                        { // expand bounds.
                            _bounds.ExpandWith(
                                new GeoCoordinate(node.Latitude.Value, node.Longitude.Value));
                        }

                        // add the node as a possible restriction.
                        if (_interpreter.IsRestriction(OsmGeoType.Node, node.Tags))
                        { // tests quickly if a given node is possibly a restriction.
                            List <Vehicle> vehicles = _interpreter.CalculateRestrictions(node);
                            if (vehicles != null &&
                                vehicles.Count > 0)
                            {                                                               // add all the restrictions.
                                uint   vertexId    = this.AddRoadNode(node.Id.Value).Value; // will always exists, has just been added to coordinates.
                                uint[] restriction = new uint[] { vertexId };
                                if (vehicles.Contains(null))
                                { // restriction is valid for all vehicles.
                                    _dynamicGraph.AddRestriction(restriction);
                                }
                                else
                                { // restriction is restricted to some vehicles only.
                                    foreach (Vehicle vehicle in vehicles)
                                    {
                                        _dynamicGraph.AddRestriction(vehicle, restriction);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
Ejemplo n.º 10
0
        public override IList <OsmGeo> Get(GeoCoordinateBox box, Filter filter)
        {
            List <OsmGeo>  osmGeoList1 = new List <OsmGeo>();
            HashSet <long> longSet1    = new HashSet <long>();

            foreach (Node node in this._nodes.Values)
            {
                if (filter == null || filter.Evaluate((OsmGeo)node))
                {
                    GeoCoordinateBox geoCoordinateBox = box;
                    double?          nullable         = node.Latitude;
                    double           latitude         = nullable.Value;
                    nullable = node.Longitude;
                    double        longitude     = nullable.Value;
                    GeoCoordinate geoCoordinate = new GeoCoordinate(latitude, longitude);
                    if (geoCoordinateBox.Contains((PointF2D)geoCoordinate))
                    {
                        osmGeoList1.Add((OsmGeo)node);
                        longSet1.Add(node.Id.Value);
                    }
                }
            }
            osmGeoList1.AddRange(this.GetWaysFor((IEnumerable <long>)longSet1).Cast <OsmGeo>());
            List <Relation> source   = new List <Relation>();
            HashSet <long>  longSet2 = new HashSet <long>();

            foreach (OsmGeo osmGeo in osmGeoList1)
            {
                foreach (Relation relation in (IEnumerable <Relation>) this.GetRelationsFor(osmGeo))
                {
                    if (!longSet2.Contains(relation.Id.Value))
                    {
                        source.Add(relation);
                        longSet2.Add(relation.Id.Value);
                    }
                }
            }
            do
            {
                osmGeoList1.AddRange(source.Cast <OsmGeo>());
                List <Relation> relationList = new List <Relation>();
                foreach (OsmGeo osmGeo in source)
                {
                    foreach (Relation relation in (IEnumerable <Relation>) this.GetRelationsFor(osmGeo))
                    {
                        if (!longSet2.Contains(relation.Id.Value))
                        {
                            relationList.Add(relation);
                            longSet2.Add(relation.Id.Value);
                        }
                    }
                }
                source = relationList;
            }while (source.Count > 0);
            if (filter != null)
            {
                List <OsmGeo> osmGeoList2 = new List <OsmGeo>();
                foreach (OsmGeo osmGeo in osmGeoList1)
                {
                    if (filter.Evaluate(osmGeo))
                    {
                        osmGeoList2.Add(osmGeo);
                    }
                }
            }
            return((IList <OsmGeo>)osmGeoList1);
        }
Ejemplo n.º 11
0
        /// <summary>
        /// Returns all the objects within a given bounding box and filtered by a given filter.
        /// </summary>
        /// <param name="box"></param>
        /// <param name="filter"></param>
        /// <returns></returns>
        public override IList <OsmGeo> Get(GeoCoordinateBox box, Filter filter)
        {
            List <OsmGeo> res = new List <OsmGeo>();

            // load all nodes and keep the ids in a collection.
            HashSet <long> ids = new HashSet <long>();

            foreach (Node node in _nodes.Values)
            {
                if ((filter == null || filter.Evaluate(node)) &&
                    box.Contains(new GeoCoordinate(node.Latitude.Value, node.Longitude.Value)))
                {
                    res.Add(node);
                    ids.Add(node.Id.Value);
                }
            }

            // load all ways that contain the nodes that have been found.
            res.AddRange(this.GetWaysFor(ids).Cast <OsmGeo>()); // the .Cast<> is here for Windows Phone.

            // get relations containing any of the nodes or ways in the current results-list.
            List <Relation> relations   = new List <Relation>();
            HashSet <long>  relationIds = new HashSet <long>();

            foreach (OsmGeo osmGeo in res)
            {
                IList <Relation> relationsFor = this.GetRelationsFor(osmGeo);
                foreach (Relation relation in relationsFor)
                {
                    if (!relationIds.Contains(relation.Id.Value))
                    {
                        relations.Add(relation);
                        relationIds.Add(relation.Id.Value);
                    }
                }
            }

            // recursively add all relations containing other relations as a member.
            do
            {
                res.AddRange(relations.Cast <OsmGeo>()); // the .Cast<> is here for Windows Phone.
                List <Relation> newRelations = new List <Relation>();
                foreach (OsmGeo osmGeo in relations)
                {
                    IList <Relation> relationsFor = this.GetRelationsFor(osmGeo);
                    foreach (Relation relation in relationsFor)
                    {
                        if (!relationIds.Contains(relation.Id.Value))
                        {
                            newRelations.Add(relation);
                            relationIds.Add(relation.Id.Value);
                        }
                    }
                }
                relations = newRelations;
            } while (relations.Count > 0);

            if (filter != null)
            {
                List <OsmGeo> filtered = new List <OsmGeo>();
                foreach (OsmGeo geo in res)
                {
                    if (filter.Evaluate(geo))
                    {
                        filtered.Add(geo);
                    }
                }
            }

            return(res);
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Returns true if the given object is relevant in the bounding box.
        /// </summary>
        /// <param name="osmGeo"></param>
        /// <returns></returns>
        private bool IsInBB(OsmGeo osmGeo)
        {
            bool isIn = false;

            switch (osmGeo.Type)
            {
            case OsmGeoType.Node:
                isIn = _box.Contains(new GeoCoordinate(
                                         (osmGeo as Node).Latitude.Value,
                                         (osmGeo as Node).Longitude.Value));
                break;

            case OsmGeoType.Way:
                foreach (long nodeId in (osmGeo as Way).Nodes)
                {
                    if (_nodesIn.Contains(nodeId))
                    {
                        isIn = true;
                        break;
                    }
                }
                if (isIn)
                {
                    foreach (long nodeId in (osmGeo as Way).Nodes)
                    {
                        _nodesToInclude.Add(nodeId);
                    }
                }
                break;

            case OsmGeoType.Relation:
                if (!_relationsConsidered.Contains(osmGeo.Id.Value))
                {
                    foreach (RelationMember member in (osmGeo as Relation).Members)
                    {
                        switch (member.MemberType.Value)
                        {
                        case OsmGeoType.Node:
                            if (_nodesIn.Contains(member.MemberId.Value))
                            {
                                isIn = true;
                                break;
                            }
                            break;

                        case OsmGeoType.Way:
                            if (_waysIn.Contains(member.MemberId.Value))
                            {
                                isIn = true;
                                break;
                            }
                            break;

                        case OsmGeoType.Relation:
                            if (_relationIn.Contains(member.MemberId.Value))
                            {
                                isIn = true;
                                break;
                            }
                            break;
                        }
                    }

                    if (isIn)
                    {
                        foreach (RelationMember member in (osmGeo as Relation).Members)
                        {
                            switch (member.MemberType.Value)
                            {
                            case OsmGeoType.Node:
                                _nodesToInclude.Add(member.MemberId.Value);
                                break;

                            case OsmGeoType.Way:
                                _waysToInclude.Add(member.MemberId.Value);
                                break;

                            case OsmGeoType.Relation:
                                _relationsToInclude.Add(member.MemberId.Value);
                                break;
                            }
                        }
                    }
                }
                break;
            }
            return(isIn);
        }
        /// <summary>
        /// Calculates edge data.
        /// </summary>
        /// <param name="edgeInterpreter"></param>
        /// <param name="tagsIndex"></param>
        /// <param name="tags"></param>
        /// <param name="tagsForward"></param>
        /// <param name="from"></param>
        /// <param name="to"></param>
        /// <param name="intermediates"></param>
        /// <returns></returns>
        protected override CHEdgeData CalculateEdgeData(IEdgeInterpreter edgeInterpreter, ITagsIndex tagsIndex,
                                                        TagsCollectionBase tags, bool tagsForward, GeoCoordinate from, GeoCoordinate to, List <GeoCoordinateSimple> intermediates)
        {
            var direction = _vehicle.IsOneWay(tags);
            var forward   = false;
            var backward  = false;

            if (!direction.HasValue)
            { // both directions.
                forward  = true;
                backward = true;
            }
            else
            {     // define back/forward.
                if (tagsForward)
                { // relatively same direction.
                    forward  = direction.Value;
                    backward = !direction.Value;
                }
                else
                { // relatively opposite direction.
                    forward  = !direction.Value;
                    backward = direction.Value;
                }
            }

            // add tags.
            uint tagsId = 0;

            if (_storeTags)
            { // yes, store the tags!
                tagsId = tagsIndex.Add(tags);
            }

            // calculate weight including intermediates.
            var   shapeInBox = true;
            float weight     = 0;
            var   previous   = from;

            if (intermediates != null)
            {
                var box = new GeoCoordinateBox(from, to);
                for (int idx = 0; idx < intermediates.Count; idx++)
                {
                    var current = new GeoCoordinate(intermediates[idx].Latitude, intermediates[idx].Longitude);
                    weight   = weight + (float)_vehicle.Weight(tags, previous, current);
                    previous = current;

                    if (!box.Contains(intermediates[idx].Longitude, intermediates[idx].Latitude))
                    { // shape not in box.
                        shapeInBox = false;
                    }
                }
            }
            weight = weight + (float)_vehicle.Weight(tags, previous, to);

            // initialize the edge data.
            var edge = new CHEdgeData(tagsId, tagsForward, forward, backward, weight);

            edge.ShapeInBox = shapeInBox;
            return(edge);
        }
Ejemplo n.º 14
0
        /// <summary>
        /// Returns all objects in the given bounding box and that pass the given filter.
        /// </summary>
        /// <param name="box"></param>
        /// <param name="filter"></param>
        /// <returns></returns>
        public override IList <OsmGeo> Get(GeoCoordinateBox box, OsmSharp.Osm.Filters.Filter filter)
        {
            List <OsmGeo> res = new List <OsmGeo>();

            // create a range or tiles around the given bounding box.
            TileRange range = TileRange.CreateAroundBoundingBox(box, 14);

            // build all redis keys for the given boxes.
            var hashKeys = new List <string>();

            foreach (Tile tile in range)
            {
                hashKeys.Add(tile.Id.ToString());
            }

            byte[][]         box_members = _client.SUnion(hashKeys.ToArray());
            HashSet <string> nodeKeys    = new HashSet <string>();

            foreach (byte[] box_member in box_members)
            {
                long   node_id  = BitConverter.ToInt64(box_member, 0);
                string node_key = PrimitiveExtensions.BuildNodeRedisKey(node_id);
                nodeKeys.Add(node_key);
            }

            List <RedisNode> redisNodes = _clientNode.GetValues(new List <string>(nodeKeys));
            var nodeIds = new List <long>();

            foreach (RedisNode redisNode in redisNodes)
            {
                // test if the node is in the given bb.
                GeoCoordinate coordinate = new GeoCoordinate(redisNode.Latitude.Value, redisNode.Longitude.Value);
                if (box.Contains(coordinate))
                {
                    res.Add(PrimitiveExtensions.ConvertFrom(redisNode));
                    nodeIds.Add(redisNode.Id.Value);
                }
            }

            // load all ways that contain the nodes that have been found.
            res.AddRange(this.GetWaysFor(nodeIds));

            // get relations containing any of the nodes or ways in the current results-list.
            List <Relation> relations   = new List <Relation>();
            HashSet <long>  relationIds = new HashSet <long>();

            foreach (OsmGeo osmGeo in res)
            {
                IList <Relation> relationsFor = this.GetRelationsFor(osmGeo);
                foreach (Relation relation in relationsFor)
                {
                    if (!relationIds.Contains(relation.Id.Value))
                    {
                        relations.Add(relation);
                        relationIds.Add(relation.Id.Value);
                    }
                }
            }

            // recursively add all relations containing other relations as a member.
            do
            {
                res.AddRange(relations); // add previous relations-list.
                List <Relation> newRelations = new List <Relation>();
                foreach (OsmGeo osmGeo in relations)
                {
                    IList <Relation> relationsFor = this.GetRelationsFor(osmGeo);
                    foreach (Relation relation in relationsFor)
                    {
                        if (!relationIds.Contains(relation.Id.Value))
                        {
                            newRelations.Add(relation);
                            relationIds.Add(relation.Id.Value);
                        }
                    }
                }
                relations = newRelations;
            } while (relations.Count > 0);

            if (filter != null)
            {
                List <OsmGeo> filtered = new List <OsmGeo>();
                foreach (OsmGeo geo in res)
                {
                    if (filter.Evaluate(geo))
                    {
                        filtered.Add(geo);
                    }
                }
            }

            return(res);
        }