diff options
author | Charlie Brej <cbrej@cs.man.ac.uk> | 2009-11-23 00:23:22 +0000 |
---|---|---|
committer | Charlie Brej <cbrej@cs.man.ac.uk> | 2009-11-23 00:23:22 +0000 |
commit | fea30a08abd2cb8c2632de697b5ecb90b70c9750 (patch) | |
tree | 1281a5accf18f0b053057e233dc49767cacf1a87 | |
parent | aea6de47881831135266932d63c11384e3d60f05 (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.c | 40 | ||||
-rw-r--r-- | src/libply/ply-rectangle.h | 5 | ||||
-rw-r--r-- | src/libply/ply-region.c | 59 |
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; + } |