0

图 1:我在 2d 图层(CoreGraphics)上绘制贝塞尔曲线,我有 A 点和 B 点。

图 2:我可以将图层旋转大约 70 度。

图 3:我想知道点 A 和 B 现在是什么,通过某种方式将图像从 3D 压缩回 2D。

我理想地想要做的是这样的功能:

-(CGPoint)calculateNewPointFrom:(CGPoint)p withAngle:(float)angle
{
    //Rotate point by angle in 3d space
    //Return new point in 2d space
}

2D转3D,再转2D

欢迎大家帮忙。谢谢

4

1 回答 1

0

如果您有Q3D 中某个点的坐标: (x, y, z)

你想把它投影到一个平面上,这个平面包含一个点P并且有法向量n,

平面方程为

(R - P) . n = 0

我在哪里使用矢量减法,并且.是点积。

由此您可以推断出任何点在该平面上的投影:沿着法向量绘制一条线,n直到它与平面相交。

所以会有一些价值a使得

Q + a * n 

位于平面内,即

(Q - a * n - P) . n = 0

求解(注意n . n = 1):

a = (Q - P) . n

(注意——这是从 Q 到 P 的“正常距离”;绝非巧合!)

它们相交点的值现在是

Q + ((Q - P) . n ) * n

再次注意 - 我正在使用向量数学,因此最后一个*n结果是三个值(因为 n 是一个 3D 向量)。

如果您尝试在平面上进行非法线投影(例如,您想投影到 XY 平面上,但您正在“看一个角度”),您可以概括这一点。在这种情况下,你需要沿着不同的方向m(你正在看的方向)进行投影,相交的方程变为

Q + ((Q - P) . n ) * m / (m . n)

如您所见,如果 m 垂直于 n(您是沿着平面看,而不是看它),则没有解决方案......

您还可以看到,如果您直接在 XY 平面上进行投影,因此 n = [0 0 1]),整个事情简化为设置 Z=0

让我知道这是否足够,或者您是否需要实际的代码行......

--- 编辑 --- 添加一些简单的代码:

如果您有一系列描述曲线的点 (x, y),您可以通过以下方式围绕 Z 轴(垂直于您的平面)旋转角度 θ:

x1 = x * cos(theta) - y * sin(theta);
y1 = x * sin(theta) + y * cos(theta);

现在您可以通过简单地减少 y 坐标来“挤压”这些点,这样您就可以从侧面看到它们:

x2 = x1;
y2 = y1 * cos(alpha);

alpha您查看曲线的表观角度在哪里。因此,如果您直接向下看 XY 平面,alpha则为 0,并且y2 = y1。如果你看 45 度,alphapi/4y2 = 0.707 * y1(大约)。

您可以将这两种转换组合成:

xnew = x * cos(theta) - y * sin(theta);
ynew = cos(alpha) * (x * sin(theta) + y * cos(theta));

尝试一些 theta 值(在 0 和 0.5 之间,以 0.1 为步长)和 alpha 值(类似的范围可能很好)。看看你喜不喜欢这个结果。

也许这对您来说是一个更好的(在“更有用”的意义上)答案?

于 2013-02-20T12:45:20.973 回答