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>(); } } }