Ejemplo n.º 1
0
        public IEnumerable <Node> NodeContainment(Dictionary <Relation, Polygon[]> relationsDict, IEnumerable <Node> nodeStreamer)
        {
            // prebuild polygons to reduce contention
            foreach (var node in nodeStreamer)
            {
                var containingRelations = relationsDict.AsParallel().Where(kvp =>
                {
                    var target   = kvp.Key;
                    var polygons = kvp.Value;

                    foreach (var polygon in polygons)
                    {
                        if (PolygonContainment.Contains(polygon, node))
                        {
                            return(true);
                        }

                        foreach (var polyNodes in polygon.Nodes)
                        {
                            if (polyNodes.Id == node.Id)
                            {
                                return(true);
                            }
                        }
                    }

                    return(false);
                }).Select(x => x.Key.Id);

                node.Relations.AddRange(containingRelations);
                yield return(node);
            }
        }
Ejemplo n.º 2
0
        public void SplitContained()
        {
            var polygon = GetSquare(1, 0);

            var way = new Way("abc", new[]
            {
                new Node("20", -1, 0.5),
                new Node("21", 0, 0.5),
                new Node("22", 0.5, 0.5),
                new Node("23", 1.5, 0.5),
                new Node("24", 0.5, 0.25),
                new Node("25", 0.5, -0.5)
            });
            var polygonContainment = new PolygonContainment(polygon);

            var(contained, uncontained) = polygonContainment.SplitWayByContainment(way);
            Assert.Contains(way.Nodes[0], uncontained[0].Nodes);
            Assert.Contains(way.Nodes[1], contained[0].Nodes);
            Assert.Contains(way.Nodes[2], contained[0].Nodes);
            Assert.Contains(way.Nodes[3], contained[0].Nodes);
            Assert.Contains(way.Nodes[3], uncontained[1].Nodes);
            Assert.Contains(way.Nodes[4], contained[1].Nodes);
            Assert.Contains(way.Nodes[5], contained[1].Nodes);
            Assert.Equal(2, contained.Count);
            Assert.Equal(2, uncontained.Count);
        }
Ejemplo n.º 3
0
        public void TotallyContained(double edgeLength, double center)
        {
            var polygon = GetSquare(edgeLength, center);
            var way     = new Way("abc", new []
            {
                new Node("20", center, center),
                new Node("21", center + edgeLength / 2, center + edgeLength / 2),
                new Node("22", center + edgeLength, center + edgeLength)
            });
            var polygonContainment = new PolygonContainment(polygon);

            var(contained, uncontained) = polygonContainment.SplitWayByContainment(way);
            Assert.Contains(way, contained);
            Assert.Empty(uncontained);
        }
Ejemplo n.º 4
0
        public void NotContained(double edgeLength, double center)
        {
            var polygon = GetSquare(edgeLength, center);

            var moveOut = 2 * edgeLength;

            var way = new Way("abc", new[]
            {
                new Node("2", center + moveOut, 2 * center + moveOut),
                new Node("2", center + edgeLength / 2 + moveOut, center + edgeLength / 2 + moveOut),
                new Node("2", center + edgeLength + moveOut, center + edgeLength + moveOut)
            });
            var polygonContainment = new PolygonContainment(polygon);

            var(contained, uncontained) = polygonContainment.SplitWayByContainment(way);
            Assert.Contains(way, uncontained);
            Assert.Null(contained);
        }
Ejemplo n.º 5
0
        public List <Way> Transform(Relation target, Geometry geometry)
        {
            var polygon     = RelationPolygonMemoizer.Instance.GetPolygons(target).First(); // todo first is a problem. some relations have more than one!
            var containment = new PolygonContainment(polygon);
            var ways        = new List <Way>();

            foreach (var way in geometry.Ways)
            {
                var(contains, notContains) = containment.SplitWayByContainment(way);
                foreach (var newWay in contains)
                {
                    newWay.Tags.Add("rfInPolygon", newWay.FootTraffic() ? "in" : "notfoot");
                }
                foreach (var newWay in notContains)
                {
                    newWay.Tags.Add("rfInPolygon", "out");
                }

                ways.AddRange(contains);
                ways.AddRange(notContains);
            }

            return(ways);
        }
