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,...
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...