Skip to content

Commit

Permalink
add subtraction to CRect for determining bounds overlap coverage, thx…
Browse files Browse the repository at this point in the history
… to Memphiz for figuring this out
  • Loading branch information
davilla committed Aug 6, 2012
1 parent 7f6c54f commit 2a7e9e9
Showing 1 changed file with 188 additions and 0 deletions.
188 changes: 188 additions & 0 deletions xbmc/guilib/Geometry.h
Expand Up @@ -27,6 +27,8 @@
#else
#define XBMC_FORCE_INLINE
#endif

#include <vector>
#include <algorithm>

class CPoint
Expand Down Expand Up @@ -154,6 +156,192 @@ class CRect
return Width() * Height();
};

std::vector<CRect> SubtractRect(CRect splitterRect)
{
#define ADD_RECT_ABOVE_INTERSECTION(add) \
{ \
add = CRect(x1, y1, x2, intersection.y1);\
newRectaglesList.push_back(add);\
}
#define ADD_RECT_BELOW_INTERSECTION(add) \
{\
add = CRect(x1, intersection.y2, x2, y2);\
newRectaglesList.push_back(add);\
}
#define ADD_RECT_LEFT_OF_INTERSECTION(add) \
{\
add = CRect(x1, intersection.y1, intersection.x1, intersection.y2);\
newRectaglesList.push_back(add);\
}
#define ADD_RECT_RIGHT_OF_INTERSECTION(add) \
{\
add = CRect(intersection.x2, intersection.y1, x2, intersection.y2);\
newRectaglesList.push_back(add);\
}

std::vector<CRect> newRectaglesList;
CRect intersection = splitterRect.Intersect(*this);

if (!intersection.IsEmpty())
{
CRect add;
// intersection rect upper edge
if (intersection.y1 == y1) // y starts with baserect
{
// intersection rect lower edge
if (intersection.y2 == y2) // y goes down to baserect
{
if (intersection.x1 == x1) // x starts with baserect
{
if (intersection.x2 == x2) // x ends with baserect
{ // result 100% covered
// add nothing
}
else // x ends in baserect
{ // results in 1 rect
ADD_RECT_RIGHT_OF_INTERSECTION(add);
}
}
else // x starts in baserect
{
if (intersection.x2 == x2) // x ends with baserect
{ // results in 1 rect
ADD_RECT_LEFT_OF_INTERSECTION(add);
}
else // x ends in baserect
{ //results in 2 rects
ADD_RECT_LEFT_OF_INTERSECTION(add);
ADD_RECT_RIGHT_OF_INTERSECTION(add);
}
}
}
else // y ends in baserect
{
if (intersection.x1 == x1) // x starts with baserect
{
if (intersection.x2 == x2) // x ends with baserect
{ //results in 1 rect, below intersection
ADD_RECT_BELOW_INTERSECTION(add);
}
else // x ends in baserect
{ // results in 2 rects
ADD_RECT_BELOW_INTERSECTION(add);
ADD_RECT_RIGHT_OF_INTERSECTION(add);
}
}
else // x starts in baserect
{
if (intersection.x2 == x2) // x ends with baserect
{ //results in 2 rects
ADD_RECT_BELOW_INTERSECTION(add);
ADD_RECT_LEFT_OF_INTERSECTION(add);
}
else // x ends in baserect
{ //results in 3 rects
ADD_RECT_BELOW_INTERSECTION(add);
ADD_RECT_LEFT_OF_INTERSECTION(add);
ADD_RECT_RIGHT_OF_INTERSECTION(add);
}
}
}
}
else // y starts in baserect
{
// intersection rect lower edge
if (intersection.y2 == y2) // y goes down to baserect
{
if (intersection.x1 == x1) // xstarts with baserect
{
if (intersection.x2 == x2) // x ends with baserect
{ //results in 1 rect above intersection
ADD_RECT_ABOVE_INTERSECTION(add);
}
else // x ends in baserect
{ // results in 2 rects
ADD_RECT_ABOVE_INTERSECTION(add);
ADD_RECT_RIGHT_OF_INTERSECTION(add);
}
}
else // x starts in baserect
{
if (intersection.x2 == x2) // x ends with baserect
{ // results in 2 rects
ADD_RECT_ABOVE_INTERSECTION(add);
ADD_RECT_LEFT_OF_INTERSECTION(add);
}
else // x ends in baserect
{ // results in 3 rects
ADD_RECT_ABOVE_INTERSECTION(add);
ADD_RECT_LEFT_OF_INTERSECTION(add);
ADD_RECT_RIGHT_OF_INTERSECTION(add);
}
}
}
else // y ends in baserect
{
if (intersection.x1 == x1) // x starts with baserect
{
if (intersection.x2 == x2) // x ends with baserect
{ // results in 2 rects
ADD_RECT_ABOVE_INTERSECTION(add);
ADD_RECT_BELOW_INTERSECTION(add);
}
else // x ends in baserect
{ // results in 3 rects
ADD_RECT_ABOVE_INTERSECTION(add);
ADD_RECT_BELOW_INTERSECTION(add);
ADD_RECT_RIGHT_OF_INTERSECTION(add);
}
}
else // x starts in baserect
{
if (intersection.x2 == x2) // x ends with baserect
{ // results in 3 rects
ADD_RECT_ABOVE_INTERSECTION(add);
ADD_RECT_BELOW_INTERSECTION(add);
ADD_RECT_LEFT_OF_INTERSECTION(add);
}
else // x ends in baserect
{ // results in 4 rects
ADD_RECT_ABOVE_INTERSECTION(add);
ADD_RECT_BELOW_INTERSECTION(add);
ADD_RECT_LEFT_OF_INTERSECTION(add);
ADD_RECT_RIGHT_OF_INTERSECTION(add);
}
}
}
}
}
else
{
newRectaglesList.push_back(*this);
}

return newRectaglesList;
}

