Example #1
0
featureset_ptr gdal_datasource::features(query const& q) const
{
    if (! is_bound_) bind();

    gdal_query gq = q;

    // TODO - move to boost::make_shared, but must reduce # of args to <= 9
    return featureset_ptr(new gdal_featureset(*open_dataset(),
                                              band_,
                                              gq,
                                              extent_,
                                              width_,
                                              height_,
                                              nbands_,
                                              dx_,
                                              dy_,
                                              filter_factor_));
}
/*
 * Opens a GDALDataset and returns a pointer to it.
 * Caller is responsible for calling GDALClose on it
 */
inline GDALDataset *gdal_datasource::open_dataset() const
{

#ifdef MAPNIK_DEBUG
    std::clog << "GDAL Plugin: opening: " << dataset_name_ << std::endl;
#endif

    GDALDataset *dataset;
#if GDAL_VERSION_NUM >= 1600
    if (shared_dataset_)
        dataset = reinterpret_cast<GDALDataset*>(GDALOpenShared((dataset_name_).c_str(),GA_ReadOnly));
    else
#endif
        dataset = reinterpret_cast<GDALDataset*>(GDALOpen((dataset_name_).c_str(),GA_ReadOnly));

    if (! dataset) throw datasource_exception(CPLGetLastErrorMsg());
    return dataset;
}
Example #3
0
feature_ptr gdal_featureset::get_feature_at_point(mapnik::coord2d const& pt)
{
    if (band_ > 0)
    {
        unsigned raster_xsize = dataset_.GetRasterXSize();
        unsigned raster_ysize = dataset_.GetRasterYSize();

        double gt[6];
        dataset_.GetGeoTransform(gt);

        double det = gt[1] * gt[5] - gt[2] * gt[4];
        // subtract half a pixel width & height because gdal coord reference
        // is the top-left corner of a pixel, not the center.
        double X = pt.x - gt[0] - gt[1]/2;
        double Y = pt.y - gt[3] - gt[5]/2;
        double det1 = gt[1]*Y + gt[4]*X;
        double det2 = gt[2]*Y + gt[5]*X;
        unsigned x = det2/det, y = det1/det;

        if (x < raster_xsize && y < raster_ysize)
        {
            MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: pt.x=" << pt.x << " pt.y=" << pt.y;
            MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: x=" << x << " y=" << y;

            GDALRasterBand* band = dataset_.GetRasterBand(band_);
            int hasNoData;
            double nodata = band->GetNoDataValue(&hasNoData);
            double value;
            band->RasterIO(GF_Read, x, y, 1, 1, &value, 1, 1, GDT_Float64, 0, 0);

            if (! hasNoData || value != nodata)
            {
                // construct feature
                feature_ptr feature = feature_factory::create(ctx_,1);
                geometry_type * point = new geometry_type(mapnik::Point);
                point->move_to(pt.x, pt.y);
                feature->add_geometry(point);
                feature->put("value",value);
                return feature;
            }
        }
    }
    return feature_ptr();
}
feature_ptr rasterlite_featureset::next()
{
   if (first_)
   {
      first_ = false;

      query *q = boost::get<query>(&gquery_);
      if(q) {
          return get_feature(*q);
      } else {
          coord2d *p = boost::get<coord2d>(&gquery_);
          if(p) {
              return get_feature_at_point(*p);
          }
      }
      // should never reach here
   }
   return feature_ptr();
}
featureset_ptr geos_datasource::features_at_point(coord2d const& pt) const
{
    if (!is_bound_) bind();

    std::ostringstream s;
    s << "POINT(" << pt.x << " " << pt.y << ")";

#ifdef MAPNIK_DEBUG
    clog << "GEOS Plugin: using point: " << s.str() << endl;
#endif

    return featureset_ptr(new geos_featureset (*geometry_,
                                               GEOSGeomFromWKT(s.str().c_str()),
                                               geometry_id_,
                                               geometry_data_,
                                               geometry_data_name_,
                                               desc_.get_encoding(),
                                               multiple_geometries_));
}
Example #6
0
kismet_datasource::kismet_datasource(parameters const& params, bool bind)
    : datasource(params),
      extent_(),
      extent_initialized_(false),
      type_(datasource::Vector),
      srs_("+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs"),
      desc_(*params.get<std::string>("type"), *params.get<std::string>("encoding","utf-8"))
{
    boost::optional<std::string> host = params_.get<std::string>("host");
    if (host)
    {
        host_ = *host;
    }
    else
    {
        throw datasource_exception("Kismet Plugin: missing <host> parameter");
    }

    boost::optional<unsigned int> port = params_.get<unsigned int>("port", 2501);
    if (port)
    {
        port_ = *port;
    }

    boost::optional<std::string> srs = params_.get<std::string>("srs");
    if (srs)
    {
        srs_ = *srs;
    }

    boost::optional<std::string> ext = params_.get<std::string>("extent");
    if (ext)
    {
        extent_initialized_ = extent_.from_string(*ext);
    }

    kismet_thread.reset(new boost::thread(boost::bind(&kismet_datasource::run, this, host_, port_)));

    if (bind)
    {
        this->bind();
    }
}
sqlite_datasource::sqlite_datasource(parameters const& params, bool bind)
   : datasource(params),
     extent_(),
     extent_initialized_(false),
     type_(datasource::Vector),
     table_(*params.get<std::string>("table","")),
     fields_(*params.get<std::string>("fields","*")),
     metadata_(*params.get<std::string>("metadata","")),
     geometry_field_(*params.get<std::string>("geometry_field","the_geom")),
     key_field_(*params.get<std::string>("key_field","OGC_FID")),
     row_offset_(*params_.get<int>("row_offset",0)),
     row_limit_(*params_.get<int>("row_limit",0)),
     desc_(*params.get<std::string>("type"), *params.get<std::string>("encoding","utf-8")),
     format_(mapnik::wkbGeneric)
{
    boost::optional<std::string> file = params.get<std::string>("file");
    if (!file) throw datasource_exception("Sqlite Plugin: missing <file> parameter");

    boost::optional<std::string> wkb = params.get<std::string>("wkb_format");
    if (wkb)
    {
        if (*wkb == "spatialite")
            format_ = mapnik::wkbSpatiaLite;  
    }

    multiple_geometries_ = *params_.get<mapnik::boolean>("multiple_geometries",false);
    use_spatial_index_ = *params_.get<mapnik::boolean>("use_spatial_index",true);

    boost::optional<std::string> ext  = params_.get<std::string>("extent");
    if (ext) extent_initialized_ = extent_.from_string(*ext);

    boost::optional<std::string> base = params.get<std::string>("base");
    if (base)
        dataset_name_ = *base + "/" + *file;
    else
        dataset_name_ = *file;

    if (bind)
    {
        this->bind();
    }
}
Example #8
0
featureset_ptr gdal_datasource::features_at_point(coord2d const& pt, double tol) const
{
#ifdef MAPNIK_STATS
    mapnik::progress_timer __stats__(std::clog, "gdal_datasource::features_at_point");
#endif

    gdal_query gq = pt;

    // TODO - move to std::make_shared, but must reduce # of args to <= 9
    return featureset_ptr(new gdal_featureset(*open_dataset(),
                                              band_,
                                              gq,
                                              extent_,
                                              width_,
                                              height_,
                                              nbands_,
                                              dx_,
                                              dy_,
                                              nodata_value_,
                                              nodata_tolerance_));
}
feature_ptr gdal_featureset::next()
{
    if (first_)
    {
        first_ = false;
#ifdef MAPNIK_DEBUG
        std::clog << "GDAL Plugin: featureset, dataset = " << &dataset_ << std::endl;
#endif

        query *q = boost::get<query>(&gquery_);
        if(q) {
            return get_feature(*q);
        } else {
            coord2d *p = boost::get<coord2d>(&gquery_);
            if(p) {
                return get_feature_at_point(*p);
            }
        }
        // should never reach here
    }
    return feature_ptr();
}
Example #10
0
ogr_datasource::ogr_datasource(parameters const& params, bool bind)
  : datasource(params),
    extent_(),
    type_(datasource::Vector),
    desc_(*params_.get<std::string>("type"), *params_.get<std::string>("encoding", "utf-8")),
    indexed_(false)
{
    boost::optional<std::string> file = params.get<std::string>("file");
    boost::optional<std::string> string = params.get<std::string>("string");
    if (! file && ! string)
    {
        throw datasource_exception("missing <file> or <string> parameter");
    }

    multiple_geometries_ = *params.get<mapnik::boolean>("multiple_geometries", false);

    if (string)
    {
       dataset_name_ = *string;
    }
    else
    {
        boost::optional<std::string> base = params.get<std::string>("base");
        if (base)
        {
            dataset_name_ = *base + "/" + *file;
        }
        else
        {
            dataset_name_ = *file;
        }
    }

    if (bind)
    {
        this->bind();
    }
}
Example #11
0
shape_datasource::shape_datasource(const parameters &params, bool bind)
    : datasource (params),
      type_(datasource::Vector),
      file_length_(0),
      indexed_(false),
      desc_(*params.get<std::string>("type"), *params.get<std::string>("encoding","utf-8"))
{
    boost::optional<std::string> file = params.get<std::string>("file");
    if (!file) throw datasource_exception("Shape Plugin: missing <file> parameter");
      
    boost::optional<std::string> base = params.get<std::string>("base");
    if (base)
        shape_name_ = *base + "/" + *file;
    else
        shape_name_ = *file;

    boost::algorithm::ireplace_last(shape_name_,".shp","");
    
    if (bind)
    {
        this->bind();
    }
}
Example #12
0
/*
 * Opens a GDALDataset and returns a pointer to it.
 * Caller is responsible for calling GDALClose on it
 */
