Esempio n. 1
0
        /// <summary>
        /// Generates a term that gets smaller as the given 2D point fits a 3D points set projection.
        /// </summary>
        /// <param name="pointsSet">A representation for the 3D points set</param>
        /// <param name="point">The 2D point</param>
        /// <returns>The term that measures fitness of <paramref name="point"/> being on the 2D projection of the set specified by <paramref name="pointsSet"/></returns>
        public static Term Compute(CircleFeatureCurve pointsSet, Point point)
        {
            // here we explicitly assume that the view vector is (0, 0, 1) or (0, 0, -1)
            var x_ = point.X;
            var y_ = point.Y;

            var cx = pointsSet.Center.X;
            var cy = pointsSet.Center.Y;
            var cz = pointsSet.Center.Z;

            var nx = pointsSet.Normal.X;
            var ny = pointsSet.Normal.Y;
            var nz = pointsSet.Normal.Z;

            var r = pointsSet.Radius;

            var dx = cx - x_;
            var dy = cy + y_;

            var lhs = TermBuilder.Sum(
                TermBuilder.Power(dx * nz, 2),
                TermBuilder.Power(dy * nz, 2),
                TermBuilder.Power(dx * nx + dy * ny, 2));
            var rhs = TermBuilder.Power(r * nz, 2);

            return(TermBuilder.Power(lhs - rhs, 2));
        }
        private static OptimizationProblem GetOptimizationProblem(IEnumerable <PrimitiveEditConstraint> constraints)
        {
            // generate constraint terms
            var constraintTerms = new List <Term>();
            var paramsToVars    = new Dictionary <IEditParameter, ParameterVariable[]>();

            foreach (var constraint in constraints)
            {
                TryAxisOnLine(constraintTerms, paramsToVars, constraint);
                TryPointOnPlane(constraintTerms, paramsToVars, constraint);
            }

            // get variables
            var variables =
                (from vars in paramsToVars.Values
                 from var in vars
                 select var).ToArray();

            // construct objective --> sum of squared distances to current values
            var values    = GetCurrentValues(variables);
            var objective = TermUtils.SafeSum(
                from i in Enumerable.Range(0, variables.Length)
                select TermBuilder.Power(variables[i] - values[i], 2));

            return(new OptimizationProblem
            {
                Constraints = constraintTerms.ToArray(),
                Variables = variables,
                Objective = objective,
            });
        }
        public IEnumerable <double[]> Solve(Term objective, IEnumerable <Term> constraints, Variable[] variables, double[] startPoint)
        {
            var constraintSquares          = constraints.Select(c => TermBuilder.Power(c, 2));
            var penalizedObjective         = objective + penaltyWeight * TermUtils.SafeSum(constraintSquares);
            var compiledPenalizedObjective = penalizedObjective.Compile(variables);
            var solution = unconstrainedOptimizer.Solve(x => compiledPenalizedObjective.Differentiate(x), startPoint, gradientNormThreshold);

            yield return(solution);
        }
Esempio n. 4
0
        public static Term DiffSquared(Term[] left, Term[] right)
        {
            Contract.Requires(left != null);
            Contract.Requires(right != null);
            Contract.Requires(left.Length == right.Length);

            var toSum = from i in System.Linq.Enumerable.Range(0, left.Length)
                        select TermBuilder.Power(left[i] - right[i], 2);

            return(TermBuilder.Sum(toSum));
        }
Esempio n. 5
0
        protected override Tuple <Term, Term[]> Reconstruct(SnappedSphere snappedPrimitive, Dictionary <FeatureCurve, ISet <Annotation> > curvesToAnnotations)
        {
            var circle = CircleFitter.Fit(snappedPrimitive.ProjectionParallelCircle.SnappedTo.Points);

            var result =
                TermBuilder.Power(snappedPrimitive.Center.X - circle.Center.X, 2) +
                TermBuilder.Power(snappedPrimitive.Center.Y + circle.Center.Y, 2) +
                TermBuilder.Power(snappedPrimitive.Radius - circle.Radius, 2);

            return(Tuple.Create(result, NO_TERMS));
        }
Esempio n. 6
0
        public void PowerContract()
        {
            Assert.Throws <ArgumentNullException>(() => TermBuilder.Power(null, 1));
            Assert.Throws <ArgumentNullException>(() => TermBuilder.Power(x, null));
            Assert.Throws <ArgumentNullException>(() => TermBuilder.Power(null, x));
            Assert.IsType <ConstPower>(TermBuilder.Power(x, 1));

            Assert.Throws <ArgumentException>(() => TermBuilder.Power(x, double.NaN));
            Assert.Throws <ArgumentException>(() => TermBuilder.Power(x, double.PositiveInfinity));
            Assert.IsType <TermPower>(TermBuilder.Power(x, y));
            Assert.IsType <TermPower>(TermBuilder.Power(1, y));
        }
Esempio n. 7
0
        public static Term SoftMin(Term[] terms, double exponent = 6)
        {
            Contract.Requires(terms != null);
            Contract.Requires(terms.Length > 0);
            Contract.Requires(Contract.ForAll(terms, term => term != null));
            Contract.Requires(exponent > 1);
            Contract.Ensures(Contract.Result <Term>() != null);

            var powers = terms.Select(term => TermBuilder.Power(term, -exponent));

            return(TermBuilder.Power(TermBuilder.Sum(powers), -1 / exponent));
        }
