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, }); }
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)); }
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); }
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)); }
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)); }
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)); }
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)); }
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 }
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())); }