Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/actionscript-3/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Apache flex 如何一次从3个给定点绘制连续曲线_Apache Flex_Actionscript 3_Bezier_Continuous_Spline - Fatal编程技术网

Apache flex 如何一次从3个给定点绘制连续曲线

Apache flex 如何一次从3个给定点绘制连续曲线,apache-flex,actionscript-3,bezier,continuous,spline,Apache Flex,Actionscript 3,Bezier,Continuous,Spline,我试图用闪光灯画一条连续的曲线。有很多方法,但到目前为止,我发现没有一种方法完全符合我的要求。首先,我想使用flash graphic api的curveTo()方法。我不想。根据我的经验和理解,线段需要大量处理器。闪存的二次贝塞尔曲线应该占用更少的CPU电源。如果你认为我错了,请挑战这个假设 我也不想使用将整行作为参数的预制方法(例如mx.charts.ChartClass.GraphicsUtilities.drawPolyline())。 原因是,我最终需要修改逻辑,以便为我正在绘制的线条

我试图用闪光灯画一条连续的曲线。有很多方法,但到目前为止,我发现没有一种方法完全符合我的要求。首先,我想使用flash graphic api的curveTo()方法。我不想。根据我的经验和理解,线段需要大量处理器。闪存的二次贝塞尔曲线应该占用更少的CPU电源。如果你认为我错了,请挑战这个假设

我也不想使用将整行作为参数的预制方法(例如mx.charts.ChartClass.GraphicsUtilities.drawPolyline())。 原因是,我最终需要修改逻辑,以便为我正在绘制的线条添加装饰,因此我需要一些我在最低层次上理解的东西

我目前创建了一个方法,可以在给定3个点的情况下绘制曲线

这是一张照片:

问题是这些线实际上并没有通过线的“真实”点(灰色圆)弯曲。有没有一种方法可以利用数学的力量来调整控制点,使曲线实际通过“真实”点?仅将当前点及其上/下一点作为参数?下面是复制上述图片的代码。如果我能修改它以满足这个要求,那就太好了(注意第一点和最后一点的例外)

