Exemplo n.º 1
0
        private void AddUntouchedLoop(SectorConstrainedOSMAreaGraph map, List <Way> superLoop)
        {
            List <AreaNode> newNodes = new List <AreaNode>();
            var             broken   = BreakDownSuperLoop(superLoop);

            for (int i = 0; i < broken.Count - 1; i++) // since our loops end in a duplicate
            {
                AreaNode curr = new AreaNode()
                {
                    id = broken[i]
                };
                newNodes.Add(curr);
                if (!map.nodes.ContainsKey(broken[i]))
                {
                    map.nodes[broken[i]] = new List <AreaNode>();
                }
                map.nodes[broken[i]].Add(curr);
            }
            for (int i = 0; i < newNodes.Count; i++)
            {
                AreaNode prev = newNodes[i];
                AreaNode next = newNodes[(i + 1) % newNodes.Count];
                prev.next = next;
                next.prev = prev;
            }
        }
Exemplo n.º 2
0
        private SectorConstrainedOSMAreaGraph GridToArea(bool[,] grid, int size, BlobCollection blobs)
        {
            SectorConstrainedOSMAreaGraph newMap = new SectorConstrainedOSMAreaGraph();

            for (int i = 0; i < size * size; i++)
            {
                if (grid[i / size, i % size])
                {
                    int x1 = i / size;
                    int y1 = i % size;
                    int x2 = i / size + 1;
                    int y2 = i % size + 1;
                    if (x1 == 0 || !grid[x1 - 1, y1])
                    {
                        AddLine(blobs.nodes, newMap, x1, y1, x1, y2, true);                               // down
                    }
                    if (y2 == size || !grid[x1, y2])
                    {
                        AddLine(blobs.nodes, newMap, x1, y2, x2, y2, true);                              // right
                    }
                    if (x2 == size || !grid[x2, y1])
                    {
                        AddLine(blobs.nodes, newMap, x2, y2, x2, y1, true);                              // up
                    }
                    if (y1 == 0 || !grid[x1, y1 - 1])
                    {
                        AddLine(blobs.nodes, newMap, x2, y1, x1, y1, true);                               // left
                    }
                }
            }
            return(newMap);
        }
Exemplo n.º 3
0
        private void RandomSubtractTest(Random rand)
        {
            var blobs = new BlobCollection();
            int size  = 2;

            bool[,] grid1 = RandomGrid(rand, size);
            bool[,] grid2 = RandomGrid(rand, size);
            bool[,] grid3 = SubtractGrids(grid1, grid2, size);
            if (!IsValidGrid(grid1, size))
            {
                return;
            }
            if (!IsValidGrid(grid2, size))
            {
                return;
            }
            int expectedArea = AreaOfGrid(grid3, size);
            SectorConstrainedOSMAreaGraph asGraph1 = GridToArea(grid1, size, blobs);
            SectorConstrainedOSMAreaGraph asGraph2 = GridToArea(grid2, size, blobs);
            double area = GetArea(asGraph1.Subtract(asGraph2, blobs).Finalize(blobs).GetTesselationVertices(Color.White));

            if (expectedArea != area)
            {
                throw new NotImplementedException();
            }
        }
Exemplo n.º 4
0
        private static SectorConstrainedOSMAreaGraph MakeOpenRect(Dictionary <long, Vector2d> nodes, int x1, int y1, int x2, int y2, bool leftOpen, bool cornersOnly)
        {
            SectorConstrainedOSMAreaGraph graph = new SectorConstrainedOSMAreaGraph();

            if (!leftOpen)
            {
                AddLine(nodes, graph, x1, y1, x1, y2, cornersOnly); // down
            }
            AddLine(nodes, graph, x1, y2, x2, y2, cornersOnly);     // right
            if (leftOpen)
            {
                AddLine(nodes, graph, x2, y2, x2, y1, cornersOnly); // up
            }
            AddLine(nodes, graph, x2, y1, x1, y1, cornersOnly);     // left
            if (leftOpen)
            {
                MarkStartPoint(graph, x1, y2);
                MarkEndPoint(graph, x1, y1);
            }
            else
            {
                MarkStartPoint(graph, x2, y1);
                MarkEndPoint(graph, x2, y2);
            }
            return(graph);
        }
