dxf reader

This commit is contained in:
David Rose 2004-05-04 19:50:48 +00:00
parent 4c3d7e893c
commit 63d2fad3dd
13 changed files with 1645 additions and 0 deletions

View File

@ -0,0 +1,17 @@
#begin ss_lib_target
#define TARGET dxf
#define LOCAL_LIBS pandatoolbase
#define OTHER_LIBS \
mathutil:c linmath:c panda:m \
dtoolbase:c dtool:m
#define UNIX_SYS_LIBS m
#define SOURCES \
dxfFile.cxx dxfFile.h dxfLayer.h dxfLayerMap.cxx dxfLayerMap.h \
dxfVertex.cxx dxfVertex.h dxfVertexMap.cxx dxfVertexMap.h
#define INSTALL_HEADERS \
dxfFile.h dxfLayer.h dxfLayerMap.h dxfVertex.h dxfVertexMap.h
#end ss_lib_target

View File

@ -0,0 +1,979 @@
// Filename: dxfFile.cxx
// Created by: drose (04May04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "dxfFile.h"
#include "string_utils.h"
DXFFile::Color DXFFile::_colors[DXF_num_colors] = {
{ 1, 1, 1 }, // Color 0 is not used.
{ 1, 0, 0 }, // Color 1 = Red
{ 1, 1, 0 }, // Color 2 = Yellow
{ 0, 1, 0 }, // Color 3 = Green
{ 0, 1, 1 }, // Color 4 = Cyan
{ 0, 0, 1 }, // Color 5 = Blue
{ 1, 0, 1 }, // Color 6 = Magenta
{ 1, 1, 1 }, // Color 7 = Black/White
{ 0.3, 0.3, 0.3 }, // Color 8 = Gray
{ 0.7, 0.7, 0.7 }, // Color 9 = Gray
{ 1, 0, 0 }, // Remaining colors are from the fancy palette.
{ 1, 0.5, 0.5 },
{ 0.65, 0, 0 },
{ 0.65, 0.325, 0.325 },
{ 0.5, 0, 0 },
{ 0.5, 0.25, 0.25 },
{ 0.3, 0, 0 },
{ 0.3, 0.15, 0.15 },
{ 0.15, 0, 0 },
{ 0.15, 0.075, 0.075 },
{ 1, 0.25, 0 },
{ 1, 0.625, 0.5 },
{ 0.65, 0.1625, 0 },
{ 0.65, 0.4063, 0.325 },
{ 0.5, 0.125, 0 },
{ 0.5, 0.3125, 0.25 },
{ 0.3, 0.075, 0 },
{ 0.3, 0.1875, 0.15 },
{ 0.15, 0.0375, 0 },
{ 0.15, 0.0938, 0.075 },
{ 1, 0.5, 0 },
{ 1, 0.75, 0.5 },
{ 0.65, 0.325, 0 },
{ 0.65, 0.4875, 0.325 },
{ 0.5, 0.25, 0 },
{ 0.5, 0.375, 0.25 },
{ 0.3, 0.15, 0 },
{ 0.3, 0.225, 0.15 },
{ 0.15, 0.075, 0 },
{ 0.15, 0.1125, 0.075 },
{ 1, 0.75, 0 },
{ 1, 0.875, 0.5 },
{ 0.65, 0.4875, 0 },
{ 0.65, 0.5688, 0.325 },
{ 0.5, 0.375, 0 },
{ 0.5, 0.4375, 0.25 },
{ 0.3, 0.225, 0 },
{ 0.3, 0.2625, 0.15 },
{ 0.15, 0.1125, 0 },
{ 0.15, 0.1313, 0.075 },
{ 1, 1, 0 },
{ 1, 1, 0.5 },
{ 0.65, 0.65, 0 },
{ 0.65, 0.65, 0.325 },
{ 0.5, 0.5, 0 },
{ 0.5, 0.5, 0.25 },
{ 0.3, 0.3, 0 },
{ 0.3, 0.3, 0.15 },
{ 0.15, 0.15, 0 },
{ 0.15, 0.15, 0.075 },
{ 0.75, 1, 0 },
{ 0.875, 1, 0.5 },
{ 0.4875, 0.65, 0 },
{ 0.5688, 0.65, 0.325 },
{ 0.375, 0.5, 0 },
{ 0.4375, 0.5, 0.25 },
{ 0.225, 0.3, 0 },
{ 0.2625, 0.3, 0.15 },
{ 0.1125, 0.15, 0 },
{ 0.1313, 0.15, 0.075 },
{ 0.5, 1, 0 },
{ 0.75, 1, 0.5 },
{ 0.325, 0.65, 0 },
{ 0.4875, 0.65, 0.325 },
{ 0.25, 0.5, 0 },
{ 0.375, 0.5, 0.25 },
{ 0.15, 0.3, 0 },
{ 0.225, 0.3, 0.15 },
{ 0.075, 0.15, 0 },
{ 0.1125, 0.15, 0.075 },
{ 0.25, 1, 0 },
{ 0.625, 1, 0.5 },
{ 0.1625, 0.65, 0 },
{ 0.4063, 0.65, 0.325 },
{ 0.125, 0.5, 0 },
{ 0.3125, 0.5, 0.25 },
{ 0.075, 0.3, 0 },
{ 0.1875, 0.3, 0.15 },
{ 0.0375, 0.15, 0 },
{ 0.0938, 0.15, 0.075 },
{ 0, 1, 0 },
{ 0.5, 1, 0.5 },
{ 0, 0.65, 0 },
{ 0.325, 0.65, 0.325 },
{ 0, 0.5, 0 },
{ 0.25, 0.5, 0.25 },
{ 0, 0.3, 0 },
{ 0.15, 0.3, 0.15 },
{ 0, 0.15, 0 },
{ 0.075, 0.15, 0.075 },
{ 0, 1, 0.25 },
{ 0.5, 1, 0.625 },
{ 0, 0.65, 0.1625 },
{ 0.325, 0.65, 0.4063 },
{ 0, 0.5, 0.125 },
{ 0.25, 0.5, 0.3125 },
{ 0, 0.3, 0.075 },
{ 0.15, 0.3, 0.1875 },
{ 0, 0.15, 0.0375 },
{ 0.075, 0.15, 0.0938 },
{ 0, 1, 0.5 },
{ 0.5, 1, 0.75 },
{ 0, 0.65, 0.325 },
{ 0.325, 0.65, 0.4875 },
{ 0, 0.5, 0.25 },
{ 0.25, 0.5, 0.375 },
{ 0, 0.3, 0.15 },
{ 0.15, 0.3, 0.225 },
{ 0, 0.15, 0.075 },
{ 0.075, 0.15, 0.1125 },
{ 0, 1, 0.75 },
{ 0.5, 1, 0.875 },
{ 0, 0.65, 0.4875 },
{ 0.325, 0.65, 0.5688 },
{ 0, 0.5, 0.375 },
{ 0.25, 0.5, 0.4375 },
{ 0, 0.3, 0.225 },
{ 0.15, 0.3, 0.2625 },
{ 0, 0.15, 0.1125 },
{ 0.075, 0.15, 0.1313 },
{ 0, 1, 1 },
{ 0.5, 1, 1 },
{ 0, 0.65, 0.65 },
{ 0.325, 0.65, 0.65 },
{ 0, 0.5, 0.5 },
{ 0.25, 0.5, 0.5 },
{ 0, 0.3, 0.3 },
{ 0.15, 0.3, 0.3 },
{ 0, 0.15, 0.15 },
{ 0.075, 0.15, 0.15 },
{ 0, 0.75, 1 },
{ 0.5, 0.875, 1 },
{ 0, 0.4875, 0.65 },
{ 0.325, 0.5688, 0.65 },
{ 0, 0.375, 0.5 },
{ 0.25, 0.4375, 0.5 },
{ 0, 0.225, 0.3 },
{ 0.15, 0.2625, 0.3 },
{ 0, 0.1125, 0.15 },
{ 0.075, 0.1313, 0.15 },
{ 0, 0.5, 1 },
{ 0.5, 0.75, 1 },
{ 0, 0.325, 0.65 },
{ 0.325, 0.4875, 0.65 },
{ 0, 0.25, 0.5 },
{ 0.25, 0.375, 0.5 },
{ 0, 0.15, 0.3 },
{ 0.15, 0.225, 0.3 },
{ 0, 0.075, 0.15 },
{ 0.075, 0.1125, 0.15 },
{ 0, 0.25, 1 },
{ 0.5, 0.625, 1 },
{ 0, 0.1625, 0.65 },
{ 0.325, 0.4063, 0.65 },
{ 0, 0.125, 0.5 },
{ 0.25, 0.3125, 0.5 },
{ 0, 0.075, 0.3 },
{ 0.15, 0.1875, 0.3 },
{ 0, 0.0375, 0.15 },
{ 0.075, 0.0938, 0.15 },
{ 0, 0, 1 },
{ 0.5, 0.5, 1 },
{ 0, 0, 0.65 },
{ 0.325, 0.325, 0.65 },
{ 0, 0, 0.5 },
{ 0.25, 0.25, 0.5 },
{ 0, 0, 0.3 },
{ 0.15, 0.15, 0.3 },
{ 0, 0, 0.15 },
{ 0.075, 0.075, 0.15 },
{ 0.25, 0, 1 },
{ 0.625, 0.5, 1 },
{ 0.1625, 0, 0.65 },
{ 0.4063, 0.325, 0.65 },
{ 0.125, 0, 0.5 },
{ 0.3125, 0.25, 0.5 },
{ 0.075, 0, 0.3 },
{ 0.1875, 0.15, 0.3 },
{ 0.0375, 0, 0.15 },
{ 0.0938, 0.075, 0.15 },
{ 0.5, 0, 1 },
{ 0.75, 0.5, 1 },
{ 0.325, 0, 0.65 },
{ 0.4875, 0.325, 0.65 },
{ 0.25, 0, 0.5 },
{ 0.375, 0.25, 0.5 },
{ 0.15, 0, 0.3 },
{ 0.225, 0.15, 0.3 },
{ 0.075, 0, 0.15 },
{ 0.1125, 0.075, 0.15 },
{ 0.75, 0, 1 },
{ 0.875, 0.5, 1 },
{ 0.4875, 0, 0.65 },
{ 0.5688, 0.325, 0.65 },
{ 0.375, 0, 0.5 },
{ 0.4375, 0.25, 0.5 },
{ 0.225, 0, 0.3 },
{ 0.2625, 0.15, 0.3 },
{ 0.1125, 0, 0.15 },
{ 0.1313, 0.075, 0.15 },
{ 1, 0, 1 },
{ 1, 0.5, 1 },
{ 0.65, 0, 0.65 },
{ 0.65, 0.325, 0.65 },
{ 0.5, 0, 0.5 },
{ 0.5, 0.25, 0.5 },
{ 0.3, 0, 0.3 },
{ 0.3, 0.15, 0.3 },
{ 0.15, 0, 0.15 },
{ 0.15, 0.075, 0.15 },
{ 1, 0, 0.75 },
{ 1, 0.5, 0.875 },
{ 0.65, 0, 0.4875 },
{ 0.65, 0.325, 0.5688 },
{ 0.5, 0, 0.375 },
{ 0.5, 0.25, 0.4375 },
{ 0.3, 0, 0.225 },
{ 0.3, 0.15, 0.2625 },
{ 0.15, 0, 0.1125 },
{ 0.15, 0.075, 0.1313 },
{ 1, 0, 0.5 },
{ 1, 0.5, 0.75 },
{ 0.65, 0, 0.325 },
{ 0.65, 0.325, 0.4875 },
{ 0.5, 0, 0.25 },
{ 0.5, 0.25, 0.375 },
{ 0.3, 0, 0.15 },
{ 0.3, 0.15, 0.225 },
{ 0.15, 0, 0.075 },
{ 0.15, 0.075, 0.1125 },
{ 1, 0, 0.25 },
{ 1, 0.5, 0.625 },
{ 0.65, 0, 0.1625 },
{ 0.65, 0.325, 0.4063 },
{ 0.5, 0, 0.125 },
{ 0.5, 0.25, 0.3125 },
{ 0.3, 0, 0.075 },
{ 0.3, 0.15, 0.1875 },
{ 0.15, 0, 0.0375 },
{ 0.15, 0.075, 0.0938 },
{ 0.33, 0.33, 0.33 },
{ 0.464, 0.464, 0.464 },
{ 0.598, 0.598, 0.598 },
{ 0.732, 0.732, 0.732 },
{ 0.866, 0.866, 0.866 },
{ 1, 1, 1 },
};
////////////////////////////////////////////////////////////////////
// Function: DXFFile::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
DXFFile::
DXFFile() {
_layer = NULL;
reset_entity();
}
////////////////////////////////////////////////////////////////////
// Function: DXFFile::Destructor
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
DXFFile::
~DXFFile() {
}
////////////////////////////////////////////////////////////////////
// Function: DXFFile::process
// Access: Public
// Description: Opens the indicated filename and reads it as a DXF
// file.
////////////////////////////////////////////////////////////////////
void DXFFile::
process(Filename filename) {
filename.set_text();
filename.open_read(_in_file);
process(_in_file);
}
////////////////////////////////////////////////////////////////////
// Function: DXFFile::process
// Access: Public
// Description: Reads the indicated stream as a DXF file.
////////////////////////////////////////////////////////////////////
void DXFFile::
process(istream &in) {
_in = ∈
_state = ST_top;
begin_file();
while (_state != ST_done && _state != ST_error) {
if (get_group()) {
switch (_state) {
case ST_top:
state_top();
break;
case ST_section:
state_section();
break;
case ST_entity:
state_entity();
break;
case ST_verts:
state_verts();
break;
default:
break;
}
}
}
}
////////////////////////////////////////////////////////////////////
// Function: DXFFile::Begin File
// Access: Public, Virtual
// Description: A hook for user code, if desired. This function is
// called whenever processing begins on the DXF file.
////////////////////////////////////////////////////////////////////
void DXFFile::
begin_file() {
}
////////////////////////////////////////////////////////////////////
// Function: DXFFile::begin_section
// Access: Public, Virtual
// Description: A hook for user code, if desired. This function is
// called whenever a new section in the DXF file is
// encountered.
////////////////////////////////////////////////////////////////////
void DXFFile::
begin_section() {
}
////////////////////////////////////////////////////////////////////
// Function: DXFFile::done_vertex
// Access: Public, Virtual
// Description: A hook for user code, if desired. This function is
// called whenever a vertex is read from the DXF file.
// This function has the default behavior of adding the
// vertex to the _verts list, so that when done_entity()
// is called later, it will have the complete list of
// vertices available to it.
////////////////////////////////////////////////////////////////////
void DXFFile::
done_vertex() {
DXFVertex v;
v._p = _p;
_verts.push_back(v);
}
////////////////////////////////////////////////////////////////////
// Function: DXFFile::done_entity
// Access: Public, Virtual
// Description: This is the primary hook for user code. This
// function is called when an entity is read from the
// DXF file. This may be something like a polygon,
// point, or a polygon mesh: any geometry. It is up to
// the user code to override this function and do
// something interesting with each piece of geometry
// that is read.
////////////////////////////////////////////////////////////////////
void DXFFile::
done_entity() {
}
////////////////////////////////////////////////////////////////////
// Function: DXFFile::end_section
// Access: Public, Virtual
// Description: A hook for user code, if desired. This function is
// called as each section in the DXF file is finished.
////////////////////////////////////////////////////////////////////
void DXFFile::
end_section() {
}
////////////////////////////////////////////////////////////////////
// Function: DXFFile::end_file
// Access: Public, Virtual
// Description: A hook for user code, if desired. This function is
// called when the DXF processing is complete.
////////////////////////////////////////////////////////////////////
void DXFFile::
end_file() {
}
////////////////////////////////////////////////////////////////////
// Function: DXFFile::Error
// Access: Public, Virtual
// Description: A hook for user code, if desired. This function is
// called when some unexpected error occurs while
// reading the DXF file.
////////////////////////////////////////////////////////////////////
void DXFFile::
error() {
nout << "Error!\n";
}
////////////////////////////////////////////////////////////////////
// Function: DXFFile::find_color
// Access: Public, Static
// Description: Returns the index of the closest matching AutoCAD
// color to the indicated r, g, b.
////////////////////////////////////////////////////////////////////
int DXFFile::
find_color(double r, double g, double b) {
double best_diff = 4.0; // 4 is greater than our expected max, 3.
int best_index = 7;
for (int i = 0; i < 255; i++) {
double diff = ((r - _colors[i].r) * (r - _colors[i].r) +
(g - _colors[i].g) * (g - _colors[i].g) +
(b - _colors[i].b) * (b - _colors[i].b));
if (diff < best_diff) {
best_diff = diff;
best_index = i;
}
}
return best_index;
}
////////////////////////////////////////////////////////////////////
// Function: DXFFile::get_color
// Access: Public
// Description: This is a convenience function to return the r,g,b
// color of the current entity (at the time of
// done_entity()). It's based on the _color_index value
// that was read from the DXF file.
////////////////////////////////////////////////////////////////////
const DXFFile::Color &DXFFile::
get_color() const {
if (_color_index >= 0 && _color_index <= 255) {
return _colors[_color_index];
}
return _colors[0];
}
////////////////////////////////////////////////////////////////////
// Function: DXFFile::ocs_2_wcs
// Access: Public
// Description: Assuming the current entity is a planar-based entity,
// for instance, a 2-d polygon (as opposed to a 3-d
// polygon), this converts the coordinates from the
// funny planar coordinate system to the world
// coordinates. It converts the _p value of the entity,
// as well as all vertices in the _verts list.
////////////////////////////////////////////////////////////////////
void DXFFile::
ocs_2_wcs() {
compute_ocs();
// Convert the entity's position.
_p = _p * _ocs2wcs;
// Maybe we have these coordinates too.
_q = _q * _ocs2wcs;
_r = _r * _ocs2wcs;
_s = _s * _ocs2wcs;
// If there are any vertices, convert them too.
DXFVertices::iterator vi;
for (vi = _verts.begin(); vi != _verts.end(); ++vi) {
(*vi)._p = (*vi)._p * _ocs2wcs;
}
}
////////////////////////////////////////////////////////////////////
// Function: DXFFile::compute_ocs
// Access: Protected
// Description: Computes the matrix used to convert from the planar
// coordinate system to world coordinates.
////////////////////////////////////////////////////////////////////
void DXFFile::
compute_ocs() {
// A 2-d entity's vertices might be defined in an "Object Coordinate
// System" which has a funny definition. Its Z axis is defined by
// _z, and its X and Y axes are inferred from that. The origin is
// the same as the world coordinate system's origin.
// The Z axis is _z. Determine the x and y axes.
LVector3d x, y;
if (fabs(_z[0]) < 1.0/64.0 && fabs(_z[1]) < 1.0/64.0) {
x = cross(LVector3d(0.0, 1.0, 0.0), _z);
} else {
x = cross(LVector3d(0.0, 0.0, 1.0), _z);
}
x.normalize();
y = cross(x, _z);
y.normalize();
// Now build a rotate matrix from these vectors.
LMatrix4d
ocs( x[0], x[1], x[2], 0,
y[0], y[1], y[2], 0,
_z[0], _z[1], _z[2], 0,
0, 0, 0, 1);
_ocs2wcs.invert_from(ocs);
}
////////////////////////////////////////////////////////////////////
// Function: DXFFile::get_group
// Access: Protected
// Description: Reads the next code, string pair from the DXF file.
// This is the basic unit of data in a DXF file.
////////////////////////////////////////////////////////////////////
bool DXFFile::
get_group() {
istream &in = *_in;
do {
in >> _code;
if (!in) {
change_state(ST_error);
return false;
}
// Now skip past exactly one newline character and any number of
// other whitespace characters.
while (in!=0 && in.peek() != '\n') {
in.get();
}
in.get();
while (in!=0 && isspace(in.peek()) && in.peek() != '\n') {
in.get();
}
getline(in, _string);
_string = trim_right(_string);
if (!in) {
change_state(ST_error);
return false;
}
// If we just read a comment, go back and get another one.
} while (_code == 999);
return true;
}
////////////////////////////////////////////////////////////////////
// Function: DXFFile::change_state
// Access: Protected
// Description: Called as new nodes are read to update the internal
// state correctly.
////////////////////////////////////////////////////////////////////
void DXFFile::
change_state(State new_state) {
if (_state == ST_verts) {
done_vertex();
_p.set(0.0, 0.0, 0.0);
_q.set(0.0, 0.0, 0.0);
_r.set(0.0, 0.0, 0.0);
_s.set(0.0, 0.0, 0.0);
}
if ((_state == ST_entity || _state == ST_verts) &&
new_state != ST_verts) {
// We finish an entity when we read a new entity, or when we've
// read the last vertex (if we were scanning the vertices after an
// entity).
done_entity();
reset_entity();
}
switch (new_state) {
case ST_top:
end_section();
break;
case ST_done:
end_file();
break;
default:
break;
}
_state = new_state;
}
////////////////////////////////////////////////////////////////////
// Function: DXFFile::change_section
// Access: Protected
// Description:
////////////////////////////////////////////////////////////////////
void DXFFile::
change_section(Section new_section) {
change_state(ST_section);
_section = new_section;
begin_section();
}
////////////////////////////////////////////////////////////////////
// Function: DXFFile::change_layer
// Access: Protected
// Description: Given a newly read layer name, sets the _layer
// pointer to point to the associate layer. If the
// layer name has not been encountered before, creates a
// new layer definition.
////////////////////////////////////////////////////////////////////
void DXFFile::
change_layer(const string &layer_name) {
if (_layer == NULL || _layer->_name != layer_name) {
_layer = _layers.get_layer(layer_name, this);
}
}
////////////////////////////////////////////////////////////////////
// Function: DXFFile::change_entity
// Access: Protected
// Description:
////////////////////////////////////////////////////////////////////
void DXFFile::
change_entity(Entity new_entity) {
if (new_entity == EN_vertex && _vertices_follow) {
// If we read a new vertex and we're still scanning the vertices
// that follow an entity, keep scanning it--we haven't finished
// the entity yet.
change_state(ST_verts);
} else {
// Otherwise, begin a new entity.
change_state(ST_entity);
_entity = new_entity;
}
}
////////////////////////////////////////////////////////////////////
// Function: DXFFile::reset_entity
// Access: Protected
// Description: Resets the current entity to its initial, default
// state prior to reading a new entity.
////////////////////////////////////////////////////////////////////
void DXFFile::
reset_entity() {
_p.set(0.0, 0.0, 0.0);
_q.set(0.0, 0.0, 0.0);
_r.set(0.0, 0.0, 0.0);
_s.set(0.0, 0.0, 0.0);
_z.set(0.0, 0.0, 1.0);
_vertices_follow = false;
_color_index = -1;
_verts.erase(_verts.begin(), _verts.end());
}
////////////////////////////////////////////////////////////////////
// Function: DXFFile::state_top
// Access: Protected
// Description: Does the DXF processing when we are at the top of the
// file, outside of any section.
////////////////////////////////////////////////////////////////////
void DXFFile::
state_top() {
if (_code != 0) {
nout << "Group code 0 not found at top level; found code " << _code
<< " instead.\n";
change_state(ST_error);
} else {
if (_string == "SECTION") {
if (get_group()) {
if (_code != 2) {
nout << "Group code 0 not immediately followed by code 2; found code "
<< _code << " instead.\n";
} else {
if (_string == "HEADER") {
change_section(SE_header);
} else if (_string == "TABLES") {
change_section(SE_tables);
} else if (_string == "BLOCKS") {
change_section(SE_blocks);
} else if (_string == "ENTITIES") {
change_section(SE_entities);
} else if (_string == "OBJECTS") {
change_section(SE_objects);
} else {
change_section(SE_unknown);
}
}
}
} else if (_string == "EOF") {
change_state(ST_done);
} else {
nout << "Unexpected section at top level: '" << _string << "'\n";
change_state(ST_error);
}
}
}
////////////////////////////////////////////////////////////////////
// Function: DXFFile::state_section
// Access: Protected
// Description: Does the DXF processing when we are within some
// section.
////////////////////////////////////////////////////////////////////
void DXFFile::
state_section() {
switch (_code) {
case 0:
if (_string == "ENDSEC") {
change_state(ST_top);
} else {
if (_section == SE_entities) {
if (_string == "3DFACE") {
change_entity(EN_3dface);
} else if (_string == "POINT") {
change_entity(EN_point);
} else if (_string == "INSERT") {
change_entity(EN_insert);
} else if (_string == "VERTEX") {
change_entity(EN_vertex);
} else if (_string == "POLYLINE") {
change_entity(EN_polyline);
} else {
change_entity(EN_unknown);
}
}
}
break;
case 8:
change_layer(_string);
break;
default:
break;
}
}
////////////////////////////////////////////////////////////////////
// Function: DXFFile::state_entity
// Access: Protected
// Description: Does the DXF processing when we are reading an
// entity.
////////////////////////////////////////////////////////////////////
void DXFFile::
state_entity() {
string tail;
switch (_code) {
case 0:
state_section();
break;
case 8:
change_layer(_string);
break;
case 10:
_p[0] = string_to_double(_string, tail);
break;
case 11:
_q[0] = string_to_double(_string, tail);
break;
case 12:
_r[0] = string_to_double(_string, tail);
break;
case 13:
_s[0] = string_to_double(_string, tail);
break;
case 20:
_p[1] = string_to_double(_string, tail);
break;
case 21:
_q[1] = string_to_double(_string, tail);
break;
case 22:
_r[1] = string_to_double(_string, tail);
break;
case 23:
_s[1] = string_to_double(_string, tail);
break;
case 30:
_p[2] = string_to_double(_string, tail);
break;
case 31:
_q[2] = string_to_double(_string, tail);
break;
case 32:
_r[2] = string_to_double(_string, tail);
break;
case 33:
_s[2] = string_to_double(_string, tail);
break;
case 62: // Color.
_color_index = string_to_int(_string, tail);
break;
case 66: // Vertices-follow.
_vertices_follow = string_to_int(_string, tail);
break;
case 70: // Polyline flags.
_flags = string_to_int(_string, tail);
break;
case 210:
_z[0] = string_to_double(_string, tail);
break;
case 220:
_z[1] = string_to_double(_string, tail);
break;
case 230:
_z[2] = string_to_double(_string, tail);
break;
default:
break;
}
}
////////////////////////////////////////////////////////////////////
// Function: DXFFile::state_verts
// Access: Protected
// Description: Does the DXF processing when we are reading the list
// of vertices that might follow an entity.
////////////////////////////////////////////////////////////////////
void DXFFile::
state_verts() {
string tail;
switch (_code) {
case 0:
state_section();
break;
case 8:
change_layer(_string);
break;
case 10:
_p[0] = string_to_double(_string, tail);
break;
case 20:
_p[1] = string_to_double(_string, tail);
break;
case 30:
_p[2] = string_to_double(_string, tail);
break;
default:
break;
}
}
ostream &operator << (ostream &out, const DXFFile::State &state) {
switch (state) {
case DXFFile::ST_top:
return out << "ST_top";
case DXFFile::ST_section:
return out << "ST_section";
case DXFFile::ST_entity:
return out << "ST_entity";
case DXFFile::ST_verts:
return out << "ST_verts";
case DXFFile::ST_error:
return out << "ST_error";
case DXFFile::ST_done:
return out << "ST_done";
}
return out << "Unknown state";
}
ostream &operator << (ostream &out, const DXFFile::Section &section) {
switch (section) {
case DXFFile::SE_unknown:
return out << "SE_unknown";
case DXFFile::SE_header:
return out << "SE_header";
case DXFFile::SE_tables:
return out << "SE_tables";
case DXFFile::SE_blocks:
return out << "SE_blocks";
case DXFFile::SE_entities:
return out << "SE_entities";
case DXFFile::SE_objects:
return out << "SE_objects";
}
return out << "Unknown section";
}
ostream &operator << (ostream &out, const DXFFile::Entity &entity) {
switch (entity) {
case DXFFile::EN_unknown:
return out << "EN_unknown";
case DXFFile::EN_3dface:
return out << "EN_3dface";
case DXFFile::EN_point:
return out << "EN_point";
case DXFFile::EN_insert:
return out << "EN_insert";
case DXFFile::EN_vertex:
return out << "EN_vertex";
case DXFFile::EN_polyline:
return out << "EN_polyline";
}
return out << "Unknown entity";
}

