求救,坐标旋转算法问题

电脑不需要休息吗? 2018-03-13 11:16:13
各位大神,遇到一个坐标旋转的问题,旋转后坐标总是不对求助。
具体问题:有一个点坐标(-75,350),需要求解以坐标原点为轴旋转45的坐标。
DPoint 为自己重载的Point类,改用double类型表示坐标。

解决方法1:使用c#Graphic的方法进行旋转:
private DPoint Get45DPoint(DPoint pt, float angle)
{
float tAngle = 0;
tAngle = angle;
Bitmap bit = (Bitmap)this.pSpots.BackgroundImage;
bit = (Bitmap)this.pSpots.BackgroundImage;
Graphics gct = Graphics.FromImage(bit);
PointF tp = _Origin.getFormPoint(new PointF((float)pt.X, (float)pt.Y), 5);
PointF[] points = new PointF[] { new PointF((float)tp.X, (float)tp.Y) };
gct.TranslateTransform(_Origin.X, _Origin.Y);
gct.RotateTransform(tAngle);
gct.TranslateTransform(-_Origin.X, -_Origin.Y);
gct.Transform.TransformPoints(points);

DPoint c2 = new DPoint((double)points[0].X, (double)points[0].Y);
c2 = _Origin.getDPointFromFormPoint(new Point((int)points[0].X, (int)points[0].Y));
return c2;
}
原坐标(-75,350)旋转后坐标(194,305);距离原点的距离:357.94552658190884,361.47060738046184

方法2:自己实现坐标旋转
private DPoint Get45DPoint2(DPoint p, float angle = 45)
{
float tAngle = 45;
tAngle = angle;
DPoint ori = new DPoint(0, 0);

double x = ori.X + (p.X - ori.X) * Math.Cos(tAngle) - (p.Y - ori.Y) * Math.Sin(tAngle);
double y = ori.Y + (p.X - ori.X) * Math.Sin(tAngle) - (p.Y - ori.Y) * Math.Cos(tAngle);

DPoint c2 = new DPoint(x, y);

return c2;
}
原坐标(-75,350)旋转后坐标( -337.22,-247.68);到原点距离分别为357.94552658190884,418.40496029564468
方法三:自己实现旋转算法2
private DPoint Get45DPoint3(DPoint p, float angle = 45)
{
float tAngle = 45;
tAngle = angle;
if (angle < 0)
{
tAngle = 360 + angle;
}
DPoint ori = new DPoint(0, 0);

double x = 0;
double y = 0;

x = p.X * Math.Cos(angle) - p.Y * Math.Sin(angle);
y = -p.X * Math.Sin(angle) + p.Y * Math.Cos(angle);

DPoint c2 = new DPoint(x, y);
return c2;
}

原坐标(-75,350)旋转后坐标(-337.22,247.68);到原点的距离分别为:357.94552658190884,418.40496029564468

求教:为什么旋转后到原点的距离会有这么大偏差?有没有误差在0.5以内的算法?哪位大神提供一个围绕原点旋转45度计算后重新转回原坐标的算法?项目紧急状态,望大神帮忙!
...全文
544 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
极客诗人 2018-03-16
  • 打赏
  • 举报
回复
昨天看见 写了一大堆 写了这么一堆废话

有一个点在(x,y)

算法

x*x+y*y=z*z(z为长边)

假设要旋转p度

先求出最长边。。
即 
z*z=x*x+y*y;

即最长边恒定长度。。 且可将这个与坐标轴原定看做直角三角形

使用cos 来求出x坐标 因为最长边恒定 根据三角形 x*x+y*y=z*z

void count3(float x,float y,float point)
{
	float z=x*x+y*y;//求出最长边。
	//求出夹角
	var _point =(x*x+z*z-y*y)/2/x/z;
	var new_point=_point+point;
	
	x*x+(z*z-x*x)=z*z;
	
	//算法暂时没有弄明白。。ps泰勒展开公式
	
	
}
xuzuning 2018-03-15
  • 打赏
  • 举报
回复
逆向旋转就用负角 顺时针和逆时针取决于你是遵守左手定律还是右手定律,和坐标系的布局。其实都是相对的
assky124 2018-03-15
  • 打赏
  • 举报
回复

        /// <summary>
        /// 获取点绕旋转点旋转
        /// </summary>
        /// <param name="rotatePt">中心旋转点</param>
        /// <param name="angle">旋转角度</param>
        /// <param name="pt">要旋转的点</param>
        /// <returns></returns>
        public static PointF GetRotatedPoint(PointF rotatePt, float angle, PointF pt)
        {
            Matrix matrix = new Matrix();
            matrix.RotateAt(angle, rotatePt);
            PointF[] pts = new PointF[] { pt };
            matrix.TransformPoints(pts);
            matrix.Dispose();
            return pts[0];
        }
