private void CheckEdges(SubdivisionSearch search)
        {
            foreach (SubdivisionEdge edge in search.Source.Edges.Values)
            {
                var edgeElement = new SubdivisionElement(edge);
                var twinElement = new SubdivisionElement(edge._twin);

                // SubdivisionSearch always returns lexicographically increasing half-edges
                PointD start = edge._origin, end = edge._twin._origin;
                int    result  = PointDComparerX.CompareEpsilon(start, end, search.Source.Epsilon);
                var    element = (result < 0 ? edgeElement : twinElement);

                PointD q = new PointD((start.X + end.X) / 2, (start.Y + end.Y) / 2);
                Assert.AreEqual(element, search.Find(q));

                // brute force search may return half-edge or its twin
                var found = search.Source.Find(q, 1e-10);
                Assert.IsTrue(found == edgeElement || found == twinElement);

                // brute force search also supports comparison epsilon
                PointD offset = GeoAlgorithms.RandomPoint(-0.1, -0.1, 0.2, 0.2);
                found = search.Source.Find(q + offset, 0.25);
                Assert.IsTrue(found == edgeElement || found == twinElement);
            }
        }
Exemplo n.º 2
0
        private static void RandomPointsComparer(IPointDComparer comparer)
        {
            RectD bounds = new RectD(-100, -100, 200, 200);

            PointD[] points = GeoAlgorithms.RandomPoints(100, bounds, comparer, 2);

            for (int i = 0; i < points.Length; i++)
            {
                PointD p = points[i];
                Assert.IsTrue(bounds.Contains(p));
                if (i > 0)
                {
                    Assert.AreEqual(+1, comparer.Compare(p, points[i - 1]));
                }
                if (i < points.Length - 1)
                {
                    Assert.AreEqual(-1, comparer.Compare(p, points[i + 1]));
                }

                for (int j = 0; j < points.Length; j++)
                {
                    if (i == j)
                    {
                        continue;
                    }
                    double distance = p.Subtract(points[j]).LengthSquared;
                    Assert.GreaterOrEqual(distance, 4);
                }
            }
        }
 public void Polygon()
 {
     for (int i = 3; i < 9; i++)
     {
         var     polygon = new RegularPolygon(30.0 / i, i, PolygonOrientation.OnEdge);
         LineD[] lines   = GeoAlgorithms.ConnectPoints(true, polygon.Vertices);
         CheckSearch(lines);
     }
 }
Exemplo n.º 4
0
        private void DrawIntersections(LineD[] lines)
        {
            const double radius = 4.0;

            // generate new random line set if desired
            if (lines == null)
            {
                Size scale = new Size(OutputBox.Width - 4 * radius, OutputBox.Height - 4 * radius);

                int count = MersenneTwister.Default.Next(3, 20);
                lines = new LineD[count];

                for (int i = 0; i < lines.Length; i++)
                {
                    lines[i] = GeoAlgorithms.RandomLine(
                        2 * radius, 2 * radius, scale.Width, scale.Height);
                }
            }

            _lines = lines;
            double epsilon = (double)ToleranceUpDown.Value;

            _crossings = (epsilon > 0.0 ?
                          MultiLineIntersection.FindSimple(lines, epsilon) :
                          MultiLineIntersection.FindSimple(lines));

            LinesLabel.Content = String.Format("{0}/{1}", lines.Length, _crossings.Length);
            OutputBox.Children.Clear();

            // draw line set
            foreach (LineD line in lines)
            {
                var shape = new Line()
                {
                    X1     = line.Start.X, Y1 = line.Start.Y,
                    X2     = line.End.X, Y2 = line.End.Y,
                    Stroke = Brushes.Black
                };

                OutputBox.Children.Add(shape);
            }

            // draw intersections as hollow circles
            foreach (var crossing in _crossings)
            {
                var circle = new Ellipse()
                {
                    Width  = 2 * radius, Height = 2 * radius,
                    Stroke = Brushes.Red
                };

                Canvas.SetLeft(circle, crossing.Shared.X - radius);
                Canvas.SetTop(circle, crossing.Shared.Y - radius);

                OutputBox.Children.Add(circle);
            }
        }
Exemplo n.º 5
0
        public void RandomPoints()
        {
            RectD bounds = new RectD(-100, -100, 200, 200);

            PointD[] points = GeoAlgorithms.RandomPoints(100, bounds);
            foreach (PointD p in points)
            {
                Assert.IsTrue(bounds.Contains(p));
            }
        }
        public void Random()
        {
            LineD[] lines = new LineD[100];
            for (int i = 0; i < lines.Length; i++)
            {
                lines[i] = GeoAlgorithms.RandomLine(0, 0, 1000000, 1000000);
            }

            FindBoth(lines);
        }
