+ added index facility by using a *.index file to OGR layers (10-15% faster than internal OGR spatial filter)

This commit is contained in:
Lucio Asnaghi 2009-05-11 22:06:48 +00:00
parent e4aab13cb7
commit 539f1bcf9b
11 changed files with 869 additions and 294 deletions

View file

@ -26,8 +26,10 @@ install_prefix = env['DESTDIR'] + '/' + prefix
ogr_src = Split(
"""
ogr_converter.cpp
ogr_datasource.cpp
ogr_featureset.cpp
ogr_index_featureset.cpp
"""
)

View file

@ -0,0 +1,277 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2007 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
//$Id$
#include <mapnik/global.hpp>
#include <mapnik/envelope.hpp>
#include <mapnik/geometry.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/feature_layer_desc.hpp>
#include <mapnik/wkb.hpp>
#include <mapnik/unicode.hpp>
// ogr
#include "ogr_converter.hpp"
using std::clog;
using std::endl;
using mapnik::feature_ptr;
using mapnik::geometry_utils;
using mapnik::geometry2d;
using mapnik::point_impl;
using mapnik::line_string_impl;
using mapnik::polygon_impl;
/*
using mapnik::query;
using mapnik::Envelope;
using mapnik::CoordTransform;
using mapnik::Feature;
*/
void ogr_converter::convert_geometry (OGRGeometry* geom, feature_ptr feature, bool multiple_geometries)
{
switch (wkbFlatten (geom->getGeometryType()))
{
case wkbPoint:
convert_point (static_cast<OGRPoint*>(geom), feature);
break;
case wkbLineString:
convert_linestring (static_cast<OGRLineString*>(geom), feature);
break;
case wkbPolygon:
convert_polygon (static_cast<OGRPolygon*>(geom), feature);
break;
case wkbMultiPoint:
if (multiple_geometries)
convert_multipoint_2 (static_cast<OGRMultiPoint*>(geom), feature);
else
convert_multipoint (static_cast<OGRMultiPoint*>(geom), feature);
break;
case wkbMultiLineString:
if (multiple_geometries)
convert_multilinestring_2 (static_cast<OGRMultiLineString*>(geom), feature);
else
convert_multilinestring (static_cast<OGRMultiLineString*>(geom), feature);
break;
case wkbMultiPolygon:
if (multiple_geometries)
convert_multipolygon_2 (static_cast<OGRMultiPolygon*>(geom), feature);
else
convert_multipolygon (static_cast<OGRMultiPolygon*>(geom), feature);
break;
case wkbGeometryCollection:
convert_collection (static_cast<OGRGeometryCollection*>(geom), feature, multiple_geometries);
break;
case wkbLinearRing:
convert_linestring (static_cast<OGRLinearRing*>(geom), feature);
break;
case wkbNone:
case wkbUnknown:
default:
#ifdef MAPNIK_DEBUG
clog << "unknown <ogr> geometry_type=" << wkbFlatten (geom->getGeometryType()) << endl;
#endif
break;
}
}
void ogr_converter::convert_point (OGRPoint* geom, feature_ptr feature)
{
geometry2d* point = new point_impl;
point->move_to (geom->getX(), geom->getY());
feature->add_geometry (point);
}
void ogr_converter::convert_linestring (OGRLineString* geom, feature_ptr feature)
{
int num_points = geom->getNumPoints ();
geometry2d * line = new line_string_impl;
line->set_capacity (num_points);
line->move_to (geom->getX (0), geom->getY (0));
for (int i=1;i<num_points;++i)
{
line->line_to (geom->getX (i), geom->getY (i));
}
feature->add_geometry (line);
}
void ogr_converter::convert_polygon (OGRPolygon* geom, feature_ptr feature)
{
OGRLinearRing* exterior = geom->getExteriorRing ();
int num_points = exterior->getNumPoints ();
int num_interior = geom->getNumInteriorRings ();
int capacity = 0;
for (int r=0;r<num_interior;r++)
{
OGRLinearRing* interior = geom->getInteriorRing (r);
capacity += interior->getNumPoints ();
}
geometry2d * poly = new polygon_impl;
poly->set_capacity (num_points + capacity);
poly->move_to (exterior->getX (0), exterior->getY (0));
for (int i=1;i<num_points;++i)
{
poly->line_to (exterior->getX (i), exterior->getY (i));
}
for (int r=0;r<num_interior;r++)
{
OGRLinearRing* interior = geom->getInteriorRing (r);
num_points = interior->getNumPoints ();
poly->move_to(interior->getX (0), interior->getY (0));
for (int i=1;i<num_points;++i)
{
poly->line_to(interior->getX (i), interior->getY (i));
}
}
feature->add_geometry (poly);
}
void ogr_converter::convert_multipoint (OGRMultiPoint* geom, feature_ptr feature)
{
int num_geometries = geom->getNumGeometries ();
geometry2d* point = new point_impl;
for (int i=0;i<num_geometries;i++)
{
OGRPoint* ogrpoint = static_cast<OGRPoint*>(geom->getGeometryRef (i));
point->move_to (ogrpoint->getX(), ogrpoint->getY());
}
}
void ogr_converter::convert_multipoint_2 (OGRMultiPoint* geom, feature_ptr feature)
{
int num_geometries = geom->getNumGeometries ();
for (int i=0;i<num_geometries;i++)
{
convert_point (static_cast<OGRPoint*>(geom->getGeometryRef (i)), feature);
}
}
void ogr_converter::convert_multilinestring (OGRMultiLineString* geom, feature_ptr feature)
{
int num_geometries = geom->getNumGeometries ();
int num_points = 0;
for (int i=0;i<num_geometries;i++)
{
OGRLineString* ls = static_cast<OGRLineString*>(geom->getGeometryRef (i));
num_points += ls->getNumPoints ();
}
geometry2d * line = new line_string_impl;
line->set_capacity (num_points);
for (int i=0;i<num_geometries;i++)
{
OGRLineString* ls = static_cast<OGRLineString*>(geom->getGeometryRef (i));
num_points = ls->getNumPoints ();
line->move_to (ls->getX (0), ls->getY (0));
for (int i=1;i<num_points;++i)
{
line->line_to (ls->getX (i), ls->getY (i));
}
}
feature->add_geometry (line);
}
void ogr_converter::convert_multilinestring_2 (OGRMultiLineString* geom, feature_ptr feature)
{
int num_geometries = geom->getNumGeometries ();
for (int i=0;i<num_geometries;i++)
{
convert_linestring (static_cast<OGRLineString*>(geom->getGeometryRef (i)), feature);
}
}
void ogr_converter::convert_multipolygon (OGRMultiPolygon* geom, feature_ptr feature)
{
int num_geometries = geom->getNumGeometries ();
int capacity = 0;
for (int i=0;i<num_geometries;i++)
{
OGRPolygon* p = static_cast<OGRPolygon*>(geom->getGeometryRef (i));
OGRLinearRing* exterior = p->getExteriorRing ();
capacity += exterior->getNumPoints ();
for (int r=0;r<p->getNumInteriorRings ();r++)
{
OGRLinearRing* interior = p->getInteriorRing (r);
capacity += interior->getNumPoints ();
}
}
geometry2d * poly = new polygon_impl;
poly->set_capacity (capacity);
for (int i=0;i<num_geometries;i++)
{
OGRPolygon* p = static_cast<OGRPolygon*>(geom->getGeometryRef (i));
OGRLinearRing* exterior = p->getExteriorRing ();
int num_points = exterior->getNumPoints ();
int num_interior = p->getNumInteriorRings ();
poly->move_to (exterior->getX (0), exterior->getY (0));
for (int i=1;i<num_points;++i)
{
poly->line_to (exterior->getX (i), exterior->getY (i));
}
for (int r=0;r<num_interior;r++)
{
OGRLinearRing* interior = p->getInteriorRing (r);
num_points = interior->getNumPoints ();
poly->move_to(interior->getX (0), interior->getY (0));
for (int i=1;i<num_points;++i)
{
poly->line_to(interior->getX (i), interior->getY (i));
}
}
}
feature->add_geometry (poly);
}
void ogr_converter::convert_multipolygon_2 (OGRMultiPolygon* geom, feature_ptr feature)
{
int num_geometries = geom->getNumGeometries ();
for (int i=0;i<num_geometries;i++)
{
convert_polygon (static_cast<OGRPolygon*>(geom->getGeometryRef (i)), feature);
}
}
void ogr_converter::convert_collection (OGRGeometryCollection* geom, feature_ptr feature, bool multiple_geometries)
{
int num_geometries = geom->getNumGeometries ();
for (int i=0;i<num_geometries;i++)
{
OGRGeometry* g = geom->getGeometryRef (i);
if (g != NULL)
{
convert_geometry (g, feature, multiple_geometries);
}
}
}

