librtree 0.9.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +72 -0
  3. data/COPYING +21 -0
  4. data/README.md +86 -0
  5. data/ext/rtree/extconf.rb +37 -19
  6. data/ext/rtree/lib/bindex.c +157 -0
  7. data/ext/rtree/lib/bindex.h +31 -0
  8. data/ext/rtree/lib/bounds.h +21 -0
  9. data/ext/rtree/lib/branch.c +51 -0
  10. data/ext/rtree/lib/branches.c +17 -0
  11. data/ext/rtree/lib/bsrt.c +704 -0
  12. data/ext/rtree/lib/bsrt.h +16 -0
  13. data/ext/rtree/lib/constants.h +19 -0
  14. data/ext/rtree/lib/csv.c +81 -0
  15. data/ext/rtree/lib/csv.h +16 -0
  16. data/ext/rtree/lib/endianness.h +83 -0
  17. data/ext/rtree/lib/error.c +47 -0
  18. data/ext/rtree/lib/json.c +491 -0
  19. data/ext/rtree/lib/json.h +16 -0
  20. data/ext/rtree/lib/mk/Hdr.mk +3 -0
  21. data/ext/rtree/lib/mk/MakeDepend +25 -0
  22. data/ext/rtree/lib/mk/Obj.mk +3 -0
  23. data/ext/rtree/lib/node.c +708 -0
  24. data/ext/rtree/lib/package.c +11 -0
  25. data/ext/rtree/lib/page.c +47 -0
  26. data/ext/rtree/lib/page.h +13 -0
  27. data/ext/rtree/lib/postscript.c +543 -0
  28. data/ext/rtree/lib/rect.c +139 -0
  29. data/ext/rtree/lib/rectf.c +219 -0
  30. data/ext/rtree/lib/rtree/branch.h +105 -0
  31. data/ext/rtree/lib/rtree/branches.h +38 -0
  32. data/ext/rtree/lib/rtree/error.h +42 -0
  33. data/ext/rtree/lib/rtree/extent.h +20 -0
  34. data/ext/rtree/lib/rtree/node.h +92 -0
  35. data/ext/rtree/lib/rtree/package.h +14 -0
  36. data/ext/rtree/lib/rtree/postscript.h +66 -0
  37. data/ext/rtree/lib/rtree/rect.h +38 -0
  38. data/ext/rtree/lib/rtree/rectf.h +34 -0
  39. data/ext/rtree/lib/rtree/search.h +27 -0
  40. data/ext/rtree/lib/rtree/state.h +113 -0
  41. data/ext/rtree/lib/rtree/types.h +14 -0
  42. data/ext/rtree/lib/rtree-base.c +190 -0
  43. data/ext/rtree/lib/rtree.h +61 -0
  44. data/ext/rtree/lib/search.c +54 -0
  45. data/ext/rtree/lib/split.c +710 -0
  46. data/ext/rtree/lib/split.h +15 -0
  47. data/ext/rtree/lib/spvol.c +48 -0
  48. data/ext/rtree/lib/spvol.h +13 -0
  49. data/ext/rtree/lib/state.c +169 -0
  50. metadata +50 -3
@@ -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
+ }