Skip to content
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

Adds a Quadrilateral primitive #1181

Merged
merged 26 commits into from
Sep 28, 2023
Merged

Conversation

adayton1
Copy link
Member

@adayton1 adayton1 commented Sep 8, 2023

Summary

  • This PR is a feature
  • It does the following:
    • Adds Quadrilateral primitive
    • Adds BoundingBox constructor that takes an initializer list
    • Adds compute_bounding_box operator for Quadrilateral

@adayton1
Copy link
Member Author

Is there a command I can use to do automatic formatting since the style check is failing?

@kennyweiss
Copy link
Member

Is there a command I can use to do automatic formatting since the style check is failing?

Thanks @adayton1 -- make style from the build directory should do the trick.

@adayton1
Copy link
Member Author

Can someone tell me why the ci/gitlab/lc.llnl.gov pipeline failed? I don't have access to view that page.

@bmhan12
Copy link
Contributor

bmhan12 commented Sep 12, 2023

Can someone tell me why the ci/gitlab/lc.llnl.gov pipeline failed? I don't have access to view that page.

This was the error for jobs with CUDA enabled:
/usr/WS1/atk/gitlab-runner/builds/zkQzXxmM/002/gitlab/axom/axom/src/axom/spin/tests/spin_bvh.cpp(1868): error: copy-list-initialization cannot use a constructor marked "explicit"

Error message in HIP enabled jobs:

/usr/WS1/atk/gitlab-runner/builds/9YsVm9VV/001/gitlab/axom/axom/src/axom/spin/tests/spin_bvh.cpp:1868:20: error: chosen constructor is explicit in copy-initialization
      boxes[idx] = {PointType(0.), PointType(1.)};
                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/WS1/atk/gitlab-runner/builds/9YsVm9VV/001/gitlab/axom/axom/src/axom/core/../../axom/primal/geometry/BoundingBox.hpp:101:12: note: explicit constructor declared here
  explicit BoundingBox(std::initializer_list<PointType> pts);
           ^
/usr/WS1/atk/gitlab-runner/builds/9YsVm9VV/001/gitlab/axom/axom/src/axom/core/../../axom/primal/geometry/BoundingBox.hpp:67:7: note: passing argument to parameter here
class BoundingBox
      ^

@kennyweiss
Copy link
Member

Can someone tell me why the ci/gitlab/lc.llnl.gov pipeline failed? I don't have access to view that page.

Looks like with your new initializer list constructor, it needs:

  // single bounding box in [0,1] x [0,1] x [0,1]
  BoxType* boxes = axom::allocate<BoxType>(1, allocID);
  axom::for_all<exec>(
    0,
    1,
    AXOM_LAMBDA(axom::IndexType idx) {
-      boxes[idx] = {PointType(0.), PointType(1.)};
+      boxes[idx] = BoxType{PointType(0.), PointType(1.)};
    });

Copy link
Member

@kennyweiss kennyweiss left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this contribution @adayton1

Overall, it looks great, but it would be nice to have a few more unit tests for your expected use case of intersecting 2D and 3D bounding boxes.

It would also be nice to have a unit test for a 3D quadrilateral, and its associated area, but that could wait until we have a direct need.

src/axom/primal/geometry/BoundingBox.hpp Outdated Show resolved Hide resolved
src/axom/primal/geometry/BoundingBox.hpp Outdated Show resolved Hide resolved
src/axom/primal/geometry/Quadrilateral.hpp Show resolved Hide resolved
src/axom/primal/geometry/Quadrilateral.hpp Outdated Show resolved Hide resolved
src/axom/primal/geometry/Quadrilateral.hpp Show resolved Hide resolved
src/axom/primal/geometry/Quadrilateral.hpp Outdated Show resolved Hide resolved
@cyrush
Copy link
Member

cyrush commented Sep 12, 2023

@kennyweiss can we get @adayton1 access to CZ Gitlab?

@kennyweiss
Copy link
Member

@kennyweiss can we get @adayton1 access to CZ Gitlab?

Good call! Done.

@kennyweiss kennyweiss added the Primal Issues related to Axom's 'primal component label Sep 12, 2023
@adayton1
Copy link
Member Author

Can someone tell me why the ci/gitlab/lc.llnl.gov pipeline failed? I don't have access to view that page.

Looks like with your new initializer list constructor, it needs:

  // single bounding box in [0,1] x [0,1] x [0,1]
  BoxType* boxes = axom::allocate<BoxType>(1, allocID);
  axom::for_all<exec>(
    0,
    1,
    AXOM_LAMBDA(axom::IndexType idx) {
-      boxes[idx] = {PointType(0.), PointType(1.)};
+      boxes[idx] = BoxType{PointType(0.), PointType(1.)};
    });

Or should I make the initializer list constructor implicit?

@adayton1
Copy link
Member Author

Thanks for this contribution @adayton1

Overall, it looks great, but it would be nice to have a few more unit tests for your expected use case of intersecting 2D and 3D bounding boxes.

