Style buildStyle( const osg::Vec4 &color, float width ) { // Define a style for the feature data. Since we are going to render the // vectors as lines, configure the line symbolizer: Style style; LineSymbol* ls = style.getOrCreateSymbol<LineSymbol>(); ls->stroke()->color() = color; ls->stroke()->width() = width; ls->tessellation() = 10; AltitudeSymbol* as = style.getOrCreate<AltitudeSymbol>(); as->clamping() = AltitudeSymbol::CLAMP_TO_TERRAIN; as->technique() = AltitudeSymbol::TECHNIQUE_SCENE; RenderSymbol* rs = style.getOrCreateSymbol<RenderSymbol>(); rs->depthOffset()->enabled() = true; rs->depthOffset()->minBias() = 1000; return style; }
void GeodeticGraticule::initLabelPool(CameraData& cdata) { const osgEarth::SpatialReference* srs = osgEarth::SpatialReference::create("wgs84"); Style style; TextSymbol* text = style.getOrCreateSymbol<TextSymbol>(); text->alignment() = TextSymbol::ALIGN_CENTER_CENTER; text->fill()->color() = options().labelColor().get(); AltitudeSymbol* alt = style.getOrCreateSymbol<AltitudeSymbol>(); alt->clamping() = AltitudeSymbol::CLAMP_TO_TERRAIN; unsigned int labelPoolSize = 8 * options().gridLines().get(); for (unsigned int i = 0; i < labelPoolSize; i++) { GeoPoint pt(srs, 0,0,0); LabelNode* label = new LabelNode(_mapNode.get(), pt, "0,0"); label->setDynamic(true); label->setStyle(style); cdata._labelPool.push_back(label); } }
void KML_Geometry::parseStyle( const Config& conf, KMLContext& cx, Style& style ) { _extrude = conf.value("extrude") == "1"; _tessellate = conf.value("tessellate") == "1"; std::string am = conf.value("altitudemode"); // clampToGround is the default. We will be draping the geometry UNLESS tessellate is // set to true. if ( (am.empty() || am == "clampToGround") && _tessellate ) { AltitudeSymbol* af = style.getOrCreate<AltitudeSymbol>(); af->clamping() = AltitudeSymbol::CLAMP_TO_TERRAIN; _extrude = false; } // "relativeToGround" means the coordinates' Z values are relative to the Z of the // terrain at that point. NOTE: GE flattens rooftops in this mode when extrude=1, // which seems wrong.. else if ( am == "relativeToGround" ) { AltitudeSymbol* af = style.getOrCreate<AltitudeSymbol>(); af->clamping() = AltitudeSymbol::CLAMP_RELATIVE_TO_TERRAIN; } // "absolute" means to treat the Z values as-is else if ( am == "absolute" ) { AltitudeSymbol* af = style.getOrCreate<AltitudeSymbol>(); af->clamping() = AltitudeSymbol::CLAMP_ABSOLUTE; } if ( _extrude ) { ExtrusionSymbol* es = style.getOrCreate<ExtrusionSymbol>(); es->flatten() = false; } }
void ExtrudeGeometryFilter::reset( const FilterContext& context ) { _cosWallAngleThresh = cos( _wallAngleThresh_deg ); _geodes.clear(); if ( _styleDirty ) { const StyleSheet* sheet = context.getSession() ? context.getSession()->styles() : 0L; _wallSkinSymbol = 0L; _wallPolygonSymbol = 0L; _roofSkinSymbol = 0L; _roofPolygonSymbol = 0L; _extrusionSymbol = 0L; _outlineSymbol = 0L; _extrusionSymbol = _style.get<ExtrusionSymbol>(); if ( _extrusionSymbol.valid() ) { // make a copy of the height expression so we can use it: if ( _extrusionSymbol->heightExpression().isSet() ) { _heightExpr = *_extrusionSymbol->heightExpression(); } // If there is no height expression, and we have either absolute or terrain-relative // clamping, THAT means that we want to extrude DOWN from the geometry to the ground // (instead of from the geometry.) AltitudeSymbol* alt = _style.get<AltitudeSymbol>(); if ( alt && !_extrusionSymbol->heightExpression().isSet() && !_extrusionSymbol->height().isSet() ) { if (alt->clamping() == AltitudeSymbol::CLAMP_ABSOLUTE || alt->clamping() == AltitudeSymbol::CLAMP_RELATIVE_TO_TERRAIN ) { _heightExpr = NumericExpression( "0-[__max_hat]" ); } } // attempt to extract the wall symbols: if ( _extrusionSymbol->wallStyleName().isSet() && sheet != 0L ) { const Style* wallStyle = sheet->getStyle( *_extrusionSymbol->wallStyleName(), false ); if ( wallStyle ) { _wallSkinSymbol = wallStyle->get<SkinSymbol>(); _wallPolygonSymbol = wallStyle->get<PolygonSymbol>(); } } // attempt to extract the rooftop symbols: if ( _extrusionSymbol->roofStyleName().isSet() && sheet != 0L ) { const Style* roofStyle = sheet->getStyle( *_extrusionSymbol->roofStyleName(), false ); if ( roofStyle ) { _roofSkinSymbol = roofStyle->get<SkinSymbol>(); _roofPolygonSymbol = roofStyle->get<PolygonSymbol>(); } } // if there's a line symbol, use it to outline the extruded data. _outlineSymbol = _style.get<LineSymbol>(); } // backup plan for skin symbols: const SkinSymbol* skin = _style.get<SkinSymbol>(); if ( skin ) { if ( !_wallSkinSymbol.valid() ) _wallSkinSymbol = skin; if ( !_roofSkinSymbol.valid() ) _roofSkinSymbol = skin; } // backup plan for poly symbols: const PolygonSymbol* poly = _style.get<PolygonSymbol>(); if ( poly ) { if ( !_wallPolygonSymbol.valid() ) _wallPolygonSymbol = poly; if ( !_roofPolygonSymbol.valid() ) _roofPolygonSymbol = poly; } _styleDirty = false; } }
void KML_Placemark::build( xml_node<>* node, KMLContext& cx ) { Style masterStyle; std::string styleUrl = getValue(node, "styleurl"); if (!styleUrl.empty()) { // process a "stylesheet" style const Style* ref_style = cx._sheet->getStyle( styleUrl, false ); if (ref_style) { masterStyle = masterStyle.combineWith(*ref_style); } } xml_node<>* style = node->first_node("style", 0, false); if ( style ) { // process an "inline" style KML_Style kmlStyle; kmlStyle.scan(style, cx); masterStyle = masterStyle.combineWith(cx._activeStyle); } // parse the geometry. the placemark must have geometry to be valid. The // geometry parse may optionally specify an altitude mode as well. KML_Geometry geometry; geometry.build(node, cx, masterStyle); Geometry* allGeom = geometry._geom.get(); if ( allGeom ) { GeometryIterator giter( allGeom, false ); while( giter.hasMore() ) { Geometry* geom = giter.next(); Style style = masterStyle; AltitudeSymbol* alt = style.get<AltitudeSymbol>(); if ( geom && geom->getTotalPointCount() > 0 ) { // resolve the proper altitude mode for the anchor point AltitudeMode altMode = ALTMODE_RELATIVE; if (alt && !alt->clamping().isSetTo( alt->CLAMP_TO_TERRAIN ) && !alt->clamping().isSetTo( alt->CLAMP_RELATIVE_TO_TERRAIN ) ) { altMode = ALTMODE_ABSOLUTE; } GeoPoint position(cx._srs.get(), geom->getBounds().center(), altMode); bool isPoly = geom->getComponentType() == Geometry::TYPE_POLYGON; bool isPoint = geom->getComponentType() == Geometry::TYPE_POINTSET; // check for symbols. ModelSymbol* model = style.get<ModelSymbol>(); IconSymbol* icon = style.get<IconSymbol>(); TextSymbol* text = style.get<TextSymbol>(); // the annotation name: std::string name = getValue(node, "name"); AnnotationNode* featureNode = 0L; AnnotationNode* iconNode = 0L; AnnotationNode* modelNode = 0L; // one coordinate? It's a place marker or a label. if ( (model || icon || text) && geom->getTotalPointCount() == 1 ) { // load up the default icon if there we don't have one. if ( !model && !icon ) { icon = cx._options->defaultIconSymbol().get(); if ( icon ) style.add( icon ); } // if there's a model, render that - models do NOT get labels. if ( model ) { ModelNode* node = new ModelNode( cx._mapNode, style, cx._dbOptions ); node->setPosition( position ); // model scale: if ( cx._options->modelScale() != 1.0f ) { float s = *cx._options->modelScale(); node->setScale( osg::Vec3f(s,s,s) ); } // model local tangent plane rotation: if ( !cx._options->modelRotation()->zeroRotation() ) { node->setLocalRotation( *cx._options->modelRotation() ); } modelNode = node; } // is there a label? else if ( !name.empty() ) { if ( !text && cx._options->defaultTextSymbol().valid() ) { text = cx._options->defaultTextSymbol().get(); style.addSymbol( text ); } else { text = style.getOrCreate<TextSymbol>(); text->encoding() = TextSymbol::ENCODING_UTF8; } text->content()->setLiteral( name ); } // is there an icon? if ( icon ) { iconNode = new PlaceNode( cx._mapNode, position, style, cx._dbOptions ); } else if ( !model && text && !name.empty() ) { // note: models do not get labels. iconNode = new LabelNode( cx._mapNode, position, style ); } } // multiple coords? feature: if ( geom->getTotalPointCount() > 1 ) { ExtrusionSymbol* extruded = style.get<ExtrusionSymbol>(); // Remove symbols that we have already processed so the geometry // compiler doesn't get confused. if ( model ) style.removeSymbol( model ); if ( icon ) style.removeSymbol( icon ); if ( text ) style.removeSymbol( text ); Feature* feature = new Feature(geom, cx._srs.get(), style); featureNode = new FeatureNode( cx._mapNode, feature ); } // assemble the results: if ( (iconNode || modelNode) && featureNode ) { osg::Group* group = new osg::Group(); group->addChild( featureNode ); if ( iconNode ) group->addChild( iconNode ); if ( modelNode ) group->addChild( modelNode ); cx._groupStack.top()->addChild( group ); if ( iconNode && cx._options->declutter() == true ) { Decluttering::setEnabled( iconNode->getOrCreateStateSet(), true ); } if ( iconNode ) KML_Feature::build( node, cx, iconNode ); if ( modelNode ) KML_Feature::build( node, cx, modelNode ); if ( featureNode ) KML_Feature::build( node, cx, featureNode ); } else { if ( iconNode ) { if ( cx._options->iconAndLabelGroup().valid() ) { cx._options->iconAndLabelGroup()->addChild( iconNode ); } else { cx._groupStack.top()->addChild( iconNode ); if ( cx._options->declutter() == true ) { Decluttering::setEnabled( iconNode->getOrCreateStateSet(), true ); } } KML_Feature::build( node, cx, iconNode ); } if ( modelNode ) { cx._groupStack.top()->addChild( modelNode ); KML_Feature::build( node, cx, modelNode ); } if ( featureNode ) { cx._groupStack.top()->addChild( featureNode ); KML_Feature::build( node, cx, featureNode ); } } } } } }
int main(int argc, char** argv) { osg::ArgumentParser arguments(&argc,argv); if ( arguments.read("--help") ) return usage(argv[0]); // general setup: osgViewer::Viewer viewer(arguments); viewer.getDatabasePager()->setUnrefImageDataAfterApplyPolicy( false, false ); viewer.setCameraManipulator( new EarthManipulator(arguments) ); viewer.getCamera()->setSmallFeatureCullingPixelSize(-1.0f); viewer.getCamera()->setNearFarRatio(0.00002); // load an earth file, and support all or our example command-line options // and earth file <external> tags osg::Node* node = MapNodeHelper().load( arguments, &viewer ); if ( node ) { MapNode* mapNode = MapNode::get(node); if ( !mapNode ) return usage(argv[0]); // Create the WFS driver: osgEarth::Drivers::WFSFeatureOptions wfs; wfs.url() = osgEarth::URI("http://demo.opengeo.org/geoserver/wfs"); wfs.typeName() = "states"; wfs.outputFormat() = "json"; // JSON or GML // Configure a rendering style: Style style; style.setName( "states" ); LineSymbol* line = style.getOrCreate<LineSymbol>(); line->stroke()->color() = Color::Yellow; line->stroke()->width() = 5.0f; line->stroke()->widthUnits() = Units::PIXELS; AltitudeSymbol* alt = style.getOrCreate<AltitudeSymbol>(); alt->clamping() = AltitudeSymbol::CLAMP_TO_TERRAIN; alt->technique() = AltitudeSymbol::TECHNIQUE_DRAPE; // Configure a model layer to render the features: osgEarth::Drivers::FeatureGeomModelOptions geom; geom.featureOptions() = wfs; geom.styles() = new StyleSheet(); geom.styles()->addStyle(style); // Make the new layer and add it to the map. ModelLayerOptions layerOptions("states", geom); ModelLayer* layer = new ModelLayer(layerOptions); mapNode->getMap()->addModelLayer(layer); viewer.setSceneData( node ); return viewer.run(); } else { return usage(argv[0]); } }
void KML_Geometry::parseStyle( xml_node<>* node, KMLContext& cx, Style& style ) { _extrude = getValue(node, "extrude") == "1"; _tessellate = getValue(node, "tessellate") == "1"; std::string am = getValue(node, "altitudemode"); if ( am.empty() ) am = "clampToGround"; // default. bool isPoly = _geom.valid() && _geom->getComponentType() == Geometry::TYPE_POLYGON; bool isLine = _geom.valid() && _geom->getComponentType() == Geometry::TYPE_LINESTRING; // Resolve the correct altitude symbol. CLAMP_TO_TERRAIN is the default, but the // technique will depend on the geometry's type and setup. AltitudeSymbol* alt = style.getOrCreate<AltitudeSymbol>(); alt->clamping() = alt->CLAMP_TO_TERRAIN; // Compute some info about the geometry // Are all of the elevations zero? bool zeroElev = true; // Are all of the the elevations the same? bool sameElev = true; double maxElevation = -DBL_MAX; //if ( isPoly ) //compute maxElevation also for line strings for extrusion height { bool first = true; double e = 0.0; ConstGeometryIterator gi( _geom.get(), false ); while(gi.hasMore() ) { const Geometry* g = gi.next(); for( Geometry::const_iterator ji = g->begin(); ji != g->end(); ++ji ) { if ( !osg::equivalent(ji->z(), 0.0) ) zeroElev = false; if (first) { first = false; e = ji->z(); } else { if (!osg::equivalent(e, ji->z())) { sameElev = false; } } if (ji->z() > maxElevation) maxElevation = ji->z(); } } } // clamp to ground mode: if ( am == "clampToGround" ) { if ( _extrude ) { alt->technique() = alt->TECHNIQUE_MAP; } else if ( isPoly ) { alt->technique() = alt->TECHNIQUE_DRAPE; } else if ( isLine) { alt->technique() = alt->TECHNIQUE_DRAPE; // or could be GPU. } else // line or point { alt->technique() = alt->TECHNIQUE_SCENE; } // extrusion is not compatible with clampToGround. _extrude = false; } // "relativeToGround" means the coordinates' Z values are relative to the Z of the // terrain at that point. NOTE: GE flattens rooftops in this mode when extrude=1, // which seems wrong.. else if ( am == "relativeToGround" ) { alt->clamping() = alt->CLAMP_RELATIVE_TO_TERRAIN; if (isPoly) { // If all of the verts have the same elevation then assume that it should be clamped at the centroid and not per vertex. if (sameElev) { alt->binding() = AltitudeSymbol::BINDING_CENTROID; } if ( _extrude ) { alt->technique() = alt->TECHNIQUE_MAP; } else { alt->technique() = alt->TECHNIQUE_SCENE; if ( zeroElev ) { alt->clamping() = alt->CLAMP_TO_TERRAIN; alt->technique() = alt->TECHNIQUE_DRAPE; } } } } // "absolute" means to treat the Z values as-is else if ( am == "absolute" ) { alt->clamping() = AltitudeSymbol::CLAMP_NONE; } if ( _extrude ) { ExtrusionSymbol* es = style.getOrCreate<ExtrusionSymbol>(); es->flatten() = false; if (*alt->clamping() == AltitudeSymbol::CLAMP_NONE) { // Set the height to the max elevation + the approx depth of the mariana trench so that it will extend low enough to be always go to the surface of the earth. // This lets us avoid clamping absolute absolute extruded polygons completely. es->height() = -(maxElevation + 11100.0); } } else { // remove polystyle since it doesn't apply to non-extruded lines and points if ( !isPoly ) { style.remove<PolygonSymbol>(); } } }
bool SLDReader::readStyleFromCSSParams( const Config& conf, Style& sc ) { sc.setName( conf.key() ); LineSymbol* line = 0L; PolygonSymbol* polygon = 0L; PointSymbol* point = 0L; TextSymbol* text = 0L; ExtrusionSymbol* extrusion = 0L; MarkerSymbol* marker = 0L; AltitudeSymbol* altitude = 0L; for(Properties::const_iterator p = conf.attrs().begin(); p != conf.attrs().end(); p++ ) { if ( p->first == CSS_STROKE ) { if (!line) line = sc.getOrCreateSymbol<LineSymbol>(); line->stroke()->color() = htmlColorToVec4f( p->second ); } else if ( p->first == CSS_STROKE_OPACITY ) { if (!line) line = sc.getOrCreateSymbol<LineSymbol>(); line->stroke()->color().a() = as<float>( p->second, 1.0f ); } else if ( p->first == CSS_STROKE_WIDTH ) { if (!line) line = sc.getOrCreateSymbol<LineSymbol>(); line->stroke()->width() = as<float>( p->second, 1.0f ); } else if ( p->first == CSS_STROKE_LINECAP ) { if (!line) line = sc.getOrCreateSymbol<LineSymbol>(); parseLineCap( p->second, line->stroke()->lineCap() ); } else if ( p->first == CSS_FILL ) { if (!polygon) polygon = sc.getOrCreateSymbol<PolygonSymbol>(); polygon->fill()->color() = htmlColorToVec4f( p->second ); if ( !point ) point = sc.getOrCreateSymbol<PointSymbol>(); point->fill()->color() = htmlColorToVec4f( p->second ); if ( !text ) text = new TextSymbol(); text->fill()->color() = htmlColorToVec4f( p->second ); } else if ( p->first == CSS_FILL_OPACITY ) { if (!polygon) polygon = sc.getOrCreateSymbol<PolygonSymbol>(); polygon->fill()->color().a() = as<float>( p->second, 1.0f ); if (!polygon) polygon = sc.getOrCreateSymbol<PolygonSymbol>(); point->fill()->color().a() = as<float>( p->second, 1.0f ); if (!text) text = sc.getOrCreateSymbol<TextSymbol>(); text->fill()->color().a() = as<float>( p->second, 1.0f ); } else if (p->first == CSS_POINT_SIZE) { if ( !point ) point = sc.getOrCreateSymbol<PointSymbol>(); point->size() = as<float>(p->second, 1.0f); } else if (p->first == CSS_TEXT_SIZE) { if (!text) text = sc.getOrCreateSymbol<TextSymbol>(); text->size() = as<float>(p->second, 32.0f); } else if (p->first == CSS_TEXT_FONT) { if (!text) text = sc.getOrCreateSymbol<TextSymbol>(); text->font() = p->second; } else if (p->first == CSS_TEXT_HALO) { if (!text) text = sc.getOrCreateSymbol<TextSymbol>(); text->halo()->color() = htmlColorToVec4f( p->second ); } //else if (p->first == CSS_TEXT_ATTRIBUTE) //{ // if (!text) text = sc.getOrCreateSymbol<TextSymbol>(); // text->attribute() = p->second; //} else if (p->first == CSS_TEXT_ROTATE_TO_SCREEN) { if (!text) text = sc.getOrCreateSymbol<TextSymbol>(); if (p->second == "true") text->rotateToScreen() = true; else if (p->second == "false") text->rotateToScreen() = false; } else if (p->first == CSS_TEXT_SIZE_MODE) { if (!text) text = sc.getOrCreateSymbol<TextSymbol>(); if (p->second == "screen") text->sizeMode() = TextSymbol::SIZEMODE_SCREEN; else if (p->second == "object") text->sizeMode() = TextSymbol::SIZEMODE_OBJECT; } else if (p->first == CSS_TEXT_REMOVE_DUPLICATE_LABELS) { if (!text) text = sc.getOrCreateSymbol<TextSymbol>(); if (p->second == "true") text->removeDuplicateLabels() = true; else if (p->second == "false") text->removeDuplicateLabels() = false; } else if (p->first == CSS_TEXT_LINE_ORIENTATION) { if (!text) text = sc.getOrCreateSymbol<TextSymbol>(); if (p->second == "parallel") text->lineOrientation() = TextSymbol::LINEORIENTATION_PARALLEL; else if (p->second == "horizontal") text->lineOrientation() = TextSymbol::LINEORIENTATION_HORIZONTAL; else if (p->second == "perpendicular") text->lineOrientation() = TextSymbol::LINEORIENTATION_PERPENDICULAR; } else if (p->first == CSS_TEXT_LINE_PLACEMENT) { if (!text) text = sc.getOrCreateSymbol<TextSymbol>(); if (p->second == "centroid") text->linePlacement() = TextSymbol::LINEPLACEMENT_CENTROID; else if (p->second == "along-line") text->linePlacement() = TextSymbol::LINEPLACEMENT_ALONG_LINE; } else if (p->first == "text-content") { if (!text) text = sc.getOrCreate<TextSymbol>(); text->content() = StringExpression( p->second ); } else if (p->first == "text-priority") { if (!text) text = sc.getOrCreateSymbol<TextSymbol>(); text->priority() = NumericExpression( p->second ); } else if (p->first == "text-provider") { if (!text) text = sc.getOrCreate<TextSymbol>(); text->provider() = p->second; } //else if (p->first == CSS_TEXT_CONTENT) //{ // if (!text) text = sc.getOrCreateSymbol<TextSymbol>(); // text->content() = p->second; //} //else if (p->first == CSS_TEXT_CONTENT_ATTRIBUTE_DELIMITER) //{ // if (!text) text = sc.getOrCreateSymbol<TextSymbol>(); // text->contentAttributeDelimiter() = p->second; //} else if (p->first == "marker") { if (!marker) marker = sc.getOrCreateSymbol<MarkerSymbol>(); marker->url() = p->second; } else if (p->first == "marker-placement") { if (!marker) marker = sc.getOrCreateSymbol<MarkerSymbol>(); if (p->second == "centroid") marker->placement() = MarkerSymbol::PLACEMENT_CENTROID; else if (p->second == "interval") marker->placement() = MarkerSymbol::PLACEMENT_INTERVAL; else if (p->second == "random" ) marker->placement() = MarkerSymbol::PLACEMENT_RANDOM; } else if (p->first == "marker-density") { if (!marker) marker = sc.getOrCreateSymbol<MarkerSymbol>(); marker->density() = as<float>(p->second, 1.0f); } else if (p->first == "marker-random-seed") { if (!marker) marker = sc.getOrCreateSymbol<MarkerSymbol>(); marker->randomSeed() = as<unsigned>(p->second, 0); } else if (p->first == "marker-scale") { if (!marker) marker = sc.getOrCreateSymbol<MarkerSymbol>(); marker->scale() = stringToVec3f(p->second, osg::Vec3f(1,1,1)); } else if (p->first == "extrusion-height") { if (!extrusion) extrusion = sc.getOrCreateSymbol<ExtrusionSymbol>(); extrusion->heightExpression() = NumericExpression(p->second); } else if (p->first == "extrusion-flatten") { if (!extrusion) extrusion = sc.getOrCreateSymbol<ExtrusionSymbol>(); extrusion->flatten() = as<bool>(p->second, true); } else if (p->first == "altitude-clamping") { if (!altitude) altitude = sc.getOrCreateSymbol<AltitudeSymbol>(); if (p->second == "none" ) altitude->clamping() = AltitudeSymbol::CLAMP_NONE; else if (p->second == "terrain" ) altitude->clamping() = AltitudeSymbol::CLAMP_TO_TERRAIN; else if (p->second == "relative") altitude->clamping() = AltitudeSymbol::CLAMP_RELATIVE_TO_TERRAIN; } else if (p->first == "altitude-offset") { if (!altitude) altitude = sc.getOrCreateSymbol<AltitudeSymbol>(); altitude->verticalOffset() = as<float>( p->second, 0.0f ); } } #if 0 if (line) sc.addSymbol(line); if (polygon) sc.addSymbol(polygon); if (point) sc.addSymbol(point); if (text) sc.addSymbol(text); if (extrusion) sc.addSymbol(extrusion); if (marker) sc.addSymbol(marker); if (altitude) sc.addSymbol(altitude); #endif return true; }
void KML_Placemark::build( xml_node<>* node, KMLContext& cx ) { Style masterStyle; std::string styleUrl = getValue(node, "styleurl"); if (!styleUrl.empty()) { // process a "stylesheet" style const Style* ref_style = cx._sheet->getStyle( styleUrl, false ); if (ref_style) { masterStyle = masterStyle.combineWith(*ref_style); } } xml_node<>* style = node->first_node("style", 0, false); if ( style ) { // process an "inline" style KML_Style kmlStyle; kmlStyle.scan(style, cx); masterStyle = masterStyle.combineWith(cx._activeStyle); } // parse the geometry. the placemark must have geometry to be valid. The // geometry parse may optionally specify an altitude mode as well. KML_Geometry geometry; geometry.build(node, cx, masterStyle); Geometry* allGeom = geometry._geom.get(); if ( allGeom ) { GeometryIterator giter( allGeom, false ); while( giter.hasMore() ) { Geometry* geom = giter.next(); Style style = masterStyle; AltitudeSymbol* alt = style.get<AltitudeSymbol>(); if ( geom && geom->getTotalPointCount() > 0 ) { // resolve the proper altitude mode for the anchor point AltitudeMode altMode = ALTMODE_RELATIVE; if (alt && !alt->clamping().isSetTo( alt->CLAMP_TO_TERRAIN ) && !alt->clamping().isSetTo( alt->CLAMP_RELATIVE_TO_TERRAIN ) ) { altMode = ALTMODE_ABSOLUTE; } GeoPoint position(cx._srs.get(), geom->getBounds().center(), altMode); // check for symbols. ModelSymbol* model = style.get<ModelSymbol>(); IconSymbol* icon = style.get<IconSymbol>(); TextSymbol* text = style.get<TextSymbol>(); // for a single point placemark, apply the default icon and text symbols // if none are specified in the KML. if (geom->getTotalPointCount() == 1) { if (!model && !icon && cx._options->defaultIconSymbol().valid()) { icon = cx._options->defaultIconSymbol().get(); style.add(icon); } if (!text && cx._options->defaultTextSymbol().valid()) { text = cx._options->defaultTextSymbol().get(); style.add(text); } } // the annotation name: std::string name = getValue(node, "name"); if (!name.empty()) { OE_INFO << LC << "Placemark: " << name << std::endl; } AnnotationNode* featureNode = 0L; AnnotationNode* iconNode = 0L; AnnotationNode* modelNode = 0L; // one coordinate? It's a place marker or a label. if ( (model || icon || text) && geom->getTotalPointCount() == 1 ) { // if there's a model, render that - models do NOT get labels. if ( model ) { ModelNode* node = new ModelNode( cx._mapNode, style, cx._dbOptions.get() ); node->setPosition( position ); // model scale: if ( cx._options->modelScale() != 1.0f ) { float s = *cx._options->modelScale(); node->getPositionAttitudeTransform()->setScale(osg::Vec3d(s,s,s)); } // model local tangent plane rotation: if ( !cx._options->modelRotation()->zeroRotation() ) { node->getPositionAttitudeTransform()->setAttitude( *cx._options->modelRotation() ); } modelNode = node; } // is there a label? else if ( !name.empty() ) { if ( !text ) { text = style.getOrCreate<TextSymbol>(); text->encoding() = TextSymbol::ENCODING_UTF8; } text->content()->setLiteral( name ); } // is there an icon? if ( icon ) { PlaceNode* placeNode = new PlaceNode( position ); placeNode->setStyle(style, cx._dbOptions.get()); iconNode = placeNode; } else if ( !model && text && !name.empty() ) { // note: models do not get labels. iconNode = new LabelNode(); iconNode->setStyle(style); } } // multiple coords? feature: if ( geom->getTotalPointCount() > 1 ) { // Remove symbols that we have already processed so the geometry // compiler doesn't get confused. if ( model ) style.removeSymbol( model ); if ( icon ) style.removeSymbol( icon ); if ( text ) style.removeSymbol( text ); Feature* feature = new Feature(geom, cx._srs.get(), style); featureNode = new FeatureNode(feature ); featureNode->setMapNode( cx._mapNode ); } if ( iconNode ) { Registry::objectIndex()->tagNode( iconNode, iconNode ); } if ( modelNode ) { Registry::objectIndex()->tagNode( modelNode, modelNode ); } if ( featureNode ) { Registry::objectIndex()->tagNode( featureNode, featureNode ); } // assemble the results: if ( (iconNode || modelNode) && featureNode ) { osg::Group* group = new osg::Group(); group->addChild( featureNode ); if ( iconNode ) group->addChild( iconNode ); if ( modelNode ) group->addChild( modelNode ); cx._groupStack.top()->addChild( group ); if ( iconNode ) KML_Feature::build( node, cx, iconNode ); if ( modelNode ) KML_Feature::build( node, cx, modelNode ); if ( featureNode ) KML_Feature::build( node, cx, featureNode ); } else { if ( iconNode ) { if ( cx._options->iconAndLabelGroup().valid() ) { cx._options->iconAndLabelGroup()->addChild( iconNode ); } else { cx._groupStack.top()->addChild( iconNode ); } KML_Feature::build( node, cx, iconNode ); } if ( modelNode ) { cx._groupStack.top()->addChild( modelNode ); KML_Feature::build( node, cx, modelNode ); } if ( featureNode ) { osg::Node* child = featureNode; // If this feature node is map-clamped, we most likely need a depth-offset // shader to prevent z-fighting with the terrain. if (alt && alt->clamping() == alt->CLAMP_TO_TERRAIN && alt->technique() == alt->TECHNIQUE_MAP) { DepthOffsetGroup* g = new DepthOffsetGroup(); g->addChild( featureNode ); child = g; } cx._groupStack.top()->addChild( child ); KML_Feature::build( node, cx, featureNode ); } } } } } }
void KML_Placemark::build( const Config& conf, KMLContext& cx ) { Style style; if ( conf.hasValue("styleurl") ) { // process a "stylesheet" style const Style* ref_style = cx._sheet->getStyle( conf.value("styleurl"), false ); if ( ref_style ) style = *ref_style; } else if ( conf.hasChild("style") ) { // process an "inline" style KML_Style kmlStyle; kmlStyle.scan( conf.child("style"), cx ); style = cx._activeStyle; } // parse the geometry. the placemark must have geometry to be valid. The // geometry parse may optionally specify an altitude mode as well. KML_Geometry geometry; geometry.build(conf, cx, style); // KML's default altitude mode is clampToGround. AltitudeMode altMode = ALTMODE_RELATIVE; AltitudeSymbol* altSym = style.get<AltitudeSymbol>(); if ( !altSym ) { altSym = style.getOrCreate<AltitudeSymbol>(); altSym->clamping() = AltitudeSymbol::CLAMP_RELATIVE_TO_TERRAIN; } else if ( !altSym->clamping().isSetTo(AltitudeSymbol::CLAMP_RELATIVE_TO_TERRAIN) ) { altMode = ALTMODE_ABSOLUTE; } if ( geometry._geom.valid() && geometry._geom->getTotalPointCount() > 0 ) { Geometry* geom = geometry._geom.get(); GeoPoint position(cx._srs.get(), geom->getBounds().center(), altMode); bool isPoly = geom->getComponentType() == Geometry::TYPE_POLYGON; bool isPoint = geom->getComponentType() == Geometry::TYPE_POINTSET; // read in the Marker if there is one. URI markerURI; osg::ref_ptr<osg::Image> markerImage; osg::ref_ptr<osg::Node> markerModel; MarkerSymbol* marker = style.get<MarkerSymbol>(); if ( marker && marker->url().isSet() ) { if ( marker->isModel() == false ) { markerImage = marker->getImage( *cx._options->iconMaxSize() ); } else { markerURI = URI( marker->url()->eval(), marker->url()->uriContext() ); markerModel = markerURI.getNode(); // We can't leave the marker symbol in the style, or the GeometryCompiler will // think we want to do Point-model substitution. So remove it. A bit of a hack if ( marker ) style.removeSymbol(marker); } } std::string text = conf.hasValue("name") ? conf.value("name") : ""; AnnotationNode* fNode = 0L; AnnotationNode* pNode = 0L; // place a 3D model: if ( markerModel.valid() ) { LocalGeometryNode* lg = new LocalGeometryNode(cx._mapNode, markerModel.get(), style, false); lg->setPosition( position ); if ( marker ) { if ( marker->scale().isSet() ) { float scale = marker->scale()->eval(); lg->setScale( osg::Vec3f(scale,scale,scale) ); } if ( marker->orientation().isSet() ) { // lg->setRotation( ); } } fNode = lg; //Feature* feature = new Feature(geometry._geom.get(), cx._srs.get(), style); //fNode = new FeatureNode( cx._mapNode, feature, false ); } // Place node (icon + text) or Label node (text only) else if ( marker || geometry._geom->getTotalPointCount() == 1 ) { if ( !markerImage.valid() ) { markerImage = cx._options->defaultIconImage().get(); if ( !markerImage.valid() ) { markerImage = cx._options->defaultIconURI()->getImage(); } } if ( !style.get<TextSymbol>() && cx._options->defaultTextSymbol().valid() ) { style.addSymbol( cx._options->defaultTextSymbol().get() ); } if ( markerImage.valid() ) pNode = new PlaceNode( cx._mapNode, position, markerImage.get(), text, style ); else pNode = new LabelNode( cx._mapNode, position, text, style ); } if ( geometry._geom->getTotalPointCount() > 1 ) { const ExtrusionSymbol* ex = style.get<ExtrusionSymbol>(); const AltitudeSymbol* alt = style.get<AltitudeSymbol>(); if ( style.get<MarkerSymbol>() ) style.removeSymbol(style.get<MarkerSymbol>()); bool draped = isPoly && ex == 0L && (alt == 0L || alt->clamping() == AltitudeSymbol::CLAMP_TO_TERRAIN); // Make a feature node; drape if we're not extruding. GeometryCompilerOptions options; options.clustering() = false; Feature* feature = new Feature(geometry._geom.get(), cx._srs.get(), style); fNode = new FeatureNode( cx._mapNode, feature, draped, options ); if ( !ex ) { fNode->getOrCreateStateSet()->setMode(GL_LIGHTING, 0); } } if ( pNode && fNode ) { osg::Group* group = new osg::Group(); group->addChild( fNode ); group->addChild( pNode ); cx._groupStack.top()->addChild( group ); if ( cx._options->declutter() == true ) Decluttering::setEnabled( pNode->getOrCreateStateSet(), true ); KML_Feature::build( conf, cx, pNode ); KML_Feature::build( conf, cx, fNode ); } else if ( pNode ) { if ( cx._options->iconAndLabelGroup().valid() ) { cx._options->iconAndLabelGroup()->addChild( pNode ); } else { cx._groupStack.top()->addChild( pNode ); if ( cx._options->declutter() == true ) Decluttering::setEnabled( pNode->getOrCreateStateSet(), true ); } KML_Feature::build( conf, cx, pNode ); } else if ( fNode ) { cx._groupStack.top()->addChild( fNode ); KML_Feature::build( conf, cx, fNode ); } } }
void GeodeticGraticule::rebuild() { this->removeChildren( 0, this->getNumChildren() ); if ( !getMapNode() ) { OE_WARN << LC << "Illegal NULL map node" << std::endl; return; } if ( !getMapNode()->isGeocentric() ) { OE_WARN << LC << "Projected map mode is not yet supported" << std::endl; return; } const Profile* mapProfile = _mapNode->getMap()->getProfile(); _profile = Profile::create( mapProfile->getSRS(), mapProfile->getExtent().xMin(), mapProfile->getExtent().yMin(), mapProfile->getExtent().xMax(), mapProfile->getExtent().yMax(), 8, 4 ); _featureProfile = new FeatureProfile(_profile->getSRS()); //todo: do this right.. osg::StateSet* set = this->getOrCreateStateSet(); set->setRenderBinDetails( 9999, "RenderBin" ); set->setMode( GL_LIGHTING, 0 ); // set up default options if the caller did not supply them if ( !_options.isSet() ) { _options->lineStyle() = Style(); LineSymbol* line = _options->lineStyle()->getOrCreate<LineSymbol>(); line->stroke()->color() = Color::Gray; line->stroke()->width() = 1.0; AltitudeSymbol* alt = _options->lineStyle()->getOrCreate<AltitudeSymbol>(); alt->verticalOffset() = NumericExpression(5000.0); _options->textStyle() = Style(); TextSymbol* text = _options->textStyle()->getOrCreate<TextSymbol>(); text->alignment() = TextSymbol::ALIGN_CENTER_CENTER; if ( _mapNode->isGeocentric() ) { double r = _mapNode->getMapSRS()->getEllipsoid()->getRadiusEquator(); _options->addLevel( FLT_MAX, 0.0f, 1u ); double d = 4.5*r; for(int i=0; i<3; i++) { d *= 0.5; _options->addLevel( d, d*0.25 ); } } else { //todo? } } _root = new DrapeableNode( _mapNode.get(), false ); this->addChild( _root ); // need at least one level if ( _options->levels().size() < 1 ) return; const GeodeticGraticuleOptions::Level& level0 = _options->levels()[0]; // build the top level cell grid. unsigned tilesX, tilesY; _profile->getNumTiles( 0, tilesX, tilesY ); for( unsigned tx = 0; tx < tilesX; ++tx ) { for( unsigned ty = 0; ty < tilesY; ++ty ) { TileKey key( 0, tx, ty, _profile.get() ); osg::Node* tile = buildTile( key, getMapNode()->getMap() ); if ( tile ) _root->addChild( tile ); } } }
void KML_Placemark::build( const Config& conf, KMLContext& cx ) { Style masterStyle; if ( conf.hasValue("styleurl") ) { // process a "stylesheet" style const Style* ref_style = cx._sheet->getStyle( conf.value("styleurl"), false ); if ( ref_style ) masterStyle = *ref_style; } else if ( conf.hasChild("style") ) { // process an "inline" style KML_Style kmlStyle; kmlStyle.scan( conf.child("style"), cx ); masterStyle = cx._activeStyle; } // parse the geometry. the placemark must have geometry to be valid. The // geometry parse may optionally specify an altitude mode as well. KML_Geometry geometry; geometry.build(conf, cx, masterStyle); Geometry* allGeom = geometry._geom.get(); if ( allGeom ) { GeometryIterator giter( allGeom, false ); while( giter.hasMore() ) { Geometry* geom = giter.next(); Style style = masterStyle; // KML's default altitude mode is clampToGround. AltitudeMode altMode = ALTMODE_RELATIVE; AltitudeSymbol* altSym = style.get<AltitudeSymbol>(); if ( !altSym ) { altSym = style.getOrCreate<AltitudeSymbol>(); altSym->clamping() = AltitudeSymbol::CLAMP_RELATIVE_TO_TERRAIN; altSym->technique() = AltitudeSymbol::TECHNIQUE_SCENE; } else if ( !altSym->clamping().isSetTo(AltitudeSymbol::CLAMP_RELATIVE_TO_TERRAIN) ) { altMode = ALTMODE_ABSOLUTE; } if ( geom && geom->getTotalPointCount() > 0 ) { GeoPoint position(cx._srs.get(), geom->getBounds().center(), altMode); bool isPoly = geom->getComponentType() == Geometry::TYPE_POLYGON; bool isPoint = geom->getComponentType() == Geometry::TYPE_POINTSET; // check for symbols. ModelSymbol* model = style.get<ModelSymbol>(); IconSymbol* icon = style.get<IconSymbol>(); TextSymbol* text = style.get<TextSymbol>(); if ( !text && cx._options->defaultTextSymbol().valid() ) text = cx._options->defaultTextSymbol().get(); // the annotation name: std::string name = conf.hasValue("name") ? conf.value("name") : ""; if ( text && !name.empty() ) { text->content()->setLiteral( name ); } AnnotationNode* featureNode = 0L; AnnotationNode* iconNode = 0L; AnnotationNode* modelNode = 0L; // one coordinate? It's a place marker or a label. if ( model || icon || text || geom->getTotalPointCount() == 1 ) { // load up the default icon if there we don't have one. if ( !model && !icon ) { icon = cx._options->defaultIconSymbol().get(); if ( icon ) style.add( icon ); } // if there's a model, render that - models do NOT get labels. if ( model ) { ModelNode* node = new ModelNode( cx._mapNode, style, cx._dbOptions ); node->setPosition( position ); if ( cx._options->modelScale() != 1.0f ) { float s = *cx._options->modelScale(); node->setScale( osg::Vec3f(s,s,s) ); } if ( !cx._options->modelRotation()->zeroRotation() ) { node->setLocalRotation( *cx._options->modelRotation() ); } modelNode = node; } else if ( !text && !name.empty() ) { text = style.getOrCreate<TextSymbol>(); text->content()->setLiteral( name ); } if ( icon ) { iconNode = new PlaceNode( cx._mapNode, position, style, cx._dbOptions ); } else if ( !model && text && !name.empty() ) { // note: models do not get labels. iconNode = new LabelNode( cx._mapNode, position, style ); } } // multiple coords? feature: if ( geom->getTotalPointCount() > 1 ) { ExtrusionSymbol* extruded = style.get<ExtrusionSymbol>(); AltitudeSymbol* altitude = style.get<AltitudeSymbol>(); // Remove symbols that we have already processed so the geometry // compiler doesn't get confused. if ( model ) style.removeSymbol( model ); if ( icon ) style.removeSymbol( icon ); if ( text ) style.removeSymbol( text ); // analyze the data; if the Z coords are all 0.0, enable draping. if ( /*isPoly &&*/ !extruded && altitude && altitude->clamping() != AltitudeSymbol::CLAMP_TO_TERRAIN ) { bool zeroElev = true; ConstGeometryIterator gi( geom, false ); while( zeroElev == true && gi.hasMore() ) { const Geometry* g = gi.next(); for( Geometry::const_iterator ji = g->begin(); ji != g->end() && zeroElev == true; ++ji ) { if ( !osg::equivalent(ji->z(), 0.0) ) zeroElev = false; } } if ( zeroElev ) { altitude->clamping() = AltitudeSymbol::CLAMP_TO_TERRAIN; altitude->technique() = AltitudeSymbol::TECHNIQUE_GPU; } } // Make a feature node; drape if we're not extruding. bool draped = isPoly && !extruded && (!altitude || altitude->clamping() == AltitudeSymbol::CLAMP_TO_TERRAIN); if ( draped && style.get<LineSymbol>() && !style.get<PolygonSymbol>() ) { draped = false; } // turn off the clamping if we're draping. if ( draped && altitude ) { altitude->technique() = AltitudeSymbol::TECHNIQUE_DRAPE; } GeometryCompilerOptions compilerOptions; // Check for point-model substitution: if ( style.has<ModelSymbol>() ) { compilerOptions.instancing() = true; } Feature* feature = new Feature(geom, cx._srs.get(), style); featureNode = new FeatureNode( cx._mapNode, feature, draped, compilerOptions ); } // assemble the results: if ( (iconNode || modelNode) && featureNode ) { osg::Group* group = new osg::Group(); group->addChild( featureNode ); if ( iconNode ) group->addChild( iconNode ); if ( modelNode ) group->addChild( modelNode ); cx._groupStack.top()->addChild( group ); if ( iconNode && cx._options->declutter() == true ) Decluttering::setEnabled( iconNode->getOrCreateStateSet(), true ); if ( iconNode ) KML_Feature::build( conf, cx, iconNode ); if ( modelNode ) KML_Feature::build( conf, cx, modelNode ); if ( featureNode ) KML_Feature::build( conf, cx, featureNode ); } else { if ( iconNode ) { if ( cx._options->iconAndLabelGroup().valid() ) { cx._options->iconAndLabelGroup()->addChild( iconNode ); } else { cx._groupStack.top()->addChild( iconNode ); if ( cx._options->declutter() == true ) Decluttering::setEnabled( iconNode->getOrCreateStateSet(), true ); } KML_Feature::build( conf, cx, iconNode ); } if ( modelNode ) { cx._groupStack.top()->addChild( modelNode ); KML_Feature::build( conf, cx, modelNode ); } if ( featureNode ) { cx._groupStack.top()->addChild( featureNode ); KML_Feature::build( conf, cx, featureNode ); } } } } } }