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