diff --git a/dometyl.opam b/dometyl.opam index 03c147e..fde61c3 100644 --- a/dometyl.opam +++ b/dometyl.opam @@ -12,9 +12,9 @@ depends: [ "ocaml" {>= "4.14.0"} "dune" {>= "3.6"} "dune-site" - "OCADml" {= "0.2.2"} - "OSCADml" {= "0.1.1"} - "ppx_deriving_cad" {= "0.1.0"} + "OCADml" {>= "0.3.2"} + "OSCADml" {>= "0.2.0"} + "ppx_deriving_cad" {>= "0.2.0"} "odoc" {with-doc} ] build: [ diff --git a/dune-project b/dune-project index 17aeead..05cba0c 100644 --- a/dune-project +++ b/dune-project @@ -30,8 +30,8 @@ dune dune-site (OCADml - (= 0.2.2)) + (>= 0.3.2)) (OSCADml - (= 0.1.1)) + (>= 0.2.0)) (ppx_deriving_cad - (= 0.1.0)))) + (>= 0.2.0)))) diff --git a/lib/bastardShield.ml b/lib/bastardShield.ml index b241f7b..436e38f 100644 --- a/lib/bastardShield.ml +++ b/lib/bastardShield.ml @@ -125,9 +125,9 @@ let place = let left_foot = (IMap.find 0 north).foot and right_foot = (IMap.find 1 north).foot in - let x = left_foot.bot_left.x +. x_off + let x = V3.x left_foot.bot_left +. x_off and y = - let inner (ps : Points.t) = V3.(get_y ps.bot_left +. get_y ps.bot_right) /. 2. in + let inner (ps : Points.t) = V3.(y ps.bot_left +. y ps.bot_right) /. 2. in y_off +. ((inner left_foot +. inner right_foot) /. 2.) in zrot z_rot t |> translate (v3 x y z_off) @@ -141,9 +141,9 @@ let eyelets { screw_l; screw_r; thickness; _ } = let build p = - Eyelet.place ?width ~bury ~config ~inline ~outline (`Loc { p with z = 0. }) + Eyelet.place ?width ~bury ~config ~inline ~outline (`Loc V3.(v (x p) (y p) 0.)) |> Eyelet.to_scad - |> Scad.ztrans (p.z +. thickness +. z_off) + |> Scad.ztrans (V3.z p +. thickness +. z_off) in Scad.union [ build screw_l; build screw_r ] diff --git a/lib/bottom.ml b/lib/bottom.ml index 2f40397..028d981 100644 --- a/lib/bottom.ml +++ b/lib/bottom.ml @@ -15,8 +15,8 @@ let locate (key : Key.t) = function | Some (loc : v2) -> let xaxis = key.faces.east.normal and yaxis = key.faces.north.normal in - let xshift = V3.(xaxis *$ (key.config.outer_w *. (loc.x -. 0.5))) - and yshift = V3.(yaxis *$ (key.config.outer_h *. (loc.y -. 0.5))) in + let xshift = V3.(xaxis *$ (key.config.outer_w *. (V2.x loc -. 0.5))) + and yshift = V3.(yaxis *$ (key.config.outer_h *. (V2.y loc -. 0.5))) in V3.(to_v2 @@ (key.origin +@ xshift +@ yshift)) | None -> V2.of_v3 key.origin diff --git a/lib/bridge.ml b/lib/bridge.ml index b0f34df..566d32d 100644 --- a/lib/bridge.ml +++ b/lib/bridge.ml @@ -50,7 +50,7 @@ let keys Scad.union [ Scad.hull [ in_b; out_b ]; out_a ] and face1 = Key.Faces.face k1.faces start and face2 = Key.Faces.face k2.faces dest in - if V3.get_z face1.points.centre > V3.get_z face2.points.centre + if V3.z face1.points.centre > V3.z face2.points.centre then aux (start, k1) (dest, k2) else aux (dest, k2) (start, k1) @@ -110,11 +110,11 @@ let cols let w_z = let last_c = (Key.Faces.face w_last.faces start).points.centre and next_c = (Key.Faces.face w_next.faces start).points.centre in - V3.(get_z @@ mid last_c next_c) + V3.(z @@ mid last_c next_c) and e_z = let last_c = (Key.Faces.face e_last.faces dest).points.centre and next_c = (Key.Faces.face e_next.faces dest).points.centre in - V3.(get_z @@ mid last_c next_c) + V3.(z @@ mid last_c next_c) in if w_z > e_z then huller ~low_west:false e_set w_set :: hulls diff --git a/lib/connect.ml b/lib/connect.ml index 08601a0..3521750 100644 --- a/lib/connect.ml +++ b/lib/connect.ml @@ -58,7 +58,7 @@ let fillet ~d ~h rows = let h = match h with | `Rel h -> h - | `Abs h -> h /. (Path3.bbox (List.hd rows)).max.z + | `Abs h -> h /. (Box3.maxz @@ Path3.bbox (List.hd rows)) in fun u row -> let u = if u > 0.5 then 1. -. u else u in @@ -164,7 +164,7 @@ let spline_base let align_q = Quaternion.align dir2 dir1 in let b' = Path3.quaternion align_q b' in let ang = V3.angle (V3.neg dir1) V3.(p3 -@ p0) *. outward_sign w1 w2 in - let dist = V2.(distance (v p0.x p0.y) (v p3.x p3.y)) in + let dist = V2.distance V3.(v2 (x p0) (y p0)) V3.(v2 (x p3) (y p3)) in let ang_ratio = dist /. Float.abs ang /. Float.pi in let step = 1. /. Float.of_int fn in let transition i = List.map2 (fun a b -> V3.lerp a b (Float.of_int i *. step)) a' b' in diff --git a/lib/curvature.ml b/lib/curvature.ml index 8dd8baf..6458797 100644 --- a/lib/curvature.ml +++ b/lib/curvature.ml @@ -58,15 +58,16 @@ let place ?well ?fan ~centre_idx i key = match well, fan with | Some spec, None -> let r = well_theta spec i in - Key.rotate (well_tilt ~xrot:r.x spec) key |> Key.rotate ~about:(well_point spec) r + Key.rotate (well_tilt ~xrot:(V3.x r) spec) key + |> Key.rotate ~about:(well_point spec) r | None, Some spec -> Key.yrot spec.tilt key |> Key.rotate ~about:(fan_point spec) (fan_theta spec i) | Some w, Some f -> let welled = let r = well_theta w i in - Key.rotate (well_tilt ~xrot:r.x w) key |> Key.rotate ~about:(well_point w) r + Key.rotate (well_tilt ~xrot:(V3.x r) w) key |> Key.rotate ~about:(well_point w) r in - Key.ytrans (welled.origin.y *. -1.) welled + Key.ytrans (V3.y welled.origin *. -1.) welled |> Key.yrot f.tilt |> Key.rotate ~about:(fan_point f) (fan_theta f i) | None, None -> key diff --git a/lib/eyelet.ml b/lib/eyelet.ml index acd34cb..8533eb0 100644 --- a/lib/eyelet.ml +++ b/lib/eyelet.ml @@ -108,8 +108,8 @@ let make and p1' = proj p1 and p2' = proj p2 and hole_offset' = proj hole_offset in - let l = V2.(hole_centre' +@ (v2 normal.y (-.normal.x) *$ outer_rad)) - and r = V2.(hole_centre' -@ (v2 normal.y (-.normal.x) *$ outer_rad)) in + let l = V2.(hole_centre' +@ (v2 (V3.y normal) (-.V3.x normal) *$ outer_rad)) + and r = V2.(hole_centre' -@ (v2 (V3.y normal) (-.V3.x normal) *$ outer_rad)) in let outer = List.tl @@ Path2.arc_about_centre ~dir:`CW ~centre:hole_centre' ~fn l r and inner = List.rev_map (V2.add hole_centre') @@ Path2.circle ~fn inner_rad in let outline = diff --git a/lib/hand.ml b/lib/hand.ml index 5f97f59..33a79d3 100644 --- a/lib/hand.ml +++ b/lib/hand.ml @@ -217,15 +217,15 @@ let make ?(carpal_len = 58.) ?(knuckle_rad = 5.) (fingers : Fingers.t) (thumb : |> Scad.rotate (v3 0. (Float.pi /. 2.) 0.) |> Scad.translate thumb.bones.prox.base in - let { x = mid_x; y = mid_y; z = _ } = fingers.middle.prox.base + let mid = fingers.middle.prox.base and z = Fingers.fold - (fun m a -> Float.min m (V3.get_z a.prox.base)) - (V3.get_z thumb.bones.prox.base) + (fun m a -> Float.min m (V3.z a.prox.base)) + (V3.z thumb.bones.prox.base) fingers in - let heading = V3.normalize (v3 0. mid_y (-.z)) - and origin = v3 mid_x thumb.bones.prox.base.y z in + let heading = V3.normalize (v3 0. (V3.y mid) (-.z)) + and origin = v3 (V3.x mid) (V3.y thumb.bones.prox.base) z in { fingers ; thumb ; carpals diff --git a/lib/key.ml b/lib/key.ml index 953a1c2..932e8ce 100644 --- a/lib/key.ml +++ b/lib/key.ml @@ -111,7 +111,7 @@ let make let a, _, b, _ = List.fold_left f (s0, V3.distance s0.a s0.b, s1, V3.distance s1.a s1.b) segs in - if a.a.z > 0. then a, b else b, a + if V3.z a.a > 0. then a, b else b, a | _ -> failwith "unreachable" in let south = diff --git a/lib/plate.ml b/lib/plate.ml index cbae0d5..aa13024 100644 --- a/lib/plate.ml +++ b/lib/plate.ml @@ -168,7 +168,7 @@ let make let lift = let lowest_z = let face_low ({ points = ps; _ } : Key.Face.t) = - Points.fold (fun m p -> Float.min m (V3.get_z p)) Float.max_float ps + Points.fold (fun m p -> Float.min m (V3.z p)) Float.max_float ps in let key_low ({ faces = fs; _ } : Key.t) = Key.Faces.fold (fun m face -> Float.min m (face_low face)) Float.max_float fs diff --git a/lib/points.ml b/lib/points.ml index 0fca434..24210d0 100644 --- a/lib/points.ml +++ b/lib/points.ml @@ -46,13 +46,14 @@ let of_ccw_path = function let overlapping_bounds a b = let a = Path3.bbox (to_cw_path a) and b = Path3.bbox (to_cw_path b) in - match V3.bbox_intersect a b with - | Some inter -> - let area_inter = V3.bbox_area inter - and area_a = (a.max.x -. a.min.x) *. (a.max.y -. a.min.y) - and area_b = (b.max.x -. b.min.x) *. (b.max.y -. b.min.y) in - area_inter /. (area_a +. area_b -. area_inter) - | None -> 0. + let i = Box3.inter a b in + if Box3.is_empty i + then 0. + else ( + let area_i = Box3.((maxx i -. minx i) *. (maxy i -. miny i)) + and area_a = Box3.((maxx a -. minx a) *. (maxy a -. miny a)) + and area_b = Box3.((maxx b -. minx b) *. (maxy b -. miny b)) in + area_i /. (area_a +. area_b -. area_i) ) let get t = function | `TL -> t.top_left diff --git a/lib/ports.ml b/lib/ports.ml index 724e0a0..b6e1329 100644 --- a/lib/ports.ml +++ b/lib/ports.ml @@ -33,9 +33,7 @@ let make = let left_foot = (IMap.find 0 north).foot and right_foot = (IMap.find 1 north).foot in - let inner_y (foot : Points.t) = - V3.(get_y foot.bot_left +. get_y foot.bot_right) /. 2. - in + let inner_y (foot : Points.t) = V3.(y foot.bot_left +. y foot.bot_right) /. 2. in let jack = Scad.cylinder ~center:true ~fn:16 ~height:20. jack_radius |> Scad.xrot (Float.pi /. 2.) and usb = @@ -53,7 +51,7 @@ let make and below = Float.max ((usb_height /. 2.) +. board_thickness) jack_radius in let h = jack_radius +. below and len (foot : Points.t) = - (V3.(get_y foot.top_left +. get_y foot.top_right) /. 2.) -. inner_y foot + (V3.(y foot.top_left +. y foot.top_right) /. 2.) -. inner_y foot in let left = let l = len left_foot in @@ -76,8 +74,7 @@ let make in let cutout = Scad.union [ jack; usb; inset ] - |> Scad.translate - V3.(v3 (get_x left_foot.bot_left +. x_off) (inner_y left_foot) z_off) + |> Scad.translate V3.(v3 (x left_foot.bot_left +. x_off) (inner_y left_foot) z_off) in { plus = None; minus = Some cutout } @@ -92,11 +89,11 @@ let place_tray and right = IMap.find_opt 1 north in let x = match left, right with - | Some w, _ | None, Some w -> V3.get_x w.foot.bot_left +. x_off + | Some w, _ | None, Some w -> V3.x w.foot.bot_left +. x_off | None, None -> 0. and y = let outer = - let f (ps : Points.t) = V3.(get_y ps.top_left +. get_y ps.top_right) /. 2. in + let f (ps : Points.t) = V3.(y ps.top_left +. y ps.top_right) /. 2. in value_map_opt ~default:0. (fun w -> f w.Wall.foot) in y_off +. ((outer left +. outer right) /. 2.) diff --git a/lib/tent.ml b/lib/tent.ml index a42d151..ad3d229 100644 --- a/lib/tent.ml +++ b/lib/tent.ml @@ -102,8 +102,8 @@ let prison_shell Easing.make (v2 d 1.) (v2 d 1.) in let prune (acc, last) row = - let min_z = (Path3.bbox last).min.z in - let valid = List.for_all (fun p -> p.z > min_z) row in + let min_z = Box3.minz (Path3.bbox last) in + let valid = List.for_all (fun p -> V3.z p > min_z) row in if valid then row :: acc, row else acc, last and rounder out_edge in_edge = match corner with @@ -116,7 +116,7 @@ let prison_shell in let pillar i = let u = (pillar_step *. Float.of_int i) +. phase_shift in - let z = (cont_outer u).z in + let z = V3.z (cont_outer u) in let slices = slices z and t_outer = t_outer z and t_outer' = t_outer' z in @@ -162,7 +162,7 @@ let prison_shell |> Mesh.skin ~slices:(`Flat 0) |> Scad.of_mesh in - let z = (Path3.bbox top_outer).min.z in + let z = Box3.minz (Path3.bbox top_outer) in let bot = let outer = Mesh.skin_between ~slices:1 bot_outer (Path3.ztrans z bot_outer) and inner = @@ -226,8 +226,7 @@ let make (case : Case.t) = let bb_pinky, rot_sign = - let V3.{ min = { x = bb_left; _ }; max = { x = bb_right; _ } } = - Path3.bbox case.connections.outline + let bb = Path3.bbox case.connections.outline and pinky_home = let n = case.plate.config.n_body_cols - 1 in (Columns.key_exn @@ -236,6 +235,8 @@ let make (Int.of_float @@ case.plate.config.body_centres n) ) .origin in + let bb_left = Box3.minx bb + and bb_right = Box3.maxx bb in if V3.(norm (pinky_home -@ v3 bb_right 0. 0.)) < V3.(norm (pinky_home -@ v3 bb_left 0. 0.)) then bb_right, 1. @@ -297,7 +298,7 @@ let make | Magnet { rad; thickness } -> magnetize rad thickness (thickness +. 1.4) in (* raise top above the feet or the tilted eyelets (avoid clipping) *) - let rise = Float.max foot_thickness (V3.rotate rot (v3 0. 0. hole_height)).z in + let rise = Float.max foot_thickness V3.(z @@ rotate rot (v 0. 0. hole_height)) in let place_scad s = Scad.ztrans rise @@ Scad.rotate ~about rot s and place_v3 p = V3.ztrans rise @@ V3.rotate ~about rot (V3.of_v2 p) in let eyelets = @@ -318,8 +319,8 @@ let make in let outer = List.map place_v3 outline and inner = List.map place_v3 inline in - let outer' = List.map (fun { x; y; z = _ } -> v3 x y 0.) outer - and inner' = List.map (fun { x; y; z = _ } -> v3 x y 0.) inner in + let outer' = List.map V3.projection outer + and inner' = List.map V3.projection inner in let shell = shell_of_style style outer' inner' outer inner in let feet, final_cuts = let f (bumps, insets) loc = diff --git a/lib/wall.ml b/lib/wall.ml index f24ecee..1dea3bb 100644 --- a/lib/wall.ml +++ b/lib/wall.ml @@ -90,7 +90,7 @@ type t = let swing_face face = let dir = Key.Face.direction face in let about, z_sign = - if V3.get_z face.normal > 0. + if V3.z face.normal > 0. then V3.mid face.points.bot_left face.points.bot_right, 1. else V3.mid face.points.top_left face.points.top_right, -1. in @@ -119,22 +119,22 @@ let make let cleared_face = Key.Face.translate (V3.map (( *. ) clearance) ortho) pivoted_face in let xy = V3.(normalize (mul ortho (v3 1. 1. 0.))) and dir = Points.direction cleared_face.points - and fn = Steps.to_int n_steps cleared_face.points.centre.z in + and fn = Steps.to_int n_steps (V3.z cleared_face.points.centre) in let d1 = match d1 with | `Abs d -> d - | `Rel frac -> cleared_face.points.centre.z *. frac + | `Rel frac -> V3.z cleared_face.points.centre *. frac and step = 1. /. Float.of_int fn in let bz end_z = - let ({ x; y; z = _ } as cx) = cleared_face.points.centre in + let cx = cleared_face.points.centre in let p1 = V3.(cx -@ (ortho *$ 0.01)) (* fudge for union *) and p2 = V3.((xy *@ v d1 d1 0.) +@ cx) - and p3 = V3.((xy *@ v d2 d2 0.) +@ v x y end_z) in + and p3 = V3.((xy *@ v d2 d2 0.) +@ v (x cx) (y cx) end_z) in Bezier3.make [ p1; p2; p3 ] and counter = (* counter the rotation created by the z tilt of the face, such that the angle of the wall is more in line with the xy angle of the originating face *) - let a = V3.angle dir (v3 dir.x dir.y 0.) *. Math.sign dir.z *. -1. in + let a = V3.angle dir (v3 (V3.x dir) (V3.y dir) 0.) *. Math.sign (V3.z dir) *. -1. in let s = Quaternion.(slerp (make ortho 0.) (make ortho a)) and ez = Easing.make (v2 0.42 0.) (v2 1. 1.) in let f i = Affine3.of_quaternion @@ s (ez (Float.of_int i *. step)) in @@ -168,7 +168,7 @@ let make |> Affine3.compose (Util.last counter) in let last_shape = Path3.affine trans (List.map (scaler fn) centred) in - let end_z = Float.max ((Path3.bbox last_shape).min.z *. -1.) 0. +. end_z in + let end_z = Float.max (Box3.minz (Path3.bbox last_shape) *. -1.) 0. +. end_z in Path3.to_transforms ~mode:`NoAlign (Bezier3.curve ~fn (bz end_z)) |> List.map2 (fun c m -> Affine3.(c %> m)) counter |> Util.prune_transforms ~min_dist:min_step_dist ~shape:(fun i -> @@ -188,17 +188,14 @@ let make in let final = let s = Util.last rows in - let flat = List.map (fun { x; y; z = _ } -> v3 x y 0.) s in + let flat = List.map V3.projection s in Mesh.slice_profiles ~slices:(`Flat 5) [ s; flat ] in Mesh.of_rows ~style:`MinEdge (List.concat [ clearing; List.tl rows; List.tl final ]) |> Scad.of_mesh and foot = let i, m = Util.last transforms in - let f p = - let { x; y; z = _ } = V3.(affine m (scaler i (p -@ cleared_face.points.centre))) in - v3 x y 0. - in + let f p = V3.(projection @@ affine m (scaler i (p -@ cleared_face.points.centre))) in Points.map f cleared_face.points and drawer ~bounds = let start, cleared = diff --git a/models/examples/splaytyl.ml b/models/examples/splaytyl.ml index c95ca88..3ba7bd5 100644 --- a/models/examples/splaytyl.ml +++ b/models/examples/splaytyl.ml @@ -20,7 +20,7 @@ let body_lookups = Curvature.(curve ~well:(well ~radius:37. (Float.pi /. 4.25)) ()) | i when i = 0 -> Curvature.( - curve ~well:(well ~tilt:(Float.pi /. 7.5) ~radius:46. (Float.pi /. 5.95)) ()) + curve ~well:(well ~tilt:(Float.pi /. 7.5) ~radius:46. (Float.pi /. 5.95)) () ) | _ -> Curvature.(curve ~well:(well ~radius:46.5 (Float.pi /. 6.1)) ()) and splay = function | i when i = 3 -> Float.pi /. -25. (* ring *) @@ -35,7 +35,7 @@ let thumb_lookups = curve ~fan:(fan ~radius:70. ~tilt:(Float.pi /. 48.) (Float.pi /. 9.)) ~well:(well ~radius:47. (Float.pi /. 7.5)) - ()) + () ) in Plate.Lookups.thumb ~curve ()