Comment trouver les points de contrôle d'un tronçon de voie donné pts de départ, D'arrivée et de 2 Intersections en C# - alias Cube Bezier Interpolation à 4 points

j'ai eu du mal à trouver une façon compréhensible de faire ça. J'ai quatre points, un StartPt, un EndPoint, et des Points D'Intersection pour représenter le pic et la vallée dans le bezier.

Le BezierSegment en C# nécessite de commencer, controlPoint 1, controlPoint 2, extrémité - cependant je n'ai pas de points de contrôle, je n'ai que ces deux points qui se situent le long des courbes de bézier (je suis en les appelant des points d'intersection ci-dessus)... comment puis-je calculer les deux contrôle les points?

Merci à l'avance, ce qui a été me rend fou.

There is some kind of explanation here: http://www.tinaja.com/glib/nubz4pts1.pdf mais c'est écrit en postscript et ce langage n'a aucun sens pour moi - il est au-dessus de ma tête.

16
demandé sur softwarequestioneer 2010-02-23 03:50:52

4 réponses

il y a un nombre infini de solutions à une courbe passant par 4 points, mais la meilleure solution simple est d'essayer de rendre les longueurs de segment de courbe proportionnelles aux longueurs d'accord. Le code auquel vous faites référence est l'approximation de premier ordre qui fonctionne bien et est assez rapide.

Voici la traduction du code PostScript:

static class DrawingUtility
{
    // linear equation solver utility for ai + bj = c and di + ej = f
    static void solvexy(double a, double b, double c, double d, double e, double f, out double i, out double j)
    {
        j = (c - a / d * f) / (b - a * e / d);
        i = (c - (b * j)) / a;
    }

    // basis functions
    static double b0(double t) { return Math.Pow(1 - t, 3); }
    static double b1(double t) { return t * (1 - t) * (1 - t) * 3; }
    static double b2(double t) { return (1 - t) * t * t * 3; }
    static double b3(double t) { return Math.Pow(t, 3); }

    static void bez4pts1(double x0, double y0, double x4, double y4, double x5, double y5, double x3, double y3, out double x1, out double y1, out double x2, out double y2)
    {
        // find chord lengths
        double c1 = Math.Sqrt((x4 - x0) * (x4 - x0) + (y4 - y0) * (y4 - y0));
        double c2 = Math.Sqrt((x5 - x4) * (x5 - x4) + (y5 - y4) * (y5 - y4));
        double c3 = Math.Sqrt((x3 - x5) * (x3 - x5) + (y3 - y5) * (y3 - y5));
        // guess "best" t
        double t1 = c1 / (c1 + c2 + c3);
        double t2 = (c1 + c2) / (c1 + c2 + c3);
        // transform x1 and x2
        solvexy(b1(t1), b2(t1), x4 - (x0 * b0(t1)) - (x3 * b3(t1)), b1(t2), b2(t2), x5 - (x0 * b0(t2)) - (x3 * b3(t2)), out x1, out x2);
        // transform y1 and y2
        solvexy(b1(t1), b2(t1), y4 - (y0 * b0(t1)) - (y3 * b3(t1)), b1(t2), b2(t2), y5 - (y0 * b0(t2)) - (y3 * b3(t2)), out y1, out y2);
    }

    static public PathFigure BezierFromIntersection(Point startPt, Point int1, Point int2, Point endPt)
    {
        double x1, y1, x2, y2;
        bez4pts1(startPt.X, startPt.Y, int1.X, int1.Y, int2.X, int2.Y, endPt.X, endPt.Y, out x1, out y1, out x2, out y2);
        PathFigure p = new PathFigure { StartPoint = startPt };
        p.Segments.Add(new BezierSegment { Point1 = new Point(x1, y1), Point2 = new Point(x2, y2), Point3 = endPt } );
        return p;
    }
}

Je ne l'ai pas testé, mais il se compile. Appelez simplement DrawingUtility.BezierFromIntersection avec les 4 points que vous avez, et il sera de retour une PathFigure pour le dessin de la courbe.

16
répondu Gabe 2010-02-23 07:46:38

voici deux bons exemples:

