librtree 0.9.1 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +80 -0
  3. data/COPYING +21 -0
  4. data/README.md +87 -0
  5. data/ext/rtree/extconf.rb +37 -19
  6. data/ext/rtree/lib/README.md +9 -0
  7. data/ext/rtree/lib/bindex.c +157 -0
  8. data/ext/rtree/lib/bindex.h +31 -0
  9. data/ext/rtree/lib/bounds.h +21 -0
  10. data/ext/rtree/lib/branch.c +51 -0
  11. data/ext/rtree/lib/branches.c +17 -0
  12. data/ext/rtree/lib/bsrt.c +704 -0
  13. data/ext/rtree/lib/bsrt.h +16 -0
  14. data/ext/rtree/lib/constants.h +19 -0
  15. data/ext/rtree/lib/csv.c +81 -0
  16. data/ext/rtree/lib/csv.h +16 -0
  17. data/ext/rtree/lib/endianness.h +83 -0
  18. data/ext/rtree/lib/error.c +47 -0
  19. data/ext/rtree/lib/json.c +491 -0
  20. data/ext/rtree/lib/json.h +16 -0
  21. data/ext/rtree/lib/mk/Hdr.mk +3 -0
  22. data/ext/rtree/lib/mk/MakeDepend +25 -0
  23. data/ext/rtree/lib/mk/Obj.mk +3 -0
  24. data/ext/rtree/lib/node.c +736 -0
  25. data/ext/rtree/lib/package.c +11 -0
  26. data/ext/rtree/lib/page.c +47 -0
  27. data/ext/rtree/lib/page.h +13 -0
  28. data/ext/rtree/lib/postscript.c +543 -0
  29. data/ext/rtree/lib/rect.c +139 -0
  30. data/ext/rtree/lib/rectf.c +219 -0
  31. data/ext/rtree/lib/rtree/branch.h +105 -0
  32. data/ext/rtree/lib/rtree/branches.h +38 -0
  33. data/ext/rtree/lib/rtree/error.h +42 -0
  34. data/ext/rtree/lib/rtree/extent.h +20 -0
  35. data/ext/rtree/lib/rtree/node.h +96 -0
  36. data/ext/rtree/lib/rtree/package.h +14 -0
  37. data/ext/rtree/lib/rtree/postscript.h +66 -0
  38. data/ext/rtree/lib/rtree/rect.h +38 -0
  39. data/ext/rtree/lib/rtree/rectf.h +34 -0
  40. data/ext/rtree/lib/rtree/search.h +27 -0
  41. data/ext/rtree/lib/rtree/state.h +113 -0
  42. data/ext/rtree/lib/rtree/types.h +14 -0
  43. data/ext/rtree/lib/rtree-base.c +197 -0
  44. data/ext/rtree/lib/rtree.h +62 -0
  45. data/ext/rtree/lib/search.c +54 -0
  46. data/ext/rtree/lib/split.c +710 -0
  47. data/ext/rtree/lib/split.h +15 -0
  48. data/ext/rtree/lib/spvol.c +48 -0
  49. data/ext/rtree/lib/spvol.h +13 -0
  50. data/ext/rtree/lib/state.c +169 -0
  51. data/ext/rtree/rtree.c +11 -0
  52. data/lib/rtree.rb +4 -4
  53. metadata +65 -3
