1 /* -*-c++-*- */ 2 /* osgEarth - Geospatial SDK for OpenSceneGraph 3 * Copyright 2019 Pelican Mapping 4 * http://osgearth.org 5 * 6 * osgEarth is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU Lesser General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public License 17 * along with this program. If not, see <http://www.gnu.org/licenses/> 18 */ 19 20 #include <osgEarth/MaskSource> 21 #include <osgEarth/Registry> 22 #include <osgEarth/Map> 23 24 #include <osgEarthFeatures/TransformFilter> 25 #include <osgEarthFeatures/FeatureSource> 26 #include <osgEarthFeatures/FilterContext> 27 #include <osgEarthFeatures/FeatureCursor> 28 29 #include <osgDB/FileNameUtils> 30 #include <OpenThreads/Mutex> 31 #include <OpenThreads/ScopedLock> 32 33 #include "FeatureMaskOptions" 34 35 #define LC "[FeatureMaskDriver] " 36 37 using namespace osgEarth; 38 using namespace osgEarth::Features; 39 using namespace osgEarth::Drivers; 40 41 //------------------------------------------------------------------------ 42 43 class FeatureMaskSource : public MaskSource 44 { 45 public: FeatureMaskSource(const MaskSourceOptions & options)46 FeatureMaskSource( const MaskSourceOptions& options ) 47 : MaskSource( options ), _options( options ), _failed( false ) 48 { 49 // the data source from which to pull features: 50 if ( _options.featureSource().valid() ) 51 { 52 _features = _options.featureSource().get(); 53 } 54 else if ( _options.featureOptions().isSet() ) 55 { 56 _features = FeatureSourceFactory::create( _options.featureOptions().value() ); 57 if ( !_features.valid() ) 58 { 59 OE_WARN << "FeatureModelSource - no valid feature source provided" << std::endl; 60 } 61 } 62 } 63 getOptions() const64 const MaskSourceOptions& getOptions() const { 65 return _options; 66 } 67 68 //override initialize(const osgDB::Options * readOptions)69 Status initialize(const osgDB::Options* readOptions) 70 { 71 if (!_features.valid()) 72 return Status::Error(LC, "No feature source available"); 73 74 const Status& fstatus = _features->open(readOptions); 75 if (fstatus.isError()) 76 return fstatus; 77 78 return Status::OK(); 79 } 80 createBoundary(const SpatialReference * srs,ProgressCallback * progress)81 osg::Vec3dArray* createBoundary(const SpatialReference* srs, ProgressCallback* progress) 82 { 83 if (getStatus().isError()) 84 return 0L; 85 86 if ( _features.valid() ) 87 { 88 if ( _features->getFeatureProfile() ) 89 { 90 osg::ref_ptr<FeatureCursor> cursor = _features->createFeatureCursor(progress); 91 if ( cursor.valid() && cursor->hasMore() ) 92 { 93 Feature* f = cursor->nextFeature(); 94 if ( f && f->getGeometry() ) 95 { 96 // Init a filter to transform feature in desired SRS 97 if (!srs->isEquivalentTo(_features->getFeatureProfile()->getSRS())) 98 { 99 FilterContext cx; 100 cx.setProfile( new FeatureProfile(_features->getFeatureProfile()->getExtent()) ); 101 102 TransformFilter xform( srs ); 103 FeatureList featureList; 104 featureList.push_back(f); 105 cx = xform.push(featureList, cx); 106 } 107 108 return f->getGeometry()->createVec3dArray(); 109 } 110 } 111 } 112 else 113 { 114 setStatus(Status::Error("Failed to create boundary")); 115 OE_WARN << LC << getStatus().message() << std::endl; 116 } 117 } 118 else 119 { 120 setStatus(Status::Error("Failed to create boundary")); 121 OE_WARN << LC << getStatus().message() << std::endl; 122 } 123 return 0L; 124 } 125 126 private: 127 bool _failed; 128 const FeatureMaskOptions _options; 129 osg::ref_ptr<FeatureSource> _features; 130 }; 131 132 //------------------------------------------------------------------------ 133 134 class FeatureMaskDriver : public MaskSourceDriver 135 { 136 public: FeatureMaskDriver()137 FeatureMaskDriver() 138 { 139 supportsExtension( "osgearth_mask_feature", "osgEarth feature mask plugin" ); 140 } 141 className() const142 virtual const char* className() const 143 { 144 return "osgEarth Feature Mask Plugin"; 145 } 146 readObject(const std::string & file_name,const Options * options) const147 virtual ReadResult readObject(const std::string& file_name, const Options* options) const 148 { 149 if ( !acceptsExtension(osgDB::getLowerCaseFileExtension( file_name ))) 150 return ReadResult::FILE_NOT_HANDLED; 151 152 return new FeatureMaskSource( getMaskSourceOptions(options) ); 153 } 154 }; 155 156 REGISTER_OSGPLUGIN(osgearth_mask_feature, FeatureMaskDriver) 157