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 "KML_Geometry" 00020 #include "KML_Point" 00021 #include "KML_LineString" 00022 #include "KML_LinearRing" 00023 #include "KML_Polygon" 00024 #include "KML_MultiGeometry" 00025 #include "KML_Model" 00026 #include <osgEarth/StringUtils> 00027 00028 void 00029 KML_Geometry::build( const Config& parentConf, KMLContext& cx, Style& style) 00030 { 00031 const ConfigSet& children = parentConf.children(); 00032 for( ConfigSet::const_iterator i = children.begin(); i != children.end(); ++i ) 00033 { 00034 buildChild( *i, cx, style ); 00035 } 00036 } 00037 00038 void 00039 KML_Geometry::buildChild( const Config& conf, KMLContext& cx, Style& style) 00040 { 00041 if ( conf.key() == "point" ) 00042 { 00043 KML_Point g; 00044 g.parseStyle(conf, cx, style); 00045 g.parseCoords(conf, cx); 00046 _geom = g._geom.get(); 00047 } 00048 else if ( conf.key() == "linestring" ) 00049 { 00050 KML_LineString g; 00051 g.parseStyle(conf, cx, style); 00052 g.parseCoords(conf, cx); 00053 _geom = g._geom.get(); 00054 } 00055 else if ( conf.key() == "linearring" ) 00056 { 00057 KML_LinearRing g; 00058 g.parseStyle(conf, cx, style); 00059 g.parseCoords(conf, cx); 00060 _geom = g._geom.get(); 00061 } 00062 else if ( conf.key() == "polygon" || conf.key() == "gx:latlonquad" ) 00063 { 00064 KML_Polygon g; 00065 g.parseStyle(conf, cx, style); 00066 g.parseCoords(conf, cx); 00067 _geom = g._geom.get(); 00068 } 00069 else if ( conf.key() == "multigeometry" ) 00070 { 00071 KML_MultiGeometry g; 00072 g.parseStyle(conf, cx, style); 00073 g.parseCoords(conf, cx); 00074 const ConfigSet& mgChildren = conf.children(); 00075 00076 for( ConfigSet::const_iterator i = mgChildren.begin(); i != mgChildren.end(); ++i ) 00077 { 00078 const Config& mgChild = *i; 00079 Style subStyle = style; 00080 KML_Geometry subGeom; 00081 subGeom.parseStyle( mgChild, cx, subStyle ); 00082 subGeom.buildChild( mgChild, cx, style ); 00083 if ( subGeom._geom.valid() ) 00084 dynamic_cast<MultiGeometry*>(g._geom.get())->getComponents().push_back( subGeom._geom.get() ); 00085 } 00086 //g.parseCoords(conf.child("multigeometry"), cx); 00087 _geom = g._geom.get(); 00088 } 00089 else if ( conf.key() == "model" ) 00090 { 00091 KML_Model g; 00092 g.parseStyle(conf, cx, style); 00093 g.parseCoords(conf, cx); 00094 _geom = g._geom.get(); 00095 } 00096 } 00097 00098 void 00099 KML_Geometry::parseCoords( const Config& conf, KMLContext& cx ) 00100 { 00101 const Config& coords = conf.child("coordinates"); 00102 StringVector tuples; 00103 StringTokenizer( coords.value(), tuples, " ", "", false, true ); 00104 for( StringVector::const_iterator s=tuples.begin(); s != tuples.end(); ++s ) 00105 { 00106 StringVector parts; 00107 StringTokenizer( *s, parts, ",", "", false, true ); 00108 if ( parts.size() >= 2 ) 00109 { 00110 osg::Vec3d point; 00111 point.x() = as<double>( parts[0], 0.0 ); 00112 point.y() = as<double>( parts[1], 0.0 ); 00113 if ( parts.size() >= 3 ) { 00114 point.z() = as<double>( parts[2], 0.0 ); 00115 } 00116 _geom->push_back(point); 00117 } 00118 } 00119 } 00120 00121 void 00122 KML_Geometry::parseStyle( const Config& conf, KMLContext& cx, Style& style ) 00123 { 00124 _extrude = conf.value("extrude") == "1"; 00125 _tessellate = conf.value("tessellate") == "1"; 00126 00127 std::string am = conf.value("altitudemode"); 00128 00129 // clampToGround is the default. We will be draping the geometry UNLESS tessellate is 00130 // set to true. 00131 if ( (am.empty() || am == "clampToGround") && _tessellate ) 00132 { 00133 AltitudeSymbol* af = style.getOrCreate<AltitudeSymbol>(); 00134 af->clamping() = AltitudeSymbol::CLAMP_TO_TERRAIN; 00135 _extrude = false; 00136 } 00137 00138 // "relativeToGround" means the coordinates' Z values are relative to the Z of the 00139 // terrain at that point. NOTE: GE flattens rooftops in this mode when extrude=1, 00140 // which seems wrong.. 00141 else if ( am == "relativeToGround" ) 00142 { 00143 AltitudeSymbol* af = style.getOrCreate<AltitudeSymbol>(); 00144 af->clamping() = AltitudeSymbol::CLAMP_RELATIVE_TO_TERRAIN; 00145 } 00146 00147 // "absolute" means to treat the Z values as-is 00148 else if ( am == "absolute" ) 00149 { 00150 AltitudeSymbol* af = style.getOrCreate<AltitudeSymbol>(); 00151 af->clamping() = AltitudeSymbol::CLAMP_ABSOLUTE; 00152 } 00153 00154 if ( _extrude ) 00155 { 00156 ExtrusionSymbol* es = style.getOrCreate<ExtrusionSymbol>(); 00157 es->flatten() = false; 00158 } 00159 }