@@ -0,0 +1,11 @@
1
+ /*
2
+ Generated from package.c.in, do not edit (but do not delete,
3
+ this file is checked into version control)
4
+ */
5
+
6
+ #include "rtree/package.h"
7
+
8
+ const char rtree_package_version[] = "1.1.4";
9
+ const char rtree_package_name[] = "librtree";
10
+ const char rtree_package_url[] = "https://gitlab.com/jjg/librtree";
11
+ const char rtree_package_bugreport[] = "j.j.green@gmx.co.uk";
@@ -0,0 +1,47 @@
1
+ #ifdef HAVE_CONFIG_H
2
+ #include "config.h"
3
+ #endif
4
+
5
+ #include "page.h"
6
+
7
+ #ifdef HAVE_UNISTD_H
8
+ #include <unistd.h>
9
+ #endif
10
+
11
+
12
+ int page_size(size_t *sz)
13
+ {
14
+
15
+ #if defined HAVE_SYSCONF
16
+
17
+ long val = sysconf(_SC_PAGESIZE);
18
+
19
+ if (val >= 1)
20
+ {
21
+ *sz = val;
22
+ return 0;
23
+ }
24
+ else
25
+ return 1;
26
+
27
+ #elif defined HAVE_GETPAGESIZE
28
+
29
+ int val = getpagesize();
30
+
31
+ if (val >= 1)
32
+ {
33
+ *sz = val;
34
+ return 0;
35
+ }
36
+ else
37
+ return 1;
38
+
39
+ #else
40
+ #warning Using default page-size (4,096 bytes)
41
+
42
+ *sz = 0x1000;
43
+ return 0;
44
+
45
+ #endif
46
+
47
+ }
@@ -0,0 +1,13 @@
1
+ /*
2
+ page.h
3
+ Copyright (c) J.J. Green 2019
4
+ */
5
+
6
+ #ifndef PAGE_H
7
+ #define PAGE_H
8
+
9
+ #include <stdlib.h>
10
+
11
+ int page_size(size_t*);
12
+
13
+ #endif
@@ -0,0 +1,543 @@
1
+ #ifdef HAVE_CONFIG_H
2
+ #include "config.h"
3
+ #endif
4
+
5
+ #include "rtree/postscript.h"
6
+ #include "rtree/package.h"
7
+ #include "rtree/error.h"
8
+
9
+ #include <time.h>
10
+ #include <errno.h>
11
+ #include <stdbool.h>
12
+
13
+ #ifdef HAVE_TGMATH_H
14
+ #include <tgmath.h>
15
+ #else
16
+ #include <math.h>
17
+ #endif
18
+
19
+ #define POSTSCRIPT_LEVEL 1
20
+
21
+ typedef struct {
22
+ struct {
23
+ double width, height;
24
+ } body;
25
+ struct {
26
+ double x, y;
27
+ } offset;
28
+ double margin, scale;
29
+ uint32_t bbox[4];
30
+ } page_t;
31
+
32
+ typedef struct {
33
+ const state_t *state;
34
+ const node_t *root;
35
+ const style_t *style;
36
+ page_t page;
37
+ } ps_t;
38
+
39
+ #ifdef WITH_JSON
40
+
41
+ #include <jansson.h>
42
+
43
+ static bool clamped(float value)
44
+ {
45
+ return (value >= 0.0) && (value <= 1.0);
46
+ }
47
+
48
+ static int psr_colour(json_t *json, colour_t *colour)
49
+ {
50
+ json_t *json_colour;
51
+
52
+ if (((json_colour = json_object_get(json, "grey")) != NULL) ||
53
+ ((json_colour = json_object_get(json, "gray")) != NULL))
54
+ {
55
+ if (! json_is_number(json_colour))
56
+ return 1;
57
+
58
+ float value = json_number_value(json_colour);
59
+
60
+ if (! clamped(value))
61
+ return 1;
62
+
63
+ colour->model = model_grey;
64
+ colour->grey[0] = value;
65
+
66
+ return 0;
67
+ }
68
+
69
+ if ((json_colour = json_object_get(json, "rgb")) != NULL)
70
+ {
71
+ if (! json_is_array(json_colour))
72
+ return 1;
73
+
74
+ if (json_array_size(json_colour) != 3)
75
+ return 1;
76
+
77
+ colour->model = model_rgb;
78
+
79
+ size_t i;
80
+ json_t *json_band;
81
+
82
+ json_array_foreach(json_colour, i, json_band)
83
+ {
84
+ if (! json_is_number(json_band))
85
+ return 1;
86
+
87
+ float value = json_number_value(json_band);
88
+
89
+ if (! clamped(value))
90
+ return 1;
91
+
92
+ colour->rgb[i] = value;
93
+ }
94
+
95
+ return 0;
96
+ }
97
+
98
+ if ((json_colour = json_object_get(json, "cmyk")) != NULL)
99
+ {
100
+ if (! json_is_array(json_colour))
101
+ return 1;
102
+
103
+ if (json_array_size(json_colour) != 4)
104
+ return 1;
105
+
106
+ colour->model = model_cmyk;
107
+
108
+ size_t i;
109
+ json_t *json_band;
110
+
111
+ json_array_foreach(json_colour, i, json_band)
112
+ {
113
+ if (! json_is_number(json_band))
114
+ return 1;
115
+
116
+ float value = json_number_value(json_band);
117
+
118
+ if (! clamped(value))
119
+ return 1;
120
+
121
+ colour->cmyk[i] = value;
122
+ }
123
+
124
+ return 0;
125
+ }
126
+
127
+ return 1;
128
+ }
129
+
130
+ static int psr_style_level(json_t *json, style_level_t *style_level)
131
+ {
132
+ if (! json_is_object(json))
133
+ return 1;
134
+
135
+ json_t *json_fill;
136
+
137
+ if ((json_fill = json_object_get(json, "fill")) == NULL)
138
+ {
139
+ style_level->fill.colour.model = model_none;
140
+ }
141
+ else
142
+ {
143
+ if (psr_colour(json_fill, &(style_level->fill.colour)) != 0)
144
+ return 1;
145
+ }
146
+
147
+ json_t *json_stroke;
148
+
149
+ if ((json_stroke = json_object_get(json, "stroke")) == NULL)
150
+ {
151
+ style_level->stroke.colour.model = model_none;
152
+ }
153
+ else
154
+ {
155
+ if (psr_colour(json_stroke, &(style_level->stroke.colour)) != 0)
156
+ return 1;
157
+
158
+ json_t *json_width;
159
+
160
+ if ((json_width = json_object_get(json_stroke, "width")) == NULL)
161
+ return 1;
162
+
163
+ if (! json_is_number(json_width))
164
+ return 1;
165
+
166
+ style_level->stroke.width = json_number_value(json_width);
167
+ }
168
+
169
+ return 0;
170
+ }
171
+
172
+ static style_t* psr_style(json_t *json)
173
+ {
174
+ if (! json_is_array(json))
175
+ return NULL;
176
+
177
+ size_t n = json_array_size(json);
178
+
179
+ if (n == 0)
180
+ return NULL;
181
+
182
+ style_level_t *array;
183
+
184
+ if ((array = calloc(n, sizeof(style_level_t))) != NULL)
185
+ {
186
+ size_t i;
187
+ json_t *json_style;
188
+
189
+ json_array_foreach(json, i, json_style)
190
+ {
191
+ style_level_t *style_level = array + i;
192
+
193
+ if (psr_style_level(json_style, style_level) != 0)
194
+ {
195
+ free(array);
196
+ return NULL;
197
+ }
198
+ }
199
+
200
+ style_t *style;
201
+
202
+ if ((style = malloc(sizeof(style_t))) != NULL)
203
+ {
204
+ style->n = n;
205
+ style->array = array;
206
+ return style;
207
+ }
208
+
209
+ free(array);
210
+ }
211
+
212
+ return NULL;
213
+ }
214
+
215
+ style_t* postscript_style_read(FILE *stream)
216
+ {
217
+ const size_t flags = JSON_REJECT_DUPLICATES;
218
+ json_t *json;
219
+
220
+ if ((json = json_loadf(stream, flags, NULL)) != NULL)
221
+ {
222
+ style_t *style = psr_style(json);
223
+ json_decref(json);
224
+ return style;
225
+ }
226
+
227
+ return NULL;
228
+ }
229
+
230
+ #else
231
+
232
+ #pragma GCC diagnostic push
233
+ #pragma GCC diagnostic ignored "-Wunused-parameter"
234
+ style_t* postscript_style_read(FILE *stream)
235
+ {
236
+ errno = ENOSYS;
237
+ return NULL;
238
+ }
239
+ #pragma GCC diagnostic pop
240
+
241
+ #endif
242
+
243
+ void postscript_style_destroy(style_t *style)
244
+ {
245
+ if (style != NULL)
246
+ free(style->array);
247
+ free(style);
248
+ }
249
+
250
+ static int pw_header(FILE *stream, uint32_t *bbox, const char *title)
251
+ {
252
+ time_t t; time(&t);
253
+ struct tm *tm = gmtime(&t);
254
+ size_t n = 1024;
255
+ char time_string[n];
256
+ if (strftime(time_string, n, "%a, %d %b %Y %T %z", tm) == 0)
257
+ return RTREE_ERR_BUFFER;
258
+
259
+ fprintf(stream,
260
+ "%%!PS-Adobe-3.0 EPSF-3.0\n"
261
+ "%%%%LanguageLevel: %i\n"
262
+ "%%%%Creator: %s %s\n"
263
+ "%%%%Title: %s\n"
264
+ "%%%%CreationDate: %s\n"
265
+ "%%%%BoundingBox: %u %u %u %u\n"
266
+ "%%%%DocumentData: Clean7Bit\n"
267
+ "%%%%EndComments\n",
268
+ POSTSCRIPT_LEVEL,
269
+ rtree_package_name,
270
+ rtree_package_version,
271
+ title ? title : "librtree output",
272
+ time_string,
273
+ bbox[0], bbox[1], bbox[2], bbox[3]);
274
+
275
+ return RTREE_OK;
276
+ }
277
+
278
+ static int pw_prologue(FILE *stream)
279
+ {
280
+ fprintf(stream, "%%%%BeginProlog\n");
281
+ fprintf(stream,
282
+ "%% box\n"
283
+ "/box {\n"
284
+ "/h exch def\n"
285
+ "/w exch def\n"
286
+ "newpath\n"
287
+ "0 0 moveto\n"
288
+ "0 h lineto\n"
289
+ "w h lineto\n"
290
+ "w 0 lineto\n"
291
+ "closepath\n"
292
+ "} def\n");
293
+ fprintf(stream,
294
+ "%% filled box\n"
295
+ "/R {\n"
296
+ "gsave\n"
297
+ "translate\n"
298
+ "box\n"
299
+ "fill\n"
300
+ "grestore\n"
301
+ "} def\n");
302
+ fprintf(stream,
303
+ "%% box interior stroke\n"
304
+ "/I {\n"
305
+ "gsave\n"
306
+ "translate\n"
307
+ "/h0 exch def\n"
308
+ "/w0 exch def\n"
309
+ "/d currentlinewidth def\n"
310
+ "/d2 d 2 div def\n"
311
+ "/w w0 d sub def\n"
312
+ "/h h0 d sub def\n"
313
+ "d2 d2 translate\n"
314
+ "w h box\n"
315
+ "stroke\n"
316
+ "grestore\n"
317
+ "} def\n");
318
+ fprintf(stream, "%%%%EndProlog\n");
319
+
320
+ return RTREE_OK;
321
+ }
322
+
323
+ static void pw_footer(FILE *stream)
324
+ {
325
+ fprintf(stream,
326
+ "showpage\n"
327
+ "%%%%EOF\n");
328
+ }
329
+
330
+ typedef struct
331
+ {
332
+ FILE *stream;
333
+ page_t *page;
334
+ } rect_data_t;
335
+
336
+ static int rect_proc(const branch_t *branch, const char *proc, rect_data_t *data)
337
+ {
338
+ const rtree_coord_t *rect = branch_get_rect(branch);
339
+ page_t *page = data->page;
340
+ float scale = page->scale;
341
+ fprintf(data->stream,
342
+ "%.2f %.2f %.2f %.2f %s\n",
343
+ (rect[2] - rect[0]) * scale,
344
+ (rect[3] - rect[1]) * scale,
345
+ (rect[0] - page->offset.x) * scale,
346
+ (rect[1] - page->offset.y) * scale,
347
+ proc);
348
+ return RTREE_OK;
349
+ }
350
+
351
+ #pragma GCC diagnostic push
352
+ #pragma GCC diagnostic ignored "-Wunused-parameter"
353
+ static int rect_fill(const state_t *state, const branch_t *branch, void *arg)
354
+ {
355
+ return rect_proc(branch, "R", (rect_data_t*)arg);
356
+
357
+ }
358
+ #pragma GCC diagnostic pop
359
+
360
+ #pragma GCC diagnostic push
361
+ #pragma GCC diagnostic ignored "-Wunused-parameter"
362
+ static int rect_stroke(const state_t *state, const branch_t *branch, void *arg)
363
+ {
364
+ return rect_proc(branch, "I", (rect_data_t*)arg);
365
+ }
366
+ #pragma GCC diagnostic pop
367
+
368
+ static int pw_rects_fill(const state_t *state, const node_t *root,
369
+ unsigned level, rect_data_t *data)
370
+ {
371
+ return node_branch_each_level(state, root, level, rect_fill, data);
372
+ }
373
+
374
+ static int pw_rects_stroke(const state_t *state, const node_t *root,
375
+ unsigned level, rect_data_t *data)
376
+ {
377
+ return node_branch_each_level(state, root, level, rect_stroke, data);
378
+ }
379
+
380
+ static int pw_state(const rtree_postscript_t *opts, ps_t *ps)
381
+ {
382
+ rtree_coord_t rect[4];
383
+ int err;
384
+
385
+ if ((err = node_envelope(ps->state, ps->root, rect)) != RTREE_OK)
386
+ return err;
387
+
388
+ /*
389
+ Given the desired output image width, the margin and the envelope
390
+ of the R-tree, find the various parameters of the page. Likewise
391
+ for desired output height.
392
+ */
393
+
394
+ page_t *page = &(ps->page);
395
+ uint32_t *bbox = page->bbox;
396
+
397
+ bbox[0] = bbox[1] = 0;
398
+
399
+ double
400
+ env_width = rect[2] - rect[0],
401
+ env_height = rect[3] - rect[1],
402
+ margin = opts->margin,
403
+ width, height, body_width, body_height, scale;
404
+
405
+ switch (opts->axis)
406
+ {
407
+ case axis_width:
408
+ width = opts->extent;
409
+ body_width = width - 2 * margin;
410
+ scale = body_width / env_width;
411
+ body_height = env_height * scale;
412
+ height = body_height + 2 * margin;
413
+ bbox[2] = round(width);
414
+ bbox[3] = ceil(height);
415
+ break;
416
+ case axis_height:
417
+ height = opts->extent;
418
+ body_height = height - 2 * margin;
419
+ scale = body_height / env_height;
420
+ body_width = env_width * scale;
421
+ width = body_height + 2 * margin;
422
+ bbox[2] = ceil(width);
423
+ bbox[3] = round(height);
424
+ break;
425
+ default:
426
+ return RTREE_ERR_INVAL;
427
+ }
428
+
429
+ page->body.height = body_height;
430
+ page->body.width = body_width;
431
+ page->scale = scale;
432
+ page->offset.x = rect[0] - margin / scale;
433
+ page->offset.y = rect[1] - margin / scale;
434
+
435
+ return RTREE_OK;
436
+ }
437
+
438
+ int postscript_write(const state_t *state,
439
+ const node_t *root,
440
+ const rtree_postscript_t *opts,
441
+ FILE *stream)
442
+ {
443
+ if ((state == NULL) ||
444
+ (root == NULL) ||
445
+ (opts == NULL) ||
446
+ (opts->style == NULL))
447
+ return RTREE_ERR_INVAL;
448
+
449
+ if (state_dims(state) != 2)
450
+ return RTREE_ERR_DIMS;
451
+
452
+ if (node_count(root) == 0)
453
+ return RTREE_ERR_EMPTY;
454
+
455
+ ps_t ps = {
456
+ .root = root,
457
+ .state = state,
458
+ .style = opts->style
459
+ };
460
+
461
+ int err;
462
+
463
+ if (((err = pw_state(opts, &ps)) != RTREE_OK) ||
464
+ ((err = pw_header(stream, ps.page.bbox, opts->title)) != RTREE_OK) ||
465
+ ((err = pw_prologue(stream)) != RTREE_OK))
466
+ return err;
467
+
468
+ rect_data_t rect_data = { .stream = stream, .page = &(ps.page) };
469
+ node_level_t max_level = node_level(root);
470
+
471
+ for (size_t i = 0 ; i <= max_level ; i++)
472
+ {
473
+ if (i >= ps.style->n)
474
+ break;
475
+
476
+ style_level_t style_level = ps.style->array[i];
477
+ node_level_t level = max_level - i;
478
+
479
+ switch (style_level.fill.colour.model)
480
+ {
481
+ case model_grey:
482
+ fprintf(stream, "%.3f setgray\n", style_level.fill.colour.grey[0]);
483
+ err = pw_rects_fill(state, root, level, &rect_data);
484
+ break;
485
+ case model_rgb:
486
+ fprintf(stream, "%.3f %.3f %.3f setrgbcolor\n",
487
+ style_level.fill.colour.rgb[0],
488
+ style_level.fill.colour.rgb[1],
489
+ style_level.fill.colour.rgb[2]);
490
+ err = pw_rects_fill(state, root, level, &rect_data);
491
+ break;
492
+ case model_cmyk:
493
+ fprintf(stream, "%.3f %.3f %.3f %.3f setcmykcolor\n",
494
+ style_level.fill.colour.cmyk[0],
495
+ style_level.fill.colour.cmyk[1],
496
+ style_level.fill.colour.cmyk[2],
497
+ style_level.fill.colour.cmyk[3]);
498
+ err = pw_rects_fill(state, root, level, &rect_data);
499
+ break;
500
+ case model_none:
501
+ break;
502
+ }
503
+
504
+ if (err != RTREE_OK)
505
+ return err;
506
+
507
+ switch (style_level.stroke.colour.model)
508
+ {
509
+ case model_grey:
510
+ fprintf(stream, "%.3f setgray\n",
511
+ style_level.stroke.colour.grey[0]);
512
+ fprintf(stream, "%.3f setlinewidth\n", style_level.stroke.width);
513
+ err = pw_rects_stroke(state, root, level, &rect_data);
514
+ break;
515
+ case model_rgb:
516
+ fprintf(stream, "%.3f %.3f %.3f setrgbcolor\n",
517
+ style_level.stroke.colour.rgb[0],
518
+ style_level.stroke.colour.rgb[1],
519
+ style_level.stroke.colour.rgb[2]);
520
+ fprintf(stream, "%.3f setlinewidth\n", style_level.stroke.width);
521
+ err = pw_rects_stroke(state, root, level, &rect_data);
522
+ break;
523
+ case model_cmyk:
524
+ fprintf(stream, "%.3f %.3f %.3f %.3f setcmykcolor\n",
525
+ style_level.stroke.colour.cmyk[0],
526
+ style_level.stroke.colour.cmyk[1],
527
+ style_level.stroke.colour.cmyk[2],
528
+ style_level.stroke.colour.cmyk[3]);
529
+ fprintf(stream, "%.3f setlinewidth\n", style_level.stroke.width);
530
+ err = pw_rects_stroke(state, root, level, &rect_data);
531
+ break;
532
+ case model_none:
533
+ break;
534
+ }
535
+
536
+ if (err != RTREE_OK)
537
+ return err;
538
+ }
539
+
540
+ pw_footer(stream);
541
+
542
+ return RTREE_OK;
543
+ }