private void clearValues() { NodesById.Clear(); WaysById.Clear(); RelationsById.Clear(); Intersections.Clear(); Bounds = new BoundingBox(); }
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); }
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); } } } }
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); }