我正在开发一个转弯导航软件,我正在使用以下解决方案将我的道路划分为2.5D或3D视图
Draw 2.5D or 3D Map with C# from lines
然而,上述解决方案对于视口内的线路是非常好的,其中0 <0。 x&lt;宽度和0 < y&lt;身高。然而,有些线可能具有y
vvvv使用3D算法vvvv
vvvv没有3D算法vvvv
更新:: 使用此代码后
double x = p->x();
double y = p->y();
double t = -0.5;
x = x - w / 2;
y = y - h / 2;
double a = h / (h + y* sin(t));
double u = a * x + w / 2;
double v = a * y * cos(t) + h / 2;
p->setX(u);
p->setY(v);
return p;
地图变得如下
我认为当Y计算超出负值时会出现问题。我正在使用Qt和线条上的裂缝似乎是Qt渲染器的错误,与我们原来的问题无关。
答案 0 :(得分:4)
问题是您正在使用的变换不会将直线映射到直线。相反,直线通常是抛物线。您可以在示例图像中看到,在2D视图中从上到下的或多或少直的主要道路在2.5D视图中转换为弯曲道路。如果你将它们分成更短的部分,你会看到在你的例子中“变得疯狂”的那条线也是一样的。
在数学上,您可以通过返回正在使用的变换来查看正在发生的事情:
x_ = (x - w/2)*(t1+(y/h)*(t2-t1)) + w/2
y_ = y
如果我们将一条直线表示为x = ay+b
,则此行上的点(ay+b,y)
会映射到(ay+b - w/2)*(t1+(y/h)*(t2-t1)) + w/2,y)
。这个表达式看起来很复杂,但你可以看到它的评估结果类似于(c*y^2+d*y+e,y)
,适用于c,d,e
的值,它是一个抛物线。
所以你最好的办法就是放弃这种转变并切换到perspective transform。
在您的原始问题中,您提到渲染图像的非仿射变换太慢。现在看来你现在已经切换到渲染它们之前变换线条了,这足够快了。你现在唯一要做的就是改变变换。
这是建议的转换。这是几个步骤,并将您的2D(x,y)坐标带到某些2.5D(u,v)坐标。我假设您正在使用C#。
t = 0.3 // tilt angle - try different values
X = x - w/2 ;
Y = y - h/2 ;
a = h/(h + Y*Math.Sin(t)) ;
u = a*X + w/2 ;
v = a*Y*Math.Cos(t) + h/2 ;
此处有一个参数t
,用于定义倾斜量,以弧度表示。我建议玩一个大约0.3,加或减的值。
我用铅笔和纸做过这个,但没有运行它,所以让我知道如果这不起作用..总是有可能是转录错误。
更新:您希望避免绘制任何具有(x,y)
点的实体(线,多边形等),使a
为非正数。更好的是,为了避免溢出,您应该避免在a<epsilon
时绘制,其中epsilon
是一些小的正值,如0.05或0.1。
答案 1 :(得分:0)
等式的问题在于它允许投影的x值越过中线(w/2
)。当尝试对透视变换进行建模时,这是不可取的,因为线应该接近,但不要越过消失点。此外,由于方程式的编写方式,这种交叉发生在相机前面而不是后面,这会导致不必要的伪影。尝试这样的事情:
halfW = w/2 dx = (x - halfW) dy = (h - y) // y increases downwards // tune these constants to taste. top = 1.25 bottom = 0.75 lowerBound = 0.1 // Avoids divide by zero and perspective lines crossing midline x_ = (dx / max(lowerBound, (bottom + ((dy / h) * (top - bottom))))) + w/2