예제 #1
0
        public void CropBy_Plane_with_two_plane_orientations_yields_polygons_lying_on_respective_halfspaces_whose_area_sum_is_the_area_of_the_original_polygon()
        {
            var rectangles = new List <IPolygon>
            {
                new Box2(minX: 0, minY: 0, width: 2, height: 2),
                new Box2(minX: -1, minY: -1, width: 4, height: 2),
                new Box2(minX: -1, minY: -1, width: 2, height: 4)
            };

            var polygon2 = PolygonUtils.Union(rectangles);
            var cs       = new RotoTranslation3(new Rotation3(new Quaternion(1.1, -2.2, 3.3, -4.4)), new Vector3(4.1, -2.4, 1.3));

            var polygon3 = new Polygon3(cs, polygon2);

            var point1 = polygon3.PlaneToSpace(new Vector2(0.1, 0.2));
            var point2 = polygon3.PlaneToSpace(new Vector2(0.9, 0.7));
            var point3 = new Vector3(3.141, 2.718, 0.577);

            var plane = Plane.Through(point1, point2, point3);

            var half1 = polygon3.CropBy(plane);
            var half2 = polygon3.CropBy(plane.Reverse);

            Expect(half1.IsOnNegativeSide(Plane.ParallelTo(plane, _tolerance)));
            Expect(half2.IsOnPositiveSide(Plane.ParallelTo(plane, -_tolerance)));

            Expect(half1.InPlane.Area() + half2.InPlane.Area(), Is.EqualTo(polygon3.InPlane.Area()).Within(_tolerance));
        }
예제 #2
0
        public void Difference_between_square_p_and_square_q_contained_in_p_results_in_p_with_q_added_as_a_hole_contour()
        {
            var corner1    = new Vector2(0.1, 0.2);
            var side1      = 4.5;
            var bigPolygon = (Polygon)Square(corner1, side1, positive: true);

            var corner2      = new Vector2(0.9, 0.8);
            var side2        = 2.3;
            var smallPolygon = (Polygon)Square(corner2, side2, positive: true);

            var result = PolygonUtils.Difference(bigPolygon, smallPolygon);

            Expect(result.Contours.Count, Is.EqualTo(2));

            var contour0 = result.Contours.ElementAt(0);
            var contour1 = result.Contours.ElementAt(1);

            Expect(Math.Sign(contour0.SignedArea()) != Math.Sign(contour1.SignedArea()));

            var outContour = contour0.SignedArea() > 0 ? contour0 : contour1;
            var inContour  = contour0.SignedArea() > 0 ? contour1 : contour0;

            Expect(outContour.Vertices.Count, Is.EqualTo(bigPolygon.CountVertices()));
            Expect(outContour.SignedArea(), Is.EqualTo(bigPolygon.Area()).Within(_tolerance));

            Expect(inContour.Vertices.Count, Is.EqualTo(smallPolygon.CountVertices()));
            Expect(inContour.SignedArea(), Is.EqualTo(-smallPolygon.Area()).Within(_tolerance));
        }
예제 #3
0
        private void ExpectPolygonsAreEqualWithinTolerance(IPolygon p, IPolygon q, double tolerance)
        {
            var pMinusQ = PolygonUtils.Difference(p, q);
            var qMinusP = PolygonUtils.Difference(q, p);

            Expect(qMinusP.Area(), Is.LessThan(tolerance));
            Expect(pMinusQ.Area(), Is.LessThan(tolerance));
        }
예제 #4
0
        public void Difference_of_two_empty_polygons_is_empty()
        {
            var p = Polygon.Empty;
            var q = Polygon.Empty;

            var result = PolygonUtils.Difference(p, q);

            Expect(result.IsEmpty);
        }
예제 #5
0
        public void MinkowskiDifference_of_two_boxes_amounts_to_subtracting_minima_and_maxima()
        {
            var box1 = new Box2(new Interval(0.123, 0.456), new Interval(2.718, 3.141));
            var box2 = new Box2(new Interval(0.0777, 0.0888), new Interval(-0.1, +0.1));

            var expectedAnswer = Box2.Hull(box1.MinCorner - box2.MaxCorner, box1.MaxCorner - box2.MinCorner);
            var actualAnswer   = PolygonUtils.MinkowskiDifference(box1, box2);

            ExpectPolygonsAreEqualWithinTolerance(actualAnswer, expectedAnswer, _tolerance);
        }