Exemplo n.º 5
0
 private static void AddLine(Dictionary <long, Vector2d> nodes, SectorConstrainedOSMAreaGraph graph, int x1, int y1, int x2, int y2, bool cornersOnly)
 {
     if (cornersOnly)
     {
         AddLineSeg(nodes, graph, x1, y1, x2, y2);
     }
     else
     {
         if (x1 == x2)
         {
             int length = Math.Abs(y2 - y1);
             int inc    = (y2 - y1) / length;
             for (int i = 0; i < length; i++)
             {
                 AddLineSeg(nodes, graph, x1, y1 + i * inc, x2, y1 + (i + 1) * inc);
             }
         }
         else if (y1 == y2)
         {
             int length = Math.Abs(x2 - x1);
             int inc    = (x2 - x1) / length;
             for (int i = 0; i < length; i++)
             {
                 AddLineSeg(nodes, graph, x1 + i * inc, y1, x1 + (i + 1) * inc, y2);
             }
         }
         else
         {
             throw new NotImplementedException();
         }
     }
 }
Exemplo n.º 6
0
 public void Load(BlobCollection blobs)
 {
     if (loaded)
     {
         return;
     }
     graph  = isCoast ? blobs.GetCoastAreaMap(key, value) : blobs.GetAreaMap(key, value);
     loaded = true;
 }
Exemplo n.º 7
0
 public void Load(BlobCollection blobs)
 {
     if (loaded)
     {
         return;
     }
     polygonSource.Load(blobs);
     graph  = polygonSource.GetGraph();
     loaded = true;
 }
Exemplo n.º 8
0
        private static SectorConstrainedOSMAreaGraph MakeRect(Dictionary <long, Vector2d> nodes, int x1, int y1, int x2, int y2, bool cornersOnly)
        {
            SectorConstrainedOSMAreaGraph graph = new SectorConstrainedOSMAreaGraph();

            AddLine(nodes, graph, x1, y1, x1, y2, cornersOnly); // down
            AddLine(nodes, graph, x1, y2, x2, y2, cornersOnly); // right
            AddLine(nodes, graph, x2, y2, x2, y1, cornersOnly); // up
            AddLine(nodes, graph, x2, y1, x1, y1, cornersOnly); // left
            return(graph);
        }
Exemplo n.º 9
0
        private static void TestAddThenSubtract(int size1, int offsetX1, int offsetY1, int size2, int offsetX2, int offsetY2, int size3, int area, BlobCollection blobs, bool cornersOnly)
        {
            SectorConstrainedOSMAreaGraph square1 = MakeRect(blobs.nodes, 0, 0, size1, size1, cornersOnly);
            SectorConstrainedOSMAreaGraph square2 = MakeRect(blobs.nodes, offsetX1, offsetY1, offsetX1 + size2, offsetY1 + size2, cornersOnly);
            SectorConstrainedOSMAreaGraph square3 = MakeRect(blobs.nodes, offsetX2, offsetY2, offsetX2 + size3, offsetY2 + size3, cornersOnly);
            double areaAns = GetArea(square1.Subtract(square2.Add(square3, blobs), blobs).Finalize(blobs).GetTesselationVertices(Color.White));

            if (areaAns != area)
            {
                throw new NotImplementedException();
            }
        }
Exemplo n.º 10
0
 public void Dispose()
 {
     if (polygonSource1 != null)
     {
         polygonSource1.Dispose();
     }
     if (polygonSource2 != null)
     {
         polygonSource2.Dispose();
     }
     graph = null;
     map   = null;
 }
Exemplo n.º 11
0
 public void Dispose()
 {
     if (polygonSource != null)
     {
         polygonSource.Dispose();
     }
     graph     = null;
     lineGraph = null;
     foreach (var pair in bufferCache)
     {
         pair.Value.Dispose();
     }
 }
Exemplo n.º 12
0
 public void Load(BlobCollection blobs)
 {
     if (loaded)
     {
         return;
     }
     polygonSource1.Load(blobs);
     polygonSource2.Load(blobs);
     graph = polygonSource1.GetGraph().Subtract(polygonSource2.GetGraph(), blobs);
     if (Constants.DEBUG_MODE)
     {
         graph.CheckValid();
     }
     loaded = true;
 }