Exemplo n.º 7
0
        public void VoronoiTest()
        {
            int count  = MersenneTwister.Default.Next(10, 100);
            var points = new PointD[count];

            for (int i = 0; i < points.Length; i++)
            {
                points[i] = GeoAlgorithms.RandomPoint(-1000, -1000, 2000, 2000);
            }

            var results  = Voronoi.FindAll(points, new RectD(-1000, -1000, 2000, 2000));
            var delaunay = results.ToDelaunySubdivision();

            delaunay.Validate();
            var voronoi = results.ToVoronoiSubdivision();

            voronoi.Source.Validate();

            // compare original and subdivision’s Delaunay edges
            var delaunayEdges = delaunay.ToLines();

            Assert.AreEqual(results.DelaunayEdges.Length, delaunayEdges.Length);

            foreach (LineD edge in results.DelaunayEdges)
            {
                if (PointDComparerY.CompareExact(edge.Start, edge.End) > 0)
                {
                    Assert.Contains(edge.Reverse(), delaunayEdges);
                }
                else
                {
                    Assert.Contains(edge, delaunayEdges);
                }
            }

            // compare original and subdivision’s Voronoi regions
            var voronoiFaces = voronoi.Source.Faces;

            Assert.AreEqual(results.VoronoiRegions.Length, voronoiFaces.Count - 1);

            foreach (var face in voronoiFaces.Values)
            {
                if (face.OuterEdge == null)
                {
                    continue;
                }
                int index = voronoi.FromFace(face);

                PointD[] polygon = results.VoronoiRegions[index];
                CollectionAssert.AreEquivalent(polygon, face.OuterEdge.CyclePolygon);

                PointD site = results.GeneratorSites[index];
                Assert.AreNotEqual(PolygonLocation.Outside, face.OuterEdge.Locate(site));
            }
        }
Exemplo n.º 8
0
        private void GeometryTest()
        {
            Stopwatch timer     = new Stopwatch();
            var       testCases = _geometryTestCases;

            Output(String.Format("{0,6}", " "));
            foreach (TestCase test in testCases)
            {
                Output(String.Format("{0,12}", test.Name));
            }
            Output("\n");

            const int outerLoop = 100, innerLoop = 100;
            const int iterations = outerLoop * innerLoop;

            for (int size = 10; size <= 120; size += 10)
            {
                PointD[] points = new PointD[size];

                for (int i = 0; i < outerLoop; i++)
                {
                    for (int j = 0; j < points.Length; j++)
                    {
                        points[j] = GeoAlgorithms.RandomPoint(0, 0, 1000, 1000);
                    }

                    foreach (TestCase test in testCases)
                    {
                        // trigger JIT compilation and reset ticks
                        if (i == 0)
                        {
                            test.FindPoints(points);
                            test.Ticks = 0;
                        }

                        timer.Restart();
                        for (int k = 0; k < innerLoop; k++)
                        {
                            test.FindPoints(points);
                        }
                        timer.Stop();
                        test.Ticks += timer.ElapsedTicks;
                    }
                }

                Output(String.Format("{0,6}", size));
                foreach (TestCase test in testCases)
                {
                    Output(String.Format("{0,12:N2}", AverageMicrosecs(test.Ticks, iterations)));
                }
                Output("\n");
            }

            Output("\nTimes are µsec averages for point sets of the indicated size.\n");
        }
        public PointInPolygonTest()
        {
            InitializeComponent();
            _polygon = GeoAlgorithms.RandomPolygon(0.0, 0.0, OutputBox.Width, OutputBox.Height);

            OutputBox.Children.Add(new Polygon()
            {
                Points = _polygon.ToWpfPoints(),
                Stroke = Brushes.Black
            });
        }
Exemplo n.º 10
0
        public void PolygonCentroid()
        {
            PointD p0 = new PointD(0, 0), p1 = new PointD(1, 1), p2 = new PointD(2, 0);
            PointD p3 = new PointD(0, 2), p4 = new PointD(2, 2);

            Assert.AreEqual(new PointD(1, 1 / 3.0), GeoAlgorithms.PolygonCentroid(p0, p1, p2));
            Assert.AreEqual(new PointD(1, 1 / 3.0), GeoAlgorithms.PolygonCentroid(p2, p1, p0));

            Assert.AreEqual(p1, GeoAlgorithms.PolygonCentroid(p0, p3, p4, p2));
            Assert.AreEqual(p1, GeoAlgorithms.PolygonCentroid(p2, p4, p3, p0));
        }