View file

@ -0,0 +1,50 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2007 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
//$Id$
#ifndef OGR_CONVERTER_HPP
#define OGR_CONVERTER_HPP
// mapnik
#include <mapnik/datasource.hpp>
// ogr
#include <ogrsf_frmts.h>
class ogr_converter
{
public:
static void convert_geometry (OGRGeometry* geom, mapnik::feature_ptr feature, bool multiple_geometries);
static void convert_collection (OGRGeometryCollection* geom, mapnik::feature_ptr feature, bool multiple_geometries);
static void convert_point (OGRPoint* geom, mapnik::feature_ptr feature);
static void convert_linestring (OGRLineString* geom, mapnik::feature_ptr feature);
static void convert_polygon (OGRPolygon* geom, mapnik::feature_ptr feature);
static void convert_multipoint (OGRMultiPoint* geom, mapnik::feature_ptr feature);
static void convert_multipoint_2 (OGRMultiPoint* geom, mapnik::feature_ptr feature);
static void convert_multilinestring (OGRMultiLineString* geom, mapnik::feature_ptr feature);
static void convert_multilinestring_2 (OGRMultiLineString* geom, mapnik::feature_ptr feature);
static void convert_multipolygon (OGRMultiPolygon* geom, mapnik::feature_ptr feature);
static void convert_multipolygon_2 (OGRMultiPolygon* geom, mapnik::feature_ptr feature);
};
#endif // OGR_FEATURESET_HPP

