1 /* dxfReader for OpenSceneGraph Copyright (C) 2005 by GraphArchitecture ( grapharchitecture.com )
2 * Programmed by Paul de Repentigny <pdr@grapharchitecture.com>
3 *
4 * OpenSceneGraph is (C) 2004 Robert Osfield
5 *
6 * This library is provided as-is, without support of any kind.
7 *
8 * Read DXF docs or OSG docs for any related questions.
9 *
10 * You may contact the author if you have suggestions/corrections/enhancements.
11 */
12
13
14 #ifndef DXF_ENTITY
15 #define DXF_ENTITY 1
16
17 #include <vector>
18 #include <string>
19 #include <iostream>
20
21 #include <osg/Referenced>
22 #include <osg/ref_ptr>
23 #include <osg/Array>
24 #include <osg/Vec3d>
25 #include <osg/Node>
26 #include <osg/Matrixd>
27 #include <osgText/Text>
28
29 #include "dxfBlock.h"
30
31
32 class scene;
33 class codeValue;
34 class dxfFile;
35
36 static inline void
getOCSMatrix(const osg::Vec3d & ocs,osg::Matrixd & m)37 getOCSMatrix(const osg::Vec3d& ocs, osg::Matrixd& m)
38 {
39 static const double one_64th = 1.0/64.0;
40 m.makeIdentity();
41 if (ocs == osg::Vec3d(0,0,1)) return;
42 osg::Vec3d ax(1,0,0), ay(0,1,0), az(0,0,1);
43 osg::Vec3d ocsaxis(ocs);
44 ocsaxis.normalize();
45 if (fabs(ocsaxis.x()) < one_64th && fabs(ocsaxis.y()) < one_64th) {
46 ax = ay ^ ocsaxis;
47 } else {
48 ax = az ^ ocsaxis;
49 }
50 ax.normalize();
51 ay = ocsaxis ^ ax;
52 ay.normalize();
53 m = osg::Matrixd( ax.x(), ax.y(), ax.z(), 0,
54 ay.x(), ay.y(), ay.z(), 0,
55 ocsaxis.x(), ocsaxis.y(), ocsaxis.z(), 0,
56 0,0,0,1);
57 // m = m.inverse(m);
58 }
59
60 class dxfBasicEntity : public osg::Referenced
61 {
62 public:
dxfBasicEntity()63 dxfBasicEntity() : _color(0), _useAccuracy(false), _maxError(0.01), _improveAccuracyOnly(false) {}
~dxfBasicEntity()64 virtual ~dxfBasicEntity() {}
65 virtual dxfBasicEntity* create() = 0;
66 virtual const char* name() = 0;
67 virtual void assign(dxfFile* dxf, codeValue& cv);
drawScene(scene *)68 virtual void drawScene(scene*) {}
getLayer()69 const std::string getLayer() const { return _layer; }
70
setAccuracy(bool useAccuracy,double maxError,bool improveAccuracyOnly)71 void setAccuracy(bool useAccuracy,double maxError,bool improveAccuracyOnly) {
72 _useAccuracy=useAccuracy;
73 _maxError=maxError;
74 _improveAccuracyOnly=improveAccuracyOnly;
75 }
76
77
78 protected:
79 std::string _layer;
80 unsigned short _color;
81
82 bool _useAccuracy; // true to specify a maximum deviation for curve rendering
83 double _maxError; // the error in model units, if _useAccuracy==true
84 bool _improveAccuracyOnly;// if true only use _maxError where it would increase the quality of curves compared to the previous algorithm
85
86 };
87
88
89 class dxfCircle : public dxfBasicEntity
90 {
91 public:
dxfCircle()92 dxfCircle() : _radius(0), _ocs(0,0,1) {}
~dxfCircle()93 virtual ~dxfCircle() {}
create()94 virtual dxfBasicEntity* create() { // we create a copy which uses our accuracy settings
95 dxfBasicEntity* circle=new dxfCircle;
96 circle->setAccuracy(_useAccuracy,_maxError,_improveAccuracyOnly);
97 return circle;
98 }
name()99 virtual const char* name() { return "CIRCLE"; }
100 virtual void assign(dxfFile* dxf, codeValue& cv);
101 virtual void drawScene(scene* sc);
102 protected:
103 osg::Vec3d _center;
104 double _radius;
105 osg::Vec3d _ocs;
106 };
107
108 class dxfArc : public dxfBasicEntity
109 {
110 public:
dxfArc()111 dxfArc() : _radius(0), _startAngle(0), _endAngle(360), _ocs(0,0,1) {}
~dxfArc()112 virtual ~dxfArc() {}
create()113 virtual dxfBasicEntity* create() { // we create a copy which uses our accuracy settings
114 dxfBasicEntity* arc=new dxfArc;
115 arc->setAccuracy(_useAccuracy,_maxError,_improveAccuracyOnly);
116 //std::cout<<"dxfArc::create with _useAccuracy="<<_useAccuracy<<" maxError="<<_maxError<<" improveAccuracyOnly="<<_improveAccuracyOnly<<std::endl;
117 return arc;
118 }
name()119 virtual const char* name() { return "ARC"; }
120 virtual void assign(dxfFile* dxf, codeValue& cv);
121 virtual void drawScene(scene* sc);
122 protected:
123 osg::Vec3d _center;
124 double _radius;
125 double _startAngle;
126 double _endAngle;
127 osg::Vec3d _ocs;
128 };
129
130 class dxfPoint : public dxfBasicEntity
131 {
132 public:
dxfPoint()133 dxfPoint() : _ocs(0,0,1) {}
~dxfPoint()134 virtual ~dxfPoint() {}
create()135 virtual dxfBasicEntity* create() { return new dxfPoint; }
name()136 virtual const char* name() { return "POINT"; }
137 virtual void assign(dxfFile* dxf, codeValue& cv);
138 virtual void drawScene(scene* sc);
139 protected:
140 osg::Vec3d _a;
141 //osg::Vec3d _b;
142 osg::Vec3d _ocs;
143 };
144
145 class dxfLine : public dxfBasicEntity
146 {
147 public:
dxfLine()148 dxfLine() : _ocs(0,0,1) {}
~dxfLine()149 virtual ~dxfLine() {}
create()150 virtual dxfBasicEntity* create() { return new dxfLine; }
name()151 virtual const char* name() { return "LINE"; }
152 virtual void assign(dxfFile* dxf, codeValue& cv);
153 virtual void drawScene(scene* sc);
154 protected:
155 osg::Vec3d _a;
156 osg::Vec3d _b;
157 osg::Vec3d _ocs;
158 };
159
160 class dxf3DFace : public dxfBasicEntity
161 {
162 public:
dxf3DFace()163 dxf3DFace()
164 {
165 _vertices[0] = osg::Vec3d(0,0,0);
166 _vertices[1] = osg::Vec3d(0,0,0);
167 _vertices[2] = osg::Vec3d(0,0,0);
168 _vertices[3] = osg::Vec3d(0,0,0);
169 }
~dxf3DFace()170 virtual ~dxf3DFace() {}
create()171 virtual dxfBasicEntity* create() { return new dxf3DFace; }
name()172 virtual const char* name() { return "3DFACE"; }
173 virtual void assign(dxfFile* dxf, codeValue& cv);
174 virtual void drawScene(scene* sc);
175 protected:
176 osg::Vec3d _vertices[4];
177 };
178
179 class dxfVertex : public dxfBasicEntity
180 {
181 public:
dxfVertex()182 dxfVertex() : _vertex(osg::Vec3d(0,0,0)), _indice1(0), _indice2(0), _indice3(0), _indice4(0) {}
~dxfVertex()183 virtual ~dxfVertex() {}
create()184 virtual dxfBasicEntity* create() { return new dxfVertex; }
name()185 virtual const char* name() { return "VERTEX"; }
186 virtual void assign(dxfFile* dxf, codeValue& cv);
getVertex(double & x,double & y,double & z)187 void getVertex(double &x, double &y, double &z) { x=_vertex.x();y=_vertex.y();z=_vertex.z(); }
getVertex()188 const osg::Vec3d& getVertex() const { return _vertex; }
getIndice1()189 unsigned int getIndice1() const { return _indice1; }
getIndice2()190 unsigned int getIndice2() const { return _indice2; }
getIndice3()191 unsigned int getIndice3() const { return _indice3; }
getIndice4()192 unsigned int getIndice4() const { return _indice4; }
193
194 protected:
195 osg::Vec3d _vertex;
196 unsigned int _indice1, _indice2, _indice3, _indice4;
197 };
198
199 class dxfPolyline : public dxfBasicEntity
200 {
201 public:
dxfPolyline()202 dxfPolyline() : _currentVertex(NULL),
203 _elevation(0.0),
204 _flag(0),
205 _mcount(0),
206 _ncount(0),
207 _nstart(0),
208 _nend(0),
209 _ocs(osg::Vec3d(0,0,1)),
210 _mdensity(0),
211 _ndensity(0),
212 _surfacetype(0)
213 {}
~dxfPolyline()214 virtual ~dxfPolyline() {}
create()215 virtual dxfBasicEntity* create() { return new dxfPolyline; }
name()216 virtual const char* name() { return "POLYLINE"; }
217 virtual void assign(dxfFile* dxf, codeValue& cv);
vertexCount()218 virtual int vertexCount() { return _vertices.size(); }
219 virtual void drawScene(scene* sc);
220
221 protected:
222 dxfVertex* _currentVertex;
223 std::vector<osg::ref_ptr<dxfVertex> > _vertices;
224 std::vector<osg::ref_ptr<dxfVertex> > _indices;
225 double _elevation;
226 unsigned short _flag;
227 unsigned int _mcount;
228 unsigned int _ncount;
229 unsigned short _nstart; // 71
230 unsigned short _nend; //72
231 osg::Vec3d _ocs; //210 220 230
232 unsigned short _mdensity; // 73
233 unsigned short _ndensity; // 74
234 unsigned short _surfacetype; //75
235
236 };
237
238 class dxfLWPolyline : public dxfBasicEntity
239 {
240 public:
dxfLWPolyline()241 dxfLWPolyline() :
242 _elevation(0.0),
243 _flag(0),
244 _vcount(0),
245 _ocs(osg::Vec3d(0,0,1)),
246 _lastv(0,0,0)
247 {}
~dxfLWPolyline()248 virtual ~dxfLWPolyline() {}
create()249 virtual dxfBasicEntity* create() { return new dxfLWPolyline; }
name()250 virtual const char* name() { return "LWPOLYLINE"; }
251 virtual void assign(dxfFile* dxf, codeValue& cv);
vertexCount()252 virtual int vertexCount() { return _vertices.size(); }
253 virtual void drawScene(scene* sc);
254
255 protected:
256 double _elevation;
257 unsigned short _flag;
258 unsigned short _vcount; // 90
259 osg::Vec3d _ocs; //210 220 230
260 osg::Vec3d _lastv;
261 std::vector< osg::Vec3d > _vertices;
262
263 };
264
265 class dxfInsert : public dxfBasicEntity
266 {
267 public:
dxfInsert()268 dxfInsert() : _block(NULL),
269 _done(false),
270 _rotation(0),
271 _scale(1,1,1),
272 _point(osg::Vec3d(0,0,0)),
273 _ocs(osg::Vec3d(0,0,1)) {}
~dxfInsert()274 virtual ~dxfInsert() {}
create()275 virtual dxfBasicEntity* create() { return new dxfInsert; }
name()276 virtual const char* name() { return "INSERT"; }
277 virtual void assign(dxfFile* dxf, codeValue& cv);
278 virtual void drawScene(scene* sc);
279
280 protected:
281 std::string _blockName;
282 osg::ref_ptr<dxfBlock> _block;
283 bool _done; // since we are on a SEQEND, we must
284 // make sure not getting values addressed to other
285 // entities (dxf garble things) in the sequence
286 double _rotation;
287 osg::Vec3d _scale;
288 osg::Vec3d _point;
289 osg::Vec3d _ocs;
290 };
291
292 class dxfText : public dxfBasicEntity
293 {
294 public:
dxfText()295 dxfText() :
296 encoding(osgText::String::ENCODING_ASCII),
297 font("arial.ttf"),
298 _string(""),
299 _point1(0,0,0),
300 _point2(0,0,0),
301 _ocs(0,0,1),
302 _height(1),
303 _xscale(1),
304 _rotation(0),
305 _flags(0),
306 _hjustify(0),
307 _vjustify(0) {}
308
~dxfText()309 virtual ~dxfText() {}
create()310 virtual dxfBasicEntity* create()
311 {
312 dxfText* text = new dxfText;
313 text->encoding = encoding;
314 text->font = font;
315 return text;
316 }
317
name()318 virtual const char* name() { return "TEXT"; }
319 virtual void assign(dxfFile* dxf, codeValue& cv);
320 virtual void drawScene(scene* sc);
321
322 // application settings
323 osgText::String::Encoding encoding;
324 std::string font;
325
326 protected:
327 std::string _string; // 1
328 osg::Vec3d _point1; // 10,20,30
329 osg::Vec3d _point2; // 11,21,31
330 osg::Vec3d _ocs; // 210,220,230
331 double _height; // 40
332 double _xscale; // 41
333 double _rotation; // 50
334 int _flags; // 71
335 int _hjustify; // 72
336 int _vjustify; // 73
337 };
338
339 class dxfEntity : public osg::Referenced
340 {
341 public:
dxfEntity(std::string s)342 dxfEntity(std::string s) : _entity(NULL), _seqend(false)
343 {
344 _entity = findByName(s);
345 if (_entity) {
346 _entityList.push_back(_entity);
347 // std::cout << "entity " << s << std::endl;
348 }
349 }
350 virtual void assign(dxfFile* dxf, codeValue& cv);
done()351 virtual bool done() { return !_seqend; }
352 static void registerEntity(dxfBasicEntity*);
353 static void unregisterEntity(dxfBasicEntity*);
findByName(std::string s)354 static dxfBasicEntity* findByName(std::string s)
355 {
356 dxfBasicEntity* be = _registry[s].get();
357 if (be)
358 return be->create();
359 else {
360 std::cout << " no " << s << std::endl;
361 return NULL;
362 }
363 }
364 virtual void drawScene(scene* sc);
getEntity()365 dxfBasicEntity* getEntity() { return _entity; }
366
367 // Returns the exemplar from the registry - all other entities of this type are created by this one via entity->create
getRegistryEntity(std::string s)368 static dxfBasicEntity* getRegistryEntity(std::string s) {
369 return _registry[s].get();
370 }
371
372 protected:
373 std::vector<osg::ref_ptr<dxfBasicEntity> > _entityList;
374 static std::map<std::string, osg::ref_ptr<dxfBasicEntity> > _registry;
375 dxfBasicEntity* _entity;
376 bool _seqend; // bypass 0 codes. needs a 0 seqend to close.
377
378
379
380 };
381
382 /** Proxy class for automatic registration of dxf entities reader/writers.*/
383 template<class T>
384 class RegisterEntityProxy
385 {
386 public:
RegisterEntityProxy()387 RegisterEntityProxy()
388 {
389 _rw = new T;
390 dxfEntity::registerEntity(_rw.get());
391 }
392
~RegisterEntityProxy()393 ~RegisterEntityProxy()
394 {
395 dxfEntity::unregisterEntity(_rw.get());
396 }
397
get()398 T* get() { return _rw.get(); }
399
400 protected:
401 osg::ref_ptr<T> _rw;
402 };
403
404 #endif
405