inline GDALDataset* gdal_datasource::open_dataset() const
{
    MAPNIK_LOG_DEBUG(gdal) << "gdal_datasource: Opening " << dataset_name_;

    GDALDataset *dataset;
#if GDAL_VERSION_NUM >= 1600
    if (shared_dataset_)
    {
        dataset = reinterpret_cast<GDALDataset*>(GDALOpenShared((dataset_name_).c_str(), GA_ReadOnly));
    }
    else
#endif
    {
        dataset = reinterpret_cast<GDALDataset*>(GDALOpen((dataset_name_).c_str(), GA_ReadOnly));
    }

    if (! dataset)
    {
        throw datasource_exception(CPLGetLastErrorMsg());
    }

    return dataset;
}
Example #13
0
feature_ptr kismet_featureset::next()
{
    if (knd_list_it != knd_list_.end ())
    {
        const kismet_network_data& knd = *knd_list_it;
        const std::string key = "internet_access";

        std::string value;
        if (knd.crypt_ == crypt_none)
        {
            value = "wlan_uncrypted";
        }
        else if (knd.crypt_ == crypt_wep)
        {
            value = "wlan_wep";
        }
        else
        {
            value = "wlan_crypted";
        }

        feature_ptr feature(feature_factory::create(feature_id_));
        ++feature_id_;
      
        geometry_type* pt = new geometry_type(mapnik::Point);
        pt->move_to(knd.bestlon_, knd.bestlat_);
        feature->add_geometry(pt);
      
        boost::put(*feature, key, tr_->transcode(value.c_str()));
      
        ++knd_list_it;
        
        return feature;
    }
    
    return feature_ptr();
}
void sqlite_datasource::bind() const
{
    if (is_bound_) return;
    
    if (!boost::filesystem::exists(dataset_name_))
        throw datasource_exception("Sqlite Plugin: " + dataset_name_ + " does not exist");
          
    dataset_ = new sqlite_connection (dataset_name_);

    if(geometry_table_.empty())
    {
        geometry_table_ = mapnik::table_from_sql(table_);
    }
    

    // should we deduce column names and types using PRAGMA?
    bool use_pragma_table_info = true;
    
    if (table_ != geometry_table_)
    {
        // if 'table_' is a subquery then we try to deduce names
        // and types from the first row returned from that query
        use_pragma_table_info = false;
    }

    if (!use_pragma_table_info)
    {
        std::ostringstream s;
        s << "SELECT " << fields_ << " FROM (" << table_ << ") LIMIT 1";

        boost::scoped_ptr<sqlite_resultset> rs (dataset_->execute_query (s.str()));
        if (rs->is_valid () && rs->step_next())
        {
            for (int i = 0; i < rs->column_count (); ++i)
            {
               const int type_oid = rs->column_type (i);
               const char* fld_name = rs->column_name (i);
               switch (type_oid)
               {
                  case SQLITE_INTEGER:
                     desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::Integer));
                     break;
                     
                  case SQLITE_FLOAT:
                     desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::Double));
                     break;
                     
                  case SQLITE_TEXT:
                     desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::String));
                     break;
                     
                  case SQLITE_NULL:
                     // sqlite reports based on value, not actual column type unless
                     // PRAGMA table_info is used so here we assume the column is a string
                     // which is a lesser evil than altogether dropping the column
                     desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::String));

                  case SQLITE_BLOB:
                        if (geometry_field_.empty() && 
                             (boost::algorithm::icontains(fld_name,"geom") ||
                              boost::algorithm::icontains(fld_name,"point") ||
                              boost::algorithm::icontains(fld_name,"linestring") ||
                              boost::algorithm::icontains(fld_name,"polygon"))
                            )
                            geometry_field_ = std::string(fld_name);
                     break;
                     
                  default:
#ifdef MAPNIK_DEBUG
                     std::clog << "Sqlite Plugin: unknown type_oid=" << type_oid << std::endl;
#endif
                     break;
                }
            }
        }
        else
        {
            // if we do not have at least a row and
            // we cannot determine the right columns types and names 
            // as all column_type are SQLITE_NULL
            // so we fallback to using PRAGMA table_info
            use_pragma_table_info = true;
        }
    }

    // TODO - ensure that the supplied key_field is a valid "integer primary key"
    desc_.add_descriptor(attribute_descriptor("rowid",mapnik::Integer));
    
    if (use_pragma_table_info)
    {
        std::ostringstream s;
        s << "PRAGMA table_info(" << geometry_table_ << ")";
        boost::scoped_ptr<sqlite_resultset> rs (dataset_->execute_query (s.str()));
        bool found_table = false;
        while (rs->is_valid () && rs->step_next())
        {
            found_table = true;
            const char* fld_name = rs->column_text(1);
            std::string fld_type(rs->column_text(2));
            boost::algorithm::to_lower(fld_type);

            // see 2.1 "Column Affinity" at http://www.sqlite.org/datatype3.html
            if (geometry_field_.empty() && 
                       (
                       (boost::algorithm::icontains(fld_name,"geom") ||
                        boost::algorithm::icontains(fld_name,"point") ||
                        boost::algorithm::icontains(fld_name,"linestring") ||
                        boost::algorithm::icontains(fld_name,"polygon"))
                       ||
                       (boost::algorithm::contains(fld_type,"geom") ||
                        boost::algorithm::contains(fld_type,"point") ||
                        boost::algorithm::contains(fld_type,"linestring") ||
                        boost::algorithm::contains(fld_type,"polygon"))
                       )
                    )
                    geometry_field_ = std::string(fld_name);
            else if (boost::algorithm::contains(fld_type,"int"))
            {
                desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::Integer));
            }
            else if (boost::algorithm::contains(fld_type,"text") ||
                     boost::algorithm::contains(fld_type,"char") ||
                     boost::algorithm::contains(fld_type,"clob"))
            {
                desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::String));
            }
            else if (boost::algorithm::contains(fld_type,"real") ||
                     boost::algorithm::contains(fld_type,"float") ||
                     boost::algorithm::contains(fld_type,"double"))
            {
                desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::Double));
            }
            else if (boost::algorithm::contains(fld_type,"blob") && !geometry_field_.empty())
                 desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::String));
