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