Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Track and Match CQ Objects On an Export-Import Round Trip #1243

Closed
jmwright opened this issue Jan 21, 2023 · 20 comments · Fixed by #1353
Closed

Track and Match CQ Objects On an Export-Import Round Trip #1243

jmwright opened this issue Jan 21, 2023 · 20 comments · Fixed by #1353
Labels
enhancement New feature or request OCC feature Requires coding at OCC implementation level

Comments

@jmwright
Copy link
Member

jmwright commented Jan 21, 2023

User Story: As a user, I want to be able to export a CQ object or assembly to STEP/BRep, then import it again and be able to match the imported objects with the original pre-export CQ objects.

This will require some work on the CQ internals to accomplish.

Reference: Google Groups

@shimwell Please feel free to add additional details.

Related to #449

@jmwright jmwright changed the title Track and Match CQ Objects On and Export-Import Round Trip Track and Match CQ Objects On an Export-Import Round Trip Jan 21, 2023
@jmwright jmwright added the enhancement New feature or request label Jan 21, 2023
@shimwell
Copy link
Contributor

shimwell commented Jan 21, 2023

Yes that would be a really useful feature for me.

The only tiny detail is that the Brep exported is also slightly differently to the default cadquery brep.

I use some code Adam wrote to merge shared surfaces link in the Brep file. This makes is easier to mesh in subsequent steps.

Full details of the messy workflow I have assembled are here in this unfinished paper I am working on. But having this round trip feature would allow the unreliable brep-part-finder package to be removed.
production_of_DAGMC_geometry_with_open_source_software_paper (1).pdf

@adam-urbanczyk
Copy link
Member

@shimwell is this in the end about storing user defined labels per shape of subshape (e.g. face) that can survive the face merging process?

So something like:

As a user I want to be able to add labels to my models and use them to reference arbitrary shapes, possibly after merging duplicate faces.

@shimwell
Copy link
Contributor

For me I just need to track the volumes. The removal of shared surfaces is a bit of a distraction. It happens in the workflow. But I just need to correlate the volumes in an assembly with the volumes in a brep file. I think in many cases the volume order is the same but not guaranteed to be the same

@adam-urbanczyk adam-urbanczyk added the OCC feature Requires coding at OCC implementation level label Jan 30, 2023
@shimwell
Copy link
Contributor

Is there anything I can do to help with this

@adam-urbanczyk
Copy link
Member

Hm, you could check if BOPAlgo_MakeConnected is indeed the correct algo for what you need.

@shimwell
Copy link
Contributor

shimwell commented Jun 2, 2023

I've checked with the DAGMC community and we think BOPAlgo_MakeConnected that would be great for merging surfaces which is one of the things we would find very useful. The existing workflow uses the BOPALgo_Splitter (which you provided an example of a while ago) and this has also worked well for us.

@pshriwise and @ebknudsen might have further comments

@adam-urbanczyk
Copy link
Member

adam-urbanczyk commented Jun 4, 2023

Thanks @shimwell. I'm still not sure if this is at all about import/export. Based on the paper I concluded that you want to do this imprinting and matching in the back-end of CAD to DAGMC, so persisting to disk is not really needed. Is my conclusion correct?

What I have in mind so far is something like:

  1. Start with a cq.Assembly
  2. Construct a dictionary cq.Solid->id
  3. Merge all cq.Solid instances using BOPAlgo_MakeConnected
  4. Build a dictionary of cq.Solid->cq.Solid (after -> before (3)).
  5. Create another dictionary cq.Solid -> id combining (4) and (2)
  6. Return (5) and (3)

If it turns out that you do need to serialize, then using XDE/OCAF (native OCCT formats) would be preferred.

@shimwell
Copy link
Contributor

shimwell commented Jun 4, 2023

The writing of a brep file to disk was done so that we can read it in by gmsh and meshed. I couldn't find another way of getting the geometry fro cadquery to gmsh so I currently write a brep file as they can both interact with that.

