Panda3D
 All Classes Functions Variables Enumerations
dxfFile.cxx
1 // Filename: dxfFile.cxx
2 // Created by: drose (04May04)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "dxfFile.h"
16 #include "string_utils.h"
17 #include "virtualFileSystem.h"
18 
19 DXFFile::Color DXFFile::_colors[DXF_num_colors] = {
20  { 1, 1, 1 }, // Color 0 is not used.
21  { 1, 0, 0 }, // Color 1 = Red
22  { 1, 1, 0 }, // Color 2 = Yellow
23  { 0, 1, 0 }, // Color 3 = Green
24  { 0, 1, 1 }, // Color 4 = Cyan
25  { 0, 0, 1 }, // Color 5 = Blue
26  { 1, 0, 1 }, // Color 6 = Magenta
27  { 1, 1, 1 }, // Color 7 = Black/White
28  { 0.3, 0.3, 0.3 }, // Color 8 = Gray
29  { 0.7, 0.7, 0.7 }, // Color 9 = Gray
30  { 1, 0, 0 }, // Remaining colors are from the fancy palette.
31  { 1, 0.5, 0.5 },
32  { 0.65, 0, 0 },
33  { 0.65, 0.325, 0.325 },
34  { 0.5, 0, 0 },
35  { 0.5, 0.25, 0.25 },
36  { 0.3, 0, 0 },
37  { 0.3, 0.15, 0.15 },
38  { 0.15, 0, 0 },
39  { 0.15, 0.075, 0.075 },
40  { 1, 0.25, 0 },
41  { 1, 0.625, 0.5 },
42  { 0.65, 0.1625, 0 },
43  { 0.65, 0.4063, 0.325 },
44  { 0.5, 0.125, 0 },
45  { 0.5, 0.3125, 0.25 },
46  { 0.3, 0.075, 0 },
47  { 0.3, 0.1875, 0.15 },
48  { 0.15, 0.0375, 0 },
49  { 0.15, 0.0938, 0.075 },
50  { 1, 0.5, 0 },
51  { 1, 0.75, 0.5 },
52  { 0.65, 0.325, 0 },
53  { 0.65, 0.4875, 0.325 },
54  { 0.5, 0.25, 0 },
55  { 0.5, 0.375, 0.25 },
56  { 0.3, 0.15, 0 },
57  { 0.3, 0.225, 0.15 },
58  { 0.15, 0.075, 0 },
59  { 0.15, 0.1125, 0.075 },
60  { 1, 0.75, 0 },
61  { 1, 0.875, 0.5 },
62  { 0.65, 0.4875, 0 },
63  { 0.65, 0.5688, 0.325 },
64  { 0.5, 0.375, 0 },
65  { 0.5, 0.4375, 0.25 },
66  { 0.3, 0.225, 0 },
67  { 0.3, 0.2625, 0.15 },
68  { 0.15, 0.1125, 0 },
69  { 0.15, 0.1313, 0.075 },
70  { 1, 1, 0 },
71  { 1, 1, 0.5 },
72  { 0.65, 0.65, 0 },
73  { 0.65, 0.65, 0.325 },
74  { 0.5, 0.5, 0 },
75  { 0.5, 0.5, 0.25 },
76  { 0.3, 0.3, 0 },
77  { 0.3, 0.3, 0.15 },
78  { 0.15, 0.15, 0 },
79  { 0.15, 0.15, 0.075 },
80  { 0.75, 1, 0 },
81  { 0.875, 1, 0.5 },
82  { 0.4875, 0.65, 0 },
83  { 0.5688, 0.65, 0.325 },
84  { 0.375, 0.5, 0 },
85  { 0.4375, 0.5, 0.25 },
86  { 0.225, 0.3, 0 },
87  { 0.2625, 0.3, 0.15 },
88  { 0.1125, 0.15, 0 },
89  { 0.1313, 0.15, 0.075 },
90  { 0.5, 1, 0 },
91  { 0.75, 1, 0.5 },
92  { 0.325, 0.65, 0 },
93  { 0.4875, 0.65, 0.325 },
94  { 0.25, 0.5, 0 },
95  { 0.375, 0.5, 0.25 },
96  { 0.15, 0.3, 0 },
97  { 0.225, 0.3, 0.15 },
98  { 0.075, 0.15, 0 },
99  { 0.1125, 0.15, 0.075 },
100  { 0.25, 1, 0 },
101  { 0.625, 1, 0.5 },
102  { 0.1625, 0.65, 0 },
103  { 0.4063, 0.65, 0.325 },
104  { 0.125, 0.5, 0 },
105  { 0.3125, 0.5, 0.25 },
106  { 0.075, 0.3, 0 },
107  { 0.1875, 0.3, 0.15 },
108  { 0.0375, 0.15, 0 },
109  { 0.0938, 0.15, 0.075 },
110  { 0, 1, 0 },
111  { 0.5, 1, 0.5 },
112  { 0, 0.65, 0 },
113  { 0.325, 0.65, 0.325 },
114  { 0, 0.5, 0 },
115  { 0.25, 0.5, 0.25 },
116  { 0, 0.3, 0 },
117  { 0.15, 0.3, 0.15 },
118  { 0, 0.15, 0 },
119  { 0.075, 0.15, 0.075 },
120  { 0, 1, 0.25 },
121  { 0.5, 1, 0.625 },
122  { 0, 0.65, 0.1625 },
123  { 0.325, 0.65, 0.4063 },
124  { 0, 0.5, 0.125 },
125  { 0.25, 0.5, 0.3125 },
126  { 0, 0.3, 0.075 },
127  { 0.15, 0.3, 0.1875 },
128  { 0, 0.15, 0.0375 },
129  { 0.075, 0.15, 0.0938 },
130  { 0, 1, 0.5 },
131  { 0.5, 1, 0.75 },
132  { 0, 0.65, 0.325 },
133  { 0.325, 0.65, 0.4875 },
134  { 0, 0.5, 0.25 },
135  { 0.25, 0.5, 0.375 },
136  { 0, 0.3, 0.15 },
137  { 0.15, 0.3, 0.225 },
138  { 0, 0.15, 0.075 },
139  { 0.075, 0.15, 0.1125 },
140  { 0, 1, 0.75 },
141  { 0.5, 1, 0.875 },
142  { 0, 0.65, 0.4875 },
143  { 0.325, 0.65, 0.5688 },
144  { 0, 0.5, 0.375 },
145  { 0.25, 0.5, 0.4375 },
146  { 0, 0.3, 0.225 },
147  { 0.15, 0.3, 0.2625 },
148  { 0, 0.15, 0.1125 },
149  { 0.075, 0.15, 0.1313 },
150  { 0, 1, 1 },
151  { 0.5, 1, 1 },
152  { 0, 0.65, 0.65 },
153  { 0.325, 0.65, 0.65 },
154  { 0, 0.5, 0.5 },
155  { 0.25, 0.5, 0.5 },
156  { 0, 0.3, 0.3 },
157  { 0.15, 0.3, 0.3 },
158  { 0, 0.15, 0.15 },
159  { 0.075, 0.15, 0.15 },
160  { 0, 0.75, 1 },
161  { 0.5, 0.875, 1 },
162  { 0, 0.4875, 0.65 },
163  { 0.325, 0.5688, 0.65 },
164  { 0, 0.375, 0.5 },
165  { 0.25, 0.4375, 0.5 },
166  { 0, 0.225, 0.3 },
167  { 0.15, 0.2625, 0.3 },
168  { 0, 0.1125, 0.15 },
169  { 0.075, 0.1313, 0.15 },
170  { 0, 0.5, 1 },
171  { 0.5, 0.75, 1 },
172  { 0, 0.325, 0.65 },
173  { 0.325, 0.4875, 0.65 },
174  { 0, 0.25, 0.5 },
175  { 0.25, 0.375, 0.5 },
176  { 0, 0.15, 0.3 },
177  { 0.15, 0.225, 0.3 },
178  { 0, 0.075, 0.15 },
179  { 0.075, 0.1125, 0.15 },
180  { 0, 0.25, 1 },
181  { 0.5, 0.625, 1 },
182  { 0, 0.1625, 0.65 },
183  { 0.325, 0.4063, 0.65 },
184  { 0, 0.125, 0.5 },
185  { 0.25, 0.3125, 0.5 },
186  { 0, 0.075, 0.3 },
187  { 0.15, 0.1875, 0.3 },
188  { 0, 0.0375, 0.15 },
189  { 0.075, 0.0938, 0.15 },
190  { 0, 0, 1 },
191  { 0.5, 0.5, 1 },
192  { 0, 0, 0.65 },
193  { 0.325, 0.325, 0.65 },
194  { 0, 0, 0.5 },
195  { 0.25, 0.25, 0.5 },
196  { 0, 0, 0.3 },
197  { 0.15, 0.15, 0.3 },
198  { 0, 0, 0.15 },
199  { 0.075, 0.075, 0.15 },
200  { 0.25, 0, 1 },
201  { 0.625, 0.5, 1 },
202  { 0.1625, 0, 0.65 },
203  { 0.4063, 0.325, 0.65 },
204  { 0.125, 0, 0.5 },
205  { 0.3125, 0.25, 0.5 },
206  { 0.075, 0, 0.3 },
207  { 0.1875, 0.15, 0.3 },
208  { 0.0375, 0, 0.15 },
209  { 0.0938, 0.075, 0.15 },
210  { 0.5, 0, 1 },
211  { 0.75, 0.5, 1 },
212  { 0.325, 0, 0.65 },
213  { 0.4875, 0.325, 0.65 },
214  { 0.25, 0, 0.5 },
215  { 0.375, 0.25, 0.5 },
216  { 0.15, 0, 0.3 },
217  { 0.225, 0.15, 0.3 },
218  { 0.075, 0, 0.15 },
219  { 0.1125, 0.075, 0.15 },
220  { 0.75, 0, 1 },
221  { 0.875, 0.5, 1 },
222  { 0.4875, 0, 0.65 },
223  { 0.5688, 0.325, 0.65 },
224  { 0.375, 0, 0.5 },
225  { 0.4375, 0.25, 0.5 },
226  { 0.225, 0, 0.3 },
227  { 0.2625, 0.15, 0.3 },
228  { 0.1125, 0, 0.15 },
229  { 0.1313, 0.075, 0.15 },
230  { 1, 0, 1 },
231  { 1, 0.5, 1 },
232  { 0.65, 0, 0.65 },
233  { 0.65, 0.325, 0.65 },
234  { 0.5, 0, 0.5 },
235  { 0.5, 0.25, 0.5 },
236  { 0.3, 0, 0.3 },
237  { 0.3, 0.15, 0.3 },
238  { 0.15, 0, 0.15 },
239  { 0.15, 0.075, 0.15 },
240  { 1, 0, 0.75 },
241  { 1, 0.5, 0.875 },
242  { 0.65, 0, 0.4875 },
243  { 0.65, 0.325, 0.5688 },
244  { 0.5, 0, 0.375 },
245  { 0.5, 0.25, 0.4375 },
246  { 0.3, 0, 0.225 },
247  { 0.3, 0.15, 0.2625 },
248  { 0.15, 0, 0.1125 },
249  { 0.15, 0.075, 0.1313 },
250  { 1, 0, 0.5 },
251  { 1, 0.5, 0.75 },
252  { 0.65, 0, 0.325 },
253  { 0.65, 0.325, 0.4875 },
254  { 0.5, 0, 0.25 },
255  { 0.5, 0.25, 0.375 },
256  { 0.3, 0, 0.15 },
257  { 0.3, 0.15, 0.225 },
258  { 0.15, 0, 0.075 },
259  { 0.15, 0.075, 0.1125 },
260  { 1, 0, 0.25 },
261  { 1, 0.5, 0.625 },
262  { 0.65, 0, 0.1625 },
263  { 0.65, 0.325, 0.4063 },
264  { 0.5, 0, 0.125 },
265  { 0.5, 0.25, 0.3125 },
266  { 0.3, 0, 0.075 },
267  { 0.3, 0.15, 0.1875 },
268  { 0.15, 0, 0.0375 },
269  { 0.15, 0.075, 0.0938 },
270  { 0.33, 0.33, 0.33 },
271  { 0.464, 0.464, 0.464 },
272  { 0.598, 0.598, 0.598 },
273  { 0.732, 0.732, 0.732 },
274  { 0.866, 0.866, 0.866 },
275  { 1, 1, 1 },
276 };
277 
278 
279 ////////////////////////////////////////////////////////////////////
280 // Function: DXFFile::Constructor
281 // Access: Public
282 // Description:
283 ////////////////////////////////////////////////////////////////////
284 DXFFile::
285 DXFFile() {
286  _in = NULL;
287  _owns_in = false;
288  _layer = NULL;
289  reset_entity();
290  _color_index = -1;
291 }
292 
293 ////////////////////////////////////////////////////////////////////
294 // Function: DXFFile::Destructor
295 // Access: Public, Virtual
296 // Description:
297 ////////////////////////////////////////////////////////////////////
298 DXFFile::
299 ~DXFFile() {
300  if (_owns_in) {
302  vfs->close_read_file(_in);
303  }
304 }
305 
306 
307 ////////////////////////////////////////////////////////////////////
308 // Function: DXFFile::process
309 // Access: Public
310 // Description: Opens the indicated filename and reads it as a DXF
311 // file.
312 ////////////////////////////////////////////////////////////////////
313 void DXFFile::
314 process(Filename filename) {
315  filename.set_text();
316 
318  istream *in = vfs->open_read_file(filename, true);
319  if (in == (istream *)NULL) {
320  return;
321  }
322  process(in, true);
323 }
324 
325 
326 ////////////////////////////////////////////////////////////////////
327 // Function: DXFFile::process
328 // Access: Public
329 // Description: Reads the indicated stream as a DXF file. If owns_in
330 // is true, then the istream will be deleted via
331 // vfs->close_read_file() when the DXFFile object
332 // destructs.
333 ////////////////////////////////////////////////////////////////////
334 void DXFFile::
335 process(istream *in, bool owns_in) {
336  if (_owns_in) {
338  vfs->close_read_file(_in);
339  }
340  _in = in;
341  _owns_in = owns_in;
342  _state = ST_top;
343 
344  begin_file();
345  while (_state != ST_done && _state != ST_error) {
346  if (get_group()) {
347  switch (_state) {
348  case ST_top:
349  state_top();
350  break;
351 
352  case ST_section:
353  state_section();
354  break;
355 
356  case ST_entity:
357  state_entity();
358  break;
359 
360  case ST_verts:
361  state_verts();
362  break;
363 
364  default:
365  break;
366  }
367  }
368  }
369 }
370 
371 
372 
373 ////////////////////////////////////////////////////////////////////
374 // Function: DXFFile::Begin File
375 // Access: Public, Virtual
376 // Description: A hook for user code, if desired. This function is
377 // called whenever processing begins on the DXF file.
378 ////////////////////////////////////////////////////////////////////
379 void DXFFile::
381 }
382 
383 
384 ////////////////////////////////////////////////////////////////////
385 // Function: DXFFile::begin_section
386 // Access: Public, Virtual
387 // Description: A hook for user code, if desired. This function is
388 // called whenever a new section in the DXF file is
389 // encountered.
390 ////////////////////////////////////////////////////////////////////
391 void DXFFile::
393 }
394 
395 
396 ////////////////////////////////////////////////////////////////////
397 // Function: DXFFile::done_vertex
398 // Access: Public, Virtual
399 // Description: A hook for user code, if desired. This function is
400 // called whenever a vertex is read from the DXF file.
401 // This function has the default behavior of adding the
402 // vertex to the _verts list, so that when done_entity()
403 // is called later, it will have the complete list of
404 // vertices available to it.
405 ////////////////////////////////////////////////////////////////////
406 void DXFFile::
408  DXFVertex v;
409  v._p = _p;
410  _verts.push_back(v);
411 }
412 
413 
414 ////////////////////////////////////////////////////////////////////
415 // Function: DXFFile::done_entity
416 // Access: Public, Virtual
417 // Description: This is the primary hook for user code. This
418 // function is called when an entity is read from the
419 // DXF file. This may be something like a polygon,
420 // point, or a polygon mesh: any geometry. It is up to
421 // the user code to override this function and do
422 // something interesting with each piece of geometry
423 // that is read.
424 ////////////////////////////////////////////////////////////////////
425 void DXFFile::
427 }
428 
429 
430 ////////////////////////////////////////////////////////////////////
431 // Function: DXFFile::end_section
432 // Access: Public, Virtual
433 // Description: A hook for user code, if desired. This function is
434 // called as each section in the DXF file is finished.
435 ////////////////////////////////////////////////////////////////////
436 void DXFFile::
438 }
439 
440 
441 ////////////////////////////////////////////////////////////////////
442 // Function: DXFFile::end_file
443 // Access: Public, Virtual
444 // Description: A hook for user code, if desired. This function is
445 // called when the DXF processing is complete.
446 ////////////////////////////////////////////////////////////////////
447 void DXFFile::
449 }
450 
451 
452 ////////////////////////////////////////////////////////////////////
453 // Function: DXFFile::Error
454 // Access: Public, Virtual
455 // Description: A hook for user code, if desired. This function is
456 // called when some unexpected error occurs while
457 // reading the DXF file.
458 ////////////////////////////////////////////////////////////////////
459 void DXFFile::
460 error() {
461  nout << "Error!\n";
462 }
463 
464 
465 
466 ////////////////////////////////////////////////////////////////////
467 // Function: DXFFile::find_color
468 // Access: Public, Static
469 // Description: Returns the index of the closest matching AutoCAD
470 // color to the indicated r, g, b.
471 ////////////////////////////////////////////////////////////////////
472 int DXFFile::
473 find_color(double r, double g, double b) {
474  double best_diff = 4.0; // 4 is greater than our expected max, 3.
475  int best_index = 7;
476 
477  for (int i = 0; i < 255; i++) {
478  double diff = ((r - _colors[i].r) * (r - _colors[i].r) +
479  (g - _colors[i].g) * (g - _colors[i].g) +
480  (b - _colors[i].b) * (b - _colors[i].b));
481  if (diff < best_diff) {
482  best_diff = diff;
483  best_index = i;
484  }
485  }
486 
487  return best_index;
488 }
489 
490 ////////////////////////////////////////////////////////////////////
491 // Function: DXFFile::get_color
492 // Access: Public
493 // Description: This is a convenience function to return the r,g,b
494 // color of the current entity (at the time of
495 // done_entity()). It's based on the _color_index value
496 // that was read from the DXF file.
497 ////////////////////////////////////////////////////////////////////
499 get_color() const {
500  if (_color_index >= 0 && _color_index <= 255) {
501  return _colors[_color_index];
502  }
503  return _colors[0];
504 }
505 
506 
507 ////////////////////////////////////////////////////////////////////
508 // Function: DXFFile::ocs_2_wcs
509 // Access: Public
510 // Description: Assuming the current entity is a planar-based entity,
511 // for instance, a 2-d polygon (as opposed to a 3-d
512 // polygon), this converts the coordinates from the
513 // funny planar coordinate system to the world
514 // coordinates. It converts the _p value of the entity,
515 // as well as all vertices in the _verts list.
516 ////////////////////////////////////////////////////////////////////
517 void DXFFile::
519  compute_ocs();
520 
521  // Convert the entity's position.
522  _p = _p * _ocs2wcs;
523 
524  // Maybe we have these coordinates too.
525  _q = _q * _ocs2wcs;
526  _r = _r * _ocs2wcs;
527  _s = _s * _ocs2wcs;
528 
529  // If there are any vertices, convert them too.
530  DXFVertices::iterator vi;
531  for (vi = _verts.begin(); vi != _verts.end(); ++vi) {
532  (*vi)._p = (*vi)._p * _ocs2wcs;
533  }
534 }
535 
536 
537 ////////////////////////////////////////////////////////////////////
538 // Function: DXFFile::compute_ocs
539 // Access: Protected
540 // Description: Computes the matrix used to convert from the planar
541 // coordinate system to world coordinates.
542 ////////////////////////////////////////////////////////////////////
543 void DXFFile::
544 compute_ocs() {
545  // A 2-d entity's vertices might be defined in an "Object Coordinate
546  // System" which has a funny definition. Its Z axis is defined by
547  // _z, and its X and Y axes are inferred from that. The origin is
548  // the same as the world coordinate system's origin.
549 
550  // The Z axis is _z. Determine the x and y axes.
551  LVector3d x, y;
552 
553  if (fabs(_z[0]) < 1.0/64.0 && fabs(_z[1]) < 1.0/64.0) {
554  x = cross(LVector3d(0.0, 1.0, 0.0), _z);
555  } else {
556  x = cross(LVector3d(0.0, 0.0, 1.0), _z);
557  }
558  x.normalize();
559  y = cross(x, _z);
560  y.normalize();
561 
562  // Now build a rotate matrix from these vectors.
563  LMatrix4d
564  ocs( x[0], x[1], x[2], 0,
565  y[0], y[1], y[2], 0,
566  _z[0], _z[1], _z[2], 0,
567  0, 0, 0, 1);
568 
569  _ocs2wcs.invert_from(ocs);
570 }
571 
572 
573 ////////////////////////////////////////////////////////////////////
574 // Function: DXFFile::get_group
575 // Access: Protected
576 // Description: Reads the next code, string pair from the DXF file.
577 // This is the basic unit of data in a DXF file.
578 ////////////////////////////////////////////////////////////////////
579 bool DXFFile::
580 get_group() {
581  istream &in = *_in;
582  do {
583  in >> _code;
584  if (!in) {
585  change_state(ST_error);
586  return false;
587  }
588 
589  // Now skip past exactly one newline character and any number of
590  // other whitespace characters.
591  while (in && in.peek() != '\n') {
592  in.get();
593  }
594  in.get();
595  while (in && isspace(in.peek()) && in.peek() != '\n') {
596  in.get();
597  }
598 
599  getline(in, _string);
600  _string = trim_right(_string);
601 
602  if (!in) {
603  change_state(ST_error);
604  return false;
605  }
606 
607  // If we just read a comment, go back and get another one.
608  } while (_code == 999);
609 
610  return true;
611 }
612 
613 
614 ////////////////////////////////////////////////////////////////////
615 // Function: DXFFile::change_state
616 // Access: Protected
617 // Description: Called as new nodes are read to update the internal
618 // state correctly.
619 ////////////////////////////////////////////////////////////////////
620 void DXFFile::
621 change_state(State new_state) {
622  if (_state == ST_verts) {
623  done_vertex();
624  _p.set(0.0, 0.0, 0.0);
625  _q.set(0.0, 0.0, 0.0);
626  _r.set(0.0, 0.0, 0.0);
627  _s.set(0.0, 0.0, 0.0);
628  }
629  if ((_state == ST_entity || _state == ST_verts) &&
630  new_state != ST_verts) {
631  // We finish an entity when we read a new entity, or when we've
632  // read the last vertex (if we were scanning the vertices after an
633  // entity).
634  done_entity();
635  reset_entity();
636  }
637  switch (new_state) {
638  case ST_top:
639  end_section();
640  break;
641 
642  case ST_done:
643  end_file();
644  break;
645 
646  default:
647  break;
648  }
649  _state = new_state;
650 }
651 
652 
653 ////////////////////////////////////////////////////////////////////
654 // Function: DXFFile::change_section
655 // Access: Protected
656 // Description:
657 ////////////////////////////////////////////////////////////////////
658 void DXFFile::
659 change_section(Section new_section) {
660  change_state(ST_section);
661  _section = new_section;
662  begin_section();
663 }
664 
665 
666 ////////////////////////////////////////////////////////////////////
667 // Function: DXFFile::change_layer
668 // Access: Protected
669 // Description: Given a newly read layer name, sets the _layer
670 // pointer to point to the associate layer. If the
671 // layer name has not been encountered before, creates a
672 // new layer definition.
673 ////////////////////////////////////////////////////////////////////
674 void DXFFile::
675 change_layer(const string &layer_name) {
676  if (_layer == NULL || _layer->get_name() != layer_name) {
677  _layer = _layers.get_layer(layer_name, this);
678  }
679 }
680 
681 
682 ////////////////////////////////////////////////////////////////////
683 // Function: DXFFile::change_entity
684 // Access: Protected
685 // Description:
686 ////////////////////////////////////////////////////////////////////
687 void DXFFile::
688 change_entity(Entity new_entity) {
689  if (new_entity == EN_vertex && _vertices_follow) {
690  // If we read a new vertex and we're still scanning the vertices
691  // that follow an entity, keep scanning it--we haven't finished
692  // the entity yet.
693  change_state(ST_verts);
694 
695  } else {
696  // Otherwise, begin a new entity.
697  change_state(ST_entity);
698  _entity = new_entity;
699  }
700 }
701 
702 
703 ////////////////////////////////////////////////////////////////////
704 // Function: DXFFile::reset_entity
705 // Access: Protected
706 // Description: Resets the current entity to its initial, default
707 // state prior to reading a new entity.
708 ////////////////////////////////////////////////////////////////////
709 void DXFFile::
710 reset_entity() {
711  _p.set(0.0, 0.0, 0.0);
712  _q.set(0.0, 0.0, 0.0);
713  _r.set(0.0, 0.0, 0.0);
714  _s.set(0.0, 0.0, 0.0);
715  _z.set(0.0, 0.0, 1.0);
716  _vertices_follow = false;
717  //_color_index = -1;
718 
719  _verts.erase(_verts.begin(), _verts.end());
720 }
721 
722 
723 ////////////////////////////////////////////////////////////////////
724 // Function: DXFFile::state_top
725 // Access: Protected
726 // Description: Does the DXF processing when we are at the top of the
727 // file, outside of any section.
728 ////////////////////////////////////////////////////////////////////
729 void DXFFile::
730 state_top() {
731  if (_code != 0) {
732  nout << "Group code 0 not found at top level; found code " << _code
733  << " instead.\n";
734  change_state(ST_error);
735  } else {
736  if (_string == "SECTION") {
737  if (get_group()) {
738  if (_code != 2) {
739  nout << "Group code 0 not immediately followed by code 2; found code "
740  << _code << " instead.\n";
741  } else {
742  if (_string == "HEADER") {
743  change_section(SE_header);
744  } else if (_string == "TABLES") {
745  change_section(SE_tables);
746  } else if (_string == "BLOCKS") {
747  change_section(SE_blocks);
748  } else if (_string == "ENTITIES") {
749  change_section(SE_entities);
750  } else if (_string == "OBJECTS") {
751  change_section(SE_objects);
752  } else {
753  change_section(SE_unknown);
754  }
755  }
756  }
757  } else if (_string == "EOF") {
758  change_state(ST_done);
759  } else {
760  nout << "Unexpected section at top level: '" << _string << "'\n";
761  change_state(ST_error);
762  }
763  }
764 }
765 
766 
767 
768 ////////////////////////////////////////////////////////////////////
769 // Function: DXFFile::state_section
770 // Access: Protected
771 // Description: Does the DXF processing when we are within some
772 // section.
773 ////////////////////////////////////////////////////////////////////
774 void DXFFile::
775 state_section() {
776  string tail;
777 
778  switch (_code) {
779  case 0:
780  if (_string == "ENDSEC") {
781  change_state(ST_top);
782  } else {
783  if (_section == SE_entities) {
784  if (_string == "3DFACE") {
785  change_entity(EN_3dface);
786  } else if (_string == "POINT") {
787  change_entity(EN_point);
788  } else if (_string == "INSERT") {
789  change_entity(EN_insert);
790  } else if (_string == "VERTEX") {
791  change_entity(EN_vertex);
792  } else if (_string == "POLYLINE") {
793  change_entity(EN_polyline);
794  } else {
795  change_entity(EN_unknown);
796  }
797  }
798  }
799  break;
800 
801  case 8:
802  change_layer(_string);
803  break;
804 
805  case 62: // Color.
806  _color_index = string_to_int(_string, tail);
807  break;
808 
809  default:
810  break;
811  }
812 }
813 
814 
815 ////////////////////////////////////////////////////////////////////
816 // Function: DXFFile::state_entity
817 // Access: Protected
818 // Description: Does the DXF processing when we are reading an
819 // entity.
820 ////////////////////////////////////////////////////////////////////
821 void DXFFile::
822 state_entity() {
823  string tail;
824 
825  switch (_code) {
826  case 0:
827  state_section();
828  break;
829 
830  case 8:
831  change_layer(_string);
832  break;
833 
834  case 10:
835  _p[0] = string_to_double(_string, tail);
836  break;
837 
838  case 11:
839  _q[0] = string_to_double(_string, tail);
840  break;
841 
842  case 12:
843  _r[0] = string_to_double(_string, tail);
844  break;
845 
846  case 13:
847  _s[0] = string_to_double(_string, tail);
848  break;
849 
850  case 20:
851  _p[1] = string_to_double(_string, tail);
852  break;
853 
854  case 21:
855  _q[1] = string_to_double(_string, tail);
856  break;
857 
858  case 22:
859  _r[1] = string_to_double(_string, tail);
860  break;
861 
862  case 23:
863  _s[1] = string_to_double(_string, tail);
864  break;
865 
866  case 30:
867  _p[2] = string_to_double(_string, tail);
868  break;
869 
870  case 31:
871  _q[2] = string_to_double(_string, tail);
872  break;
873 
874  case 32:
875  _r[2] = string_to_double(_string, tail);
876  break;
877 
878  case 33:
879  _s[2] = string_to_double(_string, tail);
880  break;
881 
882  case 62: // Color.
883  _color_index = string_to_int(_string, tail);
884  break;
885 
886  case 66: // Vertices-follow.
887  _vertices_follow = (string_to_int(_string, tail) != 0);
888  break;
889 
890  case 70: // Polyline flags.
891  _flags = string_to_int(_string, tail);
892  break;
893 
894  case 210:
895  _z[0] = string_to_double(_string, tail);
896  break;
897 
898  case 220:
899  _z[1] = string_to_double(_string, tail);
900  break;
901 
902  case 230:
903  _z[2] = string_to_double(_string, tail);
904  break;
905 
906  default:
907  break;
908  }
909 }
910 
911 
912 ////////////////////////////////////////////////////////////////////
913 // Function: DXFFile::state_verts
914 // Access: Protected
915 // Description: Does the DXF processing when we are reading the list
916 // of vertices that might follow an entity.
917 ////////////////////////////////////////////////////////////////////
918 void DXFFile::
919 state_verts() {
920  string tail;
921 
922  switch (_code) {
923  case 0:
924  state_section();
925  break;
926 
927  case 8:
928  change_layer(_string);
929  break;
930 
931  case 10:
932  _p[0] = string_to_double(_string, tail);
933  break;
934 
935  case 20:
936  _p[1] = string_to_double(_string, tail);
937  break;
938 
939  case 30:
940  _p[2] = string_to_double(_string, tail);
941  break;
942 
943  default:
944  break;
945  }
946 }
947 
948 
949 ostream &operator << (ostream &out, const DXFFile::State &state) {
950  switch (state) {
951  case DXFFile::ST_top:
952  return out << "ST_top";
953  case DXFFile::ST_section:
954  return out << "ST_section";
955  case DXFFile::ST_entity:
956  return out << "ST_entity";
957  case DXFFile::ST_verts:
958  return out << "ST_verts";
959  case DXFFile::ST_error:
960  return out << "ST_error";
961  case DXFFile::ST_done:
962  return out << "ST_done";
963  }
964  return out << "Unknown state";
965 }
966 
967 ostream &operator << (ostream &out, const DXFFile::Section &section) {
968  switch (section) {
969  case DXFFile::SE_unknown:
970  return out << "SE_unknown";
971  case DXFFile::SE_header:
972  return out << "SE_header";
973  case DXFFile::SE_tables:
974  return out << "SE_tables";
975  case DXFFile::SE_blocks:
976  return out << "SE_blocks";
977  case DXFFile::SE_entities:
978  return out << "SE_entities";
979  case DXFFile::SE_objects:
980  return out << "SE_objects";
981  }
982  return out << "Unknown section";
983 }
984 
985 ostream &operator << (ostream &out, const DXFFile::Entity &entity) {
986  switch (entity) {
987  case DXFFile::EN_unknown:
988  return out << "EN_unknown";
989  case DXFFile::EN_3dface:
990  return out << "EN_3dface";
991  case DXFFile::EN_point:
992  return out << "EN_point";
993  case DXFFile::EN_insert:
994  return out << "EN_insert";
995  case DXFFile::EN_vertex:
996  return out << "EN_vertex";
997  case DXFFile::EN_polyline:
998  return out << "EN_polyline";
999  }
1000  return out << "Unknown entity";
1001 }
1002 
This is a 4-by-4 transform matrix.
Definition: lmatrix.h:4716
virtual void end_file()
A hook for user code, if desired.
Definition: dxfFile.cxx:448
A hierarchy of directories and files that appears to be one continuous file system, even though the files may originate from several different sources that may not be related to the actual OS&#39;s file system.
virtual void begin_section()
A hook for user code, if desired.
Definition: dxfFile.cxx:392
DXFLayer * get_layer(const string &name, DXFFile *dxffile)
Looks up the layer name in the map, and returns a pointer to the associated DXFLayer.
Definition: dxfLayerMap.cxx:30
void set_text()
Indicates that the filename represents a text file.
Definition: filename.I:507
static void close_read_file(istream *stream)
Closes a file opened by a previous call to open_read_file().
bool normalize()
Normalizes the vector in place.
Definition: lvecBase3.h:2132
virtual void error()
A hook for user code, if desired.
Definition: dxfFile.cxx:460
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:44
virtual void begin_file()
A hook for user code, if desired.
Definition: dxfFile.cxx:380
virtual void done_entity()
This is the primary hook for user code.
Definition: dxfFile.cxx:426
static VirtualFileSystem * get_global_ptr()
Returns the default global VirtualFileSystem.
bool invert_from(const LMatrix4d &other)
Computes the inverse of the other matrix, and stores the result in this matrix.
Definition: lmatrix.h:6438
istream * open_read_file(const Filename &filename, bool auto_unwrap) const
Convenience function; returns a newly allocated istream if the file exists and can be read...
const Color & get_color() const
This is a convenience function to return the r,g,b color of the current entity (at the time of done_e...
Definition: dxfFile.cxx:499
virtual void end_section()
A hook for user code, if desired.
Definition: dxfFile.cxx:437
This is a three-component vector distance (as opposed to a three-component point, which represents a ...
Definition: lvector3.h:746
Stored within DXFFile, this is the basic Vertex data of a DXF file.
Definition: dxfVertex.h:30
void ocs_2_wcs()
Assuming the current entity is a planar-based entity, for instance, a 2-d polygon (as opposed to a 3-...
Definition: dxfFile.cxx:518
static int find_color(double r, double g, double b)
Returns the index of the closest matching AutoCAD color to the indicated r, g, b. ...
Definition: dxfFile.cxx:473
virtual void done_vertex()
A hook for user code, if desired.
Definition: dxfFile.cxx:407
void process(Filename filename)
Opens the indicated filename and reads it as a DXF file.
Definition: dxfFile.cxx:314