This comment has been minimized.

Copy link
@jmarshallnz

jmarshallnz Aug 6, 2012

Contributor

Correct me if I'm wrong, but you could make this much less code by generating the 4 outside rects and then intersecting them with the current rect, throwing away anything where the intersection is empty.

This comment has been minimized.

Copy link
@Memphiz

Memphiz Aug 6, 2012

Member

Muuh - now i feel stupid.

This comment has been minimized.

Copy link
@jmarshallnz

jmarshallnz via email Aug 6, 2012

Contributor

This comment has been minimized.

Copy link
@Memphiz

Memphiz Aug 6, 2012

Member

Yeah its just that i didn't stumble over it. We could even intersect once and then calc all 4 rects and only add the ones that are not empty (only one intersection needed then).

This comment has been minimized.

Copy link
@Memphiz

Memphiz Aug 6, 2012

Member

http://pastebin.com/NFsf5me6 <- that could do it. Unbelievable that i lost half a sunday on this ...

This comment has been minimized.

Copy link
@jmarshallnz

jmarshallnz via email Aug 6, 2012

Contributor

std::vector<CRect> SubtractRects(std::vector<CRect> intersectionList)
{
std::vector<CRect> fragmentsList;
fragmentsList.push_back(*this);

for (std::vector<CRect>::iterator splitter = intersectionList.begin(); splitter != intersectionList.end(); ++splitter)
{
std::vector<CRect> toAddList;

for (std::vector<CRect>::iterator fragment = fragmentsList.begin(); fragment != fragmentsList.end(); ++fragment)
{
std::vector<CRect> newFragmentsList = fragment->SubtractRect(*splitter);
toAddList.insert(toAddList.end(), newFragmentsList.begin(), newFragmentsList.end());
}

fragmentsList.clear();
fragmentsList.insert(fragmentsList.end(), toAddList.begin(), toAddList.end());
}

return fragmentsList;
}

bool operator !=(const CRect &rect) const
{
if (x1 != rect.x1) return true;
Expand Down

0 comments on commit 2a7e9e9

Please sign in to comment.