MeshKit
1.0
|
00001 #include "meshkit/Mesh.hpp" 00002 00003 using namespace Jaal; 00004 00006 Point3D 00007 LaplaceSmoothing::displace( const Point3D &head, const Point3D &tail, double r ) 00008 { 00009 double d = Math::length( head, tail); 00010 if( d < 1.0E-10) return head; 00011 00012 Vec3D vec = Math::unit_vector(head, tail); 00013 00014 Point3D newpos; 00015 newpos[0] = tail[0] + d*r*vec[0]; 00016 newpos[1] = tail[1] + d*r*vec[1]; 00017 newpos[2] = tail[2] + d*r*vec[2]; 00018 return newpos; 00019 } 00020 00022 00023 double 00024 LaplaceSmoothing::update_vertex_position(Vertex *vertex, const Point3D &newpos) 00025 { 00026 double area0, area1, localerror = 0.0; 00027 00028 NodeSequence vneighs; 00029 vertex->getRelations( vneighs ); 00030 00031 Point3D oldpos = vertex->getXYZCoords(); 00032 00033 FaceSequence vfaces; 00034 vertex->getRelations( vfaces ); 00035 00036 area0 = 0.0; 00037 for (size_t i = 0; i < vfaces.size(); i++) 00038 { 00039 MeshEntity::idtype id = vfaces[i]->getID(); 00040 area0 += facearea[id]; 00041 } 00042 00043 // Change the coordinate ( temporary ) 00044 vertex->setXYZCoords(newpos); 00045 00046 // Check for validity of the sounding patch... 00047 int some_face_inverted = 0; 00048 area1 = 0.0; 00049 for (size_t i = 0; i < vfaces.size(); i++) 00050 { 00051 MeshEntity::idtype id = vfaces[i]->getID(); 00052 facearea[id] = vfaces[i]->getArea(); // Recalculate new face area ... 00053 area1 += facearea[id]; 00054 if (vfaces[i]->concaveAt() >= 0) 00055 { 00056 some_face_inverted = 1; 00057 break; 00058 } 00059 } 00060 00061 // Both the area must be invariant and no face must inverte in order to update the 00062 // postion. 00063 if (fabs(area1 - area0) > 1.0E-10 || some_face_inverted == 1) 00064 { 00065 vertex->setXYZCoords(oldpos); // Revert back 00066 localerror = 0.0; 00067 return localerror; 00068 } 00069 00070 // Update the area of the surrounding faces ... 00071 localerror = max(localerror, fabs(newpos[0] - oldpos[0])); 00072 localerror = max(localerror, fabs(newpos[1] - oldpos[1])); 00073 localerror = max(localerror, fabs(newpos[2] - oldpos[2])); 00074 maxerror = max(maxerror, localerror); 00075 00076 return localerror; 00077 } 00078 00080 00081 double 00082 LaplaceSmoothing::update_vertex_position(Vertex *vertex) 00083 { 00084 if (vertex->isConstrained()) return 0.0; 00085 00086 const Point3D &oldpos = vertex->getXYZCoords(); 00087 00088 NodeSequence neighs; 00089 vertex->getRelations( neighs ); 00090 assert(neighs.size()); 00091 00092 Point3D newpos, xyz; 00093 newpos[0] = 0.0; 00094 newpos[1] = 0.0; 00095 newpos[2] = 0.0; 00096 00097 double weight, sum_weight = 0.0; 00098 for (size_t i = 0; i < neighs.size(); i++) 00099 { 00100 weight = lapweight->get(vertex, neighs[i]); 00101 xyz = neighs[i]->getXYZCoords(); 00102 newpos[0] += weight * xyz[0]; 00103 newpos[1] += weight * xyz[1]; 00104 newpos[2] += weight * xyz[2]; 00105 sum_weight += weight; 00106 } 00107 00108 newpos[0] /= sum_weight; 00109 newpos[1] /= sum_weight; 00110 newpos[2] /= sum_weight; 00111 00112 newpos[0] = (1.0 - lambda) * oldpos[0] + lambda * newpos[0]; 00113 newpos[1] = (1.0 - lambda) * oldpos[1] + lambda * newpos[1]; 00114 newpos[2] = (1.0 - lambda) * oldpos[2] + lambda * newpos[2]; 00115 00116 return update_vertex_position(vertex, newpos); 00117 } 00118 00120 int 00121 LaplaceSmoothing::execute() 00122 { 00123 return global_smoothing(); 00124 } 00125 00127 00128 int 00129 LaplaceSmoothing::global_smoothing() 00130 { 00131 assert(lapweight); 00132 mesh->search_boundary(); 00133 00134 int relexist0 = mesh->build_relations(0, 0); 00135 int relexist2 = mesh->build_relations(0, 2); 00136 00137 size_t numnodes = mesh->getSize(0); 00138 size_t numfaces = mesh->getSize(2); 00139 00140 facearea.resize(numfaces); 00141 size_t num_inverted_before_smoothing = 0; 00142 for (size_t i = 0; i < numfaces; i++) 00143 { 00144 Face *face = mesh->getFaceAt(i); 00145 face->setID(i); // Needed because of facearea is an external array... 00146 facearea[i] = face->getArea(); 00147 if (face->concaveAt() >= 0) num_inverted_before_smoothing++; 00148 } 00149 00150 for (int iter = 0; iter < numIters; iter++) 00151 { 00152 maxerror = 0.0; 00153 for (size_t i = 0; i < numnodes; i++) 00154 { 00155 Vertex *v = mesh->getNodeAt(i); 00156 if( !v->isRemoved() ) 00157 maxerror = max(maxerror, update_vertex_position(v)); 00158 } 00159 cout << " iter " << maxerror << endl; 00160 00161 if (maxerror < 1.0E-06) break; 00162 } 00163 00164 if (!relexist0) mesh->clear_relations(0, 0); 00165 if (!relexist2) mesh->clear_relations(0, 2); 00166 00167 /* 00168 size_t num_inverted_after_smoothing = 0; 00169 for (size_t i = 0; i < numfaces; i++) 00170 { 00171 Face *face = mesh->getFaceAt(i); 00172 if (face->invertedAt() >= 0) num_inverted_after_smoothing++; 00173 } 00174 assert(num_inverted_after_smoothing <= num_inverted_before_smoothing); 00175 */ 00176 00177 return 0; 00178 } 00179 00181 00182 int 00183 LaplaceSmoothing::localized_at(const NodeSequence &vertexQ) 00184 { 00185 assert(lapweight); 00186 00187 assert( mesh->isBoundaryKnown() ); 00188 assert( mesh->getAdjTable(0,0) ); 00189 assert( mesh->getAdjTable(0,2) ); 00190 00191 /* 00192 int relexist0 = mesh->build_relations(0, 0); 00193 int relexist2 = mesh->build_relations(0, 2); 00194 */ 00195 00196 //How many faces will be affected by changing the coordinates of vertexQ 00197 00198 FaceSequence vfaces; 00199 size_t numfaces = mesh->getSize(2); 00200 00201 for (size_t i = 0; i < numfaces; i++) 00202 { 00203 Face *face = mesh->getFaceAt(i); // assert( face ); 00204 face->setVisitMark(0); 00205 } 00206 00207 for (size_t i = 0; i < vertexQ.size(); i++) 00208 { 00209 Vertex *v = vertexQ[i]; 00210 v->getRelations( vfaces ); 00211 for (size_t j = 0; j < vfaces.size(); j++) 00212 vfaces[j]->setVisitMark(1); 00213 } 00214 00215 facearea.resize(numfaces); 00216 for (size_t i = 0; i < numfaces; i++) 00217 { 00218 Face *face = mesh->getFaceAt(i); 00219 face->setID(i); // Needed because of facearea is an external array... 00220 facearea[i] = 0.0; 00221 if (face->isVisited()) 00222 facearea[i] = face->getArea(); 00223 } 00224 00225 for (int iter = 0; iter < numIters; iter++) 00226 { 00227 maxerror = 0.0; 00228 for (size_t i = 0; i < vertexQ.size(); i++) 00229 maxerror = max(maxerror, update_vertex_position(vertexQ[i])); 00230 if (maxerror < 1.0E-06) break; 00231 } 00232 00233 int status = 0; 00234 for (size_t i = 0; i < numfaces; i++) 00235 { 00236 Face *face = mesh->getFaceAt(i); 00237 if (face->isVisited() && face->concaveAt() >= 0) 00238 { 00239 status = 1; 00240 break; 00241 } 00242 } 00243 00244 /* 00245 if (!relexist0) mesh->clear_relations(0, 0); 00246 if (!relexist2) mesh->clear_relations(0, 2); 00247 */ 00248 00249 return status; 00250 } 00251 00253 00254 int 00255 LaplaceSmoothing::convexify() 00256 { 00257 if (mesh->isHomogeneous() != 4) return 1; 00258 assert( mesh->isPruned() ); 00259 00260 int relexist0 = mesh->build_relations(0, 0); 00261 int relexist2 = mesh->build_relations(0, 2); 00262 00263 size_t numnodes = mesh->getSize(0); 00264 size_t numfaces = mesh->getSize(2); 00265 00266 facearea.resize(numfaces); 00267 for (size_t i = 0; i < numfaces; i++) 00268 { 00269 Face *face = mesh->getFaceAt(i); 00270 face->setID(i); // Needed because of facearea is an external array... 00271 facearea[i] = face->getArea(); 00272 } 00273 00274 NodeSequence fixnodes; 00275 double r = 0.5; 00276 00277 size_t ncount = 0; 00278 for (size_t iface = 0; iface < numfaces; iface++) 00279 { 00280 Face *face = mesh->getFaceAt(iface); 00281 int pos = face->concaveAt(); 00282 if (pos >= 0) 00283 { 00284 Vertex *v0 = face->getNodeAt((pos + 0) % 4); 00285 if (!v0->isBoundary()) 00286 { 00287 ncount++; 00288 fixnodes.clear(); 00289 // Constrained the face nodes .. 00290 for (int j = 0; j < face->getSize(0); j++) 00291 { 00292 Vertex *vertex = mesh->getNodeAt(j); 00293 if (!vertex->isConstrained()) 00294 { 00295 vertex->setConstrainedMark(1); 00296 fixnodes.push_back(vertex); 00297 } 00298 } 00299 00300 Vertex *v1 = face->getNodeAt((pos + 1) % 4); 00301 Vertex *v2 = face->getNodeAt((pos + 2) % 4); 00302 Vertex *v3 = face->getNodeAt((pos + 3) % 4); 00303 00304 Point3D pm ; 00305 Vertex::mid_point(v1, v3, pm, r); 00306 Point3D newpos = displace( pm, v2->getXYZCoords(), 1.0001); 00307 00308 v0->setXYZCoords(newpos); 00309 00310 // Upate the remaining nodes... 00311 for (size_t i = 0; i < numnodes; i++) 00312 update_vertex_position(mesh->getNodeAt(i)); 00313 // unconstrained the face nodes .. 00314 for (size_t j = 0; j < fixnodes.size(); j++) 00315 fixnodes[j]->setConstrainedMark(0); 00316 } 00317 } 00318 } 00319 00320 if (ncount) { 00321 cout << "#of Concave faces " << ncount << endl; 00322 global_smoothing(); 00323 } 00324 00325 if (!relexist0) mesh->clear_relations(0, 0); 00326 if (!relexist2) mesh->clear_relations(0, 2); 00327 00328 ncount = mesh->count_concave_faces(); 00329 00330 if (ncount) 00331 { 00332 cout << "Warning: Laplacian could not eliminate concave faces " << ncount << endl; 00333 return 1; 00334 } 00335 return 0; 00336 } 00337 00339 00340 00341 00342 /* 00343 double 00344 LaplaceSmoothing::angle_based_update (const LVertex &lnode) 00345 { 00346 // 00347 // Presently this works only for 2D case where z = 0.0; 00348 // 00349 Vertex *vertex = lnode.apex; 00350 if (vertex->isConstrained ()) return 0.0; 00351 00352 map<Vertex*, vector<Vertex*> >::const_iterator it; 00353 Point3D p0 = vertex->getXYZCoords (); 00354 double x = p0[0]; 00355 double y = p0[1]; 00356 double xsum = 0.0; 00357 double ysum = 0.0; 00358 for (it = lnode.neighs.begin (); it != lnode.neighs.end (); ++it) 00359 { 00360 Vertex *v1 = it->first; 00361 vector<Vertex*> vneighs = it->second; 00362 assert (vneighs.size () == 2); 00363 Point3D pj = v1->getXYZCoords (); 00364 Point3D pp = vneighs[0]->getXYZCoords (); // Right side of pj 00365 Point3D pm = vneighs[1]->getXYZCoords (); // Left side of pj 00366 Vec3D vec0 = Math::create_vector (p0, pj); 00367 Vec3D vec1 = Math::create_vector (pp, pj); 00368 Vec3D vec2 = Math::create_vector (pm, pj); 00369 double a1 = Math::getVectorAngle (vec0, vec1, ANGLE_IN_RADIANS); 00370 double b1 = Math::getVectorAngle (vec0, vec2, ANGLE_IN_RADIANS); 00371 double t = 0.5 * (b1 - a1); 00372 double x0 = pj[0]; 00373 double y0 = pj[1]; 00374 double xn = x0 + (x - x0) * cos (t) - (y - y0) * sin (t); 00375 double yn = y0 + (x - x0) * sin (t) + (y - y0) * cos (t); 00376 xsum += xn; 00377 ysum += xn; 00378 } 00379 int nsize = lnode.neighs.size (); 00380 Point3D newpos; 00381 newpos[0] = xsum / (double) nsize; 00382 newpos[1] = ysum / (double) nsize; 00383 newpos[2] = 0.0; 00384 return update_vertex_position (vertex, newpos); 00385 } 00386 00388 00389 void 00390 LaplaceSmoothing::build_angle_based_neighbors () 00391 { 00392 size_t numnodes = mesh->getSize (0); 00393 lnodes.clear (); 00394 lnodes.reserve(numnodes); 00395 LVertex lnode; 00396 for (size_t inode = 0; inode < numnodes; inode++) 00397 { 00398 Vertex *vertex = mesh->getNodeAt (inode); 00399 if (!vertex->isBoundary ()) 00400 { 00401 lnode.apex = vertex; 00402 lnode.neighs.clear(); 00403 vector<Face*> vfaces = vertex->getRelations2 (); 00404 for (size_t j = 0; j < vfaces.size (); j++) 00405 { 00406 Face *face = vfaces[j]; 00407 int pos = face->queryPosOf (vertex); 00408 Vertex *v1 = face->getNodeAt ((pos + 1) % 4); 00409 Vertex *v2 = face->getNodeAt ((pos + 2) % 4); 00410 Vertex *v3 = face->getNodeAt ((pos + 3) % 4); 00411 lnode.neighs[v1].push_back (v2); 00412 lnode.neighs[v2].push_back (v1); 00413 lnode.neighs[v3].push_back (v2); 00414 lnode.neighs[v2].push_back (v3); 00415 } 00416 lnodes.push_back (lnode); 00417 } 00418 } 00419 } 00420 */ 00421