Exemplo n.º 1
0
 private static IEnumerable <OsmGeo> WithChildren(OsmGeo parent, IOsmGeoSource possibleChilden)
 {
     if (parent is Node)
     {
         return new[] { parent }
     }
     ;
     else if (parent is Way way)
     {
         return(way.Nodes.Select(n => possibleChilden.Get(OsmGeoType.Node, n))
                .Append(parent));
     }
     else if (parent is Relation relation)
     {
         return(relation.Members
                .SelectMany(m =>
         {
             var child = possibleChilden.Get(m.Type, m.Id);
             return child != null
                                                 ? WithChildren(child, possibleChilden) // warning, infinite recursion if references have circular members
                                                 : Enumerable.Empty <OsmGeo>();
         })
                .Where(m => m != null)
                .Append(parent));
     }
     throw new Exception("OsmGeo wasn't a Node, Way or Relation.");
 }
Exemplo n.º 2
0
 // Needs to prevent infinite recusion using a reference id exclusion listS
 public static IEnumerable <OsmGeo> WithChildren(this OsmGeo parent, IOsmGeoSource possibleChilden)
 {
     if (parent is Node)
     {
         return new[] { parent }
     }
     ;
     else if (parent is Way way)
     {
         return(way.Nodes.Select(n => possibleChilden.Get(OsmGeoType.Node, n))
                .Append(parent));
     }
     else if (parent is Relation relation)
     {
         return(relation.Members
                .SelectMany(m =>
         {
             var child = possibleChilden.Get(m.Type, m.Id);
             return child != null
                                                 ? WithChildren(child, possibleChilden)
                                                 : Enumerable.Empty <OsmGeo>();
         })
                .Where(m => m != null)
                .Append(parent));
     }
     throw new Exception("OsmGeo wasn't a Node, Way or Relation.");
 }
Exemplo n.º 3
0
        /// <summary>
        /// Creates a complete object.
        /// </summary>
        public static ICompleteOsmGeo CreateComplete(this OsmGeo simpleOsmGeo, IOsmGeoSource osmGeoSource)
        {
            switch (simpleOsmGeo.Type)
            {
            case OsmGeoType.Node:
                return(simpleOsmGeo as Node);

            case OsmGeoType.Way:
                return((simpleOsmGeo as Way).CreateComplete(osmGeoSource));

            case OsmGeoType.Relation:
                return((simpleOsmGeo as Relation).CreateComplete(osmGeoSource));
            }
            throw new Exception("Unknown OsmGeoType.");
        }
Exemplo n.º 4
0
        /// <summary>
        /// Creates a complete way.
        /// </summary>
        public static CompleteWay CreateComplete(this Way way, IOsmGeoSource osmGeoSource)
        {
            if (way == null)
            {
                throw new ArgumentNullException("simpleWay");
            }
            if (way.Id == null)
            {
                throw new Exception("simpleWay.id is null");
            }
            if (osmGeoSource == null)
            {
                throw new ArgumentNullException("osmGeoSource");
            }

            var completeWay = new CompleteWay();

            completeWay.Id          = way.Id.Value;
            completeWay.ChangeSetId = way.ChangeSetId;
            if (way.Tags != null)
            {
                completeWay.Tags = new TagsCollection(way.Tags);
            }
            if (way.Nodes != null)
            {
                var nodes = new List <Node>();
                for (int i = 0; i < way.Nodes.Length; i++)
                {
                    var node = osmGeoSource.GetNode(way.Nodes[i]);
                    if (node == null)
                    {
                        return(null);
                    }
                    nodes.Add(node);
                }
                completeWay.Nodes = nodes.ToArray();
            }
            completeWay.TimeStamp = way.TimeStamp;
            completeWay.UserName  = way.UserName;
            completeWay.UserId    = way.UserId;
            completeWay.Version   = way.Version;
            completeWay.Visible   = way.Visible;
            return(completeWay);
        }
