GRASS Programmer's Manual  6.4.2(2012)
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
spindex_rw.c
Go to the documentation of this file.
1 /*
2  ****************************************************************************
3  *
4  * MODULE: Vector library
5  *
6  * AUTHOR(S): Radim Blazek.
7  *
8  * PURPOSE: Lower level functions for reading/writing/manipulating vectors.
9  *
10  * COPYRIGHT: (C) 2001 by the GRASS Development Team
11  *
12  * This program is free software under the GNU General Public
13  * License (>=v2). Read the file COPYING that comes with GRASS
14  * for details.
15  *
16  *****************************************************************************/
17 #include <stdlib.h>
18 #include <string.h>
19 #include <grass/gis.h>
20 #include <grass/Vect.h>
21 
22 
23 int dig_Wr_spindx_head(GVFILE * fp, struct Plus_head *ptr)
24 {
25  unsigned char buf[5];
26  long length = 42;
27 
28  dig_rewind(fp);
29  dig_set_cur_port(&(ptr->spidx_port));
30 
31  /* bytes 1 - 5 */
32  buf[0] = GV_SIDX_VER_MAJOR;
33  buf[1] = GV_SIDX_VER_MINOR;
34  buf[2] = GV_SIDX_EARLIEST_MAJOR;
35  buf[3] = GV_SIDX_EARLIEST_MINOR;
36  buf[4] = ptr->spidx_port.byte_order;
37  if (0 >= dig__fwrite_port_C(buf, 5, fp))
38  return (-1);
39 
40  /* bytes 6 - 9 : header size */
41  if (0 >= dig__fwrite_port_L(&length, 1, fp))
42  return (0);
43 
44  /* byte 10 : dimension 2D or 3D */
45  buf[0] = ptr->spidx_with_z;
46  if (0 >= dig__fwrite_port_C(buf, 1, fp))
47  return (-1);
48 
49  /* bytes 11 - 38 : Offsets */
50  if (0 >= dig__fwrite_port_L(&(ptr->Node_spidx_offset), 1, fp))
51  return (-1);
52  if (0 >= dig__fwrite_port_L(&(ptr->Edge_spidx_offset), 1, fp))
53  return (-1);
54  if (0 >= dig__fwrite_port_L(&(ptr->Line_spidx_offset), 1, fp))
55  return (-1);
56  if (0 >= dig__fwrite_port_L(&(ptr->Area_spidx_offset), 1, fp))
57  return (-1);
58  if (0 >= dig__fwrite_port_L(&(ptr->Isle_spidx_offset), 1, fp))
59  return (-1);
60  if (0 >= dig__fwrite_port_L(&(ptr->Volume_spidx_offset), 1, fp))
61  return (-1);
62  if (0 >= dig__fwrite_port_L(&(ptr->Hole_spidx_offset), 1, fp))
63  return (-1);
64 
65  G_debug(3, "spidx offset node = %ld line = %ld, area = %ld isle = %ld",
66  ptr->Node_spidx_offset, ptr->Line_spidx_offset,
67  ptr->Area_spidx_offset, ptr->Isle_spidx_offset);
68 
69  /* bytes 39 - 42 : Offsets */
70  if (0 >= dig__fwrite_port_L(&(ptr->coor_size), 1, fp))
71  return (-1);
72 
73  G_debug(2, "spidx body offset %ld", dig_ftell(fp));
74 
75  return (0);
76 }
77 
78 
79 int dig_Rd_spindx_head(GVFILE * fp, struct Plus_head *ptr)
80 {
81  unsigned char buf[5];
82  int byte_order;
83  long coor_size;
84 
85  dig_rewind(fp);
86 
87  /* bytes 1 - 5 */
88  if (0 >= dig__fread_port_C(buf, 5, fp))
89  return (-1);
90  ptr->spidx_Version_Major = buf[0];
91  ptr->spidx_Version_Minor = buf[1];
92  ptr->spidx_Back_Major = buf[2];
93  ptr->spidx_Back_Minor = buf[3];
94  byte_order = buf[4];
95 
96  G_debug(2,
97  "Sidx header: file version %d.%d , supported from GRASS version %d.%d",
98  ptr->spidx_Version_Major, ptr->spidx_Version_Minor,
99  ptr->spidx_Back_Major, ptr->spidx_Back_Minor);
100 
101  G_debug(2, " byte order %d", byte_order);
102 
103  /* check version numbers */
104  if (ptr->spidx_Version_Major > GV_SIDX_VER_MAJOR ||
105  ptr->spidx_Version_Minor > GV_SIDX_VER_MINOR) {
106  /* The file was created by GRASS library with higher version than this one */
107 
108  if (ptr->spidx_Back_Major > GV_SIDX_VER_MAJOR ||
109  ptr->spidx_Back_Minor > GV_SIDX_VER_MINOR) {
110  /* This version of GRASS lib is lower than the oldest which can read this format */
112  ("Spatial index format version %d.%d is not supported by this release."
113  " Try to rebuild topology or upgrade GRASS.",
114  ptr->spidx_Version_Major, ptr->spidx_Version_Minor);
115  return (-1);
116  }
117 
118  G_warning
119  ("Your GRASS version does not fully support spatial index format %d.%d of the vector."
120  " Consider to rebuild topology or upgrade GRASS.",
121  ptr->spidx_Version_Major, ptr->spidx_Version_Minor);
122  }
123 
124  dig_init_portable(&(ptr->spidx_port), byte_order);
125  dig_set_cur_port(&(ptr->spidx_port));
126 
127  /* bytes 6 - 9 : header size */
128  if (0 >= dig__fread_port_L(&(ptr->spidx_head_size), 1, fp))
129  return (-1);
130  G_debug(2, " header size %ld", ptr->spidx_head_size);
131 
132  /* byte 10 : dimension 2D or 3D */
133  if (0 >= dig__fread_port_C(buf, 1, fp))
134  return (-1);
135  ptr->spidx_with_z = buf[0];
136  G_debug(2, " with_z %d", ptr->spidx_with_z);
137 
138  /* bytes 11 - 38 : Offsets */
139  if (0 >= dig__fread_port_L(&(ptr->Node_spidx_offset), 1, fp))
140  return (-1);
141  if (0 >= dig__fread_port_L(&(ptr->Edge_spidx_offset), 1, fp))
142  return (-1);
143  if (0 >= dig__fread_port_L(&(ptr->Line_spidx_offset), 1, fp))
144  return (-1);
145  if (0 >= dig__fread_port_L(&(ptr->Area_spidx_offset), 1, fp))
146  return (-1);
147  if (0 >= dig__fread_port_L(&(ptr->Isle_spidx_offset), 1, fp))
148  return (-1);
149  if (0 >= dig__fread_port_L(&(ptr->Volume_spidx_offset), 1, fp))
150  return (-1);
151  if (0 >= dig__fread_port_L(&(ptr->Hole_spidx_offset), 1, fp))
152  return (-1);
153 
154  /* bytes 39 - 42 : Offsets */
155  if (0 >= dig__fread_port_L(&coor_size, 1, fp))
156  return (-1);
157  G_debug(2, " coor size %ld", coor_size);
158 
159  dig_fseek(fp, ptr->spidx_head_size, SEEK_SET);
160 
161  return (0);
162 }
163 
164 int rtree_dump_node(FILE * fp, struct Node *n, int with_z);
165 
166 /* Dump RTree branch to file */
167 int rtree_dump_branch(FILE * fp, struct Branch *b, int with_z, int level)
168 {
169  struct Rect *r;
170 
171  r = &(b->rect);
172 
173  if (level == 0)
174  fprintf(fp, " id = %d ", (int)b->child);
175 
176  fprintf(fp, " %f %f %f %f %f %f\n", r->boundary[0], r->boundary[1],
177  r->boundary[2], r->boundary[3], r->boundary[4], r->boundary[5]);
178 
179  if (level > 0) {
180  rtree_dump_node(fp, b->child, with_z);
181  }
182  return 0;
183 }
184 
185 /* Dump RTree node to file */
186 int rtree_dump_node(FILE * fp, struct Node *n, int with_z)
187 {
188  int i, nn;
189 
190  fprintf(fp, "Node level=%d count=%d\n", n->level, n->count);
191 
192  if (n->level > 0)
193  nn = NODECARD;
194  else
195  nn = LEAFCARD;
196 
197  for (i = 0; i < nn; i++) {
198  if (n->branch[i].child) {
199  fprintf(fp, " Branch %d", i);
200  rtree_dump_branch(fp, &n->branch[i], with_z, n->level);
201  }
202  }
203 
204  return 0;
205 }
206 
207 int rtree_write_node(GVFILE * fp, struct Node *n, int with_z);
208 
209 /* Write RTree branch to file */
210 int rtree_write_branch(GVFILE * fp, struct Branch *b, int with_z, int level)
211 {
212  struct Rect *r;
213  int i;
214 
215  r = &(b->rect);
216 
217  /* rectangle */
218  if (with_z) {
219  if (0 >= dig__fwrite_port_D(&(r->boundary[0]), 6, fp))
220  return (-1);
221  }
222  else {
223  if (0 >= dig__fwrite_port_D(&(r->boundary[0]), 2, fp))
224  return (-1);
225  if (0 >= dig__fwrite_port_D(&(r->boundary[3]), 2, fp))
226  return (-1);
227  }
228  if (level == 0) { /* write data (element id) */
229  i = (int)b->child;
230  if (0 >= dig__fwrite_port_I(&i, 1, fp))
231  return (-1);
232  }
233  else {
234  rtree_write_node(fp, b->child, with_z);
235  }
236  return 0;
237 }
238 
239 /* Write RTree node to file */
240 int rtree_write_node(GVFILE * fp, struct Node *n, int with_z)
241 {
242  int i, nn;
243 
244  /* level ( 0 = leaf, data ) */
245  if (0 >= dig__fwrite_port_I(&(n->level), 1, fp))
246  return (-1);
247 
248  /* count */
249  if (0 >= dig__fwrite_port_I(&(n->count), 1, fp))
250  return (-1);
251 
252  if (n->level > 0)
253  nn = NODECARD;
254  else
255  nn = LEAFCARD;
256  for (i = 0; i < nn; i++) {
257  if (n->branch[i].child) {
258  rtree_write_branch(fp, &n->branch[i], with_z, n->level);
259  }
260  }
261 
262  return 0;
263 }
264 
265 int rtree_read_node(GVFILE * fp, struct Node *n, int with_z);
266 
267 /* Read RTree branch from file */
268 int rtree_read_branch(GVFILE * fp, struct Branch *b, int with_z, int level)
269 {
270  struct Rect *r;
271  int i;
272 
273  G_debug(3, "rtree_read_branch()");
274 
275  r = &(b->rect);
276 
277  /* rectangle */
278  if (with_z) {
279  if (0 >= dig__fread_port_D(&(r->boundary[0]), 6, fp))
280  return (-1);
281  }
282  else {
283  if (0 >= dig__fread_port_D(&(r->boundary[0]), 2, fp))
284  return (-1);
285  if (0 >= dig__fread_port_D(&(r->boundary[3]), 2, fp))
286  return (-1);
287  r->boundary[2] = 0;
288  r->boundary[5] = 0;
289  }
290 
291  if (level == 0) { /* read data (element id) */
292  if (0 >= dig__fread_port_I(&i, 1, fp))
293  return (-1);
294  b->child = (struct Node *)i;
295  }
296  else {
297  /* create new node */
298  b->child = RTreeNewNode();
299  rtree_read_node(fp, b->child, with_z);
300  }
301  return 0;
302 }
303 
304 /* Read RTree node to file */
305 int rtree_read_node(GVFILE * fp, struct Node *n, int with_z)
306 {
307  int level, count, i;
308 
309  G_debug(3, "rtree_read_node()");
310 
311  /* level ( 0 = leaf, data ) */
312  if (0 >= dig__fread_port_I(&level, 1, fp))
313  return (-1);
314  n->level = level;
315 
316  /* count */
317  if (0 >= dig__fread_port_I(&count, 1, fp))
318  return (-1);
319  n->count = count;
320 
321  for (i = 0; i < count; i++) {
322  if (0 > rtree_read_branch(fp, &n->branch[i], with_z, level))
323  return (-1);
324  }
325 
326  return 0;
327 }
328 
329 /* Write spatial index */
330 int dig_write_spidx(GVFILE * fp, struct Plus_head *Plus)
331 {
332  dig_set_cur_port(&(Plus->spidx_port));
333  dig_rewind(fp);
334 
335  dig_Wr_spindx_head(fp, Plus);
336 
337  Plus->Node_spidx_offset = dig_ftell(fp);
338  rtree_write_node(fp, Plus->Node_spidx, Plus->with_z);
339 
340  Plus->Line_spidx_offset = dig_ftell(fp);
341  rtree_write_node(fp, Plus->Line_spidx, Plus->with_z);
342 
343  Plus->Area_spidx_offset = dig_ftell(fp);
344  rtree_write_node(fp, Plus->Area_spidx, Plus->with_z);
345 
346  Plus->Isle_spidx_offset = dig_ftell(fp);
347  rtree_write_node(fp, Plus->Isle_spidx, Plus->with_z);
348 
349  dig_rewind(fp);
350  dig_Wr_spindx_head(fp, Plus); /* rewrite with offsets */
351 
352  return 0;
353 }
354 
355 /* Read spatial index file */
356 int dig_read_spidx(GVFILE * fp, struct Plus_head *Plus)
357 {
358  G_debug(1, "dig_read_spindx()");
359 
360  /* TODO: free old tree */
361  dig_spidx_init(Plus);
362 
363  dig_rewind(fp);
364  dig_Rd_spindx_head(fp, Plus);
365  dig_set_cur_port(&(Plus->spidx_port));
366 
367  dig_fseek(fp, Plus->Node_spidx_offset, 0);
368  rtree_read_node(fp, Plus->Node_spidx, Plus->with_z);
369 
370  dig_fseek(fp, Plus->Line_spidx_offset, 0);
371  rtree_read_node(fp, Plus->Line_spidx, Plus->with_z);
372 
373  dig_fseek(fp, Plus->Area_spidx_offset, 0);
374  rtree_read_node(fp, Plus->Area_spidx, Plus->with_z);
375 
376  dig_fseek(fp, Plus->Isle_spidx_offset, 0);
377  rtree_read_node(fp, Plus->Isle_spidx, Plus->with_z);
378 
379  return 0;
380 }
381 
382 /* Dump spatial index */
383 int dig_dump_spidx(FILE * fp, struct Plus_head *Plus)
384 {
385 
386  fprintf(fp, "Nodes\n");
387  rtree_dump_node(fp, Plus->Node_spidx, Plus->with_z);
388 
389  fprintf(fp, "Lines\n");
390  rtree_dump_node(fp, Plus->Line_spidx, Plus->with_z);
391 
392  fprintf(fp, "Areas\n");
393  rtree_dump_node(fp, Plus->Area_spidx, Plus->with_z);
394 
395  fprintf(fp, "Isles\n");
396  rtree_dump_node(fp, Plus->Isle_spidx, Plus->with_z);
397 
398  return 0;
399 }