rt300@0: /* rt300@0: * spring.cpp rt300@0: * simplespring rt300@0: * rt300@0: * Created by Robert Tubb on 02/06/2011. rt300@0: * Copyright 2011 __MyCompanyName__. All rights reserved. rt300@0: * rt300@0: */ rt300@0: rt300@0: #include "spring.h" rt300@0: #include "lump.h" rt300@0: #include "globalForces.h" rt300@0: rt300@0: #include rt300@0: #include "globalUI.h" rt300@0: extern GlobalForces globalForces; rt300@0: extern GlobalUI globalUI; rt300@0: // statics rt300@0: int Spring::numSprings = 0; rt300@0: double Spring::maxForce = 0.0; rt300@0: double Spring::minForce = 0.0; rt300@0: bool Spring::forcesOn = true; rt300@0: rt300@0: //--------------------------------------------------------------- rt300@0: Spring::Spring(){ rt300@0: //cout << "constructing a default spring" << endl; rt300@3: rt300@3: isInScanPath = false; rt300@0: rt300@3: springConst = 0.3; rt300@3: rt300@0: rt300@0: startLumpPtr = 0; rt300@0: endLumpPtr = 0; rt300@0: restLength = 0.0; rt300@0: myIndex = Spring::numSprings++; rt300@0: maxForce = 0.005; rt300@0: minForce = -0.005; rt300@0: rt300@0: force.x = 0.0; rt300@0: force.y = 0.0; rt300@0: rt300@0: // width of a spring is proportional to how beefy it is rt300@0: //ofSetLineWidth(springConst*2); rt300@0: rt300@0: } rt300@0: //--------------------------------------------------------------- rt300@0: Spring::Spring(double aStartx, double aStarty, double aEndx, double aEndy, double aK){ rt300@0: // hfsjsfhfshsgr rt300@0: rt300@0: rt300@0: } rt300@0: //--------------------------------------------------------------- rt300@0: void Spring::attachLump(Lump * aLump){ rt300@0: // set position of spring start to mass position rt300@0: if(startLumpPtr == 0){ rt300@0: startLumpPtr = aLump; rt300@0: rt300@0: }else if(endLumpPtr == 0){ rt300@0: endLumpPtr = aLump; rt300@0: //cout << "----------------------------------------end point attached to " << endLumpPtr << endl; rt300@0: updateEndPoints(); // now both ends attached - set the spring start and end points to the relevant lumps rt300@0: setRestLength(); // the default length for the spring can be set rt300@0: }else{ rt300@0: cerr << "PERROR can't attach lump to this spring cos it's already attached both ends" << endl; rt300@0: } rt300@0: } rt300@0: Lump * Spring::getLumpOnOtherEnd(Lump * alump){ rt300@0: if (startLumpPtr == alump){ rt300@0: return endLumpPtr; rt300@0: rt300@0: }else if (endLumpPtr == alump){ rt300@0: return startLumpPtr; rt300@0: } rt300@0: cout << "getLumpOnOtherEnd: this should never happen" << endl; rt300@0: rt300@0: return NULL; rt300@0: } rt300@9: rt300@9: Lump * Spring::getStartLump(){ rt300@9: return startLumpPtr; rt300@9: } rt300@9: Lump * Spring::getEndLump(){ rt300@9: return endLumpPtr; rt300@9: } rt300@9: int Spring::getStartLumpIndex(){ rt300@9: return startLumpPtr->myIndexInMesh; rt300@9: } rt300@9: int Spring::getEndLumpIndex(){ rt300@9: return endLumpPtr->myIndexInMesh; rt300@9: } rt300@0: //--------------------------------------------------------------- rt300@0: void Spring::setRestLength(){ rt300@0: rt300@0: //set rest length according to what the length is now rt300@0: TwoVector diff(startPoint.x - endPoint.x, startPoint.y - endPoint.y); rt300@0: rt300@0: restLength = diff.norm(); rt300@0: rt300@0: //restLength = 0.0; rt300@0: rt300@0: } rt300@0: rt300@0: void Spring::setRestLength(double aLength){ rt300@0: restLength = aLength; rt300@0: rt300@0: } rt300@0: void Spring::setSpringConstant(double aK){ rt300@0: springConst = aK; rt300@0: } rt300@0: double Spring::getLength(){ rt300@0: return startPoint.distanceTo(endPoint); rt300@0: } rt300@0: //--------------------------------------------------------------- rt300@0: void Spring::updateEndPoints(){ rt300@0: // tweak the end points eg: from mass move rt300@0: if (startLumpPtr ==0 || endLumpPtr == 0){ rt300@0: cerr << "PERROR spring masses not attached!" << endl; rt300@0: }else{ rt300@0: startPoint = startLumpPtr->position; rt300@0: //cout << "start pt x = " << startPoint.x << ", y = " << startPoint.y << endl; rt300@0: endPoint = endLumpPtr->position; rt300@0: } rt300@0: } rt300@0: //--------------------------------------------------------------- rt300@0: void Spring::calculateForce(){ rt300@0: rt300@0: if(!Spring::forcesOn){ rt300@0: force.x = 0.0; rt300@0: force.y = 0.0; rt300@0: return; rt300@0: } rt300@0: // get force from the extension rt300@0: double xe = endPoint.x - startPoint.x; rt300@0: double ye = endPoint.y - startPoint.y; rt300@0: double extendedLength = sqrt(xe*xe + ye*ye); rt300@0: rt300@0: // doing this enables us to get away with only one division etc rt300@0: double FF = springConst*(restLength/extendedLength - 1.0); rt300@0: rt300@0: force.x = FF*xe; rt300@0: force.y = FF*ye; rt300@0: rt300@0: } rt300@0: //--------------------------------------------------------------- rt300@0: TwoVector Spring::getForce(Lump * aLump){ // pass in the lump that we want the force for rt300@0: rt300@0: // above force refers to force at END force at START negative of this... rt300@0: if(aLump == startLumpPtr){ rt300@0: TwoVector rForce; rt300@0: rForce.setCoord(-force.x, -force.y); rt300@0: return rForce; rt300@0: }else if(aLump == endLumpPtr ){ rt300@0: return force; rt300@0: } rt300@0: cout << "PERROR this lump is not attached to this spring\n"; rt300@0: rt300@0: return force; rt300@0: rt300@0: } rt300@0: rt300@0: rt300@0: //--------------------------------------------------------------- rt300@0: void Spring::draw(){ rt300@0: rt300@0: int sxpos = startPoint.x * ofGetHeight() + globalUI.borderSize; // TODO make this nicer rt300@0: int sypos = startPoint.y * ofGetHeight(); rt300@0: //cout << "start position = " << sxpos << "," << sypos << endl; rt300@0: int expos = endPoint.x * ofGetHeight() + globalUI.borderSize; rt300@0: int eypos = endPoint.y*ofGetHeight(); rt300@0: //cout << "end position = " << expos << "," << eypos << endl; rt300@0: rt300@0: if(isInScanPath){ rt300@0: ofSetLineWidth(4); rt300@0: ofSetColor(0, 255, 0); rt300@0: }else{ rt300@0: ofSetLineWidth(1); rt300@0: ofSetColor(0, 0, 255); rt300@0: } rt300@0: rt300@0: ofLine(sxpos, sypos, expos, eypos); rt300@0: } rt300@0: //--------------------------------------------------------------- rt300@0: double Spring::getForceMag(){ rt300@0: return force.norm(); rt300@0: } rt300@0: //--------------------------------------------------------------- rt300@0: void Spring::addToScanPath(){ rt300@0: isInScanPath = true; rt300@0: } rt300@0: //--------------------------------------------------------------- rt300@0: void Spring::removeFromScanPath(){ rt300@0: isInScanPath = false; rt300@0: } rt300@0: //--------------------------------------------------------------- rt300@0: /* rt300@0: void Spring::checkStuff(){ rt300@0: cout << "checking\n"; rt300@0: } rt300@0: */ rt300@0: PressureSpring::PressureSpring(){ rt300@0: cout << "constructing a pressure spring for droplet mesh\n"; rt300@0: } rt300@0: rt300@0: //--------------------------------------------------------------- rt300@0: TwoVector PressureSpring::getForce(Lump * aLump){ // pass in the lump that we want the force for rt300@0: rt300@0: // PRESSURE STUFF rt300@0: // by convention a positive pressure allways acts to the left as looking from start to end point rt300@0: // ie: Droplet MUST be constructed in clockwise fashion rt300@0: // we rotate the spring vector anti clockwise pi/2 radians this gives us the force vector rt300@0: // x = -y , y = x except damn y coordinate points downwards so handedness is reversed rt300@0: rt300@0: // conveniently this is proportional to length just as pressure would be rt300@0: //cout << "pressure spring get force\n"; rt300@0: double xe = endPoint.x - startPoint.x; rt300@0: double ye = endPoint.y - startPoint.y; rt300@0: // above force refers to force at END force at START negative of this... rt300@0: if(aLump == startLumpPtr){ rt300@0: TwoVector rForce; rt300@0: rForce.setCoord(-force.x, -force.y); rt300@0: rForce.x += ye * globalForces.pressure * 0.5; rt300@0: rForce.y -= xe * globalForces.pressure * 0.5; rt300@0: return rForce; rt300@0: }else if(aLump == endLumpPtr ){ rt300@0: TwoVector rForce; rt300@0: rForce.setCoord(force.x, force.y); rt300@0: rForce.x += ye * globalForces.pressure * 0.5; rt300@0: rForce.y -= xe * globalForces.pressure * 0.5; rt300@0: return rForce; rt300@0: } rt300@0: cout << "PERROR this lump is not attached to this spring\n"; rt300@0: rt300@0: return force; rt300@0: rt300@0: }