Commit 788043cd authored by Alexey Botchkov's avatar Alexey Botchkov

Precise GIS functions added.

parent aaf9fb0d
......@@ -136,6 +136,7 @@ SET(LIBMYSQLD_SOURCES libmysqld.c emb_qcache.cc lib_sql.cc
../sql/sql_tablespace.cc ../sql/sql_table.cc ../sql/sql_test.cc
../sql/sql_trigger.cc ../sql/sql_udf.cc ../sql/sql_union.cc
../sql/sql_update.cc ../sql/sql_view.cc ../sql/sql_profile.cc
../sql/gcalc_tools.cc ../sql/gcalc_slicescan.cc
../sql/strfunc.cc ../sql/table.cc ../sql/thr_malloc.cc
../sql/time.cc ../sql/tztime.cc ../sql/uniques.cc ../sql/unireg.cc
../sql/partition_info.cc ../sql/sql_connect.cc
......
......@@ -62,6 +62,7 @@ sqlsources = derror.cc field.cc field_conv.cc strfunc.cc filesort.cc \
opt_sum.cc procedure.cc records.cc sql_acl.cc \
sql_load.cc discover.cc sql_locale.cc \
sql_profile.cc \
gcalc_slicescan.cc gcalc_tools.cc \
sql_analyse.cc sql_base.cc sql_cache.cc sql_class.cc \
sql_crypt.cc sql_db.cc sql_delete.cc sql_error.cc sql_insert.cc \
sql_join_cache.cc \
......
This diff is collapsed.
This diff is collapsed.
......@@ -17,16 +17,12 @@ SHOW CREATE TABLE t1;
let $1=150;
let $2=150;
--disable_query_log
begin;
while ($1)
{
eval INSERT INTO t1 (g) VALUES (GeomFromText('LineString($1 $1, $2 $2)'));
dec $1;
inc $2;
}
commit;
--enable_query_log
SELECT count(*) FROM t1;
EXPLAIN SELECT fid, AsText(g) FROM t1 WHERE Within(g, GeomFromText('Polygon((140 140,160 140,160 160,140 160,140 140))'));
......@@ -39,8 +35,6 @@ CREATE TABLE t2 (
g GEOMETRY NOT NULL
) ENGINE=MyISAM;
--disable_query_log
begin;
let $1=10;
while ($1)
{
......@@ -52,8 +46,6 @@ while ($1)
}
dec $1;
}
commit;
--enable_query_log
ALTER TABLE t2 ADD SPATIAL KEY(g);
SHOW CREATE TABLE t2;
......@@ -63,8 +55,6 @@ EXPLAIN SELECT fid, AsText(g) FROM t2 WHERE Within(g,
SELECT fid, AsText(g) FROM t2 WHERE Within(g,
GeomFromText('Polygon((40 40,60 40,60 60,40 60,40 40))'));
--disable_query_log
begin;
let $1=10;
while ($1)
{
......@@ -77,8 +67,6 @@ while ($1)
}
dec $1;
}
commit;
--enable_query_log
DROP TABLE t2;
......
This diff is collapsed.
......@@ -78,6 +78,7 @@ SET (SQL_SOURCE
rpl_rli.cc rpl_mi.cc sql_servers.cc
sql_connect.cc scheduler.cc
sql_profile.cc event_parse_data.cc opt_table_elimination.cc
gcalc_slicescan.cc gcalc_tools.cc
multi_range_read.cc
opt_subselect.cc
opt_index_cond_pushdown.cc
......
......@@ -56,6 +56,7 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \
sql_map.h sql_string.h unireg.h \
sql_error.h field.h handler.h mysqld_suffix.h \
sql_profile.h \
gcalc_slicescan.h gcalc_tools.h \
ha_ndbcluster.h ha_ndbcluster_cond.h \
ha_ndbcluster_binlog.h ha_ndbcluster_tables.h \
ha_partition.h rpl_constants.h \
......@@ -101,6 +102,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \
sql_join_cache.cc \
sql_base.cc table.cc sql_select.cc sql_insert.cc \
sql_profile.cc \
gcalc_slicescan.cc gcalc_tools.cc \
sql_prepare.cc sql_error.cc sql_locale.cc \
sql_update.cc sql_delete.cc uniques.cc sql_do.cc \
procedure.cc sql_test.cc \
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/* Copyright (c) 2000, 2010 Oracle and/or its affiliates. All rights reserved.
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; version 2 of the License.
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 */
#ifndef GCALC_TOOLS_INCLUDED
#define GCALC_TOOLS_INCLUDED
#include "gcalc_slicescan.h"
/*
The Gcalc_function class objects are used to check for a binary relation.
The relation can be constructed with the prefix notation using predicates as
op_not (as !A)
op_union ( A || B || C... )
op_intersection ( A && B && C ... )
op_symdifference ( A+B+C+... == 1 )
op_difference ( A && !(B||C||..))
with the calls of the add_operation(operation, n_operands) method.
The relation is calculated over a set of shapes, that in turn have
to be added with the add_new_shape() method. All the 'shapes' can
be set to 0 with clear_shapes() method and single value
can be changed with the invert_state() method.
Then the value of the relation can be calculated with the count() method.
Frequently used method is find_function(Gcalc_scan_iterator it) that
iterates through the 'it' until the relation becomes TRUE.
*/
class Gcalc_function
{
private:
String shapes_buffer;
String function_buffer;
const char *cur_func;
int *i_states;
uint32 cur_object_id;
uint n_shapes;
int count_internal();
public:
enum op_type
{
op_shape= 0,
op_not= 0x80000000,
op_union= 0x10000000,
op_intersection= 0x20000000,
op_symdifference= 0x30000000,
op_difference= 0x40000000,
op_backdifference= 0x50000000,
op_any= 0x70000000
};
enum shape_type
{
shape_point= 0,
shape_line= 1,
shape_polygon= 2,
shape_hole= 3
};
Gcalc_function() : n_shapes(0) {}
gcalc_shape_info add_new_shape(uint32 shape_id, shape_type shape_kind);
/*
Adds the leaf operation that returns the shape value.
Also adds the shape to the list of operands.
*/
int single_shape_op(shape_type shape_kind, gcalc_shape_info *si);
void add_operation(op_type operation, uint32 n_operands);
void add_not_operation(op_type operation, uint32 n_operands);
uint32 get_next_operation_pos() { return function_buffer.length(); }
void add_operands_to_op(uint32 operation_pos, uint32 n_operands);
void set_cur_obj(uint32 cur_obj) { cur_object_id= cur_obj; }
int reserve_shape_buffer(uint n_shapes);
int reserve_op_buffer(uint n_ops);
uint get_nshapes() const { return n_shapes; }
shape_type get_shape_kind(gcalc_shape_info si) const
{
return (shape_type) uint4korr(shapes_buffer.ptr() + (si*4));
}
void set_states(int *shape_states) { i_states= shape_states; }
int alloc_states();
void invert_state(gcalc_shape_info shape) { i_states[shape]^= 1; }
int get_state(gcalc_shape_info shape) { return i_states[shape]; }
int count()
{
cur_func= function_buffer.ptr();
return count_internal();
}
void clear_state() { bzero(i_states, n_shapes * sizeof(int)); }
void reset();
int find_function(Gcalc_scan_iterator &scan_it);
};
/*
Gcalc_operation_transporter class extends the Gcalc_shape_transporter.
In addition to the parent's functionality, it fills the Gcalc_function
object so it has the function that determines the proper shape.
For example Multipolyline will be represented as an union of polylines.
*/
class Gcalc_operation_transporter : public Gcalc_shape_transporter
{
protected:
Gcalc_function *m_fn;
gcalc_shape_info m_si;
public:
Gcalc_operation_transporter(Gcalc_function *fn, Gcalc_heap *heap) :
Gcalc_shape_transporter(heap), m_fn(fn) {}
int single_point(double x, double y);
int start_line();
int complete_line();
int start_poly();
int complete_poly();
int start_ring();
int complete_ring();
int add_point(double x, double y);
int start_collection(int n_objects);
};
/*
When we calculate the result of an spatial operation like
Union or Intersection, we receive vertexes of the result
one-by-one, and probably need to treat them in variative ways.
So, the Gcalc_result_receiver class designed to get these
vertexes and construct shapes/objects out of them.
and to store the result in an appropriate format
*/
class Gcalc_result_receiver
{
String buffer;
uint32 n_points;
Gcalc_function::shape_type common_shapetype;
bool collection_result;
uint32 n_shapes;
uint32 n_holes;
Gcalc_function::shape_type cur_shape;
uint32 shape_pos;
double first_x, first_y, prev_x, prev_y;
double shape_area;
public:
Gcalc_result_receiver() : collection_result(FALSE), n_shapes(0), n_holes(0)
{}
int start_shape(Gcalc_function::shape_type shape);
int add_point(double x, double y);
int complete_shape();
int single_point(double x, double y);
int done();
void reset();
const char *result() { return buffer.ptr(); }
uint length() { return buffer.length(); }
int get_nshapes() { return n_shapes; }
int get_nholes() { return n_holes; }
int get_result_typeid();
uint32 position() { return buffer.length(); }
int move_hole(uint32 dest_position, uint32 source_position,
uint32 *new_dest_position);
};
/*
Gcalc_operation_reducer class incapsulates the spatial
operation functionality. It analyses the slices generated by
the slicescan and calculates the shape of the result defined
by some Gcalc_function.
*/
class Gcalc_operation_reducer : public Gcalc_dyn_list
{
public:
enum modes
{
/* Numeric values important here - careful with changing */
default_mode= 0,
prefer_big_with_holes= 1,
polygon_selfintersections_allowed= 2, /* allowed in the result */
line_selfintersections_allowed= 4 /* allowed in the result */
};
Gcalc_operation_reducer(size_t blk_size=8192);
void init(Gcalc_function *fn, modes mode= default_mode);
Gcalc_operation_reducer(Gcalc_function *fn, modes mode= default_mode,
size_t blk_size=8192);
int count_slice(Gcalc_scan_iterator *si);
int count_all(Gcalc_heap *hp);
int get_result(Gcalc_result_receiver *storage);
void reset();
class res_point : public Gcalc_dyn_list::Item
{
public:
bool intersection_point;
double x,y;
res_point *up;
res_point *down;
res_point *glue;
union
{
const Gcalc_heap::Info *pi;
res_point *first_poly_node;
};
union
{
res_point *outer_poly;
uint32 poly_position;
};
Gcalc_dyn_list::Item **prev_hook;
res_point *get_next() { return (res_point *)next; }
};
class active_thread : public Gcalc_dyn_list::Item
{
public:
res_point *rp;
int result_range;
res_point *thread_start;
active_thread *get_next() { return (active_thread *)next; }
};
protected:
Gcalc_function *m_fn;
Gcalc_dyn_list::Item **m_res_hook;
res_point *m_result;
int m_mode;
res_point *result_heap;
active_thread *m_first_active_thread;
res_point *add_res_point()
{
res_point *result= (res_point *)new_item();
*m_res_hook= result;
result->prev_hook= m_res_hook;
m_res_hook= &result->next;
return result;
}
active_thread *new_active_thread() { return (active_thread *)new_item(); }
private:
int continue_range(active_thread *t, const Gcalc_heap::Info *p);
int continue_i_range(active_thread *t, const Gcalc_heap::Info *p,
double x, double y);
int start_range(active_thread *t, const Gcalc_heap::Info *p);
int start_i_range(active_thread *t, const Gcalc_heap::Info *p,
double x, double y);
int end_range(active_thread *t, const Gcalc_heap::Info *p);
int end_i_range(active_thread *t, const Gcalc_heap::Info *p,
double x, double y);
int start_couple(active_thread *t0, active_thread *t1,const Gcalc_heap::Info *p,
const active_thread *prev_range);
int start_i_couple(active_thread *t0, active_thread *t1,
const Gcalc_heap::Info *p0,
const Gcalc_heap::Info *p1,
double x, double y,
const active_thread *prev_range);
int end_couple(active_thread *t0, active_thread *t1, const Gcalc_heap::Info *p);
int end_i_couple(active_thread *t0, active_thread *t1,
const Gcalc_heap::Info *p0,
const Gcalc_heap::Info *p1,
double x, double y);
int add_single_point(const Gcalc_heap::Info *p);
int add_i_single_point(const Gcalc_heap::Info *p, double x, double y);
int handle_lines_intersection(active_thread *t0, active_thread *t1,
const Gcalc_heap::Info *p0,
const Gcalc_heap::Info *p1,
double x, double y);
int handle_polygons_intersection(active_thread *t0, active_thread *t1,
Gcalc_dyn_list::Item **t_hook,
const Gcalc_heap::Info *p0,
const Gcalc_heap::Info *p1,
int prev_state, double x, double y,
const active_thread *prev_range);
int handle_line_polygon_intersection(active_thread *l,
const Gcalc_heap::Info *pl,
int line_state, int poly_state,
double x, double y);
int get_single_result(res_point *res, Gcalc_result_receiver *storage);
int get_result_thread(res_point *cur, Gcalc_result_receiver *storage,
int move_upward);
int get_polygon_result(res_point *cur, Gcalc_result_receiver *storage);
int get_line_result(res_point *cur, Gcalc_result_receiver *storage);
void free_result(res_point *res);
};
#endif /*GCALC_TOOLS_INCLUDED*/
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/* Copyright (c) 2000, 2010 Oracle and/or its affiliates. All rights reserved.
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; version 2 of the License.
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 */
/*
things to define before including the file:
#define LS_LIST_ITEM ListItem
#define LS_COMPARE_FUNC_DECL compare_func var_name,
#define LS_COMPARE_FUNC_CALL(list_el1, list_el2) (*var_name)(list_el1, list_el2)
#define LS_NEXT(A) (A)->next
#define LS_SET_NEXT(A,val) (A)->next= val
#define LS_P_NEXT(A) &(A)->next
#define LS_NAME plistsort
#define LS_SCOPE static
#define LS_STRUCT_NAME ls_struct_name
*/
typedef struct LS_STRUCT_NAME
{
LS_LIST_ITEM *list1;
int list_len;
int return_point;
} LS_STRUCT_NAME;
LS_SCOPE LS_LIST_ITEM* LS_NAME(LS_COMPARE_FUNC_DECL LS_LIST_ITEM *list, int list_len)
{
LS_LIST_ITEM *list_end;
LS_LIST_ITEM *sorted_list;
struct LS_STRUCT_NAME stack[63], *sp= stack;
if (list_len < 2)
return list;
sp->list_len= list_len;
sp->return_point= 2;
recursion_point:
if (sp->list_len < 4)
{
LS_LIST_ITEM *e1, *e2;
sorted_list= list;
e1= LS_NEXT(sorted_list);
list_end= LS_NEXT(e1);
if (LS_COMPARE_FUNC_CALL(sorted_list, e1))
{
sorted_list= e1;
e1= list;
}
if (sp->list_len == 2)
{
LS_SET_NEXT(sorted_list, e1);
LS_SET_NEXT(e1, NULL);
goto exit_point;
}
e2= list_end;
list_end= LS_NEXT(e2);
if (LS_COMPARE_FUNC_CALL(e1, e2))
{
{
LS_LIST_ITEM *tmp_e= e1;
e1= e2;
e2= tmp_e;
}
if (LS_COMPARE_FUNC_CALL(sorted_list, e1))
{
LS_LIST_ITEM *tmp_e= sorted_list;
sorted_list= e1;
e1= tmp_e;
}
}
LS_SET_NEXT(sorted_list, e1);
LS_SET_NEXT(e1, e2);
LS_SET_NEXT(e2, NULL);
goto exit_point;
}
{
register struct LS_STRUCT_NAME *sp0= sp++;
sp->list_len= sp0->list_len >> 1;
sp0->list_len-= sp->list_len;
sp->return_point= 0;
}
goto recursion_point;
return_point0:
sp->list1= sorted_list;
{
register struct LS_STRUCT_NAME *sp0= sp++;
list= list_end;
sp->list_len= sp0->list_len;
sp->return_point= 1;
}
goto recursion_point;
return_point1:
{
register LS_LIST_ITEM **hook= &sorted_list;
register LS_LIST_ITEM *list1= sp->list1;
register LS_LIST_ITEM *list2= sorted_list;
if (LS_COMPARE_FUNC_CALL(list1, list2))
{
LS_LIST_ITEM *tmp_e= list2;
list2= list1;
list1= tmp_e;
}
for (;;)
{
*hook= list1;
do
{
if (!(list1= *(hook= LS_P_NEXT(list1))))
{
*hook= list2;
goto exit_point;
}
} while (LS_COMPARE_FUNC_CALL(list2, list1));
*hook= list2;
do
{
if (!(list2= *(hook= LS_P_NEXT(list2))))
{
*hook= list1;
goto exit_point;
}
} while (LS_COMPARE_FUNC_CALL(list1, list2));
}
}
exit_point:
switch ((sp--)->return_point)
{
case 0: goto return_point0;
case 1: goto return_point1;
default:;
}
return sorted_list;
}
#undef LS_LIST_ITEM
#undef LS_NEXT
#undef LS_SET_NEXT
#undef LS_P_NEXT
#undef LS_NAME
#undef LS_STRUCT_NAME
#undef LS_SCOPE
#undef LS_COMPARE_FUNC_DECL
#undef LS_COMPARE_FUNC_CALL
This diff is collapsed.
/* Copyright (C) 2002-2006 MySQL AB
/* Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
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
......@@ -10,14 +10,19 @@
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 */
along with this program; if not, write to the Free Software Foundation,
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
#ifndef _spatial_h
#define _spatial_h
#include "sql_string.h" /* String, LEX_STRING */
#include <my_compiler.h>
#ifdef HAVE_SPATIAL
#include "gcalc_tools.h"
const uint SRID_SIZE= 4;
const uint SIZEOF_STORED_DOUBLE= 8;
const uint POINT_DATA_SIZE= SIZEOF_STORED_DOUBLE*2;
......@@ -242,10 +247,13 @@ class Geometry
virtual const Class_info *get_class_info() const=0;
virtual uint32 get_data_size() const=0;
virtual bool init_from_wkt(Gis_read_stream *trs, String *wkb)=0;
/* returns the length of the wkb that was read */
virtual uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo,
String *res)=0;
virtual uint init_from_opresult(String *bin,
const char *opres, uint32 n_shapes=1)
{ return init_from_wkb(opres + 4, UINT_MAX32, wkb_ndr, bin) + 4; }
virtual bool get_data_as_wkt(String *txt, const char **end) const=0;
virtual bool get_mbr(MBR *mbr, const char **end) const=0;
virtual bool dimension(uint32 *dim, const char **end) const=0;
......@@ -264,16 +272,20 @@ class Geometry
virtual int point_n(uint32 num, String *result) const { return -1; }
virtual int interior_ring_n(uint32 num, String *result) const { return -1; }
virtual int geometry_n(uint32 num, String *result) const { return -1; }
virtual int store_shapes(Gcalc_shape_transporter *trn) const=0;
public:
static Geometry *create_by_typeid(Geometry_buffer *buffer, int type_id);
static Geometry *construct(Geometry_buffer *buffer,
const char *data, uint32 data_len);
static Geometry *create_from_wkt(Geometry_buffer *buffer,
Gis_read_stream *trs, String *wkt,
bool init_stream=1);
static Geometry *create_from_wkb(Geometry_buffer *buffer, const char *wkb,
uint32 len, String *res);
static Geometry *create_from_wkb(Geometry_buffer *buffer,
const char *wkb, uint32 len, String *res);
static int create_from_opresult(Geometry_buffer *g_buf,
String *res, Gcalc_result_receiver &rr);
int as_wkt(String *wkt, const char **end)
{
uint32 len= (uint) get_class_info()->m_name.length;
......@@ -369,6 +381,7 @@ class Gis_point: public Geometry
*end= 0; /* No default end */
return 0;
}
int store_shapes(Gcalc_shape_transporter *trn) const;
const Class_info *get_class_info() const;
};
......@@ -397,6 +410,7 @@ class Gis_line_string: public Geometry
*end= 0; /* No default end */
return 0;
}
int store_shapes(Gcalc_shape_transporter *trn) const;
const Class_info *get_class_info() const;
};
......@@ -411,6 +425,13 @@ class Gis_polygon: public Geometry
uint32 get_data_size() const;
bool init_from_wkt(Gis_read_stream *trs, String *wkb);
uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res);
uint priv_init_from_opresult(String *bin, const char *opres,
uint32 n_shapes, uint32 *poly_shapes);
uint init_from_opresult(String *bin, const char *opres, uint32 n_shapes)
{
uint32 foo;
return priv_init_from_opresult(bin, opres, n_shapes, &foo);
}
bool get_data_as_wkt(String *txt, const char **end) const;
bool get_mbr(MBR *mbr, const char **end) const;
int area(double *ar, const char **end) const;
......@@ -425,6 +446,7 @@ class Gis_polygon: public Geometry
*end= 0; /* No default end */
return 0;
}
int store_shapes(Gcalc_shape_transporter *trn) const;
const Class_info *get_class_info() const;
};
......@@ -439,6 +461,7 @@ class Gis_multi_point: public Geometry
uint32 get_data_size() const;
bool init_from_wkt(Gis_read_stream *trs, String *wkb);
uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res);
uint init_from_opresult(String *bin, const char *opres, uint32 n_shapes);
bool get_data_as_wkt(String *txt, const char **end) const;
bool get_mbr(MBR *mbr, const char **end) const;
int num_geometries(uint32 *num) const;
......@@ -449,6 +472,7 @@ class Gis_multi_point: public Geometry
*end= 0; /* No default end */
return 0;
}
int store_shapes(Gcalc_shape_transporter *trn) const;
const Class_info *get_class_info() const;
};
......@@ -463,6 +487,7 @@ class Gis_multi_line_string: public Geometry
uint32 get_data_size() const;
bool init_from_wkt(Gis_read_stream *trs, String *wkb);
uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res);
uint init_from_opresult(String *bin, const char *opres, uint32 n_shapes);
bool get_data_as_wkt(String *txt, const char **end) const;
bool get_mbr(MBR *mbr, const char **end) const;
int num_geometries(uint32 *num) const;
......@@ -475,6 +500,7 @@ class Gis_multi_line_string: public Geometry
*end= 0; /* No default end */
return 0;
}
int store_shapes(Gcalc_shape_transporter *trn) const;
const Class_info *get_class_info() const;
};
......@@ -501,7 +527,9 @@ class Gis_multi_polygon: public Geometry
*end= 0; /* No default end */
return 0;
}
int store_shapes(Gcalc_shape_transporter *trn) const;
const Class_info *get_class_info() const;
uint init_from_opresult(String *bin, const char *opres, uint32 n_shapes);
};
......@@ -515,11 +543,13 @@ class Gis_geometry_collection: public Geometry
uint32 get_data_size() const;
bool init_from_wkt(Gis_read_stream *trs, String *wkb);
uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res);
uint init_from_opresult(String *bin, const char *opres, uint32 n_shapes);
bool get_data_as_wkt(String *txt, const char **end) const;
bool get_mbr(MBR *mbr, const char **end) const;
int num_geometries(uint32 *num) const;
int geometry_n(uint32 num, String *result) const;
bool dimension(uint32 *dim, const char **end) const;
int store_shapes(Gcalc_shape_transporter *trn) const;
const Class_info *get_class_info() const;
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment