New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
DM-34721: miscellaneous cleanups and union/intersection regions #37
Conversation
This implements DM-15200. These release() calls were originally a workaround for a pybind11 bug that has since been fixed upstream.
It's understandable that the general implementation of these operations doesn't handle this case the way we'd like due to round-off error, and the old behavior isn't even wrong, given their clearly-documented limited guarantees. But it's very nice for unit tests at least to satisfy "equality is equivalent to CONTAINS and WITHIN".
#else | ||
union { uint64_t u; double d; }; | ||
d = item; | ||
buffer.push_back(static_cast<uint8_t>(u)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You might consider a resize()
here and then just using array subscripting assignments, to avoid the redundant bounds checking in eight successive push_back()
calls. OTOH, there are less than ten of them, so it's probably a shrug :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a little worried it could be an accidental pessimization, because the pattern is that lots of functions like this are going to be pushing into the same buffer
vector, and I don't actually know if resize
is going to (when the capacity isn't big enough) allocate just the amount of extra space needed or do the kind of "allocate more than you did last time" thing that keeps push_back
amortized constant-time. Do you happen to know?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. I think you could call capacity()
before resize()
to avoid the undesired behavior, but I have also just realized the the resize()
is going to have to do a default init on all eight slots, so that will have a cost as well.
In any case, for eight items per batch I think it's hard to argue convincingly that there would be much of a win or loss here in the end.
include/lsst/sphgeom/python/utils.h
Outdated
/// Create a vector of Region (or Region-subclass) pointers by copying the | ||
/// regions from a sized Python iterable (e.g. S == py::tuple). | ||
/// | ||
/// Note that the pybind11 built-in STL conversions don't work, because they we |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo: "they we"
// within it. | ||
| ((r1 & WITHIN) & (r2 & WITHIN)) | ||
// If either operand contains the given region, the union contains it. | ||
| ((r1 & CONTAINS) | (r2 & CONTAINS)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about cases where neither r1 nor r2 individually contain rhs, but the union of r1 and r2 does (for example, two overlapping circles that together contain an ellipse not entirely contained by either one individually?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're absolute right about the behavior, but we're saved by the limited guarantees made by the Region
interface on the behavior; from the docs on Region::relate
:
/// Said another way: if the CONTAINS, WITHIN or DISJOINT bit is set, then
/// the corresponding spatial relationship between the two regions holds
/// conclusively. If it is not set, the relationship may or may not
/// hold.
///
/// These semantics allow for conservative relationship computations. In
/// particular, a Region may choose to implement `relate` by replacing
/// itself and/or the argument with a simplified bounding region.
It'd be nice to do better, but I think we'd at least need way for all Region
classes to be able to compute some common set of shapes they bound (rather than are bounded by), and that's a lot of hard math for still not being able to formally guarantee any more than we do.
| ((r1 & DISJOINT) | (r2 & DISJOINT)) | ||
// If either operand is within the given region, the intersection is | ||
// within it. | ||
| ((r1 & WITHIN) | (r2 & WITHIN)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there are also cases where neither operand is individually within rhs, but the intersection of the operands is (consider two overlapping circles, and rhs an ellipse that surrounds the intersection but extends outside both of the circles)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(other thread on related problem for unions applies here, too)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks like a nice feature to have. Some questions in comments about whether all cases are properly covered in the relate()
methods?
Additionally interesting: compound regions are the first possibly non-convex regions in this library. At first I wondered if this might violate some assumptions elsewhere in the library (e.g. in various pixelization codes) but I didn't see any issues with this offhand...
That's a good question, but I don't have a strong enough understanding of what "convex" means for general regions on the sphere to tell if it is qualitatively new in that respect. It certainly does permit non-convex great-circle polygons, which we didn't before, but we could already define |
6bf440d
to
f9daf64
Compare
No description provided.