http://www.codeproject.com/KB/graphics/ClosedBezierSpline.aspx http://www.codeproject.com/KB/graphics/BezierSpline.aspx

Voir Aussi cette animation pour mieux comprendre comment fonctionnent les machines BezierSplines http://en.wikipedia.org/wiki/B%C3%A9zier_curve

1
répondu thomas nn 2010-04-21 12:16:21

vous devriez envisager D'utiliser des cannelures cardinales (canoniques), qui utilisent un ensemble de points qui existent sur le chemin, plus un paramètre "tension" qui contrôle la netteté des coins lissés aux tangentes de coin.

dans les formes Windows, on utiliserait le DrawCurve et DrawClosedCurve méthodes. Il n'y a pas d'équivalent direct au FPF. Voici deux articles qui décrivent l'utilisation du cardinal splines dans WPF avec C#.

Floris-AddCurve pour WPF Cardinal Spline!--10-->

Petzold - Canonique Splines En WPF Et Silverlight

1
répondu dapi 2011-07-03 06:30:30

version as3:

package 
{
    import flash.geom.Vector3D;

    public class DrawingUtility 
    {
        private var x1:Number; 
        private var y1:Number; 
        private var x2:Number;
        private var y2:Number;

        // linear equation solver utility for ai + bj = c and di + ej = f
        private function solvexy(a:Number, b:Number, c:Number, d:Number, e:Number, f:Number):Vector.<Number>
        {
            var returnVal:Vector.<Number> = new Vector.<Number>();
            var j:Number = (c - a / d * f) / (b - a * e / d);
            var i:Number = (c - (b * j)) / a;
            returnVal[0] = i;
            returnVal[1] = j;
            return returnVal;
        }

        // basis functions
        private function b0(t:Number):Number { 
            return Math.pow(1 - t, 3);
        }
        private function b1(t:Number):Number {
            return t * (1 - t) * (1 - t) * 3;
        }
        private function b2(t:Number):Number {
            return (1 - t) * t * t * 3;
        }
        private function b3(t:Number):Number {
            return Math.pow(t, 3);
        }

        private function bez4pts1(x0:Number, y0:Number, x4:Number, y4:Number, x5:Number, y5:Number, x3:Number, y3:Number):void
        {
            // find chord lengths
            var c1:Number = Math.sqrt((x4 - x0) * (x4 - x0) + (y4 - y0) * (y4 - y0));
            var c2:Number = Math.sqrt((x5 - x4) * (x5 - x4) + (y5 - y4) * (y5 - y4));
            var c3:Number = Math.sqrt((x3 - x5) * (x3 - x5) + (y3 - y5) * (y3 - y5));
            // guess "best" t
            var t1:Number = c1 / (c1 + c2 + c3);
            var t2:Number = (c1 + c2) / (c1 + c2 + c3);
            // transform x1 and x2
            var x1x2:Vector.<Number> = solvexy(b1(t1), b2(t1), x4 - (x0 * b0(t1)) - (x3 * b3(t1)), b1(t2), b2(t2), x5 - (x0 * b0(t2)) - (x3 * b3(t2)));
            x1 = x1x2[0];
            x2 = x1x2[1];
            // transform y1 and y2
            var y1y2:Vector.<Number> = solvexy(b1(t1), b2(t1), y4 - (y0 * b0(t1)) - (y3 * b3(t1)), b1(t2), b2(t2), y5 - (y0 * b0(t2)) - (y3 * b3(t2)));
            y1 = y1y2[0];
            y2 = y1y2[1];
        }

        public function BezierFromIntersection(startPt:Vector3D, int1:Vector3D, int2:Vector3D, endPt:Vector3D):Vector.<Vector3D>
        {
            var returnVec:Vector.<Vector3D> = new Vector.<Vector3D>();
            bez4pts1(startPt.x, startPt.y, int1.x, int1.y, int2.x, int2.y, endPt.x, endPt.y);

            returnVec.push(startPt);
            returnVec.push(new Vector3D(x1, y1));
            returnVec.push(new Vector3D(x2, y2));
            returnVec.push(endPt);
            return returnVec;
        }
    }
}
0
répondu user2630051 2013-07-29 11:10:09