~jil26/fabathome-model1/FabInterpreter

« back to all changes in this revision

Viewing changes to software/projects/FabStudio v0/Fab@Home Studio/Tool.cpp

  • Committer: jil26
  • Date: 2010-03-17 09:27:31 UTC
  • Revision ID: svn-v4:02918aed-e80b-b844-b231-15c4a9332dc2:trunk:7
Added FabStudio v0 to the repository

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
f/*License Notification
 
2
Fab@Home operates under the BSD Open Source License
 
3
 
 
4
Copyright (c) 2006, Hod Lipson and Evan Malone (evan.malone@cornell.edu) All rights reserved. 
 
5
 
 
6
Redistribution and use in source and binary forms, with or without modification, 
 
7
are permitted provided that the following conditions are met: 
 
8
 
 
9
Redistributions of source code must retain the above copyright notice, 
 
10
this list of conditions and the following disclaimer. 
 
11
Redistributions in binary form must reproduce the above copyright notice, 
 
12
this list of conditions and the following disclaimer in the documentation and/or 
 
13
other materials provided with the distribution. 
 
14
Neither the name of the Fab@Home Project nor the names of its contributors may be 
 
15
used to endorse or promote products derived from this software without specific 
 
16
prior written permission. 
 
17
 
 
18
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
 
19
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 
20
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
 
21
IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
 
22
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
 
23
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
 
24
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 
25
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
 
26
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
 
27
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
28
*/
 
29
 
 
30
// Tool.cpp: implementation of the CTool class.
 
31
//
 
32
//////////////////////////////////////////////////////////////////////
 
33
 
 
34
#include "StdAfx.h"
 
35
#include "Tool.h"
 
36
 
 
37
#ifdef _DEBUG
 
38
#undef THIS_FILE
 
39
static char THIS_FILE[]=__FILE__;
 
40
#define new DEBUG_NEW
 
41
#endif
 
42
 
 
43
//////////////////////////////////////////////////////////////////////
 
44
// Construction/Destruction
 
45
//////////////////////////////////////////////////////////////////////
 
46
 
 
47
//---------------------------------------------------------------------------
 
48
CTool::CTool()
 
49
//---------------------------------------------------------------------------
 
50
{
 
51
 
 
52
        SetDefaults();
 
53
}
 
54
 
 
55
//---------------------------------------------------------------------------
 
56
CTool::~CTool()
 
57
//---------------------------------------------------------------------------
 
58
{
 
59
 
 
60
}
 
61
 
 
62
//---------------------------------------------------------------------------
 
63
CTool::CTool(CTool& s)
 
64
//---------------------------------------------------------------------------
 
65
{
 
66
        *this = s;
 
67
}
 
68
 
 
69
//---------------------------------------------------------------------------
 
70
CTool& CTool::operator=(const CTool& s)
 
71
//---------------------------------------------------------------------------
 
72
{// copy tool object
 
73
 
 
74
        m_bIsMounted = s.m_bIsMounted;
 
75
        name = s.name;
 
76
        description = s.description;
 
77
        maxvolume = s.maxvolume;
 
78
        currentvolume = s.currentvolume;
 
79
        pathwidth = s.pathwidth;
 
80
        pathheight = s.pathheight;
 
81
        backfill = s.backfill;
 
82
        tip = s.tip;
 
83
        tooloffset = s.tooloffset;
 
84
        barreloffset = s.barreloffset;
 
85
        tipoffset = s.tipoffset;
 
86
        plungeroffset = s.plungeroffset;
 
87
        toolgeom = s.toolgeom;
 
88
        plungergeom = s.plungergeom;
 
89
        barrelgeom = s.barrelgeom;
 
90
        tipgeom = s.tipgeom;
 
91
        toolcolor = s.toolcolor;
 
92
        plungercolor = s.plungercolor;
 
93
        barrelcolor = s.barrelcolor;
 
94
        tipcolor = s.tipcolor;
 
95
        toolalpha = s.toolalpha;
 
96
        plungeralpha = s.plungeralpha;
 
97
        tipalpha = s.tipalpha;
 
98
        barrelalpha = s.barrelalpha;
 
99
        disprate = s.disprate;
 
100
        dir = s.dir;
 
101
        mmps = s.mmps;
 
102
        axis = s.axis;
 
103
        axisDir = s.axisDir;
 
104
        curstep=s.curstep;
 
105
        cmdstep=s.cmdstep;
 
106
        rangemin=s.rangemin;
 
107
        rangemax=s.rangemax;
 
108
        stepstomove=s.stepstomove;
 
109
        bottompos=s.bottompos;
 
110
        unloadpos=s.unloadpos;
 
111
        pushout=s.pushout;
 
112
        suckback = s.suckback;
 
113
        suckbackDelay = s.suckbackDelay;
 
114
        //posLimitSwitch = s.posLimitSwitch;
 
115
        //negLimitSwitch = s.negLimitSwitch;
 
116
        jogIncrement = s.jogIncrement;
 
117
        clearance = s.clearance;
 
118
        pathspeed = s.pathspeed;
 
119
        jogspeed = s.jogspeed;
 
120
        m_dTipID = s.m_dTipID;
 
121
        m_dBarrelID = s.m_dBarrelID;
 
122
        m_dVolNeeded = s.m_dVolNeeded;
 
123
        m_nPausePathCount = s.m_nPausePathCount;
 
124
        m_dMinPathLength = s.m_dMinPathLength;
 
125
        return *this;
 
126
}
 
127
 
 
128
 
 
129
//---------------------------------------------------------------------------
 
130
CString CTool::GetDescription()
 
131
//---------------------------------------------------------------------------
 
132
{ // Get textual description of tool (of parameters user might care about)
 
133
 
 
134
        CString desc, line;
 
135
 
 
136
        line.Format("Description:\t%s\n", description);
 
137
        desc += line;
 
138
 
 
139
        line.Format("Path width:\t%.3fmm\n", pathwidth);
 
140
        desc += line;
 
141
 
 
142
        line.Format("Layer Thickness:\t%.3fmm\n", pathheight);
 
143
        desc += line;
 
144
 
 
145
        line.Format("Path speed:\t%.3fmm/s\n", pathspeed);
 
146
        return desc;
 
147
}
 
148
 
 
149
//---------------------------------------------------------------------------
 
150
bool CTool::RequestPause(int pathCnt)
 
151
//---------------------------------------------------------------------------
 