Exemplo n.º 11
0
        public void Empty()
        {
            var search = new SubdivisionSearch(new Subdivision());

            search.Validate();

            for (int i = 0; i < 10; i++)
            {
                PointD q = GeoAlgorithms.RandomPoint(-100, -100, 200, 200);
                Assert.IsTrue(search.Find(q).IsUnboundedFace);
                Assert.IsTrue(search.Source.Find(q).IsUnboundedFace);
            }
        }
Exemplo n.º 12
0
        private void CheckVertices(SubdivisionSearch search)
        {
            foreach (PointD vertex in search.Source.Vertices.Keys)
            {
                var element = new SubdivisionElement(vertex);
                Assert.AreEqual(element, search.Find(vertex));
                Assert.AreEqual(element, search.Source.Find(vertex));

                // brute force search also supports comparison epsilon
                PointD offset = GeoAlgorithms.RandomPoint(-0.1, -0.1, 0.2, 0.2);
                Assert.AreEqual(element, search.Source.Find(vertex + offset, 0.25));
            }
        }
        protected override void OnMouseMove(MouseEventArgs args)
        {
            base.OnMouseMove(args);
            args.Handled = true;

            PointD cursor = args.GetPosition(OutputBox).ToPointD();

            // determine relative location of cursor
            PolygonLocation location = (_tolerance == 0m ?
                                        GeoAlgorithms.PointInPolygon(cursor, _polygon) :
                                        GeoAlgorithms.PointInPolygon(cursor, _polygon, (double)_tolerance));

            LocationLabel.Content = location;
        }
Exemplo n.º 14
0
        public void PointInPolygonEpsilon()
        {
            PointD[] p = { new PointD(0, 0), new PointD(1, 1), new PointD(2, 0) };
            Assert.AreEqual(PolygonLocation.Inside, GeoAlgorithms.PointInPolygon(new PointD(1.0, 0.5), p, 0.2));

            Assert.AreEqual(PolygonLocation.Outside, GeoAlgorithms.PointInPolygon(new PointD(1.0, -0.5), p, 0.2));
            Assert.AreEqual(PolygonLocation.Outside, GeoAlgorithms.PointInPolygon(new PointD(0.0, 0.5), p, 0.2));
            Assert.AreEqual(PolygonLocation.Outside, GeoAlgorithms.PointInPolygon(new PointD(2.0, 0.5), p, 0.2));

            Assert.AreEqual(PolygonLocation.Vertex, GeoAlgorithms.PointInPolygon(new PointD(1.0, 0.9), p, 0.2));
            Assert.AreEqual(PolygonLocation.Vertex, GeoAlgorithms.PointInPolygon(new PointD(0.0, 0.1), p, 0.2));
            Assert.AreEqual(PolygonLocation.Vertex, GeoAlgorithms.PointInPolygon(new PointD(2.1, 0.0), p, 0.2));

            Assert.AreEqual(PolygonLocation.Edge, GeoAlgorithms.PointInPolygon(new PointD(1.0, -0.1), p, 0.2));
            Assert.AreEqual(PolygonLocation.Edge, GeoAlgorithms.PointInPolygon(new PointD(0.6, 0.5), p, 0.2));
            Assert.AreEqual(PolygonLocation.Edge, GeoAlgorithms.PointInPolygon(new PointD(1.4, 0.5), p, 0.2));
        }
Exemplo n.º 15
0
        public void PolygonArea()
        {
            PointD p0 = new PointD(0, 0), p1 = new PointD(1, 1), p2 = new PointD(2, 0);
            PointD p3 = new PointD(0, 2), p4 = new PointD(2, 2);

            // triangles in both orientations
            Assert.AreEqual(-1, GeoAlgorithms.PolygonArea(p0, p1, p2));
            Assert.AreEqual(+1, GeoAlgorithms.PolygonArea(p2, p1, p0));

            // squares in both orientations
            Assert.AreEqual(-4, GeoAlgorithms.PolygonArea(p0, p3, p4, p2));
            Assert.AreEqual(+4, GeoAlgorithms.PolygonArea(p2, p4, p3, p0));

            // collinear points and star shape
            Assert.AreEqual(0, GeoAlgorithms.PolygonArea(p0, p1, p4));
            Assert.AreEqual(0, GeoAlgorithms.PolygonArea(p0, p1, p3, p1, p2, p1, p4, p1));
        }
