1 2cdef class BooleanSelector(SelectorObject): 3 4 def __init__(self, dobj): 5 # Note that this has a different API than the other selector objects, 6 # so will not work as a traditional data selector. 7 if not hasattr(dobj.dobj1, "selector"): 8 self.sel1 = dobj.dobj1 9 else: 10 self.sel1 = dobj.dobj1.selector 11 if not hasattr(dobj.dobj2, "selector"): 12 self.sel2 = dobj.dobj2 13 else: 14 self.sel2 = dobj.dobj2.selector 15 16cdef class BooleanANDSelector(BooleanSelector): 17 cdef int select_bbox(self, np.float64_t left_edge[3], 18 np.float64_t right_edge[3]) nogil: 19 cdef int rv1 = self.sel1.select_bbox(left_edge, right_edge) 20 if rv1 == 0: return 0 21 cdef int rv2 = self.sel2.select_bbox(left_edge, right_edge) 22 if rv2 == 0: return 0 23 return 1 24 25 cdef int select_bbox_edge(self, np.float64_t left_edge[3], 26 np.float64_t right_edge[3]) nogil: 27 cdef int rv1 = self.sel1.select_bbox_edge(left_edge, right_edge) 28 if rv1 == 0: return 0 29 cdef int rv2 = self.sel2.select_bbox_edge(left_edge, right_edge) 30 if rv2 == 0: return 0 31 return max(rv1, rv2) 32 33 cdef int select_grid(self, np.float64_t left_edge[3], 34 np.float64_t right_edge[3], np.int32_t level, 35 Oct *o = NULL) nogil: 36 cdef int rv1 = self.sel1.select_grid(left_edge, right_edge, level, o) 37 if rv1 == 0: return 0 38 cdef int rv2 = self.sel2.select_grid(left_edge, right_edge, level, o) 39 if rv2 == 0: return 0 40 return 1 41 42 cdef int select_cell(self, np.float64_t pos[3], np.float64_t dds[3]) nogil: 43 cdef int rv1 = self.sel1.select_cell(pos, dds) 44 if rv1 == 0: return 0 45 cdef int rv2 = self.sel2.select_cell(pos, dds) 46 if rv2 == 0: return 0 47 return 1 48 49 cdef int select_point(self, np.float64_t pos[3]) nogil: 50 cdef int rv1 = self.sel1.select_point(pos) 51 if rv1 == 0: return 0 52 cdef int rv2 = self.sel2.select_point(pos) 53 if rv2 == 0: return 0 54 return 1 55 56 cdef int select_sphere(self, np.float64_t pos[3], np.float64_t radius) nogil: 57 cdef int rv1 = self.sel1.select_sphere(pos, radius) 58 if rv1 == 0: return 0 59 cdef int rv2 = self.sel2.select_sphere(pos, radius) 60 if rv2 == 0: return 0 61 return 1 62 63 def _hash_vals(self): 64 return (self.sel1._hash_vals() + 65 ("and",) + 66 self.sel2._hash_vals()) 67 68cdef class BooleanORSelector(BooleanSelector): 69 cdef int select_bbox(self, np.float64_t left_edge[3], 70 np.float64_t right_edge[3]) nogil: 71 cdef int rv1 = self.sel1.select_bbox(left_edge, right_edge) 72 if rv1 == 1: return 1 73 cdef int rv2 = self.sel2.select_bbox(left_edge, right_edge) 74 if rv2 == 1: return 1 75 return 0 76 77 cdef int select_bbox_edge(self, np.float64_t left_edge[3], 78 np.float64_t right_edge[3]) nogil: 79 cdef int rv1 = self.sel1.select_bbox_edge(left_edge, right_edge) 80 if rv1 == 1: return 1 81 cdef int rv2 = self.sel2.select_bbox_edge(left_edge, right_edge) 82 if rv2 == 1: return 1 83 return max(rv1, rv2) 84 85 cdef int select_grid(self, np.float64_t left_edge[3], 86 np.float64_t right_edge[3], np.int32_t level, 87 Oct *o = NULL) nogil: 88 cdef int rv1 = self.sel1.select_grid(left_edge, right_edge, level, o) 89 if rv1 == 1: return 1 90 cdef int rv2 = self.sel2.select_grid(left_edge, right_edge, level, o) 91 if rv2 == 1: return 1 92 if (rv1 == 2) or (rv2 == 2): return 2 93 return 0 94 95 cdef int select_cell(self, np.float64_t pos[3], np.float64_t dds[3]) nogil: 96 cdef int rv1 = self.sel1.select_cell(pos, dds) 97 if rv1 == 1: return 1 98 cdef int rv2 = self.sel2.select_cell(pos, dds) 99 if rv2 == 1: return 1 100 return 0 101 102 cdef int select_point(self, np.float64_t pos[3]) nogil: 103 cdef int rv1 = self.sel1.select_point(pos) 104 if rv1 == 1: return 1 105 cdef int rv2 = self.sel2.select_point(pos) 106 if rv2 == 1: return 1 107 return 0 108 109 cdef int select_sphere(self, np.float64_t pos[3], np.float64_t radius) nogil: 110 cdef int rv1 = self.sel1.select_sphere(pos, radius) 111 if rv1 == 1: return 1 112 cdef int rv2 = self.sel2.select_sphere(pos, radius) 113 if rv2 == 1: return 1 114 return 0 115 116 def _hash_vals(self): 117 return (self.sel1._hash_vals() + 118 ("or",) + 119 self.sel2._hash_vals()) 120 121cdef class BooleanNOTSelector(BooleanSelector): 122 cdef int select_bbox(self, np.float64_t left_edge[3], 123 np.float64_t right_edge[3]) nogil: 124 # We always return True here, because we don't have a "fully included" 125 # check anywhere else. 126 return 1 127 128 cdef int select_bbox_edge(self, np.float64_t left_edge[3], 129 np.float64_t right_edge[3]) nogil: 130 cdef int rv1 = self.sel1.select_bbox_edge(left_edge, right_edge) 131 if rv1 == 0: return 1 132 elif rv1 == 1: return 0 133 return 2 134 135 cdef int select_grid(self, np.float64_t left_edge[3], 136 np.float64_t right_edge[3], np.int32_t level, 137 Oct *o = NULL) nogil: 138 return 1 139 140 cdef int select_cell(self, np.float64_t pos[3], np.float64_t dds[3]) nogil: 141 cdef int rv1 = self.sel1.select_cell(pos, dds) 142 if rv1 == 0: return 1 143 return 0 144 145 cdef int select_point(self, np.float64_t pos[3]) nogil: 146 cdef int rv1 = self.sel1.select_point(pos) 147 if rv1 == 0: return 1 148 return 0 149 150 cdef int select_sphere(self, np.float64_t pos[3], np.float64_t radius) nogil: 151 cdef int rv1 = self.sel1.select_sphere(pos, radius) 152 if rv1 == 0: return 1 153 return 0 154 155 def _hash_vals(self): 156 return (self.sel1._hash_vals() + 157 ("not",)) 158 159cdef class BooleanXORSelector(BooleanSelector): 160 161 cdef int select_bbox(self, np.float64_t left_edge[3], 162 np.float64_t right_edge[3]) nogil: 163 # We always return True here, because we don't have a "fully included" 164 # check anywhere else. 165 return 1 166 167 cdef int select_bbox_edge(self, np.float64_t left_edge[3], 168 np.float64_t right_edge[3]) nogil: 169 # Return 2 in cases where one or both selectors partially overlap since 170 # part of the bounding box could satisfy the condition unless the 171 # selectors are identical. 172 cdef int rv1 = self.sel1.select_bbox_edge(left_edge, right_edge) 173 cdef int rv2 = self.sel2.select_bbox_edge(left_edge, right_edge) 174 if rv1 == rv2: 175 if rv1 == 2: 176 # If not identical, part of the bbox will be touched by one 177 # selector and not the other. 178 # if self.sel1 == self.sel2: return 0 # requires gil 179 return 2 180 return 0 181 if rv1 == 0: return rv2 182 if rv2 == 0: return rv1 183 return 2 # part of bbox only touched by selector fully covering bbox 184 185 cdef int select_grid(self, np.float64_t left_edge[3], 186 np.float64_t right_edge[3], np.int32_t level, 187 Oct *o = NULL) nogil: 188 return 1 189 190 cdef int select_cell(self, np.float64_t pos[3], np.float64_t dds[3]) nogil: 191 cdef int rv1 = self.sel1.select_cell(pos, dds) 192 cdef int rv2 = self.sel2.select_cell(pos, dds) 193 if rv1 == rv2: return 0 194 return 1 195 196 cdef int select_point(self, np.float64_t pos[3]) nogil: 197 cdef int rv1 = self.sel1.select_point(pos) 198 cdef int rv2 = self.sel2.select_point(pos) 199 if rv1 == rv2: return 0 200 return 1 201 202 cdef int select_sphere(self, np.float64_t pos[3], np.float64_t radius) nogil: 203 cdef int rv1 = self.sel1.select_sphere(pos, radius) 204 cdef int rv2 = self.sel2.select_sphere(pos, radius) 205 if rv1 == rv2: return 0 206 return 1 207 208 def _hash_vals(self): 209 return (self.sel1._hash_vals() + 210 ("xor",) + 211 self.sel2._hash_vals()) 212 213cdef class BooleanNEGSelector(BooleanSelector): 214 215 cdef int select_bbox(self, np.float64_t left_edge[3], 216 np.float64_t right_edge[3]) nogil: 217 # We always return True here, because we don't have a "fully included" 218 # check anywhere else. 219 return self.sel1.select_bbox(left_edge, right_edge) 220 221 cdef int select_bbox_edge(self, np.float64_t left_edge[3], 222 np.float64_t right_edge[3]) nogil: 223 cdef int rv1 = self.sel1.select_bbox_edge(left_edge, right_edge) 224 if rv1 == 0: return 0 225 cdef int rv2 = self.sel2.select_bbox_edge(left_edge, right_edge) 226 if rv2 == 1: 227 return 0 228 elif rv2 == 0: 229 return rv1 230 # If sel2 is partial, then sel1 - sel2 will be partial as long 231 # as sel1 != sel2 232 # if self.sel1 == self.sel2: return 0 # requires gil 233 return 2 234 235 cdef int select_grid(self, np.float64_t left_edge[3], 236 np.float64_t right_edge[3], np.int32_t level, 237 Oct *o = NULL) nogil: 238 return self.sel1.select_grid(left_edge, right_edge, level, o) 239 240 cdef int select_cell(self, np.float64_t pos[3], np.float64_t dds[3]) nogil: 241 cdef int rv1 = self.sel1.select_cell(pos, dds) 242 if rv1 == 0: return 0 243 cdef int rv2 = self.sel2.select_cell(pos, dds) 244 if rv2 == 1: return 0 245 return 1 246 247 cdef int select_point(self, np.float64_t pos[3]) nogil: 248 cdef int rv1 = self.sel1.select_point(pos) 249 if rv1 == 0: return 0 250 cdef int rv2 = self.sel2.select_point(pos) 251 if rv2 == 1: return 0 252 return 1 253 254 cdef int select_sphere(self, np.float64_t pos[3], np.float64_t radius) nogil: 255 cdef int rv1 = self.sel1.select_sphere(pos, radius) 256 if rv1 == 0: return 0 257 cdef int rv2 = self.sel2.select_sphere(pos, radius) 258 if rv2 == 1: return 0 259 return 1 260 261 def _hash_vals(self): 262 return (self.sel1._hash_vals() + 263 ("neg",) + 264 self.sel2._hash_vals()) 265 266cdef class ChainedBooleanSelector(SelectorObject): 267 cdef int n_obj 268 cdef np.ndarray selectors 269 def __init__(self, dobj): 270 # These are data objects, not selectors 271 self.n_obj = len(dobj.data_objects) 272 self.selectors = np.empty(self.n_obj, dtype="object") 273 for i in range(self.n_obj): 274 self.selectors[i] = dobj.data_objects[i].selector 275 276cdef class ChainedBooleanANDSelector(ChainedBooleanSelector): 277 @cython.cdivision(True) 278 @cython.boundscheck(False) 279 @cython.wraparound(False) 280 cdef int select_bbox(self, np.float64_t left_edge[3], 281 np.float64_t right_edge[3]) nogil: 282 with gil: 283 for i in range(self.n_obj): 284 if (<SelectorObject>self.selectors[i]).select_bbox( 285 left_edge, right_edge) == 0: 286 return 0 287 return 1 288 289 @cython.cdivision(True) 290 @cython.boundscheck(False) 291 @cython.wraparound(False) 292 cdef int select_bbox_edge(self, np.float64_t left_edge[3], 293 np.float64_t right_edge[3]) nogil: 294 cdef int selected = 1 295 cdef int ret 296 with gil: 297 for i in range(self.n_obj): 298 ret = (<SelectorObject>self.selectors[i]).select_bbox_edge( 299 left_edge, right_edge) 300 if ret == 0: 301 return 0 302 elif ret == 2: 303 selected = 2 304 return selected 305 306 @cython.cdivision(True) 307 @cython.boundscheck(False) 308 @cython.wraparound(False) 309 cdef int select_grid(self, np.float64_t left_edge[3], 310 np.float64_t right_edge[3], np.int32_t level, 311 Oct *o = NULL) nogil: 312 with gil: 313 for i in range(self.n_obj): 314 if (<SelectorObject>self.selectors[i]).select_grid( 315 left_edge, right_edge, level, o) == 0: 316 return 0 317 return 1 318 319 @cython.cdivision(True) 320 @cython.boundscheck(False) 321 @cython.wraparound(False) 322 cdef int select_cell(self, np.float64_t pos[3], np.float64_t dds[3]) nogil: 323 with gil: 324 for i in range(self.n_obj): 325 if (<SelectorObject>self.selectors[i]).select_cell( 326 pos, dds) == 0: 327 return 0 328 return 1 329 330 @cython.cdivision(True) 331 @cython.boundscheck(False) 332 @cython.wraparound(False) 333 cdef int select_point(self, np.float64_t pos[3]) nogil: 334 with gil: 335 for i in range(self.n_obj): 336 if (<SelectorObject>self.selectors[i]).select_point(pos) == 0: 337 return 0 338 return 1 339 340 @cython.cdivision(True) 341 @cython.boundscheck(False) 342 @cython.wraparound(False) 343 cdef int select_sphere(self, np.float64_t pos[3], np.float64_t radius) nogil: 344 with gil: 345 for i in range(self.n_obj): 346 if (<SelectorObject>self.selectors[i]).select_sphere( 347 pos, radius) == 0: 348 return 0 349 return 1 350 351 def _hash_vals(self): 352 v = ("chained_and",) 353 for s in self.selectors: 354 v += s._hash_vals() 355 return v 356 357intersection_selector = ChainedBooleanANDSelector 358 359cdef class ChainedBooleanORSelector(ChainedBooleanSelector): 360 @cython.cdivision(True) 361 @cython.boundscheck(False) 362 @cython.wraparound(False) 363 cdef int select_bbox(self, np.float64_t left_edge[3], 364 np.float64_t right_edge[3]) nogil: 365 with gil: 366 for i in range(self.n_obj): 367 if (<SelectorObject>self.selectors[i]).select_bbox( 368 left_edge, right_edge) == 1: 369 return 1 370 return 0 371 372 @cython.cdivision(True) 373 @cython.boundscheck(False) 374 @cython.wraparound(False) 375 cdef int select_bbox_edge(self, np.float64_t left_edge[3], 376 np.float64_t right_edge[3]) nogil: 377 cdef int selected = 0 378 cdef int ret 379 with gil: 380 for i in range(self.n_obj): 381 ret = (<SelectorObject>self.selectors[i]).select_bbox_edge( 382 left_edge, right_edge) 383 if ret == 1: 384 return 1 385 elif ret == 2: 386 selected = 2 387 return selected 388 389 @cython.cdivision(True) 390 @cython.boundscheck(False) 391 @cython.wraparound(False) 392 cdef int select_grid(self, np.float64_t left_edge[3], 393 np.float64_t right_edge[3], np.int32_t level, 394 Oct *o = NULL) nogil: 395 with gil: 396 for i in range(self.n_obj): 397 if (<SelectorObject>self.selectors[i]).select_grid( 398 left_edge, right_edge, level, o) == 1: 399 return 1 400 return 0 401 402 @cython.cdivision(True) 403 @cython.boundscheck(False) 404 @cython.wraparound(False) 405 cdef int select_cell(self, np.float64_t pos[3], np.float64_t dds[3]) nogil: 406 with gil: 407 for i in range(self.n_obj): 408 if (<SelectorObject>self.selectors[i]).select_cell( 409 pos, dds) == 1: 410 return 1 411 return 0 412 413 @cython.cdivision(True) 414 @cython.boundscheck(False) 415 @cython.wraparound(False) 416 cdef int select_point(self, np.float64_t pos[3]) nogil: 417 with gil: 418 for i in range(self.n_obj): 419 if (<SelectorObject>self.selectors[i]).select_point(pos) == 1: 420 return 1 421 return 0 422 423 @cython.cdivision(True) 424 @cython.boundscheck(False) 425 @cython.wraparound(False) 426 cdef int select_sphere(self, np.float64_t pos[3], np.float64_t radius) nogil: 427 with gil: 428 for i in range(self.n_obj): 429 if (<SelectorObject>self.selectors[i]).select_sphere( 430 pos, radius) == 1: 431 return 1 432 return 0 433 434 def _hash_vals(self): 435 v = ("chained_or",) 436 for s in self.selectors: 437 v += s._hash_vals() 438 return v 439 440union_selector = ChainedBooleanORSelector 441