/***************************************************************************
* SphTri.h                                                                 *
*                                                                          *
* This file defines the SphericalTriangle class definition, which          *
* supports member functions for Monte Carlo sampling, point containment,   *
* and other basic operations on spherical triangles.                       *
*                                                                          *
*   Changes:                                                               *
*     01/01/2000  arvo  Added New_{Alpha,Beta,Gamma} methods.              *
*     12/30/1999  arvo  Added VecIrrad method for "Vector Irradiance".     *
*     04/08/1995  arvo  Further optimized sampling algorithm.              *
*     10/11/1994  arvo  Added analytic sampling algorithm.                 *
*     06/14/1994  arvo  Initial implementation.                            *
*                                                                          *
*--------------------------------------------------------------------------*
* Copyright (C) 1995, 2000, James Arvo                                     *
*                                                                          *
* This program is free software; you can redistribute it and/or modify it  *
* under the terms of the GNU General Public License as published by the    *
* Free Software Foundation.  See http://www.fsf.org/copyleft/gpl.html      *
*                                                                          *
* This program is distributed in the hope that it will be useful, but      *
* WITHOUT EXPRESS OR IMPLIED WARRANTY of merchantability or fitness for    *
* any particular purpose.  See the GNU General Public License for more     *
* details.                                                                 *
*                                                                          *
***************************************************************************/
#ifndef __SPHTRI_INCLUDED__
#define __SPHTRI_INCLUDED__

#include <util/Vec3.h>
#include <util/Vec2.h>

/*
 *  The (Oblique) Spherical Triangle ABC.  Edge lengths (segments of great 
 *  circles) are a, b, and c.  The (dihedral) angles are Alpha, Beta, and Gamma.
 *
 *                      B
 *                      o
 *                     / \
 *                    /   \
 *                   /Beta \
 *                  /       \
 *               c /         \ a
 *                /           \ 
 *               /             \
 *              /               \
 *             /                 \
 *            /                   \
 *           /Alpha          Gamma \
 *          o-----------------------o
 *         A            b            C
 *
 */

class SphericalTriangle {

    public: // methods
        SphericalTriangle() { Init(); }
        SphericalTriangle( const SphericalTriangle &T ) { *this = T; }
        SphericalTriangle( const Vec3 &, const Vec3 &, const Vec3 & );
        SphericalTriangle & operator()( const Vec3 &, const Vec3 &, const Vec3 & );
       ~SphericalTriangle( ) {}
        void   operator=( const SphericalTriangle &T ) { *this = T; }
        Vec3   Chart    ( float x, float y ) const;  // Const-Jacobian map from square.
        Vec2   Coord    ( const Vec3 &P    ) const;  // Get 2D coords of a point.
        int    Orient( ) const { return orient; }
        int    Inside( const Vec3 & ) const;
        float  SolidAngle() const { return area; }
        float  SignedSolidAngle() const { return -orient * area; } // CC is pos.
        const  Vec3 &A()  const { return A_       ; }
        const  Vec3 &B()  const { return B_       ; }
        const  Vec3 &C()  const { return C_       ; }
        float  a()        const { return a_       ; }
        float  b()        const { return b_       ; }
        float  c()        const { return c_       ; }
        float  Cos_a()    const { return cos_a    ; }
        float  Cos_b()    const { return cos_b    ; }
        float  Cos_c()    const { return cos_c    ; }
        float  Alpha()    const { return alpha    ; }
        float  Beta ()    const { return beta     ; }
        float  Gamma()    const { return gamma    ; }
        float  CosAlpha() const { return cos_alpha; }
        float  CosBeta () const { return cos_beta ; }
        float  CosGamma() const { return cos_gamma; }
        Vec3   VecIrrad() const; // Returns the vector irradiance.
        SphericalTriangle Dual() const;
        SphericalTriangle New_Alpha( float alpha ) const;
        SphericalTriangle New_Beta ( float beta  ) const;
        SphericalTriangle New_Gamma( float gamma ) const;

    private: // methods
        void Init( );
        void Init( const Vec3 &A, const Vec3 &B, const Vec3 &C );

    private: // data
        Vec3  A_, B_, C_, U;       // The vertices (and a temp vector).
        float a_, b_, c_;          // The edge lengths.
        float alpha, beta, gamma;  // The angles.
        float cos_a, cos_b, cos_c;
        float cos_alpha, cos_beta, cos_gamma;
        float area;
        float sin_alpha, product;  // Used in sampling algorithm.
        int   orient;              // Orientation.
    };

inline double CosDihedralAngle( const Vec3 &A, const Vec3 &B, const Vec3 &C )
    {
    float x = Unit( A ^ B ) * Unit( C ^ B );
    if( x < -1.0 ) x = -1.0;
    if( x >  1.0 ) x =  1.0;
    return x;
    }

inline double DihedralAngle( const Vec3 &A, const Vec3 &B, const Vec3 &C )
    {
    return acos( CosDihedralAngle( A, B, C ) );
    }

extern ostream &operator<<( ostream &out, const SphericalTriangle & );

#endif




