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 #ifndef OSGEARTHFEATURES_FEATURE_OGR_UTILS 00020 #define OSGEARTHFEATURES_FEATURE_OGR_UTILS 1 00021 00022 #include <osgEarthFeatures/Feature> 00023 #include <osgEarthSymbology/Geometry> 00024 #include <osgEarth/StringUtils> 00025 #include <osg/Notify> 00026 #include <ogr_api.h> 00027 00028 using namespace osgEarth; 00029 using namespace osgEarth::Features; 00030 using namespace osgEarth::Symbology; 00031 00032 struct OgrUtils 00033 { 00034 static void 00035 populate( OGRGeometryH geomHandle, Symbology::Geometry* target, int numPoints ) 00036 { 00037 for( int v = numPoints-1; v >= 0; v-- ) // reverse winding.. we like ccw 00038 { 00039 double x=0, y=0, z=0; 00040 OGR_G_GetPoint( geomHandle, v, &x, &y, &z ); 00041 osg::Vec3d p( x, y, z ); 00042 if ( target->size() == 0 || p != target->back() ) // remove dupes 00043 target->push_back( p ); 00044 } 00045 } 00046 00047 static Symbology::Polygon* 00048 createPolygon( OGRGeometryH geomHandle ) 00049 { 00050 Symbology::Polygon* output = 0L; 00051 00052 int numParts = OGR_G_GetGeometryCount( geomHandle ); 00053 if ( numParts == 0 ) 00054 { 00055 int numPoints = OGR_G_GetPointCount( geomHandle ); 00056 output = new Symbology::Polygon( numPoints ); 00057 populate( geomHandle, output, numPoints ); 00058 output->open(); 00059 } 00060 else if ( numParts > 0 ) 00061 { 00062 for( int p = 0; p < numParts; p++ ) 00063 { 00064 OGRGeometryH partRef = OGR_G_GetGeometryRef( geomHandle, p ); 00065 int numPoints = OGR_G_GetPointCount( partRef ); 00066 if ( p == 0 ) 00067 { 00068 output = new Symbology::Polygon( numPoints ); 00069 populate( partRef, output, numPoints ); 00070 //output->open(); 00071 output->rewind( Symbology::Ring::ORIENTATION_CCW ); 00072 } 00073 else 00074 { 00075 Symbology::Ring* hole = new Symbology::Ring( numPoints ); 00076 populate( partRef, hole, numPoints ); 00077 //hole->open(); 00078 hole->rewind( Symbology::Ring::ORIENTATION_CW ); 00079 output->getHoles().push_back( hole ); 00080 } 00081 } 00082 } 00083 return output; 00084 } 00085 00086 static Symbology::Geometry* 00087 createGeometry( OGRGeometryH geomHandle ) 00088 { 00089 Symbology::Geometry* output = 0L; 00090 00091 OGRwkbGeometryType wkbType = OGR_G_GetGeometryType( geomHandle ); 00092 00093 if ( 00094 wkbType == wkbPolygon || 00095 wkbType == wkbPolygon25D ) 00096 { 00097 output = createPolygon( geomHandle ); 00098 } 00099 else if ( 00100 wkbType == wkbLineString || 00101 wkbType == wkbLineString25D ) 00102 { 00103 int numPoints = OGR_G_GetPointCount( geomHandle ); 00104 output = new Symbology::LineString( numPoints ); 00105 populate( geomHandle, output, numPoints ); 00106 } 00107 else if ( 00108 wkbType == wkbLinearRing ) 00109 { 00110 int numPoints = OGR_G_GetPointCount( geomHandle ); 00111 output = new Symbology::Ring( numPoints ); 00112 populate( geomHandle, output, numPoints ); 00113 } 00114 else if ( 00115 wkbType == wkbPoint || 00116 wkbType == wkbPoint25D ) 00117 { 00118 int numPoints = OGR_G_GetPointCount( geomHandle ); 00119 output = new Symbology::PointSet( numPoints ); 00120 populate( geomHandle, output, numPoints ); 00121 } 00122 else if ( 00123 wkbType == wkbGeometryCollection || 00124 wkbType == wkbGeometryCollection25D || 00125 wkbType == wkbMultiPoint || 00126 wkbType == wkbMultiPoint25D || 00127 wkbType == wkbMultiLineString || 00128 wkbType == wkbMultiLineString25D || 00129 wkbType == wkbMultiPolygon || 00130 wkbType == wkbMultiPolygon25D ) 00131 { 00132 Symbology::MultiGeometry* multi = new Symbology::MultiGeometry(); 00133 00134 int numGeoms = OGR_G_GetGeometryCount( geomHandle ); 00135 for( int n=0; n<numGeoms; n++ ) 00136 { 00137 OGRGeometryH subGeomRef = OGR_G_GetGeometryRef( geomHandle, n ); 00138 if ( subGeomRef ) 00139 { 00140 Symbology::Geometry* geom = createGeometry( subGeomRef ); 00141 if ( geom ) multi->getComponents().push_back( geom ); 00142 } 00143 } 00144 00145 output = multi; 00146 } 00147 00148 return output; 00149 } 00150 00151 static OGRGeometryH 00152 encodePart( Geometry* geometry, OGRwkbGeometryType part_type ) 00153 { 00154 OGRGeometryH part_handle = OGR_G_CreateGeometry( part_type ); 00155 00156 for( int v = geometry->size()-1; v >= 0; v-- ) 00157 { 00158 osg::Vec3d p = (*geometry)[v]; 00159 OGR_G_AddPoint( part_handle, p.x(), p.y(), p.z() ); 00160 } 00161 00162 return part_handle; 00163 } 00164 00165 00166 static OGRGeometryH 00167 encodeShape( Geometry* geometry, OGRwkbGeometryType shape_type, OGRwkbGeometryType part_type ) 00168 { 00169 OGRGeometryH shape_handle = OGR_G_CreateGeometry( shape_type ); 00170 if ( shape_handle ) 00171 { 00172 GeometryIterator itr(geometry, true); 00173 while (itr.hasMore()) 00174 { 00175 Geometry* geom = itr.next(); 00176 OGRGeometryH part_handle = encodePart( geom, part_type ); 00177 if ( part_handle ) 00178 { 00179 OGR_G_AddGeometryDirectly( shape_handle, part_handle ); 00180 } 00181 } 00182 } 00183 return shape_handle; 00184 } 00185 00186 static OGRGeometryH createOgrGeometry(osgEarth::Symbology::Geometry* geometry, OGRwkbGeometryType requestedType = wkbUnknown) 00187 { 00188 if (!geometry) return NULL; 00189 00190 if (requestedType == wkbUnknown) 00191 { 00192 osgEarth::Symbology::Geometry::Type geomType = geometry->getType(); 00193 switch( geomType) 00194 { 00195 case osgEarth::Symbology::Geometry::TYPE_POLYGON: 00196 requestedType = wkbPolygon; 00197 break; 00198 case osgEarth::Symbology::Geometry::TYPE_POINTSET: 00199 requestedType = wkbPoint; 00200 break; 00201 case osgEarth::Symbology::Geometry::TYPE_LINESTRING: 00202 requestedType = wkbLineString; 00203 break; 00204 case osgEarth::Symbology::Geometry::TYPE_RING: 00205 requestedType = wkbLinearRing; 00206 break; 00207 } 00208 } 00209 00210 OGRwkbGeometryType shape_type = 00211 requestedType == wkbPolygon || requestedType == wkbMultiPolygon ? wkbPolygon : 00212 requestedType == wkbPolygon25D || requestedType == wkbMultiPolygon25D? wkbPolygon25D : 00213 requestedType == wkbLineString || requestedType == wkbMultiLineString? wkbMultiLineString : 00214 requestedType == wkbLineString25D || requestedType == wkbMultiLineString25D? wkbMultiLineString25D : 00215 requestedType == wkbPoint || requestedType == wkbMultiPoint? wkbMultiPoint : 00216 requestedType == wkbPoint25D || requestedType == wkbMultiPoint25D? wkbMultiPoint25D : 00217 wkbNone; 00218 00219 OGRwkbGeometryType part_type = 00220 shape_type == wkbPolygon || shape_type == wkbPolygon25D? wkbLinearRing : 00221 shape_type == wkbMultiLineString? wkbLineString : 00222 shape_type == wkbMultiLineString25D? wkbLineString25D : 00223 shape_type == wkbMultiPoint? wkbPoint : 00224 shape_type == wkbMultiPoint25D? wkbPoint25D : 00225 wkbNone; 00226 00227 00228 osgEarth::Symbology::MultiGeometry* multi = dynamic_cast<MultiGeometry*>(geometry); 00229 00230 if ( multi ) 00231 { 00232 OGRGeometryH group_handle = OGR_G_CreateGeometry( requestedType ); 00233 for (GeometryCollection::iterator itr = multi->getComponents().begin(); itr != multi->getComponents().end(); ++itr) 00234 { 00235 OGRGeometryH shape_handle = encodeShape( itr->get(), shape_type, part_type ); 00236 if ( shape_handle ) 00237 { 00238 if ( OGR_G_AddGeometryDirectly( group_handle, shape_handle ) != OGRERR_NONE ) 00239 { 00240 OE_WARN << "OGR_G_AddGeometryDirectly failed!" << std::endl; 00241 } 00242 } 00243 } 00244 00245 return group_handle; 00246 } 00247 else 00248 { 00249 OGRGeometryH shape_handle = encodeShape( geometry, shape_type, part_type ); 00250 return shape_handle; 00251 } 00252 } 00253 00254 static Symbology::Geometry* 00255 createGeometryFromWKT( const std::string& wkt ) 00256 { 00257 OGRwkbGeometryType type = 00258 startsWith( wkt, "POINT" ) ? wkbPoint : 00259 startsWith( wkt, "LINESTRING" ) ? wkbLineString : 00260 startsWith( wkt, "POLYGON" ) ? wkbPolygon : 00261 startsWith( wkt, "MULTIPOINT" ) ? wkbMultiPoint : 00262 startsWith( wkt, "MULTILINESTRING" ) ? wkbMultiLineString : 00263 startsWith( wkt, "MULTIPOLYGON" ) ? wkbMultiPolygon : 00264 startsWith( wkt, "GEOMETRYCOLLECTION" ) ? wkbGeometryCollection : 00265 wkbNone; 00266 00267 Symbology::Geometry* output = 0L; 00268 if ( type != wkbNone ) 00269 { 00270 OGRGeometryH geom = OGR_G_CreateGeometry( type ); 00271 if ( geom ) 00272 { 00273 char* ptr = (char*)wkt.c_str(); 00274 if ( OGRERR_NONE == OGR_G_ImportFromWkt( geom, &ptr ) ) 00275 { 00276 output = createGeometry( geom ); 00277 OGR_G_DestroyGeometry( geom ); 00278 } 00279 else 00280 { 00281 OE_NOTICE 00282 << "OGR Feature Source: malformed WKT geometry" << std::endl; 00283 } 00284 } 00285 } 00286 return output; 00287 } 00288 00289 static Feature* createFeature( OGRFeatureH handle ) 00290 { 00291 long fid = OGR_F_GetFID( handle ); 00292 00293 Feature* feature = new Feature( fid ); 00294 00295 OGRGeometryH geomRef = OGR_F_GetGeometryRef( handle ); 00296 if ( geomRef ) 00297 { 00298 Symbology::Geometry* geom = OgrUtils::createGeometry( geomRef ); 00299 feature->setGeometry( geom ); 00300 } 00301 00302 int numAttrs = OGR_F_GetFieldCount(handle); 00303 for (int i = 0; i < numAttrs; ++i) 00304 { 00305 void* field_handle_ref = OGR_F_GetFieldDefnRef( handle, i ); 00306 00307 // get the field name and convert to lower case: 00308 const char* field_name = OGR_Fld_GetNameRef( field_handle_ref ); 00309 std::string name = std::string( field_name ); 00310 std::transform( name.begin(), name.end(), name.begin(), ::tolower ); 00311 00312 // get the field type and set the value appropriately 00313 OGRFieldType field_type = OGR_Fld_GetType( field_handle_ref ); 00314 switch( field_type ) 00315 { 00316 case OFTInteger: 00317 { 00318 int value = OGR_F_GetFieldAsInteger( handle, i ); 00319 feature->set( name, value ); 00320 } 00321 break; 00322 case OFTReal: 00323 { 00324 double value = OGR_F_GetFieldAsDouble( handle, i ); 00325 feature->set( name, value ); 00326 } 00327 break; 00328 default: 00329 { 00330 const char* value = OGR_F_GetFieldAsString(handle, i); 00331 feature->set( name, std::string(value) ); 00332 } 00333 } 00334 00335 //const char* field_value= OGR_F_GetFieldAsString(handle, i); 00336 //std::string value = std::string( field_value); 00338 //feature->set(name, value); 00340 } 00341 00342 return feature; 00343 } 00344 00345 static AttributeType getAttributeType( OGRFieldType type ) 00346 { 00347 switch (type) 00348 { 00349 case OFTString: return ATTRTYPE_STRING; 00350 case OFTReal: return ATTRTYPE_DOUBLE; 00351 case OFTInteger: return ATTRTYPE_INT; 00352 default: return ATTRTYPE_UNSPECIFIED; 00353 }; 00354 } 00355 }; 00356 00357 00358 #endif // OSGEARTHFEATURES_FEATURE_OGR_GEOM_UTILS 00359