Exemplo n.º 16
0
        public void ConnectPoints()
        {
            PointD p0 = new PointD(0, 0), p1 = new PointD(1, 1), p2 = new PointD(2, 0);

            CollectionAssert.AreEqual(new LineD[0], GeoAlgorithms.ConnectPoints(false));
            CollectionAssert.AreEqual(new LineD[0], GeoAlgorithms.ConnectPoints(true));
            CollectionAssert.AreEqual(new LineD[0], GeoAlgorithms.ConnectPoints(false, p0));
            CollectionAssert.AreEqual(new LineD[0], GeoAlgorithms.ConnectPoints(true, p0));

            CollectionAssert.AreEqual(new[] { new LineD(p0, p1) },
                                      GeoAlgorithms.ConnectPoints(false, p0, p1));
            CollectionAssert.AreEqual(new[] { new LineD(p0, p1), new LineD(p1, p0) },
                                      GeoAlgorithms.ConnectPoints(true, p0, p1));

            CollectionAssert.AreEqual(new[] { new LineD(p0, p1), new LineD(p1, p2) },
                                      GeoAlgorithms.ConnectPoints(false, p0, p1, p2));
            CollectionAssert.AreEqual(new[] { new LineD(p0, p1), new LineD(p1, p2), new LineD(p2, p0) },
                                      GeoAlgorithms.ConnectPoints(true, p0, p1, p2));
        }
Exemplo n.º 17
0
        private void DrawConvexHull(PointD[] points)
        {
            const double radius = 4.0;

            // generate new random point set if desired
            if (points == null)
            {
                Size  scale  = new Size(OutputBox.Width - 4 * radius, OutputBox.Height - 4 * radius);
                int   count  = MersenneTwister.Default.Next(4, 40);
                RectD bounds = new RectD(2 * radius, 2 * radius, scale.Width, scale.Height);
                points = GeoAlgorithms.RandomPoints(
                    count, bounds, new PointDComparerY(), 2 * radius);
            }

            _points = points;
            PointD[] polygon = GeoAlgorithms.ConvexHull(points);
            OutputBox.Children.Clear();

            // draw hull vertices filled, other points hollow
            for (int i = 0; i < points.Length; i++)
            {
                bool isVertex = polygon.Contains(points[i]);

                var circle = new Ellipse()
                {
                    Width  = 2 * radius, Height = 2 * radius,
                    Stroke = Brushes.Black,
                    Fill   = isVertex ? Brushes.Black : null
                };

                Canvas.SetLeft(circle, points[i].X - radius);
                Canvas.SetTop(circle, points[i].Y - radius);

                OutputBox.Children.Add(circle);
            }

            // draw edges of convex hull
            OutputBox.Children.Add(new Polygon()
            {
                Points = polygon.ToWpfPoints(),
                Stroke = Brushes.Red
            });
        }
Exemplo n.º 18
0
        public static GraphManager <PointD> CreateSubdivisionManager(GraphDialog dialog)
        {
            RectD output = new RectD(0, 0, dialog.OutputBox.Width, dialog.OutputBox.Height);
            RectD bounds = new RectD(8, 8, output.Width - 16, output.Height - 16);

            PointD[] points = GeoAlgorithms.RandomPoints(40, bounds, new PointDComparerX(), 20);

            VoronoiResults results  = Voronoi.FindAll(points, output);
            Subdivision    division = results.ToDelaunySubdivision(output, true);

            var manager = new GraphManager <PointD>(dialog, 8);

            manager.Graph    = division;
            manager.Renderer = new GraphRenderer <PointD>(manager);

            // scaling factor to keep step costs above node distance
            manager._scaleCost = output.Width + output.Height;
            return(manager);
        }