Exemplo n.º 5
0
        /// <summary>
        /// Creates a relation from a SimpleRelation.
        /// </summary>
        /// <param name="simpleRelation"></param>
        /// <param name="osmGeoSource"></param>
        /// <param name="ways"></param>
        /// <param name="relations"></param>
        /// <returns></returns>
        public static CompleteRelation CreateFrom(Relation simpleRelation, IOsmGeoSource osmGeoSource,
                                                  IDictionary <long, CompleteWay> ways,
                                                  IDictionary <long, CompleteRelation> relations)
        {
            if (simpleRelation == null)
            {
                throw new ArgumentNullException("simpleRelation");
            }
            if (osmGeoSource == null)
            {
                throw new ArgumentNullException("osmGeoSource");
            }
            if (simpleRelation.Id == null)
            {
                throw new Exception("simpleRelation.Id is null");
            }

            CompleteRelation relation = Create(simpleRelation.Id.Value);

            relation.ChangeSetId = simpleRelation.ChangeSetId;
            foreach (Tag pair in simpleRelation.Tags)
            {
                relation.Tags.Add(pair);
            }
            for (int idx = 0; idx < simpleRelation.Members.Count; idx++)
            {
                long   memberId = simpleRelation.Members[idx].MemberId.Value;
                string role     = simpleRelation.Members[idx].MemberRole;

                var member = new CompleteRelationMember();
                member.Role = role;
                switch (simpleRelation.Members[idx].MemberType.Value)
                {
                case OsmGeoType.Node:
                    Node simpleNode = osmGeoSource.GetNode(memberId);
                    if (simpleNode != null)
                    {
                        member.Member = simpleNode;
                    }
                    else
                    {
                        return(null);
                    }
                    break;

                case OsmGeoType.Way:
                    CompleteWay completeWay;
                    if (!ways.TryGetValue(memberId, out completeWay))
                    {
                        Way simpleWay = osmGeoSource.GetWay(memberId);
                        if (simpleWay != null)
                        {
                            completeWay = CompleteWay.CreateFrom(simpleWay, osmGeoSource);
                        }
                    }
                    if (completeWay != null)
                    {
                        member.Member = completeWay;
                    }
                    else
                    {
                        return(null);
                    }
                    break;

                case OsmGeoType.Relation:
                    CompleteRelation completeRelation;
                    if (!relations.TryGetValue(memberId, out completeRelation))
                    {
                        Relation simpleRelationMember = osmGeoSource.GetRelation(memberId);
                        if (simpleRelationMember != null)
                        {
                            completeRelation = CompleteRelation.CreateFrom(simpleRelationMember, osmGeoSource);
                        }
                    }
                    if (completeRelation != null)
                    {
                        member.Member = completeRelation;
                    }
                    else
                    {
                        return(null);
                    }
                    break;
                }
                relation.Members.Add(member);
            }
            relation.TimeStamp = simpleRelation.TimeStamp;
            relation.User      = simpleRelation.UserName;
            relation.UserId    = simpleRelation.UserId;
            relation.Version   = simpleRelation.Version.HasValue ? (long)simpleRelation.Version.Value : (long?)null;
            relation.Visible   = simpleRelation.Visible.HasValue && simpleRelation.Visible.Value;

            return(relation);
        }
