void ply_rectangle_intersect (ply_rectangle_t *rectangle1, ply_rectangle_t *rectangle2, ply_rectangle_t *result) { long rectangle1_top_edge; long rectangle1_left_edge; long rectangle1_right_edge; long rectangle1_bottom_edge; long rectangle2_top_edge; long rectangle2_left_edge; long rectangle2_right_edge; long rectangle2_bottom_edge; long result_top_edge; long result_left_edge; long result_right_edge; long result_bottom_edge; if (ply_rectangle_is_empty (rectangle1)) { *result = *rectangle1; return; } if (ply_rectangle_is_empty (rectangle2)) { *result = *rectangle2; return; } rectangle1_top_edge = rectangle1->y; rectangle1_left_edge = rectangle1->x; rectangle1_right_edge = rectangle1->x + rectangle1->width - 1; rectangle1_bottom_edge = rectangle1->y + rectangle1->height - 1; rectangle2_top_edge = rectangle2->y; rectangle2_left_edge = rectangle2->x; rectangle2_right_edge = rectangle2->x + rectangle2->width - 1; rectangle2_bottom_edge = rectangle2->y + rectangle2->height - 1; result_top_edge = MAX (rectangle1_top_edge, rectangle2_top_edge); result_left_edge = MAX (rectangle1_left_edge, rectangle2_left_edge); result_right_edge = MIN (rectangle1_right_edge, rectangle2_right_edge); result_bottom_edge = MIN (rectangle1_bottom_edge, rectangle2_bottom_edge); result->x = result_left_edge; result->y = result_top_edge; if (result_right_edge >= result_left_edge) result->width = result_right_edge - result_left_edge + 1; else result->width = 0; if (result_bottom_edge >= result_top_edge) result->height = result_bottom_edge - result_top_edge + 1; else result->height = 0; if (ply_rectangle_is_empty (result)) { result->width = 0; result->height = 0; } }
static void merge_rectangle_with_sub_list (ply_region_t *region, ply_rectangle_t *new_area, ply_list_node_t *node) { if (ply_rectangle_is_empty (new_area)) { free (new_area); return; } while (node != NULL) { ply_list_node_t *next_node; ply_rectangle_t *old_area; ply_rectangle_overlap_t overlap; old_area = (ply_rectangle_t *) ply_list_node_get_data (node); next_node = ply_list_get_next_node (region->rectangle_list, node); if (ply_rectangle_is_empty (new_area)) overlap = PLY_RECTANGLE_OVERLAP_NO_EDGES; else if (ply_rectangle_is_empty (old_area)) overlap = PLY_RECTANGLE_OVERLAP_ALL_EDGES; else overlap = ply_rectangle_find_overlap (old_area, new_area); switch (overlap) { /* NNNN The new rectangle and node rectangle don't touch, * NNNN OOOO so let's move on to the next one. * OOOO */ case PLY_RECTANGLE_OVERLAP_NONE: break; /* NNNNN We need to split the new rectangle into * NNOOOOO two rectangles: The top row of Ns and * NNOOOOO the left side of Ns. * OOOOO */ case PLY_RECTANGLE_OVERLAP_TOP_AND_LEFT_EDGES: { ply_rectangle_t *rectangle; rectangle = copy_rectangle (new_area); rectangle->y = old_area->y; rectangle->width = old_area->x - new_area->x; rectangle->height = (new_area->y + new_area->height) - old_area->y; merge_rectangle_with_sub_list (region, rectangle, next_node); new_area->height = old_area->y - new_area->y; } break; /* NNNNN We need to split the new rectangle into * OOOOONN two rectangles: The top row of Ns and * OOOOONN the right side of Ns. * OOOOO */ case PLY_RECTANGLE_OVERLAP_TOP_AND_RIGHT_EDGES: { ply_rectangle_t *rectangle; rectangle = copy_rectangle (new_area); rectangle->x = old_area->x + old_area->width; rectangle->y = old_area->y; rectangle->width = (new_area->x + new_area->width) - (old_area->x + old_area->width); rectangle->height = (new_area->y + new_area->height) - old_area->y; merge_rectangle_with_sub_list (region, rectangle, next_node); new_area->height = old_area->y - new_area->y; } break; /* NNNNNNN We need to trim out the part of * NOOOOON old rectangle that overlaps the new * NOOOOON rectangle by shrinking and moving it * OOOOO and then we need to add the new rectangle. */ case PLY_RECTANGLE_OVERLAP_TOP_AND_SIDE_EDGES: { old_area->height = (old_area->y + old_area->height) - (new_area->y + new_area->height); old_area->y = new_area->y + new_area->height; } break; /* NNN We only care about the top row of Ns, * ONNNO everything below that is already handled by * ONNNO the old rectangle. * OOOOO */ case PLY_RECTANGLE_OVERLAP_TOP_EDGE: new_area->height = old_area->y - new_area->y; break; /* OOOOO We need to split the new rectangle into * NNOOOOO two rectangles: The left side of Ns and * NNOOOOO the bottom row of Ns. * NNOOOOO * NNNNN */ case PLY_RECTANGLE_OVERLAP_BOTTOM_AND_LEFT_EDGES: { ply_rectangle_t *rectangle; rectangle = copy_rectangle (new_area); rectangle->width = old_area->x - new_area->x; rectangle->height = (old_area->y + old_area->height) - new_area->y; merge_rectangle_with_sub_list (region, rectangle, next_node); new_area->height = (new_area->y + new_area->height) - (old_area->y + old_area->height); new_area->y = old_area->y + old_area->height; } break; /* OOOOO We need to split the new rectangle into * OOOOONN two rectangles: The right side of Ns and * OOOOONN the bottom row of Ns. * OOOOONN * NNNNN */ case PLY_RECTANGLE_OVERLAP_BOTTOM_AND_RIGHT_EDGES: { ply_rectangle_t *rectangle; rectangle = copy_rectangle (new_area); rectangle->x = old_area->x + old_area->width; rectangle->width = (new_area->x + new_area->width) - (old_area->x + old_area->width); rectangle->height = (old_area->y + old_area->height) - new_area->y; merge_rectangle_with_sub_list (region, rectangle, next_node); new_area->height = (new_area->y + new_area->height) - (old_area->y + old_area->height); new_area->y = old_area->y + old_area->height; } break; /* OOOOO We need to trim out the part of * NOOOOON old rectangle that overlaps the new * NOOOOON rectangle by shrinking it * NNNNNNN and then we need to add the new rectangle. */ case PLY_RECTANGLE_OVERLAP_BOTTOM_AND_SIDE_EDGES: { old_area->height = new_area->y - old_area->y; } break; /* OOOOO We only care about the bottom row of Ns, * ONNNO everything above that is already handled by * ONNNO the old rectangle. * NNN */ case PLY_RECTANGLE_OVERLAP_BOTTOM_EDGE: { new_area->height = (new_area->y + new_area->height) - (old_area->y + old_area->height); new_area->y = old_area->y + old_area->height; } break; /* NNNN We need to trim out the part of * NNNNO old rectangle that overlaps the new * NNNNO rectangle by shrinking it and moving it * NNNN and then we need to add the new rectangle. */ case PLY_RECTANGLE_OVERLAP_TOP_LEFT_AND_BOTTOM_EDGES: { old_area->width = (old_area->x + old_area->width) - (new_area->x + new_area->width); old_area->x = new_area->x + new_area->width; } break; /* NNNN We need to trim out the part of * ONNNN old rectangle that overlaps the new * ONNNN rectangle by shrinking it and then we * NNNN need to add the new rectangle. */ case PLY_RECTANGLE_OVERLAP_TOP_RIGHT_AND_BOTTOM_EDGES: old_area->width = new_area->x - old_area->x; break; /* NNNNNNN The old rectangle is completely inside the new rectangle * NOOOOON so replace the old rectangle with the new rectangle. * NOOOOON * NNNNNNN */ case PLY_RECTANGLE_OVERLAP_ALL_EDGES: merge_rectangle_with_sub_list (region, new_area, next_node); free (old_area); ply_list_remove_node (region->rectangle_list, node); return; /* NNN We need to split the new rectangle into * ONNNO two rectangles: the top and bottom row of Ns * ONNNO * NNN */ case PLY_RECTANGLE_OVERLAP_TOP_AND_BOTTOM_EDGES: { ply_rectangle_t *rectangle; rectangle = copy_rectangle (new_area); rectangle->y = old_area->y + old_area->height; rectangle->width = new_area->width; rectangle->height = (new_area->y + new_area->height) - (old_area->y + old_area->height); merge_rectangle_with_sub_list (region, rectangle, next_node); new_area->height = old_area->y - new_area->y; } break; /* OOOOO We only care about the side row of Ns, * NNNNOO everything rigth of that is already handled by * NNNNOO the old rectangle. * OOOOO */ case PLY_RECTANGLE_OVERLAP_LEFT_EDGE: new_area->width = old_area->x - new_area->x; break; /* OOOOO We only care about the side row of Ns, * NNNNNN everything left of that is already handled by * NNNNNN the old rectangle. * OOOOO */ case PLY_RECTANGLE_OVERLAP_RIGHT_EDGE: { long temp = new_area->x; new_area->x = old_area->x + old_area->width; new_area->width = (temp + new_area->width) - (old_area->x + old_area->width); } break; /* OOOOO We need to split the new rectangle into * NNNNNNN two rectangles: the side columns of Ns * NNNNNNN * OOOOO */ case PLY_RECTANGLE_OVERLAP_SIDE_EDGES: { ply_rectangle_t *rectangle; rectangle = copy_rectangle (new_area); rectangle->x = old_area->x + old_area->width; rectangle->width = (new_area->x + new_area->width) - (old_area->x + old_area->width); merge_rectangle_with_sub_list (region, rectangle, next_node); new_area->width = old_area->x - new_area->x; } break; /* OOOOOOO The new rectangle is completely inside an old rectangle * ONNNNNO so return early without adding the new rectangle. * ONNNNNO * OOOOOOO */ case PLY_RECTANGLE_OVERLAP_NO_EDGES: free (new_area); 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; } node = ply_list_get_next_node (region->rectangle_list, node); } ply_list_append_data (region->rectangle_list, new_area); }