将列表/网格分隔为子列表/子网格
本文关键字:网格 列表 分隔 | 更新日期: 2023-09-27 18:33:13
编辑:为了了解我拥有的网格类型:
想象一下,一块乐高积木的顶部有四个旋钮。我阅读了一个包含整块砖表面的 STL 文件。在识别出所有具有唯一坐标的节点(并将其下一个相邻节点保存在列表中(后,我切掉了大部分砖块,只剩下四个旋钮。对我来说不幸的是,这四个旋钮仍然在一个大列表中(一个用于节点,一个用于下一个邻居(。如果我指定一个我知道属于该旋钮的节点,我想要最快的方法来获取一个旋钮的所有节点。
我有一个(相对(大List<cNode> nodes
class cNode
{
int nodeNumber;
cVector vector;
}
还有一个更大的(约14e6条目(List<cNodeCoincidence> coincidences
其中
class cNodeCoincidence
{
cNode node1;
cNode node2;
}
我的节点表示 3D 中的点,我的巧合类似于以前由三角形组成的网格,由 STL 文件压缩而成。我知道一个事实(并且用户相应地进行了输入(,我的节点网格实际上是一个节点/巧合列表中的 4 个独立网格。我的目标是将每个子网格的节点提取到其自己的节点列表中。为了实现这一点,我从每个子网格的一个节点开始,我知道这是所述子网格的一部分。提示递归函数:
private void AssembleSubMesh(ReadOnlyCollection<cNode> in_nodesToRead, List<cNode> in_nodesAlreadyRead)
{
List<cNode> newNodesToRead = new List<cNode>();
List<cNodeCoincidence> foundCoincidences = coincidences.Where(x => (in_nodesToRead.Any(y => y == x.node1)) || in_nodesToRead.Any(z => z == x.node2)).ToList();
in_nodesAlreadyRead.AddRange(in_nodesToRead);
List<cNode> allRemainingNodes = new List<cNode>();
foreach (cNodeCoincidence nc in foundCoincidences)
{
allRemainingNodes.Add(nc.node1);
allRemainingNodes.Add(nc.node2);
}
allRemainingNodes = allRemainingNodes.Distinct().ToList();
allRemainingNodes.RemoveAll(x => in_nodesAlreadyRead.Contains(x));
if (allRemainingNodes.Count != 0)
AssembleSubMesh(new ReadOnlyCollection<cNode>(allRemainingNodes), in_nodesAlreadyRead);
}
调用者: AssembleSubMesh(new ReadOnlyCollection<cNode>(firstNodeIKnow), globalResultListForSubmesh);
因此将递归的结果写入更全局的列表。
此过程有效(使用小网格进行测试(,但速度非常慢(在我中止该过程之前超过 15 小时(。
有没有办法以更快、也许更优雅的方式分离网格?
我找到了这个SO帖子并看了这个讲座,似乎有可能这个(尤其是WQUPC(是我需要的,但我不明白它到底有什么帮助,因为他们只有一个节点列表,我还有一个巧合列表,如果不使用这将是一种耻辱, 真的(?
数据库可以提供帮助(因为索引(吗?
您需要能够识别边缘。 这是 2 个顶点之间的单个连接(未找到更多其他连接(。我假设所有三角形都有所有顶点,所以它们是重复的。这当然取决于网格的尺寸,但应该不会花费太多时间。
您需要定义字典,这将泵送应用程序的内存,但也会通过保证 O(1( 访问显著提高速度。
总之:
1( 加载数据
2(扫描并构建适当的数据结构如果您观察任何CAD建模软件,则在加载网格时花费的时间要多得多,原因相同:他们需要扫描加载的数据并构建适当的数据结构,以便能够尽快处理该数据。
3(使用这些数据结构尽快获取所需的信息。
因此,请明智地选择数据结构和键,以满足应用程序的要求。