H3C HEALPix library for PostgreSQL  (version 1.2)
h3c.c
1 /*
2  Copyright (C) 2012 Gilles Landais (CDS)
3 
4  Author: Gilles Landais, Strasbourg astronomical Data Center (CDS)
5  Email: gilles.landais@unistra.fr
6 
7  This file is part of H3C.
8 
9  H3C is free software; you can redistribute it and/or modify
10  it under the terms of the GNU General Public License as published by
11  the Free Software Foundation; either version 2 of the License, or
12  (at your option) any later version.
13 
14  H3C is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  GNU General Public License for more details.
18 
19  You should have received a copy of the GNU General Public License
20  along with H3C; if not, write to the Free Software
21  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23 
63 #include <string.h>
64 
65 /* Postgres stuff */
66 #include "postgres.h"
67 #include "executor/spi.h"
68 #include "funcapi.h"
69 #include "utils/lsyscache.h"
70 #include "utils/array.h"
71 #include "catalog/pg_type.h"
72 
73 #if PG_VERSION_NUM >= 80300
74 #include "access/tupmacs.h"
75 #endif
76 
77 /* End of Postgres stuff */
78 
79 #include "common.h"
80 #include "h3c_util.h"
81 
82 #define LOG_NPASS 200000
83 
84 /* For PostgreSQL versions >= 8.2 */
85 #ifdef PG_MODULE_MAGIC
86 PG_MODULE_MAGIC;
87 #endif
88 
89 
90 /* Postgres functions */
91 Datum pgh3c_version(PG_FUNCTION_ARGS);
92 Datum pgh3c_ang2ipix(PG_FUNCTION_ARGS);
93 Datum pgh3c_ang2ipix_default(PG_FUNCTION_ARGS);
94 Datum pgh3c_ipix2ang(PG_FUNCTION_ARGS);
95 Datum pgh3c_ipix2ang_default(PG_FUNCTION_ARGS);
96 Datum pgh3c_disk_ipix(PG_FUNCTION_ARGS);
97 Datum pgh3c_disk_ipix_default(PG_FUNCTION_ARGS);
98 Datum pgh3c_radial_query_it(PG_FUNCTION_ARGS);
99 Datum pgh3c_radial_query_it_default(PG_FUNCTION_ARGS);
100 Datum pgh3c_dist(PG_FUNCTION_ARGS);
101 Datum pgh3c_sindist(PG_FUNCTION_ARGS);
102 Datum pgh3c_poly_query_it(PG_FUNCTION_ARGS);
103 Datum pgh3c_poly_query_it_default(PG_FUNCTION_ARGS);
104 Datum pgh3c_in_poly_convex(PG_FUNCTION_ARGS);
105 Datum pgh3c_in_poly(PG_FUNCTION_ARGS);
106 /*Datum pgh3c_in_box(PG_FUNCTION_ARGS);*/
107 Datum pgh3c_poly_center(PG_FUNCTION_ARGS);
108 Datum pgh3c_circle_intersect_poly(PG_FUNCTION_ARGS);
109 Datum pgh3c_poly_intersect_poly(PG_FUNCTION_ARGS);
110 /*Datum pgh3c_box_query_it(PG_FUNCTION_ARGS);
111 Datum pgh3c_box_query_it_default(PG_FUNCTION_ARGS);*/
112 Datum pgh3c_box_to_poly(PG_FUNCTION_ARGS);
113 
114 Datum pgh3c_nearby_it(PG_FUNCTION_ARGS);
115 Datum pgh3c_nearby_it_default(PG_FUNCTION_ARGS);
116 Datum pgh3c_dist_ipix(PG_FUNCTION_ARGS);
117 Datum pgh3c_in_ellipse(PG_FUNCTION_ARGS);
118 Datum pgh3c_ellipse_query_it(PG_FUNCTION_ARGS);
119 
120 Datum pgh3c_circle_area(PG_FUNCTION_ARGS);
121 Datum pgh3c_poly_area(PG_FUNCTION_ARGS);
122 Datum pgh3c_ipix2default_it(PG_FUNCTION_ARGS);
123 
124 /*****************************************************************************/
127 /*****************************************************************************/
128 PG_FUNCTION_INFO_V1(pgh3c_version);
129 Datum pgh3c_version(PG_FUNCTION_ARGS)
130 {
131 #ifdef VERSION
132  PG_RETURN_FLOAT8(VERSION);
133 #else
134  PG_RETURN_NULL();
135 #endif
136 }
137 
138 /*****************************************************************************/
145 /*****************************************************************************/
146 PG_FUNCTION_INFO_V1(pgh3c_ang2ipix);
147 Datum pgh3c_ang2ipix(PG_FUNCTION_ARGS)
148 {
149  h3c_coord_t ra = PG_GETARG_FLOAT8(0);
150  h3c_coord_t dec = PG_GETARG_FLOAT8(1);
151  int nside = PG_GETARG_UINT32(2);
152  h3c_ipix_t ipix;
153  static int invocation;
154  static h3c_coord_t ra_buf, dec_buf;
155  static h3c_ipix_t ipix_buf;
156  static int nside_buf;
157 
158  if (invocation == 0)
159  {
160 
161  }
162  else
163  {
164  if ((ra == ra_buf) && (dec == dec_buf) && nside == nside_buf)
165  {
166  PG_RETURN_INT64(ipix_buf);
167  }
168  }
169 
170  h3c_ang2pix_nest(nside,
171  h3c_dec2theta(dec*H3C_DEGRA),
172  h3c_ra2phi(ra*H3C_DEGRA),
173  (h3c_ipix_t *) &ipix);
174 
175  ra_buf = ra;
176  dec_buf = dec;
177  ipix_buf = ipix;
178  nside_buf=nside;
179  invocation=1;
180  PG_RETURN_INT64(ipix);
181 }
182 
183 /*****************************************************************************/
191 /*****************************************************************************/
192 PG_FUNCTION_INFO_V1(pgh3c_ang2ipix_default);
193 Datum pgh3c_ang2ipix_default(PG_FUNCTION_ARGS)
194 {
195  h3c_coord_t ra = PG_GETARG_FLOAT8(0);
196  h3c_coord_t dec = PG_GETARG_FLOAT8(1);
197  h3c_ipix_t ipix;
198  static int invocation;
199  static h3c_coord_t ra_buf, dec_buf;
200  static h3c_ipix_t ipix_buf;
201 
202  if (invocation == 0)
203  {
204 
205  }
206  else
207  {
208  if ((ra == ra_buf) && (dec == dec_buf))
209  {
210  PG_RETURN_INT64(ipix_buf);
211  }
212  }
213 
214  h3c_ang2pix_nest(H3C_DEFAULT_NSIDE,
215  h3c_dec2theta(dec*H3C_DEGRA),
216  h3c_ra2phi(ra*H3C_DEGRA),
217  (h3c_ipix_t *) &ipix);
218 
219  ra_buf = ra;
220  dec_buf = dec;
221  ipix_buf = ipix;
222  invocation=1;
223  PG_RETURN_INT64(ipix);
224 }
225 
226 /*****************************************************************************/
232 /*****************************************************************************/
233 PG_FUNCTION_INFO_V1(pgh3c_ipix2ang);
234 Datum pgh3c_ipix2ang(PG_FUNCTION_ARGS)
235 {
236  h3c_ipix_t ipix;
237  h3c_coord_t theta, phi;
238 
239  Datum *data;
240  int16 typlen;
241  bool typbyval;
242  char typalign;
243  ArrayType *result;
244  ipix = PG_GETARG_INT64(0);
245  h3c_pix2ang_nest(PG_GETARG_INT32(1),
246  ipix,
247  &theta,
248  &phi);
249 
250  theta=h3c_theta2dec(theta)*H3C_RADEG;
251  phi=h3c_phi2ra(phi)*H3C_RADEG;
252 
253  /* we have one dimension */
254  data = ( Datum *) palloc(sizeof(Datum)*2);
255  data[0] = Float8GetDatum (phi);
256  data[1] = Float8GetDatum (theta);
257  /* get required info about the element type */
258  get_typlenbyvalalign(FLOAT8OID, &typlen, &typbyval, &typalign);
259 
260  /* now build the array */
261  result = construct_array(data, 2, FLOAT8OID, typlen, typbyval, typalign);
262 
263  PG_RETURN_ARRAYTYPE_P(result);
264 }
265 
266 /*****************************************************************************/
273 /*****************************************************************************/
274 PG_FUNCTION_INFO_V1(pgh3c_ipix2ang_default);
275 Datum pgh3c_ipix2ang_default(PG_FUNCTION_ARGS)
276 {
277  h3c_ipix_t ipix;
278  h3c_coord_t theta, phi;
279 
280  Datum *data;
281  int16 typlen;
282  bool typbyval;
283  char typalign;
284  ArrayType *result;
285  ipix = PG_GETARG_INT64(0);
286  h3c_pix2ang_nest(H3C_DEFAULT_NSIDE,
287  ipix,
288  &theta,
289  &phi);
290  theta=h3c_theta2dec(theta)*H3C_RADEG;
291  phi=h3c_phi2ra(phi)*H3C_RADEG;
292 
293  /* we have one dimension */
294  data = ( Datum *) palloc(sizeof(Datum)*2);
295  data[0] = Float8GetDatum (phi);
296  data[1] = Float8GetDatum (theta);
297  /* get required info about the element type */
298  get_typlenbyvalalign(FLOAT8OID, &typlen, &typbyval, &typalign);
299 
300  /* now build the array */
301  result = construct_array(data, 2, FLOAT8OID, typlen, typbyval, typalign);
302 
303  PG_RETURN_ARRAYTYPE_P(result);
304 }
305 
306 /*****************************************************************************/
314 /*****************************************************************************/
315 PG_FUNCTION_INFO_V1(pgh3c_disk_ipix);
316 Datum pgh3c_disk_ipix(PG_FUNCTION_ARGS)
317 {
318  FuncCallContext *funcctx;
319  int call_cntr, count;
320  static h3c_ipix_t *ipix;
321 
322  if (SRF_IS_FIRSTCALL()) {
323  MemoryContext oldcontext;
325 
326  /* create a function context for cross-call persistence
327  */
328  funcctx = SRF_FIRSTCALL_INIT();
329 
330  /* switch to memory context appropriate for multiple
331  function calls */
332  oldcontext =
333  MemoryContextSwitchTo(funcctx->
334  multi_call_memory_ctx);
335 
336  MemoryContextSwitchTo(oldcontext);
337 
338  ipix = h3c_disk_ipix(PG_GETARG_FLOAT8(0),
339  PG_GETARG_FLOAT8(1),
340  PG_GETARG_FLOAT8(2),
341  PG_GETARG_UINT32(3),
342  &count) ;
343  }
344 
345  /* stuff done on every call of the function */
346  funcctx = SRF_PERCALL_SETUP();
347 
348  call_cntr = funcctx->call_cntr;
349 
350  h3c_log(H3C_DEBUG, "pgh3c_disk_ipix end");
351  if (ipix && ipix[call_cntr] > -1) { /* do when there is more left to send */
352  if (ipix[call_cntr] < 0) ipix[call_cntr] = ipix[call_cntr]*-1;
353  SRF_RETURN_NEXT(funcctx,Int64GetDatum(ipix[call_cntr]));
354  }
355  else { /* do when there is no more left */
356  free(ipix);
357  SRF_RETURN_DONE(funcctx);
358  }
359 }
360 
361 /*****************************************************************************/
372 /*****************************************************************************/
373 PG_FUNCTION_INFO_V1(pgh3c_disk_ipix_default);
374 Datum pgh3c_disk_ipix_default(PG_FUNCTION_ARGS)
375 {
376  FuncCallContext *funcctx;
377  int call_cntr, count;
378  static h3c_ipix_t *ipix;
379 
380  if (SRF_IS_FIRSTCALL()) {
381  MemoryContext oldcontext;
383 
384  /* create a function context for cross-call persistence
385  */
386  funcctx = SRF_FIRSTCALL_INIT();
387 
388  /* switch to memory context appropriate for multiple
389  function calls */
390  oldcontext =
391  MemoryContextSwitchTo(funcctx->
392  multi_call_memory_ctx);
393 
394  MemoryContextSwitchTo(oldcontext);
395 
396  ipix = h3c_disk_ipix(PG_GETARG_FLOAT8(0),
397  PG_GETARG_FLOAT8(1),
398  PG_GETARG_FLOAT8(2),
399  H3C_DEFAULT_NSIDE,
400  &count) ;
401  }
402 
403  /* stuff done on every call of the function */
404  funcctx = SRF_PERCALL_SETUP();
405 
406  call_cntr = funcctx->call_cntr;
407 
408  h3c_log(H3C_DEBUG, "pgh3c_disk_ipix_default end");
409  if (ipix && ipix[call_cntr] > -1) { /* do when there is more left to send */
410  SRF_RETURN_NEXT(funcctx,Int64GetDatum(ipix[call_cntr]));
411  }
412  else { /* do when there is no more left */
413  free(ipix);
414  SRF_RETURN_DONE(funcctx);
415  }
416 }
417 
418 /*****************************************************************************/
435 /*****************************************************************************/
436 PG_FUNCTION_INFO_V1(pgh3c_radial_query_it);
437 Datum pgh3c_radial_query_it(PG_FUNCTION_ARGS)
438 {
439  static h3c_ipix_t ipix[H3C_DEFAULT_MEM_BLOCK];
440  static h3c_coord_t ra_cen_buf,dec_cen_buf, radius_buf;
441  static int invocation=0;
442  static int nside_buf;
443  h3c_coord_t ra_cen = PG_GETARG_FLOAT8(0);
444  h3c_coord_t dec_cen = PG_GETARG_FLOAT8(1);
445  h3c_coord_t radius = PG_GETARG_FLOAT8(2);
446  int iteration = PG_GETARG_INT32(3);
447  int nside = PG_GETARG_INT32(4);
448  static int max_ipix;
449 
450 
451  if (invocation == 0)
452  /* If this is the first invocation of the function */
453  {
454  /* I should set invocation=1 ONLY!!! after setting ra_cen_buf, dec_cen_buf and
455  * ipix_buf. Because if the program will be canceled or crashed
456  * for some reason the invocation should be == 0
457  */
458  }
459  else
460  {
461  if ((ra_cen == ra_cen_buf) && (dec_cen == dec_cen_buf) &&
462  (radius == radius_buf) && (nside == nside_buf))
463  {
464  if (iteration<max_ipix) PG_RETURN_INT64(ipix[iteration]);
465  PG_RETURN_INT64(-1);
466  }
467  }
468 
470  max_ipix = h3c_disk_ipix_it(PG_GETARG_FLOAT8(0),
471  PG_GETARG_FLOAT8(1),
472  PG_GETARG_FLOAT8(2),
473  nside,
474  ipix,
475  H3C_DEFAULT_MEM_BLOCK) ;
476 
477  invocation = 1;
478  ra_cen_buf = ra_cen;
479  dec_cen_buf = dec_cen;
480  radius_buf = radius;
481  nside_buf = nside;
482 
483  h3c_log(H3C_DEBUG, "pgh3c_radial_query_it end");
484  PG_RETURN_INT64(ipix[iteration]);
485 }
486 
487 /*****************************************************************************/
501 /*****************************************************************************/
502 PG_FUNCTION_INFO_V1(pgh3c_radial_query_it_default);
503 Datum pgh3c_radial_query_it_default(PG_FUNCTION_ARGS)
504 {
505  static h3c_ipix_t ipix[H3C_DEFAULT_MEM_BLOCK];
506  static h3c_coord_t ra_cen_buf,dec_cen_buf, radius_buf;
507  static int invocation=0;
508  h3c_coord_t ra_cen = PG_GETARG_FLOAT8(0);
509  h3c_coord_t dec_cen = PG_GETARG_FLOAT8(1);
510  h3c_coord_t radius = PG_GETARG_FLOAT8(2);
511  int iteration = PG_GETARG_INT32(3);
512  static int max_ipix;
513 
514 
515  if (invocation == 0)
516  /* If this is the first invocation of the function */
517  {
518  /* I should set invocation=1 ONLY!!! after setting ra_cen_buf, dec_cen_buf and
519  * ipix_buf. Because if the program will be canceled or crashed
520  * for some reason the invocation should be == 0
521  */
522  }
523  else
524  {
525  if ((ra_cen == ra_cen_buf) && (dec_cen == dec_cen_buf) &&
526  (radius == radius_buf))
527  {
528  if (iteration<max_ipix) PG_RETURN_INT64(ipix[iteration]);
529  PG_RETURN_INT64(-1);
530  }
531  }
532 
534  max_ipix = h3c_disk_ipix_it(PG_GETARG_FLOAT8(0),
535  PG_GETARG_FLOAT8(1),
536  PG_GETARG_FLOAT8(2),
537  H3C_DEFAULT_NSIDE,
538  ipix,
539  H3C_DEFAULT_MEM_BLOCK) ;
540 
541  invocation = 1;
542  ra_cen_buf = ra_cen;
543  dec_cen_buf = dec_cen;
544  radius_buf = radius;
545 
546  h3c_log(H3C_DEBUG, "pgh3c_radial_query_it_default end");
547  PG_RETURN_INT64(ipix[iteration]);
548 }
549 
550 /*****************************************************************************/
568 /*****************************************************************************/
569 PG_FUNCTION_INFO_V1(pgh3c_nearby_it);
570 Datum pgh3c_nearby_it(PG_FUNCTION_ARGS)
571 {
572  static h3c_ipix_t ipix[H3C_DEFAULT_NEARBY_MEM_BLOCK];
573  static h3c_coord_t ra_cen_buf,dec_cen_buf, radius_buf;
574  static int invocation = 0;
575  static int nside_buf;
576  static int max_ipix;
577  h3c_coord_t ra_cen = PG_GETARG_FLOAT8(0);
578  h3c_coord_t dec_cen = PG_GETARG_FLOAT8(1);
579  h3c_coord_t radius = PG_GETARG_FLOAT8(2);
580  int iteration = PG_GETARG_INT32(3);
581  int nside = PG_GETARG_INT32(4);
582  static int npass = 0;
583 
584  if (invocation == 0)
585  /* If this is the first invocation of the function */
586  {
587  /* I should set invocation=1 ONLY!!! after setting ra_cen_buf, dec_cen_buf and
588  * ipix_buf. Because if the program will be canceled or crashed
589  * for some reason the invocation should be == 0
590  */
591  h3c_log(H3C_INFO, "initialize pgh3c_nearby_it");
592  }
593  else
594  {
595  if (((npass++) % LOG_NPASS)==0) h3c_log(H3C_INFO, "pgh3c_nearby_it_default npass %d", npass);
596  if ((ra_cen == ra_cen_buf) && (dec_cen == dec_cen_buf) &&
597  (radius == radius_buf) && (nside == nside_buf))
598  {
599  if (iteration < max_ipix) PG_RETURN_INT64(ipix[iteration]);
600  PG_RETURN_INT64(-1);
601  }
602  }
603 
605  max_ipix = h3c_disk_ipix_it(PG_GETARG_FLOAT8(0),
606  PG_GETARG_FLOAT8(1),
607  PG_GETARG_FLOAT8(2),
608  nside,
609  ipix,
610  H3C_DEFAULT_NEARBY_MEM_BLOCK) ;
611  if (max_ipix < 0) h3c_log(H3C_ERROR, "pgh3c_nearby_it_default nothing found");
612 
613  invocation = 1;
614  ra_cen_buf = ra_cen;
615  dec_cen_buf = dec_cen;
616  radius_buf = radius;
617  nside_buf = nside;
618 
619  h3c_log(H3C_DEBUG, "pgh3c_nearby_it_default end");
620  PG_RETURN_INT64(ipix[iteration]);
621 }
622 
623 /*****************************************************************************/
636 /*****************************************************************************/
637 PG_FUNCTION_INFO_V1(pgh3c_nearby_it_default);
638 Datum pgh3c_nearby_it_default(PG_FUNCTION_ARGS)
639 {
640  static h3c_ipix_t ipix[H3C_DEFAULT_NEARBY_MEM_BLOCK];
641  static h3c_coord_t ra_cen_buf,dec_cen_buf, radius_buf;
642  static int invocation=0;
643  h3c_coord_t ra_cen = PG_GETARG_FLOAT8(0);
644  h3c_coord_t dec_cen = PG_GETARG_FLOAT8(1);
645  h3c_coord_t radius = PG_GETARG_FLOAT8(2);
646  int iteration = PG_GETARG_INT32(3);
647  static int max_ipix;
648  static int npass = 0;
649 
650  if (invocation == 0)
651  /* If this is the first invocation of the function */
652  {
653  /* I should set invocation=1 ONLY!!! after setting ra_cen_buf, dec_cen_buf and
654  * ipix_buf. Because if the program will be canceled or crashed
655  * for some reason the invocation should be == 0
656  */
657  h3c_log(H3C_INFO, "initialize pgh3c_nearby_it_default");
658  }
659  else
660  {
661  if (((npass++) % LOG_NPASS)==0) h3c_log(H3C_INFO, "pgh3c_nearby_it_default npass %d", npass);
662  if ((ra_cen == ra_cen_buf) && (dec_cen == dec_cen_buf) && (radius == radius_buf))
663  {
664  if (iteration < max_ipix) PG_RETURN_INT64(ipix[iteration]);
665  PG_RETURN_INT64(-1);
666  }
667  }
668 
670  max_ipix = h3c_disk_ipix_it(PG_GETARG_FLOAT8(0),
671  PG_GETARG_FLOAT8(1),
672  PG_GETARG_FLOAT8(2),
673  H3C_DEFAULT_NSIDE,
674  ipix,
675  H3C_DEFAULT_NEARBY_MEM_BLOCK) ;
676  if (max_ipix < 0) h3c_log(H3C_ERROR, "pgh3c_nearby_it_default nothing found");
677 
678  invocation = 1;
679  ra_cen_buf = ra_cen;
680  dec_cen_buf = dec_cen;
681  radius_buf = radius;
682 
683  h3c_log(H3C_DEBUG, "pgh3c_nearby_it_default end");
684  PG_RETURN_INT64(ipix[iteration]);
685 }
686 
687 /*****************************************************************************/
695 /*****************************************************************************/
696 PG_FUNCTION_INFO_V1(pgh3c_dist);
697 Datum pgh3c_dist(PG_FUNCTION_ARGS)
698 {
699  h3c_coord_t ra1 = PG_GETARG_FLOAT8(0);
700  h3c_coord_t dec1 = PG_GETARG_FLOAT8(1);
701  h3c_coord_t ra2 = PG_GETARG_FLOAT8(2);
702  h3c_coord_t dec2 = PG_GETARG_FLOAT8(3);
703  PG_RETURN_FLOAT8(h3c_dist(ra1, dec1, ra2, dec2));
704 }
705 
706 /*****************************************************************************/
715 /*****************************************************************************/
716 PG_FUNCTION_INFO_V1(pgh3c_sindist);
717 Datum pgh3c_sindist(PG_FUNCTION_ARGS)
718 {
719  h3c_coord_t ra1 = PG_GETARG_FLOAT8(0);
720  h3c_coord_t dec1 = PG_GETARG_FLOAT8(1);
721  h3c_coord_t ra2 = PG_GETARG_FLOAT8(2);
722  h3c_coord_t dec2 = PG_GETARG_FLOAT8(3);
723  PG_RETURN_FLOAT8(h3c_sindist(ra1, dec1, ra2, dec2));
724 }
725 
726 /*****************************************************************************/
736 /*****************************************************************************/
737 static int h3c_array_push(int poly_nitems,
738  h3c_coord_t *in_ra,
739  h3c_coord_t *in_dec,
740  ArrayType *poly_arr)
741 {
742  int16 typlen;
743  bool typbyval;
744  char typalign;
745  Oid element_type=FLOAT8OID;
746  int i, same = 1; /* the same polygon than the previous call */
747  char *p;
748  h3c_coord_t ra_cur, dec_cur;
749 
750 #if PG_VERSION_NUM >= 80300
751  bits8 *bitmap;
752  int bitmask;
753 
754  bitmap = ARR_NULLBITMAP(poly_arr);
755  bitmask=1;
756 #endif
757 
758  p = ARR_DATA_PTR(poly_arr);
759  get_typlenbyvalalign(element_type, &typlen, &typbyval, &typalign);
760 
761  for (i = 0; i < poly_nitems; i++)
762  {
763 #if PG_VERSION_NUM >= 80300
764  if (bitmap && (*bitmap & bitmask) == 0)
765  {
766  h3c_log(H3C_ERROR,
767  "null array element not allowed in this context");
768  }
769 
770  ra_cur = DatumGetFloat8(fetch_att(p, typbyval, typlen));
771  p = att_addlength_pointer(p, typlen, PointerGetDatum(p));
772  p = (char *) att_align_nominal(p, typalign);
773  if (bitmap)
774  {
775  bitmask <<= 1;
776  if (bitmask == 0x100)
777  {
778  bitmap++;
779  bitmask = 1;
780  }
781  }
782 
783  if (in_ra[i] != ra_cur) same = 0;
784  in_ra[i] = ra_cur;
785 
786  if (bitmap && (*bitmap & bitmask) == 0)
787  {
788  h3c_log(H3C_ERROR,
789  "null array element not allowed in this context");
790  }
791 
792  dec_cur = DatumGetFloat8(fetch_att(p, typbyval, typlen));
793  p = att_addlength_pointer(p, typlen, PointerGetDatum(p));
794  p = (char *) att_align_nominal(p, typalign);
795 
796  if (bitmap)
797  {
798  bitmask <<= 1;
799  if (bitmask == 0x100)
800  {
801  bitmap++;
802  bitmask = 1;
803  }
804  }
805 
806  if (in_dec[i] != dec_cur) same = 0;
807  in_dec[i] = dec_cur;
808 
809 #else
810  ra_cur = DatumGetFloat8(fetch_att(p, typbyval, typlen));
811  if (in_ra[i] != ra_cur) same = 0;
812  in_ra[i] = ra_cur;
813 
814  p = att_addlength(p, typlen, PointerGetDatum(p));
815  p = (char *) att_align(p, typalign);
816  dec_cur = DatumGetFloat8(fetch_att(p, typbyval, typlen));
817  if (in_dec[i] != dec_cur) same = 0;
818  in_dec[i] = dec_cur;
819 
820  p = att_addlength(p, typlen, PointerGetDatum(p));
821  p = (char *) att_align(p, typalign);
822 #endif
823 
824  }
825 
826  return same;
827 }
828 
829 /*****************************************************************************/
842 /*****************************************************************************/
843 PG_FUNCTION_INFO_V1(pgh3c_poly_query_it);
844 Datum pgh3c_poly_query_it(PG_FUNCTION_ARGS)
845 {
846  static h3c_coord_t in_ra[H3C_MAX_N_POLY_VERTEX], in_dec[H3C_MAX_N_POLY_VERTEX];
847  static h3c_ipix_t ipix[H3C_DEFAULT_MEM_BLOCK];
848  static int max_ipix;
849  static int nside_buf;
850 
851  ArrayType *poly_arr = PG_GETARG_ARRAYTYPE_P(0);
852  int iteration = PG_GETARG_UINT32(1);
853  int nside = PG_GETARG_UINT32(2);
854 
855  int poly_nitems = ArrayGetNItems(ARR_NDIM(poly_arr), ARR_DIMS(poly_arr));
856  int same = 1; /* the same polygon than the previous call */
857 
858  /* Taken from /pgsql/src/backend/utils/adt/arrayfuncs.c
859  * function deconstruct_array
860  */
861 
862  if (poly_nitems % 2 != 0)
863  {
864  h3c_log(H3C_ERROR, "Invalid array argument! The array should contain even number of arguments");
865  }
866  else if (poly_nitems <= 4)
867  {
868  h3c_log(H3C_ERROR, "Invalid polygon! Less than 3 vertexes");
869  }
870 
871  poly_nitems /= 2;
872 
873  same = h3c_array_push(poly_nitems, in_ra, in_dec, poly_arr);
874  if (same && (nside == nside_buf)) {
875  if (iteration < max_ipix) PG_RETURN_INT64(ipix[iteration]);
876  PG_RETURN_INT64(-1);
877  }
878 
880  max_ipix = h3c_polygon_ipix_it(in_ra,
881  in_dec,
882  poly_nitems,
883  nside,
884  ipix,
885  H3C_DEFAULT_MEM_BLOCK);
886  if (max_ipix < 1) h3c_log(H3C_ERROR, "pgh3c_poly_query_it nothing found");
887  nside_buf = nside;
888 
889  h3c_log(H3C_DEBUG, "pgh3c_poly_query_it end");
890  if (max_ipix > 0) PG_RETURN_INT64(ipix[0]);
891  PG_RETURN_INT64(-1);
892 }
893 
894 /*****************************************************************************/
905 /*****************************************************************************/
906 PG_FUNCTION_INFO_V1(pgh3c_poly_query_it_default);
907 Datum pgh3c_poly_query_it_default(PG_FUNCTION_ARGS)
908 {
909  static h3c_coord_t in_ra[H3C_MAX_N_POLY_VERTEX], in_dec[H3C_MAX_N_POLY_VERTEX];
910  static h3c_ipix_t ipix[H3C_DEFAULT_MEM_BLOCK];
911  static int max_ipix;
912 
913  ArrayType *poly_arr = PG_GETARG_ARRAYTYPE_P(0);
914  int iteration = PG_GETARG_UINT32(1);
915 
916  int poly_nitems = ArrayGetNItems(ARR_NDIM(poly_arr), ARR_DIMS(poly_arr));
917  int same = 1; /* the same polygon than the previous call */
918 
919  /* Taken from /pgsql/src/backend/utils/adt/arrayfuncs.c
920  * function deconstruct_array
921  */
922 
923  if (poly_nitems % 2 != 0)
924  {
925  h3c_log(H3C_ERROR, "Invalid array argument! The array should contain even number of arguments");
926  }
927  else if (poly_nitems <= 4)
928  {
929  h3c_log(H3C_ERROR, "Invalid polygon! Less than 3 vertexes");
930  }
931 
932  poly_nitems /= 2;
933 
934  same = h3c_array_push(poly_nitems, in_ra, in_dec, poly_arr);
935  if (same) {
936  if (iteration < max_ipix) PG_RETURN_INT64(ipix[iteration]);
937  PG_RETURN_INT64(-1);
938  }
939 
941  max_ipix = h3c_polygon_ipix_it(in_ra,
942  in_dec,
943  poly_nitems,
944  H3C_DEFAULT_NSIDE,
945  ipix,
946  H3C_DEFAULT_MEM_BLOCK);
947  if (max_ipix < 0) h3c_log(H3C_ERROR, "pgh3c_poly_query_it_default nothing found");
948 
949  h3c_log(H3C_DEBUG, "pgh3c_poly_query_it_default end");
950  if (max_ipix > 0) PG_RETURN_INT64(ipix[0]);
951  PG_RETURN_INT64(-1);
952 }
953 
954 /*****************************************************************************/
962 /*****************************************************************************/
963 PG_FUNCTION_INFO_V1(pgh3c_box_to_poly);
964 Datum pgh3c_box_to_poly(PG_FUNCTION_ARGS)
965 {
966  static ArrayType *result;
967  Datum *data;
968  int16 typlen;
969  bool typbyval;
970  char typalign;
971 
972  static h3c_coord_t in_ra[4];
973  static h3c_coord_t in_dec[4];
974  static h3c_coord_t ra_cen_buf, dec_cen_buf;
975  static h3c_coord_t width_buf, height_buf;
976 
977  if (PG_GETARG_FLOAT8(0) == ra_cen_buf &&
978  PG_GETARG_FLOAT8(1) == dec_cen_buf &&
979  PG_GETARG_FLOAT8(2) == width_buf &&
980  PG_GETARG_FLOAT8(3) == height_buf) {
981 
982  }
983  else {
984  ra_cen_buf = PG_GETARG_FLOAT8(0);
985  dec_cen_buf = PG_GETARG_FLOAT8(1);
986  width_buf = PG_GETARG_FLOAT8(2);
987  height_buf = PG_GETARG_FLOAT8(3);
988 
989  h3c_box_2_polygon(PG_GETARG_FLOAT8(0),
990  PG_GETARG_FLOAT8(1),
991  PG_GETARG_FLOAT8(2),
992  PG_GETARG_FLOAT8(3),
993  in_ra, in_dec);
994  }
995 
996  data = ( Datum *) palloc(sizeof(Datum)*8);
997  data[0] = Float8GetDatum (in_ra[0]);
998  data[1] = Float8GetDatum (in_dec[0]);
999  data[2] = Float8GetDatum (in_ra[1]);
1000  data[3] = Float8GetDatum (in_dec[1]);
1001  data[4] = Float8GetDatum (in_ra[2]);
1002  data[5] = Float8GetDatum (in_dec[2]);
1003  data[6] = Float8GetDatum (in_ra[3]);
1004  data[7] = Float8GetDatum (in_dec[3]);
1005 
1006  /* get required info about the element type */
1007  get_typlenbyvalalign(FLOAT8OID, &typlen, &typbyval, &typalign);
1008 
1009  /* now build the array */
1010  result = construct_array(data, 8, FLOAT8OID, typlen, typbyval, typalign);
1011 
1012  PG_RETURN_ARRAYTYPE_P(result);
1013 }
1014 
1015 #if 0
1016 /*****************************************************************************/
1032 /*****************************************************************************/
1033 PG_FUNCTION_INFO_V1(pgh3c_box_query_it);
1034 Datum pgh3c_box_query_it(PG_FUNCTION_ARGS)
1035 {
1036  static int invocation=0;
1037  static h3c_coord_t ra_cen_buf,dec_cen_buf, height_buf, width_buf;
1038  static h3c_ipix_t ipix[H3C_DEFAULT_MEM_BLOCK];
1039  static int max_ipix;
1040  static int nside_buf;
1041  h3c_coord_t in_ra[4], in_dec[4];
1042 
1043  h3c_coord_t ra_cen = PG_GETARG_FLOAT8(0);
1044  h3c_coord_t dec_cen = PG_GETARG_FLOAT8(1);
1045  h3c_coord_t width = PG_GETARG_FLOAT8(2);
1046  h3c_coord_t height = PG_GETARG_FLOAT8(3);
1047 
1048  int iteration = PG_GETARG_UINT32(4);
1049  int nside = PG_GETARG_UINT32(5);
1050 
1051 
1052  if (invocation == 0)
1053  /* If this is the first invocation of the function */
1054  {
1055  /* I should set invocation=1 ONLY!!! after setting ra_cen_buf, dec_cen_buf and
1056  * ipix_buf. Because if the program will be canceled or crashed
1057  * for some reason the invocation should be == 0
1058  */
1059  h3c_log(H3C_INFO, "initialize pgh3c_box_query_it");
1060  }
1061  else
1062  {
1063  if ((ra_cen == ra_cen_buf) && (dec_cen == dec_cen_buf)
1064  && (height == height_buf) && (width == width_buf)
1065  && nside == nside_buf)
1066  {
1067  if (iteration < max_ipix) PG_RETURN_INT64(ipix[iteration]);
1068  PG_RETURN_INT64(-1);
1069  }
1070  }
1071 
1072  _box_2_polygon(ra_cen, dec_cen, width, height, in_ra, in_de);
1073 
1075  max_ipix = h3c_polygon_ipix_it(in_ra,
1076  in_dec,
1077  4,
1078  nside,
1079  ipix,
1080  H3C_DEFAULT_MEM_BLOCK);
1081  if (max_ipix < 1) h3c_log(H3C_ERROR, "pgh3c_box_query_it nothing found");
1082 
1083  nside_buf = nside;
1084  invocation = 1;
1085  ra_cen_buf = ra_cen;
1086  dec_cen_buf = dec_cen;
1087  width_buf = width;
1088  height_buf = height;
1089 
1090  h3c_log(H3C_DEBUG, "pgh3c_box_query_it end");
1091  if (max_ipix > 0) PG_RETURN_INT64(ipix[0]);
1092  PG_RETURN_INT64(-1);
1093 }
1094 
1095 /*****************************************************************************/
1109 /*****************************************************************************/
1110 PG_FUNCTION_INFO_V1(pgh3c_box_query_it_default);
1111 Datum pgh3c_box_query_it_default(PG_FUNCTION_ARGS)
1112 {
1113  static int invocation=0;
1114  static h3c_coord_t ra_cen_buf,dec_cen_buf, height_buf, width_buf;
1115  static h3c_ipix_t ipix[H3C_DEFAULT_MEM_BLOCK];
1116  static int max_ipix;
1117  h3c_coord_t in_ra[4], in_dec[4];
1118 
1119  h3c_coord_t ra_cen = PG_GETARG_FLOAT8(0);
1120  h3c_coord_t dec_cen = PG_GETARG_FLOAT8(1);
1121  h3c_coord_t width = PG_GETARG_FLOAT8(2);
1122  h3c_coord_t height = PG_GETARG_FLOAT8(3);
1123 
1124  int iteration = PG_GETARG_UINT32(4);
1125 
1126  if (invocation == 0)
1127  /* If this is the first invocation of the function */
1128  {
1129  /* I should set invocation=1 ONLY!!! after setting ra_cen_buf, dec_cen_buf and
1130  * ipix_buf. Because if the program will be canceled or crashed
1131  * for some reason the invocation should be == 0
1132  */
1133  h3c_log(H3C_INFO, "initialize pgh3c_box_query_it");
1134  }
1135  else
1136  {
1137  if ((ra_cen == ra_cen_buf) && (dec_cen == dec_cen_buf)
1138  && (height == height_buf) && (width == width_buf))
1139  {
1140  if (iteration < max_ipix) PG_RETURN_INT64(ipix[iteration]);
1141  PG_RETURN_INT64(-1);
1142  }
1143  }
1144 
1145  _box_2_polygon(ra_cen, dec_cen, width, height, in_ra, in_de);
1146 
1147  if (iteration ==0)
1148  h3c_log(H3C_DEBUG, "pgh3c_box_query_it: update to polygon h3c_poly_query: (%f,%f),(%f,%f), (%f,%f), (%f,%f)",
1149  in_ra[0], in_dec[0], in_ra[1], in_dec[1], in_ra[2], in_dec[2], in_ra[3], in_dec[3]);
1150 
1152  max_ipix = h3c_polygon_ipix_it(in_ra,
1153  in_dec,
1154  4,
1155  H3C_DEFAULT_NSIDE,
1156  ipix,
1157  H3C_DEFAULT_MEM_BLOCK);
1158  if (max_ipix < 1) h3c_log(H3C_ERROR, "pgh3c_box_query_it nothing found");
1159 
1160  invocation = 1;
1161  ra_cen_buf = ra_cen;
1162  dec_cen_buf = dec_cen;
1163  width_buf = width;
1164  height_buf = height;
1165 
1166  h3c_log(H3C_DEBUG, "pgh3c_box_query_it end");
1167  if (max_ipix > 0) PG_RETURN_INT64(ipix[0]);
1168  PG_RETURN_INT64(-1);
1169 }
1170 #endif
1171 /*****************************************************************************/
1187 /*****************************************************************************/
1188 PG_FUNCTION_INFO_V1(pgh3c_in_poly_convex);
1189 Datum pgh3c_in_poly_convex(PG_FUNCTION_ARGS)
1190 {
1191  static h3c_coord_t in_ra[H3C_MAX_N_POLY_VERTEX], in_dec[H3C_MAX_N_POLY_VERTEX];
1192 
1193  ArrayType *poly_arr = PG_GETARG_ARRAYTYPE_P(2);
1194  h3c_coord_t ra_cen = PG_GETARG_FLOAT8(0);
1195  h3c_coord_t dec_cen = PG_GETARG_FLOAT8(1);
1196 
1197  int poly_nitems = ArrayGetNItems(ARR_NDIM(poly_arr), ARR_DIMS(poly_arr));
1198  static bool result;
1199 
1200  /*h3c_debug_init_clock();*/
1201 
1202  /* Taken from /pgsql/src/backend/utils/adt/arrayfuncs.c
1203  * function deconstruct_array
1204  */
1205 
1206  if (poly_nitems % 2 != 0)
1207  {
1208  h3c_log(H3C_ERROR, "Invalid array argument! The array should contain even number of arguments");
1209  }
1210  else if (poly_nitems <= 4)
1211  {
1212  h3c_log(H3C_ERROR, "Invalid polygon! Less than 3 vertexes");
1213  }
1214 
1215  poly_nitems /= 2;
1216 
1217  h3c_array_push(poly_nitems, in_ra, in_dec, poly_arr);
1218  if ( !h3c_poly_is_convex(poly_nitems, in_ra, in_dec)) {
1219  h3c_log(H3C_ERROR, "The polygon is not convex");
1220  }
1221 
1222  result = (h3c_check_sphere_point_in_poly_convex(poly_nitems, in_ra, in_dec,
1223  ra_cen, dec_cen)) != H3C_DISJUNCT;
1224 
1225  /*h3c_debug("pgh3c_in_poly_convex end");*/
1226  PG_RETURN_BOOL((result));
1227 }
1228 
1229 /*****************************************************************************/
1241 /*****************************************************************************/
1242 PG_FUNCTION_INFO_V1(pgh3c_in_poly);
1243 Datum pgh3c_in_poly(PG_FUNCTION_ARGS)
1244 {
1245  static h3c_coord_t in_ra[H3C_MAX_N_POLY_VERTEX], in_dec[H3C_MAX_N_POLY_VERTEX];
1246 
1247  ArrayType *poly_arr = PG_GETARG_ARRAYTYPE_P(2);
1248  h3c_coord_t ra_cen = PG_GETARG_FLOAT8(0);
1249  h3c_coord_t dec_cen = PG_GETARG_FLOAT8(1);
1250 
1251  int poly_nitems = ArrayGetNItems(ARR_NDIM(poly_arr), ARR_DIMS(poly_arr));
1252  static bool result;
1253 
1254  /*h3c_debug_init_clock();*/
1255 
1256  /* Taken from /pgsql/src/backend/utils/adt/arrayfuncs.c
1257  * function deconstruct_array
1258  */
1259 
1260  if (poly_nitems % 2 != 0)
1261  {
1262  h3c_log(H3C_ERROR, "Invalid array argument! The array should contain even number of arguments");
1263  }
1264  else if (poly_nitems <= 4)
1265  {
1266  h3c_log(H3C_ERROR, "Invalid polygon! Less than 3 vertexes");
1267  }
1268 
1269  poly_nitems /= 2;
1270 
1271  h3c_array_push(poly_nitems, in_ra, in_dec, poly_arr);
1272 
1273  result = (h3c_check_sphere_point_in_poly(poly_nitems, in_ra, in_dec,
1274  ra_cen, dec_cen)) != H3C_DISJUNCT;
1275 
1276  /*h3c_debug("pgh3c_in_poly end");*/
1277  PG_RETURN_BOOL((result));
1278 }
1279 
1280 #if 0
1281 /*****************************************************************************/
1289 /*****************************************************************************/
1290 PG_FUNCTION_INFO_V1(pgh3c_in_box);
1291 Datum pgh3c_in_box(PG_FUNCTION_ARGS)
1292 {
1293  h3c_coord_t in_ra[4], in_dec[4];
1294  h3c_coord_t ra_cen = PG_GETARG_FLOAT8(0);
1295  h3c_coord_t dec_cen = PG_GETARG_FLOAT8(1);
1296  h3c_coord_t width = PG_GETARG_FLOAT8(2);
1297  h3c_coord_t height = PG_GETARG_FLOAT8(3);
1298 
1299  _box_2_polygon(ra_cen, dec_cen, width, height, in_ra, in_dec);
1300 
1301  result = (h3c_check_sphere_point_in_poly(poly_nitems, in_ra, in_dec,
1302  ra_cen, dec_cen)) != H3C_DISJUNCT;
1303 
1304  /*h3c_debug("pgh3c_in_poly end");*/
1305  PG_RETURN_BOOL((result));
1306 }
1307 #endif
1308 
1309 /*****************************************************************************/
1314 /*****************************************************************************/
1315 PG_FUNCTION_INFO_V1(pgh3c_poly_center);
1316 Datum pgh3c_poly_center(PG_FUNCTION_ARGS)
1317 {
1318  static h3c_coord_t in_ra[H3C_MAX_N_POLY_VERTEX], in_dec[H3C_MAX_N_POLY_VERTEX];
1319  ArrayType *poly_arr = PG_GETARG_ARRAYTYPE_P(0);
1320  int poly_nitems = ArrayGetNItems(ARR_NDIM(poly_arr), ARR_DIMS(poly_arr));
1321  h3c_coord_t radec[2];
1322  Datum *data;
1323  int16 typlen;
1324  bool typbyval;
1325  char typalign;
1326  ArrayType *result;
1327 
1328  if (poly_nitems % 2 != 0)
1329  {
1330  h3c_log(H3C_ERROR, "Invalid array argument! The array should contain even number of arguments");
1331  }
1332  else if (poly_nitems <= 4)
1333  {
1334  h3c_log(H3C_ERROR, "Invalid polygon! Less than 3 vertexes");
1335  }
1336 
1337  poly_nitems /= 2;
1338 
1339  h3c_array_push(poly_nitems, in_ra, in_dec, poly_arr);
1340  if ( !h3c_poly_is_convex(poly_nitems, in_ra, in_dec)) {
1341  h3c_log(H3C_ERROR, "The polygon is not convex");
1342  }
1343 
1344  h3c_poly_center(poly_nitems, in_ra, in_dec, radec);
1345 
1346  data = ( Datum *) palloc(sizeof(Datum)*2);
1347  data[0] = Float8GetDatum (radec[0]);
1348  data[1] = Float8GetDatum (radec[1]);
1349  /* get required info about the element type */
1350  get_typlenbyvalalign(FLOAT8OID, &typlen, &typbyval, &typalign);
1351 
1352  /* now build the array */
1353  result = construct_array(data, 2, FLOAT8OID, typlen, typbyval, typalign);
1354 
1355  PG_RETURN_ARRAYTYPE_P(result);
1356 }
1357 
1358 /*****************************************************************************/
1365 /*****************************************************************************/
1366 PG_FUNCTION_INFO_V1(pgh3c_circle_intersect_poly);
1367 Datum pgh3c_circle_intersect_poly(PG_FUNCTION_ARGS)
1368 {
1369  static h3c_coord_t in_ra[H3C_MAX_N_POLY_VERTEX], in_dec[H3C_MAX_N_POLY_VERTEX];
1370  static bool result;
1371  int poly_nitems;
1372  ArrayType *poly_arr;
1373 
1374  h3c_coord_t ra_cen = PG_GETARG_FLOAT8(0);
1375  h3c_coord_t dec_cen = PG_GETARG_FLOAT8(1);
1376  h3c_coord_t radius = PG_GETARG_FLOAT8(2);
1377  poly_arr = PG_GETARG_ARRAYTYPE_P(3);
1378 
1379  poly_nitems = ArrayGetNItems(ARR_NDIM(poly_arr), ARR_DIMS(poly_arr));
1380  if (poly_nitems % 2 != 0)
1381  {
1382  h3c_log(H3C_ERROR, "Invalid array argument! The array should contain even number of arguments");
1383  }
1384  else if (poly_nitems <= 4)
1385  {
1386  h3c_log(H3C_ERROR, "Invalid polygon! Less than 3 vertexes");
1387  }
1388  poly_nitems /= 2;
1389 
1390  h3c_array_push(poly_nitems, in_ra, in_dec, poly_arr);
1391  if ( !h3c_poly_is_convex(poly_nitems, in_ra, in_dec)) {
1392  h3c_log(H3C_ERROR, "The polygon is not convex");
1393  }
1394 
1395  result = (h3c_check_sphere_circle_intersect_poly(poly_nitems, in_ra, in_dec,
1396  ra_cen, dec_cen, radius)) != H3C_DISJUNCT;
1397 
1398  PG_RETURN_BOOL((result));
1399 }
1400 
1401 /*****************************************************************************/
1407 /*****************************************************************************/
1408 PG_FUNCTION_INFO_V1(pgh3c_poly_intersect_poly);
1409 Datum pgh3c_poly_intersect_poly(PG_FUNCTION_ARGS)
1410 {
1411  static h3c_coord_t in_ra1[H3C_MAX_N_POLY_VERTEX], in_dec1[H3C_MAX_N_POLY_VERTEX];
1412  static h3c_coord_t in_ra2[H3C_MAX_N_POLY_VERTEX], in_dec2[H3C_MAX_N_POLY_VERTEX];
1413  static bool result;
1414  int poly_nitems1, poly_nitems2;
1415  ArrayType *poly_arr1, *poly_arr2;
1416 
1417  poly_arr1 = PG_GETARG_ARRAYTYPE_P(0);
1418  poly_arr2 = PG_GETARG_ARRAYTYPE_P(1);
1419 
1420  poly_nitems1 = ArrayGetNItems(ARR_NDIM(poly_arr1), ARR_DIMS(poly_arr1));
1421  if (poly_nitems1 % 2 != 0)
1422  {
1423  h3c_log(H3C_ERROR, "Invalid array argument! The array should contain even number of arguments");
1424  }
1425  else if (poly_nitems1 <= 4)
1426  {
1427  h3c_log(H3C_ERROR, "Invalid polygon! Less than 3 vertexes");
1428  }
1429  poly_nitems1 /= 2;
1430 
1431  h3c_array_push(poly_nitems1, in_ra1, in_dec1, poly_arr1);
1432  if ( !h3c_poly_is_convex(poly_nitems1, in_ra1, in_dec1)) {
1433  h3c_log(H3C_ERROR, "The polygon1 is not convex");
1434  }
1435 
1436  poly_nitems2 = ArrayGetNItems(ARR_NDIM(poly_arr2), ARR_DIMS(poly_arr2));
1437  if (poly_nitems2 % 2 != 0)
1438  {
1439  h3c_log(H3C_ERROR, "Invalid array argument! The array should contain even number of arguments");
1440  }
1441  else if (poly_nitems2 <= 4)
1442  {
1443  h3c_log(H3C_ERROR, "Invalid polygon! Less than 3 vertexes");
1444  }
1445  poly_nitems2 /= 2;
1446 
1447  h3c_array_push(poly_nitems2, in_ra2, in_dec2, poly_arr2);
1448  if ( !h3c_poly_is_convex(poly_nitems2, in_ra2, in_dec2)) {
1449  h3c_log(H3C_ERROR, "The polygon2 is not convex");
1450  }
1451 
1452  result = (h3c_check_poly_intersect_poly(poly_nitems1, in_ra1, in_dec1,
1453  poly_nitems2, in_ra2, in_dec2)) != H3C_DISJUNCT;
1454 
1455  PG_RETURN_BOOL((result));
1456 }
1457 
1458 /*****************************************************************************/
1464 /*****************************************************************************/
1465 PG_FUNCTION_INFO_V1(pgh3c_dist_ipix);
1466 Datum pgh3c_dist_ipix(PG_FUNCTION_ARGS)
1467 {
1468  h3c_coord_t coo1[2], coo2[2], d;
1469  h3c_ipix_t ipix1 = PG_GETARG_INT64(0);
1470  h3c_ipix_t ipix2 = PG_GETARG_INT64(1);
1471 
1472  h3c_pix2ang_nest(H3C_DEFAULT_NSIDE,
1473  ipix1,
1474  &coo1[1],
1475  &coo1[0]);
1476  coo1[1]=h3c_theta2dec(coo1[1])*H3C_RADEG;
1477  coo1[0]=h3c_phi2ra(coo1[0])*H3C_RADEG;
1478 
1479  h3c_pix2ang_nest(H3C_DEFAULT_NSIDE,
1480  ipix2,
1481  &coo2[1],
1482  &coo2[0]);
1483  coo2[1]=h3c_theta2dec(coo2[1])*H3C_RADEG;
1484  coo2[0]=h3c_phi2ra(coo2[0])*H3C_RADEG;
1485 
1486  d = h3c_dist(coo1[0], coo1[1], coo2[0], coo2[2]);
1487  PG_RETURN_FLOAT8(d);
1488 }
1489 
1490 /*****************************************************************************/
1501 /*****************************************************************************/
1502 PG_FUNCTION_INFO_V1(pgh3c_in_ellipse);
1503 Datum pgh3c_in_ellipse(PG_FUNCTION_ARGS)
1504 {
1505 
1506  h3c_coord_t ra = PG_GETARG_FLOAT8(0); /* ra_cen */
1507  h3c_coord_t dec = PG_GETARG_FLOAT8(1); /* dec_cen */
1508  h3c_coord_t ra_cen = PG_GETARG_FLOAT8(2); /* ra_cen */
1509  h3c_coord_t dec_cen = PG_GETARG_FLOAT8(3); /* dec_cen */
1510  h3c_coord_t radius = PG_GETARG_FLOAT8(4); /* error radius */
1511  h3c_coord_t axis_ratio = PG_GETARG_FLOAT8(5); /* axis_ratio */
1512  h3c_coord_t PA = PG_GETARG_FLOAT8(6); /* PA */
1513  h3c_coord_t e = sqrt(1 - axis_ratio * axis_ratio);
1514  bool result = h3c_in_ellipse(ra_cen, dec_cen, ra,dec, radius, e, PA);
1515  PG_RETURN_BOOL(result);
1516 }
1517 
1518 /*****************************************************************************/
1527 /*****************************************************************************/
1528 PG_FUNCTION_INFO_V1(pgh3c_ellipse_query_it);
1529 Datum pgh3c_ellipse_query_it(PG_FUNCTION_ARGS)
1530 {
1531  static h3c_ipix_t ipix[H3C_DEFAULT_MEM_BLOCK];
1532  static h3c_coord_t ra_cen_buf,dec_cen_buf, radius_buf;
1533  static int invocation=0;
1534  static int nside_buf, axis_ratio_buf;
1535  h3c_coord_t ra_cen = PG_GETARG_FLOAT8(0);
1536  h3c_coord_t dec_cen = PG_GETARG_FLOAT8(1);
1537  h3c_coord_t radius = PG_GETARG_FLOAT8(2);
1538  h3c_coord_t axis_ratio = PG_GETARG_FLOAT8(3);
1539  int iteration = PG_GETARG_INT32(4);
1540  int nside = PG_GETARG_INT32(5);
1541  static int max_ipix;
1542 
1543  if (invocation == 0)
1544  /* If this is the first invocation of the function */
1545  {
1546  /* I should set invocation=1 ONLY!!! after setting ra_cen_buf, dec_cen_buf and
1547  * ipix_buf. Because if the program will be canceled or crashed
1548  * for some reason the invocation should be == 0
1549  */
1550  }
1551  else
1552  {
1553  if ((ra_cen == ra_cen_buf) && (dec_cen == dec_cen_buf) &&
1554  (radius == radius_buf) && (nside == nside_buf) &&
1555  (axis_ratio == axis_ratio_buf))
1556  {
1557  if (iteration<max_ipix) PG_RETURN_INT64(ipix[iteration]);
1558  PG_RETURN_INT64(-1);
1559  }
1560  }
1561 
1563  max_ipix = h3c_disk_ipix_it(PG_GETARG_FLOAT8(0),
1564  PG_GETARG_FLOAT8(1),
1565  PG_GETARG_FLOAT8(2)/2.,
1566  nside,
1567  ipix,
1568  H3C_DEFAULT_MEM_BLOCK) ;
1569  if (max_ipix < 0) h3c_log(H3C_ERROR, "pgh3c_ellipse_query_it nothing found");
1570 
1571  invocation = 1;
1572  ra_cen_buf = ra_cen;
1573  dec_cen_buf = dec_cen;
1574  radius_buf = radius;
1575  nside_buf = nside;
1576  axis_ratio_buf = axis_ratio;
1577 
1578  h3c_log(H3C_DEBUG, "pgh3c_ellipse_query_it end");
1579  PG_RETURN_INT64(ipix[iteration]);
1580 }
1581 
1582 /*****************************************************************************/
1587 /*****************************************************************************/
1588 PG_FUNCTION_INFO_V1(pgh3c_circle_area);
1589 Datum pgh3c_circle_area(PG_FUNCTION_ARGS)
1590 {
1591  h3c_coord_t radius = PG_GETARG_FLOAT8(0);
1592  h3c_coord_t val = sin(radius*H3C_DEGRA/2.);
1593  PG_RETURN_FLOAT8(4*H3C_PI*val*val);
1594 }
1595 
1596 /*****************************************************************************/
1601 /*****************************************************************************/
1602 PG_FUNCTION_INFO_V1(pgh3c_poly_area);
1603 Datum pgh3c_poly_area(PG_FUNCTION_ARGS)
1604 {
1605  h3c_coord_t area;
1606  static h3c_coord_t in_ra[H3C_MAX_N_POLY_VERTEX], in_dec[H3C_MAX_N_POLY_VERTEX];
1607  ArrayType *poly_arr = PG_GETARG_ARRAYTYPE_P(0);
1608  int poly_nitems = ArrayGetNItems(ARR_NDIM(poly_arr), ARR_DIMS(poly_arr));
1609 
1610  /* Taken from /pgsql/src/backend/utils/adt/arrayfuncs.c
1611  * function deconstruct_array
1612  */
1613 
1614  if (poly_nitems % 2 != 0)
1615  {
1616  h3c_log(H3C_ERROR, "Invalid array argument! The array should contain even number of arguments");
1617  }
1618  else if (poly_nitems <= 4)
1619  {
1620  h3c_log(H3C_ERROR, "Invalid polygon! Less than 3 vertexes");
1621  }
1622 
1623  poly_nitems /= 2;
1624  h3c_array_push(poly_nitems, in_ra, in_dec, poly_arr);
1625 
1627  if ( !h3c_poly_is_convex(poly_nitems, in_ra, in_dec)) {
1628  h3c_log(H3C_ERROR, "The polygon is not convex");
1629  }
1630  area = h3c_polygon_area(in_ra, in_dec, poly_nitems);
1631 
1632  h3c_log(H3C_DEBUG, "pgh3c_poly_area end");
1633  PG_RETURN_FLOAT8(area);
1634 }
1635 
1636 /*****************************************************************************/
1643 /*****************************************************************************/
1644 PG_FUNCTION_INFO_V1(pgh3c_ipix2default_it);
1645 Datum pgh3c_ipix2default_it(PG_FUNCTION_ARGS)
1646 {
1647  static h3c_ipix_t m_ipix[2];
1648  static h3c_ipix_t ipix_buf, nside_buf;
1649  static int invocation = 0;
1650  h3c_ipix_t ipix = PG_GETARG_INT32(0);
1651  int nside = PG_GETARG_INT32(1);
1652  int iteration = PG_GETARG_INT32(2);
1653  int order, order_default;
1654 
1655  if (invocation == 0)
1656  /* If this is the first invocation of the function */
1657  {
1658  /* I should set invocation=1 ONLY!!! after setting ra_cen_buf, dec_cen_buf and
1659  * ipix_buf. Because if the program will be canceled or crashed
1660  * for some reason the invocation should be == 0
1661  */
1662  }
1663  else
1664  {
1665  if ((ipix == ipix_buf) && (nside == nside_buf))
1666  {
1667  if (iteration < 2) PG_RETURN_INT64(m_ipix[iteration]);
1668  PG_RETURN_INT64(-1);
1669  }
1670  }
1671 
1672  order_default = h3c_order(H3C_DEFAULT_NSIDE);
1673  order = h3c_order(nside);
1674  if (order == order_default) {
1675  m_ipix[0] = ipix;
1676  m_ipix[1] = ipix+1;
1677  }
1678  else if (order < order_default) {
1679  m_ipix[0] = ipix<<(order_default-order)*2;
1680  m_ipix[1] = (ipix+1)<<(order_default-order)*2;
1681  }
1682  else {
1683  m_ipix[0] = ipix>>(order_default-order)*2;
1684  m_ipix[1] = (ipix+1)>>(order_default-order)*2;
1685  }
1686 
1687  invocation = 1;
1688  ipix_buf = ipix;
1689  nside_buf = nside;
1690 
1691  h3c_log(H3C_DEBUG, "pgh3c_ipix2default_it");
1692  PG_RETURN_INT64(m_ipix[iteration]);
1693 }
1694 
1695 /*****************************************************************************/
1699 /*****************************************************************************/
1700 PG_FUNCTION_INFO_V1(pgh3c_nside_config);
1701 Datum pgh3c_nside_config(PG_FUNCTION_ARGS)
1702 {
1703  PG_RETURN_INT64(H3C_DEFAULT_NSIDE);
1704 }
1705 
1706 
h3c_sindist
h3c_coord_t h3c_sindist(h3c_coord_t ra1, h3c_coord_t dec1, h3c_coord_t ra2, h3c_coord_t dec2)
calculate the sinus distance (to be compatible with Q3C)
Definition: h3c_util.c:486
h3c_log
void h3c_log(int level, char *fmt,...)
print statistics
Definition: h3c_util.c:57
h3c_dist
h3c_coord_t h3c_dist(h3c_coord_t ra1, h3c_coord_t dec1, h3c_coord_t ra2, h3c_coord_t dec2)
calculate the distance between 2 points
Definition: h3c_util.c:460
h3c_ra2phi
h3c_coord_t h3c_ra2phi(h3c_coord_t ra)
get the phi value from the right ascension
Definition: h3c_util.c:161
h3c_dec2theta
h3c_coord_t h3c_dec2theta(h3c_coord_t dec)
get the theta value from the declination
Definition: h3c_util.c:136
h3c_debug_init_clock
void h3c_debug_init_clock()
initalize the debugger timer
Definition: h3c_util.c:114
h3c_theta2dec
h3c_coord_t h3c_theta2dec(h3c_coord_t theta)
get the declination from the theta value
Definition: h3c_util.c:125
h3c_phi2ra
h3c_coord_t h3c_phi2ra(h3c_coord_t phi)
get the right ascension from the phi value
Definition: h3c_util.c:149
h3c_poly_is_convex
int h3c_poly_is_convex(int n, h3c_coord_t *in_ra, h3c_coord_t *in_dec)
verify if the polygon is convex
Definition: h3c_poly_more.c:220
h3c_disk_ipix
h3c_ipix_t * h3c_disk_ipix(h3c_coord_t ra, h3c_coord_t dec, h3c_coord_t radius, int nside, int *count)
(c++ interface) get the ipix list of a cone
Definition: h3c_util.c:225
h3c_order
int h3c_order(int nside)
get the order from the nside number
Definition: h3c_util.c:173
h3c_check_sphere_point_in_poly_convex
int h3c_check_sphere_point_in_poly_convex(int n, h3c_coord_t *in_ra, h3c_coord_t *in_dec, h3c_coord_t ra0, h3c_coord_t dec0)
verify if a point is inside a convex polygon
Definition: h3c_poly_more.c:185
common.h
h3c_util.h
usefull functions in the library heaplix for PostgreSQL
h3c_check_poly_intersect_poly
int h3c_check_poly_intersect_poly(int n1, h3c_coord_t in_ra1[], h3c_coord_t in_dec1[], int n2, h3c_coord_t in_ra2[], h3c_coord_t in_dec2[])
check if a polygon intersects a vertex of an other polygon
Definition: h3c_poly_more.c:575
h3c_check_sphere_circle_intersect_poly
int h3c_check_sphere_circle_intersect_poly(int n, h3c_coord_t in_ra[], h3c_coord_t in_dec[], h3c_coord_t ra0, h3c_coord_t dec0, h3c_coord_t radius)
check if a circle intersects a vertex of a polygon
Definition: h3c_poly_more.c:320
h3c_in_ellipse
char h3c_in_ellipse(h3c_coord_t alpha, h3c_coord_t delta0, h3c_coord_t alpha1, h3c_coord_t delta01, h3c_coord_t d0, h3c_coord_t e, h3c_coord_t PA0)
verify if a point is inside an ellipse
Definition: h3c_util.c:615
h3c_poly_center
void h3c_poly_center(int, h3c_coord_t *, h3c_coord_t *, h3c_coord_t *)
get the polgon center
Definition: h3c_poly_more.c:86
h3c_polygon_area
h3c_coord_t h3c_polygon_area(h3c_coord_t *in_ra, h3c_coord_t *in_dec, int n)
calculate the area of a polygon
Definition: h3c_poly_more.c:649