Ejemplo n.º 6
0
        /// <summary>
        /// use n + 2 threads.
        /// Thread 0 will iterate through nodeStreamer and add to n queues in round robin.
        /// Threads 1-n will read a queue and process, writing to a queue.
        /// Thread n+1 will read all output queues and yield one at a time.
        /// </summary>
        /// <param name="relationsDict"></param>
        /// <param name="nodeStreamer"></param>
        /// <returns></returns>

        public IEnumerable <Node> ThreadedNodeContainment(Dictionary <Relation, Polygon[]> relationsDict, IEnumerable <Node> nodeStreamer)
        {
            var allDone        = false; // shared - read but only written by the main thread.
            int numThreads     = RouteCleanerSettings.GetInstance().NumThreads;
            var requestQueues  = Enumerable.Range(0, numThreads).Select(_ => new ConcurrentQueue <Node>()).ToArray();
            var responseQueues = Enumerable.Range(0, numThreads).Select(_ => new ConcurrentQueue <Node>()).ToArray();
            var readThread     = Task <int> .Factory.StartNew(() =>
            {
                var numNodes = 0;
                foreach (var node in nodeStreamer)
                {
                    requestQueues[numNodes % numThreads].Enqueue(node);
                    numNodes++;

                    if (numNodes % 10000 == 0)
                    {
                        var depths       = requestQueues.Select(q => q.Count);
                        var averageDepth = depths.Average();
                        while (averageDepth > 20000)
                        {
                            //   Console.WriteLine($"Reader thread sleeping to let other threads catch up");
                            Thread.Sleep(RouteCleanerSettings.GetInstance().ReaderThreadSleepInterval); // give it a little time to cool off.

                            depths       = requestQueues.Select(q => q.Count);
                            averageDepth = depths.Average();
                        }
                    }
                }

                // when done, push a null to each queue
                Console.WriteLine($"Reader thread done");
                foreach (var q in requestQueues)
                {
                    q.Enqueue(null);
                }

                return(numNodes);
            });

            var processedCount = new int[numThreads];
            var processThreads = Enumerable.Range(0, numThreads).Select(processThreadIdx => Task <int> .Factory.StartNew(() =>
            {
                Console.WriteLine($"Thread {processThreadIdx} reporting for duty");
                while (true)
                {
                    Node nodeToProcess = null;
                    while (requestQueues[processThreadIdx].TryDequeue(out nodeToProcess))  // when queue is empty, we want to keep processing. When it has a null in it, we halt. Thus two whiles.
                    {
                        if (nodeToProcess == null)
                        {
                            // pusher will push a null when the queue is done.
                            responseQueues[processThreadIdx].Enqueue(null);
                            Console.WriteLine($"Thread {processThreadIdx} done");
                            return(processThreadIdx);
                        }

                        var containingRelations = relationsDict.Where(kvp =>
                        {
                            var target   = kvp.Key;
                            var polygons = kvp.Value;

                            foreach (var polygon in polygons)
                            {
                                if (PolygonContainment.Contains(polygon, nodeToProcess))
                                {
                                    return(polygon.IsOuter);
                                }
                            }

                            return(false);
                        }).Select(x => x.Key.Id);

                        nodeToProcess.Relations.AddRange(containingRelations);
                        responseQueues[processThreadIdx].Enqueue(nodeToProcess);
                        processedCount[processThreadIdx]++;
                    }

                    Console.WriteLine($"Thread {processThreadIdx} failed to dequeue");
                    Thread.Sleep(1000);
                }
            })).ToArray(); // <-- that's important - otherwise these never actually happen!

            // print status thread
            var statusThread = Task.Factory.StartNew(() =>
            {
                while (!allDone)
                {
                    Thread.Sleep(10 * 1000);
                    var queueDepths     = requestQueues.Select(q => q.Count).Average();
                    var averageFinished = processedCount.Sum();
                    Console.WriteLine($"Checkin: {queueDepths} average depth with {averageFinished} processed.");
                }
                Console.WriteLine("Checking thread done.");
            });

            // main thread writes
            var deadThreads = Enumerable.Range(0, numThreads).Select(_ => false).ToArray();

            while (true)
            {
                var didWork = false;
                for (var i = 0; i < numThreads; i++)
                {
                    if (!deadThreads[i])
                    {
                        Node processedNode = null;
                        if (responseQueues[i].TryDequeue(out processedNode))
                        {
                            if (processedNode == null)
                            {
                                deadThreads[i] = true;
                            }
                            else
                            {
                                didWork = true;
                                yield return(processedNode);
                            }
                        }
                    }
                }
                if (deadThreads.All(x => x))
                {
                    break;
                }
                if (!didWork)
                {
                    Thread.Sleep(1000); // if the queues are all empty, then wait for a little while. No sense having this thread spin.
                    // maybe we should do message passing here?
                }
            }

            allDone = true;
        }