Exemplo n.º 6
0
        /// <summary>
        /// Returns all restrictions that are represented by the given node.
        /// </summary>
        /// <param name="relation"></param>
        /// <param name="source"></param>
        /// <returns></returns>
        public List<KeyValuePair<string, long[]>> CalculateRestrictions(Relation relation, IOsmGeoSource source)
        {
            var restrictions = new List<KeyValuePair<string, long[]>>();
            if(relation.Tags.ContainsKeyValue("type", "restriction") &&
                relation.Members != null)
            { // regular restriction.
                Way fromWay = null, toWay = null, viaWay = null;
                Node viaNode = null;
                for(int idx = 0; idx < relation.Members.Count; idx++)
                {
                    var member = relation.Members[idx];
                    if(member.MemberRole == "from")
                    { // the from-way.
                        fromWay = source.GetWay(member.MemberId.Value);
                    }
                    else if(member.MemberRole == "to")
                    { // the to-way.
                        toWay = source.GetWay(member.MemberId.Value);
                    }
                    else if(member.MemberRole == "via")
                    { // the via node/way.
                        if (member.MemberType.Value == OsmGeoType.Node)
                        {
                            viaNode = source.GetNode(member.MemberId.Value);
                        }
                        else if(member.MemberType.Value == OsmGeoType.Way)
                        {
                            viaWay = source.GetWay(member.MemberId.Value);
                        }
                    }
                }

                // check if all data was found and type of restriction.
                if(fromWay != null && toWay != null &&
                    fromWay.Nodes.Count > 1 && toWay.Nodes.Count > 1)
                { // ok, from-to is there and has enough nodes.
                    if(viaWay != null)
                    { // via-part is a way.

                    }
                    else if (viaNode != null)
                    { // via-node is a node.
                        var restriction = new long[3];
                        // get from.
                        if (fromWay.Nodes[0] == viaNode.Id)
                        { // next node is from-node.
                            restriction[0] = fromWay.Nodes[1];
                        }
                        else if(fromWay.Nodes[fromWay.Nodes.Count - 1] == viaNode.Id)
                        { // previous node is from-node.
                            restriction[0] = fromWay.Nodes[fromWay.Nodes.Count - 2];
                        }
                        else
                        { // not found!
                            return restrictions;
                        }
                        restriction[1] = viaNode.Id.Value;
                        // get to.
                        if (toWay.Nodes[0] == viaNode.Id)
                        { // next node is to-node.
                            restriction[2] = toWay.Nodes[1];
                        }
                        else if (toWay.Nodes[toWay.Nodes.Count - 1] == viaNode.Id)
                        { // previous node is to-node.
                            restriction[2] = toWay.Nodes[toWay.Nodes.Count - 2];
                        }
                        else
                        { // not found!
                            return restrictions;
                        }
                        restrictions.Add(new KeyValuePair<string, long[]>(VehicleType.Vehicle, restriction));
                    }
                }
            }
            return restrictions;
        }
Exemplo n.º 7
0
 public static ICompleteOsmGeo AsComplete(this OsmGeo parent, IOsmGeoSource possibleChilden)
 {
     return(parent.CreateComplete(possibleChilden));
 }
Exemplo n.º 8
0
        public static List <List <OsmGeo> > GroupCloseNeighbors(OsmGeo[] elements, double closenessMeters, IOsmGeoSource index, bool all = true)
        {
            var stacks = elements.GroupBy(a => a.AsComplete(index).AsPosition())
                         .Select(stack => new
            {
                positions = new List <Coordinate> {
                    stack.Key
                },
                nodes = stack.ToList()
            })
                         .ToList();

            // Combine groups when everything in them is close to everything in another group.
            for (int i = 0; i < stacks.Count - 1; i++)
            {
                for (int j = i + 1; j < stacks.Count; j++)
                {
                    var maybeMergeable = all ?
                                         stacks[i].positions.SelectMany(l => stacks[j].positions, DistanceMeters)
                                         .All(d => d < closenessMeters)
                                                : stacks[i].positions.SelectMany(l => stacks[j].positions, DistanceMeters)
                                         .Any(d => d < closenessMeters);
                    if (maybeMergeable)
                    {
                        stacks[i].positions.AddRange(stacks[j].positions);
                        stacks[i].nodes.AddRange(stacks[j].nodes);
                        stacks.RemoveAt(j);
                        j--;
                    }
                }
            }

            return(stacks.Select(g => g.nodes).ToList());
        }
Exemplo n.º 9
0
 /// <summary>
 /// Gets the node with the given id.
 /// </summary>
 public static Node GetNode(this IOsmGeoSource db, long id)
 {
     return(db.Get(OsmGeoType.Node, id) as Node);
 }