152
{
 
153
        //return true if auto pause is desirable
 
154
        if(m_nPausePathCount <= 0) return false;
 
155
        return (pathCnt > m_nPausePathCount);
 
156
}
 
157
 
 
158
//---------------------------------------------------------------------------
 
159
void CTool::SetPausePathCount(int count)
 
160
//---------------------------------------------------------------------------
 
161
{
 
162
        //number of paths after which an automatic pause will be triggered
 
163
        if(count > 1)
 
164
                m_nPausePathCount = count;
 
165
        else
 
166
                m_nPausePathCount = 0; //zero means never auto pause
 
167
}
 
168
 
 
169
//---------------------------------------------------------------------------
 
170
double CTool::GetPathspeed()
 
171
//---------------------------------------------------------------------------
 
172
{
 
173
        //get the current commanded build path tangential speed for this tool
 
174
        return pathspeed;
 
175
}
 
176
 
 
177
//---------------------------------------------------------------------------
 
178
bool CTool::SetPathspeed(double spd)
 
179
//---------------------------------------------------------------------------
 
180
{
 
181
        //set the current commanded build path tangential speed for this tool
 
182
        //return true if value is acceptable
 
183
        if( (spd<0) || (spd>MAX_STEP_FREQ*mmps)) return false;
 
184
        pathspeed = spd;
 
185
        return true;
 
186
}
 
187
 
 
188
//---------------------------------------------------------------------------
 
189
double CTool::GetJogspeed()
 
190
//---------------------------------------------------------------------------
 
191
{
 
192
        //get the current commanded jog speed (in Hz) for this tool
 
193
        return jogspeed;
 
194
}
 
195
 
 
196
//---------------------------------------------------------------------------
 
197
bool CTool::SetJogspeed(double spd)
 
198
//---------------------------------------------------------------------------
 
199
{
 
200
        //set the current commanded jog speed for this tool (in Hz)
 
201
        //return true if value is acceptable
 
202
        if( (spd<0) || (spd>MAX_STEP_FREQ)) return false;
 
203
        jogspeed = spd;
 
204
        return true;
 
205
}
 
206
 
 
207
//---------------------------------------------------------------------------
 
208
double CTool::GetVolumeFlowrate()
 
209
//---------------------------------------------------------------------------
 
210
{
 
211
        //return the average volumetric flowrate (estimated)
 
212
        //per unit length of path traversed, mm^3/mm
 
213
        return (disprate*GetBarrelXSection());
 
214
}
 
215
 
 
216
//---------------------------------------------------------------------------
 
217
double CTool::GetLinearFlowrate()
 
218
//---------------------------------------------------------------------------
 
219
{
 
220
        //return the average linear extrusion flowrate (estimated)
 
221
        //per unit length of path traversed, mm/mm
 
222
        return (GetVolumeFlowrate()/GetTipXSection());
 
223
}
 
224
 
 
225
//---------------------------------------------------------------------------
 
226
double CTool::GetPathXSection()
 
227
//---------------------------------------------------------------------------
 
228
{
 
229
        //estimate path crosssection as ellipse from deposition parameters
 
230
        //return value in mm^2
 
231
        return (3.1415926*pathwidth*pathheight/4.0);
 
232
}
 
233
 
 
234
//---------------------------------------------------------------------------
 
235
double CTool::GetTipXSection()
 
236
//---------------------------------------------------------------------------
 
237
{
 
238
        //return the (interior) cross section area of the tip, mm^2
 
239
        return(3.1415926*m_dTipID*m_dTipID/4.0);
 
240
}
 
241
 
 
242
//---------------------------------------------------------------------------
 
243
double CTool::GetBarrelXSection()
 
244
//---------------------------------------------------------------------------
 
245
{
 
246
        //return the (interior) cross section area of the syringe barrel, mm^2
 
247
        return(3.1415926*m_dBarrelID*m_dBarrelID/4.0);
 
248
}
 
249
 
 
250
//---------------------------------------------------------------------------
 
251
bool CTool::LoadFile(CString toolfilename, CString& errorstr, bool loadgeom)
 
252
//---------------------------------------------------------------------------
 