178
pandatool/src/dxf/dxfFile.h Normal file
View File

@ -0,0 +1,178 @@
// Filename: dxfFile.h
// Created by: drose (04May04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef DXFFILE_H
#define DXFFILE_H
#include "pandatoolbase.h"
#include "dxfLayer.h"
#include "dxfLayerMap.h"
#include "dxfVertex.h"
#include "luse.h"
#include "filename.h"
static const int DXF_max_line = 256;
static const int DXF_num_colors = 256;
////////////////////////////////////////////////////////////////////
// Class : DXFFile
// Description : A generic DXF-reading class. This class can read a
// DXF file but doesn't actually do anything with the
// data; it's intended to be inherited from and the
// appropriate functions overridden (particularly
// DoneEntity()).
////////////////////////////////////////////////////////////////////
class DXFFile {
public:
DXFFile();
virtual ~DXFFile();
void process(Filename filename);
void process(istream &in);
// These functions are called as the file is processed. These are
// the main hooks for redefining how the class should dispense its
// data. As each function is called, the state stored in the
// DXFFile class reflects the data that was most recently read.
virtual void begin_file();
virtual void begin_section();
virtual void done_vertex();
virtual void done_entity();
virtual void end_section();
virtual void end_file();
virtual void error();
// new_layer() is called whenever the DXFFile class encounters a new
// Layer definition, and must allocate a DXFLayer instance. This
// function is provided so that user code may force allocate of a
// specialized DXFLayer instance instead.
virtual DXFLayer *new_layer(const string &name) {
return new DXFLayer(name);
}
enum State {
ST_top,
ST_section,
ST_entity,
ST_verts,
ST_error,
ST_done,
};
enum Section {
SE_unknown,
SE_header,
SE_tables,
SE_blocks,
SE_entities,
SE_objects,
};
enum Entity {
EN_unknown,
EN_3dface,
EN_point,
EN_insert,
EN_vertex,
EN_polyline,
};
enum PolylineFlags {
PF_closed = 0x01,
PF_curve_fit = 0x02,
PF_spline_fit = 0x04,
PF_3d = 0x08,
PF_3d_mesh = 0x10,
PF_closed_n = 0x20,
PF_polyface = 0x40,
PF_continuous_linetype = 0x80,
};
// This is a table of standard Autocad colors. DXF files can store
// only a limited range of colors; specifically, the 255 colors
// defined by Autocad.
struct Color {
double r, g, b;
};
static Color _colors[DXF_num_colors];
// find_color() returns the index of the closest matching AutoCAD
// color to the indicated r, g, b.
static int find_color(double r, double g, double b);
// get_color() returns the r,g,b of the current entity. It is valid
// at the time done_entity() is called.
const Color &get_color() const;
// Some entities are defined in world coordinates, in 3-d space;
// other entities are inherently 2-d in nature and are defined in
// planar coordinates and must be converted to 3-d space. Call this
// function from done_entity() to convert a 2-d entity to 3-d world
// coordinates.
void ocs_2_wcs();
// These members indicate the current state and describe properties
// of the current thing being processed. They are valid at
// done_entity(), and at other times.
int _flags;
Section _section;
Entity _entity;
LPoint3d _p, _q, _r, _s;
LVector3d _z;
int _color_index;
DXFLayer *_layer;
// _verts is the list of vertices associated with the current
// entity. It is valid at the time done_entity() is called.
DXFVertices _verts;
// This is the set of layers encountered within the DXF file.
DXFLayerMap _layers;
protected:
State _state;
bool _vertices_follow;
LMatrix4d _ocs2wcs;
istream *_in;
ifstream _in_file;
int _code;
string _string;
void compute_ocs();
bool get_group();
void change_state(State new_state);
void change_section(Section new_section);
void change_layer(const string &layer_name);
void change_entity(Entity new_entity);
void reset_entity();
void state_top();
void state_section();
void state_entity();
void state_verts();
};
ostream &operator << (ostream &out, const DXFFile::State &state);
ostream &operator << (ostream &out, const DXFFile::Section &section);
ostream &operator << (ostream &out, const DXFFile::Entity &entity);
#endif