Exemplo n.º 10
0
        /// <summary>
        /// Creates a relation from a SimpleRelation.
        /// </summary>
        /// <returns></returns>
        public static CompleteRelation CreateFrom(Relation simpleRelation, IOsmGeoSource osmGeoSource,
            IDictionary<long, CompleteWay> ways,
            IDictionary<long, CompleteRelation> relations)
        {
            if (simpleRelation == null) throw new ArgumentNullException("simpleRelation");
            if (osmGeoSource == null) throw new ArgumentNullException("osmGeoSource");
            if (simpleRelation.Id == null) throw new Exception("simpleRelation.Id is null");

            var relation = Create(simpleRelation.Id.Value);
            relation.ChangeSetId = simpleRelation.ChangeSetId;
            foreach (var pair in simpleRelation.Tags)
            {
                relation.Tags.Add(pair);
            }
            for (int idx = 0; idx < simpleRelation.Members.Count; idx++)
            {
                long memberId = simpleRelation.Members[idx].MemberId.Value;
                string role = simpleRelation.Members[idx].MemberRole;
                var member = new CompleteRelationMember();
                member.Role = role;
                switch (simpleRelation.Members[idx].MemberType.Value)
                {
                    case OsmGeoType.Node:
                        var simpleNode = osmGeoSource.GetNode(memberId);
                        if (simpleNode != null)
                        {
                            member.Member = simpleNode;
                        }
                        else
                        {
                            return null;
                        }
                        break;
                    case OsmGeoType.Way:
                        CompleteWay completeWay;
                        if (!ways.TryGetValue(memberId, out completeWay))
                        {
                            var simpleWay = osmGeoSource.GetWay(memberId);
                            if (simpleWay != null)
                            {
                                completeWay = CompleteWay.CreateFrom(simpleWay, osmGeoSource);
                            }
                        }
                        if (completeWay != null)
                        {
                            member.Member = completeWay;
                        }
                        else
                        {
                            return null;
                        }
                        break;
                    case OsmGeoType.Relation:
                        CompleteRelation completeRelation;
                        if (!relations.TryGetValue(memberId, out completeRelation))
                        {
                            Relation simpleRelationMember = osmGeoSource.GetRelation(memberId);
                            if (simpleRelationMember != null)
                            {
                                completeRelation = CompleteRelation.CreateFrom(simpleRelationMember, osmGeoSource);
                            }
                        }
                        if (completeRelation != null)
                        {
                            member.Member = completeRelation;
                        }
                        else
                        {
                            return null;
                        }
                        break;
                }
                relation.Members.Add(member);
            }
            relation.TimeStamp = simpleRelation.TimeStamp;
            relation.User = simpleRelation.UserName;
            relation.UserId = simpleRelation.UserId;
            relation.Version = simpleRelation.Version.HasValue ? (long)simpleRelation.Version.Value : (long?)null;
            relation.Visible = simpleRelation.Visible.HasValue && simpleRelation.Visible.Value;
            return relation;
        }
Exemplo n.º 11
0
 private static IEnumerable <OsmGeo> WithChildren(IEnumerable <OsmGeo> parents, IOsmGeoSource possibleChilden)
 {
     return(parents.SelectMany(p => WithChildren(p, possibleChilden)).GroupBy(e => new OsmGeoKey(e)).Select(g => g.First()));
 }