Exemplo n.º 13
0
        internal SectorConstrainedOSMAreaGraph GetCoastAreaMap(string key, string value)
        {
            // remember: "If you regard this as tracing around an area of land, then the coastline way should be running counterclockwise."
            // gather ways with matching starts/ends to form a super-way, coast ways should always run the same direction, so this becomes easier
            SuperWayCollection            superWays = GenerateSuperWayCollection(EnumerateWays().Where(x => x.keyValues.ContainsKey(key) && x.keyValues[key] == value), false);
            SectorConstrainedOSMAreaGraph map       = DoMultipolygon(superWays);

            if (OSMMetaFinal.IsPixelLand(sector) || borderWay.refs.Count > 5) // just return a big ol' square
            {
                SectorConstrainedOSMAreaGraph temp = new SectorConstrainedOSMAreaGraph();
                for (int i = 1; i < borderWay.refs.Count; i++)
                {
                    if (!temp.nodes.ContainsKey(borderWay.refs[i]))
                    {
                        temp.nodes[borderWay.refs[i]] = new List <AreaNode>();
                        temp.nodes[borderWay.refs[i]].Add(new AreaNode()
                        {
                            id = borderWay.refs[i]
                        });
                    }
                }
                for (int i = 1; i < borderWay.refs.Count; i++)
                {
                    AreaNode prev = temp.nodes[borderWay.refs[i - 1]].Single();
                    AreaNode next = temp.nodes[borderWay.refs[i]].Single();
                    if (prev.id != next.id)
                    {
                        prev.next = next;
                        next.prev = prev;
                    }
                }
                map = map.Intersect(temp, this);
            }
            BlobsIntersector.FixLoops(new List <SectorConstrainedOSMAreaGraph>()
            {
                map
            }, this);
            if (Constants.DEBUG_MODE)
            {
                map.CheckValid();
            }
            return(map);
        }
Exemplo n.º 14
0
        private SectorConstrainedOSMAreaGraph DoMultipolygon(SuperWayCollection superWays)
        {
            SectorConstrainedOSMAreaGraph map = new SectorConstrainedOSMAreaGraph();

            foreach (var superWay in superWays.linkedWays) // we expect these to always start and end outside the sector
            {
                AddConstrainedPaths(map, superWay);
            }
            map.CloseLines(this);
            map.RemoveDuplicateLines();
            if (Constants.DEBUG_MODE)
            {
                map.CheckValid();
            }
            foreach (var superLoop in superWays.loopedWays)
            {
                double wayArea = GetArea(superLoop);
                if (Math.Abs(wayArea) < SMALLEST_ALLOWED_AREA)
                {
                    continue;                                            // ignore zero-area ways since it really messes with the tesselator (ex: way 43624681) TODO: maybe check for absolute zero via node duplication?
                }
                bool isCW          = wayArea < 0;
                var  temp          = new SectorConstrainedOSMAreaGraph();
                bool untouchedLoop = CheckIfUntouchedAndSpin(superLoop);
                if (untouchedLoop)
                {
                    AddUntouchedLoop(temp, superLoop);
                }
                else
                {
                    AddConstrainedPaths(temp, superLoop);
                }
                temp.CloseLines(this);
                temp.RemoveDuplicateLines();
                if (Constants.DEBUG_MODE)
                {
                    temp.CheckValid();
                }
                map.Add(temp, this);
            }
            return(map);
        }
Exemplo n.º 15
0
 private static void TestAddAndSubtract(int size1, int offsetX, int offsetY, int size2, BlobCollection blobs, int addArea, int subArea, bool testOpen, bool cornersOnly)
 {
     if (!testOpen)
     {
         SectorConstrainedOSMAreaGraph square1 = MakeRect(blobs.nodes, 0, 0, size1, size1, cornersOnly);
         SectorConstrainedOSMAreaGraph square2 = MakeRect(blobs.nodes, offsetX, offsetY, offsetX + size2, offsetY + size2, cornersOnly);
         var blobs2 = Clone(blobs); // clone since we modify blobs now
         //if (square1.Clone().Add(square2, blobs).Area(blobs) != addArea) throw new NotImplementedException();
         //if (square1.Clone().Subtract(square2, blobs).Area(blobs) != subArea) throw new NotImplementedException();
         double area1 = GetArea(square1.Clone().Add(square2, blobs).Finalize(blobs).GetTesselationVertices(Color.White));
         double area2 = GetArea(square1.Clone().Subtract(square2, blobs2).Finalize(blobs2).GetTesselationVertices(Color.White));
         if (area1 != addArea)
         {
             throw new NotImplementedException();
         }
         if (area2 != subArea)
         {
             throw new NotImplementedException();
         }
     }
     else
     {
         // test some coastline stuff
         SectorConstrainedOSMAreaGraph square1 = MakeOpenRect(blobs.nodes, 0, 0, size1, size1, true, cornersOnly);                                  // leave left open
         SectorConstrainedOSMAreaGraph square2 = MakeOpenRect(blobs.nodes, offsetX, offsetY, offsetX + size2, offsetY + size2, false, cornersOnly); // leave right open
         var    blobs2 = Clone(blobs);                                                                                                              // clone since we modify blobs now
         double area1  = GetArea(square1.Clone().Add(square2, blobs).Finalize(blobs).GetTesselationVertices(Color.White));
         double area2  = GetArea(square1.Clone().Subtract(square2, blobs2).Finalize(blobs2).GetTesselationVertices(Color.White));
         if (area1 != addArea)
         {
             throw new NotImplementedException();
         }
         if (area2 != subArea)
         {
             throw new NotImplementedException();
         }
     }
 }