View File

@ -0,0 +1,49 @@
// Filename: dxfLayer.h
// Created by: drose (04May04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef DXFLAYER_H
#define DXFLAYER_H
#include "pandatoolbase.h"
#include "dxfVertexMap.h"
////////////////////////////////////////////////////////////////////
// Class : DXFLayer
// Description : This represents a "layer" as read from the DXF file.
// A layer may be defined by reading the header part of
// the file, or it may be implicitly defined by an
// entity's having referenced it.
//
// The DXFLayer class provides a facility for collapsing
// identical vertices, via the _vmap member; however,
// this is not automatic and must be done explicitly by
// user code.
//
// User code may derive from DXFLayer to associate
// private data with each layer, if desired.
////////////////////////////////////////////////////////////////////
class DXFLayer {
public:
DXFLayer(const string &name) : _name(name) { }
virtual ~DXFLayer() { }
string _name;
DXFVertexMap _vmap;
};
#endif

View File

@ -0,0 +1,48 @@
// Filename: dxfLayerMap.cxx
// Created by: drose (04May04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "dxfLayerMap.h"
#include "dxfFile.h"
////////////////////////////////////////////////////////////////////
// Function: DXFLayerMap::get_layer
// Access: Public
// Description: Looks up the layer name in the map, and returns a
// pointer to the associated DXFLayer. If this is the
// first time this layer name has been used, creates a
// new DXFLayer by the given name. In this case, it
// calls dxffile->new_layer() to create the layer,
// allowing user code to override this function to
// create a specialized time, if desired.
////////////////////////////////////////////////////////////////////
DXFLayer *DXFLayerMap::
get_layer(const string &name, DXFFile *dxffile) {
iterator lmi;
lmi = find(name);
if (lmi != end()) {
// The layer was already here.
return (*lmi).second;
}
// Need a new layer.
DXFLayer *layer = dxffile->new_layer(name);
(*this)[name] = layer;
return layer;
}

