osgEarth 2.1.1
|
Public Member Functions | |
BuildGeometryFilter (const Style &style=Style()) | |
osg::Node * | push (FeatureList &input, FilterContext &context) |
const Style & | getStyle () |
void | setStyle (const Style &s) |
optional< double > & | maxGranularity () |
const optional< double > & | maxGranularity () const |
optional< GeoInterpolation > & | geoInterp () |
const optional < GeoInterpolation > & | geoInterp () const |
optional< bool > & | mergeGeometry () |
const optional< bool > & | mergeGeometry () const |
optional< StringExpression > & | featureName () |
const optional < StringExpression > & | featureName () const |
Protected Member Functions | |
void | reset () |
bool | process (FeatureList &input, const FilterContext &context) |
Protected Attributes | |
osg::ref_ptr< osg::Node > | _result |
osg::ref_ptr< osg::Geode > | _geode |
Style | _style |
optional< double > | _maxAngle_deg |
optional< GeoInterpolation > | _geoInterp |
optional< bool > | _mergeGeometry |
optional< StringExpression > | _featureNameExpr |
bool | _hasPoints |
bool | _hasLines |
bool | _hasPolygons |
Builds geometry from a stream of input features.
Definition at line 38 of file BuildGeometryFilter.
Definition at line 48 of file BuildGeometryFilter.cpp.
: _style ( style ), _maxAngle_deg ( 5.0 ), _geoInterp ( GEOINTERP_RHUMB_LINE ), _mergeGeometry( false ) { reset(); }
optional<StringExpression>& osgEarth::Features::BuildGeometryFilter::featureName | ( | ) | [inline] |
Sets an expression to evaluate for setting the name of a Geometry. This only takes effect if mergeGeometry is false.
Definition at line 79 of file BuildGeometryFilter.
{ return _featureNameExpr; }
const optional<StringExpression>& osgEarth::Features::BuildGeometryFilter::featureName | ( | ) | const [inline] |
Definition at line 80 of file BuildGeometryFilter.
{ return _featureNameExpr; }
optional<GeoInterpolation>& osgEarth::Features::BuildGeometryFilter::geoInterp | ( | ) | [inline] |
The algorithm to use when interpolating between geodetic locations. The default is GEOINTERP_RHUMBLINE.
Definition at line 64 of file BuildGeometryFilter.
{ return _geoInterp; }
const optional<GeoInterpolation>& osgEarth::Features::BuildGeometryFilter::geoInterp | ( | ) | const [inline] |
Definition at line 65 of file BuildGeometryFilter.
{ return _geoInterp; }
const Style& osgEarth::Features::BuildGeometryFilter::getStyle | ( | ) | [inline] |
The style to apply to feature geometry
Definition at line 47 of file BuildGeometryFilter.
{ return _style; }
const optional<double>& osgEarth::Features::BuildGeometryFilter::maxGranularity | ( | ) | const [inline] |
Definition at line 58 of file BuildGeometryFilter.
{ return _maxAngle_deg; }
optional<double>& osgEarth::Features::BuildGeometryFilter::maxGranularity | ( | ) | [inline] |
For geocentric data, sets the granularity of edges created by the filter. This is the maximum angle (in degrees) between the vectors representing two geocentric points comprising an edge. Since large polygons won't naturally conform to the ellipsoid very well, this setting lets you specify a minimum edge size so that they will break down and conform better.
Definition at line 57 of file BuildGeometryFilter.
{ return _maxAngle_deg; }
optional<bool>& osgEarth::Features::BuildGeometryFilter::mergeGeometry | ( | ) | [inline] |
Whether to merge the geometries from mutliple features together. Doing this can help performance by batching geometries together. The downside will be that individual geometries are no longer addressable in the scene graph. Default is FALSE.
Definition at line 72 of file BuildGeometryFilter.
{ return _mergeGeometry; }
const optional<bool>& osgEarth::Features::BuildGeometryFilter::mergeGeometry | ( | ) | const [inline] |
Definition at line 73 of file BuildGeometryFilter.
{ return _mergeGeometry; }
bool BuildGeometryFilter::process | ( | FeatureList & | input, |
const FilterContext & | context | ||
) | [protected] |
Definition at line 68 of file BuildGeometryFilter.cpp.
{ bool makeECEF = context.getSession()->getMapInfo().isGeocentric(); const SpatialReference* srs = context.extent()->getSRS(); for( FeatureList::iterator f = features.begin(); f != features.end(); ++f ) { Feature* input = f->get(); GeometryIterator parts( input->getGeometry(), false ); while( parts.hasMore() ) { Geometry* part = parts.next(); osg::PrimitiveSet::Mode primMode = osg::PrimitiveSet::POINTS; const Style& myStyle = input->style().isSet() ? *input->style() : _style; osg::Vec4f color = osg::Vec4(1,1,1,1); bool tessellatePolys = true; bool setWidth = input->style().isSet(); // otherwise it will be set globally, we assume float width = 1.0f; switch( part->getType() ) { case Geometry::TYPE_POINTSET: { _hasPoints = true; primMode = osg::PrimitiveSet::POINTS; const PointSymbol* point = myStyle.getSymbol<PointSymbol>(); if (point) { color = point->fill()->color(); } } break; case Geometry::TYPE_LINESTRING: { _hasLines = true; primMode = osg::PrimitiveSet::LINE_STRIP; const LineSymbol* lineSymbol = myStyle.getSymbol<LineSymbol>(); if (lineSymbol) { color = lineSymbol->stroke()->color(); width = lineSymbol->stroke()->width().isSet() ? *lineSymbol->stroke()->width() : 1.0f; } } break; case Geometry::TYPE_RING: { _hasLines = true; primMode = osg::PrimitiveSet::LINE_LOOP; const LineSymbol* lineSymbol = myStyle.getSymbol<LineSymbol>(); if (lineSymbol) { color = lineSymbol->stroke()->color(); width = lineSymbol->stroke()->width().isSet() ? *lineSymbol->stroke()->width() : 1.0f; } } break; case Geometry::TYPE_POLYGON: { primMode = osg::PrimitiveSet::LINE_LOOP; // loop will tessellate into polys const PolygonSymbol* poly = myStyle.getSymbol<PolygonSymbol>(); if (poly) { _hasPolygons = true; color = poly->fill()->color(); } else { // if we have a line symbol and no polygon symbol, draw as an outline. _hasLines = true; const LineSymbol* line = myStyle.getSymbol<LineSymbol>(); if ( line ) { color = line->stroke()->color(); width = line->stroke()->width().isSet() ? *line->stroke()->width() : 1.0f; tessellatePolys = false; } } } break; } osg::Geometry* osgGeom = new osg::Geometry(); if ( _featureNameExpr.isSet() ) { const std::string& name = input->eval( _featureNameExpr.mutable_value() ); osgGeom->setName( name ); } // NOTE: benchmarking reveals VBOs to be much slower (for static data, at least) //osgGeom->setUseVertexBufferObjects( true ); //osgGeom->setUseDisplayList( false ); if ( setWidth && width != 1.0f ) { osgGeom->getOrCreateStateSet()->setAttributeAndModes( new osg::LineWidth( width ), osg::StateAttribute::ON ); } if (_hasLines) { const LineSymbol* line = myStyle.getSymbol<LineSymbol>(); if (line && line->stroke().isSet() && line->stroke()->stipple().isSet()) { osg::LineStipple* lineStipple = new osg::LineStipple; lineStipple->setPattern( *line->stroke()->stipple() ); osgGeom->getOrCreateStateSet()->setAttributeAndModes( lineStipple, osg::StateAttribute::ON ); } } if (part->getType() == Geometry::TYPE_POLYGON && static_cast<Polygon*>(part)->getHoles().size() > 0 ) { Polygon* poly = static_cast<Polygon*>(part); int totalPoints = poly->getTotalPointCount(); osg::Vec3Array* allPoints; // = new osg::Vec3Array( totalPoints ); if ( makeECEF ) { allPoints = new osg::Vec3Array(); ECEF::transformAndLocalize( part->asVector(), allPoints, srs, _world2local ); } else { allPoints = new osg::Vec3Array( totalPoints ); std::copy( part->begin(), part->end(), allPoints->begin() ); } osgGeom->addPrimitiveSet( new osg::DrawArrays( primMode, 0, part->size() ) ); int offset = part->size(); for( RingCollection::const_iterator h = poly->getHoles().begin(); h != poly->getHoles().end(); ++h ) { Geometry* hole = h->get(); if ( hole->isValid() ) { if ( makeECEF ) ECEF::transformAndLocalize( hole->asVector(), allPoints, srs, _world2local ); else std::copy( hole->begin(), hole->end(), allPoints->begin() + offset ); osgGeom->addPrimitiveSet( new osg::DrawArrays( primMode, offset, hole->size() ) ); offset += hole->size(); } } osgGeom->setVertexArray( allPoints ); } else { if ( makeECEF ) { osg::Vec3Array* newPart = new osg::Vec3Array(); ECEF::transformAndLocalize( part->asVector(), newPart, srs, _world2local ); osgGeom->setVertexArray( newPart ); } else { osgGeom->setVertexArray( part->toVec3Array() ); } osgGeom->addPrimitiveSet( new osg::DrawArrays( primMode, 0, part->size() ) ); } // tessellate all polygon geometries. Tessellating each geometry separately // with TESS_TYPE_GEOMETRY is much faster than doing the whole bunch together // using TESS_TYPE_DRAWABLE. if ( part->getType() == Geometry::TYPE_POLYGON && tessellatePolys ) { osgUtil::Tessellator tess; //tess.setTessellationType( osgUtil::Tessellator::TESS_TYPE_DRAWABLE ); //tess.setWindingType( osgUtil::Tessellator::TESS_WINDING_ODD ); tess.setTessellationType( osgUtil::Tessellator::TESS_TYPE_GEOMETRY ); tess.setWindingType( osgUtil::Tessellator::TESS_WINDING_POSITIVE ); tess.retessellatePolygons( *osgGeom ); // the tessellator results in a collection of trifans, strips, etc. This step will // consolidate those into one (or more if necessary) GL_TRIANGLES primitive. //NOTE: this now happens elsewhere //MeshConsolidator::run( *osgGeom ); // mark this geometry as DYNAMIC because otherwise the OSG optimizer will destroy it. //osgGeom->setDataVariance( osg::Object::DYNAMIC ); } if ( context.getSession()->getMapInfo().isGeocentric() && part->getType() != Geometry::TYPE_POINTSET ) // if ( context.isGeocentric() && part->getType() != Geometry::TYPE_POINTSET ) { double threshold = osg::DegreesToRadians( *_maxAngle_deg ); MeshSubdivider ms( _world2local, _local2world ); //context.referenceFrame(), context.inverseReferenceFrame() ); //ms.setMaxElementsPerEBO( INT_MAX ); if ( input->geoInterp().isSet() ) ms.run( *osgGeom, threshold, *input->geoInterp() ); else ms.run( *osgGeom, threshold, *_geoInterp ); } // NOTE! per-vertex colors makes the optimizer destroy the geometry.... osg::Vec4Array* colors = new osg::Vec4Array(1); (*colors)[0] = color; osgGeom->setColorArray( colors ); osgGeom->setColorBinding( osg::Geometry::BIND_OVERALL ); // add the part to the geode. _geode->addDrawable( osgGeom ); } } return true; }
osg::Node * BuildGeometryFilter::push | ( | FeatureList & | input, |
FilterContext & | context | ||
) | [virtual] |
Pushes a list of features through the filter.
Implements osgEarth::Features::FeaturesToNodeFilter.
Definition at line 288 of file BuildGeometryFilter.cpp.
{ reset(); computeLocalizers( context ); bool ok = process( input, context ); // convert all geom to triangles and consolidate into minimal set of Geometries if ( !_featureNameExpr.isSet() ) { MeshConsolidator::run( *_geode.get() ); } osg::Node* result = 0L; if ( ok ) { if ( !_style.empty() && _geode.valid() ) { // could optimize this to only happen is lines or points were created .. const LineSymbol* lineSymbol = _style.getSymbol<LineSymbol>(); float size = 1.0; if (lineSymbol) size = lineSymbol->stroke()->width().value(); _geode->getOrCreateStateSet()->setAttribute( new osg::Point(size), osg::StateAttribute::ON ); _geode->getOrCreateStateSet()->setAttribute( new osg::LineWidth(size), osg::StateAttribute::ON ); const PointSymbol* pointSymbol = _style.getSymbol<PointSymbol>(); if ( pointSymbol && pointSymbol->size().isSet() ) _geode->getOrCreateStateSet()->setAttribute( new osg::Point( *pointSymbol->size() ), osg::StateAttribute::ON ); } result = delocalize( _geode.release() ); } else { result = 0L; } return result; }
void BuildGeometryFilter::reset | ( | ) | [protected] |
Definition at line 58 of file BuildGeometryFilter.cpp.
{ _result = 0L; _geode = new osg::Geode(); _hasLines = false; _hasPoints = false; _hasPolygons = false; }
void osgEarth::Features::BuildGeometryFilter::setStyle | ( | const Style & | s | ) | [inline] |
Definition at line 48 of file BuildGeometryFilter.
{ _style = s; }
Definition at line 89 of file BuildGeometryFilter.
osg::ref_ptr<osg::Geode> osgEarth::Features::BuildGeometryFilter::_geode [protected] |
Definition at line 84 of file BuildGeometryFilter.
Definition at line 87 of file BuildGeometryFilter.
bool osgEarth::Features::BuildGeometryFilter::_hasLines [protected] |
Definition at line 91 of file BuildGeometryFilter.
bool osgEarth::Features::BuildGeometryFilter::_hasPoints [protected] |
Definition at line 90 of file BuildGeometryFilter.
bool osgEarth::Features::BuildGeometryFilter::_hasPolygons [protected] |
Definition at line 92 of file BuildGeometryFilter.
optional<double> osgEarth::Features::BuildGeometryFilter::_maxAngle_deg [protected] |
Definition at line 86 of file BuildGeometryFilter.
optional<bool> osgEarth::Features::BuildGeometryFilter::_mergeGeometry [protected] |
Definition at line 88 of file BuildGeometryFilter.
osg::ref_ptr<osg::Node> osgEarth::Features::BuildGeometryFilter::_result [protected] |
Definition at line 83 of file BuildGeometryFilter.
Style osgEarth::Features::BuildGeometryFilter::_style [protected] |
Definition at line 85 of file BuildGeometryFilter.