包{
导入flash.display.Shape;
导入flash.display.Sprite;
导入flash.display.Stage;
导入flash.geom.Point;
[SWF(width=“200”,height=“200”)]
公共类TestCurves扩展了Sprite{
公共函数TestCurves(){
stage.scaleMode=“noScale”;
变量点:数组=[
新观点(10,10),
新点(80,80),
新点(80160),
新观点(20160),
新点(20200),
新点(200100)
];
图形。线条样式(2,0xFF0000);
变量点:点=点[0];
var nextPoint:Point=points[1];
样条线方法。绘制样条线(图形、点、空、下一点);
var prevPoint:点=点;
变量n:int=points.length;
变量i:int;
对于(i=2;i

稍后,我将向draw方法添加箭头和其他内容。

我想您正在寻找Catmull Rom样条线。我已经为您搜索了一个AS3实现,但还没有尝试过,所以请自行决定使用:


好的,Catmull-Rom样条线建议很好,但并不完全是我想要的。 提供的链接中的示例是一个很好的起点,但有点不灵活。我已经使用了它,并修改了我的原始源代码以使用它。我将此作为一个答案发布,因为我认为它比Zevan的博客文章(无意冒犯Zevan!)更模块化,更容易理解。以下代码将显示以下图像:

代码如下:

    package {
        import flash.display.Shape;
        import flash.display.Sprite;
        import flash.display.Stage;
        import flash.geom.Point;

        [SWF(width="300",height="300")]
        public class TestCurves extends Sprite {
            public function TestCurves() {
                stage.scaleMode = "noScale";

                //draw a helpful grid
                graphics.lineStyle(1, 0xC0C0C0, 0.5);
                for (var x:int = 0; x <= 300; x += 10) {
                    graphics.moveTo(x, 0);
                    graphics.lineTo(x, 300);
                    graphics.moveTo(0, x);
                    graphics.lineTo(300, x);
                }

                var points:Array = [
                    new Point(40, 20), 
                    new Point(120, 80), 
                    new Point(120, 160), 
                    new Point(60, 160), 
                    new Point(60, 200), 
                    new Point(240, 150), 
                    new Point(230, 220), 
                    new Point(230, 280)
                ];

                SplineMethod.setResolution(5);

                graphics.lineStyle(2, 0xF00000);
                graphics.moveTo(points[0].x, points[0].y);

                var n:int = points.length;
                var i:int;

                for (i = 0; i < n - 1; i++) {
                    SplineMethod.drawSpline(
                        graphics, 
                        points[i], //segment start
                        points[i + 1], //segment end
                        points[i - 1], //previous point (may be null)
                        points[i + 2] //next point (may be null)
                    );
                }

                //straight lines and vertices for comparison
                graphics.lineStyle(2, 0x808080, 0.5);
                graphics.drawCircle(points[0].x, points[0].y, 4);
                for (i = 1; i < n; i++) {
                    graphics.moveTo(points[i - 1].x, points[i - 1].y);
                    graphics.lineTo(points[i].x, points[i].y);
                    graphics.drawCircle(points[i].x, points[i].y, 4);
                }
            }
        }
    }
    import flash.display.Graphics;
    import flash.geom.Point;

    internal class SplineMethod {

        //default setting will just draw a straight line
        private static var hermiteValues:Array = [0, 0, 1, 0];

        public static function setResolution(value:int):void {
            var resolution:Number = 1 / value;
            hermiteValues = [];
            for (var t:Number = resolution; t <= 1; t += resolution) {
                var h00:Number = (1 + 2 * t) * (1 - t) * (1 - t);
                var h10:Number = t  * (1 - t) * (1 - t);
                var h01:Number = t * t * (3 - 2 * t);
                var h11:Number = t * t * (t - 1);
                hermiteValues.push(h00, h10, h01, h11);
            }
        }

        public static function drawSpline(target:Graphics, segmentStart:Point, segmentEnd:Point, prevSegmentEnd:Point=null, nextSegmentStart:Point=null):void {
            if (!prevSegmentEnd) {
                prevSegmentEnd = segmentStart;
            }
            if (!nextSegmentStart) {
                nextSegmentStart = segmentEnd;
            }

            var m1:Point = new Point((segmentEnd.x - prevSegmentEnd.x) / 2, (segmentEnd.y - prevSegmentEnd.y) / 2);
            var m2:Point = new Point((nextSegmentStart.x - segmentStart.x) / 2, (nextSegmentStart.y - segmentStart.y) / 2);

            var n:int = hermiteValues.length;
            for (var i:int = 0; i < n; i += 4) {
                var h00:Number = hermiteValues[i];
                var h10:Number = hermiteValues[i + 1];
                var h01:Number = hermiteValues[i + 2];
                var h11:Number = hermiteValues[i + 3];

                var px:Number = h00 * segmentStart.x + h10 * m1.x + h01 * segmentEnd.x + h11 * m2.x;
                var py:Number = h00 * segmentStart.y + h10 * m1.y + h01 * segmentEnd.y + h11 * m2.y;

                target.lineTo(px, py);
            }
        }
    }
包{
导入flash.display.Shape;
导入flash.display.Sprite;
导入flash.display.Stage;
导入flash.geom.Point;
[SWF(width=“300”,height=“300”)]
公共类TestCurves扩展了Sprite{
公共函数TestCurves(){
stage.scaleMode=“noScale”;
//画一个有用的网格
图形.线条样式(1,0xC0,0.5);

对于(var x:int=0;x我编写了这个代码,我认为它可能会有帮助:

主权财富基金:

代码:

我在代码上留下了很多评论。我希望它能有所帮助

以下是代码背后的理论:

    package {
        import flash.display.Shape;
        import flash.display.Sprite;
        import flash.display.Stage;
        import flash.geom.Point;

        [SWF(width="300",height="300")]
        public class TestCurves extends Sprite {
            public function TestCurves() {
                stage.scaleMode = "noScale";

                //draw a helpful grid
                graphics.lineStyle(1, 0xC0C0C0, 0.5);
                for (var x:int = 0; x <= 300; x += 10) {
                    graphics.moveTo(x, 0);
                    graphics.lineTo(x, 300);
                    graphics.moveTo(0, x);
                    graphics.lineTo(300, x);
                }

                var points:Array = [
                    new Point(40, 20), 
                    new Point(120, 80), 
                    new Point(120, 160), 
                    new Point(60, 160), 
                    new Point(60, 200), 
                    new Point(240, 150), 
                    new Point(230, 220), 
                    new Point(230, 280)
                ];

                SplineMethod.setResolution(5);

                graphics.lineStyle(2, 0xF00000);
                graphics.moveTo(points[0].x, points[0].y);

                var n:int = points.length;
                var i:int;

                for (i = 0; i < n - 1; i++) {
                    SplineMethod.drawSpline(
                        graphics, 
                        points[i], //segment start
                        points[i + 1], //segment end
                        points[i - 1], //previous point (may be null)
                        points[i + 2] //next point (may be null)
                    );
                }

                //straight lines and vertices for comparison
                graphics.lineStyle(2, 0x808080, 0.5);
                graphics.drawCircle(points[0].x, points[0].y, 4);
                for (i = 1; i < n; i++) {
                    graphics.moveTo(points[i - 1].x, points[i - 1].y);
                    graphics.lineTo(points[i].x, points[i].y);
                    graphics.drawCircle(points[i].x, points[i].y, 4);
                }
            }
        }
    }
    import flash.display.Graphics;
    import flash.geom.Point;

    internal class SplineMethod {

        //default setting will just draw a straight line
        private static var hermiteValues:Array = [0, 0, 1, 0];

        public static function setResolution(value:int):void {
            var resolution:Number = 1 / value;
            hermiteValues = [];
            for (var t:Number = resolution; t <= 1; t += resolution) {
                var h00:Number = (1 + 2 * t) * (1 - t) * (1 - t);
                var h10:Number = t  * (1 - t) * (1 - t);
                var h01:Number = t * t * (3 - 2 * t);
                var h11:Number = t * t * (t - 1);
                hermiteValues.push(h00, h10, h01, h11);
            }
        }

        public static function drawSpline(target:Graphics, segmentStart:Point, segmentEnd:Point, prevSegmentEnd:Point=null, nextSegmentStart:Point=null):void {
            if (!prevSegmentEnd) {
                prevSegmentEnd = segmentStart;
            }
            if (!nextSegmentStart) {
                nextSegmentStart = segmentEnd;
            }

            var m1:Point = new Point((segmentEnd.x - prevSegmentEnd.x) / 2, (segmentEnd.y - prevSegmentEnd.y) / 2);
            var m2:Point = new Point((nextSegmentStart.x - segmentStart.x) / 2, (nextSegmentStart.y - segmentStart.y) / 2);

            var n:int = hermiteValues.length;
            for (var i:int = 0; i < n; i += 4) {
                var h00:Number = hermiteValues[i];
                var h10:Number = hermiteValues[i + 1];
                var h01:Number = hermiteValues[i + 2];
                var h11:Number = hermiteValues[i + 3];

                var px:Number = h00 * segmentStart.x + h10 * m1.x + h01 * segmentEnd.x + h11 * m2.x;
                var py:Number = h00 * segmentStart.y + h10 * m1.y + h01 * segmentEnd.y + h11 * m2.y;

                target.lineTo(px, py);
            }
        }
    }

A和C是第一个和最后一个点,B是AS3中的“控制点”。您可以这样绘制曲线:

graphics.moveTo(A.x, A.y);
graphics.curveTo(B.x, B.y, C.x, C.y);
现在,D是向量AC的中点,DB的中点是曲线的中点。现在我在代码中做的是将B精确移动到D+DB*2,所以,如果你用该点作为控制点绘制曲线,曲线的中点将是B


PS:对不起,我的英语不好

好的,为了得到想要的效果,看起来我在任何给定的时间都可能需要至少4分来使用我的画法。对吗