예제 #6
0
        public void MinkowskiDifference_is_distributive_with_Union()
        {
            var box1 = new Box2(new Interval(0.123, 0.456), new Interval(2.718, 3.141));
            var box2 = new Box2(new Interval(0.777, 0.888), new Interval(-1, +1));
            var box3 = new Box2(new Interval(1.519, 1.784), new Interval(-0.256, +0.324));

            var diff1 = PolygonUtils.MinkowskiDifference(box1, PolygonUtils.Union(box2, box3));
            var diff2 = PolygonUtils.Union(PolygonUtils.MinkowskiDifference(box1, box2), PolygonUtils.MinkowskiDifference(box1, box3));

            ExpectPolygonsAreEqualWithinTolerance(diff1, diff2, _tolerance);
        }
예제 #7
0
        public void Union_of_3_rectangles_yields_the_correct_octagon()
        {
            var rectangles = new List <IPolygon>
            {
                new Box2(minX: 0, minY: 0, width: 2, height: 2),
                new Box2(minX: -1, minY: -1, width: 4, height: 2),
                new Box2(minX: -1, minY: -1, width: 2, height: 4)
            };

            var result = PolygonUtils.Union(rectangles);

            Expect(result.IsSimple);
            Expect(result.CountVertices(), Is.EqualTo(8));
            Expect(result.Area(), Is.EqualTo(13).Within(_tolerance));

            var resultBox = result.BoundingBox();

            Expect(resultBox.Width, Is.EqualTo(4).Within(_tolerance));
            Expect(resultBox.Height, Is.EqualTo(4).Within(_tolerance));
            Expect(resultBox.MinCorner.X, Is.EqualTo(-1).Within(_tolerance));
            Expect(resultBox.MinCorner.Y, Is.EqualTo(-1).Within(_tolerance));
        }
예제 #8
0
        public void CropBy_Line2_with_two_line_orientations_yields_polygons_lying_on_respective_halfplanes_whose_union_is_the_original_polygon()
        {
            var rectangles = new List <IPolygon>
            {
                new Box2(minX: 0, minY: 0, width: 2, height: 2),
                new Box2(minX: -1, minY: -1, width: 4, height: 2),
                new Box2(minX: -1, minY: -1, width: 2, height: 4)
            };

            var polygon = PolygonUtils.Union(rectangles);

            var point1 = new Vector2(0.1, 0.2);
            var point2 = new Vector2(0.9, 0.7);
            var line   = Line2.Through(point1, point2);

            var half1 = polygon.CropBy(line);
            var half2 = polygon.CropBy(line.Reverse);

            Expect(half1.IsOnNegativeSide(Line2.ParallelTo(line, _tolerance)));
            Expect(half2.IsOnPositiveSide(Line2.ParallelTo(line, -_tolerance)));

            ExpectPolygonsAreEqualWithinTolerance(PolygonUtils.Union(half1, half2), polygon, _tolerance);
        }
예제 #9
0
        public void Intersection_of_3_rectangles_yields_the_correct_square()
        {
            var rectangles = new List <IPolygon>
            {
                new Box2(minX: 0, minY: 0, width: 2, height: 2),
                new Box2(minX: -1, minY: -1, width: 4, height: 2),
                new Box2(minX: -1, minY: -1, width: 2, height: 4)
            };

            var result = PolygonUtils.Intersection(rectangles);

            Expect(result.IsSimple);
            Expect(result.CountVertices(), Is.EqualTo(4));
            Expect(result.Area(), Is.EqualTo(1).Within(_tolerance));

            var resultBox = result.BoundingBox();

            Expect(PolygonUtils.Difference(resultBox, result).Area(), Is.EqualTo(0).Within(_tolerance));
            Expect(resultBox.Width, Is.EqualTo(1).Within(_tolerance));
            Expect(resultBox.Height, Is.EqualTo(1).Within(_tolerance));
            Expect(resultBox.MinCorner.X, Is.EqualTo(0).Within(_tolerance));
            Expect(resultBox.MinCorner.Y, Is.EqualTo(0).Within(_tolerance));
        }
예제 #10
0
        private IPolygon AddComponentTo(IPolygon p)
        {
            var component = new Box2(minX: -2, minY: -2, width: 1, height: 1);

            return(PolygonUtils.Union(p, component));
        }
예제 #11
0
        private IPolygon MakeHoleIn(IPolygon p)
        {
            var hole = new Box2(minX: 1, minY: 1, width: 1, height: 1);

            return(PolygonUtils.Difference(p, hole));
        }