Exemplo n.º 12
0
        /// <summary>
        /// Creates a relation from a SimpleRelation.
        /// </summary>
        /// <returns></returns>
        public static CompleteRelation CreateFrom(Relation simpleRelation, IOsmGeoSource osmGeoSource)
        {
            if (simpleRelation == null)
            {
                throw new ArgumentNullException("simpleRelation");
            }
            if (osmGeoSource == null)
            {
                throw new ArgumentNullException("osmGeoSource");
            }
            if (simpleRelation.Id == null)
            {
                throw new Exception("simpleRelation.Id is null");
            }

            var relation = Create(simpleRelation.Id.Value);

            relation.ChangeSetId = simpleRelation.ChangeSetId;
            if (simpleRelation.Tags != null)
            {
                foreach (var pair in simpleRelation.Tags)
                {
                    relation.Tags.Add(pair);
                }
            }
            if (simpleRelation.Members != null)
            {
                for (var idx = 0; idx < simpleRelation.Members.Count; idx++)
                {
                    var memberId = simpleRelation.Members[idx].MemberId.Value;
                    var role     = simpleRelation.Members[idx].MemberRole;
                    var member   = new CompleteRelationMember();
                    member.Role = role;
                    switch (simpleRelation.Members[idx].MemberType.Value)
                    {
                    case OsmGeoType.Node:
                        var simpleNode = osmGeoSource.GetNode(memberId);
                        if (simpleNode == null)
                        {
                            return(null);
                        }
                        var completeNode = simpleNode;
                        if (completeNode != null)
                        {
                            member.Member = completeNode;
                        }
                        else
                        {
                            return(null);
                        }
                        break;

                    case OsmGeoType.Way:
                        var simpleWay = osmGeoSource.GetWay(memberId);
                        if (simpleWay == null)
                        {
                            return(null);
                        }
                        var completeWay = CompleteWay.CreateFrom(simpleWay, osmGeoSource);
                        if (completeWay != null)
                        {
                            member.Member = completeWay;
                        }
                        else
                        {
                            return(null);
                        }
                        break;

                    case OsmGeoType.Relation:
                        var simpleRelationMember = osmGeoSource.GetRelation(memberId);
                        if (simpleRelationMember == null)
                        {
                            return(null);
                        }
                        var completeRelation = CompleteRelation.CreateFrom(simpleRelationMember, osmGeoSource);
                        if (completeRelation != null)
                        {
                            member.Member = completeRelation;
                        }
                        else
                        {
                            return(null);
                        }
                        break;
                    }
                    relation.Members.Add(member);
                }
            }
            relation.TimeStamp = simpleRelation.TimeStamp;
            relation.User      = simpleRelation.UserName;
            relation.UserId    = simpleRelation.UserId;
            relation.Version   = simpleRelation.Version.HasValue ? (long)simpleRelation.Version.Value : (long?)null;
            relation.Visible   = simpleRelation.Visible.HasValue && simpleRelation.Visible.Value;
            return(relation);
        }
Exemplo n.º 13
0
 /// <summary>
 /// Gets the relation with the given id.
 /// </summary>
 public static Relation GetRelation(this IOsmGeoSource db, long id)
 {
     return(db.Get(OsmGeoType.Relation, id) as Relation);
 }
Exemplo n.º 14
0
 /// <summary>
 /// Gets the way with the given id.
 /// </summary>
 public static Way GetWay(this IOsmGeoSource db, long id)
 {
     return(db.Get(OsmGeoType.Way, id) as Way);
 }
Exemplo n.º 15
0
        /// <summary>
        /// Creates a complete relation.
        /// </summary>
        public static CompleteRelation CreateComplete(this Relation relation, IOsmGeoSource osmGeoSource)
        {
            if (relation == null)
            {
                throw new ArgumentNullException("relation");
            }
            if (relation.Id == null)
            {
                throw new Exception("relation.Id is null");
            }
            if (osmGeoSource == null)
            {
                throw new ArgumentNullException("osmGeoSource");
            }

            var completeRelation = new CompleteRelation();

            completeRelation.Id = relation.Id.Value;

            completeRelation.ChangeSetId = relation.ChangeSetId;
            if (relation.Tags != null)
            {
                completeRelation.Tags = new TagsCollection(relation.Tags);
            }
            if (relation.Members != null)
            {
                var relationMembers = new List <CompleteRelationMember>();
                for (var i = 0; i < relation.Members.Length; i++)
                {
                    var memberId = relation.Members[i].Id;
                    var role     = relation.Members[i].Role;
                    var member   = new CompleteRelationMember();
                    member.Role = role;
                    switch (relation.Members[i].Type)
                    {
                    case OsmGeoType.Node:
                        var memberNode = osmGeoSource.GetNode(memberId);
                        if (memberNode == null)
                        {
                            continue;
                        }
                        var completeMemberNode = memberNode;
                        if (completeMemberNode != null)
                        {
                            member.Member = completeMemberNode;
                        }
                        else
                        {
                            continue;
                        }
                        break;

                    case OsmGeoType.Way:
                        var memberWay = osmGeoSource.GetWay(memberId);
                        if (memberWay == null)
                        {
                            continue;
                        }
                        var completeMemberWay = memberWay.CreateComplete(osmGeoSource);
                        if (completeMemberWay != null)
                        {
                            member.Member = completeMemberWay;
                        }
                        else
                        {
                            continue;
                        }
                        break;

                    case OsmGeoType.Relation:
                        if (relation.Id == memberId)
                        {
                            continue;
                        }
                        var relationMember = osmGeoSource.GetRelation(memberId);
                        if (relationMember == null)
                        {
                            continue;
                        }
                        var completeMemberRelation = relationMember.CreateComplete(osmGeoSource);
                        if (completeMemberRelation != null)
                        {
                            member.Member = completeMemberRelation;
                        }
                        else
                        {
                            continue;
                        }
                        break;
                    }
                    relationMembers.Add(member);
                }
                completeRelation.Members = relationMembers.ToArray();
            }
            completeRelation.TimeStamp = relation.TimeStamp;
            completeRelation.UserName  = relation.UserName;
            completeRelation.UserId    = relation.UserId;
            completeRelation.Version   = relation.Version;
            completeRelation.Visible   = relation.Visible;
            return(completeRelation);
        }
