public void TestAngleAbsDifference()
        {
            const double eps = 1e-10;

            Assert.AreEqual(0, MathHelper.AngleAbsDifference(0, 0), eps);
            Assert.AreEqual(0, MathHelper.AngleAbsDifference(Math.PI, -Math.PI), eps);
            Assert.AreEqual(Math.PI * 0.5, MathHelper.AngleAbsDifference(Math.PI * 0.75, Math.PI * 0.25), eps);
            Assert.AreEqual(Math.PI * 0.5, MathHelper.AngleAbsDifference(-Math.PI * 0.75, -Math.PI * 0.25), eps);
            Assert.AreEqual(Math.PI * 0.5, MathHelper.AngleAbsDifference(Math.PI * 0.75, -Math.PI * 0.75), eps);
            Assert.AreEqual(Math.PI * 0.5, MathHelper.AngleAbsDifference(-Math.PI * 0.75, Math.PI * 0.75), eps);
        }
Ejemplo n.º 2
0
        public double CalculateEdgePairAngleEnergyTerm(int edgeIndex1, int edgeIndex2, Vector edge1Vector, Vector edge2Vector)
        {
            Tuple <int, int>    pair = new Tuple <int, int>(edgeIndex1, edgeIndex2);
            ShapeEdgePairParams pairParams;

            if (!this.edgePairParams.TryGetValue(pair, out pairParams))
            {
                throw new ArgumentException("Given edge pair has no common pairwise constraints.");
            }

            double angle     = Vector.AngleBetween(edge1Vector, edge2Vector);
            double angleDiff = MathHelper.AngleAbsDifference(angle, pairParams.MeanAngle);
            double angleTerm = angleDiff * angleDiff / (2 * pairParams.AngleDeviation * pairParams.AngleDeviation);

            return(angleTerm);
        }
