## Regions

### OBJECTS

      typedef struct Region  Region;

      struct Region {
        Rect    extents;    /* enclosing rectangle */
        int     size;       /* allocated size of rectangle list */
        int     num_rects;  /* list of non-intersecting rects */
        Rect *  rects;
      };

### FUNCTIONS

      Region * new_region(void);
      void     del_region(Region *rgn);
      Region * new_rect_region(Rect r);
      Region * copy_region(Region *rgn);

      void move_region(Region *rgn, int dx, int dy);
      int  union_region(Region *rgn1, Region *rgn2, Region *dest);
      int  union_region_with_rect(Region *rgn, Rect r, Region *dest);
      int  intersect_region(Region *rgn1, Region *rgn2, Region *dest);
      int  intersect_region_with_rect(Region *rgn, Rect r, Region *dest);
      int  subtract_region(Region *rgn1, Region *rgn2, Region *dest);
      int  xor_region(Region *rgn1, Region *rgn2, Region *dest);

      int  region_is_empty(Region *rgn);
      int  regions_equal(Region *rgn1, Region *rgn2);
      int  point_in_region(Point p, Region *rgn);
      int  rect_intersects_region(Rect r, Region *rgn);
      int  rect_in_region(Rect r, Region *rgn);

### NOTES

A Region defines an arbitrary collection of points. It is implemented as an array of non-intersecting rectangles.

Important note: Regions, unlike Rect objects, are usually passed by pointer, not on the stack. Hence, changing a region within a function will usually also change it outside that function.

A new empty region can be returned using new_region. The function returns NULL if it runs out of memory and cannot create the region.

The del_region function should be used to delete regions when they are no longer needed.

The new_rect_region function creates a new region which contains all points within a given rectangle. It returns NULL if it runs out of memory.

To create a complete copy of an existing region, use copy_region. This function returns NULL if it runs out of memory.

To move a region to a new location, move_region is used. It adds `(dx,dy)` to all points within a region.

union_region forms in `dest` a region which is the union of all points within the regions `rgn1` and `rgn2`. The `dest` parameter must be an existing region, which may or may not be empty. The function returns one on success, zero if it runs out of memory. The union of two regions is defined as all points which are within either region.

union_region_with_rect performs the same operation, but using a rectangle as one of the items in the union.

intersect_region forms the intersection of two regions, placing the result in `dest`, which must be an existing, possibly empty, region. It returns one on success, zero if it runs out of memory. The intersection of two regions is defined as all points within both regions.

intersect_region_with_rect performs the same operation, but using a rectangle as one of the items to be intersected.

subtract_region forms a region which is `rgn1` with `rgn2` removed, storing the result into the already existing, possibly empty, region `dest`. Only `dest` is changed. This will be the set of all points which are inside `rgn1`, but not inside `rgn2`. The function returns one on success, zero if it runs out of memory.

xor_region forms the exclusive-or of two regions, placing the result in `dest`, which must be an existing, possibly empty, region. It returns one on success, zero if it runs out of memory. The exclusive-or of two regions is defined as all points which are within either region `rgn1` or `rgn2`, but not within both regions.

region_is_empty return one if the region is empty, zero if it is not. A region is empty if it encloses no points.

regions_equal returns one if the two regions enclose the same set of points, or zero if they differ.

point_in_region returns one if the given point is within the region, or zero if it is not.

rect_intersects_region returns one if any part of the given rectangle lies within the region (some parts of the rectangle may also lie outside the region). It returns zero if they are completely distinct.

rect_in_region returns one if the entire rectangle lies within the region, or zero if any part of the rectangle lies outside the region.