Seperate list / mesh into sub-lists / sub-meshes

2019-06-08 15:42发布

问题:

EDIT: To give an idea of what type of mesh I have:

Imagine a LEGO brick with four knobs on the top. I read a STL file containing the surface of the whole brick. After identifying all nodes with unique coordinates (and saving their next neighbours in a list) I cut away most of the brick, so that only the four knobs remain. Unluckily for me, these four knobs are still in one big list (one for the nodes, one for the next neighbours). I want the fastest way to get all nodes of one knob if I specify one node which I know belongs to that knob.

I have a (relatively) big List<cNode> nodes where

class cNode
{
    int nodeNumber;
    cVector vector;
}

and an even bigger (ca. 14e6 entries) List<cNodeCoincidence> coincidences where

class cNodeCoincidence
{
    cNode node1;
    cNode node2;
}

My nodes represent points in 3D and my coincidences resembles what was formerly a mesh consisting of triangles, condensed from a STL file. I know for a fact (and the user made his input accordingly), that my node-mesh is actually 4 seperate meshes in one node/coincidence list. My goal is to extract the nodes of each sub-mesh to its own nodelist. To achieve this, I start with one node for each sub-mesh, which I know to be part of said sub-mesh. Cue a recursive function:

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);
}

which is called by: AssembleSubMesh(new ReadOnlyCollection<cNode>(firstNodeIKnow), globalResultListForSubmesh); thus writing the results of the recursion to a more global list.

This procedure works (tested with small mesh), but is painfully slow (over 15 hours before I aborted the process).

Is there any way to seperate the mesh in a faster and perhaps more elegant way?

I found this SO post and had a look at this lecture and it seems, that there might be a chance that this (especially WQUPC) is what I need, but I don't understand how exactly it could help, because they only have a node list and I additionally have the coincidence list which would be a shame not to use, really (?).

Could a database help (because of indexing)?

回答1:

You need to be able to identify edge. which is a a single connection between 2 vertices (no more other connections found). I assume that there are all vertices for all triangles, so they are duplicated. It depends on the dimension of your mesh sure, but it shouldn't take so much time.

You need to define dictionaries, which will pump your app's memory, but will also dramatically increase speed with guaranteed O(1) access.

In short:

1) load data

2) scan it and construct appropriate data structures If you observe any CAD modelling software it takes much more time then it should during loading of meshes, for the same reason: they need to scan data loaded and construct appropriate data structures to be able to process that data after as fast as it possible.

3) use those data structures to get information you need as fast as it possible.

So choose data structures and keys wisely, to meet requirements of your application.