Beispiel #1
0
        private void createEndIntersections()
        {
            foreach (OSMWay way in Ways)
            {
                if (!way.Tags.ContainsKey("highway") || !AcceptedRoadTypes.Contains(way.Tags["highway"]) || way.NodeReferences.Count < 2)
                {
                    continue;
                }

                string firstNodeId = way.NodeReferences[0];
                string lastNodeId  = way.NodeReferences[way.NodeReferences.Count - 1];

                OSMNode firstNode, lastNode;

                if (NodesById.TryGetValue(firstNodeId, out firstNode) && firstNode.References == 1 && !Intersections.ContainsKey(firstNode.ID))
                {
                    OSMIntersection intersection = new OSMIntersection();
                    intersection.ID             = firstNode.ID;
                    intersection.Location       = firstNode.Location;
                    Intersections[firstNode.ID] = intersection;
                }

                if (NodesById.TryGetValue(lastNodeId, out lastNode) && lastNode.References == 1 && !Intersections.ContainsKey(lastNode.ID))
                {
                    OSMIntersection intersection = new OSMIntersection();
                    intersection.ID            = lastNode.ID;
                    intersection.Location      = lastNode.Location;
                    Intersections[lastNode.ID] = intersection;
                }
            }
        }
Beispiel #2
0
        public List <OSMWay> GetWaysIntersectingLine(LatitudeLongitude point1, LatitudeLongitude point2)
        {
            List <OSMWay> output = new List <OSMWay>();

            try
            {
                foreach (OSMWay way in Ways)
                {
                    if (way.BoundingBox.IntersectsLine(point1, point2))
                    {
                        for (int i = 0; i < way.NodeReferences.Count - 1; i++)
                        {
                            OSMNode thisNode, thatNode;
                            if (!NodesById.TryGetValue(way.NodeReferences[i], out thisNode) || !NodesById.TryGetValue(way.NodeReferences[i + 1], out thatNode))
                            {
                                continue;
                            }

                            Point2 intersectionPoint = LineSegment2.Intersection(point1, point2, thisNode.Location, thatNode.Location);
                            if (intersectionPoint != null)
                            {
                                output.Add(way);
                            }
                        }
                    }
                }

                return(output);
            }
            catch (Exception ex)
            {
                LogHelper.LogException(ex, "Error getting intersecting ways", true);
            }
            return(output);
        }
Beispiel #3
0
 private void clearValues()
 {
     NodesById.Clear();
     WaysById.Clear();
     RelationsById.Clear();
     Intersections.Clear();
     Bounds = new BoundingBox();
 }
Beispiel #4
0
        private void findConnectedIntersections()
        {
            foreach (OSMWay way in Ways)
            {
                if (way.NodeReferences.Count < 2)
                {
                    continue;
                }

                if (!way.Tags.ContainsKey("highway") || !AcceptedRoadTypes.Contains(way.Tags["highway"]))
                {
                    continue;
                }

                bool              firstLoop = true;
                double            distSinceMatch = 0;
                LatitudeLongitude previousLoc = null;
                OSMIntersection   intersection = null, previousIntersection = null;
                foreach (string nodeId in way.NodeReferences)
                {
                    if (nodeId == "149232745" && previousIntersection != null && previousIntersection.ID == "149161225")
                    {
                        var str = "str";
                    }
                    OSMNode node;
                    if (!NodesById.TryGetValue(nodeId, out node))
                    {
                        int index = way.NodeReferences.IndexOf(nodeId);
                        way.NodeReferences.RemoveAt(index);
                        way.NodeDistances.RemoveAt(index);
                        continue;
                    }

                    if (!firstLoop)
                    {
                        distSinceMatch += previousLoc.DistanceFrom(node.Location);
                    }

                    previousLoc = node.Location;
                    firstLoop   = false;
                    if (Intersections.TryGetValue(nodeId, out intersection))
                    {
                        if (previousIntersection != null)
                        {
                            previousIntersection.ConnectedIntersectionDistances[nodeId] = distSinceMatch;
                            if (!way.Oneway)
                            {
                                intersection.ConnectedIntersectionDistances[previousIntersection.ID] = distSinceMatch;
                            }
                            distSinceMatch = 0;
                        }
                        previousIntersection = intersection;
                    }
                }
            }
        }