View file

@ -21,11 +21,20 @@
*****************************************************************************/
// $Id$
#include <iostream>
#include <fstream>
#include <stdexcept>
#include "ogr_datasource.hpp"
#include "ogr_featureset.hpp"
#include "ogr_index_featureset.hpp"
// mapnik
#include <mapnik/ptree_helpers.hpp>
#include <mapnik/geom_util.hpp>
// boost
#include <boost/algorithm/string.hpp>
#include <boost/filesystem/operations.hpp>
using std::clog;
@ -43,13 +52,16 @@ using mapnik::featureset_ptr;
using mapnik::layer_descriptor;
using mapnik::attribute_descriptor;
using mapnik::datasource_exception;
using mapnik::filter_in_box;
using mapnik::filter_at_point;
ogr_datasource::ogr_datasource(parameters const& params)
: datasource(params),
extent_(),
type_(datasource::Vector),
desc_(*params.get<std::string>("type"), *params.get<std::string>("encoding","utf-8"))
desc_(*params.get<std::string>("type"), *params.get<std::string>("encoding","utf-8")),
indexed_(false)
{
OGRRegisterAll();
@ -63,7 +75,8 @@ ogr_datasource::ogr_datasource(parameters const& params)
dataset_name_ = *base + "/" + *file;
else
dataset_name_ = *file;
// open ogr driver
dataset_ = OGRSFDriverRegistrar::Open ((dataset_name_).c_str(), FALSE);
if (!dataset_)
{
@ -76,6 +89,7 @@ ogr_datasource::ogr_datasource(parameters const& params)
}
}
// initialize layer
boost::optional<std::string> layer = params.get<std::string>("layer");
if (!layer)
{
@ -100,10 +114,23 @@ ogr_datasource::ogr_datasource(parameters const& params)
layer_ = dataset_->GetLayerByName (layerName_.c_str());
if (! layer_) throw datasource_exception("cannot find <layer> in dataset");
// initialize envelope
OGREnvelope envelope;
layer_->GetExtent (&envelope);
extent_.init (envelope.MinX, envelope.MinY, envelope.MaxX, envelope.MaxY);
// scan for index file
int breakpoint = dataset_name_.find_last_of (".");
if (breakpoint == std::string::npos) breakpoint = dataset_name_.length();
index_name_ = dataset_name_.substr(0, breakpoint) + ".index";
std::ifstream index_file (index_name_.c_str(), std::ios::in | std::ios::binary);
if (index_file)
{
indexed_=true;
index_file.close();
}
// deal with attributes descriptions
OGRFeatureDefn* def = layer_->GetLayerDefn ();
if (def != 0)
{
@ -191,13 +218,6 @@ featureset_ptr ogr_datasource::features(query const& q) const
{
if (dataset_ && layer_)
{
mapnik::Envelope<double> const& query_extent = q.get_bbox();
layer_->SetSpatialFilterRect (query_extent.minx(),
query_extent.miny(),
query_extent.maxx(),
query_extent.maxy());
#if 0
std::ostringstream s;
@ -219,7 +239,25 @@ featureset_ptr ogr_datasource::features(query const& q) const
dataset_->ReleaseResultSet (layer);
#endif
return featureset_ptr(new ogr_featureset(*dataset_, *layer_, desc_.get_encoding(), multiple_geometries_));
if (indexed_)
{
filter_in_box filter(q.get_bbox());
return featureset_ptr(new ogr_index_featureset<filter_in_box> (*dataset_,
*layer_,
filter,
index_name_,
desc_.get_encoding(),
multiple_geometries_));
}
else
{
return featureset_ptr(new ogr_featureset (*dataset_,
*layer_,
q.get_bbox(),
desc_.get_encoding(),
multiple_geometries_));
}
}
return featureset_ptr();
}
@ -228,13 +266,29 @@ featureset_ptr ogr_datasource::features_at_point(coord2d const& pt) const
{
if (dataset_ && layer_)
{
OGRPoint point;
point.setX (pt.x);
point.setY (pt.y);
if (indexed_)
{
filter_at_point filter(pt);
return featureset_ptr(new ogr_index_featureset<filter_at_point> (*dataset_,
*layer_,
filter,
index_name_,
desc_.get_encoding(),
multiple_geometries_));
}
else
{
OGRPoint point;
point.setX (pt.x);
point.setY (pt.y);
layer_->SetSpatialFilter (&point);
return featureset_ptr(new ogr_featureset(*dataset_, *layer_, desc_.get_encoding(), multiple_geometries_));
return featureset_ptr(new ogr_featureset (*dataset_,
*layer_,
point,
desc_.get_encoding(),
multiple_geometries_));
}
}
return featureset_ptr();
}

View file

@ -50,11 +50,13 @@ class ogr_datasource : public mapnik::datasource
mapnik::Envelope<double> extent_;
int type_;
std::string dataset_name_;
std::string index_name_;
OGRDataSource* dataset_;
OGRLayer* layer_;
std::string layerName_;
mapnik::layer_descriptor desc_;
bool multiple_geometries_;
bool indexed_;
};

View file

@ -0,0 +1,54 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2007 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
//$Id$
#ifndef OGR_FEATURE_PTR_HPP
#define OGR_FEATURE_PTR_HPP
// ogr
#include <ogrsf_frmts.h>
class ogr_feature_ptr
{
public:
ogr_feature_ptr (OGRFeature* const feat)
: feat_ (feat)
{
}
~ogr_feature_ptr ()
{
if (feat_ != NULL)
OGRFeature::DestroyFeature (feat_);
}
OGRFeature* operator*()
{
return feat_;
}
private:
OGRFeature* feat_;
};
#endif // OGR_FEATURE_PTR_HPP

View file

@ -32,6 +32,8 @@
// ogr
#include "ogr_featureset.hpp"
#include "ogr_converter.hpp"
#include "ogr_feature_ptr.hpp"
using std::clog;
using std::endl;
@ -41,50 +43,43 @@ using mapnik::Envelope;
using mapnik::CoordTransform;
using mapnik::Feature;
using mapnik::feature_ptr;
using mapnik::point_impl;
using mapnik::line_string_impl;
using mapnik::polygon_impl;
using mapnik::geometry2d;
using mapnik::geometry_utils;
using mapnik::transcoder;
class ogr_feature_ptr
{
public:
ogr_feature_ptr (OGRFeature* const feat)
: feat_ (feat)
{
}
~ogr_feature_ptr ()
{
if (feat_ != NULL)
OGRFeature::DestroyFeature (feat_);
}
OGRFeature* operator*()
{
return feat_;
}
private:
OGRFeature* feat_;
};
ogr_featureset::ogr_featureset(OGRDataSource & dataset,
OGRLayer & layer,
std::string const& encoding,
bool multiple_geometries)
OGRGeometry & extent,
const std::string& encoding,
const bool multiple_geometries)
: dataset_(dataset),
layer_(layer),
layerdef_(layer.GetLayerDefn()),
tr_(new transcoder(encoding)),
fidcolumn_(layer_.GetFIDColumn ()),
multiple_geometries_(multiple_geometries)
multiple_geometries_(multiple_geometries),
count_(0)
{
layer_.ResetReading ();
layer_.SetSpatialFilter (&extent);
}
ogr_featureset::ogr_featureset(OGRDataSource & dataset,
OGRLayer & layer,
const mapnik::Envelope<double> & extent,
const std::string& encoding,
const bool multiple_geometries)
: dataset_(dataset),
layer_(layer),
layerdef_(layer.GetLayerDefn()),
tr_(new transcoder(encoding)),
fidcolumn_(layer_.GetFIDColumn ()),
multiple_geometries_(multiple_geometries),
count_(0)
{
layer_.SetSpatialFilterRect (extent.minx(),
extent.miny(),
extent.maxx(),
extent.maxy());
}
ogr_featureset::~ogr_featureset() {}
@ -99,7 +94,8 @@ feature_ptr ogr_featureset::next()
{
feature_ptr feature(new Feature((*feat)->GetFID()));
convert_geometry (geom, feature);
ogr_converter::convert_geometry (geom, feature, multiple_geometries_);
++count_;
int fld_count = layerdef_->GetFieldCount();
for (int i = 0; i < fld_count; i++)
@ -174,232 +170,9 @@ feature_ptr ogr_featureset::next()
}
}
#ifdef MAPNIK_DEBUG
clog << count_ << " features" << endl;
#endif
return feature_ptr();
}
void ogr_featureset::convert_geometry (OGRGeometry* geom, feature_ptr feature)
{
switch (wkbFlatten (geom->getGeometryType()))
{
case wkbPoint:
convert_point (static_cast<OGRPoint*>(geom), feature);
break;
case wkbLineString:
convert_linestring (static_cast<OGRLineString*>(geom), feature);
break;
case wkbPolygon:
convert_polygon (static_cast<OGRPolygon*>(geom), feature);
break;
case wkbMultiPoint:
if (multiple_geometries_)
convert_multipoint_2 (static_cast<OGRMultiPoint*>(geom), feature);
else
convert_multipoint (static_cast<OGRMultiPoint*>(geom), feature);
break;
case wkbMultiLineString:
if (multiple_geometries_)
convert_multilinestring_2 (static_cast<OGRMultiLineString*>(geom), feature);
else
convert_multilinestring (static_cast<OGRMultiLineString*>(geom), feature);
break;
case wkbMultiPolygon:
if (multiple_geometries_)
convert_multipolygon_2 (static_cast<OGRMultiPolygon*>(geom), feature);
else
convert_multipolygon (static_cast<OGRMultiPolygon*>(geom), feature);
break;
case wkbGeometryCollection:
convert_collection (static_cast<OGRGeometryCollection*>(geom), feature);
break;
case wkbLinearRing:
convert_linestring (static_cast<OGRLinearRing*>(geom), feature);
break;
case wkbNone:
case wkbUnknown:
default:
#ifdef MAPNIK_DEBUG
clog << "unknown <ogr> geometry_type=" << wkbFlatten (geom->getGeometryType()) << endl;
#endif
break;
}
}
void ogr_featureset::convert_point (OGRPoint* geom, feature_ptr feature)
{
geometry2d* point = new point_impl;
point->move_to (geom->getX(), geom->getY());
feature->add_geometry (point);
}
void ogr_featureset::convert_linestring (OGRLineString* geom, feature_ptr feature)
{
int num_points = geom->getNumPoints ();
geometry2d * line = new line_string_impl;
line->set_capacity (num_points);
line->move_to (geom->getX (0), geom->getY (0));
for (int i=1;i<num_points;++i)
{
line->line_to (geom->getX (i), geom->getY (i));
}
feature->add_geometry (line);
}
void ogr_featureset::convert_polygon (OGRPolygon* geom, feature_ptr feature)
{
OGRLinearRing* exterior = geom->getExteriorRing ();
int num_points = exterior->getNumPoints ();
int num_interior = geom->getNumInteriorRings ();
int capacity = 0;
for (int r=0;r<num_interior;r++)
{
OGRLinearRing* interior = geom->getInteriorRing (r);
capacity += interior->getNumPoints ();
}
geometry2d * poly = new polygon_impl;
poly->set_capacity (num_points + capacity);
poly->move_to (exterior->getX (0), exterior->getY (0));
for (int i=1;i<num_points;++i)
{
poly->line_to (exterior->getX (i), exterior->getY (i));
}
for (int r=0;r<num_interior;r++)
{
OGRLinearRing* interior = geom->getInteriorRing (r);
num_points = interior->getNumPoints ();
poly->move_to(interior->getX (0), interior->getY (0));
for (int i=1;i<num_points;++i)
{
poly->line_to(interior->getX (i), interior->getY (i));
}
}
feature->add_geometry (poly);
}
void ogr_featureset::convert_multipoint (OGRMultiPoint* geom, feature_ptr feature)
{
int num_geometries = geom->getNumGeometries ();
geometry2d* point = new point_impl;
for (int i=0;i<num_geometries;i++)
{
OGRPoint* ogrpoint = static_cast<OGRPoint*>(geom->getGeometryRef (i));
point->move_to (ogrpoint->getX(), ogrpoint->getY());
}
}
void ogr_featureset::convert_multipoint_2 (OGRMultiPoint* geom, feature_ptr feature)
{
int num_geometries = geom->getNumGeometries ();
for (int i=0;i<num_geometries;i++)
{
convert_point (static_cast<OGRPoint*>(geom->getGeometryRef (i)), feature);
}
}
void ogr_featureset::convert_multilinestring (OGRMultiLineString* geom, feature_ptr feature)
{
int num_geometries = geom->getNumGeometries ();
int num_points = 0;
for (int i=0;i<num_geometries;i++)
{
OGRLineString* ls = static_cast<OGRLineString*>(geom->getGeometryRef (i));
num_points += ls->getNumPoints ();
}
geometry2d * line = new line_string_impl;
line->set_capacity (num_points);
for (int i=0;i<num_geometries;i++)
{
OGRLineString* ls = static_cast<OGRLineString*>(geom->getGeometryRef (i));
num_points = ls->getNumPoints ();
line->move_to (ls->getX (0), ls->getY (0));
for (int i=1;i<num_points;++i)
{
line->line_to (ls->getX (i), ls->getY (i));
}
}
feature->add_geometry (line);
}
void ogr_featureset::convert_multilinestring_2 (OGRMultiLineString* geom, feature_ptr feature)
{
int num_geometries = geom->getNumGeometries ();
for (int i=0;i<num_geometries;i++)
{
convert_linestring (static_cast<OGRLineString*>(geom->getGeometryRef (i)), feature);
}
}
void ogr_featureset::convert_multipolygon (OGRMultiPolygon* geom, feature_ptr feature)
{
int num_geometries = geom->getNumGeometries ();
int capacity = 0;
for (int i=0;i<num_geometries;i++)
{
OGRPolygon* p = static_cast<OGRPolygon*>(geom->getGeometryRef (i));
OGRLinearRing* exterior = p->getExteriorRing ();
capacity += exterior->getNumPoints ();
for (int r=0;r<p->getNumInteriorRings ();r++)
{
OGRLinearRing* interior = p->getInteriorRing (r);
capacity += interior->getNumPoints ();
}
}
geometry2d * poly = new polygon_impl;
poly->set_capacity (capacity);
for (int i=0;i<num_geometries;i++)
{
OGRPolygon* p = static_cast<OGRPolygon*>(geom->getGeometryRef (i));
OGRLinearRing* exterior = p->getExteriorRing ();
int num_points = exterior->getNumPoints ();
int num_interior = p->getNumInteriorRings ();
poly->move_to (exterior->getX (0), exterior->getY (0));
for (int i=1;i<num_points;++i)
{
poly->line_to (exterior->getX (i), exterior->getY (i));
}
for (int r=0;r<num_interior;r++)
{
OGRLinearRing* interior = p->getInteriorRing (r);
num_points = interior->getNumPoints ();
poly->move_to(interior->getX (0), interior->getY (0));
for (int i=1;i<num_points;++i)
{
poly->line_to(interior->getX (i), interior->getY (i));
}
}
}
feature->add_geometry (poly);
}
void ogr_featureset::convert_multipolygon_2 (OGRMultiPolygon* geom, feature_ptr feature)
{
int num_geometries = geom->getNumGeometries ();
for (int i=0;i<num_geometries;i++)
{
convert_polygon (static_cast<OGRPolygon*>(geom->getGeometryRef (i)), feature);
}
}
void ogr_featureset::convert_collection (OGRGeometryCollection* geom, feature_ptr feature)
{
int num_geometries = geom->getNumGeometries ();
for (int i=0;i<num_geometries;i++)
{
OGRGeometry* g = geom->getGeometryRef (i);
if (g != NULL)
{
convert_geometry (g, feature);
}
}
}

