void DXFImporter::ParseInsertion(DXF::LineReader& reader, DXF::FileData& output) { output.blocks.back().insertions.push_back( DXF::InsertBlock() ); DXF::InsertBlock& bl = output.blocks.back().insertions.back(); while( !reader.End() && !reader.Is(0)) { switch(reader.GroupCode()) { // name of referenced block case 2: bl.name = reader.Value(); break; // translation case 10: bl.pos.x = reader.ValueAsFloat(); break; case 20: bl.pos.y = reader.ValueAsFloat(); break; case 30: bl.pos.z = reader.ValueAsFloat(); break; // scaling case 41: bl.scale.x = reader.ValueAsFloat(); break; case 42: bl.scale.y = reader.ValueAsFloat(); break; case 43: bl.scale.z = reader.ValueAsFloat(); break; // rotation angle case 50: bl.angle = reader.ValueAsFloat(); break; } reader++; } }
// ------------------------------------------------------------------------------------------------ void DXFImporter::ParseBlock(DXF::LineReader& reader, DXF::FileData& output) { // push a new block onto the stack. output.blocks.push_back( DXF::Block() ); DXF::Block& block = output.blocks.back(); while( !reader.End() && !reader.Is(0,"ENDBLK")) { switch(reader.GroupCode()) { case 2: block.name = reader.Value(); break; case 10: block.base.x = reader.ValueAsFloat(); break; case 20: block.base.y = reader.ValueAsFloat(); break; case 30: block.base.z = reader.ValueAsFloat(); break; } if (reader.Is(0,"POLYLINE")) { ParsePolyLine(++reader,output); continue; } // XXX is this a valid case? if (reader.Is(0,"INSERT")) { DefaultLogger::get()->warn("DXF: INSERT within a BLOCK not currently supported; skipping"); for( ;!reader.End() && !reader.Is(0,"ENDBLK"); ++reader); break; } else if (reader.Is(0,"3DFACE") || reader.Is(0,"LINE") || reader.Is(0,"3DLINE")) { //http://sourceforge.net/tracker/index.php?func=detail&aid=2970566&group_id=226462&atid=1067632 Parse3DFace(++reader, output); continue; } ++reader; } }
// ------------------------------------------------------------------------------------------------ void DXFImporter::Parse3DFace(DXF::LineReader& reader, DXF::FileData& output) { // (note) this is also used for for parsing line entities, so we // must handle the vertex_count == 2 case as well. output.blocks.back().lines.push_back( std::shared_ptr<DXF::PolyLine>( new DXF::PolyLine() ) ); DXF::PolyLine& line = *output.blocks.back().lines.back(); aiVector3D vip[4]; aiColor4D clr = AI_DXF_DEFAULT_COLOR; bool b[4] = {false,false,false,false}; while( !reader.End() ) { // next entity with a groupcode == 0 is probably already the next vertex or polymesh entity if (reader.GroupCode() == 0) { break; } switch (reader.GroupCode()) { // 8 specifies the layer case 8: line.layer = reader.Value(); break; // x position of the first corner case 10: vip[0].x = reader.ValueAsFloat(); b[2] = true; break; // y position of the first corner case 20: vip[0].y = reader.ValueAsFloat(); b[2] = true; break; // z position of the first corner case 30: vip[0].z = reader.ValueAsFloat(); b[2] = true; break; // x position of the second corner case 11: vip[1].x = reader.ValueAsFloat(); b[3] = true; break; // y position of the second corner case 21: vip[1].y = reader.ValueAsFloat(); b[3] = true; break; // z position of the second corner case 31: vip[1].z = reader.ValueAsFloat(); b[3] = true; break; // x position of the third corner case 12: vip[2].x = reader.ValueAsFloat(); b[0] = true; break; // y position of the third corner case 22: vip[2].y = reader.ValueAsFloat(); b[0] = true; break; // z position of the third corner case 32: vip[2].z = reader.ValueAsFloat(); b[0] = true; break; // x position of the fourth corner case 13: vip[3].x = reader.ValueAsFloat(); b[1] = true; break; // y position of the fourth corner case 23: vip[3].y = reader.ValueAsFloat(); b[1] = true; break; // z position of the fourth corner case 33: vip[3].z = reader.ValueAsFloat(); b[1] = true; break; // color case 62: clr = g_aclrDxfIndexColors[reader.ValueAsUnsignedInt() % AI_DXF_NUM_INDEX_COLORS]; break; }; ++reader; } // the fourth corner may even be identical to the third, // in this case we treat it as if it didn't exist. if (vip[3] == vip[2]) { b[1] = false; } // sanity checks to see if we got something meaningful if ((b[1] && !b[0]) || !b[2] || !b[3]) { DefaultLogger::get()->warn("DXF: unexpected vertex setup in 3DFACE/LINE/FACE entity; ignoring"); output.blocks.back().lines.pop_back(); return; } const unsigned int cnt = (2+(b[0]?1:0)+(b[1]?1:0)); line.counts.push_back(cnt); for (unsigned int i = 0; i < cnt; ++i) { line.indices.push_back(static_cast<unsigned int>(line.positions.size())); line.positions.push_back(vip[i]); line.colors.push_back(clr); } }
// ------------------------------------------------------------------------------------------------ void DXFImporter::ParsePolyLineVertex(DXF::LineReader& reader, DXF::PolyLine& line) { unsigned int cnti = 0, flags = 0; unsigned int indices[4]; aiVector3D out; aiColor4D clr = AI_DXF_DEFAULT_COLOR; while( !reader.End() ) { if (reader.Is(0)) { // SEQEND or another VERTEX break; } switch (reader.GroupCode()) { case 8: // layer to which the vertex belongs to - assume that // this is always the layer the top-level polyline // entity resides on as well. if(reader.Value() != line.layer) { DefaultLogger::get()->warn("DXF: expected vertex to be part of a polyface but the 0x128 flag isn't set"); } break; case 70: flags = reader.ValueAsUnsignedInt(); break; // VERTEX COORDINATES case 10: out.x = reader.ValueAsFloat();break; case 20: out.y = reader.ValueAsFloat();break; case 30: out.z = reader.ValueAsFloat();break; // POLYFACE vertex indices case 71: case 72: case 73: case 74: if (cnti == 4) { DefaultLogger::get()->warn("DXF: more than 4 indices per face not supported; ignoring"); break; } indices[cnti++] = reader.ValueAsUnsignedInt(); break; // color case 62: clr = g_aclrDxfIndexColors[reader.ValueAsUnsignedInt() % AI_DXF_NUM_INDEX_COLORS]; break; }; reader++; } if (line.flags & DXF_POLYLINE_FLAG_POLYFACEMESH && !(flags & DXF_VERTEX_FLAG_PART_OF_POLYFACE)) { DefaultLogger::get()->warn("DXF: expected vertex to be part of a polyface but the 0x128 flag isn't set"); } if (cnti) { line.counts.push_back(cnti); for (unsigned int i = 0; i < cnti; ++i) { // IMPORTANT NOTE: POLYMESH indices are ONE-BASED if (indices[i] == 0) { DefaultLogger::get()->warn("DXF: invalid vertex index, indices are one-based."); --line.counts.back(); continue; } line.indices.push_back(indices[i]-1); } } else { line.positions.push_back(out); line.colors.push_back(clr); } }
// ------------------------------------------------------------------------------------------------ void DXFImporter::ParsePolyLine(DXF::LineReader& reader, DXF::FileData& output) { output.blocks.back().lines.push_back( std::shared_ptr<DXF::PolyLine>( new DXF::PolyLine() ) ); DXF::PolyLine& line = *output.blocks.back().lines.back(); unsigned int iguess = 0, vguess = 0; while( !reader.End() && !reader.Is(0,"ENDSEC")) { if (reader.Is(0,"VERTEX")) { ParsePolyLineVertex(++reader,line); if (reader.Is(0,"SEQEND")) { break; } continue; } switch(reader.GroupCode()) { // flags --- important that we know whether it is a // polyface mesh or 'just' a line. case 70: if (!line.flags) { line.flags = reader.ValueAsSignedInt(); } break; // optional number of vertices case 71: vguess = reader.ValueAsSignedInt(); line.positions.reserve(vguess); break; // optional number of faces case 72: iguess = reader.ValueAsSignedInt(); line.indices.reserve(iguess); break; // 8 specifies the layer on which this line is placed on case 8: line.layer = reader.Value(); break; } reader++; } //if (!(line.flags & DXF_POLYLINE_FLAG_POLYFACEMESH)) { // DefaultLogger::get()->warn((Formatter::format("DXF: polyline not currently supported: "),line.flags)); // output.blocks.back().lines.pop_back(); // return; //} if (vguess && line.positions.size() != vguess) { DefaultLogger::get()->warn((Formatter::format("DXF: unexpected vertex count in polymesh: "), line.positions.size(),", expected ", vguess )); } if (line.flags & DXF_POLYLINE_FLAG_POLYFACEMESH ) { if (line.positions.size() < 3 || line.indices.size() < 3) { DefaultLogger::get()->warn("DXF: not enough vertices for polymesh; ignoring"); output.blocks.back().lines.pop_back(); return; } // if these numbers are wrong, parsing might have gone wild. // however, the docs state that applications are not required // to set the 71 and 72 fields, respectively, to valid values. // So just fire a warning. if (iguess && line.counts.size() != iguess) { DefaultLogger::get()->warn((Formatter::format("DXF: unexpected face count in polymesh: "), line.counts.size(),", expected ", iguess )); } } else if (!line.indices.size() && !line.counts.size()) { // a polyline - so there are no indices yet. size_t guess = line.positions.size() + (line.flags & DXF_POLYLINE_FLAG_CLOSED ? 1 : 0); line.indices.reserve(guess); line.counts.reserve(guess/2); for (unsigned int i = 0; i < line.positions.size()/2; ++i) { line.indices.push_back(i*2); line.indices.push_back(i*2+1); line.counts.push_back(2); } // closed polyline? if (line.flags & DXF_POLYLINE_FLAG_CLOSED) { line.indices.push_back(static_cast<unsigned int>(line.positions.size()-1)); line.indices.push_back(0); line.counts.push_back(2); } } }