Beispiel #5
0
 private void flagIntersectionInNodes()
 {
     foreach (string nodeId in Intersections.Keys)
     {
         OSMNode node;
         if (NodesById.TryGetValue(nodeId, out node))
         {
             node.IsIntersection = true;
         }
     }
 }
Beispiel #6
0
 private void calculateBoundsForWay(OSMWay way)
 {
     foreach (string nodeId in way.NodeReferences)
     {
         OSMNode node;
         if (NodesById.TryGetValue(nodeId, out node))
         {
             way.BoundingBox.ExtendBounds(node.Location);
         }
     }
 }
Beispiel #7
0
        private string getValidOsmId()
        {
            // Gives a random number between 9 and 10 billion. At the time of writing (05-2020) there were only 6 billion OSM nodes. Should be safe for a year or two.
            string output = string.Empty;

            while (string.IsNullOrEmpty(output))
            {
                double variance = m_rand.NextDouble() * Math.Pow(10, 9);
                long   nodeId   = (long)Math.Floor((Math.Pow(10, 9) * 9) + variance);
                output = nodeId.ToString();
                if (NodesById.ContainsKey(output) || WaysById.ContainsKey(output))
                {
                    output = string.Empty;
                }
            }

            return(output);
        }
Beispiel #8
0
        private void searchWayForIntersectionAndSplit(OSMWay way, LatitudeLongitude point1, LatitudeLongitude point2)
        {
            if (way.BoundingBox.IntersectsLine(point1, point2))
            {
                for (int i = 0; i < way.NodeReferences.Count - 1; i++)
                {
                    OSMNode thisNode, thatNode;
                    if (!NodesById.TryGetValue(way.NodeReferences[i], out thisNode) || !NodesById.TryGetValue(way.NodeReferences[i + 1], out thatNode))
                    {
                        continue;
                    }

                    Point2 intersectionPoint = LineSegment2.Intersection(point1, point2, thisNode.Location, thatNode.Location);
                    if (intersectionPoint != null)
                    {
                        splitWayByLine(way, point1, point2, thisNode.Location, thatNode.Location, i, intersectionPoint);
                    }
                }
            }
        }
Beispiel #9
0
        private void calculateNodeDistancesForWay(OSMWay way)
        {
            OSMNode previousNode = null;
            double  previousDistance = 0, newDistance = 0;

            foreach (string nodeRef in way.NodeReferences)
            {
                OSMNode currentNode;
                if (NodesById.TryGetValue(nodeRef, out currentNode))
                {
                    if (previousNode != null)
                    {
                        double distance = previousNode.Location.DistanceFrom(currentNode.Location);
                        newDistance = previousDistance + distance;
                    }
                    previousDistance = newDistance;
                    previousNode     = currentNode;
                }
                way.NodeDistances.Add(previousDistance);
            }
        }
Beispiel #10
0
        private void generateIntersections()
        {
            foreach (OSMWay way in Ways)
            {
                List <string> nodeIdsForWay = way.NodeReferences;
                if (nodeIdsForWay.Count < 2)
                {
                    continue;
                }

                if (!way.Tags.ContainsKey("highway") || !AcceptedRoadTypes.Contains(way.Tags["highway"]))
                {
                    continue;
                }

                string firstNodeId = way.NodeReferences[0];
                string lastNodeId  = way.NodeReferences[way.NodeReferences.Count - 1];

                if (NodesById.ContainsKey(firstNodeId))
                {
                    NodesById[firstNodeId].EndNodeFlag = true;
                }
                if (NodesById.ContainsKey(lastNodeId))
                {
                    NodesById[lastNodeId].EndNodeFlag = true;
                }

                foreach (string nodeId in nodeIdsForWay)
                {
                    OSMNode node;
                    if (!NodesById.TryGetValue(nodeId, out node))
                    {
                        continue;
                    }

                    node.References++;
                    if (firstNodeId != nodeId && lastNodeId != nodeId)
                    {
                        node.References++;
                    }
                    else
                    {
                        int nodeIndex = nodeIdsForWay.IndexOf(nodeId);
                        if (nodeIndex != 0 && nodeIndex < nodeIdsForWay.Count - 1) // Handles instances where a node appears twice in a way, once in the middle and once at the end
                        {
                            node.References++;
                        }
                    }

                    if (node.References >= 3 && !Intersections.ContainsKey(nodeId))
                    {
                        OSMIntersection intersection = new OSMIntersection();
                        intersection.ID       = nodeId;
                        intersection.Location = node.Location;
                        Intersections[nodeId] = intersection;
                    }
                    else if (way.Name != null && !node.InternalName.Contains(way.Name))
                    {
                        node.InternalName = string.IsNullOrWhiteSpace(node.Name) ? way.Name : string.Format("{0} / {1}", node.Name, way.Name);
                    }
                }
            }
        }