View file

@ -27,6 +27,7 @@
// mapnik
#include <mapnik/datasource.hpp>
#include <mapnik/unicode.hpp>
#include <mapnik/geom_util.hpp>
// boost
#include <boost/scoped_ptr.hpp>
@ -36,31 +37,30 @@
class ogr_featureset : public mapnik::Featureset
{
public:
ogr_featureset(OGRDataSource & dataset,
OGRLayer & layer,
std::string const& encoding,
bool multiple_geometries);
virtual ~ogr_featureset();
mapnik::feature_ptr next();
private:
void convert_geometry (OGRGeometry* geom, mapnik::feature_ptr feature);
void convert_point (OGRPoint* geom, mapnik::feature_ptr feature);
void convert_linestring (OGRLineString* geom, mapnik::feature_ptr feature);
void convert_polygon (OGRPolygon* geom, mapnik::feature_ptr feature);
void convert_multipoint (OGRMultiPoint* geom, mapnik::feature_ptr feature);
void convert_multipoint_2 (OGRMultiPoint* geom, mapnik::feature_ptr feature);
void convert_multilinestring (OGRMultiLineString* geom, mapnik::feature_ptr feature);
void convert_multilinestring_2 (OGRMultiLineString* geom, mapnik::feature_ptr feature);
void convert_multipolygon (OGRMultiPolygon* geom, mapnik::feature_ptr feature);
void convert_multipolygon_2 (OGRMultiPolygon* geom, mapnik::feature_ptr feature);
void convert_collection (OGRGeometryCollection* geom, mapnik::feature_ptr feature);
OGRDataSource & dataset_;
OGRLayer & layer_;
OGRFeatureDefn * layerdef_;
boost::scoped_ptr<mapnik::transcoder> tr_;
const char* fidcolumn_;
bool multiple_geometries_;
mutable int count_;
public:
ogr_featureset(OGRDataSource & dataset,
OGRLayer & layer,
OGRGeometry & extent,
const std::string& encoding,
const bool multiple_geometries);
ogr_featureset(OGRDataSource & dataset,
OGRLayer & layer,
const mapnik::Envelope<double> & extent,
const std::string& encoding,
const bool multiple_geometries);
virtual ~ogr_featureset();
mapnik::feature_ptr next();
private:
ogr_featureset(const ogr_featureset&);
const ogr_featureset& operator=(const ogr_featureset&);
};
#endif // OGR_FEATURESET_HPP

