summaryrefslogtreecommitdiff
path: root/sql/spatial.cc
diff options
context:
space:
mode:
authorunknown <monty@mashka.mysql.fi>2004-03-04 08:50:37 +0200
committerunknown <monty@mashka.mysql.fi>2004-03-04 08:50:37 +0200
commitafa6728a9f7c00582b3dc9e96b2dce5c4ac1e56c (patch)
treef335ad0e2c6634a947a95d62cbee9a54ee9303e8 /sql/spatial.cc
parentf96960f9e1605189cc49397c64ff1cff97faedf1 (diff)
downloadmariadb-git-afa6728a9f7c00582b3dc9e96b2dce5c4ac1e56c.tar.gz
Optimized GIS functions
heap/hp_delete.c: Added comments mysql-test/r/gis.result: Updated results after name changes (all results line are unchanged) mysql-test/r/show_check.result: Update test results after fix in hp_delete.cc mysql-test/t/gis.test: Changed table names to longer, hopefully non conflicting ones. Added missing drop table mysys/hash.c: Inendation cleanup mysys/tree.c: Updated comments Decrease tree->allocated on delete (for status) sql/field.cc: Added safety checking for GIS objects sql/gstream.cc: Added copyright message Made a lot of speed/space optimizations Changed class names to be MySQL compliant sql/gstream.h: Made a lot of speed/space optimizations Changed class names to be MySQL compliant sql/item_create.cc: Indentation fixup sql/item_geofunc.cc: Use new gis interface functions and new gis class names. Simple optimizations Indentation fixups Fixed a lot of unlikely but possible errors. sql/item_geofunc.h: Moved SRID_SIZE to spatial.h sql/spatial.cc: Added copyright message Made a lot of speed/space optimizations Changed class names to be MySQL compliant sql/spatial.h: Made a lot of speed/space optimizations Changed class names to be MySQL compliant Indentation fixes Use bool instead of int as result type for functions that only return 0 or 1 sql/sql_string.cc: Simple optimizations sql/sql_string.h: Simple cleanups sql/structs.h: Added LEX_STRING_WITH_INIT (needed by spatial.cc)
Diffstat (limited to 'sql/spatial.cc')
-rw-r--r--sql/spatial.cc1646
1 files changed, 833 insertions, 813 deletions
diff --git a/sql/spatial.cc b/sql/spatial.cc
index d19429fdd9c..908fe6b8af4 100644
--- a/sql/spatial.cc
+++ b/sql/spatial.cc
@@ -1,9 +1,23 @@
-#include "mysql_priv.h"
+/* Copyright (C) 2004 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+ This program 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 General Public License for more details.
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "mysql_priv.h"
#define MAX_DIGITS_IN_DOUBLE 16
-/***************************** GClassInfo *******************************/
+/***************************** Gis_class_info *******************************/
#define IMPLEMENT_GEOM(class_name, type_id, name) \
{ \
@@ -14,12 +28,12 @@
(GF_GetD) &class_name::get_x, \
(GF_GetD) &class_name::get_y, \
(GF_GetD) &class_name::length, \
- (GF_GetD) &class_name::area, \
+ (GF_GetD_AND_END) &class_name::area, \
(GF_GetI) &class_name::is_closed, \
(GF_GetUI) &class_name::num_interior_ring, \
(GF_GetUI) &class_name::num_points, \
(GF_GetUI) &class_name::num_geometries, \
- (GF_GetUI) &class_name::dimension, \
+ (GF_GetUI_AND_END) &class_name::dimension, \
(GF_GetWS) &class_name::start_point, \
(GF_GetWS) &class_name::end_point, \
(GF_GetWS) &class_name::exterior_ring, \
@@ -27,54 +41,63 @@
(GF_GetUIWS) &class_name::point_n, \
(GF_GetUIWS) &class_name::interior_ring_n, \
(GF_GetUIWS) &class_name::geometry_n, \
- class_name::type_id, \
name, \
+ class_name::type_id, \
NULL \
-},
+}
+
+static LEX_STRING_WITH_INIT point_name("POINT", 5);
+static LEX_STRING_WITH_INIT linestring_name("LINESTRING", 10);
+static LEX_STRING_WITH_INIT polygon_name("POLYGON",7);
+static LEX_STRING_WITH_INIT multipoint_name("MULTIPOINT",10);
+static LEX_STRING_WITH_INIT multilinestring_name("MULTILINESTRING",15);
+static LEX_STRING_WITH_INIT multipolygon_name("MULTIPOLYGON",12);
+static LEX_STRING_WITH_INIT geometrycollection_name("GEOMETRYCOLLECTION",18);
-static Geometry::GClassInfo ci_collection[] =
+static Geometry::Gis_class_info ci_collection[]=
{
- IMPLEMENT_GEOM(GPoint, wkbPoint, "POINT")
- IMPLEMENT_GEOM(GLineString, wkbLineString, "LINESTRING")
- IMPLEMENT_GEOM(GPolygon, wkbPolygon, "POLYGON")
- IMPLEMENT_GEOM(GMultiPoint, wkbMultiPoint, "MULTIPOINT")
- IMPLEMENT_GEOM(GMultiLineString, wkbMultiLineString, "MULTILINESTRING")
- IMPLEMENT_GEOM(GMultiPolygon, wkbMultiPolygon, "MULTIPOLYGON")
- IMPLEMENT_GEOM(GGeometryCollection, wkbGeometryCollection, "GEOMETRYCOLLECTION")
+ IMPLEMENT_GEOM(Gis_point, wkbPoint, point_name),
+ IMPLEMENT_GEOM(Gis_line_string, wkbLineString, linestring_name),
+ IMPLEMENT_GEOM(Gis_polygon, wkbPolygon, polygon_name),
+ IMPLEMENT_GEOM(Gis_multi_point, wkbMultiPoint, multipoint_name),
+ IMPLEMENT_GEOM(Gis_multi_line_stringg, wkbMultiLineString, multilinestring_name),
+ IMPLEMENT_GEOM(Gis_multi_polygon, wkbMultiPolygon, multipolygon_name),
+ IMPLEMENT_GEOM(Gis_geometry_collection, wkbGeometryCollection,
+ geometrycollection_name)
};
-static Geometry::GClassInfo *ci_collection_end = ci_collection + sizeof(ci_collection)/sizeof(ci_collection[0]);
+static Geometry::Gis_class_info *ci_collection_end=
+(ci_collection + array_elements(ci_collection));
+
/***************************** Geometry *******************************/
-Geometry::GClassInfo *Geometry::find_class(int type_id)
+Geometry::Gis_class_info *Geometry::find_class(int type_id)
{
- for (GClassInfo *cur_rt = ci_collection; cur_rt < ci_collection_end; ++cur_rt)
+ for (Gis_class_info *cur_rt= ci_collection; cur_rt < ci_collection_end; cur_rt++)
{
if (cur_rt->m_type_id == type_id)
- {
return cur_rt;
- }
}
- return NULL;
+ return 0;
}
-Geometry::GClassInfo *Geometry::find_class(const char *name, size_t len)
+
+Geometry::Gis_class_info *Geometry::find_class(const char *name, uint32 len)
{
- for (GClassInfo *cur_rt = ci_collection;
- cur_rt < ci_collection_end; ++cur_rt)
+ for (Gis_class_info *cur_rt= ci_collection; cur_rt < ci_collection_end; cur_rt++)
{
- if ((cur_rt->m_name[len] == 0) &&
- (my_strnncoll(&my_charset_latin1, (const uchar*)cur_rt->m_name, len,
- (const uchar*)name, len) == 0))
- {
+ if ((cur_rt->m_name.length == len) &&
+ (my_strnncoll(&my_charset_latin1,
+ (const uchar*) cur_rt->m_name.str, len,
+ (const uchar*) name, len) == 0))
return cur_rt;
- }
}
- return NULL;
+ return 0;
}
+
int Geometry::create_from_wkb(const char *data, uint32 data_len)
{
uint32 geom_type;
@@ -82,43 +105,39 @@ int Geometry::create_from_wkb(const char *data, uint32 data_len)
if (data_len < 1 + 4)
return 1;
data++;
-//FIXME: check byte ordering
+ /*
+ FIXME: check byte ordering
+ Also check if we could replace this with one byte
+ */
geom_type= uint4korr(data);
data+= 4;
- m_vmt= find_class(geom_type);
- if (!m_vmt)
- return -1;
+ if (!(m_vmt= find_class((int) geom_type)))
+ return 1;
m_data= data;
m_data_end= data + data_len;
return 0;
}
-int Geometry::create_from_wkt(GTextReadStream *trs, String *wkt, int init_stream)
+
+int Geometry::create_from_wkt(Gis_read_stream *trs, String *wkt,
+ bool init_stream)
{
- int name_len;
- const char *name = trs->get_next_word(&name_len);
- if (!name)
+ LEX_STRING name;
+
+ if (trs->get_next_word(&name))
{
trs->set_error_msg("Geometry name expected");
- return -1;
- }
- if (!(m_vmt = find_class(name, name_len)))
- return -1;
- if (wkt->reserve(1 + 4, 512))
return 1;
- wkt->q_append((char)wkbNDR);
- wkt->q_append((uint32)get_class_info()->m_type_id);
- if (trs->get_next_symbol() != '(')
- {
- trs->set_error_msg("'(' expected");
- return -1;
}
- if (init_from_wkt(trs, wkt)) return 1;
- if (trs->get_next_symbol() != ')')
- {
- trs->set_error_msg("')' expected");
- return -1;
- }
+ if (!(m_vmt= find_class(name.str, name.length)) ||
+ wkt->reserve(1 + 4, 512))
+ return 1;
+ wkt->q_append((char) wkbNDR);
+ wkt->q_append((uint32) get_class_info()->m_type_id);
+ if (trs->check_next_symbol('(') ||
+ init_from_wkt(trs, wkt) ||
+ trs->check_next_symbol(')'))
+ return 1;
if (init_stream)
{
init_from_wkb(wkt->ptr(), wkt->length());
@@ -127,19 +146,19 @@ int Geometry::create_from_wkt(GTextReadStream *trs, String *wkt, int init_stream
return 0;
}
-int Geometry::envelope(String *result) const
+
+bool Geometry::envelope(String *result) const
{
MBR mbr;
+ const char *end;
- get_mbr(&mbr);
-
- if (result->reserve(1+4*3+sizeof(double)*10))
+ if (get_mbr(&mbr, &end) || result->reserve(1+4*3+SIZEOF_STORED_DOUBLE*10))
return 1;
- result->q_append((char)wkbNDR);
- result->q_append((uint32)wkbPolygon);
- result->q_append((uint32)1);
- result->q_append((uint32)5);
+ result->q_append((char) wkbNDR);
+ result->q_append((uint32) wkbPolygon);
+ result->q_append((uint32) 1);
+ result->q_append((uint32) 5);
result->q_append(mbr.xmin);
result->q_append(mbr.ymin);
result->q_append(mbr.xmax);
@@ -154,29 +173,151 @@ int Geometry::envelope(String *result) const
return 0;
}
+
+/*
+ Create a point from data.
+
+ SYNPOSIS
+ create_point()
+ result Put result here
+ data Data for point is here.
+
+ RETURN
+ 0 ok
+ 1 Can't reallocate 'result'
+*/
+
+bool Geometry::create_point(String *result, const char *data)
+{
+ if (no_data(data, SIZEOF_STORED_DOUBLE * 2) ||
+ result->reserve(1 + 4 + SIZEOF_STORED_DOUBLE * 2))
+ return 1;
+ result->q_append((char) wkbNDR);
+ result->q_append((uint32) wkbPoint);
+ /* Copy two double in same format */
+ result->q_append(data, SIZEOF_STORED_DOUBLE*2);
+ return 0;
+}
+
+/*
+ Create a point from coordinates.
+
+ SYNPOSIS
+ create_point()
+ result Put result here
+ x x coordinate for point
+ y y coordinate for point
+
+ RETURN
+ 0 ok
+ 1 Can't reallocate 'result'
+*/
+
+bool Geometry::create_point(String *result, double x, double y)
+{
+ if (result->reserve(1 + 4 + SIZEOF_STORED_DOUBLE * 2))
+ return 1;
+
+ result->q_append((char) wkbNDR);
+ result->q_append((uint32) wkbPoint);
+ result->q_append(x);
+ result->q_append(y);
+ return 0;
+}
+
+/*
+ Append N points from packed format to text
+
+ SYNOPSIS
+ append_points()
+ txt Append points here
+ n_points Number of points
+ data Packed data
+ offset Offset between points
+
+ RETURN
+ # end of data
+*/
+
+const char *Geometry::append_points(String *txt, uint32 n_points,
+ const char *data, uint32 offset)
+{
+ while (n_points--)
+ {
+ double d;
+ data+= offset;
+ float8get(d, data);
+ txt->qs_append(d);
+ txt->qs_append(' ');
+ float8get(d, data + SIZEOF_STORED_DOUBLE);
+ data+= SIZEOF_STORED_DOUBLE * 2;
+ txt->qs_append(d);
+ txt->qs_append(',');
+ }
+ return data;
+}
+
+
+/*
+ Get most bounding rectangle (mbr) for X points
+
+ SYNOPSIS
+ get_mbr_for_points()
+ mbr MBR (store rectangle here)
+ points Number of points
+ data Packed data
+ offset Offset between points
+
+ RETURN
+ 0 Wrong data
+ # end of data
+*/
+
+const char *Geometry::get_mbr_for_points(MBR *mbr, const char *data,
+ uint offset) const
+{
+ uint32 points;
+ /* read number of points */
+ if (no_data(data, 4))
+ return 0;
+ points= uint4korr(data);
+ data+= 4;
+
+ if (no_data(data, (SIZEOF_STORED_DOUBLE * 2 + offset) * points))
+ return 0;
+
+ /* Calculate MBR for points */
+ while (points--)
+ {
+ data+= offset;
+ mbr->add_xy(data, data + SIZEOF_STORED_DOUBLE);
+ data+= SIZEOF_STORED_DOUBLE * 2;
+ }
+ return data;
+}
+
+
/***************************** Point *******************************/
-size_t GPoint::get_data_size() const
+uint32 Gis_point::get_data_size() const
{
return POINT_DATA_SIZE;
}
-int GPoint::init_from_wkt(GTextReadStream *trs, String *wkb)
+
+bool Gis_point::init_from_wkt(Gis_read_stream *trs, String *wkb)
{
double x, y;
- if (wkb->reserve(sizeof(double)*2))
- return 1;
- if (trs->get_next_number(&x))
- return 1;
- if (trs->get_next_number(&y))
+ if (trs->get_next_number(&x) || trs->get_next_number(&y) ||
+ wkb->reserve(SIZEOF_STORED_DOUBLE * 2))
return 1;
wkb->q_append(x);
wkb->q_append(y);
-
return 0;
}
-int GPoint::get_data_as_wkt(String *txt) const
+
+bool Gis_point::get_data_as_wkt(String *txt, const char **end)
{
double x, y;
if (get_xy(&x, &y))
@@ -186,324 +327,250 @@ int GPoint::get_data_as_wkt(String *txt) const
txt->qs_append(x);
txt->qs_append(' ');
txt->qs_append(y);
+ *end= m_data+ POINT_DATA_SIZE;
return 0;
}
-int GPoint::get_mbr(MBR *mbr) const
+
+int Gis_point::get_mbr(MBR *mbr, const char **end) const
{
double x, y;
if (get_xy(&x, &y))
return 1;
mbr->add_xy(x, y);
+ *end= m_data+ POINT_DATA_SIZE;
return 0;
}
+
/***************************** LineString *******************************/
-size_t GLineString::get_data_size() const
+uint32 Gis_line_string::get_data_size() const
{
- uint32 n_points = uint4korr(m_data);
-
- return 4 + n_points*POINT_DATA_SIZE;
+ if (no_data(m_data, 4))
+ return GET_SIZE_ERROR;
+ return 4 + uint4korr(m_data) * POINT_DATA_SIZE;
}
-int GLineString::init_from_wkt(GTextReadStream *trs, String *wkb)
+
+bool Gis_line_string::init_from_wkt(Gis_read_stream *trs, String *wkb)
{
- uint32 n_points = 0;
- int np_pos = wkb->length();
- GPoint p;
+ uint32 n_points= 0;
+ uint32 np_pos= wkb->length();
+ Gis_point p;
if (wkb->reserve(4, 512))
return 1;
-
- wkb->q_append((uint32)n_points);
+ wkb->length(wkb->length()+4); // Reserve space for points
for (;;)
{
if (p.init_from_wkt(trs, wkb))
return 1;
- ++n_points;
- if (trs->get_next_toc_type() == GTextReadStream::comma)
- trs->get_next_symbol();
- else break;
+ n_points++;
+ if (trs->skip_char(',')) // Didn't find ','
+ break;
}
-
- if (n_points<2)
+ if (n_points < 2)
{
trs->set_error_msg("Too few points in LINESTRING");
return 1;
}
-
- wkb->WriteAtPosition(np_pos, n_points);
-
+ wkb->write_at_position(np_pos, n_points);
return 0;
}
-int GLineString::get_data_as_wkt(String *txt) const
+
+bool Gis_line_string::get_data_as_wkt(String *txt, const char **end)
{
uint32 n_points;
- const char *data = m_data;
+ const char *data= m_data;
if (no_data(data, 4))
return 1;
-
- n_points = uint4korr(data);
+ n_points= uint4korr(data);
data += 4;
- if (no_data(data, sizeof(double) * 2 * n_points))
+ if (n_points < 1 ||
+ no_data(data, SIZEOF_STORED_DOUBLE * 2 * n_points) ||
+ txt->reserve(((MAX_DIGITS_IN_DOUBLE + 1)*2 + 1) * n_points))
return 1;
- if (txt->reserve(((MAX_DIGITS_IN_DOUBLE + 1)*2 + 1) * n_points))
- return 1;
- for (; n_points>0; --n_points)
+ while (n_points--)
{
double x, y;
float8get(x, data);
- data += sizeof(double);
- float8get(y, data);
- data += sizeof(double);
+ float8get(y, data + SIZEOF_STORED_DOUBLE);
+ data+= SIZEOF_STORED_DOUBLE * 2;
txt->qs_append(x);
txt->qs_append(' ');
txt->qs_append(y);
txt->qs_append(',');
}
- txt->length(txt->length() - 1);
+ txt->length(txt->length() - 1); // Remove end ','
+ *end= data;
return 0;
}
-int GLineString::get_mbr(MBR *mbr) const
-{
- uint32 n_points;
- const char *data = m_data;
-
- if (no_data(data, 4))
- return 1;
-
- n_points = uint4korr(data);
- data += 4;
-
- if (no_data(data, sizeof(double) * 2 * n_points))
- return 1;
- for (; n_points>0; --n_points)
- {
- mbr->add_xy(data, data + 8);
- data += 8+8;
- }
- return 0;
+bool Gis_line_string::get_mbr(MBR *mbr, const char **end) const
+{
+ return (*end=get_mbr_for_points(mbr, m_data, 0)) == 0;
}
-int GLineString::length(double *len) const
+
+bool Gis_line_string::length(double *len) const
{
uint32 n_points;
double prev_x, prev_y;
- const char *data = m_data;
+ const char *data= m_data;
- *len=0;
+ *len= 0; // In case of errors
if (no_data(data, 4))
return 1;
- n_points = uint4korr(data);
- data += 4;
-
- if (no_data(data, sizeof(double) * 2 * n_points))
+ n_points= uint4korr(data);
+ data+= 4;
+ if (n_points < 1 || no_data(data, SIZEOF_STORED_DOUBLE * 2 * n_points))
return 1;
- --n_points;
float8get(prev_x, data);
- data += 8;
- float8get(prev_y, data);
- data += 8;
+ float8get(prev_y, data + SIZEOF_STORED_DOUBLE);
+ data+= SIZEOF_STORED_DOUBLE*2;
- for (; n_points>0; --n_points)
+ while (--n_points)
{
double x, y;
float8get(x, data);
- data += 8;
- float8get(y, data);
- data += 8;
- *len+=sqrt(pow(prev_x-x,2)+pow(prev_y-y,2));
- prev_x=x;
- prev_y=y;
+ float8get(y, data + SIZEOF_STORED_DOUBLE);
+ data+= SIZEOF_STORED_DOUBLE * 2;
+ *len+= sqrt(pow(prev_x-x,2)+pow(prev_y-y,2));
+ prev_x= x;
+ prev_y= y;
}
return 0;
}
-int GLineString::is_closed(int *closed) const
+bool Gis_line_string::is_closed(int *closed) const
{
uint32 n_points;
double x1, y1, x2, y2;
-
- const char *data = m_data;
+ const char *data= m_data;
if (no_data(data, 4))
return 1;
- n_points = uint4korr(data);
- data += 4;
- if (no_data(data, (8+8) * n_points))
+ n_points= uint4korr(data);
+ data+= 4;
+ if (no_data(data, SIZEOF_STORED_DOUBLE * 2 * n_points))
return 1;
+
+ /* Get first point */
float8get(x1, data);
- data += 8;
- float8get(y1, data);
- data += 8 + (n_points-2)*POINT_DATA_SIZE;
- float8get(x2, data);
- data += 8;
- float8get(y2, data);
+ float8get(y1, data + SIZEOF_STORED_DOUBLE);
- *closed=(x1==x2)&&(y1==y2);
+ /* get last point */
+ data+= SIZEOF_STORED_DOUBLE*2 + (n_points-2)*POINT_DATA_SIZE;
+ float8get(x2, data);
+ float8get(y2, data + SIZEOF_STORED_DOUBLE);
+ *closed= (x1==x2) && (y1==y2);
return 0;
}
-int GLineString::num_points(uint32 *n_points) const
+
+bool Gis_line_string::num_points(uint32 *n_points) const
{
- *n_points = uint4korr(m_data);
+ *n_points= uint4korr(m_data);
return 0;
}
-int GLineString::start_point(String *result) const
-{
- const char *data= m_data + 4;
- if (no_data(data, 8 + 8))
- return 1;
-
- if (result->reserve(1 + 4 + sizeof(double) * 2))
- return 1;
-
- result->q_append((char) wkbNDR);
- result->q_append((uint32) wkbPoint);
- double d;
- float8get(d, data);
- result->q_append(d);
- float8get(d, data + 8);
- result->q_append(d);
- return 0;
+bool Gis_line_string::start_point(String *result)
+{
+ /* +4 is for skipping over number of points */
+ return create_point(result, m_data + 4);
}
-int GLineString::end_point(String *result) const
+
+bool Gis_line_string::end_point(String *result)
{
- const char *data= m_data;
uint32 n_points;
-
- if (no_data(data, 4))
+ if (no_data(m_data, 4))
return 1;
- n_points= uint4korr(data);
-
- data+= 4 + (n_points - 1) * POINT_DATA_SIZE;
-
- if (no_data(data, 8 + 8))
- return 1;
-
- if (result->reserve(1 + 4 + sizeof(double) * 2))
- return 1;
- result->q_append((char) wkbNDR);
- result->q_append((uint32) wkbPoint);
- double d;
- float8get(d, data);
- result->q_append(d);
- float8get(d, data + 8);
- result->q_append(d);
-
- return 0;
+ n_points= uint4korr(m_data);
+ return create_point(result, m_data + 4 + (n_points - 1) * POINT_DATA_SIZE);
}
-int GLineString::point_n(uint32 num, String *result) const
+bool Gis_line_string::point_n(uint32 num, String *result)
{
- const char *data= m_data;
uint32 n_points;
-
- if (no_data(data, 4))
+ if (no_data(m_data, 4))
return 1;
- n_points= uint4korr(data);
-
+ n_points= uint4korr(m_data);
if ((uint32) (num - 1) >= n_points) // means (num > n_points || num < 1)
return 1;
- data+= 4 + (num - 1) * POINT_DATA_SIZE;
-
- if (no_data(data, 8 + 8))
- return 1;
- if (result->reserve(1 + 4 + sizeof(double) * 2))
- return 1;
-
- result->q_append((char) wkbNDR);
- result->q_append((uint32) wkbPoint);
- double d;
- float8get(d, data);
- result->q_append(d);
- float8get(d, data + 8);
- result->q_append(d);
-
- return 0;
+ return create_point(result, m_data + 4 + (num - 1) * POINT_DATA_SIZE);
}
+
/***************************** Polygon *******************************/
-size_t GPolygon::get_data_size() const
+uint32 Gis_polygon::get_data_size() const
{
- uint32 n_linear_rings = 0;
- const char *data = m_data;
+ uint32 n_linear_rings;
+ const char *data= m_data;
+
if (no_data(data, 4))
- return 1;
+ return GET_SIZE_ERROR;
+ n_linear_rings= uint4korr(data);
+ data+= 4;
- n_linear_rings = uint4korr(data);
- data += 4;
- for (; n_linear_rings>0; --n_linear_rings)
+ while (n_linear_rings--)
{
if (no_data(data, 4))
- return 1;
- data += 4 + uint4korr(data)*POINT_DATA_SIZE;
+ return GET_SIZE_ERROR;
+ data+= 4 + uint4korr(data)*POINT_DATA_SIZE;
}
- return data - m_data;
+ return (uint32) (data - m_data);
}
-int GPolygon::init_from_wkt(GTextReadStream *trs, String *wkb)
+
+bool Gis_polygon::init_from_wkt(Gis_read_stream *trs, String *wkb)
{
- uint32 n_linear_rings = 0;
- int lr_pos = wkb->length();
+ uint32 n_linear_rings= 0;
+ uint32 lr_pos= wkb->length();
+ int closed;
if (wkb->reserve(4, 512))
return 1;
-
- wkb->q_append((uint32)n_linear_rings);
-
+ wkb->length(wkb->length()+4); // Reserve space for points
for (;;)
{
- GLineString ls;
- size_t ls_pos=wkb->length();
- if (trs->get_next_symbol() != '(')
- {
- trs->set_error_msg("'(' expected");
- return 1;
- }
- if (ls.init_from_wkt(trs, wkb))
- return 1;
- if (trs->get_next_symbol() != ')')
- {
- trs->set_error_msg("')' expected");
+ Gis_line_string ls;
+ uint32 ls_pos=wkb->length();
+ if (trs->check_next_symbol('(') ||
+ ls.init_from_wkt(trs, wkb) ||
+ trs->check_next_symbol(')'))
return 1;
- }
+
ls.init_from_wkb(wkb->ptr()+ls_pos, wkb->length()-ls_pos);
- int closed;
- ls.is_closed(&closed);
- if (!closed)
+ if (ls.is_closed(&closed) || !closed)
{
trs->set_error_msg("POLYGON's linear ring isn't closed");
return 1;
}
- ++n_linear_rings;
- if (trs->get_next_toc_type() == GTextReadStream::comma)
- trs->get_next_symbol();
- else
+ n_linear_rings++;
+ if (trs->skip_char(',')) // Didn't find ','
break;
}
- wkb->WriteAtPosition(lr_pos, n_linear_rings);
+ wkb->write_at_position(lr_pos, n_linear_rings);
return 0;
}
-int GPolygon::get_data_as_wkt(String *txt) const
+
+bool Gis_polygon::get_data_as_wkt(String *txt, const char **end)
{
uint32 n_linear_rings;
const char *data= m_data;
@@ -514,1059 +581,1012 @@ int GPolygon::get_data_as_wkt(String *txt) const
n_linear_rings= uint4korr(data);
data+= 4;
- for (; n_linear_rings > 0; --n_linear_rings)
+ while (n_linear_rings--)
{
+ uint32 n_points;
if (no_data(data, 4))
return 1;
- uint32 n_points= uint4korr(data);
+ n_points= uint4korr(data);
data+= 4;
- if (no_data(data, (8 + 8) * n_points))
- return 1;
-
- if (txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points))
+ if (no_data(data, (SIZEOF_STORED_DOUBLE*2) * n_points) ||
+ txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points))
return 1;
txt->qs_append('(');
- for (; n_points>0; --n_points)
- {
- double d;
- float8get(d, data);
- txt->qs_append(d);
- txt->qs_append(' ');
- float8get(d, data + 8);
- txt->qs_append(d);
- txt->qs_append(',');
-
- data+= 8 + 8;
- }
- (*txt) [txt->length() - 1]= ')';
+ data= append_points(txt, n_points, data, 0);
+ (*txt) [txt->length() - 1]= ')'; // Replace end ','
txt->qs_append(',');
}
- txt->length(txt->length() - 1);
+ txt->length(txt->length() - 1); // Remove end ','
+ *end= data;
return 0;
}
-int GPolygon::get_mbr(MBR *mbr) const
+
+bool Gis_polygon::get_mbr(MBR *mbr, const char **end) const
{
uint32 n_linear_rings;
+ const char *data= m_data;
- const char *data = m_data;
if (no_data(data, 4))
return 1;
- n_linear_rings = uint4korr(data);
- data += 4;
- for (; n_linear_rings>0; --n_linear_rings)
+ n_linear_rings= uint4korr(data);
+ data+= 4;
+
+ while (n_linear_rings--)
{
- if (no_data(data, 4))
+ if (!(data= get_mbr_for_points(mbr, data, 0)))
return 1;
- uint32 n_points = uint4korr(data);
- data += 4;
- if (no_data(data, (8+8) * n_points))
- return 1;
- for (; n_points>0; --n_points)
- {
- mbr->add_xy(data, data + 8);
- data += 8+8;
- }
}
+ *end= data;
return 0;
}
-int GPolygon::area(double *ar) const
+
+bool Gis_polygon::area(double *ar, const char **end_of_data) const
{
uint32 n_linear_rings;
- double result = -1.0;
+ double result= -1.0;
+ const char *data= m_data;
- const char *data = m_data;
if (no_data(data, 4))
return 1;
- n_linear_rings = uint4korr(data);
- data += 4;
- for (; n_linear_rings>0; --n_linear_rings)
+ n_linear_rings= uint4korr(data);
+ data+= 4;
+
+ while (n_linear_rings--)
{
double prev_x, prev_y;
- double lr_area=0;
+ double lr_area= 0;
+ uint32 n_points;
+
if (no_data(data, 4))
return 1;
- uint32 n_points = uint4korr(data);
- if (no_data(data, (8+8) * n_points))
+ n_points= uint4korr(data);
+ if (no_data(data, (SIZEOF_STORED_DOUBLE*2) * n_points))
return 1;
float8get(prev_x, data+4);
- float8get(prev_y, data+(4+8));
- data += (4+8+8);
+ float8get(prev_y, data+(4+SIZEOF_STORED_DOUBLE));
+ data+= (4+SIZEOF_STORED_DOUBLE*2);
- --n_points;
- for (; n_points>0; --n_points)
+ while (--n_points) // One point is already read
{
double x, y;
float8get(x, data);
- float8get(y, data + 8);
- lr_area+=(prev_x+x)*(prev_y-y);
- prev_x=x;
- prev_y=y;
- data += (8+8);
+ float8get(y, data + SIZEOF_STORED_DOUBLE);
+ data+= (SIZEOF_STORED_DOUBLE*2);
+ /* QQ: Is the following prev_x+x right ? */
+ lr_area+= (prev_x + x)* (prev_y - y);
+ prev_x= x;
+ prev_y= y;
}
- lr_area=fabs(lr_area)/2;
- if (result==-1) result=lr_area;
- else result-=lr_area;
+ lr_area= fabs(lr_area)/2;
+ if (result == -1.0)
+ result= lr_area;
+ else
+ result-= lr_area;
}
- *ar=fabs(result);
+ *ar= fabs(result);
+ *end_of_data= data;
return 0;
}
-int GPolygon::exterior_ring(String *result) const
+bool Gis_polygon::exterior_ring(String *result)
{
- uint32 n_points;
- const char *data = m_data + 4; // skip n_linerings
+ uint32 n_points, length;
+ const char *data= m_data + 4; // skip n_linerings
if (no_data(data, 4))
return 1;
- n_points = uint4korr(data);
- data += 4;
- if (no_data(data, n_points * POINT_DATA_SIZE))
- return 1;
-
- if (result->reserve(1+4+4+ n_points * POINT_DATA_SIZE))
+ n_points= uint4korr(data);
+ data+= 4;
+ length= n_points * POINT_DATA_SIZE;
+ if (no_data(data, length) || result->reserve(1+4+4+ length))
return 1;
- result->q_append((char)wkbNDR);
- result->q_append((uint32)wkbLineString);
+ result->q_append((char) wkbNDR);
+ result->q_append((uint32) wkbLineString);
result->q_append(n_points);
result->q_append(data, n_points * POINT_DATA_SIZE);
-
return 0;
}
-int GPolygon::num_interior_ring(uint32 *n_int_rings) const
+
+bool Gis_polygon::num_interior_ring(uint32 *n_int_rings) const
{
- const char *data = m_data;
- if (no_data(data, 4))
+ if (no_data(m_data, 4))
return 1;
- *n_int_rings = uint4korr(data);
- --(*n_int_rings);
-
+ *n_int_rings= uint4korr(m_data)-1;
return 0;
}
-int GPolygon::interior_ring_n(uint32 num, String *result) const
+
+bool Gis_polygon::interior_ring_n(uint32 num, String *result) const
{
- const char *data = m_data;
+ const char *data= m_data;
uint32 n_linear_rings;
uint32 n_points;
+ uint32 points_size;
if (no_data(data, 4))
return 1;
+ n_linear_rings= uint4korr(data);
+ data+= 4;
- n_linear_rings = uint4korr(data);
- data += 4;
- if ((num >= n_linear_rings) || (num < 1))
- return -1;
+ if (num >= n_linear_rings || num < 1)
+ return 1;
- for (; num > 0; --num)
+ while (num--)
{
if (no_data(data, 4))
return 1;
- data += 4 + uint4korr(data) * POINT_DATA_SIZE;
+ data+= 4 + uint4korr(data) * POINT_DATA_SIZE;
}
if (no_data(data, 4))
return 1;
- n_points = uint4korr(data);
- int points_size = n_points * POINT_DATA_SIZE;
- data += 4;
- if (no_data(data, points_size))
- return 1;
-
- if (result->reserve(1+4+4+ points_size))
+ n_points= uint4korr(data);
+ points_size= n_points * POINT_DATA_SIZE;
+ data+= 4;
+ if (no_data(data, points_size) || result->reserve(1+4+4+ points_size))
return 1;
- result->q_append((char)wkbNDR);
- result->q_append((uint32)wkbLineString);
+ result->q_append((char) wkbNDR);
+ result->q_append((uint32) wkbLineString);
result->q_append(n_points);
result->q_append(data, points_size);
return 0;
}
-int GPolygon::centroid_xy(double *x, double *y) const
+
+bool Gis_polygon::centroid_xy(double *x, double *y) const
{
uint32 n_linear_rings;
- uint32 i;
double res_area, res_cx, res_cy;
- const char *data = m_data;
+ const char *data= m_data;
+ bool first_loop= 1;
LINT_INIT(res_area);
LINT_INIT(res_cx);
LINT_INIT(res_cy);
if (no_data(data, 4))
return 1;
- n_linear_rings = uint4korr(data);
- data += 4;
+ n_linear_rings= uint4korr(data);
+ data+= 4;
- for (i = 0; i < n_linear_rings; ++i)
+ while (n_linear_rings--)
{
- if (no_data(data, 4))
- return 1;
- uint32 n_points = uint4korr(data);
+ uint32 n_points, org_n_points;
double prev_x, prev_y;
- double cur_area = 0;
- double cur_cx = 0;
- double cur_cy = 0;
+ double cur_area= 0;
+ double cur_cx= 0;
+ double cur_cy= 0;
- data += 4;
- if (no_data(data, (8+8) * n_points))
+ if (no_data(data, 4))
+ return 1;
+ org_n_points= n_points= uint4korr(data);
+ data+= 4;
+ if (no_data(data, (SIZEOF_STORED_DOUBLE*2) * n_points))
return 1;
float8get(prev_x, data);
- float8get(prev_y, data+8);
- data += (8+8);
+ float8get(prev_y, data+SIZEOF_STORED_DOUBLE);
+ data+= (SIZEOF_STORED_DOUBLE*2);
- uint32 n = n_points - 1;
- for (; n > 0; --n)
+ while (--n_points) // One point is already read
{
double x, y;
float8get(x, data);
- float8get(y, data + 8);
-
- cur_area += (prev_x + x) * (prev_y - y);
- cur_cx += x;
- cur_cy += y;
- prev_x = x;
- prev_y = y;
- data += (8+8);
+ float8get(y, data + SIZEOF_STORED_DOUBLE);
+ data+= (SIZEOF_STORED_DOUBLE*2);
+ /* QQ: Is the following prev_x+x right ? */
+ cur_area+= (prev_x + x) * (prev_y - y);
+ cur_cx+= x;
+ cur_cy+= y;
+ prev_x= x;
+ prev_y= y;
}
- cur_area = fabs(cur_area) / 2;
- cur_cx = cur_cx / (n_points - 1);
- cur_cy = cur_cy / (n_points - 1);
+ cur_area= fabs(cur_area) / 2;
+ cur_cx= cur_cx / (org_n_points - 1);
+ cur_cy= cur_cy / (org_n_points - 1);
- if (i)
+ if (!first_loop)
{
- double d_area = res_area - cur_area;
+ double d_area= res_area - cur_area;
if (d_area <= 0)
return 1;
- res_cx = (res_area * res_cx - cur_area * cur_cx) / d_area;
- res_cy = (res_area * res_cy - cur_area * cur_cy) / d_area;
+ res_cx= (res_area * res_cx - cur_area * cur_cx) / d_area;
+ res_cy= (res_area * res_cy - cur_area * cur_cy) / d_area;
}
else
{
- res_area = cur_area;
- res_cx = cur_cx;
- res_cy = cur_cy;
+ first_loop= 0;
+ res_area= cur_area;
+ res_cx= cur_cx;
+ res_cy= cur_cy;
}
}
- *x = res_cx;
- *y = res_cy;
-
+ *x= res_cx;
+ *y= res_cy;
return 0;
}
-int GPolygon::centroid(String *result) const
+
+bool Gis_polygon::centroid(String *result)
{
double x, y;
-
- this->centroid_xy(&x, &y);
- if (result->reserve(1 + 4 + sizeof(double) * 2))
+ if (centroid_xy(&x, &y))
return 1;
-
- result->q_append((char)wkbNDR);
- result->q_append((uint32)wkbPoint);
- result->q_append(x);
- result->q_append(y);
-
- return 0;
+ return create_point(result, x, y);
}
/***************************** MultiPoint *******************************/
-size_t GMultiPoint::get_data_size() const
+uint32 Gis_multi_point::get_data_size() const
{
+ if (no_data(m_data, 4))
+ return GET_SIZE_ERROR;
return 4 + uint4korr(m_data)*(POINT_DATA_SIZE + WKB_HEADER_SIZE);
}
-int GMultiPoint::init_from_wkt(GTextReadStream *trs, String *wkb)
+
+bool Gis_multi_point::init_from_wkt(Gis_read_stream *trs, String *wkb)
{
- uint32 n_points = 0;
- int np_pos = wkb->length();
- GPoint p;
+ uint32 n_points= 0;
+ uint32 np_pos= wkb->length();
+ Gis_point p;
if (wkb->reserve(4, 512))
return 1;
- wkb->q_append((uint32)n_points);
+ wkb->length(wkb->length()+4); // Reserve space for points
for (;;)
{
if (wkb->reserve(1+4, 512))
return 1;
- wkb->q_append((char)wkbNDR);
- wkb->q_append((uint32)wkbPoint);
+ wkb->q_append((char) wkbNDR);
+ wkb->q_append((uint32) wkbPoint);
if (p.init_from_wkt(trs, wkb))
return 1;
- ++n_points;
- if (trs->get_next_toc_type() == GTextReadStream::comma)
- trs->get_next_symbol();
- else
+ n_points++;
+ if (trs->skip_char(',')) // Didn't find ','
break;
}
- wkb->WriteAtPosition(np_pos, n_points);
-
+ wkb->write_at_position(np_pos, n_points); // Store number of found points
return 0;
}
-int GMultiPoint::get_data_as_wkt(String *txt) const
+
+bool Gis_multi_point::get_data_as_wkt(String *txt, const char **end)
{
uint32 n_points;
- const char *data= m_data;
- if (no_data(data, 4))
- return 1;
-
- n_points= uint4korr(data);
- data+= 4;
- if (no_data(data, n_points * (8 + 8 + WKB_HEADER_SIZE)))
+ if (no_data(m_data, 4))
return 1;
- if (txt->reserve(((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points))
+ n_points= uint4korr(m_data);
+ if (no_data(m_data+4,
+ n_points * (SIZEOF_STORED_DOUBLE * 2 + WKB_HEADER_SIZE)) ||
+ txt->reserve(((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points))
return 1;
-
- for (; n_points>0; --n_points)
- {
- double d;
- float8get(d, data + WKB_HEADER_SIZE);
- txt->qs_append(d);
- txt->qs_append(' ');
- float8get(d, data + WKB_HEADER_SIZE + 8);
- txt->qs_append(d);
- txt->qs_append(',');
- data+= WKB_HEADER_SIZE + 8 + 8;
- }
- txt->length(txt->length()-1);
+ *end= append_points(txt, n_points, m_data+4, WKB_HEADER_SIZE);
+ txt->length(txt->length()-1); // Remove end ','
return 0;
}
-int GMultiPoint::get_mbr(MBR *mbr) const
+
+bool Gis_multi_point::get_mbr(MBR *mbr, const char **end) const
{
- uint32 n_points;
- const char *data = m_data;
- if (no_data(data, 4))
- return 1;
- n_points = uint4korr(data);
- data += 4;
- if (no_data(data, n_points * (8+8+WKB_HEADER_SIZE)))
- return 1;
- for (; n_points>0; --n_points)
- {
- mbr->add_xy(data + WKB_HEADER_SIZE, data + 8 + WKB_HEADER_SIZE);
- data += (8+8+WKB_HEADER_SIZE);
- }
- return 0;
+ return (*end= get_mbr_for_points(mbr, m_data, WKB_HEADER_SIZE)) == 0;
}
-int GMultiPoint::num_geometries(uint32 *num) const
+
+bool Gis_multi_point::num_geometries(uint32 *num) const
{
- *num = uint4korr(m_data);
+ *num= uint4korr(m_data);
return 0;
}
-int GMultiPoint::geometry_n(uint32 num, String *result) const
+
+bool Gis_multi_point::geometry_n(uint32 num, String *result) const
{
const char *data= m_data;
uint32 n_points;
+
if (no_data(data, 4))
return 1;
n_points= uint4korr(data);
- data+= 4;
- if ((num > n_points) || (num < 1))
- return -1;
- data+= (num - 1) * (WKB_HEADER_SIZE + POINT_DATA_SIZE);
- if (result->reserve(WKB_HEADER_SIZE + POINT_DATA_SIZE))
+ data+= 4+ (num - 1) * (WKB_HEADER_SIZE + POINT_DATA_SIZE);
+
+ if (num > n_points || num < 1 ||
+ no_data(data, WKB_HEADER_SIZE + POINT_DATA_SIZE) ||
+ result->reserve(WKB_HEADER_SIZE + POINT_DATA_SIZE))
return 1;
- result->q_append(data, WKB_HEADER_SIZE + POINT_DATA_SIZE);
+ result->q_append(data, WKB_HEADER_SIZE + POINT_DATA_SIZE);
return 0;
}
+
/***************************** MultiLineString *******************************/
-size_t GMultiLineString::get_data_size() const
+uint32 Gis_multi_line_stringg::get_data_size() const
{
- uint32 n_line_strings = 0;
- const char *data = m_data;
+ uint32 n_line_strings;
+ const char *data= m_data;
+
if (no_data(data, 4))
- return 1;
- n_line_strings = uint4korr(data);
- data += 4;
+ return GET_SIZE_ERROR;
+ n_line_strings= uint4korr(data);
+ data+= 4;
- for (; n_line_strings>0; --n_line_strings)
+ while (n_line_strings--)
{
if (no_data(data, WKB_HEADER_SIZE + 4))
- return 1;
- data += WKB_HEADER_SIZE + 4 + uint4korr(data + WKB_HEADER_SIZE) * POINT_DATA_SIZE;
+ return GET_SIZE_ERROR;
+ data+= (WKB_HEADER_SIZE + 4 + uint4korr(data + WKB_HEADER_SIZE) *
+ POINT_DATA_SIZE);
}
- return data - m_data;
+ return (uint32) (data - m_data);
}
-int GMultiLineString::init_from_wkt(GTextReadStream *trs, String *wkb)
+
+bool Gis_multi_line_stringg::init_from_wkt(Gis_read_stream *trs, String *wkb)
{
- uint32 n_line_strings = 0;
- int ls_pos = wkb->length();
+ uint32 n_line_strings= 0;
+ uint32 ls_pos= wkb->length();
if (wkb->reserve(4, 512))
return 1;
-
- wkb->q_append((uint32)n_line_strings);
+ wkb->length(wkb->length()+4); // Reserve space for points
for (;;)
{
- GLineString ls;
+ Gis_line_string ls;
if (wkb->reserve(1+4, 512))
return 1;
- wkb->q_append((char)wkbNDR);
- wkb->q_append((uint32)wkbLineString);
-
- if (trs->get_next_symbol() != '(')
- {
- trs->set_error_msg("'(' expected");
- return 1;
- }
- if (ls.init_from_wkt(trs, wkb))
- return 1;
+ wkb->q_append((char) wkbNDR);
+ wkb->q_append((uint32) wkbLineString);
- if (trs->get_next_symbol() != ')')
- {
- trs->set_error_msg("')' expected");
+ if (trs->check_next_symbol('(') ||
+ ls.init_from_wkt(trs, wkb) ||
+ trs->check_next_symbol(')'))
return 1;
- }
- ++n_line_strings;
- if (trs->get_next_toc_type() == GTextReadStream::comma)
- trs->get_next_symbol();
- else
+ n_line_strings++;
+ if (trs->skip_char(',')) // Didn't find ','
break;
}
- wkb->WriteAtPosition(ls_pos, n_line_strings);
-
+ wkb->write_at_position(ls_pos, n_line_strings);
return 0;
}
-int GMultiLineString::get_data_as_wkt(String *txt) const
+
+bool Gis_multi_line_stringg::get_data_as_wkt(String *txt, const char **end)
{
uint32 n_line_strings;
const char *data= m_data;
+
if (no_data(data, 4))
return 1;
n_line_strings= uint4korr(data);
data+= 4;
- for (; n_line_strings > 0; --n_line_strings)
+
+ while (n_line_strings--)
{
+ uint32 n_points;
if (no_data(data, (WKB_HEADER_SIZE + 4)))
return 1;
- uint32 n_points= uint4korr(data + WKB_HEADER_SIZE);
+ n_points= uint4korr(data + WKB_HEADER_SIZE);
data+= WKB_HEADER_SIZE + 4;
- if (no_data(data, n_points * (8 + 8)))
- return 1;
-
- if (txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points))
+ if (no_data(data, n_points * (SIZEOF_STORED_DOUBLE*2)) ||
+ txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points))
return 1;
txt->qs_append('(');
- for (; n_points>0; --n_points)
- {
- double d;
- float8get(d, data);
- txt->qs_append(d);
- txt->qs_append(' ');
- float8get(d, data + 8);
- txt->qs_append(d);
- txt->qs_append(',');
- data+= 8 + 8;
- }
- (*txt) [txt->length() - 1] = ')';
+ data= append_points(txt, n_points, data, 0);
+ (*txt) [txt->length() - 1]= ')';
txt->qs_append(',');
}
txt->length(txt->length() - 1);
+ *end= data;
return 0;
}
-int GMultiLineString::get_mbr(MBR *mbr) const
+
+bool Gis_multi_line_stringg::get_mbr(MBR *mbr, const char **end) const
{
uint32 n_line_strings;
- const char *data = m_data;
+ const char *data= m_data;
+
if (no_data(data, 4))
return 1;
- n_line_strings = uint4korr(data);
- data += 4;
+ n_line_strings= uint4korr(data);
+ data+= 4;
- for (; n_line_strings>0; --n_line_strings)
+ while (n_line_strings--)
{
- if (no_data(data, WKB_HEADER_SIZE + 4))
- return 1;
- uint32 n_points = uint4korr(data + WKB_HEADER_SIZE);
- data += 4+WKB_HEADER_SIZE;
- if (no_data(data, (8+8)*n_points))
+ data+= WKB_HEADER_SIZE;
+ if (!(data= get_mbr_for_points(mbr, data, 0)))
return 1;
-
- for (; n_points>0; --n_points)
- {
- mbr->add_xy(data, data + 8);
- data += 8+8;
- }
}
+ *end= data;
return 0;
}
-int GMultiLineString::num_geometries(uint32 *num) const
+
+bool Gis_multi_line_stringg::num_geometries(uint32 *num) const
{
- *num = uint4korr(m_data);
+ *num= uint4korr(m_data);
return 0;
}
-int GMultiLineString::geometry_n(uint32 num, String *result) const
+
+bool Gis_multi_line_stringg::geometry_n(uint32 num, String *result) const
{
- uint32 n_line_strings;
+ uint32 n_line_strings, n_points, length;
const char *data= m_data;
+
if (no_data(data, 4))
return 1;
n_line_strings= uint4korr(data);
data+= 4;
if ((num > n_line_strings) || (num < 1))
- return -1;
+ return 1;
- for (; num > 0; --num)
+ for (;;)
{
if (no_data(data, WKB_HEADER_SIZE + 4))
return 1;
- uint32 n_points= uint4korr(data + WKB_HEADER_SIZE);
- if (num == 1)
- {
- if (result->reserve(WKB_HEADER_SIZE + 4 + POINT_DATA_SIZE * n_points))
- return 1;
- result->q_append(data, WKB_HEADER_SIZE + 4 + POINT_DATA_SIZE *n_points);
+ n_points= uint4korr(data + WKB_HEADER_SIZE);
+ length= WKB_HEADER_SIZE + 4+ POINT_DATA_SIZE * n_points;
+ if (no_data(data, length))
+ return 1;
+ if (!--num)
break;
- }
- else
- {
- data+= WKB_HEADER_SIZE + 4 + POINT_DATA_SIZE * n_points;
- }
+ data+= length;
}
- return 0;
+ return result->append(data, length, (uint32) 0);
}
-int GMultiLineString::length(double *len) const
+
+bool Gis_multi_line_stringg::length(double *len) const
{
uint32 n_line_strings;
- const char *data = m_data;
+ const char *data= m_data;
+
if (no_data(data, 4))
return 1;
- n_line_strings = uint4korr(data);
- data += 4;
+ n_line_strings= uint4korr(data);
+ data+= 4;
+
*len=0;
- for (; n_line_strings>0; --n_line_strings)
+ while (n_line_strings--)
{
double ls_len;
- GLineString ls;
- data += WKB_HEADER_SIZE;
- ls.init_from_wkb(data, m_data_end - data);
+ Gis_line_string ls;
+ data+= WKB_HEADER_SIZE;
+ ls.init_from_wkb(data, (uint32) (m_data_end - data));
if (ls.length(&ls_len))
return 1;
- *len+=ls_len;
- data += ls.get_data_size();
+ *len+= ls_len;
+ /*
+ We know here that ls was ok, so we can call the trivial function
+ Gis_line_string::get_data_size without error checking
+ */
+ data+= ls.get_data_size();
}
return 0;
}
-int GMultiLineString::is_closed(int *closed) const
+
+bool Gis_multi_line_stringg::is_closed(int *closed) const
{
uint32 n_line_strings;
- const char *data = m_data;
- if (no_data(data, 1))
+ const char *data= m_data;
+
+ if (no_data(data, 4 + WKB_HEADER_SIZE))
return 1;
- n_line_strings = uint4korr(data);
- data += 4 + WKB_HEADER_SIZE;
- for (; n_line_strings>0; --n_line_strings)
+ n_line_strings= uint4korr(data);
+ data+= 4 + WKB_HEADER_SIZE;
+
+ while (n_line_strings--)
{
- GLineString ls;
- ls.init_from_wkb(data, m_data_end - data);
+ Gis_line_string ls;
+ if (no_data(data, 0))
+ return 1;
+ ls.init_from_wkb(data, (uint32) (m_data_end - data));
if (ls.is_closed(closed))
return 1;
if (!*closed)
return 0;
- data += ls.get_data_size() + WKB_HEADER_SIZE;
+ /*
+ We know here that ls was ok, so we can call the trivial function
+ Gis_line_string::get_data_size without error checking
+ */
+ data+= ls.get_data_size() + WKB_HEADER_SIZE;
}
return 0;
}
+
/***************************** MultiPolygon *******************************/
-size_t GMultiPolygon::get_data_size() const
+uint32 Gis_multi_polygon::get_data_size() const
{
uint32 n_polygons;
- const char *data = m_data;
+ const char *data= m_data;
+
if (no_data(data, 4))
- return 1;
- n_polygons = uint4korr(data);
- data += 4;
+ return GET_SIZE_ERROR;
+ n_polygons= uint4korr(data);
+ data+= 4;
- for (; n_polygons>0; --n_polygons)
+ while (n_polygons--)
{
+ uint32 n_linear_rings;
if (no_data(data, 4 + WKB_HEADER_SIZE))
- return 1;
- uint32 n_linear_rings = uint4korr(data + WKB_HEADER_SIZE);
- data += 4 + WKB_HEADER_SIZE;
+ return GET_SIZE_ERROR;
- for (; n_linear_rings > 0; --n_linear_rings)
+ n_linear_rings= uint4korr(data + WKB_HEADER_SIZE);
+ data+= 4 + WKB_HEADER_SIZE;
+
+ while (n_linear_rings--)
{
- data += 4 + uint4korr(data) * POINT_DATA_SIZE;
+ if (no_data(data, 4))
+ return GET_SIZE_ERROR;
+ data+= 4 + uint4korr(data) * POINT_DATA_SIZE;
}
}
- return data - m_data;
+ return (uint32) (data - m_data);
}
-int GMultiPolygon::init_from_wkt(GTextReadStream *trs, String *wkb)
+
+bool Gis_multi_polygon::init_from_wkt(Gis_read_stream *trs, String *wkb)
{
- uint32 n_polygons = 0;
- int np_pos = wkb->length();
- GPolygon p;
+ uint32 n_polygons= 0;
+ int np_pos= wkb->length();
+ Gis_polygon p;
if (wkb->reserve(4, 512))
return 1;
-
- wkb->q_append((uint32)n_polygons);
+ wkb->length(wkb->length()+4); // Reserve space for points
for (;;)
{
if (wkb->reserve(1+4, 512))
return 1;
- wkb->q_append((char)wkbNDR);
- wkb->q_append((uint32)wkbPolygon);
+ wkb->q_append((char) wkbNDR);
+ wkb->q_append((uint32) wkbPolygon);
- if (trs->get_next_symbol() != '(')
- {
- trs->set_error_msg("'(' expected");
- return 1;
- }
- if (p.init_from_wkt(trs, wkb))
- return 1;
- if (trs->get_next_symbol() != ')')
- {
- trs->set_error_msg("')' expected");
+ if (trs->check_next_symbol('(') ||
+ p.init_from_wkt(trs, wkb) ||
+ trs->check_next_symbol(')'))
return 1;
- }
- ++n_polygons;
- if (trs->get_next_toc_type() == GTextReadStream::comma)
- trs->get_next_symbol();
- else
+ n_polygons++;
+ if (trs->skip_char(',')) // Didn't find ','
break;
}
- wkb->WriteAtPosition(np_pos, n_polygons);
+ wkb->write_at_position(np_pos, n_polygons);
return 0;
}
-int GMultiPolygon::get_data_as_wkt(String *txt) const
+
+bool Gis_multi_polygon::get_data_as_wkt(String *txt, const char **end)
{
uint32 n_polygons;
const char *data= m_data;
+
if (no_data(data, 4))
return 1;
n_polygons= uint4korr(data);
data+= 4;
- for (; n_polygons>0; --n_polygons)
+ while (n_polygons--)
{
- if (no_data(data, 4 + WKB_HEADER_SIZE))
- return 1;
- data+= WKB_HEADER_SIZE;
- uint32 n_linear_rings= uint4korr(data);
- data+= 4;
-
- if (txt->reserve(1, 512))
+ uint32 n_linear_rings;
+ if (no_data(data, 4 + WKB_HEADER_SIZE) ||
+ txt->reserve(1, 512))
return 1;
+ n_linear_rings= uint4korr(data+WKB_HEADER_SIZE);
+ data+= 4 + WKB_HEADER_SIZE;
txt->q_append('(');
- for (; n_linear_rings>0; --n_linear_rings)
+
+ while (n_linear_rings--)
{
if (no_data(data, 4))
return 1;
uint32 n_points= uint4korr(data);
data+= 4;
- if (no_data(data, (8 + 8) * n_points)) return 1;
-
- if (txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points,
- 512)) return 1;
+ if (no_data(data, (SIZEOF_STORED_DOUBLE * 2) * n_points) ||
+ txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points,
+ 512))
+ return 1;
txt->qs_append('(');
- for (; n_points>0; --n_points)
- {
- double d;
- float8get(d, data);
- txt->qs_append(d);
- txt->qs_append(' ');
- float8get(d, data + 8);
- txt->qs_append(d);
- txt->qs_append(',');
- data+= 8 + 8;
- }
- (*txt) [txt->length() - 1] = ')';
+ data= append_points(txt, n_points, data, 0);
+ (*txt) [txt->length() - 1]= ')';
txt->qs_append(',');
}
- (*txt) [txt->length() - 1] = ')';
+ (*txt) [txt->length() - 1]= ')';
txt->qs_append(',');
}
txt->length(txt->length() - 1);
+ *end= data;
return 0;
}
-int GMultiPolygon::get_mbr(MBR *mbr) const
+
+bool Gis_multi_polygon::get_mbr(MBR *mbr, const char **end) const
{
uint32 n_polygons;
- const char *data = m_data;
+ const char *data= m_data;
+
if (no_data(data, 4))
return 1;
- n_polygons = uint4korr(data);
- data += 4;
+ n_polygons= uint4korr(data);
+ data+= 4;
- for (; n_polygons>0; --n_polygons)
+ while (n_polygons--)
{
+ uint32 n_linear_rings;
if (no_data(data, 4+WKB_HEADER_SIZE))
return 1;
- uint32 n_linear_rings = uint4korr(data + WKB_HEADER_SIZE);
- data += WKB_HEADER_SIZE + 4;
+ n_linear_rings= uint4korr(data + WKB_HEADER_SIZE);
+ data+= WKB_HEADER_SIZE + 4;
- for (; n_linear_rings>0; --n_linear_rings)
+ while (n_linear_rings--)
{
- if (no_data(data, 4))
- return 1;
- uint32 n_points = uint4korr(data);
- data += 4;
- if (no_data(data, (8+8)*n_points))
- return 1;
-
- for (; n_points>0; --n_points)
- {
- mbr->add_xy(data, data + 8);
- data += 8+8;
- }
+ if (!(data= get_mbr_for_points(mbr, data, 0)))
+ return 1;
}
}
+ *end= data;
return 0;
}
-int GMultiPolygon::num_geometries(uint32 *num) const
+
+bool Gis_multi_polygon::num_geometries(uint32 *num) const
{
- *num = uint4korr(m_data);
+ *num= uint4korr(m_data);
return 0;
}
-int GMultiPolygon::geometry_n(uint32 num, String *result) const
+
+bool Gis_multi_polygon::geometry_n(uint32 num, String *result) const
{
uint32 n_polygons;
- const char *data= m_data, *polygon_n;
- LINT_INIT(polygon_n);
+ const char *data= m_data, *start_of_polygon;
if (no_data(data, 4))
return 1;
n_polygons= uint4korr(data);
data+= 4;
- if ((num > n_polygons) || (num < 1))
+ if (num > n_polygons || num < 1)
return -1;
- for (; num > 0; --num)
+ do
{
+ uint32 n_linear_rings;
+ start_of_polygon= data;
+
if (no_data(data, WKB_HEADER_SIZE + 4))
return 1;
- uint32 n_linear_rings= uint4korr(data + WKB_HEADER_SIZE);
-
- if (num == 1)
- polygon_n= data;
+ n_linear_rings= uint4korr(data + WKB_HEADER_SIZE);
data+= WKB_HEADER_SIZE + 4;
- for (; n_linear_rings > 0; --n_linear_rings)
+
+ while (n_linear_rings--)
{
+ uint32 n_points;
if (no_data(data, 4))
return 1;
- uint32 n_points= uint4korr(data);
+ n_points= uint4korr(data);
data+= 4 + POINT_DATA_SIZE * n_points;
}
- if (num == 1)
- {
- if (result->reserve(data - polygon_n))
- return -1;
- result->q_append(polygon_n, data - polygon_n);
- break;
- }
- }
- return 0;
+ } while (--num);
+ if (no_data(data, 0)) // We must check last segment
+ return 1;
+ return result->append(start_of_polygon, (uint32) (data - start_of_polygon),
+ (uint32) 0);
}
-int GMultiPolygon::area(double *ar) const
+
+bool Gis_multi_polygon::area(double *ar, const char **end_of_data) const
{
uint32 n_polygons;
- const char *data = m_data;
- double result = 0;
+ const char *data= m_data;
+ double result= 0;
+
if (no_data(data, 4))
return 1;
- n_polygons = uint4korr(data);
- data += 4;
+ n_polygons= uint4korr(data);
+ data+= 4;
- for (; n_polygons>0; --n_polygons)
+ while (n_polygons--)
{
double p_area;
+ Gis_polygon p;
- GPolygon p;
- data += WKB_HEADER_SIZE;
- p.init_from_wkb(data, m_data_end - data);
- if (p.area(&p_area))
+ data+= WKB_HEADER_SIZE;
+ p.init_from_wkb(data, (uint32) (m_data_end - data));
+ if (p.area(&p_area, &data))
return 1;
- result += p_area;
- data += p.get_data_size();
+ result+= p_area;
}
- *ar = result;
+ *ar= result;
+ *end_of_data= data;
return 0;
}
-int GMultiPolygon::centroid(String *result) const
+
+bool Gis_multi_polygon::centroid(String *result)
{
uint32 n_polygons;
- uint i;
- GPolygon p;
+ bool first_loop= 1;
+ Gis_polygon p;
double res_area, res_cx, res_cy;
double cur_area, cur_cx, cur_cy;
+ const char *data= m_data;
LINT_INIT(res_area);
LINT_INIT(res_cx);
LINT_INIT(res_cy);
- const char *data = m_data;
if (no_data(data, 4))
return 1;
- n_polygons = uint4korr(data);
- data += 4;
+ n_polygons= uint4korr(data);
+ data+= 4;
- for (i = 0; i < n_polygons; ++i)
+ while (n_polygons--)
{
- data += WKB_HEADER_SIZE;
- p.init_from_wkb(data, m_data_end - data);
- if (p.area(&cur_area))
- return 1;
-
- if (p.centroid_xy(&cur_cx, &cur_cy))
+ data+= WKB_HEADER_SIZE;
+ p.init_from_wkb(data, (uint32) (m_data_end - data));
+ if (p.area(&cur_area, &data) ||
+ p.centroid_xy(&cur_cx, &cur_cy))
return 1;
- if (i)
+ if (!first_loop)
{
- double sum_area = res_area + cur_area;
- res_cx = (res_area * res_cx + cur_area * cur_cx) / sum_area;
- res_cy = (res_area * res_cy + cur_area * cur_cy) / sum_area;
+ double sum_area= res_area + cur_area;
+ res_cx= (res_area * res_cx + cur_area * cur_cx) / sum_area;
+ res_cy= (res_area * res_cy + cur_area * cur_cy) / sum_area;
}
else
{
- res_area = cur_area;
- res_cx = cur_cx;
- res_cy = cur_cy;
+ first_loop= 0;
+ res_area= cur_area;
+ res_cx= cur_cx;
+ res_cy= cur_cy;
}
-
- data += p.get_data_size();
}
- if (result->reserve(1 + 4 + sizeof(double) * 2))
- return 1;
- result->q_append((char)wkbNDR);
- result->q_append((uint32)wkbPoint);
- result->q_append(res_cx);
- result->q_append(res_cy);
-
- return 0;
+ return create_point(result, res_cx, res_cy);
}
-/***************************** GeometryCollection *******************************/
-size_t GGeometryCollection::get_data_size() const
+/************************* GeometryCollection ****************************/
+
+uint32 Gis_geometry_collection::get_data_size() const
{
uint32 n_objects;
- const char *data = m_data;
+ const char *data= m_data;
+
if (no_data(data, 4))
- return 1;
- n_objects = uint4korr(data);
- data += 4;
+ return GET_SIZE_ERROR;
+ n_objects= uint4korr(data);
+ data+= 4;
- for (; n_objects>0; --n_objects)
+ while (n_objects--)
{
- if (no_data(data, WKB_HEADER_SIZE))
- return 1;
- uint32 wkb_type = uint4korr(data + sizeof(char));
- data += WKB_HEADER_SIZE;
-
+ uint32 wkb_type,object_size;
Geometry geom;
- if (geom.init(wkb_type))
- return 0;
+ if (no_data(data, WKB_HEADER_SIZE))
+ return GET_SIZE_ERROR;
+ wkb_type= uint4korr(data + 1);
+ data+= WKB_HEADER_SIZE;
- geom.init_from_wkb(data, m_data_end - data);
- size_t object_size=geom.get_data_size();
- data += object_size;
+ if (geom.init(wkb_type))
+ return GET_SIZE_ERROR;
+ geom.init_from_wkb(data, (uint) (m_data_end - data));
+ if ((object_size= geom.get_data_size()) == GET_SIZE_ERROR)
+ return GET_SIZE_ERROR;
+ data+= object_size;
}
- return data - m_data;
+ return (uint32) (data - m_data);
}
-int GGeometryCollection::init_from_wkt(GTextReadStream *trs, String *wkb)
+
+bool Gis_geometry_collection::init_from_wkt(Gis_read_stream *trs, String *wkb)
{
- uint32 n_objects = 0;
- int no_pos = wkb->length();
+ uint32 n_objects= 0;
+ uint32 no_pos= wkb->length();
Geometry g;
if (wkb->reserve(4, 512))
return 1;
- wkb->q_append((uint32)n_objects);
+ wkb->length(wkb->length()+4); // Reserve space for points
for (;;)
{
if (g.create_from_wkt(trs, wkb))
return 1;
- if (g.get_class_info()->m_type_id==wkbGeometryCollection)
+ if (g.get_class_info()->m_type_id == wkbGeometryCollection)
{
trs->set_error_msg("Unexpected GEOMETRYCOLLECTION");
return 1;
}
- ++n_objects;
- if (trs->get_next_toc_type() == GTextReadStream::comma)
- trs->get_next_symbol();
- else break;
+ n_objects++;
+ if (trs->skip_char(',')) // Didn't find ','
+ break;
}
- wkb->WriteAtPosition(no_pos, n_objects);
+ wkb->write_at_position(no_pos, n_objects);
return 0;
}
-int GGeometryCollection::get_data_as_wkt(String *txt) const
+
+bool Gis_geometry_collection::get_data_as_wkt(String *txt, const char **end)
{
uint32 n_objects;
- const char *data = m_data;
Geometry geom;
+ const char *data= m_data;
+
if (no_data(data, 4))
return 1;
- n_objects = uint4korr(data);
- data += 4;
+ n_objects= uint4korr(data);
+ data+= 4;
- for (; n_objects>0; --n_objects)
+ while (n_objects--)
{
+ uint32 wkb_type;
+
if (no_data(data, WKB_HEADER_SIZE))
return 1;
- uint32 wkb_type = uint4korr(data + sizeof(char));
- data += WKB_HEADER_SIZE;
+ wkb_type= uint4korr(data + 1);
+ data+= WKB_HEADER_SIZE;
if (geom.init(wkb_type))
return 1;
- geom.init_from_wkb(data, m_data_end - data);
- if (geom.as_wkt(txt))
+ geom.init_from_wkb(data, (uint) (m_data_end - data));
+ if (geom.as_wkt(txt, &data))
+ return 1;
+ if (txt->append(",", 1, 512))
return 1;
- data += geom.get_data_size();
- txt->reserve(1, 512);
- txt->q_append(',');
}
txt->length(txt->length() - 1);
+ *end= data;
return 0;
}
-int GGeometryCollection::get_mbr(MBR *mbr) const
+
+bool Gis_geometry_collection::get_mbr(MBR *mbr, const char **end) const
{
uint32 n_objects;
- const char *data = m_data;
+ const char *data= m_data;
+
if (no_data(data, 4))
return 1;
- n_objects = uint4korr(data);
- data += 4;
- for (; n_objects>0; --n_objects)
+ n_objects= uint4korr(data);
+ data+= 4;
+
+ while (n_objects--)
{
+ uint32 wkb_type;
+ Geometry geom;
+
if (no_data(data, WKB_HEADER_SIZE))
return 1;
- uint32 wkb_type = uint4korr(data + sizeof(char));
- data += WKB_HEADER_SIZE;
- Geometry geom;
+ wkb_type= uint4korr(data + 1);
+ data+= WKB_HEADER_SIZE;
if (geom.init(wkb_type))
return 1;
- geom.init_from_wkb(data, m_data_end - data);
- geom.get_mbr(mbr);
- data += geom.get_data_size();
+ geom.init_from_wkb(data, (uint32) (m_data_end - data));
+ if (geom.get_mbr(mbr, &data))
+ return 1;
}
+ *end= data;
return 0;
}
-int GGeometryCollection::num_geometries(uint32 *num) const
+
+bool Gis_geometry_collection::num_geometries(uint32 *num) const
{
- *num = uint4korr(m_data);
+ if (no_data(m_data, 4))
+ return 1;
+ *num= uint4korr(m_data);
return 0;
}
-int GGeometryCollection::geometry_n(uint32 num, String *result) const
+
+bool Gis_geometry_collection::geometry_n(uint32 num, String *result) const
{
- const char *data = m_data;
- uint32 n_objects;
+ uint32 n_objects, wkb_type, length;
+ const char *data= m_data;
+
if (no_data(data, 4))
return 1;
- n_objects = uint4korr(data);
- data += 4;
+ n_objects= uint4korr(data);
+ data+= 4;
+ if (num > n_objects || num < 1)
+ return 1;
- if ((num > n_objects) || (num < 1))
- {
- return -1;
- }
- for (; num > 0; --num)
+ do
{
+ Geometry geom;
+
if (no_data(data, WKB_HEADER_SIZE))
return 1;
- uint32 wkb_type = uint4korr(data + sizeof(char));
- data += WKB_HEADER_SIZE;
+ wkb_type= uint4korr(data + 1);
+ data+= WKB_HEADER_SIZE;
- Geometry geom;
if (geom.init(wkb_type))
return 1;
- geom.init_from_wkb(data, m_data_end - data);
- if (num == 1)
- {
- if (result->reserve(1+4+geom.get_data_size()))
- return 1;
- result->q_append((char)wkbNDR);
- result->q_append((uint32)wkb_type);
- result->q_append(data, geom.get_data_size());
- break;
- }
- else
- {
- data += geom.get_data_size();
- }
- }
+ geom.init_from_wkb(data, (uint) (m_data_end - data));
+ if ((length= geom.get_data_size()) == GET_SIZE_ERROR)
+ return 1;
+ data+= length;
+ } while (--num);
+
+ /* Copy found object to result */
+ if (result->reserve(1+4+length))
+ return 1;
+ result->q_append((char) wkbNDR);
+ result->q_append((uint32) wkb_type);
+ result->q_append(data-length, length); // data-length = start_of_data
return 0;
}
-int GGeometryCollection::dimension(uint32 *dim) const
+
+/*
+ Return dimension for object
+
+ SYNOPSIS
+ dimension()
+ res_dim Result dimension
+ end End of object will be stored here. May be 0 for
+ simple objects!
+ RETURN
+ 0 ok
+ 1 error
+*/
+
+bool Gis_geometry_collection::dimension(uint32 *res_dim, const char **end) const
{
uint32 n_objects;
- *dim = 0;
- const char *data = m_data;
+ const char *data= m_data;
+
if (no_data(data, 4))
return 1;
- n_objects = uint4korr(data);
- data += 4;
+ n_objects= uint4korr(data);
+ data+= 4;
- for (; n_objects > 0; --n_objects)
+ *res_dim= 0;
+ while (n_objects--)
{
+ uint32 wkb_type, length, dim;
+ const char *end_data;
+ Geometry geom;
+
if (no_data(data, WKB_HEADER_SIZE))
return 1;
- uint32 wkb_type = uint4korr(data + sizeof(char));
- data += WKB_HEADER_SIZE;
-
- uint32 d;
-
- Geometry geom;
+ wkb_type= uint4korr(data + 1);
+ data+= WKB_HEADER_SIZE;
if (geom.init(wkb_type))
return 1;
- geom.init_from_wkb(data, m_data_end - data);
- if (geom.dimension(&d))
+ geom.init_from_wkb(data, (uint32) (m_data_end - data));
+ if (geom.dimension(&dim, &end_data))
return 1;
-
- if (d > *dim)
- *dim = d;
- data += geom.get_data_size();
+ set_if_bigger(*res_dim, dim);
+ if (end_data) // Complex object
+ data= end_data;
+ else if ((length= geom.get_data_size()) == GET_SIZE_ERROR)
+ return 1;
+ else
+ data+= length;
}
+ *end= data;
return 0;
}
-
-/***************************** /objects *******************************/