mapnik/plugins/input/occi/occi_featureset.cpp

518 lines
18 KiB
C++
Raw Normal View History

/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
2014-11-20 15:25:50 +01:00
* Copyright (C) 2014 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
*
*****************************************************************************/
2010-11-22 12:40:08 +01:00
// mapnik
#include <mapnik/global.hpp>
2012-04-08 02:20:56 +02:00
#include <mapnik/debug.hpp>
2009-12-16 21:02:06 +01:00
#include <mapnik/box2d.hpp>
#include <mapnik/geometry.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/feature_layer_desc.hpp>
#include <mapnik/wkb.hpp>
#include <mapnik/unicode.hpp>
#include <mapnik/value_types.hpp>
#include <mapnik/feature_factory.hpp>
2015-02-17 08:09:16 +01:00
#include <mapnik/make_unique.hpp>
// ogr
#include "occi_featureset.hpp"
using mapnik::query;
2009-12-16 21:02:06 +01:00
using mapnik::box2d;
using mapnik::feature_ptr;
using mapnik::geometry_type;
using mapnik::geometry_utils;
using mapnik::transcoder;
using mapnik::datasource_exception;
2011-05-23 17:54:58 +02:00
using mapnik::feature_factory;
using oracle::occi::Connection;
using oracle::occi::Statement;
using oracle::occi::ResultSet;
using oracle::occi::StatelessConnectionPool;
using oracle::occi::MetaData;
using oracle::occi::SQLException;
using oracle::occi::Type;
using oracle::occi::Number;
2010-11-22 12:40:08 +01:00
using oracle::occi::Blob;
occi_featureset::occi_featureset(StatelessConnectionPool* pool,
Connection* conn,
mapnik::context_ptr const& ctx,
std::string const& sqlstring,
std::string const& encoding,
bool use_connection_pool,
2012-04-08 02:20:56 +02:00
bool use_wkb,
unsigned prefetch_rows)
2013-11-27 16:52:47 +01:00
: rs_(nullptr),
tr_(new transcoder(encoding)),
feature_id_(1),
2012-04-08 02:20:56 +02:00
ctx_(ctx),
use_wkb_(use_wkb)
{
if (use_connection_pool)
{
conn_.set_pool(pool);
}
else
{
conn_.set_connection(conn, false);
}
try
{
rs_ = conn_.execute_query(sqlstring, prefetch_rows);
}
catch (SQLException &ex)
{
MAPNIK_LOG_ERROR(occi) << "OCCI Plugin: error processing " << sqlstring << " : " << ex.getMessage();
2013-11-27 16:52:47 +01:00
rs_ = nullptr;
}
}
occi_featureset::~occi_featureset()
{
}
feature_ptr occi_featureset::next()
{
2013-11-27 16:52:47 +01:00
while (rs_ != nullptr && rs_->next() == oracle::occi::ResultSet::DATA_AVAILABLE)
{
feature_ptr feature(feature_factory::create(ctx_, feature_id_));
2012-04-08 02:20:56 +02:00
if (use_wkb_)
{
Blob blob = rs_->getBlob(1);
2012-04-08 02:20:56 +02:00
blob.open(oracle::occi::OCCI_LOB_READONLY);
unsigned int size = blob.length();
2012-04-08 02:20:56 +02:00
if (buffer_.size() < size)
{
buffer_.resize(size);
}
oracle::occi::Stream* instream = blob.getStream(1, 0);
2012-04-08 02:20:56 +02:00
instream->readBuffer(buffer_.data(), size);
blob.closeStream(instream);
blob.close();
if (! geometry_utils::from_wkb(feature->paths(), buffer_.data(), size))
{
continue;
}
2012-04-08 02:20:56 +02:00
}
else
{
const std::unique_ptr<SDOGeometry> geom(dynamic_cast<SDOGeometry*>(rs_->getObject(1)));
2012-04-08 02:20:56 +02:00
if (geom.get())
{
convert_geometry(geom.get(), feature);
}
else
{
continue;
}
}
2009-02-05 12:17:27 +01:00
std::vector<MetaData> listOfColumns = rs_->getColumnListMetaData();
for (unsigned int i = 1; i < listOfColumns.size(); ++i)
{
2010-11-22 12:40:08 +01:00
MetaData columnObj = listOfColumns[i];
2010-11-22 12:40:08 +01:00
std::string fld_name = columnObj.getString(MetaData::ATTR_NAME);
int type_oid = columnObj.getInt(MetaData::ATTR_DATA_TYPE);
/*
2011-11-14 04:54:32 +01:00
int type_code = columnObj.getInt(MetaData::ATTR_TYPECODE);
if (type_code == OCCI_TYPECODE_OBJECT)
{
continue;
}
2010-11-22 12:40:08 +01:00
*/
2010-11-22 12:40:08 +01:00
switch (type_oid)
{
case oracle::occi::OCCIBOOL:
feature->put(fld_name, (rs_->getInt(i + 1) != 0));
break;
case oracle::occi::OCCIINT:
case oracle::occi::OCCIUNSIGNED_INT:
feature->put(fld_name, static_cast<mapnik::value_integer>(rs_->getInt(i + 1)));
break;
case oracle::occi::OCCIFLOAT:
case oracle::occi::OCCIBFLOAT:
feature->put(fld_name, (double)rs_->getFloat(i + 1));
break;
case oracle::occi::OCCIDOUBLE:
case oracle::occi::OCCIBDOUBLE:
case oracle::occi::OCCINUMBER:
case oracle::occi::OCCI_SQLT_NUM:
feature->put(fld_name, rs_->getDouble(i + 1));
break;
case oracle::occi::OCCICHAR:
case oracle::occi::OCCISTRING:
case oracle::occi::OCCI_SQLT_AFC:
case oracle::occi::OCCI_SQLT_AVC:
case oracle::occi::OCCI_SQLT_CHR:
case oracle::occi::OCCI_SQLT_LNG:
case oracle::occi::OCCI_SQLT_LVC:
case oracle::occi::OCCI_SQLT_STR:
case oracle::occi::OCCI_SQLT_VCS:
case oracle::occi::OCCI_SQLT_VNU:
case oracle::occi::OCCI_SQLT_VBI:
case oracle::occi::OCCI_SQLT_VST:
case oracle::occi::OCCIROWID:
case oracle::occi::OCCI_SQLT_RDD:
case oracle::occi::OCCI_SQLT_RID:
case oracle::occi::OCCIDATE:
case oracle::occi::OCCI_SQLT_DAT:
case oracle::occi::OCCI_SQLT_DATE:
case oracle::occi::OCCI_SQLT_TIME:
case oracle::occi::OCCI_SQLT_TIME_TZ:
case oracle::occi::OCCITIMESTAMP:
case oracle::occi::OCCI_SQLT_TIMESTAMP:
case oracle::occi::OCCI_SQLT_TIMESTAMP_LTZ:
case oracle::occi::OCCI_SQLT_TIMESTAMP_TZ:
feature->put(fld_name, static_cast<mapnik::value_unicode_string>(tr_->transcode(rs_->getString(i + 1).c_str())));
break;
case oracle::occi::OCCIINTERVALDS:
case oracle::occi::OCCIINTERVALYM:
case oracle::occi::OCCI_SQLT_INTERVAL_YM:
case oracle::occi::OCCI_SQLT_INTERVAL_DS:
case oracle::occi::OCCIANYDATA:
case oracle::occi::OCCIBLOB:
case oracle::occi::OCCIBFILE:
case oracle::occi::OCCIBYTES:
case oracle::occi::OCCICLOB:
case oracle::occi::OCCIVECTOR:
case oracle::occi::OCCIMETADATA:
case oracle::occi::OCCIPOBJECT:
case oracle::occi::OCCIREF:
case oracle::occi::OCCIREFANY:
case oracle::occi::OCCISTREAM:
case oracle::occi::OCCICURSOR:
case oracle::occi::OCCI_SQLT_FILE:
case oracle::occi::OCCI_SQLT_CFILE:
case oracle::occi::OCCI_SQLT_REF:
case oracle::occi::OCCI_SQLT_CLOB:
case oracle::occi::OCCI_SQLT_BLOB:
case oracle::occi::OCCI_SQLT_RSET:
2012-04-08 02:20:56 +02:00
{
MAPNIK_LOG_WARN(occi) << "occi_featureset: Unsupported datatype "
<< occi_enums::resolve_datatype(type_oid)
<< " (type_oid=" << type_oid << ")";
2012-04-08 02:20:56 +02:00
break;
}
default: // shouldn't get here
2012-04-08 02:20:56 +02:00
{
MAPNIK_LOG_WARN(occi) << "occi_featureset: Unknown datatype "
<< "(type_oid=" << type_oid << ")";
2012-04-08 02:20:56 +02:00
break;
}
}
}
++feature_id_;
return feature;
}
return feature_ptr();
}
void occi_featureset::convert_geometry(SDOGeometry* geom, feature_ptr feature)
{
int gtype = (int)geom->getSdo_gtype();
2010-11-22 12:40:08 +01:00
int dimensions = gtype / 1000;
int lrsvalue = (gtype - dimensions * 1000) / 100;
int geomtype = (gtype - dimensions * 1000 - lrsvalue * 100);
2009-02-05 12:17:27 +01:00
const std::vector<Number>& elem_info = geom->getSdo_elem_info();
const std::vector<Number>& ordinates = geom->getSdo_ordinates();
const int ordinates_size = (int)ordinates.size();
2010-11-22 12:40:08 +01:00
switch (geomtype)
{
2010-11-22 12:40:08 +01:00
case SDO_GTYPE_POINT:
{
SDOPointType* sdopoint = geom->getSdo_point();
if (sdopoint && ! sdopoint->isNull())
2010-11-22 12:40:08 +01:00
{
std::unique_ptr<geometry_type> point = std::make_unique<geometry_type>(mapnik::new_geometry::geometry_types::Point);
point->move_to(sdopoint->getX(), sdopoint->getY());
Merge branch '2.3.x' of github.com:mapnik/mapnik Conflicts: .travis.yml CHANGELOG.md bindings/python/build.py include/mapnik/feature_style_processor_context.hpp include/mapnik/feature_style_processor_impl.hpp include/mapnik/json/feature_collection_grammar.hpp include/mapnik/json/feature_collection_parser.hpp include/mapnik/json/feature_generator_grammar.hpp include/mapnik/json/feature_parser.hpp include/mapnik/json/geojson_generator.hpp include/mapnik/json/geometry_generator_grammar.hpp include/mapnik/json/geometry_parser.hpp plugins/input/gdal/gdal_featureset.cpp plugins/input/geojson/geojson_datasource.cpp plugins/input/occi/occi_featureset.cpp plugins/input/osm/osm_featureset.cpp plugins/input/postgis/build.py plugins/input/postgis/connection.hpp src/agg/agg_renderer.cpp src/build.py src/cairo_context.cpp src/datasource_cache.cpp src/grid/process_line_symbolizer.cpp src/grid/process_polygon_pattern_symbolizer.cpp src/grid/process_polygon_symbolizer.cpp src/grid/process_text_symbolizer.cpp src/json/feature_grammar.cpp tests/cpp_tests/fontset_runtime_test.cpp tests/visual_tests/images/collision-600-400-1.0-agg-reference.png tests/visual_tests/images/image-filters-multi-blur-512-512-1.0-agg-reference.png tests/visual_tests/images/image-filters-multi-blur-512-512-2.0-agg-reference.png tests/visual_tests/images/image-filters-multi-blur-inflate-512-512-1.0-agg-reference.png tests/visual_tests/images/image-filters-multi-blur-inflate-512-512-2.0-agg-reference.png tests/visual_tests/images/lines-1-400-400-2.0-agg-reference.png tests/visual_tests/images/lines-1-600-600-1.0-agg-reference.png tests/visual_tests/images/lines-1-600-600-2.0-agg-reference.png tests/visual_tests/images/lines-2-200-200-1.0-agg-reference.png tests/visual_tests/images/lines-2-400-400-1.0-cairo-reference.png tests/visual_tests/images/lines-2-400-400-2.0-agg-reference.png tests/visual_tests/images/lines-2-600-600-2.0-agg-reference.png tests/visual_tests/images/lines-2-800-800-2.0-agg-reference.png tests/visual_tests/images/lines-3-400-400-2.0-agg-reference.png tests/visual_tests/images/lines-3-600-600-1.0-agg-reference.png tests/visual_tests/images/lines-3-600-600-2.0-agg-reference.png tests/visual_tests/images/lines-5-200-200-1.0-agg-reference.png tests/visual_tests/images/lines-5-200-200-2.0-agg-reference.png tests/visual_tests/images/lines-5-400-400-1.0-agg-reference.png tests/visual_tests/images/lines-5-400-400-2.0-agg-reference.png tests/visual_tests/images/lines-5-600-600-1.0-agg-reference.png tests/visual_tests/images/lines-5-600-600-2.0-agg-reference.png tests/visual_tests/images/lines-5-800-800-1.0-agg-reference.png tests/visual_tests/images/lines-5-800-800-2.0-agg-reference.png tests/visual_tests/images/lines-6-200-200-1.0-agg-reference.png tests/visual_tests/images/lines-6-200-200-2.0-agg-reference.png tests/visual_tests/images/lines-6-400-400-1.0-agg-reference.png tests/visual_tests/images/lines-6-600-600-1.0-agg-reference.png tests/visual_tests/images/lines-6-600-600-2.0-agg-reference.png tests/visual_tests/images/lines-6-800-800-1.0-agg-reference.png tests/visual_tests/images/lines-6-800-800-2.0-agg-reference.png tests/visual_tests/images/lines-shield-600-600-2.0-agg-reference.png tests/visual_tests/images/lines-shield-600-600-2.0-cairo-reference.png tests/visual_tests/images/shield-on-polygon-600-400-1.0-agg-reference.png tests/visual_tests/images/shield-on-polygon-600-400-2.0-agg-reference.png tests/visual_tests/images/shieldsymbolizer-1-490-100-2.0-agg-reference.png tests/visual_tests/images/shieldsymbolizer-1-495-100-2.0-agg-reference.png tests/visual_tests/images/shieldsymbolizer-1-495-100-2.0-cairo-reference.png tests/visual_tests/images/shieldsymbolizer-1-497-100-1.0-cairo-reference.png tests/visual_tests/images/shieldsymbolizer-1-497-100-2.0-agg-reference.png tests/visual_tests/images/shieldsymbolizer-1-497-100-2.0-cairo-reference.png tests/visual_tests/images/shieldsymbolizer-1-498-100-2.0-agg-reference.png tests/visual_tests/images/shieldsymbolizer-1-499-100-1.0-cairo-reference.png tests/visual_tests/images/shieldsymbolizer-1-499-100-2.0-agg-reference.png tests/visual_tests/images/shieldsymbolizer-1-499-100-2.0-cairo-reference.png tests/visual_tests/images/shieldsymbolizer-1-500-100-2.0-agg-reference.png tests/visual_tests/images/shieldsymbolizer-1-501-100-2.0-agg-reference.png tests/visual_tests/images/shieldsymbolizer-1-502-100-1.0-cairo-reference.png tests/visual_tests/images/shieldsymbolizer-1-502-100-2.0-agg-reference.png tests/visual_tests/images/shieldsymbolizer-1-505-100-2.0-agg-reference.png tests/visual_tests/images/shieldsymbolizer-1-505-100-2.0-cairo-reference.png tests/visual_tests/images/shieldsymbolizer-1-510-100-2.0-agg-reference.png tests/visual_tests/images/shieldsymbolizer-3-490-100-2.0-agg-reference.png tests/visual_tests/images/shieldsymbolizer-3-495-100-2.0-agg-reference.png tests/visual_tests/images/shieldsymbolizer-3-497-100-2.0-agg-reference.png tests/visual_tests/images/shieldsymbolizer-3-498-100-2.0-agg-reference.png tests/visual_tests/images/shieldsymbolizer-3-499-100-2.0-agg-reference.png tests/visual_tests/images/shieldsymbolizer-3-500-100-2.0-agg-reference.png tests/visual_tests/images/shieldsymbolizer-3-501-100-2.0-agg-reference.png tests/visual_tests/images/shieldsymbolizer-3-502-100-2.0-agg-reference.png tests/visual_tests/images/shieldsymbolizer-3-505-100-2.0-agg-reference.png tests/visual_tests/images/shieldsymbolizer-3-510-100-2.0-agg-reference.png tests/visual_tests/images/shieldsymbolizer-4-490-100-2.0-agg-reference.png tests/visual_tests/images/shieldsymbolizer-4-495-100-2.0-agg-reference.png tests/visual_tests/images/shieldsymbolizer-4-497-100-2.0-agg-reference.png tests/visual_tests/images/shieldsymbolizer-4-498-100-2.0-agg-reference.png tests/visual_tests/images/shieldsymbolizer-4-499-100-2.0-agg-reference.png tests/visual_tests/images/shieldsymbolizer-4-500-100-2.0-agg-reference.png tests/visual_tests/images/shieldsymbolizer-4-501-100-2.0-agg-reference.png tests/visual_tests/images/shieldsymbolizer-4-502-100-2.0-agg-reference.png tests/visual_tests/images/shieldsymbolizer-4-505-100-2.0-agg-reference.png tests/visual_tests/images/shieldsymbolizer-4-510-100-2.0-agg-reference.png tests/visual_tests/test.py
2014-04-24 23:50:55 +02:00
feature->add_geometry(point.release());
2010-11-22 12:40:08 +01:00
}
}
break;
2010-11-22 12:40:08 +01:00
case SDO_GTYPE_LINE:
{
if (ordinates_size >= dimensions)
2010-11-22 12:40:08 +01:00
{
const bool is_single_geom = true;
const bool is_point_type = false;
convert_ordinates(feature,
mapnik::new_geometry::geometry_types::LineString,
elem_info,
ordinates,
dimensions,
is_single_geom,
is_point_type);
2010-11-22 12:40:08 +01:00
}
}
break;
2010-11-22 12:40:08 +01:00
case SDO_GTYPE_POLYGON:
{
if (ordinates_size >= dimensions)
2010-11-22 12:40:08 +01:00
{
const bool is_single_geom = true;
const bool is_point_type = false;
convert_ordinates(feature,
mapnik::new_geometry::geometry_types::Polygon,
elem_info,
ordinates,
dimensions,
is_single_geom,
is_point_type);
2010-11-22 12:40:08 +01:00
}
}
break;
2010-11-22 12:40:08 +01:00
case SDO_GTYPE_MULTIPOINT:
{
if (ordinates_size >= dimensions)
2010-11-22 12:40:08 +01:00
{
const bool is_single_geom = false;
const bool is_point_type = true;
convert_ordinates(feature,
mapnik::new_geometry::geometry_types::Point,
elem_info,
ordinates,
dimensions,
is_single_geom,
is_point_type);
2010-11-22 12:40:08 +01:00
}
}
break;
2010-11-22 12:40:08 +01:00
case SDO_GTYPE_MULTILINE:
{
if (ordinates_size >= dimensions)
2010-11-22 12:40:08 +01:00
{
const bool is_single_geom = false;
const bool is_point_type = false;
convert_ordinates(feature,
mapnik::new_geometry::geometry_types::LineString,
elem_info,
ordinates,
dimensions,
is_single_geom,
is_point_type);
2010-11-22 12:40:08 +01:00
}
}
break;
2010-11-22 12:40:08 +01:00
case SDO_GTYPE_MULTIPOLYGON:
{
if (ordinates_size >= dimensions)
2010-11-22 12:40:08 +01:00
{
const bool is_single_geom = false;
const bool is_point_type = false;
convert_ordinates(feature,
mapnik::new_geometry::geometry_types::Polygon,
elem_info,
ordinates,
dimensions,
is_single_geom,
is_point_type);
2010-11-22 12:40:08 +01:00
}
}
break;
2010-11-22 12:40:08 +01:00
case SDO_GTYPE_COLLECTION:
{
if (ordinates_size >= dimensions)
2010-11-22 12:40:08 +01:00
{
const bool is_single_geom = false;
const bool is_point_type = false;
convert_ordinates(feature,
mapnik::new_geometry::geometry_types::Polygon,
elem_info,
ordinates,
dimensions,
is_single_geom,
is_point_type);
2010-11-22 12:40:08 +01:00
}
}
break;
2010-11-22 12:40:08 +01:00
case SDO_GTYPE_UNKNOWN:
default:
2012-04-08 02:20:56 +02:00
{
MAPNIK_LOG_WARN(occi) << "occi_featureset: Unknown oracle enum "
<< occi_enums::resolve_gtype(geomtype)
<< "(gtype=" << gtype << ")";
2012-04-08 02:20:56 +02:00
}
break;
}
}
void occi_featureset::convert_ordinates(mapnik::feature_ptr feature,
2013-10-22 22:05:44 +02:00
const mapnik::geometry_type::types& geom_type,
const std::vector<Number>& elem_info,
const std::vector<Number>& ordinates,
const int dimensions,
const bool is_single_geom,
const bool is_point_geom)
{
const int elem_size = elem_info.size();
const int ord_size = ordinates.size();
if (elem_size >= 0)
{
int offset = elem_info[0];
int etype = elem_info[1];
int interp = elem_info[2];
if (! is_single_geom && elem_size > SDO_ELEM_INFO_SIZE)
{
geometry_type* geom = new geometry_type(geom_type);
2012-03-13 15:59:22 +01:00
for (int i = SDO_ELEM_INFO_SIZE; i < elem_size; i+=3)
{
int next_offset = elem_info[i];
int next_etype = elem_info[i + 1];
int next_interp = elem_info[i + 2];
bool is_linear_element = true;
bool is_unknown_etype = false;
mapnik::geometry_type::types gtype = mapnik::new_geometry::geometry_types::Point;
switch (etype)
{
case SDO_ETYPE_POINT:
if (interp == SDO_INTERPRETATION_POINT) {}
if (interp > SDO_INTERPRETATION_POINT) {}
gtype = mapnik::new_geometry::geometry_types::Point;
break;
case SDO_ETYPE_LINESTRING:
if (interp == SDO_INTERPRETATION_STRAIGHT) {}
if (interp == SDO_INTERPRETATION_CIRCULAR) {}
gtype = mapnik::new_geometry::geometry_types::LineString;
break;
case SDO_ETYPE_POLYGON:
case SDO_ETYPE_POLYGON_INTERIOR:
if (interp == SDO_INTERPRETATION_STRAIGHT) {}
if (interp == SDO_INTERPRETATION_CIRCULAR) {}
if (interp == SDO_INTERPRETATION_RECTANGLE) {}
if (interp == SDO_INTERPRETATION_CIRCLE) {}
gtype = mapnik::new_geometry::geometry_types::Polygon;
break;
case SDO_ETYPE_COMPOUND_LINESTRING:
case SDO_ETYPE_COMPOUND_POLYGON:
case SDO_ETYPE_COMPOUND_POLYGON_INTERIOR:
// interp = next ETYPE to consider
is_linear_element = false;
gtype = mapnik::new_geometry::geometry_types::Polygon;
break;
case SDO_ETYPE_UNKNOWN: // unknown
default:
is_unknown_etype = true;
break;
}
if (is_unknown_etype)
{
break;
}
if (is_linear_element)
{
if (geom)
{
feature->add_geometry(geom);
}
2012-02-02 02:37:35 +01:00
geom = new geometry_type(gtype);
fill_geometry_type(geom,
offset - 1,
next_offset - 1,
ordinates,
dimensions,
is_point_geom);
}
offset = next_offset;
etype = next_etype;
interp = next_interp;
}
if (geom)
{
feature->add_geometry(geom);
geom = 0;
}
}
else
{
geometry_type * geom = new geometry_type(geom_type);
fill_geometry_type(geom,
offset - 1,
ord_size,
ordinates,
dimensions,
is_point_geom);
feature->add_geometry(geom);
}
}
}
void occi_featureset::fill_geometry_type(geometry_type* geom,
const int real_offset,
const int next_offset,
const std::vector<Number>& ordinates,
const int dimensions,
const bool is_point_geom)
2009-02-05 12:17:27 +01:00
{
geom->move_to((double) ordinates[real_offset], (double) ordinates[real_offset + 1]);
2009-02-05 12:17:27 +01:00
if (is_point_geom)
{
2009-02-05 12:17:27 +01:00
for (int p = real_offset + dimensions; p < next_offset; p += dimensions)
{
geom->move_to((double) ordinates[p], (double) ordinates[p + 1]);
}
}
2009-02-05 12:17:27 +01:00
else
{
2009-02-05 12:17:27 +01:00
for (int p = real_offset + dimensions; p < next_offset; p += dimensions)
{
geom->line_to((double) ordinates[p], (double) ordinates[p + 1]);
}
}
2009-02-05 12:17:27 +01:00
}