253
{ // read tool parameters from asci file
 
254
 
 
255
        SetDefaults();
 
256
 
 
257
        CStdioFile file;
 
258
        if (file.Open(toolfilename, CFile::modeRead) == 0)
 
259
                return false;
 
260
 
 
261
        CString line, filename = toolfilename;
 
262
        BOOL readok;
 
263
        CString error;
 
264
        int idx = 0;
 
265
 
 
266
        //get the name from the file name
 
267
        //strip off the directory info
 
268
        while((idx=filename.Find('\\')) != -1)
 
269
        {
 
270
                filename = filename.Right(filename.GetLength()-idx-1);
 
271
        }
 
272
        name = filename;
 
273
 
 
274
        do {
 
275
                readok = file.ReadString(line);
 
276
                line.Trim();
 
277
                if (readok && !line.IsEmpty() && !(line[0]=='#')  && !(line[0]=='/') && !(line[0]=='%') && !(line[0]==';')) {
 
278
                        CString str1 = line.SpanExcluding(" \t,:");
 
279
                        CString str1a = line.Mid(str1.GetLength());
 
280
                        CString str1b = str1a.SpanIncluding(" \t,:");
 
281
                        CString str2 = str1a.Mid(str1b.GetLength());
 
282
                        str1.Trim();
 
283
                        str2.Trim();
 
284
                        if (!str1.IsEmpty()) {
 
285
                                if (str1.CompareNoCase("DESCRIPTION")==0) {
 
286
                                        description = str2;
 
287
                                } else if (str1.CompareNoCase("PATHWIDTH")==0) {
 
288
                                        pathwidth = atof(str2);
 
289
                                        if (pathwidth < 0.01 && pathwidth > 20) {
 
290
                                                error.Format("Path width %.2f [mm] is unreasonable in file\n%s\n", pathwidth, toolfilename);
 
291
                                                errorstr += error;
 
292
                                                return false;
 
293
                                        }
 
294
                                }
 
295
                                // 04-18-2008: fix for name of the parameter
 
296
                                else if (str1.CompareNoCase("BACKFILL")==0) {
 
297
                                        backfill = atof(str2);
 
298
                                        if (backfill < 0.01 && backfill > 20) {
 
299
                                                error.Format("Backfill parameter %.2f [mm] is unreasonable in file\n%s\n", pathwidth, toolfilename);
 
300
                                                errorstr += error;
 
301
                                                return false;
 
302
                                        }
 
303
                                } else if (str1.CompareNoCase("PUSHOUT")==0) {
 
304
                                        str2.Replace(","," ");
 
305
                                        int j=sscanf_s(str2,"%lf", &pushout);
 
306
                                        if (j != 1) {
 
307
                                                error.Format("%s: Cannot read predispensing parameters '%s'\n", toolfilename, line);
 
308
                                                errorstr += error;
 
309
                                                pushout = 0;
 
310
                                                return false;
 
311
                                        }
 
312
                                } else if (str1.CompareNoCase("SUCKBACK")==0) {
 
313
                                        str2.Replace(","," ");
 
314
                                        int j=sscanf_s(str2,"%lf", &suckback);
 
315
                                        if (j != 1) {
 
316
                                                error.Format("%s: Cannot read suck-back parameters '%s'\n", toolfilename, line);
 
317
                                                errorstr += error;
 
318
                                                suckback = 0;
 
319
                                                return false;
 
320
                                        }
 
321
                                } else if (str1.CompareNoCase("SUCKBACKDELAY")==0) {
 
322
                                        str2.Replace(","," ");
 
323
                                        int j=sscanf_s(str2,"%lf", &suckbackDelay);
 
324
                                        if ((j != 1)||(suckbackDelay < 0)||(suckbackDelay>suckback)) {
 
325
                                                error.Format("%s: SUCKBACKDELAY '%s' should be positive and smaller than SUCKBACK\n", toolfilename, line);
 
326
                                                errorstr += error;
 
327
                                                suckbackDelay = 0;
 
328
                                                return false;
 
329
                                        }
 
330
                                } else if (str1.CompareNoCase("DIRECTION")==0) {
 
331
                                        str2.Replace(","," ");
 
332
                                        int j=sscanf_s(str2,"%lf %lf %lf", 
 
333
                                                &dir.x, &dir.y, &dir.z);
 
334
                                        if (j != 3) {
 
335
                                                error.Format("%s: Cannot read graphics direction parameters '%s'\n", toolfilename, line);
 
336
                                                errorstr += error;
 
337
                                                dir = CVec(0,0,-1);
 
338
                                                return false;
 
339
                                        }
 
340
                                } else if (str1.CompareNoCase("MOTOR")==0) {
 
341
                                        str2.Replace(","," ");
 
342
                                        int j=sscanf_s(str2,"%ld %ld %lf", 
 
343
                                                &axis, &axisDir, &mmps);
 
344
                                        if (j != 3) {
 
345
                                                error.Format("%s: Cannot read tool motor parameters '%s'\n", toolfilename, line);
 
346
                                                errorstr += error;
 
347
                                                return false;
 
348
                                        }
 
349
                                } else if (str1.CompareNoCase("VOLUME")==0) {
 
350
                                        maxvolume = atof(str2);
 
351
                                        if (maxvolume < 1 && maxvolume > 100) {
 
352
                                                error.Format("Volume parameter %.2f [cc] is unreasonable in file\n%s\n", maxvolume, toolfilename);
 
353
                                                errorstr += error;
 
354
                                                maxvolume = 10;
 
355
                                                return false;
 
356
                                        }
 
357
                                } else if (str1.CompareNoCase("DEPOSITIONRATE")==0) {
 
358
                                        disprate = atof(str2);
 
359
                                        if (disprate < 0.0000001 && disprate > 1000) {
 
360
                                                error.Format("Dispensing rate parameter %.2f [mm^2] is unreasonable in file\n%s\n", disprate, toolfilename);
 
361
                                                errorstr += error;
 
362
                                                disprate = 2;
 
363
                                                return false;
 
364
                                        }
 
365
                                } else if (str1.CompareNoCase("PATHHEIGHT")==0) {
 
366
                                        pathheight = atof(str2);
 
367
                                        if (pathheight < 0.001 && pathheight > 20) {
 
368
                                                error.Format("Path Height %.2f [mm] is unreasonable in file\n%s\n", pathwidth, toolfilename);
 
369
                                                errorstr += error;
 
370
                                                return false;
 
371
                                        }
 
372
                                } else if (str1.CompareNoCase("RANGE")==0) {
 
373
                                        str2.Replace(","," ");
 
374
                                        int j=sscanf_s(str2,"%lf %lf %lf", &rangemin, &rangemax, &unloadpos);
 
375
                                        if (j != 3) {
 
376
                                                error.Format("%s: Cannot read range parameters '%s'\n", toolfilename, line);
 
377
                                                errorstr += error;
 
378
                                                rangemin = 0;
 
379
                                                rangemax = 100;
 
380
                                                curstep = 0;
 
381
                                        }
 
382
                                } else if (str1.CompareNoCase("TIPPOINT")==0) {
 
383
                                        str2.Replace(","," ");
 
384
                                        int j=sscanf_s(str2,"%lf %lf %lf", &tip.x, &tip.y, &tip.z);
 
385
                                        if (j != 3) {
 
386
                                                error.Format("%s: Cannot read tip coordinates '%s'\n", toolfilename, line);
 
387
                                                errorstr += error;
 
388
                                                tip = CVec(0,0,0);
 
389
                                                return false;
 
390
                                        }
 
391
                                } else if (str1.CompareNoCase("TOOLOFFSET")==0) {
 
392
                                        str2.Replace(","," ");
 
393
                                        int j=sscanf_s(str2,"%lf %lf %lf", &tooloffset.x, &tooloffset.y, &tooloffset.z);
 
394
                                        if (j != 3) {
 
395
                                                error.Format("%s: Cannot read tool offset coordinates '%s'\n", toolfilename, line);
 
396
                                                errorstr += error;
 
397
                                                tooloffset = CVec(0,0,0);
 
398
                                        }
 
399
                                } else if (str1.CompareNoCase("BARRELOFFSET")==0) {
 
400
                                        str2.Replace(","," ");
 
401
                                        int j=sscanf_s(str2,"%lf %lf %lf", &barreloffset.x, &barreloffset.y, &barreloffset.z);
 
402
                                        if (j != 3) {
 
403
                                                error.Format("%s: Cannot read barrel offset coordinates '%s'\n", toolfilename, line);
 
404
                                                errorstr += error;
 
405
                                                barreloffset = CVec(0,0,0);
 
406
                                        }
 
407
                                } else if (str1.CompareNoCase("PLUNGEROFFSET")==0) {
 
408
                                        str2.Replace(","," ");
 
409
                                        int j=sscanf_s(str2,"%lf %lf %lf", &plungeroffset.x, &plungeroffset.y, &plungeroffset.z);
 
410
                                        if (j != 3) {
 
411
                                                error.Format("%s: Cannot read plunger offset coordinates '%s'\n", toolfilename, line);
 
412
                                                errorstr += error;
 
413
                                                plungeroffset = CVec(0,0,0);
 
414
                                        }
 
415
                                } else if (str1.CompareNoCase("TIPOFFSET")==0) {
 
416
                                        str2.Replace(","," ");
 
417
                                        int j=sscanf_s(str2,"%lf %lf %lf", &tipoffset.x, &tipoffset.y, &tipoffset.z);
 
418
                                        if (j != 3) {
 
419
                                                error.Format("%s: Cannot read tip offset coordinates '%s'\n", toolfilename, line);
 
420
                                                errorstr += error;
 
421
                                                tipoffset = CVec(0,0,0);
 
422
                                        }
 
423
                                } else if (str1.CompareNoCase("TOOLGEOM")==0) {
 
424
                                        if (loadgeom) { // skip geometry if not neccesary
 
425
                                                CString geomfile = CUtils::RemoveComment(str2);
 
426
                                                CString geompath = CUtils::GetPath(toolfilename)+"\\"+geomfile;
 
427
                                                if (_access(geompath,4) != 0 || !toolgeom.LoadSTL(geompath, 10000)) {
 
428
                                                        error.Format("%s: Cannot load tool geometry '%s'\n", toolfilename, geompath);
 
429
                                                        errorstr += error;
 
430
                                                        return false;
 
431
                                                }
 
432
                                                toolgeom.name = geomfile;
 
433
                                        }
 
434
                                } else if (str1.CompareNoCase("BARRELGEOM")==0) {
 
435
                                        if (loadgeom) { // skip geometry if not neccesary
 
436
                                                CString geomfile = CUtils::RemoveComment(str2);
 
437
                                                CString geompath = CUtils::GetPath(toolfilename)+"\\"+geomfile;
 
438
                                                if (_access(geompath,4) != 0 || !barrelgeom.LoadSTL(geompath, 10000)) {
 
439
                                                        error.Format("%s: Cannot load barrel geometry '%s'\n", toolfilename, geompath);
 
440
                                                        errorstr += error;
 
441
                                                        return false;
 
442
                                                }
 
443
                                                barrelgeom.name = geomfile;
 
444
                                        }
 
445
                                } else if (str1.CompareNoCase("TIPGEOM")==0) {
 
446
                                        if (loadgeom) { // skip geometry if not neccesary
 
447
                                                CString geomfile = CUtils::RemoveComment(str2);
 
448
                                                CString geompath = CUtils::GetPath(toolfilename)+"\\"+geomfile;
 
449
                                                if (_access(geompath,4) != 0 || !tipgeom.LoadSTL(geompath, 10000)) {
 
450
                                                        error.Format("%s: Cannot load tip geometry '%s'\n", toolfilename, geompath);
 
451
                                                        errorstr += error;
 
452
                                                        return false;
 
453
                                                }
 
454
                                                tipgeom.name = geomfile;
 
455
                                        }
 
456
                                } else if (str1.CompareNoCase("PLUNGERGEOM")==0) {
 
457
                                        if (loadgeom) { // skip geometry if not neccesary
 
458
                                                CString geomfile = CUtils::RemoveComment(str2);
 
459
                                                CString geompath = CUtils::GetPath(toolfilename)+"\\"+geomfile;
 
460
                                                if (_access(geompath,4) != 0 || !plungergeom.LoadSTL(geompath, 10000)) {
 
461
                                                        error.Format("%s: Cannot load plunger geometry '%s'\n", toolfilename, geompath);
 
462
                                                        errorstr += error;
 
463
                                                        return false;
 
464
                                                }
 
465
                                                plungergeom.name = geomfile;
 
466
                                        }
 
467
                                } else if (str1.CompareNoCase("TOOLCOLOR")==0) {
 
468
                                        str2.Replace(","," ");
 
469
                                        int j=sscanf_s(str2,"%lf %lf %lf %lf", &toolcolor.x, &toolcolor.y, &toolcolor.z, &toolalpha);
 
470
                                        if (j != 4) {
 
471
                                                error.Format("%s: Cannot read tool color '%s'\n", toolfilename, line);
 
472
                                                errorstr += error;
 
473
                                                barrelcolor = CVec(0.5,0.5,0.5);
 
474
                                                barrelalpha = 1;
 
475
                                        }
 
476
                                } else if (str1.CompareNoCase("BARRELCOLOR")==0) {
 
477
                                        str2.Replace(","," ");
 
478
                                        int j=sscanf_s(str2,"%lf %lf %lf %lf", &barrelcolor.x, &barrelcolor.y, &barrelcolor.z, &barrelalpha);
 
479
                                        if (j != 4) {
 
480
                                                error.Format("%s: Cannot read barrel color '%s'\n", toolfilename, line);
 
481
                                                errorstr += error;
 
482
                                                barrelcolor = CVec(0.5,0.5,0.5);
 
483
                                                barrelalpha = 1;
 
484
                                        }
 
485
                                } else if (str1.CompareNoCase("TIPCOLOR")==0) {
 
486
                                        str2.Replace(","," ");
 
487
                                        int j=sscanf_s(str2,"%lf %lf %lf %lf", &tipcolor.x, &tipcolor.y, &tipcolor.z, &tipalpha);
 
488
                                        if (j != 4) {
 
489
                                                error.Format("%s: Cannot read tip color '%s'\n", toolfilename, line);
 
490
                                                errorstr += error;
 
491
                                                tipcolor = CVec(0.5,0.5,0.5);
 
492
                                                tipalpha = 1;
 
493
                                        }
 
494
                                } else if (str1.CompareNoCase("PLUNGERCOLOR")==0) {
 
495
                                        str2.Replace(","," ");
 
496
                                        int j=sscanf_s(str2,"%lf %lf %lf %lf", &plungercolor.x, &plungercolor.y, &plungercolor.z, &plungeralpha);
 
497
                                        if (j != 4) {
 
498
                                                error.Format("%s: Cannot read plunger color '%s'\n", toolfilename, line);
 
499
                                                errorstr += error;
 
500
                                                plungercolor = CVec(0.5,0.5,0.5);
 
501
                                                plungeralpha = 1;
 
502
                                        }
 
503
                                } else if (str1.CompareNoCase("INCREMENT")==0) {
 
504
                                        str2.Replace(","," ");
 
505
                                        int j=sscanf_s(str2,"%lf", &jogIncrement);
 
506
                                        if (j != 1) {
 
507
                                                error.Format("%s: Cannot read jog increment '%s'\n", toolfilename, line);
 
508
                                                errorstr += error;
 
509
                                                jogIncrement = JOG_STEP_TOOL;
 
510
                                        }
 
511
                                } else if (str1.CompareNoCase("CLEARANCE")==0) {
 
512
                                        str2.Replace(","," ");
 
513
                                        int j=sscanf_s(str2,"%lf", &clearance);
 
514
                                        if (j != 1) {
 
515
                                                error.Format("%s: Cannot read travel clearance '%s'\n", toolfilename, line);
 
516
                                                errorstr += error;
 
517
                                                clearance = DEFAULT_TRAVEL_CLEARANCE;
 
518
                                        }
 
519
 
 
520
                                } else if (str1.CompareNoCase("PATHSPEED")==0) {
 
521
                                        str2.Replace(","," ");
 
522
                                        int j=sscanf_s(str2,"%lf", &pathspeed);
 
523
                                        if (j != 1) {
 
524
                                                error.Format("%s: Cannot read speed'%s'\n", toolfilename, line);
 
525
                                                errorstr += error;
 
526
                                                pathspeed = 5.0;
 
527
                                        }
 
528
                                } else if (str1.CompareNoCase("JOGSPEED")==0) {
 
529
                                        str2.Replace(","," ");
 
530
                                        int j=sscanf_s(str2,"%lf", &jogspeed);
 
531
                                        if (j != 1) {
 
532
                                                error.Format("%s: Cannot read jog speed'%s'\n", toolfilename, line);
 
533
                                                errorstr += error;
 
534
                                                jogspeed = MAX_STEP_FREQ;
 
535
                                        }
 
536
                                } else if (str1.CompareNoCase("TIPDIAM")==0) {
 
537
                                        str2.Replace(","," ");
 
538
                                        int j=sscanf_s(str2,"%lf", &m_dTipID);
 
539
                                        if (j != 1) {
 
540
                                                error.Format("%s: Cannot read tip ID '%s'\n", toolfilename, line);
 
541
                                                errorstr += error;
 
542
                                                m_dTipID = 0.25; //red EFD tip id
 
543
                                        }
 
544
                                } else if (str1.CompareNoCase("BARRELDIAM")==0) {
 
545
                                        str2.Replace(","," ");
 
546
                                        int j=sscanf_s(str2,"%lf", &m_dBarrelID);
 
547
                                        if (j != 1) {
 
548
                                                error.Format("%s: Cannot read barrel ID '%s'\n", toolfilename, line);
 
549
                                                errorstr += error;
 
550
                                                m_dBarrelID = 15.8; //standard for 10cc EFC
 
551
                                        }
 
552
                                } else if (str1.CompareNoCase("PAUSEPATHS")==0) {
 
553
                                        str2.Replace(","," ");
 
554
                                        int j=sscanf_s(str2,"%d", &m_nPausePathCount);
 
555
                                        if (j != 1) {
 
556
                                                error.Format("%s: Cannot read pause path count '%s'\n", toolfilename, line);
 
557
                                                errorstr += error;
 
558
                                                m_nPausePathCount = 0;
 
559
                                        }
 
560
                                } else if (str1.CompareNoCase("MINPATHLENGTH")==0) {
 
561
                                        str2.Replace(","," ");
 
562
                                        int j=sscanf_s(str2,"%lf", &m_dMinPathLength);
 
563
                                        if (j != 1) {
 
564
                                                error.Format("%s: Cannot read minimum path length '%s'\n", toolfilename, line);
 
565
                                                errorstr += error;
 
566
                                                m_dMinPathLength = 0;
 
567
                                        } else {
 
568
        //                              error.Format("%s: Unrecognized token '%s'\n", toolfilename, str1);
 
569
        //                              errorstr += error;
 
570
                                        }
 
571
                                }
 
572
                        } else {
 
573
                                error.Format("%s: Cannot parse '%s'\n", toolfilename, line);
 
574
                                errorstr += error;
 
575
                        }
 
576
                }
 
577
        } while (readok);
 
578
 
 
579
        // home current position
 
580
 
 
581
        curstep = (long) (unloadpos/mmps);
 
582
        cmdstep = curstep;
 
583
 
 
584
        file.Close();
 
585
        return true;
 
586
}
 
