osgEarth 2.1.1

/home/cube/sources/osgearth/src/osgEarthSymbology/MarkerSymbolizer.cpp

Go to the documentation of this file.
00001 /* -*-c++-*- */
00002 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
00003  * Copyright 2008-2010 Pelican Mapping
00004  * http://osgearth.org
00005  *
00006  * osgEarth is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU Lesser General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public License
00017  * along with this program.  If not, see <http://www.gnu.org/licenses/>
00018  */
00019 #include <osgEarthSymbology/MarkerSymbolizer>
00020 #include <osgEarthSymbology/MarkerSymbol>
00021 #include <osgDB/ReadFile>
00022 #include <osgDB/ReaderWriter>
00023 #include <osg/Geometry>
00024 #include <osg/MatrixTransform>
00025 #include <osg/Material>
00026 #include <osg/Geode>
00027 #include <osg/Version>
00028 
00029 
00030 using namespace osgEarth::Symbology;
00031 
00032 static osg::Node* getNode(const std::string& str)
00033 {
00034 #if OSG_VERSION_LESS_THAN(2,9,8)
00035     osg::ref_ptr<osgDB::ReaderWriter::Options> options = new osgDB::ReaderWriter::Options;
00036     options->setObjectCacheHint(osgDB::ReaderWriter::Options::CACHE_ALL);
00037     osg::Node* node = osgDB::readNodeFile(str, options.get());
00038     return node;
00039 #else
00040     osg::ref_ptr<osgDB::Options> options = new osgDB::Options;
00041     options->setObjectCacheHint(osgDB::Options::CACHE_ALL);
00042     osg::Node* node = osgDB::readNodeFile(str, options.get());
00043     return node;
00044 #endif
00045 }
00046 
00047 static double getRandomValueInRange(double value)
00048 {
00049     return (-value/2) + ((rand() * value)/(RAND_MAX-1));
00050 }
00051 
00052 MarkerSymbolizer::MarkerSymbolizer()
00053 {
00054 }
00055 
00056 bool MarkerSymbolizer::pointInPolygon(const osg::Vec3d& point, osg::Vec3dArray* pointList)
00057 {
00058     if (!pointList)
00059         return false;
00060 
00061     bool result = false;
00062     const osg::Vec3dArray& polygon = *pointList;
00063     for( unsigned int i=0, j=polygon.size()-1; i<polygon.size(); j = i++ )
00064     {
00065         if ((((polygon[i].y() <= point.y()) && (point.y() < polygon[j].y())) ||
00066              ((polygon[j].y() <= point.y()) && (point.y() < polygon[i].y()))) &&
00067             (point.x() < (polygon[j].x()-polygon[i].x()) * (point.y()-polygon[i].y())/(polygon[j].y()-polygon[i].y())+polygon[i].x()))
00068         {
00069             result = !result;
00070         }
00071     }
00072     return result;
00073 }
00074 
00075 bool 
00076 MarkerSymbolizer::compile(MarkerSymbolizerState* state,
00077                           osg::Group* attachPoint)
00078 {
00079     if ( !state || !attachPoint || !state->getContent() || !state->getStyle() )
00080         return false;
00081 
00082     osg::ref_ptr<osg::Group> newSymbolized = new osg::Group;
00083     const GeometryList& geometryList = state->getContent()->getGeometryList();
00084     for (GeometryList::const_iterator it = geometryList.begin(); it != geometryList.end(); ++it)
00085     {
00086         Geometry* geometry = *it;
00087         if (!geometry)
00088             continue;
00089 
00090         GeometryIterator geomIterator( geometry );
00091         geomIterator.traverseMultiGeometry() = true;
00092         geomIterator.traversePolygonHoles() = true;
00093 
00094         while( geomIterator.hasMore() )
00095         {
00096             Geometry* part = geomIterator.next();
00097             if (!part)
00098                 continue;
00099 
00100             switch( part->getType())
00101             {
00102             case Geometry::TYPE_POINTSET:
00103             {
00104                 const MarkerSymbol* point = state->getStyle()->getSymbol<MarkerSymbol>();
00105                 if (point)
00106                 {
00107                     if (point && part->size() && !point->marker().value().empty())
00108                     {
00109                         osg::Node* node = getNode(point->marker().value());
00110                         if (!node) {
00111                             osg::notify(osg::WARN) << "can't load Marker Node " << point->marker().value() << std::endl;
00112                             continue;
00113                         }
00114                         osg::Group* group = new osg::Group;
00115                         for ( osg::Vec3dArray::iterator it = part->begin(); it != part->end(); ++it)
00116                         {
00117                             osg::Vec3d pos = *it;
00118                             osg::MatrixTransform* tr = new osg::MatrixTransform;
00119                             tr->setMatrix(osg::Matrix::translate(pos));
00120                             tr->addChild(node);
00121                             group->addChild(tr);
00122                         }
00123                         newSymbolized->addChild(group);
00124                     }
00125                 }
00126             }
00127             break;
00128 
00129             case Geometry::TYPE_LINESTRING:
00130             case Geometry::TYPE_RING:
00131             {
00132                 const MarkerLineSymbol* line = state->getStyle()->getSymbol<MarkerLineSymbol>();
00133                 if (line)
00134                 {
00135                     if (line && part->size() && !line->marker().value().empty())
00136                     {
00137                         osg::Node* node = getNode(line->marker().value());
00138                         if (!node) {
00139                             osg::notify(osg::WARN) << "can't load Marker Node " << line->marker().value() << std::endl;
00140                             continue;
00141                         }
00142                         float interval = line->interval().value();
00143                         if (!interval)
00144                             interval = 1.0;
00145 
00146 
00147                         osg::Group* group = new osg::Group;                        
00148                         float currentDist = 0;
00149 
00150                         // start to put one first node
00151                         {
00152                             osg::MatrixTransform* tr = new osg::MatrixTransform;
00153                             tr->setMatrix(osg::Matrix::translate(*part->begin()));
00154                             tr->addChild(node);
00155                             group->addChild(tr);
00156                         }
00157 
00158                         for ( unsigned int i = 0; i < part->size(); ++i)
00159                         {
00160                             osg::Vec3d start = (*part)[i];
00161                             osg::Vec3d end;
00162                             if (i < (part->size() - 1)) {
00163                                 end = (*part)[i+1];
00164                             } else {
00165                                 if (part->getType() == Geometry::TYPE_RING) {
00166                                     end = (*part)[0];
00167                                 } else {
00168                                     end = start;
00169                                 }
00170                             }
00171                             osg::Vec3d direction = end - start;
00172                             float segmentSize = direction.length();
00173                             direction.normalize();
00174 
00175                             float previousDist = currentDist;
00176                             currentDist += segmentSize;
00177                             if (currentDist < interval)
00178                                 continue;
00179                                 
00180                             float offset = interval - previousDist;
00181                                 
00182                             float rate = currentDist / interval;
00183                             int nbItems = static_cast<int>(floorf(rate));
00184                             rate -= (float)nbItems;
00185                             float remaining = rate * interval;
00186                             currentDist = remaining;
00187 
00188                             osg::Vec3d startOnTheLine = start + direction * offset;
00189                             for (int j = 0; j < nbItems; ++j)
00190                             {
00191                                 osg::MatrixTransform* tr = new osg::MatrixTransform;
00192                                 tr->setMatrix(osg::Matrix::translate(startOnTheLine + direction*j*interval));
00193                                 tr->addChild(node);
00194                                 group->addChild(tr);
00195                             }
00196                         }
00197                         newSymbolized->addChild(group);
00198                     }
00199                 }
00200             }
00201             break;
00202 
00203             case Geometry::TYPE_POLYGON:
00204             {
00205                 const MarkerPolygonSymbol* poly = state->getStyle()->getSymbol<MarkerPolygonSymbol>();
00206                 if (poly)
00207                 {
00208                     if (poly && part->size() && !poly->marker().value().empty())
00209                     {
00210                         osg::Node* node = getNode(poly->marker().value());
00211                         if (!node) {
00212                             osg::notify(osg::WARN) << "can't load Marker Node " << poly->marker().value() << std::endl;
00213                             continue;
00214                         }
00215                         float interval = poly->interval().value();
00216                         if (!interval)
00217                             interval = 1.0;
00218 
00219                         float randomRatio = poly->randomRatio().value();
00220 
00221                         osg::Group* group = new osg::Group;
00222                         osg::BoundingBox bb;
00223                         for (osg::Vec3dArray::iterator it = part->begin(); it != part->end(); ++it) 
00224                         {
00225                             bb.expandBy(*it);
00226                         }
00227 
00228                         // use a grid on x and y
00229                         osg::Vec3d startOnGrid = bb.corner(0);
00230                         float sizex = bb.xMax() - bb.xMin();
00231                         float sizey = bb.yMax() - bb.yMin();
00232                         int numX = static_cast<int>(floorf(sizex / interval));
00233                         int numY = static_cast<int>(floorf(sizey / interval));
00234                         for (int y = 0; y < numY; ++y)
00235                         {
00236                             for (int x = 0; x < numX; ++x)
00237                             {
00238 
00239 
00240                                 // get two random number in interval
00241                                 osg::Vec3d randOffset(0, 0, 0);
00242                                 randOffset = osg::Vec3d(getRandomValueInRange(1.0), getRandomValueInRange(1.0), 0);
00243                                 if (randOffset.length2() > 0.0)
00244                                     randOffset.normalize();
00245                                 randOffset *= ( getRandomValueInRange( interval) ) * randomRatio;
00246 
00247                                 osg::Vec3d point = startOnGrid + randOffset + osg::Vec3d(x*interval, y*interval, 0);
00248 
00249                                 if (pointInPolygon(point, part))
00250                                 {
00251 
00252                                     osg::MatrixTransform* tr = new osg::MatrixTransform;
00253                                     tr->setMatrix(osg::Matrix::translate(point));
00254                                     tr->addChild(node);
00255                                     group->addChild(tr);
00256                                 }
00257                             }
00258                         }
00259                         newSymbolized->addChild(group);
00260                     }
00261                 }
00262             }
00263             break;
00264 
00265             default:
00266                 break;
00267 
00268             }
00269         }
00270     }
00271 
00272     if (newSymbolized->getNumChildren())
00273     {
00274         attachPoint->removeChildren(0, attachPoint->getNumChildren());
00275         attachPoint->addChild(newSymbolized.get());
00276         return true;
00277     }
00278 
00279     return false;
00280 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines