/*
 * Copyright information removed for SIGGRAPH anonymous review process.
 * This file is licensed under the GNU General Public License.
 *
 * geometry.h: Point and vectors in 2d (Vec2) + operators, 
 * Polygons in 2d, Sutherland-Hogdman re-entrant clipping.
 */

#ifndef __GEOMETRY__
#define __GEOMETRY__

#include "types.h"

namespace OGF {

    class Vec2 {
    public:
        Vec2(double x, double y) {  coord_[0] = x ; coord_[1] = y ;   }
        Vec2() {  coord_[0] = 0 ; coord_[1] = 0 ;  }
        Vec2(const Vec2& rhs) { coord_[0] = rhs.coord_[0] ; coord_[1] = rhs.coord_[1] ;  }
        const Vec2& operator=(const Vec2& rhs) {
            coord_[0] = rhs.coord_[0] ; coord_[1] = rhs.coord_[1] ;
            return *this ;
        }
        Vec2& operator += (const Vec2& rhs) {
            coord_[0] += rhs.coord_[0] ; coord_[1] += rhs.coord_[1] ;
            return *this ;            
        }
        Vec2& operator -= (const Vec2& rhs) {
            coord_[0] -= rhs.coord_[0] ; coord_[1] -= rhs.coord_[1] ;
            return *this ;            
        }
        Vec2& operator *= (double s) {
            coord_[0] *= s ; coord_[1] *= s ;
            return *this ;
        }
        double x() const { return coord_[0] ; }
        double y() const { return coord_[1] ; }
    private:
        double coord_[2] ;
    } ;

    inline Vec2 operator+(const Vec2& v1, const Vec2& v2) {
        return Vec2(v1.x() + v2.x(), v1.y() + v2.y()) ;
    }

    inline Vec2 operator-(const Vec2& v1, const Vec2& v2) {
        return Vec2(v1.x() - v2.x(), v1.y() - v2.y()) ;
    }
    
    inline Vec2 operator*(double s, const Vec2& v) {
        return Vec2(s*v.x(), s*v.y()) ;
    }
    
    inline double operator*(const Vec2& v1, const Vec2& v2) {
        return v1.x()*v2.x() + v1.y()*v2.y() ;
    }

    inline double det(const Vec2& v1, const Vec2& v2) {
        return v1.x()*v2.y() - v1.y()*v2.x() ;
    }

    typedef std::vector<Vec2> Polygon2 ;

    namespace Geom {

        /**
         * result <- P clipped by window
         * Precondition: polygon_is_convex(window).
         * Uses Sutherland-Hogdman reentrant clipping.
         */
        void convex_clip_polygon(
            const Polygon2& P, const Polygon2& window, Polygon2& result
        ) ;

        double signed_area(const Polygon2& P) ;
        inline double area(const Polygon2& P) { return ::fabs(signed_area(P)) ; }

    }
    

}


#endif