Exemplo n.º 16
0
 private static Osm AsOsm(this IEnumerable <CompleteOsmGeo> elements, IOsmGeoSource index)
 {
     return(elements.Select(e => e.ToSimple()).WithChildren(index).AsOsm());
 }
Exemplo n.º 17
0
 // Playing with different ways to index elements, this one is the intent of OsmSharp
 public static IEnumerable <OsmGeo> WithChildren(this IEnumerable <OsmGeo> parents, IOsmGeoSource possibleChilden)
 {
     return(parents.SelectMany(p => p.WithChildren(possibleChilden)));
 }
Exemplo n.º 18
0
        public static CompleteRelation CreateFrom(Relation simpleRelation, IOsmGeoSource osmGeoSource, IDictionary <long, CompleteWay> ways, IDictionary <long, CompleteRelation> relations)
        {
            if (simpleRelation == null)
            {
                throw new ArgumentNullException("simpleRelation");
            }
            if (osmGeoSource == null)
            {
                throw new ArgumentNullException("osmGeoSource");
            }
            if (!simpleRelation.Id.HasValue)
            {
                throw new Exception("simpleRelation.Id is null");
            }
            CompleteRelation completeRelation1 = CompleteRelation.Create(simpleRelation.Id.Value);

            completeRelation1.ChangeSetId = simpleRelation.ChangeSetId;
            foreach (Tag tag in simpleRelation.Tags)
            {
                completeRelation1.Tags.Add(tag);
            }
            long?nullable1;

            for (int index = 0; index < simpleRelation.Members.Count; ++index)
            {
                nullable1 = simpleRelation.Members[index].MemberId;
                long   num        = nullable1.Value;
                string memberRole = simpleRelation.Members[index].MemberRole;
                CompleteRelationMember completeRelationMember = new CompleteRelationMember();
                completeRelationMember.Role = memberRole;
                switch (simpleRelation.Members[index].MemberType.Value)
                {
                case OsmGeoType.Node:
                    Node node = osmGeoSource.GetNode(num);
                    if (node == null)
                    {
                        return((CompleteRelation)null);
                    }
                    completeRelationMember.Member = (ICompleteOsmGeo)node;
                    break;

                case OsmGeoType.Way:
                    CompleteWay from1;
                    if (!ways.TryGetValue(num, out from1))
                    {
                        Way way = osmGeoSource.GetWay(num);
                        if (way != null)
                        {
                            from1 = CompleteWay.CreateFrom(way, (INodeSource)osmGeoSource);
                        }
                    }
                    if (!((CompleteOsmBase)from1 != (CompleteOsmBase)null))
                    {
                        return((CompleteRelation)null);
                    }
                    completeRelationMember.Member = (ICompleteOsmGeo)from1;
                    break;

                case OsmGeoType.Relation:
                    CompleteRelation from2;
                    if (!relations.TryGetValue(num, out from2))
                    {
                        Relation relation = osmGeoSource.GetRelation(num);
                        if (relation != null)
                        {
                            from2 = CompleteRelation.CreateFrom(relation, osmGeoSource);
                        }
                    }
                    if (!((CompleteOsmBase)from2 != (CompleteOsmBase)null))
                    {
                        return((CompleteRelation)null);
                    }
                    completeRelationMember.Member = (ICompleteOsmGeo)from2;
                    break;
                }
                completeRelation1.Members.Add(completeRelationMember);
            }
            completeRelation1.TimeStamp = simpleRelation.TimeStamp;
            completeRelation1.User      = simpleRelation.UserName;
            completeRelation1.UserId    = simpleRelation.UserId;
            CompleteRelation completeRelation2 = completeRelation1;
            long?            nullable2;

            if (!simpleRelation.Version.HasValue)
            {
                nullable1 = new long?();
                nullable2 = nullable1;
            }
            else
            {
                nullable2 = new long?((long)simpleRelation.Version.Value);
            }
            completeRelation2.Version = nullable2;
            completeRelation1.Visible = simpleRelation.Visible.HasValue && simpleRelation.Visible.Value;
            return(completeRelation1);
        }
