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/GeometrySymbolizer> 00020 #include <osgEarthSymbology/PointSymbol> 00021 #include <osgEarthSymbology/LineSymbol> 00022 #include <osgEarthSymbology/PolygonSymbol> 00023 #include <osgUtil/Tessellator> 00024 #include <osg/Geometry> 00025 #include <osg/Point> 00026 #include <osg/LineWidth> 00027 #include <osg/Material> 00028 #include <osg/Geode> 00029 00030 using namespace osgEarth::Symbology; 00031 00032 00033 osg::Node* GeometrySymbolizer::GeometrySymbolizerOperator::operator()(const GeometryList& geometryList, 00034 const Style* style) 00035 { 00036 osg::ref_ptr<osg::Geode> geode = new osg::Geode; 00037 for (GeometryList::const_iterator it = geometryList.begin(); it != geometryList.end(); ++it) 00038 { 00039 Geometry* geometry = *it; 00040 if (!geometry) 00041 continue; 00042 00043 GeometryIterator geomIterator( geometry ); 00044 geomIterator.traverseMultiGeometry() = true; 00045 geomIterator.traversePolygonHoles() = true; 00046 00047 while( geomIterator.hasMore() ) 00048 { 00049 Geometry* part = geomIterator.next(); 00050 if (!part) 00051 continue; 00052 00053 osg::ref_ptr<osg::Geometry> osgGeom = new osg::Geometry; 00054 osg::PrimitiveSet::Mode primMode = osg::PrimitiveSet::POINTS; 00055 00056 osg::Vec4 color = osg::Vec4(1.0, 0.0, 1.0, 1.); 00057 00058 switch( part->getType()) 00059 { 00060 case Geometry::TYPE_POINTSET: 00061 { 00062 primMode = osg::PrimitiveSet::POINTS; 00063 const PointSymbol* point = style->getSymbol<PointSymbol>(); 00064 if (point) 00065 { 00066 color = point->fill()->color(); 00067 00068 float size = point->size().value(); 00069 osgGeom->getOrCreateStateSet()->setAttributeAndModes( new osg::Point(size) ); 00070 } 00071 } 00072 break; 00073 00074 case Geometry::TYPE_LINESTRING: 00075 { 00076 primMode = osg::PrimitiveSet::LINE_STRIP; 00077 const LineSymbol* line = style->getSymbol<LineSymbol>(); 00078 if (line) 00079 { 00080 color = line->stroke()->color(); 00081 float size = line->stroke()->width().value(); 00082 osgGeom->getOrCreateStateSet()->setAttributeAndModes( new osg::LineWidth(size)); 00083 } 00084 } 00085 break; 00086 00087 case Geometry::TYPE_RING: 00088 { 00089 primMode = osg::PrimitiveSet::LINE_LOOP; 00090 const LineSymbol* line = style->getSymbol<LineSymbol>(); 00091 if (line) 00092 { 00093 color = line->stroke()->color(); 00094 float size = line->stroke()->width().value(); 00095 osgGeom->getOrCreateStateSet()->setAttributeAndModes( new osg::LineWidth(size)); 00096 } 00097 } 00098 break; 00099 00100 case Geometry::TYPE_POLYGON: 00101 { 00102 primMode = osg::PrimitiveSet::LINE_LOOP; // loop will tessellate into polys 00103 const PolygonSymbol* poly = style->getSymbol<PolygonSymbol>(); 00104 if (poly) 00105 { 00106 color = poly->fill()->color(); 00107 } 00108 } 00109 break; 00110 00111 default: 00112 break; 00113 } 00114 00115 osg::Material* material = new osg::Material; 00116 material->setDiffuse(osg::Material::FRONT_AND_BACK, color); 00117 00118 if ( part->getType() == Geometry::TYPE_POLYGON && static_cast<Polygon*>(part)->getHoles().size() > 0 ) 00119 { 00120 Polygon* poly = static_cast<Polygon*>(geometry); 00121 int totalPoints = poly->getTotalPointCount(); 00122 osg::Vec3Array* allPoints = new osg::Vec3Array( totalPoints ); 00123 int offset = 0; 00124 for( RingCollection::const_iterator h = poly->getHoles().begin(); h != poly->getHoles().end(); ++h ) 00125 { 00126 Geometry* hole = h->get(); 00127 std::copy( hole->begin(), hole->end(), allPoints->begin() + offset ); 00128 osgGeom->addPrimitiveSet( new osg::DrawArrays( primMode, offset, hole->size() ) ); 00129 offset += hole->size(); 00130 } 00131 osgGeom->setVertexArray( allPoints ); 00132 } 00133 else 00134 { 00135 osgGeom->setVertexArray( part->toVec3Array() ); 00136 osgGeom->addPrimitiveSet( new osg::DrawArrays( primMode, 0, part->size() ) ); 00137 } 00138 00139 // tessellate all polygon geometries. Tessellating each geometry separately 00140 // with TESS_TYPE_GEOMETRY is much faster than doing the whole bunch together 00141 // using TESS_TYPE_DRAWABLE. 00142 00143 if ( part->getType() == Geometry::TYPE_POLYGON) 00144 { 00145 osgUtil::Tessellator tess; 00146 tess.setTessellationType( osgUtil::Tessellator::TESS_TYPE_GEOMETRY ); 00147 tess.setWindingType( osgUtil::Tessellator::TESS_WINDING_POSITIVE ); 00148 tess.retessellatePolygons( *osgGeom ); 00149 } 00150 osgGeom->getOrCreateStateSet()->setAttributeAndModes(material); 00151 geode->addDrawable(osgGeom); 00152 } 00153 } 00154 00155 if (geode->getNumDrawables()) 00156 return geode.release(); 00157 return 0; 00158 } 00159 00160 00161 GeometrySymbolizer::GeometrySymbolizer() 00162 { 00163 //nop 00164 } 00165 00166 bool 00167 GeometrySymbolizer::compile(GeometrySymbolizerState* state, 00168 osg::Group* attachPoint) 00169 { 00170 if ( !state || !state->getContent() || !attachPoint || !state->getStyle() ) 00171 return false; 00172 00173 //const GeometryContent* geometryInput = dynamic_cast<const GeometryContent*>(dataSet); 00174 //if (!geometryInput) 00175 // return false; 00176 00177 const GeometryList& geometryList = state->getContent()->getGeometryList(); 00178 00179 GeometrySymbolizerOperator functor; 00180 osg::Node* node = (functor)(geometryList, state->getStyle()); 00181 if (node) 00182 { 00183 attachPoint->removeChildren(0, attachPoint->getNumChildren()); 00184 attachPoint->addChild(node); 00185 return true; 00186 } 00187 00188 return false; 00189 }