Esempio n. 8
0
        private static Term MeanSquaredError(Term[] terms, double[] values)
        {
            Contract.Requires(terms != null);
            Contract.Requires(values != null);
            Contract.Requires(terms.Length == values.Length);
            Contract.Requires(Contract.ForAll(terms, term => term != null));
            Contract.Ensures(Contract.Result <Term>() != null);

            var errorTerms = from i in Enumerable.Range(0, terms.Length)
                             select TermBuilder.Power(terms[i] + (-values[i]), 2);

            return((1 / (double)terms.Length) * TermUtils.SafeSum(errorTerms));
        }
Esempio n. 9
0
        private Term[] GetConcreteAnnotationTerm(OnSphere onSphere)
        {
            var center = onSphere.SphereOwned.Center;
            var radius = onSphere.SphereOwned.Radius;

            var touchingPoint  = onSphere.CenterTouchesSphere.Center;
            var touchingNormal = onSphere.CenterTouchesSphere.Normal;

            var radiusConstraint = (center - touchingPoint).NormSquared - TermBuilder.Power(radius, 2);
            var normalConstraint = VectorParallelism(center - touchingPoint, touchingNormal);

            return(normalConstraint.Append(radiusConstraint).ToArray());
        }
Esempio n. 10
0
        private static Tuple <Term, Term[]> CreateSGCTerms(SnappedStraightGenCylinder snappedPrimitive, double[] radii, Point spineStart, Point spineEnd)
        {
            var constraints = new Term[] { snappedPrimitive.Axis.NormSquared - 1 };

            if (radii.Length > 0)
            {
                var featureCurveTerms =
                    from item in snappedPrimitive.FeatureCurves.Cast <CircleFeatureCurve>()
                    where item != null
                    where item.SnappedTo != null
                    from term in ProjectionFit.Compute(item)
                    select term;

                var featureCurvesTerm = 0.1 * TermUtils.SafeAvg(featureCurveTerms);

                // the difference between the primitive's radii and the computed radii is minimized
                var radiiApproxTerm = TermUtils.SafeAvg(
                    from i in Enumerable.Range(0, snappedPrimitive.Components.Length)
                    let component = snappedPrimitive.Components[i]
                                    let radius = radii[i]
                                                 select TermBuilder.Power(component.Radius - radius, 2));

                // the smoothness of the primitive's radii (laplacian norm) is minimized
                var radiiSmoothTerm = TermUtils.SafeAvg(
                    from pair in snappedPrimitive.Components.SeqTripples()
                    let r1                                              = pair.Item1.Radius
                                               let r2                   = pair.Item2.Radius
                                                                 let r3 = pair.Item3.Radius
                                                                          select TermBuilder.Power(r2 - 0.5 * (r1 + r3), 2)); // how far is r2 from the avg of r1 and r3

                // we specifically wish to give higher weight to first and last radii, so we have
                // an additional first/last radii term.
                var endpointsRadiiTerm =
                    TermBuilder.Power(radii[0] - snappedPrimitive.Components.First().Radius, 2) +
                    TermBuilder.Power(radii.Last() - snappedPrimitive.Components.Last().Radius, 2);

                // objective - weighed average of all terms
                var objective =
                    radiiApproxTerm +
                    radiiSmoothTerm +
                    featureCurvesTerm +
                    endpointsRadiiTerm;

                return(Tuple.Create(objective, constraints));
            }
            else
            {
                return(Tuple.Create((Term)0, constraints)); // if we can't extract radii approximation, we don't do any snapping
            }
        }
Esempio n. 11
0
        private static ICompiledTerm ConstructTerm(Coefficient[][] coefficients, Variable[] variables)
        {
            var squareTerms =
                from i in Enumerable.Range(0, coefficients.Length)
                let termCoefficients = coefficients[i]
                                       let sumTerms = from j in Enumerable.Range(0, termCoefficients.Length)
                                                      select termCoefficients[j].Value * variables[termCoefficients[j].Index]
                                                      let sum = TermBuilder.Sum(sumTerms)
                                                                select TermBuilder.Power(sum, 2);

            var finalTerm = TermBuilder.Sum(squareTerms);
            var compiled  = finalTerm.Compile(variables);

            return(compiled);
        }
Esempio n. 12
0
        static void Main(string[] args)
        {
            var x = new Variable();
            var y = new Variable();
            var z = new Variable();

            // f(x, y, z) = (x-2)² + (y+4)² + (z-1)²
            // the min should be (x, y, z) = (2, -4, 1)
            var func     = TermBuilder.Power(x - 2, 2) + TermBuilder.Power(y + 4, 2) + TermBuilder.Power(z - 1, 2);
            var compiled = func.Compile(x, y, z);

            // perform optimization
            var vec = new double[3];

            vec = GradientDescent(compiled, vec, stepSize: 0.01, iterations: 1000);

            Console.WriteLine("The approx. minimizer is: {0}, {1}, {2}", vec[0], vec[1], vec[2]);
        }
Esempio n. 13
0
        protected Term EndpointsProjectionFit(CircleFeatureCurve pointsSet, Point p1, Point p2)
        {
            var x1 = p1.X;
            var y1 = -p1.Y;

            var x2 = p2.X;
            var y2 = -p2.Y;

            var cx = pointsSet.Center.X;
            var cy = pointsSet.Center.Y;
            var r  = pointsSet.Radius;

            var eq1 = TermBuilder.Power(x1 - cx, 2) + TermBuilder.Power(y1 - cy, 2) - TermBuilder.Power(r, 2);
            var eq2 = TermBuilder.Power(x2 - cx, 2) + TermBuilder.Power(y2 - cy, 2) - TermBuilder.Power(r, 2);

            var result = TermBuilder.Power(eq1, 2) + TermBuilder.Power(eq2, 2);

            return(result);
        }
