Coordinates and bounding boxes
==============================

Coordinate System
-----------------

  NUKE coordinate system are internally pixel-based based with 0,0 being the lower left.  Support for non-one pixel
  aspect ratios and proxy-scaling/downrezzing exist and are generally transparent, with the user seeing coordinates
  that are properly canonical coordinates, but the code generally seeing pixel coordinates.

  The pixel aspect ratio is a property of the image format, rather than the data itself.  When the knobs are being stored, NUKE
  will take into account the pixel aspect ratio for certain types of knobs.  For example, suppose there is a Blur node, which has
  a "size" parameter, as follows:

  .. code-block:: c

     float size[2];

     Blur() {
       _size[0] = _size[1] = 10;
     }

     void knobs(Knob_Callback f) {
       WH_knob(f, _size, "size");
     }

  With square pixels and without being in any proxy mode, the size will end up being set to (10,10).  If the pixels are twice
  the width they are high, then to achieve a blur that appears the same vertically as horizontally, we should only blur by half
  the number of pixels horizontally as we are doing vertically.  Therefore, the call to WH_Knob() takes the value of
  input_format().pixel_aspect() into account in this case, and would result in _size being set to (5, 10) rather than (10, 10)
  in this case.

  Proxy scaling is handled in a similar manner, except that proxy scales are passed in through the OutputContext (ie go from the bottom upwards,
  rather than coming from the top downwards, like pixel aspect ratios).  In this example, if the OutputContext() was set to downrez by 2, then
  then _size would end up being (5, 5).  The effect is multiplicative, so that if the pixel aspect ratio is 2:1 in addition to the downrez being
  2, then _size would be (2.5, 5).

  This sort of automatic downrezzing happens with the knobs() call, on certain knobs: those dealing with 2D space.  These are

  * BBox_knob
  * Transform2d_knob
  * WH_Knob
  * XY_knob
    
  It is possible to turn this off on a per-knob basis by setting the NO_PROXYSCALE flag on a knob.  This applies only to the scaling from the
  OutputContext: that from the pixel aspect ratio always takes place.  If you wish to do the equivalent on data not in those types of knobs, you can 
  use the OutputContext::to_proxy and OutputContext::from_proxy functions to do this manually.

Bounding boxes and formats
--------------------------

  _validate() produces as a side-effect the region of definition (in pixel coordinates) for an Iop, and places it into the IopInfo.

  It also should produce two formats, being the "full size format" (ignoring any downrez/proxy) and the "format" (which takes into account any
  downrez/proxy).

  A simple implementation, that just copies the (sole) input's IopInfo is as follows:

  .. code-block:: c

    void _validate(bool forReal)
    {
       copy_info(0);
    }

  The default implementation also calls merge_info() to merge in the bboxes and channels of the other inputs.

  NUKE then will call _request to indicate the region of interest.  This should call request() on all its inputs as necessary, with
  that Op's region of interest on those inputs.  For example, a blur might wish to implement this like so:

  .. code-block:: c

    void _request(int x, int y, int r, int t, ChannelMask channels, int count)
    {
      input(0)->request(x - _size[0], y - _size[1], r + _size[0], t + _size[1], channels, count);
    }

  NUKE clips the regions in its implementation of request() that forwards to the plugin's function _request(), so that
  you will never see a request that is larger than your bbox as you specify in _validate(), and you can happily request larger
  boxes than your info bboxes.

