예제 #1
0
 private static double Sorter(NewIntersection intersection, BlobCollection blobs)
 {
     // return ex: 2.5 means halfway between ref[2] and ref[3]
     Vector2d A = blobs.nodes[intersection.wayRef.refs[intersection.nodePos - 1]];
     Vector2d B = blobs.nodes[intersection.nodeID];
     Vector2d C = blobs.nodes[intersection.wayRef.refs[intersection.nodePos]];
     double partial = (B - A).Length() / (C - A).Length();
     if (partial < -0.1 || partial > 1.1) throw new NotImplementedException();
     return intersection.nodePos - 1 + partial;
 }
예제 #2
0
 // also setup the collinearness
 private static bool CheckCollinear(long v, int aPos, int bPos, WayRef wayRefAB, Dictionary<Way, List<NewIntersection>> intersections, BlobCollection blobs, bool doCollinearness, bool isBorderIntersection)
 {
     bool isCollinear = false;
     if (isBorderIntersection)
     {
         long a = wayRefAB.wayRef.refs[aPos];
         long b = wayRefAB.wayRef.refs[bPos];
         if (v == a || v == b) return false; // points are already shared, so we'll ignore it
         Vector2d aV = blobs.nodes[a];
         Vector2d bV = blobs.nodes[b];
         Vector2d vV = blobs.nodes[v];
         if (vV.X == aV.X && vV.X == bV.X && vV.Y < 1 && vV.Y > 0) isCollinear = true;
         if (vV.Y == aV.Y && vV.Y == bV.Y && vV.X < 1 && vV.X > 0) isCollinear = true;
     }
     else
     {
         long a = wayRefAB.wayRef.refs[aPos];
         long b = wayRefAB.wayRef.refs[bPos];
         if (v == a || v == b) return false; // points are already shared, so we'll ignore it
         double angle1 = CalcAngleDiff(a, b, a, v, blobs);
         double angle2 = CalcAngleDiff(b, a, b, v, blobs);
         double angleDiff = 0.01;
         if (angle1 < angleDiff && angle2 < angleDiff)
         {
             isCollinear = true;
         }
     }
     if (isCollinear)
     {
         if (doCollinearness)
         {
             NewIntersection newNode = new NewIntersection() { wayRef = wayRefAB.wayRef, nodeID = v, nodePos = aPos + 1 };
             if (!intersections.ContainsKey(wayRefAB.wayRef)) intersections.Add(wayRefAB.wayRef, new List<NewIntersection>());
             intersections[wayRefAB.wayRef].Add(newNode);
         }
         return true;
     }
     return false;
 }