View File

@ -0,0 +1,40 @@
// Filename: dxfLayerMap.h
// Created by: drose (04May04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef DXFLAYERMAP_H
#define DXFLAYERMAP_H
#include "pandatoolbase.h"
#include "pmap.h"
class DXFLayer;
class DXFFile;
////////////////////////////////////////////////////////////////////
// Class : DXFLayerMap
// Description : A map of string (layer name) to DXFLayer: that is,
// the layers of a file ordered by name. This is used
// as a lookup within DXFFile to locate the layer
// associated with a particular entity.
////////////////////////////////////////////////////////////////////
class DXFLayerMap : public pmap<string, DXFLayer *> {
public:
DXFLayer *get_layer(const string &name, DXFFile *dxffile);
};
#endif

View File

@ -0,0 +1,40 @@
// Filename: dxfVertex.cxx
// Created by: drose (04May04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "dxfVertex.h"
////////////////////////////////////////////////////////////////////
// Function: DXFVertex::Ordering operator
// Access: Public
// Description: This defines a unique ordering for vertices so that
// the DXFVertexMap can group identical vertices
// together.
////////////////////////////////////////////////////////////////////
int DXFVertex::
operator < (const DXFVertex &other) const {
if (fabs(_p[0] - other._p[0]) > 0.0001) {
return _p[0] < other._p[0];
} else if (fabs(_p[1] - other._p[1]) > 0.0001) {
return _p[1] < other._p[1];
} else if (fabs(_p[2] - other._p[2]) > 0.0001) {
return _p[2] < other._p[2];
}
return false;
}

