Пример #1
0
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;
        }
}
Пример #2
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);
}