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 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; }
/** * This code example effectively duplicates the "boston.earth" sample, * demonstrating how to create a 3D city model in osgEarth. * * Run this from the tests folder. */ int main(int argc, char** argv) { osg::ArgumentParser arguments(&argc,argv); // create the map. Map* map = new Map(); // add a TMS imagery layer: TMSOptions imagery; imagery.url() = "http://readymap.org/readymap/tiles/1.0.0/22/"; map->addImageLayer( new ImageLayer("ReadyMap imagery", imagery) ); // create a feature source to load the building footprint shapefile. OGRFeatureOptions feature_opt; feature_opt.name() = "buildings"; feature_opt.url() = "../data/boston_buildings_utm19.shp"; feature_opt.buildSpatialIndex() = true; // a style for the building data: Style buildingStyle; buildingStyle.setName( "default" ); ExtrusionSymbol* extrusion = buildingStyle.getOrCreate<ExtrusionSymbol>(); extrusion->heightExpression() = NumericExpression( "3.5 * max( [story_ht_], 1 )" ); extrusion->flatten() = true; extrusion->wallStyleName() = "building-wall"; extrusion->roofStyleName() = "building-roof"; // a style for the wall textures: Style wallStyle; wallStyle.setName( "building-wall" ); SkinSymbol* wallSkin = wallStyle.getOrCreate<SkinSymbol>(); wallSkin->libraryName() = "us_resources"; wallSkin->addTag( "building" ); wallSkin->randomSeed() = 1; // a style for the rooftop textures: Style roofStyle; roofStyle.setName( "building-roof" ); SkinSymbol* roofSkin = roofStyle.getOrCreate<SkinSymbol>(); roofSkin->libraryName() = "us_resources"; roofSkin->addTag( "rooftop" ); roofSkin->randomSeed() = 1; roofSkin->isTiled() = true; // assemble a stylesheet and add our styles to it: StyleSheet* styleSheet = new StyleSheet(); styleSheet->addStyle( buildingStyle ); styleSheet->addStyle( wallStyle ); styleSheet->addStyle( roofStyle ); // load a resource library that contains the building textures. ResourceLibrary* reslib = new ResourceLibrary( "us_resources", "../data/resources/textures_us/catalog.xml" ); styleSheet->addResourceLibrary( reslib ); // set up a paging layout for incremental loading. FeatureDisplayLayout layout; layout.tileSizeFactor() = 45.0; layout.addLevel( FeatureLevel(0.0f, 20000.0f) ); // create a model layer that will render the buildings according to our style sheet. FeatureGeomModelOptions fgm_opt; fgm_opt.featureOptions() = feature_opt; fgm_opt.styles() = styleSheet; fgm_opt.layout() = layout; map->addModelLayer( new ModelLayer( "buildings", fgm_opt ) ); // initialize a viewer: osgViewer::Viewer viewer(arguments); EarthManipulator* manip = new EarthManipulator(); viewer.setCameraManipulator( manip ); // make the map scene graph: osg::Group* root = new osg::Group(); viewer.setSceneData( root ); MapNode* mapNode = new MapNode( map ); root->addChild( mapNode ); // Process cmdline args MapNodeHelper helper; helper.configureView( &viewer ); helper.parse(mapNode, arguments, &viewer, root, new LabelControl("City Demo")); // zoom to a good startup position manip->setViewpoint( Viewpoint(-71.0763, 42.34425, 0, 24.261, -21.6, 3450.0), 5.0 ); viewer.getDatabasePager()->setDoPreCompile( true ); viewer.getCamera()->addCullCallback( new AutoClipPlaneCullCallback(mapNode) ); return viewer.run(); }