View file

@ -0,0 +1,105 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
#ifndef OGR_INDEX_HH
#define OGR_INDEX_HH
// st
#include <fstream>
#include <vector>
// mapnik
#include <mapnik/envelope.hpp>
#include <mapnik/query.hpp>
using mapnik::Envelope;
using mapnik::query;
template <typename filterT, typename IStream = std::ifstream>
class ogr_index
{
public:
static void query(const filterT& filter, IStream& file,std::vector<int>& pos);
private:
ogr_index();
~ogr_index();
ogr_index(const ogr_index&);
ogr_index& operator=(const ogr_index&);
static int read_ndr_integer(IStream & in);
static void read_envelope(IStream & in,Envelope<double> &envelope);
static void query_node(const filterT& filter,IStream & in,std::vector<int>& pos);
};
template <typename filterT,typename IStream>
void ogr_index<filterT, IStream>::query(const filterT& filter,IStream & file,std::vector<int>& pos)
{
file.seekg(16,std::ios::beg);
query_node(filter,file,pos);
}
template <typename filterT, typename IStream>
void ogr_index<filterT,IStream>::query_node(const filterT& filter,IStream & file,std::vector<int>& ids)
{
int offset=read_ndr_integer(file);
Envelope<double> node_ext;
read_envelope(file,node_ext);
int num_shapes=read_ndr_integer(file);
if (!filter.pass(node_ext))
{
file.seekg(offset+num_shapes*4+4,std::ios::cur);
return;
}
for (int i=0;i<num_shapes;++i)
{
int id=read_ndr_integer(file);
ids.push_back(id);
}
int children=read_ndr_integer(file);
for (int j=0;j<children;++j)
{
query_node(filter,file,ids);
}
}
template <typename filterT,typename IStream>
int ogr_index<filterT,IStream>::read_ndr_integer(IStream & file)
{
char b[4];
file.read(b,4);
return (b[0]&0xff) | (b[1]&0xff)<<8 | (b[2]&0xff)<<16 | (b[3]&0xff)<<24;
}
template <typename filterT,typename IStream>
void ogr_index<filterT,IStream>::read_envelope(IStream & file,Envelope<double>& envelope)
{
file.read(reinterpret_cast<char*>(&envelope),sizeof(envelope));
}
#endif //SHP_INDEX_HH

