rt300@0: /* rt300@0: * mesh.cpp rt300@0: * springstructure rt300@0: * rt300@0: * Created by Robert Tubb on 07/06/2011. rt300@0: * Copyright 2011 __MyCompanyName__. All rights reserved. rt300@0: * rt300@0: */ rt300@0: rt300@0: #include "mesh.h" rt300@0: #include "testApp.h" rt300@0: #include "lump.h" rt300@0: #include rt300@0: rt300@0: extern GlobalForces globalForces; rt300@3: extern ScanPath scanPath; // now global rt300@0: rt300@0: //-------------------------------------------------------------- rt300@0: Mesh::Mesh(){ rt300@0: // construct an empty structure rt300@10: setReasonableDefaults(); rt300@10: rt300@10: cout << "constructed mesh base" << endl; rt300@10: } rt300@10: rt300@10: rt300@10: Mesh::~Mesh(){ rt300@10: cout << "destroying mesh" << endl; rt300@10: rt300@10: rt300@10: } rt300@10: //-------------------------------------------------------------- rt300@10: void Mesh::setReasonableDefaults(){ rt300@10: numSprings = 0; rt300@0: numLumps = 0; rt300@10: rt300@0: syrup = false; rt300@0: GRAB_RANGE = 0.040; rt300@0: propagationSpeed = 0.5; // this will be changed by adjusting k/m rt300@10: rt300@0: rt300@0: m = 123.0; rt300@0: k = 0.1; rt300@0: f = 0.999; rt300@10: rt300@0: prevLump = -1; rt300@0: rt300@0: // some reasonable defaults rt300@0: setSpringConstant(0.8); rt300@0: setMass(1); rt300@0: setFriction(0.999991); rt300@0: } rt300@9: //-------------------------------------------------------------- rt300@9: //-------------------------------------------------------------- rt300@9: Mesh::Mesh(Json::Value& jmesh){ rt300@10: setReasonableDefaults(); // sensible? rt300@9: rt300@9: meshType = (MeshType)jmesh.get("meshType",0).asInt(); rt300@9: dim1 = jmesh.get("dim1",0).asInt(); rt300@9: dim2 = jmesh.get("dim1",0).asInt(); rt300@9: rt300@9: // need to know how many springs and lumps rt300@9: numLumps = jmesh.get("numLumps",0).asInt(); rt300@9: numSprings = jmesh.get("numSprings",0).asInt(); rt300@9: rt300@9: // make them rt300@9: makeComponents(numLumps, numSprings); rt300@13: setLumpPositionsFromJson(jmesh["lumpPositions"], jmesh["lumpRestPositions"]); rt300@9: makeConnectionsFromJson(jmesh["connections"]); rt300@9: makeScanPathFromJson(jmesh["scanPath"]); rt300@9: constrainFromJson(jmesh["constrainedLumps"]); rt300@9: rt300@9: // now set saved properties rt300@9: setSpringConstant(jmesh["springConstant"].asDouble()); rt300@9: setMass(jmesh["mass"].asDouble()); rt300@9: setFriction(jmesh["friction" ].asDouble()); rt300@9: // rest length? rt300@9: zeroRestLength(); rt300@9: } rt300@9: rt300@9: //-------------------------------------------------------------- rt300@13: void Mesh::setLumpPositionsFromJson(Json::Value lumpPositions, Json::Value lumpRestPositions){ rt300@9: int N = lumpPositions.size(); rt300@9: rt300@9: for(int i=0;i 24){ rt300@4: for(int i=0;i 48) updown = 0; rt300@0: // update the ends of the springs to reflect lump movement rt300@0: rt300@0: for(int i=0;i avLumpPos = vector(lumps.size()); rt300@0: rt300@4: rt300@4: for(int i=0;i::iterator spriter = springs.begin(); spriter < springs.end(); spriter++){ rt300@3: (*spriter).setRestLength(0.0); rt300@0: } rt300@3: rt300@0: } rt300@0: //-------------------------------------------------------------- rt300@0: int Mesh::getNearestLump(double ax, double ay){ rt300@0: // not used yet rt300@0: int nearestLumpIndex = -1; rt300@0: TwoVector diff; rt300@0: double distance = 1.0; rt300@0: double minDistance = 1.0; rt300@0: rt300@4: for(int i = 0; i(numLumps); rt300@9: cout << "made " << numLumps << " lumps\n"; rt300@9: rt300@9: // one by one rt300@9: springs = vector(numSprings); rt300@9: rt300@9: cout << "made " << numSprings << " springs\n"; rt300@9: rt300@9: // tell them what index they are (for connections) rt300@9: for(int i = 0; i= lumps.size()){ rt300@1: cout << " setLumpPosisions index error!\n"; rt300@1: } rt300@0: lumps[i].setPosition(hspacing*col,vspacing*row); rt300@0: rt300@0: i++; rt300@0: } rt300@0: } rt300@9: rt300@9: } rt300@9: //-------------------------------------------------------------- rt300@9: void SquareMesh::makeConnections(){ rt300@9: rt300@9: // could be cleverer in terms of numbering? rt300@9: int lumpnum = 0; rt300@9: int springnum = 0; rt300@9: // attach horizontal rt300@9: for ( int i=0;i= numSprings){ rt300@9: cout << " makeConnections index error!\n"; rt300@9: } rt300@9: if(lumpnum >= lumps.size()){ rt300@9: cout << " makeConnections index error!\n"; rt300@9: } rt300@9: connect(springnum,lumpnum); rt300@9: springnum++; rt300@9: rt300@9: } rt300@9: lumpnum++; rt300@9: } rt300@9: cout << "lumps attach horz: " << lumpnum-1 << ", spring " << springnum-1 << "\n"; rt300@9: // attach vertical rt300@9: lumpnum = 0; rt300@9: for ( int i=0;i= numSprings){ rt300@9: cout << " makeConnections index error!\n"; rt300@9: } rt300@9: if(lumpnum >= lumps.size()){ rt300@9: cout << " makeConnections index error!\n"; rt300@9: } rt300@9: connect(springnum,lumpnum); rt300@9: springnum++; rt300@9: rt300@9: } rt300@9: lumpnum -= (width*(height-1)) - 1; rt300@9: } rt300@1: rt300@0: } rt300@9: rt300@9: //-------------------------------------------------------------- rt300@9: void SquareMesh::constrain(double ax, double ay, constrainMode aMode){ rt300@9: rt300@9: TwoVector diff; rt300@9: int i = 0; rt300@9: rt300@9: // check if lump is within grab range rt300@9: switch (aMode) { rt300@9: case CONSTRAIN_GRAB_REGION: rt300@9: for(i = 0; i= lumps.size()){ rt300@9: cout << "constrain index error\n"; rt300@9: } rt300@9: lumps[i].constrain(); rt300@9: } rt300@9: } rt300@9: break; rt300@9: case CONSTRAIN_EDGES: rt300@9: i = 0; rt300@9: for(int row = 0; row < height; row++){ // go down column rt300@9: for(int col = 0;col < width; col++){ // go along row rt300@9: if(row == 0 || row == height-1 || col == 0 || col == width-1){ rt300@9: if(i >= lumps.size()){ rt300@9: cout << "constrain index error\n"; rt300@9: } rt300@9: lumps[i].constrain(); rt300@9: } rt300@9: i++; rt300@9: } rt300@9: } rt300@9: break; rt300@9: case CONSTRAIN_EDGES_XY: rt300@9: i = 0; rt300@9: for(int row = 0; row < height; row++){ // go down column rt300@9: for(int col = 0;col < width; col++){ // go along row rt300@9: if(row == 0 || row == height-1){ rt300@9: if(i >= lumps.size()){ rt300@9: cout << "constrain index error\n"; rt300@9: } rt300@9: lumps[i].constrain(Lump::CONSTRAIN_Y); rt300@9: }else if( col == 0 || col == width-1){ rt300@9: if(i >= lumps.size()){ rt300@9: cout << "constrain index error\n"; rt300@9: } rt300@9: lumps[i].constrain(Lump::CONSTRAIN_X); rt300@9: } rt300@9: i++; rt300@9: } rt300@9: } rt300@9: break; rt300@9: case CONSTRAIN_CORNERS: rt300@9: i = 0; rt300@9: for(int row = 0; row < height; row++){ // go down column rt300@9: for(int col = 0;col < width; col++){ // go along row rt300@9: if( (row == 0 && col == 0) rt300@9: || (row == height-1 && col == 0) rt300@9: || (row == 0 && col == width-1) rt300@9: || (row == height-1 && col == width-1)){ rt300@9: if(i >= lumps.size()){ rt300@9: cout << "constrain index error\n"; rt300@9: } rt300@9: lumps[i].constrain(); rt300@9: } rt300@9: i++; rt300@9: } rt300@9: } rt300@9: break; rt300@9: rt300@9: default: rt300@9: break; rt300@9: } rt300@9: rt300@9: } rt300@9: rt300@9: //-------------------------------------------------------------- rt300@9: void SquareMesh::makeDefaultScanPath(){ rt300@9: if (height < 10 || width < 10) return; // not much point rt300@9: rt300@9: int vmarg = 5; rt300@9: int hmarg = 5; rt300@9: rt300@9: int lumpno = vmarg * width + hmarg; // top left corner rt300@9: int springno = vmarg * (width - 1) + hmarg; rt300@9: // do top horz rt300@9: for(int i = 0; i < width - 2*hmarg; i++){ rt300@9: if(lumpno >= lumps.size()) cout << "makeDefaultScanPath index error\n"; rt300@9: if(springno >= numSprings) cout << "makeDefaultScanPath index error\n"; rt300@9: scanPath.addElement(&lumps[lumpno], &springs[springno]); rt300@9: lumpno++; rt300@9: springno++; rt300@9: } rt300@9: rt300@9: // do right vert, lumpno starts the same rt300@9: // all horz spr // left marg rows // top margin rt300@9: springno = height*(width-1) + ((height-1) * (width - hmarg)) + vmarg; rt300@9: rt300@9: for(int i = 0; i < height - (2 * vmarg); i++){ rt300@9: if(lumpno >= lumps.size()) cout << "makeDefaultScanPath index error\n"; rt300@9: if(springno >= numSprings) cout << "makeDefaultScanPath index error\n"; rt300@9: scanPath.addElement(&lumps[lumpno], &springs[springno]); rt300@9: springno++; // jump to next row rt300@9: lumpno += width; // ditto rt300@9: } rt300@9: rt300@9: rt300@9: // do bottom horz right to left rt300@9: springno = (height - vmarg) * (width - 1) + (width - hmarg - 1); rt300@9: for(int i = 0; i < width - 2*hmarg; i++){ rt300@9: if(lumpno >= lumps.size()) cout << "makeDefaultScanPath index error\n"; rt300@9: if(springno >= numSprings) cout << "makeDefaultScanPath index error\n"; rt300@9: scanPath.addElement(&lumps[lumpno], &springs[springno]); rt300@9: springno--; // jump to next row rt300@9: lumpno--; // ditto rt300@9: } rt300@9: rt300@9: // all horz spr // left marg rows // top margin rt300@9: springno = height*(width-1) + ((height-1) * hmarg) + height - vmarg - 1; rt300@9: for(int i = 0; i < height - 2 * vmarg; i++){ rt300@9: if(lumpno >= lumps.size()) cout << "makeDefaultScanPath index error\n"; rt300@9: if(springno >= numSprings) cout << "makeDefaultScanPath index error\n"; rt300@9: scanPath.addElement(&lumps[lumpno], &springs[springno]); rt300@9: springno--; // jump to next row rt300@9: lumpno -= width; // ditto rt300@9: } rt300@9: rt300@9: } rt300@9: //-------------------------------------------------------------- rt300@9: rt300@9: /****************************************/ rt300@9: // SquareCrossMesh */ rt300@9: /****************************************/ rt300@9: //-------------------------------------------------------------- rt300@9: SquareCrossMesh::SquareCrossMesh(int height, int width){ rt300@9: rt300@9: meshType = SQUARE_CROSS_MESH; rt300@9: makeComponents(height, width); rt300@9: rt300@9: setLumpPositions(); rt300@9: rt300@9: makeConnections(); rt300@9: rt300@9: makeDefaultScanPath(); rt300@9: rt300@9: constrain(0,0,CONSTRAIN_EDGES); rt300@9: rt300@9: zeroRestLength(); rt300@9: rt300@9: radial = false; rt300@9: rt300@9: cout << "constructing SQUARECROSS mesh\n"; rt300@9: } rt300@9: SquareCrossMesh::~SquareCrossMesh(){ rt300@9: rt300@9: cout << "destructing SQUARECROSS mesh\n"; rt300@9: } rt300@9: rt300@0: //-------------------------------------------------------------- rt300@0: void SquareCrossMesh::makeConnections(){ rt300@0: rt300@0: // could be cleverer in terms of numbering? rt300@0: int lumpnum = 0; rt300@0: int springnum = 0; rt300@0: // attach horizontal rt300@0: for ( int i=0;i= numSprings){ rt300@1: cout << " makeConnections index error!\n"; rt300@1: } rt300@4: if(lumpnum >= lumps.size()){ rt300@1: cout << " makeConnections index error!\n"; rt300@1: } rt300@0: connect(springnum,lumpnum); rt300@0: springnum++; rt300@0: rt300@0: } rt300@0: lumpnum++; rt300@0: } rt300@1: cout << "lumps attach horz: " << lumpnum-1 << ", spring " << springnum-1 << "\n"; rt300@0: // attach vertical rt300@0: lumpnum = 0; rt300@0: for ( int i=0;i= numSprings){ rt300@1: cout << " makeConnections index error!\n"; rt300@1: } rt300@4: if(lumpnum >= lumps.size()){ rt300@1: cout << " makeConnections index error!\n"; rt300@1: } rt300@0: connect(springnum,lumpnum); rt300@0: springnum++; rt300@0: rt300@0: } rt300@0: lumpnum -= (width*(height-1)) - 1; rt300@0: } rt300@0: // attach diagonal rt300@0: lumpnum = 0; rt300@0: for ( int i=0;i= numSprings){ rt300@1: cout << " makeConnections index error!\n"; rt300@1: } rt300@4: if(lumpnum >= lumps.size()){ rt300@1: cout << " makeConnections index error!\n"; rt300@1: } rt300@0: connect(springnum,lumpnum+1); rt300@0: springnum++; rt300@0: rt300@0: } rt300@0: lumpnum -= (width*(height-1)) - 1; rt300@0: } rt300@0: // attach other diagonal rt300@0: lumpnum = 1; rt300@0: for ( int i=0;i= numSprings){ rt300@1: cout << " makeConnections index error!\n"; rt300@1: } rt300@4: if(lumpnum >= lumps.size()){ rt300@1: cout << " makeConnections index error!\n"; rt300@1: } rt300@0: connect(springnum,lumpnum-1); rt300@0: springnum++; rt300@0: rt300@0: } rt300@0: lumpnum -= (width*(height-1)) - 1; rt300@0: } rt300@0: } rt300@0: rt300@0: //-------------------------------------------------------------- rt300@9: rt300@0: //-------------------------------------------------------------- rt300@0: rt300@0: rt300@0: /****************************************/ rt300@0: // SpiderMesh */ rt300@0: /****************************************/ rt300@0: SpiderMesh::SpiderMesh(int aNumSpokes,int aNumRings) : Mesh(){ rt300@8: meshType = SPIDER_MESH; rt300@8: rt300@0: numSpokes = aNumSpokes; rt300@0: numRings = aNumRings; rt300@0: rt300@0: radial = true; rt300@0: rt300@0: makeComponents(numSpokes, numRings); rt300@0: rt300@0: setLumpPositions(); rt300@0: rt300@0: makeConnections(); rt300@0: rt300@0: makeDefaultScanPath(); rt300@0: rt300@0: constrain(0.0,0.0,CONSTRAIN_EDGES); rt300@0: constrain(0.0,0.0,CONSTRAIN_CORNERS); rt300@0: rt300@0: cout << "constructed SPIDER mesh\n"; rt300@0: rt300@0: rt300@0: rt300@0: } rt300@0: //-------------------------------------------------------------- rt300@0: void SpiderMesh::makeComponents(int aDimension1, int aDimension2){ rt300@0: // make componets creates the correct number of lumps and springs according to dimensions and mesh type rt300@0: cout << "!!!spider makeComponents\n"; rt300@0: numLumps = numSpokes * numRings + 1; // +1 cos one in the middle rt300@0: numSprings = 2 * numSpokes * numRings; rt300@0: rt300@4: //lumps = new Lump[numLumps]; rt300@4: lumps = vector(numLumps); rt300@4: cout << "made " << numLumps << " lumps\n"; rt300@3: springs = vector(numSprings); rt300@3: rt300@0: cout << "made " << numSprings << " springs\n"; rt300@0: rt300@0: rt300@0: } rt300@0: //-------------------------------------------------------------- rt300@0: void SpiderMesh::setLumpPositions(){ rt300@0: cout << "!spider setLumpPositions\n"; rt300@0: // here we're assuming that zero spoke is to right rt300@0: // work out sines / cosines for each spoke rt300@0: int l = 1; rt300@0: double hyplen,xpos,ypos; rt300@0: rt300@0: double * cosines = new double[numSpokes]; rt300@0: double * sines = new double[numSpokes]; rt300@0: double angle = 2 * PI / numSpokes; rt300@0: rt300@0: double ringSpacing = 1.0/(2*numRings); rt300@0: rt300@0: for(int spoke = 0; spoke < numSpokes; spoke++){ rt300@0: cosines[spoke] = cos(angle*spoke); rt300@0: sines[spoke] = sin(angle*spoke); rt300@0: } rt300@0: rt300@0: lumps[0].setPosition(0.5,0.5); rt300@0: rt300@0: for(int ring = 0; ring < numRings; ring++){ rt300@0: for(int spoke = 0; spoke < numSpokes; spoke++){ rt300@0: hyplen = ringSpacing * (ring+1); rt300@0: xpos = hyplen * cosines[spoke] + 0.5; rt300@0: ypos = hyplen*sines[spoke] + 0.5; rt300@0: lumps[l].setPosition(xpos,ypos); rt300@0: l++; rt300@0: rt300@0: } rt300@0: } rt300@0: delete [] cosines; rt300@0: delete [] sines; rt300@0: rt300@0: } rt300@0: //-------------------------------------------------------------- rt300@0: void SpiderMesh::makeConnections(){ rt300@0: // TODO needs to be rewritten to automatically rt300@0: // add in lumps and springs AS we're connecting rt300@0: //using std vector rt300@0: // this is dumb rt300@0: cout << "!!!spider make connections\n"; rt300@0: rt300@0: // UNLIKE a spider we're going to make rings first, to make indexing the scan path easier... rt300@0: rt300@0: for(int ring = 0; ring < numRings; ring++){ rt300@0: for(int spoke = 0; spoke < numSpokes-1; spoke++){ rt300@0: // spring , lump rt300@0: connect(numSpokes*ring + spoke, ring*numSpokes + spoke + 1); rt300@0: connect(numSpokes*ring + spoke, ring*numSpokes + spoke + 2); rt300@0: } rt300@0: // remember the last one on the ring goes back to first rt300@0: // spring , lump rt300@0: connect(numSpokes*ring + numSpokes - 1 , ring*numSpokes + numSpokes); rt300@0: connect(numSpokes*ring + numSpokes - 1, ring*numSpokes + 1); rt300@0: } rt300@0: // at which point we have used numSpokes*numRings springs rt300@0: int used = numSpokes*numRings; rt300@0: // first ring is different cos it connects to central point rt300@0: for(int spoke = 0; spoke < numSpokes; spoke++){ rt300@0: connect(used,0); // inner radial on center rt300@0: connect(used,spoke+1); // outer radial rt300@0: springs[used].setRestLength(0.0); // need tension on spokes rt300@0: used++; rt300@0: } rt300@0: // now do the rest of the radial spokes rt300@0: for(int ring = 0; ring < numRings-1; ring++){ rt300@0: for(int spoke = 0; spoke < numSpokes; spoke++){ rt300@0: connect(used,ring*numSpokes+1+spoke); // rt300@0: connect(used,(ring+1)*numSpokes+1+spoke); // going to next ring out rt300@0: springs[used].setRestLength(0.0); rt300@0: used++; rt300@0: } rt300@0: } rt300@0: } rt300@0: rt300@0: //-------------------------------------------------------------- rt300@0: void SpiderMesh::constrain(double ax, double ay, constrainMode aMode){ rt300@0: cout << "!!spider constrain\n"; rt300@0: rt300@0: TwoVector diff; rt300@0: int i = 0; rt300@0: rt300@0: // check if lump is within grab range rt300@0: switch (aMode) { rt300@0: case CONSTRAIN_GRAB_REGION: rt300@4: for(i = 0; i= 0 ; i--){ rt300@5: lumpno = numSpokes*i; // zero, numspokes etc rt300@5: springno = springsinrings + numSpokes*i; // starts from total rings, increments by numspokes etc rt300@5: scanPath.addElement(&lumps[lumpno], &springs[springno]); rt300@5: } rt300@5: */ rt300@5: rt300@0: } rt300@0: rt300@0: rt300@0: //-------------------------------------------------------------- rt300@0: /****************************************/ rt300@0: // Holed Spider Mesh */ rt300@0: /****************************************/ rt300@0: //-------------------------------------------------------------- rt300@0: HoledSpiderMesh::HoledSpiderMesh(int aNumSpokes,int aNumRings) : Mesh(){ rt300@8: meshType = HOLED_SPIDER_MESH; rt300@0: numSpokes = aNumSpokes; rt300@0: numRings = aNumRings; rt300@0: radial = true; rt300@0: rt300@0: makeComponents(numSpokes, numRings); rt300@0: rt300@0: setLumpPositions(); rt300@0: rt300@0: makeConnections(); rt300@0: rt300@0: makeDefaultScanPath(); rt300@0: rt300@0: constrain(0.0,0.0,CONSTRAIN_EDGES); rt300@0: constrain(0.0,0.0,CONSTRAIN_CORNERS); rt300@0: rt300@0: cout << "constructed SPIDER mesh\n"; rt300@0: } rt300@0: rt300@0: void HoledSpiderMesh::makeComponents(int aDimension1, int aDimension2){ rt300@0: // make componets creates the correct number of lumps and springs according to dimensions and mesh type rt300@0: cout << "HOLED spider makeComponents\n"; rt300@0: numLumps = numSpokes * numRings; rt300@0: numSprings = numSpokes * numRings + numSpokes * (numRings - 1); rt300@0: rt300@4: lumps = vector(numLumps); rt300@4: cout << "made " << numLumps << " lumps\n"; rt300@3: springs = vector(numSprings); rt300@0: cout << "made " << numSprings << " springs\n"; rt300@0: rt300@0: rt300@0: } rt300@0: //-------------------------------------------------------------- rt300@0: void HoledSpiderMesh::setLumpPositions(){ rt300@0: cout << "HOLED spider setLumpPositions\n"; rt300@0: // here we're assuming that zero spoke is to right rt300@0: // work out sines / cosines for each spoke rt300@0: int l = 0; rt300@0: double hyplen,xpos,ypos; rt300@0: rt300@0: double * cosines = new double[numSpokes]; rt300@0: double * sines = new double[numSpokes]; rt300@0: double angle = 2 * PI / numSpokes; rt300@0: rt300@0: double ringSpacing = 1.0/(2*numRings); rt300@0: rt300@0: for(int spoke = 0; spoke < numSpokes; spoke++){ rt300@0: cosines[spoke] = cos(angle*spoke); rt300@0: sines[spoke] = sin(angle*spoke); rt300@0: } rt300@0: rt300@0: for(int ring = 0; ring < numRings; ring++){ rt300@0: for(int spoke = 0; spoke < numSpokes; spoke++){ rt300@0: hyplen = ringSpacing * (ring+1); rt300@0: xpos = hyplen * cosines[spoke] + 0.5; rt300@0: ypos = hyplen*sines[spoke] + 0.5; rt300@0: lumps[l].setPosition(xpos,ypos); rt300@0: l++; rt300@0: rt300@0: } rt300@0: } rt300@0: delete [] cosines; rt300@0: delete [] sines; rt300@0: rt300@0: } rt300@0: //-------------------------------------------------------------- rt300@0: void HoledSpiderMesh::makeConnections(){ rt300@0: // TODO needs to be rewritten to automatically rt300@0: // add in lumps and springs AS we're connecting rt300@0: //using std vector rt300@0: // this is dumb rt300@0: cout << "HOLED spider make connections\n"; rt300@0: rt300@0: // UNLIKE a spider we're going to make rings first, to make indexing the scan path easier... rt300@0: rt300@0: for(int ring = 0; ring < numRings; ring++){ rt300@0: for(int spoke = 0; spoke < numSpokes-1; spoke++){ rt300@0: // spring , lump rt300@0: connect(numSpokes*ring + spoke, ring*numSpokes + spoke + 0); rt300@0: connect(numSpokes*ring + spoke, ring*numSpokes + spoke + 1); rt300@0: } rt300@0: // remember the last one on the ring goes back to first rt300@0: // spring , lump rt300@0: connect(numSpokes*ring + numSpokes - 1 , ring*numSpokes + numSpokes - 1); rt300@0: connect(numSpokes*ring + numSpokes - 1, ring*numSpokes); rt300@0: } rt300@0: // at which point we have used numSpokes*numRings springs rt300@0: int used = numSpokes*numRings; rt300@0: // now do the rest of the radial spokes rt300@0: for(int ring = 0; ring < numRings-1; ring++){ rt300@0: for(int spoke = 0; spoke < numSpokes; spoke++){ rt300@0: connect(used,ring*numSpokes+spoke); // rt300@0: connect(used,(ring+1)*numSpokes+spoke); // going to next ring out rt300@0: springs[used].setRestLength(0.0); rt300@0: used++; rt300@0: } rt300@0: } rt300@0: } rt300@0: rt300@0: //-------------------------------------------------------------- rt300@0: void HoledSpiderMesh::constrain(double ax, double ay, constrainMode aMode){ rt300@0: cout << "HOLED spider constrain\n"; rt300@0: rt300@0: TwoVector diff; rt300@0: int i = 0; rt300@0: int startLump = 0; rt300@0: // check if lump is within grab range rt300@0: switch (aMode) { rt300@0: case CONSTRAIN_GRAB_REGION: rt300@4: for(i = 0; i