2D 投影的 3D 模型的最佳旋转
我正在寻找一种方法来确定在 2D 画布上渲染的一组顶点的最佳 X/Y/Z 旋转(使用 X/Y 坐标,忽略 Z)。
我有几个想法,一个是纯粹的蛮力,涉及对一组顶点执行 0..359 范围内的 3 维循环(步长为 1 或更多,具体取决于结果/速度要求),测量 X/Y 轴上的最小/最大之间的差异,存储最高结果/旋转对并使用最有效的对。
第二个想法是确定欧几里德距离中距离最大的两个点,计算旋转这两点之间的“路径”以沿 X 轴放置所需的角度(同样,我们忽略了 Z 轴) ,因此结果内的深度并不重要),然后重复几次。我看到的问题是,首先通过重复它,我们可能会用新的旋转覆盖之前的旋转,并且原始/后续的旋转可能不一定会导致使用最大的 2D 区域。第二个问题是,如果我们使用单次迭代,则会出现同样的问题 - 相距最远的两个点可能没有其他点沿着同一“路径”对齐,因此我们可能无法获得 2D 项目的最佳旋转。
使用第二个想法,也许使用第一个迭代,例如 3 次迭代,存储所需的旋转角度,并对 3 次进行平均将返回更准确的结果,因为它不仅考虑单个旋转,还考虑前 3 个“对”。
请把这些想法拆开,给出你自己的见解。我很想看看你们都有什么解决方案,或者你们可以引用我不知道的算法。
I'm looking for a way to determine the optimal X/Y/Z rotation of a set of vertices for rendering (using the X/Y coordinates, ignoring Z) on a 2D canvas.
I've had a couple of ideas, one being pure brute-force involving performing a 3-dimensional loop ranging from 0..359 (either in steps of 1 or more, depending on results/speed requirements) on the set of vertices, measuring the difference between the min/max on both X/Y axis, storing the highest results/rotation pairs and using the most effective pair.
The second idea would be to determine the two points with the greatest distance between them in Euclidean distance, calculate the angle required to rotate the 'path' between these two points to lay along the X axis (again, we're ignoring the Z axis, so the depth within the result would not matter) and then repeating several times. The problem I can see with this is first by repeating it we may be overriding our previous rotation with a new rotation, and that the original/subsequent rotation may not neccesarily result in the greatest 2D area used. The second issue being if we use a single iteration, then the same problem occurs - the two points furthest apart may not have other poitns aligned along the same 'path', and as such we will probably not get an optimal rotation for a 2D project.
Using the second idea, perhaps using the first say 3 iterations, storing the required rotation angle, and averaging across the 3 would return a more accurate result, as it is taking into account not just a single rotation but the top 3 'pairs'.
Please, rip these ideas apart, give insight of your own. I'm intreaged to see what solutions you all may have, or algorithms unknown to me you may quote.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我将计算惯性主轴,并采用具有最高对应力矩的轴向量 v。然后,我将旋转顶点以使
v
与 z 轴对齐。如果您想了解有关如何进行此操作的更多详细信息,请告诉我。直观上,这找到了最难旋转点的轴,即顶点最“分散”的轴。
如果没有对您认为最佳的具体定义,就不可能说出该方法的性能如何。但是,它有一些理想的属性:
如果顶点共面,则此方法是最佳的,因为它将始终将该平面与 xy 平面对齐。
如果顶点排列在矩形框中,则该框的最短尺寸将与 z 轴对齐。
如果顶点排列在矩形框中,则
编辑:这是有关如何实现此方法的更详细信息。
首先,为每个顶点分配一个质量。我将在下面讨论如何执行此操作的选项。
接下来,计算顶点集的质心。然后将所有顶点平移 -1 倍质心,以便新的质心现在为 (0,0,0)。
计算转动惯量张量。这是一个 3x3 矩阵,其条目由您可以在 Wikipedia 上找到的公式给出。这些公式仅取决于顶点位置和您分配给它们的质量。
现在您需要对惯性张量进行对角化。由于它是对称正定的,因此可以通过找到其特征向量和特征值来做到这一点。不幸的是,寻找这些的数值算法往往很复杂。最直接的方法需要找到三次多项式的根。然而,查找矩阵的特征值和特征向量是一个极其常见的问题,任何有价值的线性代数包都会附带可以为您完成此操作的代码(例如,开源线性代数包 Eigen 具有 SelfAdjointEigenSolver。)还可以在 Internet 上找到专门针对 3x3 情况的轻量级代码。
您现在拥有三个特征向量及其相应的特征值。这些特征值将为正。取最大特征值对应的特征向量;该向量指向新 z 轴的方向。
现在,关于质量的选择。最简单的方法是将所有顶点的质量设置为 1。如果您拥有的只是点云,这可能是一个很好的解决方案。
如果您有权访问该数据,您还可以将每颗恒星的质量设置为其真实世界的质量。如果这样做,您计算的 z 轴也将是恒星系统(最有可能)旋转的轴。
I would compute the principal axes of inertia, and take the axis vector
v
with highest corresponding moment. I would then rotate the vertices to alignv
with the z-axis. Let me know if you want more details about how to go about this.Intuitively, this finds the axis about which it's hardest to rotate the points, ie, around which the vertices are the most "spread out".
Without a concrete definition of what you consider optimal, it's impossible to say how well this method performs. However, it has a few desirable properties:
If the vertices are coplanar, this method is optimal in that it will always align that plane with the x-y plane.
If the vertices are arranged into a rectangular box, the box's shortest dimension gets aligned to the z-axis.
EDIT: Here's more detailed information about how to implement this approach.
First, assign a mass to each vertex. I'll discuss options for how to do this below.
Next, compute the center of mass of your set of vertices. Then translate all of your vertices by -1 times the center of mass, so that the new center of mass is now (0,0,0).
Compute the moment of inertia tensor. This is a 3x3 matrix whose entries are given by formulas you can find on Wikipedia. The formulas depend only on the vertex positions and the masses you assigned them.
Now you need to diagonalize the inertia tensor. Since it is symmetric positive-definite, it is possible to do this by finding its eigenvectors and eigenvalues. Unfortunately, numerical algorithms for finding these tend to be complicated; the most direct approach requires finding the roots of a cubic polynomial. However finding the eigenvalues and eigenvectors of a matrix is an extremely common problem and any linear algebra package worth its salt will come with code that can do this for you (for example, the open-source linear algebra package Eigen has SelfAdjointEigenSolver.) You might also be able to find lighter-weight code specialized to the 3x3 case on the Internet.
You now have three eigenvectors and their corresponding eigenvalues. These eigenvalues will be positive. Take the eigenvector corresponding to the largest eigenvalue; this vector points in the direction of your new z-axis.
Now, about the choice of mass. The simplest thing to do is to give all vertices a mass of 1. If all you have is a cloud of points, this is probably a good solution.
You could also set each star's mass to be its real-world mass, if you have access to that data. If you do this, the z-axis you compute will also be the axis about which the star system is (most likely) rotating.
该答案仅对凸多面体有效。
在 http://203.208.166.84/masudhasan/cgta_silhouette.pdf 中您可以找到
论文深入分析了多面体投影的性质和算法。但我必须承认,遵循这一点并不容易。
有了这个算法,你的问题就是组合学:选择所有可能的顶点集,检查每个集是否存在投影,如果存在,则计算轮廓的凸包面积。
您没有提供顶点的大约数量。但与往常一样,对于无界(又称大)数量,不建议使用组合解决方案。
This answer is intended to be valid only for convex polyhedra.
In http://203.208.166.84/masudhasan/cgta_silhouette.pdf you can find
The paper is an in-depth analysis of the properties and algorithms of polyhedra projections. But it is not easy to follow, I should admit.
With that algorithm at hand, your problem is combinatorics: select all sets of possible vertexes, check whether or not exist a projection for each set, and if it does exists, calculate the area of the convex hull of the silhouette.
You did not provide the approx number of vertex. But as always, a combinatorial solution is not recommended for unbounded (aka big) quantities.