moab
SmoothFace.cpp
Go to the documentation of this file.
00001 #include <iostream>
00002 #include <fstream>
00003 #include "SmoothFace.hpp"
00004 
00005 #include <algorithm>
00006 #include <iomanip>
00007 
00008 #include "assert.h"
00009 // included in the header now
00010 // #include "Range.hpp"
00011 // #include "CartVect.hpp"
00012 
00013 // some defines from CUBIT
00014 #define GEOMETRY_RESABS 1.e-6
00015 #define CUBIT_DBL_MAX 1.e+30
00016 //#define DBL_EPSILON  1.e-8
00017 #include <float.h>
00018 
00019 namespace moab {
00020 
00021 bool within_tolerance(CartVect & p1, CartVect & p2, const double & tolerance)
00022 {
00023   if ((fabs(p1[0] - p2[0]) < tolerance) && (fabs(p1[1] - p2[1]) < tolerance)
00024       && (fabs(p1[2] - p2[2]) < tolerance))
00025     return true;
00026   return false;
00027 }
00028 int numAdjTriInSet(Interface * mb, EntityHandle startEdge, EntityHandle set)
00029 {
00030   std::vector<EntityHandle> adjTri;
00031   mb->get_adjacencies(&startEdge, 1, 2, false, adjTri, Interface::UNION);
00032   // count how many are in the set
00033   int nbInSet = 0;
00034   for (size_t i = 0; i < adjTri.size(); i++)
00035   {
00036     EntityHandle tri = adjTri[i];
00037     if (mb->contains_entities(set, &tri, 1))
00038       nbInSet++;
00039   }
00040   return nbInSet;
00041 }
00042 
00043 bool debug_surf_eval1 = false;
00044 
00045 SmoothFace::SmoothFace(Interface * mb, EntityHandle surface_set,
00046     GeomTopoTool * gTool) :
00047   _mb(mb), _set(surface_set), _my_geomTopoTool(gTool), _evaluationsCounter(0)
00048 {
00049   //_smooth_face = NULL;
00050   //_mbOut->create_meshset(MESHSET_SET, _oSet); //will contain the
00051   // get also the obb_root
00052   if (_my_geomTopoTool)
00053   {
00054     _my_geomTopoTool->get_root(this->_set, _obb_root);
00055     if (debug_surf_eval1)
00056       _my_geomTopoTool->obb_tree()->stats(_obb_root, std::cout);
00057   }
00058 }
00059 
00060 SmoothFace::~SmoothFace()
00061 {
00062 }
00063 
00064 double SmoothFace::area()
00065 {
00066   // find the area of this entity
00067   //assert(_smooth_face);
00068   //double area1 = _smooth_face->area();
00069   double totArea = 0.;
00070   for (Range::iterator it = _triangles.begin(); it != _triangles.end(); it++)
00071   {
00072     EntityHandle tria = *it;
00073     const EntityHandle * conn3;
00074     int nnodes;
00075     _mb->get_connectivity(tria, conn3, nnodes);
00076     //
00077     //double coords[9]; // store the coordinates for the nodes
00078     //_mb->get_coords(conn3, 3, coords);
00079     CartVect p[3];
00080     _mb->get_coords(conn3, 3, (double*) &p[0]);
00081     // need to compute the angles
00082     // compute angles and the normal
00083     //CartVect p1(&coords[0]), p2(&coords[3]), p3(&coords[6]);
00084 
00085     CartVect AB(p[1] - p[0]);//(p2 - p1);
00086     CartVect BC(p[2] - p[1]);//(p3 - p2);
00087     CartVect normal = AB * BC;
00088     totArea += normal.length() / 2;
00089   }
00090   return totArea;
00091 }
00092 // these tags will be collected for deletion
00093 void SmoothFace::append_smooth_tags(std::vector<Tag> & smoothTags)
00094 {
00095   // these are created locally, for each smooth face
00096   smoothTags.push_back(_gradientTag);
00097   smoothTags.push_back(_planeTag);
00098 
00099 }
00100 void SmoothFace::bounding_box(double box_min[3], double box_max[3])
00101 {
00102 
00103   for (int i = 0; i < 3; i++)
00104   {
00105     box_min[i] = _minim[i];
00106     box_max[i] = _maxim[i];
00107   }
00108   // _minim, _maxim
00109 }
00110 
00111 void SmoothFace::move_to_surface(double& x, double& y, double& z)
00112 {
00113 
00114   CartVect loc2(x, y, z);
00115   bool trim = false;// is it needed?
00116   bool outside = true;
00117   CartVect closestPoint;
00118 
00119   ErrorCode rval = project_to_facets_main(loc2, trim, outside, &closestPoint,
00120       NULL);
00121   if (MB_SUCCESS != rval) return;
00122   assert(rval==MB_SUCCESS);
00123   x = closestPoint[0];
00124   y = closestPoint[1];
00125   z = closestPoint[2];
00126 
00127 }
00128 /*
00129  void SmoothFace::move_to_surface(double& x, double& y, double& z,
00130  double& u_guess, double& v_guess) {
00131  if (debug_surf_eval1) {
00132  std::cout << "move_to_surface called." << std::endl;
00133  }
00134  }*/
00135 
00136 bool SmoothFace::normal_at(double x, double y, double z, double& nx,
00137     double& ny, double& nz)
00138 {
00139 
00140   CartVect loc2(x, y, z);
00141 
00142   bool trim = false;// is it needed?
00143   bool outside = true;
00144   //CartVect closestPoint;// not needed
00145   // not interested in normal
00146   CartVect normal;
00147   ErrorCode rval = project_to_facets_main(loc2, trim, outside, NULL, &normal);
00148   if (MB_SUCCESS != rval) return false;
00149   assert(rval==MB_SUCCESS);
00150   nx = normal[0];
00151   ny = normal[1];
00152   nz = normal[2];
00153 
00154   return true;
00155 }
00156 
00157 ErrorCode SmoothFace::compute_control_points_on_edges(double min_dot,
00158     Tag edgeCtrlTag, Tag markTag)
00159 {
00160 
00161   _edgeCtrlTag = edgeCtrlTag;
00162   _markTag = markTag;
00163 
00164   // now, compute control points for all edges that are not marked already (they are no on the boundary!)
00165   for (Range::iterator it = _edges.begin(); it != _edges.end(); it++)
00166   {
00167     EntityHandle edg = *it;
00168     // is the edge marked? already computed
00169     unsigned char tagVal = 0;
00170     _mb->tag_get_data(_markTag, &edg, 1, &tagVal);
00171     if (tagVal)
00172       continue;
00173     //double min_dot;
00174     init_bezier_edge(edg, min_dot);
00175     tagVal = 1;
00176     _mb->tag_set_data(_markTag, &edg, 1, &tagVal);
00177   }
00178   return MB_SUCCESS;
00179 }
00180 
00181 int SmoothFace::init_gradient()
00182 {
00183   // first, create a Tag for gradient (or normal)
00184   // loop over all triangles in set, and modify the normals according to the angle as weight
00185   // get all the edges from this subset
00186   if (NULL == _mb)
00187     return 1; //fail
00188   _triangles.clear();
00189   ErrorCode rval = _mb->get_entities_by_type(_set, MBTRI, _triangles);
00190   if (MB_SUCCESS != rval)
00191     return 1;
00192   // get a new range of edges, and decide the loops from here
00193   _edges.clear();
00194   rval = _mb-> get_adjacencies(_triangles, 1, true, _edges, Interface::UNION);
00195   assert(rval == MB_SUCCESS);
00196 
00197   rval = _mb->get_adjacencies(_triangles, 0, false, _nodes, Interface::UNION);
00198   assert(rval == MB_SUCCESS);
00199 
00200   // initialize bounding box limits
00201   CartVect vert1;
00202   EntityHandle v1 = _nodes[0];// first vertex
00203   _mb->get_coords(&v1, 1, (double*) &vert1);
00204   _minim = vert1;
00205   _maxim = vert1;
00206 
00207   double defNormal[] = { 0., 0., 0. };
00208   // look for a tag name here that is definitely unique. We do not want the tags to interfere with each other
00209   // this normal will be for each node in a face
00210   // some nodes have multiple normals, if they are at the feature edges
00211   unsigned long setId = _mb->id_from_handle(_set);
00212   char name[50] = { 0 };
00213   sprintf(name, "GRADIENT%ld", setId);// name should be something like GRADIENT29, where 29 is the set ID of the face
00214   rval = _mb->tag_get_handle(name, 3, MB_TYPE_DOUBLE, _gradientTag,
00215       MB_TAG_DENSE|MB_TAG_CREAT, &defNormal);
00216 
00217   double defPlane[4] = { 0., 0., 1., 0. };
00218   // also define a plane tag ; this will be for each triangle
00219   char namePlaneTag[50] = { 0 };
00220   sprintf(namePlaneTag, "PLANE%ld", setId);
00221   rval = _mb->tag_get_handle("PLANE", 4, MB_TYPE_DOUBLE, _planeTag,
00222       MB_TAG_DENSE|MB_TAG_CREAT, &defPlane);
00223   // the fourth double is for weight, accumulated at each vertex so far
00224   // maybe not needed in the end
00225   for (Range::iterator it = _triangles.begin(); it != _triangles.end(); it++)
00226   {
00227     EntityHandle tria = *it;
00228     const EntityHandle * conn3;
00229     int nnodes;
00230     _mb->get_connectivity(tria, conn3, nnodes);
00231     if (nnodes != 3)
00232       return 1; // error
00233     //double coords[9]; // store the coordinates for the nodes
00234     //_mb->get_coords(conn3, 3, coords);
00235     CartVect p[3];
00236     _mb->get_coords(conn3, 3, (double*) &p[0]);
00237     // need to compute the angles
00238     // compute angles and the normal
00239     //CartVect p1(&coords[0]), p2(&coords[3]), p3(&coords[6]);
00240 
00241     CartVect AB(p[1] - p[0]);//(p2 - p1);
00242     CartVect BC(p[2] - p[1]);//(p3 - p2);
00243     CartVect CA(p[0] - p[2]);//(p1 - p3);
00244     double a[3];
00245     a[1] = angle(AB, -BC); // angle at B (p2), etc.
00246     a[2] = angle(BC, -CA);
00247     a[0] = angle(CA, -AB);
00248     CartVect normal = -AB * CA;
00249     normal.normalize();
00250     double plane[4];
00251 
00252     const double * coordNormal = normal.array();
00253 
00254     plane[0] = coordNormal[0];
00255     plane[1] = coordNormal[1];
00256     plane[2] = coordNormal[2];
00257     plane[3] = -normal % p[0]; // dot product
00258     //set the plane
00259     rval = _mb->tag_set_data(_planeTag, &tria, 1, plane);
00260     assert(rval == MB_SUCCESS);
00261 
00262     // add to each vertex the tag value the normal multiplied by the angle
00263     double values[9];
00264 
00265     _mb->tag_get_data(_gradientTag, conn3, 3, values);
00266     for (int i = 0; i < 3; i++)
00267     {
00268       //values[4*i]+=a[i]; // first is the weight, which we do not really need
00269       values[3 * i + 0] += a[i] * coordNormal[0];
00270       values[3 * i + 1] += a[i] * coordNormal[1];
00271       values[3 * i + 2] += a[i] * coordNormal[2];
00272     }
00273 
00274     // reset those values
00275     _mb->tag_set_data(_gradientTag, conn3, 3, values);
00276 
00277   }
00278   // normalize the gradients at each node; maybe not needed here?
00279   // no, we will do it, it is important
00280   int numNodes = _nodes.size();
00281   double * normalVal = new double[3 * numNodes];
00282   _mb->tag_get_data(_gradientTag, _nodes, normalVal);// get all the normal values at the _nodes
00283   for (int i = 0; i < numNodes; i++)
00284   {
00285     CartVect p1(&normalVal[3 * i]);
00286     p1.normalize();
00287     p1.get(&normalVal[3 * i]);
00288   }
00289 
00290   // reset the normal values after normalization
00291   _mb->tag_set_data(_gradientTag, _nodes, normalVal);
00292   // print the loops size and some other stuff
00293   if (debug_surf_eval1)
00294   {
00295     std::cout << " normals at  " << numNodes << " nodes" << std::endl;
00296     int i = 0;
00297     for (Range::iterator it = _nodes.begin(); it != _nodes.end(); it++, i++)
00298     {
00299       EntityHandle node = *it;
00300       std::cout << " Node id " << _mb->id_from_handle(node) << "  "
00301           << normalVal[3 * i] << " " << normalVal[3 * i + 1] << " "
00302           << normalVal[3 * i + 2] << std::endl;
00303     }
00304   }
00305 
00306   delete[] normalVal;
00307 
00308   return 0;
00309 }
00310 
00311 // init bezier edges
00312 // start copy
00313 //===========================================================================
00314 //Function Name: init_bezier_edge
00315 //
00316 //Member Type:  PRIVATE
00317 //Description:  compute the control points for an edge
00318 //===========================================================================
00319 ErrorCode SmoothFace::init_bezier_edge(EntityHandle edge, double )
00320 {
00321   // min dot was used for angle here
00322   //int stat = 0; // CUBIT_SUCCESS;
00323   // all boundaries will be simple, initially
00324   // we may complicate them afterwards
00325 
00326   CartVect ctrl_pts[3];
00327   int nnodes;
00328   const EntityHandle * conn2;
00329   ErrorCode rval = _mb->get_connectivity(edge, conn2, nnodes);
00330   assert(rval == MB_SUCCESS);
00331   if (MB_SUCCESS != rval) return rval;
00332   
00333   assert(2 == nnodes);
00334   //double coords[6]; // store the coordinates for the nodes
00335   CartVect P[2];
00336   //ErrorCode rval = _mb->get_coords(conn2, 2, coords);
00337   rval = _mb->get_coords(conn2, 2, (double*) &P[0]);
00338   assert(rval == MB_SUCCESS);
00339   if (MB_SUCCESS != rval) return rval;
00340 
00341   //CartVect P0(&coords[0]);
00342   //CartVect P3(&coords[3]);
00343 
00344   //double normalVec[6];
00345   CartVect N[2];
00346   //_mb->tag_get_data(_gradientTag, conn2, 2, normalVec);
00347   rval = _mb->tag_get_data(_gradientTag, conn2, 2, (double*) &N[0]);
00348   assert(rval == MB_SUCCESS);
00349   if (MB_SUCCESS != rval) return rval;
00350 
00351   CartVect T[2]; // T0, T3
00352 
00353   rval = _mb->tag_get_data(_tangentsTag, &edge, 1, &T[0]);
00354   assert(rval == MB_SUCCESS);
00355   if (MB_SUCCESS != rval) return rval;
00356 
00357   rval = init_edge_control_points(P[0], P[1], N[0], N[1], T[0], T[1], ctrl_pts);
00358   assert(rval == MB_SUCCESS);
00359   if (MB_SUCCESS != rval) return rval;
00360 
00361   rval = _mb->tag_set_data(_edgeCtrlTag, &edge, 1, &ctrl_pts[0]);
00362   assert(rval == MB_SUCCESS);
00363   if (MB_SUCCESS != rval) return rval;
00364 
00365   if (debug_surf_eval1)
00366   {
00367     std::cout << "edge: " << _mb-> id_from_handle(edge) << " tangents: "
00368         << T[0] << T[1] << std::endl;
00369     std::cout << "  points: " << P[0] << " " << P[1] << std::endl;
00370     std::cout << "  normals: " << N[0] << " " << N[1] << std::endl;
00371     std::cout << "  Control points  " << ctrl_pts[0] << " " << ctrl_pts[1]
00372         << " " << ctrl_pts[2] << std::endl;
00373   }
00374 
00375   return MB_SUCCESS;
00376 }
00377 
00378 ErrorCode SmoothFace::compute_tangents_for_each_edge()
00379 // they will be used for control points
00380 {
00381   double defTangents[6] = { 0., 0., 0., 0., 0., 0. };
00382   ErrorCode rval = _mb->tag_get_handle("TANGENTS", 6, MB_TYPE_DOUBLE,
00383       _tangentsTag, MB_TAG_DENSE|MB_TAG_CREAT, &defTangents);
00384   if (MB_SUCCESS != rval)
00385     return MB_FAILURE;
00386 
00387   // now, compute Tangents for all edges that are not on boundary, so they are not marked
00388   for (Range::iterator it = _edges.begin(); it != _edges.end(); it++)
00389   {
00390     EntityHandle edg = *it;
00391 
00392     int nnodes;
00393     const EntityHandle * conn2;//
00394     _mb->get_connectivity(edg, conn2, nnodes);
00395     assert(nnodes == 2);
00396     CartVect P[2]; // store the coordinates for the nodes
00397     rval = _mb->get_coords(conn2, 2, (double *) &P[0]);
00398     if (MB_SUCCESS != rval) return rval;
00399     assert(rval==MB_SUCCESS);
00400     CartVect T[2];
00401     T[0] = P[1] - P[0];
00402     T[0].normalize();
00403     T[1] = T[0]; //
00404     _mb->tag_set_data(_tangentsTag, &edg, 1, (double*) &T[0]);// set the tangents computed at every edge
00405   }
00406   return MB_SUCCESS;
00407 }
00408 // start copy
00409 //===========================================================================
00410 //Function Name: init_edge_control_points
00411 //
00412 //Member Type:  PRIVATE
00413 //Description:  compute the control points for an edge
00414 //===========================================================================
00415 ErrorCode SmoothFace::init_edge_control_points(CartVect &P0, CartVect &P3,
00416     CartVect &N0, CartVect &N3, CartVect &T0, CartVect &T3, CartVect * Pi)
00417 {
00418   CartVect Vi[4];
00419   Vi[0] = P0;
00420   Vi[3] = P3;
00421   CartVect P03(P3 - P0);
00422   double di = P03.length();
00423   double ai = N0 % N3;// this is the dot operator, the same as in cgm for CubitVector
00424   double ai0 = N0 % T0;
00425   double ai3 = N3 % T3;
00426   double denom = 4 - ai * ai;
00427   if (fabs(denom) < 1e-20)
00428   {
00429     return MB_FAILURE; // CUBIT_FAILURE;
00430   }
00431   double row = 6.0e0 * (2.0e0 * ai0 + ai * ai3) / denom;
00432   double omega = 6.0e0 * (2.0e0 * ai3 + ai * ai0) / denom;
00433   Vi[1] = Vi[0] + (di * (((6.0e0 * T0) - ((2.0e0 * row) * N0) + (omega * N3))
00434       / 18.0e0));
00435   Vi[2] = Vi[3] - (di * (((6.0e0 * T3) + (row * N0) - ((2.0e0 * omega) * N3))
00436       / 18.0e0));
00437   CartVect Wi[3];
00438   Wi[0] = Vi[1] - Vi[0];
00439   Wi[1] = Vi[2] - Vi[1];
00440   Wi[2] = Vi[3] - Vi[2];
00441 
00442   Pi[0] = 0.25 * Vi[0] + 0.75 * Vi[1];
00443   Pi[1] = 0.50 * Vi[1] + 0.50 * Vi[2];
00444   Pi[2] = 0.75 * Vi[2] + 0.25 * Vi[3];
00445 
00446   return MB_SUCCESS;
00447 }
00448 
00449 ErrorCode SmoothFace::find_edges_orientations(EntityHandle edges[3],
00450     const EntityHandle * conn3, int orient[3])// maybe we will set it?
00451 {
00452   // find the edge that is adjacent to 2 vertices at a time
00453   for (int i = 0; i < 3; i++)
00454   {
00455     // edge 0 is 1-2, 1 is 3-1, 2 is 0-1
00456     EntityHandle v[2];
00457     v[0] = conn3[(i + 1) % 3];
00458     v[1] = conn3[(i + 2) % 3];
00459     std::vector<EntityHandle> adjacencies;
00460     // generate all edges for these two hexes
00461     ErrorCode rval = _mb->get_adjacencies(v, 2, 1, false, adjacencies,
00462                                           Interface::INTERSECT);
00463     if (MB_SUCCESS != rval) return rval;
00464 
00465     // find the edge connected to both vertices, and then see its orientation
00466     assert(adjacencies.size() == 1);
00467     const EntityHandle * conn2;
00468     int nnodes;
00469     rval = _mb->get_connectivity(adjacencies[0], conn2, nnodes);
00470     assert(rval == MB_SUCCESS);
00471     assert(2 == nnodes);
00472     edges[i] = adjacencies[0];
00473     // what is the story morning glory?
00474     if (conn2[0] == v[0] && conn2[1] == v[1])
00475       orient[i] = 1;
00476     else if (conn2[0] == v[1] && conn2[1] == v[0])
00477       orient[i] = -1;
00478     else
00479       return MB_FAILURE;
00480   }
00481   return MB_SUCCESS;
00482 }
00483 ErrorCode SmoothFace::compute_internal_control_points_on_facets(double ,
00484     Tag facetCtrlTag, Tag facetEdgeCtrlTag)
00485 {
00486   // collect from each triangle the control points in order
00487   //
00488 
00489   _facetCtrlTag = facetCtrlTag;
00490   _facetEdgeCtrlTag = facetEdgeCtrlTag;
00491 
00492   for (Range::iterator it = _triangles.begin(); it != _triangles.end(); it++)
00493   {
00494     EntityHandle tri = *it;
00495     // first get connectivity, and the edges
00496     // we need a fast method to retrieve the adjacent edges to each triangle
00497     const EntityHandle * conn3;
00498     int nnodes;
00499     ErrorCode rval = _mb->get_connectivity(tri, conn3, nnodes);
00500     assert(MB_SUCCESS == rval);
00501     if (MB_SUCCESS != rval) return rval;
00502     assert(3 == nnodes);
00503 
00504     // would it be easier to do
00505     CartVect vNode[3];// position at nodes
00506     rval = _mb->get_coords(conn3, 3, (double*) &vNode[0]);
00507     assert(MB_SUCCESS == rval);
00508     if (MB_SUCCESS != rval) return rval;
00509 
00510     // get gradients (normal) at each node of triangle
00511     CartVect NN[3];
00512     rval = _mb->tag_get_data(_gradientTag, conn3, 3, &NN[0]);
00513     assert(MB_SUCCESS == rval);
00514     if (MB_SUCCESS != rval) return rval;
00515 
00516     EntityHandle edges[3];
00517     int orient[3]; // + 1 or -1, if the edge is positive or negative within the face
00518     rval = find_edges_orientations(edges, conn3, orient);// maybe we will set it?
00519     assert(MB_SUCCESS == rval);
00520     if (MB_SUCCESS != rval) return rval;
00521     // maybe we will store some tags with edges and their orientation with respect to
00522     // a triangle;
00523     CartVect P[3][5];
00524     CartVect N[6], G[6];
00525     // create the linear array for control points on edges, for storage (expensive !!!)
00526     CartVect CP[9];
00527     int index = 0;
00528     // maybe store a tag / entity handle for edges?
00529     for (int i = 0; i < 3; i++)
00530     {
00531       // populate P and N with the right vectors
00532       int i1 = (i + 1) % 3; // the first node of the edge
00533       int i2 = (i + 2) % 3; // the second node of the edge
00534       N[2 * i] = NN[i1];
00535       N[2 * i + 1] = NN[i2];
00536       P[i][0] = vNode[i1];
00537       rval = _mb->tag_get_data(_edgeCtrlTag, &edges[i], 1, &(P[i][1]));
00538       // if sense is -1, swap 1 and 3 control points
00539       if (orient[i] == -1)
00540       {
00541         CartVect tmp;
00542         tmp = P[i][1];
00543         P[i][1] = P[i][3];
00544         P[i][3] = tmp;
00545       }
00546       P[i][4] = vNode[i2];
00547       for (int j = 1; j < 4; j++)
00548         CP[index++] = P[i][j];
00549 
00550       // the first edge control points
00551     }
00552 
00553     //  stat = facet->get_edge_control_points( P );
00554     init_facet_control_points(N, P, G);
00555     // what do we need to store in the tag control points?
00556     rval = _mb->tag_set_data(_facetCtrlTag, &tri, 1, &G[0]);
00557     assert(MB_SUCCESS == rval);
00558     if (MB_SUCCESS != rval) return rval;
00559 
00560     // store here again the 9 control points on the edges
00561     rval = _mb->tag_set_data(_facetEdgeCtrlTag, &tri, 1, &CP[0]);
00562     assert(MB_SUCCESS == rval);
00563     if (MB_SUCCESS != rval) return rval;
00564     // look at what we retrieve later
00565 
00566     // adjust the bounding box
00567     int j = 0;
00568     for (j = 0; j < 3; j++)
00569       adjust_bounding_box(vNode[j]);
00570     // edge control points
00571     for (j = 0; j < 9; j++)
00572       adjust_bounding_box(CP[j]);
00573     // internal facet control points
00574     for (j = 0; j < 6; j++)
00575       adjust_bounding_box(G[j]);
00576 
00577   }
00578   return MB_SUCCESS;
00579 }
00580 void SmoothFace::adjust_bounding_box(CartVect & vect)
00581 {
00582   // _minim, _maxim
00583   for (int j = 0; j < 3; j++)
00584   {
00585     if (_minim[j] > vect[j])
00586       _minim[j] = vect[j];
00587     if (_maxim[j] < vect[j])
00588       _maxim[j] = vect[j];
00589   }
00590 }
00591 //===============================================================
00597 ErrorCode SmoothFace::init_facet_control_points(CartVect N[6], // vertex normals (per edge)
00598     CartVect P[3][5], // edge control points
00599     CartVect G[6]) // return internal control points
00600 {
00601   CartVect Di[4], Ai[3], N0, N3, Vi[4], Wi[3];
00602   double denom;
00603   double lambda[2], mu[2];
00604 
00605   ErrorCode rval = MB_SUCCESS;
00606 
00607   for (int i = 0; i < 3; i++)
00608   {
00609     N0 = N[i * 2];
00610     N3 = N[i * 2 + 1];
00611     Vi[0] = P[i][0];
00612     Vi[1] = (P[i][1] - 0.25 * P[i][0]) / 0.75;
00613     Vi[2] = (P[i][3] - 0.25 * P[i][4]) / 0.75;
00614     Vi[3] = P[i][4];
00615     Wi[0] = Vi[1] - Vi[0];
00616     Wi[1] = Vi[2] - Vi[1];
00617     Wi[2] = Vi[3] - Vi[2];
00618     Di[0] = P[(i + 2) % 3][3] - 0.5 * (P[i][1] + P[i][0]);
00619     Di[3] = P[(i + 1) % 3][1] - 0.5 * (P[i][4] + P[i][3]);
00620     Ai[0] = (N0 * Wi[0]) / Wi[0].length();
00621     Ai[2] = (N3 * Wi[2]) / Wi[2].length();
00622     Ai[1] = Ai[0] + Ai[2];
00623     denom = Ai[1].length();
00624     Ai[1] /= denom;
00625     lambda[0] = (Di[0] % Wi[0]) / (Wi[0] % Wi[0]);
00626     lambda[1] = (Di[3] % Wi[2]) / (Wi[2] % Wi[2]);
00627     mu[0] = (Di[0] % Ai[0]);
00628     mu[1] = (Di[3] % Ai[2]);
00629     G[i * 2] = 0.5 * (P[i][1] + P[i][2]) + 0.66666666666666 * lambda[0] * Wi[1]
00630         + 0.33333333333333 * lambda[1] * Wi[0] + 0.66666666666666 * mu[0]
00631         * Ai[1] + 0.33333333333333 * mu[1] * Ai[0];
00632     G[i * 2 + 1] = 0.5 * (P[i][2] + P[i][3]) + 0.33333333333333 * lambda[0]
00633         * Wi[2] + 0.66666666666666 * lambda[1] * Wi[1] + 0.33333333333333
00634         * mu[0] * Ai[2] + 0.66666666666666 * mu[1] * Ai[1];
00635   }
00636   return rval;
00637 }
00638 
00639 void SmoothFace::DumpModelControlPoints()
00640 {
00641   // here, we will dump all control points from edges and facets (6 control points for each facet)
00642   // we may also create some edges; maybe later...
00643   // create a point3D file
00644   // output a Point3D file (special visit format)
00645   unsigned long setId = _mb->id_from_handle(_set);
00646   char name[50] = { 0 };
00647   sprintf(name, "%ldcontrol.Point3D", setId);// name should be something 2control.Point3D
00648   std::ofstream point3DFile;
00649   point3DFile.open(name);//("control.Point3D");
00650   point3DFile << "# x y z \n";
00651   std::ofstream point3DEdgeFile;
00652   sprintf(name, "%ldcontrolEdge.Point3D", setId);//
00653   point3DEdgeFile.open(name);//("controlEdge.Point3D");
00654   point3DEdgeFile << "# x y z \n";
00655   std::ofstream smoothPoints;
00656   sprintf(name, "%ldsmooth.Point3D", setId);//
00657   smoothPoints.open(name);//("smooth.Point3D");
00658   smoothPoints << "# x y z \n";
00659   CartVect controlPoints[3]; // edge control points
00660   for (Range::iterator it = _edges.begin(); it != _edges.end(); it++)
00661   {
00662     EntityHandle edge = *it;
00663 
00664     _mb->tag_get_data(_edgeCtrlTag, &edge, 1, (double*) &controlPoints[0]);
00665     for (int i = 0; i < 3; i++)
00666     {
00667       CartVect & c = controlPoints[i];
00668       point3DEdgeFile << std::setprecision(11) << c[0] << " " << c[1] << " "
00669           << c[2] << " \n";
00670     }
00671   }
00672   CartVect controlTriPoints[6]; // triangle control points
00673   CartVect P_facet[3];// result in 3 "mid" control points
00674   for (Range::iterator it2 = _triangles.begin(); it2 != _triangles.end(); it2++)
00675   {
00676     EntityHandle tri = *it2;
00677 
00678     _mb->tag_get_data(_facetCtrlTag, &tri, 1, (double*) &controlTriPoints[0]);
00679 
00680     // draw a line of points between pairs of control points
00681     int numPoints = 7;
00682     for (int n = 0; n < numPoints; n++)
00683     {
00684       double a = 1. * n / (numPoints - 1);
00685       double b = 1.0 - a;
00686 
00687       P_facet[0] = a * controlTriPoints[3] + b * controlTriPoints[4];
00688       //1,2,1
00689       P_facet[1] = a * controlTriPoints[0] + b * controlTriPoints[5];
00690       //1,1,2
00691       P_facet[2] = a * controlTriPoints[1] + b * controlTriPoints[2];
00692       for (int i = 0; i < 3; i++)
00693       {
00694         CartVect & c = P_facet[i];
00695         point3DFile << std::setprecision(11) << c[0] << " " << c[1] << " "
00696             << c[2] << " \n";
00697       }
00698     }
00699 
00700     // evaluate for each triangle a lattice of points
00701     int N = 40;
00702     for (int k = 0; k <= N; k++)
00703     {
00704       for (int m = 0; m <= N - k; m++)
00705       {
00706         int n = N - m - k;
00707         CartVect areacoord(1. * k / N, 1. * m / N, 1. * n / N);
00708         CartVect pt;
00709         eval_bezier_patch(tri, areacoord, pt);
00710         smoothPoints << std::setprecision(11) << pt[0] << " " << pt[1] << " "
00711             << pt[2] << " \n";
00712 
00713       }
00714     }
00715   }
00716   point3DFile.close();
00717   smoothPoints.close();
00718   point3DEdgeFile.close();
00719   return;
00720 }
00721 //===========================================================================
00722 //Function Name: evaluate_single
00723 //
00724 //Member Type:  PUBLIC
00725 //Description:  evaluate edge not associated with a facet (this is used
00726 // by camal edge mesher!!!)
00727 //Note:         t is a value from 0 to 1, for us
00728 //===========================================================================
00729 ErrorCode SmoothFace::evaluate_smooth_edge(EntityHandle eh, double &tt,
00730     CartVect & outv)
00731 {
00732   CartVect P[2]; // P0 and P1
00733   CartVect controlPoints[3]; // edge control points
00734   double t4, t3, t2, one_minus_t, one_minus_t2, one_minus_t3, one_minus_t4;
00735 
00736   // project the position to the linear edge
00737   // t is from 0 to 1 only!!
00738   //double tt = (t + 1) * 0.5;
00739   if (tt <= 0.0)
00740     tt = 0.0;
00741   if (tt >= 1.0)
00742     tt = 1.0;
00743 
00744   int nnodes;
00745   const EntityHandle * conn2;
00746   ErrorCode rval = _mb->get_connectivity(eh, conn2, nnodes);
00747   assert(rval == MB_SUCCESS);
00748   if (MB_SUCCESS != rval) return rval;
00749 
00750   rval = _mb->get_coords(conn2, 2, (double*) &P[0]);
00751   assert(rval == MB_SUCCESS);
00752   if (MB_SUCCESS != rval) return rval;
00753 
00754   rval = _mb->tag_get_data(_edgeCtrlTag, &eh, 1, (double*) &controlPoints[0]);
00755   assert(rval == MB_SUCCESS);
00756   if (MB_SUCCESS != rval) return rval;
00757 
00758   t2 = tt * tt;
00759   t3 = t2 * tt;
00760   t4 = t3 * tt;
00761   one_minus_t = 1. - tt;
00762   one_minus_t2 = one_minus_t * one_minus_t;
00763   one_minus_t3 = one_minus_t2 * one_minus_t;
00764   one_minus_t4 = one_minus_t3 * one_minus_t;
00765 
00766   outv = one_minus_t4 * P[0] + 4. * one_minus_t3 * tt * controlPoints[0] + 6.
00767       * one_minus_t2 * t2 * controlPoints[1] + 4. * one_minus_t * t3
00768       * controlPoints[2] + t4 * P[1];
00769 
00770   return MB_SUCCESS;
00771 }
00772 
00773 ErrorCode SmoothFace::eval_bezier_patch(EntityHandle tri, CartVect &areacoord,
00774     CartVect &pt)
00775 {
00776   //
00777   // interpolate internal control points
00778 
00779   CartVect gctrl_pts[6];
00780   // get the control points  facet->get_control_points( gctrl_pts );
00781   //init_facet_control_points( N, P, G) ;
00782   // what do we need to store in the tag control points?
00783   ErrorCode rval = _mb->tag_get_data(_facetCtrlTag, &tri, 1, &gctrl_pts[0]);// get all 6 control points
00784   assert(MB_SUCCESS == rval);
00785   if (MB_SUCCESS != rval) return rval;
00786   const EntityHandle * conn3;
00787   int nnodes;
00788   rval = _mb->get_connectivity(tri, conn3, nnodes);
00789   assert(MB_SUCCESS == rval);
00790 
00791   CartVect vN[3];
00792   _mb->get_coords(conn3, 3, (double*) &vN[0]); // fill the coordinates of the vertices
00793 
00794   if (fabs(areacoord[1] + areacoord[2]) < 1.0e-6)
00795   {
00796     pt = vN[0];
00797     return MB_SUCCESS;
00798   }
00799   if (fabs(areacoord[0] + areacoord[2]) < 1.0e-6)
00800   {
00801     pt = vN[0];
00802     return MB_SUCCESS;
00803   }
00804   if (fabs(areacoord[0] + areacoord[1]) < 1.0e-6)
00805   {
00806     pt = vN[0];
00807     return MB_SUCCESS;
00808   }
00809 
00810   CartVect P_facet[3];
00811   //2,1,1
00812   P_facet[0] = (1.0e0 / (areacoord[1] + areacoord[2])) * (areacoord[1]
00813       * gctrl_pts[3] + areacoord[2] * gctrl_pts[4]);
00814   //1,2,1
00815   P_facet[1] = (1.0e0 / (areacoord[0] + areacoord[2])) * (areacoord[0]
00816       * gctrl_pts[0] + areacoord[2] * gctrl_pts[5]);
00817   //1,1,2
00818   P_facet[2] = (1.0e0 / (areacoord[0] + areacoord[1])) * (areacoord[0]
00819       * gctrl_pts[1] + areacoord[1] * gctrl_pts[2]);
00820 
00821   // sum the contribution from each of the control points
00822 
00823   pt = CartVect(0.);// set all to 0, we start adding / accumulating different parts
00824   // first edge is from node 0 to 1, index 2 in
00825 
00826   // retrieve the points, in order, and the control points on edges
00827 
00828   // store here again the 9 control points on the edges
00829   CartVect CP[9];
00830   rval = _mb->tag_get_data(_facetEdgeCtrlTag, &tri, 1, &CP[0]);
00831   assert(MB_SUCCESS == rval);
00832 
00833   //CubitFacetEdge *edge;
00834   //edge = facet->edge(2);! start with edge 2, from 0-1
00835   int k = 0;
00836   CartVect ctrl_pts[5];
00837   //edge->control_points(facet, ctrl_pts);
00838   ctrl_pts[0] = vN[0]; //
00839   for (k = 1; k < 4; k++)
00840     ctrl_pts[k] = CP[k + 5]; // for edge index 2
00841   ctrl_pts[4] = vN[1]; //
00842 
00843   //i=4; j=0; k=0;
00844   double B = quart(areacoord[0]);
00845   pt += B * ctrl_pts[0];
00846 
00847   //i=3; j=1; k=0;
00848   B = 4.0 * cube(areacoord[0]) * areacoord[1];
00849   pt += B * ctrl_pts[1];
00850 
00851   //i=2; j=2; k=0;
00852   B = 6.0 * sqr(areacoord[0]) * sqr(areacoord[1]);
00853   pt += B * ctrl_pts[2];
00854 
00855   //i=1; j=3; k=0;
00856   B = 4.0 * areacoord[0] * cube(areacoord[1]);
00857   pt += B * ctrl_pts[3];
00858 
00859   //edge = facet->edge(0);
00860   //edge->control_points(facet, ctrl_pts);
00861   // edge index 0, from 1 to 2
00862   ctrl_pts[0] = vN[1]; //
00863   for (k = 1; k < 4; k++)
00864     ctrl_pts[k] = CP[k - 1]; // for edge index 0
00865   ctrl_pts[4] = vN[2]; //
00866 
00867   //i=0; j=4; k=0;
00868   B = quart(areacoord[1]);
00869   pt += B * ctrl_pts[0];
00870 
00871   //i=0; j=3; k=1;
00872   B = 4.0 * cube(areacoord[1]) * areacoord[2];
00873   pt += B * ctrl_pts[1];
00874 
00875   //i=0; j=2; k=2;
00876   B = 6.0 * sqr(areacoord[1]) * sqr(areacoord[2]);
00877   pt += B * ctrl_pts[2];
00878 
00879   //i=0; j=1; k=3;
00880   B = 4.0 * areacoord[1] * cube(areacoord[2]);
00881   pt += B * ctrl_pts[3];
00882 
00883   //edge = facet->edge(1);
00884   //edge->control_points(facet, ctrl_pts);
00885   // edge index 1, from 2 to 0
00886   ctrl_pts[0] = vN[2]; //
00887   for (k = 1; k < 4; k++)
00888     ctrl_pts[k] = CP[k + 2]; // for edge index 0
00889   ctrl_pts[4] = vN[0]; //
00890 
00891   //i=0; j=0; k=4;
00892   B = quart(areacoord[2]);
00893   pt += B * ctrl_pts[0];
00894 
00895   //i=1; j=0; k=3;
00896   B = 4.0 * areacoord[0] * cube(areacoord[2]);
00897   pt += B * ctrl_pts[1];
00898 
00899   //i=2; j=0; k=2;
00900   B = 6.0 * sqr(areacoord[0]) * sqr(areacoord[2]);
00901   pt += B * ctrl_pts[2];
00902 
00903   //i=3; j=0; k=1;
00904   B = 4.0 * cube(areacoord[0]) * areacoord[2];
00905   pt += B * ctrl_pts[3];
00906 
00907   //i=2; j=1; k=1;
00908   B = 12.0 * sqr(areacoord[0]) * areacoord[1] * areacoord[2];
00909   pt += B * P_facet[0];
00910 
00911   //i=1; j=2; k=1;
00912   B = 12.0 * areacoord[0] * sqr(areacoord[1]) * areacoord[2];
00913   pt += B * P_facet[1];
00914 
00915   //i=1; j=1; k=2;
00916   B = 12.0 * areacoord[0] * areacoord[1] * sqr(areacoord[2]);
00917   pt += B * P_facet[2];
00918 
00919   return MB_SUCCESS;
00920 
00921 }
00922 
00923 //===========================================================================
00924 //Function Name: project_to_facet_plane
00925 //
00926 //Member Type:  PUBLIC
00927 //Descriptoin:  Project a point to the plane of a facet
00928 //===========================================================================
00929 void SmoothFace::project_to_facet_plane(EntityHandle tri, CartVect &pt,
00930     CartVect &point_on_plane, double &dist_to_plane)
00931 {
00932   double plane[4];
00933 
00934   ErrorCode rval = _mb->tag_get_data(_planeTag, &tri, 1, plane);
00935   if (MB_SUCCESS != rval) return;
00936   assert(rval == MB_SUCCESS);
00937   // _planeTag
00938   CartVect normal(&plane[0]);// just first 3 components are used
00939 
00940   double dist = normal % pt + plane[3]; // coeff d is saved!!!
00941   dist_to_plane = fabs(dist);
00942   point_on_plane = pt - dist * normal;
00943 
00944   return;
00945 }
00946 
00947 //===========================================================================
00948 //Function Name: facet_area_coordinate
00949 //
00950 //Member Type:  PUBLIC
00951 //Descriptoin:  Determine the area coordinates of a point on the plane
00952 //              of a facet
00953 //===========================================================================
00954 void SmoothFace::facet_area_coordinate(EntityHandle facet,
00955     CartVect & pt_on_plane, CartVect & areacoord)
00956 {
00957 
00958   const EntityHandle * conn3;
00959   int nnodes;
00960   ErrorCode rval = _mb->get_connectivity(facet, conn3, nnodes);
00961   assert(MB_SUCCESS == rval);
00962   if (rval) {} // empty statement to prevent compiler warning
00963 
00964   //double coords[9]; // store the coordinates for the nodes
00965   //_mb->get_coords(conn3, 3, coords);
00966   CartVect p[3];
00967   rval = _mb->get_coords(conn3, 3, (double*) &p[0]);
00968   assert(MB_SUCCESS == rval);
00969   if (rval) {} // empty statement to prevent compiler warning
00970   double plane[4];
00971 
00972   rval = _mb->tag_get_data(_planeTag, &facet, 1, plane);
00973   assert(rval == MB_SUCCESS);
00974   if (rval) {} // empty statement to prevent compiler warning
00975   CartVect normal(&plane[0]);// just first 3 components are used
00976 
00977   double area2;
00978 
00979   double tol = GEOMETRY_RESABS * 1.e-5;// 1.e-11;
00980 
00981   CartVect v1(p[1] - p[0]);
00982   CartVect v2(p[2] - p[0]);
00983 
00984   area2 = (v1 * v2).length_squared();// the same for CartVect
00985   if (area2 < 100 * tol)
00986   {
00987     tol = .01 * area2;
00988   }
00989   CartVect absnorm(fabs(normal[0]), fabs(normal[1]), fabs(normal[2]));
00990 
00991   // project to the closest coordinate plane so we only have to do this in 2D
00992 
00993   if (absnorm[0] >= absnorm[1] && absnorm[0] >= absnorm[2])
00994   {
00995     area2 = determ3( p[0][1], p[0][2],
00996         p[1][1], p[1][2],
00997         p[2][1], p[2][2]);
00998     if (fabs(area2) < tol)
00999     {
01000       areacoord = CartVect(-CUBIT_DBL_MAX);// .set( -CUBIT_DBL_MAX, -CUBIT_DBL_MAX, -CUBIT_DBL_MAX );
01001     }
01002     else if (within_tolerance(p[0], pt_on_plane, GEOMETRY_RESABS))
01003     {
01004       areacoord = CartVect(1., 0., 0.);//.set( 1.0, 0.0, 0.0 );
01005     }
01006     else if (within_tolerance(p[1], pt_on_plane, GEOMETRY_RESABS))
01007     {
01008       areacoord = CartVect(0., 1., 0.);//.set( 0.0, 1.0, 0.0 );
01009     }
01010     else if (within_tolerance(p[2], pt_on_plane, GEOMETRY_RESABS))
01011     {
01012       areacoord = CartVect(0., 0., 1.);//.set( 0.0, 0.0, 1.0 );
01013     }
01014     else
01015     {
01016 
01017       areacoord[0] = determ3(pt_on_plane[1], pt_on_plane[2],
01018           p[1][1], p[1][2], p[2][1], p[2][2] ) / area2;
01019 
01020       areacoord[1] = determ3( p[0][1], p[0][2],
01021           pt_on_plane[1], pt_on_plane[2],
01022           p[2][1], p[2][2]) / area2;
01023 
01024       areacoord[2] = determ3( p[0][1], p[0][2], p[1][1], p[1][2],
01025           pt_on_plane[1], pt_on_plane[2]) / area2;
01026     }
01027   }
01028   else if (absnorm[1] >= absnorm[0] && absnorm[1] >= absnorm[2])
01029   {
01030 
01031     area2 = determ3(p[0][0], p[0][2],
01032         p[1][0], p[1][2],
01033         p[2][0], p[2][2]);
01034     if (fabs(area2) < tol)
01035     {
01036       areacoord = CartVect(-CUBIT_DBL_MAX);//.set( -CUBIT_DBL_MAX, -CUBIT_DBL_MAX, -CUBIT_DBL_MAX );
01037     }
01038     else if (within_tolerance(p[0], pt_on_plane, GEOMETRY_RESABS))
01039     {
01040       areacoord = CartVect(1., 0., 0.);//.set( 1.0, 0.0, 0.0 );
01041     }
01042     else if (within_tolerance(p[1], pt_on_plane, GEOMETRY_RESABS))
01043     {
01044       areacoord = CartVect(0., 1., 0.);//.set( 0.0, 1.0, 0.0 );
01045     }
01046     else if (within_tolerance(p[2], pt_on_plane, GEOMETRY_RESABS))
01047     {
01048       areacoord = CartVect(0., 0., 1.);//.set( 0.0, 0.0, 1.0 );
01049     }
01050     else
01051     {
01052 
01053       areacoord[0] = determ3(pt_on_plane[0], pt_on_plane[2],
01054           p[1][0], p[1][2], p[2][0], p[2][2] ) / area2;
01055 
01056       areacoord[1] = determ3( p[0][0], p[0][2],
01057           pt_on_plane[0], pt_on_plane[2],
01058           p[2][0], p[2][2]) / area2;
01059 
01060       areacoord[2] = determ3( p[0][0], p[0][2], p[1][0], p[1][2],
01061           pt_on_plane[0], pt_on_plane[2]) / area2;
01062 
01063     }
01064   }
01065   else
01066   {
01067     /*area2 = determ3(pt0->x(), pt0->y(),
01068      pt1->x(), pt1->y(),
01069      pt2->x(), pt2->y());*/
01070     area2 = determ3( p[0][0], p[0][1],
01071         p[1][0], p[1][1],
01072         p[2][0], p[2][1]);
01073     if (fabs(area2) < tol)
01074     {
01075       areacoord = CartVect(-CUBIT_DBL_MAX);//.set( -CUBIT_DBL_MAX, -CUBIT_DBL_MAX, -CUBIT_DBL_MAX );
01076     }
01077     else if (within_tolerance(p[0], pt_on_plane, GEOMETRY_RESABS))
01078     {
01079       areacoord = CartVect(1., 0., 0.);//.set( 1.0, 0.0, 0.0 );
01080     }
01081     else if (within_tolerance(p[1], pt_on_plane, GEOMETRY_RESABS))
01082     {
01083       areacoord = CartVect(0., 1., 0.);//.set( 0.0, 1.0, 0.0 );
01084     }
01085     else if (within_tolerance(p[2], pt_on_plane, GEOMETRY_RESABS))
01086     {
01087       areacoord = CartVect(0., 0., 1.);//.set( 0.0, 0.0, 1.0 );
01088     }
01089     else
01090     {
01091 
01092       areacoord[0] = determ3(pt_on_plane[0], pt_on_plane[1],
01093           p[1][0], p[1][1], p[2][0], p[2][1] ) / area2;
01094 
01095       areacoord[1] = determ3( p[0][0], p[0][1],
01096           pt_on_plane[0], pt_on_plane[1],
01097           p[2][0], p[2][1]) / area2;
01098 
01099       areacoord[2] = determ3( p[0][0], p[0][1], p[1][0], p[1][1],
01100           pt_on_plane[0], pt_on_plane[1]) / area2;
01101     }
01102   }
01103 }
01104 
01105 ErrorCode SmoothFace::project_to_facets_main(CartVect &this_point, bool trim,
01106     bool & outside, CartVect * closest_point_ptr, CartVect * normal_ptr)
01107 {
01108 
01109   // if there are a lot of facets on this surface - use the OBB search first
01110   // to narrow the selection
01111 
01112   _evaluationsCounter++;
01113   double tolerance = 1.e-5;
01114   std::vector<EntityHandle> facets_out;
01115   // we will start with a list of facets anyway, the best among them wins
01116   ErrorCode rval = _my_geomTopoTool->obb_tree()->closest_to_location(
01117       (double*) &this_point, _obb_root, tolerance, facets_out);
01118 
01119   int interpOrder = 4;
01120   double compareTol = 1.e-5;
01121   EntityHandle lastFacet = facets_out.front();
01122   rval = project_to_facets(facets_out, lastFacet, interpOrder, compareTol,
01123       this_point, trim, outside, closest_point_ptr, normal_ptr);
01124 
01125   return rval;
01126 }
01127 ErrorCode SmoothFace::project_to_facets(std::vector<EntityHandle> & facet_list,
01128     EntityHandle & lastFacet, int interpOrder, double compareTol,
01129     CartVect &this_point, bool , bool & outside,
01130     CartVect *closest_point_ptr, CartVect * normal_ptr)
01131 {
01132 
01133   bool outside_facet, best_outside_facet = true;
01134   double mindist = 1.e20;
01135   CartVect close_point, best_point(mindist, mindist, mindist), best_areacoord;
01136   EntityHandle best_facet = 0L;// no best facet found yet
01137   EntityHandle facet;
01138   assert(facet_list.size() > 0);
01139 
01140   double big_dist = compareTol * 1.0e3;
01141 
01142   // from the list of close facets, determine the closest point
01143   for (size_t i = 0; i < facet_list.size(); i++)
01144   {
01145     facet = facet_list[i];
01146     CartVect pt_on_plane;
01147     double dist_to_plane;
01148     project_to_facet_plane(facet, this_point, pt_on_plane, dist_to_plane);
01149 
01150     CartVect areacoord;
01151     //CartVect close_point;
01152     facet_area_coordinate(facet, pt_on_plane, areacoord);
01153     if (interpOrder != 0)
01154     {
01155 
01156       // modify the areacoord - project to the bezier patch- snaps to the
01157       // edge of the patch if necessary
01158 
01159 
01160       if (project_to_facet(facet, this_point, areacoord, close_point,
01161           outside_facet, compareTol) != MB_SUCCESS)
01162       {
01163         return MB_FAILURE;
01164       }
01165       //if (closest_point_ptr)
01166       //*closest_point_ptr = close_point;
01167     }
01168     // keep track of the minimum distance
01169 
01170     double dist = (close_point - this_point).length();//close_point.distance_between(this_point);
01171     if ((best_outside_facet == outside_facet && dist < mindist)
01172         || (best_outside_facet && !outside_facet && (dist < big_dist
01173             || best_facet == 0L)))
01174     {
01175       mindist = dist;
01176       best_point = close_point;
01177       best_facet = facet;
01178       best_areacoord = areacoord;
01179       best_outside_facet = outside_facet;
01180 
01181       if (dist < compareTol)
01182       {
01183         break;
01184       }
01185       big_dist = 10.0 * mindist;
01186     }
01187     //facet->marked(1);
01188     //used_facet_list.append(facet);
01189 
01190   }
01191 
01192   if (normal_ptr)
01193   {
01194     CartVect normal;
01195     if (eval_bezier_patch_normal(best_facet, best_areacoord, normal)
01196         != MB_SUCCESS)
01197     {
01198       return MB_FAILURE;
01199     }
01200     *normal_ptr = normal;
01201   }
01202 
01203   if (closest_point_ptr)
01204   {
01205     *closest_point_ptr = best_point;
01206   }
01207 
01208   outside = best_outside_facet;
01209   lastFacet = best_facet;
01210 
01211   return MB_SUCCESS;
01212   //end copy
01213 }
01214 
01215 //===========================================================================
01216 //Function Name: project_to_patch
01217 //
01218 //Member Type:  PUBLIC
01219 //Descriptoin:  Project a point to a bezier patch. Pass in the areacoord
01220 //              of the point projected to the linear facet.  Function
01221 //              assumes that the point is contained within the patch -
01222 //              if not, it will project to one of its edges.
01223 //===========================================================================
01224 ErrorCode SmoothFace::project_to_patch(EntityHandle facet, // (IN) the facet where the patch is defined
01225     CartVect &ac, // (IN) area coordinate initial guess (from linear facet)
01226     CartVect &pt, // (IN) point we are projecting to patch
01227     CartVect &eval_pt, // (OUT) The projected point
01228     CartVect *eval_norm, // (OUT) normal at evaluated point
01229     bool &outside, // (OUT) the closest point on patch to pt is on an edge
01230     double compare_tol, // (IN) comparison tolerance
01231     int edge_id) // (IN) only used if this is to be projected to one
01232 //      of the edges.  Otherwise, should be -1
01233 {
01234   ErrorCode status = MB_SUCCESS;
01235 
01236   // see if we are at a vertex
01237 
01238 #define INCR 0.01
01239   const double tol = compare_tol;
01240 
01241   if (is_at_vertex(facet, pt, ac, compare_tol, eval_pt, eval_norm))
01242   {
01243     outside = false;
01244     return MB_SUCCESS;
01245   }
01246 
01247   // check if the start ac is inside the patch -if not, then move it there
01248 
01249   int nout = 0;
01250   const double atol = 0.001;
01251   if (move_ac_inside(ac, atol))
01252     nout++;
01253 
01254   int diverge = 0;
01255   int iter = 0;
01256   CartVect newpt;
01257   eval_bezier_patch(facet, ac, newpt);
01258   CartVect move = pt - newpt;
01259   double lastdist = move.length();
01260   double bestdist = lastdist;
01261   CartVect bestac = ac;
01262   CartVect bestpt = newpt;
01263   CartVect bestnorm(0, 0, 0);
01264 
01265   // If we are already close enough, then return now
01266 
01267   if (lastdist <= tol && !eval_norm && nout == 0)
01268   {
01269     eval_pt = pt;
01270     outside = false;
01271     return status;
01272   }
01273 
01274   double ratio, mag, umove, vmove, det, distnew, movedist;
01275   CartVect lastpt = newpt;
01276   CartVect lastac = ac;
01277   CartVect norm;
01278   CartVect xpt, ypt, zpt, xac, yac, zac, xvec, yvec, zvec;
01279   CartVect du, dv, newac;
01280   bool done = false;
01281   while (!done)
01282   {
01283 
01284     // We will be locating the projected point within the u,v,w coordinate
01285     // system of the triangular bezier patch.  Since u+v+w=1, the components
01286     // are not linearly independent.  We will choose only two of the
01287     // coordinates to use and compute the third.
01288 
01289     int system;
01290     if (lastac[0] >= lastac[1] && lastac[0] >= lastac[2])
01291     {
01292       system = 0;
01293     }
01294     else if (lastac[1] >= lastac[2])
01295     {
01296       system = 1;
01297     }
01298     else
01299     {
01300       system = 2;
01301     }
01302 
01303     // compute the surface derivatives with respect to each
01304     // of the barycentric coordinates
01305 
01306 
01307     if (system == 1 || system == 2)
01308     {
01309       xac[0] = lastac[0] + INCR; // xac.x( lastac.x() + INCR );
01310       if (lastac[1] + lastac[2] == 0.0)
01311         return MB_FAILURE;
01312       ratio = lastac[2] / (lastac[1] + lastac[2]);//ratio = lastac.z() / (lastac.y() + lastac.z());
01313       xac[1] = (1.0 - xac[0]) * (1.0 - ratio);//xac.y( (1.0 - xac.x()) * (1.0 - ratio) );
01314       xac[2] = 1.0 - xac[0] - xac[1]; // xac.z( 1.0 - xac.x() - xac.y() );
01315       eval_bezier_patch(facet, xac, xpt);
01316       xvec = xpt - lastpt;
01317       xvec /= INCR;
01318     }
01319     if (system == 0 || system == 2)
01320     {
01321       yac[1] = (lastac[1] + INCR);//yac.y( lastac.y() + INCR );
01322       if (lastac[0] + lastac[2] == 0.0)//if (lastac.x() + lastac.z() == 0.0)
01323         return MB_FAILURE;
01324       ratio = lastac[2] / (lastac[0] + lastac[2]);//ratio = lastac.z() / (lastac.x() + lastac.z());
01325       yac[0] = ((1.0 - yac[1]) * (1.0 - ratio));//yac.x( (1.0 - yac.y()) * (1.0 - ratio) );
01326       yac[2] = (1.0 - yac[0] - yac[1]);//yac.z( 1.0 - yac.x() - yac.y() );
01327       eval_bezier_patch(facet, yac, ypt);
01328       yvec = ypt - lastpt;
01329       yvec /= INCR;
01330     }
01331     if (system == 0 || system == 1)
01332     {
01333       zac[2] = (lastac[2] + INCR);//zac.z( lastac.z() + INCR );
01334       if (lastac[0] + lastac[1] == 0.0)//if (lastac.x() + lastac.y() == 0.0)
01335         return MB_FAILURE;
01336       ratio = lastac[1] / (lastac[0] + lastac[1]);//ratio = lastac.y() / (lastac.x() + lastac.y());
01337       zac[0] = ((1.0 - zac[2]) * (1.0 - ratio));//zac.x( (1.0 - zac.z()) * (1.0 - ratio) );
01338       zac[1] = (1.0 - zac[0] - zac[2]);//zac.y( 1.0 - zac.x() - zac.z() );
01339       eval_bezier_patch(facet, zac, zpt);
01340       zvec = zpt - lastpt;
01341       zvec /= INCR;
01342     }
01343 
01344     // compute the surface normal
01345 
01346     switch (system) {
01347     case 0:
01348       du = yvec;
01349       dv = zvec;
01350       break;
01351     case 1:
01352       du = zvec;
01353       dv = xvec;
01354       break;
01355     case 2:
01356       du = xvec;
01357       dv = yvec;
01358       break;
01359     }
01360     norm = du * dv;
01361     mag = norm.length();
01362     if (mag < DBL_EPSILON)
01363     {
01364       return MB_FAILURE;
01365       // do something else here (it is likely a flat triangle -
01366       // so try evaluating just an edge of the bezier patch)
01367     }
01368     norm /= mag;
01369     if (iter == 0)
01370       bestnorm = norm;
01371 
01372     // project the move vector to the tangent plane
01373 
01374     move = (norm * move) * norm;
01375 
01376     // compute an equivalent u-v-w vector
01377 
01378     CartVect absnorm(fabs(norm[0]), fabs(norm[1]), fabs(norm[2]));
01379     if (absnorm[2] >= absnorm[1] && absnorm[2] >= absnorm[0])
01380     {
01381       det = du[0] * dv[1] - dv[0] * du[1];
01382       if (fabs(det) <= DBL_EPSILON)
01383       {
01384         return MB_FAILURE; // do something else here
01385       }
01386       umove = (move[0] * dv[1] - dv[0] * move[1]) / det;
01387       vmove = (du[0] * move[1] - move[0] * du[1]) / det;
01388     }
01389     else if (absnorm[1] >= absnorm[2] && absnorm[1] >= absnorm[0])
01390     {
01391       det = du[0] * dv[2] - dv[0] * du[2];
01392       if (fabs(det) <= DBL_EPSILON)
01393       {
01394         return MB_FAILURE;
01395       }
01396       umove = (move[0] * dv[2] - dv[0] * move[2]) / det;
01397       vmove = (du[0] * move[2] - move[0] * du[2]) / det;
01398     }
01399     else
01400     {
01401       det = du[1] * dv[2] - dv[1] * du[2];
01402       if (fabs(det) <= DBL_EPSILON)
01403       {
01404         return MB_FAILURE;
01405       }
01406       umove = (move[1] * dv[2] - dv[1] * move[2]) / det;
01407       vmove = (du[1] * move[2] - move[1] * du[2]) / det;
01408     }
01409 
01410     /* === compute the new u-v coords and evaluate surface at new location */
01411 
01412     switch (system) {
01413     case 0:
01414       newac[1] = (lastac[1] + umove);//newac.y( lastac.y() + umove );
01415       newac[2] = (lastac[2] + vmove);//newac.z( lastac.z() + vmove );
01416       newac[0] = (1.0 - newac[1] - newac[2]);//newac.x( 1.0 - newac.y() - newac.z() );
01417       break;
01418     case 1:
01419       newac[2] = (lastac[2] + umove);//newac.z( lastac.z() + umove );
01420       newac[0] = (lastac[0] + vmove);//newac.x( lastac.x() + vmove );
01421       newac[1] = (1.0 - newac[2] - newac[0]);//newac.y( 1.0 - newac.z() - newac.x() );
01422       break;
01423     case 2:
01424       newac[0] = (lastac[0] + umove);//newac.x( lastac.x() + umove );
01425       newac[1] = (lastac[1] + vmove);//newac.y( lastac.y() + vmove );
01426       newac[2] = (1.0 - newac[0] - newac[1]);//newac.z( 1.0 - newac.x() - newac.y() );
01427       break;
01428     }
01429 
01430     // Keep it inside the patch
01431 
01432     if (newac[0] >= -atol && newac[1] >= -atol && newac[2] >= -atol)
01433     {
01434       nout = 0;
01435     }
01436     else
01437     {
01438       if (move_ac_inside(newac, atol))
01439         nout++;
01440     }
01441 
01442     // Evaluate at the new location
01443 
01444     if (edge_id != -1)
01445       ac_at_edge(newac, newac, edge_id); // move to edge first
01446     eval_bezier_patch(facet, newac, newpt);
01447 
01448     // Check for convergence
01449 
01450     distnew = (pt - newpt).length();//pt.distance_between(newpt);
01451     move = newpt - lastpt;
01452     movedist = move.length();
01453     if (movedist < tol || distnew < tol)
01454     {
01455       done = true;
01456       if (distnew < bestdist)
01457       {
01458         bestdist = distnew;
01459         bestac = newac;
01460         bestpt = newpt;
01461         bestnorm = norm;
01462       }
01463     }
01464     else
01465     {
01466 
01467       // don't allow more than 30 iterations
01468 
01469       iter++;
01470       if (iter > 30)
01471       {
01472         //if (movedist > tol * 100.0) nout=1;
01473         done = true;
01474       }
01475 
01476       // Check for divergence - don't allow more than 5 divergent
01477       // iterations
01478 
01479       if (distnew > lastdist)
01480       {
01481         diverge++;
01482         if (diverge > 10)
01483         {
01484           done = true;
01485           //if (movedist > tol * 100.0) nout=1;
01486         }
01487       }
01488 
01489       // Check if we are continuing to project outside the facet.
01490       // If so, then stop now
01491 
01492       if (nout > 3)
01493       {
01494         done = true;
01495       }
01496 
01497       // set up for next iteration
01498 
01499       if (!done)
01500       {
01501         if (distnew < bestdist)
01502         {
01503           bestdist = distnew;
01504           bestac = newac;
01505           bestpt = newpt;
01506           bestnorm = norm;
01507         }
01508         lastdist = distnew;
01509         lastpt = newpt;
01510         lastac = newac;
01511         move = pt - lastpt;
01512       }
01513     }
01514   }
01515 
01516   eval_pt = bestpt;
01517   if (eval_norm)
01518   {
01519     *eval_norm = bestnorm;
01520   }
01521   outside = (nout > 0) ? true : false;
01522   ac = bestac;
01523 
01524   return status;
01525 }
01526 
01527 //===========================================================================
01528 //Function Name: ac_at_edge
01529 //
01530 //Member Type:  PRIVATE
01531 //Description:  determine the area coordinate of the facet at the edge
01532 //===========================================================================
01533 void SmoothFace::ac_at_edge(CartVect &fac, // facet area coordinate
01534     CartVect &eac, // edge area coordinate
01535     int edge_id) // id of edge
01536 {
01537   double u, v, w;
01538   switch (edge_id) {
01539   case 0:
01540     u = 0.0;
01541     v = fac[1] / (fac[1] + fac[2]);//v = fac.y() / (fac.y() + fac.z());
01542     w = 1.0 - v;
01543     break;
01544   case 1:
01545     u = fac[0] / (fac[0] + fac[2]);// u = fac.x() / (fac.x() + fac.z());
01546     v = 0.0;
01547     w = 1.0 - u;
01548     break;
01549   case 2:
01550     u = fac[0] / (fac[0] + fac[1]);//u = fac.x() / (fac.x() + fac.y());
01551     v = 1.0 - u;
01552     w = 0.0;
01553     break;
01554   default:
01555     assert(0);
01556     u = -1; // needed to eliminate warnings about used before set
01557     v = -1; // needed to eliminate warnings about used before set
01558     w = -1; // needed to eliminate warnings about used before set
01559     break;
01560   }
01561   eac[0] = u;
01562   eac[1] = v;
01563   eac[2] = w; //= CartVect(u, v, w);
01564 }
01565 
01566 //===========================================================================
01567 //Function Name: project_to_facet
01568 //
01569 //Member Type:  PUBLIC
01570 //Description:  project to a single facet.  Uses the input areacoord as
01571 //              a starting guess.
01572 //===========================================================================
01573 ErrorCode SmoothFace::project_to_facet(EntityHandle facet, CartVect &pt,
01574     CartVect &areacoord, CartVect &close_point, bool &outside_facet,
01575     double compare_tol)
01576 {
01577 
01578   ErrorCode stat = MB_SUCCESS;
01579   const EntityHandle * conn3;
01580   int nnodes;
01581   _mb->get_connectivity(facet, conn3, nnodes);
01582   //
01583   //double coords[9]; // store the coordinates for the nodes
01584   //_mb->get_coords(conn3, 3, coords);
01585   CartVect p[3];
01586   _mb->get_coords(conn3, 3, (double*) &p[0]);
01587 
01588   int edge_id = -1;
01589   stat = project_to_patch(facet, areacoord, pt, close_point, NULL,
01590       outside_facet, compare_tol, edge_id);
01591   /* }
01592    break;
01593    }*/
01594 
01595   return stat;
01596 }
01597 
01598 //===========================================================================
01599 //Function Name: is_at_vertex
01600 //
01601 //Member Type:  PRIVATE
01602 //Description:  determine if the point is at one of the facet's vertices
01603 //===========================================================================
01604 bool SmoothFace::is_at_vertex(EntityHandle facet, // (IN) facet we are evaluating
01605     CartVect &pt, // (IN) the point
01606     CartVect &ac, // (IN) the ac of the point on the facet plane
01607     double compare_tol, // (IN) return TRUE of closer than this
01608     CartVect &eval_pt, // (OUT) location at vertex if TRUE
01609     CartVect *eval_norm_ptr) // (OUT) normal at vertex if TRUE
01610 {
01611   double dist;
01612   CartVect vert_loc;
01613   const double actol = 0.1;
01614   // get coordinates get_coords
01615   const EntityHandle * conn3;
01616   int nnodes;
01617   _mb->get_connectivity(facet, conn3, nnodes);
01618   //
01619   //double coords[9]; // store the coordinates for the nodes
01620   //_mb->get_coords(conn3, 3, coords);
01621   CartVect p[3];
01622   _mb->get_coords(conn3, 3, (double*) &p[0]);
01623   // also get the normals at nodes
01624   CartVect NN[3];
01625   _mb->tag_get_data(_gradientTag, conn3, 3, (double*) &NN[0]);
01626   if (fabs(ac[0]) < actol && fabs(ac[1]) < actol)
01627   {
01628     vert_loc = p[2];
01629     dist = (pt - vert_loc).length(); //pt.distance_between( vert_loc );
01630     if (dist <= compare_tol)
01631     {
01632       eval_pt = vert_loc;
01633       if (eval_norm_ptr)
01634       {
01635         *eval_norm_ptr = NN[2];
01636       }
01637       return true;
01638     }
01639   }
01640 
01641   if (fabs(ac[0]) < actol && fabs(ac[2]) < actol)
01642   {
01643     vert_loc = p[1];
01644     dist = (pt - vert_loc).length();//pt.distance_between( vert_loc );
01645     if (dist <= compare_tol)
01646     {
01647       eval_pt = vert_loc;
01648       if (eval_norm_ptr)
01649       {
01650         *eval_norm_ptr = NN[1];//facet->point(1)->normal( facet );
01651       }
01652       return true;
01653     }
01654   }
01655 
01656   if (fabs(ac[1]) < actol && fabs(ac[2]) < actol)
01657   {
01658     vert_loc = p[0];
01659     dist = (pt - vert_loc).length();//pt.distance_between( vert_loc );
01660     if (dist <= compare_tol)
01661     {
01662       eval_pt = vert_loc;
01663       if (eval_norm_ptr)
01664       {
01665         *eval_norm_ptr = NN[0];
01666       }
01667       return true;
01668     }
01669   }
01670 
01671   return false;
01672 }
01673 
01674 //===========================================================================
01675 //Function Name: move_ac_inside
01676 //
01677 //Member Type:  PRIVATE
01678 //Description:  find the closest area coordinate to the boundary of the
01679 //              patch if any of its components are < 0
01680 //              Return if the ac was modified.
01681 //===========================================================================
01682 bool SmoothFace::move_ac_inside(CartVect &ac, double tol)
01683 {
01684   int nout = 0;
01685   if (ac[0] < -tol)
01686   {
01687     ac[0] = 0.0;
01688     ac[1] = ac[1] / (ac[1] + ac[2]); //( ac.y() / (ac.y() + ac.z()) ;
01689     ac[2] = 1. - ac[1]; //ac.z( 1.0 - ac.y() );
01690     nout++;
01691   }
01692   if (ac[1] < -tol)
01693   {
01694     ac[1] = 0.;//ac.y( 0.0 );
01695     ac[0] = ac[0] / (ac[0] + ac[2]);//ac.x( ac.x() / (ac.x() + ac.z()) );
01696     ac[2] = 1. - ac[0];//ac.z( 1.0 - ac.x() );
01697     nout++;
01698   }
01699   if (ac[2] < -tol)
01700   {
01701     ac[2] = 0.;// ac.z( 0.0 );
01702     ac[0] = ac[0] / (ac[0] + ac[1]);//ac.x( ac.x() / (ac.x() + ac.y()) );
01703     ac[1] = 1. - ac[0]; // ac.y( 1.0 - ac.x() );
01704     nout++;
01705   }
01706   return (nout > 0) ? true : false;
01707 }
01708 
01709 //===========================================================================
01710 //Function Name: hodograph
01711 //
01712 //Member Type:  PUBLIC
01713 //Description:  get the hodograph control points for the facet
01714 //Note:  This is a triangle cubic patch that is defined by the
01715 //       normals of quartic facet control point lattice.  Returned coordinates
01716 //       in Nijk are defined by the following diagram
01717 //
01718 //
01719 //                         *9               index  polar
01720 //                        / \                 0     300    point(0)
01721 //                       /   \                1     210
01722 //                     7*-----*8              2     120
01723 //                     / \   / \              3     030    point(1)
01724 //                    /   \ /   \             4     201
01725 //                  4*----5*-----*6           5     111
01726 //                  / \   / \   / \           6     021
01727 //                 /   \ /   \ /   \          7     102
01728 //                *-----*-----*-----*         8     012
01729 //                0     1     2     3         9     003    point(2)
01730 //
01731 
01732 //===========================================================================
01733 //Function Name: eval_bezier_patch_normal
01734 //
01735 //Member Type:  PRIVATE
01736 //Description:  evaluate the Bezier patch defined at a facet
01737 //===========================================================================
01738 ErrorCode SmoothFace::eval_bezier_patch_normal(EntityHandle facet,
01739     CartVect &areacoord, CartVect &normal)
01740 {
01741   // interpolate internal control points
01742 
01743   CartVect gctrl_pts[6];
01744   //facet->get_control_points( gctrl_pts );
01745   ErrorCode rval = _mb->tag_get_data(_facetCtrlTag, &facet, 1, &gctrl_pts[0]);
01746   assert(rval == MB_SUCCESS);
01747   if (MB_SUCCESS != rval) return rval;
01748   // _gradientTag
01749   // get normals at points
01750   const EntityHandle * conn3;
01751   int nnodes;
01752   rval = _mb->get_connectivity(facet, conn3, nnodes);
01753   if (MB_SUCCESS != rval) return rval;
01754 
01755   CartVect NN[3];
01756   rval = _mb->tag_get_data(_gradientTag, conn3, 3, &NN[0]);
01757   assert(rval == MB_SUCCESS);
01758   if (MB_SUCCESS != rval) return rval;
01759 
01760   if (fabs(areacoord[1] + areacoord[2]) < 1.0e-6)
01761   {
01762     normal = NN[0];
01763     return MB_SUCCESS;
01764   }
01765   if (fabs(areacoord[0] + areacoord[2]) < 1.0e-6)
01766   {
01767     normal = NN[1];//facet->point(1)->normal(facet);
01768     return MB_SUCCESS;
01769   }
01770   if (fabs(areacoord[0] + areacoord[1]) < 1.0e-6)
01771   {
01772     normal = NN[2]; //facet->point(2)->normal(facet);
01773     return MB_SUCCESS;
01774   }
01775 
01776   // compute the hodograph of the quartic Gregory patch
01777 
01778   CartVect Nijk[10];
01779   //hodograph(facet,areacoord,Nijk);
01780   // start copy from hodograph
01781   //CubitVector gctrl_pts[6];
01782   // facet->get_control_points( gctrl_pts );
01783   CartVect P_facet[3];
01784 
01785   //2,1,1
01786   /*P_facet[0] = (1.0e0 / (areacoord.y() + areacoord.z())) *
01787    (areacoord.y() * gctrl_pts[3] +
01788    areacoord.z() * gctrl_pts[4]);*/
01789   P_facet[0] = (1.0e0 / (areacoord[1] + areacoord[2])) * (areacoord[1]
01790       * gctrl_pts[3] + areacoord[2] * gctrl_pts[4]);
01791   //1,2,1
01792   /*P_facet[1] = (1.0e0 / (areacoord.x() + areacoord.z())) *
01793    (areacoord.x() * gctrl_pts[0] +
01794    areacoord.z() * gctrl_pts[5]);*/
01795   P_facet[1] = (1.0e0 / (areacoord[0] + areacoord[2])) * (areacoord[0]
01796       * gctrl_pts[0] + areacoord[2] * gctrl_pts[5]);
01797   //1,1,2
01798   /*P_facet[2] = (1.0e0 / (areacoord.x() + areacoord.y())) *
01799    (areacoord.x() * gctrl_pts[1] +
01800    areacoord.y() * gctrl_pts[2]);*/
01801   P_facet[2] = (1.0e0 / (areacoord[0] + areacoord[1])) * (areacoord[0]
01802       * gctrl_pts[1] + areacoord[1] * gctrl_pts[2]);
01803 
01804   // corner control points are just the normals at the points
01805 
01806   //3, 0, 0
01807   Nijk[0] = NN[0];
01808   //0, 3, 0
01809   Nijk[3] = NN[1];
01810   //0, 0, 3
01811   Nijk[9] = NN[2];//facet->point(2)->normal(facet);
01812 
01813   // fill in the boundary control points.  Define as the normal to the local
01814   // triangle formed by the quartic control point lattice
01815 
01816   // store here again the 9 control points on the edges
01817   CartVect CP[9]; // 9 control points on the edges,
01818   rval = _mb->tag_get_data(_facetEdgeCtrlTag, &facet, 1, &CP[0]);
01819   if (MB_SUCCESS != rval) return rval;
01820   // there are 3 CP for each edge, 0, 1, 2; first edge is 1-2
01821   //CubitFacetEdge *edge;
01822   //edge = facet->edge( 2 );
01823   //CubitVector ctrl_pts[5];
01824   //edge->control_points(facet, ctrl_pts);
01825 
01826   //2, 1, 0
01827   //Nijk[1] = (ctrl_pts[2] - ctrl_pts[1]) * (P_facet[0] - ctrl_pts[1]);
01828   Nijk[1] = (CP[7] - CP[6]) * (P_facet[0] - CP[6]);
01829   Nijk[1].normalize();
01830 
01831   //1, 2, 0
01832   //Nijk[2] = (ctrl_pts[3] - ctrl_pts[2]) * (P_facet[1] - ctrl_pts[2]);
01833   Nijk[2] = (CP[8] - CP[7]) * (P_facet[1] - CP[7]);
01834   Nijk[2].normalize();
01835 
01836   //edge = facet->edge( 0 );
01837   //edge->control_points(facet, ctrl_pts);
01838 
01839   //0, 2, 1
01840   //Nijk[6] = (ctrl_pts[1] - P_facet[1]) * (ctrl_pts[2] - P_facet[1]);
01841   Nijk[6] = (CP[0] - P_facet[1]) * (CP[1] - P_facet[1]);
01842   Nijk[6].normalize();
01843 
01844   //0, 1, 2
01845   //Nijk[8] = (ctrl_pts[2] - P_facet[2]) * (ctrl_pts[3] - P_facet[2]);
01846   Nijk[8] = (CP[1] - P_facet[2]) * (CP[2] - P_facet[2]);
01847   Nijk[8].normalize();
01848 
01849   //edge = facet->edge( 1 );
01850   //edge->control_points(facet, ctrl_pts);
01851 
01852   //1, 0, 2
01853   //Nijk[7] = (P_facet[2] - ctrl_pts[2]) * (ctrl_pts[1] - ctrl_pts[2]);
01854   Nijk[7] = (P_facet[2] - CP[4]) * (CP[3] - CP[4]);
01855   Nijk[7].normalize();
01856 
01857   //2, 0, 1
01858   //Nijk[4] = (P_facet[0] - ctrl_pts[3]) * (ctrl_pts[2] - ctrl_pts[3]);
01859   Nijk[4] = (P_facet[0] - CP[5]) * (CP[4] - CP[5]);
01860   Nijk[4].normalize();
01861 
01862   //1, 1, 1
01863   Nijk[5] = (P_facet[1] - P_facet[0]) * (P_facet[2] - P_facet[0]);
01864   Nijk[5].normalize();
01865   // end copy from hodograph
01866 
01867   // sum the contribution from each of the control points
01868 
01869   normal = CartVect(0.0e0, 0.0e0, 0.0e0);
01870 
01871   //i=3; j=0; k=0;
01872   double Bsum = 0.0;
01873   double B = cube(areacoord[0]);
01874   Bsum += B;
01875   normal += B * Nijk[0];
01876 
01877   //i=2; j=1; k=0;
01878   B = 3.0 * sqr(areacoord[0]) * areacoord[1];
01879   Bsum += B;
01880   normal += B * Nijk[1];
01881 
01882   //i=1; j=2; k=0;
01883   B = 3.0 * areacoord[0] * sqr(areacoord[1]);
01884   Bsum += B;
01885   normal += B * Nijk[2];
01886 
01887   //i=0; j=3; k=0;
01888   B = cube(areacoord[1]);
01889   Bsum += B;
01890   normal += B * Nijk[3];
01891 
01892   //i=2; j=0; k=1;
01893   B = 3.0 * sqr(areacoord[0]) * areacoord[2];
01894   Bsum += B;
01895   normal += B * Nijk[4];
01896 
01897   //i=1; j=1; k=1;
01898   B = 6.0 * areacoord[0] * areacoord[1] * areacoord[2];
01899   Bsum += B;
01900   normal += B * Nijk[5];
01901 
01902   //i=0; j=2; k=1;
01903   B = 3.0 * sqr(areacoord[1]) * areacoord[2];
01904   Bsum += B;
01905   normal += B * Nijk[6];
01906 
01907   //i=1; j=0; k=2;
01908   B = 3.0 * areacoord[0] * sqr(areacoord[2]);
01909   Bsum += B;
01910   normal += B * Nijk[7];
01911 
01912   //i=0; j=1; k=2;
01913   B = 3.0 * areacoord[1] * sqr(areacoord[2]);
01914   Bsum += B;
01915   normal += B * Nijk[8];
01916 
01917   //i=0; j=0; k=3;
01918   B = cube(areacoord[2]);
01919   Bsum += B;
01920   normal += B * Nijk[9];
01921 
01922   //assert(fabs(Bsum - 1.0) < 1e-9);
01923 
01924   normal.normalize();
01925 
01926   return MB_SUCCESS;
01927 }
01928 
01929 ErrorCode SmoothFace::get_normals_for_vertices(const EntityHandle * conn2,
01930     CartVect N[2])
01931 // this method will be called to retrieve the normals needed in the calculation of control edge points..
01932 {
01933   //CartVect N[2];
01934   //_mb->tag_get_data(_gradientTag, conn2, 2, normalVec);
01935   ErrorCode rval = _mb->tag_get_data(_gradientTag, conn2, 2, (double*) &N[0]);
01936   return rval;
01937 }
01938 
01939 ErrorCode SmoothFace::ray_intersection_correct(EntityHandle , // (IN) the facet where the patch is defined
01940     CartVect &pt, // (IN) shoot from
01941     CartVect &ray, // (IN) ray direction
01942     CartVect &eval_pt, // (INOUT) The intersection point
01943     double & distance, // (IN OUT) the new distance
01944     bool &outside)
01945 {
01946   // find a point on the smooth surface
01947   CartVect currentPoint = eval_pt;
01948   int numIter = 0;
01949   double improvement = 1.e20;
01950   CartVect diff;
01951   while (numIter++ < 5 && improvement > 0.01)
01952   {
01953     CartVect newPos;
01954 
01955     bool trim = false;// is it needed?
01956     outside = true;
01957     CartVect closestPoint;
01958     CartVect normal;
01959 
01960     ErrorCode rval = project_to_facets_main(currentPoint, trim, outside,
01961         &newPos, &normal);
01962     if (MB_SUCCESS != rval) return rval;
01963     assert(rval==MB_SUCCESS);
01964     diff = newPos - currentPoint;
01965     improvement = diff.length();
01966     // ( pt + t * ray - closest ) % normal = 0;
01967     // intersect tangent plane that goes through closest point with the direction
01968     // t = normal%(closest-pt) / normal%ray;
01969     double dot = normal % ray; // if it is 0, get out while we can
01970     if (dot < 0.00001)
01971     {
01972       // bad convergence, get out, do not modify anything
01973       return MB_SUCCESS;
01974     }
01975     double t = ((newPos - pt) % normal) / (dot);
01976     currentPoint = pt + t * ray;
01977 
01978   }
01979   eval_pt = currentPoint;
01980   diff = currentPoint - pt;
01981   distance = diff.length();
01982   return MB_SUCCESS;
01983 }
01984 }// namespace moab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines