public void TestEdgeLimits7()
        {
            VertexConstraints constraint1 = new VertexConstraints(new Vector(0, 0), new Vector(10, 10));
            VertexConstraints constraint2 = new VertexConstraints(new Vector(5, 5), new Vector(8, 8));

            Range lengthRange, angleRange;

            TestEdgeLimitsCommonImpl(constraint1, constraint2, out lengthRange, out angleRange);
        }
        static void PointIsClosestExperiment(
            Vector point,
            VertexConstraints point1Constraints,
            VertexConstraints point2Constraints,
            string fileName)
        {
            Console.WriteLine(string.Format("Doing experiment for {0}", fileName));

            Bitmap    image      = new Bitmap(320, 240);
            const int iterations = 200000;

            using (Graphics graphics = Graphics.FromImage(image))
            {
                for (int i = 0; i < iterations; ++i)
                {
                    Vector point1 = new Vector(
                        point1Constraints.MinCoord.X + (point1Constraints.MaxCoord.X - point1Constraints.MinCoord.X) * Random.Double(),
                        point1Constraints.MinCoord.Y + (point1Constraints.MaxCoord.Y - point1Constraints.MinCoord.Y) * Random.Double());
                    Vector point2 = new Vector(
                        point2Constraints.MinCoord.X + (point2Constraints.MaxCoord.X - point2Constraints.MinCoord.X) * Random.Double(),
                        point2Constraints.MinCoord.Y + (point2Constraints.MaxCoord.Y - point2Constraints.MinCoord.Y) * Random.Double());

                    double distanceSqr, alpha;
                    point.DistanceToSegmentSquared(point1, point2, out distanceSqr, out alpha);
                    alpha = MathHelper.Trunc(alpha, 0, 1);
                    Vector      closestPoint = point1 + (point2 - point1) * alpha;
                    const float radius       = 2;
                    graphics.FillEllipse(
                        Brushes.Green,
                        (float)closestPoint.X - radius,
                        (float)closestPoint.Y - radius,
                        radius * 2,
                        radius * 2);
                }

                graphics.DrawRectangle(
                    Pens.Blue,
                    point1Constraints.CoordRectangle.Left,
                    point1Constraints.CoordRectangle.Top,
                    point1Constraints.CoordRectangle.Width,
                    point1Constraints.CoordRectangle.Height);
                graphics.DrawRectangle(
                    Pens.Blue,
                    point2Constraints.CoordRectangle.Left,
                    point2Constraints.CoordRectangle.Top,
                    point2Constraints.CoordRectangle.Width,
                    point2Constraints.CoordRectangle.Height);
                graphics.FillEllipse(Brushes.Red, (float)point.X - 2, (float)point.Y - 2, 4, 4);
            }

            image.Save(fileName);
        }
        public void TestEdgeLimits2()
        {
            VertexConstraints constraint1 = new VertexConstraints(new Vector(11, -7), new Vector(13, 15));
            VertexConstraints constraint2 = new VertexConstraints(new Vector(-10, -10), new Vector(10, 10));

            Range lengthRange, angleRange;

            TestEdgeLimitsCommonImpl(constraint1, constraint2, out lengthRange, out angleRange);

            Assert.IsTrue(angleRange.Outside);
            Assert.IsFalse(angleRange.Contains(0));
            Assert.IsTrue(angleRange.Contains(Math.PI));
            Assert.IsTrue(angleRange.Contains(-Math.PI));
            Assert.IsFalse(angleRange.Contains(Math.PI * 0.5));
            Assert.IsFalse(angleRange.Contains(-Math.PI * 0.5));
        }
        public void TestEdgeLimits3()
        {
            VertexConstraints constraint1 = new VertexConstraints(new Vector(0, 0), new Vector(10, 10));
            VertexConstraints constraint2 = new VertexConstraints(new Vector(11, 11), new Vector(12, 16));

            Range lengthRange, angleRange;

            TestEdgeLimitsCommonImpl(constraint1, constraint2, out lengthRange, out angleRange);

            Assert.IsFalse(angleRange.Outside);
            Assert.IsTrue(angleRange.Contains(Math.PI * 0.25));
            Assert.IsFalse(angleRange.Contains(0));
            Assert.IsFalse(angleRange.Contains(Math.PI * 0.5));

            Assert.IsFalse(lengthRange.Contains(0));
            Assert.IsFalse(lengthRange.Contains(1));
        }
