osgEarth 2.1.1
|
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 }