View file

@ -0,0 +1,197 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2007 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
//$Id$
// mapnik
#include <mapnik/global.hpp>
#include <mapnik/datasource.hpp>
#include <mapnik/envelope.hpp>
#include <mapnik/geometry.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/feature_layer_desc.hpp>
#include <mapnik/wkb.hpp>
#include <mapnik/unicode.hpp>
// boost
#include <boost/iostreams/stream.hpp>
#include <boost/iostreams/device/file.hpp>
#include <boost/iostreams/device/mapped_file.hpp>
// ogr
#include "ogr_index_featureset.hpp"
#include "ogr_converter.hpp"
#include "ogr_index.hpp"
#include "ogr_feature_ptr.hpp"
using std::clog;
using std::endl;
using mapnik::query;
using mapnik::Envelope;
using mapnik::CoordTransform;
using mapnik::Feature;
using mapnik::feature_ptr;
using mapnik::geometry_utils;
using mapnik::transcoder;
using namespace boost::iostreams;
template <typename filterT>
ogr_index_featureset<filterT>::ogr_index_featureset(OGRDataSource & dataset,
OGRLayer & layer,
const filterT& filter,
const std::string& index_file,
const std::string& encoding,
const bool multiple_geometries)
: dataset_(dataset),
layer_(layer),
layerdef_(layer.GetLayerDefn()),
filter_(filter),
tr_(new transcoder(encoding)),
fidcolumn_(layer_.GetFIDColumn ()),
multiple_geometries_(multiple_geometries),
count_(0)
{
stream<mapped_file_source> file (index_file);
if (file)
{
ogr_index<filterT,stream<mapped_file_source> >::query(filter,file,ids_);
file.close();
}
std::sort(ids_.begin(),ids_.end());
#ifdef MAPNIK_DEBUG
std::clog<< "query size=" << ids_.size() << "\n";
#endif
itr_ = ids_.begin();
// reset reading
layer_.ResetReading();
}
template <typename filterT>
ogr_index_featureset<filterT>::~ogr_index_featureset() {}
template <typename filterT>
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)
{
OGRGeometry* geom=(*feat)->GetGeometryRef();
if (!geom->IsEmpty())
{
feature_ptr feature(new Feature((*feat)->GetFID()));
ogr_converter::convert_geometry (geom, feature, multiple_geometries_);
++count_;
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
clog << "unhandled type_oid=" << type_oid << endl;
#endif
break;
}
case OFTBinary:
{
#ifdef MAPNIK_DEBUG
clog << "unhandled type_oid=" << type_oid << endl;
#endif
//boost::put(*feature,name,feat->GetFieldAsBinary (i, size));
break;
}
case OFTDate:
case OFTTime:
case OFTDateTime: // unhandled !
{
#ifdef MAPNIK_DEBUG
clog << "unhandled type_oid=" << type_oid << endl;
#endif
break;
}
default: // unknown
{
#ifdef MAPNIK_DEBUG
clog << "unknown type_oid=" << type_oid << endl;
#endif
break;
}
}
}
return feature;
}
}
}
#ifdef MAPNIK_DEBUG
clog << count_ << " features" << endl;
#endif
return feature_ptr();
}
template class ogr_index_featureset<mapnik::filter_in_box>;
template class ogr_index_featureset<mapnik::filter_at_point>;

View file

@ -0,0 +1,61 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2007 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
//$Id$
#ifndef OGR_INDEX_FEATURESET_HPP
#define OGR_INDEX_FEATURESET_HPP
#include <set>
#include <vector>
#include <boost/scoped_ptr.hpp>
#include "ogr_featureset.hpp"
template <typename filterT>
class ogr_index_featureset : public mapnik::Featureset
{
OGRDataSource & dataset_;
OGRLayer & layer_;
OGRFeatureDefn * layerdef_;
filterT filter_;
std::vector<int> ids_;
std::vector<int>::iterator itr_;
boost::scoped_ptr<mapnik::transcoder> tr_;
const char* fidcolumn_;
bool multiple_geometries_;
mutable int count_;
public:
ogr_index_featureset(OGRDataSource & dataset,
OGRLayer & layer,
const filterT& filter,
const std::string& index_file,
const std::string& encoding,
const bool multiple_geometries);
virtual ~ogr_index_featureset();
mapnik::feature_ptr next();
private:
//no copying
ogr_index_featureset(const ogr_index_featureset&);
ogr_index_featureset& operator=(const ogr_index_featureset&);
};
#endif // OGR_FEATURESET_HPP