587
 
 
588
 
 
589
//---------------------------------------------------------------------------
 
590
void CTool::SetDefaults(void)
 
591
//---------------------------------------------------------------------------
 
592
{
 
593
        m_bIsMounted = false;
 
594
        name = "";
 
595
        description = "";
 
596
        pathheight = 1;
 
597
        pathwidth = 1;
 
598
        maxvolume = 100;
 
599
        currentvolume = 100;
 
600
        backfill = 2;
 
601
        tip = CVec(0,0,0);
 
602
        tooloffset = barreloffset = tipoffset = plungeroffset = CVec(0,0,0);
 
603
        toolcolor = barrelcolor = tipcolor = plungercolor = CVec(200,200,200);
 
604
        toolalpha = barrelalpha = tipalpha = plungeralpha = 15;
 
605
        toolgeom.Clear();
 
606
        barrelgeom.Clear();
 
607
        plungergeom.Clear();
 
608
        tipgeom.Clear();
 
609
        dir = CVec(0,0,-1);
 
610
        mmps = 0.005;
 
611
        axis = -1; //which amp axis tool is connected to
 
612
        axisDir = 1; // +/-1 for normal / reverse motor motion relative to commands
 
613
        disprate = 2; // mm of plunger motion per mm travel of tool along path
 
614
        curstep = 0; //"real-time" position (in steps) - typically inaccurate if hardware is connected
 
615
        cmdstep = 0; //commanded position, in steps
 
616
        rangemin = 0; // minimum allowed steps
 
617
        rangemax = 100; // [mm] maximum allowed step
 
618
        stepstomove = 0; // number of steps to move in current segmnent
 
619
        bottompos = 0; // [mm] position at bottom of displenser
 
620
        unloadpos = 100; // [mm] position suitable for loading/unloading plunger
 
621
        pushout = 0;
 
622
        suckback = 0;
 
623
        suckbackDelay = 0;
 
624
        pathspeed = 5.0; //default maximum path traverse speed for this tool
 
625
        jogspeed = MAX_STEP_FREQ;
 
626
        m_dTipID = 0.25; //standard EFD red tip ID
 
627
        m_dBarrelID = 15.8; //standard EFD 10cc barrel ID
 
628
        m_dVolNeeded = 0; //volume of material in mL needed to build current model
 
629
        m_nPausePathCount = 0; //at zero, auto pause will never occur
 
630
        m_dMinPathLength = 0.0; //mm length of shortest build path (not path segment)
 
631
}
 
