Basilisk CFD
Adaptive Cartesian mesh PDE framework
Loading...
Searching...
No Matches
kdt.c
Go to the documentation of this file.
1/** @file kdt.c
2 */
3/* Gerris - The GNU Flow Solver
4 * Copyright (C) 2010-2012 National Institute of Water and Atmospheric Research
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 * 02111-1307, USA.
20 */
21
22#include <stdlib.h>
23#include <string.h>
24#include <stdio.h>
25#include <math.h>
26#include <assert.h>
27#include <sys/types.h>
28#include <sys/stat.h>
29#include <sys/time.h>
30#include <fcntl.h>
31#include <unistd.h>
32
33#include "kdt.h"
34
35#define MIN(a,b) ((a) < (b) ? (a) : (b))
36#define MAX(a,b) ((a) > (b) ? (a) : (b))
37
38#define VERSION 20120405 /* the file format version */
39
40/* same as the system tmpfile() but uses the working directory (rather
41 than /tmp) */
43{
44 char name[] = "kdtXXXXXX";
45 int fd = mkstemp (name);
46 if (fd == -1) {
47 perror ("kdt_tmpfile");
48 exit (1);
49 }
50 FILE * fp = fdopen (fd, "r+w");
51 assert (unlink (name) == 0);
52 if (fp == NULL) {
53 perror ("kdt_tmpfile");
54 exit (1);
55 }
56 return fp;
57}
58
59/* refcounted buffer */
60
61typedef struct {
63 int ref;
64} Buffer;
65
66static Buffer * buffer_new (long len)
67{
68 Buffer * b = malloc (sizeof (Buffer));
69 b->p = malloc (len*sizeof (KdtPoint));
70 b->ref = 1;
71 return b;
72}
73
75{
76 b->ref++;
77 return b;
78}
79
80static void buffer_unref (Buffer * b)
81{
82 b->ref--;
83 if (b->ref == 0) {
84 free (b->p);
85 free (b);
86 }
87}
88
89/* KdtHeap */
90
91void kdt_heap_resize (KdtHeap * h, long len)
92{
93 assert (h->len < 0 || len < h->len);
94 if (h->len == h->buflen) {
95 h->buflen = len;
96 h->end = h->buflen;
97 }
98 else if (len <= h->buflen) {
99 h->buflen = len;
101 assert (h->end == len);
102 }
103 h->len = len;
104}
105
106static long heap_read (KdtHeap * h, long len)
107{
108 if (ftell (h->fp) != h->current)
109 assert (fseek (h->fp, h->current, SEEK_SET) == 0);
110 if (h->len > 0) {
111 long maxlen = h->start + h->len - h->current/sizeof (KdtPoint);
112 if (len > maxlen)
113 len = maxlen;
114 }
115 long n = 0;
116 if (len > 0) {
117 n = fread (h->p, sizeof (KdtPoint), len, h->fp);
118 h->current = ftell (h->fp);
119 }
120 return n;
121}
122
123static void heap_write (KdtHeap * h, long len)
124{
125 if (ftell (h->fp) != h->current)
126 assert (fseek (h->fp, h->current, SEEK_SET) == 0);
127 if (fwrite (h->p, sizeof (KdtPoint), len, h->fp) != len) {
128 perror ("heap_write");
129 exit (1);
130 }
131 h->current = ftell (h->fp);
132}
133
134void kdt_heap_create (KdtHeap * h, FILE * fp, long start, long len, long buflen)
135{
136 h->fp = fp;
137 h->start = start;
138 if (len > 0 && len < buflen)
139 buflen = len;
140 h->len = len;
141 h->buflen = buflen;
142 h->i = 0;
143 h->buf = buffer_new (buflen);
144 h->p = ((Buffer *) h->buf)->p;
145 h->current = start*sizeof (KdtPoint);
146 if (fp != NULL) {
147 assert (fseek (fp, start*sizeof (KdtPoint), SEEK_SET) == 0);
148 assert (ftell (fp) == h->current);
149 h->end = heap_read (h, buflen);
150 if (buflen == len)
151 assert (h->end == len);
152 }
153 else
154 h->end = 0;
155}
156
158{
159 if (h->len == h->buflen) {
160 h->i = 0;
161 assert (h->end == h->buflen);
162 }
163 else {
164 assert (fseek (h->fp, h->start*sizeof (KdtPoint), SEEK_SET) == 0);
165 h->current = ftell (h->fp);
166 h->end = heap_read (h, h->buflen);
167 h->i = 0;
168 }
169}
170
172{
173 if (h->len == h->buflen && h->i >= h->len)
174 return 0;
175 if (h->i < h->end) {
176 *p = h->p[h->i++];
177 return 1;
178 }
179 if (h->end < h->buflen)
180 return 0;
181 h->end = heap_read (h, h->buflen);
182 h->i = 0;
183 return kdt_heap_get (h, p);
184}
185
186void kdt_heap_split (KdtHeap * h1, long len1, KdtHeap * h2)
187{
188 assert (len1 < h1->len);
189 if (h1->len == h1->buflen) {
190 h2->fp = NULL;
191 h2->start = 0;
192 h2->len = h1->len - len1;
193 h2->buflen = h2->len;
194 h2->i = 0;
195 h2->p = &h1->p[len1];
196 h2->buf = buffer_ref (h1->buf);
197 h2->end = h2->len;
198 kdt_heap_resize (h1, len1);
199 }
200 else {
201 kdt_heap_create (h2, h1->fp, h1->start + len1, h1->len - len1, h1->buflen);
202
203 KdtHeap h;
204 kdt_heap_create (&h, NULL, 0, len1, h1->buflen);
205 if (len1 > h1->buflen)
206 h.fp = kdt_tmpfile ();
207 else
208 h.end = h.len;
209
211 long i;
212 for (i = 0; i < len1; i++) {
213 KdtPoint p;
214 assert (kdt_heap_get (h1, &p));
215 kdt_heap_put (&h, &p);
216 }
217 kdt_heap_flush (&h);
218 h1->fp = NULL;
220 *h1 = h;
221 }
222}
223
225{
226 if (h->i == h->buflen) {
227 heap_write (h, h->buflen);
228 h->i = 0;
229 }
230 h->p[h->i++] = *p;
231}
232
234{
235 if (h->i > 0 && h->fp != NULL)
236 heap_write (h, h->i);
237}
238
240{
241 buffer_unref (h->buf);
242 if (h->fp != NULL)
243 assert (fclose (h->fp) == 0);
244}
245
246/* sort */
247
248static int put (KdtHeap * h, KdtPoint * p, KdtHeap * merged)
249{
251 return kdt_heap_get (h, p);
252}
253
255{
257 long i = 0;
258 KdtPoint p;
259 while (kdt_heap_get (h, &p)) {
260 fprintf (fp, "%ld %g %g\n", i, p.x, p.y);
261 i++;
262 }
263}
264
265static void merge (KdtHeap * h1, KdtHeap * h2,
266 int (*compar) (const void *, const void *),
267 long buflen)
268{
269 KdtHeap hm;
270 assert (h1->len + h2->len > buflen);
271 kdt_heap_create (&hm, NULL, h2->start - h1->len, h1->len + h2->len, buflen);
272 hm.fp = h2->fp;
273 KdtPoint p1, p2;
275 int r1 = kdt_heap_get (h1, &p1);
277 int r2 = kdt_heap_get (h2, &p2);
278 while (r1 && r2) {
279 if ((* compar) (&p2, &p1))
280 r1 = put (h1, &p1, &hm);
281 else
282 r2 = put (h2, &p2, &hm);
283 }
284 while (r1)
285 r1 = put (h1, &p1, &hm);
286 while (r2)
287 r2 = put (h2, &p2, &hm);
289 h2->fp = NULL;
292 *h1 = hm;
293}
294
295#if TIMING
296static double elapsed (const struct timeval * start, const struct timeval * end)
297{
298 return (double) (end->tv_usec - start->tv_usec) +
299 1e6*(double) (end->tv_sec - start->tv_sec);
300}
301#endif
302
303static void kdt_heap_sort (KdtHeap * h,
304 int (*compar) (const void *, const void *),
305 void (*progress) (void *), void * data)
306{
307#if TIMING
308 struct timeval start;
309 gettimeofday (&start, NULL);
310#endif
311 if (h->len == h->buflen) {
312 qsort (h->p, h->len, sizeof (KdtPoint), compar);
313 if (progress)
314 (* progress) (data);
315 }
316 else {
317 KdtHeap h2;
318 long buflen = h->buflen;
319 kdt_heap_split (h, h->len/2, &h2);
322 merge (h, &h2, compar, buflen);
323 }
324#if TIMING
325 struct timeval end;
326 gettimeofday (&end, NULL);
327 fprintf (stderr, "kdt_heap_sort %ld %g\n", len, elapsed (&start, &end));
328#endif
329}
330
331/* number of qsort() calls for a given kdt_heap_sort() */
332static int kdt_heap_sort_cost (long len, long buflen)
333{
334 int m = 1;
335 while (len > buflen) {
336 m *= 2;
337 len /= 2;
338 }
339 return m;
340}
341
342/* Kdt */
343
344typedef struct {
346 long len1;
347 int n1;
348} Node;
349
350typedef struct {
352 long len;
354 long np;
356} Header;
357
358struct _Kdt {
362 /* progress stuff */
363 void (* progress) (float complete, void * data);
364 void * data;
365 int i, m;
366};
367
368static int check_32_bits (const Kdt * kdt)
369{
370#if (!defined (__LP64__) && !defined (__64BIT__) && \
371 !defined (_LP64) && !(__WORDSIZE == 64))
372 long maxlen = (1 << 31)/sizeof (KdtPoint);
373 if (kdt->h.len > maxlen) {
374 fprintf (stderr, "kdt: 32-bits systems are limited to %ld data points\n",
375 maxlen);
376 return 1;
377 }
378#endif
379 return 0;
380}
381
382static void sizes (const Node * n, long * nodes, long * sums, long * leaves)
383{
384 *nodes = n->n1*sizeof (Node);
385 *sums = n->n1*sizeof (KdtSumCore);
386 *leaves = n->len1*sizeof (KdtPoint);
387}
388
389static void relative (const KdtRect rect, double * o, double * h)
390{
391 o[0] = (((double)rect[0].l) + ((double)rect[0].h))/2.;
392 o[1] = (((double)rect[1].l) + ((double)rect[1].h))/2.;
393 *h = ((double)rect[0].h) - ((double)rect[0].l);
394 if (((double)rect[1].h) - ((double)rect[1].l) > *h)
395 *h = ((double)rect[1].h) - ((double)rect[1].l);
396}
397
398static void sum_add_point (const KdtRect parent, KdtSumCore * sum,
399 const KdtPoint * a, double w)
400{
401 double p[3], o[2], h;
402
403 relative (parent, o, &h);
404
405 p[0] = (a->x - o[0])/h; p[1] = (a->y - o[1])/h; p[2] = a->z;
406#if AVG_TERRAIN
407 sum->H0 += p[2];
408 sum->n++;
409 if (p[2] < sum->Hmin) sum->Hmin = p[2];
410 if (p[2] > sum->Hmax) sum->Hmax = p[2];
411#else
412 sum->m01 += w*p[0];
413 sum->m02 += w*p[1];
414 sum->m03 += w*p[0]*p[1];
415 sum->m11 += w*p[0]*p[0];
416 sum->m13 += w*p[0]*p[0]*p[1];
417 sum->m22 += w*p[1]*p[1];
418 sum->m23 += w*p[0]*p[1]*p[1];
419 sum->m33 += w*p[0]*p[0]*p[1]*p[1];
420 sum->m44 += w*p[0]*p[0]*p[0];
421 sum->m55 += w*p[1]*p[1]*p[1];
422 sum->m66 += w*p[0]*p[0]*p[0]*p[0];
423 sum->m77 += w*p[1]*p[1]*p[1]*p[1];
424 sum->m67 += w*p[0]*p[0]*p[0]*p[1];
425 sum->m76 += w*p[1]*p[1]*p[1]*p[0];
426 sum->H0 += w*p[2];
427 sum->H1 += w*p[0]*p[2];
428 sum->H2 += w*p[1]*p[2];
429 sum->H3 += w*p[0]*p[1]*p[2];
430 sum->H4 += w*p[2]*p[2];
431 sum->H5 += w*p[0]*p[0]*p[2];
432 sum->H6 += w*p[1]*p[1]*p[2];
433 sum->n ++;
434 if (p[2] < sum->Hmin) sum->Hmin = p[2];
435 if (p[2] > sum->Hmax) sum->Hmax = p[2];
436#endif
437}
438
439static float area (const KdtRect rect)
440{
441 return (rect[0].h - rect[0].l)*(rect[1].h - rect[1].l);
442}
443
444static float length (const KdtRect rect)
445{
446 float w = rect[0].h - rect[0].l, h = rect[1].h - rect[1].l;
447 return w > h ? w : h;
448}
449
451{
452 fprintf (fp, "%f %f\n%f %f\n%f %f\n%f %f\n%f %f\n\n",
453 rect[0].l, rect[1].l, rect[0].h, rect[1].l,
454 rect[0].h, rect[1].h, rect[0].l, rect[1].h,
455 rect[0].l, rect[1].l);
456}
457
458static int sort_x (const void * p1, const void * p2)
459{
460 return ((KdtPoint *) p1)->x > ((KdtPoint *) p2)->x ? 1 : -1;
461}
462
463static int sort_y (const void * p1, const void * p2)
464{
465 return ((KdtPoint *) p1)->y > ((KdtPoint *) p2)->y ? 1 : -1;
466}
467
469{
470 memset (s, 0, sizeof (KdtSumCore));
471 s->Hmax = - 1e30;
472 s->Hmin = 1e30;
473}
474
475#define GAP 0.2
476#define MINLEN 6
477
478static int update_sum (const KdtRect rect, KdtSumCore * n, KdtHeap * h,
479 int index)
480{
482 long i, imax = 0;
483 double min, x, smax = 0;
484 KdtPoint p;
486 assert (kdt_heap_get (h, &p));
487 sum_add_point (rect, n, &p, 1.);
488 min = x = (&p.x)[index];
489 for (i = 1; i < h->len; i++) {
490 assert (kdt_heap_get (h, &p));
491 sum_add_point (rect, n, &p, 1.);
492 double s = (&p.x)[index] - x;
493 if (s > smax && i > MINLEN && i < h->len - MINLEN) {
494 smax = s;
495 imax = i;
496 }
497 x = (&p.x)[index];
498 }
499 return smax/(x - min) > GAP ? imax : -1;
500}
501
503{
504 long len = 0;
505 rect[0].h = rect[1].h = -1e30;
506 rect[0].l = rect[1].l = 1e30;
508 KdtPoint p;
509 while (kdt_heap_get (h, &p)) {
510 if (p.x > rect[0].h) rect[0].h = p.x;
511 if (p.x < rect[0].l) rect[0].l = p.x;
512 if (p.y > rect[1].h) rect[1].h = p.y;
513 if (p.y < rect[1].l) rect[1].l = p.y;
514 len++;
515 }
516 return len;
517}
518
519static void progress (void * data)
520{
521 Kdt * kdt = data;
522 if (kdt->progress && kdt->m > 0)
523 (* kdt->progress) (++kdt->i/(float) kdt->m, kdt->data);
524}
525
526static void fwrite_check (const void * ptr, size_t size, size_t nmemb,
527 FILE * stream)
528{
529 if (fwrite (ptr, size, nmemb, stream) != nmemb) {
530 perror ("kdt_write");
531 exit (1);
532 }
533}
534
535static void union_bound (KdtRect b, const KdtRect b1, const KdtRect b2)
536{
537 b[0].l = MIN (b1[0].l, b2[0].l);
538 b[1].l = MIN (b1[1].l, b2[1].l);
539 b[0].h = MAX (b1[0].h, b2[0].h);
540 b[1].h = MAX (b1[1].h, b2[1].h);
541}
542
543static int split (KdtHeap * h1, KdtRect bound, int index, Kdt * kdt,
544 float * coverage)
545{
546#if TIMING
547 struct timeval start;
548 gettimeofday (&start, NULL);
549#endif
550 int ns = 0;
551 if (h1->len > kdt->h.np) {
552 // fprintf (stderr, " splitting: %ld \r", len);
553 int nindex = (bound[0].h - bound[0].l < bound[1].h - bound[1].l);
554 if (index != nindex) {
556 index = nindex;
557 }
558 else
559 /* update cost estimate */
560 kdt->m -= kdt_heap_sort_cost (h1->len, h1->buflen);
562 int imax = update_sum (bound, &s, h1, index);
563 long spos = ftell (kdt->sums);
564 fwrite_check (&s, sizeof (KdtSumCore), 1, kdt->sums);
565 Node n;
566 n.len1 = imax > 0 ? imax : h1->len/2;
567#if TIMING
568 struct timeval s1;
569 gettimeofday (&s1, NULL);
570#endif
571 KdtHeap h2;
572 kdt_heap_split (h1, n.len1, &h2);
573#if TIMING
574 struct timeval end;
575 gettimeofday (&end, NULL);
576 fprintf (stderr, "half %ld %f\n", len, elapsed (&s1, &end));
577#endif
578 update_bounds (n.bound1, h1);
579 update_bounds (n.bound2, &h2);
580 long pos = ftell (kdt->nodes);
581 fwrite_check (&n, sizeof (Node), 1, kdt->nodes);
582 float coverage1;
583 n.n1 = split (h1, n.bound1, index, kdt, &coverage1);
584 float coverage2;
585 int n2 = split (&h2, n.bound2, index, kdt, &coverage2);
586 ns = n.n1 + n2 + 1;
587
588 /* update bound */
589 union_bound (bound, n.bound1, n.bound2);
590
591 /* update sums */
592 double a = area (bound);
593 if (a > 0.)
594 s.coverage = (coverage1*area (n.bound1) + coverage2*area (n.bound2))/a;
595 else
596 s.coverage = 1.;
597 assert (fseek (kdt->sums, spos + ((long) &s.coverage - (long) &s),
598 SEEK_SET) == 0);
599 fwrite_check (&s.coverage, sizeof (float), 1, kdt->sums);
600 assert (fseek (kdt->sums, 0, SEEK_END) == 0);
601 *coverage = s.coverage;
602
603 /* update node */
604 assert (fseek (kdt->nodes, pos, SEEK_SET) == 0);
605 fwrite_check (&n, sizeof (Node), 1, kdt->nodes);
606 assert (fseek (kdt->nodes, 0, SEEK_END) == 0);
607 }
608 else {
609 assert (h1->len > 0);
610 /* half the average distance between samples */
611 double delta = length (bound)/sqrt (h1->len)/2.;
612 bound[0].l -= delta;
613 bound[1].l -= delta;
614 bound[0].h += delta;
615 bound[1].h += delta;
616#if DEBUG
617 kdt_rect_write (bound, stderr);
618#endif
619 assert (h1->len <= h1->buflen);
620 fwrite_check (h1->p, sizeof (KdtPoint), h1->len, kdt->leaves);
622 *coverage = 1.;
623 }
624#if TIMING
625 struct timeval end;
626 gettimeofday (&end, NULL);
627 fprintf (stderr, "splitfile %ld %f\n", len, elapsed (&start, &end));
628#endif
629 return ns;
630}
631
632Kdt * kdt_new (void)
633{
634 Kdt * kdt = calloc (1, sizeof (Kdt));
635 return kdt;
636}
637
638static FILE * open_ext (const char * name, const char * ext, const char * mode)
639{
640 int len = strlen (name), len1 = strlen (ext);
641 char * fname = malloc (sizeof(char)*(len + len1 + 1));
642 strcpy (fname, name);
643 strcpy (&fname[len], ext);
644 FILE * fp = fopen (fname, mode);
645 free (fname);
646#if BUFFERED_KDT
647 if (fp && strchr (mode, 'r')) {
648 fseek (fp, 0, SEEK_END);
649 long fsize = ftell (fp);
650 fseek (fp, 0, SEEK_SET);
651 char * buf = malloc (fsize);
652 size_t len = fread (buf, 1, fsize, fp);
653 fclose (fp);
654 fp = fmemopen (buf, len, mode);
655 }
656#endif /* BUFFERED_KDT */
657 return fp;
658}
659
660static int kdt_init (Kdt * kdt, const char * name, int npmax, long len)
661{
662 kdt->nodes = open_ext (name, ".kdt", "w");
663 if (!kdt->nodes)
664 return -1;
665
666 kdt->sums = open_ext (name, ".sum", "w");
667 if (!kdt->sums)
668 return -1;
669
670 kdt->leaves = open_ext (name, ".pts", "w");
671 if (!kdt->leaves)
672 return -1;
673
674 kdt->h.version = VERSION;
675 kdt->h.len = len;
676 kdt->h.np = npmax;
677 kdt->h.bound[0].l = kdt->h.bound[1].l = 1e30;
678 kdt->h.bound[0].h = kdt->h.bound[1].h = -1e30;
679
680 if (check_32_bits (kdt))
681 return -1;
682
683 return 0;
684}
685
686int kdt_create (Kdt * kdt, const char * name, int blksize,
687 KdtHeap * h,
688 void (* progress) (float complete, void * data),
689 void * data)
690{
691 KdtRect bound;
692 long len = update_bounds (bound, h);
693 kdt_heap_resize (h, len);
694
695 int npmax = blksize/sizeof (KdtPoint);
696 if (kdt_init (kdt, name, npmax, len))
697 return -1;
698 kdt->h.bound[0] = bound[0];
699 kdt->h.bound[1] = bound[1];
700
701 fwrite_check (&kdt->h, sizeof (Header), 1, kdt->nodes);
702
703 /* cost estimate kdt->m (number of qsort() calls) based on balanced
704 binary tree */
705 kdt->m = kdt->i = 0;
706 int m2 = 1;
707 while (len > kdt->h.np) {
708 kdt->m += kdt_heap_sort_cost (len, h->buflen)*m2;
709 len /= 2;
710 m2 *= 2;
711 }
712 kdt->progress = progress;
713 kdt->data = data;
714 float coverage;
715 split (h, kdt->h.bound, -1, kdt, &coverage);
716 /* write updated header (bounds have been updated) */
717 rewind (kdt->nodes);
718 fwrite_check (&kdt->h, sizeof (Header), 1, kdt->nodes);
719
720 return 0;
721}
722
723int kdt_open (Kdt * kdt, const char * name)
724{
725 kdt->nodes = open_ext (name, ".kdt", "r");
726 if (!kdt->nodes)
727 return -1;
728
729 kdt->sums = open_ext (name, ".sum", "r");
730 if (!kdt->sums)
731 return -1;
732
733 kdt->leaves = open_ext (name, ".pts", "r");
734 if (!kdt->leaves)
735 return -1;
736
737 if (fread (&kdt->h, sizeof (Header), 1, kdt->nodes) != 1)
738 return -1;
739
740 if (kdt->h.version != VERSION) {
741 fprintf (stderr,
742 "kdt: incompatible version number. Use:\n"
743 "%% kdt2kdt -v %s\n"
744 "to convert to the new format.\n",
745 name);
746 return -1;
747 }
748
749 kdt->buffer = malloc (sizeof (KdtPoint)*kdt->h.np);
750
751 if (check_32_bits (kdt))
752 return -1;
753
754 return 0;
755}
756
758{
759 if (kdt->nodes)
760 fclose (kdt->nodes);
761 if (kdt->sums)
762 fclose (kdt->sums);
763 if (kdt->leaves)
764 fclose (kdt->leaves);
765 if (kdt->buffer)
766 free (kdt->buffer);
767 free (kdt);
768}
769
771{
772 return (rect[0].l <= query[0].h && rect[1].l <= query[1].h &&
773 rect[0].h >= query[0].l && rect[1].h >= query[1].l);
774}
775
777{
778 return (rect[0].h <= query[0].h && rect[1].h <= query[1].h &&
779 rect[0].l >= query[0].l && rect[1].l >= query[1].l);
780}
781
782static long query (const Kdt * kdt, const KdtRect rect, long len)
783{
784 if (len > kdt->h.np) {
785 Node node;
786 if (fread (&node, sizeof (Node), 1, kdt->nodes) != 1)
787 return -1;
788 long pos = ftell (kdt->nodes), lpos = ftell (kdt->leaves);
789 if (pos < 0 || lpos < 0)
790 return -1;
791 long n = 0;
792 if (kdt_intersects (node.bound1, rect)) {
793#if DEBUG
794 kdt_rect_write (node.bound1, stderr);
795#endif
796 long n1 = query (kdt, rect, node.len1);
797 if (n1 < 0)
798 return -1;
799 n += n1;
800 }
801 if (kdt_intersects (node.bound2, rect)) {
802#if DEBUG
803 kdt_rect_write (node.bound2, stderr);
804#endif
805 long snodes, ssums, sleaves;
806 sizes (&node, &snodes, &ssums, &sleaves);
807 if (fseek (kdt->nodes, pos + snodes, SEEK_SET))
808 return -1;
809 if (fseek (kdt->leaves, lpos + sleaves, SEEK_SET))
810 return -1;
811 long n1 = query (kdt, rect, len - node.len1);
812 if (n1 < 0)
813 return -1;
814 n += n1;
815 }
816 return n;
817 }
818 else if (len > 0) {
819 if (fread (kdt->buffer, sizeof (KdtPoint), len, kdt->leaves) != len)
820 return -1;
821 int i, n = 0;
822 for (i = 0; i < len; i++)
823 if (kdt->buffer[i].x >= rect[0].l && kdt->buffer[i].x <= rect[0].h &&
824 kdt->buffer[i].y >= rect[1].l && kdt->buffer[i].y <= rect[1].h) {
825 printf ("%.8f %.8f %f\n",
826 kdt->buffer[i].x, kdt->buffer[i].y, kdt->buffer[i].z);
827 n++;
828 }
829 return n;
830 }
831 return 0;
832}
833
834long kdt_query (const Kdt * kdt, const KdtRect rect)
835{
836 rewind (kdt->nodes);
837 rewind (kdt->leaves);
838 Header h;
839 if (fread (&h, sizeof (Header), 1, kdt->nodes) != 1)
840 return -1;
841 if (!kdt_intersects (rect, h.bound))
842 return 0;
843 return query (kdt, rect, h.len);
844}
845
846static void intersection (const KdtRect rect1, const KdtRect rect2,
848{
849 inter[0].l = MAX (rect1[0].l, rect2[0].l);
850 inter[0].h = MIN (rect1[0].h, rect2[0].h);
851 inter[1].l = MAX (rect1[1].l, rect2[1].l);
852 inter[1].h = MIN (rect1[1].h, rect2[1].h);
853 assert (inter[0].h >= inter[0].l && inter[1].h >= inter[1].l);
854}
855
856static float intersection_area (const KdtRect rect1, const KdtRect rect2)
857{
860 return area (inter);
861}
862
863static void sum_add_sum (const KdtRect parent, KdtSum * sum,
864 const KdtRect rect, const KdtSumCore * a)
865{
866 /* weigh by effective area per sample */
867 double w = intersection_area (rect, parent)*a->coverage/a->n;
868 if (w == 0.)
869 return;
870
871 double op[2], oa[2], hp, ha;
872
873 relative (parent, op, &hp);
874 relative (rect, oa, &ha);
875
876 double oap0 = oa[0] - op[0], oap1 = oa[1] - op[1];
877 double an = a->n;
878 double ha2 = ha*ha, hp2 = hp*hp;
879 sum->m01 += w*(an*oap0 + a->m01*ha)/hp;
880 sum->m02 += w*(an*oap1 + a->m02*ha)/hp;
881 sum->m03 += w*(oap0*(an*oap1 + a->m02*ha) + ha*(a->m01*oap1 + a->m03*ha))/hp2;
882 double m11 = (oap0*(an*oap0 + 2.*a->m01*ha) + a->m11*ha2)/hp2;
883 sum->m11 += w*m11;
884 double m13 = ha*(oap0*(a->m02*oap0 + 2.*a->m03*ha) + a->m13*ha2)/hp2;
885 sum->m13 += w*(oap1*m11 + m13)/hp;
886 double m22 = (oap1*(an*oap1 + 2.*a->m02*ha) + a->m22*ha2)/hp2;
887 sum->m22 += w*m22;
888 sum->m23 += w*(oap0*m22 + ha*(oap1*(oap1*a->m01 + 2.*a->m03*ha) +
889 a->m23*ha2)/hp2)/hp;
890 sum->m33 += w*(oap1*(oap1*m11 + 2.*m13) +
891 ha2*(oap0*(oap0*a->m22 + 2.*a->m23*ha) + ha2*a->m33)/hp2)/hp2;
892 double ha3 = ha2*ha, hp3 = hp2*hp;
893 sum->m44 += w*(oap0*(oap0*(oap0*an + 3.*ha*a->m01) + 3.*ha2*a->m11) +
894 ha3*a->m44)/hp3;
895 sum->m55 += w*(oap1*(oap1*(oap1*an + 3.*ha*a->m02) + 3.*ha2*a->m22) +
896 ha3*a->m55)/hp3;
897 double ha4 = ha3*ha, hp4 = hp3*hp;
898 sum->m66 += w*(oap0*(oap0*(oap0*(oap0*an + 4.*ha*a->m01) + 6.*ha2*a->m11)
899 + 4.*ha3*a->m44) + ha4*a->m66)/hp4;
900 sum->m77 += w*(oap1*(oap1*(oap1*(oap1*an + 4.*ha*a->m02) + 6.*ha2*a->m22)
901 + 4.*ha3*a->m55) + ha4*a->m77)/hp4;
902 sum->m67 += w*(oap1*(oap0*(oap0*(oap0*an + 3.*ha*a->m01) + 3.*ha2*a->m11) +
903 ha3*a->m44)
904 + oap0*(oap0*(ha*a->m02*oap0 + 3.*ha2*a->m03) + 3.*ha3*a->m13)
905 + ha4*a->m67)/hp4;
906 sum->m76 += w*(oap0*(oap1*(oap1*(oap1*an + 3.*ha*a->m02) + 3.*ha2*a->m22) +
907 ha3*a->m55)
908 + oap1*(oap1*(ha*a->m01*oap1 + 3.*ha2*a->m03) + 3.*ha3*a->m23)
909 + ha4*a->m76)/hp4;
910 sum->H0 += w*a->H0;
911 sum->H1 += w*(a->H0*oap0 + a->H1*ha)/hp;
912 sum->H2 += w*(a->H0*oap1 + a->H2*ha)/hp;
913 sum->H3 += w*(ha*(ha*a->H3 + oap0*a->H2 + oap1*a->H1) + oap0*oap1*a->H0)/hp2;
914 sum->H4 += w*a->H4;
915 sum->H5 += w*(oap0*(2.*ha*a->H1 + oap0*a->H0) + ha2*a->H5)/hp2;
916 sum->H6 += w*(oap1*(2.*ha*a->H2 + oap1*a->H0) + ha2*a->H6)/hp2;
917 sum->n += w*a->n*a->n/area (rect);
918 float aparent = area (parent);
919 if (aparent > 0.)
920 sum->coverage += w*a->n/aparent;
921 else
922 sum->coverage = 1.;
923 sum->w += w*a->n;
924 if (a->Hmin < sum->Hmin) sum->Hmin = a->Hmin;
925 if (a->Hmax > sum->Hmax) sum->Hmax = a->Hmax;
926}
927
928typedef struct {
929 long np, sp, lp;
931
932static long query_sum (const Kdt * kdt,
934 KdtRect bound, long len,
935 FilePointers * f,
936 const KdtRect query, KdtSum * sum)
937{
938 if (len > kdt->h.np) {
939 if (length (bound) <= length (query) || (* includes) (bound, data)) {
941 if (fseek (kdt->sums, f->sp, SEEK_SET))
942 return -1;
943 if (fread (&s, sizeof (KdtSumCore), 1, kdt->sums) != 1)
944 return -1;
945#if DEBUG
946 fprintf (stderr, "read 1 sum %ld\n", sizeof (KdtSumCore));
947#endif
948 f->sp += sizeof (KdtSumCore);
949 sum_add_sum (query, sum, bound, &s);
950 return len;
951 }
952 f->sp += sizeof (KdtSumCore);
953
954 Node node;
955 if (fseek (kdt->nodes, f->np, SEEK_SET))
956 return -1;
957 if (fread (&node, sizeof (Node), 1, kdt->nodes) != 1)
958 return -1;
959 f->np += sizeof (Node);
960#if DEBUG
961 fprintf (stderr, "read 1 node %ld\n", sizeof (Node));
962#endif
963
964 long pos = f->np, lpos = f->lp, spos = f->sp;
965 long n = 0;
966
967 if ((* intersects) (node.bound1, data)) {
968 long n1 = query_sum (kdt, includes, intersects, data,
969 node.bound1, node.len1, f, query, sum);
970 if (n1 < 0)
971 return -1;
972 n += n1;
973 }
974
975 if ((* intersects) (node.bound2, data)) {
976 long snodes, ssums, sleaves;
977 sizes (&node, &snodes, &ssums, &sleaves);
978 f->np = pos + snodes;
979 f->sp = spos + ssums;
980 f->lp = lpos + sleaves;
981 long n1 = query_sum (kdt, includes, intersects, data,
982 node.bound2, len - node.len1, f, query, sum);
983 if (n1 < 0)
984 return -1;
985 n += n1;
986 }
987 return n;
988 }
989 else {
990 float h = length (bound)/sqrt (len); /* average distance between samples */
991 if (h <= length (query)) {
992#if DEBUG
993 fprintf (stderr, "# area: %f %f\n", area (query), area (bound)/len);
994 kdt_rect_write (bound, stderr);
995#endif
996 if (fseek (kdt->leaves, f->lp, SEEK_SET))
997 return -1;
998 if (fread (kdt->buffer, sizeof (KdtPoint), len, kdt->leaves) != len)
999 return -1;
1000#if DEBUG
1001 fprintf (stderr, "read %ld leaves %ld\n", len, sizeof (KdtPoint));
1002#endif
1003 KdtPoint * a = kdt->buffer;
1004 int i, n = 0;
1005 for (i = 0; i < len; i++, a++) {
1007 boundp[0].l = a->x - h/2.;
1008 boundp[0].h = a->x + h/2.;
1009 boundp[1].l = a->y - h/2.;
1010 boundp[1].h = a->y + h/2.;
1011 if ((* intersects) (boundp, data)) {
1012 double w = intersection_area (boundp, query);
1014 sum->w += w;
1015 sum->coverage += w/area (query);
1016 n++;
1017 }
1018 }
1019 return n;
1020 }
1021 }
1022 return 0;
1023}
1024
1025long kdt_query_sum (const Kdt * kdt,
1027 const KdtRect query, KdtSum * sum)
1028{
1029 rewind (kdt->nodes);
1030 rewind (kdt->leaves);
1031 Header h;
1032 if (fread (&h, sizeof (Header), 1, kdt->nodes) != 1)
1033 return -1;
1035 f.np = sizeof (Header);
1036 f.sp = f.lp = 0;
1037 if (!(* intersects) (h.bound, data))
1038 return 0;
1039 return query_sum (kdt, includes, intersects, data, h.bound, h.len, &f,
1040 query, sum);
1041}
1042
1044{
1046 s->w = 0.;
1047}
double b2
Definition NASG.h:19
double b1
Definition NASG.h:19
const vector a
Definition all-mach.h:59
scalar h[]
Definition atmosphere.h:6
bool leaves
Definition balance.h:193
int min
Definition balance.h:192
define l
define m((k)==0 &&(l)==0 &&(m)==0) macro2 foreach_point(double _x=0.
free(list1)
int x
Definition common.h:76
scalar f[]
The primary fields are:
Definition two-phase.h:56
vector w[]
#define p
Definition tree.h:320
define sysmalloc malloc define syscalloc calloc define sysrealloc realloc define sysfree free define systrdup strdup define line calloc(n, s) @ define prealloc(p
define sysmalloc malloc define syscalloc calloc define sysrealloc realloc define sysfree free define systrdup strdup define line line line line op define op
Definition config.h:573
#define assert(a)
Definition config.h:107
double pos
Definition curvature.h:674
coord o
Definition curvature.h:672
else return n
Definition curvature.h:101
scalar s
Definition embed-tree.h:56
scalar int i
Definition embed.h:74
static char * fname
Definition errors.c:753
#define intersection(a, b)
Definition fractions.h:387
vector ha
Definition hydro.h:209
void includes(int argc, char **argv, char **grid1, int *default_grid, int *dim, int *bg, int *lyrs, int *gpus, const char *dir)
Definition include.c:2886
#define MINLEN
Definition kdt.c:476
FILE * kdt_tmpfile(void)
Definition kdt.c:42
void kdt_heap_resize(KdtHeap *h, long len)
Definition kdt.c:91
static void fwrite_check(const void *ptr, size_t size, size_t nmemb, FILE *stream)
Definition kdt.c:526
#define VERSION
Definition kdt.c:38
static void relative(const KdtRect rect, double *o, double *h)
Definition kdt.c:389
static void kdt_heap_sort(KdtHeap *h, int(*compar)(const void *, const void *), void(*progress)(void *), void *data)
Definition kdt.c:303
#define GAP
Definition kdt.c:475
void kdt_sum_init(KdtSum *s)
Definition kdt.c:1043
static void union_bound(KdtRect b, const KdtRect b1, const KdtRect b2)
Definition kdt.c:535
static int kdt_init(Kdt *kdt, const char *name, int npmax, long len)
Definition kdt.c:660
#define MIN(a, b)
Definition kdt.c:35
static Buffer * buffer_ref(Buffer *b)
Definition kdt.c:74
Kdt * kdt_new(void)
Definition kdt.c:632
static float area(const KdtRect rect)
Definition kdt.c:439
long kdt_query_sum(const Kdt *kdt, KdtCheck includes, KdtCheck intersects, void *data, const KdtRect query, KdtSum *sum)
Definition kdt.c:1025
static long query_sum(const Kdt *kdt, KdtCheck includes, KdtCheck intersects, void *data, KdtRect bound, long len, FilePointers *f, const KdtRect query, KdtSum *sum)
Definition kdt.c:932
static Buffer * buffer_new(long len)
Definition kdt.c:66
void kdt_rect_write(const KdtRect rect, FILE *fp)
Definition kdt.c:450
long kdt_query(const Kdt *kdt, const KdtRect rect)
Definition kdt.c:834
void kdt_destroy(Kdt *kdt)
Definition kdt.c:757
static void sum_add_sum(const KdtRect parent, KdtSum *sum, const KdtRect rect, const KdtSumCore *a)
Definition kdt.c:863
void kdt_heap_split(KdtHeap *h1, long len1, KdtHeap *h2)
Definition kdt.c:186
static int sort_y(const void *p1, const void *p2)
Definition kdt.c:463
void kdt_heap_create(KdtHeap *h, FILE *fp, long start, long len, long buflen)
Definition kdt.c:134
static int kdt_heap_sort_cost(long len, long buflen)
Definition kdt.c:332
static int update_sum(const KdtRect rect, KdtSumCore *n, KdtHeap *h, int index)
Definition kdt.c:478
static long update_bounds(KdtRect rect, KdtHeap *h)
Definition kdt.c:502
int kdt_intersects(const KdtRect rect, const KdtRect query)
Definition kdt.c:770
static void sizes(const Node *n, long *nodes, long *sums, long *leaves)
Definition kdt.c:382
static int put(KdtHeap *h, KdtPoint *p, KdtHeap *merged)
Definition kdt.c:248
int kdt_includes(const KdtRect rect, const KdtRect query)
Definition kdt.c:776
static long query(const Kdt *kdt, const KdtRect rect, long len)
Definition kdt.c:782
void kdt_heap_rewind(KdtHeap *h)
Definition kdt.c:157
static FILE * open_ext(const char *name, const char *ext, const char *mode)
Definition kdt.c:638
static void merge(KdtHeap *h1, KdtHeap *h2, int(*compar)(const void *, const void *), long buflen)
Definition kdt.c:265
static long heap_read(KdtHeap *h, long len)
Definition kdt.c:106
static int check_32_bits(const Kdt *kdt)
Definition kdt.c:368
void kdt_write(KdtHeap *h, FILE *fp)
Definition kdt.c:254
void kdt_heap_free(KdtHeap *h)
Definition kdt.c:239
int kdt_create(Kdt *kdt, const char *name, int blksize, KdtHeap *h, void(*progress)(float complete, void *data), void *data)
Definition kdt.c:686
int kdt_heap_get(KdtHeap *h, KdtPoint *p)
Definition kdt.c:171
static float length(const KdtRect rect)
Definition kdt.c:444
static void kdt_sum_core_init(KdtSumCore *s)
Definition kdt.c:468
void kdt_heap_flush(KdtHeap *h)
Definition kdt.c:233
static int sort_x(const void *p1, const void *p2)
Definition kdt.c:458
int kdt_open(Kdt *kdt, const char *name)
Definition kdt.c:723
void kdt_heap_put(KdtHeap *h, KdtPoint *p)
Definition kdt.c:224
static int split(KdtHeap *h1, KdtRect bound, int index, Kdt *kdt, float *coverage)
Definition kdt.c:543
#define MAX(a, b)
Definition kdt.c:36
static float intersection_area(const KdtRect rect1, const KdtRect rect2)
Definition kdt.c:856
static void heap_write(KdtHeap *h, long len)
Definition kdt.c:123
static void buffer_unref(Buffer *b)
Definition kdt.c:80
static void sum_add_point(const KdtRect parent, KdtSumCore *sum, const KdtPoint *a, double w)
Definition kdt.c:398
#define PADDING_32_BITS
Definition kdt.h:27
int(* KdtCheck)(const KdtRect rect, void *data)
Definition kdt.h:98
KdtInterval KdtRect[2]
Definition kdt.h:40
double * sum
#define data(k, l)
Definition linear.h:26
FILE * fp
Definition mtrace.h:7
size_t size
size *double * b
size *double * buf
int progress
Definition qcc.c:60
Definition kdt.c:61
int ref
Definition kdt.c:63
KdtPoint * p
Definition kdt.c:62
long lp
Definition kdt.c:929
Definition kdt.c:350
long len
Definition kdt.c:352
KdtRect bound
Definition kdt.c:351
int version
Definition kdt.c:355
long np
Definition kdt.c:354
Definition kdt.h:42
float l
Definition kdt.h:37
Definition kdt.h:32
double x
Definition kdt.h:33
Definition kdt.h:77
Definition kdt.c:344
int n1
Definition kdt.c:347
KdtRect bound1
Definition kdt.c:345
long len1
Definition kdt.c:346
Definition kdt.c:358
FILE * leaves
Definition kdt.c:360
int m
Definition kdt.c:365
void(* progress)(float complete, void *data)
Definition kdt.c:363
FILE * nodes
Definition kdt.c:360
void * data
Definition kdt.c:364
int i
Definition kdt.c:365
Header h
Definition kdt.c:359
KdtPoint * buffer
Definition kdt.c:361
FILE * sums
Definition kdt.c:360
int i
Definition common.h:44
scalar x
Definition common.h:47
scalar y
Definition common.h:49
static int intersects(KdtRect rect, Point *p)
Definition terrain.h:39
define n sizeof(Cell))) @define fine(a
Array * index