예제 #1
0
void RtSourceLocDataWorker::setAnnotationData(const Eigen::VectorXi& vecLabelIdsLeftHemi,
                                              const Eigen::VectorXi& vecLabelIdsRightHemi,
                                              const QList<FSLIB::Label>& lLabelsLeftHemi,
                                              const QList<FSLIB::Label>& lLabelsRightHemi)
{
    QMutexLocker locker(&m_qMutex);

    if(vecLabelIdsLeftHemi.rows() == 0 || lLabelsLeftHemi.isEmpty() || vecLabelIdsRightHemi.rows() == 0 || lLabelsRightHemi.isEmpty()) {
        qDebug() << "RtSourceLocDataWorker::setAnnotationData - Annotation data is empty. Returning ...";
        return;
    }

    m_lLabelsLeftHemi = lLabelsLeftHemi;
    m_lLabelsRightHemi = lLabelsRightHemi;

    //Generate fast lookup map for each source and corresponding label
    for(qint32 i = 0; i < m_vecVertNoLeftHemi.rows(); ++i) {
        m_mapLabelIdSourcesLeftHemi.insert(m_vecVertNoLeftHemi(i), vecLabelIdsLeftHemi(m_vecVertNoLeftHemi(i)));
    }

    for(qint32 i = 0; i < m_vecVertNoRightHemi.rows(); ++i) {
        m_mapLabelIdSourcesRightHemi.insert(m_vecVertNoRightHemi(i), vecLabelIdsRightHemi(m_vecVertNoRightHemi(i)));
    }

    m_bAnnotationDataIsInit = true;
}
예제 #2
0
파일: main.cpp 프로젝트: Codermay/libigl
void drawConstraints(igl::viewer::Viewer &viewer)
{
  for (int n=0; n<2; ++n)
  {
    Eigen::MatrixXd Bc = igl::slice(B, b, 1);
    Eigen::MatrixXd color;
    color.setZero(b.rows(),3);
    color.col(2).setOnes();
    for (int i =0; i<b.rows(); ++i)
      if (blevel[i] ==1 && n>0)
        color.row(i)<<0.7,0.7,0.7;
    // Eigen::RowVector3d color; color<<0.5,0.5,0.5;
    viewer.data.add_edges(Bc - global_scale*bc.block(0,n*3,bc.rows(),3), Bc + global_scale*bc.block(0,n*3,bc.rows(),3) , color);
  }

}
예제 #3
0
파일: example.cpp 프로젝트: dut09/libigl
bool update_arap()
{
  using namespace Eigen;
  using namespace igl;
  using namespace std;
  MatrixXd bc(num_in_selection(S),V.cols());
  // get b from S
  {
    if(!paused)
    {
      t = get_seconds()-pause_time;
    }
    int bi = 0;
    for(int v = 0;v<S.rows(); v++)
    {
      if(S(v) >= 0)
      {
        bc.row(bi) = V.row(v);
        switch(S(v))
        {
          case 0:
          {
            const double r = mid(0)*0.25;
            bc(bi,0) += r*cos(0.5*t*2.*PI);
            bc(bi,1) -= r+r*sin(0.5*t*2.*PI);
            break;
          }
          case 1:
          {
            const double r = mid(1)*0.15;
            bc(bi,1) += r+r*cos(0.15*t*2.*PI);
            bc(bi,2) -= r*sin(0.15*t*2.*PI);

            //// Pull-up
            //bc(bi,0) += 0.42;//mid(0)*0.5;
            //bc(bi,1) += 0.55;//mid(0)*0.5;
            //// Bend
            //Vector3d t(-1,0,0);
            //Quaterniond q(AngleAxisd(PI/1.5,Vector3d(0,1.0,0.1).normalized()));
            //const Vector3d a = bc.row(bi);
            //bc.row(bi) = (q*(a-t) + t) + Vector3d(1.5,0.1,0.9);


            break;
          }
          default:
          break;
        }
        bi++;
      }
    }
  }
  if(!arap_solve(bc,arap_data,U))
  {
    cerr<<"arap_solve failed."<<endl;
    return false;
  }
  per_face_normals(U,F,N);
  return true;
}
예제 #4
0
void NuTo::Structure::ElementCreate(int rElementNumber, int rInterpolationTypeId, const Eigen::VectorXi& rNodeNumbers,
                                    const Eigen::MatrixXd& rKnots, const Eigen::VectorXi& rKnotIDs)
{
    // convert node numbers to pointer
    std::vector<NodeBase*> nodeVector;
    for (int iNode = 0; iNode < rNodeNumbers.rows(); iNode++)
        nodeVector.push_back(NodeGetNodePtr(rNodeNumbers(iNode)));

    boost::ptr_map<int, InterpolationType>::iterator itIterator = mInterpolationTypeMap.find(rInterpolationTypeId);

    if (itIterator == mInterpolationTypeMap.end())
        throw NuTo::Exception(__PRETTY_FUNCTION__, "Interpolation type does not exist.");

    InterpolationType& interpolationType = *itIterator->second;

    if (not interpolationType.IsDof(Node::eDof::COORDINATES))
        throw NuTo::Exception(__PRETTY_FUNCTION__, "COORDINATE interpolation required.");

    unsigned int numNodesCoordinates = interpolationType.Get(Node::eDof::COORDINATES).GetNumNodes();
    if (numNodesCoordinates != nodeVector.size())
        throw NuTo::Exception(__PRETTY_FUNCTION__, "COORDINATE interpolation requires " +
                                                           std::to_string(numNodesCoordinates) + " nodes. " +
                                                           std::to_string(nodeVector.size()) + " are provided.");

    interpolationType.ClearCache();
    const auto& integrationType = *GetPtrIntegrationType(interpolationType.GetStandardIntegrationType());

    ElementBase* ptrElement = nullptr;
    switch (interpolationType.GetShapeType())
    {
    case NuTo::Interpolation::eShapeType::SPRING:
        throw NuTo::Exception(__PRETTY_FUNCTION__, "Element1DSpring currently not implemented.");
        break;
    case NuTo::Interpolation::eShapeType::TRUSS1D:
    case NuTo::Interpolation::eShapeType::TRUSSXD:
    case NuTo::Interpolation::eShapeType::TRIANGLE2D:
    case NuTo::Interpolation::eShapeType::QUAD2D:
    case NuTo::Interpolation::eShapeType::TETRAHEDRON3D:
    case NuTo::Interpolation::eShapeType::BRICK3D:
    case NuTo::Interpolation::eShapeType::INTERFACE:
        throw NuTo::Exception(__PRETTY_FUNCTION__,
                              "Please use approriate functions for element creation, this is IGA implementation.");
        break;
    case NuTo::Interpolation::eShapeType::IGA1D:
        ptrElement = new ContinuumElementIGA<1>(nodeVector, rKnots, rKnotIDs, interpolationType, integrationType,
                                                GetDofStatus());
        ptrElement->CheckElement();
        break;
    case NuTo::Interpolation::eShapeType::IGA2D:
        ptrElement = new ContinuumElementIGA<2>(nodeVector, rKnots, rKnotIDs, interpolationType, integrationType,
                                                GetDofStatus());
        ptrElement->CheckElement();
        break;
    default:
        throw Exception(__PRETTY_FUNCTION__, "invalid dimension.");
    }

    mElementMap.insert(rElementNumber, ptrElement);
}
예제 #5
0
파일: example.cpp 프로젝트: dut09/libigl
int num_in_selection(const Eigen::VectorXi & S)
{
  int count = 0;
  for(int v = 0;v<S.rows(); v++)
  {
    if(S(v) >= 0)
    {
      count++;
    }
  }
  return count;
}
예제 #6
0
void randomly_color(
  const Eigen::VectorXi & CC,
  Eigen::MatrixXd & C)
{
  using namespace Eigen;
  using namespace igl;
  using namespace std;
  VectorXi I;
  srand ( unsigned ( time(0) ) );
  double num_cc = (double)CC.maxCoeff()+1.0;
  randperm(num_cc,I);
  C.resize(CC.rows(),3);
  for(int f = 0;f<CC.rows();f++)
  {
    jet(
      (double)I(CC(f))/num_cc,
      C(f,0),
      C(f,1),
      C(f,2));
  }
}
예제 #7
0
파일: Fund.cpp 프로젝트: Tythos/cuben
		int findValue(Eigen::VectorXi vec, int value) {
			int toReturn  = -1;
			int currNdx = 0;
			while (toReturn == -1 && currNdx < vec.rows()) {
				if (vec(currNdx) == value) {
					toReturn = currNdx;
				} else {
					currNdx++;
				}
			}
			return toReturn;
		}
예제 #8
0
        void addEdgeType( CEdgeTypePtr edgeType, Eigen::VectorXi &typeOfEdgeFeatures )
        {
            // Consistency checks
            assert( edgeType->getNumberOfFeatures() == typeOfEdgeFeatures.rows() );

            ITERATE_SIZE_T(typeOfEdgeFeatures)
                assert( typeOfEdgeFeatures(i) <= 3 );

            // Add the edge type to the vector of edge types
            m_edgeTypes.push_back( edgeType );
            m_typesOfEdgeFeatures[ edgeType ] = typeOfEdgeFeatures;
        }
