18 #include <sys/types.h> 66 if (
sizeof(off_t) > 4) {
100 G_fatal_error(
_(
"Topology file must be written before spatial index file"));
108 G_fatal_error(
_(
"Topology file must be written before spatial index file"));
240 G_debug(3,
"spidx offset node = %lu line = %lu, area = %lu isle = %lu",
251 G_debug(1,
"spidx body offset %lu", length);
270 unsigned char buf[6];
287 "Spidx header: file version %d.%d , supported from GRASS version %d.%d",
291 G_debug(2,
" byte order %d", byte_order);
301 G_debug(1,
"Spatial index format version %d.%d",
304 (
_(
"This version of GRASS (%d.%d) is too old to read this spatial index format." 305 " Try to rebuild topology or upgrade GRASS to at 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."),
320 "supported by this release." 321 " Please rebuild topology."),
329 "GRASS version does not support LFS. " 330 "Please get a GRASS version with LFS support.");
515 static int rtree_dump_node(FILE *,
struct RTree_Node *n,
int);
527 static int rtree_dump_branch(FILE * fp,
struct RTree_Branch *
b,
int with_z,
535 fprintf(fp,
" id = %d ", b->
child.
id);
541 rtree_dump_node(fp, b->
child.
ptr, with_z);
555 int rtree_dump_node(FILE * fp,
struct RTree_Node *n,
int with_z)
564 fprintf(fp,
"Node level=%d count=%d\n", n->
level, n->
count);
569 fprintf(fp,
" Branch %d", i);
570 rtree_dump_branch(fp, &n->
branch[i], with_z, n->
level);
576 fprintf(fp,
" Branch %d", i);
577 rtree_dump_branch(fp, &n->
branch[i], with_z, n->
level);
584 static int rtree_dump_node_file(FILE *, off_t,
int,
struct RTree *);
596 static int rtree_dump_branch_file(FILE * fp,
struct RTree_Branch *b,
int with_z,
597 int level,
struct RTree *
t)
604 fprintf(fp,
" id = %d ", b->
child.
id);
610 rtree_dump_node_file(fp, b->
child.
pos, with_z, t);
625 int rtree_dump_node_file(FILE * fp, off_t pos,
int with_z,
struct RTree *t)
640 fprintf(fp,
"Node level=%d count=%d\n", n->
level, n->
count);
645 fprintf(fp,
" Branch %d", i);
646 rtree_dump_branch_file(fp, &(n->
branch[i]), with_z, n->
level, t);
652 fprintf(fp,
" Branch %d", i);
653 rtree_dump_branch_file(fp, &(n->
branch[i]), with_z, n->
level, t);
695 static off_t rtree_write_from_memory(
struct gvfile *fp, off_t startpos,
696 struct RTree *t,
int off_t_size)
698 off_t nextfreepos = startpos;
699 int sidx_nodesize, sidx_leafsize;
701 int i, j, writeout, maxcard;
716 s[top].branch_id = i = 0;
726 if (s[top].sn ==
NULL)
733 if (s[top].sn->level > 0) {
734 for (i = s[top].branch_id; i < t->
nodecard; i++) {
737 s[top++].branch_id = i + 1;
739 s[top].branch_id = 0;
760 for (j = 0; j < maxcard; j++) {
764 if (s[top].sn->level == 0)
765 s[top].pos[j] = (off_t) s[top].sn->branch[j].child.id;
776 s[top].pos[s[top].branch_id - 1] = nextfreepos;
777 nextfreepos += (s[top + 1].sn->level ? sidx_nodesize : sidx_leafsize);
801 static off_t rtree_write_from_file(
struct gvfile *fp, off_t startpos,
802 struct RTree *t,
int off_t_size)
804 off_t nextfreepos = startpos;
805 int sidx_nodesize, sidx_leafsize;
807 int i, j, writeout, maxcard;
808 static struct spidxstack *s =
NULL;
815 for (j = 0; j <
MAXCARD; j++) {
835 s[top].branch_id = i = 0;
850 if (s[top].sn.level > 0) {
851 for (i = s[top].branch_id; i < t->
nodecard; i++) {
854 s[top++].branch_id = i + 1;
856 s[top].branch_id = 0;
877 for (j = 0; j < maxcard; j++) {
881 if (s[top].sn.level == 0)
882 s[top].pos[j] = (off_t) s[top].sn.branch[j].child.id;
893 s[top].pos[s[top].branch_id - 1] = nextfreepos;
894 nextfreepos += (s[top + 1].sn.level ? sidx_nodesize : sidx_leafsize);
905 static off_t rtree_write_to_sidx(
struct gvfile *fp, off_t startpos,
906 struct RTree *t,
int off_t_size)
909 return rtree_write_from_file(fp, startpos, t, off_t_size);
911 return rtree_write_from_memory(fp, startpos, t, off_t_size);
926 static void rtree_load_to_memory(
struct gvfile *fp, off_t rootpos,
927 struct RTree *t,
int off_t_size)
930 int i, j, loadnode, maxcard;
931 struct spidxstack *last;
932 static struct spidxstack *s =
NULL;
939 for (j = 0; j <
MAXCARD; j++) {
956 for (j = 0; j < maxcard; j++) {
960 if (s[top].sn.level == 0) {
961 s[top].sn.branch[j].child.id = (int)s[top].pos[j];
964 s[top].sn.branch[j].child.ptr =
NULL;
968 s[top].branch_id = i = 0;
979 if (s[top].sn.level > 0) {
980 for (i = s[top].branch_id; i < t->
nodecard; i++) {
981 if (s[top].pos[i] > 0) {
982 s[top++].branch_id = i + 1;
988 for (j = 0; j < maxcard; j++) {
997 if (s[top].sn.level == 0) {
998 s[top].sn.branch[j].child.id =
1002 s[top].sn.branch[j].child.ptr =
NULL;
1005 s[top].branch_id = 0;
1009 else if (last->pos[i] < 0)
1031 s[top].sn.branch[s[top].branch_id - 1].child.ptr = newnode;
1051 static void rtree_load_to_file(
struct gvfile *fp, off_t rootpos,
1052 struct RTree *t,
int off_t_size)
1054 off_t newnode_pos = -1;
1055 int i, j, loadnode, maxcard;
1056 struct spidxstack *last;
1057 static struct spidxstack *s =
NULL;
1064 for (j = 0; j <
MAXCARD; j++) {
1081 for (j = 0; j < maxcard; j++) {
1085 if (s[top].sn.level == 0) {
1086 s[top].sn.branch[j].child.id = (int)s[top].pos[j];
1089 s[top].sn.branch[j].child.pos = -1;
1093 s[top].branch_id = i = 0;
1104 if (s[top].sn.level > 0) {
1105 for (i = s[top].branch_id; i < t->
nodecard; i++) {
1106 if (s[top].pos[i] > 0) {
1107 s[top++].branch_id = i + 1;
1113 for (j = 0; j < maxcard; j++) {
1122 if (s[top].sn.level == 0) {
1123 s[top].sn.branch[j].child.id =
1127 s[top].sn.branch[j].child.pos = -1;
1130 s[top].branch_id = 0;
1134 else if (last->pos[i] < 0)
1155 s[top].sn.branch[s[top].branch_id - 1].child.pos = newnode_pos;
1163 static void rtree_load_from_sidx(
struct gvfile *fp, off_t rootpos,
1164 struct RTree *t,
int off_t_size)
1167 return rtree_load_to_file(fp, rootpos, t, off_t_size);
1169 return rtree_load_to_memory(fp, rootpos, t, off_t_size);
1232 G_debug(1,
"dig_read_spindx()");
1276 fprintf(fp,
"Nodes\n");
1285 fprintf(fp,
"Lines\n");
1294 fprintf(fp,
"Areas\n");
1303 fprintf(fp,
"Isles\n");
1316 static void rtree_read_node(
struct NodeBuffer *nb,
1328 for (i = 0; i < maxcard; i++) {
1361 rtree_read_node(&(t->
nb[
level][which]), nodepos, t, Plus);
1401 int hitCount = 0, found;
1404 struct spidxpstack s[MAXLEVEL];
1424 for (j = 0; j < maxcard; j++) {
1430 if (s[top].sn.level == 0) {
1431 s[top].sn.branch[j].child.id = (int)s[top].pos[j];
1434 s[top].sn.branch[j].child.pos = s[top].pos[j];
1439 s[top].branch_id = i = 0;
1442 level = s[top].sn->level;
1445 for (i = s[top].branch_id; i < t->
nodecard; i++) {
1446 lastpos = s[top].sn->branch[i].child.pos;
1449 s[top++].branch_id = i + 1;
1450 s[top].sn = rtree_get_node(lastpos, level - 1, t, Plus);
1460 for (j = 0; j < maxcard; j++) {
1466 if (s[top].sn.level == 0) {
1467 s[top].sn.branch[j].child.id = (int)s[top].pos[j];
1470 s[top].sn.branch[j].child.pos = s[top].pos[j];
1474 s[top].branch_id = 0;
1486 for (i = 0; i < t->
leafcard; i++) {
1487 if (s[top].sn->branch[i].child.id &&
1491 if (!shcb((
int)s[top].sn->branch[i].child.id,
1492 &s[top].sn->branch[i].rect, cbarg)) {
struct Version_info spidx
Version info for spatial index file.
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
off_t coor_size
Size of coor file.
void dig_rewind(struct gvfile *file)
Rewind file position.
size_t RTreeReadNode(struct RTree_Node *n, off_t nodepos, struct RTree *t)
int SearchHitCallback(int id, const struct RTree_Rect *rect, void *arg)
void dig_init_portable(struct Port_info *, int)
Set Port_info structure to byte order of file.
int dig__fwrite_port_I(const int *, size_t, struct gvfile *)
Write integers to the Portable Vector Format.
off_t Isle_spidx_offset
Offset of isles in sidx file.
int back_major
Earliest version that can use this data format (major)
int dig__fwrite_port_C(const char *, size_t, struct gvfile *)
Write chars to the Portable Vector Format.
int dig__fread_port_I(int *, size_t, struct gvfile *)
Read integers from the Portable Vector Format.
int spidx_with_z
2D/3D spatial index
int with_z
2D/3D vector data
int dig__fread_port_C(char *, size_t, struct gvfile *)
Read chars from the Portable Vector Format.
#define MAXLEVEL
Maximum verbosity level.
void RTreeCopyNode(struct RTree_Node *n1, struct RTree_Node *n2, struct RTree *t)
struct RTree * Isle_spidx
Isles spatial index.
int off_t_size
Size of off_t data type.
struct RTree * Node_spidx
Node spatial index.
void G_free(void *)
Free allocated memory.
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__fread_port_L(long *, size_t, struct gvfile *)
Read longs from the Portable Vector Format.
#define GRASS_VERSION_MINOR
struct RTree * Line_spidx
Line spatial index.
#define GV_SIDX_EARLIEST_MINOR
#define GV_SIDX_VER_MINOR
off_t dig_ftell(struct gvfile *file)
Get struct gvfile position.
int dig__fwrite_port_O(const off_t *, size_t, struct gvfile *, size_t)
Write off_ts to the Portable Vector Format.
off_t Area_spidx_offset
Offset of areas in sidx file.
#define PORT_DOUBLE
Sizes of types used in portable format (different names used in Vlib/ and diglib/ for the same thing)...
#define GRASS_VERSION_MAJOR
int dig_fflush(struct gvfile *file)
Flush struct gvfile.
void dig_spidx_free(struct Plus_head *)
Free spatial index (nodes, lines, areas, isles)
void RTreeFlushBuffer(struct RTree *t)
int off_t_size
Offset size.
struct gvfile spidx_fp
Spatial index file pointer.
#define GV_SIDX_EARLIEST_MAJOR
Basic topology-related info.
int dig_Wr_spidx(struct gvfile *fp, struct Plus_head *Plus)
Write spatial index to file.
#define assert(condition)
int major
Current version (major)
struct RTree * Area_spidx
Area spatial index.
int dig_Rd_spidx_head(struct gvfile *fp, struct Plus_head *ptr)
Read spatial index header from sidx file.
struct RTree_Branch * branch
int dig_dump_spidx(FILE *fp, const struct Plus_head *Plus)
Dump spatial index.
void G_fseek(FILE *, off_t, int)
Change the file position of the stream.
long spidx_head_size
Spatial index header size.
struct RTree_Node * RTreeAllocNode(struct RTree *t, int level)
off_t RTreeGetNodePos(struct RTree *t)
int dig_Wr_spidx_head(struct gvfile *fp, struct Plus_head *ptr)
Write spatial index header to file.
off_t Line_spidx_offset
Offset of lines in sidx file.
int byte_order
File byte order.
off_t G_ftell(FILE *)
Get the current file position of the stream.
int dig__fread_port_O(off_t *, size_t, struct gvfile *, size_t)
Read off_ts from the Portable Vector Format.
#define GV_SIDX_VER_MAJOR
FILE * file
File descriptor.
int dig_spidx_init(struct Plus_head *)
Initit spatial index (nodes, lines, areas, isles)
void G_warning(const char *,...) __attribute__((format(printf
off_t Volume_spidx_offset
Offset of volumes in sidx file.
struct Port_info spidx_port
Portability information for spatial index.
off_t Node_spidx_offset
Offset of nodes in sidx file.
size_t RTreeWriteNode(struct RTree_Node *n, struct RTree *t)
int minor
Current version (minor)
int dig_set_cur_port(struct Port_info *)
Set current Port_info structure.
int dig__fwrite_port_L(const long *, size_t, struct gvfile *)
Write longs to the Portable Vector Format.
int back_minor
Earliest version that can use this data format (minor)
int RTreeOverlap(struct RTree_Rect *r, struct RTree_Rect *s, struct RTree *t)
off_t Hole_spidx_offset
Offset of holes in sidx file.
int G_debug(int, const char *,...) __attribute__((format(printf
int dig_fseek(struct gvfile *file, off_t offset, int whence)
Set struct gvfile position.
struct Plus_head::@9 version
Backward compatibility version info.
int dig__fwrite_port_D(const double *, size_t, struct gvfile *)
Write doubles to the Portable Vector Format.
off_t Face_spidx_offset
Offset of faces in sidx file.
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...
int dig__fread_port_D(double *, size_t, struct gvfile *)
Read doubles from the Portable Vector Format.