void GlobalFun::find_original_neighbors(CGrid::iterator starta, CGrid::iterator enda, CGrid::iterator startb, CGrid::iterator endb, double radius) { double radius2 = radius*radius; double iradius16 = -4/radius2; const double PI = 3.1415926; for(CGrid::iterator dest = starta; dest != enda; dest++) { CVertex &v = *(*dest); Point3f &p = v.P(); for(CGrid::iterator origin = startb; origin != endb; origin++) { CVertex &t = *(*origin); Point3f &q = t.P(); Point3f diff = p-q; double dist2 = diff.SquaredNorm(); if(dist2 < radius2) { v.original_neighbors.push_back((*origin)->m_index); } } } }
void WLOP::computeRepulsionTerm(CMesh* samples) { double repulsion_power = para->getDouble("Repulsion Power"); bool need_density = para->getBool("Need Compute Density"); double radius = para->getDouble("CGrid Radius"); double radius2 = radius * radius; double iradius16 = -para->getDouble("H Gaussian Para")/radius2; cout << endl<< endl<< "Sample Neighbor Size:" << samples->vert[0].neighbors.size() << endl<< endl; for(int i = 0; i < samples->vert.size(); i++) { CVertex& v = samples->vert[i]; for (int j = 0; j < v.neighbors.size(); j++) { CVertex& t = samples->vert[v.neighbors[j]]; Point3f diff = v.P() - t.P(); double dist2 = diff.SquaredNorm(); double len = sqrt(dist2); if(len <= 0.001 * radius) len = radius*0.001; double w = exp(dist2*iradius16); double rep = w * pow(1.0 / len, repulsion_power); if (need_density) { rep *= samples_density[t.m_index]; } repulsion[i] += diff * rep; repulsion_weight_sum[i] += rep; } } }
Point3f RandomUnitVec(){ Point3f k; do { k=Point3f( (random(200)-100)*0.01, (random(200)-100)*0.01, (random(200)-100)*0.01 ); } while (k.SquaredNorm()>1.0); return k.Normalize(); }
void WLOP::computeAverageTerm(CMesh* samples, CMesh* original) { double average_power = para->getDouble("Average Power"); bool need_density = para->getBool("Need Compute Density"); double radius = para->getDouble("CGrid Radius"); double radius2 = radius * radius; double iradius16 = -para->getDouble("H Gaussian Para")/radius2; cout << "Original Size:" << samples->vert[0].original_neighbors.size() << endl; for(int i = 0; i < samples->vert.size(); i++) { CVertex& v = samples->vert[i]; for (int j = 0; j < v.original_neighbors.size(); j++) { CVertex& t = original->vert[v.original_neighbors[j]]; Point3f diff = v.P() - t.P(); double dist2 = diff.SquaredNorm(); double w = 1; if (para->getBool("Run Anisotropic LOP")) { double len = sqrt(dist2); if(len <= 0.001 * radius) len = radius*0.001; double hn = diff * v.N(); double phi = exp(hn * hn * iradius16); w = phi / pow(len, 2 - average_power); } else if (average_power < 2) { double len = sqrt(dist2); if(len <= 0.001 * radius) len = radius*0.001; w = exp(dist2 * iradius16) / pow(len, 2 - average_power); } else { w = exp(dist2 * iradius16); } if (need_density) { w *= original_density[t.m_index]; } average[i] += t.P() * w; average_weight_sum[i] += w; } } }
void GlobalFun::other_neighbors(CGrid::iterator starta, CGrid::iterator enda, CGrid::iterator startb, CGrid::iterator endb, double radius) { double radius2 = radius*radius; for(CGrid::iterator dest = starta; dest != enda; dest++) { CVertex &v = *(*dest); Point3f &p = v.P(); for(CGrid::iterator origin = startb; origin != endb; origin++) { CVertex &t = *(*origin); Point3f &q = t.P(); Point3f diff = p-q; double dist2 = diff.SquaredNorm(); if(dist2 < radius2) { v.neighbors.push_back((*origin)->m_index); t.neighbors.push_back((*dest)->m_index); } } } }
void GlobalFun::computeEigenWithTheta(CMesh* _samples, double radius) { vector<vector<int> > neighborMap; typedef vector<CVertex>::iterator VertexIterator; VertexIterator begin = _samples->vert.begin(); VertexIterator end = _samples->vert.end(); neighborMap.assign(end - begin, vector<int>()); int curr_index = 0; for (VertexIterator iter=begin; iter!=end; iter++, curr_index++) { if(iter->neighbors.size() <= 3) { iter->eigen_confidence = 0.5; continue; } for(int j = 0; j < iter->neighbors.size(); j++) { neighborMap[curr_index].push_back(iter->neighbors[j]); } } double radius2 = radius*radius; double iradius16 = -1/radius2; int currIndex = 0; for (VertexIterator iter=begin; iter!=end; iter++, currIndex++) { if(iter->neighbors.size() <= 3) { iter->eigen_confidence = 0.5; continue; } Matrix33d covariance_matrix; Point3f diff; covariance_matrix.SetZero(); int neighborIndex = -1; int neighbor_size = iter->neighbors.size(); for (unsigned int n=0; n<neighbor_size; n++) { neighborIndex = neighborMap[currIndex][n]; if(neighborIndex < 0) break; VertexIterator neighborIter = begin + neighborIndex; diff = iter->P() - neighborIter->P(); Point3f vm = iter->N(); Point3f tm = neighborIter->N(); double dist2 = diff.SquaredNorm(); double theta = exp(dist2*iradius16); for (int i=0; i<3; i++) for (int j=0; j<3; j++) covariance_matrix[i][j] += diff[i]*diff[j] * theta; } Point3f eigenvalues; Matrix33d eigenvectors; int required_rotations; vcg::Jacobi< Matrix33d, Point3f >(covariance_matrix, eigenvalues, eigenvectors, required_rotations); vcg::SortEigenvaluesAndEigenvectors< Matrix33d, Point3f >(eigenvalues, eigenvectors); double sum_eigen_value = (eigenvalues[0] + eigenvalues[1] + eigenvalues[2]); iter->eigen_confidence = eigenvalues[0] / sum_eigen_value; for (int d=0; d<3; d++) iter->eigen_vector0[d] = eigenvectors[d][0]; for (int d=0; d<3; d++) iter->eigen_vector1[d] = eigenvectors[d][1]; for (int d=0; d<3; d++) iter->N()[d] = eigenvectors[d][2]; iter->eigen_vector0.Normalize(); iter->eigen_vector1.Normalize(); iter->N().Normalize(); } }
double WLOP::iterate() { Timer time; initVertexes(); time.start("Sample Original Neighbor Tree!!!"); GlobalFun::computeBallNeighbors(samples, original, para->getDouble("CGrid Radius"), box); time.end(); time.start("Sample Sample Neighbor Tree"); GlobalFun::computeBallNeighbors(samples, NULL, para->getDouble("CGrid Radius"), samples->bbox); time.end(); if (nTimeIterated == 0) { if (para->getBool("Need Compute Density")) { double local_density_para = 0.95; time.start("Original Original Neighbor Tree"); GlobalFun::computeBallNeighbors(original, NULL, para->getDouble("CGrid Radius") * local_density_para, original->bbox); time.end(); time.start("Compute Original Density"); original_density.assign(original->vn, 0); computeDensity(true, para->getDouble("CGrid Radius") * local_density_para); time.end(); } } if (para->getBool("Need Compute Density")) { time.start("Compute Density For Sample"); computeDensity(false, para->getDouble("CGrid Radius")); time.end(); } time.start("Sample Original Neighbor Tree!!!"); GlobalFun::computeBallNeighbors(samples, original, para->getDouble("CGrid Radius"), box); time.end(); time.start("Compute Average Term"); computeAverageTerm(samples, original); time.end(); time.start("Compute Repulsion Term"); computeRepulsionTerm(samples); time.end(); double mu = para->getDouble("Repulsion Mu"); Point3f c; for(int i = 0; i < samples->vert.size(); i++) { CVertex& v = samples->vert[i]; c = v.P(); if (average_weight_sum[i] > 1e-20) { v.P() = average[i] / average_weight_sum[i]; } if (repulsion_weight_sum[i] > 1e-20 && mu >= 0) { v.P() += repulsion[i] * (mu / repulsion_weight_sum[i]); } if (average_weight_sum[i] > 1e-20 && repulsion_weight_sum[i] > 1e-20 ) { Point3f diff = v.P() - c; double move_error = sqrt(diff.SquaredNorm()); error_x += move_error; } } error_x = error_x / samples->vn; para->setValue("Current Movement Error", DoubleValue(error_x)); cout << "****finished compute WLOP error: " << error_x << endl; if (para->getBool("Need Compute PCA")) { time.start("Recompute PCA"); recomputePCA_Normal(); time.end(); } return error_x; }