632
 
 
633
//---------------------------------------------------------------------------
 
634
CVec CTool::GetPos(bool bCommanded, bool bGraphics)
 
635
//---------------------------------------------------------------------------
 
636
{// get the component (stage) position; use commanded if bCommanded, else "real-time"
 
637
//if bGraphics, then adjust for graphics offset relative to hardware home position
 
638
        CFabAtHomeApp* pApp = (CFabAtHomeApp *) AfxGetApp();
 
639
 
 
640
        // calculate aggregated position of current stage
 
641
 
 
642
        int ref = 2;
 
643
        CVec pos(0,0,0);
 
644
        long grOffs = 0; //offset in mm
 
645
        
 
646
        while (ref != -1) {
 
647
                //home is stored for component when the hardware/emulator is homed
 
648
                if(bGraphics)
 
649
                        grOffs = (long)pApp->printer.component[ref].home;
 
650
                if(bCommanded)
 
651
                        pos += pApp->printer.component[ref].dir * 
 
652
                                   (pApp->printer.component[ref].GetCMDPos() + grOffs);
 
653
                else
 
654
                        pos += pApp->printer.component[ref].dir * 
 
655
                                   (pApp->printer.component[ref].GetRTPos() + grOffs);
 
656
 
 
657
                ref = pApp->printer.component[ref].refidx;
 
658
        }
 
659
 
 
660
        return pos;
 
661
}
 
