public void TestShapeTwist()
        {
            const double edgeLength = 50;
            const double startAngle = Math.PI * 0.5;

            ShapeModel    shapeModel = TestHelper.CreateTestShapeModelWith2Edges(Math.PI * 0.5, 1);
            List <Vector> vertices   = new List <Vector>();

            vertices.Add(new Vector(0, 0));
            vertices.Add(new Vector(Math.Cos(startAngle) * edgeLength, Math.Sin(startAngle) * edgeLength));
            vertices.Add(new Vector());

            List <double> edgeWidths = new List <double> {
                10, 10
            };

            const int    iterationCount = 10;
            const double angleStep      = 2 * Math.PI / iterationCount;
            Shape        lastShape      = null;

            for (int i = 0; i < iterationCount; ++i)
            {
                double angle = startAngle + Math.PI * 0.5 + angleStep * i;
                vertices[2] = new Vector(vertices[1].X + edgeLength * Math.Cos(angle), vertices[1].Y + edgeLength * Math.Sin(angle));
                Shape shape = new Shape(shapeModel.Structure, vertices, edgeWidths);

                // Test if energy is increasing/decreasing properly
                if (i <= iterationCount / 2)
                {
                    Assert.IsTrue(lastShape == null || shapeModel.CalculateEnergy(lastShape) < shapeModel.CalculateEnergy(shape));
                }
                else
                {
                    Assert.IsTrue(shapeModel.CalculateEnergy(lastShape) > shapeModel.CalculateEnergy(shape));
                }

                TestShapeEnergyCalculationApproachesImpl(shapeModel, vertices, edgeWidths, new Size(51, 51), 2001, 2001, 0.01);

                lastShape = shape;
            }
        }
        private static double TestShapeEnergyCalculationApproachesImpl(
            ShapeModel model,
            IEnumerable <Vector> vertices,
            IEnumerable <double> edgeWidths,
            Size imageSize,
            int lengthGridSize,
            int angleGridSize,
            double eps)
        {
            // Create shape model and calculate energy in normal way
            Shape  shape   = new Shape(model.Structure, vertices, edgeWidths);
            double energy1 = model.CalculateEnergy(shape);

            // Calculate energy via generalized distance transforms
            ShapeConstraints constraints = ShapeConstraints.CreateFromShape(shape);
            ShapeEnergyLowerBoundCalculator calculator = new ShapeEnergyLowerBoundCalculator(lengthGridSize, angleGridSize);
            double energy2 = calculator.CalculateLowerBound(imageSize, model, constraints);

            Assert.AreEqual(energy1, energy2, eps);

            return(energy1);
        }
        private static double TestShapeEnergyCalculationApproachesImpl(
            ShapeModel model,
            IEnumerable<Vector> vertices,
            IEnumerable<double> edgeWidths,
            Size imageSize,
            int lengthGridSize,
            int angleGridSize,
            double eps)
        {
            // Create shape model and calculate energy in normal way
            Shape shape = new Shape(model.Structure, vertices, edgeWidths);
            double energy1 = model.CalculateEnergy(shape);

            // Calculate energy via generalized distance transforms
            ShapeConstraints constraints = ShapeConstraints.CreateFromShape(shape);
            ShapeEnergyLowerBoundCalculator calculator = new ShapeEnergyLowerBoundCalculator(lengthGridSize, angleGridSize);
            double energy2 = calculator.CalculateLowerBound(imageSize, model, constraints);

            Assert.AreEqual(energy1, energy2, eps);

            return energy1;
        }