Exemplo n.º 19
0
        public void ConvexHull()
        {
            PointD p0 = new PointD(0, 0), p1 = new PointD(1, 1), p2 = new PointD(2, 0);

            CollectionAssert.AreEqual(new[] { p0 }, GeoAlgorithms.ConvexHull(p0));
            CollectionAssert.AreEqual(new[] { p0 }, GeoAlgorithms.ConvexHull(p0, p0));
            CollectionAssert.AreEqual(new[] { p0 }, GeoAlgorithms.ConvexHull(p0, p0, p0));

            CollectionAssert.AreEqual(new[] { p0, p1 }, GeoAlgorithms.ConvexHull(p0, p1));
            CollectionAssert.AreEqual(new[] { p1, p0 }, GeoAlgorithms.ConvexHull(p0, p1, p0));
            CollectionAssert.AreEqual(new[] { p1, p0 }, GeoAlgorithms.ConvexHull(p0, p0, p1));
            CollectionAssert.AreEqual(new[] { p1, p0 }, GeoAlgorithms.ConvexHull(p0, p1, p1));

            CollectionAssert.AreEqual(new[] { p1, p2, p0 }, GeoAlgorithms.ConvexHull(p0, p1, p2));
            CollectionAssert.AreEqual(new[] { p1, p2, p0 }, GeoAlgorithms.ConvexHull(p1, p0, p2));

            PointD p3 = new PointD(1, 0);

            CollectionAssert.AreEqual(new[] { p1, p2, p0 }, GeoAlgorithms.ConvexHull(p3, p1, p0, p2));
        }
Exemplo n.º 20
0
        /// <summary>
        /// Creates a random <see cref="Subdivision"/> with the specified number of full edges and
        /// comparison epsilon.</summary>
        /// <param name="size">
        /// The number of full edges, i.e. half the number of <see cref="Subdivision.Edges"/>, in
        /// the returned <see cref="Subdivision"/>.</param>
        /// <param name="epsilon">
        /// The maximum absolute difference at which two coordinates should be considered equal.
        /// </param>
        /// <returns>
        /// A new random <see cref="Subdivision"/> with the specified <paramref name="size"/> and
        /// <paramref name="epsilon"/>.</returns>

        private static Subdivision CreateSubdivision(int size, double epsilon)
        {
            LineD[] lines = new LineD[size];
            for (int i = 0; i < size; i++)
            {
                lines[i] = GeoAlgorithms.RandomLine(0, 0, 1000, 1000);
            }

            // split random set into non-intersecting line segments
            var crossings  = MultiLineIntersection.FindSimple(lines, epsilon);
            var splitLines = MultiLineIntersection.Split(lines, crossings);

            Array.Copy(splitLines, lines, size);

            // re-randomize lines to eliminate split ordering
            CollectionsUtility.Randomize(lines);
            Subdivision division = Subdivision.FromLines(lines);

            division.Validate();
            return(division);
        }
Exemplo n.º 21
0
        private static void CheckGridDivision(PolygonGrid.SubdivisionMap map)
        {
            map.Source.Validate();

            // test finding vertices with FindNearestVertex
            for (int i = 0; i < map.Source.Vertices.Count; i++)
            {
                PointD q = map.Source.Vertices.GetKey(i) + GeoAlgorithms.RandomPoint(-2, -2, 4, 4);
                Assert.AreEqual(i, map.Source.FindNearestVertex(q));
            }

            // test GetElementVertices and face mapping
            for (int x = 0; x < map.Target.Size.Width; x++)
            {
                for (int y = 0; y < map.Target.Size.Height; y++)
                {
                    var polygon = map.Target.GetElementVertices(x, y);
                    var face    = map.Source.FindFace(polygon, true);

                    Assert.AreSame(face, map.ToFace(new PointI(x, y)));
                    Assert.AreEqual(new PointI(x, y), map.FromFace(face));
                }
            }
        }
Exemplo n.º 22
0
        public void FindNearestEpsilonOverlap()
        {
            var points = new PointD[100];

            for (int i = 0; i < points.Length; i++)
            {
                points[i] = new PointD((i % 10) / 10.0, i / 10);
            }

            // unpredictable sorting since epsilon overlaps point distances
            var comparer = new PointDComparerY()
            {
                Epsilon = 0.2
            };

            Array.Sort <PointD>(points, comparer.Compare);

            for (int i = 0; i < points.Length; i++)
            {
                PointD q = points[i];
                Assert.AreEqual(i, comparer.FindNearest(points, q));

                /*
                 * Since epsilon overlaps adjacent points, sorting is unpredictable
                 * and we cannot know which index contains the point nearest to a
                 * non-collection point. So we use brute force to find that index.
                 */
                q = new PointD(q.X + 0.1, q.Y - 0.1);
                int index = GeoAlgorithms.NearestPoint(points, q);
                Assert.AreEqual(index, comparer.FindNearest(points, q));

                q     = new PointD(q.X - 0.4, q.Y + 0.4);
                index = GeoAlgorithms.NearestPoint(points, q);
                Assert.AreEqual(index, comparer.FindNearest(points, q));
            }
        }