662
 
 
663
//---------------------------------------------------------------------------
 
664
bool CTool::Draw(bool bCommanded)
 
665
//---------------------------------------------------------------------------
 
666
{// draw the tool component, show commanded if bCommanded, else show "real-time"
 
667
 
 
668
        CFabAtHomeApp* pApp = (CFabAtHomeApp *) AfxGetApp();
 
669
        CVec pmotion, toolpos;
 
670
        double pdist;
 
671
 
 
672
        // calculate aggregated position of printer head stage
 
673
        toolpos = GetPos(bCommanded, true); //get the graphics offset position
 
674
        // calculate the location of the tool body
 
675
        toolpos -= tooloffset;
 
676
 
 
677
        // calculate plunger motion
 
678
        if(bCommanded)
 
679
                pdist = cmdstep*mmps;
 
680
        else
 
681
                pdist = curstep*mmps;
 
682
        if(pdist > rangemax) pdist = rangemax;
 
683
        if(pdist < rangemin) pdist = rangemin;
 
684
 
 
685
        pmotion = axisDir*dir*pdist;
 
686
 
 
687
        // prep OpenGL for drawing transparency of components
 
688
        glEnable (GL_BLEND);
 
689
        glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 
690
 
 
691
        // draw tool
 
692
        glPushMatrix();
 
693
        glColor4d(toolcolor.x,toolcolor.y,toolcolor.z,toolalpha);
 
694
        CGLUtils::glTranslate(toolpos);
 
695
        toolgeom.Draw(false, true);
 
696
        glPopMatrix();
 
697
        // draw plunger
 
698
        glPushMatrix();
 
699
        glColor4d(plungercolor.x,plungercolor.y,plungercolor.z,plungeralpha);
 
700
        CGLUtils::glTranslate(toolpos+plungeroffset+pmotion);
 
701
        plungergeom.Draw(false, true);
 
702
        glPopMatrix();
 
703
        // draw barrel
 
704
        glPushMatrix();
 
705
        glColor4d(barrelcolor.x,barrelcolor.y,barrelcolor.z,barrelalpha);
 
706
        CGLUtils::glTranslate(toolpos+barreloffset);
 
707
        barrelgeom.Draw(false, true);
 
708
        glPopMatrix();
 
709
        // draw tip
 
710
        glPushMatrix();
 
711
        glColor4d(tipcolor.x,tipcolor.y,tipcolor.z,tipalpha);
 
712
        CGLUtils::glTranslate(toolpos+tipoffset);
 
713
        tipgeom.Draw(false, true);
 
714
        glPopMatrix();
 
715
        // draw tip point
 
716
        glColor4d(plungercolor.x,plungercolor.y,plungercolor.z,1);
 
717
        CGLUtils::DrawSphere(toolpos+tip, 1.5);
 
718
 
 
719
        //glPopMatrix();
 
720
        glDisable(GL_BLEND);
 
721
 
 
722
        return false;
 
723
}
 
724
 
 
725
//---------------------------------------------------------------------------
 
726
bool CTool::LoadTools(CString directory, bool bUpdateParams)
 
727
//---------------------------------------------------------------------------
 