I actually also tried making triangular meshes in cadquery (then we wouldn't need to export) but that didn't result in watertight meshes a the surface mesh in gmsh did. If this had worked then the brep format could be avoided
https://github.com/fusion-energy/cad_to_dagmc/blob/7efb6805e52a4587a48de4a0a209f73b54ded91a/src/cad_to_dagmc/core.py#L164

@adam-urbanczyk
Copy link
Member

I'm referring to the interface marked in red. AFAICT this part can be done in memory and has no relation to GMSH.

afbeelding

@shimwell
Copy link
Contributor

shimwell commented Jun 5, 2023

Thanks Adam. Yes this interface is done in memory currently. Perhaps I've used the wrong terminology but a BREP "object" is passed between these stages

@adam-urbanczyk
Copy link
Member

OK, so does what I proposed above (points 1-6) solve the problem you have?

@shimwell
Copy link
Contributor

shimwell commented Jun 5, 2023

Yes, it would be perfect.

@adam-urbanczyk
Copy link
Member

Great! For my understanding, how do you actually pass the "material tag" information to gmsh?

@shimwell
Copy link
Contributor

shimwell commented Jun 5, 2023

The brep gets meshed by gmsh and each volume is meshed.

The meshed representation of each volume (coords and triangles) are then passed along with the material tags are then passed to pymoab based package that saves the collections as tagged volumes in a DAGMC formated h5m file.

So gmsh doesn't do much with the material tags it just passes then along and keep the same order of material tags and brep volumes.

I guess we wouldn't need to pass the material tags to gmsh in the future. We would just get the meshed volumes back and already know what material tag each one of them is. Then we can write them to h5m format

@adam-urbanczyk
Copy link
Member

Unrelated to this issue, but @shimwell it seems that gmsh can in principle import from memory: https://gitlab.onelab.info/gmsh/gmsh/blob/gmsh_4_11_1/api/gmsh.py#L8437. I'm going to add TopoDS_Shape._address() to OCP 7.7.1. Maybe you can test it, once available.

@shimwell
Copy link
Contributor

shimwell commented Jun 5, 2023

Wow super useful find there. Yes I would be super keen to test that

@adam-urbanczyk
Copy link
Member

@shimwell latest OCP (7.7.1 - not released, but available via cadquery channel) has TopoDS_Shape._address(). Could you try if it works with gmsh (you'll need one linked against OCCT 7.7.1, conda-forge should have it)?

@shimwell
Copy link
Contributor

Thanks @adam-urbanczyk I have tried the following and I shall continue tomorrow

I created a new conda env with this environment.yml file and this command

conda env create -f environment.yml

name: env_cad
channels:
  - cadquery
  - conda-forge
dependencies:
  - python=3.9
  - ocp=7.7.1
  - occt=7.7.1
  - cadquery=2.2.0
  - gmsh
  - python-gmsh

running conda list I can see that I have occt and ocp from these sources

occt                      7.7.1           all_h16763a6_201    conda-forge
ocp                       7.7.1.0                  py39_0    cadquery

I then proceeded to run this file that makes a cadquery shape and converts it to OCC then trys to import with gsm

import gmsh
import cadquery as cq

result = cq.Workplane("XY").box(3, 3, 0.5).edges("|Z").fillet(0.125)

topods = result.toOCC()

gmsh.model.occ.importShapesNativePointer(topods)

Unfortunately this last line errored with the message

>>> c_void_p(shape),TypeError: cannot be converted to pointer

I shall continue tomorrow, thanks for your efforts on adding these features

@adam-urbanczyk
Copy link
Member

I think it should be:

gmsh.model.occ.importShapesNativePointer(topods._address())

@adam-urbanczyk
Copy link
Member

FWIW this seems to work (or at least does not crash). I'll open another issue, gmsh import might be interesting for other users.

import OCP
import gmsh

gmsh.initialize()

s = OCP.BRepPrimAPI.BRepPrimAPI_MakeBox(1,1,1).Solid()
gmsh.model.occ.importShapesNativePointer(s._address())

@adam-urbanczyk adam-urbanczyk linked a pull request Jun 20, 2023 that will close this issue
5 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request OCC feature Requires coding at OCC implementation level
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants