desk-hook.hs
A hook that can be attached to the side of a desk, possibly to hang headphones from.
Assumes a 18mm thick desk, but should be quite easy to modify for a different thickness.
#!/usr/bin/env stack
{- stack script --resolver lts-22.6
--package linear
--package waterfall-cad
--extra-dep waterfall-cad-0.3.0.1
--extra-dep opencascade-hs-0.3.0.1
-}
-- short-description: Hook, for the Underside of a Desk
--
-- description: A hook that can be attached to the side of a desk, possibly to hang headphones from.
-- description:
-- description: Assumes a 18mm thick desk, but should be quite easy to modify for a different thickness.
--
-- image: https://doscienceto.it/blog/photos/desk-hook-01.jpg
import qualified Waterfall
import Linear
import Data.Function ((&))
import Control.Lens ((^.), (.~ ))
hook :: Waterfall.Solid
=
hook let
= 20
w = 18
deskT = 4
t = 95
l = Waterfall.centeredCube
clampA & Waterfall.translate (zero & _yz .~ 0.5)
& Waterfall.scale (V3 w 20 (deskT + t * 2))
& Waterfall.roundFillet (t/2)
= Waterfall.centeredCube
clampB & Waterfall.translate (zero & _yz .~ 0.5)
& Waterfall.scale (V3 w l t)
& Waterfall.roundConditionalFillet (\(s, e) -> if s ^. _xy == e ^. _xy then Just 2 else Nothing)
= Waterfall.centeredCube
clampGap & Waterfall.translate (zero & _yz .~ 0.5)
& Waterfall.scale (V3 (w*2) l deskT)
& Waterfall.translate (zero & _y .~ t & _z .~ t)
= 1.5
screwR = Waterfall.centeredCylinder
screwHole & Waterfall.scale (V3 screwR screwR 100)
& (<> (Waterfall.unitCone & Waterfall.uScale 100 & Waterfall.rotate (unit _x) pi))
& Waterfall.translate (zero & _z .~ t & _y .~ (l - w/2 - t))
= (clampA <> clampB) `Waterfall.difference` (clampGap <> screwHole)
clamp = 30
hookR = 50
hookAH = Waterfall.pathFrom ((zero & _y .~ (l/2 - 20)) :: V3 Double)
hookPath & _z .~ -hookAH/2) (zero & _z .~ -hookAH/2 & _y .~ hookR) (zero & _z .~ -hookAH & _y .~ hookR)
[ Waterfall.bezierRelative (zero & _z .~ (-hookR) & _y .~ (-hookR)) (zero & _y .~ (-2 * hookR))
, Waterfall.arcViaRelative (zero
]{--hookPathB = Waterfall.pathFrom ((zero & _y .~ (l/2 + 5)) :: V3 Double)
[ Waterfall.bezierRelative (zero & _z .~ -hookAH/2) (zero & _z .~ -hookAH/2 & _y .~ (hookR -25)) (zero & _z .~ -hookAH & _y .~ (hookR-25))
]--}
= Waterfall.pathFrom ((zero & _y .~ (l/2 + 35)) :: V3 Double)
hookPathC & _z .~ -hookAH/2) (zero & _z .~ -hookAH/2 & _y .~ (hookR -55)) (zero & _z .~ -hookAH & _y .~ (hookR-55))
[ Waterfall.bezierRelative (zero
]= 12
hookTR = Waterfall.pathEndpoints hookPath
(_, end)
= Waterfall.uScale hookTR Waterfall.unitSphere
hookEndcap & Waterfall.translate end
= (Waterfall.uScale2D hookTR Waterfall.unitCircle)
hookProfile
= 5
hookScrewR = Waterfall.centeredCylinder
hookScrewHole & Waterfall.scale (V3 hookScrewR hookScrewR 400)
& Waterfall.translate (zero & _z .~ t & _y .~ (l - w/2 - t))
= ((Waterfall.sweep hookPath hookProfile
hook -- <> Waterfall.sweep hookPathB hookProfile
<> Waterfall.sweep hookPathC hookProfile
<> hookEndcap) `Waterfall.intersection`
& Waterfall.scale (zero & _x .~ w & _yz .~ 400))
( Waterfall.centeredCube `Waterfall.difference` hookScrewHole
)
in clamp <> hook
main :: IO ()
= Waterfall.writeSolid 0.1 "desk-hook.stl" hook main