% % Very simple model of my hand % % Gene Ressler % % In particular, this completely ignores the carpal joints. % % Try this with various options to sketch. % % -D fist \ % -D ok > none or one of these % -D spread / % % -D topview \ % -D frontview > none or one of these % -D sideview / % % -D repeated % % I am not responsible for modifications to draw % obscene gestures. % parameterization of model % for fingers, 0 is thumb, 1 is index, % 2 is middle, 3 is ring, 4 is little % lateral angle between fingers def spread_rot 0 5 10 <> 0 % and between thumb and index finger def spread_rot_0 40 55 55 <> 25 % rotations of finger parts % distal is the finger tip % middle is below that % meta is the knuckle def distal_0_rot 60 45 <> -10 def middle_0_rot 50 40 0 <> 10 def meta_0_rot 40 35 <> 0 def distal_1_rot 90 54 <> 0 def meta_1_rot 90 60 <> 0 def distal_2_rot 90 30 <> 0 def meta_2_rot 90 35 <> 0 def distal_3_rot 90 30 <> 0 def meta_3_rot 90 30 <> 0 def distal_4_rot 90 30 <> 0 def meta_4_rot 90 25 <> 0 % end parameters % useful stuff def O (0,0,0) def I [1,0,0] def J [0,1,0] def K [0,0,1] % dependent rotations % fingers have the last two joints wired together def middle_1_rot distal_1_rot def middle_2_rot distal_2_rot def middle_3_rot distal_3_rot def middle_4_rot distal_4_rot % proportions def proximal_rad .6 def distal_rad .5 def distal_len 1.8 def joint_rad .6 def joint_gap .7 def middle_ratio 1.8 def proximal_distal_ratio proximal_rad / distal_rad % primitive segment of a finger is a truncated cone def segment { def n_faces 8 sweep { n_faces<>, rotate(360 / n_faces, [J]) } line(proximal_rad, 0)(distal_rad, distal_len) } % spheres to connect segments at joints def joint_sphere { def n_joint_faces 8 sweep [fillcolor=lightgray] { n_joint_faces, rotate(360 / n_joint_faces, [J]) } sweep { n_joint_faces, rotate(180 / n_joint_faces) } (0, -joint_rad) } % following is five separate definitions for five fingers % with parameters, this would be much shorter! def distal_0 { put { translate(joint_gap * joint_rad * [J]) then rotate(distal_0_rot, [I]) then translate((distal_len + joint_gap * joint_rad) * [J]) } {segment} put { rotate(distal_0_rot / 2, [I]) then translate((distal_len + joint_gap * joint_rad) * [J]) } {joint_sphere} put { scale( [J] + proximal_distal_ratio * ([I]+[K]) ) } {segment} } def finger_0 { put { translate(joint_gap * joint_rad * [J]) then rotate(middle_0_rot, [I]) then translate((middle_ratio * distal_len + joint_gap * joint_rad) * [J]) } {distal_0} put { scale(proximal_distal_ratio) then rotate(middle_0_rot / 2, [I]) then translate((middle_ratio * distal_len + joint_gap * joint_rad) * [J]) } {joint_sphere} put { scale( middle_ratio * [J] + proximal_distal_ratio^2 * ([I]+[K]) ) } {segment} } def distal_1 { put { translate(joint_gap * joint_rad * [J]) then rotate(distal_1_rot, [I]) then translate((distal_len + joint_gap * joint_rad) * [J]) } {segment} put { rotate(distal_1_rot / 2, [I]) then translate((distal_len + joint_gap * joint_rad) * [J]) } {joint_sphere} put { scale( [J] + proximal_distal_ratio * ([I]+[K]) ) } {segment} } def finger_1 { put { translate(joint_gap * joint_rad * [J]) then rotate(middle_1_rot, [I]) then translate((middle_ratio * distal_len + joint_gap * joint_rad) * [J]) } {distal_1} put { scale(proximal_distal_ratio) then rotate(middle_1_rot / 2, [I]) then translate((middle_ratio * distal_len + joint_gap * joint_rad) * [J]) } {joint_sphere} put { scale( middle_ratio * [J] + proximal_distal_ratio^2 * ([I]+[K]) ) } {segment} } def distal_2 { put { translate(joint_gap * joint_rad * [J]) then rotate(distal_2_rot, [I]) then translate((distal_len + joint_gap * joint_rad) * [J]) } {segment} put { rotate(distal_2_rot / 2, [I]) then translate((distal_len + joint_gap * joint_rad) * [J]) } {joint_sphere} put { scale( [J] + proximal_distal_ratio * ([I]+[K]) ) } {segment} } def finger_2 { put { translate(joint_gap * joint_rad * [J]) then rotate(middle_2_rot, [I]) then translate((middle_ratio * distal_len + joint_gap * joint_rad) * [J]) } {distal_2} put { scale(proximal_distal_ratio) then rotate(middle_2_rot / 2, [I]) then translate((middle_ratio * distal_len + joint_gap * joint_rad) * [J]) } {joint_sphere} put { scale( middle_ratio * [J] + proximal_distal_ratio^2 * ([I]+[K]) ) } {segment} } def distal_3 { put { translate(joint_gap * joint_rad * [J]) then rotate(distal_3_rot, [I]) then translate((distal_len + joint_gap * joint_rad) * [J]) } {segment} put { rotate(distal_3_rot / 2, [I]) then translate((distal_len + joint_gap * joint_rad) * [J]) } {joint_sphere} put { scale( [J] + proximal_distal_ratio * ([I]+[K]) ) } {segment} } def finger_3 { put { translate(joint_gap * joint_rad * [J]) then rotate(middle_3_rot, [I]) then translate((middle_ratio * distal_len + joint_gap * joint_rad) * [J]) } {distal_3} put { scale(proximal_distal_ratio) then rotate(middle_3_rot / 2, [I]) then translate((middle_ratio * distal_len + joint_gap * joint_rad) * [J]) } {joint_sphere} put { scale( middle_ratio * [J] + proximal_distal_ratio^2 * ([I]+[K]) ) } {segment} } def distal_4 { put { translate(joint_gap * joint_rad * [J]) then rotate(distal_4_rot, [I]) then translate((distal_len + joint_gap * joint_rad) * [J]) } {segment} put { rotate(distal_4_rot / 2, [I]) then translate((distal_len + joint_gap * joint_rad) * [J]) } {joint_sphere} put { scale( [J] + proximal_distal_ratio * ([I]+[K]) ) } {segment} } def finger_4 { put { translate(joint_gap * joint_rad * [J]) then rotate(middle_4_rot, [I]) then translate((middle_ratio * distal_len + joint_gap * joint_rad) * [J]) } {distal_4} put { scale(proximal_distal_ratio) then rotate(middle_4_rot / 2, [I]) then translate((middle_ratio * distal_len + joint_gap * joint_rad) * [J]) } {joint_sphere} put { scale( middle_ratio * [J] + proximal_distal_ratio^2 * ([I]+[K]) ) } {segment} } % points on the palm of the hand def proximal_0_loc (1.8,-5.5,0) def proximal_1_loc (1.8,.1,0) def proximal_2_loc (O) def proximal_3_loc (-1.8,-.2,0) def proximal_4_loc (-3.6,-.5,0) def h5 (proximal_4_loc) + [-.6,-.2] def h6 (h5) + [1,-5] def h8 (proximal_0_loc) + [.75,-.5] def h7 (h8) + [-.6,-.8] def h6a (h6) + .6 * ((h7) - (h6)) def h9 (h8) + [-1.9,1] def h10 (proximal_1_loc) + [.85,-.3] def hand { % thumb has an extra rotation for opposable-ness! def opposition_rot rotate(-50, [J]) def thk_scale_0 1.2 put { scale([thk_scale_0,.9,thk_scale_0]) % this distorts a little; oh well then translate((joint_gap * joint_rad) * [J]) then [[opposition_rot]] then rotate(meta_0_rot, [I]) then rotate(-spread_rot_0, [K]) then translate((proximal_0_loc) - (O)) } {finger_0} put { scale(thk_scale_0 * proximal_distal_ratio^2) then [[opposition_rot]] then rotate(meta_0_rot / 2, [I]) then rotate(-spread_rot_0, [K]) then translate((proximal_0_loc) - (O)) } {joint_sphere} % index finger def scale_1 .85 put { scale(scale_1) then translate((joint_gap * joint_rad) * [J]) then rotate(meta_1_rot, [I]) then rotate(-spread_rot, [K]) then translate((proximal_1_loc) - (O)) } {finger_1} put { scale(scale_1 * proximal_distal_ratio^2) then rotate(meta_1_rot / 2, [I]) then rotate(-spread_rot, [K]) then translate((proximal_1_loc) - (O)) } {joint_sphere} % middle finger put { % no scale then translate((joint_gap * joint_rad) * [J]) then rotate(meta_2_rot, [I]) % no spread rotation then translate((proximal_2_loc) - (O)) } {finger_2} put { scale(proximal_distal_ratio^2) then rotate(meta_2_rot / 2, [I]) then rotate(-spread_rot, [K]) then translate((proximal_2_loc) - (O)) } {joint_sphere} % ring finger def scale_3 .85 put { scale(scale_3) then translate((joint_gap * joint_rad) * [J]) then rotate(meta_3_rot, [I]) then rotate(spread_rot, [K]) then translate((proximal_3_loc) - (O)) } {finger_3} put { scale(scale_3 * proximal_distal_ratio^2) then rotate(meta_3_rot / 2, [I]) then rotate(-spread_rot, [K]) then translate((proximal_3_loc) - (O)) } {joint_sphere} % little finger def scale_4 .7 put { scale(scale_4) then translate((joint_gap * joint_rad) * [J]) then rotate(meta_4_rot, [I]) then rotate(2 * spread_rot, [K]) then translate((proximal_4_loc) - (O)) } {finger_4} put { scale(scale_4 * proximal_distal_ratio^2) then rotate(meta_4_rot / 2, [I]) then rotate(-spread_rot, [K]) then translate((proximal_4_loc) - (O)) } {joint_sphere} % palm is built by sweeping a polygon through a small % angle in order to make it thicker at the wrist put { translate(joint_gap * joint_rad * -[J]) } % drop polytope to expose knuckles sweep { 1, rotate(6, (0,15,0), [I]) } put { rotate(-3, (0,15,0), [I]) } { % need two polygons for convexity; the desired shape is concave at the thumb polygon(proximal_1_loc)(proximal_2_loc)(proximal_3_loc)(proximal_4_loc) (h5)(h6)(h6a)(h9)(h10) polygon(h6a)(h7)(h8)(h9) } } % a few views def viewxf view((0,0,10)) view((10,0,0)) view((0,10,0), (O), -[K]) <> view((4,3,10)) % either a single copy or a repeat to show different angles def scene put { [[viewxf]] then scale(.25) } { def N 4 repeat { N, rotate(270/N, [3,2,1]), translate(14*[I]) } {hand} } <> put { [[viewxf]] then scale(.3) } {hand} {scene} global { set [linewidth=.3pt] }