fish/simplestreamline/SimpleStreamline.cpp

00001 #include <ocean/GLvish/VRenderObject.hpp>
00002 #include <fish/lakeview/bone/FishSlice.hpp>
00003 #include <fish/lakeview/bone/FishField.hpp>
00004 
00005 #include <ocean/GLvish/Colormap.hpp> // use of color_t
00006 
00007 #include <eagle/FixedArray.hpp>
00008 #include <field/DirectProductArray.hpp>
00009 #include <ocean/GLvish/BoundingBox.hpp>
00010 
00011 #include <fish/fiber/vector/Interpolate.hpp>
00012 #include <fish/fiber/vector/LinearIpol.hpp>
00013 #include <fish/fiber/vector/CubicIpol.hpp>
00014 
00015 #include <ocean/plankton/VOperatorCache.hpp>
00016 
00017 
00018 
00019 using namespace Wizt;
00020 using namespace Fiber;
00021 
00039 class SimpleStreamline : public virtual VRenderObject,  public virtual Fish<Slice>, public virtual Fish<Field>
00040 {
00041 public:
00042         typedef MemArray<3, tvector>           VectorArray_t; 
00043         typedef MemArray<3, point>             CoordsArray_t; 
00044         typedef DirectProductMemArray<point>   ProceduralArray_t; 
00045 
00046         typedef FixedArray<float,3> rgb; 
00047 
00048         // define data type for storing one line
00049         typedef std::vector<point> Line_t;
00050 
00051         // prepare storing and caching of computed lines in an std::vector of lines
00052         typedef VOperatorCache<std::vector<Line_t> > OpCache_t;
00053 
00054         TypedSlot<int> LineLength;
00055         TypedSlot<int> LineWidth;
00056         TypedSlot<int> PointSize;
00057         TypedSlot<int> LineNumber;
00058         TypedSlot<double> StepSize;
00059         TypedSlot<double> FanDelta;
00060 
00061         TypedSlot<double> X,
00062                           Y,
00063                           Z;
00064 
00065         struct  MyState : State
00066         {};
00067 
00068         override RefPtr<State> newState() const
00069         {
00070                 return new MyState();
00071         }
00072 
00073         SimpleStreamline(const string&name, int p, const RefPtr<VCreationPreferences>&VP)
00074         : VRenderObject(name, p, VP)
00075         , Fish<VObject>(this)
00076         , Fish<Field>("datafield")
00077         , LineLength(this, "LineLength", 40)
00078         , LineWidth(this, "LineWidth", 2)
00079         , PointSize(this, "PointSize", 2)
00080         , LineNumber(this, "LineNumber", 10)
00081         , StepSize(this, "StepSize", 0.1)
00082         , FanDelta(this, "FanDelta", 0.05)
00083         , X(this, "X", 0.271)
00084         , Y(this, "Y", 0.294)
00085         , Z(this, "Z", 0.531)
00086         {
00087                 LineLength.setProperty("max", 100); 
00088                 LineLength.setProperty("min", 1); 
00089                 LineWidth.setProperty("max", 20); 
00090                 PointSize.setProperty("max", 20); 
00091                 LineNumber.setProperty("min", 1);
00092                 X.setProperty("max", 1.0);
00093                 Y.setProperty("max", 1.0);
00094                 Z.setProperty("max", 1.0); 
00095 
00096                 acceptType<Eagle::tvector3>();
00097         }
00098 
00099 
00100         override bool update( VRequest&R, double precision );
00101         override void render( VRenderContext&R ) const;
00102 
00103         void getCoordinates(const point& float_index, point& position_cordinates);
00104 };
00105 
00106 
00110 bool SimpleStreamline::update( VRequest&R, double precision )
00111 {
00112         printf("SimpleStreamline::update(): updating\n"); 
00113 
00114 FieldSelector FS = getFieldSelector(R);
00115 
00116 // get the grid of the fiber bundle 
00117 RefPtr<Grid>  G = FS.GridSource();
00118         if (!G)
00119                 return true;
00120 
00121 // get the coordinates of the grid
00122 RefPtr<Field> Coords  = G->CartesianPositions();
00123         if (!Coords)  { puts("SimpleStreamline::update(): No coord field!"); return true; } 
00124 
00125 
00126 // get the vector data of the grid
00127 RefPtr<Field> Vectors = FS.getField();
00128         if (!Vectors) { puts("SimpleStreamline::update(): No vector field!"); return true; } 
00129 
00130 
00131 // associate the caching object to the field. As long as the field is valid the 
00132 // cached lines can by used. If a new field is load (e.g. from another time step) 
00133 // OC is a reference pointer to a std::vector of lines, where they are going to be stored.
00134 RefPtr<OpCache_t>&OC = OpCache_t::retrieve( *Vectors ) [ self() ]; 
00135         if (!OC) OC = new OpCache_t(); 
00136 
00137 
00138 RefPtr<VectorArray_t> Vctrs = Vectors->getData(); 
00139         if( !Vctrs)
00140         {
00141                 printf("SimpleStreamline::update(): Could get vector field data yet!\n"); 
00142                 if (OC)
00143                 {
00144                         OC->resize( 0 );
00145                         GLCache::clear( *OC );
00146                 }
00147                 return true;
00148         } 
00149         else
00150                 printf("SimpleStreamline::update(): Gotvector field data!\n"); 
00151 
00152         RefPtr<ProceduralArray_t>   PCrds = Coords->getData(); 
00153         RefPtr<CoordsArray_t>       Crds  = Coords->getData(); 
00154         if (!(Crds || PCrds))
00155                 {
00156                         printf("SimpleStreamline::update(): Did not find any coordinates :  %s\n",
00157                                Typename( Coords->getType() ).c_str() ); 
00158                         return true;
00159                 } 
00160 
00161 
00162 
00163 RefPtr<ValueSet> Changeables = new ValueSet(); 
00164         // Register parameters that shall invoke an update call, if changed.
00165         Changeables & R += X, Y, Z, LineLength, PointSize, StepSize, FanDelta, LineNumber; 
00166 
00167         // if parameters didn't change, don't do a new calculation
00168         if (OC->unchanged( Changeables ) ) 
00169         {
00170                 printf("SimpleStreamline::update(): Line Calc Skipped, Lines in Cache...\n");
00171                 return true;
00172         } 
00173 
00174 
00175 int line_number = 1; 
00176         LineNumber << R >> line_number; 
00177 
00178 // resize std::vector to number of lines
00179         OC->resize( line_number ); 
00180         GLCache::clear( *OC );
00181 
00182 // Now do the Interpolation of the Coordinates 
00183 // Get index Range of Data (and Coordinates)
00184         MultiIndex<3> FieldSize = Vctrs->Size(); 
00185 
00186 
00187 double x, y, z; 
00188 point float_index; 
00189 point max_float_index; 
00190 point vertex; 
00191 int line_length; 
00192 double hh; 
00193 double fan_delta;
00194 
00195         LineLength << R >> line_length; 
00196         StepSize << R >> hh; 
00197         FanDelta<< R >> fan_delta;
00198 
00199 // Get user specified position ranging from 0 to 1.0 in each coordinate covering the whole dataset 
00200         X << R >> x; 
00201         Y << R >> y; 
00202         Z << R >> z; 
00203 
00204         max_float_index = FieldSize[0] - 1, FieldSize[1] - 1, FieldSize[2] - 1;
00205         float_index = x * FieldSize[0] - 1, y * FieldSize[1] -1 , z * FieldSize[2] - 1; 
00206 
00207 // Clamp wrong inputs
00208         for (int i = 0; i < 3; i++)
00209         {
00210                 if( float_index[i] < 0 )
00211                         float_index[i] = 0.0; 
00212 
00213                 if( float_index[i] >= FieldSize[i] )
00214                         float_index[i] = FieldSize[i] - 1;
00215         } 
00216 
00217 // assume uniform PCrds here (should be extended to other types of coordinates (curvlinear, ...) as well ) 
00218 // get maximum and minimum coordinates
00219 point DomainStart = PCrds->first(); 
00220 point DomaintEnd = PCrds->last(); 
00221 
00222 tvector DomainDiagonal = DomaintEnd - DomainStart; 
00223 
00224 
00225 // Calc Positions of the StartPoints of the fan of streamlines
00226 std::vector<point> StartVertex; 
00227         StartVertex.resize(line_number); 
00228 
00229         // First calculate the start position of the first of the start points 
00230         // This is done using DomainDiagonal as a basis and componentwise array operations, so 
00231         // it can be optimized using the vector SMID unit of the CPU.
00232         StartVertex[0] = ( DomainStart + tvector(component_wise( component_wise(DomainDiagonal, max_float_index, Eagle::Operator<'/'>() ), float_index, Eagle::Operator<'*'>() ) ) ); 
00233 
00234 
00235 tvector CurrentDir; 
00236 point CurrentVertex; 
00237 point CurrentFloatIndex; 
00238 tvector FanOffset; 
00239         FanOffset = 1, 0, 0;
00240 
00241         resetBBox( R ); 
00242         embrace( R, StartVertex[0]); 
00243 
00244         // Calculate stream lines
00245         for(int l = 0; l < line_number; l++)
00246         {
00247                 // Calucalte startpoints of the fan  by adding the offest to the x-coordinate
00248                 StartVertex[l] = StartVertex[0] + FanOffset * l * fan_delta;
00249                 
00250         Line_t&myLine = (*OC)[l]; 
00251                 myLine.clear(); 
00252                 
00253                 for(int i = 0; i < line_length; i++)
00254                 {
00255                         if (i == 0)
00256                         {
00257                                 CurrentVertex = StartVertex[l]; 
00258 
00259                                 // We have to use the float_index space for the interpolator. We already know 
00260                                 // it for the startpoint.
00261                                 Interpolate<3, tvector, CubicIpol <tvector> > VecField(*Vctrs, float_index); 
00262                                 // Get direction at current point
00263                                 CurrentDir = VecField.eval(); 
00264                         }
00265                         else
00266                         {
00267                                 // Calculate the floatindex of the current position from data coordinates
00268                                 CurrentFloatIndex = point( tvector( component_wise(component_wise(CurrentVertex - DomainStart, DomainDiagonal, Eagle::Operator<'/'>() ), max_float_index, Eagle::Operator<'*'>()) )); 
00269 
00270                                 // Stop line calculation, when going out of the data range
00271                                 if(CurrentFloatIndex [0] < 0.0 ||CurrentFloatIndex [0] > max_float_index[0])
00272                                         break; 
00273                                 if(CurrentFloatIndex [1] < 0.0 ||CurrentFloatIndex [1] > max_float_index[1])
00274                                         break; 
00275                                 if(CurrentFloatIndex [2] < 0.0 ||CurrentFloatIndex [2] > max_float_index[2])
00276                                         break; 
00277 
00278                                 // Get direction at current point.
00279                                 Interpolate<3, tvector, CubicIpol <tvector> > VecField(*Vctrs, CurrentFloatIndex); 
00280                                 CurrentDir = VecField.eval(); 
00281                         } 
00282 
00283                         // calc new point
00284                         CurrentVertex += CurrentDir * hh; 
00285                         myLine.push_back(CurrentVertex); 
00286                         embrace( R, CurrentVertex); 
00287                 }
00288         } 
00289 
00290         printf("SimpleStreamline::update(): Integrated into Cache\n");
00291         closeBBox( R ); 
00292         
00293         return true;
00294 }
00295 
00296 
00297 void SimpleStreamline::render( VRenderContext& Context ) const
00298 {
00299 
00300 // Get handle to vectorfield 
00301  RefPtr<Field> Vectors = getField( Context ); 
00302         if (!Vectors) 
00303         {
00304                 puts("void SimpleStreamline::render(VRenderContext&RenderContext): NO VECTORS");
00305                 return;
00306         } 
00307 
00308 // Get cached lines
00309 const RefPtr<OpCache_t>&OC = OpCache_t::retrieve( *Vectors ) ( self() );
00310         if (!OC)
00311         {
00312                 puts("void SimpleStreamline::render(VRenderContext&RenderContext): NO LINE CACHE"); 
00313                 return;
00314         } 
00315         if (OC->size()<1)
00316         {
00317                 puts("void SimpleStreamline::render(VRenderContext&RenderContext): NO LINES in CACHE"); 
00318                 return;
00319         } 
00320 
00321 int line_width, point_size; 
00322 int line_length  = 1; 
00323 
00324         LineWidth  << Context >> line_width; 
00325         PointSize  << Context >> point_size; 
00326         LineLength << Context >> line_length;
00327 
00328         if(line_width < 1)
00329                 line_width = 1; 
00330 
00331         glEnable(GL_DEPTH_TEST); 
00332         glDisable(GL_LIGHTING); 
00333 
00334         glLineWidth( line_width ); 
00335 
00336         if(point_size > 0)
00337                 glPointSize( point_size ); 
00338         else
00339                 glPointSize( 1 ); 
00340 
00341         RefPtr<MyState>  state = myState(Context); 
00342 
00343         RefPtr<ValueSet> RenderParameterSpace = new ValueSet(); 
00344         RefPtr<DisplayList> DL;
00345                 try{
00346                         DL = Context(*OC)(this)( RenderParameterSpace ); 
00347                 } 
00348                 catch(...){}
00349         RefPtr<ValueSet> Changeables = new ValueSet();
00350 Changeables & Context += LineLength, LineNumber, StepSize; 
00351 
00352         if ( DL && OC->unchanged( Changeables  ))   //call display list if availlable, check if changables have changed         
00353         {
00354                 printf("SimpleStreamline::render(): Calling List\n"); 
00355                 DL->call(); 
00356         } 
00357         else                                        //prepare display list
00358         {
00359                 printf("SimpleStreamline::render(): Rendering List\n");
00360  
00361                 DL = Context[*OC][this][ RenderParameterSpace ]; 
00362                 if (!DL) throw "SimpleStreamline::render() No Display List!?"; 
00363 
00364                 glCompile( *DL ) 
00365                 {
00366                 int l = 0; 
00367                 int p = 0; 
00368 
00369                         // iterate over all lines in cache and draw a line_strip
00370                         for( OpCache_t::const_iterator lbit = OC->begin(); lbit != OC->end(); lbit++ )
00371                         {
00372                                 p = 0; 
00373                                 //printf("SimpleStreamline::render()> :Line %d\n", l);
00374                         Line_t::const_iterator lit = lbit->begin(); 
00375 
00376                                 if (lit == lbit->end() )
00377                                         break; 
00378 
00379                                 glBegin( GL_LINE_STRIP );    // GLCHECK must not be used in between a glBegin and glEnd statement
00380                         bivector dir;
00381 
00382                                 for(; lit != lbit->end();)
00383                                 {
00384 //                                      printf("SimpleStreamline::render()> :point %d\n", p);
00385                                 point   P = *lit; 
00386                                         lit++; 
00387                                         if (lit != lbit->end()) 
00388                                                 dir = (*lit - P).unit(); 
00389 
00390                                         // use length of the line as color information
00391                                         glColor3f((double)p/lbit->size() , 1-(double)p/lbit->size(), 0.0);
00392                                         glVertex( P ); 
00393 
00394                                         p++;
00395                                 } 
00396 
00397                                 l++; 
00398                                 glEnd(); 
00399                         } 
00400 
00401 
00402                         // draw points 
00403                         if(point_size > 0 )
00404                         {
00405                                 for( OpCache_t::const_iterator lbit = OC->begin(); lbit != OC->end(); lbit++ ) 
00406                                 {
00407                                         p = 0; 
00408                                         //printf("SimpleStreamline::render()> :Line %d\n", l); 
00409                                         Line_t::const_iterator lit = lbit->begin(); 
00410 
00411                                         if (lit == lbit->end() ) 
00412                                                 break; 
00413 
00414                                 tvector dir; 
00415                                         glBegin(GL_POINTS); 
00416 
00417                                         for(; lit != lbit->end();)
00418                                         {
00419                                                 //printf("SimpleStreamline::render()> :point %d\n", p);
00420                                         point   P = *lit; 
00421                                                 lit++; 
00422                                                 if (lit != lbit->end())
00423                                                         dir = (*lit - P).unit(); 
00424 
00425                                                 glColor3f((double)p/lbit->size(), 1-(double)p/lbit->size(), 0.7); 
00426                                                 glVertex( P ); 
00427 
00428                                                 p++;
00429                                         } 
00430                                         glEnd(); 
00431                                 } 
00432                         }
00433                 }
00434         } 
00435 
00436         state->touch(); // synchinozes state, prevents unneccessary calls of the update function.
00437 }
00438 
00439 
00440 static Ref<VCreator<SimpleStreamline, AcceptList<Fiber::Field> >  > myCreator("Tutorial/SimpleStreamline");
00441 
00442 VISH_DEFAULT_INIT

Generated on Thu Apr 2 18:58:50 2009 for VISHTutorial by  doxygen 1.4.7