1 /* sticfigure drawings in asymptote.
3 * Copyright (C) 2008-2009 W. Trevor King <wking@drexel.edu>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 real torsoHeightRatio;
26 real shoulderHeightRatio;
28 real centerTorsoRatio;
37 void operator init(pair standsOn=(0,0), real height=10mm) {
39 this.headHeightRatio = 0.2;
40 this.neckHeightRatio = 0.1;
41 this.torsoHeightRatio = 0.28;
42 this.shoulderHeightRatio = 0.1;
43 /* at shoulder width, a leg takes this much height:
44 * 1 - head - neck - torso (opposite legAngle)
45 * and this much width:
46 * shoulder/2 (adjavent legAngle)
48 this.rightLegAngle = -aTan(
49 2*(1-this.headHeightRatio-this.neckHeightRatio-this.torsoHeightRatio)
50 /this.shoulderHeightRatio);
51 this.leftLegAngle = rightLegAngle;
52 this.legHeightRatio = this.shoulderHeightRatio/2/Cos(this.rightLegAngle);
53 this.centerTorsoRatio = 0.2;
54 this.armTorsoRatio = 1.2;
55 this.rightArmAngle = -70;
56 this.leftArmAngle = -70;
57 this.outline = currentpen;
58 this.fill = currentpen;
60 this.center = standsOn +
61 (0, this.height*(this.legHeightRatio*Sin(-this.rightLegAngle)
62 +this.torsoHeightRatio*this.centerTorsoRatio));
65 /* center a fixed torso fraction (centerTorsoRatio) above tail.
66 * Everything else located from that point.
71 - (0,this.height*this.torsoHeightRatio*this.centerTorsoRatio);
75 return this.tailPos() + (0,this.height*this.torsoHeightRatio);
79 return this.neckBasePos() + (0,this.height*this.neckHeightRatio);
83 return this.chinPos() + (0,this.height*this.headHeightRatio);
87 return (this.crownPos() + this.chinPos())/2;
90 pair shoulderPos(bool leftSide=false) {
94 return this.neckBasePos() + (sign*this.height*this.shoulderHeightRatio/2,0);
97 pair handPos(bool leftSide=false) {
98 real len = this.height*this.torsoHeightRatio*this.armTorsoRatio;
100 if (leftSide == true) {
101 ang = 180 - this.leftArmAngle;
103 ang = this.rightArmAngle;
105 return this.shoulderPos(leftSide=leftSide) + len * dir(ang);
109 pair footPos(bool leftSide=false) {
110 real len = this.height*this.legHeightRatio;
112 if (leftSide == true) {
113 ang = 180 - this.leftLegAngle;
115 ang = this.rightLegAngle;
117 return this.tailPos() + len * dir(ang);
121 return (this.footPos() + this.footPos(leftSide=true))/2;
124 void standsOn(pair pos) {
125 this.center += pos - this.standsOnPos();
128 void draw(picture pic=currentpicture) {
130 shift(this.headPos())
131 *scale(this.height*this.headHeightRatio/2)
137 path armsAndShoulders =
138 this.handPos(leftSide=false)
139 --this.shoulderPos(leftSide=false)
140 --this.shoulderPos(leftSide=true)
141 --this.handPos(leftSide=true);
143 this.footPos(leftSide=false)
145 --this.footPos(leftSide=true);
146 draw(pic, armsAndShoulders, this.outline);
147 draw(pic, legs, this.outline);
148 draw(pic, neckAndTorso, this.outline);
149 dot(this.handPos(leftSide=false), this.fill);
150 dot(this.handPos(leftSide=true), this.fill);
151 dot(this.footPos(leftSide=false), this.fill);
152 dot(this.footPos(leftSide=true), this.fill);
153 filldraw(pic, head, this.fill, this.outline);