int	// ADD-BY-LEETEN 12/20/2011
main(int argc, char**argv) {

  VECTOR3 minLen, maxLen; 

  printf("hello! entering testmain...\n"); 

  OSUFlow *osuflow = new OSUFlow(); 
  printf("read file %s\n", argv[1]); 
  osuflow->LoadUncertainDataInGaussian(argv[1], argv[2], true); //true: a steady flow field
  osuflow->Boundary(minLen, maxLen); 
  printf(" volume boundary X: [%f %f] Y: [%f %f] Z: [%f %f]\n", 
                                minLen[0], maxLen[0], minLen[1], maxLen[1], 
                                minLen[2], maxLen[2]); 
  float from[3], to[3]; 
  from[0] = minLen[0];   from[1] = minLen[1];   from[2] = minLen[2]; 
  to[0] = maxLen[0];   to[1] = maxLen[1];   to[2] = maxLen[2]; 

  size_t numSeeds[3] = {1,1,1};
  osuflow->SetRegularSeedPoints(from, to, numSeeds);

  // print seeds
  int nSeeds;
  VECTOR3* seeds = osuflow->GetSeeds(nSeeds); 
  for (int i=0; i<nSeeds; i++) 
    printf(" seed no. %d : [%f %f %f]\n", i, seeds[i][0], 
	   seeds[i][1], seeds[i][2]); 

  int samples = 10;

  list<vtListSeedTrace*> list; 
  osuflow->SetIntegrationParams(1, 5); 
  osuflow->GenStreamLines(list , FORWARD_DIR, 50, 0, samples);
  printf(" done integrations\n"); 
  printf("list size = %d\n", (int)list.size()); 

  std::list<vtListSeedTrace*>::iterator pIter; 


  pIter = list.begin(); 
  for (; pIter!=list.end(); pIter++) {
    vtListSeedTrace *trace = *pIter; 
    std::list<VECTOR3*>::iterator pnIter; 
    pnIter = trace->begin(); 
    for (; pnIter!=trace->end(); pnIter++) {

      VECTOR3 p = **pnIter; 
      printf("%f %f %f, ", p[0], p[1], p[2]); 


    }
    printf("\n\n");
  }
  return 0;	// ADD-BY-LEETEN 12/20/2011
}
Exemple #2
0
main(int argc, void *argv[]) {

  VECTOR3 minLen, maxLen; 

  printf("hello! entering testmain...\n"); 

  OSUFlow *osuflow = new OSUFlow(); 
  printf("read file %s\n", argv[1]); 
  osuflow->LoadData((const char*)argv[1], true); //true: a steady flow field 
  osuflow->Boundary(minLen, maxLen); 
  printf(" volume boundary X: [%f %f] Y: [%f %f] Z: [%f %f]\n", 
                                minLen[0], maxLen[0], minLen[1], maxLen[1], 
                                minLen[2], maxLen[2]); 
  float from[3], to[3]; 
  from[0] = minLen[0];   from[1] = minLen[1];   from[2] = minLen[2]; 
  to[0] = maxLen[0];   to[1] = maxLen[1];   to[2] = maxLen[2]; 
  osuflow->SetRandomSeedPoints(from, to, 100); 
  int nSeeds; 
  VECTOR3* seeds = osuflow->GetSeeds(nSeeds); 
  for (int i=0; i<nSeeds; i++) 
    printf(" seed no. %d : [%f %f %f]\n", i, seeds[i][0], 
	   seeds[i][1], seeds[i][2]); 

  list<vtListSeedTrace*> list; 
  osuflow->SetIntegrationParams(1, 5); 
  osuflow->GenStreamLines(list , FORWARD_DIR, 50, 0); 
  printf(" done integrations\n"); 
  printf("list size = %d\n", list.size()); 

  std::list<vtListSeedTrace*>::iterator pIter; 


  pIter = list.begin(); 
  for (; pIter!=list.end(); pIter++) {
    vtListSeedTrace *trace = *pIter; 
    std::list<VECTOR3*>::iterator pnIter; 
    pnIter = trace->begin(); 
    for (; pnIter!=trace->end(); pnIter++) {

      VECTOR3 p = **pnIter; 
      //      printf(" %f %f %f ", p[0], p[1], p[2]); 


    }

  }
}
int main(int argc, char ** argv)
{
#if 1
    // read PLOT3D data
    char file1[256], file2[256];
    int files;
    if (argc<=1) { // load default data
        sprintf(file1, "%s/curvilinear/combxyz.bin", SAMPLE_DATA_DIR); //t->GetDataRoot());
        printf("%s\n", file1);
        sprintf(file2, "%s/curvilinear/combq.bin", SAMPLE_DATA_DIR); //t->GetDataRoot());
        files = 2;
    } else {
        strcpy(file1, argv[1]);
        strcpy(file2, argv[2]);
    }

    // Start by loading some data.
    vtkMultiBlockPLOT3DReader *pl3dReader = vtkMultiBlockPLOT3DReader::New();
    // set data
    pl3dReader->SetXYZFileName(file1);
    pl3dReader->SetQFileName(file2);
    pl3dReader->SetAutoDetectFormat(1);  // should be on for loading binary file
    //pl3dReader->SetScalarFunctionNumber(100);
    pl3dReader->SetVectorFunctionNumber(200); // load velocity
    pl3dReader->Update();
    vtkDataSet *data = vtkDataSet::SafeDownCast( pl3dReader->GetOutput()->GetBlock(0) );

    OSUFlow *osuflow = new OSUFlow;
    CVectorField *field = new VectorFieldVTK( data );
    osuflow->SetFlowField( field );

#else
    // debug with regular grids
    OSUFlow *osuflow = new OSUFlow;
    osuflow->LoadData(SAMPLE_DATA_DIR "/regular/tornado/1.vec", true); //true: static dataset
    CVectorField *field = osuflow->GetFlowField();
#endif


    //field->NormalizeField(true);


    VECTOR3 minLen, maxLen;
    osuflow->Boundary(minLen, maxLen);
    printf(" volume boundary X: [%f %f] Y: [%f %f] Z: [%f %f]\n",
                                minLen[0], maxLen[0], minLen[1], maxLen[1],
                                minLen[2], maxLen[2]);


    int dim[3]	;
    field->getDimension(dim[0], dim[1], dim[2]);
    printf("dim: %d %d %d\n", dim[0], dim[1], dim[2]);

    // define range
    int i1, i2, j1, j2, k1, k2;
    int i,j,k;
    i1 = 0; i2 = dim[0];
    j1 = 0; j2 = dim[1];
    k1 = 0; k2 = dim[2];

    // init file
    char out_fname[4][256];
    char prefix[4][10]={"lambda2", "q", "delta", "gamma"};
    for (i=0; i<4; i++)
    {
        sprintf(out_fname[i], "vortex_%s.raw", prefix[i]);
        printf("Output file: %s\n", out_fname[i]);
    }

    // determine unit
    float x,y,z;
    float unit = std::min(std::min(maxLen[0]-minLen[0], maxLen[1]-minLen[1]), maxLen[2]-minLen[2]) / 50;
    float delta = unit * .1f; // for Jacobian computation
    printf("Sampling unit: %f\n", unit);

    // open file
    int count=0;
    FILE *fp[4];
    for (i=0; i<4; i++)
        fp[i] = fopen(out_fname[i], "wb");

    // detect vortices
    for (z=minLen[2]; z< maxLen[2]; z+=unit) {
        for (y=minLen[1]; y< maxLen[1]; y+=unit)
            for (x=minLen[0]; x< maxLen[0]; x+=unit)
            {
#if 0
                //VECTOR3 v;
                //osuflow->GetFlowField()->at_phys(VECTOR3(x,y,z), 0, v);
                //printf("%f %f %f\n", v[0], v[1], v[2]);
#endif
                float f[4]; //lambda2, q, delta, gamma;
                field->GenerateVortexMetrics(VECTOR3(x,y,z), f[0], f[1], f[2], f[3], delta);
                for (i=0; i<4; i++)
                    fwrite((char *)&f[i], 1, 4, fp[i]);
                count++;
            }
        printf("z=%f\n", z);
    }
    for (i=0; i<4; i++)
        fclose(fp[i]);


    // get sampling dim
    int bdim[3];
    bdim[0] = bdim[1] = bdim[2] = 0;
    {
        int d;
        for (d=0; d<3; d++)
            for (x=minLen[d]; x<=maxLen[d]; x+=unit)
                bdim[d] ++;
    }

    // output
    for (i=0; i<4; i++)
    {
        // get out_fname filename only (no path)
        char *out_fname_no_path = strrchr(out_fname[i], '/');
        if (out_fname_no_path==NULL) out_fname_no_path = out_fname[i]; else out_fname_no_path++;

        char out_desc_fname[256];
        sprintf(out_desc_fname, "%s_%s.nhdr", "vortex", prefix[i]);
        FILE *fp = fopen(out_desc_fname, "wt");
        fprintf(fp,
                "NRRD0001\n"
                "type: float\n"
                "dimension: 3\n"
                "sizes: %d %d %d\n"
                "encoding: raw\n"
                "data file: %s\n"
                "space origin: (%f,%f,%f)\n"
                "space directions: (%f,0,0) (0,%f,0) (0,0,%f)\n"
                "# sampling distance: %f\n"
                "# grid range: %d %d %d - %d %d %d\n"
                "# physical range: %f %f %f - %f %f %f\n",
                bdim[0], bdim[1], bdim[2], out_fname_no_path,
                minLen[0], minLen[1], minLen[2], unit, unit, unit,
                unit, i1, j1, k1, i2, j2, k2, minLen[0], minLen[1], minLen[2], maxLen[0], maxLen[1], maxLen[2]);
        fclose(fp);
    }

    printf("Done (%d elems)\n", count);
    return 0;
}
int main(int argc, char** argv) 
{
  VECTOR3 minLen, maxLen; 

  OSUFlow *osuflow = new OSUFlow(); 
  printf("read file %s\n", argv[1]); 

  osuflow_list = new OSUFlow*[npart];  

  //loading the whole dataset just to get dims. 
  //obviously not very smart. need to change. 

  osuflow->LoadData((const char*)argv[1], true); 
  osuflow->Boundary(minLen, maxLen);    // query the dims

  printf(" volume boundary X: [%f %f] Y: [%f %f] Z: [%f %f]\n", 
	 minLen[0], maxLen[0], minLen[1], maxLen[1], 
	 minLen[2], maxLen[2]); 

  // now subdivide the entire domain into npart subdomains
  // partition the domain and create a lattice

  lat = new Lattice(maxLen[0]-minLen[0]+1, maxLen[1]-minLen[1]+1, 
		    maxLen[2]-minLen[2]+1, 0, npart);
  vb_list = lat->GetBoundsList(); 
  lat->InitSeedLists(); 
  lat->RoundRobin_proc(nproc); 

  plist = new int*[nproc]; 
  num_partitions = new int[nproc]; 
  
  for (int i=0; i<nproc; i++)
    lat->GetPartitions(i, &(plist[i]), num_partitions[i]);
  
  // now create a list of flow field for the subdomains 
  for (int i=0; i<npart; i++) {
    osuflow_list[i] = new OSUFlow(); 
    printf("Domain(%d):  %d %d %d : %d %d %d\n", i, vb_list[i].xmin,  
	   vb_list[i].ymin,  vb_list[i].zmin, vb_list[i].xmax,  
	   vb_list[i].ymax,  vb_list[i].zmax); 

    // load subdomain data into OSUFlow
    VECTOR3 minB, maxB; 
    minB[0] = vb_list[i].xmin;  maxB[0] = vb_list[i].xmax;  
    minB[1] = vb_list[i].ymin;  maxB[1] = vb_list[i].ymax;
    minB[2] = vb_list[i].zmin;  maxB[2] = vb_list[i].zmax; 

    osuflow_list[i]->LoadData((const char*)argv[1], true, minB, maxB); 
  }

  // one streamline list per process 
  sl_list = new list<vtListSeedTrace*>*[nproc]; 

  center[0] = (minLen[0]+maxLen[0])/2.0; 
  center[1] = (minLen[1]+maxLen[1])/2.0; 
  center[2] = (minLen[2]+maxLen[2])/2.0; 
  len[0] = maxLen[0]-minLen[0]; 
  len[1] = maxLen[1]-minLen[1]; 
  len[2] = maxLen[2]-minLen[2]; 

  glutInit(&argc, argv); 
  glutInitDisplayMode(GLUT_RGB|GLUT_DOUBLE|GLUT_DEPTH); 
  glutInitWindowSize(600,600); 
  
  glutCreateWindow("Display streamlines"); 
  glutDisplayFunc(display); 
  glutTimerFunc(10, timer, 0); 
  glutMouseFunc(mymouse); 
  glutMotionFunc(mymotion);
  glutKeyboardFunc(mykey); 
  glutMainLoop(); 
}
int main(int argc, char **argv)
{
	printf("Press 'i' to change the rake\n");

	streamer = vtkOSUFlow::New();

	// read data
	OSUFlow *osuflow = streamer->getOSUFlow();
	const char *filename;
	if (argc>1)
		filename = argv[1];
	else
		filename = SAMPLE_DATA_DIR "/regular/tornado/1.vec";
	osuflow->LoadData(filename, true); //true: static dataset

#ifdef _OPENMP
	osuflow->initOpenMP(8);
#endif

	// dummy dataset for boundary
	VECTOR3 minB, maxB;
	osuflow->Boundary(minB, maxB);

	vtkPolyData *data = vtkPolyData::New();
	vtkPoints *points = vtkPoints::New();
	float p[3];
	p[0] = minB[0]; p[1] = minB[1]; p[2] = minB[2];	points->InsertNextPoint(p);
	p[0] = minB[0]; p[1] = minB[1]; p[2] = maxB[2];	points->InsertNextPoint(p);
	p[0] = minB[0]; p[1] = maxB[1]; p[2] = minB[2];	points->InsertNextPoint(p);
	p[0] = minB[0]; p[1] = maxB[1]; p[2] = maxB[2];	points->InsertNextPoint(p);
	p[0] = maxB[0]; p[1] = minB[1]; p[2] = minB[2];	points->InsertNextPoint(p);
	p[0] = maxB[0]; p[1] = minB[1]; p[2] = maxB[2];	points->InsertNextPoint(p);
	p[0] = maxB[0]; p[1] = maxB[1]; p[2] = minB[2];	points->InsertNextPoint(p);
	p[0] = maxB[0]; p[1] = maxB[1]; p[2] = maxB[2];	points->InsertNextPoint(p);
	data->SetPoints(points);
	points->Delete();


	//
	// Determine seeds
	//
	// rake
	lineWidget = vtkLineWidget::New();
	lineWidget->SetInputData(data);
	lineWidget->SetResolution(21); // 22 seeds along the line
	lineWidget->SetAlignToYAxis();
	lineWidget->PlaceWidget();
	lineWidget->ClampToBoundsOn();
	seeds = vtkPolyData::New();
	lineWidget->GetPolyData(seeds);

#if 0
	// plane
	planeWidget = vtkPlaneWidget::New();
	planeWidget->SetInputData(data);
	planeWidget->SetResolution(5);
	planeWidget->PlaceWidget();
	planeWidget->SetKeyPressActivationValue('j');
	seeds2 = vtkPolyData::New();
	planeWidget->GetPolyData(seeds2);
#endif

	//
	// vtkOSUFlow
	//
	streamer->SetSourceData(seeds);	//streamer->SetSourceConnection(rake->GetOutputPort());
	streamer->SetIntegrationDirectionToForward();
	streamer->SetMaximumPropagationTime(1000);
	streamer->SetNumberOfThreads(1);
	streamer->VorticityOn();

	vtkPolyDataMapper *mapper = vtkPolyDataMapper::New();
	mapper->SetInputConnection(streamer->GetOutputPort());
	mapper->SetScalarRange(data->GetScalarRange());
	vtkActor *actor = vtkActor::New();
	actor->SetMapper(mapper);


	//
	// outline
	//
	vtkOutlineFilter *outline = vtkOutlineFilter ::New();
	outline->SetInputData(data);

	vtkPolyDataMapper *outlineMapper = vtkPolyDataMapper::New();
	outlineMapper->SetInputConnection(outline->GetOutputPort());

	vtkActor *outlineActor = vtkActor::New();
	outlineActor->SetMapper(outlineMapper);
	outlineActor->GetProperty()->SetColor(0,0,0);


	//
	// renderer
	//
	vtkRenderer *ren = vtkRenderer::New();
	renWin = vtkRenderWindow::New();
	renWin->AddRenderer(ren);
	vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
	iren->SetRenderWindow(renWin);
	vtkInteractorStyleTrackballCamera *style = vtkInteractorStyleTrackballCamera::New();
	iren->SetInteractorStyle(style);

	// line widget interactor
	lineWidget->SetInteractor(iren);
	lineWidget->SetDefaultRenderer(ren);
	vtkCallbackCommand *callback = vtkCallbackCommand::New();
	callback->SetCallback(computeStreamlines);
	lineWidget->AddObserver(vtkCommand::EndInteractionEvent, callback);

#if 0
	// plane widget interactor
	planeWidget->SetInteractor(iren);
	planeWidget->SetDefaultRenderer(ren);
	vtkCallbackCommand *callback2 = vtkCallbackCommand::New();
	callback2->SetCallback(computeStreamlines2);
	planeWidget->AddObserver(vtkCommand::EndInteractionEvent, callback2);
#endif


	ren->AddActor(actor);
	ren->AddActor(outlineActor);
	ren->SetBackground(.5,.5,.5);

	renWin->SetSize(500,500);

	iren->Initialize();
	renWin->Render();
	iren->Start();

	return 0;
}
int main(int argc, char ** argv)
{
	prirntf("Usage: [plot3d file prefix] [labeled TXT file]\n");

	OSUFlow *osuflow = new OSUFlow();
	printf("read file %s\n", argv[1]);

	VECTOR3 minLen, maxLen, minB, maxB;
	minB[0] = 0; minB[1] = 0; minB[2] = 0;
    maxB[0] = 200; maxB[1] = 200; maxB[2] = 200;

	osuflow->LoadDataCurvilinear((const char*)argv[1], true, minB, maxB); //true: a steady flow field
	osuflow->Boundary(minLen, maxLen);
	printf(" volume boundary X: [%f %f] Y: [%f %f] Z: [%f %f]\n",
								minLen[0], maxLen[0], minLen[1], maxLen[1],
								minLen[2], maxLen[2]);


	int dim[3]	;
	CurvilinearGrid *grid = (CurvilinearGrid*)osuflow->GetFlowField()->GetGrid();
	grid->GetDimension(dim[0], dim[1], dim[2]);
	printf("dim: %d %d %d\n", dim[0], dim[1], dim[2]);
	int i,j,k;
#if 0
	for (k=0; k<dim[2]; k++)
		for (j=0; j<dim[1]; j++)
			for (i=0; i<dim[0]; i++) {
				VECTOR3 v;
				grid->coordinates_at_vertex(VECTOR3(i,j,k),&v);	//return 1 velocity value
				printf("%f %f %f\n", v[0], v[1], v[2]);
			}
#endif

	int i1, i2, j1, j2, k1, k2;
	if (argc<8) {
		printf("Please input range: (i2 i1 j2 j1 k2 k1)\n");
		scanf("%d %d %d %d %d %d", &i2, &i1, &j2, &j1, &k2, &k1);
	} else {
		i2 = atoi(argv[2]);
		i1 = atoi(argv[3]);
		j2 = atoi(argv[4]);
		j1 = atoi(argv[5]);
		k2 = atoi(argv[6]);
		k1 = atoi(argv[7]);
	}
	// Does not include upbound


	char out_fname[4][256];
	char prefix[4][10]={"lambda2", "q", "delta", "gamma"};
	for (i=0; i<4; i++)
	{
		sprintf(out_fname[i], "%s_%s.raw", argv[8], prefix[i]);
		printf("Output file: %s\n", out_fname[i]);
	}

	float x,y,z;
	VECTOR3 from, to;
	grid->coordinates_at_vertex(VECTOR3(i1, j1, k1), &from);
	grid->coordinates_at_vertex(VECTOR3(i2, j2, k2), &to);
	printf("from: %f %f %f, to: %f %f %f\n", from[0], from[1], from[2], to[0], to[1], to[2]);

	// get min offset unit
	float min_off[3] =  {1e+9,1e+9,1e+9};
	{
		for (i=i1+1; i<i2; i++) {
			VECTOR3 v1, v2;
			grid->coordinates_at_vertex(VECTOR3(i-1, j1, k1), &v1);
			grid->coordinates_at_vertex(VECTOR3(i, j1, k1), &v2);
			min_off[0] = min(v2[0]-v1[0], min_off[0]);
		}
		for (j=j1+1; j<j2; j++) {
			VECTOR3 v1, v2;
			grid->coordinates_at_vertex(VECTOR3(i1, j-1, k1), &v1);
			grid->coordinates_at_vertex(VECTOR3(i1, j, k1), &v2);
			min_off[1] = min(v2[1]-v1[1], min_off[1]);
		}
		for (k=k1+1; k<k2; k++) {
			VECTOR3 v1, v2;
			grid->coordinates_at_vertex(VECTOR3(i1, j1, k-1), &v1);
			grid->coordinates_at_vertex(VECTOR3(i1, j1, k), &v2);
			min_off[2] = min(v2[2]-v1[2], min_off[2]);
		}
		printf("Min grid unit: %f %f %f\n", min_off[0], min_off[1], min_off[2]);
	}

	if (!(from[0]<=to[0] && from[1]<=to[1] && from[2]<=to[2]))
		printf("Input invalid.  Program halts\n");
	int count=0;
	FILE *fp[4];
	for (i=0; i<4; i++)
		fp[i] = fopen(out_fname[i], "wb");

	for (z=from[2]; z< to[2]; z+=unit) {
		for (y=from[1]; y< to[1]; y+=unit)
			for (x=from[0]; x< to[0]; x+=unit)
			{
#if 0
				//VECTOR3 v;
				//osuflow->GetFlowField()->at_phys(VECTOR3(x,y,z), 0, v);
				//printf("%f %f %f\n", v[0], v[1], v[2]);
#endif
				float f[4]; //lambda2, q, delta, gamma;
				osuflow->GetFlowField()->GenerateVortexMetrics(VECTOR3(x,y,z), f[0], f[1], f[2], f[3]);
				for (i=0; i<4; i++)
					fwrite((char *)&f[i], 1, 4, fp[i]);
				count++;
			}
		printf("z=%f\n", z);
	}
	for (i=0; i<4; i++)
		fclose(fp[i]);


	// get dim for given range
	int bdim[3];
	bdim[0] = bdim[1] = bdim[2] = 0;
	{
		int d;
		for (d=0; d<3; d++)
			for (x=from[d]; x<=to[d]; x+=unit)
				bdim[d] ++;
	}

	for (i=0; i<4; i++)
	{
		// get out_fname filename only (no path)
		char *out_fname_no_path = strrchr(out_fname[i], '/');
		if (out_fname_no_path==NULL) out_fname_no_path = out_fname[i]; else out_fname_no_path++;

		char out_desc_fname[256];
		sprintf(out_desc_fname, "%s_%s.nhdr", argv[8], prefix[i]);
		FILE *fp = fopen(out_desc_fname, "wt");
		fprintf(fp,
				"NRRD0001\n"
				"type: float\n"
				"dimension: 3\n"
				"sizes: %d %d %d\n"
				"encoding: raw\n"
				"data file: %s\n"
				"# sampling distance: %f\n"
				"# grid range: %d %d %d - %d %d %d\n"
				"# physical range: %f %f %f - %f %f %f\n"
				"# min grid unit: %f %f %f\n",
				bdim[0], bdim[1], bdim[2], out_fname_no_path,
				unit, i1, j1, k1, i2, j2, k2, from[0], from[1], from[2], to[0], to[1], to[2], min_off[0], min_off[1], min_off[2]);
		fclose(fp);
	}

	printf("Done (%d elems)\n", count);

	return 0;
}
Exemple #7
0
int main(int argc, char **argv)
{
	printf("Usage: computeFTLE flowmap.raw w h d RES\n");
	int w = atoi(argv[2]),
		h = atoi(argv[3]),
		d = atoi(argv[4]);
	float RES = atof(argv[5]);
	printf("Opening file %s, w h d: %d %d %d\n", argv[1], w, h, d);

	vector<VECTOR3> offset(w*h*d);

	FILE *fp = fopen(argv[1], "rb");
	fread(&offset[0], w*h*d, 12, fp);
	fclose(fp);

	if (0) // now we generate flowmap
	{
		int x,y,z, count=0;
		for (z=0; z<d; z++)
			for (y=0; y<h; y++)
				for (x=0; x<w; x++) {
					offset[count] = offset[count] + VECTOR3(x*RES, y*RES, z*RES);
					//printf("offset: %f %f %f\n", offset[count][0], offset[count][1], offset[count][2]);
					count ++;
				}
	}

	// use osuflow
	OSUFlow *osuflow = new OSUFlow();
	float minB[3] = {0,0,0}, maxB[3];
	maxB[0] = w-1;  maxB[1] = h-1; maxB[2] = d-1;
	osuflow->CreateStaticFlowField((float *)&offset[0], w, h, d, minB, maxB);
	CVectorField *field = osuflow->GetFlowField();




	// FTLE
    vector<float> ftle(w*h*d);
	int x,y,z, count=0;
	for (z=0; z<d; z++)
	{
		for (y=0; y<h; y++)
			for (x=0; x<w; x++)
			{
                MATRIX3 jac = field->Jacobian(VECTOR3(x,y,z)),
                        jsquare; // TODO: delta in Jac. computation
				jac = jac * (1/RES);
				jsquare = jac.transpose() * jac;

				float m[3][3], eigenvalues[3];
				for (int i = 0; i < 3; i++) {
					for (int j = 0; j < 3; j++) {
						m[i][j] = jsquare(i, j);
					}
				}
				compute_eigenvalues(m, eigenvalues);
				float max_eig = max(eigenvalues[0], max(eigenvalues[1], eigenvalues[2]));
				//printf("%f\n", max_eig);
				ftle[count++] = log(max_eig)*.5;
			}
		printf("z=%d\n", z);
	}

	fp = fopen("ftle.raw", "wb");
	fwrite(&ftle[0], w*h*d, sizeof(float), fp);
	fclose(fp);

	printf("output: ftle.raw\n");
	return 0;
}