threenewbee 2018-03-14
  • 打赏
  • 举报
回复
https://download.csdn.net/download/lcm60546054/7254091
  • 打赏
  • 举报
回复
引用 3 楼 xuzuning的回复:
            var angle = 45.0 / 180 * Math.PI;
            var x = p.X * Math.Cos(angle) - p.Y * Math.Sin(angle); //-194.4544
            var y = p.X * Math.Sin(angle) + p.Y * Math.Cos(angle); // 300.5204
对于你的算法一,由于含有未公开的自定义成分,无法测试。但从结果上看,算法上是小有错误的 对以你的算法二、三,你违背了基本规则:Math 再计算三角函数时,使用的是弧度而不是角度。当然结果就不会正确 请注意,旋转是有方向的 Math.Sqrt(75 * 75 + 350 * 350) = 357.9455 Math.Sqrt(-194.4544 * -194.4544 + 300.5204 * 300.5204) = 357.9455
x = p.X * Math.Cos(angle) + p.Y * Math.Sin(angle); y = -p.X * Math.Sin(angle) + p.Y *Math.Cos(angle); 这样是不是可以?
  • 打赏
  • 举报
回复
引用 3 楼 xuzuning的回复:
            var angle = 45.0 / 180 * Math.PI;
            var x = p.X * Math.Cos(angle) - p.Y * Math.Sin(angle); //-194.4544
            var y = p.X * Math.Sin(angle) + p.Y * Math.Cos(angle); // 300.5204
对于你的算法一,由于含有未公开的自定义成分,无法测试。但从结果上看,算法上是小有错误的 对以你的算法二、三,你违背了基本规则:Math 再计算三角函数时,使用的是弧度而不是角度。当然结果就不会正确 请注意,旋转是有方向的 Math.Sqrt(75 * 75 + 350 * 350) = 357.9455 Math.Sqrt(-194.4544 * -194.4544 + 300.5204 * 300.5204) = 357.9455
谢谢指点,请问顺时针旋转怎样计算?
xuzuning 2018-03-14
  • 打赏
  • 举报
回复
            var angle = 45.0 / 180 * Math.PI;
            var x = p.X * Math.Cos(angle) - p.Y * Math.Sin(angle); //-194.4544
            var y = p.X * Math.Sin(angle) + p.Y * Math.Cos(angle); // 300.5204
对于你的算法一,由于含有未公开的自定义成分,无法测试。但从结果上看,算法上是小有错误的 对以你的算法二、三,你违背了基本规则:Math 再计算三角函数时,使用的是弧度而不是角度。当然结果就不会正确 请注意,旋转是有方向的 Math.Sqrt(75 * 75 + 350 * 350) = 357.9455 Math.Sqrt(-194.4544 * -194.4544 + 300.5204 * 300.5204) = 357.9455
  • 打赏
  • 举报
回复
@xuzuning 逆向旋转呢?
SoulRed 2018-03-13
  • 打赏
  • 举报
回复
unity有相关的函数,直接rotate一下即可。。你这个我没看错的话,仅仅是水平rotate unity里的transform.Rotate()即可解决。。而且还能3维旋转,比较麻烦的是Quaternion 4个点控制一次旋转。 给你这个

        public static double GetAngle(int X1, int Y1, int X2, int Y2)
        {
            double angleOfLine = Math.Atan2((X2 - X1), (Y2 - Y1)) * 180.0d / Math.PI;

            //+180°后0的起点是0点钟逆时针

            return angleOfLine + 180.0d;
        }
调用方法是

var r = GetAngle(132, 138, 105, 35);
里面的参数根据自己写。是两个点的坐标。 这个函数是根据两个点来获取角度(相对于时钟0点方向) 别看仅仅一句。很绕逻辑的。你把他反过来就是你要的公式了
SoulRed 2018-03-13
  • 打赏
  • 举报
回复
原点位置在推演算法中应该一直是0,0的位置,因为原点不会动。动的是你要操作的这个目标点,他移动,角度就增大或减小。 上面我发的那个函数是我自己写的。比较绕。但2D角度完全正确。 第1,2个参数是原点的坐标,第3,4的参数是你目标要移动到的坐标,很准确。

           var a1 = M.GetAngle(132, 138, 105, 35);
            var a2 = M.GetAngle(132, 138, 53, 33);
            var a3 = M.GetAngle(132, 138, 32, 95);
            var a4 = M.GetAngle(132, 138, 47, 140);
            var a5 = M.GetAngle(132, 138, 45, 195);
            var a6 = M.GetAngle(132, 138, 199, 195);
            var a7 = M.GetAngle(132, 138, 204, 95);
可以看出来前两个参数一直不变,因为他是原点的位置。不需要变

110,535

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