View File

@ -0,0 +1,46 @@
// Filename: dxfVertex.h
// Created by: drose (04May04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef DXFVERTEX_H
#define DXFVERTEX_H
#include "pandatoolbase.h"
#include "pvector.h"
#include "luse.h"
////////////////////////////////////////////////////////////////////
// Class : DXFVertex
// Description : Stored within DXFFile, this is the basic Vertex data
// of a DXF file. When DXFFile::DoneEntity() is called,
// if the entity is a type to have vertices, then
// DXFFile::_verts contains a list of all the vertices
// that belong to the entity.
////////////////////////////////////////////////////////////////////
class DXFVertex {
public:
DXFVertex() { }
DXFVertex(const LPoint3d &p) : _p(p) { }
int operator < (const DXFVertex &other) const;
LPoint3d _p;
};
typedef pvector<DXFVertex> DXFVertices;
#endif

View File

@ -0,0 +1,48 @@
// Filename: dxfVertexMap.cxx
// Created by: drose (04May04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "dxfVertexMap.h"
////////////////////////////////////////////////////////////////////
// Function: DXFVertexMap::get_vertex_index
// Access: Public
// Description: Looks up the vertex in the map, and returns an index
// unique to that vertex. If the vertex has been used
// before, returns the index used previously; otherwise,
// assigns a new, unique index to the vertex and returns
// that.
////////////////////////////////////////////////////////////////////
int DXFVertexMap::
get_vertex_index(const DXFVertex &vert) {
iterator vmi;
vmi = find(vert);
if (vmi != end()) {
// The vertex was already here.
return (*vmi).second;
}
// Nope, need a new vertex.
int index = size();
(*this)[vert] = index;
// That should have added one to the map.
nassertr((int)size() == index+1, index);
return index;
}

