diff --git a/assets/illustration/meshbit_illustration/meshbit_illustration.3dm b/assets/illustration/meshbit_illustration/meshbit_illustration.3dm index 10ed1c69..9c10e294 100644 Binary files a/assets/illustration/meshbit_illustration/meshbit_illustration.3dm and b/assets/illustration/meshbit_illustration/meshbit_illustration.3dm differ diff --git a/assets/illustration/meshbit_illustration/meshbit_illustration.3dm.rhl b/assets/illustration/meshbit_illustration/meshbit_illustration.3dm.rhl index ad4022d7..18ae39a8 100644 --- a/assets/illustration/meshbit_illustration/meshbit_illustration.3dm.rhl +++ b/assets/illustration/meshbit_illustration/meshbit_illustration.3dm.rhl @@ -1,3 +1,3 @@ andre LAPTOP-RR341PAC -Saturday, December 21, 2024 \ No newline at end of file +Sunday, December 22, 2024 \ No newline at end of file diff --git a/assets/illustration/meshbit_illustration/meshbit_illustration.3dmbak b/assets/illustration/meshbit_illustration/meshbit_illustration.3dmbak new file mode 100644 index 00000000..14fb669b Binary files /dev/null and b/assets/illustration/meshbit_illustration/meshbit_illustration.3dmbak differ diff --git a/assets/illustration/meshbit_illustration/meshbit_illustration_v2.3dm b/assets/illustration/meshbit_illustration/meshbit_illustration_v2.3dm new file mode 100644 index 00000000..71b6f9d0 Binary files /dev/null and b/assets/illustration/meshbit_illustration/meshbit_illustration_v2.3dm differ diff --git a/assets/illustration/meshbit_illustration/meshbit_illustration_v2.3dm.rhl b/assets/illustration/meshbit_illustration/meshbit_illustration_v2.3dm.rhl new file mode 100644 index 00000000..18ae39a8 --- /dev/null +++ b/assets/illustration/meshbit_illustration/meshbit_illustration_v2.3dm.rhl @@ -0,0 +1,3 @@ +andre +LAPTOP-RR341PAC +Sunday, December 22, 2024 \ No newline at end of file diff --git a/assets/illustration/meshbit_illustration/meshbit_illustration_v2.3dmbak b/assets/illustration/meshbit_illustration/meshbit_illustration_v2.3dmbak new file mode 100644 index 00000000..0f4bc8d8 Binary files /dev/null and b/assets/illustration/meshbit_illustration/meshbit_illustration_v2.3dmbak differ diff --git a/assets/illustration/meshbit_illustration/moveit.py b/assets/illustration/meshbit_illustration/moveit.py new file mode 100644 index 00000000..35824899 --- /dev/null +++ b/assets/illustration/meshbit_illustration/moveit.py @@ -0,0 +1,200 @@ +#! python3 +#r: pillow +#r: Wand + +import System +import System.Drawing + +import math +import sys +import os + +from wand.image import Image +from wand.api import library + +import Rhino +import Rhino.Geometry as rg +import rhinoscriptsyntax as rs + + +def gaussian(x, mu, sigma): + return (1.0 / (sigma * math.sqrt(2 * math.pi))) * math.exp(-0.5 * ((x - mu) / sigma) ** 2) + +def print_progress_bar( + iteration, total, + prefix='', suffix='', + decimals=1, length=10, + fill='▒', empty='■'): + percent = ("{0:." + str(decimals) + "f}").format(100 * (iteration / float(total))) + filled_length = int(length * iteration // total) + bar = fill * filled_length + empty * (length - filled_length) + Rhino.RhinoApp.SetCommandPrompt(f'{prefix} |{bar}| {percent}% {suffix}') + if iteration == total: + Rhino.RhinoApp.SetCommandPrompt(f'{prefix} |{bar}| {percent}% {suffix}\n') + +def main() -> None: + #------------------------------------------------------------ + # Rhin commandline options + #------------------------------------------------------------ + start_log = \ + ">" * 60 + \ + r""" + __ __ __ + >-->--> .--------..-----..--.--..-----. |__|| |_ | | >-->--> + >-->--> | || _ || | || -__| | || _| |__| >-->--> + >-->--> |__|__|__||_____| \___/ |_____| |__||____| |__| >-->--> + """ + "\n" + \ + "Author: @AndreaSettimi: andrea.settimi@epfl.ch (IBOIS,EPFL)" + "\n" + \ + "Description: Animate a mesh object in Rhino and save the animation as a gif." + "\n" + \ + "Usage: Select an object to animate and set the options." + "\n" + \ + ">" * 60 + print(start_log) + + go = Rhino.Input.Custom.GetObject() + go.SetCommandPrompt("Select object to animate") + go.AcceptNothing(True) + go.ClearCommandOptions() + go.EnableHighlight(False) + __OPT_is_saving_gif = Rhino.Input.Custom.OptionToggle(False, "Off", "On") + __OPT_transparent_background = Rhino.Input.Custom.OptionToggle(True, "Off", "On") + __OPT_fps = Rhino.Input.Custom.OptionInteger(30, 0, 120) + __OPT_duration = Rhino.Input.Custom.OptionInteger(3500, 1, 10000) + _build_folder = os.path.dirname(Rhino.RhinoDoc.ActiveDoc.Path) + __OPT_width = Rhino.Input.Custom.OptionInteger(1500, 1, 5000) + __OPT_height = Rhino.Input.Custom.OptionInteger(1500, 1, 5000) + go.AddOptionToggle("isSavingGif", __OPT_is_saving_gif) + go.AddOptionToggle("TransparentBackground", __OPT_transparent_background) + go.AddOptionInteger("Fps", __OPT_fps) + go.AddOptionInteger("Duration_ms", __OPT_duration) + go.AddOption("BuildDirectory") + go.AddOptionInteger("Width", __OPT_width) + go.AddOptionInteger("Height", __OPT_height) + while True: + get_rc: Rhino.Input.GetResult = go.Get() + if go.CommandResult() == Rhino.Commands.Result.Cancel: + return go.CommandResult() + if get_rc == Rhino.Input.GetResult.Object: + break + elif get_rc == Rhino.Input.GetResult.Cancel: + return Rhino.Commands.Result.Cancel + elif get_rc == Rhino.Input.GetResult.Option: + option = go.Option().EnglishName + if option == "BuildDirectory": + folder = rs.BrowseForFolder("Select folder to save the animation") + if folder: + _build_folder = folder + continue + break + + go.Get() + obj_ref = go.Object(0) + mesh = obj_ref.Mesh() + + _is_saving_gif = __OPT_is_saving_gif.CurrentValue + _transparent_background = __OPT_transparent_background.CurrentValue + _fps = __OPT_fps.CurrentValue + _duration = __OPT_duration.CurrentValue + _width = __OPT_width.CurrentValue + _height = __OPT_height.CurrentValue + num_frames = int(_fps * (_duration / 1000)) + gif_delay = int(1000 / _fps) // 10 + print("\nOptions values:") + print(f"\tSaving gif: {_is_saving_gif}") + print(f"\tTransparent background: {_transparent_background}") + print(f"\tFPS: {_fps}") + print(f"\tNumber of frames: {num_frames}") + print(f"\tGif delay (hundredths secs): {gif_delay}") + print(f"\tDuration: {_duration}") + print(f"\tWidth: {_width}") + print(f"\tHeight: {_height}\n") + + build_folder = os.path.join(_build_folder, "build") + if os.path.exists(build_folder): + for file in os.listdir(build_folder): + os.remove(os.path.join(build_folder, file)) + else: + os.makedirs(build_folder) + + if _is_saving_gif: + view = Rhino.RhinoDoc.ActiveDoc.Views.ActiveView + if view is None: + raise Exception("No active view found") + view_capture = Rhino.Display.ViewCapture() + view_capture.Width = _width + view_capture.Height = _height + view_capture.ScaleScreenItems = False + view_capture.DrawAxes = False + view_capture.DrawGrid = False + view_capture.DrawGridAxes = False + view_capture.TransparentBackground = _transparent_background + + #------------------------------------------------------------ + # Animation + save bitmpas on memory + #------------------------------------------------------------ + # FIXME: add sub-options for rotation + total_rotation = 360 # << input (default: 360) + + mu = num_frames // 2 + sigma = num_frames // 6 + gaussian_values = [gaussian(x, mu, sigma) for x in range(num_frames)] + max_gaussian = max(gaussian_values) + normalized_gaussian_values = [val / max_gaussian for val in gaussian_values] + total_gaussian_sum = sum(normalized_gaussian_values) + normalized_gaussian_values = [val / total_gaussian_sum for val in normalized_gaussian_values] + + total_angle = 0 + mesh_ctr = mesh.GetBoundingBox(True).Center + for i in range(num_frames): + angle = normalized_gaussian_values[i] * total_rotation # scale the angle by the Gaussian value + total_angle += angle + xform = rg.Transform.Rotation(math.radians(angle), rg.Vector3d.ZAxis, mesh_ctr) + mesh.Transform(xform) + Rhino.RhinoDoc.ActiveDoc.Objects.Replace(obj_ref, mesh) + Rhino.RhinoDoc.ActiveDoc.Views.Redraw() + + if _is_saving_gif: + bitmap = view_capture.CaptureToBitmap(view) + if bitmap is None: + raise Exception("Failed to capture view to bitmap") + bitmap.Save(os.path.join(build_folder, f"frame_{i}.png"), System.Drawing.Imaging.ImageFormat.Png) + print_progress_bar(i + 1, num_frames, prefix='Animate:', suffix='Complete') + rs.Sleep(1) + + rs.UnselectAllObjects() + + #------------------------------------------------------------ + # Bake gif + #------------------------------------------------------------ + if _is_saving_gif: + gif_path = os.path.join(build_folder, "animation.gif") + frames = [os.path.join(build_folder, f"frame_{i}.png") for i in range(num_frames)] + + with Image() as new_gif: + arg2 = library.NewPixelWand() + library.MagickSetOption( + new_gif.wand, + b"dispose", + b"2" + ) + for img_path in frames: + library.MagickReadImage( + new_gif.wand, + img_path.encode('utf-8') + ) + new_gif.delay = gif_delay + print_progress_bar(frames.index(img_path) + 1, len(frames), prefix='Saving:', suffix='Complete') + rs.Sleep(1) + Rhino.RhinoApp.SetCommandPrompt("Saving gif, please wait..") + new_gif.save(filename=gif_path) + + for frame in frames: + os.remove(frame) + + os.system(f"start {gif_path}") + print(f"Animation saved to: {gif_path}") + + print("Closing moveit.") + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/assets/illustration/meshbit_illustration/twist_drill_bit_32_165/twist_drill_bit_32_165/metadata.acit b/assets/illustration/meshbit_illustration/twist_drill_bit_32_165/twist_drill_bit_32_165/metadata.acit new file mode 100644 index 00000000..2cd5f625 --- /dev/null +++ b/assets/illustration/meshbit_illustration/twist_drill_bit_32_165/twist_drill_bit_32_165/metadata.acit @@ -0,0 +1,9 @@ + + + 0 0 0 + 0 0 0.162 + 0 0 0.149602 + 0 0 0.0399 + 0.025 + + diff --git a/assets/illustration/meshbit_illustration/twist_drill_bit_32_165/twist_drill_bit_32_165/model.initpose b/assets/illustration/meshbit_illustration/twist_drill_bit_32_165/twist_drill_bit_32_165/model.initpose new file mode 100644 index 00000000..5cd46489 --- /dev/null +++ b/assets/illustration/meshbit_illustration/twist_drill_bit_32_165/twist_drill_bit_32_165/model.initpose @@ -0,0 +1,3 @@ + - [ 9.50834990e-01, 2.37247661e-01, -1.99040413e-01, 2.44926587e-02, + -6.98316872e-01, -7.15365469e-01, -3.08712870e-01, 6.75321281e-01, + -6.69801235e-01, -2.26506889e-02, 2.32661795e-02, 1.76990986e-01 ] \ No newline at end of file diff --git a/assets/illustration/meshbit_illustration/twist_drill_bit_32_165/twist_drill_bit_32_165/model.jpg b/assets/illustration/meshbit_illustration/twist_drill_bit_32_165/twist_drill_bit_32_165/model.jpg new file mode 100644 index 00000000..15697841 Binary files /dev/null and b/assets/illustration/meshbit_illustration/twist_drill_bit_32_165/twist_drill_bit_32_165/model.jpg differ diff --git a/assets/illustration/meshbit_illustration/twist_drill_bit_32_165/twist_drill_bit_32_165/model.mtl b/assets/illustration/meshbit_illustration/twist_drill_bit_32_165/twist_drill_bit_32_165/model.mtl new file mode 100644 index 00000000..9724b7f4 --- /dev/null +++ b/assets/illustration/meshbit_illustration/twist_drill_bit_32_165/twist_drill_bit_32_165/model.mtl @@ -0,0 +1,12 @@ +# Blender 3.6.0 MTL File: 'reformatter_dataset.blend' +# www.blender.org + +newmtl model.004 +Ns 0.000000 +Ka 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ke 0.000000 0.000000 0.000000 +Ni 1.450000 +d 1.000000 +illum 1 +map_Kd C:/Users/localuser/TTool/assets/toolheads_rework/ck30/model.jpg diff --git a/assets/illustration/meshbit_illustration/twist_drill_bit_32_165/twist_drill_bit_32_165/model_occlusion.jpg b/assets/illustration/meshbit_illustration/twist_drill_bit_32_165/twist_drill_bit_32_165/model_occlusion.jpg new file mode 100644 index 00000000..184b48b5 Binary files /dev/null and b/assets/illustration/meshbit_illustration/twist_drill_bit_32_165/twist_drill_bit_32_165/model_occlusion.jpg differ diff --git a/assets/illustration/mounts/drawings_illustration_total_mounts.3dm b/assets/illustration/mounts/drawings_illustration_total_mounts.3dm new file mode 100644 index 00000000..3b68f326 Binary files /dev/null and b/assets/illustration/mounts/drawings_illustration_total_mounts.3dm differ diff --git a/docs/assets/images/getting_started/drill_anim.gif b/docs/assets/images/getting_started/drill_anim.gif new file mode 100644 index 00000000..08d7ef98 Binary files /dev/null and b/docs/assets/images/getting_started/drill_anim.gif differ diff --git a/docs/assets/images/test/test_cat.gif b/docs/assets/images/test/test_cat.gif new file mode 100644 index 00000000..4cf8e1d8 Binary files /dev/null and b/docs/assets/images/test/test_cat.gif differ diff --git a/docs/changelog/index.md b/docs/changelog/index.md index 1fb8a55d..2450aa0f 100644 Binary files a/docs/changelog/index.md and b/docs/changelog/index.md differ diff --git a/docs/hardware/woodworking-tools.md b/docs/hardware/woodworking-tools.md index 0ee91628..8e073713 100644 --- a/docs/hardware/woodworking-tools.md +++ b/docs/hardware/woodworking-tools.md @@ -25,25 +25,35 @@ If you want to add your own 3d-printable mount or tool head model and share it w /// html | div[style='clear: both;'] /// + -## Available Toolheads - -The following is a list of the available toolheads that are already integrated into the AC system. You will need to use or acquire the corresponding physical toolhead to use the AC system. +## Available Toolheads -The Zenodo repository containing the dataset is [here](https://zenodo.org/records/12578820). +/// html | div[style='float: left; width: 52%;'] - +The following is a list of the available toolheads that are already integrated into the AC system. You will need to use or acquire the corresponding physical toolhead to use the AC system. Each toolhead is digitize and integrated to the dataset, the digital model is necessary to allow AC to detect the 3D position of the toolhead from the sensor stream. The Zenodo repository containing the dataset is [here](https://zenodo.org/records/12578820). -{{ run_python_script('docs/scripts/get_zenodo_toolheads.py') }} +!!! note "Toolhead integration" + If you want to know more about the details of the integration and how toolhead are managed in the AC system, you can read the [developer guide](../developer-guide/toolheads.md). !!! tip "Want to add a new toolhead?" If you want to add your own toolhead to the AC system, follow the instructions in the section [contributing](../contributing/index.md). -!!! note "Toolhead integration" - If you want to know more about the details of the integration and how toolhead are managed in the AC system, you can read the [developer guide](../developer-guide/toolheads.md). +/// + +/// html | div[style='float: right;width: 45%;'] + +![rotating model drill bit](../assets/images/getting_started/drill_anim.gif){width="500" class="rounded-corners"} +/// + +/// html | div[style='clear: both;'] +/// + + +{{ run_python_script('docs/scripts/get_zenodo_toolheads.py') }} ## Available 3D mounts @@ -60,15 +70,12 @@ Each mount is designed with a flexible integration mechanism, allowing for the a The Zenodo repository containing the dataset is [here](https://zenodo.org/records/14531724). -For convinience, here is a list of the available mounts regrouped by brands: - -{{ run_python_script('docs/scripts/get_zenodo_mounts.py') }} - !!! tip "Want to add a new mount?" If you want to add your own toolhead to the AC system, follow the instructions in the section [contributing](../contributing/index.md). - +{{ run_python_script('docs/scripts/get_zenodo_mounts.py') }} + ## Components list diff --git a/mkdocs.yml b/mkdocs.yml index 31d00d3c..4e5de65e 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -272,5 +272,5 @@ nav: - Publications: publications/index.md - - Team: + - Research team: - team/index.md