Panda3D
 All Classes Functions Variables Enumerations
eggToDXFLayer.cxx
00001 // Filename: eggToDXFLayer.cxx
00002 // Created by:  drose (04May04)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "eggToDXFLayer.h"
00016 #include "eggToDXF.h"
00017 #include "dxfFile.h"
00018 #include "eggGroup.h"
00019 #include "eggGroupNode.h"
00020 #include "eggPolygon.h"
00021 #include "dcast.h"
00022 
00023 ////////////////////////////////////////////////////////////////////
00024 //     Function: EggToDXFLayer::Constructor
00025 //       Access: Public
00026 //  Description: 
00027 ////////////////////////////////////////////////////////////////////
00028 EggToDXFLayer::
00029 EggToDXFLayer(EggToDXF *egg2dxf, EggGroupNode *group) :
00030   _egg2dxf(egg2dxf), _group(group) 
00031 {
00032   _layer_color = -1;
00033 }
00034 
00035 ////////////////////////////////////////////////////////////////////
00036 //     Function: EggToDXFLayer::Copy Constructor
00037 //       Access: Public
00038 //  Description: 
00039 ////////////////////////////////////////////////////////////////////
00040 EggToDXFLayer::
00041 EggToDXFLayer(const EggToDXFLayer &copy) :
00042   _egg2dxf(copy._egg2dxf),
00043   _group(copy._group),
00044   _layer_color(copy._layer_color) 
00045 {
00046   // The copy constructor doesn't bother with the ColorCounts.
00047 }
00048 
00049 ////////////////////////////////////////////////////////////////////
00050 //     Function: EggToDXFLayer::Copy Assignment Operator
00051 //       Access: Public
00052 //  Description: 
00053 ////////////////////////////////////////////////////////////////////
00054 void EggToDXFLayer::
00055 operator = (const EggToDXFLayer &copy) {
00056   _egg2dxf = copy._egg2dxf;
00057   _group = copy._group;
00058   _layer_color = copy._layer_color;
00059 
00060   // The copy constructor doesn't bother with the ColorCounts.
00061 }
00062 
00063 ////////////////////////////////////////////////////////////////////
00064 //     Function: EggToDXFLayer::add_color 
00065 //       Access: Public
00066 //  Description: Records that one polygon is defined using the
00067 //               indicated color.  This will get accumulated; the
00068 //               color used by the majority of polygons will become
00069 //               the layer color.
00070 ////////////////////////////////////////////////////////////////////
00071 void EggToDXFLayer::
00072 add_color(const LColor &color) {
00073   int autocad_color = get_autocad_color(color);
00074 
00075   ColorCounts::iterator cci;
00076   cci = _color_counts.find(autocad_color);
00077   if (cci == _color_counts.end()) {
00078     // The first time a particular color was used.  Count it once.
00079     _color_counts[autocad_color] = 1;
00080   } else {
00081     // This color has been used before.  Count it again.
00082     (*cci).second++;
00083   }
00084 }
00085 
00086 
00087 ////////////////////////////////////////////////////////////////////
00088 //     Function: EggToDXFLayer::choose_overall_color 
00089 //       Access: Public
00090 //  Description: After all polygons have been accounted for, chooses
00091 //               the polygon color that occurred most often as the
00092 //               layer color.
00093 ////////////////////////////////////////////////////////////////////
00094 void EggToDXFLayer::
00095 choose_overall_color() {
00096   int max_count = 0;
00097   
00098   ColorCounts::iterator cci;
00099   for (cci = _color_counts.begin(); cci != _color_counts.end(); ++cci) {
00100     int count = (*cci).second;
00101     if (count > max_count) {
00102       _layer_color = (*cci).first;
00103       max_count = count;
00104     }
00105   }
00106 }
00107 
00108 
00109 ////////////////////////////////////////////////////////////////////
00110 //     Function: EggToDXFLayer::write_layer
00111 //       Access: Public
00112 //  Description: Writes the layer definition into the table at the
00113 //               beginning of the DXF file.  This does not write the
00114 //               actual geometry; that gets done later by
00115 //               write_entities().
00116 ////////////////////////////////////////////////////////////////////
00117 void EggToDXFLayer::
00118 write_layer(ostream &out) {
00119   out << "0\nLAYER\n"
00120       << "2\n" << _group->get_name() << "\n"
00121       << "70\n0\n"
00122       << "62\n" << _layer_color << "\n"
00123       << "6\nCONTINUOUS\n";
00124 }
00125 
00126 ////////////////////////////////////////////////////////////////////
00127 //     Function: EggToDXFLayer::write_polyline 
00128 //       Access: Public
00129 //  Description: Writes a polygon as a POLYLINE entity.
00130 ////////////////////////////////////////////////////////////////////
00131 void EggToDXFLayer::
00132 write_polyline(EggPolygon *poly, ostream &out) {
00133   out << "0\nPOLYLINE\n"
00134       << "8\n" << _group->get_name() << "\n"
00135       << "66\n1\n"
00136       << "70\n1\n"
00137       << "62\n" << get_autocad_color(poly->get_color()) << "\n";
00138   
00139   // Since DXF uses a clockwise ordering convention, we must
00140   // reverse the order in which we write out the vertices.
00141   EggPolygon::reverse_iterator vi;
00142   for (vi = poly->rbegin(); vi != poly->rend(); ++vi) {
00143     EggVertex *vtx = (*vi);
00144     LVecBase3d pos = vtx->get_pos3() * _group->get_vertex_frame();
00145     out << "0\nVERTEX\n"
00146         << "10\n" << pos[0] << "\n"
00147         << "20\n" << pos[1] << "\n"
00148         << "30\n" << pos[2] << "\n";
00149   }
00150   out << "0\nSEQEND\n";
00151 }
00152 
00153 ////////////////////////////////////////////////////////////////////
00154 //     Function: EggToDXFLayer::write_3d_face
00155 //       Access: Public
00156 //  Description: Writes a polygon as a 3DFACE entity.
00157 ////////////////////////////////////////////////////////////////////
00158 void EggToDXFLayer::
00159 write_3d_face(EggPolygon *poly, ostream &out) {
00160   if (poly->size() > 4) {
00161     // If we have a big polygon, we have to triangulate it, since
00162     // 3DFaces can only be tris and quads.
00163     PT(EggGroup) group = new EggGroup;
00164     poly->triangulate_into(group, true);
00165 
00166     EggGroupNode::iterator ci;
00167     for (ci = group->begin(); ci != group->end(); ++ci) {
00168       EggNode *child = (*ci);
00169       if (child->is_of_type(EggPolygon::get_class_type())) {
00170         write_3d_face(DCAST(EggPolygon, child), out);
00171       }
00172     }
00173 
00174   } else if (poly->size() > 2) {
00175     // Otherwise, if we have a tri or a quad, just write it out.
00176     out << "0\n3DFACE\n"
00177         << "8\n" << _group->get_name() << "\n";
00178 
00179     // Since DXF uses a clockwise ordering convention, we must
00180     // reverse the order in which we write out the vertices.
00181     int i;
00182     EggPolygon::reverse_iterator vi;
00183     for (i = 0, vi = poly->rbegin(); vi != poly->rend(); ++i, ++vi) {
00184       EggVertex *vtx = (*vi);
00185       LVecBase3d pos = vtx->get_pos3() * _group->get_vertex_frame();
00186       out << 10 + i << "\n" << pos[0] << "\n"
00187           << 20 + i << "\n" << pos[1] << "\n"
00188           << 30 + i << "\n" << pos[2] << "\n";
00189       if (i == 2 && poly->size() == 3) {
00190         // A special case for triangles: repeat the last vertex.
00191         out << 11 + i << "\n" << pos[0] << "\n"
00192             << 21 + i << "\n" << pos[1] << "\n"
00193             << 31 + i << "\n" << pos[2] << "\n";
00194       }
00195     }
00196   }
00197 }
00198   
00199 
00200 ////////////////////////////////////////////////////////////////////
00201 //     Function: EggToDXFLayer::write_entities 
00202 //       Access: Public
00203 //  Description: Writes out the "entities", e.g. polygons, defined for
00204 //               the current layer.
00205 ////////////////////////////////////////////////////////////////////
00206 void EggToDXFLayer::
00207 write_entities(ostream &out) {
00208   EggGroupNode::iterator ci;
00209   for (ci = _group->begin(); ci != _group->end(); ++ci) {
00210     EggNode *child = (*ci);
00211     if (child->is_of_type(EggPolygon::get_class_type())) {
00212       EggPolygon *poly = DCAST(EggPolygon, child);
00213       if (_egg2dxf->_use_polyline) {
00214         write_polyline(poly, out);
00215       } else {
00216         write_3d_face(poly, out);
00217       }
00218     }
00219   }
00220 }
00221 
00222 ////////////////////////////////////////////////////////////////////
00223 //     Function: EggToDXFLayer::get_autocad_color
00224 //       Access: Private
00225 //  Description: Returns the AutoCAD color index that most closely
00226 //               matches the indicated EggColor.
00227 ////////////////////////////////////////////////////////////////////
00228 int EggToDXFLayer::
00229 get_autocad_color(const LColor &color) {
00230   typedef pmap<LColor, int> ColorMap;
00231   static ColorMap _map;
00232 
00233   ColorMap::iterator cmi;
00234   cmi = _map.find(color);
00235   if (cmi != _map.end()) {
00236     return (*cmi).second;
00237   }
00238 
00239   int result = DXFFile::find_color(color[0], color[1], color[2]);
00240   _map[color] = result;
00241   return result;
00242 }
 All Classes Functions Variables Enumerations