Beispiel #1
0
        private Tuple <Term, Term[]> TwoSilhouettesNoFeatures(TSnapped snappedPrimitive, ISet <FeatureCurve> annotated)
        {
            var sil0   = SegmentApproximator.ApproximateSegment(snappedPrimitive.LeftSilhouette.Points);
            var sil1   = SegmentApproximator.ApproximateSegment(snappedPrimitive.RightSilhouette.Points);
            var axis2d = Get2DVector(snappedPrimitive.AxisResult);

            var sil0Top = GetForwardPoint(sil0, axis2d);
            var sil0Bot = GetForwardPoint(sil0, -axis2d);
            var sil1Top = GetForwardPoint(sil1, axis2d);
            var sil1Bot = GetForwardPoint(sil1, -axis2d);

            var topFit = ProjectionFit.Compute(
                snappedPrimitive.TopFeatureCurve, new Point[] { sil0Top, sil1Top });
            var botFit = ProjectionFit.Compute(
                snappedPrimitive.BottomFeatureCurve, new Point[] { sil0Bot, sil1Bot });

            if (annotated.Contains(snappedPrimitive.TopFeatureCurve))
            {
                topFit = Enumerable.Empty <Term>();
            }
            if (annotated.Contains(snappedPrimitive.BottomFeatureCurve))
            {
                botFit = Enumerable.Empty <Term>();
            }

            var objective   = TermUtils.SafeSum(topFit.Concat(botFit));
            var constraints = new Term[] { snappedPrimitive.Axis.NormSquared - 1 };

            return(Tuple.Create(objective, constraints));
        }
        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,
            });
        }
Beispiel #3
0
        private Tuple <Term, Term[]> TwoSilhouettesSingleFeature(TSnapped snappedPrimitive, ISet <FeatureCurve> annotated)
        {
            var sil0   = SegmentApproximator.ApproximateSegment(snappedPrimitive.LeftSilhouette.Points);
            var sil1   = SegmentApproximator.ApproximateSegment(snappedPrimitive.RightSilhouette.Points);
            var axis2d = Get2DVector(snappedPrimitive.AxisResult);

            var isTopSnapped    = snappedPrimitive.TopFeatureCurve.SnappedTo != null;
            var isBottomSnapped = snappedPrimitive.BottomFeatureCurve.SnappedTo != null;

            var snappedFeatureCurve   = isTopSnapped ? snappedPrimitive.TopFeatureCurve : snappedPrimitive.BottomFeatureCurve;
            var unsnappedFeatureCurve = isTopSnapped ? snappedPrimitive.BottomFeatureCurve : snappedPrimitive.TopFeatureCurve;

            var sil0Top = GetForwardPoint(sil0, axis2d);
            var sil0Bot = GetForwardPoint(sil0, -axis2d);
            var sil1Top = GetForwardPoint(sil1, axis2d);
            var sil1Bot = GetForwardPoint(sil1, -axis2d);

            var sil0Far = isTopSnapped ? sil0Bot : sil0Top;
            var sil1Far = isTopSnapped ? sil1Bot : sil1Top;

            var featureProj = ProjectionFit.Compute(snappedFeatureCurve);
            var farProj     = Enumerable.Repeat(EndpointsProjectionFit(unsnappedFeatureCurve, sil0Far, sil1Far), 1);

            var objective   = TermUtils.SafeSum(new Term[] { TermUtils.SafeAvg(featureProj), TermUtils.SafeAvg(farProj) });
            var constraints = new Term[] { snappedPrimitive.Axis.NormSquared - 1 };

            return(Tuple.Create(objective, constraints));
        }
Beispiel #4
0
        private Term FeaturesTerm(IEnumerable <CircleFeatureCurve> iEnumerable)
        {
            var terms =
                from item in iEnumerable
                from term in ProjectionFit.Compute(item)
                select term;

            var objective = TermUtils.SafeAvg(terms);

            return(objective);
        }
Beispiel #5
0
        private Tuple <Term, Term[]> FullInfo(TSnapped snappedPrimitive)
        {
            var terms =
                from item in snappedPrimitive.FeatureCurves.Cast <CircleFeatureCurve>()
                from term in ProjectionFit.Compute(item)
                select term;

            var objective   = TermUtils.SafeAvg(terms);
            var constraints = new Term[] { snappedPrimitive.Axis.NormSquared - 1 };

            return(Tuple.Create(objective, constraints));
        }
Beispiel #6
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));
        }
Beispiel #7
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
            }
        }
        public static Term DiffSquared(TVec[] left, TVec[] right)
        {
            Contract.Requires(left != null);
            Contract.Requires(right != null);
            Contract.Requires(left.Length == right.Length);
            Contract.Requires(Contract.ForAll(left, item => item != null));
            Contract.Requires(Contract.ForAll(right, item => item != null));
            Contract.Requires(Contract.ForAll(0, left.Length, i => left[i].Dimension == right[i].Dimension));

            var leftFlat  = left.SelectMany(x => x.GetTerms()).ToArray();
            var rightFlat = right.SelectMany(x => x.GetTerms()).ToArray();

            return(TermUtils.DiffSquared(leftFlat, rightFlat));
        }
        /// <summary>
        /// Parallelism measure of planes represented by three point triples.
        /// </summary>
        /// <param name="left">Three points to represent the first plane</param>
        /// <param name="right">Three points to represent the second plane.</param>
        /// <returns>A term measuring parallelism of the two planes.</returns>
        public static Term PlaneParallelism3D(TVec[] left, TVec[] right)
        {
            Contract.Requires(left != null);
            Contract.Requires(right != null);
            Contract.Requires(left.Length == 3);
            Contract.Requires(right.Length == 3);
            Contract.Requires(Contract.ForAll(left, item => item != null));
            Contract.Requires(Contract.ForAll(right, item => item != null));
            Contract.Requires(Contract.ForAll(left, item => item.Dimension == 3));
            Contract.Requires(Contract.ForAll(right, item => item.Dimension == 3));

            var leftNormal  = TermUtils.Normal3D(left[0], left[1], left[2]);
            var rightNormal = TermUtils.Normal3D(right[0], right[1], right[2]);

            return(VectorParallelism3D(leftNormal, rightNormal));
        }