예제 #9
0
void parse_rhs(
  const int nrhs, 
  const mxArray *prhs[], 
  Eigen::MatrixXd & V,
  Eigen::MatrixXi & Ele,
  Eigen::MatrixXd & Q,
  Eigen::MatrixXd & bb_mins,
  Eigen::MatrixXd & bb_maxs,
  Eigen::VectorXi & elements)
{
  using namespace std;
  using namespace igl;
  using namespace igl::matlab;
  mexErrMsgTxt(nrhs >= 3, "The number of input arguments must be >=3.");

  const int dim = mxGetN(prhs[0]);
  mexErrMsgTxt(dim == 3 || dim == 2,
    "Mesh vertex list must be #V by 2 or 3 list of vertex positions");

  mexErrMsgTxt(dim+1 == mxGetN(prhs[1]),
    "Mesh \"face\" simplex size must equal dimension+1");

  parse_rhs_double(prhs,V);
  parse_rhs_index(prhs+1,Ele);
  parse_rhs_double(prhs+2,Q);
  mexErrMsgTxt(Q.cols() == dim,"Dimension of Q should match V");
  if(nrhs > 3)
  {
    mexErrMsgTxt(nrhs >= 6, "The number of input arguments must be 3 or >=6.");
    parse_rhs_double(prhs+3,bb_mins);
    if(bb_mins.size()>0)
    {
      mexErrMsgTxt(bb_mins.cols() == dim,"Dimension of bb_mins should match V");
      mexErrMsgTxt(bb_mins.rows() >= Ele.rows(),"|bb_mins| should be > |Ele|");
    }
    parse_rhs_double(prhs+4,bb_maxs);
    mexErrMsgTxt(bb_maxs.cols() == bb_mins.cols(),
      "|bb_maxs| should match |bb_mins|");
    mexErrMsgTxt(bb_mins.rows() == bb_maxs.rows(),
      "|bb_mins| should match |bb_maxs|");
    parse_rhs_index(prhs+5,elements);
    mexErrMsgTxt(elements.cols() == 1,"Elements should be column vector");
    mexErrMsgTxt(bb_mins.rows() == elements.rows(),
      "|bb_mins| should match |elements|");
  }else
  {
    // Defaults
    bb_mins.resize(0,dim);
    bb_maxs.resize(0,dim);
    elements.resize(0,1);
  }
}
예제 #10
0
IGL_INLINE void igl::forward_kinematics(
  const Eigen::MatrixXd & C,
  const Eigen::MatrixXi & BE,
  const Eigen::VectorXi & P,
  const std::vector<
    Eigen::Quaterniond,Eigen::aligned_allocator<Eigen::Quaterniond> > & dQ,
  std::vector<
    Eigen::Quaterniond,Eigen::aligned_allocator<Eigen::Quaterniond> > & vQ,
  std::vector<Eigen::Vector3d> & vT)
{
  using namespace std;
  using namespace Eigen;
  const int m = BE.rows(); 
  assert(m == P.rows());
  assert(m == (int)dQ.size());
  vector<bool> computed(m,false);
  vQ.resize(m);
  vT.resize(m);
  function<void (int) > fk_helper = [&] (int b)
  {
    if(!computed[b])
    {
      if(P(b) < 0)
      {
        // base case for roots
        vQ[b] = dQ[b];
        const Vector3d r = C.row(BE(b,0)).transpose();
        vT[b] = r-dQ[b]*r;
      }else
      {
        // Otherwise first compute parent's
        const int p = P(b);
        fk_helper(p);
        vQ[b] = vQ[p] * dQ[b];
        const Vector3d r = C.row(BE(b,0)).transpose();
        vT[b] = vT[p] - vQ[b]*r + vQ[p]*r;
      }
      computed[b] = true;
    }
  };
  for(int b = 0;b<m;b++)
  {
    fk_helper(b);
  }
}
예제 #11
0
IGL_INLINE void igl::n_polyvector_general(const Eigen::MatrixXd &V,
                             const Eigen::MatrixXi &F,
                             const Eigen::VectorXi& b,
                             const Eigen::MatrixXd& bc,
                             const Eigen::VectorXi &I,
                             Eigen::MatrixXd &output)
{
  Eigen::VectorXi isConstrained = Eigen::VectorXi::Constant(F.rows(),0);
  Eigen::MatrixXd cfW = Eigen::MatrixXd::Constant(F.rows(),bc.cols(),0);

  for(unsigned i=0; i<b.size();++i)
  {
    isConstrained(b(i)) = 1;
    cfW.row(b(i)) << bc.row(i);
  }
  int n = I.rows();
  igl::GeneralPolyVectorFieldFinder<Eigen::MatrixXd, Eigen::MatrixXi> pvff(V,F,n);
  pvff.solve(isConstrained, cfW, I, output);
}
예제 #12
0
void RtSourceLocDataWorker::setSurfaceData(const QByteArray& arraySurfaceVertColorLeftHemi,
                                           const QByteArray& arraySurfaceVertColorRightHemi,
                                           const Eigen::VectorXi& vecVertNoLeftHemi,
                                           const Eigen::VectorXi& vecVertNoRightHemi)
{
    QMutexLocker locker(&m_qMutex);

    if(arraySurfaceVertColorLeftHemi.size() == 0 || vecVertNoLeftHemi.rows() == 0 || arraySurfaceVertColorRightHemi.size() == 0 || vecVertNoRightHemi.rows() == 0) {
        qDebug() << "RtSourceLocDataWorker::setSurfaceData - Surface data is empty. Returning ...";
        return;
    }

    m_arraySurfaceVertColorLeftHemi = arraySurfaceVertColorLeftHemi;
    m_vecVertNoLeftHemi = vecVertNoLeftHemi;

    m_arraySurfaceVertColorRightHemi = arraySurfaceVertColorRightHemi;
    m_vecVertNoRightHemi = vecVertNoRightHemi;

    m_bSurfaceDataIsInit = true;
}
예제 #13
0
파일: eigen.cpp 프로젝트: Cerarus/v4r
bool
writeLabelToFile (const std::string &file, const Eigen::VectorXi &vector)
{
    std::ofstream out (file.c_str ());
    if (!out)
    {
        std::cout << "Cannot open file.\n";
        return false;
    }
    size_t i ,j;

    for (i = 0; i < vector.rows(); i++)
    {

            out << vector (i);


        out<<" ";
    }
    out.close ();

    return true;
}
예제 #14
0
파일: main.cpp 프로젝트: hankstag/libigl
int main(int argc, char *argv[])
{
  using namespace std;
  // Load a mesh in OFF format
  igl::readOBJ(TUTORIAL_SHARED_PATH "/camel_b.obj", V, F);

  Eigen::MatrixXd bnd_uv, uv_init;

  Eigen::VectorXd M;
  igl::doublearea(V, F, M);
  std::vector<std::vector<int>> all_bnds;
  igl::boundary_loop(F, all_bnds);

  // Heuristic primary boundary choice: longest
  auto primary_bnd = std::max_element(all_bnds.begin(), all_bnds.end(), [](const std::vector<int> &a, const std::vector<int> &b) { return a.size()<b.size(); });

  Eigen::VectorXi bnd = Eigen::Map<Eigen::VectorXi>(primary_bnd->data(), primary_bnd->size());

  igl::map_vertices_to_circle(V, bnd, bnd_uv);
  bnd_uv *= sqrt(M.sum() / (2 * igl::PI));
  if (all_bnds.size() == 1)
  {
    if (bnd.rows() == V.rows()) // case: all vertex on boundary
    {
      uv_init.resize(V.rows(), 2);
      for (int i = 0; i < bnd.rows(); i++)
        uv_init.row(bnd(i)) = bnd_uv.row(i);
    }
    else
    {
      igl::harmonic(V, F, bnd, bnd_uv, 1, uv_init);
      if (igl::flipped_triangles(uv_init, F).size() != 0)
        igl::harmonic(F, bnd, bnd_uv, 1, uv_init); // fallback uniform laplacian
    }
  }
  else
  {
    // if there is a hole, fill it and erase additional vertices.
    all_bnds.erase(primary_bnd);
    Eigen::MatrixXi F_filled;
    igl::topological_hole_fill(F, bnd, all_bnds, F_filled);
    igl::harmonic(F_filled, bnd, bnd_uv ,1, uv_init);
    uv_init = uv_init.topRows(V.rows());
  }

  Eigen::VectorXi b; Eigen::MatrixXd bc;
  igl::scaf_precompute(V, F, uv_init, scaf_data, igl::MappingEnergyType::SYMMETRIC_DIRICHLET, b, bc, 0);

  // Plot the mesh
  igl::opengl::glfw::Viewer viewer;
  viewer.data().set_mesh(V, F);
  const auto& V_uv = uv_scale * scaf_data.w_uv.topRows(V.rows());
  viewer.data().set_uv(V_uv);
  viewer.callback_key_down = &key_down;

  // Enable wireframe
  viewer.data().show_lines = true;

  // Draw checkerboard texture
  viewer.data().show_texture = true;


  std::cerr << "Press space for running an iteration." << std::endl;
  std::cerr << "Press 1 for Mesh 2 for UV" << std::endl;

  // Launch the viewer
  viewer.launch();
}
예제 #15
0
void SliceStack::computeLaplace(const Eigen::MatrixXd &TV, const Eigen::MatrixXi &TT,
                                const Eigen::MatrixXi &TF, const Eigen::VectorXi &TO,
                                Eigen::VectorXd &Z, const set<int> &allowed) {
  bool laplace_DEBUG = false;
	Eigen::IOFormat CleanFmt(4, 0, ", ", "\n", "[", "]");
	Eigen::IOFormat LongFmt(10, 0, ", ", "\n", "[", "]");
	Eigen::IOFormat RFmt(4, 0, ", ", ", ", "", "", "(", ")");

	assert(TO.rows() == TV.rows());

	std::vector<int> known_v;
	std::vector<double> known_c_v;
  auto mx = TV.colwise().maxCoeff();
  auto mn = TV.colwise().minCoeff();

	for (int i = 0; i < TO.rows(); ++i) {
		if (allowed.size() == 0 && TO(i) != GLOBAL::nonoriginal_marker) {
			known_v.push_back(i);
			known_c_v.push_back(GLOBAL::inside_temp);
		}
    else if (allowed.find(TO(i)) != allowed.end()) {
			known_v.push_back(i);
			known_c_v.push_back(GLOBAL::inside_temp);
    }
    else if (TV(i,2) == mx(2) || TV(i,2) == mn(2)) {
			known_v.push_back(i);
			known_c_v.push_back(GLOBAL::outside_temp);
		}
	}

	if (laplace_DEBUG) 
    printf("done! Number of known values is %lu/%lu\n",
           known_v.size(), TV.rows());

	Eigen::VectorXi known(known_v.size());
	Eigen::VectorXd known_c(known_v.size());

	for (int i = 0; i < known_c.size(); ++i) {
		known(i) = known_v[i];
		known_c(i) = known_c_v[i];
	}

	Eigen::SparseMatrix<double> L(TV.rows(), TV.rows());
	// Set non-diag elements to 1 if connected, 0 otherwise
	// Use the tets instead of the faces
	for (int i = 0; i < TT.rows(); ++i) {
		L.coeffRef(TT(i,0), TT(i,1)) = -1; L.coeffRef(TT(i,1), TT(i,0)) = -1;
		L.coeffRef(TT(i,1), TT(i,2)) = -1; L.coeffRef(TT(i,2), TT(i,1)) = -1;
		L.coeffRef(TT(i,2), TT(i,3)) = -1; L.coeffRef(TT(i,3), TT(i,2)) = -1;
		L.coeffRef(TT(i,3), TT(i,0)) = -1; L.coeffRef(TT(i,0), TT(i,3)) = -1;
	}

	// Set diag elements to valence of entry
	for (int i = 0; i < TV.rows(); ++i) {
		L.coeffRef(i,i) = -L.row(i).sum();
	}

  if (laplace_DEBUG) {
    printf("done! Number non-zeros is %ld\n", L.nonZeros());
    printf("Solving energy constraints...");
  }

	// Solve energy constraints.
	igl::min_quad_with_fixed_data<double> mqwf;
	// Linear term is 0
	Eigen::VectorXd B = Eigen::VectorXd::Zero(TV.rows(), 1);
	// Empty Constraints
	Eigen::VectorXd Beq;
	Eigen::SparseMatrix<double> Aeq;

	if (!igl::min_quad_with_fixed_precompute(L, known, Aeq, false, mqwf))
		fprintf(stderr,"ERROR: fixed_precompute didn't work!\n");

	igl::min_quad_with_fixed_solve(mqwf,B,known_c,Beq, Z);

  if (laplace_DEBUG)
    printf("fixed_solve complete.\n");
}
예제 #16
0
bool key_down(igl::viewer::Viewer& viewer, unsigned char key, int modifier)
{
  using namespace std;
  using namespace Eigen;

  if (key <'1' || key >'9')
    return false;

  viewer.data.lines.resize(0,9);

  int num = key  - '0';

  // Interpolate
  std::cerr << "Interpolating " << num  << "-PolyVector field" << std::endl;

  VectorXi b(3);
  b << 1511, 603, 506;

  int numConstraintsToGenerate;
  // if it's not a 2-PV or a 1-PV, include a line direction (2 opposite vectors)
  // in the field
  if (num>=5)
    numConstraintsToGenerate  = num-2;
  else
    if (num>=3)
      numConstraintsToGenerate  = num-1;
    else
      numConstraintsToGenerate  = num;


  MatrixXd bc(b.size(),numConstraintsToGenerate*3);
  for (unsigned i=0; i<b.size(); ++i)
  {
    VectorXd t = random_constraints(B1.row(b(i)),B2.row(b(i)),numConstraintsToGenerate);
    bc.row(i) = t;
  }
  VectorXi rootsIndex(num);
  for (int i =0; i<numConstraintsToGenerate; ++i)
    rootsIndex[i] = i+1;
  if (num>=5)
    rootsIndex[num-2] = -2;
    if (num>=3)
      rootsIndex[num-1] = -1;

  // Interpolated PolyVector field
  Eigen::MatrixXd pvf;
  igl::n_polyvector_general(V, F, b, bc, rootsIndex, pvf);

  ofstream ofs;
  ofs.open("pvf.txt", ofstream::out);
  ofs<<pvf;
  ofs.close();
  igl::writeOFF("pvf.off",V,F);
  
  // Highlight in red the constrained faces
  MatrixXd C = MatrixXd::Constant(F.rows(),3,1);
  for (unsigned i=0; i<b.size();++i)
    C.row(b(i)) << 1, 0, 0;
  viewer.data.set_colors(C);

  for (int n=0; n<num; ++n)
  {
//    const MatrixXd &VF = pvf.block(0,n*3,F.rows(),3);
    MatrixXd VF = MatrixXd::Zero(F.rows(),3);
    for (unsigned i=0; i<b.size(); ++i)
      VF.row(b[i]) = pvf.block(b[i],n*3,1,3);
    
    for (int i=0; i<samples.rows(); ++i)
      VF.row(samples[i]) = pvf.block(samples[i],n*3,1,3);
    
    VectorXd c = VF.rowwise().norm();
    MatrixXd C2;
    igl::jet(c,1,1+rand_factor,C2);
    // viewer.data.add_edges(B - global_scale*VF, B + global_scale*VF , C2);
    viewer.data.add_edges(B, B + global_scale*VF , C2);
  }


  return false;
}
예제 #17
0
int NuTo::Structure::BoundaryElementsCreate(int rElementGroupId, int rNodeGroupId, NodeBase* rControlNode)
{
    Timer timer(__FUNCTION__, GetShowTime(), GetLogger());

    // find groups
    boost::ptr_map<int, GroupBase>::iterator itGroupElements = mGroupMap.find(rElementGroupId);
    if (itGroupElements == mGroupMap.end())
        throw Exception(__PRETTY_FUNCTION__, "Group with the given identifier does not exist.");
    if (itGroupElements->second->GetType() != NuTo::eGroupId::Elements)
        throw Exception(__PRETTY_FUNCTION__, "Group is not an element group.");

    boost::ptr_map<int, GroupBase>::iterator itGroupBoundaryNodes = mGroupMap.find(rNodeGroupId);
    if (itGroupBoundaryNodes == mGroupMap.end())
        throw Exception(__PRETTY_FUNCTION__, "Group with the given identifier does not exist.");
    if (itGroupBoundaryNodes->second->GetType() != NuTo::eGroupId::Nodes)
        throw Exception(__PRETTY_FUNCTION__, "Group is not a node group.");

    Group<ElementBase>& elementGroup = *(itGroupElements->second->AsGroupElement());
    Group<NodeBase>& nodeGroup = *(itGroupBoundaryNodes->second->AsGroupNode());

    // since the search is done via the id's, the surface nodes are ptr, so make another set with the node ptrs
    std::set<const NodeBase*> nodePtrSet;
    for (auto itNode : nodeGroup)
    {
        nodePtrSet.insert(itNode.second);
    }

    std::vector<int> newBoundaryElementIds;

    // loop over all elements
    for (auto itElement : elementGroup)
    {
        ElementBase* elementPtr = itElement.second;
        const InterpolationType& interpolationType = elementPtr->GetInterpolationType();

        // std::cout << typeid(*elementPtr).name() << "\n";
        // std::cout << typeid(ContinuumElement<1>).name() << std::endl;
        if (typeid(*elementPtr) != typeid(ContinuumElement<1>) && typeid(*elementPtr) != typeid(ContinuumElement<2>) &&
            typeid(*elementPtr) != typeid(ContinuumElement<3>))
            throw Exception(__PRETTY_FUNCTION__, "Element is not a ContinuumElement.");

        // loop over all surfaces
        for (int iSurface = 0; iSurface < interpolationType.GetNumSurfaces(); ++iSurface)
        {
            bool elementSurfaceNodesMatchBoundaryNodes = true;
            Eigen::VectorXi surfaceNodeIndices = interpolationType.GetSurfaceNodeIndices(iSurface);

            int numSurfaceNodes = surfaceNodeIndices.rows();
            std::vector<const NodeBase*> surfaceNodes(numSurfaceNodes);

            for (int iSurfaceNode = 0; iSurfaceNode < numSurfaceNodes; ++iSurfaceNode)
            {
                surfaceNodes[iSurfaceNode] = elementPtr->GetNode(surfaceNodeIndices(iSurfaceNode, 0));
            }

            // check, if all surface nodes are in the node group
            for (auto& surfaceNode : surfaceNodes)
            {
                if (nodePtrSet.find(surfaceNode) == nodePtrSet.end())
                {
                    // this surface has at least one node that is not in the list, continue
                    elementSurfaceNodesMatchBoundaryNodes = false;
                    break;
                }
            }
            if (not elementSurfaceNodesMatchBoundaryNodes)
                continue;

            int surfaceId = iSurface;

            int elementId = GetUnusedId(mElementMap);

            ElementBase* boundaryElement = nullptr;
            ConstitutiveBase& constitutiveLaw = elementPtr->GetConstitutiveLaw(0);

            switch (elementPtr->GetLocalDimension())
            {
            case 1:
            {
                const auto& integrationType = *GetPtrIntegrationType(eIntegrationType::IntegrationType0DBoundary);
                auto& element = dynamic_cast<ContinuumElement<1>&>(*elementPtr);
                if (rControlNode == nullptr)
                    boundaryElement = new ContinuumBoundaryElement<1>(element, integrationType, surfaceId);
                else
                    boundaryElement = new ContinuumBoundaryElementConstrainedControlNode<1>(element, integrationType,
                                                                                            surfaceId, rControlNode);
                break;
            }
            case 2:
            {
                eIntegrationType integrationTypeEnum;
                // check for 2D types
                switch (interpolationType.GetStandardIntegrationType())
                {
                case eIntegrationType::IntegrationType2D3NGauss1Ip:
                case eIntegrationType::IntegrationType2D4NGauss1Ip:
                    integrationTypeEnum = eIntegrationType::IntegrationType1D2NGauss1Ip;
                    break;
                case eIntegrationType::IntegrationType2D3NGauss3Ip:
                case eIntegrationType::IntegrationType2D4NGauss4Ip:
                    integrationTypeEnum = eIntegrationType::IntegrationType1D2NGauss2Ip;
                    break;
                case eIntegrationType::IntegrationType2D3NGauss6Ip:
                case eIntegrationType::IntegrationType2D4NGauss9Ip:
                    integrationTypeEnum = eIntegrationType::IntegrationType1D2NGauss3Ip;
                    break;
                case eIntegrationType::IntegrationType2D3NGauss12Ip:
                    integrationTypeEnum = eIntegrationType::IntegrationType1D2NGauss5Ip;
                    break;

                case eIntegrationType::IntegrationType2D4NLobatto9Ip:
                    integrationTypeEnum = eIntegrationType::IntegrationType1D2NLobatto3Ip;
                    break;

                case eIntegrationType::IntegrationType2D4NLobatto16Ip:
                    integrationTypeEnum = eIntegrationType::IntegrationType1D2NLobatto4Ip;
                    break;

                case eIntegrationType::IntegrationType2D4NLobatto25Ip:
                    integrationTypeEnum = eIntegrationType::IntegrationType1D2NLobatto5Ip;
                    break;

                default:
                    throw Exception(__PRETTY_FUNCTION__,
                                    "Could not automatically determine integration type of the boundary element.");
                }
                const auto& integrationType = *GetPtrIntegrationType(integrationTypeEnum);
                auto& element = dynamic_cast<ContinuumElement<2>&>(*elementPtr);
                if (rControlNode == nullptr)
                    boundaryElement = new ContinuumBoundaryElement<2>(element, integrationType, surfaceId);
                else
                    boundaryElement = new ContinuumBoundaryElementConstrainedControlNode<2>(element, integrationType,
                                                                                            surfaceId, rControlNode);

                break;
            }
            case 3:
            {
                eIntegrationType integrationTypeEnum;
                // check for 3D types
                switch (interpolationType.GetStandardIntegrationType())
                {
                case eIntegrationType::IntegrationType3D4NGauss1Ip:
                    integrationTypeEnum = eIntegrationType::IntegrationType2D3NGauss1Ip;
                    break;

                case eIntegrationType::IntegrationType3D4NGauss4Ip:
                    integrationTypeEnum = eIntegrationType::IntegrationType2D3NGauss3Ip;
                    break;

                case eIntegrationType::IntegrationType3D8NGauss1Ip:
                    integrationTypeEnum = eIntegrationType::IntegrationType2D4NGauss1Ip;
                    break;

                case eIntegrationType::IntegrationType3D8NGauss2x2x2Ip:
                    integrationTypeEnum = eIntegrationType::IntegrationType2D4NGauss4Ip;
                    break;

                case eIntegrationType::IntegrationType3D8NLobatto3x3x3Ip:
                    integrationTypeEnum = eIntegrationType::IntegrationType2D4NLobatto9Ip;
                    break;

                case eIntegrationType::IntegrationType3D8NLobatto4x4x4Ip:
                    integrationTypeEnum = eIntegrationType::IntegrationType2D4NLobatto16Ip;
                    break;

                case eIntegrationType::IntegrationType3D8NLobatto5x5x5Ip:
                    integrationTypeEnum = eIntegrationType::IntegrationType2D4NLobatto16Ip;
                    break;

                default:
                    throw Exception(__PRETTY_FUNCTION__,
                                    "Could not automatically determine integration type of the boundary element.");
                }

                const auto& integrationType = *GetPtrIntegrationType(integrationTypeEnum);
                auto& element = dynamic_cast<ContinuumElement<3>&>(*elementPtr);
                if (rControlNode == nullptr)
                    boundaryElement = new ContinuumBoundaryElement<3>(element, integrationType, surfaceId);
                else
                    boundaryElement = new ContinuumBoundaryElementConstrainedControlNode<3>(element, integrationType,
                                                                                            surfaceId, rControlNode);
                break;
            }
            default:
                throw Exception(__PRETTY_FUNCTION__, "Boundary element for Continuum element with dimension " +
                                                             std::to_string(elementPtr->GetLocalDimension()) +
                                                             "not implemented");
            }

            mElementMap.insert(elementId, boundaryElement);
            newBoundaryElementIds.push_back(elementId);

            boundaryElement->SetConstitutiveLaw(constitutiveLaw);
        }
    }

    int boundaryElementGroup = GroupCreate(eGroupId::Elements);
    for (int boundaryElementId : newBoundaryElementIds)
        GroupAddElement(boundaryElementGroup, boundaryElementId);

    return boundaryElementGroup;
}
예제 #18
0
bool BF3PointCircle::getRobustCircle(const cvb::CvContourChainCode& contour, const unsigned int maxVotes, const unsigned int maxAccu, const int maxInvalidVotesInSeries, BFCircle& circle) {

	cvb::CvChainCodes::const_iterator it 		= contour.chainCode.begin();
	cvb::CvChainCodes::const_iterator it_beg	= contour.chainCode.begin();
	cvb::CvChainCodes::const_iterator it_end 	= contour.chainCode.end();

	unsigned int x = contour.startingPoint.x;
	unsigned int y = contour.startingPoint.y;

	BFContour bfContour;
	while(it != it_end) {

		bfContour.add(BFCoordinate<int>(static_cast<int>(x),static_cast<int>(y)));

		x += cvb::cvChainCodeMoves[*it][0];
		y += cvb::cvChainCodeMoves[*it][1];

		it++;
	}
	const unsigned int nContourPoints = bfContour.getPixelCount();

	BFRectangle rect = bfContour.getBounds();
	int nRows = bfRound(rect.getHeight());
	int nCols = bfRound(rect.getWidth());
	int x0 = bfRound(rect.getX0());
	int y0 = bfRound(rect.getY0());
	BFCoordinate<int> topLeft(x0,y0);

	// generate 2d histogram for circle center estimation
	Eigen::MatrixXi H = Eigen::MatrixXi::Zero(nRows, nCols);

	unsigned int votes = 0;
	int invalidVotesInSeries = 0;
	while(votes < maxVotes) {

		unsigned int randIndex1 = (rand() % nContourPoints);
		unsigned int randIndex2 = (rand() % nContourPoints);
		while(randIndex2 == randIndex1)
			randIndex2 = (rand() % nContourPoints);
		unsigned int randIndex3 = (rand() % nContourPoints);
		while(randIndex3 == randIndex2 || randIndex3 == randIndex1)
			randIndex3 = (rand() % nContourPoints);

		BFCoordinate<int> c1 = bfContour.getCoordinate(randIndex1) - topLeft;
		BFCoordinate<int> c2 = bfContour.getCoordinate(randIndex2) - topLeft;
		BFCoordinate<int> c3 = bfContour.getCoordinate(randIndex3) - topLeft;

		BFCoordinate<double> center;
		bool validCenter = getCenter(c1,c2,c3,center);

		if(!validCenter) {
			votes--;
			invalidVotesInSeries++;

			if(invalidVotesInSeries > maxInvalidVotesInSeries) {
				return false;
			}
			continue;
		}
		invalidVotesInSeries = 0;

		double cxD = center.getX();
		double cyD = center.getY();

		int cx = bfRound(cxD);
		int cy = bfRound(cyD);

		if(cx < 0 || cy < 0 || cx >= nRows || cy >= nCols) {
			continue;
		}
		else {
			H(cx,cy) += 1;

			if(H(cx,cy) >= static_cast<int>(maxAccu)) {
				break;
			}
		}

		votes++;
	}

	int finalX = 0;
	int finalY = 0;
	H.maxCoeff(&finalX,&finalY);
	finalX += bfRound(x0);
	finalY += bfRound(y0);

	// generate 1d histogram for circle radius estimation
	Eigen::VectorXi K = Eigen::VectorXi::Zero(bfMax(nRows,nCols));

	it = it_beg;
	x = contour.startingPoint.x;
	y = contour.startingPoint.y;

	while(it != it_end) {

		int r = bfRound(sqrt(pow(static_cast<double>(static_cast<int>(x)-finalX),2.0) + pow(static_cast<double>(static_cast<int>(y)-finalY),2.0)));

		if(r < K.rows()) {
			K(r) += 1;
		}

		x += cvb::cvChainCodeMoves[*it][0];
		y += cvb::cvChainCodeMoves[*it][1];

		it++;
	}

	int finalR = 0;
	K.maxCoeff(&finalR);
	circle.set(finalX,finalY,finalR);

	return true;
}
예제 #19
0
int main(int argc, char** argv)
{
    std::string path;
    po::options_description desc("Calculates one point cloud for classification\n======================================\n**Allowed options");

    desc.add_options()
            ("help,h", "produce help message")
            ("path,p", po::value<std::string>(&path)->required(), "Path to folders with pics")

            ;

    po::variables_map vm;
    po::parsed_options parsed = po::command_line_parser(argc,argv).options(desc).allow_unregistered().run();
    po::store(parsed, vm);
    if (vm.count("help"))
    {
        std::cout << desc << std::endl;
        return false;
    }

    try
    {
        po::notify(vm);
    }
    catch(std::exception& e)
    {
        std::cerr << "Error: " << e.what() << std::endl << std::endl << desc << std::endl;
        return false;
    }

//    std::string pretrained_binary_proto = "/home/martin/github/caffe/models/bvlc_alexnet/bvlc_alexnet.caffemodel";
//    std::string feature_extraction_proto = "/home/martin/github/caffe/models/bvlc_alexnet/deploy.prototxt";
    std::string pretrained_binary_proto = "/home/martin/github/caffe/models/bvlc_reference_caffenet/bvlc_reference_caffenet.caffemodel";
    std::string feature_extraction_proto = "/home/martin/github/caffe/models/bvlc_reference_caffenet/deploy.prototxt";
    std::string mean_file = "/home/martin/github/caffe/data/ilsvrc12/imagenet_mean.binaryproto";
    //    std::vector<std::string> extract_feature_blob_names;
    //    extract_feature_blob_names.push_back("fc7");



    Eigen::MatrixXf all_model_signatures_, test;

    v4r::CNN_Feat_Extractor<pcl::PointXYZRGB,float>::Parameter estimator_param;
    //estimator_param.init(argc, argv);
    v4r::CNN_Feat_Extractor<pcl::PointXYZRGB,float>::Ptr estimator;
    //v4r::CNN_Feat_Extractor<pcl::PointXYZRGB,float> estimator;
    estimator.reset(new v4r::CNN_Feat_Extractor<pcl::PointXYZRGB, float>(estimator_param));
    //estimator.reset();
    //estimator->setExtractFeatureBlobNames(extract_feature_blob_names);
    estimator->setFeatureExtractionProto(feature_extraction_proto);
    estimator->setPretrainedBinaryProto(pretrained_binary_proto);
    estimator->setMeanFile(mean_file);
    //estimator->init();
    pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZRGB>);
    //pcl::PointCloud<pcl::PointXYZRGB> test(new pcl::PointCloud<pcl::PointXYZRGB>);
    char end = path.back();
    if(end!='/')
        path.append("/");
    std::vector<std::string> objects(v4r::io::getFoldersInDirectory(path));

    objects.erase(find(objects.begin(),objects.end(),"svm"));
    std::vector<std::string> paths,Files;
    std::vector<std::string> Temp;
    std::string fs, fp, fo;
    Eigen::VectorXi models;
    std::vector<std::string> modelnames;
    std::vector<int> indices;


    v4r::svmClassifier::Parameter paramSVM;
    paramSVM.knn_=1;
    paramSVM.do_cross_validation_=0;
    v4r::svmClassifier classifier(paramSVM);

    if(!(v4r::io::existsFile(path+"svm/Signatures.txt")&&v4r::io::existsFile(path+"svm/Labels.txt"))){
        for(size_t o=0;o<objects.size();o++){
        //for(size_t o=0;o<1;o++){
            fo = path;
            fo.append(objects[o]);
            fo.append("/");
            paths.clear();
            paths = v4r::io::getFilesInDirectory(fo,".*.JPEG",false);
            modelnames.push_back(objects[o]);
            int old_rows = all_model_signatures_.rows();
            all_model_signatures_.conservativeResize(all_model_signatures_.rows()+paths.size(),4096);
            for(size_t i=0;i<paths.size();i++){
//          for(size_t i=0;i<3;i++){
                fp = fo;
                fp.append(paths[i]);
                std::cout << "Teaching File: " << fp << std::endl;


                //            int rows = image.rows;
                //            int cols = image.cols;

                //            int a,b;
                //            if(rows>256)
                //                a = floor(rows/2)-128;
                //            else
                //                a=0;
                //            if(cols<256)
                //                b = floor(cols/2)-128;
                //            else
                //                b=0;
                //            if(rows<256||cols<256)
                //                continue;
                //cv::Rect r(b,a,256,256);
                //            cv::namedWindow( "Display window", cv::WINDOW_AUTOSIZE );// Create a window for display.
                //            cv::imshow( "Display window", image );
                //            cv::waitKey();
                //estimator.setIm(image);
                //estimator.setIndices(indices);
                //estimator->compute(image,signature);
                //test = signature.transpose();
                cv::Mat image = cv::imread(fp);
                Eigen::MatrixXf signature;
                if(image.rows != 256 || image.cols != 256)
                    cv::resize( image, image, cv::Size(256, 256));
                //bool success = estimator->computeCNN(signature);
                estimator->compute(image,signature);
                //all_model_signatures_.conservativeResize(all_model_signatures_.rows()+1,4096);


                all_model_signatures_.row(old_rows+i) = signature.row(0);
                models.conservativeResize(models.rows()+1);
                models(models.rows()-1) = o;


                // std::cout<<all_model_signatures_ <<std::endl;
                std::cout<<"ok" <<std::endl;

            }





        }

        std::string f_file = path;
        v4r::io::writeDescrToFile(f_file.append("svm/Signatures.txt"),all_model_signatures_);
        f_file = path;
        v4r::io::writeLabelToFile(f_file.append("svm/Labels.txt"),models);
    }
    else{
        all_model_signatures_ = v4r::io::readDescrFromFile(path+"svm/Signatures.txt",0,4096);
        models = v4r::io::readLabelFromFile(path+"svm/Labels.txt",0);
        std::cout << "Loading Descriptors and Labels from " << path << "svm." <<std::endl;
    }



    fs = path;
    fs.append("svm/Class.model");
    classifier.setOutFilename(fs);

    //test.resize(all_model_signatures_.cols(),all_model_signatures_.rows());
    //test = all_model_signatures_.transpose();
    //classifier.shuffleTrainingData(all_model_signatures_, models);
    classifier.param_.do_cross_validation_=0;
    int testC = classifier.param_.svm_.C;
    classifier.param_.svm_.probability=1;
    classifier.setNumClasses(objects.size());
    classifier.train(all_model_signatures_, models);

    classifier.saveModel(fs);








}
예제 #20
0
파일: main.cpp 프로젝트: Codermay/libigl
int main(int argc, char *argv[])
{

  // Load a mesh
  igl::readOBJ(TUTORIAL_SHARED_PATH "/inspired_mesh.obj", V, F);

  printf("--Initialization--\n");
  V_border = igl::is_border_vertex(V,F);
  igl::adjacency_list(F, VV);
  igl::vertex_triangle_adjacency(V,F,VF,VFi);
  igl::triangle_triangle_adjacency(F,TT,TTi);
  igl::edge_topology(V,F,E,F2E,E2F);

  // Generate "subdivided" mesh for visualization of curl terms
  igl::false_barycentric_subdivision(V, F, Vbs, Fbs);

  // Compute scale for visualizing fields
  global_scale =  .2*igl::avg_edge_length(V, F);

  //Compute scale for visualizing texture
  uv_scale = 0.6/igl::avg_edge_length(V, F);

  // Compute face barycenters
  igl::barycenter(V, F, B);

  // Compute local basis for faces
  igl::local_basis(V,F,B1,B2,B3);

  //Generate random vectors for constraints
  generate_constraints();

  // Interpolate a 2-PolyVector field to be used as the original field
  printf("--Initial solution--\n");
  igl::n_polyvector(V, F, b, bc, two_pv_ori);

  // Post process original field
  // Compute curl_minimizing matchings and curl
  Eigen::MatrixXi match_ab, match_ba;  // matchings across interior edges
  printf("--Matchings and curl--\n");
  double avgCurl = igl::polyvector_field_matchings(two_pv_ori, V, F, true, match_ab, match_ba, curl_ori);
  double maxCurl = curl_ori.maxCoeff();
  printf("original curl -- max: %.5g, avg: %.5g\n", maxCurl,  avgCurl);

  printf("--Singularities--\n");
  // Compute singularities
  igl::polyvector_field_singularities_from_matchings(V, F, V_border, VF, TT, E2F, F2E, match_ab, match_ba, singularities_ori);
  printf("original #singularities: %ld\n", singularities.rows());

  printf("--Cuts--\n");
 // Get mesh cuts based on singularities
  igl::polyvector_field_cut_mesh_with_singularities(V, F, VF, VV, TT, TTi, singularities_ori, cuts_ori);

  printf("--Combing--\n");
// Comb field
  Eigen::MatrixXd combed;
  igl::polyvector_field_comb_from_matchings_and_cuts(V, F, TT, E2F, F2E, two_pv_ori, match_ab, match_ba, cuts_ori, combed);

  printf("--Cut mesh--\n");
  // Reconstruct integrable vector fields from combed field
  igl::cut_mesh(V, F, VF, VFi, TT, TTi, V_border, cuts_ori, Vcut_ori, Fcut_ori);

  printf("--Poisson--\n");
  double avgPoisson = igl::polyvector_field_poisson_reconstruction(Vcut_ori, Fcut_ori, combed, scalars_ori, two_pv_poisson_ori, poisson_error_ori);
  double maxPoisson = poisson_error_ori.maxCoeff();
  printf("poisson error -- max: %.5g, avg: %.5g\n", maxPoisson, avgPoisson);


  // Set the curl-free 2-PolyVector to equal the original field
  two_pv = two_pv_ori;
  singularities = singularities_ori;
  curl = curl_ori;
  cuts = cuts_ori;
  two_pv_poisson = two_pv_poisson_ori;
  poisson_error = poisson_error_ori;
  Vcut = Vcut_ori;
  Fcut = Fcut_ori;
  scalars = scalars_ori;

  printf("--Integrable - Precomputation--\n");
  // Precompute stuff for solver
  igl::integrable_polyvector_fields_precompute(V, F, b, bc, blevel, two_pv_ori, ipfdata);

  cerr<<"Done. Press keys 1-0 for various visualizations, 'A' to improve integrability." <<endl;

  igl::viewer::Viewer viewer;
  viewer.callback_key_down = &key_down;
  viewer.core.show_lines = false;
  key_down(viewer,'2',0);

  // Replace the standard texture with an integer shift invariant texture
  line_texture(texture_R, texture_G, texture_B);

  viewer.launch();

  return 0;
}
예제 #21
0
bool BF3PointCircle::getRobustCircle(const BFContour& contour, const unsigned int maxVotes, const unsigned int maxAccu, const int maxInvalidVotesInSeries, BFCircle& circle) {

	unsigned int nContourPoints = contour.getPixelCount();
	BFRectangle rect = contour.getBounds();

	BFRectangle zeroRect;
	if(rect.equals(zeroRect)) {
		return false;
	}

	int nRows = bfRound(rect.getHeight());
	int nCols = bfRound(rect.getWidth());

	int x0 = bfRound(rect.getX0());
	int y0 = bfRound(rect.getY0());
	BFCoordinate<int> topLeft(x0,y0);

	int invalidVotesInSeries = 0;

	// generate 2d histogram for circle center estimation
	Eigen::MatrixXi H = Eigen::MatrixXi::Zero(nRows, nCols);
	unsigned int votes = 0;
	for(votes; votes <= maxVotes; ++votes) {
		// random index number in range [0,nContourPoints-1]
		unsigned int randIndex1 = (rand() % nContourPoints);
		unsigned int randIndex2 = (rand() % nContourPoints);
		while(randIndex2 == randIndex1)
			randIndex2 = (rand() % nContourPoints);
		unsigned int randIndex3 = (rand() % nContourPoints);
		while(randIndex3 == randIndex2 || randIndex3 == randIndex1)
			randIndex3 = (rand() % nContourPoints);

		BFCoordinate<int> c1 = contour.getCoordinate(randIndex1) - topLeft;
		BFCoordinate<int> c2 = contour.getCoordinate(randIndex2) - topLeft;
		BFCoordinate<int> c3 = contour.getCoordinate(randIndex3) - topLeft;

		BFCoordinate<double> center;
		bool validCenter = getCenter(c1,c2,c3,center);

		if(!validCenter) {
			votes--;
			invalidVotesInSeries++;

			if(invalidVotesInSeries > maxInvalidVotesInSeries) {
				return false;
			}
			continue;
		}

		invalidVotesInSeries = 0;

		double cxD = center.getX();
		double cyD = center.getY();

		int cx = bfRound(cxD);
		int cy = bfRound(cyD);

		if(cx < 0 || cy < 0 || cx >= nRows || cy >= nCols) {
			votes--;
			continue;
		}
		else {
			H(cx,cy) += 1;

			if(H(cx,cy) >= static_cast<int>(maxAccu)) {
				break;
			}
		}
	}

	int finalX = 0;
	int finalY = 0;
	H.maxCoeff(&finalX,&finalY);
	finalX += bfRound(x0);
	finalY += bfRound(y0);

	// generate 1d histogram for circle radius estimation
	Eigen::VectorXi K = Eigen::VectorXi::Zero(bfMax(nRows,nCols));
	const std::vector<BFCoordinate<int> >& cont = contour.getContour();
	std::vector<BFCoordinate<int> >::const_iterator iter = cont.begin();

	int x;
	int y;

	while(iter != cont.end()) {

		x = bfRound((*iter).getX());
		y = bfRound((*iter).getY());

		int r = bfRound(sqrt(pow(static_cast<double>(x-finalX),2) + pow(static_cast<double>(y-finalY),2)));

		if(r < K.rows()) {
			K(r) += 1;
		}

		iter++;
	}

	int finalR = 0;
	K.maxCoeff(&finalR);

	// return result
	circle.set(finalX,finalY,finalR);
	return true;
}
예제 #22
0
파일: main.cpp 프로젝트: Codermay/libigl
bool key_down(igl::viewer::Viewer& viewer, unsigned char key, int modifier)
{

  if (key == '1')
  {
    display_mode = 1;
    update_display(viewer);
  }

  if (key == '2')
  {
    display_mode = 2;
    update_display(viewer);
  }

  if (key == '3')
  {
    display_mode = 3;
    update_display(viewer);
  }

  if (key == '4')
  {
    display_mode = 4;
    update_display(viewer);
  }

  if (key == '5')
  {
    display_mode = 5;
    update_display(viewer);
  }

  if (key == '6')
  {
    display_mode = 6;
    update_display(viewer);
  }

  if (key == '7')
  {
    display_mode = 7;
    update_display(viewer);
  }

  if (key == '8')
  {
    display_mode = 8;
    update_display(viewer);
  }

  if (key == '9')
  {
    display_mode = 9;
    update_display(viewer);
  }

  if (key == '0')
  {
    display_mode = 0;
    update_display(viewer);
  }

  if (key == 'A')
  {
    //do a batch of iterations
    printf("--Improving Curl--\n");
    for (int bi = 0; bi<5; ++bi)
    {
      printf("\n\n **** Batch %d ****\n", iter);
      igl::integrable_polyvector_fields_solve(ipfdata, params, two_pv, iter ==0);
      iter++;
      params.wSmooth *= params.redFactor_wsmooth;
    }
    // Post process current field
    // Compute curl_minimizing matchings and curl
    printf("--Matchings and curl--\n");
    Eigen::MatrixXi match_ab, match_ba;  // matchings across interior edges
    double avgCurl = igl::polyvector_field_matchings(two_pv, V, F, true, match_ab, match_ba, curl);
    double maxCurl = curl.maxCoeff();
    printf("curl -- max: %.5g, avg: %.5g\n", maxCurl,  avgCurl);
    // Compute singularities
    printf("--Singularities--\n");
    igl::polyvector_field_singularities_from_matchings(V, F, match_ab, match_ba, singularities);
    printf("#singularities: %ld\n", singularities.rows());
    // Get mesh cuts based on singularities
    printf("--Cuts--\n");
    igl::polyvector_field_cut_mesh_with_singularities(V, F, singularities, cuts);
    // Comb field
    printf("--Combing--\n");
    Eigen::MatrixXd combed;
    igl::polyvector_field_comb_from_matchings_and_cuts(V, F, two_pv, match_ab, match_ba, cuts, combed);
    // Reconstruct integrable vector fields from combed field
    printf("--Cut mesh--\n");
    igl::cut_mesh(V, F, cuts, Vcut, Fcut);
    printf("--Poisson--\n");
    double avgPoisson = igl::polyvector_field_poisson_reconstruction(Vcut, Fcut, combed, scalars, two_pv_poisson, poisson_error);
    double maxPoisson = poisson_error.maxCoeff();
    printf("poisson error -- max: %.5g, avg: %.5g\n", maxPoisson, avgPoisson);

    update_display(viewer);
  }

  return false;
}
예제 #23
0
/* 
 * Implementation of Kronecker product. 
 * Eigen has an implementation of the Kronecker product,
 * but it is very slow due to poor memory reservation.
 * See: https://forum.kde.org/viewtopic.php?f=74&t=106955&p=309990&hilit=kronecker#p309990
 * When Eigen update their implementation, and officially support it, we switch to that.
 */
