MeshKit  1.0
laplace.cpp
Go to the documentation of this file.
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines