Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Rect#intersects  (Read 5812 times)

0 Members and 1 Guest are viewing this topic.

Groogy

  • Hero Member
  • *****
  • Posts: 1469
    • MSN Messenger - groogy@groogy.se
    • View Profile
    • http://www.groogy.se
    • Email
Rect#intersects
« on: November 29, 2010, 09:10:21 am »
While I was playing around with intersects on SFML::Rect I noticed that it seamed like it intersected even though it shouldn't. For instance I have the rect: [0, 0, 44, 16] and when I call intersects with [0, -35, 42, 34] it returns [0, 0, 44, 16]

I must have done something wrong unless I misunderstand intersects. Here's the original C++ code:
Code: [Select]
template <typename T>
bool Rect<T>::Intersects(const Rect<T>& rectangle, Rect<T>& intersection) const
{
    // Compute the intersection boundaries
    T left   = std::max(Left,         rectangle.Left);
    T top    = std::max(Top,          rectangle.Top);
    T right  = std::min(Left + Width, rectangle.Left + rectangle.Width);
    T bottom = std::min(Top + Height, rectangle.Top + rectangle.Height);

    // If the intersection is valid (positive non zero area), then there is an intersection
    if ((left < right) && (top < bottom))
    {
        intersection = Rect<T>(left, top, right - left, bottom - top);
        return true;
    }
    else
    {
        intersection = Rect<T>(0, 0, 0, 0);
        return false;
    }
}


And here's the original ruby code(with added comments to show what's what):
Code: [Select]

/* call-seq:
 *   rect.intersects( rectangle ) -> intersection rectangel or nil
 *
 * Check the intersection between two rectangles.
 *
 * This method returns the overlapped rectangle if intersecting otherwise nil.
 */
static VALUE Rect_Intersects( VALUE self, VALUE aRect )
{
VALUE selfLeft = rb_funcall( self, rb_intern( "left" ), 0 );
VALUE selfTop = rb_funcall( self, rb_intern( "top" ), 0 );
VALUE selfWidth  = rb_funcall( self, rb_intern( "width" ), 0 );
VALUE selfHeight = rb_funcall( self, rb_intern( "height" ), 0 );
VALUE selfRight  = rb_funcall( selfLeft, rb_intern( "+" ), 1, selfWidth );
VALUE selfBottom = rb_funcall( selfTop, rb_intern( "+" ), 1, selfHeight );
VALUE rectLeft = rb_funcall( aRect, rb_intern( "left" ), 0 );
VALUE rectTop = rb_funcall( aRect, rb_intern( "top" ), 0 );
VALUE rectWidth  = rb_funcall( aRect, rb_intern( "width" ), 0 );
VALUE rectHeight = rb_funcall( aRect, rb_intern( "height" ), 0 );
VALUE rectRight  = rb_funcall( rectLeft, rb_intern( "+" ), 1, rectWidth );
VALUE rectBottom = rb_funcall( rectTop, rb_intern( "+" ), 1, rectHeight );

VALUE left, top, right, bottom;

        // T left   = std::max(Left,         rectangle.Left);
if( rb_funcall( selfLeft, rb_intern( ">" ), 1, rectLeft ) == Qtrue )
{
left = selfLeft;
}
else
{
left = rectLeft;
}

// T top = std::max(Top,         rectangle.Top);
if( rb_funcall( selfTop, rb_intern( ">" ), 1, rectTop ) == Qtrue )
{
top = selfTop;
}
else
{
top = rectTop;
}

// T right  = std::min(Left + Width, rectangle.Left + rectangle.Width);
if( rb_funcall( selfRight , rb_intern( ">" ), 1, rectRight ) == Qtrue )
{
right = selfRight;
}
else
{
right = rectRight;
}

// T bottom = std::min(Top + Height, rectangle.Top + rectangle.Height);
if( rb_funcall( selfBottom , rb_intern( ">" ), 1, rectBottom ) == Qtrue )
{
bottom = selfBottom;
}
else
{
bottom = rectBottom;
}

// if ((left < right) && (top < bottom))
if( rb_funcall( left, rb_intern( "<" ), 1, right) == Qtrue && rb_funcall( top, rb_intern( "<" ), 1, bottom) == Qtrue )
{
// intersection = Rect<T>(left, top, right - left, bottom - top);
VALUE newWidth  = rb_funcall( right, rb_intern( "-" ), 1, left );
VALUE newHeight = rb_funcall( bottom, rb_intern( "-" ), 1, top );
return rb_funcall( globalRectClass, rb_intern( "new" ), 4, left, top, newWidth, newHeight );
}
else
{
// return false
return Qnil;
}
}


from what I understand, those two rects shouldn't intersect and thus the intersects method should return the ruby value nil. But I must have missed something somewhere in the algorithm. Does anybody see it?
Developer and Maker of rbSFML and Programmer at Paradox Development Studio

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Rect#intersects
« Reply #1 on: November 29, 2010, 09:30:58 am »
Sorry I can't have a look at your code right now, but can't this be implemented directly in Ruby (one big function call instead of one call every time you access to a member)?
Laurent Gomila - SFML developer

Groogy

  • Hero Member
  • *****
  • Posts: 1469
    • MSN Messenger - groogy@groogy.se
    • View Profile
    • http://www.groogy.se
    • Email
Rect#intersects
« Reply #2 on: November 29, 2010, 09:50:51 am »
Well I could directly access the variables but I am thinking ahead with that a user might want to inherit from SFML::Rect and might want to override how it works the different values.

Anyway I found it, I had read the std::min as std::max so I had the comparison all wrong. I'm committing the fix now.
Developer and Maker of rbSFML and Programmer at Paradox Development Studio