Exemplo n.º 23
0
        private void GeometryBasicTest()
        {
            Stopwatch timer = new Stopwatch();
            long      polyTicks = 0, polyEpsilonTicks = 0, lineTicks = 0, lineEpsilonTicks = 0;

            const double epsilon = 1e-10;
            const int    outerLoop = 10000, innerLoop = 1000;
            const int    iterations = outerLoop * innerLoop;

            for (int i = 0; i < outerLoop; i++)
            {
                PointD[] polygon = GeoAlgorithms.RandomPolygon(0, 0, 1000, 1000);
                LineD    line    = GeoAlgorithms.RandomLine(0, 0, 1000, 1000);
                LineD    line2   = GeoAlgorithms.RandomLine(0, 0, 1000, 1000);
                PointD   q       = GeoAlgorithms.RandomPoint(0, 0, 1000, 1000);

                // trigger JIT compilation
                if (i == 0)
                {
                    GeoAlgorithms.PointInPolygon(q, polygon);
                    GeoAlgorithms.PointInPolygon(q, polygon, epsilon);
                    line.Intersect(line2);
                    line.Intersect(line2, epsilon);
                }

                timer.Restart();
                for (int j = 0; j < innerLoop; j++)
                {
                    line.Intersect(line2);
                }
                timer.Stop();
                lineTicks += timer.ElapsedTicks;

                timer.Restart();
                for (int j = 0; j < innerLoop; j++)
                {
                    line.Intersect(line2, epsilon);
                }
                timer.Stop();
                lineEpsilonTicks += timer.ElapsedTicks;

                timer.Restart();
                for (int j = 0; j < innerLoop; j++)
                {
                    GeoAlgorithms.PointInPolygon(q, polygon);
                }
                timer.Stop();
                polyTicks += timer.ElapsedTicks;

                timer.Restart();
                for (int j = 0; j < innerLoop; j++)
                {
                    GeoAlgorithms.PointInPolygon(q, polygon, epsilon);
                }
                timer.Stop();
                polyEpsilonTicks += timer.ElapsedTicks;
            }

            Output("                  ");
            Output(String.Format("{0,12}", "Exact"));
            Output(String.Format("{0,12}", "Epsilon"));

            Output("\nLine Intersection ");
            Output(String.Format("{0,12:N2}", 1000 * AverageMicrosecs(lineTicks, iterations)));
            Output(String.Format("{0,12:N2}", 1000 * AverageMicrosecs(lineEpsilonTicks, iterations)));

            Output("\nPoint in Polygon  ");
            Output(String.Format("{0,12:N2}", 1000 * AverageMicrosecs(polyTicks, iterations)));
            Output(String.Format("{0,12:N2}", 1000 * AverageMicrosecs(polyEpsilonTicks, iterations)));

            Output("\nTimes are nsec averages for exact and epsilon comparisons.\n");
            Output("Point in Polygon uses random polygons with 3-60 vertices.\n");
        }