Esempio n. 14
0
        private Term PrepareStDevFunction(int count = 5)
        {
            Term stDev = null;

            for (int i = 0; i < count; ++i)
            {
                Variable w = new Variable();
                if (!variables.ContainsKey(i))
                {
                    variables.Add(i, w);
                }
                var std_mul_w = TermBuilder.Power(variables[i], 2) * TermBuilder.Power(stDevs[i], 2);
                if (i == 0)
                {
                    stDev = std_mul_w;
                }
                else
                {
                    stDev += std_mul_w;
                }
                for (int k = i + 1; k < count; ++k)
                {
                    Variable w2 = new Variable();
                    if (!variables.ContainsKey(k))
                    {
                        variables.Add(k, w2);
                    }
                    var cov = 2 * matCov[i, k] * variables[i] * variables[k];
                    stDev += cov;
                }
            }

            stDev = TermBuilder.Power(stDev, 0.5);

            return(stDev);
        }
Esempio n. 15
0
        private static Tuple <Term, Term[]> CreateBGCTerms(SnappedBendedGenCylinder snappedPrimitive, double[] radii, Point[] medial_axis)
        {
            var terms =
                from item in snappedPrimitive.FeatureCurves.Cast <CircleFeatureCurve>()
                where item.SnappedTo != null
                from term in ProjectionFit.Compute(item)
                select term;
            var featureCurvesTerm = TermUtils.SafeAvg(terms);

            var radiiApproxTerm = TermUtils.SafeAvg(
                from i in Enumerable.Range(0, snappedPrimitive.Components.Length)
                let component = snappedPrimitive.Components[i]
                                let radius = radii[i]
                                             select TermBuilder.Power(component.Radius - radius, 2));

            // the smoothness of the primitive's radii (laplacian norm) is minimized
            var radiiSmoothTerm = TermUtils.SafeAvg(
                from pair in snappedPrimitive.Components.SeqTripples()
                let r1                                              = pair.Item1.Radius
                                           let r2                   = pair.Item2.Radius
                                                             let r3 = pair.Item3.Radius
                                                                      select TermBuilder.Power(r2 - 0.5 * (r1 + r3), 2)); // how far is r2 from the avg of r1 and r3

            var positionSmoothnessTerm = TermUtils.SafeAvg(
                from triple in snappedPrimitive.Components.SeqTripples()
                let p1                                              = new TVec(triple.Item1.vS, triple.Item1.vT)
                                           let p2                   = new TVec(triple.Item2.vS, triple.Item2.vT)
                                                             let p3 = new TVec(triple.Item3.vS, triple.Item3.vT)
                                                                      let laplacian = p2 - 0.5 * (p1 + p3)
                                                                                      select laplacian.NormSquared);

            Term[] TermArray = new Term[medial_axis.Length];
            for (int i = 0; i < medial_axis.Length; i++)
            {
                TVec PointOnSpine = snappedPrimitive.BottomCenter + snappedPrimitive.Components[i].vS * snappedPrimitive.U + snappedPrimitive.Components[i].vT * snappedPrimitive.V;
                TermArray[i] = TermBuilder.Power(PointOnSpine.X - medial_axis[i].X, 2) +
                               TermBuilder.Power(PointOnSpine.Y + medial_axis[i].Y, 2);
            }
            var spinePointTerm = TermUtils.SafeAvg(TermArray);

            // we specifically wish to give higher weight to first and last radii, so we have
            // an additional first/last radii term.
            var endpointsRadiiTerm =
                TermBuilder.Power(radii[0] - snappedPrimitive.Components.First().Radius, 2) +
                TermBuilder.Power(radii.Last() - snappedPrimitive.Components.Last().Radius, 2);

            // objective - weighed average of all terms
            var objective =
                0.1 * featureCurvesTerm +
                radiiApproxTerm +
                radiiSmoothTerm +
                positionSmoothnessTerm +
                spinePointTerm +
                endpointsRadiiTerm;

            var sB = snappedPrimitive.NPbot.X;
            var tB = snappedPrimitive.NPbot.Y;

            var s0 = snappedPrimitive.Components[0].vS;
            var t0 = snappedPrimitive.Components[0].vT;
            var s1 = snappedPrimitive.Components[1].vS;
            var t1 = snappedPrimitive.Components[1].vT;
            var botNormalParallelism = tB * (s1 - s0) - sB * (t1 - t0);

            var sT                   = snappedPrimitive.NPtop.X;
            var tT                   = snappedPrimitive.NPtop.Y;
            var sLast                = snappedPrimitive.Components[snappedPrimitive.Components.Length - 1].vS;
            var tLast                = snappedPrimitive.Components[snappedPrimitive.Components.Length - 1].vT;
            var sBeforeLast          = snappedPrimitive.Components[snappedPrimitive.Components.Length - 2].vS;
            var tBeforeLast          = snappedPrimitive.Components[snappedPrimitive.Components.Length - 2].vT;
            var topNormalParallelism = tT * (sLast - sBeforeLast) - sT * (tLast - tBeforeLast);

            var topNormalized         = snappedPrimitive.NPtop.NormSquared - 1;
            var botNormalized         = snappedPrimitive.NPbot.NormSquared - 1;
            var uNormalized           = snappedPrimitive.U.NormSquared - 1;
            var vNormalized           = snappedPrimitive.V.NormSquared - 1;
            var uvOrthogonal          = TVec.InnerProduct(snappedPrimitive.U, snappedPrimitive.V);
            var firstComponentBottomS = snappedPrimitive.Components[0].vS;
            var firstComponentBottomT = snappedPrimitive.Components[0].vT;
            var constraints           = new List <Term>
            {
                topNormalized,
                botNormalized,
                uNormalized,
                vNormalized,
                uvOrthogonal,
                firstComponentBottomS,
                firstComponentBottomT,
                botNormalParallelism,
                topNormalParallelism
            };

            var meanRadius   = radii.Sum() / radii.Length;
            var stdDevRadius = Math.Sqrt(radii.Select(r => r * r).Sum() / radii.Length - meanRadius * meanRadius);

            Debug.WriteLine("ALEXALEX Mean radius is {0}, stddev is {1}", meanRadius, stdDevRadius);
            if (stdDevRadius <= 0.3 * meanRadius)
            {
                foreach (var pair in snappedPrimitive.Components.SeqPairs())
                {
                    var ra = pair.Item1.Radius;
                    var rb = pair.Item2.Radius;
                    constraints.Add(ra - rb);
                }
            }

            return(Tuple.Create(objective, constraints.ToArray()));
        }
