void ExampleExperimentFields::DrawScalarField()
{
    viewer->clear();

    //Load scalar field
    ScalarField2 field;
    if (!field.load(ScalarfieldFilename))
    {
        output << "Error loading field file " << ScalarfieldFilename << "\n";
        return;
    }

    //Get the minimum/maximum value in that field
    float32 min = std::numeric_limits<float32>::max();
    float32 max = -std::numeric_limits<float32>::max();
    for(size_t j=0; j<field.dims()[1]; j++)
    {
        for(size_t i=0; i< field.dims()[0]; i++)
        {
            const float32 val = field.nodeScalar(i,j);
            min = val < min ? val : min;
            max = val > max ? val : max;
        }
    }

    //Draw a point for each grid vertex.
    for(size_t j=0; j<field.dims()[1]; j++)
    {
        for(size_t i=0; i<field.dims()[0]; i++)
        {
            const float32 val = field.nodeScalar(i, j);
            const float32 c = (val - min) / (max - min);

            Point2D p;
            p.position  = field.nodePosition(i, j);
            p.size = 5;
            //Use a grayscale depending on the actual value
            p.color[0] = c; p.color[1] = c; p.color[2] = c;
            viewer->addPoint(p);
        }
    }

    viewer->refresh();
}
void IterativeLevelSetSolver2::extrapolate(
    const FaceCenteredGrid2& input,
    const ScalarField2& sdf,
    double maxDistance,
    FaceCenteredGrid2* output) {
    JET_THROW_INVALID_ARG_IF(!input.hasSameShape(*output));

    const Vector2D gridSpacing = input.gridSpacing();

    auto u = input.uConstAccessor();
    auto uPos = input.uPosition();
    Array2<double> sdfAtU(u.size());
    input.parallelForEachUIndex([&](size_t i, size_t j) {
        sdfAtU(i, j) = sdf.sample(uPos(i, j));
    });

    extrapolate(
        u,
        sdfAtU,
        gridSpacing,
        maxDistance,
        output->uAccessor());

    auto v = input.vConstAccessor();
    auto vPos = input.vPosition();
    Array2<double> sdfAtV(v.size());
    input.parallelForEachVIndex([&](size_t i, size_t j) {
        sdfAtV(i, j) = sdf.sample(vPos(i, j));
    });

    extrapolate(
        v,
        sdfAtV,
        gridSpacing,
        maxDistance,
        output->vAccessor());
}
void IterativeLevelSetSolver2::extrapolate(
    const CollocatedVectorGrid2& input,
    const ScalarField2& sdf,
    double maxDistance,
    CollocatedVectorGrid2* output) {
    JET_THROW_INVALID_ARG_IF(!input.hasSameShape(*output));

    Array2<double> sdfGrid(input.dataSize());
    auto pos = input.dataPosition();
    sdfGrid.parallelForEachIndex([&](size_t i, size_t j) {
        sdfGrid(i, j) = sdf.sample(pos(i, j));
    });

    const Vector2D gridSpacing = input.gridSpacing();

    Array2<double> u(input.dataSize());
    Array2<double> u0(input.dataSize());
    Array2<double> v(input.dataSize());
    Array2<double> v0(input.dataSize());

    input.parallelForEachDataPointIndex([&](size_t i, size_t j) {
        u(i, j) = input(i, j).x;
        v(i, j) = input(i, j).y;
    });

    extrapolate(
        u,
        sdfGrid.constAccessor(),
        gridSpacing,
        maxDistance,
        u0);

    extrapolate(
        v,
        sdfGrid.constAccessor(),
        gridSpacing,
        maxDistance,
        v0);

    output->parallelForEachDataPointIndex([&](size_t i, size_t j) {
        (*output)(i, j).x = u(i, j);
        (*output)(i, j).y = v(i, j);
    });
}
void IterativeLevelSetSolver2::extrapolate(
    const ScalarGrid2& input,
    const ScalarField2& sdf,
    double maxDistance,
    ScalarGrid2* output) {
    JET_THROW_INVALID_ARG_IF(!input.hasSameShape(*output));

    Array2<double> sdfGrid(input.dataSize());
    auto pos = input.dataPosition();
    sdfGrid.parallelForEachIndex([&](size_t i, size_t j) {
        sdfGrid(i, j) = sdf.sample(pos(i, j));
    });

    extrapolate(
        input.constDataAccessor(),
        sdfGrid.constAccessor(),
        input.gridSpacing(),
        maxDistance,
        output->dataAccessor());
}
Пример #5
0
void Experiment3_1::DrawRegularMesh()
{
    viewer->clear();

    //Load scalar field
    ScalarField2 field;
    if (!field.load(scalar_filename))
    {
        output << "Error loading field file " << scalar_filename << "\n";
        return;
    }


    //Get the minimum/maximum value in that field
    float32 min = std::numeric_limits<float32>::max();
    float32 max = -std::numeric_limits<float32>::max();
    for(size_t j=0; j<field.dims()[1]; j++)
    {
        for(size_t i=0; i< field.dims()[0]; i++)
        {
            const float32 val = field.nodeScalar(i,j);
            min = val < min ? val : min;
            max = val > max ? val : max;
        }
    }

  //Plot the grid
  //Traverse one dimension first and then the other dimension
   for(size_t j=0; j<field.dims()[1]; j++)
    {
        viewer->addLine(field.nodePosition(0,j), field.nodePosition(field.dims()[0]-1,j), makeVector4f(0.5,0.5,0.5,grid_alpha), 1);
    }
   for(size_t i=0; i<field.dims()[0]; i++)
    {
        viewer->addLine(field.nodePosition(i,0), field.nodePosition(i,field.dims()[1]-1), makeVector4f(0.5,0.5,0.5,grid_alpha), 1);
    }

  //Optionally overlay data on the grid
  if (grid_w_data == true )
  {
    //Draw a point for each grid vertex.
    for(size_t j=0; j<field.dims()[1]; j++)
    {
        for(size_t i=0; i<field.dims()[0]; i++)
        {
            const float32 val = field.nodeScalar(i, j);
            const float32 c = (val - min) / (max - min);

            Point2D p;
            p.position  = field.nodePosition(i, j);
            p.size = 5;
            //Use a grayscale depending on the actual value
            p.color[0] = c; p.color[1] = c; p.color[2] = c;
            viewer->addPoint(p);
        }
    }
  }



    viewer->refresh();
}
Пример #6
0
void Experiment3_1::DrawIsoContour_Asymp()
{
    viewer->clear();

    //Load scalar field
    ScalarField2 field;
    if (!field.load(scalar_filename))
    {
        output << "Error loading field file " << scalar_filename << "\n";
        return;
    }


    //Get the minimum/maximum value in that field
    float32 min = std::numeric_limits<float32>::max();
    float32 max = -std::numeric_limits<float32>::max();
    for(size_t j=0; j<field.dims()[1]; j++)
    {
        for(size_t i=0; i< field.dims()[0]; i++)
        {
            const float32 val = field.nodeScalar(i,j);
            min = val < min ? val : min;
            max = val > max ? val : max;
        }
    }

  //Plot the grid
  //Traverse one dimension first and then the other dimension
   for(size_t j=0; j<field.dims()[1]; j++)
    {
        viewer->addLine(field.nodePosition(0,j), field.nodePosition(field.dims()[0]-1,j), makeVector4f(0.5,0.5,0.5,grid_alpha), 1);
    }
   for(size_t i=0; i<field.dims()[0]; i++)
    {
        viewer->addLine(field.nodePosition(i,0), field.nodePosition(i,field.dims()[1]-1), makeVector4f(0.5,0.5,0.5,grid_alpha), 1);
    }

  //Optionally overlay data on the grid
  if (grid_w_data == true )
  {
    //Draw a point for each grid vertex.
    for(size_t j=0; j<field.dims()[1]; j++)
    {
        for(size_t i=0; i<field.dims()[0]; i++)
        {
            const float32 val = field.nodeScalar(i, j);
            const float32 c = (val - min) / (max - min);

            Point2D p;
            p.position  = field.nodePosition(i, j);
            p.size = 5;
            //Use a grayscale depending on the actual value
            p.color[0] = c; p.color[1] = c; p.color[2] = c;
            viewer->addPoint(p);
        }
    }
  }



    viewer->refresh();



  //Plot the Iso Contour
  //Traverse the cells
   for(size_t i=0; i<field.dims()[0]-1; i++)
    {
      for(size_t j=0; j<field.dims()[1]-1; j++)
       {
          
         //Compute Max and Min values in each cell
         float32 fval[4];
         fval[0]= field.nodeScalar(i,j);
         fval[1]= field.nodeScalar(i,j+1);
         fval[2]= field.nodeScalar(i+1,j+1);
         fval[3]= field.nodeScalar(i+1,j);

         vector <Vector2f> Pos;
         Pos.resize(4);
         Pos[0]=field.nodePosition(i,j);
         Pos[1]=field.nodePosition(i,j+1);
         Pos[2]=field.nodePosition(i+1,j+1);
         Pos[3]=field.nodePosition(i+1,j);

         //output << "** "<< Pos[0][0] << " " << Pos[0][1] <<"\n";
         //output << field.nodePosition(i,j)[0] << " "<< field.nodePosition(i,j)[1] << "\n" ;

         
         float32 maxf, minf;
         maxf=fmax(fval[0],fval[1]);
         maxf=fmax(maxf,fval[2]);
         maxf=fmax(maxf,fval[3]);
         minf=fmin(fval[0],fval[1]);
         minf=fmin(minf,fval[2]);
         minf=fmin(minf,fval[3]);


         //Check if the iso contour passes the grid
         if((iso_c < minf)  || (iso_c > maxf))
           continue;
         else   //We plot the iso contour
         {
            
              float32 EdgeChar[3][4];

             //Now figure out the signs for the four nodes
               bool sign[4]= {0,0,0,0};
               for(int k=0; k<4; k++)
               {
                 if(fval[k]>=iso_c)
                  sign[k] = 1;
               }

               //Traverse the nodes clockwise and see if the edge carries a crossing point
               for(int k=0; k<4; k++)
               {
                  if( sign[k] ^ sign[(k+1)%4] )
                  {
                    EdgeChar[2][k] = 1;
                    float32 x,y;
                    x = ( (Pos[(k+1)%4][0] - Pos[k][0])*iso_c + Pos[k][0] * fval[(k+1)%4] -  Pos[(k+1)%4][0] * fval[k] ) / ( fval[(k+1)%4] - fval[k] ) ;
                    y = ( (Pos[(k+1)%4][1] - Pos[k][1])*iso_c + Pos[k][1] * fval[(k+1)%4] -  Pos[(k+1)%4][1] * fval[k] ) / ( fval[(k+1)%4] - fval[k] ) ;
                    EdgeChar[0][k] = x;
                    EdgeChar[1][k] = y;

                  }
                  else
                    EdgeChar[2][k] = 0;

                } 
   
                //Count the number of edges that have a valid crossing point. It should be either 2 or 4 
               int EdgeCount=0; 
               for(int k=0; k<4; k++)
               {
                  if(EdgeChar[2][k]==1)
                  EdgeCount++;
               }
               
               if(EdgeCount == 2)
               {
                  //Simply plot the contour
                  vector <Vector2f> LineEnd;
                  LineEnd.clear();
                  LineEnd.resize(2);
                  int index=0;

                  for(int k=0; k<4; k++)
                  {
                    if(EdgeChar[2][k]==1)
                    {
                      LineEnd[index]= makeVector2f(EdgeChar[0][k], EdgeChar[1][k]) ;
                      index++;
                    }
                  }
                  viewer->addLine(LineEnd[0], LineEnd[1], makeVector4f(0.5,0.5,0.5,iso_alpha), 2);
                  viewer->refresh();
                  
                  
               }
               else   //Cell has the contour intersecting at 4 points
               {
                 //There is an ambiguity to be resolved
                 float32 fmid= (fval[3]*fval[1] - fval[2]*fval[0]) / ( fval[3]+fval[1] -fval[2] - fval[0] ) ;
                
                  vector <Vector2f> LineEnd;
                  LineEnd.clear();
                  LineEnd.resize(4);

                  for(int k=0; k<4; k++)
                  {
                      LineEnd[k]= makeVector2f(EdgeChar[0][k], EdgeChar[1][k]) ;
                  }


		 if(fval[1] < iso_c)
		 {
                    if(iso_c > fmid)  //Connect 3 to 0 and 1 to 2
                    {
                              viewer->addLine(LineEnd[3], LineEnd[0], makeVector4f(1,0.5,0.5,iso_alpha), 2);
                              viewer->addLine(LineEnd[1], LineEnd[2], makeVector4f(1,0.5,0.5,iso_alpha), 2);
                              viewer->refresh();
                    }
                    else            //Connect 0 to 1  and 2 to 3    
                    {
                              viewer->addLine(LineEnd[0], LineEnd[1], makeVector4f(1,0.5,0.5,iso_alpha), 2);
                              viewer->addLine(LineEnd[2], LineEnd[3], makeVector4f(1,0.5,0.5,iso_alpha), 2);
                              viewer->refresh();
                    }

		 }
		 else
		 {
                    if(iso_c > fmid)  //Connect 0 to 1  and 2 to 3
                    {
                              viewer->addLine(LineEnd[0], LineEnd[1], makeVector4f(1,0.5,0.5,iso_alpha), 2);
                              viewer->addLine(LineEnd[2], LineEnd[3], makeVector4f(1,0.5,0.5,iso_alpha), 2);
                                viewer->refresh();

                    }
                    else                //Connect 3 to 0 and 1 to 2
                    {
                                            
                              viewer->addLine(LineEnd[3], LineEnd[0], makeVector4f(1,0.5,0.5,iso_alpha), 2);
                              viewer->addLine(LineEnd[1], LineEnd[2], makeVector4f(1,0.5,0.5,iso_alpha), 2);
                               viewer->refresh();

                    }
		 }
         
                 
               
               }
               
          }

           
    }

  }
}
void ExampleExperimentFields::DrawTexture()
{
    viewer->clear();

    //Load the texture using Qt
    QImage image(ImageFilename.c_str());

    //Get its (original) dimensions. Used as bounds later.
    const float fWidth = (float)image.width();
    const float fHeight = (float)image.height();

    //Resize to power-of-two and mirror.
    image = image.mirrored().scaled(NextPOT(image.width()), NextPOT(image.height()));

    //Get its new integer dimensions.
    const int iWidth = image.width();
    const int iHeight = image.height();

    if (bColoredTexture)
    {
        //Create three color channels for the texture
        //Each of them is represented using a scalar field
        ScalarField2 Red;
        Red.init(makeVector2f(-fWidth, -fHeight), makeVector2f(fWidth, fHeight), makeVector2ui(iWidth, iHeight));
        ScalarField2 Green;
        Green.init(makeVector2f(-fWidth, -fHeight), makeVector2f(fWidth, fHeight), makeVector2ui(iWidth, iHeight));
        ScalarField2 Blue;
        Blue.init(makeVector2f(-fWidth, -fHeight), makeVector2f(fWidth, fHeight), makeVector2ui(iWidth, iHeight));

        //Fill the scalar fields
        for(size_t j=0; j<Red.dims()[1]; j++)
        {
            for(size_t i=0; i<Red.dims()[0]; i++)
            {
                Red.setNodeScalar(i, j, (float)(qRed(image.pixel(i, j))) / 255.0 );
                Green.setNodeScalar(i, j, (float)(qGreen(image.pixel(i, j))) / 255.0 );
                Blue.setNodeScalar(i, j, (float)(qBlue(image.pixel(i, j))) / 255.0 );
            }
        }

        //Set the texture in the viewer
        viewer->setTextureRGB(Red.getData(), Green.getData(), Blue.getData());
    }
    else
    {
        //Create one gray color channel represented as a scalar field
        ScalarField2 Gray;
        Gray.init(makeVector2f(-fWidth, -fHeight), makeVector2f(fWidth, fHeight), makeVector2ui(iWidth, iHeight));

        //Set the values at the vertices
        for(size_t j=0; j<Gray.dims()[1]; j++)
        {
            for(size_t i=0; i<Gray.dims()[0]; i++)
            {
                Gray.setNodeScalar(i, j, (float)(qGray(image.pixel(i, j))) / 255.0 );
            }
        }

        //Set the texture in the viewer
        viewer->setTextureGray(Gray.getData());
    }

    viewer->refresh();
}
void GridFractionalSinglePhasePressureSolver2::buildWeights(
    const FaceCenteredGrid2& input, const ScalarField2& boundarySdf,
    const VectorField2& boundaryVelocity, const ScalarField2& fluidSdf) {
    auto size = input.resolution();

    // Build levels
    size_t maxLevels = 1;
    if (_mgSystemSolver != nullptr) {
        maxLevels = _mgSystemSolver->params().maxNumberOfLevels;
    }
    FdmMgUtils2::resizeArrayWithFinest(size, maxLevels, &_fluidSdf);
    _uWeights.resize(_fluidSdf.size());
    _vWeights.resize(_fluidSdf.size());
    for (size_t l = 0; l < _fluidSdf.size(); ++l) {
        _uWeights[l].resize(_fluidSdf[l].size() + Size2(1, 0));
        _vWeights[l].resize(_fluidSdf[l].size() + Size2(0, 1));
    }

    // Build top-level grids
    auto cellPos = input.cellCenterPosition();
    auto uPos = input.uPosition();
    auto vPos = input.vPosition();
    _boundaryVel = boundaryVelocity.sampler();
    Vector2D h = input.gridSpacing();

    _fluidSdf[0].parallelForEachIndex([&](size_t i, size_t j) {
        _fluidSdf[0](i, j) = static_cast<float>(fluidSdf.sample(cellPos(i, j)));
    });

    _uWeights[0].parallelForEachIndex([&](size_t i, size_t j) {
        Vector2D pt = uPos(i, j);
        double phi0 = boundarySdf.sample(pt - Vector2D(0.5 * h.x, 0.0));
        double phi1 = boundarySdf.sample(pt + Vector2D(0.5 * h.x, 0.0));
        double frac = fractionInsideSdf(phi0, phi1);
        double weight = clamp(1.0 - frac, 0.0, 1.0);

        // Clamp non-zero weight to kMinWeight. Having nearly-zero element
        // in the matrix can be an issue.
        if (weight < kMinWeight && weight > 0.0) {
            weight = kMinWeight;
        }

        _uWeights[0](i, j) = static_cast<float>(weight);
    });

    _vWeights[0].parallelForEachIndex([&](size_t i, size_t j) {
        Vector2D pt = vPos(i, j);
        double phi0 = boundarySdf.sample(pt - Vector2D(0.0, 0.5 * h.y));
        double phi1 = boundarySdf.sample(pt + Vector2D(0.0, 0.5 * h.y));
        double frac = fractionInsideSdf(phi0, phi1);
        double weight = clamp(1.0 - frac, 0.0, 1.0);

        // Clamp non-zero weight to kMinWeight. Having nearly-zero element
        // in the matrix can be an issue.
        if (weight < kMinWeight && weight > 0.0) {
            weight = kMinWeight;
        }

        _vWeights[0](i, j) = static_cast<float>(weight);
    });

    // Build sub-levels
    for (size_t l = 1; l < _fluidSdf.size(); ++l) {
        const auto& finerFluidSdf = _fluidSdf[l - 1];
        auto& coarserFluidSdf = _fluidSdf[l];
        const auto& finerUWeight = _uWeights[l - 1];
        auto& coarserUWeight = _uWeights[l];
        const auto& finerVWeight = _vWeights[l - 1];
        auto& coarserVWeight = _vWeights[l];

        // Fluid SDF
        restrict(finerFluidSdf, &coarserFluidSdf);
        restrict(finerUWeight, &coarserUWeight);
        restrict(finerVWeight, &coarserVWeight);
    }
}