Beispiel #11
0
        private void splitWayByLine(OSMWay way, LatitudeLongitude point1, LatitudeLongitude point2, LatitudeLongitude nodeLoc1, LatitudeLongitude nodeLoc2, int nodeIndex, Point2 intersectionPoint)
        {
            // Make new way
            OSMWay newWay = new OSMWay();

            newWay.ID        = getValidOsmId();
            newWay.Name      = way.Name;
            newWay.MaxSpeed  = way.MaxSpeed;
            newWay.Oneway    = way.Oneway;
            newWay.Version   = "1";
            newWay.Changeset = DateTime.Now.ToString("yyMMddHHmm");
            foreach (KeyValuePair <string, string> kvp in way.Tags)
            {
                newWay.Tags[kvp.Key] = kvp.Value;
            }
            claimOsmObjectAsLevrums(newWay);
            WaysById.Add(newWay.ID, newWay);

            claimOsmObjectAsLevrums(way);

            // Make new nodes
            OSMNode oldWayTerminator = new OSMNode(), newWayTerminator = new OSMNode();

            // Move the terminators towards their nodes slightly to prevent infinite recursion
            double oldWayDistance           = Math.Sqrt(Math.Pow(nodeLoc1.Latitude - intersectionPoint.Y, 2) + Math.Pow(nodeLoc1.Longitude - intersectionPoint.X, 2));
            double oldWayTerminatorDistance = oldWayDistance - .00002;
            double ratio = oldWayTerminatorDistance / oldWayDistance;

            oldWayTerminator.Location = new LatitudeLongitude(((1 - ratio) * nodeLoc1.Latitude) + (ratio * intersectionPoint.Y), ((1 - ratio) * nodeLoc1.Longitude) + (ratio * intersectionPoint.X));

            double newWayDistance           = Math.Sqrt(Math.Pow(nodeLoc2.Latitude - intersectionPoint.Y, 2) + Math.Pow(nodeLoc2.Longitude - intersectionPoint.X, 2));
            double newWayTerminatorDistance = newWayDistance - .00002;

            ratio = newWayTerminatorDistance / newWayDistance;
            newWayTerminator.Location = new LatitudeLongitude(((1 - ratio) * nodeLoc2.Latitude) + (ratio * intersectionPoint.Y), ((1 - ratio) * nodeLoc2.Longitude) + (ratio * intersectionPoint.X));

            newWayTerminator.EndNodeFlag = oldWayTerminator.EndNodeFlag = true;

            newWayTerminator.ID = getValidOsmId();
            NodesById.Add(newWayTerminator.ID, newWayTerminator);

            oldWayTerminator.ID = getValidOsmId();
            NodesById.Add(oldWayTerminator.ID, oldWayTerminator);

            newWayTerminator.Tags.Add("roadCut", oldWayTerminator.ID);
            oldWayTerminator.Tags.Add("roadCut", newWayTerminator.ID);

            claimOsmObjectAsLevrums(newWayTerminator);
            claimOsmObjectAsLevrums(oldWayTerminator);
            newWayTerminator.Version = "1";
            oldWayTerminator.Version = "1";

            // Not exactly true but this is somewhat hard to fake reasonably?
            newWayTerminator.Changeset = newWay.Changeset;
            oldWayTerminator.Changeset = newWay.Changeset;

            // Cleanup node references
            newWay.NodeReferences.Add(newWayTerminator.ID);
            for (int j = nodeIndex + 1; j < way.NodeReferences.Count; j++)
            {
                newWay.NodeReferences.Add(way.NodeReferences[j]);
            }

            for (int j = way.NodeReferences.Count - 1; j > nodeIndex; j--)
            {
                way.NodeReferences.RemoveAt(j);
            }

            way.NodeReferences.Add(oldWayTerminator.ID);
            way.NodeDistances.Clear();
            calculateNodeDistancesForWay(way);
            calculateNodeDistancesForWay(newWay);

            calculateBoundsForWay(newWay);
            searchWayForIntersectionAndSplit(newWay, point1, point2);
        }
