diff --git a/docs/sliding_t_nut.png b/docs/sliding_t_nut.png
new file mode 100644
index 0000000..7901396
Binary files /dev/null and b/docs/sliding_t_nut.png differ
diff --git a/readme.md b/readme.md
index 6d9f2c2..2c9cd07 100644
--- a/readme.md
+++ b/readme.md
@@ -25,26 +25,26 @@ A list of changes classified as breaking, additions or fixes is maintained in [C
Antennas | Inserts | Rails | Butt_box | Bezier | Clip |
Axials | Jack | Ring_terminals | Cable_clip | Catenary | Global |
BLDC_motors | LDRs | Rockers | Cable_grommets | Core_xy | Polyholes |
- Ball_bearings | LED_meters | Rod | Camera_housing | Dogbones | Rounded_rectangle |
- Batteries | LEDs | Rod_ends | Carriers | Fillet | Sphere |
- Bearing_blocks | Leadnuts | SBR_rails | Corner_block | Gears | Teardrops |
- Belts | Light_strips | SK_brackets | Door_hinge | Hanging_hole | |
- Blowers | Linear_bearings | SMDs | Door_latch | Horiholes | |
- Box_sections | Magnets | SSRs | Drag_chain | Layout | |
- Bulldogs | Mains_sockets | Screws | Fan_guard | Maths | |
- Buttons | Microswitches | Sealing_strip | Fixing_block | Offset | |
- Cable_strips | Microview | Servo_motors | Flat_hinge | PCB_utils | |
- Cameras | Modules | Shaft_couplings | Foot | Quadrant | |
- Circlips | Nuts | Sheets | Handle | Round | |
- Components | O_ring | Spades | Knob | Rounded_cylinder | |
- DIP | Opengrab | Spools | LED_bezel | Rounded_polygon | |
- D_connectors | PCB | Springs | PCB_mount | Rounded_triangle | |
- Displays | PCBs | Stepper_motors | PSU_shroud | Sector | |
- Extrusion_brackets | PSUs | Swiss_clips | Pocket_handle | Splines | |
- Extrusions | Panel_meters | Terminals | Press_fit | Sweep | |
- Fans | Photo_interrupters | Toggles | Printed_box | Thread | |
- Fastons | Pillars | Transformers | Printed_pulleys | Tube | |
- Fuseholder | Pillow_blocks | Ttracks | Ribbon_clamp | | |
+ Ball_bearings | LED_meters | Rod | Camera_housing | Dimension | Rounded_rectangle |
+ Batteries | LEDs | Rod_ends | Carriers | Dogbones | Sphere |
+ Bearing_blocks | Leadnuts | SBR_rails | Corner_block | Fillet | Teardrops |
+ Belts | Light_strips | SK_brackets | Door_hinge | Gears | |
+ Blowers | Linear_bearings | SMDs | Door_latch | Hanging_hole | |
+ Box_sections | Magnets | SSRs | Drag_chain | Horiholes | |
+ Bulldogs | Mains_sockets | Screws | Fan_guard | Layout | |
+ Buttons | Microswitches | Sealing_strip | Fixing_block | Maths | |
+ Cable_strips | Microview | Servo_motors | Flat_hinge | Offset | |
+ Cameras | Modules | Shaft_couplings | Foot | PCB_utils | |
+ Circlips | Nuts | Sheets | Handle | Quadrant | |
+ Components | O_ring | Spades | Knob | Round | |
+ DIP | Opengrab | Spools | LED_bezel | Rounded_cylinder | |
+ D_connectors | PCB | Springs | PCB_mount | Rounded_polygon | |
+ Displays | PCBs | Stepper_motors | PSU_shroud | Rounded_triangle | |
+ Extrusion_brackets | PSUs | Swiss_clips | Pocket_handle | Sector | |
+ Extrusions | Panel_meters | Terminals | Press_fit | Splines | |
+ Fans | Photo_interrupters | Toggles | Printed_box | Sweep | |
+ Fastons | Pillars | Transformers | Printed_pulleys | Thread | |
+ Fuseholder | Pillow_blocks | Ttracks | Ribbon_clamp | Tube | |
Gear_motors | Pin_headers | Tubings | SSR_shroud | | |
Geared_steppers | Potentiometers | Variacs | Screw_knob | | |
Green_terminals | Pulleys | Veroboard | Socket_box | | |
@@ -2460,6 +2460,10 @@ Default is steel but can be drawn as brass or nylon. A utility for making nut tr
If a nut is given a child then it gets placed on its top surface.
+The following diagram shows you the parameters for drawing a sliding_t_nut:
+
+
+
[vitamins/nuts.scad](vitamins/nuts.scad) Object definitions.
[vitamins/nut.scad](vitamins/nut.scad) Implementation.
@@ -7242,6 +7246,35 @@ allows flexible positioning of the motors.
| 6 | `NEMA(NEMA17_40)` | Stepper motor NEMA17 x 40mm (5x20 shaft) |
+Top
+
+---
+
+## Dimension
+Modules for adding dimensions to assembly views.
+
+
+
+* If `text` is empty, will display the measured distance.
+* `offset` will determine how much space is between the measured point and the dimension.
+* `thickness` is the thickness of the lines, and size of the arrows, if 0, will use 0.5% of the length of the dim.
+* `text_size` will determine the size of the text, if 0, will use percentage of the length of the dim.
+
+[utils/dimension.scad](utils/dimension.scad) Implementation.
+
+[tests/dimension.scad](tests/dimension.scad) Code for this example.
+
+### Modules
+| Module | Description |
+|:--- |:--- |
+| `dimension(startpoint, endpoint, text = "", thickness = 0, text_size = 0 , rot_around_dim = 0)` | Creates a 3D dimension between two points. |
+| `dimension_x(startpoint, endpoint, offset = 1, text = "", thickness = 0, text_size = 0 , plane = "xy")` | Creates a dimension in the x direction. Plane options : xy, xz |
+| `dimension_y(startpoint, endpoint, offset = 1, text = "", thickness = 0, text_size = 0 , plane = "xy")` | Creates a dimension in the y direction. Plane options : xy, yz |
+| `dimension_z(startpoint, endpoint, offset = 1, text = "", thickness = 0, text_size = 0 , plane = "xz")` | Creates a dimension in the z direction. Plane options : xz, yz |
+
+
+
+
Top
---
diff --git a/tests/dimension.scad b/tests/dimension.scad
new file mode 100644
index 0000000..eefeec5
--- /dev/null
+++ b/tests/dimension.scad
@@ -0,0 +1,79 @@
+//
+// NopSCADlib Copyright Chris Palmer 2025
+// nop.head@gmail.com
+// hydraraptor.blogspot.com
+//
+// This file is part of NopSCADlib.
+//
+// NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the
+// GNU General Public License as published by the Free Software Foundation, either version 3 of
+// the License, or (at your option) any later version.
+//
+// NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along with NopSCADlib.
+// If not, see .
+//
+include <../utils/core/core.scad>
+use <../utils/dimension.scad>
+
+
+module dimensions_3d_xy() {
+ dimension([0,0,0], [10,10,0], "", 0.2);
+ dimension([0,0,0], [10,-10,0], "", 0.2);
+ dimension([0,0,0], [-10,10,0], "");
+ dimension([0,0,0], [-10,-10,0], "");
+
+
+ dimension([0,0,0], [0,10,0], "");
+ dimension([0,0,0], [0,-10,0], "");
+ dimension([0,0,0], [10,0,0], "",rot_around_dim=0);
+ dimension([0,0,0], [-10,0,0], "", rot_around_dim=90);
+}
+
+module dimensions_3d_xyz() {
+ dimension([0,0,0], [10,10,10], "");
+ dimension([0,0,0], [10,-10,10], "");
+ dimension([0,0,0], [-10,10,10], "");
+ dimension([0,0,0], [-10,-10,10], "");
+
+ dimension([0,0,0], [10,10,-10], "");
+ dimension([0,0,0], [10,-10,-10], "");
+ dimension([0,0,0], [-10,10,-10], "");
+ dimension([0,0,0], [-10,-10,-10], "", rot_around_dim=45);
+
+ dimension([0,0,0], [-3,0,10], "");
+ dimension([0,0,0], [0,0,-10], "");
+
+ dimension([0,0,0], [0,2,10], "");
+ dimension([0,0,0], [0,2,-10], "");
+
+}
+
+module dimension_1d_x() {
+ dimension_x([12,0,0], [18,0,0]);
+ dimension_x([12,5,0], [18,10,0], offset = -1);
+ dimension_x([12,0,-5], [18,0,0], plane= "xz");
+ dimension_x([12,5,0], [18,10,5]);
+}
+
+module dimension_1d_y() {
+ dimension_y([12,0,0], [12,-5,0]);
+ dimension_y([12,-8,0], [18,-10,0]);
+ dimension_y([12,-5,0], [18,-10,5], offset = -1, plane= "yz");
+}
+
+module dimension_1d_z() {
+ dimension_z([20,0,5], [20,0,0]);
+ dimension_z([20,0,10], [20,0,0]);
+ dimension_z([20,0,0], [20,10,10],plane= "yz");
+}
+
+if($preview)
+ dimensions_3d_xy();
+ dimensions_3d_xyz();
+ dimension_1d_x();
+ dimension_1d_y();
+ dimension_1d_z();
diff --git a/tests/png/butt_box.png b/tests/png/butt_box.png
index c2ae6e7..17620ef 100644
Binary files a/tests/png/butt_box.png and b/tests/png/butt_box.png differ
diff --git a/tests/png/dimension.png b/tests/png/dimension.png
new file mode 100644
index 0000000..f9cda94
Binary files /dev/null and b/tests/png/dimension.png differ
diff --git a/utils/dimension.scad b/utils/dimension.scad
new file mode 100644
index 0000000..e5736ce
--- /dev/null
+++ b/utils/dimension.scad
@@ -0,0 +1,174 @@
+//
+// NopSCADlib Copyright Chris Palmer 2025
+// nop.head@gmail.com
+// hydraraptor.blogspot.com
+//
+// This file is part of NopSCADlib.
+//
+// NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the
+// GNU General Public License as published by the Free Software Foundation, either version 3 of
+// the License, or (at your option) any later version.
+//
+// NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along with NopSCADlib.
+// If not, see .
+//
+
+//
+//! Modules for adding dimensions to assembly views.
+//!
+//!
+//!
+//! * If `text` is empty, will display the measured distance.
+//! * `offset` will determine how much space is between the measured point and the dimension.
+//! * `thickness` is the thickness of the lines, and size of the arrows, if 0, will use 0.5% of the length of the dim.
+//! * `text_size` will determine the size of the text, if 0, will use percentage of the length of the dim.
+
+include <../utils/core/core.scad>
+include <../utils/maths.scad>
+
+module dimension(startpoint, endpoint, text = "", thickness = 0, text_size = 0 , rot_around_dim = 0) { //! Creates a 3D dimension between two points.
+ // Compute vector between points
+ direction = endpoint - startpoint;
+ length = norm(direction);
+ midpoint = (startpoint + endpoint) / 2;
+ thickness = (thickness == 0? length/200:thickness);
+
+ // Ensure nonzero values for calculations
+ dir_xy = norm([direction.x, direction.y]);
+
+ // Compute rotation angles
+ azimuth = atan2(direction.y, direction.x);
+ elevation = -atan2(direction.z, dir_xy);
+
+ //end triangle size
+ etr_width = thickness *10;
+ etr_height = thickness *4;
+
+ // Draw measurement line as a thin cylinder
+ translate(midpoint)
+ rotate([0, elevation, azimuth])
+ rotate([0, 90, 0])
+ resize([thickness, thickness, length - etr_width+0.01 ])
+ cube(center = true);
+
+ //do some vector calculations
+ dir = (length > 0) ? (direction / length) * thickness * 4 : [1, 0, 0];
+
+ // Draw endpoint markers
+ translate(startpoint)
+ rotate([0, elevation, azimuth])
+ rotate([rot_around_dim,0,0])
+ translate([0,0,-thickness/2])
+ linear_extrude(thickness)
+ polygon([[etr_width, etr_height/2],[0,0],[etr_width, -etr_height/2]],[[0,1,2]]);
+
+ translate(endpoint)
+ rotate([0, elevation, azimuth])
+ rotate([rot_around_dim,0,0])
+ translate([0,0,-thickness/2])
+ linear_extrude(thickness)
+ polygon([[-etr_width, etr_height/2],[0,0],[-etr_width, -etr_height/2]],[[0,1,2]]);
+
+
+ // Draw the text/distance
+ translate(midpoint)
+ rotate([0, elevation, azimuth])
+ rotate([rot_around_dim,0,0])
+ translate([0,thickness,-thickness/2])
+ linear_extrude(thickness)
+ text(text == "" ? str(length) : text, size = (text_size == 0? length/15:text_size), valign = "bottom", halign = "center");
+}
+
+
+module dimension_x(startpoint, endpoint, offset = 1, text = "", thickness = 0, text_size = 0 , plane = "xy") { //! Creates a dimension in the x direction. Plane options : xy, xz
+ length = norm(endpoint - startpoint);
+ thickness = (thickness == 0? length/200:thickness);
+
+ y = offset > 0 ? max(startpoint.y, endpoint.y) + (plane=="xy"?offset:0) : min(startpoint.y, endpoint.y) + (plane=="xy"?offset:0);
+ z = offset > 0 ? max(startpoint.z, endpoint.z) + (plane=="xz"?offset:0) : min(startpoint.z, endpoint.z) + (plane=="xz"?offset:0);
+
+ dimension([startpoint.x, y, z], [endpoint.x, y, z], text, thickness, text_size, rot_around_dim=(plane=="xz"?90:0));
+
+ v1= [startpoint.x, y, z]-startpoint;
+ h1 = norm(v1);
+ axis1 = cross([0,0,1], v1);
+ angle1 = atan2(norm(axis1), v1.z);
+ translate(startpoint)
+ rotate(angle1, axis1)
+ cylinder( h= h1+thickness*2, d=thickness);
+
+
+ v2= [endpoint.x, y, z]-endpoint;
+ h2 = norm(v2);
+ axis2 = cross([0,0,1], v2);
+ angle2 = atan2(norm(axis2), v2.z);
+
+ translate(endpoint)
+ rotate(angle2, axis2)
+ cylinder( h= h2+thickness*2, d=thickness);
+}
+
+
+module dimension_y(startpoint, endpoint, offset = 1, text = "", thickness = 0, text_size = 0 , plane = "xy") { //! Creates a dimension in the y direction. Plane options : xy, yz
+ length = norm(endpoint - startpoint);
+ thickness = (thickness == 0? length/200:thickness);
+
+
+ x = offset > 0 ? max(startpoint.x, endpoint.x) + (plane=="xy"?offset:0) : min(startpoint.x, endpoint.x) + (plane=="xy"?offset:0);
+ z = offset > 0 ? max(startpoint.z, endpoint.z) + (plane=="yz"?offset:0) : min(startpoint.z, endpoint.z) + (plane=="yz"?offset:0);
+ dimension([x, startpoint.y, z], [x, endpoint.y, z], text, thickness, text_size, rot_around_dim=(plane=="yz"?90:0));
+
+ v1= [x, startpoint.y, z]-startpoint;
+ h1 = norm(v1);
+ axis1 = cross([0,0,1], v1);
+ angle1 = atan2(norm(axis1), v1.z);
+
+ translate(startpoint)
+ rotate(angle1, axis1)
+ rotate([offset>0?0:180,0,0])
+ cylinder( h= h1+thickness*2, d=thickness);
+
+
+ v2= [x, endpoint.y, z]-endpoint;
+ h2 = norm(v2);
+ axis2 = cross([0,0,1], v2);
+ angle2 = atan2(norm(axis2), v2.z);
+
+ translate(endpoint)
+ rotate(angle2, axis2)
+ rotate([offset>0?0:180,0,0])
+ cylinder( h= h2+thickness*2, d=thickness);
+}
+
+module dimension_z(startpoint, endpoint, offset = 1, text = "", thickness = 0, text_size = 0 , plane = "xz") { //! Creates a dimension in the z direction. Plane options : xz, yz
+ length = norm(endpoint - startpoint);
+ thickness = (thickness == 0? length/200:thickness);
+
+
+ x = offset > 0 ? max(startpoint.x, endpoint.x) + (plane=="xz"?offset:0) : min(startpoint.x, endpoint.x) + (plane=="xz"?offset:0);
+ y = offset > 0 ? max(startpoint.y, endpoint.y) + (plane=="yz"?offset:0) : min(startpoint.y, endpoint.y) + (plane=="yz"?offset:0);
+ dimension([x, y, startpoint.z], [x, y, endpoint.z], text, thickness, text_size, rot_around_dim=(plane=="xz"?90:0));
+
+ v1= [x, y, startpoint.z]-startpoint;
+ h1 = norm(v1);
+ axis1 = cross([0,0,1], v1);
+ angle1 = atan2(norm(axis1), v1.z);
+
+ translate(startpoint)
+ rotate(angle1, axis1)
+ cylinder( h= h1+thickness*2, d=thickness);
+
+
+ v2= [x, y, endpoint.z]-endpoint;
+ h2 = norm(v2);
+ axis2 = cross([0,0,1], v2);
+ angle2 = atan2(norm(axis2), v2.z);
+
+ translate(endpoint)
+ rotate(angle2, axis2)
+ cylinder( h= h2+thickness*2, d=thickness);
+}
diff --git a/vitamins/nut.scad b/vitamins/nut.scad
index d6534e4..5d7000b 100644
--- a/vitamins/nut.scad
+++ b/vitamins/nut.scad
@@ -21,6 +21,10 @@
//! Default is steel but can be drawn as brass or nylon. A utility for making nut traps included.
//!
//! If a nut is given a child then it gets placed on its top surface.
+//!
+//! The following diagram shows you the parameters for drawing a sliding_t_nut:
+//!
+//! 
//
include <../utils/core/core.scad>
use