SparseMatrix myKroneckerProduct(const SparseMatrix &A, const SparseMatrix &B)
{
    SparseMatrix AB(A.rows()*B.rows(), A.cols()*B.cols());

    // Reserve memory for AB

    //AB.reserve(A.nonZeros()*B.nonZeros()); // Does not reserve inner vectors (slow)
    //int innernnz = std::ceil(A.nonZeros()*B.nonZeros()/AB.outerSize());
    //AB.reserve(Eigen::VectorXi::Constant(AB.outerSize(), innernnz)); // Assumes equal distribution of non-zeros (slow)

    // Calculate exact number of non-zeros for each inner vector
    Eigen::VectorXi nnzA = Eigen::VectorXi::Zero(A.outerSize());
    Eigen::VectorXi nnzB = Eigen::VectorXi::Zero(B.outerSize());
    Eigen::VectorXi nnzAB = Eigen::VectorXi::Zero(AB.outerSize());
    //innerNonZeros.setZero();

    for (int jA = 0; jA < A.outerSize(); ++jA)
    {
        int nnz = 0;
        for (SparseMatrix::InnerIterator itA(A,jA); itA; ++itA) nnz++;
        nnzA(jA) = nnz;
    }

    for (int jB = 0; jB < B.outerSize(); ++jB)
    {
        int nnz = 0;
        for (SparseMatrix::InnerIterator itB(B,jB); itB; ++itB) nnz++;
        nnzB(jB) = nnz;
    }

    int innz = 0;
    for (int i = 0; i < nnzA.rows(); ++i)
    {
        for (int j = 0; j < nnzB.rows(); ++j)
        {
            nnzAB(innz) = nnzA(i)*nnzB(j);
            innz++;
        }
    }

    AB.reserve(nnzAB);

    // Non-zero tolerance
    double tolerance = std::numeric_limits<SparseMatrix::Scalar>::epsilon();

    // Compute Kronecker product
    for (int jA = 0; jA < A.outerSize(); ++jA)
    {
        for (SparseMatrix::InnerIterator itA(A,jA); itA; ++itA)
        {
            if (std::abs(itA.value()) > tolerance)
            {
                int jrow = itA.row()*B.rows();
                int jcol = itA.col()*B.cols();

                for (int jB = 0; jB < B.outerSize(); ++jB)
                {
                    for (SparseMatrix::InnerIterator itB(B,jB); itB; ++itB)
                    {
                        if (std::abs(itA.value()*itB.value()) > tolerance)
                        {
                            int row = jrow + itB.row();
                            int col = jcol + itB.col();
                            AB.insert(row,col) = itA.value()*itB.value();
                        }
                    }
                }
            }
        }
    }
    AB.makeCompressed();
    return AB;
}
예제 #24
0
파일: main.cpp 프로젝트: Codermay/libigl
// Create a random set of tangent vectors
void generate_constraints()
{
  b.resize(42,1);
  b<<
  663,
  513,
  3872,
  2601,
  3549,
  2721,
  3796,
  594,
  868,
  1730,
  1581,
  3081,
  1471,
  1650,
  454,
  2740,
  2945,
  3808,
  3679,
  3589,
  450,
  2656,
  1791,
  1792,
  2917,
  3744,
  1536,
  2809,
  3866,
  3658,
  1665,
  2670,
  1601,
  1793,
  3614,
  524,
  2877,
  449,
  455,
  3867,
  3871,
  2592;

blevel.setOnes(b.rows(),1);
bc.resize(b.rows(),6);
bc<<
-0.88046298335147721,0.27309862654264377,0.38755912468723769,-0.350632259447135,-0.92528970817792766,-0.14455440005410564,
0.91471470003012889,0.392936119054695,-0.094330397492144599,0.32234487030777614,-0.85027369799342767,-0.41608703787410195,
0.94335566040683105,0.073867667925654024,-0.32345581709658111,0.19950360079371404,-0.90525435056476755,0.37511714710727789,
-0.92054671613540229,0.15077598183983737,0.36036141124232496,-0.27998315313687211,-0.89796618385425386,-0.33950871360506074,
0.88944399663239937,0.23035525634795684,-0.39474780902172396,0.27297422303141039,-0.96047177712172194,0.054580572670497061,
-0.83112706922096102,-0.55599928943162547,0.0096221078617792517,0.52546831822766438,-0.79091522174894457,-0.31358596675362826,
0.90724658517664569,-0.41046292080872998,-0.091781394228251156,-0.34252813327252363,-0.84767620917196618,0.40511667741613094,
-0.8932101465465786,0.23975524191487588,0.38038540729184012,-0.33645713296414853,-0.91759364410558497,-0.21170380718016926,
-0.87839308390284521,0.27039404931731387,0.39409725734320344,-0.29712518405497651,-0.95481177255558192,-0.0071487054467167244,
-0.91448048788760505,-0.17055891298176448,0.36692655188106316,0.29811257890714044,-0.89715315396744022,0.32595261714489804,
0.82798126471567035,-0.56074230404745851,0.003885065171440813,-0.53510484459763941,-0.78801608401899037,0.30445600111594384,
-0.87831929581593793,0.25312706437601257,0.40556368658667746,-0.26531767440854004,-0.9637845762158106,0.026941089342378936,
-0.87482003689209031,-0.27011021313654948,0.4021571531272935,0.32303198334357713,-0.94388894366288889,0.0687313594225408,
0.87408456883093666,-0.48487387939766946,-0.029554823793924323,-0.43846604347950752,-0.81368808449189478,0.38165328489525413,
0.94988212941972827,-0.041936960956176939,-0.30978255521381903,-0.16637246118261648,-0.90677959514398765,-0.3873899456497869,
0.87516493768857484,-0.27181042881473483,-0.40025669591913515,-0.36755520380602424,-0.91147911093961553,-0.18468622708756641,
-0.87064244687577641,0.27922257819020818,0.40498948323008854,-0.32176729617260508,-0.94599403842079244,-0.039510585747255161,
-0.91274615133859638,-0.1832657459904497,0.36511385835536858,0.29782083933521708,-0.91026141603074595,0.28762284704690655,
0.875611546674125,0.28258715176515403,-0.39172556846369444,0.36000975242683186,-0.92250014843287764,0.13923524804764778,
0.76763693171870195,-0.64088483679642994,0.00040868803559811201,-0.63058113310112196,-0.75518119878562417,0.17907761327874747,
0.963064265211517,0.17044712473620016,-0.20845862597111031,0.061832174999749308,-0.89345471128813481,-0.44487690546019126,
-0.88228998376691692,-0.46837234310148523,0.046815945597605227,0.41604986062280985,-0.82249303168905052,-0.38782434980116298,
-0.96608602970701829,0.11121907649833783,0.23304098400879364,0.010641270548624404,-0.88457418950525291,0.46627810008860171,
-0.96329451047686887,0.055809409647239343,0.26258140810033831,0.07182051046944142,-0.88891411988025926,0.45240855623364673,
-0.71244584326772997,-0.70122065397026967,-0.026655484539588895,0.70046172163981768,-0.70836773631021255,-0.086997279682342638,
0.88646445996853696,0.2549240118236365,-0.38625705094979518,0.35132981358631576,-0.91395520354543514,0.20310895597591658,
-0.86109327343809683,-0.30822574449366841,0.40437020769461601,0.37896596246993836,-0.91928725525816557,0.10628142645421024,
0.86443027504389158,-0.29669958642983363,-0.40586901212079213,-0.37200560813855077,-0.92052106924988175,-0.11938504337027039,
0.95370728000967508,-0.24689991217686594,-0.17170572915195079,-0.14736898596800915,-0.88138264597997584,0.4488284898935197,
-0.81439393313167019,0.57995723960933832,0.020300785774083896,-0.55494919604589421,-0.78855235001798585,0.26498411478639117,
0.89527216270596455,0.22395367264061938,-0.38513959442592183,0.33680943342191538,-0.90609008785063272,0.25604717974787594,
-0.9003647006267198,0.20802946062196581,0.38218732236782926,-0.32431023000528064,-0.90640636884236436,-0.27064805418831556,
-0.87050937437709508,-0.28614105672408718,0.40042068475344922,0.37746788793940733,-0.91025870352880611,0.17013843253251126,
-0.95715079751532439,0.0030851788865496879,0.28957353554324744,0.12908381923211401,-0.89056292562302997,0.43615942397041058,
-0.87324677619075319,-0.28591869514051466,0.39457644080913162,0.3438918663433696,-0.93530416305293196,0.083333707698197687,
0.91999856277124803,-0.1621255206103257,-0.35681642348085474,-0.27672206872177485,-0.91342693749618353,-0.2984562389005877,
-0.8669467282645521,0.29036174243712859,0.40508447128995645,-0.34873789125620602,-0.93406639205959408,-0.07682355385522964,
-0.9570365266718136,-0.22821899053183647,0.17887755302603078,0.12590409644663494,-0.88275887883510706,-0.45264215483728532,
-0.94033215083998489,0.087395510869996196,0.32884262311388451,-0.2131320783418921,-0.90465024471116184,-0.36902933748646671,
-0.96131014054749453,0.18866284908038999,0.20072155603578434,-0.08260532909072589,-0.89255302833360861,0.44331191188407898,
-0.95240414686152941,-0.02752900142620229,0.30359264668538755,0.15128346580527452,-0.9073021943457209,0.39232134929083828,
-0.94070423353276911,-0.31552769387286655,0.12457053990729766,0.22959741970407915,-0.86253407908715607,-0.45091017650802745;

}
예제 #25
0
// A tet is organized in the following fashion:
//
//       0
//       
//       3       (3 is in the background; 1 and 2 are in the foreground)
//  2        1
//
// So the faces (with counterclockwise normals) are:
// (0 1 3)
// (0 2 1)
// (3 2 0)
// (1 2 3)
//
//
// This method will perform three steps:
// 1. Add all faces, duplicating ones on the interior
// 2. Remove all duplicate verts (might have been caused during #1)
// 3. Remove all duplicate faces
void marching_tets(
  const Eigen::MatrixXd& V,
  const Eigen::MatrixXi& T,
  const Eigen::VectorXd& H,
  double offset,
  Eigen::MatrixXd& NV,
  Eigen::MatrixXi& NF,
  Eigen::VectorXi& I)
{
  min_how_much = 1;
  max_how_much = 0;
  using namespace Eigen;
  using namespace std;

  // Count the faces.
  std::map<std::vector<int>, int> face_counts;
  for (int i = 0; i < T.rows(); ++i) {
    std::vector<std::vector<int> > fs;
    fs.push_back({T(i, 0), T(i, 1), T(i, 3)});
    fs.push_back({T(i, 0), T(i, 2), T(i, 1)});
    fs.push_back({T(i, 3), T(i, 2), T(i, 0)});
    fs.push_back({T(i, 1), T(i, 2), T(i, 3)});
    for (auto &f : fs) {
      std::sort(f.begin(), f.end());
      // Add it to the map.
      face_counts[f]++;
    }
  }

  vector<Eigen::RowVector3i> faces;
  vector<int> faces_markers;
  vector<Eigen::RowVector3d> new_verts;
  int times[6];
  for (int i = 0; i < 6; i++) {
    times[i] = 0;
  }

  // Create data structure.
  MarchingTetsDat dd(V, H, faces, faces_markers, face_counts, new_verts, offset);

  int numEq = 0;

  // Check each tet face, add as needed.
  for (int i = 0; i < T.rows(); ++i) {
    // See if the tet is entirely inside.
    vector<int> inside, outside, inside_t, outside_t, identical;
    for (int j = 0; j < T.cols(); ++j) {
      //if (H(T(i, j)) > offset + 1e-4) {
      if (H(T(i, j)) > offset) {
        outside.push_back(j);
      } else if (H(T(i, j)) < offset) {
        inside.push_back(j);
      } else {
        numEq++;
        identical.push_back(j);
      }

      if (H(T(i, j)) == GLOBAL::outside_temp) {
        outside_t.push_back(j);
      } else if (H(T(i, j)) == GLOBAL::inside_temp) {
        inside_t.push_back(j);
      }
    }

    // Ignore this tet if it's entirely outside.
    if (outside.size() == 4) {
      continue;
    }


    if (outside.size() == 0 && inside.size() == 0) {
      // degenerate, ignore.
      printf("WARNING: degenerate tet face found!!\n");
    } else if (inside.size() == 0 && identical.size() < 3) {
      // Nothing to add.
    } else if (identical.size() == 3) {
      //addOrig(T.row(i), 7, dd.faces, dd.faces_markers);
      // Ignore it if there's only one on the outside.
      //if (inside.size() == 0) continue;
      if (outside.size() == 0) continue;
      times[1]++;
      // Add just a single face (always)
      int i1 = T(i,identical[0]), i2 = T(i,identical[1]), i3 = T(i,identical[2]);
      Eigen::RowVector3i f({i1, i2, i3});
      dd.faces.push_back(f);
      dd.faces_markers.push_back(1);
    } else if (outside.size() == 0) {
      // (these are colored blue)
      times[0]++;
      // (A) Takes care of:
      //   inside: 1, identical: 3 (remove three duplicated faces later)
      //   inside: 2, identical: 2 (remove all four duplicated faces later)
      //   inside: 3, identical: 1 (remove all four duplicated faces later)
      //   inside: 4, identical: 0 (remove all four duplicated faces later)
      case0Out(dd, T.row(i), inside, outside, identical, inside_t, outside_t);
    } else if (inside.size() == 1) {
      // (these are colored green)
      times[2]++;
      // (B) Takes care of:
      //   inside: 1 outside: 3
      //   inside: 1 outside: 2 identical: 1
      //   inside: 1 outside: 1 identical: 2
      //
      case1In(dd, T.row(i), inside, outside, identical, inside_t, outside_t);
    } else if (inside.size() == 3 && outside.size() == 1) {
      // (these are colored orange)
      times[3]++;
      // (C) takes care of:
      //   inside: 3 outside: 1
      //
      case3In1Out(dd, T.row(i), inside, outside, identical, inside_t, outside_t);
    } else if (inside.size() == 2 && outside.size() >= 1) {
      // (these are colored red)
      times[4]++;
      // (D) takes care of:
      //   inside: 2 outside: 1 identical: 1
      //   inside: 2 outside: 2 identical: 0
      //
      case2In2Out(dd, T.row(i), inside, outside, identical, inside_t, outside_t);
    } else {
      times[5]++;
      fprintf(stderr, "WARN: marching tets found something weird, with in:%lu out:%lu\n",
              inside.size(), outside.size());
    }
  }

  printf("Finished marching tets with usages:\n");
  for (int i = 0; i < 6; ++i) {
    printf("  %d: %d\n", i, times[i]);
  }
  printf("how_much is %lf and EPS is %lf\n", min_how_much, GLOBAL::EPS);
  printf("     max is %lf\n", max_how_much);
  printf("Num equal is %d\n", numEq);

  // Copy verts
  NV.resize(V.rows() + new_verts.size(), 3);
  for (int i = 0; i < V.rows(); ++i) {
    NV.row(i) = V.row(i);
  }
  for (int i = 0; i < new_verts.size(); ++i) {
    NV.row(i + V.rows()) = new_verts[i];
  }
  // Set I
  I.resize(NV.rows());
  for (int i = 0; i < I.rows(); ++i) {
    if (i < V.rows()) {
      I(i) = i;
    } else {
      I(i) = -1;
    }
  }
  Eigen::VectorXi facesMarkers;
  facesMarkers.resize(faces.size());
  // Copy faces
  NF.resize(faces.size(), 3);
  for (int i = 0; i < faces.size(); ++i) {
    NF.row(i) = faces[i];
    facesMarkers(i) = faces_markers[i];
  }
  
  Eigen::MatrixXd newV;
  Eigen::MatrixXi newF;
  Eigen::VectorXi SVJ, SVI, I2;
  // Helpers::viewTriMesh(NV, NF, facesMarkers);
  //igl::writeOFF("offset_mesh.off", NV, NF)
  Helpers::writeMeshWithMarkers("offset_mesh", NV, NF, facesMarkers);

  /*
  igl::collapse_small_triangles(NV, NF, 1e-8, newF);
  printf("Collapsed %d small triangles\n", NF.rows() - newF.rows());
  NF = newF;
  */

  ///*
  igl::remove_duplicate_vertices(NV, NF, 1e-20, newV, SVI, SVJ, newF);
  I2.resize(newV.rows());
  I2.setConstant(-1);
  for (int i = 0; i < NV.rows(); ++i) {
    if (I2(SVJ(i)) == -1) {
      I2(SVJ(i)) = I(i);
    } else {
      I2(SVJ(i)) = std::min(I2(SVJ(i)), I(i));
    }
  }
  NF = newF;
  NV = newV;
  I = I2;

  // Now see if we have duplicated faces.
  //igl::resolve_duplicated_faces(NF, newF, SVJ);
  //NF = newF;
  //*/

  // Other option is to do these two:
  // These are bad because sometimes the "small" triangles are not area zero,
  // and doing the removeDuplicates will delete these triangles and make the
  // mesh non-manifold. Better to wait for remeshing later.
  //Helpers::removeDuplicates(NV, NF, I);
  //Helpers::collapseSmallTriangles(NV, NF);

  igl::remove_unreferenced(NV, NF, newV, newF, SVI, SVJ);
  I2.resize(newV.rows());
  I2.setConstant(-1);
  for (int i = 0; i < I2.rows(); ++i) {
    I2(i) = I(SVJ(i));
  }
  I = I2;
  NV = newV;
  NF = newF;


  // orient everything correctly.
  Eigen::VectorXi C;
  igl::orientable_patches(NF, C);
  igl::bfs_orient(NF, newF, C);
  NF = newF;
  igl::orient_outward(NV, NF, C, newF, SVJ);
  NF = newF;
  //igl::writeOFF("offset_mesh_normals.off", NV, NF);

#ifdef DEBUG_MESH
  if (!Helpers::isMeshOkay(NV, NF)) {
    printf("Error: Mesh is not okay at first...\n");
  }
  if (!Helpers::isManifold(NV, NF, I)) {
    printf("Error: Mesh from marching tets not manifold!\n");
    Eigen::VectorXi temp;
    temp.resize(I.rows());
    temp.setZero();
    Helpers::isManifold(NV, NF, temp, true);
    Helpers::viewTriMesh(NV, NF, temp);
    Helpers::writeMeshWithMarkers("marching_tets_manifold", NV, NF, temp);
    cout << "See marching_tets_manifold.off for problems.\n";
    exit(1);
  }
#endif
}
예제 #26
0
파일: example.cpp 프로젝트: dut09/libigl
bool init_arap()
{
  using namespace igl;
  using namespace Eigen;
  using namespace std;
  VectorXi b(num_in_selection(S));
  assert(S.rows() == V.rows());
  C.resize(S.rows(),3);
  MatrixXd bc = MatrixXd::Zero(b.size(),S.maxCoeff()+1);
  MatrixXi * Ele;
  if(T.rows()>0)
  {
    Ele = &T;
  }else
  {
    Ele = &F;
  }
  // get b from S
  {
    int bi = 0;
    for(int v = 0;v<S.rows(); v++)
    {
      if(S(v) >= 0)
      {
        b(bi) = v;
        bc(bi,S(v)) = 1;
        bi++;
        switch(S(v))
        {
          case 0:
            C.row(v) = RowVector3d(0.039,0.31,1);
            break;
          case 1:
            C.row(v) = RowVector3d(1,0.41,0.70);
            break;
          default:
            C.row(v) = RowVector3d(0.4,0.8,0.3);
            break;
        }
      }else
      {
        C.row(v) = RowVector3d(
          GOLD_DIFFUSE[0],
          GOLD_DIFFUSE[1],
          GOLD_DIFFUSE[2]);
      }
    }
  }
  // Store current mesh
  U = V;
  VectorXi _S;
  VectorXd _D;
  MatrixXd W;
  if(!harmonic(V,*Ele,b,bc,1,W))
  {
    return false;
  }
  //arap_data.with_dynamics = true;
  //arap_data.h = 0.5;
  //arap_data.max_iter = 100;
  //partition(W,100,arap_data.G,_S,_D);
  return arap_precomputation(V,*Ele,V.cols(),b,arap_data);
}