root/OpenSceneGraph/trunk/src/osgPlugins/shp/ESRIShapeParser.cpp @ 13041

Revision 13041, 19.4 kB (checked in by robert, 2 years ago)

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1#include <fcntl.h>
2#include <osg/Geometry>
3#include <osg/Notify>
4#include <osgUtil/Tessellator>
5
6#if defined(_MSC_VER)
7    #include <io.h>
8    #include <stdio.h>
9#endif
10
11#include "ESRIShapeParser.h"
12
13using namespace ESRIShape;
14
15ESRIShapeParser::ESRIShapeParser( const std::string fileName, bool useDouble ):
16    _valid(false),
17    _useDouble(useDouble)
18{
19    int fd = 0;
20    if( !fileName.empty() )
21    {
22#ifdef WIN32
23        if( (fd = open( fileName.c_str(), O_RDONLY | O_BINARY )) <= 0 )
24#else
25        if( (fd = open( fileName.c_str(), O_RDONLY )) <= 0 )
26#endif
27        {
28            if (fd) close ( fd );
29            perror( fileName.c_str() );
30            return ;
31        }
32    }
33
34    _valid = true;
35
36    ESRIShape::ShapeHeader head;
37    head.read(fd);
38
39    //head.print();
40
41    _geode = new osg::Geode;
42
43    switch( head.shapeType )
44    {
45        case ESRIShape::ShapeTypeNullShape  :
46            break;
47
48        case ESRIShape::ShapeTypePoint      :
49            {
50                std::vector<ESRIShape::Point> pts;
51                ESRIShape::PointRecord pointRecord;
52                while( pointRecord.read(fd) )
53                    pts.push_back( pointRecord.point );
54                _process( pts );
55            }
56            break;
57
58        case ESRIShape::ShapeTypeMultiPoint :
59            {
60                std::vector<ESRIShape::MultiPoint> mpts;
61                ESRIShape::MultiPoint mpoint;
62
63                while( mpoint.read(fd) )
64                    mpts.push_back( mpoint );
65
66                _process(  mpts );
67            }
68            break;
69
70        case ESRIShape::ShapeTypePolyLine   :
71            {
72                std::vector<ESRIShape::PolyLine> plines;
73                ESRIShape::PolyLine pline;
74
75                while( pline.read(fd) )
76                    plines.push_back( pline );
77
78                _process( plines );
79
80            }
81            break;
82
83        case ESRIShape::ShapeTypePolygon    :
84            {
85                std::vector<ESRIShape::Polygon> polys;
86                ESRIShape::Polygon poly;
87
88                while( poly.read(fd) )
89                    polys.push_back( poly );
90
91                _process( polys );
92            }
93            break;
94
95        case ESRIShape::ShapeTypePointM      :
96            {
97                std::vector<ESRIShape::PointM> ptms;
98                ESRIShape::PointMRecord pointMRecord;
99                while( pointMRecord.read(fd) )
100                    ptms.push_back( pointMRecord.pointM );
101                _process( ptms );
102            }
103            break;
104
105        case ESRIShape::ShapeTypeMultiPointM :
106            {
107                std::vector<ESRIShape::MultiPointM> mptms;
108                ESRIShape::MultiPointM mpointm;
109
110                while( mpointm.read(fd) )
111                    mptms.push_back( mpointm );
112
113                _process(  mptms );
114            }
115            break;
116
117        case ESRIShape::ShapeTypePolyLineM   :
118            {
119                std::vector<ESRIShape::PolyLineM> plinems;
120                ESRIShape::PolyLineM plinem;
121
122                while( plinem.read(fd) )
123                    plinems.push_back( plinem );
124
125                _process( plinems );
126            }
127            break;
128
129        case ESRIShape::ShapeTypePolygonM    :
130            {
131                std::vector<ESRIShape::PolygonM> polyms;
132                ESRIShape::PolygonM polym;
133
134                while( polym.read(fd) )
135                    polyms.push_back( polym );
136
137                _process( polyms );
138            }
139            break;
140
141
142        case ESRIShape::ShapeTypePointZ      :
143            {
144                std::vector<ESRIShape::PointZ> ptzs;
145                ESRIShape::PointZ pointZ;
146                while( pointZ.read( fd ) )
147                    ptzs.push_back( pointZ );
148                _process( ptzs );
149            }
150            break;
151
152        case ESRIShape::ShapeTypeMultiPointZ :
153            {
154                std::vector<ESRIShape::MultiPointZ> mptzs;
155                ESRIShape::MultiPointZ mpointz;
156
157                while( mpointz.read(fd) )
158                    mptzs.push_back( mpointz );
159
160                _process(  mptzs );
161            }
162            break;
163
164        case ESRIShape::ShapeTypePolyLineZ   :
165            {
166                std::vector<ESRIShape::PolyLineZ> plinezs;
167                ESRIShape::PolyLineZ plinez;
168
169                while( plinez.read(fd) )
170                    plinezs.push_back( plinez );
171
172                _process( plinezs );
173            }
174            break;
175
176        case ESRIShape::ShapeTypePolygonZ    :
177            {
178                std::vector<ESRIShape::PolygonZ> polyzs;
179                ESRIShape::PolygonZ polyz;
180
181                while( polyz.read(fd) )
182                    polyzs.push_back( polyz );
183
184                _process( polyzs );
185            }
186            break;
187
188
189        case ESRIShape::ShapeTypeMultiPatch  :
190            {
191                std::vector<ESRIShape::MultiPatch> mpatches;
192                ESRIShape::MultiPatch mpatch;
193
194                while( mpatch.read( fd ) )
195                    mpatches.push_back( mpatch );
196
197                _process(mpatches);
198            }
199            break;
200
201        default:
202            break;
203    }
204
205    if(fd)
206    {
207      close(fd);
208      fd = 0;
209    }
210}
211
212osg::Geode *ESRIShapeParser::getGeode()
213{
214    return _geode.get();
215}
216
217void ESRIShapeParser::_combinePointToMultipoint()
218{
219    if( !_valid ) return;
220
221    OSG_NOTICE<<"_combinePointToMultipoint()"<<std::endl;
222
223    ArrayHelper coords(_useDouble);
224
225    unsigned int numDrawables = _geode->getNumDrawables();
226
227    for( unsigned int i = 0; i < numDrawables; i++ )
228    {
229        osg::Geometry *geom = dynamic_cast<osg::Geometry *>(_geode->getDrawable(i));
230        if( geom != 0L )
231        {
232            coords.add( geom->getVertexArray(), 0 );
233        }
234    }
235
236    _geode->removeDrawables( 0, numDrawables );
237
238    osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;
239    geometry->setVertexArray(coords.get());
240    geometry->addPrimitiveSet( new osg::DrawArrays(osg::PrimitiveSet::POINTS, 0, coords.size()));
241    _geode->addDrawable( geometry.get() );
242}
243
244void ESRIShapeParser::_process( const std::vector<ESRIShape::Point> &pts )
245{
246    if( !_valid ) return;
247
248    std::vector<ESRIShape::Point>::const_iterator p;
249    for( p = pts.begin(); p != pts.end(); p++ )
250    {
251        ArrayHelper coords(_useDouble);
252
253        coords.add( p->x, p->y, 0.0 );
254        osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;
255        geometry->setVertexArray(coords.get());
256        geometry->addPrimitiveSet( new osg::DrawArrays(osg::PrimitiveSet::POINTS, 0, 1));
257        _geode->addDrawable( geometry.get() );
258    }
259    if( _geode->getNumDrawables() > 1 )
260        _combinePointToMultipoint();
261}
262
263
264void ESRIShapeParser::_process( const std::vector<ESRIShape::MultiPoint> &mpts )
265{
266    if( !_valid ) return;
267
268    std::vector<ESRIShape::MultiPoint>::const_iterator p;
269    for( p = mpts.begin(); p != mpts.end(); p++ )
270    {
271        ArrayHelper coords(_useDouble);
272
273        for( int i = 0; i < p->numPoints ; i++ )
274            coords.add( p->points[i].x, p->points[i].y, 0.0 );
275
276        osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;
277        geometry->setVertexArray(coords.get());
278        geometry->addPrimitiveSet( new osg::DrawArrays(osg::PrimitiveSet::POINTS, 0, coords.size()));
279
280        _geode->addDrawable( geometry.get() );
281    }
282}
283
284void ESRIShapeParser::_process(const std::vector<ESRIShape::PolyLine> &lines )
285{
286    if( !_valid ) return;
287
288    std::vector<ESRIShape::PolyLine>::const_iterator p;
289    for( p = lines.begin(); p != lines.end(); p++ )
290    {
291        ArrayHelper coords(_useDouble);
292
293        int i;
294        for( i = 0; i < p->numPoints; i++ )
295            coords.add( p->points[i].x, p->points[i].y, 0.0 );
296
297        osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;
298        geometry->setVertexArray(coords.get());
299
300        for( i = 0; i < p->numParts; i++ )
301        {
302            int index = p->parts[i];
303            int len = i < p->numParts - 1 ?
304                            p->parts[i+1] - p->parts[i] :
305                            p->numPoints  - p->parts[i];
306
307            geometry->addPrimitiveSet(
308                    new osg::DrawArrays(osg::PrimitiveSet::LINE_STRIP, index, len));
309        }
310        _geode->addDrawable( geometry.get() );
311    }
312}
313
314void ESRIShapeParser::_process( const std::vector<ESRIShape::Polygon> &polys )
315{
316    if( !_valid ) return;
317
318    std::vector<ESRIShape::Polygon>::const_iterator p;
319    for( p = polys.begin(); p != polys.end(); p++ )
320    {
321        ArrayHelper coords(_useDouble);
322        int i;
323        for( i = 0; i < p->numPoints; i++ )
324            coords.add( p->points[i].x, p->points[i].y, 0.0 );
325
326        osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;
327        geometry->setVertexArray(coords.get());
328
329        for( i = 0; i < p->numParts; i++ )
330        {
331            int index = p->parts[i];
332            int len = i < p->numParts - 1 ?
333                            p->parts[i+1] - p->parts[i] :
334                            p->numPoints  - p->parts[i];
335
336            geometry->addPrimitiveSet(
337                    new osg::DrawArrays(osg::PrimitiveSet::POLYGON, index, len));
338        }
339
340        // Use osgUtil::Tessellator to handle concave polygons
341        osg::ref_ptr<osgUtil::Tessellator> tscx=new osgUtil::Tessellator;
342        tscx->setTessellationType(osgUtil::Tessellator::TESS_TYPE_GEOMETRY);
343        tscx->setBoundaryOnly(false);
344        tscx->setWindingType( osgUtil::Tessellator::TESS_WINDING_ODD);
345
346        tscx->retessellatePolygons(*(geometry.get()));
347
348        _geode->addDrawable( geometry.get() );
349    }
350}
351
352void ESRIShapeParser::_process( const std::vector<ESRIShape::PointM> &ptms )
353{
354    if( !_valid ) return;
355
356    std::vector<ESRIShape::PointM>::const_iterator p;
357    for( p = ptms.begin(); p != ptms.end(); p++ )
358    {
359        ArrayHelper coords(_useDouble);
360        coords.add( p->x, p->y, 0.0 );
361        osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;
362        geometry->setVertexArray(coords.get());
363        geometry->addPrimitiveSet( new osg::DrawArrays(osg::PrimitiveSet::POINTS, 0, 1));
364        _geode->addDrawable( geometry.get() );
365    }
366    if( _geode->getNumDrawables() > 1 )
367        _combinePointToMultipoint();
368}
369
370void ESRIShapeParser::_process( const std::vector<ESRIShape::MultiPointM> &mptms )
371{
372    if( !_valid ) return;
373
374    std::vector<ESRIShape::MultiPointM>::const_iterator p;
375    for( p = mptms.begin(); p != mptms.end(); p++ )
376    {
377        osg::ref_ptr<osg::Vec3Array> coords  = new osg::Vec3Array;
378
379        // Here is where we would use the 'M' (?)
380        for( int i = 0; i < p->numPoints ; i++ )
381            coords->push_back( osg::Vec3( p->points[i].x, p->points[i].y, 0.0 ));
382
383        osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;
384        geometry->setVertexArray(coords.get());
385        geometry->addPrimitiveSet( new osg::DrawArrays(osg::PrimitiveSet::POINTS, 0, coords->size()));
386
387        _geode->addDrawable( geometry.get() );
388    }
389}
390
391void ESRIShapeParser::_process(const std::vector<ESRIShape::PolyLineM> &linems )
392{
393    if( !_valid ) return;
394
395    std::vector<ESRIShape::PolyLineM>::const_iterator p;
396    for( p = linems.begin(); p != linems.end(); p++ )
397    {
398        osg::ref_ptr<osg::Vec3Array> coords  = new osg::Vec3Array;
399
400        int i;
401        for( i = 0; i < p->numPoints; i++ )
402            coords->push_back( osg::Vec3( p->points[i].x, p->points[i].y, 0.0 ));
403
404        osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;
405        geometry->setVertexArray(coords.get());
406
407        for( i = 0; i < p->numParts; i++ )
408        {
409            int index = p->parts[i];
410            int len = i < p->numParts - 1 ?
411                            p->parts[i+1] - p->parts[i] :
412                            p->numPoints  - p->parts[i];
413
414            geometry->addPrimitiveSet(
415                    new osg::DrawArrays(osg::PrimitiveSet::LINE_STRIP, index, len));
416        }
417        _geode->addDrawable( geometry.get() );
418    }
419}
420
421void ESRIShapeParser::_process( const std::vector<ESRIShape::PolygonM> &polyms )
422{
423    if( !_valid ) return;
424
425    std::vector<ESRIShape::PolygonM>::const_iterator p;
426    for( p = polyms.begin(); p != polyms.end(); p++ )
427    {
428        osg::ref_ptr<osg::Vec3Array> coords  = new osg::Vec3Array;
429        int i;
430        for( i = 0; i < p->numPoints; i++ )
431            coords->push_back( osg::Vec3( p->points[i].x, p->points[i].y, 0.0 ));
432
433        osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;
434        geometry->setVertexArray(coords.get());
435
436        for( i = 0; i < p->numParts; i++ )
437        {
438            int index = p->parts[i];
439            int len = i < p->numParts - 1 ?
440                            p->parts[i+1] - p->parts[i] :
441                            p->numPoints  - p->parts[i];
442
443            geometry->addPrimitiveSet(
444                    new osg::DrawArrays(osg::PrimitiveSet::POLYGON, index, len));
445        }
446        _geode->addDrawable( geometry.get() );
447    }
448}
449
450void ESRIShapeParser::_process( const std::vector<ESRIShape::PointZ> &ptzs )
451{
452    if( !_valid ) return;
453
454    std::vector<ESRIShape::PointZ>::const_iterator p;
455    for( p = ptzs.begin(); p != ptzs.end(); p++ )
456    {
457        osg::ref_ptr<osg::Vec3Array> coords  = new osg::Vec3Array;
458        coords->push_back( osg::Vec3( p->x, p->y, p->z ));
459        osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;
460        geometry->setVertexArray(coords.get());
461        geometry->addPrimitiveSet( new osg::DrawArrays(osg::PrimitiveSet::POINTS, 0, 1));
462        _geode->addDrawable( geometry.get() );
463    }
464    if( _geode->getNumDrawables() > 1 )
465        _combinePointToMultipoint();
466}
467
468void ESRIShapeParser::_process( const std::vector<ESRIShape::MultiPointZ> &mptzs )
469{
470    if( !_valid ) return;
471
472    std::vector<ESRIShape::MultiPointZ>::const_iterator p;
473    for( p = mptzs.begin(); p != mptzs.end(); p++ )
474    {
475        osg::ref_ptr<osg::Vec3Array> coords  = new osg::Vec3Array;
476
477        // Here is where we would use the 'M' (?)
478        for( int i = 0; i < p->numPoints ; i++ )
479            coords->push_back( osg::Vec3( p->points[i].x, p->points[i].y, p->zArray[i] ));
480
481        osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;
482        geometry->setVertexArray(coords.get());
483        geometry->addPrimitiveSet( new osg::DrawArrays(osg::PrimitiveSet::POINTS, 0, coords->size()));
484
485        _geode->addDrawable( geometry.get() );
486    }
487}
488
489void ESRIShapeParser::_process(const std::vector<ESRIShape::PolyLineZ> &linezs )
490{
491    if( !_valid ) return;
492
493    std::vector<ESRIShape::PolyLineZ>::const_iterator p;
494    for( p = linezs.begin(); p != linezs.end(); p++ )
495    {
496        osg::ref_ptr<osg::Vec3Array> coords  = new osg::Vec3Array;
497
498        int i;
499        for( i = 0; i < p->numPoints; i++ )
500            coords->push_back( osg::Vec3( p->points[i].x, p->points[i].y, p->zArray[i] ));
501
502        osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;
503        geometry->setVertexArray(coords.get());
504
505        for( i = 0; i < p->numParts; i++ )
506        {
507            int index = p->parts[i];
508            int len = i < p->numParts - 1 ?
509                            p->parts[i+1] - p->parts[i] :
510                            p->numPoints  - p->parts[i];
511
512            geometry->addPrimitiveSet(
513                    new osg::DrawArrays(osg::PrimitiveSet::LINE_STRIP, index, len));
514        }
515        _geode->addDrawable( geometry.get() );
516    }
517}
518
519void ESRIShapeParser::_process( const std::vector<ESRIShape::PolygonZ> &polyzs )
520{
521    if( !_valid ) return;
522
523    std::vector<ESRIShape::PolygonZ>::const_iterator p;
524    for( p = polyzs.begin(); p != polyzs.end(); p++ )
525    {
526        osg::ref_ptr<osg::Vec3Array> coords  = new osg::Vec3Array;
527
528        int i;
529        for( i = 0; i < p->numPoints; i++ )
530            coords->push_back( osg::Vec3( p->points[i].x, p->points[i].y, p->zArray[i] ));
531
532        osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;
533        geometry->setVertexArray(coords.get());
534
535        for( i = 0; i < p->numParts; i++ )
536        {
537            int index = p->parts[i];
538            int len = i < p->numParts - 1 ?
539                            p->parts[i+1] - p->parts[i] :
540                            p->numPoints  - p->parts[i];
541
542            geometry->addPrimitiveSet(
543                    new osg::DrawArrays(osg::PrimitiveSet::POLYGON, index, len));
544        }
545        _geode->addDrawable( geometry.get() );
546    }
547}
548
549void ESRIShapeParser::_process( const std::vector<ESRIShape::MultiPatch> &mpatches )
550{
551    if( !_valid ) return;
552
553    std::vector<ESRIShape::MultiPatch>::const_iterator p;
554    for( p = mpatches.begin(); p != mpatches.end(); p++ )
555    {
556        osg::ref_ptr<osg::Vec3Array> coords  = new osg::Vec3Array;
557
558        int i;
559        for( i = 0; i < p->numPoints; i++ )
560            coords->push_back( osg::Vec3( p->points[i].x, p->points[i].y, p->zArray[i] ));
561
562        osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;
563        geometry->setVertexArray(coords.get());
564
565        // Lets mark poorly supported primitives with red, otherwise white
566        osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array;
567        geometry->setColorArray(colors.get());
568        geometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX );
569
570        for( i = 0; i < p->numParts; i++ )
571        {
572            int index = p->parts[i];
573            int len = i < p->numParts - 1 ?
574                            p->parts[i+1] - p->parts[i] :
575                            p->numPoints  - p->parts[i];
576
577            int  mode =
578                p->partTypes[i] == TriangleStrip ? osg::PrimitiveSet::TRIANGLE_STRIP :
579                p->partTypes[i] == TriangleFan   ? osg::PrimitiveSet::TRIANGLE_FAN :
580                // HACK for now
581                p->partTypes[i] == OuterRing     ? osg::PrimitiveSet::LINE_STRIP :
582                p->partTypes[i] == InnerRing     ? osg::PrimitiveSet::LINE_STRIP :
583                p->partTypes[i] == FirstRing     ? osg::PrimitiveSet::LINE_STRIP :
584                p->partTypes[i] == Ring          ? osg::PrimitiveSet::LINE_STRIP :
585                                                   osg::PrimitiveSet::POINTS ;
586
587            if( p->partTypes[i] == OuterRing ||
588                p->partTypes[i] == InnerRing ||
589                p->partTypes[i] == FirstRing || p->partTypes[i] == Ring )
590            {
591                OSG_WARN << "ESRIShapeParser - MultiPatch type " <<
592                    (p->partTypes[i] == TriangleStrip ? "TriangleStrip":
593                     p->partTypes[i] == TriangleFan   ? "TriangleFan":
594                     p->partTypes[i] == OuterRing     ? "OuterRing":
595                     p->partTypes[i] == InnerRing     ? "InnerRing":
596                     p->partTypes[i] == FirstRing     ? "FirstRing":
597                     p->partTypes[i] == Ring          ? "Ring": "Dunno") <<
598                    " poorly supported.  Will be represented by a red line strip" << std::endl;
599            }
600
601
602
603            // Lets mark poorly supported primitives with red, otherwise white
604            osg::Vec4 color =
605                p->partTypes[i] == TriangleStrip ? osg::Vec4(1.0,1.0,1.0,1.0) :
606                p->partTypes[i] == TriangleFan   ? osg::Vec4(1.0,1.0,1.0,1.0) :
607                // HACK for now
608                p->partTypes[i] == OuterRing     ? osg::Vec4(1.0,0.0,0.0,1.0) :
609                p->partTypes[i] == InnerRing     ? osg::Vec4(1.0,0.0,0.0,1.0) :
610                p->partTypes[i] == FirstRing     ? osg::Vec4(1.0,0.0,0.0,1.0) :
611                p->partTypes[i] == Ring          ? osg::Vec4(1.0,0.0,0.0,1.0) :
612                                                   osg::Vec4(1.0,0.0,0.0,1.0) ;
613            for( int j = 0; j < len; j++ )
614                colors->push_back( color );
615
616            geometry->addPrimitiveSet( new osg::DrawArrays(mode, index, len ));
617        }
618
619        _geode->addDrawable( geometry.get() );
620    }
621}
Note: See TracBrowser for help on using the browser.