Exemplo n.º 24
0
        private void SubdivisionSearchTest(bool random)
        {
            Stopwatch timer     = new Stopwatch();
            var       testCases = _subdivSearchTestCases;

            Output(String.Format("{0,6}", " "));
            foreach (TestCase test in testCases)
            {
                Output(String.Format("{0,12}", test.Name));
            }
            Output("\n");

            const int outerLoop = 100, innerLoop = 200;
            const int iterations = outerLoop * innerLoop;

            PointD[] query = new PointD[innerLoop];

            PolygonGrid grid = null;
            int         sizeMin, sizeMax, sizeStep;

            if (random)
            {
                sizeMin = 100; sizeMax = 1200; sizeStep = 100;
            }
            else
            {
                sizeMin = 6; sizeMax = 30; sizeStep = 2;
                RegularPolygon polygon = new RegularPolygon(10, 4, PolygonOrientation.OnEdge);
                grid = new PolygonGrid(polygon);
            }

            for (int size = sizeMin; size <= sizeMax; size += sizeStep)
            {
                Subdivision division;
                if (random)
                {
                    // create subdivision from random lines (few faces)
                    division = CreateSubdivision(size, 1e-10);
                }
                else
                {
                    // create subdivision from grid of diamonds (many faces)
                    grid.Element = new RegularPolygon(900 / size, 4, PolygonOrientation.OnEdge);
                    grid.Size    = new SizeI(size, size);
                    division     = grid.ToSubdivision(PointD.Empty).Source;
                }
                var ordered    = new SubdivisionSearch(division, true);
                var randomized = new SubdivisionSearch(division, false);

                // test cases: BruteForce, Ordered, Randomized
                testCases[0].FindSubdivision = (q) => division.Find(q, division.Epsilon);
                testCases[1].FindSubdivision = (q) => ordered.Find(q);
                testCases[2].FindSubdivision = (q) => randomized.Find(q);

                // trigger JIT compilation and reset ticks
                foreach (TestCase test in testCases)
                {
                    test.FindSubdivision(PointD.Empty);
                    test.Ticks = 0;
                }

                for (int j = 0; j < outerLoop; j++)
                {
                    for (int k = 0; k < query.Length; k++)
                    {
                        query[k] = GeoAlgorithms.RandomPoint(0, 0, 1000, 1000);
                    }

                    foreach (TestCase test in testCases)
                    {
                        timer.Restart();
                        for (int k = 0; k < query.Length; k++)
                        {
                            test.FindSubdivision(query[k]);
                        }

                        timer.Stop();
                        test.Ticks += timer.ElapsedTicks;
                    }
                }

                Output(String.Format("{0,6:N0}", division.Edges.Count / 2));
                foreach (TestCase test in testCases)
                {
                    Output(String.Format("{0,12:N2}", AverageMicrosecs(test.Ticks, iterations)));
                }
                Output("\n");
            }

            Output("\nTimes are µsec averages for subdivisions of the indicated edge count,\n");
            if (random)
            {
                Output("based on random line sets (few faces, completely random edges).\n");
            }
            else
            {
                Output("based on grids of squares (many faces, strictly ordered edges).\n");
            }
        }
Exemplo n.º 25
0
        private void RangeTreeTest()
        {
            Stopwatch timer     = new Stopwatch();
            var       testCases = _rangeTreeTestCases;

            Output(String.Format("{0,8}", " "));
            foreach (TestCase test in testCases)
            {
                Output(String.Format("{0,14}", test.Name));
            }
            Output("\n");

            // count units of size x operation in milliseconds,
            // rather than individual operations in microseconds
            const int outerLoop = 10, innerLoop = 10;
            const int iterations = outerLoop * innerLoop * 1000;

            // bounds of search space, size of point set,
            // range & iterations for range search
            const int bounds = 10000, size = 60000;
            const int range = size / 80, rangeIterations = size / 120;

            long[] addTicks = new long[testCases.Length],
            iterateTicks = new long[testCases.Length],
            searchTicks  = new long[testCases.Length],
            rangeTicks   = new long[testCases.Length],
            removeTicks  = new long[testCases.Length];

            var array = new KeyValuePair <PointD, String> [size];

            for (int i = 0; i < outerLoop; i++)
            {
                // generate random spatial keys
                for (int j = 0; j < array.Length; j++)
                {
                    var key = GeoAlgorithms.RandomPoint(0, 0, bounds, bounds);
                    array[j] = new KeyValuePair <PointD, String>(key, null);
                }

                // trigger JIT compilation
                if (i == 0)
                {
                    foreach (TestCase test in testCases)
                    {
                        test.RangeTree.Clear();
                        foreach (var pair in array)
                        {
                            test.RangeTree.Add(pair.Key, pair.Value);
                        }
                    }
                }

                for (int j = 0; j < innerLoop; j++)
                {
                    for (int k = 0; k < testCases.Length; k++)
                    {
                        TestCase test = testCases[k];
                        test.RangeTree.Clear();

                        timer.Restart();
                        foreach (var pair in array)
                        {
                            test.RangeTree.Add(pair.Key, pair.Value);
                        }
                        timer.Stop();
                        addTicks[k] += timer.ElapsedTicks;

                        double sum = 0;
                        timer.Restart();
                        foreach (var pair in test.RangeTree)
                        {
                            sum += pair.Key.X;
                        }
                        timer.Stop();
                        iterateTicks[k] += timer.ElapsedTicks;

                        timer.Restart();
                        foreach (var pair in array)
                        {
                            test.RangeTree.ContainsKey(pair.Key);
                        }
                        timer.Stop();
                        searchTicks[k] += timer.ElapsedTicks;

                        /*
                         * BraidedTree performs one-dimensional range searches within a point set
                         * sorted by y-coordinates, using PointDComparerY. Therefore, we supply a
                         * condition that limits x-coordinates.
                         */

                        var braidedTree = test.RangeTree as BraidedTree <PointD, String>;
                        var quadTree    = test.RangeTree as QuadTree <String>;

                        timer.Restart();
                        for (int l = 0; l < array.Length; l += size / rangeIterations)
                        {
                            PointD p    = array[l].Key;
                            RectD  rect = new RectD(p.X, p.Y, range, range);

                            if (braidedTree != null)
                            {
                                braidedTree.FindRange(rect.TopLeft, rect.BottomRight,
                                                      n => (n.Key.X >= rect.Left && n.Key.X <= rect.Right));
                            }
                            else if (quadTree != null)
                            {
                                quadTree.FindRange(rect);
                            }
                        }
                        timer.Stop();
                        rangeTicks[k] += timer.ElapsedTicks;

                        timer.Restart();
                        foreach (var pair in array)
                        {
                            test.RangeTree.Remove(pair.Key);
                        }
                        timer.Stop();
                        removeTicks[k] += timer.ElapsedTicks;
                    }
                }
            }

            Output(String.Format("{0,8}", "Add"));
            for (int i = 0; i < testCases.Length; i++)
            {
                Output(String.Format("{0,14:N2}", AverageMicrosecs(addTicks[i], iterations)));
            }

            Output(String.Format("\n{0,8}", "Iterate"));
            for (int i = 0; i < testCases.Length; i++)
            {
                Output(String.Format("{0,14:N2}", AverageMicrosecs(iterateTicks[i], iterations)));
            }

            Output(String.Format("\n{0,8}", "Search"));
            for (int i = 0; i < testCases.Length; i++)
            {
                Output(String.Format("{0,14:N2}", AverageMicrosecs(searchTicks[i], iterations)));
            }

            Output(String.Format("\n{0,8}", "Range"));
            for (int i = 0; i < testCases.Length; i++)
            {
                Output(String.Format("{0,14:N2}", AverageMicrosecs(rangeTicks[i], iterations)));
            }

            Output(String.Format("\n{0,8}", "Remove"));
            for (int i = 0; i < testCases.Length; i++)
            {
                Output(String.Format("{0,14:N2}", AverageMicrosecs(removeTicks[i], iterations)));
            }

            const double share = range / (double)bounds;

            Output(String.Format("\n\nTimes are msec averages for {0:N0} random points.\n", size));
            Output(String.Format("Range search performs {0} iterations on {1:0.00%} of search space.\n",
                                 rangeIterations, share * share));
        }
