×
文章路径: Java > 算法

计算某点围绕目标点旋转一定角度后的新坐标

发表于3年前(Dec 24, 2014 9:37:28 AM)  阅读 1765  评论 0

分类: Java Flex 算法

标签: flex 算法 Java ratation 旋转

这可以说是一道数学题,我讲一下我碰到这个题目的背景。

如上图所示,A可以看成我们的显示器屏幕,向右为x正方向,向下为y正方向,屏幕中有一个矩形B,他是屏幕A的子,D点为B在屏幕A中的坐标,C点为矩形B中的一点。现在对矩形B进行旋转,如旋转90度,那C点坐标为多少呢?

其实如果C点是属于矩形B的话,旋转B时,C点会自动进行旋转,C点相对D点的坐标是不变的,并不需要我们额外处理,当如果C点不是属于B,但旋转B时,又要保持C相对B的位置不变呢?其实这里就是求C点相对D点旋转一定角度后的新坐标,一直D点坐标,C点坐标(全局坐标),求C点绕D点旋转任意角度后的新坐标。

我的思路是,先计算围绕原点旋转的情形,先出A点与X轴正方向的夹角α,然后旋转β到B点,他离X轴正方向的角度为θ,由此我们根据圆的三角方程,x=r*cosθ,y=r*sinθ,可以算出B点坐标。绕原点的算出来了,绕目标点的很简单,我们先将坐标系平移到与要绕的目标点重合,旋转完后再平移回来就行了。

其实这个方法有些语言是支持的,我曾经做SVG图形的时候,就用过其自带的旋转方法,有些就不支持,如flex。所以我将这个方法写成了一个flex工具类,后又翻译成了java,相信以后还是有场景能用上的。

flex:

package mxml.com.gdtopway.util
{
	import flash.geom.Point;

	public class RotationUtil
	{
		public function RotationUtil()
		{
		}

		/**
		 * @param target 围绕旋转的目标点
	 	 * @param source 要旋转的点
	 	 * @param degree 要旋转的角度
		 */
		public static function rotationPoint(target:Point, source:Point, degree:Number):Point {
			source.x -= target.x;
			source.y -= target.y;
			var alpha:Number = 0;
			var beta:Number = 0;
			var result:Point = new Point();
			var dis:Number = Point.distance(source, new Point(0,0));
			//原点
			if(source.x==0&&source.y==0) {
                                     //return result;   --应该返回target点的坐标,而不是偏移后的坐标(20130217 update)
				return new Point(target.x,target.y);
			} else if(source.x>=0&&source.y>=0) {
				//计算与x正方向的夹角
				alpha = Math.asin(source.y/dis);
				//弧度换算成角度
				alpha = radianToDegree(alpha);
				//第二象限
			} else if(source.x<0&&source.y>=0){
				//计算与x正方向的夹角
				alpha = Math.asin(Math.abs(source.x)/dis);
				alpha = alpha+Math.PI/2;
				//弧度换算成角度
				alpha = radianToDegree(alpha);
				//第三象限
			} else if(source.x<0&&source.y<0) {
				//计算与x正方向的夹角
				alpha = Math.asin(Math.abs(source.y)/dis);
				alpha = alpha+Math.PI;
				//弧度换算成角度
				alpha = radianToDegree(alpha);
			} else if(source.x>=0&&source.y<0) {
				//计算与x正方向的夹角
				alpha = Math.asin(source.x/dis);
				alpha = alpha+Math.PI*3/2;
				//弧度换算成角度
				alpha = radianToDegree(alpha);
			}
			beta = alpha+degree;
			//角度转弧度
			beta = degreeToRadian(beta);
			result.x = Math.round(dis*Math.cos(beta));
			result.y = Math.round(dis*Math.sin(beta));
			result.x += target.x;
			result.y += target.y;

			return result;
		}

		/**
		 * 弧度转角度
		 */
		public static function radianToDegree(radian:Number):Number {
			return radian*180/Math.PI;
		}

		/**
		 * 角度转弧度
		 */
		public static function degreeToRadian(degree:Number):Number {
			return degree*Math.PI/180;
		}
	}
}
java:

package com.gdtopway.topologyweb.autolayout.util;

import java.awt.Point;

public class RotationUtil {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Point p = roationPoint(new Point(-1,1), new Point(1,1), 45);
		System.out.println(p.x+":"+p.y);
	}

	/**
	 *
	 * @param target 围绕旋转的目标点
	 * @param source 要旋转的点
	 * @param degree 要旋转的角度
	 * @return
	 */
	public static Point roationPoint(Point target, Point source, int degree) {
		source.x = source.x - target.x;
		source.y = source.y - target.y;
		double alpha = 0;
		double beta = 0;
		Point result = new Point();
		double dis = source.distance(0, 0);
		if(source.x==0&&source.y==0) {
			return target;
		//第一象限
		} else if(source.x>=0&&source.y>=0) {
			//计算与x正方向的夹角
			alpha = Math.asin(source.y/dis);
		//第二象限
		} else if(source.x<0&&source.y>=0){
			//计算与x正方向的夹角
			alpha = Math.asin(Math.abs(source.x)/dis);
			alpha = alpha+Math.PI/2;
		//第三象限
		} else if(source.x<0&&source.y<0) {
			//计算与x正方向的夹角
			alpha = Math.asin(Math.abs(source.y)/dis);
			alpha = alpha+Math.PI;
		} else if(source.x>=0&&source.y<0) {
			//计算与x正方向的夹角
			alpha = Math.asin(source.x/dis);
			alpha = alpha+Math.PI*3/2;

		}
		//弧度换算成角度
		alpha = radianToDegree(alpha);
		beta = alpha+degree;
		//角度转弧度
		beta = degreeToRadian(beta);
		result.x = (int) Math.round(dis*Math.cos(beta));
		result.y = (int) Math.round(dis*Math.sin(beta));
		result.x += target.x;
		result.y += target.y;

		return result;
	}

	/**
	 *
	 * @return
	 */
	public static double radianToDegree(double radian) {
		return radian*180/Math.PI;
	}

	public static double degreeToRadian(double degree) {
		return degree*Math.PI/180;
	}

}

2015.10.4 ADD:

国庆写js版的又碰到一个问题,又把这个派上了用场,js版本跟java版本语法基本上一样,再写的时候,突然发现,以前很多地方把rotation这个单词写错了,汗。。。其实很多问题都可以转换为上面的问题来解答。

发表评论