Beispiel #10
0
        private Tuple <Term, Term[]> TwoSilhouettesSingleFeature(TSnapped snappedPrimitive, ISet <FeatureCurve> annotated)
        {
            var sil0 = SegmentApproximator.ApproximateSegment(snappedPrimitive.LeftSilhouette.Points);
            var sil1 = SegmentApproximator.ApproximateSegment(snappedPrimitive.RightSilhouette.Points);

            var snappedFeatureCurve   = snappedPrimitive.TopCurve == null ? snappedPrimitive.BottomFeatureCurve : snappedPrimitive.TopFeatureCurve;
            var unsnappedFeatureCurve = snappedPrimitive.TopCurve == null ? snappedPrimitive.TopFeatureCurve : snappedPrimitive.BottomFeatureCurve;

            var sil0Far = GetFarPoint(sil0, snappedFeatureCurve.SnappedTo);
            var sil1Far = GetFarPoint(sil1, snappedFeatureCurve.SnappedTo);

            var featureProj = ProjectionFit(snappedFeatureCurve);
            var farProj     = ProjectionFit(unsnappedFeatureCurve, new Point[] { sil0Far, sil1Far });

            if (annotated.Contains(unsnappedFeatureCurve))
            {
                farProj = Enumerable.Empty <Term>();
            }

            var objective   = TermUtils.SafeSum(featureProj.Concat(farProj));
            var constraints = new Term[] { snappedPrimitive.Axis.NormSquared - 1 };

            return(Tuple.Create(objective, constraints));
        }
Beispiel #11
0
        private void OptimizeAll()
        {
            #region Write all variables and their current values to a vector

            var variablesWriter   = new VariableVectorsWriter();
            var startVectorWriter = new VectorsWriter();

            // write cylinders
            foreach (var snappedCylinder in sessionData.SnappedPrimitives.OfType <SnappedCylinder>())
            {
                variablesWriter.Write(snappedCylinder);
                startVectorWriter.Write(snappedCylinder);
            }

            // write cones
            foreach (var snappedCone in sessionData.SnappedPrimitives.OfType <SnappedCone>())
            {
                variablesWriter.Write(snappedCone);
                startVectorWriter.Write(snappedCone);
            }

            #endregion

            // all objective functions. Will be summed eventually to form one big objective.
            var objectives = new List <Term>();

            // all equality constraints.
            var constraints = new List <Term>();

            var curvesToAnnotations = new Dictionary <FeatureCurve, ISet <Annotation> >();

            #region Get mapping of curves to annotations

            foreach (var fc in sessionData.FeatureCurves)
            {
                curvesToAnnotations[fc] = new HashSet <Annotation>();
            }

            foreach (var annotation in sessionData.Annotations)
            {
                IEnumerable <FeatureCurve> curves = null;
                annotation.MatchClass <Parallelism>(pa => curves  = pa.Elements);
                annotation.MatchClass <Coplanarity>(ca => curves  = ca.Elements);
                annotation.MatchClass <Cocentrality>(ca => curves = ca.Elements);
                Debug.Assert(curves != null);
                foreach (var fc in curves)
                {
                    curvesToAnnotations[fc].Add(annotation);
                }
            }

            #endregion

            #region get objectives and constraints for primitives

            foreach (var snappedPrimitive in sessionData.SnappedPrimitives)
            {
                var objectiveAndConstraints = snappersManager.Reconstruct(snappedPrimitive, curvesToAnnotations);
                objectives.Add(objectiveAndConstraints.Item1);
                constraints.AddRange(objectiveAndConstraints.Item2);
            }

            #endregion

            #region get constraints for annotations

            foreach (var annotation in sessionData.Annotations)
            {
                var constraintTerms = GetAnnotationConstraints(annotation);
                constraints.AddRange(constraintTerms);
            }

            #endregion

            #region perform optimization

            var finalObjective = TermUtils.SafeSum(objectives);
            var vars           = variablesWriter.ToArray();
            var vals           = startVectorWriter.ToArray();

            var optimum = Optimizer.MinAugmentedLagrangian(finalObjective, constraints.ToArray(), vars, vals, mu: 10, tolerance: 1E-5);

            #endregion

            #region read data back from the optimized vector

            var resultReader = new VectorsReader(optimum);
            foreach (var snappedCylinder in sessionData.SnappedPrimitives.OfType <SnappedCylinder>())
            {
                resultReader.Read(snappedCylinder);
            }

            foreach (var snappedCone in sessionData.SnappedPrimitives.OfType <SnappedCone>())
            {
                resultReader.Read(snappedCone);
            }

            #endregion

            #region Update feature curves

            foreach (var snappedPrimitive in sessionData.SnappedPrimitives)
            {
                snappedPrimitive.UpdateFeatureCurves();
            }

            #endregion
        }
Beispiel #12
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()));
        }