How to convert the python code to Julia

Dear team,

How to convert below mentioned code to Julia only without using Pycall module or any Python modules. Please help

import os
import vtk
import numpy as np

def process_jaw_stl(input_file, output_file, jaw_type, plane_normal, translation_vector, middle_z_offset=5, ver=10, hor=10, xas=10, top_margin=0.1, bottom_margin=0.1):
    reader = vtk.vtkSTLReader()
    reader.SetFileName(input_file)
    reader.Update()
    mesh = reader.GetOutput()

    transform = vtk.vtkTransform()
    transform.RotateX(90)  
    transform.Translate(xas, ver, hor) 

    transform_filter = vtk.vtkTransformPolyDataFilter()
    transform_filter.SetTransform(transform)
    transform_filter.SetInputData(mesh)
    transform_filter.Update()
    transformed_mesh = transform_filter.GetOutput()

    if jaw_type == 'upper':
        slice_plane = vtk.vtkPlane()
        slice_plane.SetOrigin(transformed_mesh.GetCenter())
        slice_plane.SetNormal(plane_normal)

        slicer = vtk.vtkClipPolyData()
        slicer.SetInputData(transformed_mesh)
        slicer.SetClipFunction(slice_plane)
        slicer.InsideOutOn()  
        slicer.Update()
        sliced_mesh = slicer.GetOutput()

        middle_clipper = vtk.vtkClipPolyData()
        middle_plane = vtk.vtkPlane()
        middle_plane.SetOrigin(sliced_mesh.GetCenter()[0], sliced_mesh.GetCenter()[1], sliced_mesh.GetCenter()[2] + middle_z_offset)
        middle_plane.SetNormal(0, 0, -1)

        middle_clipper.SetInputData(sliced_mesh)
        middle_clipper.SetClipFunction(middle_plane)
        middle_clipper.Update()
        middle_removed_mesh = middle_clipper.GetOutput()

        hole_filler = vtk.vtkFillHolesFilter()
        hole_filler.SetInputData(middle_removed_mesh)
        hole_filler.SetHoleSize(50000)  
        hole_filler.Update()
        filled_mesh = hole_filler.GetOutput()

    elif jaw_type == 'lower':
        bounds = transformed_mesh.GetBounds()
        centroid = [(bounds[0] + bounds[1]) / 2, (bounds[2] + bounds[3]) / 2, (bounds[4] + bounds[5]) / 2]

        clipper_bottom = vtk.vtkClipPolyData()
        clipper_bottom.SetInputData(transformed_mesh)
        plane_bottom = vtk.vtkPlane()
        plane_bottom.SetOrigin(0, 0, bounds[4] + bottom_margin)
        plane_bottom.SetNormal(0, 0, 1)
        clipper_bottom.SetClipFunction(plane_bottom)
        clipper_bottom.Update()
        clipped_mesh_bottom = clipper_bottom.GetOutput()

        clipper_top = vtk.vtkClipPolyData()
        clipper_top.SetInputData(clipped_mesh_bottom)
        plane_top = vtk.vtkPlane()
        plane_top.SetOrigin(0, 0, bounds[5] - top_margin)
        plane_top.SetNormal(0, 0, -1)
        clipper_top.SetClipFunction(plane_top)
        clipper_top.Update()
        final_clipped_mesh = clipper_top.GetOutput()

        middle_clipper = vtk.vtkClipPolyData()
        middle_plane = vtk.vtkPlane()
        middle_plane.SetOrigin(centroid[0], centroid[1], centroid[2] + middle_z_offset / 2)
        middle_plane.SetNormal(0, 0, 1)

        middle_clipper.SetInputData(final_clipped_mesh)
        middle_clipper.SetClipFunction(middle_plane)
        middle_clipper.InsideOutOff()
        middle_clipper.Update()
        middle_removed_mesh = middle_clipper.GetOutput()

        hole_filler = vtk.vtkFillHolesFilter()
        hole_filler.SetInputData(middle_removed_mesh)
        hole_filler.SetHoleSize(1000.0)
        hole_filler.Update()
        filled_mesh = hole_filler.GetOutput()

    normals = vtk.vtkPolyDataNormals()
    normals.SetInputData(filled_mesh)
    normals.SetFeatureAngle(30.0)
    normals.SplittingOff()
    normals.Update()
    final_mesh = normals.GetOutput()

    writer = vtk.vtkSTLWriter()
    writer.SetFileName(output_file)
    writer.SetInputData(final_mesh)
    writer.Write()
    print(f"Final STL saved to {output_file}")

