leonhard-s / Py2DM

A Python module for reading and writing SMS 2DM mesh files.
MIT License
9 stars 0 forks source link

Question - Usage for combining/merging 2 or more 2DM files #6

Open Brent-Edwards opened 2 years ago

Brent-Edwards commented 2 years ago

Hi,

Is this functionality supported? If not, any help would be greatly appreciated.

I'm currently using GIS software to merge 2DM files. Here's an overview of my workflow:

  1. QGIS - Processing>Export mesh faces (polygonZ geometry)
  2. QGIS - Processing>Merge the 2 polygonZ outputs
  3. PostGIS/SQL - Build a merged 2DM from the merged polygonZ table

It would be great to be able to do this using the Py2DM library.

Reference info (SMS:Merge 2D Meshes) - https://xmswiki.com/wiki/SMS:Merge_2D_Meshes

Brent-Edwards commented 2 years ago

FYI, I just realized that the QGIS Processing>TIN Mesh Creation tool can be used to create a 2DM from the polygonZ polygons (the second step in my previous message) thus eliminating the need for the PostGIS/SQL step.

leonhard-s commented 2 years ago

Hi,

Thank you for the suggestion.

Currently, Py2DM only deals with the reading and writing meshes in the 2DM format. There is no "Mesh" object, it only converts between the Python objects representations and the *.2DM files.

I have been looking for ways of supporting higher-level mesh operations like the one you describe, but always ran into performance issues. The projects this library was written for require fairly large grids (~20 million cells), and even a check for overlapping mesh faces is quite expensive for these meshes. Hence why I limited the scope of Py2DM quite heavily for now.

That said, if your input meshes do not intersect, merging two meshes along a shared boundary should be quite straightforward:

  1. add nodes from the first mesh (mesh1)
  2. add any nodes from the second mesh (mesh2) that are not also in part of mesh1
  3. create a table mapping any nodes in mesh2 that are also in mesh1 to their respective ID in mesh1
  4. add all elements from mesh1
  5. add all elements from mesh2, using the lookup table from step 3. to relink them to the nodes in the old mesh
  6. (optional) renumber the mesh to remove any gaps in the ID ranges
leonhard-s commented 2 years ago

I have been working on a more comprehensive C++ extension to use as a mesh representation, which should allow Py2DM to support these types of mesh operations without significantly hurting performance for larger meshes.

Until then, I can look into adding a few standalone scripts for common (and performance-friendly) operations, such as merging non-overlapping meshes, renumbering meshes, deleting disjoint nodes (i.e. ones that are not connected to any elements), etc.

Brent-Edwards commented 2 years ago

Thanks for the response. The workflow you describe is pretty much what I had in mind. Most of the meshes that I deal with have up to 2 million nodes and around half as many elements. The performance issues have thus been manageable.

leonhard-s commented 2 years ago

Pushed a first version of a mesh merging utility to the develop branch which uses the merge-at-boundary strategy I posted earlier. It lives under the py2dm.utils submodule:

https://github.com/leonhard-s/Py2DM/blob/3c98bd0b954505986185d804898dde8d23de16d1/py2dm/utils.py#L124-L143

This utility only considers exact coincidence for nodes and will not perform any deduplication or self-intersection checks on the mesh elements for performance reasons.
Still working on a more comprehensive Mesh class that would allow efficient editing of mesh geometry and topology, but progress has been slow due to lack of time.

If you find yourself merging meshes again, please consider giving this utility a go and giving me some feedback on how it performs in the real world - the synthetic tests I have made worked well but might be too clean - which is why it is not part of an official Py2DM release yet.

You can install the current version straight from Git via pip:

python -m pip install --upgrade git+https://github.com/leonhard-s/py2dm@develop

Edit: Merges will now de-duplicate elements via node ID set comparison.

Brent-Edwards commented 2 years ago

That's great news! I will test it out and report any issues as needed. Thanks again!

Brent-Edwards commented 2 years ago

I finally got around to testing the merge_meshes function. For my test case, I get the following errors:

image

I suspect that the errors are due to the fact that one of my meshes has extra nodes due to a previous conversion from E6T elements to E3T elements.

I manually merged the two meshes by adding and renumbering the 2nd mesh elements and nodes based on the the node and element counts of the 1st mesh. This works, but obviously doesn't do any verification for common nodes.

leonhard-s commented 2 years ago

Hi, thank you for the update.

I have looked over the node string merging logic and believe I have resolved the issue you experienced. The extra nodes should not affect the node string conversion, though they are also not filtered.

Node strings should update to the new, merged node IDs the same way elements do, with the same exact node position deduplication logic. Additionally:

Note that like with elements, no deduplication is done on the output node strings (yet). So if both meshes define the same node string (for example at the seam between the two mesh domains), they will also be duplicates in the output as long as they are either both unnamed or have different names.

These changes are currently on the develop branch only.