Ejemplo n.º 3
0
        public static ShapeModel Learn(IEnumerable <Shape> shapes, IEnumerable <Tuple <int, int> > constrainedEdgePairs)
        {
            if (shapes == null)
            {
                throw new ArgumentNullException("shapes");
            }
            if (constrainedEdgePairs == null)
            {
                throw new ArgumentNullException("constrainedEdgePairs");
            }
            int shapeCount = shapes.Count();

            if (shapeCount <= 1)
            {
                throw new ArgumentException("Can't learn from less than two shapes.", "shapes");
            }
            ShapeStructure structure = shapes.First().Structure;

            if (!shapes.All(s => s.Structure == structure))
            {
                throw new ArgumentException("All the shapes should have the same structure.", "shapes");
            }

            // Learn root edge
            double rootEdgeLengthDeviation = Double.PositiveInfinity;
            double rootEdgeMeanLength      = 0;
            int    rootEdgeIndex           = -1;

            for (int i = 0; i < structure.Edges.Count; ++i)
            {
                double lengthSum = 0, lengthSumSqr = 0;
                foreach (Shape shape in shapes)
                {
                    double edgeLength = shape.GetEdgeVector(i).Length;
                    lengthSum    += edgeLength;
                    lengthSumSqr += edgeLength * edgeLength;
                }

                double meanLength = lengthSumSqr / lengthSum;

                double lengthRatioDiffSqrSum = 0;
                foreach (Shape shape in shapes)
                {
                    double edgeLength      = shape.GetEdgeVector(i).Length;
                    double lengthRatioDiff = edgeLength / meanLength - 1;
                    lengthRatioDiffSqrSum += lengthRatioDiff * lengthRatioDiff;
                }

                double lengthDeviation = Math.Sqrt(lengthRatioDiffSqrSum / shapeCount);

                if (rootEdgeIndex == -1 || lengthDeviation < rootEdgeLengthDeviation)
                {
                    rootEdgeLengthDeviation = lengthDeviation;
                    rootEdgeMeanLength      = meanLength;
                    rootEdgeIndex           = i;
                }
            }

            // Learn edge params
            List <ShapeEdgeParams> shapeEdgeParams = new List <ShapeEdgeParams>();

            for (int i = 0; i < structure.Edges.Count; ++i)
            {
                double sum = 0, sumSqr = 0;
                foreach (Shape shape in shapes)
                {
                    double edgeLength = shape.GetEdgeVector(i).Length;
                    double ratio      = shape.EdgeWidths[i] / edgeLength;
                    sum    += ratio;
                    sumSqr += ratio * ratio;
                }

                double meanWidthToLengthRatio = sum / shapeCount;
                double widthToLengthRatioDeviation = Math.Sqrt(sumSqr / shapeCount - meanWidthToLengthRatio * meanWidthToLengthRatio);
                shapeEdgeParams.Add(new ShapeEdgeParams(meanWidthToLengthRatio, widthToLengthRatioDeviation));
            }

            // Learn edge pair params
            Dictionary <Tuple <int, int>, ShapeEdgePairParams> shapeEdgePairParams =
                new Dictionary <Tuple <int, int>, ShapeEdgePairParams>();

            foreach (Tuple <int, int> edgePair in constrainedEdgePairs)
            {
                if (edgePair.Item1 < 0 || edgePair.Item1 >= structure.Edges.Count || edgePair.Item2 < 0 || edgePair.Item2 >= structure.Edges.Count)
                {
                    throw new ArgumentOutOfRangeException("constrainedEdgePairs", "Set of constrained edge pairs contains invalid edge index.");
                }
                ShapeEdge edge1 = structure.Edges[edgePair.Item1];
                ShapeEdge edge2 = structure.Edges[edgePair.Item2];
                if (edge1.Index1 != edge2.Index1 && edge1.Index2 != edge2.Index1 &&
                    edge1.Index1 != edge2.Index2 && edge1.Index2 != edge2.Index2)
                {
                    throw new ArgumentException("Constrained edge pairs should be connected.", "constrainedEdgePairs");
                }

                // Learn means
                double lengthProdSum = 0, lengthSqrSum = 0;
                double meanAngle        = 0;
                int    shapesConsidered = 0;
                foreach (Shape shape in shapes)
                {
                    ++shapesConsidered;

                    Vector edge1Vec = shape.GetEdgeVector(edgePair.Item1);
                    Vector edge2Vec = shape.GetEdgeVector(edgePair.Item2);

                    double length1 = edge1Vec.Length;
                    double length2 = edge2Vec.Length;
                    lengthProdSum += length1 * length2;
                    lengthSqrSum  += length2 * length2;

                    double angle = Vector.AngleBetween(edge1Vec, edge2Vec);

                    meanAngle = MathHelper.InterpolateAngle(meanAngle, angle, 1.0 / shapesConsidered);
                }

                double meanLengthRatio = lengthProdSum / lengthSqrSum;

                // Learn deviations
                double angleAbsDiffSqrSum = 0;
                double lengthDiffSqrSum   = 0;
                foreach (Shape shape in shapes)
                {
                    Vector edge1Vec = shape.GetEdgeVector(edgePair.Item1);
                    Vector edge2Vec = shape.GetEdgeVector(edgePair.Item2);

                    double length1    = edge1Vec.Length;
                    double length2    = edge2Vec.Length;
                    double lengthDiff = length1 - meanLengthRatio * length2;
                    lengthDiffSqrSum += lengthDiff * lengthDiff;

                    double angle     = Vector.AngleBetween(edge1Vec, edge2Vec);
                    double angleDiff = MathHelper.AngleAbsDifference(meanAngle, angle);
                    angleAbsDiffSqrSum += angleDiff * angleDiff;
                }

                double lengthDiffDeviation = Math.Sqrt(lengthDiffSqrSum / shapeCount);
                double angleDeviation      = Math.Sqrt(angleAbsDiffSqrSum / shapeCount);

                if (shapeEdgePairParams.ContainsKey(edgePair) || shapeEdgePairParams.ContainsKey(new Tuple <int, int>(edgePair.Item2, edgePair.Item1)))
                {
                    throw new ArgumentException("Same pair of edges is constrained more than once.", "constrainedEdgePairs");
                }
                shapeEdgePairParams.Add(edgePair, new ShapeEdgePairParams(meanAngle, meanLengthRatio, angleDeviation, lengthDiffDeviation));
            }

            return(new ShapeModel(structure, shapeEdgeParams, shapeEdgePairParams, rootEdgeIndex, rootEdgeMeanLength, rootEdgeLengthDeviation));
        }