Come trovare i punti di controllo per una BezierSegment data di Inizio e di Fine, e 2 Intersezione Pts in C# - AKA di Bézier Cubica, con 4 punti di Interpolazione

StackOverflow https://stackoverflow.com/questions/2315432

  •  22-09-2019
  •  | 
  •  

Domanda

Ho lottato cercando modo comprensibile, per fare questo.Ho quattro punti, un StartPt, EndPoint, e i punti di Intersezione di rappresentare il picco e valle di bezier.

Il BezierSegment in C# si richiede, controlPoint 1, controlPoint 2, endpoint, tuttavia non ho punti di controllo ho solo questi due punti che si trovano lungo le curve di bezier (sto chiamando loro punti di intersezione di cui sopra)...come posso calcolare i due punti di controllo?

Grazie in anticipo, questo è stato farmi impazzire.

C'è un qualche tipo di spiegazione qui: http://www.tinaja.com/glib/nubz4pts1.pdf ma è scritto in postscript e che il linguaggio non ha senso per me a tutti - è sopra la mia testa.

È stato utile?

Soluzione

Ci sono un numero infinito di soluzioni per una curva che passa attraverso 4 punti, ma la migliore soluzione semplice è quella di provare a fare la curva lunghezze di segmenti proporzionali alle lunghezze di corda.Il codice si collega a un primo ordine di approssimazione che funziona bene ed è abbastanza veloce.

Ecco il C# traduzione del codice 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;
    }
}

Non ho testato, ma non compila.Basta chiamare DrawingUtility.BezierFromIntersection con 4 punti, e verrà restituito un PathFigure per disegnare la curva.

Altri suggerimenti

Si dovrebbe considerare l'utilizzo di Cardinale (Canonica) Spline, che utilizza un insieme di punti presenti sul percorso, oltre a una "tensione", parametro che controlla come acutamente gli angoli sono smussati per angolo tangenti.

In Windows Form, si potrebbe usare la DrawCurve e DrawClosedCurve i metodi.In WPF non ci sono equivalenti diretti.Qui ci sono due articoli che descrivono che utilizza il cardinale spline in WPF con C#.

Floris - AddCurve Per WPF Cardinale Spline

Petzold - Canonica Spline In WPF E Silverlight

versione 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;
        }
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top