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

Introduce the (Typed)Box2D type. #219

Closed
wants to merge 1 commit into from
Closed

Introduce the (Typed)Box2D type. #219

wants to merge 1 commit into from

Conversation

nical
Copy link
Contributor

@nical nical commented Jun 28, 2017

This representation can improve performance when dealing with lots of rectangle intersections. It's a tradeoff so this type won't replace TypedRect which should probably remain the canonical representation for rectangles while code can opt into using boxes where it makes sense.


This change is Reviewable

@nical
Copy link
Contributor Author

nical commented Jun 28, 2017

cc @kvark @jrmuizel


#[inline]
pub fn union(&self, other: &Self) -> Self {
if other.is_empty_or_negative() {
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need to special case this or can we just rely on the maxes?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't think we can rely on the maxes for union (although it does work for intersection). We could turn this into a debug_assert and force people to use ensure_positive beforehand if this is a performance concern.

src/rect.rs Outdated
/// A 2d Rectangle represented using two points, optionally tagged with a unit.
#[repr(C)]
pub struct TypedBox2D<T, Unit = UnknownUnit> {
min: TypedPoint2D<T, Unit>,
Copy link
Member

Choose a reason for hiding this comment

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

should be public

src/rect.rs Outdated
impl<T, U> TypedBox2D<T, U> {
pub fn new(min: TypedPoint2D<T, U>, max: TypedPoint2D<T, U>) -> Self {
TypedBox2D {
min: min,
Copy link
Member

Choose a reason for hiding this comment

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

min,

src/rect.rs Outdated
}

impl<T, U> TypedBox2D<T, U>
where T: Copy + Clone + Zero + One + PartialOrd + PartialEq + Add<T, Output=T> + Sub<T, Output=T> + Mul<Output=T> {
Copy link
Member

Choose a reason for hiding this comment

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

can be Add<Output=T> and Sub<Output=T>

src/rect.rs Outdated

Some(TypedRect {
origin: self.min,
size: self.size(),
Copy link
Member

Choose a reason for hiding this comment

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

we shouldn't compute size() twice (previously done in is_empty_or_negative)

src/rect.rs Outdated

#[inline]
pub fn intersects(&self, other: &Self) -> bool {
self.min.x < other.max.x && other.min.x < self.max.x &&
Copy link
Member

Choose a reason for hiding this comment

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

appears to return true even when one of the boxes is zero/negative

src/rect.rs Outdated
let min_point = point2(max(self.min.x, other.min.x), max(self.min.y, other.min.y));
let max_point = point2(min(self.max.x, other.max.x), min(self.max.y, other.max.y));

Self::new(min_point, max_point)
Copy link
Member

Choose a reason for hiding this comment

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

nit: any reason you don't just do

TypedBox {
  min:  ..
  max: ..
}

src/rect.rs Outdated
/// `t` is expected to be between zero and one.
#[inline]
pub fn lerp(&self, other: Self, t: T) -> Self {
Self::new(
Copy link
Member

Choose a reason for hiding this comment

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

needs debug_assert! (as discussed) to be sound

src/rect.rs Outdated
let s = Rect::new(point2(20, -15), size2(250, 200)).to_box();

let pq = p.union(&q);
assert!(pq.min == point2(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.

let's use assert_eq whenever possible

Copy link
Member

Choose a reason for hiding this comment

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

this is still TODO?

src/rect.rs Outdated
let r = Rect::new(point2(-5, -5), size2(8, 8)).to_box();

let pq = p.intersection(&q);
assert!(!pq.is_empty_or_negative());
Copy link
Member

Choose a reason for hiding this comment

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

need a test for is_empty_or_negative() == true

@@ -133,3 +135,10 @@ pub type Matrix4D<T> = Transform3D<T>;
#[deprecated]
pub type TypedMatrix4D<T, Src, Dst> = TypedTransform3D<T, Src, Dst>;

fn min<T: PartialOrd>(x: T, y: T) -> T {
Copy link
Member

Choose a reason for hiding this comment

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

that seems rather sad that we need those functions

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, that's a more general rust std sadness topic. They were already there, I just moved them up so that Point::min/max can use that instead of depending on the Float trait.

src/rect.rs Outdated
/// `t` is expected to be between zero and one.
#[inline]
pub fn lerp(&self, other: Self, t: T) -> Self {
debug_assert!(!self.is_positive());
Copy link
Member

Choose a reason for hiding this comment

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

shouldn't we assert that debug_assert!(self.is_positive()); instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

oops!

src/rect.rs Outdated
let s = Rect::new(point2(20, -15), size2(250, 200)).to_box();

let pq = p.union(&q);
assert!(pq.min == point2(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.

this is still TODO?

Copy link
Member

@kvark kvark 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 addressing my concerns!

@kvark
Copy link
Member

kvark commented Jun 29, 2017

r=me if @jrmuizel is also happy

@jrmuizel
Copy link
Contributor

Yeah, this is fine to land. We can iterate on it as we see fit.

@jrmuizel
Copy link
Contributor

As I think about this more I'm leaning towards wanting a separate type for NonEmpty boxes. i.e.

@jrmuizel
Copy link
Contributor

Also, size() can overflow. I think it should return unsigned values.

@bors-servo
Copy link
Contributor

☔ The latest upstream changes (presumably #225) made this pull request unmergeable. Please resolve the merge conflicts.

@nical
Copy link
Contributor Author

nical commented Jan 13, 2018

Closing this for now, we can reopen if/when need it again.

@nical nical closed this Jan 13, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants