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 <osgEarthFeatures/CropFilter> 00020 00021 #define LC "[CropFilter] " 00022 00023 using namespace osgEarth; 00024 using namespace osgEarth::Features; 00025 using namespace osgEarth::Symbology; 00026 00027 CropFilter::CropFilter( CropFilter::Method method ) : 00028 _method( method ) 00029 { 00030 //nop 00031 } 00032 00033 FilterContext 00034 CropFilter::push( FeatureList& input, FilterContext& context ) 00035 { 00036 if ( !context.extent().isSet() ) 00037 { 00038 OE_WARN << LC << "Extent is not set (and is required)" << std::endl; 00039 return context; 00040 } 00041 00042 const GeoExtent& extent = *context.extent(); 00043 00044 GeoExtent newExtent( extent.getSRS() ); 00045 00046 if ( _method == METHOD_CENTROID ) 00047 { 00048 for( FeatureList::iterator i = input.begin(); i != input.end(); ) 00049 { 00050 bool keepFeature = false; 00051 00052 Feature* feature = i->get(); 00053 Geometry* featureGeom = feature->getGeometry(); 00054 00055 if ( featureGeom && featureGeom->isValid() ) 00056 { 00057 Bounds bounds = featureGeom->getBounds(); 00058 if ( bounds.isValid() ) 00059 { 00060 osg::Vec3d centroid = bounds.center(); 00061 if ( extent.contains( centroid.x(), centroid.y() ) ) 00062 { 00063 keepFeature = true; 00064 newExtent.expandToInclude( bounds ); 00065 } 00066 } 00067 } 00068 00069 if ( keepFeature ) 00070 ++i; 00071 else 00072 i = input.erase( i ); 00073 } 00074 } 00075 00076 else // METHOD_CROPPING (requires GEOS) 00077 { 00078 #ifdef OSGEARTH_HAVE_GEOS 00079 00080 // create the intersection polygon: 00081 osg::ref_ptr<Symbology::Polygon> poly; 00082 00083 for( FeatureList::iterator i = input.begin(); i != input.end(); ) 00084 { 00085 bool keepFeature = false; 00086 00087 Feature* feature = i->get(); 00088 Symbology::Geometry* featureGeom = feature->getGeometry(); 00089 if ( featureGeom && featureGeom->isValid() ) 00090 { 00091 // test for trivial acceptance: 00092 const Bounds bounds = featureGeom->getBounds(); 00093 if ( !bounds.isValid() ) 00094 { 00095 //nop 00096 } 00097 00098 else if ( extent.contains( bounds ) ) 00099 { 00100 keepFeature = true; 00101 newExtent.expandToInclude( bounds ); 00102 } 00103 00104 // then move on to the cropping operation: 00105 else 00106 { 00107 if ( !poly.valid() ) 00108 { 00109 poly = new Symbology::Polygon(); 00110 poly->push_back( osg::Vec3d( extent.xMin(), extent.yMin(), 0 )); 00111 poly->push_back( osg::Vec3d( extent.xMax(), extent.yMin(), 0 )); 00112 poly->push_back( osg::Vec3d( extent.xMax(), extent.yMax(), 0 )); 00113 poly->push_back( osg::Vec3d( extent.xMin(), extent.yMax(), 0 )); 00114 } 00115 00116 osg::ref_ptr<Geometry> croppedGeometry; 00117 if ( featureGeom->crop( poly.get(), croppedGeometry ) ) 00118 { 00119 if ( croppedGeometry->isValid() ) 00120 { 00121 feature->setGeometry( croppedGeometry.get() ); 00122 keepFeature = true; 00123 newExtent.expandToInclude( croppedGeometry->getBounds() ); 00124 } 00125 } 00126 } 00127 } 00128 00129 if ( keepFeature ) 00130 ++i; 00131 else 00132 i = input.erase( i ); 00133 } 00134 00135 #else // OSGEARTH_HAVE_GEOS 00136 00137 OE_WARN << "CropFilter - METHOD_CROPPING not available - please compile osgEarth with GEOS" << std::endl; 00138 return context; 00139 00140 #endif 00141 } 00142 00143 FilterContext newContext = context; 00144 newContext.extent() = newExtent; 00145 00146 return newContext; 00147 }