@@ -144,6 +144,44 @@ spg_quad_inner_consistent_box_helper(ScanKey sk, Point *centroid)
144144 return r ;
145145}
146146
147+ static int
148+ spg_quad_inner_consistent_circle_helper (ScanKey sk , Point * centroid )
149+ {
150+ /*
151+ * Evaluate distances between the query center point and the quadrants.
152+ * The distance between a set and a point is the minimal possible distance
153+ * between any set point and the point. There are three possible cases: the
154+ * point belongs to the quandrand, the point projection is on the quadrant
155+ * edge, the point projections is on the quadrant vertex.
156+ */
157+ CIRCLE * circleQuery = DatumGetCircleP (sk -> sk_argument );
158+ int r = 0 ;
159+
160+ const Point cp = {
161+ .x = float8_mi (centroid -> x , circleQuery -> center .x ),
162+ .y = float8_mi (centroid -> y , circleQuery -> center .y )
163+ };
164+
165+ const float8 x_p0 = (0. > cp .x ? 0. : cp .x );
166+ const float8 y_p0 = (0. > cp .y ? 0. : cp .y );
167+ const float8 x_n0 = (0. < cp .x ? 0. : cp .x );
168+ const float8 y_n0 = (0. < cp .y ? 0. : cp .y );
169+
170+ const float8 d [4 ] = {
171+ HYPOT (x_p0 , y_p0 ),
172+ HYPOT (x_p0 , y_n0 ),
173+ HYPOT (x_n0 , y_n0 ),
174+ HYPOT (x_n0 , y_p0 )
175+ };
176+
177+ for (int i = 0 ; i < 4 ; i ++ ) {
178+ if (d [i ] <= circleQuery -> radius )
179+ r |= (1 << (i + 1 ));
180+ }
181+
182+ return r ;
183+ }
184+
147185Datum
148186spg_quad_choose (PG_FUNCTION_ARGS )
149187{
@@ -359,7 +397,18 @@ spg_quad_inner_consistent(PG_FUNCTION_ARGS)
359397 which &= (1 << 1 ) | (1 << 4 );
360398 break ;
361399 case RTContainedByStrategyNumber :
362- which &= spg_quad_inner_consistent_box_helper (sk , centroid );
400+
401+ switch (sk -> sk_subtype ) {
402+ case BOXOID :
403+ which &= spg_quad_inner_consistent_box_helper (sk , centroid );
404+ break ;
405+ case CIRCLEOID :
406+ which &= spg_quad_inner_consistent_circle_helper (sk , centroid );
407+ break ;
408+ default :
409+ elog (ERROR , "unrecognized right type OID: %d" , sk -> sk_subtype );
410+ break ;
411+ }
363412 break ;
364413 default :
365414 elog (ERROR , "unrecognized strategy number: %d" , sk -> sk_strategy );
@@ -448,12 +497,22 @@ spg_quad_leaf_consistent(PG_FUNCTION_ARGS)
448497 break ;
449498 case RTContainedByStrategyNumber :
450499
451- /*
452- * For this operator, the query is a box not a point. We
453- * cheat to the extent of assuming that DatumGetPointP won't
454- * do anything that would be bad for a pointer-to-box.
455- */
456- res = SPTEST (box_contain_pt , query , datum );
500+ switch (sk -> sk_subtype ) {
501+ case BOXOID :
502+ /*
503+ * For this operator, the query is a box not a point. We
504+ * cheat to the extent of assuming that DatumGetPointP won't
505+ * do anything that would be bad for a pointer-to-box.
506+ */
507+ res = SPTEST (box_contain_pt , query , datum );
508+ break ;
509+ case CIRCLEOID :
510+ res = SPTEST (circle_contain_pt , query , datum );
511+ break ;
512+ default :
513+ elog (ERROR , "unrecognized right type OID: %d" , sk -> sk_subtype );
514+ break ;
515+ }
457516 break ;
458517 default :
459518 elog (ERROR , "unrecognized strategy number: %d" , sk -> sk_strategy );
0 commit comments