rt300@0
|
1 /*
|
rt300@0
|
2 * mesh.cpp
|
rt300@0
|
3 * springstructure
|
rt300@0
|
4 *
|
rt300@0
|
5 * Created by Robert Tubb on 07/06/2011.
|
rt300@0
|
6 * Copyright 2011 __MyCompanyName__. All rights reserved.
|
rt300@0
|
7 *
|
rt300@0
|
8 */
|
rt300@0
|
9
|
rt300@0
|
10 #include "mesh.h"
|
rt300@0
|
11 #include "testApp.h"
|
rt300@0
|
12 #include "lump.h"
|
rt300@0
|
13 #include <math.h>
|
rt300@0
|
14
|
rt300@0
|
15 extern GlobalForces globalForces;
|
rt300@3
|
16 extern ScanPath scanPath; // now global
|
rt300@0
|
17
|
rt300@0
|
18 //--------------------------------------------------------------
|
rt300@0
|
19 Mesh::Mesh(){
|
rt300@0
|
20 // construct an empty structure
|
rt300@10
|
21 setReasonableDefaults();
|
rt300@10
|
22
|
rt300@10
|
23 cout << "constructed mesh base" << endl;
|
rt300@10
|
24 }
|
rt300@10
|
25
|
rt300@10
|
26
|
rt300@10
|
27 Mesh::~Mesh(){
|
rt300@10
|
28 cout << "destroying mesh" << endl;
|
rt300@10
|
29
|
rt300@10
|
30
|
rt300@10
|
31 }
|
rt300@10
|
32 //--------------------------------------------------------------
|
rt300@10
|
33 void Mesh::setReasonableDefaults(){
|
rt300@10
|
34 numSprings = 0;
|
rt300@0
|
35 numLumps = 0;
|
rt300@10
|
36
|
rt300@0
|
37 syrup = false;
|
rt300@0
|
38 GRAB_RANGE = 0.040;
|
rt300@0
|
39 propagationSpeed = 0.5; // this will be changed by adjusting k/m
|
rt300@10
|
40
|
rt300@0
|
41
|
rt300@0
|
42 m = 123.0;
|
rt300@0
|
43 k = 0.1;
|
rt300@0
|
44 f = 0.999;
|
rt300@10
|
45
|
rt300@0
|
46 prevLump = -1;
|
rt300@0
|
47
|
rt300@0
|
48 // some reasonable defaults
|
rt300@0
|
49 setSpringConstant(0.8);
|
rt300@0
|
50 setMass(1);
|
rt300@0
|
51 setFriction(0.999991);
|
rt300@0
|
52 }
|
rt300@9
|
53 //--------------------------------------------------------------
|
rt300@9
|
54 //--------------------------------------------------------------
|
rt300@9
|
55 Mesh::Mesh(Json::Value& jmesh){
|
rt300@10
|
56 setReasonableDefaults(); // sensible?
|
rt300@9
|
57
|
rt300@9
|
58 meshType = (MeshType)jmesh.get("meshType",0).asInt();
|
rt300@9
|
59 dim1 = jmesh.get("dim1",0).asInt();
|
rt300@9
|
60 dim2 = jmesh.get("dim1",0).asInt();
|
rt300@9
|
61
|
rt300@9
|
62 // need to know how many springs and lumps
|
rt300@9
|
63 numLumps = jmesh.get("numLumps",0).asInt();
|
rt300@9
|
64 numSprings = jmesh.get("numSprings",0).asInt();
|
rt300@9
|
65
|
rt300@9
|
66 // make them
|
rt300@9
|
67 makeComponents(numLumps, numSprings);
|
rt300@13
|
68 setLumpPositionsFromJson(jmesh["lumpPositions"], jmesh["lumpRestPositions"]);
|
rt300@9
|
69 makeConnectionsFromJson(jmesh["connections"]);
|
rt300@9
|
70 makeScanPathFromJson(jmesh["scanPath"]);
|
rt300@9
|
71 constrainFromJson(jmesh["constrainedLumps"]);
|
rt300@9
|
72
|
rt300@9
|
73 // now set saved properties
|
rt300@9
|
74 setSpringConstant(jmesh["springConstant"].asDouble());
|
rt300@9
|
75 setMass(jmesh["mass"].asDouble());
|
rt300@9
|
76 setFriction(jmesh["friction" ].asDouble());
|
rt300@9
|
77 // rest length?
|
rt300@9
|
78 zeroRestLength();
|
rt300@9
|
79 }
|
rt300@9
|
80
|
rt300@9
|
81 //--------------------------------------------------------------
|
rt300@13
|
82 void Mesh::setLumpPositionsFromJson(Json::Value lumpPositions, Json::Value lumpRestPositions){
|
rt300@9
|
83 int N = lumpPositions.size();
|
rt300@9
|
84
|
rt300@9
|
85 for(int i=0;i<N;i++){
|
rt300@9
|
86 lumps[i].position.x = lumpPositions[i]["x"].asFloat();
|
rt300@9
|
87 lumps[i].position.y = lumpPositions[i]["y"].asFloat();
|
rt300@9
|
88
|
rt300@13
|
89 lumps[i].zeroRefPos.x = lumpRestPositions[i]["x"].asFloat();
|
rt300@13
|
90 lumps[i].zeroRefPos.y = lumpRestPositions[i]["y"].asFloat();
|
rt300@9
|
91 }
|
rt300@9
|
92 }
|
rt300@9
|
93 //--------------------------------------------------------------
|
rt300@9
|
94 void Mesh::makeConnectionsFromJson(Json::Value connections){
|
rt300@9
|
95
|
rt300@9
|
96 // format: pairs of lump indexes, and a connecting spring
|
rt300@9
|
97 for (int i=0;i<connections.size();i++){
|
rt300@13
|
98 connect(i, connections[i]["s"].asInt(),connections[i]["e"].asInt()); // will the springs be in the right order? they need to be!
|
rt300@9
|
99
|
rt300@9
|
100 }
|
rt300@9
|
101 }
|
rt300@9
|
102
|
rt300@9
|
103 //--------------------------------------------------------------
|
rt300@9
|
104 void Mesh::makeScanPathFromJson(Json::Value jscanPath){
|
rt300@9
|
105
|
rt300@9
|
106 for(int i=0;i<jscanPath.size();i++){
|
rt300@9
|
107 scanPath.addElement(&lumps[jscanPath[i]["lumpNo"].asInt()], &springs[jscanPath[i]["springNo"].asInt()]);
|
rt300@9
|
108 }
|
rt300@9
|
109 }
|
rt300@9
|
110 //--------------------------------------------------------------
|
rt300@9
|
111 void Mesh::constrainFromJson(Json::Value constrainedLumps){
|
rt300@9
|
112
|
rt300@9
|
113 for(int i=0;i<constrainedLumps.size();i++){
|
rt300@9
|
114
|
rt300@9
|
115 lumps[constrainedLumps[i].asInt()].constrain(); // TODO ignores XY thing
|
rt300@9
|
116
|
rt300@9
|
117 }
|
rt300@9
|
118 }
|
rt300@9
|
119
|
rt300@9
|
120 //--------------------------------------------------------------
|
rt300@9
|
121 Json::Value Mesh::convertToJsonForSaving(){
|
rt300@9
|
122
|
rt300@9
|
123 // needs to be good to put back into
|
rt300@9
|
124 /*
|
rt300@9
|
125 void setLumpPositionsFromJson(Json::Value lumpPositions);
|
rt300@9
|
126 void makeConnectionsFromJson(Json::Value connections);
|
rt300@9
|
127 void makeScanPathFromJson(Json::Value scanPathElements);
|
rt300@9
|
128 void constrainFromJson(Json::Value constrainedLumps);
|
rt300@9
|
129 */
|
rt300@9
|
130
|
rt300@9
|
131 Json::Value jmesh;
|
rt300@9
|
132
|
rt300@9
|
133 jmesh["meshType"] = meshType;
|
rt300@9
|
134 jmesh["dim1"] = dim1; // these don't exist...
|
rt300@9
|
135 jmesh["dim2"] = dim2;
|
rt300@9
|
136 // need to know how many springs and lumps
|
rt300@9
|
137 jmesh["numLumps"] = numLumps;
|
rt300@9
|
138 jmesh["numSprings"] = numSprings;
|
rt300@9
|
139 jmesh["springConstant"] = k;
|
rt300@9
|
140 jmesh["mass"] = m;
|
rt300@9
|
141 jmesh["friction" ] = f;
|
rt300@9
|
142 for(int i=0;i<lumps.size();i++){
|
rt300@9
|
143 jmesh["lumpPositions"][i]["x"] = lumps[i].position.x;
|
rt300@9
|
144 jmesh["lumpPositions"][i]["y"] = lumps[i].position.y;
|
rt300@13
|
145 // just use rest pos ... too much data!
|
rt300@13
|
146 jmesh["lumpRestPositions"][i]["x"] = lumps[i].zeroRefPos.x;
|
rt300@13
|
147 jmesh["lumpRestPositions"][i]["y"] = lumps[i].zeroRefPos.y;
|
rt300@9
|
148 }
|
rt300@9
|
149
|
rt300@9
|
150 jmesh["connections"] = saveConnectionsAsJson();
|
rt300@9
|
151 jmesh["scanPath"] = scanPath.convertToJsonForSaving();
|
rt300@9
|
152
|
rt300@9
|
153 // save all indexes of constrained lumps
|
rt300@9
|
154 int j = 0;
|
rt300@9
|
155 for(int i=0;i<lumps.size();i++){
|
rt300@9
|
156 if(lumps[i].constrained){
|
rt300@9
|
157
|
rt300@9
|
158 jmesh["constrainedLumps"][j] = i;
|
rt300@9
|
159 j++;
|
rt300@9
|
160 }
|
rt300@9
|
161 }
|
rt300@9
|
162
|
rt300@9
|
163
|
rt300@9
|
164 return jmesh;
|
rt300@9
|
165
|
rt300@9
|
166 }
|
rt300@9
|
167 //--------------------------------------------------------------
|
rt300@9
|
168 Json::Value Mesh::saveConnectionsAsJson(){
|
rt300@9
|
169 Json::Value connections;
|
rt300@9
|
170 // loop all springs
|
rt300@9
|
171
|
rt300@9
|
172 for(int i = 0; i<springs.size(); i++){
|
rt300@13
|
173 connections[i]["s"]= springs[i].getStartLumpIndex();
|
rt300@13
|
174 connections[i]["e"]= springs[i].getEndLumpIndex();
|
rt300@9
|
175 }
|
rt300@9
|
176 return connections;
|
rt300@9
|
177
|
rt300@9
|
178
|
rt300@9
|
179 }
|
rt300@9
|
180 //--------------------------------------------------------------
|
rt300@9
|
181 //--------------------------------------------------------------
|
rt300@0
|
182 ///////////
|
rt300@0
|
183 // interface (called from testApp)
|
rt300@0
|
184 ///////////
|
rt300@0
|
185 void Mesh::update(){
|
rt300@0
|
186 // update all the springs and masses sequentially
|
rt300@0
|
187 // INTERP HACK - this bit of code is to debug pops and clicks
|
rt300@0
|
188 /*
|
rt300@0
|
189 static int updown = 0;
|
rt300@0
|
190 updown++;
|
rt300@0
|
191 if(updown > 24){
|
rt300@4
|
192 for(int i=0;i<lumps.size();i++){
|
rt300@0
|
193 lumps[i].position.y = 0.4;
|
rt300@0
|
194 }
|
rt300@0
|
195
|
rt300@0
|
196 }else{
|
rt300@0
|
197
|
rt300@4
|
198 for(int i=0;i<lumps.size();i++){
|
rt300@0
|
199 lumps[i].position.y = 0.6;
|
rt300@0
|
200 }
|
rt300@0
|
201
|
rt300@0
|
202 }
|
rt300@0
|
203 if(updown > 48) updown = 0;
|
rt300@0
|
204 // update the ends of the springs to reflect lump movement
|
rt300@0
|
205
|
rt300@0
|
206 for(int i=0;i<numSprings;i++){
|
rt300@0
|
207 springs[i].updateEndPoints();
|
rt300@0
|
208 }
|
rt300@0
|
209
|
rt300@0
|
210 return;
|
rt300@0
|
211
|
rt300@0
|
212 */
|
rt300@0
|
213
|
rt300@0
|
214 globalForces.update();
|
rt300@0
|
215 // calculate all the forces in the springs
|
rt300@4
|
216 for(int i=0;i<springs.size();i++){
|
rt300@0
|
217 springs[i].calculateForce();
|
rt300@0
|
218 }
|
rt300@0
|
219
|
rt300@0
|
220 // accelerate the lumps
|
rt300@4
|
221 for(int i=0;i<lumps.size();i++){
|
rt300@0
|
222 lumps[i].applyForce();
|
rt300@0
|
223 }
|
rt300@0
|
224
|
rt300@0
|
225 // move filters into apply force? not really, they're not forces.
|
rt300@0
|
226 // apply homing filter
|
rt300@4
|
227 for(int i=0;i<lumps.size();i++){
|
rt300@0
|
228 lumps[i].homingFilter(globalForces.homingAmt);
|
rt300@0
|
229 }
|
rt300@0
|
230 // apply averaging filter
|
rt300@0
|
231 //
|
rt300@0
|
232 averagingFilter(globalForces.avFilterAmt);
|
rt300@0
|
233
|
rt300@0
|
234 // update the ends of the springs to reflect lump movement
|
rt300@0
|
235 for(int i=0;i<numSprings;i++){
|
rt300@0
|
236 springs[i].updateEndPoints();
|
rt300@0
|
237 }
|
rt300@0
|
238
|
rt300@0
|
239 // scan the updated mesh
|
rt300@3
|
240 scanPath.updateWavetables();
|
rt300@0
|
241 }
|
rt300@0
|
242 //--------------------------------------------------------------
|
rt300@0
|
243 void Mesh::averagingFilter(double amt){
|
rt300@0
|
244 // we need a temporary store for average position, can't update in place with central diffs
|
rt300@4
|
245 vector<TwoVector> avLumpPos = vector<TwoVector>(lumps.size());
|
rt300@0
|
246
|
rt300@4
|
247
|
rt300@4
|
248 for(int i=0;i<lumps.size();i++){
|
rt300@0
|
249 avLumpPos[i] = lumps[i].averageOfConnected();
|
rt300@0
|
250 }
|
rt300@4
|
251 // now we can set pos. needs to be separate loop because we don't want to average *moved* lumps
|
rt300@4
|
252 for(int i=0;i<lumps.size();i++){
|
rt300@0
|
253 // mix in the average with the 'real'
|
rt300@0
|
254
|
rt300@0
|
255 lumps[i].position.x = (1 - amt)*lumps[i].position.x + amt*avLumpPos[i].x;
|
rt300@0
|
256 lumps[i].position.y = (1 - amt)*lumps[i].position.y + amt*avLumpPos[i].y;
|
rt300@0
|
257
|
rt300@0
|
258 }
|
rt300@0
|
259
|
rt300@0
|
260 }
|
rt300@0
|
261 //--------------------------------------------------------------
|
rt300@0
|
262 void Mesh::draw(){
|
rt300@0
|
263 // draw all the components belonging to mesh
|
rt300@0
|
264
|
rt300@0
|
265 int i;
|
rt300@0
|
266 for(i=0;i<numSprings;i++){
|
rt300@0
|
267 springs[i].draw();
|
rt300@0
|
268 }
|
rt300@0
|
269
|
rt300@4
|
270 for(i=0;i<lumps.size();i++){
|
rt300@0
|
271 lumps[i].draw();
|
rt300@0
|
272 }
|
rt300@0
|
273
|
rt300@8
|
274
|
rt300@0
|
275
|
rt300@0
|
276
|
rt300@0
|
277 }
|
rt300@0
|
278 //--------------------------------------------------------------
|
rt300@0
|
279 TwoVector Mesh::calculateCentre(){
|
rt300@0
|
280 // calculates average of all lump positions
|
rt300@0
|
281
|
rt300@0
|
282 double x = 0, y = 0;
|
rt300@4
|
283 for(int i = 0; i < lumps.size(); i++){
|
rt300@0
|
284 x += lumps[i].position.x;
|
rt300@0
|
285 y += lumps[i].position.y;
|
rt300@0
|
286
|
rt300@0
|
287 }
|
rt300@4
|
288 x = x/lumps.size();
|
rt300@4
|
289 y = y/lumps.size();
|
rt300@0
|
290
|
rt300@0
|
291 //cout << "centre : " << x << "," << y << endl;
|
rt300@0
|
292
|
rt300@0
|
293 centre.setCoord(x,y);
|
rt300@0
|
294
|
rt300@0
|
295 return centre;
|
rt300@0
|
296 }
|
rt300@0
|
297 //--------------------------------------------------------------
|
rt300@0
|
298 void Mesh::resetAll(){
|
rt300@0
|
299 // it's this simple
|
rt300@0
|
300 resetPositions();
|
rt300@0
|
301 resetVelocities();
|
rt300@0
|
302 unconstrain();
|
rt300@0
|
303 clearScanPath();
|
rt300@0
|
304 makeDefaultScanPath();
|
rt300@0
|
305 constrain(0.0,0.0,CONSTRAIN_EDGES);
|
rt300@0
|
306 constrain(0.0,0.0,CONSTRAIN_CORNERS);
|
rt300@0
|
307
|
rt300@0
|
308 // unless we want to reset velocities...?
|
rt300@0
|
309 }
|
rt300@0
|
310 //--------------------------------------------------------------
|
rt300@0
|
311 void Mesh::resetPositions(){
|
rt300@0
|
312 // it's this simple
|
rt300@0
|
313 setLumpPositions();
|
rt300@0
|
314 // unless we want to reset velocities...?
|
rt300@0
|
315 }
|
rt300@0
|
316 //--------------------------------------------------------------
|
rt300@0
|
317 void Mesh::resetVelocities(){
|
rt300@4
|
318 for(int i = 0; i < lumps.size(); i++){
|
rt300@0
|
319 lumps[i].setVelocity(0.0,0.0);
|
rt300@0
|
320
|
rt300@0
|
321 }
|
rt300@0
|
322 }
|
rt300@0
|
323 void Mesh::toggleHome(bool on){
|
rt300@0
|
324 static double prev;
|
rt300@0
|
325
|
rt300@0
|
326 if(!home && on){
|
rt300@0
|
327 home = on;
|
rt300@0
|
328 prev = globalForces.homingAmt;
|
rt300@0
|
329 globalForces.homingAmt = 0.3;
|
rt300@0
|
330
|
rt300@0
|
331
|
rt300@0
|
332 }else if (home && !on){
|
rt300@0
|
333 home = on; // ie false
|
rt300@0
|
334 globalForces.homingAmt = prev;
|
rt300@0
|
335 }
|
rt300@0
|
336 }
|
rt300@0
|
337 //--------------------------------------------------------------
|
rt300@0
|
338 void Mesh::resetEverything(){
|
rt300@0
|
339
|
rt300@0
|
340 }
|
rt300@0
|
341
|
rt300@0
|
342 //--------------
|
rt300@0
|
343 void Mesh::toggleSyrup(){
|
rt300@0
|
344 if(syrup){
|
rt300@0
|
345 toggleSyrup(false);
|
rt300@0
|
346 }else{
|
rt300@0
|
347 toggleSyrup(true);
|
rt300@0
|
348 }
|
rt300@0
|
349 }
|
rt300@0
|
350 //--------------
|
rt300@0
|
351 void Mesh::toggleSyrup(bool on){
|
rt300@0
|
352 if (!on){
|
rt300@0
|
353 syrup = false;
|
rt300@4
|
354 for(int i=0;i<lumps.size();i++) lumps[i].setFriction(0.998);
|
rt300@0
|
355 }else{
|
rt300@0
|
356 syrup = true;
|
rt300@4
|
357 for(int i=0;i<lumps.size();i++) lumps[i].setFriction(0.90);
|
rt300@0
|
358 }
|
rt300@0
|
359 }
|
rt300@0
|
360 //----------------------------------------------------------------
|
rt300@0
|
361 void Mesh::toggleGravity(){
|
rt300@0
|
362 globalForces.gravityOn = !globalForces.gravityOn;
|
rt300@0
|
363 }
|
rt300@0
|
364 //----------------------------------------------------------------
|
rt300@0
|
365 void Mesh::toggleGravity(bool on){
|
rt300@0
|
366 if (!on){
|
rt300@0
|
367 globalForces.gravityOn = true;
|
rt300@0
|
368 }else{
|
rt300@0
|
369 globalForces.gravityOn = false;
|
rt300@0
|
370 }
|
rt300@0
|
371 }
|
rt300@0
|
372
|
rt300@0
|
373 //----------------------------------------------------------------
|
rt300@0
|
374 void Mesh::toggleSpringForces(){
|
rt300@0
|
375
|
rt300@0
|
376 Spring::forcesOn = !Spring::forcesOn;
|
rt300@0
|
377
|
rt300@0
|
378 }
|
rt300@0
|
379 //----------------------------------------------------------------
|
rt300@0
|
380 void Mesh::toggleSpringForces(bool on){
|
rt300@0
|
381 if (!on){
|
rt300@0
|
382 Spring::forcesOn = false;
|
rt300@0
|
383
|
rt300@0
|
384 }else{
|
rt300@0
|
385 Spring::forcesOn = true;
|
rt300@0
|
386
|
rt300@0
|
387 }
|
rt300@0
|
388 }
|
rt300@0
|
389
|
rt300@0
|
390 //--------------------------------------------------------------
|
rt300@0
|
391 void Mesh::unconstrain(){
|
rt300@0
|
392
|
rt300@4
|
393 for(int i = 0; i<lumps.size(); i++){
|
rt300@0
|
394
|
rt300@0
|
395 lumps[i].unconstrain();
|
rt300@0
|
396
|
rt300@0
|
397 }
|
rt300@0
|
398 }
|
rt300@0
|
399 //--------------------------------------------------------------
|
rt300@0
|
400 void Mesh::unconstrain(double ax, double ay, constrainMode aMode){
|
rt300@0
|
401 int i = 0;
|
rt300@0
|
402 TwoVector diff;
|
rt300@0
|
403 // check if lump is within grab range
|
rt300@0
|
404 switch (aMode) {
|
rt300@0
|
405 case CONSTRAIN_GRAB_REGION:
|
rt300@4
|
406 for(i = 0; i<lumps.size(); i++){
|
rt300@0
|
407
|
rt300@0
|
408 diff.setCoord(lumps[i].position.x - ax, lumps[i].position.y - ay);
|
rt300@0
|
409
|
rt300@0
|
410 if (diff.norm() < GRAB_RANGE){
|
rt300@0
|
411 lumps[i].unconstrain();
|
rt300@0
|
412 }
|
rt300@0
|
413 }
|
rt300@0
|
414 break;
|
rt300@0
|
415 case CONSTRAIN_EDGES:
|
rt300@0
|
416 // hmm
|
rt300@0
|
417 break;
|
rt300@0
|
418
|
rt300@0
|
419 default:
|
rt300@0
|
420 break;
|
rt300@0
|
421 }
|
rt300@0
|
422 }
|
rt300@0
|
423 //--------------------------------------------------------------
|
rt300@0
|
424 void Mesh::setRestLength(){
|
rt300@0
|
425 for(int i = 0; i<numSprings; i++){
|
rt300@0
|
426 springs[i].setRestLength();
|
rt300@0
|
427 }
|
rt300@0
|
428
|
rt300@0
|
429 }
|
rt300@0
|
430 //--------------------------------------------------------------
|
rt300@0
|
431 void Mesh::setZeroAudioLine(){
|
rt300@0
|
432 // set zero rest pos to where they are now
|
rt300@4
|
433 for(int i = 0; i<lumps.size(); i++){
|
rt300@0
|
434
|
rt300@0
|
435 lumps[i].setZeroRefPos();
|
rt300@0
|
436
|
rt300@0
|
437 }
|
rt300@0
|
438 }
|
rt300@0
|
439 //--------------------------------------------------------------
|
rt300@0
|
440 void Mesh::setPropagationSpeed(double aSpeed){
|
rt300@0
|
441
|
rt300@0
|
442 propagationSpeed = aSpeed;
|
rt300@4
|
443 for(int i = 0; i < lumps.size(); i++){
|
rt300@0
|
444 lumps[i].setInvMass(propagationSpeed*propagationSpeed); // inverse mass is c^2
|
rt300@0
|
445 }
|
rt300@0
|
446 }
|
rt300@0
|
447 //--------------------------------------------------------------
|
rt300@0
|
448 void Mesh::increasePropagationSpeed(){
|
rt300@0
|
449
|
rt300@0
|
450 propagationSpeed = propagationSpeed + 0.01;
|
rt300@4
|
451 for(int i = 0; i < lumps.size(); i++){
|
rt300@0
|
452 lumps[i].setInvMass(propagationSpeed*propagationSpeed); // inverse mass is c^2
|
rt300@0
|
453 }
|
rt300@0
|
454 cout << "prop speed = " << propagationSpeed << endl;
|
rt300@0
|
455 }
|
rt300@0
|
456 //--------------------------------------------------------------
|
rt300@0
|
457 void Mesh::decreasePropagationSpeed(){
|
rt300@0
|
458
|
rt300@0
|
459 propagationSpeed = propagationSpeed - 0.01;
|
rt300@4
|
460 for(int i = 0; i < lumps.size(); i++){
|
rt300@0
|
461 lumps[i].setInvMass(propagationSpeed*propagationSpeed); // inverse mass is c^2
|
rt300@0
|
462 }
|
rt300@0
|
463 cout << "prop speed = " << propagationSpeed << endl;
|
rt300@0
|
464 }
|
rt300@0
|
465 //--------------------------------------------------------------
|
rt300@0
|
466 void Mesh::setSpringConstant(double aK){
|
rt300@0
|
467 k = aK;
|
rt300@0
|
468 if(sqrt(k/m) > 0.9){
|
rt300@0
|
469 k = m * 0.9;
|
rt300@0
|
470 }
|
rt300@0
|
471 cout << "k/m = " << k/m << endl;
|
rt300@9
|
472 for(int i = 0; i < springs.size(); i++){
|
rt300@0
|
473 springs[i].setSpringConstant(k); // inverse mass is c^2
|
rt300@0
|
474 }
|
rt300@0
|
475 }
|
rt300@0
|
476 //--------------------------------------------------------------
|
rt300@0
|
477 void Mesh::setMass(double aM){
|
rt300@0
|
478
|
rt300@0
|
479 m = aM;
|
rt300@0
|
480
|
rt300@0
|
481 if(sqrt(k/m) > 0.9){
|
rt300@0
|
482 m = k/0.9;
|
rt300@0
|
483 }
|
rt300@15
|
484 //cout << "k/m = " << k/m << endl;
|
rt300@0
|
485 double im = 1/aM;
|
rt300@4
|
486 for(int i = 0; i < lumps.size(); i++){
|
rt300@0
|
487 lumps[i].setInvMass(im);
|
rt300@0
|
488 }
|
rt300@0
|
489 }
|
rt300@0
|
490 //--------------------------------------------------------------
|
rt300@0
|
491 void Mesh::setFriction(double newF){
|
rt300@0
|
492 f = newF;
|
rt300@4
|
493 for(int i = 0; i < lumps.size(); i++){
|
rt300@0
|
494 lumps[i].setFriction(f);
|
rt300@0
|
495 }
|
rt300@0
|
496 }
|
rt300@0
|
497 //--------------------------------------------------------------
|
rt300@0
|
498 void Mesh::setMassAsym(double aAsym){
|
rt300@0
|
499 // use m as bass and add asym linearly across mesh. might be wierd for some meshes!
|
rt300@0
|
500 double newm,incr;
|
rt300@0
|
501 newm = m;
|
rt300@4
|
502 incr = aAsym*m/(lumps.size()-1);
|
rt300@4
|
503 for(int i = 0; i < lumps.size(); i++){
|
rt300@0
|
504 lumps[i].setInvMass(1/newm);
|
rt300@0
|
505 newm += incr;
|
rt300@0
|
506 }
|
rt300@0
|
507 }
|
rt300@0
|
508 //--------------------------------------------------------------
|
rt300@0
|
509 void Mesh::setSpringConstantAsym(double aAsym){
|
rt300@0
|
510 // from 0 to 1
|
rt300@0
|
511 if (aAsym > 1.0){
|
rt300@0
|
512 aAsym = 1.0;
|
rt300@0
|
513 }
|
rt300@0
|
514 if (aAsym < 0.0){
|
rt300@0
|
515 aAsym = 0.0;
|
rt300@0
|
516 }
|
rt300@0
|
517 double newk, incr;
|
rt300@0
|
518 newk = k;
|
rt300@0
|
519 incr = (1-aAsym)*k/(numSprings-1);
|
rt300@0
|
520 for(int i = 0; i < numSprings; i++){
|
rt300@0
|
521 springs[i].setSpringConstant(newk);
|
rt300@0
|
522 newk -= incr;
|
rt300@0
|
523 }
|
rt300@0
|
524 }
|
rt300@0
|
525
|
rt300@0
|
526 //--------------------------------------------------------------
|
rt300@0
|
527 void Mesh::setFrictionAsym(double aAsym){
|
rt300@0
|
528 // multiplying it doesn't make sense!
|
rt300@0
|
529 double newF,incr;
|
rt300@0
|
530 newF = f;
|
rt300@4
|
531 incr = aAsym*f/(lumps.size()-1);
|
rt300@4
|
532 for(int i = 0; i < lumps.size(); i++){
|
rt300@0
|
533 lumps[i].setFriction(newF);
|
rt300@0
|
534 newF += incr;
|
rt300@0
|
535 }
|
rt300@0
|
536 }
|
rt300@0
|
537 //--------------------------------------------------------------
|
rt300@0
|
538 void Mesh::checkHover(double ax, double ay){
|
rt300@0
|
539 TwoVector diff;
|
rt300@0
|
540 bool found = false;
|
rt300@0
|
541 // check if lump is within grab range
|
rt300@4
|
542 for(int i = 0; i<lumps.size(); i++){
|
rt300@0
|
543 diff.setCoord(lumps[i].position.x - ax, lumps[i].position.y - ay);
|
rt300@0
|
544 //cout << "diff " << diff.x << "," << diff.y << endl;
|
rt300@0
|
545 if (diff.norm() < GRAB_RANGE){
|
rt300@0
|
546 if(!found) {
|
rt300@0
|
547 lumps[i].highlight();
|
rt300@0
|
548 found = true;
|
rt300@0
|
549 }
|
rt300@0
|
550 }else{
|
rt300@0
|
551 lumps[i].unhighlight();
|
rt300@0
|
552 }
|
rt300@0
|
553 }
|
rt300@0
|
554
|
rt300@0
|
555 }
|
rt300@0
|
556
|
rt300@0
|
557 //--------------------------------------------------------------
|
rt300@0
|
558 void Mesh::grab(double ax, double ay, int touchID){
|
rt300@0
|
559 // attempt to grab a lump ax and ay should be already normalised
|
rt300@0
|
560
|
rt300@0
|
561 TwoVector diff;
|
rt300@0
|
562
|
rt300@0
|
563 // find closest
|
rt300@0
|
564 int nearest = getNearestLump(ax,ay);
|
rt300@10
|
565 //if(nearest = -1) return; // there are no lumps!
|
rt300@0
|
566 diff.setCoord(lumps[nearest].position.x - ax, lumps[nearest].position.y - ay);
|
rt300@0
|
567 //cout << "diff " << diff.x << "," << diff.y << endl;
|
rt300@10
|
568 cout << GRAB_RANGE << endl;
|
rt300@0
|
569 if (diff.norm() < GRAB_RANGE){
|
rt300@10
|
570
|
rt300@0
|
571 cout << "grabbing lump " << nearest << endl;
|
rt300@10
|
572
|
rt300@0
|
573 // move this lump to mouse pos
|
rt300@0
|
574
|
rt300@0
|
575 lumps[nearest].grab(touchID);
|
rt300@0
|
576 }
|
rt300@0
|
577
|
rt300@0
|
578
|
rt300@0
|
579 }
|
rt300@0
|
580 //--------------------------------------------------------------
|
rt300@0
|
581 void Mesh::unGrab(int touchID){
|
rt300@0
|
582
|
rt300@4
|
583 for(int i=0; i<lumps.size();i++){
|
rt300@0
|
584 if(lumps[i].grabID == touchID){ // only release the lumps that were grabbed by this finger
|
rt300@0
|
585 lumps[i].unGrab();
|
rt300@0
|
586 lumps[i].unhighlight();
|
rt300@0
|
587 }
|
rt300@0
|
588 }
|
rt300@0
|
589 }
|
rt300@0
|
590
|
rt300@0
|
591 //--------------------------------------------------------------
|
rt300@0
|
592 void Mesh::drag(double ax, double ay, int touchID){
|
rt300@0
|
593 // maybe set up specific id's for grabbed lumps
|
rt300@4
|
594 for(int i=0; i<lumps.size();i++){
|
rt300@0
|
595 if(lumps[i].grabID == touchID){// only move the lumps that were grabbed by this finger
|
rt300@0
|
596
|
rt300@0
|
597 lumps[i].drag(ax,ay,touchID);
|
rt300@0
|
598 }
|
rt300@0
|
599 }
|
rt300@0
|
600 }
|
rt300@0
|
601 //--------------------------------------------------------------
|
rt300@0
|
602 /* also could:
|
rt300@0
|
603 add random velocities
|
rt300@0
|
604 etc
|
rt300@0
|
605 */
|
rt300@0
|
606 //////////////////////
|
rt300@0
|
607 // protected utils
|
rt300@0
|
608 ////////////////////////
|
rt300@0
|
609 //---------------------------------------------------------------
|
rt300@0
|
610 void Mesh::connect(int aspringnum,int alumpnum){
|
rt300@0
|
611 //cout << "connecting spring " << aspringnum << " to lump " << alumpnum << endl;
|
rt300@0
|
612 // should we check valid indexes?
|
rt300@0
|
613 lumps[alumpnum].attachSpring(&springs[aspringnum]);
|
rt300@0
|
614 springs[aspringnum].attachLump(&lumps[alumpnum]);
|
rt300@0
|
615
|
rt300@0
|
616 }
|
rt300@0
|
617 //---------------------------------------------------------------
|
rt300@0
|
618 void Mesh::connect(int aspringnum,int alumpnum,int alumpnum2){
|
rt300@0
|
619 // better version - just connects 2 lumps with a spring
|
rt300@0
|
620 // should we check valid indexes?
|
rt300@0
|
621 lumps[alumpnum].attachSpring(&springs[aspringnum]);
|
rt300@0
|
622 springs[aspringnum].attachLump(&lumps[alumpnum]);
|
rt300@0
|
623 lumps[alumpnum2].attachSpring(&springs[aspringnum]);
|
rt300@0
|
624 springs[aspringnum].attachLump(&lumps[alumpnum2]);
|
rt300@0
|
625
|
rt300@0
|
626 }
|
rt300@0
|
627
|
rt300@0
|
628 void Mesh::zeroRestLength(){
|
rt300@0
|
629 // sets springs rest length to zero - collapses structure
|
rt300@3
|
630 for(vector<Spring>::iterator spriter = springs.begin(); spriter < springs.end(); spriter++){
|
rt300@3
|
631 (*spriter).setRestLength(0.0);
|
rt300@0
|
632 }
|
rt300@3
|
633
|
rt300@0
|
634 }
|
rt300@0
|
635 //--------------------------------------------------------------
|
rt300@0
|
636 int Mesh::getNearestLump(double ax, double ay){
|
rt300@0
|
637 // not used yet
|
rt300@0
|
638 int nearestLumpIndex = -1;
|
rt300@0
|
639 TwoVector diff;
|
rt300@0
|
640 double distance = 1.0;
|
rt300@0
|
641 double minDistance = 1.0;
|
rt300@0
|
642
|
rt300@4
|
643 for(int i = 0; i<lumps.size(); i++){
|
rt300@0
|
644 diff.setCoord(lumps[i].position.x - ax, lumps[i].position.y - ay);
|
rt300@0
|
645 distance = diff.norm();
|
rt300@0
|
646 if(distance < minDistance && !lumps[i].constrained){ // don't grab if constrained ??
|
rt300@0
|
647 minDistance = distance;
|
rt300@0
|
648 nearestLumpIndex = i;
|
rt300@0
|
649 }
|
rt300@0
|
650 }
|
rt300@13
|
651 //cout << "nearest lump : " << nearestLumpIndex << endl;
|
rt300@0
|
652
|
rt300@0
|
653 return nearestLumpIndex;
|
rt300@0
|
654 }
|
rt300@0
|
655 //--------------------------------------------------------------
|
rt300@0
|
656 void Mesh::clearScanPath(){
|
rt300@0
|
657 // in between having clicked and drawn we can't play anything
|
rt300@3
|
658 scanPath.clear();
|
rt300@0
|
659 prevLump = -1;
|
rt300@0
|
660 }
|
rt300@0
|
661 //--------------------------------------------------------------
|
rt300@0
|
662 void Mesh::disconnectDraw(){
|
rt300@0
|
663 prevLump = -1;
|
rt300@0
|
664 }
|
rt300@0
|
665 //--------------------------------------------------------------
|
rt300@0
|
666 int Mesh::inscribeScanPath(double ax, double ay){
|
rt300@0
|
667 bool foundPath = false;
|
rt300@0
|
668 int targetLump, intermediateLump;
|
rt300@0
|
669 int count = 0;
|
rt300@0
|
670 TwoVector halfWay;
|
rt300@0
|
671 // is this ridiculously complicated for no reason?
|
rt300@0
|
672
|
rt300@0
|
673 targetLump = getNearestLump(ax,ay); // target is the one closest to touch point, prev is last point already on our path
|
rt300@0
|
674
|
rt300@4
|
675 while(!foundPath && count < 10000){
|
rt300@0
|
676 count++;
|
rt300@3
|
677 if(prevLump == -1){ // (scanPath.howManyElements() == 0){ //
|
rt300@0
|
678 //first lump
|
rt300@0
|
679 foundPath = true;
|
rt300@0
|
680 prevLump = targetLump;
|
rt300@0
|
681 //cout << "first lump" << endl;
|
rt300@4
|
682 lumps[targetLump].isScanPathStart = true;
|
rt300@0
|
683 return targetLump;
|
rt300@0
|
684 }
|
rt300@0
|
685 // check if this lump connected to last lump by a spring
|
rt300@0
|
686 Spring * connectedToPrev = lumps[targetLump].checkConnectedTo(&lumps[prevLump]);
|
rt300@0
|
687
|
rt300@0
|
688 // if not connectedToLast will be null
|
rt300@0
|
689 if (!connectedToPrev){
|
rt300@0
|
690 //cout << "setting half way" << endl;
|
rt300@0
|
691 // set coords to 1/2 way and recurse
|
rt300@0
|
692 double halfdiffx = ((ax-lumps[prevLump].position.x)*0.5);
|
rt300@0
|
693 double halfdiffy = ((ay - lumps[prevLump].position.y)*0.5);
|
rt300@0
|
694 if (halfdiffx < 0.0001 && halfdiffy < 0.0001){
|
rt300@0
|
695 // not found nuffun
|
rt300@0
|
696 //cout << "not found a path, quitting" << endl;
|
rt300@0
|
697 return -1;
|
rt300@0
|
698 }
|
rt300@0
|
699 halfWay.setCoord( ax - halfdiffx , ay - halfdiffy);
|
rt300@0
|
700
|
rt300@0
|
701
|
rt300@0
|
702 intermediateLump = inscribeScanPath(halfWay.x,halfWay.y);
|
rt300@0
|
703 if(intermediateLump == -1){
|
rt300@0
|
704 //cout << "finding intermediate didn't work" << endl;
|
rt300@0
|
705 return -1;
|
rt300@0
|
706 }
|
rt300@0
|
707 // now check that the found intermediate targetLump is connected to the original targetlump
|
rt300@0
|
708 Spring * connectedToNext = lumps[targetLump].checkConnectedTo(&lumps[prevLump]);
|
rt300@0
|
709 if(!connectedToNext){
|
rt300@0
|
710 // set prevLump to the interm and try again
|
rt300@0
|
711 prevLump = intermediateLump;
|
rt300@0
|
712 targetLump = inscribeScanPath(ax,ay);
|
rt300@0
|
713 if(targetLump == -1){
|
rt300@0
|
714 //cout << "joining up next one didn't work" << endl;
|
rt300@0
|
715 return -1;
|
rt300@0
|
716 }
|
rt300@0
|
717 }
|
rt300@0
|
718 }else{
|
rt300@0
|
719 //cout << "CONNECTED! adding an element" << endl;
|
rt300@0
|
720
|
rt300@0
|
721 // hurrah, add the spring and lump to the scanpath in the right order...
|
rt300@0
|
722 // get pointer to lump and spring
|
rt300@0
|
723
|
rt300@3
|
724 scanPath.addElement(&lumps[targetLump], connectedToPrev);
|
rt300@4
|
725
|
rt300@4
|
726 // indicate end
|
rt300@4
|
727 lumps[prevLump].isScanPathEnd = false;
|
rt300@4
|
728 lumps[targetLump].isScanPathEnd = true;
|
rt300@0
|
729 // and set prev lump to that one
|
rt300@0
|
730 prevLump = targetLump;
|
rt300@0
|
731 foundPath = true;
|
rt300@0
|
732 return targetLump; //
|
rt300@0
|
733 }
|
rt300@0
|
734
|
rt300@0
|
735 }
|
rt300@0
|
736
|
rt300@0
|
737 cout << "reached end of inscribe func" << endl;
|
rt300@0
|
738
|
rt300@0
|
739 return -1;
|
rt300@0
|
740 }
|
rt300@0
|
741
|
rt300@8
|
742 // ---------------------------------------------------------------------------------------
|
rt300@8
|
743
|
rt300@8
|
744
|
rt300@8
|
745
|
rt300@0
|
746 void Mesh::hit(double dax, double day,int velocity, GlobalForces::excitationTypes aEType, GlobalForces::excitationShapes aEShape){
|
rt300@0
|
747 // set filter to something low
|
rt300@0
|
748 globalForces.homingAmt = 0.0;
|
rt300@0
|
749
|
rt300@0
|
750 double radius = 0.1, distance; // size of lump
|
rt300@0
|
751 double impactStrength = globalForces.excitationStrength*velocity/1000; // velocity as in note loudness
|
rt300@0
|
752 double amt = 0.0;
|
rt300@0
|
753 TwoVector diff;
|
rt300@0
|
754 // get all the lumps and smack em
|
rt300@12
|
755 int xamt = globalForces.exciteShapeX; // harmonic number of sine
|
rt300@0
|
756 int yamt = globalForces.exciteShapeY;
|
rt300@0
|
757
|
rt300@0
|
758 switch(aEShape){
|
rt300@0
|
759
|
rt300@0
|
760 case GlobalForces::SINE:
|
rt300@0
|
761
|
rt300@0
|
762 // applies a sine wave to all lumps, x and y
|
rt300@4
|
763 for(int i = 0; i < lumps.size(); i++){
|
rt300@0
|
764 if(!lumps[i].constrained){
|
rt300@0
|
765 lumps[i].position.y = lumps[i].zeroRefPos.y + impactStrength*sin(PI* (2*(xamt-1) + 1) * lumps[i].position.x);
|
rt300@0
|
766 lumps[i].position.x = lumps[i].zeroRefPos.x + impactStrength*sin(PI* (2*(yamt-1) + 1) * lumps[i].position.y);
|
rt300@0
|
767 }
|
rt300@0
|
768 }
|
rt300@0
|
769
|
rt300@0
|
770 break;
|
rt300@0
|
771 case GlobalForces::GAUSS:
|
rt300@0
|
772 // temporarily not a gauss...
|
rt300@4
|
773 for(int i = 0; i < lumps.size(); i++){
|
rt300@0
|
774 diff.setCoord(lumps[i].position.x - dax, lumps[i].position.y - day);
|
rt300@0
|
775 distance = diff.norm();
|
rt300@0
|
776 if(distance < radius){
|
rt300@0
|
777 amt = impactStrength*(1 + cos(PI*distance/radius)); // a 2d hamming.
|
rt300@0
|
778 lumps[i].position.y += amt;
|
rt300@0
|
779
|
rt300@0
|
780 }
|
rt300@0
|
781 }
|
rt300@0
|
782 break;
|
rt300@0
|
783 case GlobalForces::NOISE:
|
rt300@0
|
784 // 2D noise
|
rt300@4
|
785 for(int i = 0; i < lumps.size(); i++){
|
rt300@0
|
786 lumps[i].position.x += impactStrength*rand();
|
rt300@0
|
787 lumps[i].position.y += impactStrength*rand();
|
rt300@0
|
788
|
rt300@0
|
789 }
|
rt300@0
|
790 break;
|
rt300@0
|
791 default:
|
rt300@0
|
792 break;
|
rt300@0
|
793 }
|
rt300@0
|
794
|
rt300@0
|
795
|
rt300@0
|
796 }
|
rt300@0
|
797
|
rt300@0
|
798 void Mesh::spatialHarmonic(int aharm, int aharm2){
|
rt300@0
|
799 double magdr,theta;
|
rt300@0
|
800 TwoVector r, nr, centre, rhat, displacement;
|
rt300@0
|
801 centre.setCoord(0.5, 0.5);
|
rt300@0
|
802 // applies a sine wave to all lumps, x and y
|
rt300@0
|
803 if(radial){
|
rt300@0
|
804 // distance from centre is tweaked
|
rt300@4
|
805 for(int i = 0; i < lumps.size(); i++){
|
rt300@0
|
806 if(!lumps[i].constrained ){ //&& lumps[i].isInScanPath
|
rt300@0
|
807
|
rt300@0
|
808 // lots of sins and tans - might be simplifiable?
|
rt300@0
|
809 r = lumps[i].position - centre;
|
rt300@0
|
810 rhat = r.unitDir();
|
rt300@0
|
811 theta = atan2(r.y,r.x);
|
rt300@0
|
812 magdr = sin(aharm*theta);
|
rt300@0
|
813
|
rt300@0
|
814 // new r for lump:
|
rt300@0
|
815 displacement = rhat * 0.1*globalForces.touchStrength*magdr;
|
rt300@0
|
816 lumps[i].position = lumps[i].position + displacement;
|
rt300@0
|
817
|
rt300@0
|
818 }
|
rt300@0
|
819 }
|
rt300@0
|
820 }else{
|
rt300@4
|
821 for(int i = 0; i < lumps.size(); i++){
|
rt300@0
|
822 if(!lumps[i].constrained){
|
rt300@1
|
823 lumps[i].position.y = lumps[i].zeroRefPos.y + globalForces.touchStrength/256.0*sin(PI* (2*(aharm-1) + 1) * lumps[i].position.x);
|
rt300@1
|
824 lumps[i].position.x = lumps[i].zeroRefPos.x + globalForces.touchStrength/256.0*sin(PI* (2*(aharm2-1) + 1) * lumps[i].position.y);
|
rt300@0
|
825 }
|
rt300@0
|
826 }
|
rt300@0
|
827 }
|
rt300@0
|
828 }
|
rt300@0
|
829
|
rt300@0
|
830 void Mesh::damp(){
|
rt300@0
|
831 // set friction and filters to something high
|
rt300@0
|
832 //globalForces.avFilterAmt = 0.0;
|
rt300@0
|
833 globalForces.homingAmt = 0.3;
|
rt300@0
|
834 }
|
rt300@0
|
835 void Mesh::forceField(double dax,double day,double strength){
|
rt300@0
|
836
|
rt300@0
|
837 //
|
rt300@0
|
838 }
|
rt300@0
|
839 //--------------------------------------------------------------
|
rt300@0
|
840 double Mesh::getNextSample(){
|
rt300@0
|
841
|
rt300@0
|
842 return 0.0;
|
rt300@0
|
843
|
rt300@0
|
844 }
|
rt300@0
|
845
|
rt300@0
|
846 //--------------------------------------------------------------
|
rt300@0
|
847 // VIRTUAL
|
rt300@0
|
848 //--------------------------------------------------------------
|
rt300@0
|
849 void Mesh::makeDefaultScanPath(){
|
rt300@9
|
850 // make
|
rt300@0
|
851 cout << "!!!!Mesh base class makeDefaultScanPath\n";
|
rt300@0
|
852 }
|
rt300@0
|
853
|
rt300@0
|
854 //--------------------------------------------------------------
|
rt300@0
|
855 void Mesh::setLumpPositions(){
|
rt300@0
|
856 // places lumps in the right positions
|
rt300@0
|
857 cout << "!!!!Mesh base class setLumpPositions\n";
|
rt300@0
|
858 }
|
rt300@0
|
859 //--------------------------------------------------------------
|
rt300@0
|
860 void Mesh::makeConnections(){
|
rt300@0
|
861 // connects the lmps and springs. the spring needs to know which lumps are at each end
|
rt300@0
|
862 // and lumps need to know which springs attached
|
rt300@0
|
863 // calls connect method that does this
|
rt300@0
|
864 cout << "!!!!Mesh base class make connections\n";
|
rt300@0
|
865 }
|
rt300@0
|
866 //--------------------------------------------------------------
|
rt300@9
|
867 void Mesh::makeComponents(int numLumps, int numSprings){
|
rt300@9
|
868 // does not need to know what shape we're in to set up the right number of lumps and springs
|
rt300@0
|
869 cout << "!!!!Mesh base class makeComponents\n";
|
rt300@9
|
870
|
rt300@9
|
871 //lumps = new Lump[numLumps];
|
rt300@9
|
872 lumps = vector<Lump>(numLumps);
|
rt300@9
|
873 cout << "made " << numLumps << " lumps\n";
|
rt300@9
|
874
|
rt300@9
|
875 // one by one
|
rt300@9
|
876 springs = vector<Spring>(numSprings);
|
rt300@9
|
877
|
rt300@9
|
878 cout << "made " << numSprings << " springs\n";
|
rt300@9
|
879
|
rt300@9
|
880 // tell them what index they are (for connections)
|
rt300@9
|
881 for(int i = 0; i<lumps.size(); i++){
|
rt300@9
|
882 lumps[i].myIndexInMesh = i;
|
rt300@9
|
883 }
|
rt300@9
|
884 for(int i = 0; i<springs.size(); i++){
|
rt300@9
|
885 springs[i].myIndexInMesh = i;
|
rt300@9
|
886 }
|
rt300@9
|
887
|
rt300@9
|
888
|
rt300@0
|
889 }
|
rt300@0
|
890 //--------------------------------------------------------------
|
rt300@0
|
891 void Mesh::constrain(double ax, double ay, constrainMode aMode){
|
rt300@0
|
892 cout << "!!!!Mesh base class constrain\n";
|
rt300@0
|
893 }
|
rt300@0
|
894 //--------------------------------------------------------------
|
rt300@0
|
895 /****************************************/
|
rt300@9
|
896 // SquareMesh */
|
rt300@0
|
897 /****************************************/
|
rt300@0
|
898 //--------------------------------------------------------------
|
rt300@9
|
899 SquareMesh::SquareMesh(): Mesh() {
|
rt300@9
|
900 // the default is called from derived classes
|
rt300@9
|
901 radial = false;
|
rt300@9
|
902 cout << "default constructor SQUARE mesh\n";
|
rt300@9
|
903 }
|
rt300@9
|
904 //---------------------------------------------------------------
|
rt300@9
|
905 SquareMesh::SquareMesh(int height, int width): Mesh() {
|
rt300@9
|
906 // this one called when no derived class
|
rt300@9
|
907 meshType = SQUARE_MESH;
|
rt300@0
|
908 makeComponents(height, width);
|
rt300@0
|
909
|
rt300@0
|
910 setLumpPositions();
|
rt300@0
|
911
|
rt300@0
|
912 makeConnections();
|
rt300@0
|
913
|
rt300@0
|
914 makeDefaultScanPath();
|
rt300@0
|
915
|
rt300@0
|
916 constrain(0,0,CONSTRAIN_EDGES_XY);
|
rt300@0
|
917
|
rt300@0
|
918 zeroRestLength();
|
rt300@0
|
919
|
rt300@0
|
920 radial = false;
|
rt300@0
|
921
|
rt300@0
|
922 cout << "constructing SQUARE mesh\n";
|
rt300@0
|
923 }
|
rt300@9
|
924 SquareMesh::~SquareMesh(){
|
rt300@0
|
925
|
rt300@9
|
926 cout << "destructing SQUARE mesh\n";
|
rt300@0
|
927 }
|
rt300@0
|
928
|
rt300@0
|
929 //--------------------------------------------------------------
|
rt300@0
|
930 // make componets for square
|
rt300@9
|
931 void SquareMesh::makeComponents(int aheight, int awidth){
|
rt300@1
|
932
|
rt300@9
|
933
|
rt300@0
|
934 height = aheight;
|
rt300@0
|
935 width = awidth;
|
rt300@0
|
936 numLumps = height * width;
|
rt300@9
|
937 // horz // vert // criss cross
|
rt300@0
|
938 numSprings = (width-1)*height + (height-1)*width + 2*(height-1)*(width-1);
|
rt300@0
|
939
|
rt300@9
|
940 Mesh::makeComponents(numLumps, numSprings); // kinda wierd but works.
|
rt300@3
|
941
|
rt300@0
|
942 }
|
rt300@0
|
943
|
rt300@0
|
944 //--------------------------------------------------------------
|
rt300@9
|
945 void SquareMesh::setLumpPositions(){
|
rt300@9
|
946 // numbering works line by line like text, analogue tv's etc
|
rt300@0
|
947 double vspacing = 1.0/(height-1);
|
rt300@0
|
948 double hspacing = 1.0/(width-1);
|
rt300@0
|
949 int i =0;
|
rt300@0
|
950 // set positions
|
rt300@0
|
951 for(int row = 0; row < height; row++){ // go down column
|
rt300@0
|
952 for(int col = 0;col < width; col++){ // go along row
|
rt300@4
|
953 if(i >= lumps.size()){
|
rt300@1
|
954 cout << " setLumpPosisions index error!\n";
|
rt300@1
|
955 }
|
rt300@0
|
956 lumps[i].setPosition(hspacing*col,vspacing*row);
|
rt300@0
|
957
|
rt300@0
|
958 i++;
|
rt300@0
|
959 }
|
rt300@0
|
960 }
|
rt300@9
|
961
|
rt300@9
|
962 }
|
rt300@9
|
963 //--------------------------------------------------------------
|
rt300@9
|
964 void SquareMesh::makeConnections(){
|
rt300@9
|
965
|
rt300@9
|
966 // could be cleverer in terms of numbering?
|
rt300@9
|
967 int lumpnum = 0;
|
rt300@9
|
968 int springnum = 0;
|
rt300@9
|
969 // attach horizontal
|
rt300@9
|
970 for ( int i=0;i<height;i++){
|
rt300@9
|
971 for(int j=0;j<width-1;j++){
|
rt300@9
|
972 connect(springnum,lumpnum);
|
rt300@9
|
973 lumpnum++;
|
rt300@9
|
974 if(springnum >= numSprings){
|
rt300@9
|
975 cout << " makeConnections index error!\n";
|
rt300@9
|
976 }
|
rt300@9
|
977 if(lumpnum >= lumps.size()){
|
rt300@9
|
978 cout << " makeConnections index error!\n";
|
rt300@9
|
979 }
|
rt300@9
|
980 connect(springnum,lumpnum);
|
rt300@9
|
981 springnum++;
|
rt300@9
|
982
|
rt300@9
|
983 }
|
rt300@9
|
984 lumpnum++;
|
rt300@9
|
985 }
|
rt300@9
|
986 cout << "lumps attach horz: " << lumpnum-1 << ", spring " << springnum-1 << "\n";
|
rt300@9
|
987 // attach vertical
|
rt300@9
|
988 lumpnum = 0;
|
rt300@9
|
989 for ( int i=0;i<width;i++){
|
rt300@9
|
990 for(int j=0;j<height-1;j++){
|
rt300@9
|
991 connect(springnum,lumpnum);
|
rt300@9
|
992 lumpnum+=width;
|
rt300@9
|
993 if(springnum >= numSprings){
|
rt300@9
|
994 cout << " makeConnections index error!\n";
|
rt300@9
|
995 }
|
rt300@9
|
996 if(lumpnum >= lumps.size()){
|
rt300@9
|
997 cout << " makeConnections index error!\n";
|
rt300@9
|
998 }
|
rt300@9
|
999 connect(springnum,lumpnum);
|
rt300@9
|
1000 springnum++;
|
rt300@9
|
1001
|
rt300@9
|
1002 }
|
rt300@9
|
1003 lumpnum -= (width*(height-1)) - 1;
|
rt300@9
|
1004 }
|
rt300@1
|
1005
|
rt300@0
|
1006 }
|
rt300@9
|
1007
|
rt300@9
|
1008 //--------------------------------------------------------------
|
rt300@9
|
1009 void SquareMesh::constrain(double ax, double ay, constrainMode aMode){
|
rt300@9
|
1010
|
rt300@9
|
1011 TwoVector diff;
|
rt300@9
|
1012 int i = 0;
|
rt300@9
|
1013
|
rt300@9
|
1014 // check if lump is within grab range
|
rt300@9
|
1015 switch (aMode) {
|
rt300@9
|
1016 case CONSTRAIN_GRAB_REGION:
|
rt300@9
|
1017 for(i = 0; i<lumps.size(); i++){
|
rt300@9
|
1018
|
rt300@9
|
1019 diff.setCoord(lumps[i].position.x - ax, lumps[i].position.y - ay);
|
rt300@9
|
1020
|
rt300@9
|
1021 if (diff.norm() < GRAB_RANGE){
|
rt300@9
|
1022 if(i >= lumps.size()){
|
rt300@9
|
1023 cout << "constrain index error\n";
|
rt300@9
|
1024 }
|
rt300@9
|
1025 lumps[i].constrain();
|
rt300@9
|
1026 }
|
rt300@9
|
1027 }
|
rt300@9
|
1028 break;
|
rt300@9
|
1029 case CONSTRAIN_EDGES:
|
rt300@9
|
1030 i = 0;
|
rt300@9
|
1031 for(int row = 0; row < height; row++){ // go down column
|
rt300@9
|
1032 for(int col = 0;col < width; col++){ // go along row
|
rt300@9
|
1033 if(row == 0 || row == height-1 || col == 0 || col == width-1){
|
rt300@9
|
1034 if(i >= lumps.size()){
|
rt300@9
|
1035 cout << "constrain index error\n";
|
rt300@9
|
1036 }
|
rt300@9
|
1037 lumps[i].constrain();
|
rt300@9
|
1038 }
|
rt300@9
|
1039 i++;
|
rt300@9
|
1040 }
|
rt300@9
|
1041 }
|
rt300@9
|
1042 break;
|
rt300@9
|
1043 case CONSTRAIN_EDGES_XY:
|
rt300@9
|
1044 i = 0;
|
rt300@9
|
1045 for(int row = 0; row < height; row++){ // go down column
|
rt300@9
|
1046 for(int col = 0;col < width; col++){ // go along row
|
rt300@9
|
1047 if(row == 0 || row == height-1){
|
rt300@9
|
1048 if(i >= lumps.size()){
|
rt300@9
|
1049 cout << "constrain index error\n";
|
rt300@9
|
1050 }
|
rt300@9
|
1051 lumps[i].constrain(Lump::CONSTRAIN_Y);
|
rt300@9
|
1052 }else if( col == 0 || col == width-1){
|
rt300@9
|
1053 if(i >= lumps.size()){
|
rt300@9
|
1054 cout << "constrain index error\n";
|
rt300@9
|
1055 }
|
rt300@9
|
1056 lumps[i].constrain(Lump::CONSTRAIN_X);
|
rt300@9
|
1057 }
|
rt300@9
|
1058 i++;
|
rt300@9
|
1059 }
|
rt300@9
|
1060 }
|
rt300@9
|
1061 break;
|
rt300@9
|
1062 case CONSTRAIN_CORNERS:
|
rt300@9
|
1063 i = 0;
|
rt300@9
|
1064 for(int row = 0; row < height; row++){ // go down column
|
rt300@9
|
1065 for(int col = 0;col < width; col++){ // go along row
|
rt300@9
|
1066 if( (row == 0 && col == 0)
|
rt300@9
|
1067 || (row == height-1 && col == 0)
|
rt300@9
|
1068 || (row == 0 && col == width-1)
|
rt300@9
|
1069 || (row == height-1 && col == width-1)){
|
rt300@9
|
1070 if(i >= lumps.size()){
|
rt300@9
|
1071 cout << "constrain index error\n";
|
rt300@9
|
1072 }
|
rt300@9
|
1073 lumps[i].constrain();
|
rt300@9
|
1074 }
|
rt300@9
|
1075 i++;
|
rt300@9
|
1076 }
|
rt300@9
|
1077 }
|
rt300@9
|
1078 break;
|
rt300@9
|
1079
|
rt300@9
|
1080 default:
|
rt300@9
|
1081 break;
|
rt300@9
|
1082 }
|
rt300@9
|
1083
|
rt300@9
|
1084 }
|
rt300@9
|
1085
|
rt300@9
|
1086 //--------------------------------------------------------------
|
rt300@9
|
1087 void SquareMesh::makeDefaultScanPath(){
|
rt300@9
|
1088 if (height < 10 || width < 10) return; // not much point
|
rt300@9
|
1089
|
rt300@9
|
1090 int vmarg = 5;
|
rt300@9
|
1091 int hmarg = 5;
|
rt300@9
|
1092
|
rt300@9
|
1093 int lumpno = vmarg * width + hmarg; // top left corner
|
rt300@9
|
1094 int springno = vmarg * (width - 1) + hmarg;
|
rt300@9
|
1095 // do top horz
|
rt300@9
|
1096 for(int i = 0; i < width - 2*hmarg; i++){
|
rt300@9
|
1097 if(lumpno >= lumps.size()) cout << "makeDefaultScanPath index error\n";
|
rt300@9
|
1098 if(springno >= numSprings) cout << "makeDefaultScanPath index error\n";
|
rt300@9
|
1099 scanPath.addElement(&lumps[lumpno], &springs[springno]);
|
rt300@9
|
1100 lumpno++;
|
rt300@9
|
1101 springno++;
|
rt300@9
|
1102 }
|
rt300@9
|
1103
|
rt300@9
|
1104 // do right vert, lumpno starts the same
|
rt300@9
|
1105 // all horz spr // left marg rows // top margin
|
rt300@9
|
1106 springno = height*(width-1) + ((height-1) * (width - hmarg)) + vmarg;
|
rt300@9
|
1107
|
rt300@9
|
1108 for(int i = 0; i < height - (2 * vmarg); i++){
|
rt300@9
|
1109 if(lumpno >= lumps.size()) cout << "makeDefaultScanPath index error\n";
|
rt300@9
|
1110 if(springno >= numSprings) cout << "makeDefaultScanPath index error\n";
|
rt300@9
|
1111 scanPath.addElement(&lumps[lumpno], &springs[springno]);
|
rt300@9
|
1112 springno++; // jump to next row
|
rt300@9
|
1113 lumpno += width; // ditto
|
rt300@9
|
1114 }
|
rt300@9
|
1115
|
rt300@9
|
1116
|
rt300@9
|
1117 // do bottom horz right to left
|
rt300@9
|
1118 springno = (height - vmarg) * (width - 1) + (width - hmarg - 1);
|
rt300@9
|
1119 for(int i = 0; i < width - 2*hmarg; i++){
|
rt300@9
|
1120 if(lumpno >= lumps.size()) cout << "makeDefaultScanPath index error\n";
|
rt300@9
|
1121 if(springno >= numSprings) cout << "makeDefaultScanPath index error\n";
|
rt300@9
|
1122 scanPath.addElement(&lumps[lumpno], &springs[springno]);
|
rt300@9
|
1123 springno--; // jump to next row
|
rt300@9
|
1124 lumpno--; // ditto
|
rt300@9
|
1125 }
|
rt300@9
|
1126
|
rt300@9
|
1127 // all horz spr // left marg rows // top margin
|
rt300@9
|
1128 springno = height*(width-1) + ((height-1) * hmarg) + height - vmarg - 1;
|
rt300@9
|
1129 for(int i = 0; i < height - 2 * vmarg; i++){
|
rt300@9
|
1130 if(lumpno >= lumps.size()) cout << "makeDefaultScanPath index error\n";
|
rt300@9
|
1131 if(springno >= numSprings) cout << "makeDefaultScanPath index error\n";
|
rt300@9
|
1132 scanPath.addElement(&lumps[lumpno], &springs[springno]);
|
rt300@9
|
1133 springno--; // jump to next row
|
rt300@9
|
1134 lumpno -= width; // ditto
|
rt300@9
|
1135 }
|
rt300@9
|
1136
|
rt300@9
|
1137 }
|
rt300@9
|
1138 //--------------------------------------------------------------
|
rt300@9
|
1139
|
rt300@9
|
1140 /****************************************/
|
rt300@9
|
1141 // SquareCrossMesh */
|
rt300@9
|
1142 /****************************************/
|
rt300@9
|
1143 //--------------------------------------------------------------
|
rt300@9
|
1144 SquareCrossMesh::SquareCrossMesh(int height, int width){
|
rt300@9
|
1145
|
rt300@9
|
1146 meshType = SQUARE_CROSS_MESH;
|
rt300@9
|
1147 makeComponents(height, width);
|
rt300@9
|
1148
|
rt300@9
|
1149 setLumpPositions();
|
rt300@9
|
1150
|
rt300@9
|
1151 makeConnections();
|
rt300@9
|
1152
|
rt300@9
|
1153 makeDefaultScanPath();
|
rt300@9
|
1154
|
rt300@9
|
1155 constrain(0,0,CONSTRAIN_EDGES);
|
rt300@9
|
1156
|
rt300@9
|
1157 zeroRestLength();
|
rt300@9
|
1158
|
rt300@9
|
1159 radial = false;
|
rt300@9
|
1160
|
rt300@9
|
1161 cout << "constructing SQUARECROSS mesh\n";
|
rt300@9
|
1162 }
|
rt300@9
|
1163 SquareCrossMesh::~SquareCrossMesh(){
|
rt300@9
|
1164
|
rt300@9
|
1165 cout << "destructing SQUARECROSS mesh\n";
|
rt300@9
|
1166 }
|
rt300@9
|
1167
|
rt300@0
|
1168 //--------------------------------------------------------------
|
rt300@0
|
1169 void SquareCrossMesh::makeConnections(){
|
rt300@0
|
1170
|
rt300@0
|
1171 // could be cleverer in terms of numbering?
|
rt300@0
|
1172 int lumpnum = 0;
|
rt300@0
|
1173 int springnum = 0;
|
rt300@0
|
1174 // attach horizontal
|
rt300@0
|
1175 for ( int i=0;i<height;i++){
|
rt300@0
|
1176 for(int j=0;j<width-1;j++){
|
rt300@0
|
1177 connect(springnum,lumpnum);
|
rt300@0
|
1178 lumpnum++;
|
rt300@1
|
1179 if(springnum >= numSprings){
|
rt300@1
|
1180 cout << " makeConnections index error!\n";
|
rt300@1
|
1181 }
|
rt300@4
|
1182 if(lumpnum >= lumps.size()){
|
rt300@1
|
1183 cout << " makeConnections index error!\n";
|
rt300@1
|
1184 }
|
rt300@0
|
1185 connect(springnum,lumpnum);
|
rt300@0
|
1186 springnum++;
|
rt300@0
|
1187
|
rt300@0
|
1188 }
|
rt300@0
|
1189 lumpnum++;
|
rt300@0
|
1190 }
|
rt300@1
|
1191 cout << "lumps attach horz: " << lumpnum-1 << ", spring " << springnum-1 << "\n";
|
rt300@0
|
1192 // attach vertical
|
rt300@0
|
1193 lumpnum = 0;
|
rt300@0
|
1194 for ( int i=0;i<width;i++){
|
rt300@0
|
1195 for(int j=0;j<height-1;j++){
|
rt300@0
|
1196 connect(springnum,lumpnum);
|
rt300@0
|
1197 lumpnum+=width;
|
rt300@1
|
1198 if(springnum >= numSprings){
|
rt300@1
|
1199 cout << " makeConnections index error!\n";
|
rt300@1
|
1200 }
|
rt300@4
|
1201 if(lumpnum >= lumps.size()){
|
rt300@1
|
1202 cout << " makeConnections index error!\n";
|
rt300@1
|
1203 }
|
rt300@0
|
1204 connect(springnum,lumpnum);
|
rt300@0
|
1205 springnum++;
|
rt300@0
|
1206
|
rt300@0
|
1207 }
|
rt300@0
|
1208 lumpnum -= (width*(height-1)) - 1;
|
rt300@0
|
1209 }
|
rt300@0
|
1210 // attach diagonal
|
rt300@0
|
1211 lumpnum = 0;
|
rt300@0
|
1212 for ( int i=0;i<width-1;i++){
|
rt300@0
|
1213 for(int j=0;j<height-1;j++){
|
rt300@0
|
1214 connect(springnum,lumpnum);
|
rt300@0
|
1215 lumpnum+=(width);
|
rt300@1
|
1216 if(springnum >= numSprings){
|
rt300@1
|
1217 cout << " makeConnections index error!\n";
|
rt300@1
|
1218 }
|
rt300@4
|
1219 if(lumpnum >= lumps.size()){
|
rt300@1
|
1220 cout << " makeConnections index error!\n";
|
rt300@1
|
1221 }
|
rt300@0
|
1222 connect(springnum,lumpnum+1);
|
rt300@0
|
1223 springnum++;
|
rt300@0
|
1224
|
rt300@0
|
1225 }
|
rt300@0
|
1226 lumpnum -= (width*(height-1)) - 1;
|
rt300@0
|
1227 }
|
rt300@0
|
1228 // attach other diagonal
|
rt300@0
|
1229 lumpnum = 1;
|
rt300@0
|
1230 for ( int i=0;i<width-1;i++){
|
rt300@0
|
1231 for(int j=0;j<height-1;j++){
|
rt300@0
|
1232 connect(springnum,lumpnum);
|
rt300@0
|
1233 lumpnum+=(width);
|
rt300@1
|
1234 if(springnum >= numSprings){
|
rt300@1
|
1235 cout << " makeConnections index error!\n";
|
rt300@1
|
1236 }
|
rt300@4
|
1237 if(lumpnum >= lumps.size()){
|
rt300@1
|
1238 cout << " makeConnections index error!\n";
|
rt300@1
|
1239 }
|
rt300@0
|
1240 connect(springnum,lumpnum-1);
|
rt300@0
|
1241 springnum++;
|
rt300@0
|
1242
|
rt300@0
|
1243 }
|
rt300@0
|
1244 lumpnum -= (width*(height-1)) - 1;
|
rt300@0
|
1245 }
|
rt300@0
|
1246 }
|
rt300@0
|
1247
|
rt300@0
|
1248 //--------------------------------------------------------------
|
rt300@9
|
1249
|
rt300@0
|
1250 //--------------------------------------------------------------
|
rt300@0
|
1251
|
rt300@0
|
1252
|
rt300@0
|
1253 /****************************************/
|
rt300@0
|
1254 // SpiderMesh */
|
rt300@0
|
1255 /****************************************/
|
rt300@0
|
1256 SpiderMesh::SpiderMesh(int aNumSpokes,int aNumRings) : Mesh(){
|
rt300@8
|
1257 meshType = SPIDER_MESH;
|
rt300@8
|
1258
|
rt300@0
|
1259 numSpokes = aNumSpokes;
|
rt300@0
|
1260 numRings = aNumRings;
|
rt300@0
|
1261
|
rt300@0
|
1262 radial = true;
|
rt300@0
|
1263
|
rt300@0
|
1264 makeComponents(numSpokes, numRings);
|
rt300@0
|
1265
|
rt300@0
|
1266 setLumpPositions();
|
rt300@0
|
1267
|
rt300@0
|
1268 makeConnections();
|
rt300@0
|
1269
|
rt300@0
|
1270 makeDefaultScanPath();
|
rt300@0
|
1271
|
rt300@0
|
1272 constrain(0.0,0.0,CONSTRAIN_EDGES);
|
rt300@0
|
1273 constrain(0.0,0.0,CONSTRAIN_CORNERS);
|
rt300@0
|
1274
|
rt300@0
|
1275 cout << "constructed SPIDER mesh\n";
|
rt300@0
|
1276
|
rt300@0
|
1277
|
rt300@0
|
1278
|
rt300@0
|
1279 }
|
rt300@0
|
1280 //--------------------------------------------------------------
|
rt300@0
|
1281 void SpiderMesh::makeComponents(int aDimension1, int aDimension2){
|
rt300@0
|
1282 // make componets creates the correct number of lumps and springs according to dimensions and mesh type
|
rt300@0
|
1283 cout << "!!!spider makeComponents\n";
|
rt300@0
|
1284 numLumps = numSpokes * numRings + 1; // +1 cos one in the middle
|
rt300@0
|
1285 numSprings = 2 * numSpokes * numRings;
|
rt300@0
|
1286
|
rt300@4
|
1287 //lumps = new Lump[numLumps];
|
rt300@4
|
1288 lumps = vector<Lump>(numLumps);
|
rt300@4
|
1289 cout << "made " << numLumps << " lumps\n";
|
rt300@3
|
1290 springs = vector<Spring>(numSprings);
|
rt300@3
|
1291
|
rt300@0
|
1292 cout << "made " << numSprings << " springs\n";
|
rt300@0
|
1293
|
rt300@0
|
1294
|
rt300@0
|
1295 }
|
rt300@0
|
1296 //--------------------------------------------------------------
|
rt300@0
|
1297 void SpiderMesh::setLumpPositions(){
|
rt300@0
|
1298 cout << "!spider setLumpPositions\n";
|
rt300@0
|
1299 // here we're assuming that zero spoke is to right
|
rt300@0
|
1300 // work out sines / cosines for each spoke
|
rt300@0
|
1301 int l = 1;
|
rt300@0
|
1302 double hyplen,xpos,ypos;
|
rt300@0
|
1303
|
rt300@0
|
1304 double * cosines = new double[numSpokes];
|
rt300@0
|
1305 double * sines = new double[numSpokes];
|
rt300@0
|
1306 double angle = 2 * PI / numSpokes;
|
rt300@0
|
1307
|
rt300@0
|
1308 double ringSpacing = 1.0/(2*numRings);
|
rt300@0
|
1309
|
rt300@0
|
1310 for(int spoke = 0; spoke < numSpokes; spoke++){
|
rt300@0
|
1311 cosines[spoke] = cos(angle*spoke);
|
rt300@0
|
1312 sines[spoke] = sin(angle*spoke);
|
rt300@0
|
1313 }
|
rt300@0
|
1314
|
rt300@0
|
1315 lumps[0].setPosition(0.5,0.5);
|
rt300@0
|
1316
|
rt300@0
|
1317 for(int ring = 0; ring < numRings; ring++){
|
rt300@0
|
1318 for(int spoke = 0; spoke < numSpokes; spoke++){
|
rt300@0
|
1319 hyplen = ringSpacing * (ring+1);
|
rt300@0
|
1320 xpos = hyplen * cosines[spoke] + 0.5;
|
rt300@0
|
1321 ypos = hyplen*sines[spoke] + 0.5;
|
rt300@0
|
1322 lumps[l].setPosition(xpos,ypos);
|
rt300@0
|
1323 l++;
|
rt300@0
|
1324
|
rt300@0
|
1325 }
|
rt300@0
|
1326 }
|
rt300@0
|
1327 delete [] cosines;
|
rt300@0
|
1328 delete [] sines;
|
rt300@0
|
1329
|
rt300@0
|
1330 }
|
rt300@0
|
1331 //--------------------------------------------------------------
|
rt300@0
|
1332 void SpiderMesh::makeConnections(){
|
rt300@0
|
1333 // TODO needs to be rewritten to automatically
|
rt300@0
|
1334 // add in lumps and springs AS we're connecting
|
rt300@0
|
1335 //using std vector
|
rt300@0
|
1336 // this is dumb
|
rt300@0
|
1337 cout << "!!!spider make connections\n";
|
rt300@0
|
1338
|
rt300@0
|
1339 // UNLIKE a spider we're going to make rings first, to make indexing the scan path easier...
|
rt300@0
|
1340
|
rt300@0
|
1341 for(int ring = 0; ring < numRings; ring++){
|
rt300@0
|
1342 for(int spoke = 0; spoke < numSpokes-1; spoke++){
|
rt300@0
|
1343 // spring , lump
|
rt300@0
|
1344 connect(numSpokes*ring + spoke, ring*numSpokes + spoke + 1);
|
rt300@0
|
1345 connect(numSpokes*ring + spoke, ring*numSpokes + spoke + 2);
|
rt300@0
|
1346 }
|
rt300@0
|
1347 // remember the last one on the ring goes back to first
|
rt300@0
|
1348 // spring , lump
|
rt300@0
|
1349 connect(numSpokes*ring + numSpokes - 1 , ring*numSpokes + numSpokes);
|
rt300@0
|
1350 connect(numSpokes*ring + numSpokes - 1, ring*numSpokes + 1);
|
rt300@0
|
1351 }
|
rt300@0
|
1352 // at which point we have used numSpokes*numRings springs
|
rt300@0
|
1353 int used = numSpokes*numRings;
|
rt300@0
|
1354 // first ring is different cos it connects to central point
|
rt300@0
|
1355 for(int spoke = 0; spoke < numSpokes; spoke++){
|
rt300@0
|
1356 connect(used,0); // inner radial on center
|
rt300@0
|
1357 connect(used,spoke+1); // outer radial
|
rt300@0
|
1358 springs[used].setRestLength(0.0); // need tension on spokes
|
rt300@0
|
1359 used++;
|
rt300@0
|
1360 }
|
rt300@0
|
1361 // now do the rest of the radial spokes
|
rt300@0
|
1362 for(int ring = 0; ring < numRings-1; ring++){
|
rt300@0
|
1363 for(int spoke = 0; spoke < numSpokes; spoke++){
|
rt300@0
|
1364 connect(used,ring*numSpokes+1+spoke); //
|
rt300@0
|
1365 connect(used,(ring+1)*numSpokes+1+spoke); // going to next ring out
|
rt300@0
|
1366 springs[used].setRestLength(0.0);
|
rt300@0
|
1367 used++;
|
rt300@0
|
1368 }
|
rt300@0
|
1369 }
|
rt300@0
|
1370 }
|
rt300@0
|
1371
|
rt300@0
|
1372 //--------------------------------------------------------------
|
rt300@0
|
1373 void SpiderMesh::constrain(double ax, double ay, constrainMode aMode){
|
rt300@0
|
1374 cout << "!!spider constrain\n";
|
rt300@0
|
1375
|
rt300@0
|
1376 TwoVector diff;
|
rt300@0
|
1377 int i = 0;
|
rt300@0
|
1378
|
rt300@0
|
1379 // check if lump is within grab range
|
rt300@0
|
1380 switch (aMode) {
|
rt300@0
|
1381 case CONSTRAIN_GRAB_REGION:
|
rt300@4
|
1382 for(i = 0; i<lumps.size(); i++){
|
rt300@0
|
1383
|
rt300@0
|
1384 diff.setCoord(lumps[i].position.x - ax, lumps[i].position.y - ay);
|
rt300@0
|
1385
|
rt300@0
|
1386 if (diff.norm() < GRAB_RANGE){
|
rt300@0
|
1387 lumps[i].constrain();
|
rt300@0
|
1388 }
|
rt300@0
|
1389 }
|
rt300@0
|
1390 break;
|
rt300@0
|
1391 case CONSTRAIN_EDGES:
|
rt300@0
|
1392 {
|
rt300@0
|
1393 // constrain outer ring
|
rt300@0
|
1394 int startLump = numSpokes*(numRings-1) + 1;
|
rt300@0
|
1395 for(int l = startLump; l < startLump + numSpokes; l++){
|
rt300@0
|
1396 lumps[l].constrain();
|
rt300@0
|
1397 }
|
rt300@0
|
1398
|
rt300@0
|
1399 break;
|
rt300@0
|
1400 }
|
rt300@0
|
1401 case CONSTRAIN_CORNERS:
|
rt300@0
|
1402 // er... constrain the centre
|
rt300@0
|
1403 lumps[0].constrain();
|
rt300@0
|
1404
|
rt300@0
|
1405 break;
|
rt300@0
|
1406
|
rt300@0
|
1407 default:
|
rt300@0
|
1408 break;
|
rt300@0
|
1409 }
|
rt300@0
|
1410 }
|
rt300@0
|
1411
|
rt300@0
|
1412 //--------------------------------------------------------------
|
rt300@0
|
1413
|
rt300@0
|
1414 void SpiderMesh::makeDefaultScanPath(){
|
rt300@0
|
1415
|
rt300@0
|
1416 cout << "!!spider makeDefaultScanPath\n";
|
rt300@0
|
1417
|
rt300@5
|
1418 /*
|
rt300@5
|
1419 // add a all inner rings to the path
|
rt300@5
|
1420
|
rt300@5
|
1421
|
rt300@0
|
1422 int ringNo = ceil(numRings/2.0);
|
rt300@0
|
1423 int springno = 0, lumpno = 0;
|
rt300@0
|
1424 for(int i = 0; i < numSpokes; i++){
|
rt300@0
|
1425 lumpno = numSpokes*ringNo + 1 + i;
|
rt300@0
|
1426 springno = numSpokes*ringNo + i;
|
rt300@3
|
1427 scanPath.addElement(&lumps[lumpno], &springs[springno]);
|
rt300@0
|
1428 }
|
rt300@0
|
1429 cout << "!!spider scan path created on ring " << ringNo << "\n";
|
rt300@5
|
1430 */
|
rt300@5
|
1431
|
rt300@0
|
1432 // add a spoke to the path
|
rt300@5
|
1433
|
rt300@0
|
1434 int springno = 0, lumpno = 0;
|
rt300@0
|
1435
|
rt300@0
|
1436 int springsinrings = numSpokes*numRings;
|
rt300@0
|
1437 for(int i = 0; i < numRings-1; i++){
|
rt300@0
|
1438 lumpno = numSpokes*i; // zero, numspokes etc
|
rt300@5
|
1439 springno = springsinrings + numSpokes*i -1; // starts from total rings, increments by numspokes etc
|
rt300@5
|
1440 scanPath.addElement(&lumps[lumpno], &springs[springno]);
|
rt300@5
|
1441 }
|
rt300@5
|
1442
|
rt300@5
|
1443 for(int i = 0; i < numRings-1; i++){
|
rt300@5
|
1444 lumpno = numSpokes*i + 1; // zero, numspokes etc
|
rt300@0
|
1445 springno = springsinrings + numSpokes*i; // starts from total rings, increments by numspokes etc
|
rt300@3
|
1446 scanPath.addElement(&lumps[lumpno], &springs[springno]);
|
rt300@5
|
1447 }
|
rt300@5
|
1448 /*
|
rt300@5
|
1449 for(int i = numRings-2; i >= 0 ; i--){
|
rt300@5
|
1450 lumpno = numSpokes*i; // zero, numspokes etc
|
rt300@5
|
1451 springno = springsinrings + numSpokes*i; // starts from total rings, increments by numspokes etc
|
rt300@5
|
1452 scanPath.addElement(&lumps[lumpno], &springs[springno]);
|
rt300@5
|
1453 }
|
rt300@5
|
1454 */
|
rt300@5
|
1455
|
rt300@0
|
1456 }
|
rt300@0
|
1457
|
rt300@0
|
1458
|
rt300@0
|
1459 //--------------------------------------------------------------
|
rt300@0
|
1460 /****************************************/
|
rt300@0
|
1461 // Holed Spider Mesh */
|
rt300@0
|
1462 /****************************************/
|
rt300@0
|
1463 //--------------------------------------------------------------
|
rt300@0
|
1464 HoledSpiderMesh::HoledSpiderMesh(int aNumSpokes,int aNumRings) : Mesh(){
|
rt300@8
|
1465 meshType = HOLED_SPIDER_MESH;
|
rt300@0
|
1466 numSpokes = aNumSpokes;
|
rt300@0
|
1467 numRings = aNumRings;
|
rt300@0
|
1468 radial = true;
|
rt300@0
|
1469
|
rt300@0
|
1470 makeComponents(numSpokes, numRings);
|
rt300@0
|
1471
|
rt300@0
|
1472 setLumpPositions();
|
rt300@0
|
1473
|
rt300@0
|
1474 makeConnections();
|
rt300@0
|
1475
|
rt300@0
|
1476 makeDefaultScanPath();
|
rt300@0
|
1477
|
rt300@0
|
1478 constrain(0.0,0.0,CONSTRAIN_EDGES);
|
rt300@0
|
1479 constrain(0.0,0.0,CONSTRAIN_CORNERS);
|
rt300@0
|
1480
|
rt300@0
|
1481 cout << "constructed SPIDER mesh\n";
|
rt300@0
|
1482 }
|
rt300@0
|
1483
|
rt300@0
|
1484 void HoledSpiderMesh::makeComponents(int aDimension1, int aDimension2){
|
rt300@0
|
1485 // make componets creates the correct number of lumps and springs according to dimensions and mesh type
|
rt300@0
|
1486 cout << "HOLED spider makeComponents\n";
|
rt300@0
|
1487 numLumps = numSpokes * numRings;
|
rt300@0
|
1488 numSprings = numSpokes * numRings + numSpokes * (numRings - 1);
|
rt300@0
|
1489
|
rt300@4
|
1490 lumps = vector<Lump>(numLumps);
|
rt300@4
|
1491 cout << "made " << numLumps << " lumps\n";
|
rt300@3
|
1492 springs = vector<Spring>(numSprings);
|
rt300@0
|
1493 cout << "made " << numSprings << " springs\n";
|
rt300@0
|
1494
|
rt300@0
|
1495
|
rt300@0
|
1496 }
|
rt300@0
|
1497 //--------------------------------------------------------------
|
rt300@0
|
1498 void HoledSpiderMesh::setLumpPositions(){
|
rt300@0
|
1499 cout << "HOLED spider setLumpPositions\n";
|
rt300@0
|
1500 // here we're assuming that zero spoke is to right
|
rt300@0
|
1501 // work out sines / cosines for each spoke
|
rt300@0
|
1502 int l = 0;
|
rt300@0
|
1503 double hyplen,xpos,ypos;
|
rt300@0
|
1504
|
rt300@0
|
1505 double * cosines = new double[numSpokes];
|
rt300@0
|
1506 double * sines = new double[numSpokes];
|
rt300@0
|
1507 double angle = 2 * PI / numSpokes;
|
rt300@0
|
1508
|
rt300@0
|
1509 double ringSpacing = 1.0/(2*numRings);
|
rt300@0
|
1510
|
rt300@0
|
1511 for(int spoke = 0; spoke < numSpokes; spoke++){
|
rt300@0
|
1512 cosines[spoke] = cos(angle*spoke);
|
rt300@0
|
1513 sines[spoke] = sin(angle*spoke);
|
rt300@0
|
1514 }
|
rt300@0
|
1515
|
rt300@0
|
1516 for(int ring = 0; ring < numRings; ring++){
|
rt300@0
|
1517 for(int spoke = 0; spoke < numSpokes; spoke++){
|
rt300@0
|
1518 hyplen = ringSpacing * (ring+1);
|
rt300@0
|
1519 xpos = hyplen * cosines[spoke] + 0.5;
|
rt300@0
|
1520 ypos = hyplen*sines[spoke] + 0.5;
|
rt300@0
|
1521 lumps[l].setPosition(xpos,ypos);
|
rt300@0
|
1522 l++;
|
rt300@0
|
1523
|
rt300@0
|
1524 }
|
rt300@0
|
1525 }
|
rt300@0
|
1526 delete [] cosines;
|
rt300@0
|
1527 delete [] sines;
|
rt300@0
|
1528
|
rt300@0
|
1529 }
|
rt300@0
|
1530 //--------------------------------------------------------------
|
rt300@0
|
1531 void HoledSpiderMesh::makeConnections(){
|
rt300@0
|
1532 // TODO needs to be rewritten to automatically
|
rt300@0
|
1533 // add in lumps and springs AS we're connecting
|
rt300@0
|
1534 //using std vector
|
rt300@0
|
1535 // this is dumb
|
rt300@0
|
1536 cout << "HOLED spider make connections\n";
|
rt300@0
|
1537
|
rt300@0
|
1538 // UNLIKE a spider we're going to make rings first, to make indexing the scan path easier...
|
rt300@0
|
1539
|
rt300@0
|
1540 for(int ring = 0; ring < numRings; ring++){
|
rt300@0
|
1541 for(int spoke = 0; spoke < numSpokes-1; spoke++){
|
rt300@0
|
1542 // spring , lump
|
rt300@0
|
1543 connect(numSpokes*ring + spoke, ring*numSpokes + spoke + 0);
|
rt300@0
|
1544 connect(numSpokes*ring + spoke, ring*numSpokes + spoke + 1);
|
rt300@0
|
1545 }
|
rt300@0
|
1546 // remember the last one on the ring goes back to first
|
rt300@0
|
1547 // spring , lump
|
rt300@0
|
1548 connect(numSpokes*ring + numSpokes - 1 , ring*numSpokes + numSpokes - 1);
|
rt300@0
|
1549 connect(numSpokes*ring + numSpokes - 1, ring*numSpokes);
|
rt300@0
|
1550 }
|
rt300@0
|
1551 // at which point we have used numSpokes*numRings springs
|
rt300@0
|
1552 int used = numSpokes*numRings;
|
rt300@0
|
1553 // now do the rest of the radial spokes
|
rt300@0
|
1554 for(int ring = 0; ring < numRings-1; ring++){
|
rt300@0
|
1555 for(int spoke = 0; spoke < numSpokes; spoke++){
|
rt300@0
|
1556 connect(used,ring*numSpokes+spoke); //
|
rt300@0
|
1557 connect(used,(ring+1)*numSpokes+spoke); // going to next ring out
|
rt300@0
|
1558 springs[used].setRestLength(0.0);
|
rt300@0
|
1559 used++;
|
rt300@0
|
1560 }
|
rt300@0
|
1561 }
|
rt300@0
|
1562 }
|
rt300@0
|
1563
|
rt300@0
|
1564 //--------------------------------------------------------------
|
rt300@0
|
1565 void HoledSpiderMesh::constrain(double ax, double ay, constrainMode aMode){
|
rt300@0
|
1566 cout << "HOLED spider constrain\n";
|
rt300@0
|
1567
|
rt300@0
|
1568 TwoVector diff;
|
rt300@0
|
1569 int i = 0;
|
rt300@0
|
1570 int startLump = 0;
|
rt300@0
|
1571 // check if lump is within grab range
|
rt300@0
|
1572 switch (aMode) {
|
rt300@0
|
1573 case CONSTRAIN_GRAB_REGION:
|
rt300@4
|
1574 for(i = 0; i<lumps.size(); i++){
|
rt300@0
|
1575
|
rt300@0
|
1576 diff.setCoord(lumps[i].position.x - ax, lumps[i].position.y - ay);
|
rt300@0
|
1577
|
rt300@0
|
1578 if (diff.norm() < GRAB_RANGE){
|
rt300@0
|
1579 lumps[i].constrain();
|
rt300@0
|
1580 }
|
rt300@0
|
1581 }
|
rt300@0
|
1582 break;
|
rt300@0
|
1583 case CONSTRAIN_EDGES:
|
rt300@0
|
1584 {
|
rt300@0
|
1585 // constrain outer ring
|
rt300@0
|
1586 startLump = numSpokes*(numRings-1);
|
rt300@0
|
1587 for(int l = startLump; l < startLump + numSpokes; l++){
|
rt300@0
|
1588 lumps[l].constrain();
|
rt300@0
|
1589 }
|
rt300@0
|
1590
|
rt300@0
|
1591 break;
|
rt300@0
|
1592 }
|
rt300@0
|
1593 case CONSTRAIN_CORNERS:
|
rt300@0
|
1594 // constrain inner ring
|
rt300@0
|
1595
|
rt300@0
|
1596 for(int l = startLump; l < startLump + numSpokes; l++){
|
rt300@0
|
1597 lumps[l].constrain();
|
rt300@0
|
1598 }
|
rt300@0
|
1599
|
rt300@0
|
1600 break;
|
rt300@0
|
1601
|
rt300@0
|
1602 default:
|
rt300@0
|
1603 break;
|
rt300@0
|
1604 }
|
rt300@0
|
1605 }
|
rt300@0
|
1606 //--------------------------------------------------------------
|
rt300@0
|
1607
|
rt300@0
|
1608 void HoledSpiderMesh::makeDefaultScanPath(){
|
rt300@0
|
1609
|
rt300@0
|
1610 cout << "HOLED spider makeDefaultScanPath\n";
|
rt300@0
|
1611
|
rt300@0
|
1612 // add a ring to the path
|
rt300@0
|
1613 int ringNo = floor(numRings/2.0);
|
rt300@0
|
1614 int springno = 0, lumpno = 0;
|
rt300@0
|
1615 for(int i = 0; i < numSpokes; i++){
|
rt300@0
|
1616 lumpno = numSpokes*ringNo + i;
|
rt300@0
|
1617 springno = numSpokes*ringNo + i;
|
rt300@0
|
1618
|
rt300@3
|
1619 scanPath.addElement(&lumps[lumpno], &springs[springno]);
|
rt300@0
|
1620 }
|
rt300@0
|
1621 cout << "HOLED spider scan path created on ring " << ringNo << "\n";
|
rt300@0
|
1622
|
rt300@0
|
1623 // add a spoke to the path
|
rt300@0
|
1624 /*
|
rt300@0
|
1625 int springno = 0, lumpno = 0;
|
rt300@0
|
1626
|
rt300@0
|
1627 int springsinrings = numSpokes*numRings;
|
rt300@0
|
1628 for(int i = 0; i < numRings-1; i++){
|
rt300@0
|
1629 lumpno = numSpokes*i; // zero, numspokes etc
|
rt300@0
|
1630 springno = springsinrings + numSpokes*i; // starts from total rings, increments by numspokes etc
|
rt300@3
|
1631 scanPath.addElement(&lumps[lumpno], &springs[springno]);
|
rt300@0
|
1632 }
|
rt300@0
|
1633 */
|
rt300@0
|
1634 }
|
rt300@0
|
1635
|
rt300@0
|
1636 //--------------------------------------------------------------
|
rt300@0
|
1637 /****************************************/
|
rt300@0
|
1638 // Holed Spider Cross Mesh */
|
rt300@0
|
1639 /****************************************/
|
rt300@0
|
1640 //--------------------------------------------------------------
|
rt300@0
|
1641 SpiderCrossMesh::SpiderCrossMesh(int aNumSpokes,int aNumRings) : Mesh(){
|
rt300@8
|
1642 meshType = SPIDER_CROSS_MESH;
|
rt300@0
|
1643 numSpokes = aNumSpokes;
|
rt300@0
|
1644 numRings = aNumRings;
|
rt300@0
|
1645 radial = true;
|
rt300@0
|
1646
|
rt300@0
|
1647 makeComponents(numSpokes, numRings);
|
rt300@0
|
1648
|
rt300@0
|
1649 setLumpPositions();
|
rt300@0
|
1650
|
rt300@0
|
1651 makeConnections();
|
rt300@0
|
1652
|
rt300@0
|
1653 makeDefaultScanPath();
|
rt300@0
|
1654
|
rt300@0
|
1655 constrain(0.0,0.0,CONSTRAIN_EDGES);
|
rt300@0
|
1656 constrain(0.0,0.0,CONSTRAIN_CORNERS);
|
rt300@0
|
1657
|
rt300@0
|
1658 cout << "constructed SpiderCrossMesh mesh\n";
|
rt300@0
|
1659 }
|
rt300@0
|
1660
|
rt300@0
|
1661 void SpiderCrossMesh::makeComponents(int aDimension1, int aDimension2){
|
rt300@0
|
1662 // make componets creates the correct number of lumps and springs according to dimensions and mesh type
|
rt300@0
|
1663 cout << "SpiderCrossMesh spider makeComponents\n";
|
rt300@0
|
1664 numLumps = numSpokes * numRings;
|
rt300@0
|
1665 // rings // spokes & diags
|
rt300@0
|
1666 numSprings = numSpokes * numRings + 3 * numSpokes * (numRings - 1);
|
rt300@0
|
1667
|
rt300@9
|
1668 Mesh::makeComponents(numLumps, numSprings);
|
rt300@0
|
1669
|
rt300@0
|
1670
|
rt300@0
|
1671 }
|
rt300@0
|
1672 //--------------------------------------------------------------
|
rt300@0
|
1673 void SpiderCrossMesh::setLumpPositions(){
|
rt300@0
|
1674 cout << "SpiderCrossMesh spider setLumpPositions\n";
|
rt300@0
|
1675 // here we're assuming that zero spoke is to right
|
rt300@0
|
1676 // work out sines / cosines for each spoke
|
rt300@0
|
1677 int l = 0;
|
rt300@0
|
1678 double hyplen,xpos,ypos;
|
rt300@0
|
1679
|
rt300@0
|
1680 double * cosines = new double[numSpokes];
|
rt300@0
|
1681 double * sines = new double[numSpokes];
|
rt300@0
|
1682 double angle = 2 * PI / numSpokes;
|
rt300@0
|
1683
|
rt300@0
|
1684 double ringSpacing = 1.0/(2*numRings);
|
rt300@0
|
1685
|
rt300@0
|
1686 for(int spoke = 0; spoke < numSpokes; spoke++){
|
rt300@0
|
1687 cosines[spoke] = cos(angle*spoke);
|
rt300@0
|
1688 sines[spoke] = sin(angle*spoke);
|
rt300@0
|
1689 }
|
rt300@0
|
1690
|
rt300@0
|
1691 for(int ring = 0; ring < numRings; ring++){
|
rt300@0
|
1692 for(int spoke = 0; spoke < numSpokes; spoke++){
|
rt300@0
|
1693 hyplen = ringSpacing * (ring+1);
|
rt300@0
|
1694 xpos = hyplen * cosines[spoke] + 0.5;
|
rt300@0
|
1695 ypos = hyplen*sines[spoke] + 0.5;
|
rt300@0
|
1696 lumps[l].setPosition(xpos,ypos);
|
rt300@0
|
1697 l++;
|
rt300@0
|
1698
|
rt300@0
|
1699 }
|
rt300@0
|
1700 }
|
rt300@0
|
1701 delete [] cosines;
|
rt300@0
|
1702 delete [] sines;
|
rt300@0
|
1703
|
rt300@0
|
1704 }
|
rt300@0
|
1705 //--------------------------------------------------------------
|
rt300@0
|
1706 void SpiderCrossMesh::makeConnections(){
|
rt300@0
|
1707
|
rt300@0
|
1708 cout << "SpiderCrossMesh spider make connections\n";
|
rt300@0
|
1709
|
rt300@0
|
1710 // UNLIKE a spider we're going to make rings first, to make indexing the scan path easier...
|
rt300@0
|
1711
|
rt300@0
|
1712 for(int ring = 0; ring < numRings; ring++){
|
rt300@0
|
1713 for(int spoke = 0; spoke < numSpokes-1; spoke++){
|
rt300@0
|
1714 // spring , lump
|
rt300@0
|
1715 connect(numSpokes*ring + spoke, ring*numSpokes + spoke + 0);
|
rt300@0
|
1716 connect(numSpokes*ring + spoke, ring*numSpokes + spoke + 1);
|
rt300@0
|
1717 }
|
rt300@0
|
1718 // remember the last one on the ring goes back to first
|
rt300@0
|
1719 // spring , lump
|
rt300@0
|
1720 connect(numSpokes*ring + numSpokes - 1 , ring*numSpokes + numSpokes - 1);
|
rt300@0
|
1721 connect(numSpokes*ring + numSpokes - 1, ring*numSpokes);
|
rt300@0
|
1722 }
|
rt300@0
|
1723 // at which point we have used numSpokes*numRings springs
|
rt300@0
|
1724 int used = numSpokes*numRings;
|
rt300@0
|
1725
|
rt300@0
|
1726 // now do radial spokes
|
rt300@0
|
1727 for(int ring = 0; ring < numRings-1; ring++){
|
rt300@0
|
1728 for(int spoke = 0; spoke < numSpokes; spoke++){
|
rt300@0
|
1729 connect(used,ring*numSpokes+spoke); //
|
rt300@0
|
1730 connect(used,(ring+1)*numSpokes+spoke); // going to next ring out
|
rt300@0
|
1731 springs[used].setRestLength(0.0);
|
rt300@0
|
1732 used++;
|
rt300@0
|
1733 }
|
rt300@0
|
1734 }
|
rt300@0
|
1735 // now do diag /
|
rt300@0
|
1736 for(int ring = 0; ring < numRings-1; ring++){
|
rt300@0
|
1737 for(int spoke = 0; spoke < numSpokes-1; spoke++){
|
rt300@0
|
1738 connect(used,ring*numSpokes+spoke,(ring+1)*numSpokes+spoke+1); //
|
rt300@0
|
1739 springs[used].setRestLength(0.0);
|
rt300@0
|
1740 used++;
|
rt300@0
|
1741 }
|
rt300@0
|
1742 connect(used,ring*numSpokes+numSpokes-1,(ring+1)*numSpokes); // wrap to first
|
rt300@0
|
1743 springs[used].setRestLength(0.0);
|
rt300@0
|
1744 used++;
|
rt300@0
|
1745 }
|
rt300@0
|
1746
|
rt300@0
|
1747 // now do \ diag
|
rt300@0
|
1748 for(int ring = 0; ring < numRings-1; ring++){
|
rt300@0
|
1749 connect(used,ring*numSpokes,(ring+1)*numSpokes+numSpokes-1); // wrap first to last
|
rt300@0
|
1750 springs[used].setRestLength(0.0);
|
rt300@0
|
1751 used++;
|
rt300@0
|
1752 for(int spoke = 1; spoke < numSpokes; spoke++){
|
rt300@0
|
1753 connect(used,ring*numSpokes+spoke,(ring+1)*numSpokes+spoke-1); //
|
rt300@0
|
1754 springs[used].setRestLength(0.0);
|
rt300@0
|
1755 used++;
|
rt300@0
|
1756 }
|
rt300@0
|
1757
|
rt300@0
|
1758 }
|
rt300@0
|
1759 cout << "used: " << used << " numSprings: " << numSprings << endl;
|
rt300@0
|
1760
|
rt300@0
|
1761 }
|
rt300@0
|
1762
|
rt300@0
|
1763 //--------------------------------------------------------------
|
rt300@0
|
1764 void SpiderCrossMesh::constrain(double ax, double ay, constrainMode aMode){
|
rt300@0
|
1765 cout << "SpiderCrossMesh spider constrain\n";
|
rt300@0
|
1766
|
rt300@0
|
1767 TwoVector diff;
|
rt300@0
|
1768 int i = 0;
|
rt300@0
|
1769 int startLump = 0;
|
rt300@0
|
1770 // check if lump is within grab range
|
rt300@0
|
1771 switch (aMode) {
|
rt300@0
|
1772 case CONSTRAIN_GRAB_REGION:
|
rt300@4
|
1773 for(i = 0; i<lumps.size(); i++){
|
rt300@0
|
1774
|
rt300@0
|
1775 diff.setCoord(lumps[i].position.x - ax, lumps[i].position.y - ay);
|
rt300@0
|
1776
|
rt300@0
|
1777 if (diff.norm() < GRAB_RANGE){
|
rt300@0
|
1778 lumps[i].constrain();
|
rt300@0
|
1779 }
|
rt300@0
|
1780 }
|
rt300@0
|
1781 break;
|
rt300@0
|
1782 case CONSTRAIN_EDGES:
|
rt300@0
|
1783 {
|
rt300@0
|
1784 // constrain outer ring
|
rt300@0
|
1785 startLump = numSpokes*(numRings-1);
|
rt300@0
|
1786 for(int l = startLump; l < startLump + numSpokes; l++){
|
rt300@0
|
1787 lumps[l].constrain();
|
rt300@0
|
1788 }
|
rt300@0
|
1789
|
rt300@0
|
1790 break;
|
rt300@0
|
1791 }
|
rt300@0
|
1792 case CONSTRAIN_CORNERS:
|
rt300@0
|
1793 // constrain inner ring
|
rt300@0
|
1794
|
rt300@0
|
1795 for(int l = startLump; l < startLump + numSpokes; l++){
|
rt300@0
|
1796 lumps[l].constrain();
|
rt300@0
|
1797 }
|
rt300@0
|
1798
|
rt300@0
|
1799 break;
|
rt300@0
|
1800
|
rt300@0
|
1801 default:
|
rt300@0
|
1802 break;
|
rt300@0
|
1803 }
|
rt300@0
|
1804 }
|
rt300@0
|
1805 //--------------------------------------------------------------
|
rt300@0
|
1806
|
rt300@0
|
1807 void SpiderCrossMesh::makeDefaultScanPath(){
|
rt300@0
|
1808
|
rt300@0
|
1809 cout << "SpiderCrossMesh spider makeDefaultScanPath\n";
|
rt300@0
|
1810
|
rt300@0
|
1811 // add a ring to the path
|
rt300@0
|
1812 int ringNo = floor(numRings/2.0);
|
rt300@0
|
1813 int springno = 0, lumpno = 0;
|
rt300@0
|
1814 for(int i = 0; i < numSpokes; i++){
|
rt300@0
|
1815 lumpno = numSpokes*ringNo + i;
|
rt300@0
|
1816 springno = numSpokes*ringNo + i;
|
rt300@3
|
1817 scanPath.addElement(&lumps[lumpno], &springs[springno]);
|
rt300@0
|
1818 }
|
rt300@0
|
1819 cout << "SpiderCrossMesh spider scan path created on ring " << ringNo << "\n";
|
rt300@0
|
1820
|
rt300@0
|
1821 // add a spoke to the path
|
rt300@0
|
1822 /*
|
rt300@0
|
1823 int springno = 0, lumpno = 0;
|
rt300@0
|
1824
|
rt300@0
|
1825 int springsinrings = numSpokes*numRings;
|
rt300@0
|
1826 for(int i = 0; i < numRings-1; i++){
|
rt300@0
|
1827 lumpno = numSpokes*i; // zero, numspokes etc
|
rt300@0
|
1828 springno = springsinrings + numSpokes*i; // starts from total rings, increments by numspokes etc
|
rt300@3
|
1829 scanPath.addElement(&lumps[lumpno], &springs[springno]);
|
rt300@0
|
1830 }
|
rt300@0
|
1831 */
|
rt300@0
|
1832 }
|
rt300@0
|
1833
|
rt300@0
|
1834 /****************************************/
|
rt300@0
|
1835 // Line Mesh */
|
rt300@0
|
1836 /****************************************/
|
rt300@0
|
1837
|
rt300@0
|
1838 LineMesh::LineMesh(int aNumSegments) : Mesh(){
|
rt300@8
|
1839 meshType = LINE_MESH;
|
rt300@0
|
1840 numSegments = aNumSegments;
|
rt300@0
|
1841 radial = false;
|
rt300@0
|
1842
|
rt300@0
|
1843 makeComponents(aNumSegments, 0);
|
rt300@0
|
1844
|
rt300@0
|
1845 setLumpPositions();
|
rt300@0
|
1846
|
rt300@0
|
1847 makeConnections();
|
rt300@0
|
1848
|
rt300@0
|
1849 makeDefaultScanPath();
|
rt300@0
|
1850
|
rt300@6
|
1851
|
rt300@0
|
1852
|
rt300@0
|
1853 setPropagationSpeed(0.6);
|
rt300@0
|
1854
|
rt300@6
|
1855 for(int i = 0; i < lumps.size(); i++){
|
rt300@6
|
1856 lumps[i].constrain(Lump::CONSTRAIN_X);
|
rt300@6
|
1857 }
|
rt300@6
|
1858
|
rt300@6
|
1859 constrain(0.0,0.0,CONSTRAIN_EDGES);
|
rt300@0
|
1860 cout << "constructed LINE mesh\n";
|
rt300@0
|
1861
|
rt300@0
|
1862 }
|
rt300@0
|
1863 //--------------------------------------------------------------
|
rt300@0
|
1864 void LineMesh::makeComponents(int aDimension1, int aDimension2){
|
rt300@0
|
1865 // make componets creates the correct number of lumps and springs according to dimensions and mesh type
|
rt300@0
|
1866 cout << "Line class makeComponents\n";
|
rt300@0
|
1867 //
|
rt300@0
|
1868 numLumps = numSegments+1;
|
rt300@0
|
1869 numSprings = numSegments;
|
rt300@9
|
1870 Mesh::makeComponents(numLumps, numSprings);
|
rt300@0
|
1871
|
rt300@0
|
1872 }
|
rt300@0
|
1873 //--------------------------------------------------------------
|
rt300@0
|
1874 void LineMesh::setLumpPositions(){
|
rt300@0
|
1875 cout << "LineMesh class setLumpPositions\n";
|
rt300@0
|
1876 //
|
rt300@0
|
1877 double hspacing = (1.0 - 0.05)/numSegments;
|
rt300@4
|
1878 for(int i = 0; i < lumps.size(); i++){
|
rt300@0
|
1879 lumps[i].setPosition(0.025+hspacing*i, 0.5);
|
rt300@0
|
1880 }
|
rt300@0
|
1881 }
|
rt300@0
|
1882 //--------------------------------------------------------------
|
rt300@0
|
1883 void LineMesh::makeConnections(){
|
rt300@0
|
1884 // connects the lmps and springs. the spring needs to know which lumps are at each end
|
rt300@0
|
1885 // and lumps need to know which springs attached
|
rt300@0
|
1886 // calls connect method that does this
|
rt300@0
|
1887 cout << "LineMesh class make connections\n";
|
rt300@0
|
1888 for(int i = 0; i < numSegments; i++){
|
rt300@0
|
1889 connect(i,i);
|
rt300@0
|
1890 connect(i,i+1);
|
rt300@0
|
1891 }
|
rt300@6
|
1892
|
rt300@0
|
1893 }
|
rt300@0
|
1894
|
rt300@0
|
1895 //--------------------------------------------------------------
|
rt300@0
|
1896 void LineMesh::constrain(double ax, double ay, constrainMode aMode){
|
rt300@0
|
1897 cout << "LineMesh class constrain\n";
|
rt300@0
|
1898 if (aMode == CONSTRAIN_EDGES || aMode == CONSTRAIN_CORNERS){
|
rt300@0
|
1899 lumps[0].constrain();
|
rt300@4
|
1900 lumps[lumps.size()-1].constrain();
|
rt300@0
|
1901 }else if (aMode == CONSTRAIN_GRAB_REGION){
|
rt300@0
|
1902 TwoVector diff;
|
rt300@4
|
1903 for(int i = 0; i<lumps.size(); i++){
|
rt300@0
|
1904
|
rt300@0
|
1905 diff.setCoord(lumps[i].position.x - ax, lumps[i].position.y - ay);
|
rt300@0
|
1906
|
rt300@0
|
1907 if (diff.norm() < GRAB_RANGE){
|
rt300@0
|
1908 lumps[i].constrain();
|
rt300@0
|
1909 }
|
rt300@0
|
1910 }
|
rt300@0
|
1911 }
|
rt300@0
|
1912 }
|
rt300@0
|
1913 //--------------------------------------------------------------
|
rt300@0
|
1914 //--------------------------------------------------------------
|
rt300@0
|
1915 void LineMesh::makeDefaultScanPath(){
|
rt300@0
|
1916
|
rt300@0
|
1917 cout << "LineMesh class makeDefaultScanPath\n";
|
rt300@14
|
1918 for(int i = 1; i < numSegments-1; i++){
|
rt300@3
|
1919 scanPath.addElement(&lumps[i], &springs[i]);
|
rt300@0
|
1920 }
|
rt300@0
|
1921 }
|
rt300@0
|
1922 //--------------------------------------------------------------
|
rt300@0
|
1923 /****************************************/
|
rt300@0
|
1924 // GROUNDED LINE Mesh */
|
rt300@0
|
1925 /****************************************/
|
rt300@0
|
1926
|
rt300@0
|
1927 GroundedLineMesh::GroundedLineMesh(int aNumSegments) : Mesh(){
|
rt300@8
|
1928 meshType = GROUNDED_LINE_MESH;
|
rt300@0
|
1929 numSegments = aNumSegments;
|
rt300@0
|
1930 radial = false;
|
rt300@0
|
1931 makeComponents(aNumSegments, 0);
|
rt300@0
|
1932
|
rt300@0
|
1933 setLumpPositions();
|
rt300@0
|
1934
|
rt300@0
|
1935 makeConnections();
|
rt300@0
|
1936
|
rt300@0
|
1937 makeDefaultScanPath();
|
rt300@0
|
1938
|
rt300@0
|
1939 constrain(0.0,0.0,CONSTRAIN_ALL_X);
|
rt300@0
|
1940
|
rt300@0
|
1941 setPropagationSpeed(0.6);
|
rt300@0
|
1942
|
rt300@0
|
1943 cout << "constructed GROUNDED LINE mesh\n";
|
rt300@0
|
1944
|
rt300@0
|
1945 }
|
rt300@0
|
1946 //--------------------------------------------------------------
|
rt300@0
|
1947 void GroundedLineMesh::makeComponents(int aDimension1, int aDimension2){
|
rt300@0
|
1948 // make componets creates the correct number of lumps and springs according to dimensions and mesh type
|
rt300@0
|
1949
|
rt300@0
|
1950 // THIS IS CRAP should be able to just create new ones and attach them...?
|
rt300@0
|
1951 cout << "Line class makeComponents\n";
|
rt300@0
|
1952 //
|
rt300@0
|
1953 numLumps = (numSegments+1)*2;
|
rt300@0
|
1954 numSprings = numSegments*2;
|
rt300@9
|
1955 Mesh::makeComponents(numLumps, numSprings);
|
rt300@0
|
1956
|
rt300@0
|
1957 }
|
rt300@0
|
1958 //--------------------------------------------------------------
|
rt300@0
|
1959 void GroundedLineMesh::setLumpPositions(){
|
rt300@0
|
1960 cout << "LineMesh class setLumpPositions\n";
|
rt300@0
|
1961 //
|
rt300@0
|
1962
|
rt300@0
|
1963 double hspacing = (1.0 - 0.05)/numSegments;
|
rt300@0
|
1964 for(int i = 0; i < (numSegments+1); i++){
|
rt300@0
|
1965 // moving ones
|
rt300@0
|
1966 lumps[i].setPosition(0.025+hspacing*i, 0.5);
|
rt300@0
|
1967 //grounded ones
|
rt300@0
|
1968 lumps[i + numSegments+1].setPosition(0.025+hspacing*i,0.5*cos(i*hspacing*PI) + 0.5 );
|
rt300@0
|
1969 }
|
rt300@0
|
1970
|
rt300@0
|
1971
|
rt300@0
|
1972
|
rt300@0
|
1973 }
|
rt300@0
|
1974 //--------------------------------------------------------------
|
rt300@0
|
1975 void GroundedLineMesh::makeConnections(){
|
rt300@0
|
1976 // connects the lmps and springs. the spring needs to know which lumps are at each end
|
rt300@0
|
1977 // and lumps need to know which springs attached
|
rt300@0
|
1978 // calls connect method that does this
|
rt300@0
|
1979 cout << "LineMesh class make connections\n";
|
rt300@0
|
1980 for(int i = 0; i < numSegments; i++){
|
rt300@0
|
1981 connect(i,i,i+1);
|
rt300@0
|
1982 connect(i + numSegments,i , i + numSegments+1);
|
rt300@0
|
1983
|
rt300@0
|
1984 }
|
rt300@0
|
1985
|
rt300@0
|
1986 setRestLength();
|
rt300@0
|
1987 }
|
rt300@0
|
1988
|
rt300@0
|
1989 //--------------------------------------------------------------
|
rt300@0
|
1990 void GroundedLineMesh::constrain(double ax, double ay, constrainMode aMode){
|
rt300@0
|
1991 cout << "LineMesh class constrain\n";
|
rt300@0
|
1992 if (aMode == CONSTRAIN_EDGES || aMode == CONSTRAIN_CORNERS){
|
rt300@0
|
1993 lumps[0].constrain();
|
rt300@4
|
1994 lumps[lumps.size()-1].constrain();
|
rt300@0
|
1995
|
rt300@4
|
1996 for(int i = numSegments; i < lumps.size(); i++){
|
rt300@0
|
1997 lumps[i].constrain();
|
rt300@0
|
1998 }
|
rt300@0
|
1999 }
|
rt300@0
|
2000
|
rt300@0
|
2001 if (aMode == CONSTRAIN_GRAB_REGION){
|
rt300@0
|
2002 TwoVector diff;
|
rt300@4
|
2003 for(int i = 0; i<lumps.size(); i++){
|
rt300@0
|
2004
|
rt300@0
|
2005 diff.setCoord(lumps[i].position.x - ax, lumps[i].position.y - ay);
|
rt300@0
|
2006
|
rt300@0
|
2007 if (diff.norm() < GRAB_RANGE){
|
rt300@0
|
2008 lumps[i].constrain();
|
rt300@0
|
2009 }
|
rt300@0
|
2010 }
|
rt300@0
|
2011 }
|
rt300@0
|
2012 if (aMode == CONSTRAIN_ALL_X){
|
rt300@0
|
2013
|
rt300@0
|
2014
|
rt300@0
|
2015 for(int i = 0; i<numSegments; i++){
|
rt300@0
|
2016
|
rt300@0
|
2017 lumps[i].constrain(Lump::CONSTRAIN_X);
|
rt300@0
|
2018 }
|
rt300@4
|
2019 for(int i = numSegments; i < lumps.size(); i++){
|
rt300@0
|
2020 lumps[i].constrain();
|
rt300@0
|
2021 }
|
rt300@0
|
2022 lumps[0].constrain();
|
rt300@4
|
2023 lumps[lumps.size()-1].constrain();
|
rt300@0
|
2024 }
|
rt300@0
|
2025
|
rt300@0
|
2026 }
|
rt300@0
|
2027 //--------------------------------------------------------------
|
rt300@0
|
2028 //--------------------------------------------------------------
|
rt300@0
|
2029 void GroundedLineMesh::makeDefaultScanPath(){
|
rt300@0
|
2030
|
rt300@0
|
2031 cout << "LineMesh class makeDefaultScanPath\n";
|
rt300@0
|
2032 for(int i = 0; i < numSegments; i++){
|
rt300@3
|
2033 scanPath.addElement(&lumps[i], &springs[i]);
|
rt300@0
|
2034 }
|
rt300@0
|
2035 }
|
rt300@0
|
2036 //--------------------------------------------------------------
|
rt300@0
|
2037
|
rt300@0
|
2038 /****************************************/
|
rt300@0
|
2039 // DROPLET Mesh */
|
rt300@0
|
2040 /****************************************/
|
rt300@0
|
2041 // more of a balloon really - filled with compressible gas
|
rt300@0
|
2042 DropletMesh::DropletMesh(int aNumSegments) : Mesh(){
|
rt300@8
|
2043 meshType = DROPLET_MESH;
|
rt300@0
|
2044 restArea = 1.0;
|
rt300@0
|
2045 radial = true;
|
rt300@0
|
2046 numSegments = aNumSegments;
|
rt300@0
|
2047
|
rt300@0
|
2048 makeComponents(aNumSegments, 0);
|
rt300@0
|
2049
|
rt300@0
|
2050 setLumpPositions();
|
rt300@0
|
2051
|
rt300@0
|
2052 makeConnections();
|
rt300@0
|
2053
|
rt300@0
|
2054 makeDefaultScanPath();
|
rt300@0
|
2055
|
rt300@0
|
2056 //constrain(0.0,0.0,CONSTRAIN_EDGES);
|
rt300@0
|
2057
|
rt300@0
|
2058 setPropagationSpeed(0.8);
|
rt300@0
|
2059
|
rt300@0
|
2060 zeroRestLength();
|
rt300@0
|
2061 globalForces.pressureAmt = 0.4;
|
rt300@0
|
2062
|
rt300@0
|
2063 cout << "constructed DropletMesh mesh\n";
|
rt300@0
|
2064
|
rt300@0
|
2065 }
|
rt300@0
|
2066 //--------------------------------------------------------------
|
rt300@0
|
2067 void DropletMesh::makeComponents(int aDimension1, int aDimension2){
|
rt300@0
|
2068 // make componets creates the correct number of lumps and springs according to dimensions and mesh type
|
rt300@0
|
2069 cout << "Line class makeComponents\n";
|
rt300@0
|
2070 //
|
rt300@0
|
2071 numLumps = numSegments;
|
rt300@0
|
2072 numSprings = numSegments;
|
rt300@9
|
2073 Mesh::makeComponents(numLumps, numSprings);
|
rt300@0
|
2074 }
|
rt300@0
|
2075 //--------------------------------------------------------------
|
rt300@0
|
2076 void DropletMesh::setLumpPositions(){
|
rt300@0
|
2077 cout << "DropletMesh class setLumpPositions\n";
|
rt300@0
|
2078 // make a circle centred around 0.5,0.5 radius 0.4
|
rt300@0
|
2079 int l = 0;
|
rt300@0
|
2080 double hyplen,xpos,ypos;
|
rt300@0
|
2081
|
rt300@0
|
2082 double * cosines = new double[numSegments];
|
rt300@0
|
2083 double * sines = new double[numSegments];
|
rt300@0
|
2084 double angle = 2 * PI / numSegments;
|
rt300@0
|
2085
|
rt300@0
|
2086 for(int spoke = 0; spoke < numSegments; spoke++){
|
rt300@0
|
2087 cosines[spoke] = cos(angle*spoke);
|
rt300@0
|
2088 sines[spoke] = sin(angle*spoke);
|
rt300@0
|
2089 }
|
rt300@0
|
2090
|
rt300@0
|
2091 hyplen = 0.2; // aka radius
|
rt300@0
|
2092
|
rt300@0
|
2093 //
|
rt300@0
|
2094 //lumps[0].setPosition(0.5,0.5);
|
rt300@0
|
2095
|
rt300@0
|
2096 for(int spoke = 0; spoke < numSegments; spoke++){
|
rt300@0
|
2097
|
rt300@0
|
2098 xpos = hyplen * cosines[spoke] + 0.5;
|
rt300@0
|
2099 ypos = hyplen*sines[spoke] + 0.5;
|
rt300@0
|
2100 lumps[l].setPosition(xpos,ypos);
|
rt300@0
|
2101 l++;
|
rt300@0
|
2102
|
rt300@0
|
2103 }
|
rt300@0
|
2104 calculateCentre();
|
rt300@0
|
2105 restArea = calculateArea() * 3; // this is like the amount of air in there originally, inflate a bit !
|
rt300@0
|
2106
|
rt300@0
|
2107 delete [] cosines;
|
rt300@0
|
2108 delete [] sines;
|
rt300@0
|
2109 }
|
rt300@0
|
2110 //--------------------------------------------------------------
|
rt300@0
|
2111 void DropletMesh::makeConnections(){
|
rt300@0
|
2112 // connects the lmps and springs. the spring needs to know which lumps are at each end
|
rt300@0
|
2113 // and lumps need to know which springs attached
|
rt300@0
|
2114 // calls connect method that does this
|
rt300@0
|
2115 cout << "DropletMesh class make connections\n";
|
rt300@0
|
2116 for(int i = 0; i < numSegments-1; i++){
|
rt300@0
|
2117 connect(i,i,i+1);
|
rt300@0
|
2118 }
|
rt300@0
|
2119 // finally connect end spring to start lump
|
rt300@0
|
2120 connect(numSegments-1,numSegments-1);
|
rt300@0
|
2121 connect(numSegments-1,0);
|
rt300@0
|
2122 }
|
rt300@0
|
2123
|
rt300@0
|
2124 //--------------------------------------------------------------
|
rt300@0
|
2125 void DropletMesh::constrain(double ax, double ay, constrainMode aMode){
|
rt300@0
|
2126 cout << "DropletMesh class constrain\n";
|
rt300@0
|
2127 if (aMode == CONSTRAIN_EDGES || aMode == CONSTRAIN_CORNERS){
|
rt300@0
|
2128 lumps[0].constrain();
|
rt300@4
|
2129 lumps[lumps.size()-1].constrain();
|
rt300@0
|
2130 } else if (aMode == CONSTRAIN_GRAB_REGION){
|
rt300@0
|
2131 TwoVector diff;
|
rt300@4
|
2132 for(int i = 0; i<lumps.size(); i++){
|
rt300@0
|
2133
|
rt300@0
|
2134 diff.setCoord(lumps[i].position.x - ax, lumps[i].position.y - ay);
|
rt300@0
|
2135
|
rt300@0
|
2136 if (diff.norm() < GRAB_RANGE){
|
rt300@0
|
2137 lumps[i].constrain();
|
rt300@0
|
2138 }
|
rt300@0
|
2139 }
|
rt300@0
|
2140 }
|
rt300@0
|
2141 }
|
rt300@0
|
2142 //--------------------------------------------------------------
|
rt300@0
|
2143 //--------------------------------------------------------------
|
rt300@0
|
2144 void DropletMesh::makeDefaultScanPath(){
|
rt300@0
|
2145
|
rt300@0
|
2146 cout << "DropletMesh class makeDefaultScanPath\n";
|
rt300@0
|
2147 for(int i = 0; i < numSegments; i++){
|
rt300@3
|
2148 scanPath.addElement(&lumps[i], &springs[i]);
|
rt300@0
|
2149 }
|
rt300@0
|
2150 cout << "DropletMesh class makeDefaultScanPath\n";
|
rt300@0
|
2151 }
|
rt300@0
|
2152 //--------------------------------------------------------------
|
rt300@0
|
2153 double DropletMesh::calculateArea(){
|
rt300@0
|
2154
|
rt300@0
|
2155 // how do we calculate area?? answer: average all radii !
|
rt300@0
|
2156
|
rt300@0
|
2157 // calc average radius magnitude
|
rt300@0
|
2158 double radiusMag = 0.0, avRadiusMag = 0.0;
|
rt300@4
|
2159 for(int i = 0; i < lumps.size(); i++){
|
rt300@0
|
2160 TwoVector radius;
|
rt300@0
|
2161 radius.setCoord(centre.x - lumps[i].position.x, centre.y - lumps[i].position.y );
|
rt300@0
|
2162 radiusMag = radius.norm();
|
rt300@0
|
2163 avRadiusMag += radiusMag;
|
rt300@0
|
2164 }
|
rt300@4
|
2165 avRadiusMag /= lumps.size();
|
rt300@0
|
2166
|
rt300@0
|
2167 // calc area
|
rt300@0
|
2168 double area = 2 * PI * avRadiusMag*avRadiusMag;
|
rt300@0
|
2169
|
rt300@0
|
2170 return area;
|
rt300@0
|
2171
|
rt300@0
|
2172 }
|
rt300@0
|
2173
|
rt300@0
|
2174 double DropletMesh::calculatePressure(){
|
rt300@0
|
2175 // work out pressure on the springs.
|
rt300@0
|
2176 // this will be proportional to the difference in the rest area to the current area
|
rt300@0
|
2177 //this will exert a force proportional to length
|
rt300@0
|
2178
|
rt300@0
|
2179 double da = restArea - calculateArea();
|
rt300@0
|
2180 // if current area is smaller this will create positive pressure
|
rt300@0
|
2181
|
rt300@0
|
2182 globalForces.setPressure(da);
|
rt300@0
|
2183 return globalForces.pressure;
|
rt300@0
|
2184
|
rt300@0
|
2185 }
|
rt300@0
|
2186 //--------------------------------------------------------------
|
rt300@0
|
2187 void DropletMesh::update(){
|
rt300@0
|
2188
|
rt300@0
|
2189 calculateCentre();
|
rt300@0
|
2190 calculatePressure();
|
rt300@0
|
2191 Mesh::update(); // schweet
|
rt300@0
|
2192
|
rt300@0
|
2193 }
|
rt300@0
|
2194 //--------------------------------------------------------------
|
rt300@0
|
2195
|
rt300@0
|
2196 /****************************************/
|
rt300@0
|
2197 // TriangleMesh */
|
rt300@0
|
2198 /****************************************/
|
rt300@0
|
2199 //--------------------------------------------------------------
|
rt300@0
|
2200 TriangleMesh::TriangleMesh(int height, int width): Mesh() {
|
rt300@8
|
2201 meshType = TRIANGLE_MESH;
|
rt300@0
|
2202 radial = false;
|
rt300@0
|
2203 makeComponents(height, width);
|
rt300@0
|
2204
|
rt300@0
|
2205 setLumpPositions();
|
rt300@0
|
2206
|
rt300@0
|
2207 makeConnections();
|
rt300@0
|
2208
|
rt300@0
|
2209 makeDefaultScanPath();
|
rt300@0
|
2210
|
rt300@0
|
2211 constrain(0,0,CONSTRAIN_EDGES);
|
rt300@0
|
2212
|
rt300@0
|
2213 zeroRestLength();
|
rt300@1
|
2214
|
rt300@0
|
2215
|
rt300@0
|
2216 cout << "constructing TRIANGLE mesh\n";
|
rt300@0
|
2217 }
|
rt300@0
|
2218 //--------------------------------------------------------------
|
rt300@0
|
2219 // make componets for tri
|
rt300@0
|
2220 void TriangleMesh::makeComponents(int aheight, int awidth){
|
rt300@0
|
2221 height = aheight;
|
rt300@0
|
2222 width = awidth;
|
rt300@0
|
2223 numLumps = height * width;
|
rt300@0
|
2224 /* horz --- \ diag / diag */
|
rt300@0
|
2225 numSprings = (width-1) * (height-1) + width * (height - 1) + (width-1) * (height - 1);
|
rt300@0
|
2226
|
rt300@9
|
2227 Mesh::makeComponents(numLumps, numSprings);
|
rt300@0
|
2228 }
|
rt300@0
|
2229
|
rt300@0
|
2230 //--------------------------------------------------------------
|
rt300@0
|
2231 void TriangleMesh::setLumpPositions(){
|
rt300@0
|
2232 double vspacing = 1.0/(height-1);
|
rt300@0
|
2233 double hspacing = 1.0/(width - 0.5);
|
rt300@0
|
2234 int i =0;
|
rt300@0
|
2235 // set positions
|
rt300@0
|
2236 for(int row = 0; row < height; row++){ // go down column
|
rt300@0
|
2237 for(int col = 0;col < width; col++){ // go along row
|
rt300@0
|
2238 // if even row start from wall
|
rt300@0
|
2239 if(row%2){ // odd
|
rt300@0
|
2240 lumps[i].setPosition(hspacing*col + 0.5*hspacing,vspacing*row);
|
rt300@0
|
2241 }else{ // even
|
rt300@0
|
2242 lumps[i].setPosition(hspacing*col,vspacing*row);
|
rt300@0
|
2243 }
|
rt300@0
|
2244 i++;
|
rt300@0
|
2245 }
|
rt300@0
|
2246 }
|
rt300@0
|
2247 }
|
rt300@0
|
2248 //--------------------------------------------------------------
|
rt300@0
|
2249 void TriangleMesh::makeConnections(){
|
rt300@0
|
2250
|
rt300@0
|
2251 // could be cleverer in terms of numbering?
|
rt300@0
|
2252 int lumpnum = 0;
|
rt300@0
|
2253 int springnum = 0;
|
rt300@0
|
2254
|
rt300@0
|
2255 // attach horizontal a
|
rt300@0
|
2256 for ( int row=1;row< height;row++){
|
rt300@0
|
2257 for(int col=0;col<width-1;col++){
|
rt300@0
|
2258 connect(springnum,lumpnum,lumpnum+1);
|
rt300@0
|
2259 lumpnum++;
|
rt300@0
|
2260 springnum++;
|
rt300@0
|
2261 }
|
rt300@0
|
2262 lumpnum++;
|
rt300@0
|
2263 }
|
rt300@0
|
2264
|
rt300@0
|
2265 /* now do /\/\/\/\/\/\/\ */
|
rt300@0
|
2266 lumpnum = 0;
|
rt300@0
|
2267 for ( int row=0;row<height-1;row++){
|
rt300@0
|
2268
|
rt300@0
|
2269 if(row%2 == 0){
|
rt300@0
|
2270 // even ie 0
|
rt300@0
|
2271 /* start with \ diag */
|
rt300@0
|
2272 for(int col=0;col<width-1;col++){
|
rt300@0
|
2273 /* \ */
|
rt300@0
|
2274 connect(springnum++, lumpnum, lumpnum+ width);
|
rt300@0
|
2275 lumpnum++;
|
rt300@0
|
2276 /* / */
|
rt300@0
|
2277 connect(springnum++, lumpnum, lumpnum+(width-1));
|
rt300@0
|
2278
|
rt300@0
|
2279 }
|
rt300@0
|
2280 connect(springnum++, lumpnum, lumpnum+width);
|
rt300@0
|
2281 lumpnum++;
|
rt300@0
|
2282
|
rt300@0
|
2283 }else{ // odd
|
rt300@0
|
2284 for(int col=0;col<width-1;col++){
|
rt300@0
|
2285 /* / */
|
rt300@0
|
2286 connect(springnum++, lumpnum, lumpnum+ width);
|
rt300@0
|
2287 /* \ */
|
rt300@0
|
2288 connect(springnum++, lumpnum, lumpnum+(width+1));
|
rt300@0
|
2289 lumpnum++;
|
rt300@0
|
2290 }
|
rt300@0
|
2291 // last r to l
|
rt300@0
|
2292 /* / */
|
rt300@0
|
2293 connect(springnum++, lumpnum, lumpnum+(width));
|
rt300@0
|
2294 lumpnum++;
|
rt300@0
|
2295
|
rt300@0
|
2296 }
|
rt300@0
|
2297 }
|
rt300@0
|
2298
|
rt300@0
|
2299 }
|
rt300@0
|
2300
|
rt300@0
|
2301
|
rt300@0
|
2302
|
rt300@0
|
2303 //--------------------------------------------------------------
|
rt300@0
|
2304 void TriangleMesh::constrain(double ax, double ay, constrainMode aMode){
|
rt300@0
|
2305 // exactly the same as square
|
rt300@0
|
2306 TwoVector diff;
|
rt300@0
|
2307 int i = 0;
|
rt300@0
|
2308
|
rt300@0
|
2309 // check if lump is within grab range
|
rt300@0
|
2310 switch (aMode) {
|
rt300@0
|
2311 case CONSTRAIN_GRAB_REGION:
|
rt300@4
|
2312 for(i = 0; i<lumps.size(); i++){
|
rt300@0
|
2313
|
rt300@0
|
2314 diff.setCoord(lumps[i].position.x - ax, lumps[i].position.y - ay);
|
rt300@0
|
2315
|
rt300@0
|
2316 if (diff.norm() < GRAB_RANGE){
|
rt300@0
|
2317 lumps[i].constrain();
|
rt300@0
|
2318 }
|
rt300@0
|
2319 }
|
rt300@0
|
2320 break;
|
rt300@0
|
2321 case CONSTRAIN_EDGES:
|
rt300@0
|
2322 i = 0;
|
rt300@0
|
2323 for(int row = 0; row < height; row++){ // go down column
|
rt300@0
|
2324 for(int col = 0;col < width; col++){ // go along row
|
rt300@0
|
2325 if(row == 0 || row == height-1 || col == 0 || col == width-1){
|
rt300@0
|
2326 lumps[i].constrain();
|
rt300@0
|
2327 }
|
rt300@0
|
2328 i++;
|
rt300@0
|
2329 }
|
rt300@0
|
2330 }
|
rt300@0
|
2331 break;
|
rt300@0
|
2332 case CONSTRAIN_CORNERS:
|
rt300@0
|
2333 i = 0;
|
rt300@0
|
2334 for(int row = 0; row < height; row++){ // go down column
|
rt300@0
|
2335 for(int col = 0;col < width; col++){ // go along row
|
rt300@0
|
2336 if( (row == 0 && col == 0)
|
rt300@0
|
2337 || (row == height-1 && col == 0)
|
rt300@0
|
2338 || (row == 0 && col == width-1)
|
rt300@0
|
2339 || (row == height-1 && col == width-1)){
|
rt300@0
|
2340 lumps[i].constrain();
|
rt300@0
|
2341 }
|
rt300@0
|
2342 i++;
|
rt300@0
|
2343 }
|
rt300@0
|
2344 }
|
rt300@0
|
2345 break;
|
rt300@0
|
2346
|
rt300@0
|
2347 default:
|
rt300@0
|
2348 break;
|
rt300@0
|
2349 }
|
rt300@0
|
2350
|
rt300@0
|
2351 }
|
rt300@0
|
2352 //--------------------------------------------------------------
|
rt300@0
|
2353 //--------------------------------------------------------------
|
rt300@0
|
2354 void TriangleMesh::makeDefaultScanPath(){
|
rt300@0
|
2355
|
rt300@0
|
2356 int vmarg = 4;
|
rt300@0
|
2357 int hmarg = 4;
|
rt300@0
|
2358
|
rt300@0
|
2359 int lumpno = vmarg * width + hmarg; // top left corner
|
rt300@0
|
2360 int springno = vmarg * (width - 1) + hmarg;
|
rt300@0
|
2361 // do top horz
|
rt300@0
|
2362 for(int i = 0; i < width - 2*hmarg; i++){
|
rt300@3
|
2363 scanPath.addElement(&lumps[lumpno], &springs[springno]);
|
rt300@0
|
2364 lumpno++;
|
rt300@0
|
2365 springno++;
|
rt300@0
|
2366 }
|
rt300@0
|
2367
|
rt300@0
|
2368
|
rt300@0
|
2369 }
|
rt300@0
|
2370
|