def automate_jaw_processing(directory):
    stl_files = [f for f in os.listdir(directory) if f.endswith('.stl')]
    
    if len(stl_files) == 2:
        for stl_file in stl_files:
            input_path = os.path.join(directory, stl_file)
            if 'UpperJaw' in stl_file:
                output_path = os.path.join(directory, 'UpperJaw_Cleaned_Filled.stl')
                process_jaw_stl(
                    input_file=input_path,
                    output_file=output_path,
                    jaw_type='upper',
                    plane_normal=[0, 0, 1],
                    translation_vector=[0, 0, 10],
                    middle_z_offset=5,
                    ver=10,
                    hor=6,
                    xas=10
                )
            elif 'LowerJaw' in stl_file:
                output_path = os.path.join(directory, 'LowerJaw_Cleaned_Filled.stl')
                process_jaw_stl(
                    input_file=input_path,
                    output_file=output_path,
                    jaw_type='lower',
                    plane_normal=[0, 0, 1],
                    translation_vector=[0, 0, 25],
                    top_margin=0.13,
                    bottom_margin=0.13
                )
    else:
        print("Please ensure there are exactly two STL files in the directory, named appropriately with 'UpperJaw' and 'LowerJaw'.")

directory_path = r'C:\Users\OMG\Desktop\Dental STL-TEST'
automate_jaw_processing(directory_path)

Attached is the sample screenshot after importing Original files to Blender software

Thanks and regards

What’s the practical intention for deviating from an officially supported wrapper language for an optimized C++ library?

2 Likes

My main requirements are as follows:

  1. There are 2 stl files inside the path: ‘C:\Users\OMG\Desktop\Dental STL-TEST’

a. File: 17253853412024-09-03_001_TNS-FABIAN_BARAJA-LowerJaw.stl
b. File: 17253853422024-09-03_001_TNS-FABIAN_BARAJA-UpperJaw.stl

first stl file contains lower Jaw teeth model and second stl file contains upper Jaw teeth model

  1. Using Julia code, open any stl file either Lower or Upper jaw teeth

a. rotate the 3d object from horizontal to vertical stage
b. slice or cut the lower part (If used Lower Jaw stl file)
below is attached screenshot:

c. slice or cut the Upper part (If used Upper Jaw stl file)
below is attached screenshot:

  1. Once slicing is done, for Lower Jaw, It should look like attached (This one is working perfectly with python code):




  1. Once slicing is done, for Upper Jaw, It should look like attached (This one is working perfectly with python code):




Please note:
Same thing i wanted to do with Julia too and not using Pycall package

Please help
thanks and regards

you could use Makie to load those files, see mesh | Makie (the brain example).

note: for more formats see GitHub - JuliaIO/MeshIO.jl: IO for Meshes

  • cutting and slicing is another story :D.
1 Like

Thanks,
I tried using below code for rotating the object which is working fine.

using FileIO
using GeometryBasics

rotate_x(point::GeometryBasics.Point{3, Float32}, angle_deg::Float64) = GeometryBasics.Point3f(
    point[1],
    cos(deg2rad(angle_deg)) * point[2] - sin(deg2rad(angle_deg)) * point[3],
    sin(deg2rad(angle_deg)) * point[2] + cos(deg2rad(angle_deg)) * point[3]
)

function rotate_stl(input_file::String, output_file::String, rotation_angle_x::Float64)
    println("Processing STL file: $input_file")
    mesh = load(input_file)
    rotated_vertices = [rotate_x(v.position, rotation_angle_x) for v in GeometryBasics.coordinates(mesh)]
    save(output_file, GeometryBasics.Mesh(rotated_vertices, GeometryBasics.faces(mesh)))
    println("Rotated STL saved to: $output_file")
end

rotate_stl(
    "LowerJaw.stl",
    "rotated_lower_jaw.stl",
    90.0
)

Below is the output of rotated_lower_jaw.stl:

Please help with the slice / remove the bottom area of the 3d object Lower jaw teeth inside the stl file.

thanks and regards

1 Like