1 /*
2 * For reading and slight parsing of dxf files
3 *
4 * Author:
5 * Matt Squires <squiresm@colorado.edu>
6 *
7 * Copyright (C) 2005 Matt Squires
8 *
9 * Released under GNU GPL and LGPL, read the file 'GPL.txt' and 'LGPL.txt' for details
10 */
14 #include<fstream>
15 #include<string>
16 #include"read_dxf.h"
18 #include<iostream>
19 using namespace std;
22 int MAX_STR_LN = 10000;
24 int section(char* value){
25 if ( strncmp(value,"HEADER",6) == 0 ) return 0;
26 if ( strncmp(value,"CLASSES",7) == 0 ) return 1;
27 if ( strncmp(value,"TABLES",6) == 0 ) return 2;
28 if ( strncmp(value,"BLOCKS",6) == 0 ) return 3;
29 if ( strncmp(value,"ENTITIES",8) == 0 ) return 4;
30 if ( strncmp(value,"OBJECTS",7) == 0 ) return 5;
31 if ( strncmp(value,"THUMBNAILIMAGE",14) == 0 ) return 6;
32 }
35 dxfpair::dxfpair(int gcode, char val[10000]){
36 group_code = gcode;
37 // Dynamically save the strings, otherwise the memory uses is bad
39 for (int i = 0; i < strlen(val); i++){
40 value.push_back(val[i]);
41 }
42 }
45 dxfpair::~dxfpair(){
46 //delete [] value;
47 }
49 char * dxfpair::value_char(char *string){
50 int size = value.size();
51 while( ( size > 0 ) && int(value[size-1]) < 33){
52 // Strip off any control characters and spaces off the end of the string
53 size--;
54 }
55 for(int i = 0; i < size; i++){
56 string[i] = value[i];
57 }
58 string[size]=0;
59 }
61 std::vector< std::vector< dxfpair > > dxf_get_sections(char* filename){
62 // In the dxf format information is paired into group codes that indicate the information that follows on the next line. The information on the next line is called the value
64 int n =0;
66 int group_code;
67 char value[MAX_STR_LN];
69 int section_num;
74 std::vector< std::vector< dxfpair > > out;
76 std::vector< dxfpair > header;
77 std::vector< dxfpair > classes;
78 std::vector< dxfpair > tables;
79 std::vector< dxfpair > blocks;
80 std::vector< dxfpair > entities;
81 std::vector< dxfpair > objects;
82 std::vector< dxfpair > thumbnailimage;
84 header.clear();
85 classes.clear();
86 tables.clear();
87 blocks.clear();
88 entities.clear();
89 objects.clear();
90 thumbnailimage.clear();
93 // Open dxf file for reading
94 std::ifstream file(filename);
96 if (!file.is_open()){
97 exit (1); // Change this to an exception
98 }
100 // Find the first SECTION header
102 while ( (!file.eof()) ){
103 n++;
105 // get the first group code and value
106 file.getline(value,MAX_STR_LN);
107 group_code = atoi(value);
108 file.getline(value,MAX_STR_LN);
110 do{
112 // TO DO set all the chars to be caps for later comparison
114 // Find the SECTION codes
115 if ( (group_code == 0 ) && ( strncmp(value,"SECTION",7) == 0 ) ){
116 // Directly after a section value is the type of section ( e.g. HEADER, TABLES )
117 file.getline(value,MAX_STR_LN);
118 group_code = atoi(value);
119 file.getline(value,MAX_STR_LN);
120 section_num = section( value );
121 if ( group_code == 2 ){
122 // Make sure the the group code is 2 for the SECTION name
123 // This is a big block of mostly repetitive code, it will result in larger code, but would be faster than putting the switch in another while loop. If I still live in a time when file size mattered alot I would change it
124 //std::cout << "section_num = " << section_num << std::endl;
125 switch ( section_num ){
126 case 0:
127 file.getline(value,MAX_STR_LN);
128 group_code = atoi(value);
129 file.getline(value,MAX_STR_LN);
130 do{
131 header.push_back( dxfpair( group_code, value ) );
132 file.getline(value,MAX_STR_LN);
133 group_code = atoi(value);
134 file.getline(value,MAX_STR_LN);
135 }while( ( (group_code != 0) || strncmp(value,"ENDSEC",6) != 0 ) && (!file.eof()) ); // I put in the (group_code != 0) in the hope that it will be a faster bool compare than the string compare. Test this later
136 break;
137 case 1:
138 file.getline(value,MAX_STR_LN);
139 group_code = atoi(value);
140 file.getline(value,MAX_STR_LN);
141 if ( (group_code != 0) || (strncmp(value,"ENDSEC",6) != 0) ){
142 // Some dxf files have blank sections. These are not handled by the do/while loop so break about if needed
143 do{
144 classes.push_back( dxfpair( group_code, value ) );
145 file.getline(value,MAX_STR_LN);
146 group_code = atoi(value);
147 file.getline(value,MAX_STR_LN);
148 }while( ( (group_code != 0) || strncmp(value,"ENDSEC",6) != 0 ) && (!file.eof()) ); // I put in the (group_code != 0) in the hope that it will be a faster bool compare than the string compare. Test this later
149 }
150 break;
151 case 2:
152 file.getline(value,MAX_STR_LN);
153 group_code = atoi(value);
154 file.getline(value,MAX_STR_LN);
155 do{
156 tables.push_back( dxfpair( group_code, value ) );
157 file.getline(value,MAX_STR_LN);
158 group_code = atoi(value);
159 file.getline(value,MAX_STR_LN);
160 }while( ( (group_code != 0) || strncmp(value,"ENDSEC",6) != 0 ) && (!file.eof()) );
161 break;
162 case 3:
163 file.getline(value,MAX_STR_LN);
164 group_code = atoi(value);
165 file.getline(value,MAX_STR_LN);
166 do{
167 blocks.push_back( dxfpair( group_code, value ) );
168 file.getline(value,MAX_STR_LN);
169 group_code = atoi(value);
170 file.getline(value,MAX_STR_LN);
171 }while( ( (group_code != 0) || strncmp(value,"ENDSEC",6) != 0 ) && (!file.eof()) ); // I put in the (group_code != 0) in the hope that it will be a faster bool compare than the string compare. Test this later
172 break;
173 case 4:
174 file.getline(value,MAX_STR_LN);
175 group_code = atoi(value);
176 file.getline(value,MAX_STR_LN);
177 do{
178 entities.push_back( dxfpair( group_code, value ) );
179 file.getline(value,MAX_STR_LN);
180 group_code = atoi(value);
181 file.getline(value,MAX_STR_LN);
182 }while( ( (group_code != 0) || strncmp(value,"ENDSEC",6) != 0 ) && (!file.eof()) ); // I put in the (group_code != 0) in the hope that it will be a faster bool compare than the string compare. Test this later
183 break;
184 case 5:
185 file.getline(value,MAX_STR_LN);
186 group_code = atoi(value);
187 file.getline(value,MAX_STR_LN);
188 do{
189 objects.push_back( dxfpair( group_code, value ) );
190 file.getline(value,MAX_STR_LN);
191 group_code = atoi(value);
192 file.getline(value,MAX_STR_LN);
193 }while( ( (group_code != 0) || strncmp(value,"ENDSEC",6) != 0 ) && (!file.eof()) ); // I put in the (group_code != 0) in the hope that it will be a faster bool compare than the string compare. Test this later
194 break;
195 case 6:
196 file.getline(value,MAX_STR_LN);
197 group_code = atoi(value);
198 file.getline(value,MAX_STR_LN);
199 do{
200 thumbnailimage.push_back( dxfpair( group_code, value ) );
201 file.getline(value,MAX_STR_LN);
202 group_code = atoi(value);
203 file.getline(value,MAX_STR_LN);
204 }while( ( (group_code != 0) || strncmp(value,"ENDSEC",6) != 0 ) && (!file.eof()) ); // I put in the (group_code != 0) in the hope that it will be a faster bool compare than the string compare. Test this later
205 break;
206 default:
207 file.getline(value,MAX_STR_LN);
208 group_code = atoi(value);
209 file.getline(value,MAX_STR_LN);
210 }
211 }
212 }
213 file.getline(value,MAX_STR_LN);
214 group_code = atoi(value);
215 file.getline(value,MAX_STR_LN);
217 n++;
218 }while( ( strncmp(value,"EOF",3) != 0 ) && (!file.eof()) );
219 }
221 out.push_back(header);
222 out.push_back(classes);
223 out.push_back(tables);
224 out.push_back(blocks);
225 out.push_back(entities);
226 out.push_back(objects);
227 out.push_back(thumbnailimage);
229 return out;
230 }
233 std::vector< std::vector< dxfpair > > separate_parts( std::vector< dxfpair > section){
234 //std::cout << "1" << std::endl;
235 //std::cout << "section.size() = " << section.size() << std::endl;
236 // Find where the major sections are and break into smaller parts
237 // Major section is defined as anything beween group_code 0 to 0
238 std::vector< dxfpair > inner;
239 std::vector< std::vector< dxfpair > > outer;
240 //std::cout << "2" << std::endl;
241 for (int i = 0; i < section.size(); i++){
242 //std::cout << "i = " << i << std::endl;
243 //std::cout << "section[i].value.size() = " << section[i].value.size() << std::endl;
245 // Make sure no control codes like LF or CR are making it past this section
246 if ( (section[i].value.size() > 0) && int(section[i].value.back()) < 32 ){
247 section[i].value.pop_back();
248 }
249 //for(int j = 0;j < section[i].value.size();j++ ) std::cout << section[i].value[j];
250 //std::cout << std::endl;
252 inner.push_back( section[i] );
254 // If the next group code is 0 then push the previously found info on outer and start looking for data again
255 if (section[i+1].group_code == 0){
256 //std::cout << "inner.push_back" << std::endl;
257 outer.push_back( inner );
258 inner.clear();
259 }
260 }
261 // Because putting the data on outer depends on find a GC=0 the last bit of data may be left behind so it inner has data in it put it on outer
262 if ( inner.size() > 0 ){
263 outer.push_back( inner );
264 inner.clear();
265 }
266 //std::cout << "3" << std::endl;
267 if (section.back().group_code == 0){
268 //outer.push_back( inner ); // Put the last part on if there is information, but I don't think it needs to.
269 }
271 return outer;
272 }