代码之家  ›  专栏  ›  技术社区  ›  user2943193

使用CubicTo绘制Bezier曲线

  •  1
  • user2943193  · 技术社区  · 12 年前

    以下代码生成Bezier曲线并创建要在画布上绘制的Path对象。 我转换了 this code 从C#.Net到Android。

    问题: 当我画这些点时,这些点不会形成一条连续的曲线。它在中间断裂,然后继续。我认为问题在于 AddBeziers ,我用过的地方 cubicTo 生成曲线。可能与不匹配 GraphicsPath.AddBeziers .Net中的方法。

    如何解决此问题?

    生成的点

    • x坐标-[0,55,-44,-54,-44、55,0]
    • y坐标-[0,-189,-20,-125,-230,-59,-250]

    这是必须在画布上绘制的图形。

    Path figure = new Path();
    BezierCurve verticalCurvex = BezierCurve.CreateVertical(250);
    verticalCurvex.FlipVertical();                  
    verticalCurvex.FlipHorizontal();
    AddBeziers(figure, verticalCurvex.Points);
    

    Android的AddBezier方法

    private Path AddBeziers(Path path, Point[] points) {
    
            int index = 1;
            if (points.length > 3) {
                path.moveTo(points[0].X, points[0].Y);
                path.cubicTo(points[index].X, points[index].Y, points[index + 1].X,
                        points[index + 1].Y, points[index + 2].X,
                        points[index + 2].Y);
            }
    
            index = index + 3;
            if (points.length > 5) {
                path.cubicTo(points[index].X, points[index].Y, points[index + 1].X,
                        points[index + 1].Y, points[index + 2].X,
                        points[index + 2].Y);
            }
    
            return path;
        }
    

    android的Bezier曲线类

    package com.example.newone;
    
    public class BezierCurve {
    
        // NOTE : A point's x and y positions are measured from bottom-left corner of the piece.
        // X~RATIO  =     point's x position / piece's width
        // Y~RATIO  =     point's y position / piece's height
        private static final double X2RATIO = 0.760869565217391;
        private static final double Y2RATIO = 0.183946488294314;
    
        private static final double X3RATIO = 0.0802675585284281;
        private static final double Y3RATIO = 0.150501672240803;
    
        private static final double X4RATIO = 0.5;
        private static final double Y4RATIO = Y2RATIO;
    
        private static final double X6RATIO = X2RATIO;
        private static final double Y6RATIO = Y2RATIO;
    
        private static final double X5RATIO = X3RATIO;
        private static final double Y5RATIO = Y3RATIO;
    
        private static final double CURVE_TENSION = 1.2;
    
        public Point[] Points ;
    
        public static BezierCurve CreateHorizontal(int length)
        {
            double curvature = length * CURVE_TENSION;
    
            int x1, y1;     // First curve's starting point
            int x2, y2;     // First curve's first control point
            int x3, y3;     // First curve's second control point
            int x4, y4;     // First curve's ending point, second curve's starting point
            int x5, y5;     // Second curve's first control point
            int x6, y6;     // Second curve's second control point
            int x7, y7;     // Second curve's ending point
    
            // First curve (first curve's ending point is (X4, Y4), which is also second curve's end point      
            x1 = 0;
            y1 = 0;
    
            x2 = x1 + (int)(length * X2RATIO);
            y2 = y1 + (int)(curvature * Y2RATIO);
    
            x3 = x1 + (int)(length * X3RATIO);
            y3 = y1 - (int)(curvature * Y3RATIO);
    
            x4 = x1 + (int)(length * X4RATIO);
            y4 = y1 - (int)(curvature * Y4RATIO);
    
            // Second curve (second curve's ending point is (X4, Y4) )      
            x7 = x1 + length;
            y7 = y1;
    
            x6 = x7 - (int)(length * X6RATIO);
            y6 = y7 + (int)(curvature * Y6RATIO);
    
            x5 = x7 - (int)(length * X5RATIO);
            y5 = y7 - (int)(curvature * Y5RATIO);
    
            BezierCurve curve = new BezierCurve();
    
            curve.Points  = new Point[] 
                {
                    new Point(x1, y1), 
                    new Point(x2, y2),
                    new Point(x3, y3), 
                    new Point(x4, y4),
                    new Point(x5, y5), 
                    new Point(x6, y6),
                    new Point(x7, y7)
                } ;
    
    
            return curve;
        }
    
        public static BezierCurve CreateVertical(int length)
        {
            BezierCurve curve = CreateHorizontal(length);
            curve.Rotate(90);
    
            int offsetX = 0 - curve.Points[0].X;
            int offsetY = 0 - curve.Points[0].Y;
    
            return curve.Translate(offsetX, offsetY);            
        }
    
        public BezierCurve Translate(int transX, int transY)
        {            
            for (int i = 0; i < this.Points.length; i++)
            {
                this.Points[i].X += transX;
                this.Points[i].Y += transY;
            }
    
            return this;
        }
    
        public BezierCurve FlipHorizontal()
        {
            for (int i = 0; i < this.Points.length; i++)
            {
                this.Points[i].X *= -1;                
            }
    
            return this;
        }
    
        public BezierCurve FlipVertical()
        {
            for (int i = 0; i < this.Points.length; i++)
            {
                this.Points[i].Y *= -1;
            }
    
            return this;
        }
    
        // ===============================================
        // Transformation code adapted from C++ source code in the book
        // Direct3D Programming (Kickstart) by Clayton Walnum
        // ===============================================
        public BezierCurve Rotate(int degrees)
        {
            double radians = 6.283185308 / (360 / degrees);
            double cosine = Math.cos(radians);
            double sine = Math.sin(radians);
    
            for (int i = 0; i < this.Points.length; i++)
            {
                int rotatedX = (int)(this.Points[i].X * cosine - this.Points[i].Y * sine);
                int rotatedY = (int)(this.Points[i].Y * cosine + this.Points[i].X * sine);
    
                this.Points[i].X = rotatedX;
                this.Points[i].Y = rotatedY;
            }
    
            return this;
        }
    }
    

    点类别

    package com.example.newone;
    
    public class Point {
    
            public int X;
            public int Y;
    
       public Point(int x , int y)
       {
           X= x;
           Y= y;
       }
    }
    
    1 回复  |  直到 11 年前
        1
  •  3
  •   fang    12 年前

    从有关cubicTo()的Android文档中,

    从最后一个点开始添加一个立方体贝塞尔,接近控制点(x1,y1)和(x2,y2),并在(x3,y3)结束。如果未对此轮廓调用moveTo(),则第一个点将自动设置为(0,0)。

    看起来您只需要在第二次调用path.cubicTo()之前添加对moveTo()的调用。