src/types.cc

changeset 557
04e140bdeb0b
child 560
39085791128f
equal deleted inserted replaced
556:5f4395ec5db0 557:04e140bdeb0b
1 /*
2 * LDForge: LDraw parts authoring CAD
3 * Copyright (C) 2013 Santeri Piippo
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include <QObject>
20 #include <QStringList>
21 #include <QTextStream>
22 #include <QFile>
23 #include <assert.h>
24 #include "main.h"
25 #include "types.h"
26 #include "misc.h"
27 #include "ldtypes.h"
28 #include "document.h"
29
30 // =============================================================================
31 // -----------------------------------------------------------------------------
32 str DoFormat (QList<StringFormatArg> args)
33 { assert (args.size() >= 1);
34 str text = args[0].value();
35
36 for (uchar i = 1; i < args.size(); ++i)
37 text = text.arg (args[i].value());
38
39 return text;
40 }
41
42 // =============================================================================
43 // -----------------------------------------------------------------------------
44 vertex::vertex (double x, double y, double z)
45 { m_coords[X] = x;
46 m_coords[Y] = y;
47 m_coords[Z] = z;
48 }
49
50 // =============================================================================
51 // -----------------------------------------------------------------------------
52 void vertex::move (const vertex& other)
53 { for_axes (ax)
54 m_coords[ax] += other[ax];
55 }
56
57 // =============================================================================
58 // -----------------------------------------------------------------------------
59 vertex vertex::midpoint (const vertex& other)
60 { vertex mid;
61
62 for_axes (ax)
63 mid[ax] = (m_coords[ax] + other[ax]) / 2;
64
65 return mid;
66 }
67
68 // =============================================================================
69 // -----------------------------------------------------------------------------
70 str vertex::stringRep (bool mangled) const
71 { str fmtstr = "%1 %2 %3";
72
73 if (mangled)
74 fmtstr = "(%1, %2, %3)";
75
76 return fmt (fmtstr, coord (X), coord (Y), coord (Z));
77 }
78
79 // =============================================================================
80 // -----------------------------------------------------------------------------
81 void vertex::transform (matrix matr, vertex pos)
82 { double x2 = (matr[0] * x()) + (matr[1] * y()) + (matr[2] * z()) + pos[X];
83 double y2 = (matr[3] * x()) + (matr[4] * y()) + (matr[5] * z()) + pos[Y];
84 double z2 = (matr[6] * x()) + (matr[7] * y()) + (matr[8] * z()) + pos[Z];
85
86 x() = x2;
87 y() = y2;
88 z() = z2;
89 }
90
91 // =============================================================================
92 // -----------------------------------------------------------------------------
93 vertex vertex::operator-() const
94 { return vertex (-m_coords[X], -m_coords[Y], -m_coords[Z]);
95 }
96
97 // =============================================================================
98 // -----------------------------------------------------------------------------
99 bool vertex::operator!= (const vertex& other) const
100 { return !operator== (other);
101 }
102
103 // =============================================================================
104 // -----------------------------------------------------------------------------
105 double& vertex::operator[] (const Axis ax)
106 { return coord ( (int) ax);
107 }
108
109 const double& vertex::operator[] (const Axis ax) const
110 { return coord ( (int) ax);
111 }
112
113 double& vertex::operator[] (const int ax)
114 { return coord (ax);
115 }
116
117 const double& vertex::operator[] (const int ax) const
118 { return coord (ax);
119 }
120
121 // =============================================================================
122 // -----------------------------------------------------------------------------
123 bool vertex::operator== (const vertex& other) const
124 { return coord (X) == other[X] &&
125 coord (Y) == other[Y] &&
126 coord (Z) == other[Z];
127 }
128
129 // =============================================================================
130 // -----------------------------------------------------------------------------
131 vertex& vertex::operator/= (const double d)
132 { for_axes (ax)
133 m_coords[ax] /= d;
134
135 return *this;
136 }
137
138 // =============================================================================
139 // -----------------------------------------------------------------------------
140 vertex vertex::operator/ (const double d) const
141 { vertex other (*this);
142 return other /= d;
143 }
144
145 // =============================================================================
146 // -----------------------------------------------------------------------------
147 vertex& vertex::operator+= (const vertex& other)
148 { move (other);
149 return *this;
150 }
151
152 // =============================================================================
153 // -----------------------------------------------------------------------------
154 vertex vertex::operator+ (const vertex& other) const
155 { vertex newvert (*this);
156 newvert.move (other);
157 return newvert;
158 }
159
160 // =============================================================================
161 // -----------------------------------------------------------------------------
162 int vertex::operator< (const vertex& other) const
163 { if (operator== (other))
164 return false;
165
166 if (coord (X) < other[X])
167 return true;
168
169 if (coord (X) > other[X])
170 return false;
171
172 if (coord (Y) < other[Y])
173 return true;
174
175 if (coord (Y) > other[Y])
176 return false;
177
178 return coord (Z) < other[Z];
179 }
180
181 // =============================================================================
182 // -----------------------------------------------------------------------------
183 matrix::matrix (double vals[])
184 { for (int i = 0; i < 9; ++i)
185 m_vals[i] = vals[i];
186 }
187
188 // =============================================================================
189 // -----------------------------------------------------------------------------
190 matrix::matrix (double fillval)
191 { for (int i = 0; i < 9; ++i)
192 m_vals[i] = fillval;
193 }
194
195 // =============================================================================
196 // -----------------------------------------------------------------------------
197 matrix::matrix (initlist<double> vals)
198 { assert (vals.size() == 9);
199 memcpy (&m_vals[0], & (*vals.begin()), sizeof m_vals);
200 }
201
202 // =============================================================================
203 // -----------------------------------------------------------------------------
204 void matrix::puts() const
205 { for (int i = 0; i < 3; ++i)
206 { for (int j = 0; j < 3; ++j)
207 log ("%1\t", m_vals[ (i * 3) + j]);
208
209 log ("\n");
210 }
211 }
212
213 // =============================================================================
214 // -----------------------------------------------------------------------------
215 str matrix::stringRep() const
216 { str val;
217
218 for (int i = 0; i < 9; ++i)
219 { if (i > 0)
220 val += ' ';
221
222 val += str::number (m_vals[i]);
223 }
224
225 return val;
226 }
227
228 // =============================================================================
229 // -----------------------------------------------------------------------------
230 void matrix::zero()
231 { memset (&m_vals[0], 0, sizeof m_vals);
232 }
233
234 // =============================================================================
235 // -----------------------------------------------------------------------------
236 matrix matrix::mult (matrix other) const
237 { matrix val;
238 val.zero();
239
240 for (int i = 0; i < 3; ++i)
241 for (int j = 0; j < 3; ++j)
242 for (int k = 0; k < 3; ++k)
243 val[(i * 3) + j] += m_vals[(i * 3) + k] * other[(k * 3) + j];
244
245 return val;
246 }
247
248 // =============================================================================
249 // -----------------------------------------------------------------------------
250 matrix& matrix::operator= (matrix other)
251 { memcpy (&m_vals[0], &other.m_vals[0], sizeof m_vals);
252 return *this;
253 }
254
255 // =============================================================================
256 // -----------------------------------------------------------------------------
257 double matrix::getDeterminant() const
258 { return (val (0) * val (4) * val (8)) +
259 (val (1) * val (5) * val (6)) +
260 (val (2) * val (3) * val (7)) -
261 (val (2) * val (4) * val (6)) -
262 (val (1) * val (3) * val (8)) -
263 (val (0) * val (5) * val (7));
264 }
265
266 // =============================================================================
267 // -----------------------------------------------------------------------------
268 bool matrix::operator== (const matrix& other) const
269 { for (int i = 0; i < 9; ++i)
270 if (val (i) != other[i])
271 return false;
272
273 return true;
274 }
275
276 // =============================================================================
277 // -----------------------------------------------------------------------------
278 StringFormatArg::StringFormatArg (const str& v)
279 { m_val = v;
280 }
281
282 StringFormatArg::StringFormatArg (const char& v)
283 { m_val = v;
284 }
285
286 StringFormatArg::StringFormatArg (const uchar& v)
287 { m_val = v;
288 }
289
290 StringFormatArg::StringFormatArg (const QChar& v)
291 { m_val = v;
292 }
293
294 StringFormatArg::StringFormatArg (const float& v)
295 { m_val = str::number (v);
296 }
297
298 StringFormatArg::StringFormatArg (const double& v)
299 { m_val = str::number (v);
300 }
301
302 StringFormatArg::StringFormatArg (const vertex& v)
303 { m_val = v.stringRep (false);
304 }
305
306 StringFormatArg::StringFormatArg (const matrix& v)
307 { m_val = v.stringRep();
308 }
309
310 StringFormatArg::StringFormatArg (const char* v)
311 { m_val = v;
312 }
313
314 StringFormatArg::StringFormatArg (const StringConfig& v)
315 { m_val = v.value;
316 }
317
318 StringFormatArg::StringFormatArg (const IntConfig& v)
319 { m_val.number (v.value);
320 }
321
322 StringFormatArg::StringFormatArg (const FloatConfig& v)
323 { m_val.number (v.value);
324 }
325
326 StringFormatArg::StringFormatArg (const void* v)
327 { m_val.sprintf ("%p", v);
328 }
329
330 // =============================================================================
331 // -----------------------------------------------------------------------------
332 File::File()
333 { // Make a null file
334 m_file = null;
335 m_textstream = null;
336 }
337
338 File::File (str path, OpenType rtype)
339 { m_file = null;
340 open (path, rtype);
341 }
342
343 File::File (FILE* fp, OpenType rtype)
344 { m_file = null;
345 open (fp, rtype);
346 }
347
348 // =============================================================================
349 // -----------------------------------------------------------------------------
350 File::~File()
351 { if (m_file)
352 { m_file->close();
353 delete m_file;
354
355 if (m_textstream)
356 delete m_textstream;
357 }
358 }
359
360 // =============================================================================
361 // -----------------------------------------------------------------------------
362 bool File::open (FILE* fp, OpenType rtype)
363 { return open ("", rtype, fp);
364 }
365
366 bool File::open (str path, OpenType rtype, FILE* fp)
367 { close();
368
369 if (!m_file)
370 m_file = new QFile;
371
372 m_file->setFileName (path);
373
374 bool result;
375
376 QIODevice::OpenMode mode =
377 (rtype == Read) ? QIODevice::ReadOnly :
378 (rtype == Write) ? QIODevice::WriteOnly : QIODevice::Append;
379
380 if (fp)
381 result = m_file->open (fp, mode);
382 else
383 result = m_file->open (mode);
384
385 if (result)
386 { m_textstream = new QTextStream (m_file);
387 return true;
388 }
389
390 delete m_file;
391 m_file = null;
392 return false;
393 }
394
395 // =============================================================================
396 // -----------------------------------------------------------------------------
397 File::iterator File::begin()
398 { return iterator (this);
399 }
400
401 File::iterator& File::end()
402 { return m_endIterator;
403 }
404
405 // =============================================================================
406 // -----------------------------------------------------------------------------
407 void File::write (str msg)
408 { m_file->write (msg.toUtf8(), msg.length());
409 }
410
411 // =============================================================================
412 // -----------------------------------------------------------------------------
413 bool File::readLine (str& line)
414 { if (!m_textstream || m_textstream->atEnd())
415 return false;
416
417 line = m_textstream->readLine();
418 return true;
419 }
420
421 // =============================================================================
422 // -----------------------------------------------------------------------------
423 bool File::atEnd() const
424 { assert (m_textstream != null);
425 return m_textstream->atEnd();
426 }
427
428 // =============================================================================
429 // -----------------------------------------------------------------------------
430 bool File::isNull() const
431 { return m_file == null;
432 }
433
434 bool File::operator!() const
435 { return isNull();
436 }
437
438 // =============================================================================
439 // -----------------------------------------------------------------------------
440 void File::close()
441 { if (!m_file)
442 return;
443
444 delete m_file;
445 m_file = null;
446
447 if (m_textstream)
448 { delete m_textstream;
449 m_textstream = null;
450 }
451 }
452
453 // =============================================================================
454 // -----------------------------------------------------------------------------
455 bool File::flush()
456 { return m_file->flush();
457 }
458
459 // =============================================================================
460 // -----------------------------------------------------------------------------
461 File::operator bool() const
462 { return !isNull();
463 }
464
465 // =============================================================================
466 // -----------------------------------------------------------------------------
467 void File::rewind()
468 { m_file->seek (0);
469 }
470
471 // =============================================================================
472 // -----------------------------------------------------------------------------
473 File::iterator::iterator (File* f) : m_file (f)
474 { operator++();
475 }
476
477 // =============================================================================
478 // -----------------------------------------------------------------------------
479 void File::iterator::operator++()
480 { m_gotdata = m_file->readLine (m_text);
481 }
482
483 // =============================================================================
484 // -----------------------------------------------------------------------------
485 str File::iterator::operator*()
486 { return m_text;
487 }
488
489 // =============================================================================
490 // The prime contestant for the weirdest operator== 2013 award?
491 // -----------------------------------------------------------------------------
492 bool File::iterator::operator== (File::iterator& other)
493 { return (other.m_file == null && !m_gotdata);
494 }
495
496 // =============================================================================
497 // -----------------------------------------------------------------------------
498 bool File::iterator::operator!= (File::iterator& other)
499 { return !operator== (other);
500 }
501
502 // =============================================================================
503 // -----------------------------------------------------------------------------
504 LDBoundingBox::LDBoundingBox()
505 { reset();
506 }
507
508 // =============================================================================
509 // -----------------------------------------------------------------------------
510 void LDBoundingBox::calculate()
511 { reset();
512
513 if (!getCurrentDocument())
514 return;
515
516 for (LDObject* obj : getCurrentDocument()->getObjects())
517 calcObject (obj);
518 }
519
520 // =============================================================================
521 // -----------------------------------------------------------------------------
522 void LDBoundingBox::calcObject (LDObject* obj)
523 { switch (obj->getType())
524 { case LDObject::Line:
525 case LDObject::Triangle:
526 case LDObject::Quad:
527 case LDObject::CondLine:
528 { for (int i = 0; i < obj->vertices(); ++i)
529 calcVertex (obj->getVertex (i));
530 } break;
531
532 case LDObject::Subfile:
533 { LDSubfile* ref = static_cast<LDSubfile*> (obj);
534 QList<LDObject*> objs = ref->inlineContents (LDSubfile::DeepCacheInline);
535
536 for (LDObject * obj : objs)
537 { calcObject (obj);
538 delete obj;
539 }
540 }
541 break;
542
543 default:
544 break;
545 }
546 }
547
548 // =============================================================================
549 // -----------------------------------------------------------------------------
550 LDBoundingBox& LDBoundingBox::operator<< (const vertex& v)
551 { calcVertex (v);
552 return *this;
553 }
554
555 // =============================================================================
556 // -----------------------------------------------------------------------------
557 LDBoundingBox& LDBoundingBox::operator<< (LDObject* obj)
558 { calcObject (obj);
559 return *this;
560 }
561
562 // =============================================================================
563 // -----------------------------------------------------------------------------
564 void LDBoundingBox::calcVertex (const vertex& v)
565 { for_axes (ax)
566 { if (v[ax] < m_Vertex0[ax])
567 m_Vertex0[ax] = v[ax];
568
569 if (v[ax] > m_Vertex1[ax])
570 m_Vertex1[ax] = v[ax];
571 }
572
573 setEmpty (false);
574 }
575
576 // =============================================================================
577 // -----------------------------------------------------------------------------
578 void LDBoundingBox::reset()
579 { m_Vertex0[X] = m_Vertex0[Y] = m_Vertex0[Z] = 0x7FFFFFFF;
580 m_Vertex1[X] = m_Vertex1[Y] = m_Vertex1[Z] = 0xFFFFFFFF;
581
582 setEmpty (true);
583 }
584
585 // =============================================================================
586 // -----------------------------------------------------------------------------
587 double LDBoundingBox::size() const
588 { double xscale = (m_Vertex0[X] - m_Vertex1[X]);
589 double yscale = (m_Vertex0[Y] - m_Vertex1[Y]);
590 double zscale = (m_Vertex0[Z] - m_Vertex1[Z]);
591 double size = zscale;
592
593 if (xscale > yscale)
594 { if (xscale > zscale)
595 size = xscale;
596 }
597 elif (yscale > zscale)
598 size = yscale;
599
600 if (abs (size) >= 2.0f)
601 return abs (size / 2);
602
603 return 1.0f;
604 }
605
606 // =============================================================================
607 // -----------------------------------------------------------------------------
608 vertex LDBoundingBox::center() const
609 { return vertex (
610 (m_Vertex0[X] + m_Vertex1[X]) / 2,
611 (m_Vertex0[Y] + m_Vertex1[Y]) / 2,
612 (m_Vertex0[Z] + m_Vertex1[Z]) / 2);
613 }

mercurial