Exemplo n.º 16
0
        private static void AddLineSeg(Dictionary <long, Vector2d> nodes, SectorConstrainedOSMAreaGraph graph, int x1, int y1, int x2, int y2)
        {
            long n1 = (x1 + 500) * 1000 + (y1 + 500);
            long n2 = (x2 + 500) * 1000 + (y2 + 500);

            if (!graph.nodes.ContainsKey(n1))
            {
                graph.nodes.Add(n1, new List <AreaNode>()
                {
                    new AreaNode()
                    {
                        id = n1
                    }
                });
            }
            if (!nodes.ContainsKey(n1))
            {
                nodes[n1] = new Vector2d(x1, y1);
            }
            if (!graph.nodes.ContainsKey(n2))
            {
                graph.nodes.Add(n2, new List <AreaNode>()
                {
                    new AreaNode()
                    {
                        id = n2
                    }
                });
            }
            if (!nodes.ContainsKey(n2))
            {
                nodes[n2] = new Vector2d(x2, y2);
            }
            graph.nodes[n1].Single().next = graph.nodes[n2].Single();
            graph.nodes[n2].Single().prev = graph.nodes[n1].Single();
        }
Exemplo n.º 17
0
        private static void MarkStartPoint(SectorConstrainedOSMAreaGraph graph, int x, int y)
        {
            long n = (x + 500) * 1000 + (y + 500);

            graph.nodes.Remove(n);
        }
Exemplo n.º 18
0
        private void OrientSuperWays(SuperWayCollection superInnerWays, SuperWayCollection superOuterWays, bool topLeftIsInside)
        {
            List <List <Way> > allLinkedWays = new List <List <Way> >();

            allLinkedWays.AddRange(superInnerWays.linkedWays);
            allLinkedWays.AddRange(superOuterWays.linkedWays);
            List <List <Way> > allLoopedWays = new List <List <Way> >();

            allLoopedWays.AddRange(superInnerWays.loopedWays);
            allLoopedWays.AddRange(superOuterWays.loopedWays);
            // assume all loops dont touch the edge for now (they can be corrected later)
            foreach (var superLoop in allLoopedWays)
            {
                SectorConstrainedOSMAreaGraph temp = new SectorConstrainedOSMAreaGraph();
                bool isCW = ApproximateCW(superLoop);
                if (isCW) // TODO: why did I have this has the opposite logic before??
                {
                    // force to be an "outer"
                    superLoop.Reverse();
                    foreach (var way in superLoop)
                    {
                        way.refs.Reverse();
                    }
                }
            }

            // now do the -real- orienting
            List <SuperWayIntersection> intersections = new List <SuperWayIntersection>();

            foreach (var superWay in superOuterWays.linkedWays) // we expect these to always start and end outside the sector
            {
                AddIntersections(intersections, superWay, false);
            }
            foreach (var superLoop in superOuterWays.loopedWays)
            {
                bool untouchedLoop = CheckIfUntouchedAndSpin(superLoop);
                if (!untouchedLoop)
                {
                    AddIntersections(intersections, superLoop, false);
                }
            }
            if (intersections.Count == 0 && topLeftIsInside)
            {
                // we are inside some quite large relation - let's add the big ol' box so we can subtract from it
                superOuterWays.loopedWays.Add(new List <Way>()
                {
                    borderWay
                });
            }
            foreach (var superWay in superInnerWays.linkedWays) // we expect these to always start and end outside the sector
            {
                AddIntersections(intersections, superWay, true);
            }
            foreach (var superLoop in superInnerWays.loopedWays)
            {
                bool untouchedLoop = CheckIfUntouchedAndSpin(superLoop);
                if (!untouchedLoop)
                {
                    AddIntersections(intersections, superLoop, true);
                }
            }
            if (intersections.Count % 2 != 0)
            {
                throw new NotImplementedException();
            }
            intersections = intersections.OrderBy(x => (Math.Atan2(x.intersection.Y - 0.5, x.intersection.X - 0.5) + 8 * Math.PI - (-Math.PI * 3 / 4)) % (2 * Math.PI)).ToList(); // clockwise order starting at top-left
            // look for duplicates that are near each other, had this issue with relation 534928, if they're close enough we'll just ignore them for now - TODO: this may cause issues later
            HashSet <int> ignore = new HashSet <int>();

            for (int i = 0; i < intersections.Count; i++)
            {
                int j = (i + 1) % intersections.Count;
                if ((intersections[i].intersection - intersections[j].intersection).Length() < 0.0000001)
                {
                    ignore.Add(i);
                    ignore.Add(j);
                }
            }
            HashSet <List <Way> > correctDirectionHash   = new HashSet <List <Way> >();
            HashSet <List <Way> > incorrectDirectionHash = new HashSet <List <Way> >();

            for (int i = 0; i < intersections.Count; i++)
            {
                if (ignore.Contains(i))
                {
                    continue;
                }
                bool correctDirection = intersections[i].leaving == (topLeftIsInside ^ (i % 2 == 1));
                if (intersections[i].inner)
                {
                    correctDirection = !correctDirection;                         // flip all of the inners back, since we're about to subtract them
                }
                if (correctDirection)
                {
                    correctDirectionHash.Add(intersections[i].superWay);
                    if (incorrectDirectionHash.Contains(intersections[i].superWay))
                    {
                        throw new NotImplementedException();                                                             // disagreement
                    }
                }
                else
                {
                    incorrectDirectionHash.Add(intersections[i].superWay);
                    if (correctDirectionHash.Contains(intersections[i].superWay))
                    {
                        throw new NotImplementedException();                                                           // disagreement
                    }
                }
            }
            foreach (var superWay in incorrectDirectionHash)
            {
                superWay.Reverse();
                foreach (var way in superWay)
                {
                    way.refs.Reverse();
                }
            }
        }