It would also be nice to have a unit test for a 3D quadrilateral, and its associated area, but that could wait until we have a direct need.

I will add a unit test for intersecting 2D and 3D bounding boxes. I have not implemented the area calculation for a 3D quadrilateral since I haven't been able to find a universal algorithm that works with skewed (non-planar) quadrilaterals.

@kennyweiss
Copy link
Member

kennyweiss commented Sep 12, 2023

I will add a unit test for intersecting 2D and 3D bounding boxes. I have not implemented the area calculation for a 3D quadrilateral since I haven't been able to find a universal algorithm that works with skewed (non-planar) quadrilaterals.

Thanks. I agree let's hold off on the 3D area until we need it.
2D/3D BBox intersections for quads would be useful though since that's needed in your application.

Copy link
Member

@rhornung67 rhornung67 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @adayton1

* \param [in] pts an initializer list containing points
*/
AXOM_HOST_DEVICE
explicit BoundingBox(std::initializer_list<PointType> pts)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Design question: Will this constructor get confused with the constructor that takes a min and max point? BoundingBox<double, 1> {Point<double, 1> {1.0}, Point<double, 1> {0.0}}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since you use 'explicit', I don't believe so. I may be wrong but I believe the compiler interprets and initializer_list as a single object while the ctor taking two points is considered a different overload. I recommend trying a simple example with several different compilers to be sure.

Copy link
Member

@rhornung67 rhornung67 Sep 14, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This may provide some insight: https://en.cppreference.com/w/cpp/language/converting_constructor

In particular, there is a distinction between copy-list initialization and direct-list-initialization, which implies the behavior is influenced by how the users calls the ctor.

Copy link
Member Author

@adayton1 adayton1 Sep 14, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It could be a little confusing and it does lead to a subtle change in behavior.

BoundingBox{Point {}, Point {}}; // Previously called two point constructor, now calls initializer_list constructor 
BoundingBox(Point {}, Point {}); // Calls two point constructor

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be better to have a make_bounding_box free function?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose the constructor from two points can be more computationally efficient when you know that one point is the min and the other is the max, and you explicitly use the third parameter (shouldFixBounds=false) -- but obviously this is explicit.
Otherwise, we should get the same result and I also wouldn't expect a meaningful performance difference (although, I suppose we should benchmark/profile it if it matters):

// 1: explicit .ctor -- explicitly set min and max, but then check and fix
BoundingBoxType bbox (point1, point2, /* shouldFixBounds=*/ true);
// 2: explicit .ctor -- most efficient, but possibly unsafe
BoundingBoxType bbox (point1, point2, /* shouldFixBounds=*/ false);
// 3: initializer-list -- will ensure that bounds are correct by inserting points one at a time
BoundingBoxType bbox {point1, point2}; 
// 4: .ctor -- implicitly sets shouldFixBounds to true, 
// performance diff to initializer list unknown, but likely negligible; should be measured if it matters
BoundingBoxType bbox (point1, point2); 

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@adayton1 thanks for confirming. That's what I would expect to happen. What do you get if you do this?

BoundingBox foo = {Point{}, Point{}}

Maybe it is sufficient to note the difference in the comments??

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BoundingBoxType foo = {Point{}, Point{}} won't compile since both constructors are explicit.
BoundingBoxType foo = BoundingBoxType{Point{}, Point{}} will use initializer_list constructor.
BoundingBoxType foo = BoundingBoxType(Point{}, Point{}) will use two point constructor.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @adayton1 -- that looks good to me.

Presumably, this would be the same as your first line?:

BoundingBoxType foo {Point{}, Point{}};

... but this would still work?

BoundingBoxType foo (Point{}, Point{});

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for confirming @adayton1 That's exactly what I would expect.

@kennyweiss they are different. Alan's first line (that doesn't compile) is copy-initialization, where as yours is direct-initialization. The first uses a copy/move ctor. The second uses a regular ctor.

@adayton1
Copy link
Member Author

@kennyweiss, @rhornung67 do you have any more comments?

@kennyweiss
Copy link
Member

@kennyweiss, @rhornung67 do you have any more comments?

Could you please add a line to the RELEASE_NOTES about the new primitive?

Looks good to me once it passes all the CI. I'm not sure why the Azure jobs are failing.

@adayton1
Copy link
Member Author

@kennyweiss, @rhornung67 do you have any more comments?

Could you please add a line to the RELEASE_NOTES about the new primitive?

Looks good to me once it passes all the CI. I'm not sure why the Azure jobs are failing.

I updated the release notes. Yeah, something weird was going on in the CI. Hopefully restarting it will do the trick.

@adayton1 adayton1 merged commit cf01b04 into develop Sep 28, 2023
12 checks passed
@adayton1 adayton1 deleted the feature/dayton8/primal_quadrilateral branch September 28, 2023 22:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Primal Issues related to Axom's 'primal component
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants