pythonocc-demos

repository·master·Indexed 43 days ago

https://github.com/tpaviot/pythonocc-demos

A collection of Python code snippets, scripts, and Jupyter notebooks demonstrating features of the pythonocc library. Examples cover 3D shape visualization using JupyterRenderer, Boolean operations with BRepAlgoAPI, shape unification via ShapeUpgrade_UnifySameDomain, and the construction of complex geometries like helices. Requires pythonocc-core version 7.8.1.

Tokens
12K
Snippets
35
Records
38
Agent score
55%

What's inside pythonocc-demos

  1. Run pythonocc feature examples

    master

    The examples/ directory contains small Python scripts that demonstrate specific pythonocc features. You can run them directly using a Python interpreter. For example, to run the 'hello world' script:

    1. Navigate to the examples directory.
    2. Execute the script with python.
    $ cd examples
    $ python core_helloworld.py
  2. Run pythonocc Jupyter Notebooks

    master

    The jupyter_notebooks/ directory contains examples designed to run within a Jupyter environment. To use these, you need jupyter and pythreejs installed.

    1. Navigate to the jupyter_notebooks directory.
    2. Launch the Jupyter notebook server.
    $ cd jupyter_notebooks
    $ jupyter notebook
  3. Configure normal rendering modes in JupyterRenderer

    master

    When using JupyterRenderer, you can control how normals are handled to change the visual appearance of faces:

    • NORMAL.CLIENT_SIDE: Used to clearly see individual faces by applying normals on the client side.
    • NORMAL.SERVER_SIDE: Results in vertex normals, which leads to a smooth rendering of the shape.
    from OCC.Display.WebGl.jupyter_renderer import JupyterRenderer, NORMAL
    
    # Example usage context:
    my_renderer = JupyterRenderer()
  4. Difference between splitting with a Face vs. a Wire frame

    master

    The type of shape used as the 'tool' in BOPAlgo_Splitter significantly changes the outcome:

    • Splitting with a Face: The tool acts as a solid surface. This cuts the argument solid into multiple distinct pieces (e.g., an upper and lower half-box), resulting in a TopoDS_Compound of multiple solids.
    • Splitting with a Wire frame: The tool acts only as a collection of edges. This does not cut the solid into separate pieces; instead, it only cuts the surfaces of the solid. The resulting shape remains a single TopoDS_Solid with modified surface geometry.
  5. Quickstart: Displaying 3D shapes in Jupyter Notebooks

    master

    To visualize OpenCASCADE shapes within a Jupyter Notebook, use the JupyterRenderer from OCC.Display.WebGl.jupyter_renderer. This allows you to render primitives (like boxes, spheres, or cylinders) and points directly in the notebook cell output using WebGL.

    Basic workflow:

    1. Initialize the JupyterRenderer.
    2. Create shapes using BRepPrimAPI classes.
    3. Use DisplayShape() to render the geometry.
    from OCC.Display.WebGl.jupyter_renderer import JupyterRenderer
    from OCC.Core.BRepPrimAPI import BRepPrimAPI_MakeBox, BRepPrimAPI_MakeCylinder
    from OCC.Core.gp import gp_Pnt
    
    # 1. Initialize renderer
    my_renderer = JupyterRenderer()
    
    # 2. Create shapes
    box_shape = BRepPrimAPI_MakeBox(10, 20, 30).Shape()
    cylinder_shape = BRepPrimAPI_MakeCylinder(10, 30).Shape()
    
    # 3. Display shapes
    my_renderer.DisplayShape(box_shape)
    my_renderer.DisplayShape(cylinder_shape)
  6. Display 3D shapes as SVG in Jupyter Notebooks

    master

    You can render 3D shapes as SVG images directly within a Jupyter Notebook using the JupyterRenderer class and the export_shape_to_svg utility. This is useful for static, high-quality vector representations of CAD models.

    To use this, you need to:

    1. Initialize a JupyterRenderer instance.
    2. Load your shape (e.g., using read_step_file).
    3. Call DisplayShapeAsSVG on the renderer instance, specifying the shape and visual parameters like viewing direction and line width.
    import os
    from OCC.Core.gp import gp_Dir
    from OCC.Display.WebGl.jupyter_renderer import JupyterRenderer
    from OCC.Extend.DataExchange import read_step_file, export_shape_to_svg
    
    # 1. Initialize the renderer
    my_renderer = JupyterRenderer()
    
    # 2. Load a shape (e.g., from a STEP file)
    robot_shp = read_step_file(os.path.join("..", "assets", "models", "KR600_R2830-4.stp"))
    
    # 3. Display the shape as an SVG
    my_renderer.DisplayShapeAsSVG(
        robot_shp, 
        direction=gp_Dir(1, 1, 0.1), 
        export_hidden_edges=False, 
        line_width=1.5
    )
  7. Visualize mesh quality in Jupyter using JupyterRenderer

    master

    You can visualize and compare the mesh quality of different shapes in a Jupyter notebook using the JupyterRenderer. By adjusting the quality parameter in DisplayShape, you can control the density of the mesh.

    When creating multiple shapes from a single base shape (e.g., using translate_shp), ensure you set copy=True to prevent all shapes from sharing the same underlying mesh data, which would make independent quality adjustments impossible.

    To control how normals are rendered:

    • Use NORMAL.CLIENT_SIDE to see individual faces clearly (useful for inspecting mesh density).
    • Use NORMAL.SERVER_SIDE for smooth rendering (vertex normals).
    from OCC.Core.BRepPrimAPI import BRepPrimAPI_MakeTorus
    from OCC.Core.gp import gp_Vec
    from OCC.Display.WebGl.jupyter_renderer import JupyterRenderer, NORMAL
    from OCC.Extend.ShapeFactory import translate_shp
    
    # Create base shape
    torus_shp1 = BRepPrimAPI_MakeTorus(20, 5).Shape()
    
    # Create copies with different translations to allow independent mesh quality
    torus_shp2 = translate_shp(torus_shp1, gp_Vec(60, 0, 0), copy=True)
    torus_shp3 = translate_shp(torus_shp1, gp_Vec(-60, 0, 0), copy=True)
    
    # Initialize renderer with CLIENT_SIDE normals to inspect faces
    my_renderer = JupyterRenderer(compute_normals_mode=NORMAL.CLIENT_SIDE)
    
    # Display shapes with varying mesh quality levels
    my_renderer.DisplayShape(torus_shp1, shape_color="blue", topo_level="Face", quality=1.0)
    my_renderer.DisplayShape(torus_shp2, shape_color="red", quality=4.0)  # Lower quality
    my_renderer.DisplayShape(torus_shp3, shape_color="green", quality=0.5) # Higher quality
    
    my_renderer.Display()
  8. Initialize JupyterRenderer for shape visualization

    master

    To visualize OpenCASCADE shapes within a Jupyter Notebook environment, use the JupyterRenderer from OCC.Display.WebGl.jupyter_renderer. This allows for interactive 3D rendering of shapes directly in the notebook cells.

    from OCC.Display.WebGl.jupyter_renderer import JupyterRenderer
    
    my_renderer = JupyterRenderer()
    # After creating a shape 'shp':
    my_renderer.DisplayShape(shp, render_edges=True, update=True)
  9. Load and display a STEP file in a Jupyter Notebook

    master

    To visualize a STEP file within a Jupyter Notebook environment, use read_step_file from OCC.Extend.DataExchange to load the geometry, and JupyterRenderer from OCC.Display.WebGl.jupyter_renderer to render it.

    1. Load the shape using read_step_file(path).
    2. Initialize a JupyterRenderer with a specified size (width, height).
    3. Use DisplayShape(shape, render_edges=True) to add the geometry to the renderer.
    4. Call Display() to render the interactive WebGL view in the notebook cell output.
    import os.path
    from OCC.Display.WebGl.jupyter_renderer import JupyterRenderer
    from OCC.Extend.DataExchange import read_step_file
    
    # Load the STEP file
    shp = read_step_file(
        os.path.join("..", "assets", "models", "RC_Buggy_2_front_suspension.stp")
    )
    
    # Initialize the Jupyter renderer
    my_renderer = JupyterRenderer(size=(800, 700))
    
    # Add the shape to the renderer
    my_renderer.DisplayShape(shp, render_edges=True)
    
    # Render the interactive view
    my_renderer.Display()
  10. Compute shape sections and slices using BRepAlgoAPI_Section

    master

    You can use BRepAlgoAPI_Section to perform slicing operations by intersecting a shape with a plane or another geometry.

    To perform a manual slice (e.g., slicing a sphere with a series of planes):

    1. Define a direction (gp_Dir) and a series of points (gp_Pnt) to create planes.
    2. Create a plane shape using BRepBuilderAPI_MakeFace from the plane definition (gp_Pln).
    3. Use BRepAlgoAPI_Section(shape, face) to compute the intersection.
    4. Check IsDone() to ensure the computation succeeded before retrieving the shape.

    For more complex intersections (like a Torus and a Sphere), you can use advanced methods on the section object:

    • ComputePCurveOn1(True): Computes the P-curve on the first shape.
    • Approximation(True): Enables approximation for the resulting curves.
    • Build(): Executes the computation.
    from OCC.Core.BRepAlgoAPI import BRepAlgoAPI_Section
    from OCC.Core.BRepBuilderAPI import BRepBuilderAPI_MakeFace
    from OCC.Core.gp import gp_Pnt, gp_Dir, gp_Pln
    
    # Slicing a sphere with a plane
    shape = BRepPrimAPI_MakeSphere(60.0).Shape()
    D = gp_Dir(0.0, 0.0, 1.0)
    for z in range(-100, 100, 5):
        P = gp_Pnt(0, 0, z)
        Pln = gp_Pln(P, D)
        face = BRepBuilderAPI_MakeFace(Pln).Shape()
        
        section_shp = BRepAlgoAPI_Section(shape, face)
        if section_shp.IsDone():
            section_shape = section_shp.Shape()
  11. Generate a triangle mesh using Gmsh and OpenCASCADE

    master

    You can convert an OpenCASCADE shape into a triangle mesh (STL) by following these steps:

    1. Export the shape to a BREP file: Use breptools.Write to save the geometry to a temporary file.
    2. Create a Gmsh .geo script: Write a Gmsh script using the SetFactory("OpenCASCADE") command. This allows Gmsh to read the BREP file directly.
    3. Execute Gmsh via CLI: Call the gmsh binary from Python using os.system to process the .geo file and output an .stl file.
    4. Re-import the mesh: Use read_stl_file to load the resulting STL back into an OpenCASCADE shape for visualization or further processing.

    Note: Ensure the gmsh binary is installed and accessible in your system path.

    # 1. Export to BREP
    BREP_FILENAME = os.path.join(TMP_DIR, "ventilator.brep")
    breptools.Write(ventilator_shp, BREP_FILENAME)
    
    # 2. Create Gmsh .geo file
    gmsh_file_content = (
        """SetFactory(\"OpenCASCADE\");\n\n"
        "Mesh.CharacteristicLengthMin = 1;\n"
        "Mesh.CharacteristicLengthMax = 5;\n\n"
        "a() = ShapeFromFile('%s');\n"
        """
        % "ventilator.brep"
    )
    GEO_FILENAME = os.path.join(TMP_DIR, "ventilator.geo")
    with open(GEO_FILENAME, "w") as f:
        f.write(gmsh_file_content)
    
    # 3. Call Gmsh to generate STL
    STL_FILENAME = os.path.join(TMP_DIR, "ventilator.stl")
    os.system("%s %s -2 -o %s -format stl" % (GMSH_BINARY, GEO_FILENAME, STL_FILENAME))
    
    # 4. Load the STL
    meshed_ventilator_shp = read_stl_file(STL_FILENAME)