Exemplo n.º 19
0
        internal SectorConstrainedOSMAreaGraph GetAreaMap(string key, string value)
        {
            var simpleWays = EnumerateWays().Where(x => x.keyValues.ContainsKey(key) && x.keyValues[key] == value); // we expect all of these to be closed loops
            // copy this dang multipolygon way id gathering logic
            Dictionary <long, Way> wayLookup = new Dictionary <long, Way>();

            foreach (var way in EnumerateWays())
            {
                wayLookup[way.id] = way;
            }
            List <List <long> > inners           = new List <List <long> >();
            List <List <long> > outers           = new List <List <long> >();
            List <long>         relationIds      = new List <long>();
            HashSet <long>      otherInnerOuters = new HashSet <long>();

            foreach (var blob in blobs)
            {
                if (blob.type != "OSMData")
                {
                    continue;
                }
                int typeIndex         = blob.pBlock.stringtable.vals.IndexOf("type");
                int multipolygonIndex = blob.pBlock.stringtable.vals.IndexOf("multipolygon");
                int outerIndex        = blob.pBlock.stringtable.vals.IndexOf("outer");
                int innerIndex        = blob.pBlock.stringtable.vals.IndexOf("inner");
                int keyIndex          = blob.pBlock.stringtable.vals.IndexOf(key);
                int valueIndex        = blob.pBlock.stringtable.vals.IndexOf(value);
                if (new[] { typeIndex, multipolygonIndex, outerIndex, innerIndex, keyIndex, valueIndex }.Contains(-1))
                {
                    continue;
                }
                foreach (var pGroup in blob.pBlock.primitivegroup)
                {
                    foreach (var relation in pGroup.relations)
                    {
                        bool isKeyValue         = false;
                        bool isTypeMultipolygon = false;
                        for (int i = 0; i < relation.keys.Count; i++)
                        {
                            if (relation.keys[i] == keyIndex && relation.vals[i] == valueIndex)
                            {
                                isKeyValue = true;
                            }
                            if (relation.keys[i] == typeIndex && relation.vals[i] == multipolygonIndex)
                            {
                                isTypeMultipolygon = true;
                            }
                        }
                        if (isTypeMultipolygon)
                        {
                            if (isKeyValue)
                            {
                                List <long> innerWayIds = new List <long>();
                                List <long> outerWayIds = new List <long>();
                                for (int i = 0; i < relation.roles_sid.Count; i++)
                                {
                                    // just outer for now
                                    if (relation.types[i] == 1)
                                    {
                                        if (relation.roles_sid[i] == 0 && innerIndex != 0 && outerIndex != 0)
                                        {
                                            // some ways are in a relation without any inner/outer tag
                                            // ex: 359181377 in relation 304768
                                            outerWayIds.Add(relation.memids[i]);
                                        }
                                        else
                                        {
                                            if (relation.roles_sid[i] == innerIndex)
                                            {
                                                innerWayIds.Add(relation.memids[i]);
                                            }
                                            if (relation.roles_sid[i] == outerIndex)
                                            {
                                                outerWayIds.Add(relation.memids[i]);
                                            }
                                        }
                                    }
                                }
                                inners.Add(innerWayIds);
                                outers.Add(outerWayIds);
                                relationIds.Add(relation.id);
                            }
                            else
                            {
                                for (int i = 0; i < relation.roles_sid.Count; i++)
                                {
                                    // just outer for now
                                    if (relation.types[i] == 1)
                                    {
                                        otherInnerOuters.Add(relation.memids[i]);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            HashSet <long> innersAndOuters = new HashSet <long>();

            foreach (var innerList in inners)
            {
                foreach (var inner in innerList)
                {
                    innersAndOuters.Add(inner);
                }
            }
            foreach (var outerList in outers)
            {
                foreach (var outer in outerList)
                {
                    innersAndOuters.Add(outer);
                }
            }
            // end gathering logic
            // add each simple way, flipping them where necessary
            List <SectorConstrainedOSMAreaGraph> addingMaps = new List <SectorConstrainedOSMAreaGraph>();

            foreach (var way in simpleWays)
            {
                if (innersAndOuters.Contains(way.id))
                {
                    continue;                                   // sometimes lake multipolygons also tag several pieces - at best this is redundant, and at worst causes errors
                }
                if (way.refs.Count < 3)
                {
                    continue;                     // we -usually- only ever see lines with multipolygons, but I found a weird way like 43435045
                }
                if (way.selfIntersects)
                {
                    continue;                     // just ignore ways like 43410874 to keep you sane
                }
                SectorConstrainedOSMAreaGraph simpleMap = new SectorConstrainedOSMAreaGraph();
                var superLoop = new List <Way>()
                {
                    way
                };
                if (way.refs.Last() != way.refs.First())
                {
                    if (otherInnerOuters.Contains(way.id))
                    {
                        continue;                   // unsure of how else to ignore bad ways like 43815149
                    }
                    way.refs.Add(way.refs.First()); // some folks forget to close a simple way, or perhaps the mistake is tagging subcomponents of a relation
                }
                if (!IsValid(superLoop))
                {
                    continue;                      // ignore relations like 512080985 which contain duplicate nodes
                }
                double wayArea = GetArea(superLoop);
                if (Math.Abs(wayArea) < SMALLEST_ALLOWED_AREA)
                {
                    continue;                                            // ignore zero-area ways since it really messes with the tesselator (ex: way 43624681) TODO: maybe check for absolute zero via node duplication?
                }
                bool isCW = wayArea < 0;
                if (isCW)
                {
                    way.refs.Reverse();       // the simple polygons are always "outers"
                }
                bool untouchedLoop = CheckIfUntouchedAndSpin(superLoop);
                if (untouchedLoop)
                {
                    AddUntouchedLoop(simpleMap, superLoop);
                }
                else
                {
                    AddConstrainedPaths(simpleMap, superLoop);
                    simpleMap.CloseLines(this);
                    if (Constants.DEBUG_MODE)
                    {
                        simpleMap.CheckValid();
                    }
                }
                simpleMap.RemoveDuplicateLines();
                if (Constants.DEBUG_MODE)
                {
                    simpleMap.CheckValid();
                }
                addingMaps.Add(simpleMap);
            }
            // construct each multipolygon to add separately
            for (int i = 0; i < inners.Count; i++) // foreach multipolygon, basically
            {
                if (OSMMetaFinal.GLOBAL_FINAL.badRelations.Contains(relationIds[i]))
                {
                    continue;
                }
                // TODO: with islands inside of ponds inside of islands inside of ponds, etc. we wouldn't expect this to work
                // however, we're taking advantage of the fact that Add/Subtract doesn't check for that for now (until Finalize)
                SuperWayCollection superInnerWays = GenerateSuperWayCollection(inners[i].Where(x => wayLookup.ContainsKey(x)).Select(x => Copy(wayLookup[x])), true);
                SuperWayCollection superOuterWays = GenerateSuperWayCollection(outers[i].Where(x => wayLookup.ContainsKey(x)).Select(x => Copy(wayLookup[x])), true);
                superInnerWays.loopedWays = superInnerWays.loopedWays.Where(x => Math.Abs(GetArea(x)) >= SMALLEST_ALLOWED_AREA).ToList(); // ignore zero-area ways since it really messes with the tesselator (ex: way 43624681) TODO: maybe check for absolute zero via node duplication?
                superOuterWays.loopedWays = superOuterWays.loopedWays.Where(x => Math.Abs(GetArea(x)) >= SMALLEST_ALLOWED_AREA).ToList(); // ignore zero-area ways since it really messes with the tesselator (ex: way 43624681) TODO: maybe check for absolute zero via node duplication?
                if (!IsValid(superInnerWays))
                {
                    continue;
                }
                if (!IsValid(superOuterWays))
                {
                    continue;
                }
                OrientSuperWays(superInnerWays, superOuterWays, gridPointInfo.relations.Contains(relationIds[i]));
                SectorConstrainedOSMAreaGraph innerMap = DoMultipolygon(superInnerWays);
                SectorConstrainedOSMAreaGraph outerMap = DoMultipolygon(superOuterWays);
                if (Constants.DEBUG_MODE)
                {
                    innerMap.CheckValid();
                }
                if (Constants.DEBUG_MODE)
                {
                    outerMap.CheckValid();
                }
                SectorConstrainedOSMAreaGraph multiPolygon = outerMap.Subtract(innerMap, this);
                if (Constants.DEBUG_MODE)
                {
                    multiPolygon.CheckValid();
                }
                addingMaps.Add(multiPolygon);
            }
            SectorConstrainedOSMAreaGraph map = new SectorConstrainedOSMAreaGraph();

            BlobsIntersector.FixLoops(addingMaps, this);
            foreach (var addingMap in addingMaps)
            {
                map.Add(addingMap, this);
            }
            if (Constants.DEBUG_MODE)
            {
                map.CheckValid();
            }
            return(map);
        }
Exemplo n.º 20
0
        private void AddConstrainedPaths(SectorConstrainedOSMAreaGraph map, List <Way> superWay)
        {
            if (sector.ContainsCoord(nodes[superWay.First().refs.First()]))
            {
                throw new NotImplementedException();
            }
            if (sector.ContainsCoord(nodes[superWay.Last().refs.Last()]))
            {
                throw new NotImplementedException();
            }
            List <AreaNode> nodesToAdd = new List <AreaNode>();

            for (int i = 0; i < superWay.Count; i++)
            {
                for (int j = 1; j < superWay[i].refs.Count; j++)
                {
                    long next = superWay[i].refs[j];
                    nodesToAdd.Add(new AreaNode()
                    {
                        id = next
                    });
                }
            }
            for (int i = 0; i < nodesToAdd.Count; i++)
            {
                var prev = nodesToAdd[(i + nodesToAdd.Count - 1) % nodesToAdd.Count];
                var curr = nodesToAdd[i];
                var next = nodesToAdd[(i + 1) % nodesToAdd.Count];
                if (sector.BorderContainsCoord(nodes[curr.id]))
                {
                    bool add = false;
                    if (!sector.BorderContainsCoord(nodes[next.id]) && sector.ContainsCoord(nodes[next.id]))
                    {
                        curr.next = next;
                        next.prev = curr;
                        add       = true;
                    }
                    if (!sector.BorderContainsCoord(nodes[prev.id]) && sector.ContainsCoord(nodes[prev.id]))
                    {
                        curr.prev = prev;
                        prev.next = curr;
                        add       = true;
                    }
                    if (sector.BorderContainsCoord(nodes[prev.id]) && nodes[prev.id].X != nodes[curr.id].X && nodes[prev.id].Y != nodes[curr.id].Y)
                    {
                        prev.next = curr;
                        curr.prev = prev;
                        add       = true;
                        if (!map.nodes.ContainsKey(prev.id))
                        {
                            map.nodes[prev.id] = new List <AreaNode>();
                        }
                        map.nodes[prev.id].Add(prev);
                    }
                    if (add)
                    {
                        if (!map.nodes.ContainsKey(curr.id))
                        {
                            map.nodes[curr.id] = new List <AreaNode>();
                        }
                        map.nodes[curr.id].Add(curr);
                    }
                }
                else if (sector.ContainsCoord(nodes[curr.id]))
                {
                    if (!map.nodes.ContainsKey(curr.id))
                    {
                        map.nodes[curr.id] = new List <AreaNode>();
                    }
                    map.nodes[curr.id].Add(curr);
                    if (!sector.ContainsCoord(nodes[prev.id]))
                    {
                        throw new NotImplementedException();                                        // previous should be border point or inside
                    }
                    if (!sector.ContainsCoord(nodes[next.id]))
                    {
                        throw new NotImplementedException();                                        // next should be border point or inside
                    }
                    if (!sector.BorderContainsCoord(nodes[prev.id]))
                    {
                        curr.prev = prev;                                              // edges will handle their prev/next logic
                    }
                    if (!sector.BorderContainsCoord(nodes[next.id]))
                    {
                        curr.next = next;
                    }
                }
            }
        }
Exemplo n.º 21
0
        private void ToughTest()
        {
            var blobs = new BlobCollection();
            SectorConstrainedOSMAreaGraph coast = new SectorConstrainedOSMAreaGraph();

            AddLineSeg(blobs.nodes, coast, 6, 6, 6, 5);
            AddLineSeg(blobs.nodes, coast, 6, 5, 6, 4);
            AddLineSeg(blobs.nodes, coast, 6, 4, 6, 3);
            AddLineSeg(blobs.nodes, coast, 6, 3, 5, 2);
            AddLineSeg(blobs.nodes, coast, 5, 2, 3, 2);
            AddLineSeg(blobs.nodes, coast, 3, 2, 2, 2);
            AddLineSeg(blobs.nodes, coast, 2, 2, 1, 2);
            MarkStartPoint(coast, 6, 6);
            MarkEndPoint(coast, 1, 2);
            SectorConstrainedOSMAreaGraph bigLake = new SectorConstrainedOSMAreaGraph();

            AddLineSeg(blobs.nodes, bigLake, 7, 0, 3, 0);
            AddLineSeg(blobs.nodes, bigLake, 3, 0, 3, 1);
            AddLineSeg(blobs.nodes, bigLake, 3, 1, 4, 1);
            AddLineSeg(blobs.nodes, bigLake, 4, 1, 5, 2);
            AddLineSeg(blobs.nodes, bigLake, 5, 2, 6, 3);
            AddLineSeg(blobs.nodes, bigLake, 6, 3, 6, 4);
            AddLineSeg(blobs.nodes, bigLake, 6, 4, 6, 5);
            AddLineSeg(blobs.nodes, bigLake, 6, 5, 7, 5);
            AddLineSeg(blobs.nodes, bigLake, 7, 5, 7, 0);
            SectorConstrainedOSMAreaGraph smallLake = new SectorConstrainedOSMAreaGraph();

            AddLineSeg(blobs.nodes, smallLake, 2, 1, 2, 2);
            AddLineSeg(blobs.nodes, smallLake, 2, 2, 3, 2);
            AddLineSeg(blobs.nodes, smallLake, 3, 2, 5, 4);
            AddLineSeg(blobs.nodes, smallLake, 5, 4, 6, 4);
            AddLineSeg(blobs.nodes, smallLake, 6, 4, 3, 1);
            AddLineSeg(blobs.nodes, smallLake, 3, 1, 2, 1);
            double coastArea = GetArea(coast.Finalize(blobs).GetTesselationVertices(Color.White));

            if (coastArea != 19.5 - 10)
            {
                throw new NotImplementedException();                         // sure, minus 10 because everything's scaled up and we can't properly close
            }
            double bigLakeArea = GetArea(bigLake.Finalize(blobs).GetTesselationVertices(Color.White));

            if (bigLakeArea != 10)
            {
                throw new NotImplementedException();
            }
            double smallLakeArea = GetArea(smallLake.Finalize(blobs).GetTesselationVertices(Color.White));

            if (smallLakeArea != 3.5)
            {
                throw new NotImplementedException();
            }
            var    lakes     = bigLake.Clone().Add(smallLake, blobs);
            double lakesArea = GetArea(lakes.Finalize(blobs).GetTesselationVertices(Color.White));
            // if (lakesArea != 13.5) throw new NotImplementedException(); // looks like the tesselator is filling in the hole?
            var    final     = coast.Clone().Subtract(lakes, blobs);
            double finalArea = GetArea(final.Finalize(blobs).GetTesselationVertices(Color.White));

            if (finalArea != 17.5 - 10)
            {
                throw new NotImplementedException();                         // sure, minus 10 because everything's scaled up and we can't properly close
            }
        }
Exemplo n.º 22
0
 public void Dispose()
 {
     graph = null;
     map   = null;
 }