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