/***********************************************************************
 * FXRuby -- the Ruby language bindings for the FOX GUI toolkit.
 * Copyright (c) 2001-2003 by J. Lyle Johnson. All Rights Reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * For further information please contact the author by e-mail
 * at "lyle@users.sourceforge.net".
 ***********************************************************************/

%{
class FXRangeSlice {
private:
  FXRange& range;
  FXint slice;
public:
  FXRangeSlice(FXRange& r,FXint s):range(r),slice(s){}
  FXfloat& operator[](FXint i){ return range[slice][i]; }
  const FXfloat& operator[](FXint i) const { return range[slice][i]; }
  };
%}

class FXRange;

// Helper class that sort-of looks like an array
class FXRangeSlice {
public:
  // Constructor
  FXRangeSlice(FXRange& r,FXint s);

  %extend {
    FXfloat __getitem__(FXint i) const {
      return (*self)[i];
      }
    FXfloat __setitem__(FXint i,FXfloat f){
      (*self)[i]=f;
      return f;
      }
    int length() const { return 2; }
  }
};

#ifdef SWIGRUBY
// Rename these methods
%rename("empty?") FXRange::empty() const;
%rename("overlaps?") FXRange::overlap(const FXRange& box) const;
%rename("contains?") FXRange::contains(FXfloat x,FXfloat y,FXfloat z) const;
%rename("intersects?") FXRange::intersects(const FXVec& u,const FXVec& v) const;
#endif


/// Range
class FXRange {
protected:
  FXfloat d[3][2];
public:

  // Default constructor
  FXRange();
  
  // Initialize
  FXRange(FXfloat xlo,FXfloat xhi,FXfloat ylo,FXfloat yhi,FXfloat zlo,FXfloat zhi);

  // Length of side i
  FXfloat side(FXint i) const;

  // Width of box
  FXfloat width() const;

  // Height of box
  FXfloat height() const;

  // Depth of box
  FXfloat depth() const;

  // Longest side
  FXfloat longest() const;

  // Shortest side
  FXfloat shortest() const;

  // Test if empty
  FXbool empty() const;

  // Test if overlap
  FXbool overlap(const FXRange& box) const;
   
  // Test if box contains point x,y,z
  FXbool contains(FXfloat x,FXfloat y,FXfloat z) const;

  %extend {
    FXRangeSlice __getitem__(FXint i){
      return FXRangeSlice(*self,i);
      }
    void __setitem__(FXint i,FXRangeSlice& slice){
      (*self)[i][0]=slice[0];
      (*self)[i][1]=slice[1];
      }
  }

  // Include given range into box
  FXRange& include(const FXRange& box);

  // Include point 
  FXRange& include(FXfloat x,FXfloat y,FXfloat z);

  // Include point 
  FXRange& include(const FXVec& v);
  
  // Clip domain against another 
  FXRange& clipTo(const FXRange& box);

  %extend {
#ifdef SWIGRUBY
    /// Get corners of box
    VALUE corners() const {
      FXVec points[8];
      boxCorners(points,*self);
      VALUE corners = rb_ary_new();
      for (int i = 0; i < 8; i++) {
        VALUE pt = rb_ary_new();
        rb_ary_push(pt, rb_float_new(points[i][0]));
        rb_ary_push(pt, rb_float_new(points[i][1]));
        rb_ary_push(pt, rb_float_new(points[i][2]));
        rb_ary_push(corners, pt);
        }
      return corners;
      }
#endif
  
    /// Ray intersection test
    FXbool intersects(const FXVec& u,const FXVec& v) const {
      return boxIntersect(*self,u,v);
      }
  
    /// Get center of box
    FXVec center() const {
      return boxCenter(*self);
      }
  
    /// Compute diagonal
    FXfloat diagonal() const {
      return boxDiagonal(*self);
      }
    }
  };