View File

@ -0,0 +1,39 @@
// Filename: dxfVertexMap.h
// Created by: drose (04May04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef DXFVERTEXMAP_H
#define DXFVERTEXMAP_H
#include "pandatoolbase.h"
#include "dxfVertex.h"
#include "pmap.h"
////////////////////////////////////////////////////////////////////
// Class : DXFVertexMap
// Description : This is a map of DXFVertex to an integer index
// number. It is intended to be used to collapse
// together identical vertices, since the DXF file has
// no inherent notion of shared vertices.
////////////////////////////////////////////////////////////////////
class DXFVertexMap : public pmap<DXFVertex, int> {
public:
int get_vertex_index(const DXFVertex &vert);
};
#endif

View File

@ -0,0 +1,11 @@
#define UNIX_SYS_LIBS m
#begin bin_target
#define TARGET dxf-points
#define LOCAL_LIBS \
progbase dxf
#define SOURCES \
dxfPoints.cxx dxfPoints.h
#end bin_target

View File

@ -0,0 +1,102 @@
// Filename: dxfPoints.cxx
// Created by: drose (04May04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "dxfPoints.h"
////////////////////////////////////////////////////////////////////
// Function: DXFPoints::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
DXFPoints::
DXFPoints() :
WithOutputFile(true, true, false)
{
// Indicate the extension name we expect the user to supply for
// output files.
_preferred_extension = ".txt";
set_program_description
("This program reads an AutoCAD .dxf file and generates a simple "
"list of all the points contained within it, one per line, to a "
"text file, or to standard output.");
clear_runlines();
add_runline("[opts] input.dxf > output.txt");
add_runline("[opts] -o output.txt input.dxf");
add_runline("[opts] input.dxf output.txt");
}
////////////////////////////////////////////////////////////////////
// Function: DXFPoints::run
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
void DXFPoints::
run() {
// Invoke the DXFFile base class to process the input file.
process(_input_filename);
}
////////////////////////////////////////////////////////////////////
// Function: DXFPoints::done_entity
// Access: Public, Virtual
// Description: This is inherited from DXFFile, and gets called as
// each entity (face, line, whatever) has finished
// processing.
////////////////////////////////////////////////////////////////////
void DXFPoints::
done_entity() {
if (_entity == EN_point) {
get_output() << _p << "\n";
} else if (_entity == EN_insert) {
ocs_2_wcs();
get_output() << _p << "\n";
}
}
////////////////////////////////////////////////////////////////////
// Function: DXFPoints::handle_args
// Access: Protected, Virtual
// Description:
////////////////////////////////////////////////////////////////////
bool DXFPoints::
handle_args(ProgramBase::Args &args) {
if (args.empty()) {
nout << "You must specify the .dxf file to read on the command line.\n";
return false;
} else if (args.size() != 1) {
nout << "You must specify only one .dxf file to read on the command line.\n";
return false;
}
_input_filename = args[0];
return true;
}
int main(int argc, char *argv[]) {
DXFPoints prog;
prog.parse_command_line(argc, argv);
prog.run();
return 0;
}

View File

@ -0,0 +1,48 @@
// Filename: dxfPoints.h
// Created by: drose (04May04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef DXFPOINTS_H
#define DXFPOINTS_H
#include "pandatoolbase.h"
#include "programBase.h"
#include "withOutputFile.h"
#include "dxfFile.h"
////////////////////////////////////////////////////////////////////
// Class : DXFPoints
// Description : A simple program to read a dxf file and list the
// points contained within it to a text file.
////////////////////////////////////////////////////////////////////
class DXFPoints : public ProgramBase, public WithOutputFile, public DXFFile {
public:
DXFPoints();
void run();
virtual void done_entity();
protected:
virtual bool handle_args(Args &args);
Filename _input_filename;
};
#endif