summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharlie Brej <cbrej@cs.man.ac.uk>2009-11-23 00:23:22 +0000
committerCharlie Brej <cbrej@cs.man.ac.uk>2009-11-23 00:23:22 +0000
commitfea30a08abd2cb8c2632de697b5ecb90b70c9750 (patch)
tree1281a5accf18f0b053057e233dc49767cacf1a87
parentaea6de47881831135266932d63c11384e3d60f05 (diff)
[rectangle] Add exact overlap detection
If the width and X position of the two rectangles is the same, we can merge them together. The new set of exact overlaps detects this and determines the direction the rectangle should be extended. The region code now uses this. WARNING, when expanding rectangles, these have to be merged with the other rectangles down the list as there may be overlap.
-rw-r--r--src/libply/ply-rectangle.c40
-rw-r--r--src/libply/ply-rectangle.h5
-rw-r--r--src/libply/ply-region.c59
3 files changed, 99 insertions, 5 deletions
diff --git a/src/libply/ply-rectangle.c b/src/libply/ply-rectangle.c
index 77f30f23..8fdd89e5 100644
--- a/src/libply/ply-rectangle.c
+++ b/src/libply/ply-rectangle.c
@@ -67,14 +67,19 @@ ply_rectangle_overlap_t
ply_rectangle_find_overlap (ply_rectangle_t *rectangle1,
ply_rectangle_t *rectangle2)
{
- enum {H_COLLISION_NONE, H_COLLISION_LEFT, H_COLLISION_RIGHT, H_COLLISION_BOTH, H_COLLISION_CONTAINED}
+ ply_rectangle_overlap_t overlap;
+
+ enum {H_COLLISION_NONE, H_COLLISION_LEFT, H_COLLISION_RIGHT, H_COLLISION_BOTH, H_COLLISION_CONTAINED, H_COLLISION_EXACT}
h_collision = H_COLLISION_NONE;
- enum {V_COLLISION_NONE, V_COLLISION_TOP, V_COLLISION_BOTTOM, V_COLLISION_BOTH, V_COLLISION_CONTAINED}
+ enum {V_COLLISION_NONE, V_COLLISION_TOP, V_COLLISION_BOTTOM, V_COLLISION_BOTH, V_COLLISION_CONTAINED, V_COLLISION_EXACT}
v_collision = V_COLLISION_NONE;
if (rectangle2->x >= rectangle1->x && (rectangle2->x + (int)rectangle2->width) <= (rectangle1->x + (int)rectangle1->width))
{
- h_collision = H_COLLISION_CONTAINED;
+ if (rectangle2->x == rectangle1->x && rectangle2->width == rectangle1->width)
+ h_collision = H_COLLISION_EXACT;
+ else
+ h_collision = H_COLLISION_CONTAINED;
}
else
{ /* Remember: x+width points to the first pixel outside the rectangle*/
@@ -97,7 +102,10 @@ ply_rectangle_find_overlap (ply_rectangle_t *rectangle1,
if (rectangle2->y >= rectangle1->y && (rectangle2->y + (int)rectangle2->height) <= (rectangle1->y + (int)rectangle1->height))
{
- v_collision = V_COLLISION_CONTAINED;
+ if (rectangle2->y == rectangle1->y && rectangle2->height == rectangle1->height)
+ v_collision = V_COLLISION_EXACT;
+ else
+ v_collision = V_COLLISION_CONTAINED;
}
else
{
@@ -132,6 +140,8 @@ ply_rectangle_find_overlap (ply_rectangle_t *rectangle1,
return PLY_RECTANGLE_OVERLAP_TOP_LEFT_AND_BOTTOM_EDGES;
case V_COLLISION_CONTAINED:
return PLY_RECTANGLE_OVERLAP_LEFT_EDGE;
+ case V_COLLISION_EXACT:
+ return PLY_RECTANGLE_OVERLAP_EXACT_LEFT_EDGE;
}
case H_COLLISION_RIGHT:
switch (v_collision)
@@ -146,6 +156,8 @@ ply_rectangle_find_overlap (ply_rectangle_t *rectangle1,
return PLY_RECTANGLE_OVERLAP_TOP_RIGHT_AND_BOTTOM_EDGES;
case V_COLLISION_CONTAINED:
return PLY_RECTANGLE_OVERLAP_RIGHT_EDGE;
+ case V_COLLISION_EXACT:
+ return PLY_RECTANGLE_OVERLAP_EXACT_RIGHT_EDGE;
}
case H_COLLISION_BOTH:
switch (v_collision)
@@ -160,6 +172,8 @@ ply_rectangle_find_overlap (ply_rectangle_t *rectangle1,
return PLY_RECTANGLE_OVERLAP_ALL_EDGES;
case V_COLLISION_CONTAINED:
return PLY_RECTANGLE_OVERLAP_SIDE_EDGES;
+ case V_COLLISION_EXACT:
+ return PLY_RECTANGLE_OVERLAP_ALL_EDGES;
}
case H_COLLISION_CONTAINED:
switch (v_collision)
@@ -174,6 +188,24 @@ ply_rectangle_find_overlap (ply_rectangle_t *rectangle1,
return PLY_RECTANGLE_OVERLAP_TOP_AND_BOTTOM_EDGES;
case V_COLLISION_CONTAINED:
return PLY_RECTANGLE_OVERLAP_NO_EDGES;
+ case V_COLLISION_EXACT:
+ return PLY_RECTANGLE_OVERLAP_NO_EDGES;
+ }
+ case H_COLLISION_EXACT:
+ switch (v_collision)
+ {
+ case V_COLLISION_NONE:
+ return PLY_RECTANGLE_OVERLAP_NONE;
+ case V_COLLISION_TOP:
+ return PLY_RECTANGLE_OVERLAP_EXACT_TOP_EDGE;
+ case V_COLLISION_BOTTOM:
+ return PLY_RECTANGLE_OVERLAP_EXACT_BOTTOM_EDGE;
+ case V_COLLISION_BOTH:
+ return PLY_RECTANGLE_OVERLAP_ALL_EDGES;
+ case V_COLLISION_CONTAINED:
+ return PLY_RECTANGLE_OVERLAP_NO_EDGES;
+ case V_COLLISION_EXACT:
+ return PLY_RECTANGLE_OVERLAP_NO_EDGES;
}
}
return PLY_RECTANGLE_OVERLAP_NONE;
diff --git a/src/libply/ply-rectangle.h b/src/libply/ply-rectangle.h
index bdbb6f4c..85ee7110 100644
--- a/src/libply/ply-rectangle.h
+++ b/src/libply/ply-rectangle.h
@@ -84,6 +84,11 @@ typedef enum
PLY_RECTANGLE_OVERLAP_BOTTOM_EDGE |
PLY_RECTANGLE_OVERLAP_RIGHT_EDGE,
PLY_RECTANGLE_OVERLAP_NO_EDGES = 1 << 4,
+ PLY_RECTANGLE_OVERLAP_EXACT_TOP_EDGE,
+ PLY_RECTANGLE_OVERLAP_EXACT_LEFT_EDGE,
+ PLY_RECTANGLE_OVERLAP_EXACT_RIGHT_EDGE,
+ PLY_RECTANGLE_OVERLAP_EXACT_BOTTOM_EDGE,
+
} ply_rectangle_overlap_t;
#ifndef PLY_HIDE_FUNCTION_DECLARATIONS
diff --git a/src/libply/ply-region.c b/src/libply/ply-region.c
index c590913d..a235f338 100644
--- a/src/libply/ply-region.c
+++ b/src/libply/ply-region.c
@@ -361,7 +361,64 @@ merge_rectangle_with_sub_list (ply_region_t *region,
*/
case PLY_RECTANGLE_OVERLAP_NO_EDGES:
free (new_area);
- return;
+ return;
+
+ /* NNNNN We expand the old rectangle up and throw away the new.
+ * NNNNN We must merge it because the new region may have overlapped
+ * NNNNN something further down the list.
+ * OOOOO
+ */
+ case PLY_RECTANGLE_OVERLAP_EXACT_TOP_EDGE:
+ {
+ old_area->height = (old_area->y + old_area->height) - new_area->y;
+ old_area->y = new_area->y;
+ free (new_area);
+ merge_rectangle_with_sub_list (region, old_area, next_node);
+ ply_list_remove_node (region->rectangle_list, node);
+ }
+ return;
+
+ /* OOOOO We expand the old rectangle down and throw away the new.
+ * NNNNN We must merge it because the new region may have overlapped
+ * NNNNN something further down the list.
+ * NNNNN
+ */
+ case PLY_RECTANGLE_OVERLAP_EXACT_BOTTOM_EDGE:
+ {
+ old_area->height = (new_area->y + new_area->height) - old_area->y;
+ free (new_area);
+ merge_rectangle_with_sub_list (region, old_area, next_node);
+ ply_list_remove_node (region->rectangle_list, node);
+ }
+ return;
+
+ /* NNNNNO We expand the old rectangle left and throw away the new.
+ * NNNNNO We must merge it because the new region may have overlapped
+ * NNNNNO something further down the list.
+ */
+ case PLY_RECTANGLE_OVERLAP_EXACT_LEFT_EDGE:
+ {
+ old_area->width = (old_area->x + old_area->width) - new_area->x;
+ old_area->x = new_area->x;
+ free (new_area);
+ merge_rectangle_with_sub_list (region, old_area, next_node);
+ ply_list_remove_node (region->rectangle_list, node);
+ }
+ return;
+
+ /* ONNNNN We expand the old rectangle right and throw away the new.
+ * ONNNNN We must merge it because the new region may have overlapped
+ * ONNNNN something further down the list.
+ */
+ case PLY_RECTANGLE_OVERLAP_EXACT_RIGHT_EDGE:
+ {
+ old_area->width = (new_area->x + new_area->width) - old_area->x;
+ free (new_area);
+ merge_rectangle_with_sub_list (region, old_area, next_node);
+ ply_list_remove_node (region->rectangle_list, node);
+ }
+ return;
+
}