-
Notifications
You must be signed in to change notification settings - Fork 370
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
Allow rectangular and box masks to be rotated #845
Conversation
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.
Thank you for this, it looks good. As far as I can see, there are just some minor things to fix, see below.
topology/mask.h
Outdated
/** | ||
* Calculate the min/max x, y, z values in case of a rotated box. | ||
*/ | ||
void create_min_max_values_(); |
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.
Perhaps rename to calculate_min_max_values_
?
topology/mask_impl.h
Outdated
return ( lower_left_ <= p ) && ( p <= upper_right_ ); | ||
} | ||
|
||
// If we have a rotated box, We rotate the point down to the unrotated box, |
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.
Small w.
topology/mask_impl.h
Outdated
const double cntr_y = ( upper_right_[ 1 ] + lower_left_[ 1 ] ) * 0.5; | ||
const double cntr_z = ( upper_right_[ 2 ] + lower_left_[ 2 ] ) * 0.5; | ||
|
||
const double new_x = ( ( p[ 0 ] - cntr_x ) * azimuth_cos_ |
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.
For efficiency p[ {0|1|2} ] - cntr_{x|y|z}
can be precalculated after calculating the centres.
topology/mask_impl.h
Outdated
|
||
const double new_x = ( ( p[ 0 ] - cntr_x ) * azimuth_cos_ | ||
+ ( p[ 1 ] - cntr_y ) * azimuth_sin_ ) * polar_cos_ | ||
- ( ( p[ 2 ] - cntr_z ) * polar_sin_ ) + cntr_x; |
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.
These lines should have the same indentation.
topology/mask_impl.h
Outdated
+ ( p[ 1 ] - cntr_y ) * azimuth_cos_ + cntr_y; | ||
const double new_z = ( ( p[ 0 ] - cntr_x ) * azimuth_cos_ | ||
+ ( p[ 1 ] - cntr_y ) * azimuth_sin_ ) * polar_sin_ | ||
+ ( ( p[ 2 ] - cntr_z ) * polar_cos_ ) + cntr_z; |
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.
Give lines same indentation here too.
def test_RotatedBoxMaskByAzimuthAndPolarAngle(self): | ||
"""Test rotated box mask with azimuth and polar angle.""" | ||
|
||
pos = [[x*1., y*1., z*1.] for x in range(-2, 3) |
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.
Missing whitespace around *
-operators.
[38, 39, 44, 58, 59, 64, 69, 70, 84, 89, 90]) | ||
|
||
def test_RotatedRectangleOutsideOrigo(self): | ||
"""Test rotated rectangle where mask is outside origo.""" |
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.
As it is the mask that contains things, not origo, perhaps something along the lines of "where origo is not in mask"?
def test_RotatedBoxOutsideOrigo(self): | ||
"""Test rotated box where mask is outside origo.""" | ||
|
||
pos = [[x*1., y*1., z*1.] for x in range(-2, 3) |
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.
Missing whitespace around *
-operators.
|
||
44 | ||
14 -> 40 | ||
36 |
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.
Looks like there's something missing with these example connections.
def suite(): | ||
suite = unittest.makeSuite(RotatedRectangularMask, 'test') | ||
return suite | ||
|
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.
Two blank lines after the function definition.
calculate_min_max_values, precalculation of some of the values, indentation, changed some comments.
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.
Great, thank you!
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.
Looks quite fine, but see comments. We should discuss once more about the "eps" that we are adding, just wondering if we are digging some future grave. For 3D, we olny have two angles. Which rotation possibility are we missing?
topology/mask.h
Outdated
Position< D > lower_left_; | ||
Position< D > upper_right_; | ||
|
||
Position< D > min_values_; |
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.
Could you add a comment what these are and how they relate to lower_left/upper_right?
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.
@heplesser I have added the comment. The min/max values correspond to the lower_left/upper_right of the boundary box around the rotated box. Should I change the names to something like bbox_lower_left_
and bbox_upper_right_
to make it more clear?
* upper_right - Position of upper right corner (array of doubles) | ||
* lower_left - Position of lower left corner (array of doubles) | ||
* upper_right - Position of upper right corner (array of doubles) | ||
* azimuth_angle - Rotation angle in degrees from x-axis (double), optional |
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.
Is it documented somewhere that the angles are in degrees? Maybe also add that the polar angle does not apply to 2D.
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 have now added a note about the angles in the python documentation for masks.
topology/mask.h
Outdated
"polar_angle not defined in 2D." ); | ||
} | ||
|
||
is_rotated_ = azimuth_angle_ or polar_angle_; |
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.
Make explicit comparisons to 0!
topology/mask_impl.h
Outdated
// We need to add a small epsilon in case of rounding errors. | ||
const double x_length = upper_right_[ 0 ] - lower_left_[ 0 ]; | ||
const double y_length = upper_right_[ 1 ] - lower_left_[ 1 ]; | ||
const Position< 2 > eps( x_length * 1e-12, y_length * 1e-12 ); |
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.
We can use the cntr_*
values to determine eps
, saving some operations.
topology/mask_impl.h
Outdated
|
||
// See https://en.wikipedia.org/wiki/Rotation_matrix for more. | ||
|
||
const double cntr_x = ( upper_right_[ 0 ] + lower_left_[ 0 ] ) * 0.5; |
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.
If I am not entirely off, we need to check quite often if a point is inside a (fixed) box. Wouldn't it make more sense to precompute all values that do not depend on p
in the box constructor?
topology/mask_impl.h
Outdated
|
||
// See https://en.wikipedia.org/wiki/Rotation_matrix for more. | ||
|
||
const double cntr_x = ( upper_right_[ 0 ] + lower_left_[ 0 ] ) * 0.5; |
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.
Same comments apply as for 2D.
topology/mask_impl.h
Outdated
Position< 2 > upper_right_cos = ( upper_right_ - cntr ) * azimuth_cos_; | ||
Position< 2 > upper_right_sin = ( upper_right_ - cntr ) * azimuth_sin_; | ||
|
||
double rotatedLLx = lower_left_cos[ 0 ] - lower_left_sin[ 1 ] + cntr_x; |
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 suppose these can call be const
?
topology/mask_impl.h
Outdated
double rotatedLLLx = | ||
( lower_left_cos[ 0 ] - lower_left_sin[ 1 ] ) * polar_cos_ | ||
- lower_left_polar_sin + cntr_x; | ||
double rotatedLLLy = lower_left_sin[ 0 ] + lower_left_cos[ 1 ] + cntr_y; |
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.
Can't these all be const?
position is pre-calculated in constructor, added some const, eps no longer calculated from length, but just a constant, small number.
@heplesser thank you for your review! I have tried to address your comments, please take a look. I changed the "eps" to be constant When it comes to the rotation angles, we are missing rotation from the y-axis to the z-axis (the γ here ). Do you want me to add it? We do not have it for the elliptical mask, but I could add it there as well and make a PR of course. |
@stinebuu Thanks for addressing the issues. I think this ready to merge now. Would you create a follow-up issue to add rotation about the third Euler angle? |
This PR adds the optional parameters
azimuth_angle
andpolar_angle
to the rectangular and box mask dictionaries so that the masks can be rotated.This have led to some changes in the
boxMask
class, most notably with theinside(..)
function and when finding the boundary box. When checking if a point is inside the mask, we have to take rotation into account. If we have rotation, we can no longer uselower_left
andupper_right
to define the boundary box, so we have to calculate the minimum and maximum values of the mask. This is done increate_min_max_values_()
.The functions check to see if we have rotation as much as possible, so that we can use
lower_left
andupper_right
and avoid unnecessary rotation calculations if we do not have rotation.I have also added a test.