Esempio n. 16
0
        protected override Tuple <Term, Term[]> Reconstruct(SnappedCuboid snappedPrimitive, Dictionary <FeatureCurve, ISet <Annotation> > curvesToAnnotations)
        {
            Point   O  = NewPrimitiveExtensions.FindCoincidentPoint(snappedPrimitive.CubicCorner);
            Point   A  = NewPrimitiveExtensions.FindEndPoint(snappedPrimitive.CubicCorner[0].AssignedTo, O);
            Point   B  = NewPrimitiveExtensions.FindEndPoint(snappedPrimitive.CubicCorner[1].AssignedTo, O);
            Point   C  = NewPrimitiveExtensions.FindEndPoint(snappedPrimitive.CubicCorner[2].AssignedTo, O);
            Point3D Op = NewPrimitiveExtensions.FindCoincident3DPoint(snappedPrimitive.CubicCorner);
            EnhancedPrimitiveCurve ec = (EnhancedPrimitiveCurve)snappedPrimitive.CubicCorner[0];
            Point3D Ap = NewPrimitiveExtensions.FindEnd3DPoint(ec.Points3D, Op);

            ec = (EnhancedPrimitiveCurve)snappedPrimitive.CubicCorner[1];
            Point3D Bp = NewPrimitiveExtensions.FindEnd3DPoint(ec.Points3D, Op);

            ec = (EnhancedPrimitiveCurve)snappedPrimitive.CubicCorner[2];
            Point3D Cp = NewPrimitiveExtensions.FindEnd3DPoint(ec.Points3D, Op);

            O.Y = -O.Y;
            A.Y = -A.Y;
            B.Y = -B.Y;
            C.Y = -C.Y;
            Vector OA = A - O;
            Vector OB = B - O;
            Vector OC = C - O;

            Debug.WriteLine("O=({0},{1})", O.X, O.Y);
            Debug.WriteLine("A=({0},{1})", A.X, A.Y);
            Debug.WriteLine("B=({0},{1})", B.X, B.Y);
            Debug.WriteLine("C=({0},{1})", C.X, C.Y);

            Vector OAn = OA.Normalized();
            Vector OBn = OB.Normalized();
            Vector OCn = OC.Normalized();

            double dotABn = OAn * OBn;
            double dotACn = OAn * OCn;
            double dotBCn = OBn * OCn;

            double a = Math.Acos(dotABn);
            double b = Math.Acos(dotACn);
            double c = Math.Acos(dotBCn);

            /*double[] anglesSort = new double[] { a, b, c };
             * double[] angles = new double[] { a, b, c };
             * int[] idx = new int[3]{0, 1, 2};
             * Vector[] vecArr = new Vector[] { OAn, OBn, OCn };
             * Array.Sort(anglesSort, idx);
             * Debug.WriteLine("(a,b,c)=({0},{1},{2})", a * 180 / Math.PI, b * 180 / Math.PI, c * 180 / Math.PI);
             * Debug.WriteLine("sorted : (a,b,c)=({0},{1},{2})", anglesSort[0] * 180 / Math.PI, anglesSort[1] * 180 / Math.PI, anglesSort[2] * 180 / Math.PI);
             * Debug.WriteLine("index : {0}, {1}, {2}", idx[0], idx[1], idx[2]);
             * if (anglesSort[1] > Math.PI / 2 && anglesSort[0] < Math.PI / 2)
             * {
             *  double theta = anglesSort[1] - Math.PI / 2 + 0.001;
             *  var rotMatrix = new RotateTransform(theta*180/Math.PI).Value;
             *  vecArr[idx[1]] = rotMatrix.Transform(vecArr[idx[1]]);
             *  angles[idx[1]] = Math.PI/2 - 0.001;
             *  angles[idx[0]] = angles[idx[2]] - angles[idx[1]];
             * }
             * Debug.WriteLine("after : (a,b,c)=({0},{1},{2},{3})", angles[0] * 180 / Math.PI, angles[1] * 180 / Math.PI, angles[2] * 180 / Math.PI, (angles[0]+angles[1])*180/Math.PI);
             *
             * dotABn = Math.Cos(angles[0]);
             * dotACn = Math.Cos(angles[1]);
             * dotBCn = Math.Cos(angles[2]);
             *
             * OAn = vecArr[0].Normalized();
             * OBn = vecArr[1].Normalized();
             * OCn = vecArr[2].Normalized();*/
            Debug.WriteLine("Cubic Corner Index:{0}", snappedPrimitive.CubicCornerIdx);

            double pn, qn, rn;
            int    signp = 0, signq = 0, signr = 0;

            if (dotABn < 0 && dotACn < 0 && dotBCn < 0)
            {
                signp = signq = signr = 1;
            }
            else
            {
                if (dotABn < 0)
                {
                    signp = signq = -1;
                    signr = 1;
                }
                else if (dotBCn < 0)
                {
                    signq = signr = 1;
                    signp = -1;
                }
                else
                {
                    signp = signr = 1;
                    signq = -1;
                }
            }

            pn = signp * Math.Sqrt(-dotACn * dotABn / dotBCn);
            qn = signq * Math.Sqrt(-dotABn * dotBCn / dotACn);
            rn = signr * Math.Sqrt(-dotACn * dotBCn / dotABn);

            Debug.WriteLine("p*q={0}, OA*OB={1}", pn * qn, dotABn);
            Debug.WriteLine("p*r={0}, OA*OC={1}", pn * rn, dotACn);
            Debug.WriteLine("q*r={0}, OB*OC={1}", rn * qn, dotBCn);

            Vector3D OA3Dn = new Vector3D(OAn.X, OAn.Y, pn);
            Vector3D OB3Dn = new Vector3D(OBn.X, OBn.Y, qn);
            Vector3D OC3Dn = new Vector3D(OCn.X, OCn.Y, rn);

            OA3Dn = OA3Dn.Normalized();
            OB3Dn = OB3Dn.Normalized();
            OC3Dn = OC3Dn.Normalized();
            Vector3D pOA     = (Ap - Op).Normalized();
            Vector3D pOB     = (Bp - Op).Normalized();
            Vector3D pOC     = (Cp - Op).Normalized();
            Vector3D approxW = new Vector3D(); // = OA3Dn.Normalized();
            Vector3D approxH = new Vector3D(); // = -OB3Dn.Normalized();
            Vector3D approxD = new Vector3D(); // = OC3Dn.Normalized();

            /*if (pOA.X * OA3Dn.X < 0) OA3Dn.X = -OA3Dn.X;
            *  if (pOA.Y * OA3Dn.Y < 0) OA3Dn.Y = -OA3Dn.Y;
            *  if (pOA.Z * OA3Dn.Z < 0) OA3Dn.Z = -OA3Dn.Z;
            *
            *  if (pOB.X * OB3Dn.X < 0) OB3Dn.X = -OB3Dn.X;
            *  if (pOB.Y * OB3Dn.Y < 0) OB3Dn.Y = -OB3Dn.Y;
            *  if (pOB.Z * OB3Dn.Z < 0) OB3Dn.Z = -OB3Dn.Z;
            *
            *  if (pOC.X * OC3Dn.X < 0) OC3Dn.X = -OC3Dn.X;
            *  if (pOC.Y * OC3Dn.Y < 0) OC3Dn.Y = -OC3Dn.Y;
            *  if (pOC.Z * OC3Dn.Z < 0) OC3Dn.Z = -OC3Dn.Z;*/



            switch (snappedPrimitive.CubicCornerIdx)
            {
            case 0:
                approxW = Vector3D.DotProduct(pOA, OA3Dn) > 0 ? OA3Dn : -OA3Dn;
                approxH = Vector3D.DotProduct(pOB, OB3Dn) < 0 ? OB3Dn : -OB3Dn;
                approxD = Vector3D.DotProduct(pOC, OC3Dn) > 0 ? OC3Dn : -OC3Dn;
                break;

            case 1:
                approxW = Vector3D.DotProduct(pOA, OA3Dn) > 0 ? -OA3Dn : OA3Dn;
                approxH = Vector3D.DotProduct(pOB, OB3Dn) > 0 ? -OB3Dn : OB3Dn;
                approxD = Vector3D.DotProduct(pOC, OC3Dn) > 0 ? OC3Dn : -OC3Dn;
                break;

            case 2:
                approxW = Vector3D.DotProduct(pOA, OA3Dn) > 0 ? -OA3Dn : OA3Dn;
                approxH = Vector3D.DotProduct(pOB, OB3Dn) > 0 ? OB3Dn : -OB3Dn;
                approxD = Vector3D.DotProduct(pOC, OC3Dn) < 0 ? OC3Dn : -OC3Dn;
                break;

            case 3:
                approxW = -OA3Dn.Normalized();
                approxH = -OB3Dn.Normalized();
                approxD = -OC3Dn.Normalized();
                break;

            case 4:
                approxW = OA3Dn.Normalized();
                approxH = OB3Dn.Normalized();
                approxD = OC3Dn.Normalized();
                break;

            case 5:
                //if (pOA.X * OA3Dn.X < 0) OA3Dn.X = -OA3Dn.X;
                //if (pOA.X * OA3Dn.X < 0) OA3Dn.X = -OA3Dn.X;
                approxW = Vector3D.DotProduct(pOA, OA3Dn) > 0 ? -OA3Dn : OA3Dn;
                approxH = Vector3D.DotProduct(pOB, OB3Dn) > 0 ? OB3Dn : -OB3Dn;
                approxD = Vector3D.DotProduct(pOC, OC3Dn) > 0 ? OC3Dn : -OC3Dn;
                //Debug.WriteLine();

                break;

            case 6:
                approxW = OA3Dn.Normalized();
                approxH = OB3Dn.Normalized();
                approxD = -OC3Dn.Normalized();
                break;

            case 7:
                approxW = -OA3Dn.Normalized();
                approxH = OB3Dn.Normalized();
                approxD = -OC3Dn.Normalized();
                break;
            }

            snappedPrimitive.W = OA3Dn.Normalized();
            snappedPrimitive.H = OB3Dn.Normalized();
            snappedPrimitive.D = OC3Dn.Normalized();

            Debug.WriteLine("Normalized W*H={0}", Vector3D.DotProduct(approxW, approxH));
            Debug.WriteLine("Normalized W*D={0}", Vector3D.DotProduct(approxW, approxD));
            Debug.WriteLine("Normalized D*H={0}", Vector3D.DotProduct(approxD, approxH));

            /*double lOA = OA.Length;
             * double lOB = OB.Length;
             * double lOC = OC.Length;
             * Debug.WriteLine("(lOA, lOB, lOC)=({0},{1},{2})", lOA, lOB, lOC);*/

            //a = Math.Acos(OAn * OBn);
            //b = Math.Acos(OAn * OCn);
            //c = Math.Acos(OBn * OCn);
            //Debug.WriteLine("(pi/2, a,b,c,sum)=({0},{1},{2}, {3},{4})", Math.PI / 2, a * 180 / Math.PI, b * 180 / Math.PI, c * 180 / Math.PI, a * 180 / Math.PI + b * 180 / Math.PI);

            /*double cota = 1 / Math.Tan(a);
            *  double cotb = 1 / Math.Tan(b);
            *  double cotc = 1 / Math.Tan(c);*/

            /*double dotAB = lOA * lOB * Math.Cos(a);
            *  double dotAC = lOA * lOC * Math.Cos(b);
            *  double dotBC = lOB * lOC * Math.Cos(c);*/

            double dotAB = OA * OB;
            double dotAC = OA * OC;
            double dotBC = OB * OC;
            double p, q, r;

            p = signp * Math.Sqrt(-dotAC * dotAB / dotBC);
            q = signq * Math.Sqrt(-dotAB * dotBC / dotAC);
            r = signr * Math.Sqrt(-dotAC * dotBC / dotAB);

            //double r = Math.Sqrt(-dotAB*dotBC/dotAC);
            //Debug.WriteLine("(p,q,r)=({0},{1},{2})", p, q, r);

            //ec = (EnhancedPrimitiveCurve)snappedPrimitive.CubicCorner[0];
            Vector3D cuboidOA = ec.Points3D[1] - ec.Points3D[0];
            //ec = (EnhancedPrimitiveCurve)snappedPrimitive.CubicCorner[1];
            Vector3D cuboidOB = ec.Points3D[1] - ec.Points3D[0];
            //ec = (EnhancedPrimitiveCurve)snappedPrimitive.CubicCorner[2];
            Vector3D cuboidOC = ec.Points3D[1] - ec.Points3D[0];
            double   zAp      = p;
            double   zAn      = -zAp;
            double   zBp      = q;
            double   zBn      = -zBp;
            double   zCp      = r;
            double   zCn      = -zCp;

            Point3D O3D = new Point3D(O.X, O.Y, 0);

            snappedPrimitive.Origin = O3D;
            Point3D  A3Dp  = new Point3D(A.X, A.Y, zAp);
            Point3D  A3Dn  = new Point3D(A.X, A.Y, -zAp);
            Vector3D OA3Dp = A3Dp - O3D;
            //Point3D A3D = (Vector3D.DotProduct(cuboidOA, OA3Dp) > 0) ? A3Dp : A3Dn;
            Point3D A3D = A3Dp;// (Vector3D.DotProduct(cuboidOA, OA3Dp) > 0) ? A3Dp : A3Dn;
            //Vector

            Point3D  B3Dp  = new Point3D(B.X, B.Y, zBp);
            Point3D  B3Dn  = new Point3D(B.X, B.Y, -zBp);
            Vector3D OB3Dp = B3Dp - O3D;
            //Point3D B3D = (Vector3D.DotProduct(cuboidOB, OB3Dp) > 0) ? B3Dp : B3Dn;
            Point3D B3D = B3Dp; //(Vector3D.DotProduct(cuboidOB, OB3Dp) > 0) ? B3Dp : B3Dn;

            Point3D  C3Dp  = new Point3D(C.X, C.Y, zCp);
            Point3D  C3Dn  = new Point3D(C.X, C.Y, -zCp);
            Vector3D OC3Dp = C3Dp - O3D;
            //Point3D C3D = (Vector3D.DotProduct(cuboidOC, OC3Dp) > 0) ? C3Dp : C3Dn;
            Point3D C3D = C3Dp;

            Debug.WriteLine("OA3D=({0},{1},{2})", OA3Dp.X, OA3Dp.Y, OA3Dp.Z);
            Debug.WriteLine("OB3D=({0},{1},{2})", OB3Dp.X, OB3Dp.Y, OB3Dp.Z);

            Debug.WriteLine("W*H={0}", Vector3D.DotProduct(approxH, approxW));
            Debug.WriteLine("W*D={0}", Vector3D.DotProduct(approxD, approxW));
            Debug.WriteLine("D*H={0}", Vector3D.DotProduct(approxH, approxD));

            double  approxWidth  = (A3D - O3D).Length;
            double  approxHeight = (O3D - B3D).Length;
            double  approxDepth  = (C3D - O3D).Length;
            Point3D approxCenter = new Point3D();

            switch (snappedPrimitive.CubicCornerIdx)
            {
            case 0:
                approxCenter = O3D + 0.5 * approxWidth * approxW - 0.5 * approxHeight * approxH + 0.5 * approxDepth * approxD;
                break;

            case 1:
                approxCenter = O3D - 0.5 * approxWidth * approxW - 0.5 * approxHeight * approxH + 0.5 * approxDepth * approxD;
                break;

            case 2:
                approxCenter = O3D + 0.5 * approxWidth * approxW - 0.5 * approxHeight * approxH - 0.5 * approxDepth * approxD;
                break;

            case 3:
                approxCenter = O3D - 0.5 * approxWidth * approxW - 0.5 * approxHeight * approxH - 0.5 * approxDepth * approxD;
                break;

            case 4:
                approxCenter = O3D + 0.5 * approxWidth * approxW + 0.5 * approxHeight * approxH + 0.5 * approxDepth * approxD;
                break;

            case 5:
                approxCenter = O3D - 0.5 * approxWidth * approxW + 0.5 * approxHeight * approxH + 0.5 * approxDepth * approxD;
                break;

            case 6:
                approxCenter = O3D + 0.5 * approxWidth * approxW + 0.5 * approxHeight * approxH - 0.5 * approxDepth * approxD;
                break;

            case 7:
                approxCenter = O3D - 0.5 * approxWidth * approxW + 0.5 * approxHeight * approxH - 0.5 * approxDepth * approxD;
                break;
            }
            var CenterTerm =
                TermBuilder.Power(snappedPrimitive.Center.X - approxCenter.X, 2) +
                TermBuilder.Power(snappedPrimitive.Center.Y - approxCenter.Y, 2) +
                TermBuilder.Power(snappedPrimitive.Center.Z - approxCenter.Z, 2);

            var LengthTerm =
                TermBuilder.Power(snappedPrimitive.Width - approxWidth, 2) +
                TermBuilder.Power(snappedPrimitive.Height - approxHeight, 2) +
                TermBuilder.Power(snappedPrimitive.Depth - approxDepth, 2);

            double widthVectorArea  = approxHeight * approxDepth; // area of the face orthogonal to width vector
            double heightVectorArea = approxWidth * approxDepth;  // area of the face orthogonal to height vector
            double depthVectorArea  = approxWidth * approxHeight; // area of the face orthogonal to depth vector

            Debug.WriteLine("WVA = {0}, HVA = {1}, DVA = {2}", widthVectorArea, heightVectorArea, depthVectorArea);

            var WidthVectorTerm = Math.Pow(widthVectorArea, 2) * (
                TermBuilder.Power(snappedPrimitive.Wv.X - approxW.X, 2) +
                TermBuilder.Power(snappedPrimitive.Wv.Y - approxW.Y, 2) +
                TermBuilder.Power(snappedPrimitive.Wv.Z - approxW.Z, 2));

            var HeightVectorTerm = Math.Pow(heightVectorArea, 2) * (
                TermBuilder.Power(snappedPrimitive.Hv.X - approxH.X, 2) +
                TermBuilder.Power(snappedPrimitive.Hv.Y - approxH.Y, 2) +
                TermBuilder.Power(snappedPrimitive.Hv.Z - approxH.Z, 2));

            var DepthVectorTerm = Math.Pow(depthVectorArea, 2) * (
                TermBuilder.Power(snappedPrimitive.Dv.X - approxD.X, 2) +
                TermBuilder.Power(snappedPrimitive.Dv.Y - approxD.Y, 2) +
                TermBuilder.Power(snappedPrimitive.Dv.Z - approxD.Z, 2));

            var objective =
                CenterTerm +
                LengthTerm +
                100 * (WidthVectorTerm +
                       HeightVectorTerm +
                       DepthVectorTerm);

            var ABorthogonal = TVec.InnerProduct(snappedPrimitive.Wv, snappedPrimitive.Hv);
            var ACorthogonal = TVec.InnerProduct(snappedPrimitive.Wv, snappedPrimitive.Dv);
            var BCorthogonal = TVec.InnerProduct(snappedPrimitive.Hv, snappedPrimitive.Dv);
            var constraints  = new Term[] { snappedPrimitive.Wv.NormSquared - 1, snappedPrimitive.Hv.NormSquared - 1, snappedPrimitive.Dv.NormSquared - 1, ABorthogonal, ACorthogonal, BCorthogonal };

            return(Tuple.Create(10 * objective, constraints));
        }