Ejemplo n.º 5
0
        public void GenerateVertexConstraintsFromFaces()
        {
            foreach (var f in Faces)
            {
                var v0 = f.posIndex [0];
                var v1 = f.posIndex [1];
                var v2 = f.posIndex [2];

                var v01 = VertexList [v1] - VertexList [v0];
                var v02 = VertexList [v2] - VertexList [v0];
                var v12 = VertexList [v2] - VertexList [v1];

                VertexConstraints.Add(new VertexConstraint()
                {
                    Vertex0 = v0, Vertex1 = v1, distance = v01.Norm()
                });
                VertexConstraints.Add(new VertexConstraint()
                {
                    Vertex0 = v0, Vertex1 = v2, distance = v02.Norm()
                });
                VertexConstraints.Add(new VertexConstraint()
                {
                    Vertex0 = v1, Vertex1 = v2, distance = v12.Norm()
                });
            }
            var vc    = new List <VertexConstraint> (VertexConstraints);
            int found = VertexConstraints.Count;

            for (var i = 0; i < VertexConstraints.Count; i++)
            {
                for (var j = i + 1; j < VertexConstraints.Count; j++)
                {
                    var v0 = VertexConstraints [i].Vertex0;
                    var v1 = VertexConstraints [i].Vertex1;

                    if ((v0 == VertexConstraints [j].Vertex0 && v1 == VertexConstraints [j].Vertex1) ||
                        (v1 == VertexConstraints [j].Vertex0 && v0 == VertexConstraints [j].Vertex1))
                    {
                        vc.Remove(VertexConstraints[j]);
                    }
                }
            }
            VertexConstraints = vc;
            Console.WriteLine("Found " + found + " .... removed " + (found - VertexConstraints.Count));
        }
        public void TestVertexConstraintSplitsNonIntersection()
        {
            VertexConstraints constraints = new VertexConstraints(new Vector(0, 0), new Vector(1, 1));

            List <VertexConstraints> split = constraints.Split();

            Assert.IsTrue(split.Count == 4);
            for (int i = 0; i < split.Count; ++i)
            {
                for (int j = i + 1; j < split.Count; ++j)
                {
                    Range xRange1 = new Range(split[i].MinCoord.X, split[i].MaxCoord.X, false);
                    Range yRange1 = new Range(split[i].MinCoord.Y, split[i].MaxCoord.Y, false);
                    Range xRange2 = new Range(split[j].MinCoord.X, split[j].MaxCoord.X, false);
                    Range yRange2 = new Range(split[j].MinCoord.Y, split[j].MaxCoord.Y, false);

                    Assert.IsFalse(xRange1.IntersectsWith(xRange2) && yRange1.IntersectsWith(yRange2));
                }
            }
        }
        public void TestEdgeLimits4()
        {
            const double      eps         = 0.01;
            VertexConstraints constraint1 = new VertexConstraints(new Vector(0, 0), new Vector(1 - eps, 1 - eps));
            VertexConstraints constraint2 = new VertexConstraints(new Vector(1 + eps, 1 + eps), new Vector(2, 2));

            Range lengthRange, angleRange;

            TestEdgeLimitsCommonImpl(constraint1, constraint2, out lengthRange, out angleRange);

            Assert.IsFalse(angleRange.Outside);
            Assert.IsTrue(angleRange.Contains(0.01));
            Assert.IsFalse(angleRange.Contains(-Math.PI * 0.501));
            Assert.IsFalse(angleRange.Contains(-Math.PI));
            Assert.IsFalse(angleRange.Contains(Math.PI * 0.501));
            Assert.IsFalse(angleRange.Contains(Math.PI));

            Assert.IsFalse(lengthRange.Contains(3));
            Assert.IsTrue(lengthRange.Contains(0.05));
            Assert.IsTrue(lengthRange.Contains(2.8));
        }
        static void LengthAngleDependenceExperiment(
            VertexConstraints constraint1, VertexConstraints constraint2, string fileName)
        {
            const int GeneratedPointCount = 100000;

            List <Vector> lengthAnglePoints = new List <Vector>();
            double        maxLength         = 0;

            for (int i = 0; i < GeneratedPointCount; ++i)
            {
                double randomX1 = constraint1.MinCoord.X + Random.Double() * (constraint1.MaxCoord.X - constraint1.MinCoord.X);
                double randomY1 = constraint1.MinCoord.Y + Random.Double() * (constraint1.MaxCoord.Y - constraint1.MinCoord.Y);
                double randomX2 = constraint2.MinCoord.X + Random.Double() * (constraint2.MaxCoord.X - constraint2.MinCoord.X);
                double randomY2 = constraint2.MinCoord.Y + Random.Double() * (constraint2.MaxCoord.Y - constraint2.MinCoord.Y);
                Vector vector1  = new Vector(randomX1, randomY1);
                Vector vector2  = new Vector(randomX2, randomY2);
                if (vector1 == vector2)
                {
                    continue;
                }

                Vector diff   = vector2 - vector1;
                double length = diff.Length;
                double angle  = Vector.AngleBetween(Vector.UnitX, diff);
                lengthAnglePoints.Add(new Vector(length, angle));

                maxLength = Math.Max(maxLength, length);
            }

            //ShapeConstraints constraintSet = ShapeConstraints.CreateFromConstraints(
            //    CreateSimpleShapeModel1(),
            //    new[] { constraint1, constraint2 },
            //    new[] { new EdgeConstraints(1) },
            //    1,
            //    1);
            BoxSetLengthAngleConstraints lengthAngleConstraints =
                BoxSetLengthAngleConstraints.FromVertexConstraints(constraint1, constraint2, 2, 0);

            const int lengthImageSize = 360;
            const int angleImageSize  = 360;
            double    lengthScale     = (lengthImageSize - 20) / maxLength;

            //Image2D<bool> myAwesomeMask = new Image2D<bool>(lengthImageSize, angleImageSize);
            //LengthAngleSpaceSeparatorSet myAwesomeSeparator = new LengthAngleSpaceSeparatorSet(constraint1, constraint2);
            //for (int i = 0; i < lengthImageSize; ++i)
            //    for (int j = 0; j < angleImageSize; ++j)
            //    {
            //        double length = i / lengthScale;
            //        double angle = MathHelper.ToRadians(j - 180.0);
            //        if (myAwesomeSeparator.IsInside(length, angle))
            //            myAwesomeMask[i, j] = true;
            //    }

            using (Bitmap image = new Bitmap(lengthImageSize, angleImageSize))
                using (Graphics graphics = Graphics.FromImage(image))
                {
                    graphics.Clear(Color.White);

                    // Draw generated points
                    for (int i = 0; i < lengthAnglePoints.Count; ++i)
                    {
                        DrawLengthAngle(graphics, Pens.Black, lengthAnglePoints[i].X, lengthAnglePoints[i].Y, lengthScale, 1);
                    }

                    // Draw estimated ranges
                    foreach (BoxLengthAngleConstraints child in lengthAngleConstraints.ChildConstraints)
                    {
                        DrawLengthAngleConstraintBox(graphics, Pens.Green, child, lengthScale);
                    }
                    DrawLengthAngleConstraintBox(graphics, new Pen(Color.Red, 2), lengthAngleConstraints.OverallRange, lengthScale);

                    // Draw constraint corners
                    //for (int i = 0; i < 4; ++i)
                    //{
                    //    for (int j = 0; j < 4; ++j)
                    //    {
                    //        Vector diff = constraint2.Corners[j] - constraint1.Corners[i];
                    //        DrawLengthAngle(diff.Length, Vector.AngleBetween(Vector.UnitX, diff), lengthScale, 5, graphics, Pens.Blue);
                    //    }
                    //}

                    // Draw my awesome separation lines
                    //for (int i = 0; i < lengthImageSize - 1; ++i)
                    //    for (int j = 0; j < lengthImageSize - 1; ++j)
                    //    {
                    //        bool border = false;
                    //        border |= myAwesomeMask[i, j] != myAwesomeMask[i + 1, j];
                    //        border |= myAwesomeMask[i, j] != myAwesomeMask[i, j + 1];
                    //        border |= myAwesomeMask[i, j] != myAwesomeMask[i + 1, j + 1];
                    //        if (border)
                    //            image.SetPixel(i, j, Color.Orange);
                    //    }

                    //graphics.DrawString(
                    //    String.Format("Max length is {0:0.0}", maxLength), SystemFonts.DefaultFont, Brushes.Green, 5, 5);

                    image.Save(fileName);
                }
        }
        private static void TestEdgeLimitsCommonImpl(
            VertexConstraints constraint1, VertexConstraints constraint2, out Range lengthRange, out Range angleRange)
        {
            BoxSetLengthAngleConstraints lengthAngleConstraints =
                BoxSetLengthAngleConstraints.FromVertexConstraints(constraint1, constraint2, 3, 0);
            GeneralizedDistanceTransform2D transform = new GeneralizedDistanceTransform2D(
                new Range(0, 35), new Range(-Math.PI * 2, Math.PI * 2), new Size(2000, 2000));
            AllowedLengthAngleChecker allowedLengthAngleChecker = new AllowedLengthAngleChecker(constraint1, constraint2, transform, 1, 0);

            lengthRange = lengthAngleConstraints.LengthBoundary;
            angleRange  = lengthAngleConstraints.AngleBoundary;

            const int insideCheckCount = 1000;

            for (int i = 0; i < insideCheckCount; ++i)
            {
                Vector edgePoint1 =
                    constraint1.MinCoord +
                    new Vector(
                        Random.Double() * (constraint1.MaxCoord.X - constraint1.MinCoord.X),
                        Random.Double() * (constraint1.MaxCoord.Y - constraint1.MinCoord.Y));
                Vector edgePoint2 =
                    constraint2.MinCoord +
                    new Vector(
                        Random.Double() * (constraint2.MaxCoord.X - constraint2.MinCoord.X),
                        Random.Double() * (constraint2.MaxCoord.Y - constraint2.MinCoord.Y));

                Vector vec    = edgePoint2 - edgePoint1;
                double length = vec.Length;
                double angle  = Vector.AngleBetween(Vector.UnitX, vec);

                const double tolerance = 1e-10;
                Assert.IsTrue(lengthAngleConstraints.InRange(length, tolerance, angle, tolerance));
                Assert.IsTrue(lengthAngleConstraints.OverallRange.InRange(length, tolerance, angle, tolerance));
                Assert.IsTrue(allowedLengthAngleChecker.IsAllowed(length, angle));
            }

            const int outsideCheckCount = 1000;

            for (int i = 0; i < outsideCheckCount; ++i)
            {
                Vector edgePoint1 =
                    constraint1.MinCoord +
                    new Vector(
                        (Random.Double() * 2 - 0.5) * (constraint1.MaxCoord.X - constraint1.MinCoord.X),
                        (Random.Double() * 2 - 0.5) * (constraint1.MaxCoord.Y - constraint1.MinCoord.Y));
                Vector edgePoint2 =
                    constraint2.MinCoord +
                    new Vector(
                        (Random.Double() * 2 - 0.5) * (constraint2.MaxCoord.X - constraint2.MinCoord.X),
                        (Random.Double() * 2 - 0.5) * (constraint2.MaxCoord.Y - constraint2.MinCoord.Y));

                Vector vec    = edgePoint2 - edgePoint1;
                double length = vec.Length;
                double angle  = Vector.AngleBetween(Vector.UnitX, vec);

                // We've generated too long edge
                if (length > transform.RangeX.Right)
                {
                    continue;
                }

                bool definitelyOutside = !lengthAngleConstraints.OverallRange.InRange(length, 1e-6, angle, 1e-6);
                Assert.IsTrue(!definitelyOutside || !allowedLengthAngleChecker.IsAllowed(length, angle));
                Assert.IsTrue(!definitelyOutside || !lengthAngleConstraints.InRange(length, 1e-6, angle, 1e-6));
            }
        }
        private static void TestEdgeLimitsCommonImpl(
            VertexConstraints constraint1, VertexConstraints constraint2, out Range lengthRange, out Range angleRange)
        {
            BoxSetLengthAngleConstraints lengthAngleConstraints =
                BoxSetLengthAngleConstraints.FromVertexConstraints(constraint1, constraint2, 3, 0);
            GeneralizedDistanceTransform2D transform = new GeneralizedDistanceTransform2D(
                new Range(0, 35), new Range(-Math.PI * 2, Math.PI * 2), new Size(2000, 2000));
            AllowedLengthAngleChecker allowedLengthAngleChecker = new AllowedLengthAngleChecker(constraint1, constraint2, transform, 1, 0);

            lengthRange = lengthAngleConstraints.LengthBoundary;
            angleRange = lengthAngleConstraints.AngleBoundary;

            const int insideCheckCount = 1000;
            for (int i = 0; i < insideCheckCount; ++i)
            {
                Vector edgePoint1 =
                    constraint1.MinCoord +
                    new Vector(
                        Random.Double() * (constraint1.MaxCoord.X - constraint1.MinCoord.X),
                        Random.Double() * (constraint1.MaxCoord.Y - constraint1.MinCoord.Y));
                Vector edgePoint2 =
                    constraint2.MinCoord +
                    new Vector(
                        Random.Double() * (constraint2.MaxCoord.X - constraint2.MinCoord.X),
                        Random.Double() * (constraint2.MaxCoord.Y - constraint2.MinCoord.Y));

                Vector vec = edgePoint2 - edgePoint1;
                double length = vec.Length;
                double angle = Vector.AngleBetween(Vector.UnitX, vec);

                const double tolerance = 1e-10;
                Assert.IsTrue(lengthAngleConstraints.InRange(length, tolerance, angle, tolerance));
                Assert.IsTrue(lengthAngleConstraints.OverallRange.InRange(length, tolerance, angle, tolerance));
                Assert.IsTrue(allowedLengthAngleChecker.IsAllowed(length, angle));
            }

            const int outsideCheckCount = 1000;
            for (int i = 0; i < outsideCheckCount; ++i)
            {
                Vector edgePoint1 =
                    constraint1.MinCoord +
                    new Vector(
                        (Random.Double() * 2 - 0.5) * (constraint1.MaxCoord.X - constraint1.MinCoord.X),
                        (Random.Double() * 2 - 0.5) * (constraint1.MaxCoord.Y - constraint1.MinCoord.Y));
                Vector edgePoint2 =
                    constraint2.MinCoord +
                    new Vector(
                        (Random.Double() * 2 - 0.5) * (constraint2.MaxCoord.X - constraint2.MinCoord.X),
                        (Random.Double() * 2 - 0.5) * (constraint2.MaxCoord.Y - constraint2.MinCoord.Y));

                Vector vec = edgePoint2 - edgePoint1;
                double length = vec.Length;
                double angle = Vector.AngleBetween(Vector.UnitX, vec);

                // We've generated too long edge
                if (length > transform.RangeX.Right)
                    continue;

                bool definitelyOutside = !lengthAngleConstraints.OverallRange.InRange(length, 1e-6, angle, 1e-6);
                Assert.IsTrue(!definitelyOutside || !allowedLengthAngleChecker.IsAllowed(length, angle));
                Assert.IsTrue(!definitelyOutside || !lengthAngleConstraints.InRange(length, 1e-6, angle, 1e-6));
            }
        }
        public void TestVertexConstraintSplitsNonIntersection()
        {
            VertexConstraints constraints = new VertexConstraints(new Vector(0, 0), new Vector(1, 1));

            List<VertexConstraints> split = constraints.Split();
            Assert.IsTrue(split.Count == 4);
            for (int i = 0; i < split.Count; ++i)
            {
                for (int j = i + 1; j < split.Count; ++j)
                {
                    Range xRange1 = new Range(split[i].MinCoord.X, split[i].MaxCoord.X, false);
                    Range yRange1 = new Range(split[i].MinCoord.Y, split[i].MaxCoord.Y, false);
                    Range xRange2 = new Range(split[j].MinCoord.X, split[j].MaxCoord.X, false);
                    Range yRange2 = new Range(split[j].MinCoord.Y, split[j].MaxCoord.Y, false);

                    Assert.IsFalse(xRange1.IntersectsWith(xRange2) && yRange1.IntersectsWith(yRange2));
                }
            }
        }
        public void TestEdgeLimits7()
        {
            VertexConstraints constraint1 = new VertexConstraints(new Vector(0, 0), new Vector(10, 10));
            VertexConstraints constraint2 = new VertexConstraints(new Vector(5, 5), new Vector(8, 8));

            Range lengthRange, angleRange;
            TestEdgeLimitsCommonImpl(constraint1, constraint2, out lengthRange, out angleRange);
        }
        public void TestEdgeLimits4()
        {
            const double eps = 0.01;
            VertexConstraints constraint1 = new VertexConstraints(new Vector(0, 0), new Vector(1 - eps, 1 - eps));
            VertexConstraints constraint2 = new VertexConstraints(new Vector(1 + eps, 1 + eps), new Vector(2, 2));

            Range lengthRange, angleRange;
            TestEdgeLimitsCommonImpl(constraint1, constraint2, out lengthRange, out angleRange);

            Assert.IsFalse(angleRange.Outside);
            Assert.IsTrue(angleRange.Contains(0.01));
            Assert.IsFalse(angleRange.Contains(-Math.PI * 0.501));
            Assert.IsFalse(angleRange.Contains(-Math.PI));
            Assert.IsFalse(angleRange.Contains(Math.PI * 0.501));
            Assert.IsFalse(angleRange.Contains(Math.PI));

            Assert.IsFalse(lengthRange.Contains(3));
            Assert.IsTrue(lengthRange.Contains(0.05));
            Assert.IsTrue(lengthRange.Contains(2.8));
        }
        public void TestEdgeLimits3()
        {
            VertexConstraints constraint1 = new VertexConstraints(new Vector(0, 0), new Vector(10, 10));
            VertexConstraints constraint2 = new VertexConstraints(new Vector(11, 11), new Vector(12, 16));

            Range lengthRange, angleRange;
            TestEdgeLimitsCommonImpl(constraint1, constraint2, out lengthRange, out angleRange);

            Assert.IsFalse(angleRange.Outside);
            Assert.IsTrue(angleRange.Contains(Math.PI * 0.25));
            Assert.IsFalse(angleRange.Contains(0));
            Assert.IsFalse(angleRange.Contains(Math.PI * 0.5));

            Assert.IsFalse(lengthRange.Contains(0));
            Assert.IsFalse(lengthRange.Contains(1));
        }
        public void TestEdgeLimits2()
        {
            VertexConstraints constraint1 = new VertexConstraints(new Vector(11, -7), new Vector(13, 15));
            VertexConstraints constraint2 = new VertexConstraints(new Vector(-10, -10), new Vector(10, 10));

            Range lengthRange, angleRange;
            TestEdgeLimitsCommonImpl(constraint1, constraint2, out lengthRange, out angleRange);

            Assert.IsTrue(angleRange.Outside);
            Assert.IsFalse(angleRange.Contains(0));
            Assert.IsTrue(angleRange.Contains(Math.PI));
            Assert.IsTrue(angleRange.Contains(-Math.PI));
            Assert.IsFalse(angleRange.Contains(Math.PI * 0.5));
            Assert.IsFalse(angleRange.Contains(-Math.PI * 0.5));
        }