spatial.cc | spatial.cc | |||
---|---|---|---|---|
/* | /* | |||
Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reser ved. | Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reser ved. | |||
This program is free software; you can redistribute it and/or modify | 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 | it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation; version 2 of the License. | the Free Software Foundation; version 2 of the License. | |||
This program is distributed in the hope that it will be useful, | This program is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | GNU General Public License for more details. | |||
skipping to change at line 128 | skipping to change at line 128 | |||
static Geometry::Class_info | static Geometry::Class_info | |||
multilinestring_class("MULTILINESTRING", | multilinestring_class("MULTILINESTRING", | |||
Geometry::wkb_multilinestring, create_multilinestring) ; | Geometry::wkb_multilinestring, create_multilinestring) ; | |||
static Geometry::Class_info multipolygon_class("MULTIPOLYGON", | static Geometry::Class_info multipolygon_class("MULTIPOLYGON", | |||
Geometry::wkb_multipolygo n, | Geometry::wkb_multipolygo n, | |||
create_multipolygon); | create_multipolygon); | |||
static Geometry::Class_info | static Geometry::Class_info | |||
geometrycollection_class("GEOMETRYCOLLECTION",Geometry::wkb_geometrycollect ion, | geometrycollection_class("GEOMETRYCOLLECTION",Geometry::wkb_geometrycollect ion, | |||
create_geometrycollection); | create_geometrycollection); | |||
static void get_point(double *x, double *y, const char *data) | ||||
{ | ||||
float8get(*x, data); | ||||
float8get(*y, data + SIZEOF_STORED_DOUBLE); | ||||
} | ||||
/***************************** Geometry *******************************/ | /***************************** Geometry *******************************/ | |||
Geometry::Class_info *Geometry::find_class(const char *name, uint32 len) | Geometry::Class_info *Geometry::find_class(const char *name, uint32 len) | |||
{ | { | |||
for (Class_info **cur_rt= ci_collection; | for (Class_info **cur_rt= ci_collection; | |||
cur_rt < ci_collection_end; cur_rt++) | cur_rt < ci_collection_end; cur_rt++) | |||
{ | { | |||
if (*cur_rt && | if (*cur_rt && | |||
((*cur_rt)->m_name.length == len) && | ((*cur_rt)->m_name.length == len) && | |||
(my_strnncoll(&my_charset_latin1, | (my_strnncoll(&my_charset_latin1, | |||
skipping to change at line 171 | skipping to change at line 165 | |||
{ | { | |||
uint32 geom_type; | uint32 geom_type; | |||
Geometry *result; | Geometry *result; | |||
if (data_len < SRID_SIZE + WKB_HEADER_SIZE) // < 4 + (1 + 4) | if (data_len < SRID_SIZE + WKB_HEADER_SIZE) // < 4 + (1 + 4) | |||
return NULL; | return NULL; | |||
/* + 1 to skip the byte order (stored in position SRID_SIZE). */ | /* + 1 to skip the byte order (stored in position SRID_SIZE). */ | |||
geom_type= uint4korr(data + SRID_SIZE + 1); | geom_type= uint4korr(data + SRID_SIZE + 1); | |||
if (!(result= create_by_typeid(buffer, (int) geom_type))) | if (!(result= create_by_typeid(buffer, (int) geom_type))) | |||
return NULL; | return NULL; | |||
result->m_data= data+ SRID_SIZE + WKB_HEADER_SIZE; | result->set_data_ptr(data + SRID_SIZE + WKB_HEADER_SIZE, | |||
result->m_data_end= data + data_len; | data_len - SRID_SIZE - WKB_HEADER_SIZE); | |||
return result; | return result; | |||
} | } | |||
Geometry *Geometry::create_from_wkt(Geometry_buffer *buffer, | Geometry *Geometry::create_from_wkt(Geometry_buffer *buffer, | |||
Gis_read_stream *trs, String *wkt, | Gis_read_stream *trs, String *wkt, | |||
bool init_stream) | bool init_stream) | |||
{ | { | |||
LEX_STRING name; | LEX_STRING name; | |||
Class_info *ci; | Class_info *ci; | |||
if (trs->get_next_word(&name)) | if (trs->get_next_word(&name)) | |||
{ | { | |||
trs->set_error_msg("Geometry name expected"); | trs->set_error_msg("Geometry name expected"); | |||
return NULL; | return NULL; | |||
} | } | |||
if (!(ci= find_class(name.str, name.length)) || | if (!(ci= find_class(name.str, name.length)) || | |||
wkt->reserve(1 + 4, 512)) | wkt->reserve(WKB_HEADER_SIZE, 512)) | |||
return NULL; | return NULL; | |||
Geometry *result= (*ci->m_create_func)(buffer->data); | Geometry *result= (*ci->m_create_func)(buffer->data); | |||
wkt->q_append((char) wkb_ndr); | wkt->q_append((char) wkb_ndr); | |||
wkt->q_append((uint32) result->get_class_info()->m_type_id); | wkt->q_append((uint32) result->get_class_info()->m_type_id); | |||
if (trs->check_next_symbol('(') || | if (trs->check_next_symbol('(') || | |||
result->init_from_wkt(trs, wkt) || | result->init_from_wkt(trs, wkt) || | |||
trs->check_next_symbol(')')) | trs->check_next_symbol(')')) | |||
return NULL; | return NULL; | |||
if (init_stream) | if (init_stream) | |||
{ | result->set_data_ptr(wkt->ptr() + WKB_HEADER_SIZE, | |||
result->set_data_ptr(wkt->ptr(), wkt->length()); | wkt->length() - WKB_HEADER_SIZE); | |||
result->shift_wkb_header(); | ||||
} | ||||
return result; | return result; | |||
} | } | |||
static double wkb_get_double(const char *ptr, Geometry::wkbByteOrder bo) | static double wkb_get_double(const char *ptr, Geometry::wkbByteOrder bo) | |||
{ | { | |||
double res; | double res; | |||
if (bo != Geometry::wkb_xdr) | if (bo != Geometry::wkb_xdr) | |||
{ | { | |||
float8get(res, ptr); | float8get(res, ptr); | |||
} | } | |||
skipping to change at line 281 | skipping to change at line 273 | |||
return 1; | return 1; | |||
res->q_append((char) wkb_ndr); | res->q_append((char) wkb_ndr); | |||
res->q_append(geom_type); | res->q_append(geom_type); | |||
return obj->init_from_opresult(res, rr.result(), rr.length()); | return obj->init_from_opresult(res, rr.result(), rr.length()); | |||
} | } | |||
bool Geometry::envelope(String *result) const | bool Geometry::envelope(String *result) const | |||
{ | { | |||
MBR mbr; | MBR mbr; | |||
const char *end; | wkb_parser wkb(&m_wkb_data); | |||
if (get_mbr(&mbr, &end) || | if (get_mbr(&mbr, &wkb) || | |||
result->reserve(1 + 4 * 3 + SIZEOF_STORED_DOUBLE * 10)) | result->reserve(1 + 4 * 3 + SIZEOF_STORED_DOUBLE * 10)) | |||
return 1; | return true; | |||
result->q_append((char) wkb_ndr); | result->q_append((char) wkb_ndr); | |||
result->q_append((uint32) wkb_polygon); | result->q_append((uint32) wkb_polygon); | |||
result->q_append((uint32) 1); | result->q_append((uint32) 1); | |||
result->q_append((uint32) 5); | result->q_append((uint32) 5); | |||
result->q_append(mbr.xmin); | result->q_append(mbr.xmin); | |||
result->q_append(mbr.ymin); | result->q_append(mbr.ymin); | |||
result->q_append(mbr.xmax); | result->q_append(mbr.xmax); | |||
result->q_append(mbr.ymin); | result->q_append(mbr.ymin); | |||
result->q_append(mbr.xmax); | result->q_append(mbr.xmax); | |||
result->q_append(mbr.ymax); | result->q_append(mbr.ymax); | |||
result->q_append(mbr.xmin); | result->q_append(mbr.xmin); | |||
result->q_append(mbr.ymax); | result->q_append(mbr.ymax); | |||
result->q_append(mbr.xmin); | result->q_append(mbr.xmin); | |||
result->q_append(mbr.ymin); | result->q_append(mbr.ymin); | |||
return 0; | return false; | |||
} | } | |||
/* | /** | |||
Create a point from data. | Create a point from data. | |||
SYNPOSIS | @param OUT result Put result here | |||
create_point() | @param wkb Data for point is here. | |||
result Put result here | ||||
data Data for point is here. | ||||
RETURN | @return false on success, true on error | |||
0 ok | ||||
1 Can't reallocate 'result' | ||||
*/ | */ | |||
bool Geometry::create_point(String *result, const char *data) const | bool Geometry::create_point(String *result, wkb_parser *wkb) const | |||
{ | { | |||
if (no_data(data, POINT_DATA_SIZE) || | if (wkb->no_data(POINT_DATA_SIZE) || | |||
result->reserve(1 + 4 + POINT_DATA_SIZE)) | result->reserve(WKB_HEADER_SIZE + POINT_DATA_SIZE)) | |||
return 1; | return true; | |||
result->q_append((char) wkb_ndr); | result->q_append((char) wkb_ndr); | |||
result->q_append((uint32) wkb_point); | result->q_append((uint32) wkb_point); | |||
/* Copy two double in same format */ | /* Copy two double in same format */ | |||
result->q_append(data, POINT_DATA_SIZE); | result->q_append(wkb->data(), POINT_DATA_SIZE); | |||
return 0; | return false; | |||
} | } | |||
/* | /** | |||
Create a point from coordinates. | Create a point from coordinates. | |||
SYNPOSIS | @param OUT result | |||
create_point() | @param x x coordinate for point | |||
result Put result here | @param y y coordinate for point | |||
x x coordinate for point | ||||
y y coordinate for point | ||||
RETURN | @return false on success, true on error | |||
0 ok | ||||
1 Can't reallocate 'result' | ||||
*/ | */ | |||
bool Geometry::create_point(String *result, double x, double y) const | bool Geometry::create_point(String *result, point_xy p) const | |||
{ | { | |||
if (result->reserve(1 + 4 + POINT_DATA_SIZE)) | if (result->reserve(1 + 4 + POINT_DATA_SIZE)) | |||
return 1; | return true; | |||
result->q_append((char) wkb_ndr); | result->q_append((char) wkb_ndr); | |||
result->q_append((uint32) wkb_point); | result->q_append((uint32) wkb_point); | |||
result->q_append(x); | result->q_append(p.x); | |||
result->q_append(y); | result->q_append(p.y); | |||
return 0; | return false; | |||
} | } | |||
/* | /** | |||
Append N points from packed format to text | Append N points from packed format to text | |||
SYNOPSIS | @param OUT txt Append points here | |||
append_points() | @param n_points Number of points | |||
txt Append points here | @param wkb Packed data | |||
n_points Number of points | @param offset Offset between points | |||
data Packed data | ||||
offset Offset between points | ||||
RETURN | ||||
# end of data | ||||
*/ | */ | |||
const char *Geometry::append_points(String *txt, uint32 n_points, | void Geometry::append_points(String *txt, uint32 n_points, | |||
const char *data, uint32 offset) const | wkb_parser *wkb, uint32 offset) const | |||
{ | { | |||
while (n_points--) | while (n_points--) | |||
{ | { | |||
double x,y; | point_xy p; | |||
data+= offset; | wkb->skip_unsafe(offset); | |||
get_point(&x, &y, data); | wkb->scan_xy_unsafe(&p); | |||
data+= POINT_DATA_SIZE; | txt->qs_append(p.x); | |||
txt->qs_append(x); | ||||
txt->qs_append(' '); | txt->qs_append(' '); | |||
txt->qs_append(y); | txt->qs_append(p.y); | |||
txt->qs_append(','); | txt->qs_append(','); | |||
} | } | |||
return data; | ||||
} | } | |||
/* | /** | |||
Get most bounding rectangle (mbr) for X points | Get most bounding rectangle (mbr) for X points | |||
SYNOPSIS | @param OUT mbr Result | |||
get_mbr_for_points() | @param wkb Data for point is here. | |||
mbr MBR (store rectangle here) | @param offset Offset between points | |||
points Number of points | ||||
data Packed data | ||||
offset Offset between points | ||||
RETURN | @return false on success, true on error | |||
0 Wrong data | ||||
# end of data | ||||
*/ | */ | |||
const char *Geometry::get_mbr_for_points(MBR *mbr, const char *data, | bool Geometry::get_mbr_for_points(MBR *mbr, wkb_parser *wkb, | |||
uint offset) const | uint offset) const | |||
{ | { | |||
uint32 points; | uint32 n_points; | |||
/* read number of points */ | ||||
if (no_data(data, 4)) | ||||
return 0; | ||||
points= uint4korr(data); | ||||
data+= 4; | ||||
if (no_data(data, (POINT_DATA_SIZE + offset) * points)) | if (wkb->scan_n_points_and_check_data(&n_points, offset)) | |||
return 0; | return true; | |||
/* Calculate MBR for points */ | /* Calculate MBR for points */ | |||
while (points--) | while (n_points--) | |||
{ | { | |||
data+= offset; | wkb->skip_unsafe(offset); | |||
mbr->add_xy(data, data + SIZEOF_STORED_DOUBLE); | mbr->add_xy(wkb->data(), wkb->data() + SIZEOF_STORED_DOUBLE); | |||
data+= POINT_DATA_SIZE; | wkb->skip_unsafe(POINT_DATA_SIZE); | |||
} | } | |||
return data; | return false; | |||
} | } | |||
int Geometry::collection_store_shapes(Gcalc_shape_transporter *trn, | int Geometry::collection_store_shapes(Gcalc_shape_transporter *trn, | |||
Gcalc_shape_status *st, | Gcalc_shape_status *st, | |||
Geometry *collection_item) const | Geometry *collection_item) const | |||
{ | { | |||
uint32 n_objects; | uint32 n_objects; | |||
const char *data= m_data; | wkb_parser wkb(&m_wkb_data); | |||
Geometry_buffer buffer; | Geometry_buffer buffer; | |||
if (no_data(data, 4)) | if (wkb.scan_non_zero_uint4(&n_objects) || | |||
return 1; | trn->start_collection(st, n_objects)) | |||
n_objects= uint4korr(data); | ||||
data+= 4; | ||||
if (trn->start_collection(st, n_objects)) | ||||
return 1; | return 1; | |||
while (n_objects--) | while (n_objects--) | |||
{ | { | |||
if (no_data(data, WKB_HEADER_SIZE)) | ||||
return 1; | ||||
Geometry *geom; | Geometry *geom; | |||
if (!(geom= collection_item)) | if (!(geom= collection_item)) | |||
{ | { | |||
/* | /* | |||
Item type is not known in advance, e.g. GeometryCollection. | Item type is not known in advance, e.g. GeometryCollection. | |||
Create an item object in every iteration, | Create an item object in every iteration, | |||
according to the current wkb type. | according to the current wkb type. | |||
*/ | */ | |||
uint32 wkb_type= uint4korr(data + 1); | if (!(geom= scan_header_and_create(&wkb, &buffer))) | |||
if (!(geom= create_by_typeid(&buffer, wkb_type))) | return 1; | |||
} | ||||
else | ||||
{ | ||||
if (wkb.skip_wkb_header()) | ||||
return 1; | return 1; | |||
geom->set_data_ptr(&wkb); | ||||
} | } | |||
data+= WKB_HEADER_SIZE; | ||||
geom->set_data_ptr(data, (uint32) (m_data_end - data)); | ||||
Gcalc_shape_status item_status; | Gcalc_shape_status item_status; | |||
if (geom->store_shapes(trn, &item_status)) | if (geom->store_shapes(trn, &item_status) || | |||
return 1; | trn->collection_add_item(st, &item_status)) | |||
if (trn->collection_add_item(st, &item_status)) | ||||
return 1; | return 1; | |||
data+= geom->get_data_size(); | wkb.skip_unsafe(geom->get_data_size()); | |||
} | } | |||
trn->complete_collection(st); | trn->complete_collection(st); | |||
return 0; | return 0; | |||
} | } | |||
int Geometry::collection_area(double *ar, const char **end_of_data, | bool Geometry::collection_area(double *ar, wkb_parser *wkb, | |||
Geometry *collection_item) const | Geometry *collection_item) const | |||
{ | { | |||
uint32 n_objects; | uint32 n_objects; | |||
const char *data= m_data; | ||||
Geometry_buffer buffer; | Geometry_buffer buffer; | |||
if (no_data(data, 4)) | if (wkb->scan_non_zero_uint4(&n_objects)) | |||
return 1; | return true; | |||
n_objects= uint4korr(data); | ||||
data+= 4; | ||||
for (*ar= 0; n_objects; n_objects--) | for (*ar= 0; n_objects; n_objects--) | |||
{ | { | |||
if (no_data(data, WKB_HEADER_SIZE)) | ||||
return 1; | ||||
Geometry *geom; | Geometry *geom; | |||
if (!(geom= collection_item)) | if (!(geom= collection_item)) | |||
{ | { | |||
/* | /* | |||
Item type is not known in advance, e.g. GeometryCollection. | Item type is not known in advance, e.g. GeometryCollection. | |||
Create an item object according to the wkb type. | Create an item object according to the wkb type. | |||
*/ | */ | |||
uint32 wkb_type= uint4korr(data + 1); | if (!(geom= scan_header_and_create(wkb, &buffer))) | |||
if (!(geom= create_by_typeid(&buffer, wkb_type))) | return true; | |||
return 1; | } | |||
else | ||||
{ | ||||
if (wkb->skip_wkb_header()) | ||||
return true; | ||||
geom->set_data_ptr(wkb); | ||||
} | } | |||
data+= WKB_HEADER_SIZE; | ||||
geom->set_data_ptr(data, (uint32) (m_data_end - data)); | ||||
double item_area; | double item_area; | |||
if (geom->area(&item_area, &data)) | if (geom->area(&item_area, wkb)) | |||
return 1; | return true; | |||
*ar+= item_area; | *ar+= item_area; | |||
} | } | |||
*end_of_data= data; | return false; | |||
return 0; | ||||
} | } | |||
uint Geometry::collection_init_from_opresult(String *bin, | uint Geometry::collection_init_from_opresult(String *bin, | |||
const char *opres, | const char *opres, | |||
uint opres_length, | uint opres_length, | |||
Geometry *collection_item) | Geometry *collection_item) | |||
{ | { | |||
Geometry_buffer buffer; | Geometry_buffer buffer; | |||
const char *opres_orig= opres; | const char *opres_orig= opres; | |||
int n_items_offs= bin->length(); | int n_items_offs= bin->length(); | |||
skipping to change at line 590 | skipping to change at line 548 | |||
uint32 Gis_point::get_data_size() const | uint32 Gis_point::get_data_size() const | |||
{ | { | |||
return POINT_DATA_SIZE; | return POINT_DATA_SIZE; | |||
} | } | |||
bool Gis_point::init_from_wkt(Gis_read_stream *trs, String *wkb) | bool Gis_point::init_from_wkt(Gis_read_stream *trs, String *wkb) | |||
{ | { | |||
double x, y; | double x, y; | |||
if (trs->get_next_number(&x) || trs->get_next_number(&y) || | if (trs->get_next_number(&x) || trs->get_next_number(&y) || | |||
wkb->reserve(POINT_DATA_SIZE)) | wkb->reserve(POINT_DATA_SIZE)) | |||
return 1; | return true; | |||
wkb->q_append(x); | wkb->q_append(x); | |||
wkb->q_append(y); | wkb->q_append(y); | |||
return 0; | return false; | |||
} | } | |||
uint Gis_point::init_from_wkb(const char *wkb, uint len, | uint Gis_point::init_from_wkb(const char *wkb, uint len, | |||
wkbByteOrder bo, String *res) | wkbByteOrder bo, String *res) | |||
{ | { | |||
double x, y; | double x, y; | |||
if (len < POINT_DATA_SIZE || res->reserve(POINT_DATA_SIZE)) | if (len < POINT_DATA_SIZE || res->reserve(POINT_DATA_SIZE)) | |||
return 0; | return 0; | |||
x= wkb_get_double(wkb, bo); | x= wkb_get_double(wkb, bo); | |||
y= wkb_get_double(wkb + SIZEOF_STORED_DOUBLE, bo); | y= wkb_get_double(wkb + SIZEOF_STORED_DOUBLE, bo); | |||
res->q_append(x); | res->q_append(x); | |||
res->q_append(y); | res->q_append(y); | |||
return POINT_DATA_SIZE; | return POINT_DATA_SIZE; | |||
} | } | |||
bool Gis_point::get_data_as_wkt(String *txt, const char **end) const | bool Gis_point::get_data_as_wkt(String *txt, wkb_parser *wkb) const | |||
{ | { | |||
double x, y; | point_xy p; | |||
if (get_xy(&x, &y)) | if (wkb->scan_xy(&p)) | |||
return 1; | return true; | |||
if (txt->reserve(MAX_DIGITS_IN_DOUBLE * 2 + 1)) | if (txt->reserve(MAX_DIGITS_IN_DOUBLE * 2 + 1)) | |||
return 1; | return true; | |||
txt->qs_append(x); | txt->qs_append(p.x); | |||
txt->qs_append(' '); | txt->qs_append(' '); | |||
txt->qs_append(y); | txt->qs_append(p.y); | |||
*end= m_data+ POINT_DATA_SIZE; | return false; | |||
return 0; | ||||
} | } | |||
bool Gis_point::get_mbr(MBR *mbr, const char **end) const | bool Gis_point::get_mbr(MBR *mbr, wkb_parser *wkb) const | |||
{ | { | |||
double x, y; | point_xy p; | |||
if (get_xy(&x, &y)) | if (wkb->scan_xy(&p)) | |||
return 1; | return true; | |||
mbr->add_xy(x, y); | mbr->add_xy(p); | |||
*end= m_data+ POINT_DATA_SIZE; | return false; | |||
return 0; | ||||
} | } | |||
int Gis_point::store_shapes(Gcalc_shape_transporter *trn, | int Gis_point::store_shapes(Gcalc_shape_transporter *trn, | |||
Gcalc_shape_status *st) const | Gcalc_shape_status *st) const | |||
{ | { | |||
if (trn->skip_point()) | if (trn->skip_point()) | |||
return 0; | return 0; | |||
double x, y; | wkb_parser wkb(&m_wkb_data); | |||
return get_xy(&x, &y) || trn->single_point(st, x, y); | point_xy p; | |||
return wkb.scan_xy(&p) || trn->single_point(st, p.x, p.y); | ||||
} | } | |||
const Geometry::Class_info *Gis_point::get_class_info() const | const Geometry::Class_info *Gis_point::get_class_info() const | |||
{ | { | |||
return &point_class; | return &point_class; | |||
} | } | |||
/***************************** LineString *******************************/ | /***************************** LineString *******************************/ | |||
uint32 Gis_line_string::get_data_size() const | uint32 Gis_line_string::get_data_size() const | |||
{ | { | |||
if (no_data(m_data, 4)) | uint32 n_points; | |||
wkb_parser wkb(&m_wkb_data); | ||||
if (wkb.scan_n_points_and_check_data(&n_points)) | ||||
return GET_SIZE_ERROR; | return GET_SIZE_ERROR; | |||
return 4 + uint4korr(m_data) * POINT_DATA_SIZE; | ||||
return 4 + n_points * POINT_DATA_SIZE; | ||||
} | } | |||
bool Gis_line_string::init_from_wkt(Gis_read_stream *trs, String *wkb) | bool Gis_line_string::init_from_wkt(Gis_read_stream *trs, String *wkb) | |||
{ | { | |||
uint32 n_points= 0; | uint32 n_points= 0; | |||
uint32 np_pos= wkb->length(); | uint32 np_pos= wkb->length(); | |||
Gis_point p; | Gis_point p; | |||
if (wkb->reserve(4, 512)) | if (wkb->reserve(4, 512)) | |||
return 1; | return true; | |||
wkb->length(wkb->length()+4); // Reserve space for points | wkb->length(wkb->length()+4); // Reserve space for points | |||
for (;;) | for (;;) | |||
{ | { | |||
if (p.init_from_wkt(trs, wkb)) | if (p.init_from_wkt(trs, wkb)) | |||
return 1; | return true; | |||
n_points++; | n_points++; | |||
if (trs->skip_char(',')) // Didn't find ',' | if (trs->skip_char(',')) // Didn't find ',' | |||
break; | break; | |||
} | } | |||
if (n_points < 1) | if (n_points < 1) | |||
{ | { | |||
trs->set_error_msg("Too few points in LINESTRING"); | trs->set_error_msg("Too few points in LINESTRING"); | |||
return 1; | return true; | |||
} | } | |||
wkb->write_at_position(np_pos, n_points); | wkb->write_at_position(np_pos, n_points); | |||
return 0; | return false; | |||
} | } | |||
uint Gis_line_string::init_from_wkb(const char *wkb, uint len, | uint Gis_line_string::init_from_wkb(const char *wkb, uint len, | |||
wkbByteOrder bo, String *res) | wkbByteOrder bo, String *res) | |||
{ | { | |||
uint32 n_points, proper_length; | uint32 n_points, proper_length; | |||
const char *wkb_end; | const char *wkb_end; | |||
Gis_point p; | Gis_point p; | |||
if (len < 4 || | if (len < 4 || | |||
skipping to change at line 710 | skipping to change at line 670 | |||
wkb_end= wkb + proper_length; | wkb_end= wkb + proper_length; | |||
for (wkb+= 4; wkb<wkb_end; wkb+= POINT_DATA_SIZE) | for (wkb+= 4; wkb<wkb_end; wkb+= POINT_DATA_SIZE) | |||
{ | { | |||
if (!p.init_from_wkb(wkb, POINT_DATA_SIZE, bo, res)) | if (!p.init_from_wkb(wkb, POINT_DATA_SIZE, bo, res)) | |||
return 0; | return 0; | |||
} | } | |||
return proper_length; | return proper_length; | |||
} | } | |||
bool Gis_line_string::get_data_as_wkt(String *txt, const char **end) const | bool Gis_line_string::get_data_as_wkt(String *txt, wkb_parser *wkb) const | |||
{ | { | |||
uint32 n_points; | uint32 n_points; | |||
const char *data= m_data; | if (wkb->scan_n_points_and_check_data(&n_points) || | |||
txt->reserve(((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points)) | ||||
if (no_data(data, 4)) | return true; | |||
return 1; | ||||
n_points= uint4korr(data); | ||||
data += 4; | ||||
if (n_points < 1 || | ||||
no_data(data, POINT_DATA_SIZE * n_points) || | ||||
txt->reserve(((MAX_DIGITS_IN_DOUBLE + 1)*2 + 1) * n_points)) | ||||
return 1; | ||||
while (n_points--) | while (n_points--) | |||
{ | { | |||
double x, y; | point_xy p; | |||
get_point(&x, &y, data); | wkb->scan_xy_unsafe(&p); | |||
data+= POINT_DATA_SIZE; | txt->qs_append(p.x); | |||
txt->qs_append(x); | ||||
txt->qs_append(' '); | txt->qs_append(' '); | |||
txt->qs_append(y); | txt->qs_append(p.y); | |||
txt->qs_append(','); | txt->qs_append(','); | |||
} | } | |||
txt->length(txt->length() - 1); // Remove end ',' | txt->length(txt->length() - 1); // Remove end ',' | |||
*end= data; | return false; | |||
return 0; | ||||
} | } | |||
bool Gis_line_string::get_mbr(MBR *mbr, const char **end) const | bool Gis_line_string::get_mbr(MBR *mbr, wkb_parser *wkb) const | |||
{ | { | |||
return (*end=get_mbr_for_points(mbr, m_data, 0)) == 0; | return get_mbr_for_points(mbr, wkb, 0); | |||
} | } | |||
int Gis_line_string::geom_length(double *len) const | int Gis_line_string::geom_length(double *len) const | |||
{ | { | |||
uint32 n_points; | uint32 n_points; | |||
double prev_x, prev_y; | wkb_parser wkb(&m_wkb_data); | |||
const char *data= m_data; | ||||
*len= 0; // In case of errors | *len= 0; // In case of errors | |||
if (no_data(data, 4)) | if (wkb.scan_n_points_and_check_data(&n_points)) | |||
return 1; | ||||
n_points= uint4korr(data); | ||||
data+= 4; | ||||
if (n_points < 1 || no_data(data, POINT_DATA_SIZE * n_points)) | ||||
return 1; | return 1; | |||
get_point(&prev_x, &prev_y, data); | point_xy prev; | |||
data+= POINT_DATA_SIZE; | wkb.scan_xy_unsafe(&prev); | |||
while (--n_points) | while (--n_points) | |||
{ | { | |||
double x, y; | point_xy p; | |||
get_point(&x, &y, data); | wkb.scan_xy_unsafe(&p); | |||
data+= POINT_DATA_SIZE; | *len+= prev.distance(p); | |||
*len+= sqrt(pow(prev_x-x,2)+pow(prev_y-y,2)); | prev= p; | |||
prev_x= x; | ||||
prev_y= y; | ||||
} | } | |||
return 0; | return 0; | |||
} | } | |||
int Gis_line_string::is_closed(int *closed) const | int Gis_line_string::is_closed(int *closed) const | |||
{ | { | |||
uint32 n_points; | uint32 n_points; | |||
double x1, y1, x2, y2; | wkb_parser wkb(&m_wkb_data); | |||
const char *data= m_data; | ||||
if (no_data(data, 4)) | if (wkb.scan_n_points_and_check_data(&n_points)) | |||
return 1; | return 1; | |||
n_points= uint4korr(data); | ||||
if (n_points == 1) | if (n_points == 1) | |||
{ | { | |||
*closed=1; | *closed=1; | |||
return 0; | return 0; | |||
} | } | |||
data+= 4; | ||||
if (n_points == 0 || | ||||
no_data(data, POINT_DATA_SIZE * n_points)) | ||||
return 1; | ||||
/* Get first point */ | point_xy p1, p2; | |||
get_point(&x1, &y1, data); | ||||
/* get last point */ | /* Get first point. */ | |||
data+= POINT_DATA_SIZE + (n_points-2)*POINT_DATA_SIZE; | wkb.scan_xy_unsafe(&p1); | |||
get_point(&x2, &y2, data); | ||||
*closed= (x1==x2) && (y1==y2); | /* Get last point. */ | |||
wkb.skip_unsafe((n_points - 2) * POINT_DATA_SIZE); | ||||
wkb.scan_xy_unsafe(&p2); | ||||
*closed= p1.eq(p2); | ||||
return 0; | return 0; | |||
} | } | |||
int Gis_line_string::num_points(uint32 *n_points) const | int Gis_line_string::num_points(uint32 *n_points) const | |||
{ | { | |||
*n_points= uint4korr(m_data); | wkb_parser wkb(&m_wkb_data); | |||
return 0; | return wkb.scan_uint4(n_points) ? 1 : 0; | |||
} | } | |||
int Gis_line_string::start_point(String *result) const | int Gis_line_string::start_point(String *result) const | |||
{ | { | |||
/* +4 is for skipping over number of points */ | uint32 n_points; | |||
return create_point(result, m_data + 4); | wkb_parser wkb(&m_wkb_data); | |||
if (wkb.scan_n_points_and_check_data(&n_points)) | ||||
return 1; | ||||
return create_point(result, &wkb); | ||||
} | } | |||
int Gis_line_string::end_point(String *result) const | int Gis_line_string::end_point(String *result) const | |||
{ | { | |||
uint32 n_points; | uint32 n_points; | |||
if (no_data(m_data, 4)) | wkb_parser wkb(&m_wkb_data); | |||
if (wkb.scan_n_points_and_check_data(&n_points)) | ||||
return 1; | return 1; | |||
n_points= uint4korr(m_data); | wkb.skip_unsafe((n_points - 1) * POINT_DATA_SIZE); | |||
return create_point(result, m_data + 4 + (n_points - 1) * POINT_DATA_SIZE | return create_point(result, &wkb); | |||
); | ||||
} | } | |||
int Gis_line_string::point_n(uint32 num, String *result) const | int Gis_line_string::point_n(uint32 num, String *result) const | |||
{ | { | |||
uint32 n_points; | uint32 n_points; | |||
if (no_data(m_data, 4)) | wkb_parser wkb(&m_wkb_data); | |||
return 1; | if (num < 1 || | |||
n_points= uint4korr(m_data); | wkb.scan_n_points_and_check_data(&n_points) || | |||
if ((uint32) (num - 1) >= n_points) // means (num > n_points || num < 1) | num > n_points) | |||
return 1; | return 1; | |||
wkb.skip_unsafe((num - 1) * POINT_DATA_SIZE); | ||||
return create_point(result, m_data + 4 + (num - 1) * POINT_DATA_SIZE); | return create_point(result, &wkb); | |||
} | } | |||
int Gis_line_string::store_shapes(Gcalc_shape_transporter *trn, | int Gis_line_string::store_shapes(Gcalc_shape_transporter *trn, | |||
Gcalc_shape_status *st) const | Gcalc_shape_status *st) const | |||
{ | { | |||
uint32 n_points; | uint32 n_points; | |||
double x, y; | wkb_parser wkb(&m_wkb_data); | |||
const char *data= m_data; | ||||
if (trn->skip_line_string()) | if (trn->skip_line_string()) | |||
return 0; | return 0; | |||
if (no_data(m_data, 4)) | if (wkb.scan_n_points_and_check_data(&n_points)) | |||
return 1; | ||||
n_points= uint4korr(data); | ||||
data+= 4; | ||||
if (n_points < 1 || no_data(data, POINT_DATA_SIZE * n_points)) | ||||
return 1; | return 1; | |||
trn->start_line(st); | trn->start_line(st); | |||
while (n_points--) | while (n_points--) | |||
{ | { | |||
get_point(&x, &y, data); | point_xy p; | |||
data+= POINT_DATA_SIZE; | wkb.scan_xy_unsafe(&p); | |||
if (trn->add_point(st, x, y)) | if (trn->add_point(st, p.x, p.y)) | |||
return 1; | return 1; | |||
} | } | |||
return trn->complete_line(st); | return trn->complete_line(st); | |||
} | } | |||
const Geometry::Class_info *Gis_line_string::get_class_info() const | const Geometry::Class_info *Gis_line_string::get_class_info() const | |||
{ | { | |||
return &linestring_class; | return &linestring_class; | |||
} | } | |||
/***************************** Polygon *******************************/ | /***************************** Polygon *******************************/ | |||
uint32 Gis_polygon::get_data_size() const | uint32 Gis_polygon::get_data_size() const | |||
{ | { | |||
uint32 n_linear_rings; | uint32 n_linear_rings; | |||
const char *data= m_data; | wkb_parser wkb(&m_wkb_data); | |||
if (no_data(data, 4)) | if (wkb.scan_non_zero_uint4(&n_linear_rings)) | |||
return GET_SIZE_ERROR; | return GET_SIZE_ERROR; | |||
n_linear_rings= uint4korr(data); | ||||
data+= 4; | ||||
while (n_linear_rings--) | while (n_linear_rings--) | |||
{ | { | |||
if (no_data(data, 4)) | uint32 n_points; | |||
if (wkb.scan_n_points_and_check_data(&n_points)) | ||||
return GET_SIZE_ERROR; | return GET_SIZE_ERROR; | |||
data+= 4 + uint4korr(data)*POINT_DATA_SIZE; | wkb.skip_unsafe(n_points * POINT_DATA_SIZE); | |||
} | } | |||
return (uint32) (data - m_data); | return (uint32) (wkb.data() - m_wkb_data.data()); | |||
} | } | |||
bool Gis_polygon::init_from_wkt(Gis_read_stream *trs, String *wkb) | bool Gis_polygon::init_from_wkt(Gis_read_stream *trs, String *wkb) | |||
{ | { | |||
uint32 n_linear_rings= 0; | uint32 n_linear_rings= 0; | |||
uint32 lr_pos= wkb->length(); | uint32 lr_pos= wkb->length(); | |||
int closed; | int closed; | |||
if (wkb->reserve(4, 512)) | if (wkb->reserve(4, 512)) | |||
return 1; | return true; | |||
wkb->length(wkb->length()+4); // Reserve space for points | wkb->length(wkb->length()+4); // Reserve space for points | |||
for (;;) | for (;;) | |||
{ | { | |||
Gis_line_string ls; | Gis_line_string ls; | |||
uint32 ls_pos=wkb->length(); | uint32 ls_pos=wkb->length(); | |||
if (trs->check_next_symbol('(') || | if (trs->check_next_symbol('(') || | |||
ls.init_from_wkt(trs, wkb) || | ls.init_from_wkt(trs, wkb) || | |||
trs->check_next_symbol(')')) | trs->check_next_symbol(')')) | |||
return 1; | return true; | |||
ls.set_data_ptr(wkb->ptr() + ls_pos, wkb->length() - ls_pos); | ls.set_data_ptr(wkb->ptr() + ls_pos, wkb->length() - ls_pos); | |||
if (ls.is_closed(&closed) || !closed) | if (ls.is_closed(&closed) || !closed) | |||
{ | { | |||
trs->set_error_msg("POLYGON's linear ring isn't closed"); | trs->set_error_msg("POLYGON's linear ring isn't closed"); | |||
return 1; | return true; | |||
} | } | |||
n_linear_rings++; | n_linear_rings++; | |||
if (trs->skip_char(',')) // Didn't find ',' | if (trs->skip_char(',')) // Didn't find ',' | |||
break; | break; | |||
} | } | |||
wkb->write_at_position(lr_pos, n_linear_rings); | wkb->write_at_position(lr_pos, n_linear_rings); | |||
return 0; | return false; | |||
} | } | |||
uint Gis_polygon::init_from_opresult(String *bin, | uint Gis_polygon::init_from_opresult(String *bin, | |||
const char *opres, uint opres_length) | const char *opres, uint opres_length) | |||
{ | { | |||
const char *opres_orig= opres; | const char *opres_orig= opres; | |||
const char *opres_end= opres + opres_length; | const char *opres_end= opres + opres_length; | |||
uint32 position= bin->length(); | uint32 position= bin->length(); | |||
uint32 poly_shapes= 0; | uint32 poly_shapes= 0; | |||
skipping to change at line 977 | skipping to change at line 915 | |||
uint Gis_polygon::init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, | uint Gis_polygon::init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, | |||
String *res) | String *res) | |||
{ | { | |||
uint32 n_linear_rings; | uint32 n_linear_rings; | |||
const char *wkb_orig= wkb; | const char *wkb_orig= wkb; | |||
if (len < 4) | if (len < 4) | |||
return 0; | return 0; | |||
n_linear_rings= wkb_get_uint(wkb, bo); | if (0 == (n_linear_rings= wkb_get_uint(wkb, bo)) || | |||
if (res->reserve(4, 512)) | res->reserve(4, 512)) | |||
return 0; | return 0; | |||
wkb+= 4; | wkb+= 4; | |||
len-= 4; | len-= 4; | |||
res->q_append(n_linear_rings); | res->q_append(n_linear_rings); | |||
while (n_linear_rings--) | while (n_linear_rings--) | |||
{ | { | |||
Gis_line_string ls; | Gis_line_string ls; | |||
uint32 ls_pos= res->length(); | uint32 ls_pos= res->length(); | |||
int ls_len; | int ls_len; | |||
skipping to change at line 1004 | skipping to change at line 942 | |||
ls.set_data_ptr(res->ptr() + ls_pos, res->length() - ls_pos); | ls.set_data_ptr(res->ptr() + ls_pos, res->length() - ls_pos); | |||
if (ls.is_closed(&closed) || !closed) | if (ls.is_closed(&closed) || !closed) | |||
return 0; | return 0; | |||
wkb+= ls_len; | wkb+= ls_len; | |||
} | } | |||
return (uint) (wkb - wkb_orig); | return (uint) (wkb - wkb_orig); | |||
} | } | |||
bool Gis_polygon::get_data_as_wkt(String *txt, const char **end) const | bool Gis_polygon::get_data_as_wkt(String *txt, wkb_parser *wkb) const | |||
{ | { | |||
uint32 n_linear_rings; | uint32 n_linear_rings; | |||
const char *data= m_data; | ||||
if (no_data(data, 4)) | ||||
return 1; | ||||
n_linear_rings= uint4korr(data); | if (wkb->scan_non_zero_uint4(&n_linear_rings)) | |||
data+= 4; | return true; | |||
while (n_linear_rings--) | while (n_linear_rings--) | |||
{ | { | |||
uint32 n_points; | uint32 n_points; | |||
if (no_data(data, 4)) | if (wkb->scan_n_points_and_check_data(&n_points) || | |||
return 1; | ||||
n_points= uint4korr(data); | ||||
data+= 4; | ||||
if (no_data(data, POINT_DATA_SIZE * n_points) || | ||||
txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points)) | txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points)) | |||
return 1; | return true; | |||
txt->qs_append('('); | txt->qs_append('('); | |||
data= append_points(txt, n_points, data, 0); | append_points(txt, n_points, wkb, 0); | |||
(*txt) [txt->length() - 1]= ')'; // Replace end ',' | (*txt) [txt->length() - 1]= ')'; // Replace end ',' | |||
txt->qs_append(','); | txt->qs_append(','); | |||
} | } | |||
txt->length(txt->length() - 1); // Remove end ',' | txt->length(txt->length() - 1); // Remove end ',' | |||
*end= data; | return false; | |||
return 0; | ||||
} | } | |||
bool Gis_polygon::get_mbr(MBR *mbr, const char **end) const | bool Gis_polygon::get_mbr(MBR *mbr, wkb_parser *wkb) const | |||
{ | { | |||
uint32 n_linear_rings; | uint32 n_linear_rings; | |||
const char *data= m_data; | ||||
if (no_data(data, 4)) | if (wkb->scan_non_zero_uint4(&n_linear_rings)) | |||
return 1; | return true; | |||
n_linear_rings= uint4korr(data); | ||||
data+= 4; | ||||
while (n_linear_rings--) | while (n_linear_rings--) | |||
{ | { | |||
if (!(data= get_mbr_for_points(mbr, data, 0))) | if (get_mbr_for_points(mbr, wkb, 0)) | |||
return 1; | return true; | |||
} | } | |||
*end= data; | return false; | |||
return 0; | ||||
} | } | |||
int Gis_polygon::area(double *ar, const char **end_of_data) const | bool Gis_polygon::area(double *ar, wkb_parser *wkb) const | |||
{ | { | |||
uint32 n_linear_rings; | uint32 n_linear_rings; | |||
double result= -1.0; | double result= -1.0; | |||
const char *data= m_data; | ||||
if (no_data(data, 4)) | if (wkb->scan_non_zero_uint4(&n_linear_rings)) | |||
return 1; | return true; | |||
n_linear_rings= uint4korr(data); | ||||
data+= 4; | ||||
while (n_linear_rings--) | while (n_linear_rings--) | |||
{ | { | |||
double prev_x, prev_y; | ||||
double lr_area= 0; | double lr_area= 0; | |||
uint32 n_points; | uint32 n_points; | |||
if (no_data(data, 4)) | if (wkb->scan_n_points_and_check_data(&n_points)) | |||
return 1; | return true; | |||
n_points= uint4korr(data); | point_xy prev; | |||
if (no_data(data, POINT_DATA_SIZE * n_points)) | wkb->scan_xy_unsafe(&prev); | |||
return 1; | ||||
get_point(&prev_x, &prev_y, data+4); | ||||
data+= (4+POINT_DATA_SIZE); | ||||
while (--n_points) // One point is already read | while (--n_points) // One point is already read | |||
{ | { | |||
double x, y; | point_xy p; | |||
get_point(&x, &y, data); | wkb->scan_xy_unsafe(&p); | |||
data+= POINT_DATA_SIZE; | lr_area+= (prev.x + p.x) * (prev.y - p.y); | |||
lr_area+= (prev_x + x)* (prev_y - y); | prev= p; | |||
prev_x= x; | ||||
prev_y= y; | ||||
} | } | |||
lr_area= fabs(lr_area)/2; | lr_area= fabs(lr_area)/2; | |||
if (result == -1.0) | if (result == -1.0) | |||
result= lr_area; | result= lr_area; | |||
else | else | |||
result-= lr_area; | result-= lr_area; | |||
} | } | |||
*ar= fabs(result); | *ar= fabs(result); | |||
*end_of_data= data; | return false; | |||
return 0; | ||||
} | } | |||
int Gis_polygon::exterior_ring(String *result) const | int Gis_polygon::exterior_ring(String *result) const | |||
{ | { | |||
uint32 n_points, length; | uint32 n_points, n_linear_rings, length; | |||
const char *data= m_data + 4; // skip n_linerings | wkb_parser wkb(&m_wkb_data); | |||
if (no_data(data, 4)) | if (wkb.scan_non_zero_uint4(&n_linear_rings) || | |||
wkb.scan_n_points_and_check_data(&n_points)) | ||||
return 1; | return 1; | |||
n_points= uint4korr(data); | ||||
data+= 4; | ||||
length= n_points * POINT_DATA_SIZE; | length= n_points * POINT_DATA_SIZE; | |||
if (no_data(data, length) || result->reserve(1 + 4 + 4 + length)) | if (result->reserve(1 + 4 + 4 + length)) | |||
return 1; | return 1; | |||
result->q_append((char) wkb_ndr); | result->q_append((char) wkb_ndr); | |||
result->q_append((uint32) wkb_linestring); | result->q_append((uint32) wkb_linestring); | |||
result->q_append(n_points); | result->q_append(n_points); | |||
result->q_append(data, n_points * POINT_DATA_SIZE); | result->q_append(wkb.data(), length); | |||
return 0; | return 0; | |||
} | } | |||
int Gis_polygon::num_interior_ring(uint32 *n_int_rings) const | int Gis_polygon::num_interior_ring(uint32 *n_int_rings) const | |||
{ | { | |||
if (no_data(m_data, 4)) | wkb_parser wkb(&m_wkb_data); | |||
if (wkb.scan_non_zero_uint4(n_int_rings)) | ||||
return 1; | return 1; | |||
*n_int_rings= uint4korr(m_data)-1; | *n_int_rings-= 1; | |||
return 0; | return 0; | |||
} | } | |||
int Gis_polygon::interior_ring_n(uint32 num, String *result) const | int Gis_polygon::interior_ring_n(uint32 num, String *result) const | |||
{ | { | |||
const char *data= m_data; | wkb_parser wkb(&m_wkb_data); | |||
uint32 n_linear_rings; | uint32 n_linear_rings; | |||
uint32 n_points; | uint32 n_points; | |||
uint32 points_size; | uint32 points_size; | |||
if (no_data(data, 4)) | if (num < 1 || | |||
return 1; | wkb.scan_non_zero_uint4(&n_linear_rings) || | |||
n_linear_rings= uint4korr(data); | num >= n_linear_rings) | |||
data+= 4; | ||||
if (num >= n_linear_rings || num < 1) | ||||
return 1; | return 1; | |||
while (num--) | while (num--) | |||
{ | { | |||
if (no_data(data, 4)) | if (wkb.scan_n_points_and_check_data(&n_points)) | |||
return 1; | return 1; | |||
data+= 4 + uint4korr(data) * POINT_DATA_SIZE; | wkb.skip_unsafe(n_points * POINT_DATA_SIZE); | |||
} | } | |||
if (no_data(data, 4)) | if (wkb.scan_n_points_and_check_data(&n_points)) | |||
return 1; | return 1; | |||
n_points= uint4korr(data); | ||||
points_size= n_points * POINT_DATA_SIZE; | points_size= n_points * POINT_DATA_SIZE; | |||
data+= 4; | if (result->reserve(1 + 4 + 4 + points_size)) | |||
if (no_data(data, points_size) || result->reserve(1 + 4 + 4 + points_size | ||||
)) | ||||
return 1; | return 1; | |||
result->q_append((char) wkb_ndr); | result->q_append((char) wkb_ndr); | |||
result->q_append((uint32) wkb_linestring); | result->q_append((uint32) wkb_linestring); | |||
result->q_append(n_points); | result->q_append(n_points); | |||
result->q_append(data, points_size); | result->q_append(wkb.data(), points_size); | |||
return 0; | return 0; | |||
} | } | |||
int Gis_polygon::centroid_xy(double *x, double *y) const | bool Gis_polygon::centroid_xy(point_xy *p) const | |||
{ | { | |||
uint32 n_linear_rings; | uint32 n_linear_rings; | |||
double UNINIT_VAR(res_area); | double UNINIT_VAR(res_area); | |||
double UNINIT_VAR(res_cx), UNINIT_VAR(res_cy); | point_xy res(0, 0); // Initialized only to make compiler hap | |||
const char *data= m_data; | py | |||
wkb_parser wkb(&m_wkb_data); | ||||
bool first_loop= 1; | bool first_loop= 1; | |||
if (no_data(data, 4)) | if (wkb.scan_non_zero_uint4(&n_linear_rings)) | |||
return 1; | return true; | |||
n_linear_rings= uint4korr(data); | ||||
data+= 4; | ||||
DBUG_ASSERT(n_linear_rings > 0); | ||||
while (n_linear_rings--) | while (n_linear_rings--) | |||
{ | { | |||
uint32 n_points, org_n_points; | uint32 n_points, org_n_points; | |||
double prev_x, prev_y; | ||||
double cur_area= 0; | double cur_area= 0; | |||
double cur_cx= 0; | point_xy prev, cur(0, 0); | |||
double cur_cy= 0; | ||||
if (no_data(data, 4)) | if (wkb.scan_n_points_and_check_data(&n_points)) | |||
return 1; | return true; | |||
org_n_points= n_points= uint4korr(data); | ||||
data+= 4; | org_n_points= n_points - 1; | |||
if (no_data(data, POINT_DATA_SIZE * n_points)) | wkb.scan_xy_unsafe(&prev); | |||
return 1; | ||||
get_point(&prev_x, &prev_y, data); | ||||
data+= POINT_DATA_SIZE; | ||||
while (--n_points) // One point is already read | while (--n_points) // One point is already read | |||
{ | { | |||
double tmp_x, tmp_y; | point_xy tmp; | |||
get_point(&tmp_x, &tmp_y, data); | wkb.scan_xy_unsafe(&tmp); | |||
data+= POINT_DATA_SIZE; | cur_area+= (prev.x + tmp.x) * (prev.y - tmp.y); | |||
cur_area+= (prev_x + tmp_x) * (prev_y - tmp_y); | cur.x+= tmp.x; | |||
cur_cx+= tmp_x; | cur.y+= tmp.y; | |||
cur_cy+= tmp_y; | prev= tmp; | |||
prev_x= tmp_x; | ||||
prev_y= tmp_y; | ||||
} | } | |||
cur_area= fabs(cur_area) / 2; | cur_area= fabs(cur_area) / 2; | |||
cur_cx= cur_cx / (org_n_points - 1); | cur.x= cur.x / org_n_points; | |||
cur_cy= cur_cy / (org_n_points - 1); | cur.y= cur.y / org_n_points; | |||
if (!first_loop) | if (!first_loop) | |||
{ | { | |||
double d_area= fabs(res_area - cur_area); | double d_area= fabs(res_area - cur_area); | |||
res_cx= (res_area * res_cx - cur_area * cur_cx) / d_area; | res.x= (res_area * res.x - cur_area * cur.x) / d_area; | |||
res_cy= (res_area * res_cy - cur_area * cur_cy) / d_area; | res.y= (res_area * res.y - cur_area * cur.y) / d_area; | |||
} | } | |||
else | else | |||
{ | { | |||
first_loop= 0; | first_loop= 0; | |||
res_area= cur_area; | res_area= cur_area; | |||
res_cx= cur_cx; | res= cur; | |||
res_cy= cur_cy; | ||||
} | } | |||
} | } | |||
*x= res_cx; | *p= res; | |||
*y= res_cy; | return false; | |||
return 0; | ||||
} | } | |||
int Gis_polygon::centroid(String *result) const | int Gis_polygon::centroid(String *result) const | |||
{ | { | |||
double x, y; | point_xy p; | |||
if (centroid_xy(&x, &y)) | if (centroid_xy(&p)) | |||
return 1; | return 1; | |||
return create_point(result, x, y); | return create_point(result, p); | |||
} | } | |||
int Gis_polygon::store_shapes(Gcalc_shape_transporter *trn, | int Gis_polygon::store_shapes(Gcalc_shape_transporter *trn, | |||
Gcalc_shape_status *st) const | Gcalc_shape_status *st) const | |||
{ | { | |||
uint32 n_linear_rings; | uint32 n_linear_rings; | |||
const char *data= m_data; | wkb_parser wkb(&m_wkb_data); | |||
if (trn->skip_poly()) | if (trn->skip_poly()) | |||
return 0; | return 0; | |||
if (trn->start_poly(st)) | if (trn->start_poly(st)) | |||
return 1; | return 1; | |||
if (no_data(data, 4)) | if (wkb.scan_non_zero_uint4(&n_linear_rings)) | |||
return 1; | return 1; | |||
n_linear_rings= uint4korr(data); | ||||
data+= 4; | ||||
while (n_linear_rings--) | while (n_linear_rings--) | |||
{ | { | |||
uint32 n_points; | uint32 n_points; | |||
if (no_data(data, 4)) | if (wkb.scan_n_points_and_check_data(&n_points)) | |||
return 1; | ||||
n_points= uint4korr(data); | ||||
data+= 4; | ||||
if (!n_points || no_data(data, POINT_DATA_SIZE * n_points)) | ||||
return 1; | return 1; | |||
trn->start_ring(st); | trn->start_ring(st); | |||
while (--n_points) | while (--n_points) | |||
{ | { | |||
double x, y; | point_xy p; | |||
get_point(&x, &y, data); | wkb.scan_xy_unsafe(&p); | |||
data+= POINT_DATA_SIZE; | if (trn->add_point(st, p.x, p.y)) | |||
if (trn->add_point(st, x, y)) | ||||
return 1; | return 1; | |||
} | } | |||
data+= POINT_DATA_SIZE; | wkb.skip_unsafe(POINT_DATA_SIZE); // Skip the last point in the ring. | |||
trn->complete_ring(st); | trn->complete_ring(st); | |||
} | } | |||
trn->complete_poly(st); | trn->complete_poly(st); | |||
return 0; | return 0; | |||
} | } | |||
const Geometry::Class_info *Gis_polygon::get_class_info() const | const Geometry::Class_info *Gis_polygon::get_class_info() const | |||
{ | { | |||
return &polygon_class; | return &polygon_class; | |||
} | } | |||
/***************************** MultiPoint *******************************/ | /***************************** MultiPoint *******************************/ | |||
uint32 Gis_multi_point::get_data_size() const | uint32 Gis_multi_point::get_data_size() const | |||
{ | { | |||
if (no_data(m_data, 4)) | uint32 n_points; | |||
wkb_parser wkb(&m_wkb_data); | ||||
if (wkb.scan_n_points_and_check_data(&n_points, WKB_HEADER_SIZE)) | ||||
return GET_SIZE_ERROR; | return GET_SIZE_ERROR; | |||
return 4 + uint4korr(m_data)*(POINT_DATA_SIZE + WKB_HEADER_SIZE); | ||||
return 4 + n_points * (POINT_DATA_SIZE + WKB_HEADER_SIZE); | ||||
} | } | |||
bool Gis_multi_point::init_from_wkt(Gis_read_stream *trs, String *wkb) | bool Gis_multi_point::init_from_wkt(Gis_read_stream *trs, String *wkb) | |||
{ | { | |||
uint32 n_points= 0; | uint32 n_points= 0; | |||
uint32 np_pos= wkb->length(); | uint32 np_pos= wkb->length(); | |||
Gis_point p; | Gis_point p; | |||
if (wkb->reserve(4, 512)) | if (wkb->reserve(4, 512)) | |||
return 1; | return true; | |||
wkb->length(wkb->length()+4); // Reserve space for points | wkb->length(wkb->length()+4); // Reserve space for points | |||
for (;;) | for (;;) | |||
{ | { | |||
if (wkb->reserve(1 + 4, 512)) | if (wkb->reserve(1 + 4, 512)) | |||
return 1; | return 1; | |||
wkb->q_append((char) wkb_ndr); | wkb->q_append((char) wkb_ndr); | |||
wkb->q_append((uint32) wkb_point); | wkb->q_append((uint32) wkb_point); | |||
if (p.init_from_wkt(trs, wkb)) | if (p.init_from_wkt(trs, wkb)) | |||
return 1; | return true; | |||
n_points++; | n_points++; | |||
if (trs->skip_char(',')) // Didn't find ',' | if (trs->skip_char(',')) // Didn't find ',' | |||
break; | break; | |||
} | } | |||
wkb->write_at_position(np_pos, n_points); // Store number of found poi nts | wkb->write_at_position(np_pos, n_points); // Store number of found poi nts | |||
return 0; | return false; | |||
} | } | |||
uint Gis_multi_point::init_from_opresult(String *bin, | uint Gis_multi_point::init_from_opresult(String *bin, | |||
const char *opres, uint opres_leng th) | const char *opres, uint opres_leng th) | |||
{ | { | |||
uint bin_size, n_points; | uint bin_size, n_points; | |||
Gis_point p; | Gis_point p; | |||
const char *opres_end; | const char *opres_end; | |||
n_points= opres_length / (4 + 8 * 2); | n_points= opres_length / (4 + 8 * 2); | |||
skipping to change at line 1378 | skipping to change at line 1270 | |||
{ | { | |||
res->q_append((char)wkb_ndr); | res->q_append((char)wkb_ndr); | |||
res->q_append((uint32)wkb_point); | res->q_append((uint32)wkb_point); | |||
if (!p.init_from_wkb(wkb + WKB_HEADER_SIZE, | if (!p.init_from_wkb(wkb + WKB_HEADER_SIZE, | |||
POINT_DATA_SIZE, (wkbByteOrder) wkb[0], res)) | POINT_DATA_SIZE, (wkbByteOrder) wkb[0], res)) | |||
return 0; | return 0; | |||
} | } | |||
return proper_size; | return proper_size; | |||
} | } | |||
bool Gis_multi_point::get_data_as_wkt(String *txt, const char **end) const | bool Gis_multi_point::get_data_as_wkt(String *txt, wkb_parser *wkb) const | |||
{ | { | |||
uint32 n_points; | uint32 n_points; | |||
if (no_data(m_data, 4)) | ||||
return 1; | ||||
n_points= uint4korr(m_data); | if (wkb->scan_n_points_and_check_data(&n_points, WKB_HEADER_SIZE) || | |||
if (no_data(m_data+4, | ||||
n_points * (POINT_DATA_SIZE + WKB_HEADER_SIZE)) || | ||||
txt->reserve(((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points)) | txt->reserve(((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points)) | |||
return 1; | return true; | |||
*end= append_points(txt, n_points, m_data+4, WKB_HEADER_SIZE); | ||||
append_points(txt, n_points, wkb, WKB_HEADER_SIZE); | ||||
txt->length(txt->length()-1); // Remove end ',' | txt->length(txt->length()-1); // Remove end ',' | |||
return 0; | return false; | |||
} | } | |||
bool Gis_multi_point::get_mbr(MBR *mbr, const char **end) const | bool Gis_multi_point::get_mbr(MBR *mbr, wkb_parser *wkb) const | |||
{ | { | |||
return (*end= get_mbr_for_points(mbr, m_data, WKB_HEADER_SIZE)) == 0; | return get_mbr_for_points(mbr, wkb, WKB_HEADER_SIZE); | |||
} | } | |||
int Gis_multi_point::num_geometries(uint32 *num) const | int Gis_multi_point::num_geometries(uint32 *num) const | |||
{ | { | |||
*num= uint4korr(m_data); | wkb_parser wkb(&m_wkb_data); | |||
return 0; | return wkb.scan_non_zero_uint4(num) ? 1 : 0; | |||
} | } | |||
int Gis_multi_point::geometry_n(uint32 num, String *result) const | int Gis_multi_point::geometry_n(uint32 num, String *result) const | |||
{ | { | |||
const char *data= m_data; | ||||
uint32 n_points; | uint32 n_points; | |||
wkb_parser wkb(&m_wkb_data); | ||||
if (no_data(data, 4)) | if (num < 1 || | |||
return 1; | wkb.scan_n_points_and_check_data(&n_points, WKB_HEADER_SIZE) || | |||
n_points= uint4korr(data); | num > n_points || | |||
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)) | result->reserve(WKB_HEADER_SIZE + POINT_DATA_SIZE)) | |||
return 1; | return 1; | |||
wkb.skip_unsafe((num - 1) * (WKB_HEADER_SIZE + POINT_DATA_SIZE)); | ||||
result->q_append(data, WKB_HEADER_SIZE + POINT_DATA_SIZE); | result->q_append(wkb.data(), WKB_HEADER_SIZE + POINT_DATA_SIZE); | |||
return 0; | return 0; | |||
} | } | |||
int Gis_multi_point::store_shapes(Gcalc_shape_transporter *trn, | int Gis_multi_point::store_shapes(Gcalc_shape_transporter *trn, | |||
Gcalc_shape_status *st) const | Gcalc_shape_status *st) const | |||
{ | { | |||
if (trn->skip_point()) | if (trn->skip_point()) | |||
return 0; | return 0; | |||
Gis_point pt; | Gis_point pt; | |||
return collection_store_shapes(trn, st, &pt); | return collection_store_shapes(trn, st, &pt); | |||
skipping to change at line 1443 | skipping to change at line 1329 | |||
const Geometry::Class_info *Gis_multi_point::get_class_info() const | const Geometry::Class_info *Gis_multi_point::get_class_info() const | |||
{ | { | |||
return &multipoint_class; | return &multipoint_class; | |||
} | } | |||
/***************************** MultiLineString **************************** ***/ | /***************************** MultiLineString **************************** ***/ | |||
uint32 Gis_multi_line_string::get_data_size() const | uint32 Gis_multi_line_string::get_data_size() const | |||
{ | { | |||
uint32 n_line_strings; | uint32 n_line_strings; | |||
const char *data= m_data; | wkb_parser wkb(&m_wkb_data); | |||
if (no_data(data, 4)) | if (wkb.scan_non_zero_uint4(&n_line_strings)) | |||
return GET_SIZE_ERROR; | return GET_SIZE_ERROR; | |||
n_line_strings= uint4korr(data); | ||||
data+= 4; | ||||
while (n_line_strings--) | while (n_line_strings--) | |||
{ | { | |||
if (no_data(data, WKB_HEADER_SIZE + 4)) | uint32 n_points; | |||
if (wkb.skip_wkb_header() || | ||||
wkb.scan_n_points_and_check_data(&n_points)) | ||||
return GET_SIZE_ERROR; | return GET_SIZE_ERROR; | |||
data+= (WKB_HEADER_SIZE + 4 + uint4korr(data + WKB_HEADER_SIZE) * | ||||
POINT_DATA_SIZE); | wkb.skip_unsafe(n_points * POINT_DATA_SIZE); | |||
} | } | |||
return (uint32) (data - m_data); | return (uint32) (wkb.data() - m_wkb_data.data()); | |||
} | } | |||
bool Gis_multi_line_string::init_from_wkt(Gis_read_stream *trs, String *wkb ) | bool Gis_multi_line_string::init_from_wkt(Gis_read_stream *trs, String *wkb ) | |||
{ | { | |||
uint32 n_line_strings= 0; | uint32 n_line_strings= 0; | |||
uint32 ls_pos= wkb->length(); | uint32 ls_pos= wkb->length(); | |||
if (wkb->reserve(4, 512)) | if (wkb->reserve(4, 512)) | |||
return 1; | return true; | |||
wkb->length(wkb->length()+4); // Reserve space for points | wkb->length(wkb->length()+4); // Reserve space for points | |||
for (;;) | for (;;) | |||
{ | { | |||
Gis_line_string ls; | Gis_line_string ls; | |||
if (wkb->reserve(1 + 4, 512)) | if (wkb->reserve(1 + 4, 512)) | |||
return 1; | return true; | |||
wkb->q_append((char) wkb_ndr); wkb->q_append((uint32) wkb_linestring); | wkb->q_append((char) wkb_ndr); wkb->q_append((uint32) wkb_linestring); | |||
if (trs->check_next_symbol('(') || | if (trs->check_next_symbol('(') || | |||
ls.init_from_wkt(trs, wkb) || | ls.init_from_wkt(trs, wkb) || | |||
trs->check_next_symbol(')')) | trs->check_next_symbol(')')) | |||
return 1; | return true; | |||
n_line_strings++; | n_line_strings++; | |||
if (trs->skip_char(',')) // Didn't find ',' | if (trs->skip_char(',')) // Didn't find ',' | |||
break; | break; | |||
} | } | |||
wkb->write_at_position(ls_pos, n_line_strings); | wkb->write_at_position(ls_pos, n_line_strings); | |||
return 0; | return false; | |||
} | } | |||
uint Gis_multi_line_string::init_from_opresult(String *bin, | uint Gis_multi_line_string::init_from_opresult(String *bin, | |||
const char *opres, | const char *opres, | |||
uint opres_length) | uint opres_length) | |||
{ | { | |||
Gis_line_string item; | Gis_line_string item; | |||
return collection_init_from_opresult(bin, opres, opres_length, &item); | return collection_init_from_opresult(bin, opres, opres_length, &item); | |||
} | } | |||
skipping to change at line 1534 | skipping to change at line 1421 | |||
if (!(ls_len= ls.init_from_wkb(wkb + WKB_HEADER_SIZE, len, | if (!(ls_len= ls.init_from_wkb(wkb + WKB_HEADER_SIZE, len, | |||
(wkbByteOrder) wkb[0], res))) | (wkbByteOrder) wkb[0], res))) | |||
return 0; | return 0; | |||
ls_len+= WKB_HEADER_SIZE;; | ls_len+= WKB_HEADER_SIZE;; | |||
wkb+= ls_len; | wkb+= ls_len; | |||
len-= ls_len; | len-= ls_len; | |||
} | } | |||
return (uint) (wkb - wkb_orig); | return (uint) (wkb - wkb_orig); | |||
} | } | |||
bool Gis_multi_line_string::get_data_as_wkt(String *txt, | bool Gis_multi_line_string::get_data_as_wkt(String *txt, wkb_parser *wkb) c | |||
const char **end) const | onst | |||
{ | { | |||
uint32 n_line_strings; | uint32 n_line_strings; | |||
const char *data= m_data; | ||||
if (no_data(data, 4)) | if (wkb->scan_non_zero_uint4(&n_line_strings)) | |||
return 1; | return true; | |||
n_line_strings= uint4korr(data); | ||||
data+= 4; | ||||
while (n_line_strings--) | while (n_line_strings--) | |||
{ | { | |||
uint32 n_points; | uint32 n_points; | |||
if (no_data(data, (WKB_HEADER_SIZE + 4))) | ||||
return 1; | if (wkb->skip_wkb_header() || | |||
n_points= uint4korr(data + WKB_HEADER_SIZE); | wkb->scan_n_points_and_check_data(&n_points) || | |||
data+= WKB_HEADER_SIZE + 4; | ||||
if (no_data(data, n_points * POINT_DATA_SIZE) || | ||||
txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points)) | txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points)) | |||
return 1; | return true; | |||
txt->qs_append('('); | txt->qs_append('('); | |||
data= append_points(txt, n_points, data, 0); | append_points(txt, n_points, wkb, 0); | |||
(*txt) [txt->length() - 1]= ')'; | (*txt) [txt->length() - 1]= ')'; | |||
txt->qs_append(','); | txt->qs_append(','); | |||
} | } | |||
txt->length(txt->length() - 1); | txt->length(txt->length() - 1); | |||
*end= data; | return false; | |||
return 0; | ||||
} | } | |||
bool Gis_multi_line_string::get_mbr(MBR *mbr, const char **end) const | bool Gis_multi_line_string::get_mbr(MBR *mbr, wkb_parser *wkb) const | |||
{ | { | |||
uint32 n_line_strings; | uint32 n_line_strings; | |||
const char *data= m_data; | ||||
if (no_data(data, 4)) | if (wkb->scan_non_zero_uint4(&n_line_strings)) | |||
return 1; | return true; | |||
n_line_strings= uint4korr(data); | ||||
data+= 4; | ||||
while (n_line_strings--) | while (n_line_strings--) | |||
{ | { | |||
data+= WKB_HEADER_SIZE; | if (wkb->skip_wkb_header() || | |||
if (!(data= get_mbr_for_points(mbr, data, 0))) | get_mbr_for_points(mbr, wkb, 0)) | |||
return 1; | return true; | |||
} | } | |||
*end= data; | return false; | |||
return 0; | ||||
} | } | |||
int Gis_multi_line_string::num_geometries(uint32 *num) const | int Gis_multi_line_string::num_geometries(uint32 *num) const | |||
{ | { | |||
*num= uint4korr(m_data); | wkb_parser wkb(&m_wkb_data); | |||
return 0; | return wkb.scan_non_zero_uint4(num) ? 1 : 0; | |||
} | } | |||
int Gis_multi_line_string::geometry_n(uint32 num, String *result) const | int Gis_multi_line_string::geometry_n(uint32 num, String *result) const | |||
{ | { | |||
uint32 n_line_strings, n_points, length; | uint32 n_line_strings, n_points, length; | |||
const char *data= m_data; | wkb_parser wkb(&m_wkb_data); | |||
if (no_data(data, 4)) | if (wkb.scan_non_zero_uint4(&n_line_strings)) | |||
return 1; | return 1; | |||
n_line_strings= uint4korr(data); | ||||
data+= 4; | ||||
if ((num > n_line_strings) || (num < 1)) | if ((num > n_line_strings) || (num < 1)) | |||
return 1; | return 1; | |||
for (;;) | for (;;) | |||
{ | { | |||
if (no_data(data, WKB_HEADER_SIZE + 4)) | if (wkb.skip_wkb_header() || | |||
return 1; | wkb.scan_n_points_and_check_data(&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; | return 1; | |||
length= POINT_DATA_SIZE * n_points; | ||||
if (!--num) | if (!--num) | |||
break; | break; | |||
data+= length; | wkb.skip_unsafe(length); | |||
} | } | |||
return result->append(data, length, (uint32) 0); | return result->append(wkb.data() - 4 - WKB_HEADER_SIZE, | |||
length + 4 + WKB_HEADER_SIZE, (uint32) 0); | ||||
} | } | |||
int Gis_multi_line_string::geom_length(double *len) const | int Gis_multi_line_string::geom_length(double *len) const | |||
{ | { | |||
uint32 n_line_strings; | uint32 n_line_strings; | |||
const char *data= m_data; | wkb_parser wkb(&m_wkb_data); | |||
if (no_data(data, 4)) | if (wkb.scan_non_zero_uint4(&n_line_strings)) | |||
return 1; | return 1; | |||
n_line_strings= uint4korr(data); | ||||
data+= 4; | ||||
*len=0; | *len=0; | |||
while (n_line_strings--) | while (n_line_strings--) | |||
{ | { | |||
double ls_len; | double ls_len; | |||
Gis_line_string ls; | Gis_line_string ls; | |||
data+= WKB_HEADER_SIZE; | if (wkb.skip_wkb_header()) | |||
ls.set_data_ptr(data, (uint32) (m_data_end - data)); | return 1; | |||
ls.set_data_ptr(&wkb); | ||||
if (ls.geom_length(&ls_len)) | if (ls.geom_length(&ls_len)) | |||
return 1; | return 1; | |||
*len+= ls_len; | *len+= ls_len; | |||
/* | /* | |||
We know here that ls was ok, so we can call the trivial function | We know here that ls was ok, so we can call the trivial function | |||
Gis_line_string::get_data_size without error checking | Gis_line_string::get_data_size without error checking | |||
*/ | */ | |||
data+= ls.get_data_size(); | wkb.skip_unsafe(ls.get_data_size()); | |||
} | } | |||
return 0; | return 0; | |||
} | } | |||
int Gis_multi_line_string::is_closed(int *closed) const | int Gis_multi_line_string::is_closed(int *closed) const | |||
{ | { | |||
uint32 n_line_strings; | uint32 n_line_strings; | |||
const char *data= m_data; | wkb_parser wkb(&m_wkb_data); | |||
if (no_data(data, 4 + WKB_HEADER_SIZE)) | if (wkb.scan_non_zero_uint4(&n_line_strings)) | |||
return 1; | return 1; | |||
n_line_strings= uint4korr(data); | ||||
data+= 4 + WKB_HEADER_SIZE; | ||||
while (n_line_strings--) | while (n_line_strings--) | |||
{ | { | |||
Gis_line_string ls; | Gis_line_string ls; | |||
if (no_data(data, 0)) | if (wkb.skip_wkb_header()) | |||
return 1; | return 1; | |||
ls.set_data_ptr(data, (uint32) (m_data_end - data)); | ls.set_data_ptr(&wkb); | |||
if (ls.is_closed(closed)) | if (ls.is_closed(closed)) | |||
return 1; | return 1; | |||
if (!*closed) | if (!*closed) | |||
return 0; | return 0; | |||
/* | wkb.skip_unsafe(ls.get_data_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; | return 0; | |||
} | } | |||
int Gis_multi_line_string::store_shapes(Gcalc_shape_transporter *trn, | int Gis_multi_line_string::store_shapes(Gcalc_shape_transporter *trn, | |||
Gcalc_shape_status *st) const | Gcalc_shape_status *st) const | |||
{ | { | |||
if (trn->skip_line_string()) | if (trn->skip_line_string()) | |||
return 0; | return 0; | |||
Gis_line_string ls; | Gis_line_string ls; | |||
skipping to change at line 1696 | skipping to change at line 1562 | |||
const Geometry::Class_info *Gis_multi_line_string::get_class_info() const | const Geometry::Class_info *Gis_multi_line_string::get_class_info() const | |||
{ | { | |||
return &multilinestring_class; | return &multilinestring_class; | |||
} | } | |||
/***************************** MultiPolygon ******************************* / | /***************************** MultiPolygon ******************************* / | |||
uint32 Gis_multi_polygon::get_data_size() const | uint32 Gis_multi_polygon::get_data_size() const | |||
{ | { | |||
uint32 n_polygons; | uint32 n_polygons; | |||
const char *data= m_data; | wkb_parser wkb(&m_wkb_data); | |||
if (no_data(data, 4)) | if (wkb.scan_non_zero_uint4(&n_polygons)) | |||
return GET_SIZE_ERROR; | return GET_SIZE_ERROR; | |||
n_polygons= uint4korr(data); | ||||
data+= 4; | ||||
while (n_polygons--) | while (n_polygons--) | |||
{ | { | |||
uint32 n_linear_rings; | uint32 n_linear_rings; | |||
if (no_data(data, 4 + WKB_HEADER_SIZE)) | if (wkb.skip_wkb_header() || | |||
wkb.scan_non_zero_uint4(&n_linear_rings)) | ||||
return GET_SIZE_ERROR; | return GET_SIZE_ERROR; | |||
n_linear_rings= uint4korr(data + WKB_HEADER_SIZE); | ||||
data+= 4 + WKB_HEADER_SIZE; | ||||
while (n_linear_rings--) | while (n_linear_rings--) | |||
{ | { | |||
if (no_data(data, 4)) | uint32 n_points; | |||
return GET_SIZE_ERROR; | ||||
data+= 4 + uint4korr(data) * POINT_DATA_SIZE; | if (wkb.scan_n_points_and_check_data(&n_points)) | |||
return GET_SIZE_ERROR; | ||||
wkb.skip_unsafe(n_points * POINT_DATA_SIZE); | ||||
} | } | |||
} | } | |||
return (uint32) (data - m_data); | return (uint32) (wkb.data() - m_wkb_data.data()); | |||
} | } | |||
bool Gis_multi_polygon::init_from_wkt(Gis_read_stream *trs, String *wkb) | bool Gis_multi_polygon::init_from_wkt(Gis_read_stream *trs, String *wkb) | |||
{ | { | |||
uint32 n_polygons= 0; | uint32 n_polygons= 0; | |||
int np_pos= wkb->length(); | int np_pos= wkb->length(); | |||
Gis_polygon p; | Gis_polygon p; | |||
if (wkb->reserve(4, 512)) | if (wkb->reserve(4, 512)) | |||
return 1; | return true; | |||
wkb->length(wkb->length()+4); // Reserve space for points | wkb->length(wkb->length()+4); // Reserve space for points | |||
for (;;) | for (;;) | |||
{ | { | |||
if (wkb->reserve(1 + 4, 512)) | if (wkb->reserve(1 + 4, 512)) | |||
return 1; | return true; | |||
wkb->q_append((char) wkb_ndr); | wkb->q_append((char) wkb_ndr); | |||
wkb->q_append((uint32) wkb_polygon); | wkb->q_append((uint32) wkb_polygon); | |||
if (trs->check_next_symbol('(') || | if (trs->check_next_symbol('(') || | |||
p.init_from_wkt(trs, wkb) || | p.init_from_wkt(trs, wkb) || | |||
trs->check_next_symbol(')')) | trs->check_next_symbol(')')) | |||
return 1; | return true; | |||
n_polygons++; | n_polygons++; | |||
if (trs->skip_char(',')) // Didn't find ',' | if (trs->skip_char(',')) // Didn't find ',' | |||
break; | break; | |||
} | } | |||
wkb->write_at_position(np_pos, n_polygons); | wkb->write_at_position(np_pos, n_polygons); | |||
return 0; | return false; | |||
} | } | |||
uint Gis_multi_polygon::init_from_wkb(const char *wkb, uint len, | uint Gis_multi_polygon::init_from_wkb(const char *wkb, uint len, | |||
wkbByteOrder bo, String *res) | wkbByteOrder bo, String *res) | |||
{ | { | |||
uint32 n_poly; | uint32 n_poly; | |||
const char *wkb_orig= wkb; | const char *wkb_orig= wkb; | |||
if (len < 4) | if (len < 4) | |||
return 0; | return 0; | |||
skipping to change at line 1794 | skipping to change at line 1659 | |||
return (uint) (wkb - wkb_orig); | return (uint) (wkb - wkb_orig); | |||
} | } | |||
uint Gis_multi_polygon::init_from_opresult(String *bin, | uint Gis_multi_polygon::init_from_opresult(String *bin, | |||
const char *opres, uint opres_le ngth) | const char *opres, uint opres_le ngth) | |||
{ | { | |||
Gis_polygon item; | Gis_polygon item; | |||
return collection_init_from_opresult(bin, opres, opres_length, &item); | return collection_init_from_opresult(bin, opres, opres_length, &item); | |||
} | } | |||
bool Gis_multi_polygon::get_data_as_wkt(String *txt, const char **end) cons t | bool Gis_multi_polygon::get_data_as_wkt(String *txt, wkb_parser *wkb) const | |||
{ | { | |||
uint32 n_polygons; | uint32 n_polygons; | |||
const char *data= m_data; | ||||
if (no_data(data, 4)) | if (wkb->scan_non_zero_uint4(&n_polygons)) | |||
return 1; | return true; | |||
n_polygons= uint4korr(data); | ||||
data+= 4; | ||||
while (n_polygons--) | while (n_polygons--) | |||
{ | { | |||
uint32 n_linear_rings; | uint32 n_linear_rings; | |||
if (no_data(data, 4 + WKB_HEADER_SIZE) || | ||||
txt->reserve(1, 512)) | if (wkb->skip_wkb_header() || | |||
return 1; | wkb->scan_non_zero_uint4(&n_linear_rings) || | |||
n_linear_rings= uint4korr(data+WKB_HEADER_SIZE); | txt->reserve(1, 512)) | |||
data+= 4 + WKB_HEADER_SIZE; | return true; | |||
txt->q_append('('); | txt->q_append('('); | |||
while (n_linear_rings--) | while (n_linear_rings--) | |||
{ | { | |||
if (no_data(data, 4)) | uint32 n_points; | |||
return 1; | if (wkb->scan_n_points_and_check_data(&n_points) || | |||
uint32 n_points= uint4korr(data); | txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points, | |||
data+= 4; | 512)) | |||
if (no_data(data, POINT_DATA_SIZE * n_points) || | return true; | |||
txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points, | ||||
512)) | ||||
return 1; | ||||
txt->qs_append('('); | txt->qs_append('('); | |||
data= append_points(txt, n_points, data, 0); | append_points(txt, n_points, wkb, 0); | |||
(*txt) [txt->length() - 1]= ')'; | (*txt) [txt->length() - 1]= ')'; | |||
txt->qs_append(','); | txt->qs_append(','); | |||
} | } | |||
(*txt) [txt->length() - 1]= ')'; | (*txt) [txt->length() - 1]= ')'; | |||
txt->qs_append(','); | txt->qs_append(','); | |||
} | } | |||
txt->length(txt->length() - 1); | txt->length(txt->length() - 1); | |||
*end= data; | return false; | |||
return 0; | ||||
} | } | |||
bool Gis_multi_polygon::get_mbr(MBR *mbr, const char **end) const | bool Gis_multi_polygon::get_mbr(MBR *mbr, wkb_parser *wkb) const | |||
{ | { | |||
uint32 n_polygons; | uint32 n_polygons; | |||
const char *data= m_data; | ||||
if (no_data(data, 4)) | if (wkb->scan_non_zero_uint4(&n_polygons)) | |||
return 1; | return true; | |||
n_polygons= uint4korr(data); | ||||
data+= 4; | ||||
while (n_polygons--) | while (n_polygons--) | |||
{ | { | |||
uint32 n_linear_rings; | uint32 n_linear_rings; | |||
if (no_data(data, 4+WKB_HEADER_SIZE)) | if (wkb->skip_wkb_header() || | |||
return 1; | wkb->scan_non_zero_uint4(&n_linear_rings)) | |||
n_linear_rings= uint4korr(data + WKB_HEADER_SIZE); | return true; | |||
data+= WKB_HEADER_SIZE + 4; | ||||
while (n_linear_rings--) | while (n_linear_rings--) | |||
{ | { | |||
if (!(data= get_mbr_for_points(mbr, data, 0))) | if (get_mbr_for_points(mbr, wkb, 0)) | |||
return 1; | return true; | |||
} | } | |||
} | } | |||
*end= data; | return false; | |||
return 0; | ||||
} | } | |||
int Gis_multi_polygon::num_geometries(uint32 *num) const | int Gis_multi_polygon::num_geometries(uint32 *num) const | |||
{ | { | |||
*num= uint4korr(m_data); | wkb_parser wkb(&m_wkb_data); | |||
return 0; | return wkb.scan_non_zero_uint4(num) ? 1 : 0; | |||
} | } | |||
int Gis_multi_polygon::geometry_n(uint32 num, String *result) const | int Gis_multi_polygon::geometry_n(uint32 num, String *result) const | |||
{ | { | |||
uint32 n_polygons; | uint32 n_polygons; | |||
const char *data= m_data, *start_of_polygon; | wkb_parser wkb(&m_wkb_data); | |||
const char *start_of_polygon= wkb.data(); | ||||
if (no_data(data, 4)) | if (wkb.scan_non_zero_uint4(&n_polygons)) | |||
return 1; | return 1; | |||
n_polygons= uint4korr(data); | ||||
data+= 4; | ||||
if (num > n_polygons || num < 1) | if (num > n_polygons || num < 1) | |||
return -1; | return -1; | |||
do | do | |||
{ | { | |||
uint32 n_linear_rings; | uint32 n_linear_rings; | |||
start_of_polygon= data; | start_of_polygon= wkb.data(); | |||
if (no_data(data, WKB_HEADER_SIZE + 4)) | if (wkb.skip_wkb_header() || | |||
wkb.scan_non_zero_uint4(&n_linear_rings)) | ||||
return 1; | return 1; | |||
n_linear_rings= uint4korr(data + WKB_HEADER_SIZE); | ||||
data+= WKB_HEADER_SIZE + 4; | ||||
while (n_linear_rings--) | while (n_linear_rings--) | |||
{ | { | |||
uint32 n_points; | uint32 n_points; | |||
if (no_data(data, 4)) | if (wkb.scan_n_points_and_check_data(&n_points)) | |||
return 1; | return 1; | |||
n_points= uint4korr(data); | wkb.skip_unsafe(POINT_DATA_SIZE * n_points); | |||
data+= 4 + POINT_DATA_SIZE * n_points; | ||||
} | } | |||
} while (--num); | } while (--num); | |||
if (no_data(data, 0)) // We must check las t segment | if (wkb.no_data(0)) // We must check last segmen t | |||
return 1; | return 1; | |||
return result->append(start_of_polygon, (uint32) (data - start_of_polygon | return result->append(start_of_polygon, | |||
), | (uint32) (wkb.data() - start_of_polygon), | |||
(uint32) 0); | (uint32) 0); | |||
} | } | |||
int Gis_multi_polygon::area(double *ar, const char **end_of_data) const | bool Gis_multi_polygon::area(double *ar, wkb_parser *wkb) const | |||
{ | { | |||
Gis_polygon p; | Gis_polygon p; | |||
return collection_area(ar, end_of_data, &p); | return collection_area(ar, wkb, &p); | |||
} | } | |||
int Gis_multi_polygon::centroid(String *result) const | int Gis_multi_polygon::centroid(String *result) const | |||
{ | { | |||
uint32 n_polygons; | uint32 n_polygons; | |||
bool first_loop= 1; | bool first_loop= 1; | |||
Gis_polygon p; | Gis_polygon p; | |||
double UNINIT_VAR(res_area), UNINIT_VAR(res_cx), UNINIT_VAR(res_cy); | double UNINIT_VAR(res_area); | |||
double cur_area, cur_cx, cur_cy; | point_xy res(0, 0); // Initialized only to make compiler hap | |||
const char *data= m_data; | py | |||
wkb_parser wkb(&m_wkb_data); | ||||
if (no_data(data, 4)) | if (wkb.scan_non_zero_uint4(&n_polygons)) | |||
return 1; | return 1; | |||
n_polygons= uint4korr(data); | ||||
data+= 4; | ||||
while (n_polygons--) | while (n_polygons--) | |||
{ | { | |||
data+= WKB_HEADER_SIZE; | double cur_area; | |||
p.set_data_ptr(data, (uint32) (m_data_end - data)); | point_xy cur; | |||
if (p.area(&cur_area, &data) || | if (wkb.skip_wkb_header()) | |||
p.centroid_xy(&cur_cx, &cur_cy)) | return 1; | |||
p.set_data_ptr(&wkb); | ||||
if (p.area(&cur_area, &wkb) || | ||||
p.centroid_xy(&cur)) | ||||
return 1; | return 1; | |||
if (!first_loop) | if (!first_loop) | |||
{ | { | |||
double sum_area= res_area + cur_area; | double sum_area= res_area + cur_area; | |||
res_cx= (res_area * res_cx + cur_area * cur_cx) / sum_area; | res.x= (res_area * res.x + cur_area * cur.x) / sum_area; | |||
res_cy= (res_area * res_cy + cur_area * cur_cy) / sum_area; | res.y= (res_area * res.y + cur_area * cur.y) / sum_area; | |||
} | } | |||
else | else | |||
{ | { | |||
first_loop= 0; | first_loop= 0; | |||
res_area= cur_area; | res_area= cur_area; | |||
res_cx= cur_cx; | res= cur; | |||
res_cy= cur_cy; | ||||
} | } | |||
} | } | |||
return create_point(result, res); | ||||
return create_point(result, res_cx, res_cy); | ||||
} | } | |||
int Gis_multi_polygon::store_shapes(Gcalc_shape_transporter *trn, | int Gis_multi_polygon::store_shapes(Gcalc_shape_transporter *trn, | |||
Gcalc_shape_status *st) const | Gcalc_shape_status *st) const | |||
{ | { | |||
if (trn->skip_poly()) | if (trn->skip_poly()) | |||
return 0; | return 0; | |||
Gis_polygon p; | Gis_polygon p; | |||
return collection_store_shapes(trn, st, &p); | return collection_store_shapes(trn, st, &p); | |||
} | } | |||
skipping to change at line 1974 | skipping to change at line 1823 | |||
const Geometry::Class_info *Gis_multi_polygon::get_class_info() const | const Geometry::Class_info *Gis_multi_polygon::get_class_info() const | |||
{ | { | |||
return &multipolygon_class; | return &multipolygon_class; | |||
} | } | |||
/************************* GeometryCollection ****************************/ | /************************* GeometryCollection ****************************/ | |||
uint32 Gis_geometry_collection::get_data_size() const | uint32 Gis_geometry_collection::get_data_size() const | |||
{ | { | |||
uint32 n_objects; | uint32 n_objects; | |||
const char *data= m_data; | wkb_parser wkb(&m_wkb_data); | |||
Geometry_buffer buffer; | Geometry_buffer buffer; | |||
Geometry *geom; | Geometry *geom; | |||
if (no_data(data, 4)) | if (wkb.scan_non_zero_uint4(&n_objects)) | |||
return GET_SIZE_ERROR; | return GET_SIZE_ERROR; | |||
n_objects= uint4korr(data); | ||||
data+= 4; | ||||
while (n_objects--) | while (n_objects--) | |||
{ | { | |||
uint32 wkb_type,object_size; | if (!(geom= scan_header_and_create(&wkb, &buffer))) | |||
if (no_data(data, WKB_HEADER_SIZE)) | ||||
return GET_SIZE_ERROR; | return GET_SIZE_ERROR; | |||
wkb_type= uint4korr(data + 1); | ||||
data+= WKB_HEADER_SIZE; | ||||
if (!(geom= create_by_typeid(&buffer, wkb_type))) | uint32 object_size; | |||
return GET_SIZE_ERROR; | ||||
geom->set_data_ptr(data, (uint) (m_data_end - data)); | ||||
if ((object_size= geom->get_data_size()) == GET_SIZE_ERROR) | if ((object_size= geom->get_data_size()) == GET_SIZE_ERROR) | |||
return GET_SIZE_ERROR; | return GET_SIZE_ERROR; | |||
data+= object_size; | wkb.skip_unsafe(object_size); | |||
} | } | |||
return (uint32) (data - m_data); | return (uint32) (wkb.data() - m_wkb_data.data()); | |||
} | } | |||
bool Gis_geometry_collection::init_from_wkt(Gis_read_stream *trs, String *w kb) | bool Gis_geometry_collection::init_from_wkt(Gis_read_stream *trs, String *w kb) | |||
{ | { | |||
uint32 n_objects= 0; | uint32 n_objects= 0; | |||
uint32 no_pos= wkb->length(); | uint32 no_pos= wkb->length(); | |||
Geometry_buffer buffer; | Geometry_buffer buffer; | |||
Geometry *g; | Geometry *g; | |||
if (wkb->reserve(4, 512)) | if (wkb->reserve(4, 512)) | |||
return 1; | return true; | |||
wkb->length(wkb->length()+4); // Reserve space for points | wkb->length(wkb->length()+4); // Reserve space for points | |||
for (;;) | for (;;) | |||
{ | { | |||
if (!(g= create_from_wkt(&buffer, trs, wkb))) | if (!(g= create_from_wkt(&buffer, trs, wkb))) | |||
return 1; | return true; | |||
if (g->get_class_info()->m_type_id == wkb_geometrycollection) | if (g->get_class_info()->m_type_id == wkb_geometrycollection) | |||
{ | { | |||
trs->set_error_msg("Unexpected GEOMETRYCOLLECTION"); | trs->set_error_msg("Unexpected GEOMETRYCOLLECTION"); | |||
return 1; | return true; | |||
} | } | |||
n_objects++; | n_objects++; | |||
if (trs->skip_char(',')) // Didn't find ',' | if (trs->skip_char(',')) // Didn't find ',' | |||
break; | break; | |||
} | } | |||
wkb->write_at_position(no_pos, n_objects); | wkb->write_at_position(no_pos, n_objects); | |||
return 0; | return false; | |||
} | } | |||
uint Gis_geometry_collection::init_from_opresult(String *bin, | uint Gis_geometry_collection::init_from_opresult(String *bin, | |||
const char *opres, | const char *opres, | |||
uint opres_length) | uint opres_length) | |||
{ | { | |||
return collection_init_from_opresult(bin, opres, opres_length, NULL); | return collection_init_from_opresult(bin, opres, opres_length, NULL); | |||
} | } | |||
uint Gis_geometry_collection::init_from_wkb(const char *wkb, uint len, | uint Gis_geometry_collection::init_from_wkb(const char *wkb, uint len, | |||
skipping to change at line 2081 | skipping to change at line 1922 | |||
(wkbByteOrder) wkb[0], res))) | (wkbByteOrder) wkb[0], res))) | |||
return 0; | return 0; | |||
g_len+= WKB_HEADER_SIZE; | g_len+= WKB_HEADER_SIZE; | |||
wkb+= g_len; | wkb+= g_len; | |||
len-= g_len; | len-= g_len; | |||
} | } | |||
return (uint) (wkb - wkb_orig); | return (uint) (wkb - wkb_orig); | |||
} | } | |||
bool Gis_geometry_collection::get_data_as_wkt(String *txt, | bool Gis_geometry_collection::get_data_as_wkt(String *txt, | |||
const char **end) const | wkb_parser *wkb) const | |||
{ | { | |||
uint32 n_objects; | uint32 n_objects; | |||
Geometry_buffer buffer; | Geometry_buffer buffer; | |||
Geometry *geom; | Geometry *geom; | |||
const char *data= m_data; | ||||
if (no_data(data, 4)) | if (wkb->scan_non_zero_uint4(&n_objects)) | |||
return 1; | return true; | |||
n_objects= uint4korr(data); | ||||
data+= 4; | ||||
while (n_objects--) | while (n_objects--) | |||
{ | { | |||
uint32 wkb_type; | if (!(geom= scan_header_and_create(wkb, &buffer)) || | |||
geom->as_wkt(txt, wkb) || | ||||
if (no_data(data, WKB_HEADER_SIZE)) | txt->append(STRING_WITH_LEN(","), 512)) | |||
return 1; | return true; | |||
wkb_type= uint4korr(data + 1); | ||||
data+= WKB_HEADER_SIZE; | ||||
if (!(geom= create_by_typeid(&buffer, wkb_type))) | ||||
return 1; | ||||
geom->set_data_ptr(data, (uint) (m_data_end - data)); | ||||
if (geom->as_wkt(txt, &data)) | ||||
return 1; | ||||
if (txt->append(STRING_WITH_LEN(","), 512)) | ||||
return 1; | ||||
} | } | |||
txt->length(txt->length() - 1); | txt->length(txt->length() - 1); | |||
*end= data; | return false; | |||
return 0; | ||||
} | } | |||
bool Gis_geometry_collection::get_mbr(MBR *mbr, const char **end) const | bool Gis_geometry_collection::get_mbr(MBR *mbr, wkb_parser *wkb) const | |||
{ | { | |||
uint32 n_objects; | uint32 n_objects; | |||
const char *data= m_data; | ||||
Geometry_buffer buffer; | Geometry_buffer buffer; | |||
Geometry *geom; | Geometry *geom; | |||
if (no_data(data, 4)) | if (wkb->scan_non_zero_uint4(&n_objects)) | |||
return 1; | return true; | |||
n_objects= uint4korr(data); | ||||
data+= 4; | ||||
while (n_objects--) | while (n_objects--) | |||
{ | { | |||
uint32 wkb_type; | if (!(geom= scan_header_and_create(wkb, &buffer)) || | |||
geom->get_mbr(mbr, wkb)) | ||||
if (no_data(data, WKB_HEADER_SIZE)) | return true; | |||
return 1; | ||||
wkb_type= uint4korr(data + 1); | ||||
data+= WKB_HEADER_SIZE; | ||||
if (!(geom= create_by_typeid(&buffer, wkb_type))) | ||||
return 1; | ||||
geom->set_data_ptr(data, (uint32) (m_data_end - data)); | ||||
if (geom->get_mbr(mbr, &data)) | ||||
return 1; | ||||
} | } | |||
*end= data; | return false; | |||
return 0; | ||||
} | } | |||
int Gis_geometry_collection::area(double *ar, const char **end_of_data) con st | bool Gis_geometry_collection::area(double *ar, wkb_parser *wkb) const | |||
{ | { | |||
return collection_area(ar, end_of_data, NULL); | return collection_area(ar, wkb, NULL); | |||
} | } | |||
int Gis_geometry_collection::num_geometries(uint32 *num) const | int Gis_geometry_collection::num_geometries(uint32 *num) const | |||
{ | { | |||
if (no_data(m_data, 4)) | wkb_parser wkb(&m_wkb_data); | |||
return 1; | return wkb.scan_non_zero_uint4(num) ? 1 : 0; | |||
*num= uint4korr(m_data); | ||||
return 0; | ||||
} | } | |||
int Gis_geometry_collection::geometry_n(uint32 num, String *result) const | int Gis_geometry_collection::geometry_n(uint32 num, String *result) const | |||
{ | { | |||
uint32 n_objects, wkb_type, length; | uint32 n_objects, length; | |||
const char *data= m_data; | wkb_parser wkb(&m_wkb_data); | |||
Geometry_buffer buffer; | Geometry_buffer buffer; | |||
Geometry *geom; | Geometry *geom; | |||
if (no_data(data, 4)) | if (wkb.scan_non_zero_uint4(&n_objects)) | |||
return 1; | return 1; | |||
n_objects= uint4korr(data); | ||||
data+= 4; | ||||
if (num > n_objects || num < 1) | if (num > n_objects || num < 1) | |||
return 1; | return 1; | |||
wkb_header header; | ||||
do | do | |||
{ | { | |||
if (no_data(data, WKB_HEADER_SIZE)) | if (wkb.scan_wkb_header(&header) || | |||
return 1; | !(geom= create_by_typeid(&buffer, header.wkb_type))) | |||
wkb_type= uint4korr(data + 1); | ||||
data+= WKB_HEADER_SIZE; | ||||
if (!(geom= create_by_typeid(&buffer, wkb_type))) | ||||
return 1; | return 1; | |||
geom->set_data_ptr(data, (uint) (m_data_end - data)); | geom->set_data_ptr(&wkb); | |||
if ((length= geom->get_data_size()) == GET_SIZE_ERROR) | if ((length= geom->get_data_size()) == GET_SIZE_ERROR) | |||
return 1; | return 1; | |||
data+= length; | wkb.skip_unsafe(length); | |||
} while (--num); | } while (--num); | |||
/* Copy found object to result */ | /* Copy found object to result */ | |||
if (result->reserve(1 + 4 + length)) | if (result->reserve(1 + 4 + length)) | |||
return 1; | return 1; | |||
result->q_append((char) wkb_ndr); | result->q_append((char) wkb_ndr); | |||
result->q_append((uint32) wkb_type); | result->q_append((uint32) header.wkb_type); | |||
result->q_append(data-length, length); // data-length = start_of_da | result->q_append(wkb.data() - length, length); // data-length = start_of_ | |||
ta | data | |||
return 0; | return 0; | |||
} | } | |||
/* | /* | |||
Return dimension for object | Return dimension for object | |||
SYNOPSIS | SYNOPSIS | |||
dimension() | dimension() | |||
res_dim Result dimension | res_dim Result dimension | |||
end End of object will be stored here. May be 0 for | end End of object will be stored here. May be 0 for | |||
simple objects! | simple objects! | |||
RETURN | RETURN | |||
0 ok | 0 ok | |||
1 error | 1 error | |||
*/ | */ | |||
bool Gis_geometry_collection::dimension(uint32 *res_dim, const char **end) | bool Gis_geometry_collection::dimension(uint32 *res_dim, | |||
const | wkb_parser *wkb) const | |||
{ | { | |||
uint32 n_objects; | uint32 n_objects; | |||
const char *data= m_data; | ||||
Geometry_buffer buffer; | Geometry_buffer buffer; | |||
Geometry *geom; | Geometry *geom; | |||
if (no_data(data, 4)) | if (wkb->scan_non_zero_uint4(&n_objects)) | |||
return 1; | return true; | |||
n_objects= uint4korr(data); | ||||
data+= 4; | ||||
*res_dim= 0; | *res_dim= 0; | |||
while (n_objects--) | while (n_objects--) | |||
{ | { | |||
uint32 wkb_type, length, dim; | uint32 dim; | |||
const char *end_data; | if (!(geom= scan_header_and_create(wkb, &buffer)) || | |||
geom->dimension(&dim, wkb)) | ||||
if (no_data(data, WKB_HEADER_SIZE)) | return true; | |||
return 1; | ||||
wkb_type= uint4korr(data + 1); | ||||
data+= WKB_HEADER_SIZE; | ||||
if (!(geom= create_by_typeid(&buffer, wkb_type))) | ||||
return 1; | ||||
geom->set_data_ptr(data, (uint32) (m_data_end - data)); | ||||
if (geom->dimension(&dim, &end_data)) | ||||
return 1; | ||||
set_if_bigger(*res_dim, dim); | 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 false; | |||
return 0; | ||||
} | } | |||
int Gis_geometry_collection::store_shapes(Gcalc_shape_transporter *trn, | int Gis_geometry_collection::store_shapes(Gcalc_shape_transporter *trn, | |||
Gcalc_shape_status *st) const | Gcalc_shape_status *st) const | |||
{ | { | |||
return collection_store_shapes(trn, st, NULL); | return collection_store_shapes(trn, st, NULL); | |||
} | } | |||
const Geometry::Class_info *Gis_geometry_collection::get_class_info() const | const Geometry::Class_info *Gis_geometry_collection::get_class_info() const | |||
{ | { | |||
End of changes. 300 change blocks. | ||||
661 lines changed or deleted | 452 lines changed or added | |||
This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/ |