AutodeskAILab / Fusion360GalleryDataset

Data, tools, and documentation of the Fusion 360 Gallery Dataset
Other
405 stars 49 forks source link

Acquire the spatial geometry data of every extrude step #62

Closed Enigma-li closed 3 years ago

Enigma-li commented 3 years ago

Hi,

I am now parsing the JSON file to get the sketch extrusion step data, not the surface or BRep file that already released, but the spatial profiles and the corresponding extruded profiles (offset), as shown in the figure below (P and P_off):

image

Now I am seeking help from the python tool sketch_extrude_importer.py, and it seems that there are some ways to achieve it, but I still not very clear. Some problems are:

  1. how to get the correct spatial positions, e.g., some sample points on a circle profile? is there any function, like the evaluator in BRep to get the real geometry?
  2. I found only the functions reconstruct_sketch_curve involves the 3D point, is it the only way to acquire the geometry?
  3. Is there a way to extract the profile and offset curves directly from the extrude feature object? As my understanding, it should contain the base and offset curves to construct the new object.
  4. Is the extrude direction vector stored in the JSON file, cannot find it

If you could help to propose a clear solution, that would be very nice :)

Thanks very much

karldd commented 3 years ago

The way I would tackle this, is to hack the reconverter example to, for every extrude, make a second extrude that is a separate body, and use that to extract the curves you want.

I actually made a quick example of this previously. Take a look at this code. And you could change it to something like:

        # Second extrude
        # Create a new body this time
        extrude_data["operation"] = "NewBodyFeatureOperation"
        extrude = self.importer.reconstruct_extrude_feature(
            extrude_data,
            extrude_uuid,
            extrude_index,
            sketch_profiles,
            second_extrude=True
        )

        # This will be P
        for face in extrude.startFaces:
                for edge in face.edges:
                        # Do something with the edge.geometry

        # This will be P_off
        for face in extrude.endFaces:
                for edge in face.edges:
                        # Do something with the edge.geometry

Doing it this way will handle all the different variations where P can be offset and by creating (then deleting) a new body you will always get the geometry even when the profile may not exist in the actual design. I'm not sure what it will do for symmetric extrudes, but probably won't be an issue.

  1. So if you do as suggested above BRepEdge.geometry is what you want. It will give you the Curve3D base class which has an evaluator if you want to sample line segments.
  2. I think it will be easier to pull the profiles from the extruded geometry here, reconstruct_sketch_curve() takes the geometry data from the json and draws it as a sketch.
  3. Yeap, this is what I would suggest (see above).
  4. The direction is not stored directly as it is simply normal to the sketch plane for a given signed distance defined as:
            "extent_one": {
                "distance": {
                    "type": "ModelParameter",
                    "value": -1.2,
                    "name": "d3",
                    "role": "AlongDistance"
                },

    So here it is going -1.2 cm, in the opposite direction to the sketch plane.

Enigma-li commented 3 years ago

Thanks very much! The solution via extracting from extrude is feasible. Actually, I also need the curves in the side faces, thus I would use extrude.faces to extract all the faces and sample the stroke lines from the resulting curves. Some of the models work well in this way, except there are cylinder side faces.

image image

What I want is to add any two 'paired profile curves' for a cylinder, as shown here: image

Regarding this problem, I have two following questions:

  1. Does the cylinder side face only contain the top and bottom two circles? Is there any way to hack a bit to add the paired lines from the extrude object?
  2. If no to questions 1, is it possible to first get the trimmed profiles, then get all the extrude parameters, and execute the extrude out-of-Fusion360, so that all the geometries can be accessed?

Any suggestions for solving this problem?

karldd commented 3 years ago

Thanks for the illustrations!

1: Yes that sounds right. Probably one 'hack' to get those lines would be to sample some points on the surface of the cylinder face and connect them. Take a look at this code here. Which will give you a grid like the one shown here.

You would need to do something to detect if it is a full cylinder.

if face.geometry.surfaceType == adsk.core.SurfaceTypes.CylinderSurfaceType:
   # do something here to check if the cylinder is partial or full?
   # then sample points to make extrude lines
  1. Its probably possible to do using py-occ but I haven't used it extensively. There are also a lot of edge cases to handle here (that we provide code for), so it would be a lot of work.
Enigma-li commented 3 years ago

Thanks very very much for your kind suggestions, I would try a bit 👍

Enigma-li commented 3 years ago

Update: There will be one issue when directly writing the newly added body/bodies into .smt or .step file.

The export function will reset the pointer of the current body, so that after executing the extrude operation, if there are two bodies, then you will not get the original second body. Sample code with this issue is shown below:

        # Create a new body this time
        extrude_data["operation"] = "NewBodyFeatureOperation"
        extrude = self.importer.reconstruct_extrude_feature(
            extrude_data,
            extrude_uuid,
            extrude_index,
            sketch_profiles,
            second_extrude=True
        )

       # TODO: Support export of multiple bodies
        for bcnt in range(len(extrude.bodies)):
            step_file = f"{self.json_file.stem}_{extrude_index:04}_{bcnt:04}.step"
            step_file_path = self.output_dir / step_file
            exporter.export_step_from_body(step_file_path, extrude.bodies[bcnt])

So either directly process the bodies data or add some check to the exporter?

karldd commented 3 years ago

Yes that sounds right, it looks like we are moving the body (rather than copying it) to a new component as the Fusion API doesn't support direct export of a body as a step/smt. https://github.com/AutodeskAILab/Fusion360GalleryDataset/blob/master/tools/common/exporter.py#L78

I think what you want to do is try to copy it instead, I haven't tested this:

transform = adsk.core.Matrix3D.create()
# Create a new component and occurrence of it at the root of the design
temp_occ = self.design.rootComponent.occurrences.addNewComponent(transform)
# Copy our body to the component
body.copyToComponent(temp_comp.component)
# Export STEP
step_export_options = self.design.exportManager.createSTEPExportOptions(str(file.resolve()), temp_comp.component)
design.exportManager.execute(step_export_options)
# Delete the temp component
temp_occ.deleteMe()

Its a bit long winded I know...

Enigma-li commented 3 years ago

That's true! I can directly process the data instead of exporting it, just want to report this in case someone else will encounter this problem later :)

Thanks very much for your kind and timely reply!