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; }
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); } }
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; }
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); }
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; }
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)); } }
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; }
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; }
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); } }
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); } }
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); }
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; }
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; }
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(); }
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"); }
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; }
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; }
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; }
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); }
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; }
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; }
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; }
/* * 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; }
// 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; }
// 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 }
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); }