예제 #1
0
파일: OsmFile.cs 프로젝트: Levrum/Levrum
 private void clearValues()
 {
     NodesById.Clear();
     WaysById.Clear();
     RelationsById.Clear();
     Intersections.Clear();
     Bounds = new BoundingBox();
 }
예제 #2
0
파일: OsmFile.cs 프로젝트: Levrum/Levrum
        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);
        }
예제 #3
0
파일: OsmFile.cs 프로젝트: Levrum/Levrum
        private void cleanSplitWays()
        {
            // This function is a doozy! Hopefully I translated its functionality okay, but if you're running into a problem with intersections it probably lies here.
            Dictionary <string, string> removedWays = new Dictionary <string, string>();
            List <OSMNode> nodes = Nodes;

            for (int i = 0; i < nodes.Count; i++)
            {
                OSMNode       node = nodes[i];
                List <OSMWay> filteredWaysForNode = new List <OSMWay>();

                // Need to create a mega way of the two ways the node is splitting. Otherwise multiple things get screwed up down the line.
                foreach (string usedInWay in node.WayReferences.ToList())
                {
                    string newID = usedInWay;
                    while (removedWays.ContainsKey(newID))
                    {
                        node.WayReferences.Remove(newID);
                        newID = removedWays[newID];
                        node.WayReferences.Add(newID);
                    }
                }

                foreach (string wayId in node.WayReferences)
                {
                    OSMWay way;
                    if (WaysById.TryGetValue(wayId, out way))
                    {
                        if (way.Tags.ContainsKey("highway") && AcceptedRoadTypes.Contains(way.Tags["highway"]))
                        {
                            filteredWaysForNode.Add(way);
                        }
                    }
                }

                if (node.References == 2 && filteredWaysForNode.Count == 2)
                {
                    OSMWay megaWay, dyingWay;

                    bool reversedDyingWay = false;

                    OSMWay way1 = filteredWaysForNode[0];
                    OSMWay way2 = filteredWaysForNode[1];

                    bool isLastNodeForWayOne = way1.NodeReferences[way1.NodeReferences.Count - 1] == node.ID;
                    bool isLastNodeForWayTwo = way2.NodeReferences[way2.NodeReferences.Count - 1] == node.ID;

                    if (isLastNodeForWayOne)
                    {
                        megaWay  = way1;
                        dyingWay = way2;

                        if (isLastNodeForWayTwo)
                        {
                            // Situation where they are both facing towards the split way node
                            reversedDyingWay = true;
                        }
                    }
                    else if (isLastNodeForWayTwo)
                    {
                        megaWay  = way2;
                        dyingWay = way1;
                    }
                    else
                    {
                        // Weird scenario where they are both facing away from the split way node
                        OSMIntersection intersection = new OSMIntersection();
                        intersection.ID        = node.ID;
                        intersection.Location  = node.Location;
                        Intersections[node.ID] = intersection;
                        continue;
                    }

                    // This is when one way loops around and connects to the other way more than once
                    bool multipleConnections = false;
                    foreach (string nodeId in dyingWay.NodeReferences)
                    {
                        if (nodeId != node.ID && megaWay.NodeReferences.Contains(nodeId))
                        {
                            multipleConnections = true;
                            if (!Intersections.ContainsKey(nodeId))
                            {
                                OSMNode multiNode = NodesById[nodeId];
                                multiNode.IsIntersection = true;

                                OSMIntersection intersection = new OSMIntersection();
                                intersection.ID       = nodeId;
                                intersection.Location = multiNode.Location;
                                Intersections[nodeId] = intersection;
                            }

                            break;
                        }
                    }

                    if (multipleConnections)
                    {
                        continue;
                    }

                    if (megaWay.ID == dyingWay.ID)
                    {
                        node.References--;
                        node.WayReferences.RemoveAt(1);
                        continue;
                    }

                    if ((megaWay.Oneway || dyingWay.Oneway) ^ (megaWay.Oneway && dyingWay.Oneway))
                    {
                        //If there is just one one-way street, add an intersection. If they both are, ...way murder time!
                        if (!Intersections.ContainsKey(node.ID))
                        {
                            OSMIntersection intersection = new OSMIntersection();
                            intersection.ID        = node.ID;
                            intersection.Location  = node.Location;
                            Intersections[node.ID] = intersection;
                        }
                        continue;
                    }

                    // Identity theft
                    megaWay.Name = string.IsNullOrWhiteSpace(megaWay.Name) ? dyingWay.Name : megaWay.Name;

                    // Combine max speeds
                    double mwMaxSpeed, dwMaxSpeed;
                    if (double.TryParse(megaWay.MaxSpeed, out mwMaxSpeed) && double.TryParse(dyingWay.MaxSpeed, out dwMaxSpeed))
                    {
                        megaWay.MaxSpeed = Math.Max(mwMaxSpeed, dwMaxSpeed).ToString();
                    }
                    else if (string.IsNullOrWhiteSpace(megaWay.MaxSpeed))
                    {
                        megaWay.MaxSpeed = dyingWay.MaxSpeed;
                    }

                    if (!reversedDyingWay)
                    {
                        foreach (string nodeId in dyingWay.NodeReferences)
                        {
                            if (nodeId != node.ID)
                            {
                                megaWay.NodeReferences.Add(nodeId);
                            }
                        }
                    }
                    else
                    {
                        for (int j = dyingWay.NodeReferences.Count - 1; j >= 0; j--)
                        {
                            if (dyingWay.NodeReferences[j] != node.ID)
                            {
                                megaWay.NodeReferences.Add(dyingWay.NodeReferences[j]);
                            }
                        }
                    }

                    double previousLength = megaWay.NodeDistances[megaWay.NodeDistances.Count - 1];
                    if (!reversedDyingWay)
                    {
                        for (int h = 0; h < dyingWay.NodeReferences.Count; h++)
                        {
                            string nodeId = dyingWay.NodeReferences[h];
                            if (nodeId != node.ID)
                            {
                                megaWay.NodeDistances.Add(previousLength + dyingWay.NodeDistances[h]);
                            }
                        }
                    }
                    else
                    {
                        for (int j = dyingWay.NodeReferences.Count - 1; j >= 0; j--)
                        {
                            string nodeId = dyingWay.NodeReferences[j];
                            if (nodeId != node.ID)
                            {
                                int inverseIndex = dyingWay.NodeReferences.Count - 1 - j;
                                megaWay.NodeDistances.Add(dyingWay.NodeDistances[inverseIndex] + previousLength);
                            }
                        }
                    }

                    //megaWay uses mega drain...
                    WaysById.Remove(dyingWay.ID);
                    node.WayReferences.Remove(dyingWay.ID);
                    node.References--;
                    removedWays[dyingWay.ID] = megaWay.ID;
                    foreach (var murderedWay in removedWays.ToList())
                    {
                        if (murderedWay.Value == dyingWay.ID)
                        {
                            removedWays[murderedWay.Key] = megaWay.ID;
                        }
                    }
                    //Its super effective!
                    //megaWay regains some HP
                    //dyingWay has fainted!

                    //Levrum used ULTRA BALL!
                    //Gotcha! megaWay was caught!
                    //megaWay's data was added to the POKEDEX
                    //Give a nickname to the captured megaWay?
                    claimOsmObjectAsLevrums(megaWay);
                }
            }

            // Fix any references that may have changed after the last loop
            foreach (OSMNode node in NodesById.Values.ToList())
            {
                foreach (string usedInWay in node.WayReferences.ToList())
                {
                    string newID = usedInWay;
                    while (removedWays.ContainsKey(newID))
                    {
                        node.WayReferences.Remove(newID);
                        newID = removedWays[newID];
                        node.WayReferences.Add(newID);
                    }
                }
            }
        }
예제 #4
0
파일: OsmFile.cs 프로젝트: Levrum/Levrum
        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);
        }