/* sticfigure drawings in asymptote. * * Copyright (C) 2008-2009 W. Trevor King * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ struct StickFigure { pair center; real height; real headHeightRatio; real neckHeightRatio; real torsoHeightRatio; real shoulderHeightRatio; real legHeightRatio; real centerTorsoRatio; real armTorsoRatio; real rightArmAngle; real leftArmAngle; real rightLegAngle; real leftLegAngle; pen outline; pen fill; void operator init(pair standsOn=(0,0), real height=10mm) { this.height = height; this.headHeightRatio = 0.2; this.neckHeightRatio = 0.1; this.torsoHeightRatio = 0.28; this.shoulderHeightRatio = 0.1; /* at shoulder width, a leg takes this much height: * 1 - head - neck - torso (opposite legAngle) * and this much width: * shoulder/2 (adjavent legAngle) */ this.rightLegAngle = -aTan( 2*(1-this.headHeightRatio-this.neckHeightRatio-this.torsoHeightRatio) /this.shoulderHeightRatio); this.leftLegAngle = rightLegAngle; this.legHeightRatio = this.shoulderHeightRatio/2/Cos(this.rightLegAngle); this.centerTorsoRatio = 0.2; this.armTorsoRatio = 1.2; this.rightArmAngle = -70; this.leftArmAngle = -70; this.outline = currentpen; this.fill = currentpen; this.center = standsOn + (0, this.height*(this.legHeightRatio*Sin(-this.rightLegAngle) +this.torsoHeightRatio*this.centerTorsoRatio)); } /* center a fixed torso fraction (centerTorsoRatio) above tail. * Everything else located from that point. */ pair tailPos() { return this.center - (0,this.height*this.torsoHeightRatio*this.centerTorsoRatio); } pair neckBasePos() { return this.tailPos() + (0,this.height*this.torsoHeightRatio); } pair chinPos() { return this.neckBasePos() + (0,this.height*this.neckHeightRatio); } pair crownPos() { return this.chinPos() + (0,this.height*this.headHeightRatio); } pair headPos() { return (this.crownPos() + this.chinPos())/2; } pair shoulderPos(bool leftSide=false) { real sign = 1; if (leftSide == true) sign = -1; return this.neckBasePos() + (sign*this.height*this.shoulderHeightRatio/2,0); } pair handPos(bool leftSide=false) { real len = this.height*this.torsoHeightRatio*this.armTorsoRatio; real ang; if (leftSide == true) { ang = 180 - this.leftArmAngle; } else{ ang = this.rightArmAngle; } return this.shoulderPos(leftSide=leftSide) + len * dir(ang); } pair footPos(bool leftSide=false) { real len = this.height*this.legHeightRatio; real ang; if (leftSide == true) { ang = 180 - this.leftLegAngle; } else{ ang = this.rightLegAngle; } return this.tailPos() + len * dir(ang); } pair standsOnPos() { return (this.footPos() + this.footPos(leftSide=true))/2; } void standsOn(pair pos) { this.center += pos - this.standsOnPos(); } void draw(picture pic=currentpicture) { path head = shift(this.headPos()) *scale(this.height*this.headHeightRatio/2) *unitcircle; path neckAndTorso = this.chinPos() --this.neckBasePos() --this.tailPos(); path armsAndShoulders = this.handPos(leftSide=false) --this.shoulderPos(leftSide=false) --this.shoulderPos(leftSide=true) --this.handPos(leftSide=true); path legs = this.footPos(leftSide=false) --this.tailPos() --this.footPos(leftSide=true); draw(pic, armsAndShoulders, this.outline); draw(pic, legs, this.outline); draw(pic, neckAndTorso, this.outline); dot(this.handPos(leftSide=false), this.fill); dot(this.handPos(leftSide=true), this.fill); dot(this.footPos(leftSide=false), this.fill); dot(this.footPos(leftSide=true), this.fill); filldraw(pic, head, this.fill, this.outline); } }