// -*- Mode: c++ -*-
// $Id: float3.C,v 1.4 1998/02/11 03:46:42 neel Exp $
// $Source: /u2/graphics/projects/6.838/gvis/gprims/float3.C,v $

static char 
__rcs_ref_float3_c(void)
{
  static char rcs_id_c[] = "$Header: /u2/graphics/projects/6.838/gvis/gprims/float3.C,v 1.4 1998/02/11 03:46:42 neel Exp $";
  return rcs_id_c[0];
}
// do not edit anything above this line
static char avoid_stupid_compiler_warnings = __rcs_ref_float3_c();

#include <iostream.h>
#include <string.h>
#include <math.h>
#include <assert.h>

#include "utils.H"
#include "float2.H"
#include "float3.H"
#include "float4.H" 


// constructors
Float3::Float3( void ) {}

Float3::Float3( const Float3& c )
{ v[X] = c.v[X], v[Y] = c.v[Y], v[Z] = c.v[Z]; }

Float3::Float3( const float a, const float b, const float c )
{ v[X] = a, v[Y] = b, v[Z] = c; }

Float3::Float3( const float* a )
{ v[X] = a[X], v[Y] = a[Y], v[Z] = a[Z]; }

Float3::Float3( const double* a )
{ v[X] = a[X], v[Y] = a[Y], v[Z] = a[Z]; }




// operators , io
void 
Float3::print(ostream& os) const
{
  os << v[0] << " " << v[1] << " " << v[2];
}

ostream&
operator<<( ostream& os, const Float3& c )
{
  c.print( os );	
  return os;
}

istream&
operator>>( istream& is, Float3& f )
{
  return is >> f.v[0] >> f.v[1] >> f.v[2];
}


// constructs some normal, perpendicular vector
Float3
Float3::perp( void ) const
{
  Float3 nrm = *this;
  if( !nrm.normalize() ) return Float3( 1, 0, 0 );

  Float3 pnrm;
  // some component must be < 1/(sqrt(3))
  if( abs( nrm.v[X] ) < 0.6f ) pnrm = cross( Float3( 1, 0, 0 ) );
  else if( abs( nrm.v[Y] ) < 0.6f ) pnrm = cross( Float3 ( 0, 1, 0 ) );
  else if( abs( nrm.v[Z] ) < 0.6f ) pnrm = cross( Float3 ( 0, 0, 1 ) );
  else assert( 0 );
  
  return pnrm.dir();
}

int
Float3::collinear( const Float3& a, const Float3& b ) const
{
  return zero( ( a - *this ).cross( a - b ).dot() );
}

int
Float3::nan ( int verbose )
{
  if ( ::nan( v[0], verbose ) ||
      ::nan( v[1], verbose ) ||
      ::nan( v[2], verbose ) ){
    if( verbose ) cerr << "found NaN Float3 at " << ( int )this << endl;
    return 1;
  }else{
    return 0;
  }
}

float
Float3::dist( const Float4& f ) const
{
  return f.dot( Float4( v[0], v[1], v[2], 1 ) );
}

float
Float3::dist( const Float2& p ) const 
{ 
  return v[X] * p.x() + v[Y] * p.y() + v[Z]; 
}


// raises a vector to a power
void            
Float3::power( double p ) 
{
  v[X] = pow ( v[X], p );
  v[Y] = pow ( v[Y], p );
  v[Z] = pow ( v[Z], p );
}









