00001
00005 #pragma once
00006
00007 #include <usml/ocean/boundary_model.h>
00008 #include <usml/ocean/reflect_loss_rayleigh.h>
00009
00010 namespace usml {
00011 namespace ocean {
00012
00030 template< class DATA_TYPE, int NUM_DIMS > class boundary_grid
00031 : public boundary_model
00032 {
00033
00034
00035
00036 private:
00037
00039 data_grid<DATA_TYPE, NUM_DIMS>* _height;
00040
00041 public:
00042
00052 virtual void height(const wposition& location, matrix<double>* rho,
00053 wvector* normal = NULL, bool quick_interp = false) {
00054 switch (NUM_DIMS) {
00055
00056
00057
00058
00059 case 1:
00060 if(quick_interp) { this->_height->interp_type(0, GRID_INTERP_LINEAR); }
00061 else{ this->_height->interp_type(0, GRID_INTERP_PCHIP); }
00062 if (normal) {
00063
00064 matrix<double> gtheta(location.size1(), location.size2());
00065 matrix<double> t(location.size1(), location.size2());
00066 this->_height->interpolate(location.theta(), rho, >heta);
00067 t = min(element_div(gtheta,*rho),1.0);
00068 normal->theta(
00069 element_div( -t, sqrt(1.0+abs2(t)) ));
00070 normal->phi(scalar_matrix<double>(location.size1(),location.size2(),0.0));
00071 normal->rho( sqrt(1.0-abs2(normal->theta())) ) ;
00072 } else {
00073 this->_height->interpolate(location.theta(), rho);
00074 }
00075 break;
00076
00077
00078
00079
00080 case 2:
00081 if(quick_interp) {
00082 this->_height->interp_type(0, GRID_INTERP_LINEAR);
00083 this->_height->interp_type(1, GRID_INTERP_LINEAR);
00084 } else{
00085 this->_height->interp_type(0, GRID_INTERP_PCHIP);
00086 this->_height->interp_type(1, GRID_INTERP_PCHIP);
00087 }
00088 if (normal) {
00089 matrix<double> gtheta(location.size1(), location.size2());
00090 matrix<double> gphi(location.size1(), location.size2());
00091 matrix<double> t(location.size1(), location.size2());
00092 matrix<double> p(location.size1(), location.size2());
00093 this->_height->interpolate(location.theta(), location.phi(),
00094 rho, >heta, &gphi);
00095
00096 t = element_div(gtheta, *rho);
00097 p = element_div(gphi, element_prod(*rho, sin(location.theta())));
00098 normal->theta(
00099 element_div( -t, sqrt(1.0+abs2(t)) ));
00100 normal->phi(
00101 element_div( -p, sqrt(1.0+abs2(p)) ));
00102 normal->rho(sqrt(
00103 1.0 - abs2(normal->theta()) - abs2(normal->phi()) ));
00104 } else {
00105 this->_height->interpolate(location.theta(), location.phi(),
00106 rho);
00107 }
00108 break;
00109
00110
00111
00112
00113 default:
00114 throw std::invalid_argument("dataset must be 1-D or 2-D");
00115 break;
00116 }
00117 }
00118
00128 virtual void height(const wposition1& location, double* rho,
00129 wvector1* normal = NULL, bool quick_interp = false) {
00130 switch (NUM_DIMS) {
00131
00132
00133
00134
00135 case 1:
00136 if(quick_interp) { this->_height->interp_type(0, GRID_INTERP_LINEAR); }
00137 else{ this->_height->interp_type(0, GRID_INTERP_PCHIP); }
00138 if (normal) {
00139 double theta = location.theta();
00140 double gtheta;
00141 *rho = this->_height->interpolate(&theta, >heta);
00142 const double t = gtheta / (*rho);
00143 normal->theta(-t / sqrt(1.0 + t * t));
00144 normal->phi(0.0);
00145 const double N = normal->theta() * normal->theta() ;
00146 normal->rho( sqrt(1.0-N) );
00147 } else {
00148 double theta = location.theta();
00149 *rho = this->_height->interpolate(&theta);
00150 }
00151 break;
00152
00153
00154
00155
00156 case 2:
00157 if(quick_interp) {
00158 this->_height->interp_type(0, GRID_INTERP_LINEAR);
00159 this->_height->interp_type(1, GRID_INTERP_LINEAR);
00160 } else{
00161 this->_height->interp_type(0, GRID_INTERP_PCHIP);
00162 this->_height->interp_type(1, GRID_INTERP_PCHIP);
00163 }
00164 if (normal) {
00165 double loc[2] = { location.theta(), location.phi() };
00166 double grad[2];
00167 *rho = this->_height->interpolate(loc, grad);
00168 const double t = grad[0] / (*rho);
00169 const double p = grad[1] / ((*rho) * sin(location.theta()));
00170 normal->theta(-t / sqrt(1.0 + t * t));
00171 normal->phi(-p / sqrt(1.0 + p * p));
00172 const double N = normal->theta() * normal->theta()
00173 + normal->phi() * normal->phi();
00174 normal->rho( sqrt(1.0-N) );
00175 } else {
00176 double loc[2] = { location.theta(), location.phi() };
00177 *rho = this->_height->interpolate(loc);
00178 }
00179 break;
00180
00181
00182
00183
00184 default:
00185 throw std::invalid_argument("bathymetry must be 1-D or 2-D");
00186 break;
00187 }
00188 }
00189
00190
00191
00192
00204 boundary_grid(data_grid<DATA_TYPE, NUM_DIMS>* height,
00205 reflect_loss_model* reflect_loss = NULL) :
00206 boundary_model(reflect_loss), _height(height) {
00207 this->_height->interp_type(0,GRID_INTERP_PCHIP);
00208 this->_height->interp_type(1,GRID_INTERP_PCHIP);
00209 this->_height->edge_limit(0,true);
00210 this->_height->edge_limit(1,true);
00211 if ( reflect_loss == NULL ) {
00212 this->reflect_loss( new reflect_loss_rayleigh(
00213 reflect_loss_rayleigh::SAND) ) ;
00214 }
00215 }
00216
00220 virtual ~boundary_grid() {
00221 delete _height;
00222 }
00223
00224 };
00225
00226 }
00227 }