728
{ // open and read all tool files in given directory
 
729
        //if bUpdateParams, just update the parameters from the files to the
 
730
        //tool array
 
731
 
 
732
   CFabAtHomeApp *pApp = (CFabAtHomeApp *) AfxGetApp();
 
733
 
 
734
   CTool newtool;
 
735
   CString errorstr;
 
736
   int toolIdx;
 
737
   int oldCnt = 0;
 
738
   int newCnt = 0;
 
739
 
 
740
   WIN32_FIND_DATA FindFileData;
 
741
   HANDLE hFind = INVALID_HANDLE_VALUE;
 
742
 
 
743
   hFind = FindFirstFile(directory+"\\*.tool", &FindFileData);
 
744
   if (hFind == INVALID_HANDLE_VALUE)
 
745
   {// Invalid file handle
 
746
           errorstr.Format("Unable to load tools from directory %s",directory);
 
747
           ((CFabAtHomeApp *)AfxGetApp())->Log(errorstr);
 
748
           return false;
 
749
   }
 
750
 
 
751
        CArray<CString,CString> mountedNames;
 
752
        int activeIdx;
 
753
        if(!bUpdateParams)
 
754
        {
 
755
           //if we are not updating parameters, but instead reading in everything
 
756
           //cache the name(s) of the mounted tool(s)
 
757
           for(int i = 0; i < pApp->tool.GetSize(); i++)
 
758
           {
 
759
                   if(pApp->tool[i].IsMounted())
 
760
                   {
 
761
                           mountedNames.Add(pApp->tool[i].GetName());
 
762
                           if(pApp->printer.GetCurToolName().CompareNoCase(pApp->tool[i].GetName())==0)
 
763
                                   activeIdx = mountedNames.GetSize()-1;
 
764
                   }
 
765
           }
 
766
           //then flush the array
 
767
           pApp->tool.RemoveAll();
 
768
        }
 
769
 
 
770
   do 
 
771
   {
 
772
           bool loaded = newtool.LoadFile(directory+"\\"+FindFileData.cFileName, errorstr, true);
 
773
           if (loaded)
 
774
           {
 
775
                   //if we are just updating changed parameters, match tools from files with
 
776
                   //tools from tool array by name, and copy in the parameters
 
777
                   if(bUpdateParams)
 
778
                   {
 
779
                           toolIdx = SearchByName(newtool.name);
 
780
                           //if we can find the tool in the current array
 
781
                           if(toolIdx >= 0 && toolIdx < pApp->tool.GetSize() )
 
782
                           {
 
783
                                   //just copy its parameters
 
784
                                   pApp->tool[toolIdx].CopyParamsFrom(newtool);
 
785
                                   oldCnt++;
 
786
                           }
 
787
                           else
 
788
                           {
 
789
                                   //couldn't find it, so add it to the array as a new tool
 
790
                                   pApp->tool.Add(newtool);
 
791
                                   newCnt++;
 
792
                           }
 
793
                   }
 
794
                   else //not updating parameters
 
795
                   {
 
796
                           //if the previously mounted tools are present in the new files
 
797
                           //mount them again
 
798
                           for(int i = 0; i < mountedNames.GetSize(); i++)
 
799
                           {
 
800
                                   if(newtool.GetName().CompareNoCase(mountedNames[i])==0)
 
801
                                   {
 
802
                                           newtool.Mount();
 
803
                                           mountedNames.RemoveAt(i);
 
804
                                   }
 
805
                           }
 
806
                           //then add new tool to the array
 
807
                           pApp->tool.Add(newtool);
 
808
                           newCnt++;
 
809
                   }
 
810
                   TRACE("Loaded tool %s\n", newtool.name);
 
811
           }
 
812
   } while (FindNextFile(hFind, &FindFileData) != 0);
 
813
 
 
814
   if (!errorstr.IsEmpty())
 
815
           ((CFabAtHomeApp *)AfxGetApp())->Log(CString("Error found while reading tool files: ")+errorstr+" Erroneous files skipped.");
 
816
 
 
817
   DWORD dwError = GetLastError();
 
818
   FindClose(hFind);
 
819
   if (dwError != ERROR_NO_MORE_FILES) // FindNextFile error; dwError
 
820
           return false;
 
821
 
 
822
   //success, so report
 
823
   if(bUpdateParams)
 
824
   {
 
825
           CString str1, str2;
 
826
           //str1.Format("Updated parameters for ");
 
827
           str1.Format("Reloaded parameters for ");
 
828
           if(newCnt == 0)
 
829
           {
 
830
                   str2.Format("%d existing tools", oldCnt);
 
831
           }
 
832
           else
 
833
           {
 
834
                   str2.Format("%d existing tools, and loaded %d new tools", oldCnt, newCnt);
 
835
 
 
836
           }
 
837
           errorstr.Format("%s%s from directory: %s", str1, str2,directory);
 
838
   }
 
839
   else
 
840
   {
 
841
           CString tmp;
 
842
           if(mountedNames.GetSize() > 0)
 
843
           {
 
844
                   for(int i = 0; i < mountedNames.GetSize(); i++)
 
845
                   {
 
846
                           tmp+=mountedNames[i];
 
847
                           tmp+=" ";
 
848
                   }
 
849
                   errorstr.Format("Previously mounted tools not found: %s",tmp);
 
850
           }
 
851
           else
 
852
           {
 
853
                   errorstr.Format("Loaded %d tools from directory: %s", newCnt, directory);
 
854
           }
 
855
   }
 
856
   ((CFabAtHomeApp *)AfxGetApp())->Log(errorstr);
 
857
 
 
858
   return true;
 
859
}
 
860
 
 
861
//---------------------------------------------------------------------------
 
862
bool CTool::CopyParamsFrom( const CTool& s )
 
863
//---------------------------------------------------------------------------
 
864
{
 
865
        //copy only the parameters, not all varables from the fromTool to this tool
 
866
        //COMMENTED OUT VARIABLES ARE STILL HERE TO SHOW WHAT IS NOT BEING COPIED
 
867
 
 
868
        description = s.description;
 
869
        maxvolume = s.maxvolume;
 
870
        currentvolume = s.currentvolume;
 
871
        pathwidth = s.pathwidth;
 
872
        pathheight = s.pathheight;
 
873
        backfill = s.backfill;
 
874
        tip = s.tip;
 
875
        tooloffset = s.tooloffset;
 
876
        barreloffset = s.barreloffset;
 
877
        tipoffset = s.tipoffset;
 
878
        plungeroffset = s.plungeroffset;
 
879
        toolgeom = s.toolgeom;
 
880
        plungergeom = s.plungergeom;
 
881
        barrelgeom = s.barrelgeom;
 
882
        tipgeom = s.tipgeom;
 
883
        toolcolor = s.toolcolor;
 
884
        plungercolor = s.plungercolor;
 
885
        barrelcolor = s.barrelcolor;
 
886
        tipcolor = s.tipcolor;
 
887
        toolalpha = s.toolalpha;
 
888
        plungeralpha = s.plungeralpha;
 
889
        tipalpha = s.tipalpha;
 
890
        barrelalpha = s.barrelalpha;
 
891
        disprate = s.disprate;
 
892
        dir = s.dir;
 
893
        mmps = s.mmps;
 
894
        axis = s.axis;
 
895
        axisDir = s.axisDir;
 
896
        //curstep=s.curstep;
 
897
        //cmdstep=s.cmdstep;
 
898
        rangemin=s.rangemin;
 
899
        rangemax=s.rangemax;
 
900
        //stepstomove=s.stepstomove;
 
901
        bottompos=s.bottompos;
 
902
        unloadpos=s.unloadpos;
 
903
        pushout=s.pushout;
 
904
        suckback = s.suckback;
 
905
        suckbackDelay = s.suckbackDelay;
 
906
        //posLimitSwitch = s.posLimitSwitch;
 
907
        //negLimitSwitch = s.negLimitSwitch;
 
908
        jogIncrement = s.jogIncrement;
 
909
        clearance = s.clearance;
 
910
        pathspeed = s.pathspeed;
 
911
        jogspeed = s.jogspeed;
 
912
        m_nPausePathCount = s.m_nPausePathCount;
 
913
        m_dMinPathLength = s.m_dMinPathLength;
 
914
        return true;
 
915
}
 
