Extrude with cut in geometry module

Hi,
Does anyone know how to make a 3d model of a plate with a hole in it in the Geometry module?

In Autodeck Inventor this can easily be done by extruding a circle through a plate, using a boolean operation.

Is there a similar functionality in Viktor?

excellent question @jochem :slight_smile:

the geometry module has been created to make very simple geometries and does not support boolean operations. there are however 3rd party packages that do it and that you can use in a VIKTOR app. in particular CADQuery is a good fit for this.

make sure you list an external dependency in the viktor.config.toml file:

packages = ["libgl1"]

app.py:

from viktor import ViktorController
from viktor.parametrization import ViktorParametrization, NumberField
from viktor import Color
from viktor.geometry import Group, LinearPattern, SquareBeam, Material
from viktor.views import GeometryResult, GeometryView, ImageView, ImageResult
from viktor.core import File

import cadquery as cq

from pathlib import Path

import warnings
warnings.filterwarnings("ignore", category=UserWarning) 
warnings.filterwarnings("ignore", category=DeprecationWarning) 

class Parametrization(ViktorParametrization):
    length = NumberField("Length [mm]", default=30)
    height = NumberField("Height [mm]", default=40)
    bearing_diam = NumberField("Bearing diameter [mm]", default=22)
    thickness = NumberField("Thickness [mm]", default=10)
    padding = NumberField("Padding [mm]", default=8)
    fillet = NumberField("Fillet [mm]", default=2, num_decimals=1, step=0.5)


def generate_assembly(params):
    assy = cq.Assembly()

    (length, height, bearing_diam, thickness, padding) = (params.length, params.height, params.bearing_diam, params.thickness, params.padding)

    body = (
        cq.Workplane("XY")
        .box(length, height, thickness)
        .faces(">Z")
        .workplane()
        .hole(bearing_diam)
        .faces(">Z")
        .workplane()
        .rect(length - padding, height - padding, forConstruction=True)
        .vertices()
        .cboreHole(2.4, 4.4, 2.1)
        .edges("|Z")
        .fillet(params.fillet)
    )
    assy.add(body, color=cq.Color(1, 0.27, 0.0), name="body")
    return assy, body

GLTB_PATH = Path(__file__).parent / "output.gltb"
SVG_PATH = Path(__file__).parent / "output.svg"

class Controller(ViktorController):
    label = 'My Entity Type'
    parametrization = Parametrization

    @GeometryView("Geometry", duration_guess=1, x_axis_to_right=True)
    def get_geometry_view(self, params, **kwargs):
        assy, _ = generate_assembly(params)
        cq.occ_impl.exporters.assembly.exportGLTF(assy, str(GLTB_PATH), True)
        return GeometryResult(File.from_path(GLTB_PATH))
    

    @ImageView("Drawing", duration_guess=1)
    def create_result(self, params, **kwargs):
        _, body = generate_assembly(params)
        cq.exporters.export(body, str(SVG_PATH))

        return ImageResult(File.from_path(SVG_PATH))

This is the resulting view:

image

let me know if this works :slight_smile:

4 Likes

Hi Matthijs,
That worked! Thanks for the quick answer!
Kind regards, Jochem

1 Like