• flash:二次贝塞尔曲线应用生成飞机路径示意图


    本周听到公司其它项目组同事在讨论一个小需求:

    给定3个点(其实是飞机经过的航站,比如:从浦东-西安-北京),在UI上生成一段曲线,用来示意飞机的路线图(其实用直线我觉得也能将就,反正只是示意,只是大家觉得直线太out,不美观),晚上无事,尝试了一下:
    有二个方案:
    1、椭圆(很快被自己给否定了,椭圆的标准方程 (x-m)^2/(a^2) + (y-n)^2/(b^2)=1,有m,n,a,b 四个未知数,3个点无法唯一确定,如果把圆心定在页面中心,理论上可以解决,但是开平方也是比较繁琐的)
    2、贝塞尔曲线

    根据:(贝塞尔曲线)喂鸡百科的解释:
    二次标准方程为:

    正好以前在学习flash时也研究过,所以决定用它了。解决了曲线的生成问题,还有飞机的朝向问题,飞机头是有方向的,必须符合曲线的前进方向,这个可用“曲线导数的几何意义”搞定:曲线某点的导数,正好为该点切线的斜率(换个角度考虑,其实就是飞机图标的旋转角度)

    捣鼓一阵后,代码出来了:

    先定义一个飞机的实体类(为方便,暂时用小三角形代替)

    package  
    {
    	import flash.display.Shape;
    	/**
    	 * 飞机实体类
    	 * @author jimmy.yang
    	 */
    	public class Plane extends Shape
    	{
    		
    		public function Plane() 
    		{
    			//用一个小三角来模拟飞机
    			graphics.lineStyle(1, 0xff0000, 1);			
    			graphics.beginFill(0xff0000, 1);
    			graphics.moveTo( -50, -25);
    			graphics.lineTo(50, 0);
    			graphics.lineTo( -50, 25);
    			graphics.lineTo( -50, -25);
    			graphics.endFill();		
    		}
    		
    		public function setAngle(y:Number,x:Number) {
    			this.rotation = Math.atan2(y,x) * 180 / Math.PI;
    		}
    		
    	}
    
    }
    

     下面是生成曲线及调整飞机头朝向的代码:

    package 
    {
    	import flash.display.Sprite;
    	import flash.events.Event;
    	import flash.events.MouseEvent;
    	import flash.text.TextField;
    
    	/**
    	 * 二次贝兹曲线,生成飞机路线图
    	 * @author jimmy.yang (yjmyzz@126.com 菩提树下的杨过 http://yjmyzz.cnblogs.com/)
    	 */
    	[Frame(factoryClass="Preloader")]
    	public class Main extends Sprite 
    	{		
    		
    		public function Main():void 
    		{
    			if (stage) init();
    			else addEventListener(Event.ADDED_TO_STAGE, init);
    		}
    
    		private function init(e:Event = null):void 
    		{
    			removeEventListener(Event.ADDED_TO_STAGE, init);		
    			testBzCurve();
    		}
    		
    		private function testBzCurve():void {
    			
    			var txtP0:TextField = new TextField();
    			var txtP1:TextField = new TextField();
    			var txtP3:TextField = new TextField();
    			addChild(txtP0);
    			addChild(txtP1);
    			addChild(txtP3);
    		
    			var p0X:int = 100;
    			var p0Y:int = 300;
    			
    			txtP0.x = p0X-10;
    			txtP0.y = p0Y+10;
    			txtP0.text = "浦东(PVG)";
    			
    			var p1X:int = 300;
    			var p1Y:int = 250;
    			txtP1.x = p1X;
    			txtP1.y = p1Y+20;
    			txtP1.text = "西安(XIY)";
    			
    			var p2X:int = 500;
    			var p2Y:int = 50;
    			txtP3.x = p2X+5;
    			txtP3.y = p2Y;
    			txtP3.text = "北京(PEK)";
    			
    			
    			//人为抬高控制点,以便让曲线经过控制点
    			p1X = p1X * 2 - (p0X + p2X) / 2;
    			p1Y = p1Y * 2 - (p1Y + p2Y) / 2;
    				
    			//生成10个示例点
    			for (var t:Number = 0; t <=1; t+=0.1) 
    			{		
    				//二次Bz曲线的公式
    				var x:Number = (1 - t) * (1 - t) * p0X + 2 * t * (1 - t) * p1X + t * t * p2X;
    				var y:Number = (1 - t) * (1 - t) * p0Y + 2 * t * (1 - t) * p1Y + t * t * p2Y;				
    				
    				
    				
    				//Bz曲线在t点时的导数坐标
    				var Fx:Number = 2 * (t - 1) * p0X + 2 * (1 - 2 * t) * p1X + 2 * t * p2X;
    				var Fy:Number = 2 * (t - 1) * p0Y + 2 * (1 - 2 * t) * p1Y + 2 * t * t * p2Y;
    				
    				
    				//放入小飞机
    				var p = new Plane();
    				addChild(p);
    				p.x = x;
    				p.y = y;
    				p.scaleX = 0.2;
    				p.scaleY = 0.2;
    				p.setAngle(Fy, Fx);//导数的几何意义
    				
    				
    				
    			}
    			
    			//画出Bz曲线(当背景用)
    			graphics.lineStyle(1, 0x000000, 0.5);
    			graphics.moveTo(p0X, p0Y);
    			graphics.curveTo(p1X, p1Y, p2X, p2Y);
    			
    			
    		}
    		
    		
    
    	}
    
    }
    

     无图无真相:

    感慨:数学真心有用!

  • 相关阅读:
    【AtCoder Regular Contest 080E】Young Maids [堆][线段树]
    【AtCoder Grand Contest 007E】Shik and Travel [Dfs][二分答案]
    【Codeforces858F】Wizard's Tour [构造]
    【AtCoder Grand Contest 001F】Wide Swap [线段树][拓扑]
    【AtCoder Grand Contest 012C】Tautonym Puzzle [构造]
    【Foreign】动态规划 [分治][DP]
    【BZOJ2683】简单题 [分治][树状数组]
    【BZOJ4237】稻草人 [分治][单调栈]
    【BZOJ3745】Norma [分治]
    【BZOJ4552】【HEOI2016】排序 [二分答案][线段树]
  • 原文地址:https://www.cnblogs.com/yjmyzz/p/2786282.html
Copyright © 2020-2023  润新知