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);
            }
        }
        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));
            }
        }
        private SubdivisionSearch CheckSearch(params LineD[] lines)
        {
            Subdivision division = Subdivision.FromLines(lines);

            division.Validate();
            SubdivisionSearch search = new SubdivisionSearch(division);

            search.Validate();
            CheckVertices(search);
            CheckEdges(search);

            PointD[] points = new[] {
                new PointD(+1, +1), new PointD(+1, -1),
                new PointD(-1, +1), new PointD(-1, -1)
            };

            if (division.Faces.Count == 1)
            {
                foreach (PointD point in points)
                {
                    Assert.IsTrue(search.Find(point).IsUnboundedFace);
                    Assert.IsTrue(division.Find(point).IsUnboundedFace);
                }
            }
            else
            {
                var element = new SubdivisionElement(division.Faces[1]);
                foreach (PointD point in points)
                {
                    Assert.AreEqual(element, search.Find(point));
                    Assert.AreEqual(element, division.Find(point));
                }
            }

            points = new[] {
                new PointD(+10, +10), new PointD(+10, -10),
                new PointD(-10, +10), new PointD(-10, -10)
            };

            foreach (PointD point in points)
            {
                Assert.IsTrue(search.Find(point).IsUnboundedFace);
                Assert.IsTrue(division.Find(point).IsUnboundedFace);
            }
            return(search);
        }
        private SubdivisionSearch CheckSearch(Subdivision division)
        {
            division.Validate();
            SubdivisionSearch search = new SubdivisionSearch(division);

            search.Validate();
            CheckVertices(search);
            CheckEdges(search);

            foreach (SubdivisionFace face in division.Faces.Values)
            {
                if (face.OuterEdge == null)
                {
                    continue;
                }
                PointD centroid = face.OuterEdge.CycleCentroid;
                var    element  = new SubdivisionElement(face);
                Assert.AreEqual(element, search.Find(centroid));
                Assert.AreEqual(element, division.Find(centroid));
            }

            return(search);
        }