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