65 if (
sizeof(
off_t) > 4) {
100 _(
"Topology file must be written before spatial index file"));
109 _(
"Topology file must be written before spatial index file"));
234 G_debug(3,
"spidx offset node = %lu line = %lu, area = %lu isle = %lu",
245 G_debug(1,
"spidx body offset %lu", length);
264 unsigned char buf[6];
273 ptr->
version.spidx.major = buf[0];
274 ptr->
version.spidx.minor = buf[1];
275 ptr->
version.spidx.back_major = buf[2];
276 ptr->
version.spidx.back_minor = buf[3];
282 "Spidx header: file version %d.%d , supported from GRASS version %d.%d",
286 G_debug(2,
" byte order %d", byte_order);
299 G_debug(1,
"Spatial index format version %d.%d",
301 G_fatal_error(
_(
"This version of GRASS (%d.%d) is too old to read "
302 "this spatial index format."
303 " Try to rebuild topology or upgrade GRASS to at "
304 "least version %d."),
310 G_warning(
_(
"Your GRASS version does not fully support "
311 "spatial index format %d.%d of the vector."
312 " Consider to rebuild topology or upgrade GRASS."),
321 "supported by this release."
322 " Please rebuild topology."),
330 "GRASS version does not support LFS. "
331 "Please get a GRASS version with LFS support.");
529 fprintf(fp,
" id = %d ",
b->child.id);
531 fprintf(fp,
" %f %f %f %f %f %f\n",
r->boundary[0],
r->boundary[1],
532 r->boundary[2],
r->boundary[3],
r->boundary[4],
r->boundary[5]);
535 rtree_dump_node(fp,
b->child.ptr, with_z);
562 if (n->
branch[i].child.ptr) {
564 rtree_dump_branch(fp, &n->
branch[i], with_z, n->
level);
569 if (n->
branch[i].child.id) {
571 rtree_dump_branch(fp, &n->
branch[i], with_z, n->
level);
578static int rtree_dump_node_file(
FILE *,
off_t,
int,
struct RTree *);
591 int level,
struct RTree *
t)
598 fprintf(fp,
" id = %d ",
b->child.id);
600 fprintf(fp,
" %f %f %f %f %f %f\n",
r->boundary[0],
r->boundary[1],
601 r->boundary[2],
r->boundary[3],
r->boundary[4],
r->boundary[5]);
604 rtree_dump_node_file(fp,
b->child.pos, with_z,
t);
619int rtree_dump_node_file(
FILE *fp,
off_t pos,
int with_z,
struct RTree *
t)
638 if (n->
branch[i].child.pos >= 0) {
640 rtree_dump_branch_file(fp, &(n->
branch[i]), with_z, n->
level,
646 if (n->
branch[i].child.id) {
648 rtree_dump_branch_file(fp, &(n->
branch[i]), with_z, n->
level,
690 struct RTree *
t,
int off_t_size)
710 s[top].branch_id = i = 0;
720 if (s[top].sn ==
NULL)
727 if (s[top].sn->level > 0) {
728 for (i = s[top].branch_id; i <
t->nodecard; i++) {
731 s[top++].branch_id = i + 1;
732 s[top].sn = n->
branch[i].child.ptr;
733 s[top].branch_id = 0;
740 s[top].branch_id =
t->nodecard;
747 "Wrong node position (%" PRId64
748 ") in file (should be %" PRId64 ").",
754 maxcard = s[top].sn->level ?
t->nodecard :
t->leafcard;
759 if (s[top].sn->level == 0)
760 s[top].pos[
j] = (
off_t)s[top].sn->branch[
j].child.id;
796 struct RTree *
t,
int off_t_size)
802 static struct spidxstack *s =
NULL;
810 s[i].sn.branch[
j].rect.boundary =
830 s[top].branch_id = i = 0;
845 if (s[top].sn.level > 0) {
846 for (i = s[top].branch_id; i <
t->nodecard; i++) {
848 if (n->
branch[i].child.pos >= 0) {
849 s[top++].branch_id = i + 1;
851 s[top].branch_id = 0;
858 s[top].branch_id =
t->nodecard;
865 "Wrong node position (%" PRId64
866 ") in file (should be %" PRId64 ").",
872 maxcard = s[top].sn.level ?
t->nodecard :
t->leafcard;
877 if (s[top].sn.level == 0)
878 s[top].pos[
j] = (
off_t)s[top].sn.branch[
j].child.id;
903 struct RTree *
t,
int off_t_size)
906 return rtree_write_from_file(fp,
startpos,
t, off_t_size);
908 return rtree_write_from_memory(fp,
startpos,
t, off_t_size);
922static void rtree_load_to_memory(
struct gvfile *fp,
off_t rootpos,
923 struct RTree *
t,
int off_t_size)
927 struct spidxstack *last;
928 static struct spidxstack *s =
NULL;
936 s[i].sn.branch[
j].rect.boundary =
952 maxcard = s[top].sn.level ?
t->nodecard :
t->leafcard;
957 if (s[top].sn.level == 0) {
958 s[top].sn.branch[
j].child.id = (
int)s[top].pos[
j];
961 s[top].sn.branch[
j].child.ptr =
NULL;
965 s[top].branch_id = i = 0;
976 if (s[top].sn.level > 0) {
977 for (i = s[top].branch_id; i <
t->nodecard; i++) {
978 if (s[top].pos[i] > 0) {
979 s[top++].branch_id = i + 1;
984 maxcard = s[top].sn.level ?
t->nodecard :
t->leafcard;
993 if (s[top].sn.level == 0) {
994 s[top].sn.branch[
j].child.id = (
int)s[top].pos[
j];
997 s[top].sn.branch[
j].child.ptr =
NULL;
1000 s[top].branch_id = 0;
1004 else if (last->pos[i] < 0)
1009 s[top].branch_id =
t->nodecard;
1026 s[top].sn.branch[s[top].branch_id - 1].child.ptr =
newnode;
1045static void rtree_load_to_file(
struct gvfile *fp,
off_t rootpos,
1046 struct RTree *
t,
int off_t_size)
1050 struct spidxstack *last;
1051 static struct spidxstack *s =
NULL;
1059 s[i].sn.branch[
j].rect.boundary =
1075 maxcard =
t->rootlevel ?
t->nodecard :
t->leafcard;
1080 if (s[top].sn.level == 0) {
1081 s[top].sn.branch[
j].child.id = (
int)s[top].pos[
j];
1084 s[top].sn.branch[
j].child.pos = -1;
1088 s[top].branch_id = i = 0;
1099 if (s[top].sn.level > 0) {
1100 for (i = s[top].branch_id; i <
t->nodecard; i++) {
1101 if (s[top].pos[i] > 0) {
1102 s[top++].branch_id = i + 1;
1107 maxcard = s[top].sn.level ?
t->nodecard :
t->leafcard;
1116 if (s[top].sn.level == 0) {
1117 s[top].sn.branch[
j].child.id = (
int)s[top].pos[
j];
1120 s[top].sn.branch[
j].child.pos = -1;
1123 s[top].branch_id = 0;
1127 else if (last->pos[i] < 0)
1132 s[top].branch_id =
t->nodecard;
1148 s[top].sn.branch[s[top].branch_id - 1].child.pos =
newnode_pos;
1156static void rtree_load_from_sidx(
struct gvfile *fp,
off_t rootpos,
1157 struct RTree *
t,
int off_t_size)
1160 rtree_load_to_file(fp, rootpos,
t, off_t_size);
1162 rtree_load_to_memory(fp, rootpos,
t, off_t_size);
1183 Plus->Node_spidx_offset = rtree_write_to_sidx(
1187 Plus->Line_spidx_offset = rtree_write_to_sidx(
1191 Plus->Area_spidx_offset = rtree_write_to_sidx(
1195 Plus->Isle_spidx_offset = rtree_write_to_sidx(
1221 G_debug(1,
"dig_read_spindx()");
1232 rtree_load_from_sidx(fp,
Plus->Node_spidx_offset,
Plus->Node_spidx,
1233 Plus->spidx_port.off_t_size);
1236 rtree_load_from_sidx(fp,
Plus->Line_spidx_offset,
Plus->Line_spidx,
1237 Plus->spidx_port.off_t_size);
1240 rtree_load_from_sidx(fp,
Plus->Area_spidx_offset,
Plus->Area_spidx,
1241 Plus->spidx_port.off_t_size);
1244 rtree_load_from_sidx(fp,
Plus->Isle_spidx_offset,
Plus->Isle_spidx,
1245 Plus->spidx_port.off_t_size);
1266 if (
Plus->Node_spidx->fd < 0)
1267 rtree_dump_node(fp,
Plus->Node_spidx->root,
Plus->with_z);
1270 rtree_dump_node_file(fp,
Plus->Node_spidx->rootpos,
Plus->with_z,
1275 if (
Plus->Line_spidx->fd < 0)
1276 rtree_dump_node(fp,
Plus->Line_spidx->root,
Plus->with_z);
1279 rtree_dump_node_file(fp,
Plus->Line_spidx->rootpos,
Plus->with_z,
1284 if (
Plus->Area_spidx->fd < 0)
1285 rtree_dump_node(fp,
Plus->Area_spidx->root,
Plus->with_z);
1288 rtree_dump_node_file(fp,
Plus->Area_spidx->rootpos,
Plus->with_z,
1293 if (
Plus->Isle_spidx->fd < 0)
1294 rtree_dump_node(fp,
Plus->Isle_spidx->root,
Plus->with_z);
1297 rtree_dump_node_file(fp,
Plus->Isle_spidx->rootpos,
Plus->with_z,
1316 maxcard = nb->
n.level ?
t->nodecard :
t->leafcard;
1317 for (i = 0; i <
maxcard; i++) {
1321 if (nb->
n.level == 0) {
1322 nb->
n.branch[i].child.id = (
int)pos;
1325 nb->
n.branch[i].child.pos = pos;
1345 which =
t->used[
level][i];
1357 t->used[
level][0] = which;
1363 t->used[
level][0] = which;
1367 return &(
t->nb[
level][which].n);
1403 s[top].sn = rtree_get_node(
t->rootpos,
t->rootlevel,
t,
Plus);
1409 maxcard =
t->rootlevel ?
t->nodecard :
t->leafcard;
1414 Plus->spidx_port.off_t_size);
1416 if (s[top].sn.level == 0) {
1417 s[top].sn.branch[
j].child.id = (
int)s[top].pos[
j];
1420 s[top].sn.branch[
j].child.pos = s[top].pos[
j];
1425 s[top].branch_id = i = 0;
1428 level = s[top].sn->level;
1431 for (i = s[top].branch_id; i <
t->nodecard; i++) {
1432 lastpos = s[top].sn->branch[i].child.pos;
1435 s[top++].branch_id = i + 1;
1436 s[top].sn = rtree_get_node(
lastpos, level - 1,
t,
Plus);
1445 maxcard = s[top].sn.level ?
t->nodecard :
t->leafcard;
1451 Plus->spidx_port.off_t_size);
1452 if (s[top].sn.level == 0) {
1453 s[top].sn.branch[
j].child.id = (
int)s[top].pos[
j];
1456 s[top].sn.branch[
j].child.pos = s[top].pos[
j];
1460 s[top].branch_id = 0;
1467 s[top].branch_id =
t->nodecard;
1472 for (i = 0; i <
t->leafcard; i++) {
1473 if (s[top].sn->branch[i].child.id &&
1477 if (!
shcb((
int)s[top].sn->branch[i].child.id,
1478 &s[top].sn->branch[i].rect,
cbarg)) {
void G_free(void *)
Free allocated memory.
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
void G_warning(const char *,...) __attribute__((format(printf
void G_fseek(FILE *, off_t, int)
Change the file position of the stream.
off_t G_ftell(FILE *)
Get the current file position of the stream.
int G_debug(int, const char *,...) __attribute__((format(printf
#define GV_SIDX_VER_MINOR
#define PORT_DOUBLE
Sizes of types used in portable format (different names used in Vlib/ and diglib/ for the same thing)
#define GV_SIDX_VER_MAJOR
#define GV_SIDX_EARLIEST_MAJOR
#define GV_SIDX_EARLIEST_MINOR
int dig__fread_port_D(double *, size_t, struct gvfile *)
Read doubles from the Portable Vector Format.
int dig__fread_port_O(off_t *, size_t, struct gvfile *, size_t)
Read off_ts from the Portable Vector Format.
int dig__fwrite_port_C(const char *, size_t, struct gvfile *)
Write chars to the Portable Vector Format.
void dig_init_portable(struct Port_info *, int)
Set Port_info structure to byte order of file.
int dig__fread_port_L(long *, size_t, struct gvfile *)
Read longs from the Portable Vector Format.
int dig__fwrite_port_L(const long *, size_t, struct gvfile *)
Write longs to the Portable Vector Format.
int dig__fwrite_port_I(const int *, size_t, struct gvfile *)
Write integers to the Portable Vector Format.
off_t dig_ftell(struct gvfile *file)
Get struct gvfile position.
int dig_set_cur_port(struct Port_info *)
Set current Port_info structure.
int dig__fwrite_port_D(const double *, size_t, struct gvfile *)
Write doubles to the Portable Vector Format.
void dig_rewind(struct gvfile *file)
Rewind file position.
int dig__fread_port_C(char *, size_t, struct gvfile *)
Read chars from the Portable Vector Format.
int dig__fread_port_I(int *, size_t, struct gvfile *)
Read integers from the Portable Vector Format.
int dig_fseek(struct gvfile *file, off_t offset, int whence)
Set struct gvfile position.
int dig_fflush(struct gvfile *file)
Flush struct gvfile.
void dig_spidx_free(struct Plus_head *)
Free spatial index (nodes, lines, areas, isles)
int dig_spidx_init(struct Plus_head *)
Initit spatial index (nodes, lines, areas, isles)
int dig__fwrite_port_O(const off_t *, size_t, struct gvfile *, size_t)
Write off_ts to the Portable Vector Format.
off_t RTreeGetNodePos(struct RTree *t)
size_t RTreeReadNode(struct RTree_Node *n, off_t nodepos, struct RTree *t)
void RTreeFlushBuffer(struct RTree *t)
size_t RTreeWriteNode(struct RTree_Node *n, struct RTree *t)
#define assert(condition)
void RTreeCopyNode(struct RTree_Node *n1, struct RTree_Node *n2, struct RTree *t)
struct RTree_Node * RTreeAllocNode(struct RTree *t, int level)
int RTreeOverlap(struct RTree_Rect *r, struct RTree_Rect *s, struct RTree *t)
int SearchHitCallback(int id, const struct RTree_Rect *rect, void *arg)
int dig_Wr_spidx_head(struct gvfile *fp, struct Plus_head *ptr)
Write spatial index header to file.
int dig_Wr_spidx(struct gvfile *fp, struct Plus_head *Plus)
Write spatial index to file.
int dig_Rd_spidx(struct gvfile *fp, struct Plus_head *Plus)
Read spatial index from sidx file Only needed when old vector is opened in update mode.
int dig_Rd_spidx_head(struct gvfile *fp, struct Plus_head *ptr)
Read spatial index header from sidx file.
int dig_dump_spidx(FILE *fp, const struct Plus_head *Plus)
Dump spatial index.
int rtree_search(struct RTree *t, struct RTree_Rect *r, SearchHitCallback shcb, void *cbarg, struct Plus_head *Plus)
Search spatial index file Can't use regular RTreeSearch() here because sidx must be read with dig__fr...
Basic topology-related info.
off_t Area_spidx_offset
Offset of areas in sidx file.
off_t coor_size
Size of coor file.
off_t Isle_spidx_offset
Offset of isles in sidx file.
struct Plus_head::@9 version
Backward compatibility version info.
off_t Hole_spidx_offset
Offset of holes in sidx file.
struct RTree * Isle_spidx
Isles spatial index.
off_t Face_spidx_offset
Offset of faces in sidx file.
int off_t_size
Offset size.
struct RTree * Area_spidx
Area spatial index.
off_t Volume_spidx_offset
Offset of volumes in sidx file.
struct RTree * Line_spidx
Line spatial index.
int spidx_with_z
2D/3D spatial index
long spidx_head_size
Spatial index header size.
struct Port_info spidx_port
Portability information for spatial index.
off_t Line_spidx_offset
Offset of lines in sidx file.
struct RTree * Node_spidx
Node spatial index.
off_t Node_spidx_offset
Offset of nodes in sidx file.
struct RTree_Branch * branch
FILE * file
File descriptor.
#define MAXLEVEL
Maximum verbosity level.
#define GRASS_VERSION_MINOR
#define GRASS_VERSION_MAJOR