Changeset 850

Show
Ignore:
Timestamp:
01/21/08 21:22:04
Author:
robert
Message:

From David Callu, support for handling forests and division of shapefile that cover tile boundaries.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/include/vpb/ExtrudeVisitor

    r811 r850  
    2626    public: 
    2727 
    28         enum Mode 
     28        enum OutputMode 
    2929        { 
    3030            Replace, 
     
    3232        }; 
    3333         
    34         enum Typ
     34        enum Mod
    3535        { 
    3636            PER_VERTEX, 
     
    3838        }; 
    3939         
    40         ExtrudeVisitor() : _mode(Merge) {} 
    41         ExtrudeVisitor(Mode mode) : _mode(mode) {} 
    42         ExtrudeVisitor(Mode mode, osg::Vec3d & extrudeVector) : _mode(mode), _extrudeVector(extrudeVector) {} 
     40        ExtrudeVisitor() : _mode(PER_GEOMETRY), _outputMode(Merge) {} 
     41        ExtrudeVisitor(Mode mode) : _mode(mode), _outputMode(Merge) {} 
     42        ExtrudeVisitor(Mode mode, osg::Vec3d & extrudeVector) : _mode(mode), _outputMode(Merge), _extrudeVector(extrudeVector) {} 
     43        ExtrudeVisitor(Mode mode, OutputMode outputMode, osg::Vec3d & extrudeVector) : _mode(mode), _outputMode(outputMode), _extrudeVector(extrudeVector) {} 
     44 
     45        OutputMode getOutputMode() { return _outputMode; } 
     46        void setOutputMode(OutputMode outputMode) { _outputMode = outputMode; } 
    4347 
    4448        Mode getMode() { return _mode; } 
    4549        void setMode(Mode mode) { _mode = mode; } 
    46  
     50         
    4751        osg::Vec3d & getExtrudeVector() { return _extrudeVector; } 
    4852        const osg::Vec3d & getExtrudeVector() const { return _extrudeVector; } 
    4953        void setExtrudeVector(osg::Vec3d extrudeVector) { _extrudeVector = extrudeVector; } 
    5054 
    51         void extrude(osg::Geometry& geometry, osg::Vec3d & extrudeVector); 
     55        void extrude(osg::Geometry& geometry); 
    5256         
    5357        virtual void apply(osg::Geode& node); 
     
    5862                                                    osg::UIntArray & extrudeIndexArray); 
    5963        Mode _mode; 
     64        OutputMode _outputMode; 
     65         
    6066        osg::Vec3d _extrudeVector; 
    6167}; 
  • trunk/src/vpb/ExtrudeVisitor.cpp

    r810 r850  
    4848typedef osgUtil::OperationArrayFunctor<DuplicateIndexOperator> DuplicateIndexFunctor; 
    4949 
     50struct DuplicateAndInterlaceOperator 
     51{ 
     52    template <typename ArrayType> 
     53    void process(ArrayType & array)  
     54    {    
     55        unsigned int size = array.size(); 
     56        osg::ref_ptr<ArrayType> newArray(new ArrayType(size * 2)); 
     57        ArrayType & refNewArray = *newArray.get(); 
     58         
     59        for (unsigned int i=0; i<size; ++i) 
     60            refNewArray[2*i] = refNewArray[2*i+1] = array[i]; 
     61         
     62        array = refNewArray; 
     63    } 
     64};    
     65typedef osgUtil::OperationArrayFunctor<DuplicateAndInterlaceOperator> DuplicateAndInterlaceFunctor; 
     66 
     67struct AddOddOperator 
     68{ 
     69    template <typename ArrayType> 
     70    void process(ArrayType & array)  
     71    {    
     72        typedef typename ArrayType::ElementDataType ElementDataType; 
     73                         
     74        ElementDataType convertedVector; 
     75        osgUtil::ConvertVec<osg::Vec3d, ElementDataType>::convert(_vector, convertedVector); 
     76         
     77         
     78        std::size_t size = array.size(); 
     79        for (unsigned int i = 1; i<size; i+=2) 
     80            array[i] += convertedVector; 
     81    } 
     82     
     83    osg::Vec3d _vector; 
     84};    
     85typedef osgUtil::OperationArrayFunctor<AddOddOperator> AddOddFunctor; 
    5086 
    5187 
     
    64100// ** search BoundaryEdgeloop in the geometry, extrude this loop 
    65101// **  and create primitiveSet to link original loop and extruded loop 
    66 void ExtrudeVisitor::extrude(osg::Geometry& geometry, osg::Vec3d & extrudeVector
     102void ExtrudeVisitor::extrude(osg::Geometry& geometry
    67103{ 
    68104//    osg::notify(osg::INFO)<<"****************Extruder : Start ************"<<std::endl; 
     
    70106    unsigned int originalVertexArraySize = geometry.getVertexArray()->getNumElements(); 
    71107     
    72      
    73      
    74     // ** collect Edge 
    75 //    osg::notify(osg::INFO)<<"****************Extruder : collect Points, Edges, Triangles"<<std::endl; 
    76     osgUtil::EdgeCollector ec; 
    77     ec.setGeometry(&geometry); 
    78     if (ec._triangleSet.size() == 0) return; 
    79 //    osg::notify(osg::INFO)<<"****************Extruder : found " << ec._pointSet.size() << " Points"<<std::endl; 
    80 //    osg::notify(osg::INFO)<<"****************Extruder : found " << ec._edgeSet.size() << " Edges"<<std::endl; 
    81 //    osg::notify(osg::INFO)<<"****************Extruder : found " << ec._triangleSet.size() << " Triangles"<<std::endl; 
    82  
    83      
    84     // ** get IndexArray of each Edgeloop 
    85      
    86     osgUtil::EdgeCollector::IndexArrayList originalIndexArrayList; 
    87     osgUtil::EdgeCollector::IndexArrayList extrudedIndexArrayList; 
    88         
    89     ec.getEdgeloopIndexList(originalIndexArrayList); 
    90     osgUtil::EdgeCollector::IndexArrayList::iterator iaIt, iaEnd = originalIndexArrayList.end(); 
    91     for (iaIt = originalIndexArrayList.begin(); iaIt != iaEnd; ++iaIt) 
     108 
     109    if (_mode == PER_VERTEX) 
    92110    { 
    93         extrudedIndexArrayList.push_back(new osg::UIntArray(*iaIt->get())); 
    94     } 
    95      
    96     _mode = Replace; 
    97      
    98     // ** replace geometry by extruded geometry 
    99     if (_mode == Replace) 
     111        // ** duplicate vertex 
     112        DuplicateAndInterlaceFunctor daif; 
     113        geometry.getVertexArray()->accept(daif); 
     114         
     115        // ** extrude vertex with odd index 
     116        AddOddFunctor aof; 
     117        aof._vector = _extrudeVector; 
     118        geometry.getVertexArray()->accept(aof); 
     119         
     120        geometry.getPrimitiveSetList().clear(); 
     121        geometry.addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES, 0, geometry.getVertexArray()->getNumElements())); 
     122         
     123    } 
     124    else // if (_mode == PER_GEOMETRY) 
    100125    { 
    101         // ** extrude vertexArray 
    102 //        osg::notify(osg::INFO)<<"****************Extruder : Duplicate Edgeloop and Extrude VertexArray ************"<<std::endl; 
    103          
    104          
    105         unsigned int currentVertexArraySize = originalVertexArraySize; 
    106          
    107         DuplicateIndexFunctor dif; 
     126        // ** collect Edge 
     127        osgUtil::EdgeCollector ec; 
     128        ec.setGeometry(&geometry); 
     129        if (ec._triangleSet.size() == 0) return; 
     130     
     131         
     132        // ** get IndexArray of each Edgeloop 
     133        osgUtil::EdgeCollector::IndexArrayList originalIndexArrayList; 
     134        osgUtil::EdgeCollector::IndexArrayList extrudedIndexArrayList; 
     135            
     136        ec.getEdgeloopIndexList(originalIndexArrayList); 
    108137        osgUtil::EdgeCollector::IndexArrayList::iterator iaIt, iaEnd = originalIndexArrayList.end(); 
    109138        for (iaIt = originalIndexArrayList.begin(); iaIt != iaEnd; ++iaIt) 
    110139        { 
    111             osg::UIntArray & indexArray = *(iaIt->get()); 
    112              
    113             // ** duplicate vertex indexed by indexArray 
    114             dif._indexArray = &indexArray; 
    115             geometry.getVertexArray()->accept(dif); 
    116                          
    117             // ** remap indexArray 
    118             unsigned int size = indexArray.size(); 
    119             for (unsigned int i=0; i<size; ++i) 
    120                 indexArray[i] = currentVertexArraySize + i; 
    121              
    122             currentVertexArraySize += size; 
    123         } 
    124          
    125         // ** extrude original vertex and keep original value in duplicate vertex 
    126         osgUtil::AddRangeFunctor erf; 
    127         erf._vector = extrudeVector; 
    128         erf._begin = 0; 
    129         erf._count = originalVertexArraySize; 
    130          
    131         geometry.getVertexArray()->accept(erf); 
    132     } 
    133     else //if (_mode == Merge) 
    134     { 
    135         // ** duplicate vertexArray 
    136 //        osg::notify(osg::INFO)<<"****************Extruder : Duplicate and extrude VertexArray ************"<<std::endl; 
    137          
    138         // ** duplicate all vertex 
    139         DuplicateFunctor df; 
    140         geometry.getVertexArray()->accept(df); 
    141          
    142         // ** duplicate edgeloop index 
    143         osgUtil::EdgeCollector::IndexArrayList::iterator iaIt, iaEnd = originalIndexArrayList.end(); 
    144         for (iaIt = originalIndexArrayList.begin(); iaIt != iaEnd; ++iaIt) 
    145         { 
    146             osg::UIntArray & indexArray = *(iaIt->get()); 
    147              
    148             // ** remap indexArray 
    149             unsigned int size = indexArray.size(); 
    150             for (unsigned int i=0; i<size; ++i) 
    151                 indexArray[i] += originalVertexArraySize; 
    152         } 
    153          
    154         // ** extrude original vertex and keep original value in duplicate vertex 
    155         osgUtil::AddRangeFunctor erf; 
    156         erf._vector = extrudeVector; 
    157         erf._begin = 0; 
    158         erf._count = originalVertexArraySize; 
    159         geometry.getVertexArray()->accept(erf); 
    160  
    161         // ** offset primitive's indices to draw duplicated vertex 
    162         osg::Geometry::PrimitiveSetList & psl = geometry.getPrimitiveSetList(); 
    163         std::for_each(psl.begin(), psl.end(), OffsetIndices(originalVertexArraySize)); 
    164      
    165     } 
    166      
    167      
    168      
    169      
    170      
    171      
    172     bool reverseTopShape = true;//needReverseTopShape(extrudeVector, ); TODO 
    173      
    174 //    osg::notify(osg::INFO)<<"****************Extruder : Make top primitiveSet List ************"<<std::endl; 
    175     { 
    176         osg::Geometry::PrimitiveSetList newPsl; 
    177          
    178         // ** for each primitive in geometry, we duplicate this primitive and reverse it if need 
    179         osg::Geometry::PrimitiveSetList & psl = geometry.getPrimitiveSetList(); 
    180         osg::Geometry::PrimitiveSetList::iterator it, end = psl.end(); 
    181         for (it = psl.begin(); it != end; ++it) 
    182         { 
    183             osg::ref_ptr<osg::PrimitiveSet> newPs; 
    184              
    185             // ** duplicate 
    186             if (reverseTopShape) 
     140            extrudedIndexArrayList.push_back(new osg::UIntArray(*iaIt->get())); 
     141        } 
     142         
     143//        _outputMode = Replace; 
     144         
     145        // ** replace geometry by extruded geometry 
     146        if (_outputMode == Replace) 
     147        { 
     148            // ** extrude vertexArray 
     149            unsigned int currentVertexArraySize = originalVertexArraySize; 
     150             
     151            DuplicateIndexFunctor dif; 
     152            osgUtil::EdgeCollector::IndexArrayList::iterator iaIt, iaEnd = originalIndexArrayList.end(); 
     153            for (iaIt = originalIndexArrayList.begin(); iaIt != iaEnd; ++iaIt) 
     154            { 
     155                osg::UIntArray & indexArray = *(iaIt->get()); 
     156                 
     157                // ** duplicate vertex indexed by indexArray 
     158                dif._indexArray = &indexArray; 
     159                geometry.getVertexArray()->accept(dif); 
     160                             
     161                // ** remap indexArray 
     162                unsigned int size = indexArray.size(); 
     163                for (unsigned int i=0; i<size; ++i) 
     164                    indexArray[i] = currentVertexArraySize + i; 
     165                 
     166                currentVertexArraySize += size; 
     167            } 
     168             
     169            // ** extrude original vertex and keep original value in duplicate vertex 
     170            osgUtil::AddRangeFunctor erf; 
     171            erf._vector = _extrudeVector; 
     172            erf._begin = 0; 
     173            erf._count = originalVertexArraySize; 
     174             
     175            geometry.getVertexArray()->accept(erf); 
     176        } 
     177        else //if (_outputMode == Merge) 
     178        { 
     179            // ** duplicate all vertex 
     180            DuplicateFunctor df; 
     181            geometry.getVertexArray()->accept(df); 
     182             
     183            // ** duplicate edgeloop index 
     184            osgUtil::EdgeCollector::IndexArrayList::iterator iaIt, iaEnd = originalIndexArrayList.end(); 
     185            for (iaIt = originalIndexArrayList.begin(); iaIt != iaEnd; ++iaIt) 
     186            { 
     187                osg::UIntArray & indexArray = *(iaIt->get()); 
     188                 
     189                // ** remap indexArray 
     190                unsigned int size = indexArray.size(); 
     191                for (unsigned int i=0; i<size; ++i) 
     192                    indexArray[i] += originalVertexArraySize; 
     193            } 
     194             
     195            // ** extrude original vertex and keep original value in duplicate vertex 
     196            osgUtil::AddRangeFunctor erf; 
     197            erf._vector = _extrudeVector; 
     198            erf._begin = 0; 
     199            erf._count = originalVertexArraySize; 
     200            geometry.getVertexArray()->accept(erf); 
     201     
     202            // ** offset primitive's indices to draw duplicated vertex 
     203            osg::Geometry::PrimitiveSetList & psl = geometry.getPrimitiveSetList(); 
     204            std::for_each(psl.begin(), psl.end(), OffsetIndices(originalVertexArraySize)); 
     205         
     206        } 
     207         
     208         
     209         
     210         
     211         
     212        // Make top primitiveSet List 
     213        bool reverseTopShape = false;//needReverseTopShape(extrudeVector, ); TODO 
     214        { 
     215            osg::Geometry::PrimitiveSetList newPsl; 
     216             
     217            // ** for each primitive in geometry, we duplicate this primitive and reverse it if need 
     218            osg::Geometry::PrimitiveSetList & psl = geometry.getPrimitiveSetList(); 
     219            osg::Geometry::PrimitiveSetList::iterator it, end = psl.end(); 
     220            for (it = psl.begin(); it != end; ++it) 
     221            { 
     222                osg::ref_ptr<osg::PrimitiveSet> newPs; 
     223                 
     224                // ** duplicate 
     225                if (reverseTopShape) 
     226                { 
     227                    osgUtil::ReversePrimitiveFunctor rpf; 
     228                    (*it)->accept(rpf); 
     229                     
     230                    newPs = rpf.getReversedPrimitiveSet(); 
     231                } 
     232                else 
     233                { 
     234                    newPs = static_cast<osg::PrimitiveSet*>((*it)->clone(osg::CopyOp::SHALLOW_COPY)); 
     235                } 
     236                 
     237                if (newPs.valid()) 
     238                { 
     239                    newPsl.push_back(newPs); 
     240                } 
     241            } 
     242             
     243            // ** Replace by or Merge new Primitives 
     244            if (_outputMode == Replace) 
     245            { 
     246                psl = newPsl; 
     247            } 
     248            else //if (_outputMode == Merge) 
     249            { 
     250                psl.insert(psl.end(), newPsl.begin(), newPsl.end()); 
     251            } 
     252        } 
     253         
     254 
     255         
     256        // ** link original and extruded Boundary Edgeloops  
     257        osgUtil::EdgeCollector::IndexArrayList::iterator oit, oend = originalIndexArrayList.end(); 
     258        osgUtil::EdgeCollector::IndexArrayList::iterator eit = extrudedIndexArrayList.begin(); 
     259        for (oit = originalIndexArrayList.begin(); oit != oend; ++oit, ++eit) 
     260        { 
     261             
     262            osg::ref_ptr<osg::DrawElementsUInt> de = linkAsTriangleStrip(*(*oit), *(*eit)); 
     263             
     264            // ** if bottom shape have up normal, we need to reverse the extruded face    
     265            if (reverseTopShape == false) 
    187266            { 
    188267                osgUtil::ReversePrimitiveFunctor rpf; 
    189                 (*it)->accept(rpf); 
    190                  
    191                 newPs = rpf.getReversedPrimitiveSet(); 
     268                de->accept(rpf); 
     269                 
     270                geometry.addPrimitiveSet(rpf._reversedPrimitiveSet.get()); 
    192271            } 
    193272            else 
    194273            { 
    195                 newPs = static_cast<osg::PrimitiveSet*>((*it)->clone(osg::CopyOp::SHALLOW_COPY)); 
    196             } 
    197              
    198             if (newPs.valid()) 
    199             { 
    200                 newPsl.push_back(newPs); 
    201             } 
    202         } 
    203          
    204         // ** Replace by or Merge new Primitives 
    205         if (_mode == Replace) 
    206         { 
    207             psl = newPsl; 
    208         } 
    209         else //if (_mode == Merge) 
    210         { 
    211             psl.insert(psl.end(), newPsl.begin(), newPsl.end()); 
    212         } 
    213     } 
    214      
    215      
    216      
    217      
    218      
    219      
    220 //    osg::notify(osg::INFO)<<"****************Extruder : link original and extruded Boundary Edgeloops ************"<<std::endl; 
    221     // ** link original and extruded Boundary Edgeloops  
    222      
    223     osgUtil::EdgeCollector::IndexArrayList::iterator oit, oend = originalIndexArrayList.end(); 
    224     osgUtil::EdgeCollector::IndexArrayList::iterator eit = extrudedIndexArrayList.begin(); 
    225     for (oit = originalIndexArrayList.begin(); oit != oend; ++oit, ++eit) 
    226     { 
    227          
    228         osg::ref_ptr<osg::DrawElementsUInt> de = linkAsTriangleStrip(*(*oit), *(*eit)); 
    229          
    230         // ** if bottom shape have up normal, we need to reverse the extruded face    
    231         if (reverseTopShape == false) 
    232         { 
    233             osgUtil::ReversePrimitiveFunctor rpf; 
    234             de->accept(rpf); 
    235              
    236             geometry.addPrimitiveSet(rpf._reversedPrimitiveSet.get()); 
    237         } 
    238         else 
    239         { 
    240             // ** add the extruded face 
    241             geometry.addPrimitiveSet(de.get()); 
    242         } 
    243     } 
    244      
    245  
    246     osgUtil::SmoothingVisitor::smooth(geometry); 
    247 //    osg::notify(osg::INFO)<<"****************Extruder : finish ************"<<std::endl; 
     274                // ** add the extruded face 
     275                geometry.addPrimitiveSet(de.get()); 
     276            } 
     277        } 
     278         
     279     
     280        osgUtil::SmoothingVisitor::smooth(geometry); 
     281    } 
    248282} 
    249283 
     
    281315        if (geo) 
    282316        { 
    283             extrude(*geo, _extrudeVector);         
     317            extrude(*geo);         
    284318        } 
    285319    } 
  • trunk/src/vpb/HeightFieldMapper.cpp

    r812 r850  
    2323#include <osgUtil/EdgeCollector> 
    2424#include <osgUtil/ConvertVec> 
     25#include <osgUtil/Tessellator> 
    2526 
    2627namespace vpb { 
     
    5152 
    5253 
    53  
    54 class ComputeCentroidVisitor : public osg::ArrayVisitor 
     54class SetZeroToZVisitor : public osg::ArrayVisitor 
    5555{ 
    5656    public: 
    57          
    58         ComputeCentroidVisitor(osg::UIntArray & ia) : _ia(ia) {} 
    59          
    6057         
    6158        void apply(osg::Vec3Array& array) { computeCentroid<osg::Vec3Array>(array); } 
     
    6562        void apply(osg::Vec4dArray& array) { computeCentroid<osg::Vec4dArray>(array); } 
    6663     
    67 #if 0         
     64 
    6865        template <typename ArrayType> 
    6966        void computeCentroid(ArrayType & array) 
    7067        { 
    71             double area = 0.0; 
    72             double centroidTmp = 0.0; 
    73             double centroidX = 0.0; 
    74             double centroidY = 0.0; 
    75              
    76             osg::UIntArray::iterator it, end = _ia.end() - 1; 
    77             for (it = _ia.begin(); it != end; ++it) 
    78             { 
    79                 typename ArrayType::ElementDataType & vec0 = array[*it]; 
    80                 typename ArrayType::ElementDataType & vec1 = array[*(it + 1)]; 
    81                  
    82                 area += vec0.x() * vec1.y(); 
    83                 area -= vec0.y() * vec1.x(); 
    84                  
    85                 centroidTmp = (vec0.x() * vec1.y() - vec1.x() * vec0.y()); 
    86                 centroidX += (vec0.x() + vec1.x()) * centroidTmp; 
    87                 centroidY += (vec0.y() + vec1.y()) * centroidTmp; 
    88             } 
    89              
    90             typename ArrayType::ElementDataType & vec0 = array[_ia.back()]; 
    91             typename ArrayType::ElementDataType & vec1 = array[_ia.front()]; 
    92              
    93             area += vec0.x() * vec1.y(); 
    94             area -= vec0.y() * vec1.x(); 
    95              
    96             centroidTmp = (vec0.x() * vec1.y() - vec1.x() * vec0.y()); 
    97             centroidX += (vec0.x() + vec1.x()) * centroidTmp; 
    98             centroidY += (vec0.y() + vec1.y()) * centroidTmp; 
    99              
    100             area *= 0.5; 
    101             area = 1 / (6 * area); 
    102             _centroid.set(area * centroidX, area * centroidY, vec0.z()); 
    103         } 
    104 #else 
     68            unsigned int size = array.size(); 
     69             
     70            for (unsigned int i=0; i<size; ++i) 
     71                array[i].z() = 0.0; 
     72        } 
     73}; 
     74 
     75class ComputeCentroidVisitor : public osg::ArrayVisitor 
     76
     77    public: 
     78         
     79        void apply(osg::Vec3Array& array) { computeCentroid<osg::Vec3Array>(array); } 
     80        void apply(osg::Vec4Array& array) { computeCentroid<osg::Vec4Array>(array); } 
     81         
     82        void apply(osg::Vec3dArray& array) { computeCentroid<osg::Vec3dArray>(array); } 
     83        void apply(osg::Vec4dArray& array) { computeCentroid<osg::Vec4dArray>(array); } 
     84     
    10585 
    10686        template <typename ArrayType> 
    10787        void computeCentroid(ArrayType & array) 
    10888        { 
    109             if (_ia.empty()) return; 
    110          
     89            unsigned int size = array.size(); 
    11190            osg::Vec3d total(0.0,0.0,0.0); 
    11291             
    113             for (osg::UIntArray::iterator it = _ia.begin(); it != _ia.end(); ++it
    114             { 
    115                 typename ArrayType::ElementDataType & vec = array[*it]; 
     92            for (unsigned int i=0; i<size; ++i
     93            { 
     94                typename ArrayType::ElementDataType & vec = array[i]; 
    11695                total.x() += vec.x(); 
    11796                total.y() += vec.y(); 
     
    11998            } 
    12099             
    121             _centroid = total / double(_ia.size()) ; 
    122         } 
    123  
    124  
    125 #endif         
    126          
    127         osg::UIntArray & _ia; 
     100            _centroid = total / double(size) ; 
     101        } 
     102 
    128103        osg::Vec3d _centroid; 
    129104}; 
    130105 
     106struct CopyIndexedOperator 
     107{  
     108    template <typename ArrayType> 
     109    void process(ArrayType & array)  
     110    {    
     111        ArrayType * va = new ArrayType(); 
     112         
     113        osg::UIntArray::iterator it, end = _indexArray->end(); 
     114        for (it = _indexArray->begin(); it < end; ++it) 
     115            va->push_back(array[*it]); 
     116         
     117        _copyArray = va; 
     118    } 
     119         
     120    osg::ref_ptr<osg::UIntArray> _indexArray; 
     121    osg::ref_ptr<osg::Array> _copyArray; 
     122}; 
     123typedef osgUtil::OperationArrayFunctor<CopyIndexedOperator> CopyIndexedFunctor;   
     124 
     125struct IsConvexPolygonVisitor : public osg::ArrayVisitor 
     126{  
     127    virtual void apply(osg::Vec3Array& array) { process<osg::Vec3Array>(array); } 
     128    virtual void apply(osg::Vec4Array& array) { process<osg::Vec4Array>(array); } 
     129 
     130 
     131    virtual void apply(osg::Vec3dArray& array) { process<osg::Vec3dArray>(array); } 
     132    virtual void apply(osg::Vec4dArray& array) { process<osg::Vec4dArray>(array); } 
     133     
     134    template <typename ArrayType> 
     135    void process(ArrayType & array)  
     136    {    
     137        typedef typename ArrayType::ElementDataType VecType; 
     138         
     139        bool positif; 
     140         
     141        { 
     142            const VecType & v1 = array[0]; 
     143            const VecType & v2 = array[1]; 
     144            const VecType & v3 = array[2]; 
     145             
     146            positif = (((v1.x() - v2.x()) * (v3.y() - v2.y()) - (v1.y() - v2.y()) * (v3.x() - v2.x())) >= 0.0); 
     147        } 
     148         
     149         
     150        unsigned int size = array.size() - 2; 
     151        unsigned int i; 
     152        for (i=1; i<size; ++i) 
     153        { 
     154            const VecType & v1 = array[i]; 
     155            const VecType & v2 = array[i+1]; 
     156            const VecType & v3 = array[i+2]; 
     157             
     158            if (positif != (((v1.x() - v2.x()) * (v3.y() - v2.y()) - (v1.y() - v2.y()) * (v3.x() - v2.x())) >= 0.0)) 
     159            { 
     160                _isConvex = false; 
     161                return; 
     162            } 
     163        } 
     164         
     165        { 
     166            const VecType & v1 = array[i]; 
     167            const VecType & v2 = array[i+1]; 
     168            const VecType & v3 = array[0]; 
     169             
     170            if (positif != (((v1.x() - v2.x()) * (v3.y() - v2.y()) - (v1.y() - v2.y()) * (v3.x() - v2.x())) >= 0.0)) 
     171            { 
     172                _isConvex = false; 
     173                return; 
     174            } 
     175        } 
     176         
     177        { 
     178            const VecType & v1 = array[i+1]; 
     179            const VecType & v2 = array[0]; 
     180            const VecType & v3 = array[1]; 
     181             
     182            if (positif != (((v1.x() - v2.x()) * (v3.y() - v2.y()) - (v1.y() - v2.y()) * (v3.x() - v2.x())) >= 0.0)) 
     183            { 
     184                _isConvex = false; 
     185                return; 
     186            } 
     187        } 
     188         
     189        _isConvex = true; 
     190    } 
     191         
     192    bool _isConvex; 
     193}; 
     194 
     195 
     196// ** This operator map each vertex and add them only if they overlap the HeightField 
    131197class HeightFieldMapperArrayVisitor : public osg::ArrayVisitor 
    132198{ 
     199public: 
     200     
     201    HeightFieldMapperArrayVisitor(const HeightFieldMapper & hfm) : _hfm(hfm) {} 
     202     
     203    virtual void apply(osg::Vec3Array& array) { process<osg::Vec3Array>(array); } 
     204    virtual void apply(osg::Vec4Array& array) { process<osg::Vec4Array>(array); } 
     205 
     206 
     207    virtual void apply(osg::Vec3dArray& array) { process<osg::Vec3dArray>(array); } 
     208    virtual void apply(osg::Vec4dArray& array) { process<osg::Vec4dArray>(array); } 
     209     
     210    template <typename ArrayType> 
     211    void process(ArrayType & array)  
     212    {    
     213        unsigned int size = array.size(); 
     214        osg::ref_ptr<ArrayType> newArray(new ArrayType); 
     215        newArray->reserve(size); 
     216         
     217        ArrayType & refNewArray = *newArray.get(); 
     218         
     219         
     220        for (unsigned int i=0; i<size; ++i) 
     221        { 
     222            typename ArrayType::ElementDataType & vec = array[i]; 
     223            vec.z() = _hfm.getZfromXY(vec.x(), vec.y()); 
     224             
     225            if (vec.z() != DBL_MAX) refNewArray.push_back(vec); 
     226        } 
     227         
     228        array = refNewArray; 
     229    } 
     230     
     231    const HeightFieldMapper & _hfm; 
     232}; 
     233 
     234 
     235// ** This operator reverse the array if its normal is not (0,0,1) 
     236class AssertUpNormalVisitor : public osg::ArrayVisitor 
     237{ 
    133238    public: 
    134          
    135         template <class T> 
    136         struct HeightFieldMapperOperator 
    137         { 
    138             HeightFieldMapperOperator(const HeightFieldMapper & hfm) : _hfm(hfm) {} 
    139             void operator ()(T & vec) { vec.z() = _hfm.getZfromXY(vec.x(), vec.y()); } 
    140  
    141         private: 
    142              
    143             const HeightFieldMapper _hfm; 
     239     
     240        virtual void apply(osg::Vec3Array& array) { process<osg::Vec3Array>(array); } 
     241        virtual void apply(osg::Vec4Array& array) { process<osg::Vec4Array>(array); } 
     242     
     243        virtual void apply(osg::Vec3dArray& array) { process<osg::Vec3dArray>(array); } 
     244        virtual void apply(osg::Vec4dArray& array) { process<osg::Vec4dArray>(array); } 
     245     
     246        template <typename ArrayType> 
     247        void process(ArrayType & array) const 
     248        { 
     249            typedef typename ArrayType::ElementDataType VecType; 
     250             
     251            const VecType & v1 = array[0]; 
     252            const VecType & v2 = array[1]; 
     253            const VecType & v3 = array[2]; 
     254   
     255            if (((v1.x() - v2.x()) * (v3.y() - v2.y()) - (v1.y() - v2.y()) * (v3.x() - v2.x())) > 0.0) 
     256            { 
     257                std::reverse(array.begin(), array.end()); 
     258            } 
     259        } 
     260}; 
     261 
     262 
     263 
     264// ** This visitor cut the geometry to overlap exactly the HeightField 
     265template <typename ArrayType, typename CreatePolicy> 
     266class CutGeometryToOverlapHeightField 
     267
     268    public: 
     269 
     270        typedef typename ArrayType::ElementDataType VecType; 
     271         
     272         
     273        CutGeometryToOverlapHeightField(double xMin, double yMin, double xMax, double yMax)  
     274        :     _xMin(xMin), _yMin(yMin), _xMax(xMax), _yMax(yMax)  
     275        {} 
     276 
     277        bool overlapHeightField(double x, double y) const 
     278        { 
     279            return !((x > _xMax) || (x < _xMin) || (y > _yMax) || (y < _yMin)); 
     280        } 
     281         
     282        void process(ArrayType & array) 
     283        {    
     284             
     285            unsigned int size = array.size(); 
     286            _cuttenVertexArray = new ArrayType; 
     287             
     288            ArrayType & refNewArray = *static_cast<ArrayType*>(_cuttenVertexArray.get()); 
     289            refNewArray.reserve(size); 
     290             
     291            // ** find the first vertex overlaping the HeightField 
     292            unsigned int i=0; 
     293            bool notFound = true; 
     294            while (notFound && (i<size))  
     295            { 
     296                VecType & vec = array[i]; 
     297                if (overlapHeightField(vec.x(), vec.y())) 
     298                    notFound = false; 
     299                else 
     300                    ++i; 
     301            } 
     302             
     303            if (i == size) return; 
     304             
     305            // ** move vertex at the end of the array. Now, the first vertex in the array overlap the HeightField 
     306            if (i) 
     307            {    
     308                std::rotate(array.begin(), array.begin() + i, array.end()); 
     309            } 
     310             
     311             
     312             
     313             
     314            VecType inToOutVec, outToInVec; 
     315             
     316            refNewArray.push_back(array[0]); 
     317            i=1; 
     318            while (i<size) 
     319            { 
     320                VecType & vec = array[i]; 
     321                 
     322                // ** if the vertex not overlap the HeightField 
     323                if (overlapHeightField(vec.x(), vec.y()) == false) 
     324                { 
     325                    computeIntersection(array[i-1], array[i], inToOutVec); 
     326                    ++i; 
     327                     
     328                    bool notOverlap = true; 
     329                    while (notOverlap && (i<size)) 
     330                    { 
     331                        VecType & v = array[i]; 
     332                        if (overlapHeightField(v.x(), v.y())) 
     333                            notOverlap = false; 
     334                        else  
     335                            ++i; 
     336                    } 
     337                     
     338                    if (notOverlap == false) 
     339                        computeIntersection(array[i], array[i-1], outToInVec); 
     340                    else 
     341                        computeIntersection(array[0], array[i-1], outToInVec); 
     342                     
     343                     
     344                    insertIntersectedVertex(refNewArray, inToOutVec, outToInVec); 
     345                 
     346                     
     347                    if (notOverlap == false) 
     348                        refNewArray.push_back(array[i]); 
     349                } 
     350                else 
     351                { 
     352                    refNewArray.push_back(vec); 
     353                } 
     354                 
     355                ++i;                 
     356            }  
     357        } 
     358         
     359        enum Corner 
     360        { 
     361            NotACorner = 0, 
     362            C00, // corner(_xMin, _yMin) 
     363            C10, // corner(_xMax, _yMin) 
     364            C11, // corner(_xMax, _yMax) 
     365            C01  // corner(_xMin, _yMax) 
    144366        }; 
    145367         
    146          
    147         HeightFieldMapperArrayVisitor(const HeightFieldMapper & hfm) : _hfm(hfm) {} 
    148          
    149         virtual void apply(osg::Vec3Array & array) 
    150         { std::for_each(array.begin(), array.end(), HeightFieldMapperOperator<osg::Vec3>(_hfm)); } 
    151         virtual void apply(osg::Vec4Array & array) 
    152           { std::for_each(array.begin(), array.end(), HeightFieldMapperOperator<osg::Vec4>(_hfm)); } 
    153         virtual void apply(osg::Vec3dArray & array) 
    154           { std::for_each(array.begin(), array.end(), HeightFieldMapperOperator<osg::Vec3d>(_hfm)); } 
    155         virtual void apply(osg::Vec4dArray & array) 
    156           { std::for_each(array.begin(), array.end(), HeightFieldMapperOperator<osg::Vec4d>(_hfm)); } 
     368        Corner isCorner(const VecType & v) 
     369        { 
     370            if (v.x() == _xMin) 
     371            { 
     372                if (v.y() == _yMin) return C00; 
     373                if (v.y() == _yMax) return C01; 
     374            } 
     375            if (v.x() == _xMax) 
     376            { 
     377                if (v.y() == _yMin) return C10; 
     378                if (v.y() == _yMax) return C11; 
     379            } 
     380            return (NotACorner); 
     381        } 
     382         
     383        void insertIntersectedVertex(ArrayType & array, const VecType & v1, const VecType & v2) 
     384        { 
     385            array.push_back(v1); 
     386             
     387            if (v1.x() == _xMin) 
     388            { 
     389                if (v2.y() == _yMin) 
     390                { 
     391                    if ((isCorner(v1) != C00) && (isCorner(v2) != C00)) array.push_back(CreatePolicy::create(_xMin, _yMin)); 
     392                } 
     393                else if (v2.x() == _xMax) 
     394                { 
     395                    if (isCorner(v1) != C00) array.push_back(CreatePolicy::create(_xMin, _yMin)); 
     396                    array.push_back(CreatePolicy::create(_xMax, _yMin)); 
     397                } 
     398                else if (v2.y() == _yMax) 
     399                { 
     400                    if (isCorner(v1) != C00) array.push_back(CreatePolicy::create(_xMin, _yMin)); 
     401                    array.push_back(CreatePolicy::create(_xMax, _yMin)); 
     402                    array.push_back(CreatePolicy::create(_xMax, _yMax)); 
     403                } 
     404                else if (v2.x() == _xMin) 
     405                { 
     406                    if (v1.y() < v2.y()) 
     407                    { 
     408                        if (isCorner(v1) != C00) array.push_back(CreatePolicy::create(_xMin, _yMin)); 
     409                        array.push_back(CreatePolicy::create(_xMax, _yMin)); 
     410                        array.push_back(CreatePolicy::create(_xMax, _yMax)); 
     411                        array.push_back(CreatePolicy::create(_xMin, _yMax)); 
     412                    } 
     413                } 
     414            } 
     415             
     416            else if (v1.y() == _yMin) 
     417            { 
     418                if (v2.x() == _xMax) 
     419                { 
     420                    if ((isCorner(v1) != C10) && (isCorner(v2) != C10)) array.push_back(CreatePolicy::create(_xMax, _yMin)); 
     421                } 
     422                else if (v2.y() == _yMax) 
     423                { 
     424                    if (isCorner(v1) != C10) array.push_back(CreatePolicy::create(_xMax, _yMin)); 
     425                    array.push_back(CreatePolicy::create(_xMax, _yMax)); 
     426                } 
     427                else if (v2.x() == _xMin) 
     428                { 
     429                    if (isCorner(v1) != C10) array.push_back(CreatePolicy::create(_xMax, _yMin)); 
     430                    array.push_back(CreatePolicy::create(_xMax, _yMax)); 
     431                    array.push_back(CreatePolicy::create(_xMin, _yMax)); 
     432                } 
     433                else if (v2.y() == _yMin) 
     434                { 
     435                    if (v1.x() > v2.x()) 
     436                    {    
     437                        if (isCorner(v1) != C10) array.push_back(CreatePolicy::create(_xMax, _yMin)); 
     438                        array.push_back(CreatePolicy::create(_xMax, _yMax)); 
     439                        array.push_back(CreatePolicy::create(_xMin, _yMax)); 
     440                        array.push_back(CreatePolicy::create(_xMin, _yMin)); 
     441                    } 
     442                } 
     443            } 
     444             
     445            else if (v1.x() == _xMax) 
     446            { 
     447                if (v2.y() == _yMax) 
     448                { 
     449                    if ((isCorner(v1) != C11) && (isCorner(v2) != C11)) array.push_back(CreatePolicy::create(_xMax, _yMax)); 
     450                } 
     451                else if (v2.x() == _xMin) 
     452                { 
     453                    if (isCorner(v1) != C11) array.push_back(CreatePolicy::create(_xMax, _yMax)); 
     454                    array.push_back(CreatePolicy::create(_xMax, _yMin)); 
     455                } 
     456                else if (v2.y() == _yMin) 
     457                { 
     458                    if (isCorner(v1) != C11) array.push_back(CreatePolicy::create(_xMax, _yMax)); 
     459                    array.push_back(CreatePolicy::create(_xMin, _yMax)); 
     460                    array.push_back(CreatePolicy::create(_xMin, _yMin)); 
     461                } 
     462                else if (v2.x() == _xMax) 
     463                { 
     464                    if (v1.y() > v2.y()) 
     465                    { 
     466                        if (isCorner(v1) != C11) array.push_back(CreatePolicy::create(_xMax, _yMax)); 
     467                        array.push_back(CreatePolicy::create(_xMin, _yMax)); 
     468                        array.push_back(CreatePolicy::create(_xMin, _yMin)); 
     469                        array.push_back(CreatePolicy::create(_xMax, _yMin)); 
     470                    } 
     471                } 
     472            } 
     473             
     474            else if (v1.y() == _yMax) 
     475            { 
     476                if (v2.x() == _xMin) 
     477                { 
     478                    if ((isCorner(v1) != C01) && (isCorner(v2) != C01)) array.push_back(CreatePolicy::create(_xMin, _yMax)); 
     479                } 
     480                else if (v2.y() == _yMin) 
     481                { 
     482<