00001
00002
00003
00004
00005
00006 #ifndef AMROC_CPTLEVELSET_H
00007 #define AMROC_CPTLEVELSET_H
00008
00016 #include "cpt/cpt.h"
00017
00025 template <class DataType, int dim>
00026 class CPTLevelSet : public GFMLevelSet<DataType,dim> {
00027 typedef GFMLevelSet<DataType,dim> base;
00028
00029 public:
00030 typedef typename base::grid_fct_type grid_fct_type;
00031 typedef typename base::grid_data_type grid_data_type;
00032 typedef typename cpt::State<dim,DataType> cpt_type;
00033
00034 CPTLevelSet() : base(), inverse(0), unsign(0), _FillWidth(0),
00035 used_num_vertices(0), used_num_connections(0), used_vertices(0), used_connections(0) {
00036 far_away = 1.e36;
00037 }
00038
00039 virtual ~CPTLevelSet() {}
00040
00041 virtual void register_at(ControlDevice& Ctrl, const std::string& prefix) {
00042 base::LocCtrl = Ctrl.getSubDevice(prefix+"CPT");
00043 RegisterAt(base::LocCtrl,"PlotPhi",base::_PlotPhi);
00044 RegisterAt(base::LocCtrl,"Inverse",inverse);
00045 RegisterAt(base::LocCtrl,"Unsigned",unsign);
00046 RegisterAt(base::LocCtrl,"FillWidth",_FillWidth);
00047 }
00048 virtual void register_at(ControlDevice& Ctrl) {
00049 register_at(Ctrl, "");
00050 }
00051
00052 virtual void SetBrep(const int num_vertices, const DataType* vertices,
00053 const int num_connections, const int* connections) {
00054 Coords ex(dim,0);
00055 BBox wholebb = grow(coarsen(base::GH().wholebbox(),DAGHShadowFactor),base::NGhosts());
00056 DCoords lbcorner = base::GH().worldCoords(wholebb.lower(), wholebb.stepsize());
00057 DCoords ubcorner = base::GH().worldCoords(wholebb.upper()+wholebb.stepsize(),
00058 wholebb.stepsize());
00059 DCoords dist = ubcorner-lbcorner; dist *= dist;
00060 DataType distance = 0.;
00061 for (register int n=0; n<dim; n++) {
00062 distance += dist(n);
00063 domain[n] = lbcorner(n); domain[dim+n] = ubcorner(n);
00064 }
00065 distance = std::sqrt(distance);
00066 state.setParameters( domain, distance );
00067 state.setBRepWithNoClipping( num_vertices, reinterpret_cast<const void*>(vertices),
00068 num_connections, reinterpret_cast<const void*>(connections) );
00069
00070 used_num_vertices = num_vertices;
00071 used_vertices = vertices;
00072 used_num_connections = num_connections;
00073 used_connections = connections;
00074 }
00075
00076 bool GetBrep(int& num_vertices, const DataType*& vertices, int& num_connections, const int*& connections) {
00077 num_vertices = used_num_vertices;
00078 vertices = used_vertices;
00079 num_connections = used_num_connections;
00080 connections = used_connections;
00081 return ((num_vertices>0) && (num_connections>0) && (vertices!=0) && (connections!=0));
00082 }
00083
00084 virtual void SetPhi(grid_fct_type& phi, const int Time, const int Level, double t) {
00085 if (state.getNumberOfGrids()>0) state.clearGrids();
00086
00087 if (phi.len(Level)<=0) return;
00088
00089 Coords ss = phi(Time,Level,0).stepsize();
00090 DCoords dx = base::GH().worldStep(ss);
00091 BBox bb = base::GH().wholebbox();
00092 if (ss(0)>bb.stepsize(0)) bb.coarsen(ss/bb.stepsize());
00093 else bb.refine(bb.stepsize()/ss);
00094 bb.grow(base::NGhosts());
00095
00096 DCoords dxh2(dx); dxh2 *= static_cast<DataType>(0.5);
00097 DCoords lbcorner = base::GH().worldCoords(bb.lower(), bb.stepsize()) + dxh2;
00098 DCoords ubcorner = base::GH().worldCoords(bb.upper(), bb.stepsize()) + dxh2;
00099 DataType ldomain[2*dim];
00100 for (register int n=0; n<dim; n++) {
00101 ldomain[n] = lbcorner(n); ldomain[dim+n] = ubcorner(n);
00102 }
00103
00104 state.setLattice(bb.extents(),ldomain);
00105
00106 forall (phi,Time,Level,c)
00107 grid_data_type& gdphi = phi(Time,Level,c);
00108 Coords lb = gdphi.lower();
00109 Coords ub = gdphi.upper()+gdphi.stepsize();
00110 lb /= gdphi.stepsize(); ub /= gdphi.stepsize();
00111 lb += base::NGhosts(); ub += base::NGhosts();
00112
00113 state.insertGrid( reinterpret_cast<const int*>(lb()),
00114 reinterpret_cast<const int*>(ub()),
00115 reinterpret_cast<DataType*> (gdphi.data()),
00116 reinterpret_cast<DataType*> (0),
00117 reinterpret_cast<DataType*> (0),
00118 reinterpret_cast<int*> (0) );
00119 end_forall
00120
00121 if (state.getNumberOfGrids()>0) {
00122 if (_FillWidth>0) {
00123 double distance = 0.;
00124 for (register int n=0; n<dim; n++)
00125 distance += dx[n]*dx[n];
00126 distance = std::sqrt(distance)*_FillWidth;
00127 state.setParameters( domain, distance );
00128 }
00129
00130 if (unsign) {
00131 if (state.areGridsValidUnsigned()) {
00132 START_WATCH
00133 state.computeClosestPointTransformUnsigned();
00134 END_WATCH(LS_CPT_TRANSFORM)
00135 START_WATCH
00136 state.floodFillUnsigned( far_away );
00137 END_WATCH(LS_CPT_FLOODFILL)
00138 }
00139 else
00140 std::cout << "Invalid grid for closest point transform on lev=" << Level
00141 << " time=" << t << std::endl;
00142 }
00143 else {
00144 if (state.areGridsValid()) {
00145 START_WATCH
00146 state.computeClosestPointTransform();
00147 END_WATCH(LS_CPT_TRANSFORM)
00148 START_WATCH
00149 state.floodFillDetermineSign( far_away );
00150 END_WATCH(LS_CPT_FLOODFILL)
00151 if (inverse) {
00152 forall (phi,Time,Level,c)
00153 grid_data_type& gdphi = phi(Time,Level,c);
00154 gdphi.multiply(-1.0);
00155 end_forall
00156 }
00157 }
00158 else
00159 std::cout << "Invalid grid for closest point transform on lev=" << Level
00160 << " time=" << t << std::endl;
00161 }
00162 }
00163
00164 START_WATCH
00165 Sync(phi,Time,Level);
00166 END_WATCH(LS_SYNC)
00167
00168
00169 if (!unsign) {
00170 if (base::Dim()==1) {
00171 forall (phi,Time,Level,c)
00172 grid_data_type& gdphi = phi(Time,Level,c);
00173 BBox bb = gdphi.bbox();
00174 Coords ss = bb.stepsize();
00175 BeginFastIndex3(ph, bb, gdphi.data(), DataType);
00176 bb.grow(-base::NGhosts());
00177 for_1 (n, bb, ss)
00178 if (FastIndex1(ph,n)==-far_away) {
00179 if (FastIndex1(ph,n-ss(0))>=0 || FastIndex1(ph,n+ss(0))>=0)
00180 FastIndex1(ph,n)=far_away;
00181 }
00182 end_for
00183 EndFastIndex1(ph);
00184 end_forall
00185 }
00186 else if (base::Dim()==2) {
00187 forall (phi,Time,Level,c)
00188 grid_data_type& gdphi = phi(Time,Level,c);
00189 BBox bb = gdphi.bbox();
00190 Coords ss = bb.stepsize();
00191 BeginFastIndex2(ph, bb, gdphi.data(), DataType);
00192 bb.grow(-base::NGhosts());
00193 for_2 (n, m, bb, ss)
00194 if (FastIndex2(ph,n,m)==-far_away) {
00195 if (FastIndex2(ph,n-ss(0),m)>=0 || FastIndex2(ph,n,m-ss(1))>=0 ||
00196 FastIndex2(ph,n+ss(0),m)>=0 || FastIndex2(ph,n,m+ss(1))>=0)
00197 FastIndex2(ph,n,m)=far_away;
00198 }
00199 end_for
00200 EndFastIndex2(ph);
00201 end_forall
00202 }
00203 else if (base::Dim()==3) {
00204 forall (phi,Time,Level,c)
00205 grid_data_type& gdphi = phi(Time,Level,c);
00206 BBox bb = gdphi.bbox();
00207 Coords ss = bb.stepsize();
00208 BeginFastIndex3(ph, bb, gdphi.data(), DataType);
00209 bb.grow(-base::NGhosts());
00210 for_3 (n, m, l, bb, ss)
00211 if (FastIndex3(ph,n,m,l)==-far_away) {
00212 if (FastIndex3(ph,n-ss(0),m,l)>=0 || FastIndex3(ph,n,m-ss(1),l)>=0 || FastIndex3(ph,n,m,l-ss(2))>=0 ||
00213 FastIndex3(ph,n+ss(0),m,l)>=0 || FastIndex3(ph,n,m+ss(1),l)>=0 || FastIndex3(ph,n,m,l+ss(2))>=0)
00214 FastIndex3(ph,n,m,l)=far_away;
00215 }
00216 end_for
00217 EndFastIndex3(ph);
00218 end_forall
00219 }
00220 }
00221
00222 START_WATCH
00223 Sync(phi,Time,Level);
00224 END_WATCH(LS_SYNC)
00225 START_WATCH
00226 ExternalBoundaryUpdate(phi,Time,Level);
00227 END_WATCH(BOUNDARIES_EXTERNAL)
00228 }
00229
00230 virtual void SetGrid(grid_data_type& gdphi, const int& Level, const double& t) {
00231 if (state.getNumberOfGrids()>0) state.clearGrids();
00232
00233 BBox bb = gdphi.bbox();
00234 Coords ss = bb.stepsize();
00235 DCoords dx = base::GH().worldStep(ss);
00236 DCoords dxh2(dx); dxh2 *= static_cast<DataType>(0.5);
00237 DCoords lbcorner = base::GH().worldCoords(bb.lower(), ss) + dxh2;
00238 DCoords ubcorner = base::GH().worldCoords(bb.upper(), ss) + dxh2;
00239 DataType ldomain[2*dim];
00240 for (register int n=0; n<dim; n++) {
00241 ldomain[n] = lbcorner(n); ldomain[dim+n] = ubcorner(n);
00242 }
00243
00244 state.setLattice(bb.extents(),ldomain);
00245
00246 Coords lb = gdphi.lower();
00247 Coords ub = gdphi.upper()+ss;
00248 lb /= ss; ub /= ss;
00249 lb += base::NGhosts(); ub += base::NGhosts();
00250
00251 state.insertGrid( reinterpret_cast<const int*>(lb()),
00252 reinterpret_cast<const int*>(ub()),
00253 reinterpret_cast<DataType*> (gdphi.data()),
00254 reinterpret_cast<DataType*> (0),
00255 reinterpret_cast<DataType*> (0),
00256 reinterpret_cast<int*> (0) );
00257
00258 if (state.getNumberOfGrids()>0) {
00259 if (_FillWidth>0) {
00260 double distance = 0.;
00261 for (register int n=0; n<dim; n++)
00262 distance += dx[n]*dx[n];
00263 distance = std::sqrt(distance)*_FillWidth;
00264 state.setParameters( domain, distance );
00265 }
00266
00267 if (unsign) {
00268 if (state.areGridsValidUnsigned()) {
00269 START_WATCH
00270 state.computeClosestPointTransformUnsigned();
00271 END_WATCH(LS_CPT_TRANSFORM)
00272 START_WATCH
00273 state.floodFillUnsigned( far_away );
00274 END_WATCH(LS_CPT_FLOODFILL)
00275 }
00276 else
00277 std::cout << "Invalid grid for closest point transform on lev=" << Level
00278 << " time=" << t << std::endl;
00279 }
00280 else {
00281 if (state.areGridsValid()) {
00282 START_WATCH
00283 state.computeClosestPointTransform();
00284 END_WATCH(LS_CPT_TRANSFORM)
00285 START_WATCH
00286 state.floodFillDetermineSign( far_away );
00287 END_WATCH(LS_CPT_FLOODFILL)
00288 if (inverse)
00289 gdphi.multiply(-1.0);
00290 }
00291 else
00292 std::cout << "Invalid grid for closest point transform on lev=" << Level
00293 << " time=" << t << std::endl;
00294 }
00295 }
00296 }
00297
00298 inline cpt_type& State() { return state; }
00299 inline const cpt_type& State() const { return state; }
00300 inline void SetUnsigned(const int us) { unsign = us; }
00301 inline int Unsigned() const { return unsign; }
00302 inline void SetInverse(const int iv) { inverse = iv; }
00303 inline int Inverse() const { return inverse; }
00304
00305 protected:
00306 cpt_type state;
00307 int inverse, unsign, _FillWidth;
00308 int used_num_vertices, used_num_connections;
00309 const DataType* used_vertices;
00310 const int* used_connections;
00311 DataType far_away;
00312 DataType domain[2*dim];
00313 };
00314
00315
00316 #endif