Esempio n. 17
0
 protected override Term GetRadiusSoftConstraint(SnappedCone snapped, double expectedTop, double expectedBottom)
 {
     return(0.5 * (
                TermBuilder.Power(snapped.TopRadius - expectedTop, 2) +
                TermBuilder.Power(snapped.BottomRadius - expectedBottom, 2)));
 }
        private AutoDiff.Term ConvertToAutoDiff(ISymbolicExpressionTreeNode node)
        {
            if (node.Symbol is Constant)
            {
                initialConstants.Add(((ConstantTreeNode)node).Value);
                var var = new AutoDiff.Variable();
                variables.Add(var);
                return(var);
            }
            if (node.Symbol is Variable || node.Symbol is BinaryFactorVariable)
            {
                var varNode       = node as VariableTreeNodeBase;
                var factorVarNode = node as BinaryFactorVariableTreeNode;
                // factor variable values are only 0 or 1 and set in x accordingly
                var varValue = factorVarNode != null ? factorVarNode.VariableValue : string.Empty;
                var par      = FindOrCreateParameter(parameters, varNode.VariableName, varValue);

                if (makeVariableWeightsVariable)
                {
                    initialConstants.Add(varNode.Weight);
                    var w = new AutoDiff.Variable();
                    variables.Add(w);
                    return(AutoDiff.TermBuilder.Product(w, par));
                }
                else
                {
                    return(varNode.Weight * par);
                }
            }
            if (node.Symbol is FactorVariable)
            {
                var factorVarNode = node as FactorVariableTreeNode;
                var products      = new List <Term>();
                foreach (var variableValue in factorVarNode.Symbol.GetVariableValues(factorVarNode.VariableName))
                {
                    var par = FindOrCreateParameter(parameters, factorVarNode.VariableName, variableValue);

                    initialConstants.Add(factorVarNode.GetValue(variableValue));
                    var wVar = new AutoDiff.Variable();
                    variables.Add(wVar);

                    products.Add(AutoDiff.TermBuilder.Product(wVar, par));
                }
                return(AutoDiff.TermBuilder.Sum(products));
            }
            if (node.Symbol is LaggedVariable)
            {
                var varNode = node as LaggedVariableTreeNode;
                var par     = FindOrCreateParameter(parameters, varNode.VariableName, string.Empty, varNode.Lag);

                if (makeVariableWeightsVariable)
                {
                    initialConstants.Add(varNode.Weight);
                    var w = new AutoDiff.Variable();
                    variables.Add(w);
                    return(AutoDiff.TermBuilder.Product(w, par));
                }
                else
                {
                    return(varNode.Weight * par);
                }
            }
            if (node.Symbol is Addition)
            {
                List <AutoDiff.Term> terms = new List <Term>();
                foreach (var subTree in node.Subtrees)
                {
                    terms.Add(ConvertToAutoDiff(subTree));
                }
                return(AutoDiff.TermBuilder.Sum(terms));
            }
            if (node.Symbol is Subtraction)
            {
                List <AutoDiff.Term> terms = new List <Term>();
                for (int i = 0; i < node.SubtreeCount; i++)
                {
                    AutoDiff.Term t = ConvertToAutoDiff(node.GetSubtree(i));
                    if (i > 0)
                    {
                        t = -t;
                    }
                    terms.Add(t);
                }
                if (terms.Count == 1)
                {
                    return(-terms[0]);
                }
                else
                {
                    return(AutoDiff.TermBuilder.Sum(terms));
                }
            }
            if (node.Symbol is Multiplication)
            {
                List <AutoDiff.Term> terms = new List <Term>();
                foreach (var subTree in node.Subtrees)
                {
                    terms.Add(ConvertToAutoDiff(subTree));
                }
                if (terms.Count == 1)
                {
                    return(terms[0]);
                }
                else
                {
                    return(terms.Aggregate((a, b) => new AutoDiff.Product(a, b)));
                }
            }
            if (node.Symbol is Division)
            {
                List <AutoDiff.Term> terms = new List <Term>();
                foreach (var subTree in node.Subtrees)
                {
                    terms.Add(ConvertToAutoDiff(subTree));
                }
                if (terms.Count == 1)
                {
                    return(1.0 / terms[0]);
                }
                else
                {
                    return(terms.Aggregate((a, b) => new AutoDiff.Product(a, 1.0 / b)));
                }
            }
            if (node.Symbol is Absolute)
            {
                var x1 = ConvertToAutoDiff(node.GetSubtree(0));
                return(abs(x1));
            }
            if (node.Symbol is AnalyticQuotient)
            {
                var x1 = ConvertToAutoDiff(node.GetSubtree(0));
                var x2 = ConvertToAutoDiff(node.GetSubtree(1));
                return(x1 / (TermBuilder.Power(1 + x2 * x2, 0.5)));
            }
            if (node.Symbol is Logarithm)
            {
                return(AutoDiff.TermBuilder.Log(
                           ConvertToAutoDiff(node.GetSubtree(0))));
            }
            if (node.Symbol is Exponential)
            {
                return(AutoDiff.TermBuilder.Exp(
                           ConvertToAutoDiff(node.GetSubtree(0))));
            }
            if (node.Symbol is Square)
            {
                return(AutoDiff.TermBuilder.Power(
                           ConvertToAutoDiff(node.GetSubtree(0)), 2.0));
            }
            if (node.Symbol is SquareRoot)
            {
                return(AutoDiff.TermBuilder.Power(
                           ConvertToAutoDiff(node.GetSubtree(0)), 0.5));
            }
            if (node.Symbol is Cube)
            {
                return(AutoDiff.TermBuilder.Power(
                           ConvertToAutoDiff(node.GetSubtree(0)), 3.0));
            }
            if (node.Symbol is CubeRoot)
            {
                return(cbrt(ConvertToAutoDiff(node.GetSubtree(0))));
            }
            if (node.Symbol is Sine)
            {
                return(sin(
                           ConvertToAutoDiff(node.GetSubtree(0))));
            }
            if (node.Symbol is Cosine)
            {
                return(cos(
                           ConvertToAutoDiff(node.GetSubtree(0))));
            }
            if (node.Symbol is Tangent)
            {
                return(tan(
                           ConvertToAutoDiff(node.GetSubtree(0))));
            }
            if (node.Symbol is HyperbolicTangent)
            {
                return(tanh(
                           ConvertToAutoDiff(node.GetSubtree(0))));
            }
            if (node.Symbol is Erf)
            {
                return(erf(
                           ConvertToAutoDiff(node.GetSubtree(0))));
            }
            if (node.Symbol is Norm)
            {
                return(norm(
                           ConvertToAutoDiff(node.GetSubtree(0))));
            }
            if (node.Symbol is StartSymbol)
            {
                if (addLinearScalingTerms)
                {
                    // scaling variables α, β are given at the beginning of the parameter vector
                    var alpha = new AutoDiff.Variable();
                    var beta  = new AutoDiff.Variable();
                    variables.Add(beta);
                    variables.Add(alpha);
                    var t = ConvertToAutoDiff(node.GetSubtree(0));
                    return(t * alpha + beta);
                }
                else
                {
                    return(ConvertToAutoDiff(node.GetSubtree(0)));
                }
            }
            throw new ConversionException();
        }
Esempio n. 19
0
        protected override Term GetRadiusSoftConstraint(SnappedCylinder snapped, double expectedTop, double expectedBottom)
        {
            var avg = 0.5 * (expectedTop + expectedBottom);

            return(TermBuilder.Power(snapped.Radius - avg, 2));
        }