63 if (
sizeof(
off_t) > 4) {
98 _(
"Topology file must be written before spatial index file"));
107 _(
"Topology file must be written before spatial index file"));
232 G_debug(3,
"spidx offset node = %lu line = %lu, area = %lu isle = %lu",
243 G_debug(1,
"spidx body offset %lu", length);
262 unsigned char buf[6];
271 ptr->
version.spidx.major = buf[0];
272 ptr->
version.spidx.minor = buf[1];
273 ptr->
version.spidx.back_major = buf[2];
274 ptr->
version.spidx.back_minor = buf[3];
280 "Spidx header: file version %d.%d , supported from GRASS version %d.%d",
284 G_debug(2,
" byte order %d", byte_order);
297 G_debug(1,
"Spatial index format version %d.%d",
299 G_fatal_error(
_(
"This version of GRASS (%d.%d) is too old to read "
300 "this spatial index format."
301 " Try to rebuild topology or upgrade GRASS to at "
302 "least version %d."),
308 G_warning(
_(
"Your GRASS version does not fully support "
309 "spatial index format %d.%d of the vector."
310 " Consider to rebuild topology or upgrade GRASS."),
319 "supported by this release."
320 " Please rebuild topology."),
328 "GRASS version does not support LFS. "
329 "Please get a GRASS version with LFS support.");
527 fprintf(fp,
" id = %d ",
b->child.id);
529 fprintf(fp,
" %f %f %f %f %f %f\n",
r->boundary[0],
r->boundary[1],
530 r->boundary[2],
r->boundary[3],
r->boundary[4],
r->boundary[5]);
533 rtree_dump_node(fp,
b->child.ptr, with_z);
560 if (n->
branch[i].child.ptr) {
562 rtree_dump_branch(fp, &n->
branch[i], with_z, n->
level);
567 if (n->
branch[i].child.id) {
569 rtree_dump_branch(fp, &n->
branch[i], with_z, n->
level);
576static int rtree_dump_node_file(
FILE *,
off_t,
int,
struct RTree *);
589 int level,
struct RTree *
t)
596 fprintf(fp,
" id = %d ",
b->child.id);
598 fprintf(fp,
" %f %f %f %f %f %f\n",
r->boundary[0],
r->boundary[1],
599 r->boundary[2],
r->boundary[3],
r->boundary[4],
r->boundary[5]);
602 rtree_dump_node_file(fp,
b->child.pos, with_z,
t);
617int rtree_dump_node_file(
FILE *fp,
off_t pos,
int with_z,
struct RTree *
t)
636 if (n->
branch[i].child.pos >= 0) {
638 rtree_dump_branch_file(fp, &(n->
branch[i]), with_z, n->
level,
644 if (n->
branch[i].child.id) {
646 rtree_dump_branch_file(fp, &(n->
branch[i]), with_z, n->
level,
688 struct RTree *
t,
int off_t_size)
708 s[top].branch_id = i = 0;
718 if (s[top].sn ==
NULL)
725 if (s[top].sn->level > 0) {
726 for (i = s[top].branch_id; i <
t->nodecard; i++) {
729 s[top++].branch_id = i + 1;
730 s[top].sn = n->
branch[i].child.ptr;
731 s[top].branch_id = 0;
738 s[top].branch_id =
t->nodecard;
745 "Wrong node position (%" PRId64
746 ") in file (should be %" PRId64 ").",
752 maxcard = s[top].sn->level ?
t->nodecard :
t->leafcard;
757 if (s[top].sn->level == 0)
758 s[top].pos[
j] = (
off_t)s[top].sn->branch[
j].child.id;
794 struct RTree *
t,
int off_t_size)
800 static struct spidxstack *s =
NULL;
808 s[i].sn.branch[
j].rect.boundary =
828 s[top].branch_id = i = 0;
843 if (s[top].sn.level > 0) {
844 for (i = s[top].branch_id; i <
t->nodecard; i++) {
846 if (n->
branch[i].child.pos >= 0) {
847 s[top++].branch_id = i + 1;
849 s[top].branch_id = 0;
856 s[top].branch_id =
t->nodecard;
863 "Wrong node position (%" PRId64
864 ") in file (should be %" PRId64 ").",
870 maxcard = s[top].sn.level ?
t->nodecard :
t->leafcard;
875 if (s[top].sn.level == 0)
876 s[top].pos[
j] = (
off_t)s[top].sn.branch[
j].child.id;
901 struct RTree *
t,
int off_t_size)
904 return rtree_write_from_file(fp,
startpos,
t, off_t_size);
906 return rtree_write_from_memory(fp,
startpos,
t, off_t_size);
920static void rtree_load_to_memory(
struct gvfile *fp,
off_t rootpos,
921 struct RTree *
t,
int off_t_size)
925 struct spidxstack *last;
926 static struct spidxstack *s =
NULL;
934 s[i].sn.branch[
j].rect.boundary =
950 maxcard = s[top].sn.level ?
t->nodecard :
t->leafcard;
955 if (s[top].sn.level == 0) {
956 s[top].sn.branch[
j].child.id = (
int)s[top].pos[
j];
959 s[top].sn.branch[
j].child.ptr =
NULL;
963 s[top].branch_id = i = 0;
974 if (s[top].sn.level > 0) {
975 for (i = s[top].branch_id; i <
t->nodecard; i++) {
976 if (s[top].pos[i] > 0) {
977 s[top++].branch_id = i + 1;
982 maxcard = s[top].sn.level ?
t->nodecard :
t->leafcard;
991 if (s[top].sn.level == 0) {
992 s[top].sn.branch[
j].child.id = (
int)s[top].pos[
j];
995 s[top].sn.branch[
j].child.ptr =
NULL;
998 s[top].branch_id = 0;
1002 else if (last->pos[i] < 0)
1007 s[top].branch_id =
t->nodecard;
1024 s[top].sn.branch[s[top].branch_id - 1].child.ptr =
newnode;
1043static void rtree_load_to_file(
struct gvfile *fp,
off_t rootpos,
1044 struct RTree *
t,
int off_t_size)
1048 struct spidxstack *last;
1049 static struct spidxstack *s =
NULL;
1057 s[i].sn.branch[
j].rect.boundary =
1073 maxcard =
t->rootlevel ?
t->nodecard :
t->leafcard;
1078 if (s[top].sn.level == 0) {
1079 s[top].sn.branch[
j].child.id = (
int)s[top].pos[
j];
1082 s[top].sn.branch[
j].child.pos = -1;
1086 s[top].branch_id = i = 0;
1097 if (s[top].sn.level > 0) {
1098 for (i = s[top].branch_id; i <
t->nodecard; i++) {
1099 if (s[top].pos[i] > 0) {
1100 s[top++].branch_id = i + 1;
1105 maxcard = s[top].sn.level ?
t->nodecard :
t->leafcard;
1114 if (s[top].sn.level == 0) {
1115 s[top].sn.branch[
j].child.id = (
int)s[top].pos[
j];
1118 s[top].sn.branch[
j].child.pos = -1;
1121 s[top].branch_id = 0;
1125 else if (last->pos[i] < 0)
1130 s[top].branch_id =
t->nodecard;
1146 s[top].sn.branch[s[top].branch_id - 1].child.pos =
newnode_pos;
1154static void rtree_load_from_sidx(
struct gvfile *fp,
off_t rootpos,
1155 struct RTree *
t,
int off_t_size)
1158 rtree_load_to_file(fp, rootpos,
t, off_t_size);
1160 rtree_load_to_memory(fp, rootpos,
t, off_t_size);
1181 Plus->Node_spidx_offset = rtree_write_to_sidx(
1185 Plus->Line_spidx_offset = rtree_write_to_sidx(
1189 Plus->Area_spidx_offset = rtree_write_to_sidx(
1193 Plus->Isle_spidx_offset = rtree_write_to_sidx(
1219 G_debug(1,
"dig_read_spindx()");
1230 rtree_load_from_sidx(fp,
Plus->Node_spidx_offset,
Plus->Node_spidx,
1231 Plus->spidx_port.off_t_size);
1234 rtree_load_from_sidx(fp,
Plus->Line_spidx_offset,
Plus->Line_spidx,
1235 Plus->spidx_port.off_t_size);
1238 rtree_load_from_sidx(fp,
Plus->Area_spidx_offset,
Plus->Area_spidx,
1239 Plus->spidx_port.off_t_size);
1242 rtree_load_from_sidx(fp,
Plus->Isle_spidx_offset,
Plus->Isle_spidx,
1243 Plus->spidx_port.off_t_size);
1264 if (
Plus->Node_spidx->fd < 0)
1265 rtree_dump_node(fp,
Plus->Node_spidx->root,
Plus->with_z);
1268 rtree_dump_node_file(fp,
Plus->Node_spidx->rootpos,
Plus->with_z,
1273 if (
Plus->Line_spidx->fd < 0)
1274 rtree_dump_node(fp,
Plus->Line_spidx->root,
Plus->with_z);
1277 rtree_dump_node_file(fp,
Plus->Line_spidx->rootpos,
Plus->with_z,
1282 if (
Plus->Area_spidx->fd < 0)
1283 rtree_dump_node(fp,
Plus->Area_spidx->root,
Plus->with_z);
1286 rtree_dump_node_file(fp,
Plus->Area_spidx->rootpos,
Plus->with_z,
1291 if (
Plus->Isle_spidx->fd < 0)
1292 rtree_dump_node(fp,
Plus->Isle_spidx->root,
Plus->with_z);
1295 rtree_dump_node_file(fp,
Plus->Isle_spidx->rootpos,
Plus->with_z,
1314 maxcard = nb->
n.level ?
t->nodecard :
t->leafcard;
1315 for (i = 0; i <
maxcard; i++) {
1319 if (nb->
n.level == 0) {
1320 nb->
n.branch[i].child.id = (
int)pos;
1323 nb->
n.branch[i].child.pos = pos;
1343 which =
t->used[
level][i];
1355 t->used[
level][0] = which;
1361 t->used[
level][0] = which;
1365 return &(
t->nb[
level][which].n);
1401 s[top].sn = rtree_get_node(
t->rootpos,
t->rootlevel,
t,
Plus);
1407 maxcard =
t->rootlevel ?
t->nodecard :
t->leafcard;
1412 Plus->spidx_port.off_t_size);
1414 if (s[top].sn.level == 0) {
1415 s[top].sn.branch[
j].child.id = (
int)s[top].pos[
j];
1418 s[top].sn.branch[
j].child.pos = s[top].pos[
j];
1423 s[top].branch_id = i = 0;
1426 level = s[top].sn->level;
1429 for (i = s[top].branch_id; i <
t->nodecard; i++) {
1430 lastpos = s[top].sn->branch[i].child.pos;
1433 s[top++].branch_id = i + 1;
1434 s[top].sn = rtree_get_node(
lastpos, level - 1,
t,
Plus);
1443 maxcard = s[top].sn.level ?
t->nodecard :
t->leafcard;
1449 Plus->spidx_port.off_t_size);
1450 if (s[top].sn.level == 0) {
1451 s[top].sn.branch[
j].child.id = (
int)s[top].pos[
j];
1454 s[top].sn.branch[
j].child.pos = s[top].pos[
j];
1458 s[top].branch_id = 0;
1465 s[top].branch_id =
t->nodecard;
1470 for (i = 0; i <
t->leafcard; i++) {
1471 if (s[top].sn->branch[i].child.id &&
1475 if (!
shcb((
int)s[top].sn->branch[i].child.id,
1476 &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