Exemplo n.º 19
0
        /// <summary>
        /// Returns all restrictions that are represented by the given node.
        /// </summary>
        /// <param name="relation"></param>
        /// <param name="source"></param>
        /// <returns></returns>
        public List <KeyValuePair <string, long[]> > CalculateRestrictions(Relation relation, IOsmGeoSource source)
        {
            var restrictions = new List <KeyValuePair <string, long[]> >();

            if (relation.Tags.ContainsKeyValue("type", "restriction") &&
                relation.Members != null)
            { // regular restriction.
                Way  fromWay = null, toWay = null, viaWay = null;
                Node viaNode = null;
                for (int idx = 0; idx < relation.Members.Count; idx++)
                {
                    var member = relation.Members[idx];
                    if (member.MemberRole == "from")
                    { // the from-way.
                        fromWay = source.GetWay(member.MemberId.Value);
                    }
                    else if (member.MemberRole == "to")
                    { // the to-way.
                        toWay = source.GetWay(member.MemberId.Value);
                    }
                    else if (member.MemberRole == "via")
                    { // the via node/way.
                        if (member.MemberType.Value == OsmGeoType.Node)
                        {
                            viaNode = source.GetNode(member.MemberId.Value);
                        }
                        else if (member.MemberType.Value == OsmGeoType.Way)
                        {
                            viaWay = source.GetWay(member.MemberId.Value);
                        }
                    }
                }

                // check if all data was found and type of restriction.
                if (fromWay != null && toWay != null &&
                    fromWay.Nodes.Count > 1 && toWay.Nodes.Count > 1)
                {     // ok, from-to is there and has enough nodes.
                    if (viaWay != null)
                    { // via-part is a way.
                    }
                    else if (viaNode != null)
                    { // via-node is a node.
                        var restriction = new long[3];
                        // get from.
                        if (fromWay.Nodes[0] == viaNode.Id)
                        { // next node is from-node.
                            restriction[0] = fromWay.Nodes[1];
                        }
                        else if (fromWay.Nodes[fromWay.Nodes.Count - 1] == viaNode.Id)
                        { // previous node is from-node.
                            restriction[0] = fromWay.Nodes[fromWay.Nodes.Count - 2];
                        }
                        else
                        { // not found!
                            return(restrictions);
                        }
                        restriction[1] = viaNode.Id.Value;
                        // get to.
                        if (toWay.Nodes[0] == viaNode.Id)
                        { // next node is to-node.
                            restriction[2] = toWay.Nodes[1];
                        }
                        else if (toWay.Nodes[toWay.Nodes.Count - 1] == viaNode.Id)
                        { // previous node is to-node.
                            restriction[2] = toWay.Nodes[toWay.Nodes.Count - 2];
                        }
                        else
                        { // not found!
                            return(restrictions);
                        }
                        restrictions.Add(new KeyValuePair <string, long[]>(VehicleType.Vehicle, restriction));
                    }
                }
            }
            return(restrictions);
        }