root/OpenSceneGraph/trunk/src/osgPlugins/dxf/dxfEntity.cpp @ 9993

Revision 9993, 29.3 kB (checked in by robert, 5 years ago)

From Mike Connell, "Here are some small fixes that allow you to specify the allowable deviation when creating polylines from arcs and circles in DXF files. Changes are against 2.8.0

It adds two options:

Accuracy(x) - ensures the polyline will be within x units from the ideal arc/curve
ImproveAccuracyOnly? - do not use the given accuracy 'x', if it would result in a worse curve than with the previous (2.8.0) implementation for a particular arc/curve.

As an added bonus there was a small bug in the existing implementation whereby the primitives were line strips but the vertices generated were actually suitable for GL_LINES, so the improved accuracy doesn't even have to come at a performance cost :-)"

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
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#include "dxfEntity.h"
14#include "dxfFile.h"
15#include "scene.h"
16#include "dxfBlock.h"
17#include "codeValue.h"
18
19#include <osg/io_utils> // just for debugging
20
21using namespace std;
22using namespace osg;
23
24// static
25std::map<std::string, ref_ptr<dxfBasicEntity> > dxfEntity::_registry;
26RegisterEntityProxy<dxf3DFace> g_dxf3DFace;
27RegisterEntityProxy<dxfCircle> g_dxfCircle;
28RegisterEntityProxy<dxfArc> g_dxfArc;
29RegisterEntityProxy<dxfPoint> g_dxfPoint;
30RegisterEntityProxy<dxfLine> g_dxfLine;
31RegisterEntityProxy<dxfVertex> g_dxfVertex;
32RegisterEntityProxy<dxfPolyline> g_dxfPolyline;
33RegisterEntityProxy<dxfLWPolyline> g_dxfLWPolyline;
34RegisterEntityProxy<dxfInsert> g_dxfInsert;
35RegisterEntityProxy<dxfText> g_dxfText;
36
37void 
38dxfBasicEntity::assign(dxfFile* , codeValue& cv)
39{
40    switch (cv._groupCode) {
41        case 8:
42            _layer = cv._string;
43            break;
44        case 62:
45            _color = cv._short;
46            break;
47    }
48}
49
50void
51dxf3DFace::assign(dxfFile* dxf, codeValue& cv)
52{
53    double d = cv._double;
54    switch (cv._groupCode) {
55        case 10:
56        case 11:
57        case 12:
58        case 13:
59            _vertices[cv._groupCode - 10].x() = d;
60            break;
61        case 20:
62        case 21:
63        case 22:
64        case 23:
65            _vertices[cv._groupCode - 20].y() = d;
66            break;
67        case 30:
68        case 31:
69        case 32:
70        case 33:
71            _vertices[cv._groupCode - 30].z() = d;
72            break;
73           
74        default:
75            dxfBasicEntity::assign(dxf, cv);
76            break;
77    }
78}
79
80void
81dxf3DFace::drawScene(scene* sc)
82{
83    std::vector<Vec3d> vlist;
84    short nfaces = 3;
85
86    // Hate to do that, but hey, that's written in the DXF specs:
87    if (_vertices[2] != _vertices[3]) nfaces = 4;
88
89    for (short i = nfaces-1; i >= 0; i--)
90        vlist.push_back(_vertices[i]);
91
92    if (nfaces == 3) {
93        // to do make sure we're % 3
94        sc->addTriangles(getLayer(), _color, vlist);
95    } else if (nfaces == 4) {
96        // to do make sure we're % 4
97        sc->addQuads(getLayer(), _color, vlist);
98    }
99}
100
101void
102dxfVertex::assign(dxfFile* dxf, codeValue& cv)
103{
104    double d = cv._double;
105    // 2005.12.13 pdr: learned today that negative indices mean something and were possible
106   
107    int s = cv._int; // 2005.12.13 pdr: group codes [70,78] now signed int.
108    if ( s < 0 ) s = -s;
109    switch (cv._groupCode) {
110        case 10:
111            _vertex.x() = d;
112            break;
113        case 20:
114            _vertex.y() = d;
115            break;
116        case 30:
117            _vertex.z() = d;
118            break;
119        case 71:
120            _indice1 = s;
121            break;
122        case 72:
123            _indice2 = s;
124            break;
125        case 73:
126            _indice3 = s;
127            break;
128        case 74:
129            _indice4 = s;
130            break;
131           
132        default:
133            dxfBasicEntity::assign(dxf, cv);
134            break;
135    }
136}
137
138void
139dxfCircle::assign(dxfFile* dxf, codeValue& cv)
140{
141    double d = cv._double;
142    //unsigned short s = cv._short;
143    switch (cv._groupCode) {
144        case 10:
145            _center.x() = d;
146            break;
147        case 20:
148            _center.y() = d;
149            break;
150        case 30:
151            _center.z() = d;
152            break;
153        case 40:
154            _radius = d;
155            break;
156        case 210:
157            _ocs.x() = d;
158            break;
159        case 220:
160            _ocs.y() = d;
161            break;
162        case 230:
163            _ocs.z() = d;
164            break;
165        default:
166            dxfBasicEntity::assign(dxf, cv);
167            break;
168    }
169}
170
171void
172dxfCircle::drawScene(scene* sc)
173{
174    Matrixd m;
175    getOCSMatrix(_ocs, m);
176    sc->ocs(m);
177    std::vector<Vec3d> vlist;
178
179    double theta=5.0; // we generate polyline from "spokes" at theta degrees at arc's center
180
181    if (_useAccuracy) {
182        // we generate points on a polyline where each point lies on the arc, thus the maximum error occurs at the midpoint of each line segment where it lies furthest inside the arc
183        // If we divide the segment in half and connect the bisection point to the arc's center, we have two rightangled triangles with
184        // one side=r-maxError, hypotenuse=r, and internal angle at center is half the angle we will step with:
185        double maxError=min(_maxError,_radius); // Avoid offending acos() in the edge case where allowable deviation is greater than radius.
186        double newtheta=acos( (_radius-maxError) / _radius);
187        newtheta=osg::RadiansToDegrees(newtheta)*2.0;
188       
189        // Option to only use the new accuracy code when it would improve on the accuracy of the old method
190        if (_improveAccuracyOnly) {
191            theta=min(newtheta,theta);
192        } else {
193            theta=newtheta;
194        }
195    }
196    theta=osg::DegreesToRadians(theta);
197
198    // We create an anglestep<=theta so that the line's points are evenly distributed around the circle
199    unsigned int numsteps=floor(osg::PI*2/theta);
200    if (numsteps<3) numsteps=3; // Sanity check: minimal representation of a circle is a tri
201    double anglestep=osg::PI*2/numsteps;
202
203    double angle1 = 0.0;
204    Vec3d a = _center;
205    Vec3d b;
206    for(unsigned int r=0;r<=numsteps;r++) {
207        b = a + Vec3d(_radius * (double) sin(angle1), _radius * (double) cos(angle1), 0);
208        angle1 += anglestep;
209        vlist.push_back(b);
210    }
211
212    sc->addLineStrip(getLayer(), _color, vlist); // Should really add LineLoop implementation and save a vertex
213    sc->ocs_clear();
214}
215
216
217void
218dxfArc::assign(dxfFile* dxf, codeValue& cv)
219{
220    double d = cv._double;
221    //unsigned short s = cv._short;
222    switch (cv._groupCode) {
223        case 10:
224            _center.x() = d;
225            break;
226        case 20:
227            _center.y() = d;
228            break;
229        case 30:
230            _center.z() = d;
231            break;
232        case 40:
233            _radius = d;
234            break;
235        case 50:
236            _startAngle = d;
237            break;
238        case 51:
239            _endAngle = d;
240            break;
241        case 210:
242            _ocs.x() = d;
243            break;
244        case 220:
245            _ocs.y() = d;
246            break;
247        case 230:
248            _ocs.z() = d;
249            break;
250        default:
251            dxfBasicEntity::assign(dxf, cv);
252            break;
253    }
254}
255
256void
257dxfArc::drawScene(scene* sc)
258{
259    Matrixd m;
260    getOCSMatrix(_ocs, m);
261    sc->ocs(m);
262    std::vector<Vec3d> vlist;
263    double end;
264    double start;
265    if (_startAngle > _endAngle) {
266        start = _startAngle;
267        end = _endAngle + 360;
268    } else {
269        start = _startAngle;
270        end = _endAngle;
271    }
272
273    double theta=5.0; // we generate polyline from "spokes" at theta degrees at arc's center
274
275    if (_useAccuracy) {
276        // we generate points on a polyline where each point lies on the arc, thus the maximum error occurs at the midpoint of each line segment where it lies furthest inside the arc
277        // If we divide the segment in half and connect the bisection point to the arc's center, we have two rightangled triangles with
278        // one side=r-maxError, hypotenuse=r, and internal angle at center is half the angle we will step with:
279        double maxError=min(_maxError,_radius); // Avoid offending acos() in the edge case where allowable deviation is greater than radius.
280        double newtheta=acos( (_radius-maxError) / _radius);
281        newtheta=osg::RadiansToDegrees(newtheta)*2.0;
282        //cout<<"r="<<_radius<<" _me="<<_maxError<<" (_radius-_maxError)="<<(_radius-_maxError)<<" newtheta="<<newtheta<<endl;
283        // Option to only use the new accuracy code when it would improve on the accuracy of the old method
284        if (_improveAccuracyOnly) {
285            theta=min(newtheta,theta);
286        } else {
287            theta=newtheta;
288        }
289    }
290
291    double angle_step = DegreesToRadians(end - start);
292    int numsteps = (int)((end - start)/theta);
293    //cout<<"arc theta="<<osg::RadiansToDegrees(theta)<<" end="<<end<<" start="<<start<<" numsteps="<<numsteps<<" e-s/theta="<<((end-start)/theta)<<" end-start="<<(end-start)<<endl;
294    if (numsteps * theta < (end - start)) numsteps++;
295    numsteps=max(numsteps,2); // Whatever else, minimum representation of an arc is a straightline
296    angle_step /=  (double) numsteps;
297    end = DegreesToRadians((-_startAngle)+90.0);
298    start = DegreesToRadians((-_endAngle)+90.0);
299    double angle1 = start;
300   
301    Vec3d a = _center;
302    Vec3d b;
303
304    for (int r = 0; r <= numsteps; r++)
305    {
306        b = a + Vec3d(_radius * (double) sin(angle1), _radius * (double) cos(angle1), 0);
307        angle1 += angle_step;
308        vlist.push_back(b);
309    }
310
311
312    sc->addLineStrip(getLayer(), _color, vlist);
313    sc->ocs_clear();
314}
315
316void
317dxfLine::assign(dxfFile* dxf, codeValue& cv)
318{
319    double d = cv._double;
320    //unsigned short s = cv._short;
321    switch (cv._groupCode) {
322        case 10:
323            _a.x() = d;
324            break;
325        case 20:
326            _a.y() = d;
327            break;
328        case 30:
329            _a.z() = d;
330            break;
331        case 11:
332            _b.x() = d;
333            break;
334        case 21:
335            _b.y() = d;
336            break;
337        case 31:
338            _b.z() = d;
339            break;
340        case 210:
341            _ocs.x() = d;
342            break;
343        case 220:
344            _ocs.y() = d;
345            break;
346        case 230:
347            _ocs.z() = d;
348            break;
349        default:
350            dxfBasicEntity::assign(dxf, cv);
351            break;
352    }
353}
354
355void
356dxfLine::drawScene(scene* sc)
357{
358    Matrixd m;
359    getOCSMatrix(_ocs, m);
360    // don't know why this doesn't work
361//    sc->ocs(m);
362    sc->addLine(getLayer(), _color, _b, _a);
363//    static long lcount = 0;
364//    std::cout << ++lcount << " ";
365//    sc->ocs_clear();
366}
367void
368dxfPoint::assign(dxfFile* dxf, codeValue& cv)
369{
370    double d = cv._double;
371    //unsigned short s = cv._short;
372    switch (cv._groupCode) {
373        case 10:
374            _a.x() = d;
375            break;
376        case 20:
377            _a.y() = d;
378            break;
379        case 30:
380            _a.z() = d;
381            break;
382        default:
383            dxfBasicEntity::assign(dxf, cv);
384            break;
385    }
386}
387
388void
389dxfPoint::drawScene(scene* sc)
390{
391    Matrixd m;
392    getOCSMatrix(_ocs, m);
393    sc->addPoint(getLayer(), _color,_a);
394}
395
396void 
397dxfPolyline::assign(dxfFile* dxf, codeValue& cv)
398{
399    string s = cv._string;
400    if (cv._groupCode == 0) {
401        if (s == "VERTEX") {
402            _currentVertex = new dxfVertex;
403            _vertices.push_back(_currentVertex);
404        }
405    } else if (_currentVertex) {
406        _currentVertex->assign(dxf, cv);
407
408        if ((_flag & 64 /*i.e. polymesh*/) &&
409            (cv._groupCode == 70 /*i.e. vertex flag*/) &&
410            (cv._int && 128 /*i.e. vertex is actually a face*/))
411            _indices.push_back(_currentVertex); // Add the index only if _currentvertex is actually an index
412    } else {
413        double d = cv._double;
414        switch (cv._groupCode) {
415            case 10:
416                // dummy
417                break;
418            case 20:
419                // dummy
420                break;
421            case 30:
422                _elevation = d; // what is elevation?
423                break;
424            case 70:
425                _flag = cv._int; // 2005.12.13 pdr: group codes [70,78] now signed int.
426                break;
427            case 71:
428                // Meaningful only when _surfacetype == 6, don' trust it for polymeshes.
429                // From the docs :
430                // "The 71 group specifies the number of vertices in the mesh, and the 72 group
431                // specifies the number of faces. Although these counts are correct for all meshes
432                // created with the PFACE command, applications are not required to place correct
433                // values in these fields.)"
434                // Amusing isn't it ?
435                _mcount = cv._int; // 2005.12.13 pdr: group codes [70,78] now signed int.
436                break;
437            case 72:
438                // Meaningful only when _surfacetype == 6, don' trust it for polymeshes.
439                // From the docs :
440                // "The 71 group specifies the number of vertices in the mesh, and the 72 group
441                // specifies the number of faces. Although these counts are correct for all meshes
442                // created with the PFACE command, applications are not required to place correct
443                // values in these fields.)"
444                // Amusing isn't it ?
445                _ncount = cv._int; // 2005.12.13 pdr: group codes [70,78] now signed int.
446                break;
447            case 73:
448                _mdensity = cv._int; // 2005.12.13 pdr: group codes [70,78] now signed int.
449                break;
450            case 74:
451                _ndensity = cv._int; // 2005.12.13 pdr: group codes [70,78] now signed int.
452                break;
453            case 75:
454                _surfacetype = cv._int; // 2005.12.13 pdr: group codes [70,78] now signed int.
455                break;
456            case 210:
457                _ocs.x() = d;
458                break;
459            case 220:
460                _ocs.y() = d;
461                break;
462            case 230:
463                _ocs.z() = d;
464                break;
465            default:
466                dxfBasicEntity::assign(dxf, cv);
467                break;
468        }
469    }
470}
471
472
473void
474dxfPolyline::drawScene(scene* sc)
475{
476    Matrixd m;
477    getOCSMatrix(_ocs, m);
478    sc->ocs(m);
479    std::vector<Vec3d> vlist;
480    std::vector<Vec3d> qlist;
481    Vec3d a, b, c, d;
482    bool invert_order = false;
483    if (_flag & 16) {
484        std::vector<Vec3d> nlist;
485        Vec3d nr;
486        bool nset = false;
487        //dxfVertex* v = NULL;
488        unsigned int ncount;
489        unsigned int mcount;
490        if (_surfacetype == 6) {
491            // I dont have examples of type 5 and 8, but they may be the same as 6
492            mcount = _mdensity;
493            ncount = _ndensity;
494        } else {
495            mcount = _mcount;
496            ncount = _ncount;
497        }
498        for (unsigned int n = 0; n < ncount-1; n++) {
499            for (unsigned int m = 1; m < mcount; m++) {
500                // 0
501                a = _vertices[(m-1)*ncount+n].get()->getVertex();
502                // 1
503                b = _vertices[m*ncount+n].get()->getVertex();
504                // 3
505                c = _vertices[(m)*ncount+n+1].get()->getVertex();
506                // 2
507                d = _vertices[(m-1)*ncount+n+1].get()->getVertex();
508                if (a == b ) {
509                    vlist.push_back(a);
510                    vlist.push_back(c);
511                    vlist.push_back(d);
512                    b = c;
513                    c = d;
514                } else if (c == d) {
515                    vlist.push_back(a);
516                    vlist.push_back(b);
517                    vlist.push_back(c);
518                } else {
519                    qlist.push_back(a);
520                    qlist.push_back(b);
521                    qlist.push_back(c);
522                    qlist.push_back(d);
523                }
524                if (!nset) {
525                    nset = true;
526                    nr = (b - a) ^ (c - a);
527                    nr.normalize();
528                }
529                nlist.push_back(a);
530            }
531        }
532        if (_flag & 1) {
533            for (unsigned int n = 0; n < ncount-1; n++) {
534                // 0
535                a = _vertices[(mcount-1)*ncount+n].get()->getVertex();
536                // 1
537                b = _vertices[0*ncount+n].get()->getVertex();
538                // 3
539                c = _vertices[(0)*ncount+n+1].get()->getVertex();
540                // 2
541                d = _vertices[(mcount-1)*ncount+n+1].get()->getVertex();
542                if (a == b ) {
543                    vlist.push_back(a);
544                    vlist.push_back(c);
545                    vlist.push_back(d);
546                    b = c;
547                    c = d;
548                } else if (c == d) {
549                    vlist.push_back(a);
550                    vlist.push_back(b);
551                    vlist.push_back(c);
552                } else {
553                    qlist.push_back(a);
554                    qlist.push_back(b);
555                    qlist.push_back(c);
556                    qlist.push_back(d);
557                }
558                nlist.push_back(a);
559            }
560        }
561        if (_flag & 32) {
562            for (unsigned int m = 1; m < mcount; m++) {
563                // 0
564                a = _vertices[(m-1)*ncount+(ncount-1)].get()->getVertex();
565                // 1
566                b = _vertices[m*ncount+(ncount-1)].get()->getVertex();
567                // 3
568                c = _vertices[(m)*ncount].get()->getVertex();
569                // 2
570                d = _vertices[(m-1)*ncount].get()->getVertex();
571                if (a == b ) {
572                    vlist.push_back(a);
573                    vlist.push_back(c);
574                    vlist.push_back(d);
575                    b = c;
576                    c = d;
577                } else if (c == d) {
578                    vlist.push_back(a);
579                    vlist.push_back(b);
580                    vlist.push_back(c);
581                } else {
582                    qlist.push_back(a);
583                    qlist.push_back(b);
584                    qlist.push_back(c);
585                    qlist.push_back(d);
586                }
587                nlist.push_back(a);
588            }
589        }
590
591        // a naive attempt to determine vertex ordering
592        VList::iterator itr = nlist.begin();
593        Vec3d lastn = (*itr++);
594        double bad_c = 0;
595        double good_c = 0;
596        long bad=0,good=0;
597        for (; itr != nlist.end(); ) {
598            ++itr;
599            if ((*itr)== lastn) continue;
600            Vec3d diff = ((*itr)-lastn);
601            diff.normalize();
602            float dot = diff * nr;
603            if (dot > 0.0) {
604                bad_c += dot;
605                ++bad;
606            } else {
607                ++good;
608                good_c += dot;
609            }
610        }
611        if (bad > good) {
612            invert_order = true;
613        }
614
615        if (qlist.size())
616            sc->addQuads(getLayer(), _color, qlist, invert_order);
617        if (vlist.size())
618            sc->addTriangles(getLayer(), _color, vlist, invert_order);
619
620    } else if (_flag & 64) {
621        unsigned short _facetype = 3;
622
623        for (unsigned int i = 0; i < _indices.size(); i++) {
624            dxfVertex* vindice = _indices[i].get();
625            if (!vindice) continue;
626            if (vindice->getIndice4()) {
627                _facetype = 4;
628                d = _vertices[vindice->getIndice4()-1].get()->getVertex();
629            } else {
630                _facetype = 3;
631            }
632            if (vindice->getIndice3()) {
633                c = _vertices[vindice->getIndice3()-1].get()->getVertex();
634            } else {
635                c = vindice->getVertex(); // Vertex not indexed. Use as is
636            }
637            if (vindice->getIndice2()) {
638                b = _vertices[vindice->getIndice2()-1].get()->getVertex();
639            } else {
640                b = vindice->getVertex(); // Vertex not indexed. Use as is
641            }
642            if (vindice->getIndice1()) {
643                a = _vertices[vindice->getIndice1()-1].get()->getVertex();
644            } else {
645                a = vindice->getVertex(); // Vertex not indexed. Use as is
646            }
647            if (_facetype == 4) {
648                qlist.push_back(d);
649                qlist.push_back(c);
650                qlist.push_back(b);
651                qlist.push_back(a);
652            } else {
653                // 2005.12.13 pdr: vlist! not qlist!
654                vlist.push_back(c);
655                vlist.push_back(b);
656                vlist.push_back(a);
657            }
658        }
659        if (vlist.size())
660            sc->addTriangles(getLayer(), _color, vlist);
661        if (qlist.size())
662            sc->addQuads(getLayer(), _color, qlist);
663        // is there a flag 1 or 32 for 64?
664    } else {
665        // simple polyline?
666        for (int i = _vertices.size()-1; i >= 0; i--)
667            vlist.push_back(_vertices[i]->getVertex());
668        if (_flag & 1) {
669//            std::cout << "line loop " << _vertices.size() << std::endl;
670            sc->addLineLoop(getLayer(), _color, vlist);
671        } else {
672//            std::cout << "line strip " << _vertices.size() << std::endl;
673            sc->addLineStrip(getLayer(), _color, vlist);
674        }
675
676    }
677    sc->ocs_clear();
678}
679
680void 
681dxfLWPolyline::assign(dxfFile* dxf, codeValue& cv)
682{
683    string s = cv._string;
684
685    double d = cv._double;
686    switch (cv._groupCode) {
687        case 10:
688            _lastv.x() = d;
689            // x
690            break;
691        case 20:
692            _lastv.y() = d;
693            _lastv.z() = _elevation;
694            _vertices.push_back ( _lastv );
695            // y -> on shoot
696            break;
697        case 38:
698            _elevation = d; // what is elevation?
699            break;
700        case 70:
701            _flag = cv._int; // 2005.12.13 pdr: group codes [70,78] now signed int.
702            break;
703        case 90:
704            _vcount = cv._short;
705            break;
706        case 210:
707            _ocs.x() = d;
708            break;
709        case 220:
710            _ocs.y() = d;
711            break;
712        case 230:
713            _ocs.z() = d;
714            break;
715        default:
716            dxfBasicEntity::assign(dxf, cv);
717            break;
718    }
719}
720
721
722void
723dxfLWPolyline::drawScene(scene* sc)
724{
725//    if (getLayer() != "UDF2" && getLayer() != "ENGINES") return;
726//    if (!(_flag & 16)) return;
727    Matrixd m;
728    getOCSMatrix(_ocs, m);
729    sc->ocs(m);
730    if (_flag & 1) {
731//        std::cout << "lwpolyline line loop " << _vertices.size() << std::endl;
732        sc->addLineLoop(getLayer(), _color, _vertices);
733    } else {
734//        std::cout << "lwpolyline line strip " << _vertices.size() << std::endl;
735        sc->addLineStrip(getLayer(), _color, _vertices);
736    }
737    sc->ocs_clear();
738}
739
740void
741dxfInsert::assign(dxfFile* dxf, codeValue& cv)
742{
743    string s = cv._string;
744    if (_done || (cv._groupCode == 0 && s != "INSERT")) {
745        _done = true;
746        return;
747    }
748    if (cv._groupCode == 2 && !_block) {
749        _blockName = s;
750        _block = dxf->findBlock(s);
751    } else {
752        double d = cv._double;
753        switch (cv._groupCode) {
754            case 10:
755                _point.x() = d;
756                break;
757            case 20:
758                _point.y() = d;
759                break;
760            case 30:
761                _point.z() = d;
762                break;
763            case 41:
764                _scale.x() = d;
765                break;
766            case 42:
767                _scale.y() = d;
768                break;
769            case 43:
770                _scale.z() = d;
771                break;
772            case 50:
773                _rotation = d;
774                break;
775            case 210:
776                _ocs.x() = d;
777                break;
778            case 220:
779                _ocs.y() = d;
780                break;
781            case 230:
782                _ocs.z() = d;
783                break;
784            default:
785                dxfBasicEntity::assign(dxf, cv);
786                break;
787        }
788    }
789}
790
791/// hum. read the doc, then come back here. then try to figure.
792void
793dxfInsert::drawScene(scene* sc)
794{
795    // INSERTs can be nested. So pull the current matrix
796    // and push it back after we fill our context
797    // This is a snapshot in time. I will rewrite all this to be cleaner,
798    // but for now, it seems working fine
799    // (with the files I have, the results are equal to Voloview,
800    // and better than Deep Exploration and Lightwave).
801   
802    // sanity check (useful when no block remains after all unsupported entities have been filtered out)
803    if (!_block)
804        return;
805
806    Matrixd back = sc->backMatrix();
807    Matrixd m;
808    m.makeIdentity();
809    sc->pushMatrix(m, true);
810    Vec3d trans = _block->getPosition();
811    sc->blockOffset(-trans);
812    if (_rotation) {
813        sc->pushMatrix(Matrixd::rotate(osg::DegreesToRadians(_rotation), 0,0,1));
814    }
815    sc->pushMatrix(Matrixd::scale(_scale.x(), _scale.y(), _scale.z()));
816    sc->pushMatrix(Matrixd::translate(_point.x(), _point.y(), _point.z()));
817    getOCSMatrix(_ocs, m);
818    sc->pushMatrix(m);
819    sc->pushMatrix(back);
820
821    EntityList& l = _block->getEntityList();
822    for (EntityList::iterator itr = l.begin(); itr != l.end(); ++itr) {
823        dxfBasicEntity* e = (*itr)->getEntity();
824        if (e) {
825            e->drawScene(sc);
826        }
827    }
828
829    sc->popMatrix(); // ocs
830    sc->popMatrix(); // translate
831    sc->popMatrix(); // scale
832    if (_rotation) {
833        sc->popMatrix(); // rotate
834    }
835    sc->popMatrix(); // identity
836    sc->popMatrix(); // back
837    sc->blockOffset(Vec3d(0,0,0));
838
839}
840
841void 
842dxfText::assign(dxfFile* dxf, codeValue& cv)
843{
844    switch (cv._groupCode) {
845        case 1:
846            _string = cv._string;
847            break;
848        case 10:
849            _point1.x() = cv._double;
850            break;
851        case 20:
852            _point1.y() = cv._double;
853            break;
854        case 30:
855            _point1.z() = cv._double;
856            break;
857        case 11:
858            _point2.x() = cv._double;
859            break;
860        case 21:
861            _point2.y() = cv._double;
862            break;
863        case 31:
864            _point2.z() = cv._double;
865            break;
866        case 40:
867            _height = cv._double;
868            break;
869        case 41:
870            _xscale = cv._double;
871            break;
872        case 50:
873            _rotation = cv._double;
874            break;
875        case 71:
876            _flags = cv._int;
877            break;
878        case 72:
879            _hjustify = cv._int;
880            break;
881        case 73:
882            _vjustify = cv._int;
883            break;
884        case 210:
885            _ocs.x() = cv._double;
886            break;
887        case 220:
888            _ocs.y() = cv._double;
889            break;
890        case 230:
891            _ocs.z() = cv._double;
892            break;
893        default:
894            dxfBasicEntity::assign(dxf, cv);
895            break;
896    }
897}
898
899
900void
901dxfText::drawScene(scene* sc)
902{
903    osgText::Text::AlignmentType align;
904
905    Matrixd m;
906    getOCSMatrix(_ocs, m);
907    sc->ocs(m);
908
909    ref_ptr<osgText::Text> _text = new osgText::Text;
910    _text->setText(_string);
911
912    _text->setCharacterSize( _height, 1.0/_xscale );
913    _text->setFont("arial.ttf");
914     
915    Quat qr( DegreesToRadians(_rotation), Z_AXIS );
916   
917    if ( _flags & 2 ) qr = Quat( PI, Y_AXIS ) * qr;
918    if ( _flags & 4 ) qr = Quat( PI, X_AXIS ) * qr;
919   
920    _text->setAxisAlignment(osgText::Text::USER_DEFINED_ROTATION);
921    _text->setRotation(qr);
922   
923    if ( _hjustify != 0 || _vjustify !=0 ) _point1 = _point2;
924   
925    switch (_vjustify) {
926    case 3:
927        switch (_hjustify) {
928        case 2:
929            align = osgText::Text::RIGHT_TOP;
930            break;
931        case 1:
932            align = osgText::Text::CENTER_TOP;
933            break;
934        default:
935            align = osgText::Text::LEFT_TOP;
936        }
937        break;
938    case 2:
939        switch (_hjustify) {
940        case 2:
941            align = osgText::Text::RIGHT_CENTER;
942            break;
943        case 1:
944            align = osgText::Text::CENTER_CENTER;
945            break;
946        default:
947            align = osgText::Text::LEFT_CENTER;
948        }
949        break;
950    case 1:
951        switch (_hjustify) {
952        case 2:
953            align = osgText::Text::RIGHT_BOTTOM;
954            break;
955        case 1:
956            align = osgText::Text::CENTER_BOTTOM;
957            break;
958        default:
959            align = osgText::Text::LEFT_BOTTOM;
960        }
961        break;
962    default:
963        switch (_hjustify) {
964        case 2:
965            align = osgText::Text::RIGHT_BOTTOM_BASE_LINE;
966            break;
967        case 1:
968            align = osgText::Text::CENTER_BOTTOM_BASE_LINE;
969            break;
970        default:
971            align = osgText::Text::LEFT_BOTTOM_BASE_LINE;
972        }
973        break;
974    }
975   
976    _text->setAlignment(align);
977   
978    sc->addText(getLayer(), _color, _point1, _text.get());
979    sc->ocs_clear();
980}
981
982
983// static
984void 
985dxfEntity::registerEntity(dxfBasicEntity* entity)
986{
987    _registry[entity->name()] = entity;
988}
989
990// static
991void 
992dxfEntity::unregisterEntity(dxfBasicEntity* entity)
993{
994    map<string, ref_ptr<dxfBasicEntity > >::iterator itr = _registry.find(entity->name());
995    if (itr != _registry.end()) {
996        _registry.erase(itr);
997    }
998}
999
1000void dxfEntity::drawScene(scene* sc)
1001{
1002    for (std::vector<ref_ptr<dxfBasicEntity > >::iterator itr = _entityList.begin();
1003        itr != _entityList.end(); ++itr) {
1004            (*itr)->drawScene(sc);
1005    }
1006}
1007
1008void 
1009dxfEntity::assign(dxfFile* dxf, codeValue& cv)
1010{
1011    string s = cv._string;
1012    if (cv._groupCode == 66 && !(_entity && string("TABLE") == _entity->name())) {
1013        // The funny thing here. Group code 66 has been called 'obsoleted'
1014        // for a POLYLINE. But not for an INSERT. Moreover, a TABLE
1015        // can have a 66 for... an obscure bottom cell color value.
1016        // I decided to rely on the presence of the 66 code for
1017        // the POLYLINE. If you find a better alternative,
1018        // contact me, or correct this code
1019        // and post the correction to osg mailing list
1020        _seqend = true;
1021    } else if (_seqend && cv._groupCode == 0 && s == "SEQEND") {
1022        _seqend = false;
1023//        cout << "... off" << endl;
1024    } else if (_entity) {
1025        _entity->assign(dxf, cv);
1026    }
1027}
Note: See TracBrowser for help on using the browser.