예제 #3
0
 internal static void DoIntersections(BlobCollection blobs)
 {
     Dictionary<string, long> uids = new Dictionary<string, long>(); // finally decided I needed something to guarantee uniqueness like this TODO: can probably eliminate this
     long uidCounter = -1000;
     List<Way> ways = TempGetWays(blobs);
     ways.Add(blobs.borderWay);
     List<WayRef> wayRefs = new List<WayRef>();
     STRtree<WayRef> rtree = new STRtree<WayRef>();
     foreach (var way in ways)
     {
         for (int i = 1; i < way.refs.Count; i++)
         {
             WayRef wayRef = new WayRef() { wayRef = way, nodePos = i - 1 };
             wayRefs.Add(wayRef);
             Vector2d pos1 = blobs.nodes[way.refs[i - 1]];
             Vector2d pos2 = blobs.nodes[way.refs[i]];
             var env = new Envelope(Math.Min(pos1.X, pos2.X), Math.Max(pos1.X, pos2.X), Math.Min(pos1.Y, pos2.Y), Math.Max(pos1.Y, pos2.Y));
             rtree.Insert(env, wayRef);
         }
     }
     rtree.Build();
     Dictionary<Way, List<NewIntersection>> intersections = new Dictionary<Way, List<NewIntersection>>();
     foreach (var n1 in wayRefs)
     {
         Vector2d pos1 = blobs.nodes[n1.wayRef.refs[n1.nodePos]];
         Vector2d pos2 = blobs.nodes[n1.wayRef.refs[n1.nodePos + 1]];
         var env = new Envelope(Math.Min(pos1.X, pos2.X), Math.Max(pos1.X, pos2.X), Math.Min(pos1.Y, pos2.Y), Math.Max(pos1.Y, pos2.Y));
         foreach (var n2 in rtree.Query(env))
         {
             if (n1.GetHashCode() <= n2.GetHashCode()) continue; // as a way of preventing the same query twice
             long Aid = n1.wayRef.refs[n1.nodePos];
             long Bid = n1.wayRef.refs[n1.nodePos + 1];
             long Cid = n2.wayRef.refs[n2.nodePos];
             long Did = n2.wayRef.refs[n2.nodePos + 1];
             Vector2d A = blobs.nodes[Aid];
             Vector2d B = blobs.nodes[Bid];
             Vector2d C = blobs.nodes[Cid];
             Vector2d D = blobs.nodes[Did];
             if (Math.Min(A.X, B.X) > Math.Max(C.X, D.X)) continue;
             if (Math.Max(A.X, B.X) < Math.Min(C.X, D.X)) continue;
             if (Math.Min(A.Y, B.Y) > Math.Max(C.Y, D.Y)) continue;
             if (Math.Max(A.Y, B.Y) < Math.Min(C.Y, D.Y)) continue;
             string intersectionKey = Aid + "," + Cid;
             // TODO: we're going to treat -1 as always matching for now
             bool ACSame = Aid == Cid;
             bool ADSame = Aid == Did;
             bool BCSame = Bid == Cid;
             bool BDSame = Bid == Did;
             // a subset of possible tiny angles that can cause rounding errors
             // only thing that changes between these is the condition, line direction, and the newpoint id
             // TODO: is this really what fixed the nonsense at 240202043? the angleDiff was only 0.009, which seems too big to cause an issue
             bool someCollinear = false;
             bool isBorderIntersection = Aid < 0 || Bid < 0 || Cid < 0 || Did < 0;
             someCollinear |= CheckCollinear(Aid, n2.nodePos, n2.nodePos + 1, n2, intersections, blobs, true, isBorderIntersection);
             someCollinear |= CheckCollinear(Bid, n2.nodePos, n2.nodePos + 1, n2, intersections, blobs, true, isBorderIntersection);
             someCollinear |= CheckCollinear(Cid, n1.nodePos, n1.nodePos + 1, n1, intersections, blobs, true, isBorderIntersection);
             someCollinear |= CheckCollinear(Did, n1.nodePos, n1.nodePos + 1, n1, intersections, blobs, true, isBorderIntersection);
             if (!ACSame && !ADSame && !BCSame && !BDSame) // proper intersection
             {
                 if (someCollinear)
                 {
                     if (n1.wayRef.id == n2.wayRef.id)
                     {
                         n1.wayRef.selfIntersects = true; // mark for destruction, probably
                     }
                 }
                 else
                 {
                     // let's sort these lines to guarantee duplicates by value
                     long[] ns = new long[] { Aid, Bid, Cid, Did };
                     if (ns[0] >= ns[2]) ns = ns.Reverse().ToArray();
                     if (ns[0] >= ns[1])
                     {
                         var t = ns[1];
                         ns[1] = ns[0];
                         ns[0] = t;
                     }
                     if (ns[2] >= ns[3])
                     {
                         var t = ns[3];
                         ns[3] = ns[2];
                         ns[2] = t;
                     }
                     Vector2d intersection = Intersect(blobs.nodes[ns[0]], blobs.nodes[ns[1]], blobs.nodes[ns[2]], blobs.nodes[ns[3]]);
                     if (intersection != null)
                     {
                         long intersectionID;
                         if (uids.ContainsKey(intersectionKey))
                         {
                             intersectionID = uids[intersectionKey];
                         }
                         else
                         {
                             intersectionID = uidCounter--;
                             uids[intersectionKey] = intersectionID;
                         }
                         NewIntersection newNode1 = new NewIntersection() { nodeID = intersectionID, wayRef = n1.wayRef, nodePos = n1.nodePos + 1 };
                         NewIntersection newNode2 = new NewIntersection() { nodeID = intersectionID, wayRef = n2.wayRef, nodePos = n2.nodePos + 1 };
                         blobs.nodes[intersectionID] = intersection;
                         if (!intersections.ContainsKey(n1.wayRef)) intersections.Add(n1.wayRef, new List<NewIntersection>());
                         intersections[n1.wayRef].Add(newNode1);
                         if (!intersections.ContainsKey(n2.wayRef)) intersections.Add(n2.wayRef, new List<NewIntersection>());
                         intersections[n2.wayRef].Add(newNode2);
                         if (n1.wayRef.id == n2.wayRef.id)
                         {
                             n1.wayRef.selfIntersects = true; // mark for destruction, probably
                         }
                     }
                 }
             }
         }
     }
     List<long> wayids = new List<long>();
     foreach (var pair in intersections)
     {
         if (wayids.Contains(pair.Key.id)) throw new NotImplementedException();
         wayids.Add(pair.Key.id);
     }
     foreach (var pair in intersections)
     {
         foreach (var intersection in pair.Value)
         {
             intersection.sortRank = Sorter(intersection, blobs);
         }
     }
     foreach (var pair in intersections)
     {
         var sorted = pair.Value.OrderBy(x => x.sortRank).ToList();
         // get rid of duplicates
         for (int i = sorted.Count - 1; i > 0; i--)
         {
             if (sorted[i].nodeID == sorted[i - 1].nodeID) sorted.RemoveAt(i);
         }
         // now insert them
         for (int i = sorted.Count - 1; i >= 0; i--)
         {
             pair.Key.refs.Insert(sorted[i].nodePos, sorted[i].nodeID);
         }
     }
     RemoveDuplicates(blobs); // remove duplicates at the end to also remove duplicate intersections
 }