Exemplo n.º 26
0
        private void NearestPointTest()
        {
            Stopwatch timer     = new Stopwatch();
            var       testCases = _nearestPointTestCases;

            Output(String.Format("{0,6}", " "));
            foreach (TestCase test in testCases)
            {
                Output(String.Format("{0,12}", test.Name));
            }
            Output("\n");

            const int outerLoop = 100, innerLoop = 100;
            const int iterations = outerLoop * innerLoop;

            var comparer = new PointDComparerY();

            PointD[] query = new PointD[innerLoop];

            for (int size = 1000; size <= 12000; size += 1000)
            {
                PointD[] points = new PointD[size];
                for (int i = 0; i < points.Length; i++)
                {
                    points[i] = GeoAlgorithms.RandomPoint(0, 0, 1000, 1000);
                }
                Array.Sort <PointD>(points, comparer);

                // trigger JIT compilation and reset ticks
                foreach (TestCase test in testCases)
                {
                    test.FindPointIndex(comparer, points, PointD.Empty);
                    test.Ticks = 0;
                }

                for (int j = 0; j < outerLoop; j++)
                {
                    for (int k = 0; k < query.Length; k++)
                    {
                        query[k] = GeoAlgorithms.RandomPoint(0, 0, 1000, 1000);
                    }

                    foreach (TestCase test in testCases)
                    {
                        timer.Restart();
                        for (int k = 0; k < query.Length; k++)
                        {
                            test.FindPointIndex(comparer, points, query[k]);
                        }

                        timer.Stop();
                        test.Ticks += timer.ElapsedTicks;
                    }
                }

                Output(String.Format("{0,6:N0}", size));
                foreach (TestCase test in testCases)
                {
                    Output(String.Format("{0,12:N2}", AverageMicrosecs(test.Ticks, iterations)));
                }
                Output("\n");
            }

            Output("\nTimes are µsec averages for point arrays of the indicated size.\n");
        }