예제 #1
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));
        }
예제 #2
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));
        }
예제 #3
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);
        }
예제 #4
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));
        }
예제 #5
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
            }
        }
예제 #6
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()));
        }