916
 
 
917
 
 
918
//---------------------------------------------------------------------------
 
919
int CTool::SearchByName(CString& name)
 
920
//---------------------------------------------------------------------------
 
921
{ // search all tools and find match by name
 
922
 
 
923
   CFabAtHomeApp *pApp = (CFabAtHomeApp *) AfxGetApp();
 
924
   name.Trim();
 
925
   if (name.IsEmpty())
 
926
           return -1;
 
927
 
 
928
   // try exact match
 
929
   for (int i=0; i<pApp->tool.GetSize(); i++) {
 
930
           if (name.CompareNoCase(pApp->tool[i].name) == 0) 
 
931
                   return i;
 
932
   }
 
933
 
 
934
   // try weak match
 
935
 
 
936
   for (int i=0; i<pApp->tool.GetSize(); i++) {
 
937
           if (name.Find(pApp->tool[i].name) != -1) 
 
938
                   return i;
 
939
   }
 
940
 
 
941
   return -1;
 
942
}
 
943
 
 
944
//---------------------------------------------------------------------------
 
945
CTool* CTool::GetByName(CString& name)
 
946
//--------------------------------------------------------------------------
 
947
{
 
948
        //return pointer to the named tool or NULL if fails
 
949
        int idx;
 
950
        CFabAtHomeApp* pApp = (CFabAtHomeApp*)AfxGetApp();
 
951
        idx = SearchByName(name);
 
952
        return GetByIndex(idx);
 
953
}
 
954
 
 
955
//---------------------------------------------------------------------------
 
956
CTool* CTool::GetByIndex(int idx)
 
957
//---------------------------------------------------------------------------
 
958
{
 
959
        //return a pointer to the indexed tool or NULL if fails
 
960
        CFabAtHomeApp* pApp = (CFabAtHomeApp*)AfxGetApp();
 
961
        if((idx >= 0) && (idx < pApp->tool.GetSize()))
 
962
                return( &(pApp->tool[idx]) );
 
963
        else
 
964
                return NULL;
 
965
}
 
966
 
 
967
//---------------------------------------------------------------------------
 
968
CString CTool::GetName(int idx)
 
969
//---------------------------------------------------------------------------
 
970
{
 
971
        //return the name of the indexed tool
 
972
        CFabAtHomeApp *pApp = (CFabAtHomeApp *) AfxGetApp();
 
973
        if((idx >= pApp->tool.GetSize()) || (idx < 0)) return CString("Undefined");
 
974
        return pApp->tool[idx].GetName();
 
975
}
 
976
 
 
977
//---------------------------------------------------------------------------
 
978
bool CTool::Mount(CString name)
 
979
//---------------------------------------------------------------------------
 
980
{
 
981
        //find the tool by name and mount it
 
982
        int idx = SearchByName(name);
 
983
        if(idx < 0) return false;
 
984
        CFabAtHomeApp *pApp = (CFabAtHomeApp *) AfxGetApp();
 
985
        pApp->tool[idx].Mount();
 
986
        return true;
 
987
}
 
988
 
 
989
//---------------------------------------------------------------------------
 
990
bool CTool::Unmount(CString name)
 
991
//---------------------------------------------------------------------------
 
992
{
 
993
        //find the tool by name and unmount it
 
994
        int idx = SearchByName(name);
 
995
        if(idx < 0) return false;
 
996
        CFabAtHomeApp *pApp = (CFabAtHomeApp *) AfxGetApp();
 
997
        pApp->tool[idx].Unmount();
 
998
        return true;
 
999
}
 
1000
 
 
1001
//---------------------------------------------------------------------------
 
1002
CString CTool::FindNextMounted(CString &curTool)
 
1003
//---------------------------------------------------------------------------
 
1004
 
1005
        //find the next mounted tool after curTool
 
1006
        //wrap to start of array if necessary
 
1007
        //return "Undefined" if none
 
1008
 
 
1009
        CFabAtHomeApp *pApp = (CFabAtHomeApp *) AfxGetApp();
 
1010
        int cnt = pApp->tool.GetSize()-1; //look at all except curTool
 
1011
        int i = SearchByName(curTool)+1;
 
1012
        if(i <= 0) //searchbyname failed
 
1013
                return CString("Undefined");
 
1014
        while(cnt > 0)
 
1015
        {       
 
1016
                if(i >= pApp->tool.GetSize()-1) 
 
1017
                        i=0; //wrap around
 
1018
                if(pApp->tool[i].IsMounted()) return pApp->tool[i].GetName();
 
1019
                    i++;
 
1020
                cnt--;
 
1021
        }
 
1022
        return CString("Undefined");
 
1023
}
 
1024
 
 
1025
//--------------------------------------------------------------------
 
1026
int CTool::MountedToolCount()
 
1027
//--------------------------------------------------------------------
 
1028
{
 
1029
        //return the number of currently mounted tools
 
1030
        CFabAtHomeApp *pApp = (CFabAtHomeApp *) AfxGetApp();
 
1031
        int cnt = 0;
 
1032
        for(int i = 0; i < pApp->tool.GetSize(); i++)
 
1033
        {
 
1034
                if(pApp->tool[i].IsMounted())
 
1035
                        cnt++;
 
1036
        }
 
1037
        return cnt;
 
1038
}
 
1039
 
 
1040
//--------------------------------------------------------------------
 
1041
int CTool::LoadedToolCount()
 
1042
//--------------------------------------------------------------------
 
1043
{
 
1044
        //return the number currently loaded tools
 
1045
        CFabAtHomeApp *pApp = (CFabAtHomeApp *) AfxGetApp();
 
1046
        return pApp->tool.GetSize();
 
1047
}
 
 
b'\\ No newline at end of file'