From 607fdf8d790df4fc6ec1db9bcc0ab8ca70236450 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Dante=20Ursini?= Date: Fri, 24 Jan 2025 16:30:27 -0300 Subject: [PATCH] Cleanup and control points documentation --- Readme.md | 4 ++ Surf-Fins-10inch.json | 12 ++--- Surf-Fins-10inch.scad | 97 ++++++++++++++++------------------------- common.scad | 6 ++- res/Control-Points.png | Bin 0 -> 11230 bytes 5 files changed, 49 insertions(+), 70 deletions(-) create mode 100644 res/Control-Points.png diff --git a/Readme.md b/Readme.md index 8abe2fc..e7fb7f9 100644 --- a/Readme.md +++ b/Readme.md @@ -10,7 +10,11 @@ The box is designed using library [Fin Base](https://github.com/hrobeers/finbase ![](https://user-images.githubusercontent.com/2812522/105723055-9fd71100-5f26-11eb-8a9e-b892212b240b.jpg) +## Fin profile +Fin profile is defined using bézier 3 points control + +![](./res/Control-Points.webp) ## Kitesurf Fins diff --git a/Surf-Fins-10inch.json b/Surf-Fins-10inch.json index 4ef201f..3aab2ed 100644 --- a/Surf-Fins-10inch.json +++ b/Surf-Fins-10inch.json @@ -36,7 +36,6 @@ "parts": "all", "piston_depth": "5", "printable": "false", - "resin_escape_diameter": "4", "scale_factor": "1", "show_curve_points": "false", "show_debug_layers": "false", @@ -83,7 +82,6 @@ "pin_dia": "3", "piston_depth": "5", "printable": "true", - "resin_escape_diameter": "4", "scale_factor": "1", "screw_dia": "4.5", "screw_pos": "9.5999999999999996", @@ -135,7 +133,6 @@ "pin_dia": "3", "piston_depth": "5", "printable": "true", - "resin_escape_diameter": "4", "scale_factor": "1", "screw_dia": "4.5", "screw_pos": "9.5999999999999996", @@ -189,7 +186,6 @@ "pin_dia": "3", "piston_depth": "5", "printable": "true", - "resin_escape_diameter": "4", "scale_factor": "1", "screw_dia": "4.5", "screw_pos": "9.5999999999999996", @@ -244,7 +240,6 @@ "pin_dia": "3", "piston_depth": "5", "printable": "true", - "resin_escape_diameter": "4", "scale_factor": "1", "screw_dia": "4.5", "screw_pos": "9.5999999999999996", @@ -265,8 +260,8 @@ "box_thickness": "9.5999999999999996", "build_box": "false", "build_fin": "false", - "build_mold": "true", - "draw_profile": "false", + "build_mold": "false", + "draw_profile": "true", "fin_back_angle": "20", "fin_back_height": "30", "fin_back_strength": "30", @@ -291,7 +286,7 @@ "mirror_vec": "[1, 1, 0]", "mold_base_height": "10", "mold_extra_width": "15", - "mold_part": "top", + "mold_part": "all", "mold_piston_height": "10", "mold_top_height": "5", "partition": "none", @@ -301,7 +296,6 @@ "pin_dia": "3", "piston_depth": "5", "printable": "true", - "resin_escape_diameter": "4", "scale_factor": "1", "screw_dia": "4.5", "screw_pos": "9.5999999999999996", diff --git a/Surf-Fins-10inch.scad b/Surf-Fins-10inch.scad index 9270bdc..dbca489 100644 --- a/Surf-Fins-10inch.scad +++ b/Surf-Fins-10inch.scad @@ -91,7 +91,7 @@ mold_extra_width = 15; mold_piston_height = 10; -resin_escape_diameter = 4; +//resin_escape_diameter = 4; // Diameter for screw holes in mm merge_holes_diameter = 6; @@ -380,6 +380,7 @@ module moldJunctionMask(moldThickness = 3,height,angle){ ); } + module buildMoldSkirt( height,offset,thickness ) { outside = expandPath(profile,offset); inside = expandPath(profile,offset-thickness); @@ -404,52 +405,27 @@ module buildMoldSkirt( height,offset,thickness ) { } -// ***************** -// * Bottom insert * -// ***************** -module bottomInsert() { - debug=true; - layer_profile = profile_curve_with_base; - skin( [ layer_profile,expandPath(layer_profile,3) ], z=[0,piston_depth], slices=0 ) - up(OFFSET) - buildFinSide(true) - ; -} - -// ***************** -// * Top piston * -// ***************** -module topPiston() { - debug=true; - layer_profile = profile_curve_with_base; - difference() { - skin( [ layer_profile,expandPath(layer_profile,3) ], z=[0,piston_depth], slices=0 ); - down(OFFSET) - buildFinSide(false); - } -} - /** * Build fin * + * @param thickness - Thickness of the fin */ module buildFin( thickness ) { union() { - if (parts != "bottom") buildFinSide( thickness ); - if (parts != "top") buildFinSide( thickness , true ); + if (parts != "bottom" ) buildFinSide( thickness ); + if (parts != "top" ) buildFinSide( thickness , true ); } } /** * Build fin side - * - * @param flip - Define it it is top or bottom fin side + * + * @param thickness - Thickness of the surf fin + * @param flip - Define it it is top or bottom fin side + * */ module buildFinSide(thickness,flip=false) { - - //profile_curve_with_base1 = subdivide_path (profile_curve_with_base,500); - //if (false) mirror([0,0,flip ? 1 : 0]) color(flip ? "Gray" : "LightGray") ellipse_extrude( thickness / 2 /*,height=2*/,center=false,twist=-7) @@ -457,31 +433,34 @@ module buildFinSide(thickness,flip=false) { polygon( profile_curve_with_base); } -module resin_escape(length) { - color ("Blue") cylinder(h=length, r=resin_escape_diameter/2); -} - +/** + * Add base to fin profile + * + * @param path - Profile of the surf fin + */ function addBase(path) = concat(path,[[fin_base,-base_extra_thickness],[0,-base_extra_thickness]]); -module partitionMask(inverse = false) { - up(10) + +/** + * Partition mask + + * @param inverse - Side of the cut + * @param cut - Cut type + */ +module partitionMask(inverse = false,cut = "sinewave") { partition_mask( - w=fin_height/2*1.5, - h=80, // height - l=fin_width*3, - cutpath="sinewave", - //spread=0.1, + l=fin_width*3, // Length on x axis + w=fin_height/2*1.5, // Deepness on y axis + h=80, // height on z axis + cutpath=cut, inverse=inverse, anchor=FRONT ); } - - - /** * Draws a profile based on Bezier path points with optional debug visualization. * @@ -495,29 +474,29 @@ module partitionMask(inverse = false) { */ module drawProfile( points,debug = true ){ + text_size=40; - debugPoint (start, "Start", "Red" ); - debugPoint (top_point, "Top", "Blue" ); - debugPoint (edge_point, "Edge", "Brown" ); - debugPoint (counter_edge_point, "Counter Edge", "Brown" ); - debugPoint (tail_point, "Tail", "Yellow" ); - debugPoint (end_point, "End", "Yellow" ); - - //pt = [100,0]; - //pos = bezpath_closest_point(points, pt); - //xy = bezpath_points(points,pos[0],pos[1]); + debugPoint (start, "Start", "Red" ,textSize=text_size , t=[-20,4,0]); + debugPoint (top_point, "Top", "Blue" ,textSize=text_size , t=[-5,5,0]); + debugPoint (edge_point, "Edge", "Brown" ,textSize=text_size , t=[10,-5,0]); + debugPoint (counter_edge_point, "Counter Edge", "Brown" ,textSize=text_size , t=[35,-5,0]); + debugPoint (tail_point, "Tail", "Yellow" ,textSize=text_size , t=[8,-5,0]); + debugPoint (end_point, "End", "Yellow" ,textSize=text_size , t=[13,4,0]); debug_bezier(points, N=3,width=1.2); } + + + echo ("****************************"); echo ("** Build **"); echo ("****************************"); echo (str("filename :"," surf-fins-10inch-",mold_part,"-",partition,"_",version,".stl"," ")); // Draw fin profile -if (draw_profile) - back(10) right(350) showDebugPath(profile_curve_with_base); +if (draw_profile) drawProfile(points); + // Show curve points if (show_curve_points) diff --git a/common.scad b/common.scad index 3d683f6..0b8c09f 100644 --- a/common.scad +++ b/common.scad @@ -31,12 +31,14 @@ function handle(point,angle,strength) = [ /** * Show Debug point */ -module debugPoint(point, id, color,textSize=20,r=1.5) { +module debugPoint(point, id, color,textSize=20,r=1.5,t = [0,0,0]) { translate(point) { color(color) sphere(r = r); //translate([3, 3, 0.6]) { - translate([textSize/7, textSize/7, textSize/10]) { + + + translate([textSize/7+t[0], textSize/7+t[1], textSize/10+t[2]]) { color("white") scale([0.2, 0.2, 1]) linear_extrude(height = 0.1) diff --git a/res/Control-Points.png b/res/Control-Points.png new file mode 100644 index 0000000000000000000000000000000000000000..4e95662916113ffb26342118915a9150fe3db1dd GIT binary patch literal 11230 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 literal 0 HcmV?d00001