1 /*
2 Open Asset Import Library (assimp)
3 ----------------------------------------------------------------------
4 
5 Copyright (c) 2006-2017, assimp team
6 
7 All rights reserved.
8 
9 Redistribution and use of this software in source and binary forms,
10 with or without modification, are permitted provided that the
11 following conditions are met:
12 
13 * Redistributions of source code must retain the above
14   copyright notice, this list of conditions and the
15   following disclaimer.
16 
17 * Redistributions in binary form must reproduce the above
18   copyright notice, this list of conditions and the
19   following disclaimer in the documentation and/or other
20   materials provided with the distribution.
21 
22 * Neither the name of the assimp team, nor the names of its
23   contributors may be used to endorse or promote products
24   derived from this software without specific prior
25   written permission of the assimp team.
26 
27 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
32 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
33 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 
39 ----------------------------------------------------------------------
40 */
41 
42 /** @file  DXFHelper.h
43  *  @brief Internal utilities for the DXF loader.
44  */
45 
46 #ifndef INCLUDED_DXFHELPER_H
47 #define INCLUDED_DXFHELPER_H
48 
49 #include "LineSplitter.h"
50 #include "TinyFormatter.h"
51 #include "StreamReader.h"
52 #include "fast_atof.h"
53 #include <vector>
54 #include <assimp/DefaultLogger.hpp>
55 
56 namespace Assimp {
57     namespace DXF {
58 
59 
60 // read pairs of lines, parse group code and value and provide utilities
61 // to convert the data to the target data type.
62 class LineReader
63 {
64 
65 public:
66 
LineReader(StreamReaderLE & reader)67     LineReader(StreamReaderLE& reader)
68          // do NOT skip empty lines. In DXF files, they count as valid data.
69         : splitter(reader,false,true)
70         , groupcode( 0 )
71         , value()
72         , end()
73     {
74     }
75 
76 public:
77 
78 
79     // -----------------------------------------
Is(int gc,const char * what)80     bool Is(int gc, const char* what) const {
81         return groupcode == gc && !strcmp(what,value.c_str());
82     }
83 
84     // -----------------------------------------
Is(int gc)85     bool Is(int gc) const {
86         return groupcode == gc;
87     }
88 
89     // -----------------------------------------
GroupCode()90     int GroupCode() const {
91         return groupcode;
92     }
93 
94     // -----------------------------------------
Value()95     const std::string& Value() const {
96         return value;
97     }
98 
99     // -----------------------------------------
End()100     bool End() const {
101         return !((bool)*this);
102     }
103 
104 public:
105 
106     // -----------------------------------------
ValueAsUnsignedInt()107     unsigned int ValueAsUnsignedInt() const {
108         return strtoul10(value.c_str());
109     }
110 
111     // -----------------------------------------
ValueAsSignedInt()112     int ValueAsSignedInt() const {
113         return strtol10(value.c_str());
114     }
115 
116     // -----------------------------------------
ValueAsFloat()117     float ValueAsFloat() const {
118         return fast_atof(value.c_str());
119     }
120 
121 public:
122 
123     // -----------------------------------------
124     /** pseudo-iterator increment to advance to the next (groupcode/value) pair */
125     LineReader& operator++() {
126         if (end) {
127             if (end == 1) {
128                 ++end;
129             }
130             return *this;
131         }
132 
133         try {
134             groupcode = strtol10(splitter->c_str());
135             splitter++;
136 
137             value = *splitter;
138             splitter++;
139 
140             // automatically skip over {} meta blocks (these are for application use
141             // and currently not relevant for Assimp).
142             if (value.length() && value[0] == '{') {
143 
144                 size_t cnt = 0;
145                 for(;splitter->length() && splitter->at(0) != '}'; splitter++, cnt++);
146 
147                 splitter++;
148                 DefaultLogger::get()->debug((Formatter::format("DXF: skipped over control group ("),cnt," lines)"));
149             }
catch(std::logic_error &)150         } catch(std::logic_error&) {
151             ai_assert(!splitter);
152         }
153         if (!splitter) {
154             end = 1;
155         }
156         return *this;
157     }
158 
159     // -----------------------------------------
160     LineReader& operator++(int) {
161         return ++(*this);
162     }
163 
164 
165     // -----------------------------------------
166     operator bool() const {
167         return end <= 1;
168     }
169 
170 private:
171 
172     LineSplitter splitter;
173     int groupcode;
174     std::string value;
175     int end;
176 };
177 
178 
179 
180 // represents a POLYLINE or a LWPOLYLINE. or even a 3DFACE The data is converted as needed.
181 struct PolyLine
182 {
PolyLinePolyLine183     PolyLine()
184         : flags()
185     {}
186 
187     std::vector<aiVector3D> positions;
188     std::vector<aiColor4D>  colors;
189     std::vector<unsigned int> indices;
190     std::vector<unsigned int> counts;
191     unsigned int flags;
192 
193     std::string layer;
194     std::string desc;
195 };
196 
197 
198 // reference to a BLOCK. Specifies its own coordinate system.
199 struct InsertBlock
200 {
InsertBlockInsertBlock201     InsertBlock()
202         : scale(1.f,1.f,1.f)
203         , angle()
204     {}
205 
206     aiVector3D pos;
207     aiVector3D scale;
208     float angle;
209 
210     std::string name;
211 };
212 
213 
214 // keeps track of all geometry in a single BLOCK.
215 struct Block
216 {
217     std::vector< std::shared_ptr<PolyLine> > lines;
218     std::vector<InsertBlock> insertions;
219 
220     std::string name;
221     aiVector3D base;
222 };
223 
224 
225 struct FileData
226 {
227     // note: the LAST block always contains the stuff from ENTITIES.
228     std::vector<Block> blocks;
229 };
230 
231 
232 
233 
234 
235 }}
236 #endif
237