地图鸟瞰或 2.5D 渲染问题

发布于 2024-09-17 06:18:09 字数 940 浏览 3 评论 0 原文

我正在开发一个路线规划导航软件,并使用以下解决方案将我的道路线变成 2.5D 或 3D 视图

用 C# 从线绘制 2.5D 或 3D 地图

但是,对于视口内为 0 的线,上述解决方案相当不错< x <宽度和 0 < y <高度 。然而,有些线其点可能具有 y < 0或x< 0或y>高度或x>宽度然后上面的解决方案变得疯狂。有人能帮我弄清楚如何解决这个问题吗?

vvvv 使用 3D 算法 vvvv

alt text

vvvv 没有 3D 算法 vvvv

alt text

更新:: 使用此代码后

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;

地图变得如下 alt text

我认为当 Y 计算远远超出负值时,它们会出现问题。我正在使用 Qt,并且 Qt 渲染器的线裂纹似乎是错误,与我们原来的问题无关。

I'm developing a turn-by-turn navigation software and I'm using the following solution to make my lines of roads into 2.5D or 3D View

Draw 2.5D or 3D Map with C# from lines

However, above solution is quite okay for lines within the view port which is 0 < x < width and 0 < y < height . However there are lines that its points may have y < 0 or x < 0 or y > height or x > width and then the above solution gone crazy. Could anyone help me figure out how to solve the problem?

vvvv With 3D algorithm vvvv

alt text

.

vvvv Without 3D algorithm vvvv

alt text

Update::
After using this code

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;

The map become like following
alt text

I think there's something wrong with Y calculations when they go way beyond negative values. I'm using Qt and cracks at line seems bug with Qt renderer, not related to our original problem.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

篱下浅笙歌 2024-09-24 06:18:09

问题在于您使用的转换不会将直线映射到直线。相反,直线通常会走向抛物线。您可以在示例图像中看到,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,d,e 的合适值,它的计算结果类似于 (c*y^2+d*y+e,y) ,这是一条抛物线。

因此,最好的选择是放弃此转换并切换到透视转换

在您最初的问题中,您提到渲染图像的非仿射变换太慢。看来您现在已经切换到在渲染线条之前转换线条,而且速度足够快。您现在唯一要做的就是更改变换。

这是建议的转换。这需要几个步骤,并将 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 是一些小的正值,例如 0.05 或 0.1。

The problem is that the transformation you are using does not map straight lines to straight lines. Rather, straight lines generally go to parabolas. You can see that in the example images, where the more-or-less-straight main road going from top to bottom in the 2D view is transformed to a curved road in the 2.5D view. You would see the same thing for the lines that "go crazy" in your example if you broke them up into shorter segments.

Mathematically, you can see what is going on by going back to the transform you're using:

x_ = (x - w/2)*(t1+(y/h)*(t2-t1)) + w/2
y_ = y

If we express a straight line as x = ay+b, then a point (ay+b,y) on this line maps to (ay+b - w/2)*(t1+(y/h)*(t2-t1)) + w/2,y). This expression looks complicated, but you can see that it evaluates to something like (c*y^2+d*y+e,y), for suitable values of c,d,e, which is a parabola.

So your best bet is to abandon this transform and switch to a perspective transform.

In your original question, you mentioned that a non-affine transform of a rendered image was too slow. It seems that you have now switched to transforming the lines before rendering them, and that is fast enough. The only thing you have to do now is change the transform.

Here's a suggested transform. It is a couple of steps, and takes your 2D (x,y) coordinates to some 2.5D (u,v) coordinates. I assume you're using 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 ;

There is a parameter t here that defines the amount of tilt, expressed in radians. I'd suggest playing with a value of somewhere around 0.3, plus or minus.

I've worked this out with pencil and paper, but not run it, so let me know if this doesn't work .. it's always possible that there's been a transcription error.

Update: You want to avoid drawing any entity (line, polygon, whatever) that has a point (x,y) such that a is non-positive. Better still, to avoid overflow, you should avoid drawing when a<epsilon, where epsilon is some small positive value like 0.05 or 0.1.

三月梨花 2024-09-24 06:18:09

该方程的问题在于它允许投影 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

The problem with the equation is that it allows the projected x value to cross the mid-line (w/2). This is not desirable when trying to model a perspective transform since lines should approach, but do not cross, a vanishing point. Also, because of the way the equation is written, this crossing happens in front of the camera instead of behind, which leads to unnecessary artifacts. Try something like this instead:

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文