Beispiel #12
0
        /// <summary>
        /// Load OSM objects from an OSM XML file
        /// </summary>
        /// <param name="calculateDistances">Calculate distances between nodes on load</param>
        /// <param name="calculateBounds">Calculate way bounding boxes on load</param>
        /// <param name="strictMode">Discard node references from ways if the nodes to not exist</param>
        /// <returns></returns>
        public bool Load(bool calculateDistances = false, bool calculateBounds = false, bool strictMode = false)
        {
            try
            {
                clearValues();

                XDocument       doc              = XDocument.Load(File.FullName);
                List <XElement> nodeElements     = doc.Descendants("node").ToList();
                List <XElement> wayElements      = doc.Descendants("way").ToList();
                List <XElement> relationElements = doc.Descendants("relation").ToList();

                double lat, lon;
                foreach (XElement nodeElement in nodeElements)
                {
                    OSMNode node = new OSMNode();
                    node.GetElementDetailsFromXElement(nodeElement);
                    if (double.TryParse(nodeElement.Attribute("lat").Value, out lat))
                    {
                        node.Latitude = lat;
                    }

                    if (double.TryParse(nodeElement.Attribute("lon").Value, out lon))
                    {
                        node.Longitude = lon;
                    }
                    node.Latitude  = double.TryParse(nodeElement.Attribute("lat").Value, out lat) ? lat : double.NaN;
                    node.Longitude = double.TryParse(nodeElement.Attribute("lon").Value, out lon) ? lon : double.NaN;

                    Bounds.ExtendBounds(node.Latitude, node.Longitude);

                    NodesById[node.ID] = node;
                    //WaysForNodes[node.ID] = new List<OSMNodeWayInfo>();
                }

                foreach (XElement wayElement in wayElements)
                {
                    OSMWay way = new OSMWay();
                    way.GetElementDetailsFromXElement(wayElement);
                    if (way.ID == "15200801")
                    {
                        var str = "str";
                    }

                    List <XElement> nodes = wayElement.Descendants("nd").ToList();
                    foreach (XElement node in nodes)
                    {
                        string refValue = node.Attribute("ref").Value;
                        if (!string.IsNullOrEmpty(refValue))
                        {
                            OSMNode osmNode;
                            if (!NodesById.TryGetValue(refValue, out osmNode))
                            {
                                if (strictMode)
                                {
                                    continue;
                                }
                                else
                                {
                                    osmNode = new OSMNode()
                                    {
                                        ID = refValue
                                    };
                                    NodesById.Add(refValue, osmNode);
                                }
                            }
                            osmNode.WayReferences.Add(way.ID);
                            way.NodeReferences.Add(osmNode.ID);
                        }
                    }

                    XElement oneWayTag = wayElement.Descendants("tag").Where(t => t.Attribute("k").Value == "oneway").SingleOrDefault();
                    if (oneWayTag != null && (oneWayTag.Attribute("v").Value == "yes" || oneWayTag.Attribute("v").Value == "true"))
                    {
                        way.Oneway = true;
                    }

                    XElement maxSpeedTag = wayElement.Descendants("tag").Where(t => t.Attribute("k").Value == "maxspeed").SingleOrDefault();
                    if (maxSpeedTag != null)
                    {
                        way.MaxSpeed = maxSpeedTag.Attribute("v").Value;
                    }

                    WaysById[way.ID] = way;
                }

                foreach (XElement relationElement in relationElements)
                {
                    OSMRelation relation = new OSMRelation();
                    relation.GetElementDetailsFromXElement(relationElement);

                    List <XElement> members = relationElement.Descendants("member").ToList();
                    foreach (XElement member in members)
                    {
                        OSMRelationMember rm = new OSMRelationMember();
                        rm.Type = member.Attribute("type")?.Value;
                        rm.Ref  = member.Attribute("ref")?.Value;
                        rm.Role = member.Attribute("role")?.Value;

                        relation.Members.Add(rm);
                    }

                    RelationsById[relation.ID] = relation;
                }

                if (calculateDistances)
                {
                    CalculateNodeDistances();
                }

                if (calculateBounds)
                {
                    CalculateWayBounds();
                }


                return(true);
            }
            catch (Exception ex)
            {
                LogHelper.LogException(ex, "Error loading OSM file", true);
                return(false);
            }
        }