#ifdef MAPNIK_DEBUG
            else
            {
                // "Column Affinity" says default to "Numeric" but for now we pass..
                //desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::Double));
                std::clog << "Sqlite Plugin: column '" << std::string(fld_name) << "' unhandled due to unknown type: " << fld_type << std::endl;
            }
#endif
        }
        if (!found_table)
        {
            throw datasource_exception("Sqlite Plugin: could not query table '" + geometry_table_ + "' using pragma table_info(" + geometry_table_  + ");");
        }
    }

    if (geometry_field_.empty()) {
        throw datasource_exception("Sqlite Plugin: cannot detect geometry_field, please supply the name of the geometry_field to use.");
    }
    
    if (use_spatial_index_)
    {
        std::ostringstream s;
        s << "SELECT COUNT (*) FROM sqlite_master";
        s << " WHERE LOWER(name) = LOWER('idx_" << geometry_table_ << "_" << geometry_field_ << "')";
        boost::scoped_ptr<sqlite_resultset> rs (dataset_->execute_query (s.str()));
        if (rs->is_valid () && rs->step_next())
        {
            use_spatial_index_ = rs->column_integer (0) == 1;
        }

        if (!use_spatial_index_)
           std::clog << "Sqlite Plugin: spatial index not found for table '"
             << geometry_table_ << "'" << std::endl;
    }

    if (metadata_ != "" && !extent_initialized_)
    {
        std::ostringstream s;
        s << "SELECT xmin, ymin, xmax, ymax FROM " << metadata_;
        s << " WHERE LOWER(f_table_name) = LOWER('" << geometry_table_ << "')";
        boost::scoped_ptr<sqlite_resultset> rs (dataset_->execute_query (s.str()));
        if (rs->is_valid () && rs->step_next())
        {
            double xmin = rs->column_double (0);
            double ymin = rs->column_double (1);
            double xmax = rs->column_double (2);
            double ymax = rs->column_double (3);

            extent_.init (xmin,ymin,xmax,ymax);
            extent_initialized_ = true;
        }
    }
    
    if (!extent_initialized_ && use_spatial_index_)
    {
        std::ostringstream s;
        s << "SELECT MIN(xmin), MIN(ymin), MAX(xmax), MAX(ymax) FROM " 
        << "idx_" << geometry_table_ << "_" << geometry_field_;
        boost::scoped_ptr<sqlite_resultset> rs (dataset_->execute_query (s.str()));
        if (rs->is_valid () && rs->step_next())
        {
            double xmin = rs->column_double (0);
            double ymin = rs->column_double (1);
            double xmax = rs->column_double (2);
            double ymax = rs->column_double (3);

            extent_.init (xmin,ymin,xmax,ymax);
            extent_initialized_ = true;
        }    
    }
    
    if (!extent_initialized_) {
        std::ostringstream s;
        s << "Sqlite Plugin: extent could not be determined for table|geometry '" 
          << geometry_table_ << "|" << geometry_field_ << "'"
          << " because an rtree spatial index is missing."
          << " - either set the table 'extent' or create an rtree spatial index";
        throw datasource_exception(s.str());
    }
    
    is_bound_ = true;
}
Example #15
0
raster_datasource::raster_datasource(parameters const& params)
: datasource(params),
    desc_(*params.get<std::string>("type"), "utf-8"),
    extent_initialized_(false)
{
    MAPNIK_LOG_DEBUG(raster) << "raster_datasource: Initializing...";

    boost::optional<std::string> file = params.get<std::string>("file");
    if (! file) throw datasource_exception("Raster Plugin: missing <file> parameter ");

    boost::optional<std::string> base = params.get<std::string>("base");
    if (base)
        filename_ = *base + "/" + *file;
    else
        filename_ = *file;

    multi_tiles_ = *params.get<mapnik::boolean>("multi", false);
    tile_size_ = *params.get<int>("tile_size", 256);
    tile_stride_ = *params.get<int>("tile_stride", 1);

    boost::optional<std::string> format_from_filename = mapnik::type_from_filename(*file);
    format_ = *params.get<std::string>("format",format_from_filename?(*format_from_filename) : "tiff");

    boost::optional<double> lox = params.get<double>("lox");
    boost::optional<double> loy = params.get<double>("loy");
    boost::optional<double> hix = params.get<double>("hix");
    boost::optional<double> hiy = params.get<double>("hiy");

    boost::optional<std::string> ext = params.get<std::string>("extent");

    if (lox && loy && hix && hiy)
    {
        extent_.init(*lox, *loy, *hix, *hiy);
        extent_initialized_ = true;
    }
    else if (ext)
    {
        extent_initialized_ = extent_.from_string(*ext);
    }

    if (! extent_initialized_)
    {
        throw datasource_exception("Raster Plugin: valid <extent> or <lox> <loy> <hix> <hiy> are required");
    }

    if (multi_tiles_)
    {
        boost::optional<int> x_width = params.get<int>("x_width");
        boost::optional<int> y_width = params.get<int>("y_width");

        if (! x_width)
        {
            throw datasource_exception("Raster Plugin: x-width parameter not supplied for multi-tiled data source.");
        }

        if (! y_width)
        {
            throw datasource_exception("Raster Plugin: y-width parameter not supplied for multi-tiled data source.");
        }

        width_ = x_width.get() * tile_size_;
        height_ = y_width.get() * tile_size_;
    }
    else
    {
        if (!mapnik::util::exists(filename_))
        {
            throw datasource_exception("Raster Plugin: " + filename_ + " does not exist");
        }

        try
        {
            std::auto_ptr<image_reader> reader(mapnik::get_image_reader(filename_, format_));
            if (reader.get())
            {
                width_ = reader->width();
                height_ = reader->height();
            }
        }
        catch (mapnik::image_reader_exception const& ex)
        {
            throw datasource_exception("Raster Plugin: image reader exception: " + std::string(ex.what()));
        }
        catch (std::exception const& ex)
        {
            throw datasource_exception("Raster Plugin: " + std::string(ex.what()));
        }
        catch (...)
        {
            throw datasource_exception("Raster Plugin: image reader unknown exception caught");
        }
    }

    MAPNIK_LOG_DEBUG(raster) << "raster_datasource: Raster size=" << width_ << "," << height_;

}
Example #16
0
featureset_ptr raster_datasource::features_at_point(coord2d const&, double tol) const
{
    MAPNIK_LOG_WARN(raster) << "raster_datasource: feature_at_point not supported";

    return featureset_ptr();
}
Example #17
0
void gdal_datasource::bind() const
{
    if (is_bound_) return;

    shared_dataset_ = *params_.get<mapnik::boolean>("shared", false);
    band_ = *params_.get<int>("band", -1);

    GDALDataset *dataset = open_dataset();

    nbands_ = dataset->GetRasterCount();
    width_ = dataset->GetRasterXSize();
    height_ = dataset->GetRasterYSize();

    double tr[6];
    bool bbox_override = false;
    boost::optional<std::string> bbox_s = params_.get<std::string>("bbox");
    if (bbox_s)
    {
#ifdef MAPNIK_DEBUG
        std::clog << "GDAL Plugin: bbox parameter=" << *bbox_s << std::endl;
#endif

        bbox_override = extent_.from_string(*bbox_s);
        if (! bbox_override)
        {
            throw datasource_exception("GDAL Plugin: bbox parameter '" + *bbox_s + "' invalid");
        }
    }

    if (bbox_override)
    {
        tr[0] = extent_.minx();
        tr[1] = extent_.width() / (double)width_;
        tr[2] = 0;
        tr[3] = extent_.maxy();
        tr[4] = 0;
        tr[5] = -extent_.height() / (double)height_;
    }
    else
    {
        dataset->GetGeoTransform(tr);
    }

#ifdef MAPNIK_DEBUG
    std::clog << "GDAL Plugin: geotransform=" << tr[0] << "," << tr[1] << ","
              << tr[2] << "," << tr[3] << ","
              << tr[4] << "," << tr[5] << std::endl;
#endif

    // TODO - We should throw for true non-north up images, but the check
    // below is clearly too restrictive.
    // https://github.com/mapnik/mapnik/issues/970
    /*
    if (tr[2] != 0 || tr[4] != 0)
    {
        throw datasource_exception("GDAL Plugin: only 'north up' images are supported");
    }
    */

    dx_ = tr[1];
    dy_ = tr[5];

    if (! bbox_override)
    {
        double x0 = tr[0];
        double y0 = tr[3];
        double x1 = tr[0] + width_ * dx_ + height_ *tr[2];
        double y1 = tr[3] + width_ *tr[4] + height_ * dy_;

        /*
          double x0 = tr[0] + (height_) * tr[2]; // minx
          double y0 = tr[3] + (height_) * tr[5]; // miny

          double x1 = tr[0] + (width_) * tr[1]; // maxx
          double y1 = tr[3] + (width_) * tr[4]; // maxy
        */

        extent_.init(x0, y0, x1, y1);
    }

    GDALClose(dataset);

#ifdef MAPNIK_DEBUG
    std::clog << "GDAL Plugin: Raster Size=" << width_ << "," << height_ << std::endl;
    std::clog << "GDAL Plugin: Raster Extent=" << extent_ << std::endl;
#endif

    is_bound_ = true;
}
Example #18
0
feature_ptr sqlite_featureset::next()
{
    while (rs_->is_valid () && rs_->step_next ())
    {
        int size;
        const char* data = (const char*) rs_->column_blob(0, size);
        if (data == 0)
        {
            return feature_ptr();
        }

        // null feature id is not acceptable
        if (rs_->column_type(1) == SQLITE_NULL)
        {
            MAPNIK_LOG_ERROR(postgis) << "sqlite_featureset: null value encountered for key_field";
            continue;
        }

        feature_ptr feature = feature_factory::create(ctx_,rs_->column_integer64(1));
        if (!geometry_utils::from_wkb(feature->paths(), data, size, format_))
            continue;

        if (!spatial_index_)
        {
            // we are not using r-tree index, check if feature intersects bounding box
            if (!bbox_.intersects(feature->envelope()))
                continue;
        }

        for (int i = 2; i < rs_->column_count(); ++i)
        {
            const int type_oid = rs_->column_type(i);
            const char* fld_name = rs_->column_name(i);

            if (! fld_name)
                continue;

            std::string fld_name_str(fld_name);

            // subqueries in sqlite lead to field double quoting which we need to strip
            if (using_subquery_)
            {
                sqlite_utils::dequote(fld_name_str);
            }

            switch (type_oid)
            {
            case SQLITE_INTEGER:
            {
                feature->put<mapnik::value_integer>(fld_name_str, rs_->column_integer64(i));
                break;
            }

            case SQLITE_FLOAT:
            {
                feature->put(fld_name_str, rs_->column_double(i));
                break;
            }

            case SQLITE_TEXT:
            {
                int text_col_size;
                const char * text_data = rs_->column_text(i, text_col_size);
                feature->put(fld_name_str, tr_->transcode(text_data, text_col_size));
                break;
            }

            case SQLITE_NULL:
            {
                // NOTE: we intentionally do not store null here
                // since it is equivalent to the attribute not existing
                break;
            }

            case SQLITE_BLOB:
                break;

            default:
                MAPNIK_LOG_WARN(sqlite) << "sqlite_featureset: Field=" << fld_name_str << " unhandled type_oid=" << type_oid;
                break;
            }
        }

        return feature;
    }

    return feature_ptr();
}
Example #19
0
feature_ptr osm_featureset<filterT>::next()
{
    feature_ptr feature;

    osm_item* cur_item = dataset_->next_item();
    if (!cur_item) return feature_ptr();
    if (dataset_->current_item_is_node())
    {
        feature = feature_factory::create(ctx_, cur_item->id);
        double lat = static_cast<osm_node*>(cur_item)->lat;
        double lon = static_cast<osm_node*>(cur_item)->lon;
        geometry_type* point = new geometry_type(mapnik::Point);
        point->move_to(lon, lat);
        feature->add_geometry(point);
    }
    else if (dataset_->current_item_is_way())
    {
        // Loop until we find a feature which passes the filter
        while (cur_item)
        {
            bounds b = static_cast<osm_way*>(cur_item)->get_bounds();
            if (filter_.pass(box2d<double>(b.w, b.s, b.e, b.n))
                    &&
                static_cast<osm_way*>(cur_item)->nodes.size()) break;
            cur_item = dataset_->next_item();
        }

        if (!cur_item) return feature_ptr();
        feature = feature_factory::create(ctx_, cur_item->id);
        geometry_type* geom;
        if (static_cast<osm_way*>(cur_item)->is_polygon())
        {
            geom = new geometry_type(mapnik::Polygon);
        }
        else
        {
            geom = new geometry_type(mapnik::LineString);
        }

        geom->move_to(static_cast<osm_way*>(cur_item)->nodes[0]->lon,
                      static_cast<osm_way*>(cur_item)->nodes[0]->lat);

        for (unsigned int count = 1;
             count < static_cast<osm_way*>(cur_item)->nodes.size();
             count++)
        {
            geom->line_to(static_cast<osm_way*>(cur_item)->nodes[count]->lon,
                          static_cast<osm_way*>(cur_item)->nodes[count]->lat);
        }
        feature->add_geometry(geom);
    }
    else
    {
        MAPNIK_LOG_ERROR(osm_featureset) << "Current item is neither node nor way.\n";
    }

    std::set<std::string>::const_iterator itr = attribute_names_.begin();
    std::set<std::string>::const_iterator end = attribute_names_.end();
    std::map<std::string,std::string>::iterator end_keyvals = cur_item->keyvals.end();
    for (; itr != end; itr++)
    {
        std::map<std::string,std::string>::iterator i = cur_item->keyvals.find(*itr);
        if (i != end_keyvals)
        {
            feature->put_new(i->first, tr_->transcode(i->second.c_str()));
        }
    }
    return feature;
}
feature_ptr rasterlite_featureset::get_feature_at_point(mapnik::coord2d const& pt)
{
    return feature_ptr();
}
Example #21
0
void save_to_file3(mapnik::image_32 const& im, std::string const& filename, std::string const& type, mapnik::rgba_palette const& pal)
{
    save_to_file(im,filename,type,pal);
}
Example #22
0
feature_ptr raster_featureset<LookupPolicy>::next()
{
    if (curIter_ != endIter_)
    {
        feature_ptr feature(feature_factory::create(ctx_,feature_id_++));

        try
        {
            std::auto_ptr<image_reader> reader(mapnik::get_image_reader(curIter_->file(),curIter_->format()));

            MAPNIK_LOG_DEBUG(raster) << "raster_featureset: Reader=" << curIter_->format() << "," << curIter_->file()
                                     << ",size(" << curIter_->width() << "," << curIter_->height() << ")";

            if (reader.get())
            {
                int image_width = policy_.img_width(reader->width());
                int image_height = policy_.img_height(reader->height());

                if (image_width > 0 && image_height > 0)
                {
                    mapnik::CoordTransform t(image_width, image_height, extent_, 0, 0);
                    box2d<double> intersect = bbox_.intersect(curIter_->envelope());
                    box2d<double> ext = t.forward(intersect);
                    box2d<double> rem = policy_.transform(ext);
                    if (ext.width() > 0.5 && ext.height() > 0.5 )
                    {
                        // select minimum raster containing whole ext
                        int x_off = static_cast<int>(std::floor(ext.minx()));
                        int y_off = static_cast<int>(std::floor(ext.miny()));
                        int end_x = static_cast<int>(std::ceil(ext.maxx()));
                        int end_y = static_cast<int>(std::ceil(ext.maxy()));

                        // clip to available data
                        if (x_off < 0)
                            x_off = 0;
                        if (y_off < 0)
                            y_off = 0;
                        if (end_x > image_width)
                            end_x = image_width;
                        if (end_y > image_height)
                            end_y = image_height;
                        int width = end_x - x_off;
                        int height = end_y - y_off;

                        // calculate actual box2d of returned raster
                        box2d<double> feature_raster_extent(rem.minx() + x_off,
                                                            rem.miny() + y_off,
                                                            rem.maxx() + x_off + width,
                                                            rem.maxy() + y_off + height);
                        intersect = t.backward(feature_raster_extent);

                        mapnik::raster_ptr raster = boost::make_shared<mapnik::raster>(intersect, width, height);
                        reader->read(x_off, y_off, raster->data_);
                        raster->premultiplied_alpha_ = reader->premultiplied_alpha();
                        feature->set_raster(raster);
                    }
                }
            }
        }
        catch (mapnik::image_reader_exception const& ex)
        {
            MAPNIK_LOG_ERROR(raster) << "Raster Plugin: image reader exception caught: " << ex.what();
        }
        catch (std::exception const& ex)
        {
            MAPNIK_LOG_ERROR(raster) << "Raster Plugin: " << ex.what();
        }
        catch (...)
        {
            MAPNIK_LOG_ERROR(raster) << "Raster Plugin: exception caught";
        }

        ++curIter_;
        return feature;
    }
    return feature_ptr();
}
Example #23
0
shape_datasource::shape_datasource(parameters const& params)
    : datasource (params),
      type_(datasource::Vector),
      file_length_(0),
      indexed_(false),
      row_limit_(*params.get<mapnik::value_integer>("row_limit",0)),
      desc_(shape_datasource::name(), *params.get<std::string>("encoding","utf-8"))
{
#ifdef MAPNIK_STATS
    mapnik::progress_timer __stats__(std::clog, "shape_datasource::init");
#endif
    boost::optional<std::string> file = params.get<std::string>("file");
    if (!file) throw datasource_exception("Shape Plugin: missing <file> parameter");

    boost::optional<std::string> base = params.get<std::string>("base");
    if (base)
        shape_name_ = *base + "/" + *file;
    else
        shape_name_ = *file;

    boost::algorithm::ireplace_last(shape_name_,".shp","");
    if (!mapnik::util::exists(shape_name_ + ".shp"))
    {
        throw datasource_exception("Shape Plugin: shapefile '" + shape_name_ + ".shp' does not exist");
    }
    if (mapnik::util::is_directory(shape_name_ + ".shp"))
    {
        throw datasource_exception("Shape Plugin: shapefile '" + shape_name_ + ".shp' appears to be a directory not a file");
    }
    if (!mapnik::util::exists(shape_name_ + ".dbf"))
    {
        throw datasource_exception("Shape Plugin: shapefile '" + shape_name_ + ".dbf' does not exist");
    }

    try
    {
#ifdef MAPNIK_STATS
        mapnik::progress_timer __stats2__(std::clog, "shape_datasource::init(get_column_description)");
#endif

        std::unique_ptr<shape_io> shape_ref = std::make_unique<shape_io>(shape_name_);
        init(*shape_ref);
        for (int i=0;i<shape_ref->dbf().num_fields();++i)
        {
            field_descriptor const& fd=shape_ref->dbf().descriptor(i);
            std::string fld_name=fd.name_;
            switch (fd.type_)
            {
            case 'C': // character
            case 'D': // date
                desc_.add_descriptor(attribute_descriptor(fld_name, String));
                break;
            case 'L': // logical
                desc_.add_descriptor(attribute_descriptor(fld_name, Boolean));
                break;
            case 'N': // numeric
            case 'O': // double
            case 'F': // float
            {
                if (fd.dec_>0)
                {
                    desc_.add_descriptor(attribute_descriptor(fld_name,Double,false,8));
                }
                else
                {
                    desc_.add_descriptor(attribute_descriptor(fld_name,Integer,false,4));
                }
                break;
            }
            default:
                // I - long
                // G - ole
                // + - autoincrement
                // @ - timestamp
                // B - binary
                // l - long
                // M - memo
                MAPNIK_LOG_ERROR(shape) << "shape_datasource: Unknown type=" << fd.type_;
                break;
            }
        }
    }
    catch (datasource_exception const& ex)
    {
        MAPNIK_LOG_ERROR(shape) << "Shape Plugin: error processing field attributes, " << ex.what();
        throw;
    }
    catch (const std::exception& ex)
    {
        MAPNIK_LOG_ERROR(shape) << "Shape Plugin: error processing field attributes, " << ex.what();
        throw;
    }
    catch (...) // exception: pipe_select_interrupter: Too many open files
    {
        MAPNIK_LOG_ERROR(shape) << "Shape Plugin: error processing field attributes";
        throw;
    }

}
Example #24
0
feature_ptr ogr_featureset::next()
{
    if (count_ == 0)
    {
        // Reset the layer reading on the first feature read
        // this is a hack, but needed due to https://github.com/mapnik/mapnik/issues/2048
        // Proper solution is to avoid storing layer state in featureset
        layer_.ResetReading();
    }
    OGRFeature *poFeature;
    while ((poFeature = layer_.GetNextFeature()) != nullptr)
    {
        // ogr feature ids start at 0, so add one to stay
        // consistent with other mapnik datasources that start at 1
        mapnik::value_integer feature_id = (poFeature->GetFID() + 1);
        feature_ptr feature(feature_factory::create(ctx_,feature_id));

        OGRGeometry* geom = poFeature->GetGeometryRef();
        if (geom && ! geom->IsEmpty())
        {
            auto geom_corrected = ogr_converter::convert_geometry(geom);
            mapnik::geometry::correct(geom_corrected);
            feature->set_geometry(std::move(geom_corrected));
        }
        else
        {
            MAPNIK_LOG_DEBUG(ogr) << "ogr_featureset: Feature with null geometry="
                << poFeature->GetFID();
            OGRFeature::DestroyFeature( poFeature );
            continue;
        }

        ++count_;

        int fld_count = layerdef_->GetFieldCount();
        for (int i = 0; i < fld_count; i++)
        {
            OGRFieldDefn* fld = layerdef_->GetFieldDefn(i);
            const OGRFieldType type_oid = fld->GetType();
            const std::string fld_name = fld->GetNameRef();

            switch (type_oid)
            {
            case OFTInteger:
            {
                feature->put<mapnik::value_integer>( fld_name, poFeature->GetFieldAsInteger(i));
                break;
            }
#if GDAL_VERSION_MAJOR >= 2
            case OFTInteger64:
            {
                feature->put<mapnik::value_integer>( fld_name, poFeature->GetFieldAsInteger64(i));
                break;
            }
#endif

            case OFTReal:
            {
                feature->put( fld_name, poFeature->GetFieldAsDouble(i));
                break;
            }

            case OFTString:
            case OFTWideString:     // deprecated !
            {
                feature->put( fld_name, tr_->transcode(poFeature->GetFieldAsString(i)));
                break;
            }

            case OFTIntegerList:
#if GDAL_VERSION_MAJOR >= 2
            case OFTInteger64List:
#endif
            case OFTRealList:
            case OFTStringList:
            case OFTWideStringList: // deprecated !
            {
                MAPNIK_LOG_WARN(ogr) << "ogr_featureset: Unhandled type_oid=" << type_oid;
                break;
            }

            case OFTBinary:
            {
                MAPNIK_LOG_WARN(ogr) << "ogr_featureset: Unhandled type_oid=" << type_oid;
                //feature->put(name,feat->GetFieldAsBinary (i, size));
                break;
            }

            case OFTDate:
            case OFTTime:
            case OFTDateTime:       // unhandled !
            {
                MAPNIK_LOG_WARN(ogr) << "ogr_featureset: Unhandled type_oid=" << type_oid;
                break;
            }

            default: // unknown
            {
                MAPNIK_LOG_WARN(ogr) << "ogr_featureset: Unknown type_oid=" << type_oid;
                break;
            }
            }
        }
        OGRFeature::DestroyFeature( poFeature );
        return feature;
    }

    MAPNIK_LOG_DEBUG(ogr) << "ogr_featureset: " << count_ << " features";

    return feature_ptr();
}
Example #25
0
gdal_datasource::gdal_datasource(parameters const& params)
    : datasource(params),
      desc_(gdal_datasource::name(), "utf-8"),
      nodata_value_(params.get<double>("nodata")),
      nodata_tolerance_(*params.get<double>("nodata_tolerance",1e-12))
{
    MAPNIK_LOG_DEBUG(gdal) << "gdal_datasource: Initializing...";

#ifdef MAPNIK_STATS
    mapnik::progress_timer __stats__(std::clog, "gdal_datasource::init");
#endif

    GDALAllRegister();

    boost::optional<std::string> file = params.get<std::string>("file");
    if (! file) throw datasource_exception("missing <file> parameter");

    boost::optional<std::string> base = params.get<std::string>("base");
    if (base)
    {
        dataset_name_ = *base + "/" + *file;
    }
    else
    {
        dataset_name_ = *file;
    }

    shared_dataset_ = *params.get<mapnik::boolean_type>("shared", false);
    band_ = *params.get<mapnik::value_integer>("band", -1);

    GDALDataset *dataset = open_dataset();

    nbands_ = dataset->GetRasterCount();
    width_ = dataset->GetRasterXSize();
    height_ = dataset->GetRasterYSize();
    desc_.add_descriptor(mapnik::attribute_descriptor("nodata", mapnik::Double));

    double tr[6];
    bool bbox_override = false;
    boost::optional<std::string> bbox_s = params.get<std::string>("extent");
    if (bbox_s)
    {
        MAPNIK_LOG_DEBUG(gdal) << "gdal_datasource: BBox Parameter=" << *bbox_s;

        bbox_override = extent_.from_string(*bbox_s);
        if (! bbox_override)
        {
            throw datasource_exception("GDAL Plugin: bbox parameter '" + *bbox_s + "' invalid");
        }
    }

    if (bbox_override)
    {
        tr[0] = extent_.minx();
        tr[1] = extent_.width() / (double)width_;
        tr[2] = 0;
        tr[3] = extent_.maxy();
        tr[4] = 0;
        tr[5] = -extent_.height() / (double)height_;
        MAPNIK_LOG_DEBUG(gdal) << "gdal_datasource extent override gives Geotransform="
                               << tr[0] << "," << tr[1] << ","
                               << tr[2] << "," << tr[3] << ","
                               << tr[4] << "," << tr[5];
    }
    else
    {
        if (dataset->GetGeoTransform(tr) != CPLE_None)
        {
            MAPNIK_LOG_DEBUG(gdal) << "gdal_datasource GetGeotransform failure gives="
                                   << tr[0] << "," << tr[1] << ","
                                   << tr[2] << "," << tr[3] << ","
                                   << tr[4] << "," << tr[5];
        }
        else
        {
            MAPNIK_LOG_DEBUG(gdal) << "gdal_datasource Geotransform="
                                   << tr[0] << "," << tr[1] << ","
                                   << tr[2] << "," << tr[3] << ","
                                   << tr[4] << "," << tr[5];
        }
    }

    // TODO - We should throw for true non-north up images, but the check
    // below is clearly too restrictive.
    // https://github.com/mapnik/mapnik/issues/970
    /*
      if (tr[2] != 0 || tr[4] != 0)
      {
      throw datasource_exception("GDAL Plugin: only 'north up' images are supported");
      }
    */

    dx_ = tr[1];
    dy_ = tr[5];

    if (! bbox_override)
    {
        double x0 = tr[0];
        double y0 = tr[3];
        double x1 = tr[0] + width_ * dx_ + height_ *tr[2];
        double y1 = tr[3] + width_ *tr[4] + height_ * dy_;

        /*
          double x0 = tr[0] + (height_) * tr[2]; // minx
          double y0 = tr[3] + (height_) * tr[5]; // miny

          double x1 = tr[0] + (width_) * tr[1]; // maxx
          double y1 = tr[3] + (width_) * tr[4]; // maxy
        */

        extent_.init(x0, y0, x1, y1);
    }

    GDALClose(dataset);

    MAPNIK_LOG_DEBUG(gdal) << "gdal_datasource: Raster Size=" << width_ << "," << height_;
    MAPNIK_LOG_DEBUG(gdal) << "gdal_datasource: Raster Extent=" << extent_;

}
featureset_ptr sqlite_datasource::features(query const& q) const
{
   if (!is_bound_) bind();
   if (dataset_)
   {
        mapnik::box2d<double> const& e = q.get_bbox();

        std::ostringstream s;
        
        s << "SELECT " << geometry_field_ << "," << key_field_;
        std::set<std::string> const& props = q.property_names();
        std::set<std::string>::const_iterator pos = props.begin();
        std::set<std::string>::const_iterator end = props.end();
        while (pos != end)
        {
            s << ",\"" << *pos << "\"";
            ++pos;
        }       
        
        s << " FROM "; 
        
        std::string query (table_); 
        
        if (use_spatial_index_)
        {
           std::ostringstream spatial_sql;
           spatial_sql << std::setprecision(16);
           spatial_sql << " WHERE " << key_field_ << " IN (SELECT pkid FROM idx_" << geometry_table_ << "_" << geometry_field_;
           spatial_sql << " WHERE xmax>=" << e.minx() << " AND xmin<=" << e.maxx() ;
           spatial_sql << " AND ymax>=" << e.miny() << " AND ymin<=" << e.maxy() << ")";
           if (boost::algorithm::ifind_first(query, "WHERE"))
           {
              boost::algorithm::ireplace_first(query, "WHERE", spatial_sql.str() + " AND ");
           }
           else if (boost::algorithm::ifind_first(query, geometry_table_))  
           {
              boost::algorithm::ireplace_first(query, table_, table_ + " " + spatial_sql.str());
           }
        }
        
        s << query ;
        
        if (row_limit_ > 0) {
            s << " LIMIT " << row_limit_;
        }

        if (row_offset_ > 0) {
            s << " OFFSET " << row_offset_;
        }

#ifdef MAPNIK_DEBUG
        std::clog << "Sqlite Plugin: " << s.str() << std::endl;
#endif

        boost::shared_ptr<sqlite_resultset> rs (dataset_->execute_query (s.str()));

        return boost::make_shared<sqlite_featureset>(rs, desc_.get_encoding(), format_, multiple_geometries_);
   }

   return featureset_ptr();
}
Example #27
0
void save_to_file2(mapnik::image_32 const& im, std::string const& filename, std::string const& type)
{
    save_to_file(im,filename,type);
}
featureset_ptr sqlite_datasource::features_at_point(coord2d const& pt) const
{
   if (!is_bound_) bind();

   if (dataset_)
   {
        // TODO - need tolerance
        mapnik::box2d<double> const e(pt.x,pt.y,pt.x,pt.y);

        std::ostringstream s;
        s << "SELECT " << geometry_field_ << "," << key_field_;
        std::vector<attribute_descriptor>::const_iterator itr = desc_.get_descriptors().begin();
        std::vector<attribute_descriptor>::const_iterator end = desc_.get_descriptors().end();
        while (itr != end)
        {
            std::string fld_name = itr->get_name();
            if (fld_name != key_field_)
                s << ",\"" << itr->get_name() << "\"";
            ++itr;
        }
        
        s << " FROM "; 
        
        std::string query (table_); 
        
        if (use_spatial_index_)
        {
           std::ostringstream spatial_sql;
           spatial_sql << std::setprecision(16);
           spatial_sql << " WHERE " << key_field_ << " IN (SELECT pkid FROM idx_" << geometry_table_ << "_" << geometry_field_;
           spatial_sql << " WHERE xmax>=" << e.minx() << " AND xmin<=" << e.maxx() ;
           spatial_sql << " AND ymax>=" << e.miny() << " AND ymin<=" << e.maxy() << ")";
           if (boost::algorithm::ifind_first(query, "WHERE"))
           {
              boost::algorithm::ireplace_first(query, "WHERE", spatial_sql.str() + " AND ");
           }
           else if (boost::algorithm::ifind_first(query, geometry_table_))  
           {
              boost::algorithm::ireplace_first(query, table_, table_ + " " + spatial_sql.str());
           }
        }
        
        s << query ;
        
        if (row_limit_ > 0) {
            s << " LIMIT " << row_limit_;
        }

        if (row_offset_ > 0) {
            s << " OFFSET " << row_offset_;
        }

#ifdef MAPNIK_DEBUG
        std::clog << "Sqlite Plugin: " << s.str() << std::endl;
#endif

        boost::shared_ptr<sqlite_resultset> rs (dataset_->execute_query (s.str()));

        return boost::make_shared<sqlite_featureset>(rs, desc_.get_encoding(), format_, multiple_geometries_);
   }
      
   return featureset_ptr();
}
feature_ptr ogr_index_featureset<filterT>::next()
{
    if (itr_ != ids_.end())
    {
        int pos = *itr_++;
        layer_.SetNextByIndex (pos);

        ogr_feature_ptr feat (layer_.GetNextFeature());
        if ((*feat) != NULL)
        {
            // ogr feature ids start at 0, so add one to stay
            // consistent with other mapnik datasources that start at 1
            int feature_id = ((*feat)->GetFID() + 1);
            feature_ptr feature(feature_factory::create(feature_id));
            
            OGRGeometry* geom=(*feat)->GetGeometryRef();
            if (geom && !geom->IsEmpty())
            {
                ogr_converter::convert_geometry (geom, feature, multiple_geometries_);
            }
    #ifdef MAPNIK_DEBUG
            else
            {
                std::clog << "### Warning: feature with null geometry: " << (*feat)->GetFID() << "\n";
            }
    #endif
            
            int fld_count = layerdef_->GetFieldCount();
            for (int i = 0; i < fld_count; i++)
            {
                OGRFieldDefn* fld = layerdef_->GetFieldDefn (i);
                OGRFieldType type_oid = fld->GetType ();
                std::string fld_name = fld->GetNameRef ();
            
                switch (type_oid)
                {
                    case OFTInteger:
                    {
                       boost::put(*feature,fld_name,(*feat)->GetFieldAsInteger (i));
                       break;
                    }
                    
                    case OFTReal:
                    {
                       boost::put(*feature,fld_name,(*feat)->GetFieldAsDouble (i));
                       break;
                    }
                           
                    case OFTString:
                    case OFTWideString:     // deprecated !
                    {
                       UnicodeString ustr = tr_->transcode((*feat)->GetFieldAsString (i));
                       boost::put(*feature,fld_name,ustr);
                       break;
                    }
                    
                    case OFTIntegerList:
                    case OFTRealList:
                    case OFTStringList:
                    case OFTWideStringList: // deprecated !
                    {
                    #ifdef MAPNIK_DEBUG
                       std::clog << "OGR Plugin: unhandled type_oid=" << type_oid << std::endl;
                    #endif
                       break;
                    }
                    
                    case OFTBinary:
                    {
                    #ifdef MAPNIK_DEBUG
                       std::clog << "OGR Plugin: unhandled type_oid=" << type_oid << std::endl;
                    #endif
                       //boost::put(*feature,name,feat->GetFieldAsBinary (i, size));
                       break;
                    }
                       
                    case OFTDate:
                    case OFTTime:
                    case OFTDateTime:       // unhandled !
                    {
                    #ifdef MAPNIK_DEBUG
                       std::clog << "OGR Plugin: unhandled type_oid=" << type_oid << std::endl;
                    #endif
                       break;
                    }
                    
                    default: // unknown
                    {
                    #ifdef MAPNIK_DEBUG
                       std::clog << "OGR Plugin: unknown type_oid=" << type_oid << std::endl;
                    #endif
                       break;
                    }
                }
            }
            return feature;
        }
    }
    
    return feature_ptr();
}
Example #30
0
feature_ptr gdal_featureset::get_feature(mapnik::query const& q)
{
    feature_ptr feature = feature_factory::create(ctx_,1);

    GDALRasterBand * red = 0;
    GDALRasterBand * green = 0;
    GDALRasterBand * blue = 0;
    GDALRasterBand * alpha = 0;
    GDALRasterBand * grey = 0;

    /*
#ifdef MAPNIK_LOG
      double tr[6];
      dataset_.GetGeoTransform(tr);

      const double dx = tr[1];
      const double dy = tr[5];
      MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: dx_=" << dx_ << " dx=" << dx << " dy_=" << dy_ << "dy=" << dy;
#endif
    */

    CoordTransform t(raster_width_, raster_height_, raster_extent_, 0, 0);
    box2d<double> intersect = raster_extent_.intersect(q.get_bbox());
    box2d<double> box = t.forward(intersect);

    //size of resized output pixel in source image domain
    double margin_x = 1.0 / (fabs(dx_) * boost::get<0>(q.resolution()));
    double margin_y = 1.0 / (fabs(dy_) * boost::get<1>(q.resolution()));
    if (margin_x < 1)
    {
        margin_x = 1.0;
    }
    if (margin_y < 1)
    {
        margin_y = 1.0;
    }

    //select minimum raster containing whole box
    int x_off = rint(box.minx() - margin_x);
    int y_off = rint(box.miny() - margin_y);
    int end_x = rint(box.maxx() + margin_x);
    int end_y = rint(box.maxy() + margin_y);

    //clip to available data
    if (x_off < 0)
    {
        x_off = 0;
    }
    if (y_off < 0)
    {
        y_off = 0;
    }
    if (end_x > (int)raster_width_)
    {
        end_x = raster_width_;
    }
    if (end_y > (int)raster_height_)
    {
        end_y = raster_height_;
    }
    int width = end_x - x_off;
    int height = end_y - y_off;

    // don't process almost invisible data
    if (box.width() < 0.5)
    {
        width = 0;
    }
    if (box.height() < 0.5)
    {
        height = 0;
    }

    //calculate actual box2d of returned raster
    box2d<double> feature_raster_extent(x_off, y_off, x_off + width, y_off + height);
    intersect = t.backward(feature_raster_extent);

    MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Raster extent=" << raster_extent_;
    MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: View extent=" << intersect;
    MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Query resolution=" << boost::get<0>(q.resolution()) << "," << boost::get<1>(q.resolution());
    MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: StartX=" << x_off << " StartY=" << y_off << " Width=" << width << " Height=" << height;

    if (width > 0 && height > 0)
    {
        double width_res = boost::get<0>(q.resolution());
        double height_res = boost::get<1>(q.resolution());
        int im_width = int(width_res * intersect.width() + 0.5);
        int im_height = int(height_res * intersect.height() + 0.5);

        // if layer-level filter_factor is set, apply it
        if (filter_factor_)
        {
            im_width *= filter_factor_;
            im_height *= filter_factor_;

            MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Applying layer filter_factor=" << filter_factor_;
        }
        // otherwise respect symbolizer level factor applied to query, default of 1.0
        else
        {
            double sym_downsample_factor = q.get_filter_factor();
            im_width *= sym_downsample_factor;
            im_height *= sym_downsample_factor;
        }

        // case where we need to avoid upsampling so that the
        // image can be later scaled within raster_symbolizer
        if (im_width >= width || im_height >= height)
        {
            im_width = width;
            im_height = height;
        }

        if (im_width > 0 && im_height > 0)
        {
            mapnik::raster_ptr raster = boost::make_shared<mapnik::raster>(intersect, im_width, im_height);
            feature->set_raster(raster);
            mapnik::image_data_32 & image = raster->data_;
            image.set(0xffffffff);

            MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Image Size=(" << im_width << "," << im_height << ")";
            MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Reading band=" << band_;

            if (band_ > 0) // we are querying a single band
            {
                if (band_ > nbands_)
                {
                    throw datasource_exception((boost::format("GDAL Plugin: '%d' is an invalid band, dataset only has '%d' bands\n") % band_ % nbands_).str());
                }

                float* imageData = (float*)image.getBytes();
                GDALRasterBand * band = dataset_.GetRasterBand(band_);
                int hasNoData(0);
                double nodata(0);
                if (nodata_value_)
                {
                    hasNoData = 1;
                    nodata = *nodata_value_;
                }
                else
                {
                    nodata = band->GetNoDataValue(&hasNoData);
                }
                band->RasterIO(GF_Read, x_off, y_off, width, height,
                               imageData, image.width(), image.height(),
                               GDT_Float32, 0, 0);

                if (hasNoData)
                {
                    feature->put("NODATA",nodata);
                }
            }
            else // working with all bands
            {
                for (int i = 0; i < nbands_; ++i)
                {
                    GDALRasterBand * band = dataset_.GetRasterBand(i + 1);

#ifdef MAPNIK_LOG
                    get_overview_meta(band);
#endif

                    GDALColorInterp color_interp = band->GetColorInterpretation();
                    switch (color_interp)
                    {
                    case GCI_RedBand:
                        red = band;

                        MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Found red band";

                        break;
                    case GCI_GreenBand:
                        green = band;

                        MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Found green band";

                        break;
                    case GCI_BlueBand:
                        blue = band;

                        MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Found blue band";

                        break;
                    case GCI_AlphaBand:
                        alpha = band;

                        MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Found alpha band";

                        break;
                    case GCI_GrayIndex:
                        grey = band;

                        MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Found gray band";

                        break;
                    case GCI_PaletteIndex:
                    {
                        grey = band;

                        MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Found gray band, and colortable...";

                        GDALColorTable *color_table = band->GetColorTable();

                        if (color_table)
                        {
                            int count = color_table->GetColorEntryCount();

                            MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Color Table count=" << count;

                            for (int j = 0; j < count; j++)
                            {
                                const GDALColorEntry *ce = color_table->GetColorEntry (j);
                                if (! ce) continue;

                                MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Color entry RGB=" << ce->c1 << "," <<ce->c2 << "," << ce->c3;
                            }
                        }
                        break;
                    }
                    case GCI_Undefined:
                        MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Found undefined band (assumming gray band)";

                        grey = band;
                        break;
                    default:
                        MAPNIK_LOG_WARN(gdal) << "gdal_featureset: Band type unknown!";

                        break;
                    }
                }

                if (red && green && blue)
                {
                    MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Processing rgb bands...";

                    int hasNoData = 0;
                    double nodata = 0.0;
                    if (nodata_value_)
                    {
                        hasNoData = 1;
                        nodata = *nodata_value_;
                    }
                    else
                    {
                        nodata = red->GetNoDataValue(&hasNoData);
                    }
                    if (hasNoData)
                    {
                        feature->put("NODATA",nodata);
                    }
                    GDALColorTable *color_table = red->GetColorTable();

                    if (! alpha && hasNoData && ! color_table)
                    {
                        // first read the data in and create an alpha channel from the nodata values
                        float* imageData = (float*)image.getBytes();
                        red->RasterIO(GF_Read, x_off, y_off, width, height,
                                      imageData, image.width(), image.height(),
                                      GDT_Float32, 0, 0);

                        int len = image.width() * image.height();

                        for (int i = 0; i < len; ++i)
                        {
                            if (nodata == imageData[i])
                            {
                                *reinterpret_cast<unsigned *>(&imageData[i]) = 0;
                            }
                            else
                            {
                                *reinterpret_cast<unsigned *>(&imageData[i]) = 0xFFFFFFFF;
                            }
                        }

                    }

                    red->RasterIO(GF_Read, x_off, y_off, width, height, image.getBytes() + 0,
                                  image.width(), image.height(), GDT_Byte, 4, 4 * image.width());
                    green->RasterIO(GF_Read, x_off, y_off, width, height, image.getBytes() + 1,
                                    image.width(), image.height(), GDT_Byte, 4, 4 * image.width());
                    blue->RasterIO(GF_Read, x_off, y_off, width, height, image.getBytes() + 2,
                                   image.width(), image.height(), GDT_Byte, 4, 4 * image.width());
                }
                else if (grey)
                {
                    MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Processing gray band...";

                    int hasNoData(0);
                    double nodata(0);
                    if (nodata_value_)
                    {
                        hasNoData = 1;
                        nodata = *nodata_value_;
                    }
                    else
                    {
                        nodata = grey->GetNoDataValue(&hasNoData);
                    }
                    GDALColorTable* color_table = grey->GetColorTable();

                    if (hasNoData && ! color_table)
                    {
                        MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: No data value for layer=" << nodata;

                        feature->put("NODATA",nodata);
                        // first read the data in and create an alpha channel from the nodata values
                        float* imageData = (float*)image.getBytes();
                        grey->RasterIO(GF_Read, x_off, y_off, width, height,
                                       imageData, image.width(), image.height(),
                                       GDT_Float32, 0, 0);

                        int len = image.width() * image.height();

                        for (int i = 0; i < len; ++i)
                        {
                            if (nodata == imageData[i])
                            {
                                *reinterpret_cast<unsigned *>(&imageData[i]) = 0;
                            }
                            else
                            {
                                *reinterpret_cast<unsigned *> (&imageData[i]) = 0xFFFFFFFF;
                            }
                        }
                    }

                    grey->RasterIO(GF_Read, x_off, y_off, width, height, image.getBytes() + 0,
                                   image.width(), image.height(), GDT_Byte, 4, 4 * image.width());
                    grey->RasterIO(GF_Read,x_off, y_off, width, height, image.getBytes() + 1,
                                   image.width(), image.height(), GDT_Byte, 4, 4 * image.width());
                    grey->RasterIO(GF_Read,x_off, y_off, width, height, image.getBytes() + 2,
                                   image.width(), image.height(), GDT_Byte, 4, 4 * image.width());

                    if (color_table)
                    {
                        MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Loading colour table...";

                        unsigned nodata_value = static_cast<unsigned>(nodata);
                        if (hasNoData)
                        {
                            feature->put("NODATA",static_cast<int>(nodata_value));
                        }
                        for (unsigned y = 0; y < image.height(); ++y)
                        {
                            unsigned int* row = image.getRow(y);
                            for (unsigned x = 0; x < image.width(); ++x)
                            {
                                unsigned value = row[x] & 0xff;
                                if (hasNoData && (value == nodata_value))
                                {
                                    // make no data fully alpha
                                    row[x] = 0;
                                }
                                else
                                {
                                    const GDALColorEntry *ce = color_table->GetColorEntry(value);
                                    if (ce)
                                    {
                                        // TODO - big endian support
                                        row[x] = (ce->c4 << 24)| (ce->c3 << 16) |  (ce->c2 << 8) | (ce->c1) ;
                                    }
                                    else
                                    {
                                        // make lacking color entry fully alpha
                                        // note - gdal_translate makes black
                                        row[x] = 0;
                                    }
                                }
                            }
                        }
                    }
                }
                if (alpha)
                {
                    MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: processing alpha band...";

                    alpha->RasterIO(GF_Read, x_off, y_off, width, height, image.getBytes() + 3,
                                    image.width(), image.height(), GDT_Byte, 4, 4 * image.width());
                }
            }
            return feature;
        }
    }
    return feature_ptr();
}