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
00027 class boundary_grid_fast : public boundary_model {
00028
00029 public:
00030
00031
00032
00033
00045 boundary_grid_fast(data_grid_bathy* height,
00046 reflect_loss_model* reflect_loss = NULL) :
00047 boundary_model(reflect_loss), _height(height) {
00048 this->_height->interp_type(0, GRID_INTERP_PCHIP);
00049 this->_height->interp_type(1, GRID_INTERP_PCHIP);
00050 this->_height->edge_limit(0, true);
00051 this->_height->edge_limit(1, true);
00052 if ( reflect_loss == NULL) {
00053 this->reflect_loss( new reflect_loss_rayleigh(
00054 reflect_loss_rayleigh::SAND) ) ;
00055 }
00056 }
00057
00061 virtual ~boundary_grid_fast() {
00062 delete _height;
00063 }
00064
00074 virtual void height(const wposition& location, matrix<double>* rho,
00075 wvector* normal = NULL, bool quick_interp = false) {
00076 if (quick_interp) {
00077 this->_height->interp_type(0, GRID_INTERP_LINEAR);
00078 this->_height->interp_type(1, GRID_INTERP_LINEAR);
00079 } else {
00080 this->_height->interp_type(0, GRID_INTERP_PCHIP);
00081 this->_height->interp_type(1, GRID_INTERP_PCHIP);
00082 }
00083 if (normal) {
00084 matrix<double> gtheta(location.size1(), location.size2());
00085 matrix<double> gphi(location.size1(), location.size2());
00086 matrix<double> t(location.size1(), location.size2());
00087 matrix<double> p(location.size1(), location.size2());
00088 this->_height->interpolate(location.theta(), location.phi(), rho,
00089 >heta, &gphi);
00090
00091 t = element_div(gtheta, *rho);
00092 p = element_div(gphi, element_prod(*rho, sin(location.theta())));
00093 normal->theta(
00094 element_div(-t, sqrt(1.0 + abs2(t))));
00095 normal->phi(element_div(-p, sqrt(1.0 + abs2(p))));
00096 normal->rho(sqrt(
00097 1.0 - abs2(normal->theta()) - abs2(normal->phi())));
00098 } else {
00099 this->_height->interpolate(location.theta(), location.phi(), rho);
00100 }
00101 }
00102
00112 virtual void height(const wposition1& location, double* rho,
00113 wvector1* normal = NULL, bool quick_interp = false) {
00114 if (quick_interp) {
00115 this->_height->interp_type(0, GRID_INTERP_LINEAR);
00116 this->_height->interp_type(1, GRID_INTERP_LINEAR);
00117 } else {
00118 this->_height->interp_type(0, GRID_INTERP_PCHIP);
00119 this->_height->interp_type(1, GRID_INTERP_PCHIP);
00120 }
00121 if (normal) {
00122 double loc[2] = { location.theta(), location.phi() };
00123 double grad[2];
00124 *rho = this->_height->interpolate(loc, grad);
00125 const double t = grad[0] / (*rho);
00126 const double p = grad[1] / ((*rho) * sin(location.theta()));
00127 normal->theta(-t / sqrt(1.0 + t * t));
00128 normal->phi(-p / sqrt(1.0 + p * p));
00129 const double N = normal->theta() * normal->theta()
00130 + normal->phi() * normal->phi();
00131 normal->rho(sqrt(1.0 - N));
00132 } else {
00133 double loc[2] = { location.theta(), location.phi() };
00134 *rho = this->_height->interpolate(loc);
00135 }
00136 }
00137
00138 private:
00139
00141 data_grid_bathy* _height;
00142
00143 };
00144
00145 }
00146 }