Branch data Line data Source code
1 : : #include <iostream>
2 : : #include <fstream>
3 : : #include <algorithm>
4 : : #include <iomanip>
5 : : #include <cassert>
6 : : #include <limits>
7 : : #include "moab/OrientedBoxTreeTool.hpp"
8 : : #include "SmoothFace.hpp"
9 : :
10 : : #define GEOMETRY_RESABS 1.e-6
11 : : #define mbsqr( a ) ( ( a ) * ( a ) )
12 : : #define mbcube( a ) ( mbsqr( a ) * ( a ) )
13 : : #define mbquart( a ) ( mbsqr( a ) * mbsqr( a ) )
14 : :
15 : : namespace moab
16 : : {
17 : :
18 : 8040 : bool within_tolerance( CartVect& p1, CartVect& p2, const double& tolerance )
19 : : {
20 [ + + ]: 8040 : if( ( fabs( p1[0] - p2[0] ) < tolerance ) && ( fabs( p1[1] - p2[1] ) < tolerance ) &&
[ - + # # ]
[ - + ]
21 : 0 : ( fabs( p1[2] - p2[2] ) < tolerance ) )
22 : 0 : return true;
23 : 8040 : return false;
24 : : }
25 : 0 : int numAdjTriInSet( Interface* mb, EntityHandle startEdge, EntityHandle set )
26 : : {
27 [ # # ]: 0 : std::vector< EntityHandle > adjTri;
28 [ # # ]: 0 : mb->get_adjacencies( &startEdge, 1, 2, false, adjTri, Interface::UNION );
29 : : // count how many are in the set
30 : 0 : int nbInSet = 0;
31 [ # # ]: 0 : for( size_t i = 0; i < adjTri.size(); i++ )
32 : : {
33 [ # # ]: 0 : EntityHandle tri = adjTri[i];
34 [ # # ][ # # ]: 0 : if( mb->contains_entities( set, &tri, 1 ) ) nbInSet++;
35 : : }
36 : 0 : return nbInSet;
37 : : }
38 : :
39 : : bool debug_surf_eval1 = false;
40 : :
41 : 12 : SmoothFace::SmoothFace( Interface* mb, EntityHandle surface_set, GeomTopoTool* gTool )
42 : : : _markTag( 0 ), _gradientTag( 0 ), _tangentsTag( 0 ), _edgeCtrlTag( 0 ), _facetCtrlTag( 0 ),
43 : : _facetEdgeCtrlTag( 0 ), _planeTag( 0 ), _mb( mb ), _set( surface_set ), _my_geomTopoTool( gTool ), _obb_root( 0 ),
44 [ + - ][ + - ]: 12 : _evaluationsCounter( 0 )
45 : : {
46 : : //_smooth_face = NULL;
47 : : //_mbOut->create_meshset(MESHSET_SET, _oSet); //will contain the
48 : : // get also the obb_root
49 [ + - ]: 12 : if( _my_geomTopoTool )
50 : : {
51 [ + - ]: 12 : _my_geomTopoTool->get_root( this->_set, _obb_root );
52 [ - + ][ # # ]: 12 : if( debug_surf_eval1 ) _my_geomTopoTool->obb_tree()->stats( _obb_root, std::cout );
[ # # ]
53 : : }
54 : 12 : }
55 : :
56 [ - + ]: 48 : SmoothFace::~SmoothFace() {}
57 : :
58 : 0 : double SmoothFace::area()
59 : : {
60 : : // find the area of this entity
61 : : // assert(_smooth_face);
62 : : // double area1 = _smooth_face->area();
63 : 0 : double totArea = 0.;
64 [ # # ][ # # ]: 0 : for( Range::iterator it = _triangles.begin(); it != _triangles.end(); ++it )
[ # # ][ # # ]
[ # # ]
65 : : {
66 [ # # ]: 0 : EntityHandle tria = *it;
67 : : const EntityHandle* conn3;
68 : : int nnodes;
69 [ # # ]: 0 : _mb->get_connectivity( tria, conn3, nnodes );
70 : : //
71 : : // double coords[9]; // store the coordinates for the nodes
72 : : //_mb->get_coords(conn3, 3, coords);
73 [ # # ][ # # ]: 0 : CartVect p[3];
74 [ # # ]: 0 : _mb->get_coords( conn3, 3, (double*)&p[0] );
75 : : // need to compute the angles
76 : : // compute angles and the normal
77 : : // CartVect p1(&coords[0]), p2(&coords[3]), p3(&coords[6]);
78 : :
79 [ # # ]: 0 : CartVect AB( p[1] - p[0] ); //(p2 - p1);
80 [ # # ]: 0 : CartVect BC( p[2] - p[1] ); //(p3 - p2);
81 [ # # ]: 0 : CartVect normal = AB * BC;
82 [ # # ]: 0 : totArea += normal.length() / 2;
83 : : }
84 : 0 : return totArea;
85 : : }
86 : : // these tags will be collected for deletion
87 : 6 : void SmoothFace::append_smooth_tags( std::vector< Tag >& smoothTags )
88 : : {
89 : : // these are created locally, for each smooth face
90 : 6 : smoothTags.push_back( _gradientTag );
91 : 6 : smoothTags.push_back( _planeTag );
92 : 6 : }
93 : 0 : void SmoothFace::bounding_box( double box_min[3], double box_max[3] )
94 : : {
95 : :
96 [ # # ]: 0 : for( int i = 0; i < 3; i++ )
97 : : {
98 : 0 : box_min[i] = _minim[i];
99 : 0 : box_max[i] = _maxim[i];
100 : : }
101 : : // _minim, _maxim
102 : 0 : }
103 : :
104 : 1763 : void SmoothFace::move_to_surface( double& x, double& y, double& z )
105 : : {
106 : :
107 [ + - ]: 1763 : CartVect loc2( x, y, z );
108 : 1763 : bool trim = false; // is it needed?
109 : 1763 : bool outside = true;
110 [ + - ]: 1763 : CartVect closestPoint;
111 : :
112 [ + - ]: 1763 : ErrorCode rval = project_to_facets_main( loc2, trim, outside, &closestPoint, NULL );
113 [ - + ]: 3526 : if( MB_SUCCESS != rval ) return;
114 [ - + ]: 1763 : assert( rval == MB_SUCCESS );
115 [ + - ]: 1763 : x = closestPoint[0];
116 [ + - ]: 1763 : y = closestPoint[1];
117 [ + - ]: 1763 : z = closestPoint[2];
118 : : }
119 : : /*
120 : : void SmoothFace::move_to_surface(double& x, double& y, double& z,
121 : : double& u_guess, double& v_guess) {
122 : : if (debug_surf_eval1) {
123 : : std::cout << "move_to_surface called." << std::endl;
124 : : }
125 : : }*/
126 : :
127 : 8 : bool SmoothFace::normal_at( double x, double y, double z, double& nx, double& ny, double& nz )
128 : : {
129 : :
130 [ + - ]: 8 : CartVect loc2( x, y, z );
131 : :
132 : 8 : bool trim = false; // is it needed?
133 : 8 : bool outside = true;
134 : : // CartVect closestPoint;// not needed
135 : : // not interested in normal
136 [ + - ]: 8 : CartVect normal;
137 [ + - ]: 8 : ErrorCode rval = project_to_facets_main( loc2, trim, outside, NULL, &normal );
138 [ - + ]: 8 : if( MB_SUCCESS != rval ) return false;
139 [ - + ]: 8 : assert( rval == MB_SUCCESS );
140 [ + - ]: 8 : nx = normal[0];
141 [ + - ]: 8 : ny = normal[1];
142 [ + - ]: 8 : nz = normal[2];
143 : :
144 : 8 : return true;
145 : : }
146 : :
147 : 12 : ErrorCode SmoothFace::compute_control_points_on_edges( double min_dot, Tag edgeCtrlTag, Tag markTag )
148 : : {
149 : :
150 : 12 : _edgeCtrlTag = edgeCtrlTag;
151 : 12 : _markTag = markTag;
152 : :
153 : : // now, compute control points for all edges that are not marked already (they are no on the
154 : : // boundary!)
155 [ + - ][ + - ]: 68205 : for( Range::iterator it = _edges.begin(); it != _edges.end(); ++it )
[ + - ][ + - ]
[ + + ]
156 : : {
157 [ + - ]: 68193 : EntityHandle edg = *it;
158 : : // is the edge marked? already computed
159 : 68193 : unsigned char tagVal = 0;
160 [ + - ]: 68193 : _mb->tag_get_data( _markTag, &edg, 1, &tagVal );
161 [ + + ]: 68193 : if( tagVal ) continue;
162 : : // double min_dot;
163 [ + - ]: 65526 : init_bezier_edge( edg, min_dot );
164 : 65526 : tagVal = 1;
165 [ + - ]: 65526 : _mb->tag_set_data( _markTag, &edg, 1, &tagVal );
166 : : }
167 : 12 : return MB_SUCCESS;
168 : : }
169 : :
170 : 12 : int SmoothFace::init_gradient()
171 : : {
172 : : // first, create a Tag for gradient (or normal)
173 : : // loop over all triangles in set, and modify the normals according to the angle as weight
174 : : // get all the edges from this subset
175 [ - + ]: 12 : if( NULL == _mb ) return 1; // fail
176 [ + - ]: 12 : _triangles.clear();
177 [ + - ]: 12 : ErrorCode rval = _mb->get_entities_by_type( _set, MBTRI, _triangles );
178 [ - + ]: 12 : if( MB_SUCCESS != rval ) return 1;
179 : : // get a new range of edges, and decide the loops from here
180 [ + - ]: 12 : _edges.clear();
181 [ + - ]: 12 : rval = _mb->get_adjacencies( _triangles, 1, true, _edges, Interface::UNION );
182 [ - + ]: 12 : assert( rval == MB_SUCCESS );
183 : :
184 [ + - ]: 12 : rval = _mb->get_adjacencies( _triangles, 0, false, _nodes, Interface::UNION );
185 [ - + ]: 12 : assert( rval == MB_SUCCESS );
186 : :
187 : : // initialize bounding box limits
188 [ + - ]: 12 : CartVect vert1;
189 [ + - ]: 12 : EntityHandle v1 = _nodes[0]; // first vertex
190 [ + - ]: 12 : _mb->get_coords( &v1, 1, (double*)&vert1 );
191 : 12 : _minim = vert1;
192 : 12 : _maxim = vert1;
193 : :
194 : 12 : double defNormal[] = { 0., 0., 0. };
195 : : // look for a tag name here that is definitely unique. We do not want the tags to interfere with
196 : : // each other this normal will be for each node in a face some nodes have multiple normals, if
197 : : // they are at the feature edges
198 [ + - ]: 12 : unsigned long setId = _mb->id_from_handle( _set );
199 : 12 : char name[50] = { 0 };
200 : : sprintf( name, "GRADIENT%lu",
201 : 12 : setId ); // name should be something like GRADIENT29, where 29 is the set ID of the face
202 [ + - ]: 12 : rval = _mb->tag_get_handle( name, 3, MB_TYPE_DOUBLE, _gradientTag, MB_TAG_DENSE | MB_TAG_CREAT, &defNormal );
203 [ - + ]: 12 : assert( rval == MB_SUCCESS );
204 : :
205 : 12 : double defPlane[4] = { 0., 0., 1., 0. };
206 : : // also define a plane tag ; this will be for each triangle
207 : 12 : char namePlaneTag[50] = { 0 };
208 : 12 : sprintf( namePlaneTag, "PLANE%lu", setId );
209 [ + - ]: 12 : rval = _mb->tag_get_handle( "PLANE", 4, MB_TYPE_DOUBLE, _planeTag, MB_TAG_DENSE | MB_TAG_CREAT, &defPlane );
210 [ - + ]: 12 : assert( rval == MB_SUCCESS );
211 : : // the fourth double is for weight, accumulated at each vertex so far
212 : : // maybe not needed in the end
213 [ + - ][ + - ]: 44585 : for( Range::iterator it = _triangles.begin(); it != _triangles.end(); ++it )
[ + - ][ + - ]
[ + + ]
214 : : {
215 [ + - ]: 44573 : EntityHandle tria = *it;
216 : : const EntityHandle* conn3;
217 : : int nnodes;
218 [ + - ]: 44573 : _mb->get_connectivity( tria, conn3, nnodes );
219 [ - + ]: 44573 : if( nnodes != 3 ) return 1; // error
220 : : // double coords[9]; // store the coordinates for the nodes
221 : : //_mb->get_coords(conn3, 3, coords);
222 [ + - ][ + + ]: 178292 : CartVect p[3];
223 [ + - ]: 44573 : _mb->get_coords( conn3, 3, (double*)&p[0] );
224 : : // need to compute the angles
225 : : // compute angles and the normal
226 : : // CartVect p1(&coords[0]), p2(&coords[3]), p3(&coords[6]);
227 : :
228 [ + - ]: 44573 : CartVect AB( p[1] - p[0] ); //(p2 - p1);
229 [ + - ]: 44573 : CartVect BC( p[2] - p[1] ); //(p3 - p2);
230 [ + - ]: 44573 : CartVect CA( p[0] - p[2] ); //(p1 - p3);
231 : : double a[3];
232 [ + - ][ + - ]: 44573 : a[1] = angle( AB, -BC ); // angle at B (p2), etc.
233 [ + - ][ + - ]: 44573 : a[2] = angle( BC, -CA );
234 [ + - ][ + - ]: 44573 : a[0] = angle( CA, -AB );
235 [ + - ][ + - ]: 44573 : CartVect normal = -AB * CA;
236 [ + - ]: 44573 : normal.normalize();
237 : : double plane[4];
238 : :
239 [ + - ]: 44573 : const double* coordNormal = normal.array();
240 : :
241 : 44573 : plane[0] = coordNormal[0];
242 : 44573 : plane[1] = coordNormal[1];
243 : 44573 : plane[2] = coordNormal[2];
244 [ + - ][ + - ]: 44573 : plane[3] = -normal % p[0]; // dot product
245 : : // set the plane
246 [ + - ]: 44573 : rval = _mb->tag_set_data( _planeTag, &tria, 1, plane );
247 [ - + ]: 44573 : assert( rval == MB_SUCCESS );
248 : :
249 : : // add to each vertex the tag value the normal multiplied by the angle
250 : : double values[9];
251 : :
252 [ + - ]: 44573 : _mb->tag_get_data( _gradientTag, conn3, 3, values );
253 [ + + ]: 178292 : for( int i = 0; i < 3; i++ )
254 : : {
255 : : // values[4*i]+=a[i]; // first is the weight, which we do not really need
256 : 133719 : values[3 * i + 0] += a[i] * coordNormal[0];
257 : 133719 : values[3 * i + 1] += a[i] * coordNormal[1];
258 : 133719 : values[3 * i + 2] += a[i] * coordNormal[2];
259 : : }
260 : :
261 : : // reset those values
262 [ + - ]: 44573 : _mb->tag_set_data( _gradientTag, conn3, 3, values );
263 : : }
264 : : // normalize the gradients at each node; maybe not needed here?
265 : : // no, we will do it, it is important
266 [ + - ]: 12 : int numNodes = _nodes.size();
267 [ + - ][ + - ]: 12 : double* normalVal = new double[3 * numNodes];
268 : : _mb->tag_get_data( _gradientTag, _nodes,
269 [ + - ]: 12 : normalVal ); // get all the normal values at the _nodes
270 [ + + ]: 23644 : for( int i = 0; i < numNodes; i++ )
271 : : {
272 [ + - ]: 23632 : CartVect p1( &normalVal[3 * i] );
273 [ + - ]: 23632 : p1.normalize();
274 [ + - ]: 23632 : p1.get( &normalVal[3 * i] );
275 : : }
276 : :
277 : : // reset the normal values after normalization
278 [ + - ]: 12 : _mb->tag_set_data( _gradientTag, _nodes, normalVal );
279 : : // print the loops size and some other stuff
280 [ - + ]: 12 : if( debug_surf_eval1 )
281 : : {
282 [ # # ][ # # ]: 0 : std::cout << " normals at " << numNodes << " nodes" << std::endl;
[ # # ][ # # ]
283 : 0 : int i = 0;
284 [ # # ][ # # ]: 0 : for( Range::iterator it = _nodes.begin(); it != _nodes.end(); ++it, i++ )
[ # # ][ # # ]
[ # # ]
285 : : {
286 [ # # ]: 0 : EntityHandle node = *it;
287 [ # # ][ # # ]: 0 : std::cout << " Node id " << _mb->id_from_handle( node ) << " " << normalVal[3 * i] << " "
[ # # ][ # # ]
[ # # ][ # # ]
288 [ # # ][ # # ]: 0 : << normalVal[3 * i + 1] << " " << normalVal[3 * i + 2] << std::endl;
[ # # ][ # # ]
289 : : }
290 : : }
291 : :
292 [ + - ]: 12 : delete[] normalVal;
293 : :
294 : 12 : return 0;
295 : : }
296 : :
297 : : // init bezier edges
298 : : // start copy
299 : : //===========================================================================
300 : : // Function Name: init_bezier_edge
301 : : //
302 : : // Member Type: PRIVATE
303 : : // Description: compute the control points for an edge
304 : : //===========================================================================
305 : 65526 : ErrorCode SmoothFace::init_bezier_edge( EntityHandle edge, double )
306 : : {
307 : : // min dot was used for angle here
308 : : // int stat = 0; // CUBIT_SUCCESS;
309 : : // all boundaries will be simple, initially
310 : : // we may complicate them afterwards
311 : :
312 [ + - ][ + + ]: 262104 : CartVect ctrl_pts[3];
313 : 65526 : int nnodes = 0;
314 : 65526 : const EntityHandle* conn2 = NULL;
315 [ + - ]: 65526 : ErrorCode rval = _mb->get_connectivity( edge, conn2, nnodes );
316 [ - + ]: 65526 : assert( rval == MB_SUCCESS );
317 [ - + ]: 65526 : if( MB_SUCCESS != rval ) return rval;
318 : :
319 [ - + ]: 65526 : assert( 2 == nnodes );
320 : : // double coords[6]; // store the coordinates for the nodes
321 [ + - ][ + + ]: 196578 : CartVect P[2];
322 : : // ErrorCode rval = _mb->get_coords(conn2, 2, coords);
323 [ + - ]: 65526 : rval = _mb->get_coords( conn2, 2, (double*)&P[0] );
324 [ - + ]: 65526 : assert( rval == MB_SUCCESS );
325 [ - + ]: 65526 : if( MB_SUCCESS != rval ) return rval;
326 : :
327 : : // CartVect P0(&coords[0]);
328 : : // CartVect P3(&coords[3]);
329 : :
330 : : // double normalVec[6];
331 [ + - ][ + + ]: 196578 : CartVect N[2];
332 : : //_mb->tag_get_data(_gradientTag, conn2, 2, normalVec);
333 [ + - ]: 65526 : rval = _mb->tag_get_data( _gradientTag, conn2, 2, (double*)&N[0] );
334 [ - + ]: 65526 : assert( rval == MB_SUCCESS );
335 [ - + ]: 65526 : if( MB_SUCCESS != rval ) return rval;
336 : :
337 [ + - ][ + + ]: 196578 : CartVect T[2]; // T0, T3
338 : :
339 [ + - ]: 65526 : rval = _mb->tag_get_data( _tangentsTag, &edge, 1, &T[0] );
340 [ - + ]: 65526 : assert( rval == MB_SUCCESS );
341 [ - + ]: 65526 : if( MB_SUCCESS != rval ) return rval;
342 : :
343 [ + - ]: 65526 : rval = init_edge_control_points( P[0], P[1], N[0], N[1], T[0], T[1], ctrl_pts );
344 [ - + ]: 65526 : assert( rval == MB_SUCCESS );
345 [ - + ]: 65526 : if( MB_SUCCESS != rval ) return rval;
346 : :
347 [ + - ]: 65526 : rval = _mb->tag_set_data( _edgeCtrlTag, &edge, 1, &ctrl_pts[0] );
348 [ - + ]: 65526 : assert( rval == MB_SUCCESS );
349 [ - + ]: 65526 : if( MB_SUCCESS != rval ) return rval;
350 : :
351 [ - + ]: 65526 : if( debug_surf_eval1 )
352 : : {
353 [ # # ][ # # ]: 0 : std::cout << "edge: " << _mb->id_from_handle( edge ) << " tangents: " << T[0] << T[1] << std::endl;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
354 [ # # ][ # # ]: 0 : std::cout << " points: " << P[0] << " " << P[1] << std::endl;
[ # # ][ # # ]
[ # # ]
355 [ # # ][ # # ]: 0 : std::cout << " normals: " << N[0] << " " << N[1] << std::endl;
[ # # ][ # # ]
[ # # ]
356 [ # # ][ # # ]: 0 : std::cout << " Control points " << ctrl_pts[0] << " " << ctrl_pts[1] << " " << ctrl_pts[2] << std::endl;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
357 : : }
358 : :
359 : 65526 : return MB_SUCCESS;
360 : : }
361 : :
362 : 12 : ErrorCode SmoothFace::compute_tangents_for_each_edge()
363 : : // they will be used for control points
364 : : {
365 : 12 : double defTangents[6] = { 0., 0., 0., 0., 0., 0. };
366 : : ErrorCode rval =
367 [ + - ]: 12 : _mb->tag_get_handle( "TANGENTS", 6, MB_TYPE_DOUBLE, _tangentsTag, MB_TAG_DENSE | MB_TAG_CREAT, &defTangents );
368 [ - + ]: 12 : if( MB_SUCCESS != rval ) return MB_FAILURE;
369 : :
370 : : // now, compute Tangents for all edges that are not on boundary, so they are not marked
371 [ + - ][ + - ]: 68205 : for( Range::iterator it = _edges.begin(); it != _edges.end(); ++it )
[ + - ][ + - ]
[ + + ]
372 : : {
373 [ + - ]: 68193 : EntityHandle edg = *it;
374 : :
375 : : int nnodes;
376 : : const EntityHandle* conn2; //
377 [ + - ]: 68193 : _mb->get_connectivity( edg, conn2, nnodes );
378 [ - + ]: 68193 : assert( nnodes == 2 );
379 [ + - ][ + + ]: 204579 : CartVect P[2]; // store the coordinates for the nodes
380 [ + - ]: 68193 : rval = _mb->get_coords( conn2, 2, (double*)&P[0] );
381 [ - + ]: 68193 : if( MB_SUCCESS != rval ) return rval;
382 [ - + ]: 68193 : assert( rval == MB_SUCCESS );
383 [ + - ][ + + ]: 204579 : CartVect T[2];
384 [ + - ]: 68193 : T[0] = P[1] - P[0];
385 [ + - ]: 68193 : T[0].normalize();
386 : 68193 : T[1] = T[0]; //
387 : : _mb->tag_set_data( _tangentsTag, &edg, 1,
388 [ + - ]: 68193 : (double*)&T[0] ); // set the tangents computed at every edge
389 : : }
390 : 12 : return MB_SUCCESS;
391 : : }
392 : : // start copy
393 : : //===========================================================================
394 : : // Function Name: init_edge_control_points
395 : : //
396 : : // Member Type: PRIVATE
397 : : // Description: compute the control points for an edge
398 : : //===========================================================================
399 : 68193 : ErrorCode SmoothFace::init_edge_control_points( CartVect& P0, CartVect& P3, CartVect& N0, CartVect& N3, CartVect& T0,
400 : : CartVect& T3, CartVect* Pi )
401 : : {
402 [ + - ][ + + ]: 340965 : CartVect Vi[4];
403 : 68193 : Vi[0] = P0;
404 : 68193 : Vi[3] = P3;
405 [ + - ]: 68193 : CartVect P03( P3 - P0 );
406 [ + - ]: 68193 : double di = P03.length();
407 [ + - ]: 68193 : double ai = N0 % N3; // this is the dot operator, the same as in cgm for CubitVector
408 [ + - ]: 68193 : double ai0 = N0 % T0;
409 [ + - ]: 68193 : double ai3 = N3 % T3;
410 : 68193 : double denom = 4 - ai * ai;
411 [ - + ]: 68193 : if( fabs( denom ) < 1e-20 )
412 : : {
413 : 0 : return MB_FAILURE; // CUBIT_FAILURE;
414 : : }
415 : 68193 : double row = 6.0e0 * ( 2.0e0 * ai0 + ai * ai3 ) / denom;
416 : 68193 : double omega = 6.0e0 * ( 2.0e0 * ai3 + ai * ai0 ) / denom;
417 [ + - ][ + - ]: 68193 : Vi[1] = Vi[0] + ( di * ( ( ( 6.0e0 * T0 ) - ( ( 2.0e0 * row ) * N0 ) + ( omega * N3 ) ) / 18.0e0 ) );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
418 [ + - ][ + - ]: 68193 : Vi[2] = Vi[3] - ( di * ( ( ( 6.0e0 * T3 ) + ( row * N0 ) - ( ( 2.0e0 * omega ) * N3 ) ) / 18.0e0 ) );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
419 : : // CartVect Wi[3];
420 : : // Wi[0] = Vi[1] - Vi[0];
421 : : // Wi[1] = Vi[2] - Vi[1];
422 : : // Wi[2] = Vi[3] - Vi[2];
423 : :
424 [ + - ][ + - ]: 68193 : Pi[0] = 0.25 * Vi[0] + 0.75 * Vi[1];
[ + - ]
425 [ + - ][ + - ]: 68193 : Pi[1] = 0.50 * Vi[1] + 0.50 * Vi[2];
[ + - ]
426 [ + - ][ + - ]: 68193 : Pi[2] = 0.75 * Vi[2] + 0.25 * Vi[3];
[ + - ]
427 : :
428 : 68193 : return MB_SUCCESS;
429 : : }
430 : :
431 : 44573 : ErrorCode SmoothFace::find_edges_orientations( EntityHandle edges[3], const EntityHandle* conn3,
432 : : int orient[3] ) // maybe we will set it?
433 : : {
434 : : // find the edge that is adjacent to 2 vertices at a time
435 [ + + ]: 178292 : for( int i = 0; i < 3; i++ )
436 : : {
437 : : // edge 0 is 1-2, 1 is 3-1, 2 is 0-1
438 : : EntityHandle v[2];
439 : 133719 : v[0] = conn3[( i + 1 ) % 3];
440 : 133719 : v[1] = conn3[( i + 2 ) % 3];
441 [ + - ]: 133719 : std::vector< EntityHandle > adjacencies;
442 : : // generate all edges for these two hexes
443 [ + - ]: 133719 : ErrorCode rval = _mb->get_adjacencies( v, 2, 1, false, adjacencies, Interface::INTERSECT );
444 [ - + ]: 133719 : if( MB_SUCCESS != rval ) return rval;
445 : :
446 : : // find the edge connected to both vertices, and then see its orientation
447 [ - + ]: 133719 : assert( adjacencies.size() == 1 );
448 : 133719 : const EntityHandle* conn2 = NULL;
449 : 133719 : int nnodes = 0;
450 [ + - ][ + - ]: 133719 : rval = _mb->get_connectivity( adjacencies[0], conn2, nnodes );
451 [ - + ]: 133719 : assert( rval == MB_SUCCESS );
452 [ - + ]: 133719 : assert( 2 == nnodes );
453 [ + - ]: 133719 : edges[i] = adjacencies[0];
454 : : // what is the story morning glory?
455 [ + + ][ + - ]: 133719 : if( conn2[0] == v[0] && conn2[1] == v[1] )
456 : 68177 : orient[i] = 1;
457 [ + - ][ + - ]: 65542 : else if( conn2[0] == v[1] && conn2[1] == v[0] )
458 : 65542 : orient[i] = -1;
459 : : else
460 [ + - ]: 133719 : return MB_FAILURE;
461 : 133719 : }
462 : 44573 : return MB_SUCCESS;
463 : : }
464 : 12 : ErrorCode SmoothFace::compute_internal_control_points_on_facets( double, Tag facetCtrlTag, Tag facetEdgeCtrlTag )
465 : : {
466 : : // collect from each triangle the control points in order
467 : : //
468 : :
469 : 12 : _facetCtrlTag = facetCtrlTag;
470 : 12 : _facetEdgeCtrlTag = facetEdgeCtrlTag;
471 : :
472 [ + - ][ + - ]: 44585 : for( Range::iterator it = _triangles.begin(); it != _triangles.end(); ++it )
[ + - ][ + - ]
[ + + ]
473 : : {
474 [ + - ]: 44573 : EntityHandle tri = *it;
475 : : // first get connectivity, and the edges
476 : : // we need a fast method to retrieve the adjacent edges to each triangle
477 : : const EntityHandle* conn3;
478 : : int nnodes;
479 [ + - ]: 44573 : ErrorCode rval = _mb->get_connectivity( tri, conn3, nnodes );
480 [ - + ]: 44573 : assert( MB_SUCCESS == rval );
481 [ - + ]: 44573 : if( MB_SUCCESS != rval ) return rval;
482 [ - + ]: 44573 : assert( 3 == nnodes );
483 : :
484 : : // would it be easier to do
485 [ + - ][ + + ]: 178292 : CartVect vNode[3]; // position at nodes
486 [ + - ]: 44573 : rval = _mb->get_coords( conn3, 3, (double*)&vNode[0] );
487 [ - + ]: 44573 : assert( MB_SUCCESS == rval );
488 [ - + ]: 44573 : if( MB_SUCCESS != rval ) return rval;
489 : :
490 : : // get gradients (normal) at each node of triangle
491 [ + - ][ + + ]: 178292 : CartVect NN[3];
492 [ + - ]: 44573 : rval = _mb->tag_get_data( _gradientTag, conn3, 3, &NN[0] );
493 [ - + ]: 44573 : assert( MB_SUCCESS == rval );
494 [ - + ]: 44573 : if( MB_SUCCESS != rval ) return rval;
495 : :
496 : : EntityHandle edges[3];
497 : : int orient[3]; // + 1 or -1, if the edge is positive or negative within the face
498 [ + - ]: 44573 : rval = find_edges_orientations( edges, conn3, orient ); // maybe we will set it?
499 [ - + ]: 44573 : assert( MB_SUCCESS == rval );
500 [ - + ]: 44573 : if( MB_SUCCESS != rval ) return rval;
501 : : // maybe we will store some tags with edges and their orientation with respect to
502 : : // a triangle;
503 [ + - ][ + + ]: 846887 : CartVect P[3][5];
[ + + ]
504 [ + - ][ + + ]: 579449 : CartVect N[6], G[6];
[ + - ][ + + ]
505 : : // create the linear array for control points on edges, for storage (expensive !!!)
506 [ + - ][ + + ]: 445730 : CartVect CP[9];
507 : 44573 : int index = 0;
508 : : // maybe store a tag / entity handle for edges?
509 [ + + ]: 178292 : for( int i = 0; i < 3; i++ )
510 : : {
511 : : // populate P and N with the right vectors
512 : 133719 : int i1 = ( i + 1 ) % 3; // the first node of the edge
513 : 133719 : int i2 = ( i + 2 ) % 3; // the second node of the edge
514 : 133719 : N[2 * i] = NN[i1];
515 : 133719 : N[2 * i + 1] = NN[i2];
516 : 133719 : P[i][0] = vNode[i1];
517 [ + - ]: 133719 : rval = _mb->tag_get_data( _edgeCtrlTag, &edges[i], 1, &( P[i][1] ) );
518 : : // if sense is -1, swap 1 and 3 control points
519 [ + + ]: 133719 : if( orient[i] == -1 )
520 : : {
521 [ + - ]: 65542 : CartVect tmp;
522 : 65542 : tmp = P[i][1];
523 : 65542 : P[i][1] = P[i][3];
524 : 65542 : P[i][3] = tmp;
525 : : }
526 : 133719 : P[i][4] = vNode[i2];
527 [ + + ]: 534876 : for( int j = 1; j < 4; j++ )
528 : 401157 : CP[index++] = P[i][j];
529 : :
530 : : // the first edge control points
531 : : }
532 : :
533 : : // stat = facet->get_edge_control_points( P );
534 [ + - ]: 44573 : init_facet_control_points( N, P, G );
535 : : // what do we need to store in the tag control points?
536 [ + - ]: 44573 : rval = _mb->tag_set_data( _facetCtrlTag, &tri, 1, &G[0] );
537 [ - + ]: 44573 : assert( MB_SUCCESS == rval );
538 [ - + ]: 44573 : if( MB_SUCCESS != rval ) return rval;
539 : :
540 : : // store here again the 9 control points on the edges
541 [ + - ]: 44573 : rval = _mb->tag_set_data( _facetEdgeCtrlTag, &tri, 1, &CP[0] );
542 [ - + ]: 44573 : assert( MB_SUCCESS == rval );
543 [ - + ]: 44573 : if( MB_SUCCESS != rval ) return rval;
544 : : // look at what we retrieve later
545 : :
546 : : // adjust the bounding box
547 : 44573 : int j = 0;
548 [ + + ]: 178292 : for( j = 0; j < 3; j++ )
549 [ + - ]: 133719 : adjust_bounding_box( vNode[j] );
550 : : // edge control points
551 [ + + ]: 445730 : for( j = 0; j < 9; j++ )
552 [ + - ]: 401157 : adjust_bounding_box( CP[j] );
553 : : // internal facet control points
554 [ + + ]: 312011 : for( j = 0; j < 6; j++ )
555 [ + - ]: 267438 : adjust_bounding_box( G[j] );
556 : : }
557 : 12 : return MB_SUCCESS;
558 : : }
559 : 802314 : void SmoothFace::adjust_bounding_box( CartVect& vect )
560 : : {
561 : : // _minim, _maxim
562 [ + + ]: 3209256 : for( int j = 0; j < 3; j++ )
563 : : {
564 [ + + ]: 2406942 : if( _minim[j] > vect[j] ) _minim[j] = vect[j];
565 [ + + ]: 2406942 : if( _maxim[j] < vect[j] ) _maxim[j] = vect[j];
566 : : }
567 : 802314 : }
568 : : //===============================================================
569 : : ////Function Name: init_facet_control_points
570 : : ////
571 : : ////Member Type: PRIVATE
572 : : ////Description: compute the control points for a facet
573 : : ////===============================================================
574 : 44573 : ErrorCode SmoothFace::init_facet_control_points( CartVect N[6], // vertex normals (per edge)
575 : : CartVect P[3][5], // edge control points
576 : : CartVect G[6] ) // return internal control points
577 : : {
578 [ + - ][ + + ]: 668595 : CartVect Di[4], Ai[3], N0, N3, Vi[4], Wi[3];
[ + - ][ + + ]
[ + - ][ + - ]
[ + - ][ + + ]
[ + - ][ + + ]
579 : : double denom;
580 : : double lambda[2], mu[2];
581 : :
582 : 44573 : ErrorCode rval = MB_SUCCESS;
583 : :
584 [ + + ]: 178292 : for( int i = 0; i < 3; i++ )
585 : : {
586 : 133719 : N0 = N[i * 2];
587 : 133719 : N3 = N[i * 2 + 1];
588 : 133719 : Vi[0] = P[i][0];
589 [ + - ][ + - ]: 133719 : Vi[1] = ( P[i][1] - 0.25 * P[i][0] ) / 0.75;
[ + - ]
590 [ + - ][ + - ]: 133719 : Vi[2] = ( P[i][3] - 0.25 * P[i][4] ) / 0.75;
[ + - ]
591 : 133719 : Vi[3] = P[i][4];
592 [ + - ]: 133719 : Wi[0] = Vi[1] - Vi[0];
593 [ + - ]: 133719 : Wi[1] = Vi[2] - Vi[1];
594 [ + - ]: 133719 : Wi[2] = Vi[3] - Vi[2];
595 [ + - ][ + - ]: 133719 : Di[0] = P[( i + 2 ) % 3][3] - 0.5 * ( P[i][1] + P[i][0] );
[ + - ]
596 [ + - ][ + - ]: 133719 : Di[3] = P[( i + 1 ) % 3][1] - 0.5 * ( P[i][4] + P[i][3] );
[ + - ]
597 [ + - ][ + - ]: 133719 : Ai[0] = ( N0 * Wi[0] ) / Wi[0].length();
[ + - ]
598 [ + - ][ + - ]: 133719 : Ai[2] = ( N3 * Wi[2] ) / Wi[2].length();
[ + - ]
599 [ + - ]: 133719 : Ai[1] = Ai[0] + Ai[2];
600 [ + - ]: 133719 : denom = Ai[1].length();
601 [ + - ]: 133719 : Ai[1] /= denom;
602 [ + - ][ + - ]: 133719 : lambda[0] = ( Di[0] % Wi[0] ) / ( Wi[0] % Wi[0] );
603 [ + - ][ + - ]: 133719 : lambda[1] = ( Di[3] % Wi[2] ) / ( Wi[2] % Wi[2] );
604 [ + - ]: 133719 : mu[0] = ( Di[0] % Ai[0] );
605 [ + - ]: 133719 : mu[1] = ( Di[3] % Ai[2] );
606 [ + - ][ + - ]: 133719 : G[i * 2] = 0.5 * ( P[i][1] + P[i][2] ) + 0.66666666666666 * lambda[0] * Wi[1] +
[ + - ][ + - ]
[ + - ]
607 [ + - ][ + - ]: 267438 : 0.33333333333333 * lambda[1] * Wi[0] + 0.66666666666666 * mu[0] * Ai[1] +
[ + - ]
608 [ + - ][ + - ]: 267438 : 0.33333333333333 * mu[1] * Ai[0];
609 [ + - ][ + - ]: 133719 : G[i * 2 + 1] = 0.5 * ( P[i][2] + P[i][3] ) + 0.33333333333333 * lambda[0] * Wi[2] +
[ + - ][ + - ]
[ + - ]
610 [ + - ][ + - ]: 267438 : 0.66666666666666 * lambda[1] * Wi[1] + 0.33333333333333 * mu[0] * Ai[2] +
[ + - ]
611 [ + - ][ + - ]: 267438 : 0.66666666666666 * mu[1] * Ai[1];
612 : : }
613 : 44573 : return rval;
614 : : }
615 : :
616 : 0 : void SmoothFace::DumpModelControlPoints()
617 : : {
618 : : // here, we will dump all control points from edges and facets (6 control points for each facet)
619 : : // we may also create some edges; maybe later...
620 : : // create a point3D file
621 : : // output a Point3D file (special visit format)
622 [ # # ]: 0 : unsigned long setId = _mb->id_from_handle( _set );
623 : 0 : char name[50] = { 0 };
624 : 0 : sprintf( name, "%lucontrol.Point3D", setId ); // name should be something 2control.Point3D
625 [ # # ]: 0 : std::ofstream point3DFile;
626 [ # # ][ # # ]: 0 : point3DFile.open( name ); //("control.Point3D");
627 [ # # ]: 0 : point3DFile << "# x y z \n";
628 [ # # ]: 0 : std::ofstream point3DEdgeFile;
629 : 0 : sprintf( name, "%lucontrolEdge.Point3D", setId ); //
630 [ # # ][ # # ]: 0 : point3DEdgeFile.open( name ); //("controlEdge.Point3D");
631 [ # # ]: 0 : point3DEdgeFile << "# x y z \n";
632 [ # # ]: 0 : std::ofstream smoothPoints;
633 : 0 : sprintf( name, "%lusmooth.Point3D", setId ); //
634 [ # # ][ # # ]: 0 : smoothPoints.open( name ); //("smooth.Point3D");
635 [ # # ]: 0 : smoothPoints << "# x y z \n";
636 [ # # ][ # # ]: 0 : CartVect controlPoints[3]; // edge control points
637 [ # # ][ # # ]: 0 : for( Range::iterator it = _edges.begin(); it != _edges.end(); ++it )
[ # # ][ # # ]
[ # # ]
638 : : {
639 [ # # ]: 0 : EntityHandle edge = *it;
640 : :
641 [ # # ]: 0 : _mb->tag_get_data( _edgeCtrlTag, &edge, 1, (double*)&controlPoints[0] );
642 [ # # ]: 0 : for( int i = 0; i < 3; i++ )
643 : : {
644 : 0 : CartVect& c = controlPoints[i];
645 [ # # ][ # # ]: 0 : point3DEdgeFile << std::setprecision( 11 ) << c[0] << " " << c[1] << " " << c[2] << " \n";
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
646 : : }
647 : : }
648 [ # # ][ # # ]: 0 : CartVect controlTriPoints[6]; // triangle control points
649 [ # # ][ # # ]: 0 : CartVect P_facet[3]; // result in 3 "mid" control points
650 [ # # ][ # # ]: 0 : for( Range::iterator it2 = _triangles.begin(); it2 != _triangles.end(); ++it2 )
[ # # ][ # # ]
[ # # ]
651 : : {
652 [ # # ]: 0 : EntityHandle tri = *it2;
653 : :
654 [ # # ]: 0 : _mb->tag_get_data( _facetCtrlTag, &tri, 1, (double*)&controlTriPoints[0] );
655 : :
656 : : // draw a line of points between pairs of control points
657 : 0 : int numPoints = 7;
658 [ # # ]: 0 : for( int n = 0; n < numPoints; n++ )
659 : : {
660 : 0 : double a = 1. * n / ( numPoints - 1 );
661 : 0 : double b = 1.0 - a;
662 : :
663 [ # # ][ # # ]: 0 : P_facet[0] = a * controlTriPoints[3] + b * controlTriPoints[4];
[ # # ]
664 : : // 1,2,1
665 [ # # ][ # # ]: 0 : P_facet[1] = a * controlTriPoints[0] + b * controlTriPoints[5];
[ # # ]
666 : : // 1,1,2
667 [ # # ][ # # ]: 0 : P_facet[2] = a * controlTriPoints[1] + b * controlTriPoints[2];
[ # # ]
668 [ # # ]: 0 : for( int i = 0; i < 3; i++ )
669 : : {
670 : 0 : CartVect& c = P_facet[i];
671 [ # # ][ # # ]: 0 : point3DFile << std::setprecision( 11 ) << c[0] << " " << c[1] << " " << c[2] << " \n";
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
672 : : }
673 : : }
674 : :
675 : : // evaluate for each triangle a lattice of points
676 : 0 : int N = 40;
677 [ # # ]: 0 : for( int k = 0; k <= N; k++ )
678 : : {
679 [ # # ]: 0 : for( int m = 0; m <= N - k; m++ )
680 : : {
681 : 0 : int n = N - m - k;
682 [ # # ]: 0 : CartVect areacoord( 1. * k / N, 1. * m / N, 1. * n / N );
683 [ # # ]: 0 : CartVect pt;
684 [ # # ]: 0 : eval_bezier_patch( tri, areacoord, pt );
685 [ # # ][ # # ]: 0 : smoothPoints << std::setprecision( 11 ) << pt[0] << " " << pt[1] << " " << pt[2] << " \n";
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
686 : : }
687 : : }
688 : : }
689 [ # # ]: 0 : point3DFile.close();
690 [ # # ]: 0 : smoothPoints.close();
691 [ # # ]: 0 : point3DEdgeFile.close();
692 : 0 : return;
693 : : }
694 : : //===========================================================================
695 : : // Function Name: evaluate_single
696 : : //
697 : : // Member Type: PUBLIC
698 : : // Description: evaluate edge not associated with a facet (this is used
699 : : // by camal edge mesher!!!)
700 : : // Note: t is a value from 0 to 1, for us
701 : : //===========================================================================
702 : 0 : ErrorCode SmoothFace::evaluate_smooth_edge( EntityHandle eh, double& tt, CartVect& outv )
703 : : {
704 [ # # ][ # # ]: 0 : CartVect P[2]; // P0 and P1
705 [ # # ][ # # ]: 0 : CartVect controlPoints[3]; // edge control points
706 : : double t4, t3, t2, one_minus_t, one_minus_t2, one_minus_t3, one_minus_t4;
707 : :
708 : : // project the position to the linear edge
709 : : // t is from 0 to 1 only!!
710 : : // double tt = (t + 1) * 0.5;
711 [ # # ]: 0 : if( tt <= 0.0 ) tt = 0.0;
712 [ # # ]: 0 : if( tt >= 1.0 ) tt = 1.0;
713 : :
714 : 0 : int nnodes = 0;
715 : 0 : const EntityHandle* conn2 = NULL;
716 [ # # ]: 0 : ErrorCode rval = _mb->get_connectivity( eh, conn2, nnodes );
717 [ # # ]: 0 : assert( rval == MB_SUCCESS );
718 [ # # ]: 0 : if( MB_SUCCESS != rval ) return rval;
719 : :
720 [ # # ]: 0 : rval = _mb->get_coords( conn2, 2, (double*)&P[0] );
721 [ # # ]: 0 : assert( rval == MB_SUCCESS );
722 [ # # ]: 0 : if( MB_SUCCESS != rval ) return rval;
723 : :
724 [ # # ]: 0 : rval = _mb->tag_get_data( _edgeCtrlTag, &eh, 1, (double*)&controlPoints[0] );
725 [ # # ]: 0 : assert( rval == MB_SUCCESS );
726 [ # # ]: 0 : if( MB_SUCCESS != rval ) return rval;
727 : :
728 : 0 : t2 = tt * tt;
729 : 0 : t3 = t2 * tt;
730 : 0 : t4 = t3 * tt;
731 : 0 : one_minus_t = 1. - tt;
732 : 0 : one_minus_t2 = one_minus_t * one_minus_t;
733 : 0 : one_minus_t3 = one_minus_t2 * one_minus_t;
734 : 0 : one_minus_t4 = one_minus_t3 * one_minus_t;
735 : :
736 [ # # ][ # # ]: 0 : outv = one_minus_t4 * P[0] + 4. * one_minus_t3 * tt * controlPoints[0] + 6. * one_minus_t2 * t2 * controlPoints[1] +
[ # # ][ # # ]
[ # # ][ # # ]
737 [ # # ][ # # ]: 0 : 4. * one_minus_t * t3 * controlPoints[2] + t4 * P[1];
[ # # ]
738 : :
739 : 0 : return MB_SUCCESS;
740 : : }
741 : :
742 : 37090 : ErrorCode SmoothFace::eval_bezier_patch( EntityHandle tri, CartVect& areacoord, CartVect& pt )
743 : : {
744 : : //
745 : : // interpolate internal control points
746 : :
747 [ + - ][ + + ]: 259630 : CartVect gctrl_pts[6];
748 : : // get the control points facet->get_control_points( gctrl_pts );
749 : : // init_facet_control_points( N, P, G) ;
750 : : // what do we need to store in the tag control points?
751 [ + - ]: 37090 : ErrorCode rval = _mb->tag_get_data( _facetCtrlTag, &tri, 1, &gctrl_pts[0] ); // get all 6 control points
752 [ - + ]: 37090 : assert( MB_SUCCESS == rval );
753 [ - + ]: 37090 : if( MB_SUCCESS != rval ) return rval;
754 : 37090 : const EntityHandle* conn3 = NULL;
755 : 37090 : int nnodes = 0;
756 [ + - ]: 37090 : rval = _mb->get_connectivity( tri, conn3, nnodes );
757 [ - + ]: 37090 : assert( MB_SUCCESS == rval );
758 : :
759 [ + - ][ + + ]: 148360 : CartVect vN[3];
760 [ + - ]: 37090 : _mb->get_coords( conn3, 3, (double*)&vN[0] ); // fill the coordinates of the vertices
761 : :
762 [ + - ][ + - ]: 37090 : if( fabs( areacoord[1] + areacoord[2] ) < 1.0e-6 )
[ + + ]
763 : : {
764 : 2 : pt = vN[0];
765 : 2 : return MB_SUCCESS;
766 : : }
767 [ + - ][ + - ]: 37088 : if( fabs( areacoord[0] + areacoord[2] ) < 1.0e-6 )
[ - + ]
768 : : {
769 : 0 : pt = vN[0];
770 : 0 : return MB_SUCCESS;
771 : : }
772 [ + - ][ + - ]: 37088 : if( fabs( areacoord[0] + areacoord[1] ) < 1.0e-6 )
[ + + ]
773 : : {
774 : 4 : pt = vN[0];
775 : 4 : return MB_SUCCESS;
776 : : }
777 : :
778 [ + - ][ + + ]: 148336 : CartVect P_facet[3];
779 : : // 2,1,1
780 : : P_facet[0] =
781 [ + - ][ + - ]: 37084 : ( 1.0e0 / ( areacoord[1] + areacoord[2] ) ) * ( areacoord[1] * gctrl_pts[3] + areacoord[2] * gctrl_pts[4] );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
782 : : // 1,2,1
783 : : P_facet[1] =
784 [ + - ][ + - ]: 37084 : ( 1.0e0 / ( areacoord[0] + areacoord[2] ) ) * ( areacoord[0] * gctrl_pts[0] + areacoord[2] * gctrl_pts[5] );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
785 : : // 1,1,2
786 : : P_facet[2] =
787 [ + - ][ + - ]: 37084 : ( 1.0e0 / ( areacoord[0] + areacoord[1] ) ) * ( areacoord[0] * gctrl_pts[1] + areacoord[1] * gctrl_pts[2] );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
788 : :
789 : : // sum the contribution from each of the control points
790 : :
791 [ + - ]: 37084 : pt = CartVect( 0. ); // set all to 0, we start adding / accumulating different parts
792 : : // first edge is from node 0 to 1, index 2 in
793 : :
794 : : // retrieve the points, in order, and the control points on edges
795 : :
796 : : // store here again the 9 control points on the edges
797 [ + - ][ + + ]: 370840 : CartVect CP[9];
798 [ + - ]: 37084 : rval = _mb->tag_get_data( _facetEdgeCtrlTag, &tri, 1, &CP[0] );
799 [ - + ]: 37084 : assert( MB_SUCCESS == rval );
800 : :
801 : : // CubitFacetEdge *edge;
802 : : // edge = facet->edge(2);! start with edge 2, from 0-1
803 : 37084 : int k = 0;
804 [ + - ][ + + ]: 222504 : CartVect ctrl_pts[5];
805 : : // edge->control_points(facet, ctrl_pts);
806 : 37084 : ctrl_pts[0] = vN[0]; //
807 [ + + ]: 148336 : for( k = 1; k < 4; k++ )
808 : 111252 : ctrl_pts[k] = CP[k + 5]; // for edge index 2
809 : 37084 : ctrl_pts[4] = vN[1]; //
810 : :
811 : : // i=4; j=0; k=0;
812 [ + - ][ + - ]: 37084 : double B = mbquart( areacoord[0] );
[ + - ][ + - ]
813 [ + - ][ + - ]: 37084 : pt += B * ctrl_pts[0];
814 : :
815 : : // i=3; j=1; k=0;
816 [ + - ][ + - ]: 37084 : B = 4.0 * mbcube( areacoord[0] ) * areacoord[1];
[ + - ][ + - ]
817 [ + - ][ + - ]: 37084 : pt += B * ctrl_pts[1];
818 : :
819 : : // i=2; j=2; k=0;
820 [ + - ][ + - ]: 37084 : B = 6.0 * mbsqr( areacoord[0] ) * mbsqr( areacoord[1] );
[ + - ][ + - ]
821 [ + - ][ + - ]: 37084 : pt += B * ctrl_pts[2];
822 : :
823 : : // i=1; j=3; k=0;
824 [ + - ][ + - ]: 37084 : B = 4.0 * areacoord[0] * mbcube( areacoord[1] );
[ + - ][ + - ]
825 [ + - ][ + - ]: 37084 : pt += B * ctrl_pts[3];
826 : :
827 : : // edge = facet->edge(0);
828 : : // edge->control_points(facet, ctrl_pts);
829 : : // edge index 0, from 1 to 2
830 : 37084 : ctrl_pts[0] = vN[1]; //
831 [ + + ]: 148336 : for( k = 1; k < 4; k++ )
832 : 111252 : ctrl_pts[k] = CP[k - 1]; // for edge index 0
833 : 37084 : ctrl_pts[4] = vN[2]; //
834 : :
835 : : // i=0; j=4; k=0;
836 [ + - ][ + - ]: 37084 : B = mbquart( areacoord[1] );
[ + - ][ + - ]
837 [ + - ][ + - ]: 37084 : pt += B * ctrl_pts[0];
838 : :
839 : : // i=0; j=3; k=1;
840 [ + - ][ + - ]: 37084 : B = 4.0 * mbcube( areacoord[1] ) * areacoord[2];
[ + - ][ + - ]
841 [ + - ][ + - ]: 37084 : pt += B * ctrl_pts[1];
842 : :
843 : : // i=0; j=2; k=2;
844 [ + - ][ + - ]: 37084 : B = 6.0 * mbsqr( areacoord[1] ) * mbsqr( areacoord[2] );
[ + - ][ + - ]
845 [ + - ][ + - ]: 37084 : pt += B * ctrl_pts[2];
846 : :
847 : : // i=0; j=1; k=3;
848 [ + - ][ + - ]: 37084 : B = 4.0 * areacoord[1] * mbcube( areacoord[2] );
[ + - ][ + - ]
849 [ + - ][ + - ]: 37084 : pt += B * ctrl_pts[3];
850 : :
851 : : // edge = facet->edge(1);
852 : : // edge->control_points(facet, ctrl_pts);
853 : : // edge index 1, from 2 to 0
854 : 37084 : ctrl_pts[0] = vN[2]; //
855 [ + + ]: 148336 : for( k = 1; k < 4; k++ )
856 : 111252 : ctrl_pts[k] = CP[k + 2]; // for edge index 0
857 : 37084 : ctrl_pts[4] = vN[0]; //
858 : :
859 : : // i=0; j=0; k=4;
860 [ + - ][ + - ]: 37084 : B = mbquart( areacoord[2] );
[ + - ][ + - ]
861 [ + - ][ + - ]: 37084 : pt += B * ctrl_pts[0];
862 : :
863 : : // i=1; j=0; k=3;
864 [ + - ][ + - ]: 37084 : B = 4.0 * areacoord[0] * mbcube( areacoord[2] );
[ + - ][ + - ]
865 [ + - ][ + - ]: 37084 : pt += B * ctrl_pts[1];
866 : :
867 : : // i=2; j=0; k=2;
868 [ + - ][ + - ]: 37084 : B = 6.0 * mbsqr( areacoord[0] ) * mbsqr( areacoord[2] );
[ + - ][ + - ]
869 [ + - ][ + - ]: 37084 : pt += B * ctrl_pts[2];
870 : :
871 : : // i=3; j=0; k=1;
872 [ + - ][ + - ]: 37084 : B = 4.0 * mbcube( areacoord[0] ) * areacoord[2];
[ + - ][ + - ]
873 [ + - ][ + - ]: 37084 : pt += B * ctrl_pts[3];
874 : :
875 : : // i=2; j=1; k=1;
876 [ + - ][ + - ]: 37084 : B = 12.0 * mbsqr( areacoord[0] ) * areacoord[1] * areacoord[2];
[ + - ][ + - ]
877 [ + - ][ + - ]: 37084 : pt += B * P_facet[0];
878 : :
879 : : // i=1; j=2; k=1;
880 [ + - ][ + - ]: 37084 : B = 12.0 * areacoord[0] * mbsqr( areacoord[1] ) * areacoord[2];
[ + - ][ + - ]
881 [ + - ][ + - ]: 37084 : pt += B * P_facet[1];
882 : :
883 : : // i=1; j=1; k=2;
884 [ + - ][ + - ]: 37084 : B = 12.0 * areacoord[0] * areacoord[1] * mbsqr( areacoord[2] );
[ + - ][ + - ]
885 [ + - ][ + - ]: 37084 : pt += B * P_facet[2];
886 : :
887 : 37090 : return MB_SUCCESS;
888 : : }
889 : :
890 : : //===========================================================================
891 : : // Function Name: project_to_facet_plane
892 : : //
893 : : // Member Type: PUBLIC
894 : : // Descriptoin: Project a point to the plane of a facet
895 : : //===========================================================================
896 : 2680 : void SmoothFace::project_to_facet_plane( EntityHandle tri, CartVect& pt, CartVect& point_on_plane,
897 : : double& dist_to_plane )
898 : : {
899 : : double plane[4];
900 : :
901 [ + - ]: 2680 : ErrorCode rval = _mb->tag_get_data( _planeTag, &tri, 1, plane );
902 [ - + ]: 2680 : if( MB_SUCCESS != rval ) return;
903 [ - + ]: 2680 : assert( rval == MB_SUCCESS );
904 : : // _planeTag
905 [ + - ]: 2680 : CartVect normal( &plane[0] ); // just first 3 components are used
906 : :
907 [ + - ]: 2680 : double dist = normal % pt + plane[3]; // coeff d is saved!!!
908 : 2680 : dist_to_plane = fabs( dist );
909 [ + - ][ + - ]: 2680 : point_on_plane = pt - dist * normal;
910 : :
911 : 2680 : return;
912 : : }
913 : :
914 : : //===========================================================================
915 : : // Function Name: facet_area_coordinate
916 : : //
917 : : // Member Type: PUBLIC
918 : : // Descriptoin: Determine the area coordinates of a point on the plane
919 : : // of a facet
920 : : //===========================================================================
921 : 2680 : void SmoothFace::facet_area_coordinate( EntityHandle facet, CartVect& pt_on_plane, CartVect& areacoord )
922 : : {
923 : :
924 : 2680 : const EntityHandle* conn3 = NULL;
925 : 2680 : int nnodes = 0;
926 [ + - ]: 2680 : ErrorCode rval = _mb->get_connectivity( facet, conn3, nnodes );
927 [ - + ]: 2680 : assert( MB_SUCCESS == rval );
928 : : if( rval ) {} // empty statement to prevent compiler warning
929 : :
930 : : // double coords[9]; // store the coordinates for the nodes
931 : : //_mb->get_coords(conn3, 3, coords);
932 [ + - ][ + + ]: 10720 : CartVect p[3];
933 [ + - ]: 2680 : rval = _mb->get_coords( conn3, 3, (double*)&p[0] );
934 [ - + ]: 2680 : assert( MB_SUCCESS == rval );
935 : : if( rval ) {} // empty statement to prevent compiler warning
936 : : double plane[4];
937 : :
938 [ + - ]: 2680 : rval = _mb->tag_get_data( _planeTag, &facet, 1, plane );
939 [ - + ]: 2680 : assert( rval == MB_SUCCESS );
940 : : if( rval ) {} // empty statement to prevent compiler warning
941 [ + - ]: 2680 : CartVect normal( &plane[0] ); // just first 3 components are used
942 : :
943 : : double area2;
944 : :
945 : 2680 : double tol = GEOMETRY_RESABS * 1.e-5; // 1.e-11;
946 : :
947 [ + - ]: 2680 : CartVect v1( p[1] - p[0] );
948 [ + - ]: 2680 : CartVect v2( p[2] - p[0] );
949 : :
950 [ + - ][ + - ]: 2680 : area2 = ( v1 * v2 ).length_squared(); // the same for CartVect
951 [ - + ]: 2680 : if( area2 < 100 * tol ) { tol = .01 * area2; }
952 [ + - ][ + - ]: 2680 : CartVect absnorm( fabs( normal[0] ), fabs( normal[1] ), fabs( normal[2] ) );
[ + - ][ + - ]
953 : :
954 : : // project to the closest coordinate plane so we only have to do this in 2D
955 : :
956 [ + - ][ + - ]: 2680 : if( absnorm[0] >= absnorm[1] && absnorm[0] >= absnorm[2] )
[ + + ][ + - ]
[ + - ][ + + ]
[ + + ]
957 : : {
958 [ + - ][ + - ]: 85 : area2 = determ3( p[0][1], p[0][2], p[1][1], p[1][2], p[2][1], p[2][2] );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
959 [ - + ]: 85 : if( fabs( area2 ) < tol )
960 : : {
961 [ # # ]: 0 : areacoord = CartVect( -std::numeric_limits< double >::min() ); // .set(
962 : : // -std::numeric_limits<double>::min(),
963 : : // -std::numeric_limits<double>::min(),
964 : : // -std::numeric_limits<double>::min() );
965 : : }
966 [ + - ][ - + ]: 85 : else if( within_tolerance( p[0], pt_on_plane, GEOMETRY_RESABS ) )
967 : : {
968 [ # # ]: 0 : areacoord = CartVect( 1., 0., 0. ); //.set( 1.0, 0.0, 0.0 );
969 : : }
970 [ + - ][ - + ]: 85 : else if( within_tolerance( p[1], pt_on_plane, GEOMETRY_RESABS ) )
971 : : {
972 [ # # ]: 0 : areacoord = CartVect( 0., 1., 0. ); //.set( 0.0, 1.0, 0.0 );
973 : : }
974 [ + - ][ - + ]: 85 : else if( within_tolerance( p[2], pt_on_plane, GEOMETRY_RESABS ) )
975 : : {
976 [ # # ]: 0 : areacoord = CartVect( 0., 0., 1. ); //.set( 0.0, 0.0, 1.0 );
977 : : }
978 : : else
979 : : {
980 : :
981 [ + - ][ + - ]: 85 : areacoord[0] = determ3( pt_on_plane[1], pt_on_plane[2], p[1][1], p[1][2], p[2][1], p[2][2] ) / area2;
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
982 : :
983 [ + - ][ + - ]: 85 : areacoord[1] = determ3( p[0][1], p[0][2], pt_on_plane[1], pt_on_plane[2], p[2][1], p[2][2] ) / area2;
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
984 : :
985 [ + - ][ + - ]: 85 : areacoord[2] = determ3( p[0][1], p[0][2], p[1][1], p[1][2], pt_on_plane[1], pt_on_plane[2] ) / area2;
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
986 : : }
987 : : }
988 [ + - ][ + - ]: 2595 : else if( absnorm[1] >= absnorm[0] && absnorm[1] >= absnorm[2] )
[ + + ][ + - ]
[ + - ][ + + ]
[ + + ]
989 : : {
990 : :
991 [ + - ][ + - ]: 89 : area2 = determ3( p[0][0], p[0][2], p[1][0], p[1][2], p[2][0], p[2][2] );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
992 [ - + ]: 89 : if( fabs( area2 ) < tol )
993 : : {
994 [ # # ]: 0 : areacoord = CartVect( -std::numeric_limits< double >::min() ); //.set(
995 : : //-std::numeric_limits<double>::min(),
996 : : //-std::numeric_limits<double>::min(),
997 : : //-std::numeric_limits<double>::min() );
998 : : }
999 [ + - ][ - + ]: 89 : else if( within_tolerance( p[0], pt_on_plane, GEOMETRY_RESABS ) )
1000 : : {
1001 [ # # ]: 0 : areacoord = CartVect( 1., 0., 0. ); //.set( 1.0, 0.0, 0.0 );
1002 : : }
1003 [ + - ][ - + ]: 89 : else if( within_tolerance( p[1], pt_on_plane, GEOMETRY_RESABS ) )
1004 : : {
1005 [ # # ]: 0 : areacoord = CartVect( 0., 1., 0. ); //.set( 0.0, 1.0, 0.0 );
1006 : : }
1007 [ + - ][ - + ]: 89 : else if( within_tolerance( p[2], pt_on_plane, GEOMETRY_RESABS ) )
1008 : : {
1009 [ # # ]: 0 : areacoord = CartVect( 0., 0., 1. ); //.set( 0.0, 0.0, 1.0 );
1010 : : }
1011 : : else
1012 : : {
1013 : :
1014 [ + - ][ + - ]: 89 : areacoord[0] = determ3( pt_on_plane[0], pt_on_plane[2], p[1][0], p[1][2], p[2][0], p[2][2] ) / area2;
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
1015 : :
1016 [ + - ][ + - ]: 89 : areacoord[1] = determ3( p[0][0], p[0][2], pt_on_plane[0], pt_on_plane[2], p[2][0], p[2][2] ) / area2;
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
1017 : :
1018 [ + - ][ + - ]: 89 : areacoord[2] = determ3( p[0][0], p[0][2], p[1][0], p[1][2], pt_on_plane[0], pt_on_plane[2] ) / area2;
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
1019 : : }
1020 : : }
1021 : : else
1022 : : {
1023 : : /*area2 = determ3(pt0->x(), pt0->y(),
1024 : : pt1->x(), pt1->y(),
1025 : : pt2->x(), pt2->y());*/
1026 [ + - ][ + - ]: 2506 : area2 = determ3( p[0][0], p[0][1], p[1][0], p[1][1], p[2][0], p[2][1] );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1027 [ - + ]: 2506 : if( fabs( area2 ) < tol )
1028 : : {
1029 [ # # ]: 0 : areacoord = CartVect( -std::numeric_limits< double >::min() ); //.set(
1030 : : //-std::numeric_limits<double>::min(),
1031 : : //-std::numeric_limits<double>::min(),
1032 : : //-std::numeric_limits<double>::min() );
1033 : : }
1034 [ + - ][ - + ]: 2506 : else if( within_tolerance( p[0], pt_on_plane, GEOMETRY_RESABS ) )
1035 : : {
1036 [ # # ]: 0 : areacoord = CartVect( 1., 0., 0. ); //.set( 1.0, 0.0, 0.0 );
1037 : : }
1038 [ + - ][ - + ]: 2506 : else if( within_tolerance( p[1], pt_on_plane, GEOMETRY_RESABS ) )
1039 : : {
1040 [ # # ]: 0 : areacoord = CartVect( 0., 1., 0. ); //.set( 0.0, 1.0, 0.0 );
1041 : : }
1042 [ + - ][ - + ]: 2506 : else if( within_tolerance( p[2], pt_on_plane, GEOMETRY_RESABS ) )
1043 : : {
1044 [ # # ]: 0 : areacoord = CartVect( 0., 0., 1. ); //.set( 0.0, 0.0, 1.0 );
1045 : : }
1046 : : else
1047 : : {
1048 : :
1049 [ + - ][ + - ]: 2506 : areacoord[0] = determ3( pt_on_plane[0], pt_on_plane[1], p[1][0], p[1][1], p[2][0], p[2][1] ) / area2;
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
1050 : :
1051 [ + - ][ + - ]: 2506 : areacoord[1] = determ3( p[0][0], p[0][1], pt_on_plane[0], pt_on_plane[1], p[2][0], p[2][1] ) / area2;
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
1052 : :
1053 [ + - ][ + - ]: 2506 : areacoord[2] = determ3( p[0][0], p[0][1], p[1][0], p[1][1], pt_on_plane[0], pt_on_plane[1] ) / area2;
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
1054 : : }
1055 : : }
1056 : 2680 : }
1057 : :
1058 : 1777 : ErrorCode SmoothFace::project_to_facets_main( CartVect& this_point, bool trim, bool& outside,
1059 : : CartVect* closest_point_ptr, CartVect* normal_ptr )
1060 : : {
1061 : :
1062 : : // if there are a lot of facets on this surface - use the OBB search first
1063 : : // to narrow the selection
1064 : :
1065 : 1777 : _evaluationsCounter++;
1066 : 1777 : double tolerance = 1.e-5;
1067 [ + - ]: 1777 : std::vector< EntityHandle > facets_out;
1068 : : // we will start with a list of facets anyway, the best among them wins
1069 : : ErrorCode rval =
1070 [ + - ][ + - ]: 1777 : _my_geomTopoTool->obb_tree()->closest_to_location( (double*)&this_point, _obb_root, tolerance, facets_out );
1071 [ - + ]: 1777 : if( MB_SUCCESS != rval ) return rval;
1072 : :
1073 : 1777 : int interpOrder = 4;
1074 : 1777 : double compareTol = 1.e-5;
1075 [ + - ]: 1777 : EntityHandle lastFacet = facets_out.front();
1076 : : rval = project_to_facets( facets_out, lastFacet, interpOrder, compareTol, this_point, trim, outside,
1077 [ + - ]: 1777 : closest_point_ptr, normal_ptr );
1078 : :
1079 : 1777 : return rval;
1080 : : }
1081 : 1777 : ErrorCode SmoothFace::project_to_facets( std::vector< EntityHandle >& facet_list, EntityHandle& lastFacet,
1082 : : int interpOrder, double compareTol, CartVect& this_point, bool, bool& outside,
1083 : : CartVect* closest_point_ptr, CartVect* normal_ptr )
1084 : : {
1085 : :
1086 : 1777 : bool outside_facet = false;
1087 : 1777 : bool best_outside_facet = true;
1088 : 1777 : double mindist = 1.e20;
1089 [ + - ][ + - ]: 1777 : CartVect close_point, best_point( mindist, mindist, mindist ), best_areacoord;
[ + - ]
1090 : 1777 : EntityHandle best_facet = 0L; // no best facet found yet
1091 : : EntityHandle facet;
1092 [ - + ]: 1777 : assert( facet_list.size() > 0 );
1093 : :
1094 : 1777 : double big_dist = compareTol * 1.0e3;
1095 : :
1096 : : // from the list of close facets, determine the closest point
1097 [ + + ]: 4457 : for( size_t i = 0; i < facet_list.size(); i++ )
1098 : : {
1099 [ + - ]: 2680 : facet = facet_list[i];
1100 [ + - ]: 2680 : CartVect pt_on_plane;
1101 : : double dist_to_plane;
1102 [ + - ]: 2680 : project_to_facet_plane( facet, this_point, pt_on_plane, dist_to_plane );
1103 : :
1104 [ + - ]: 2680 : CartVect areacoord;
1105 : : // CartVect close_point;
1106 [ + - ]: 2680 : facet_area_coordinate( facet, pt_on_plane, areacoord );
1107 [ + - ]: 2680 : if( interpOrder != 0 )
1108 : : {
1109 : :
1110 : : // modify the areacoord - project to the bezier patch- snaps to the
1111 : : // edge of the patch if necessary
1112 : :
1113 [ + - ][ - + ]: 2680 : if( project_to_facet( facet, this_point, areacoord, close_point, outside_facet, compareTol ) != MB_SUCCESS )
1114 : 0 : { return MB_FAILURE; }
1115 : : // if (closest_point_ptr)
1116 : : //*closest_point_ptr = close_point;
1117 : : }
1118 : : // keep track of the minimum distance
1119 : :
1120 [ + - ][ + - ]: 2680 : double dist = ( close_point - this_point ).length(); // close_point.distance_between(this_point);
1121 [ + + ][ + + ]: 2680 : if( ( best_outside_facet == outside_facet && dist < mindist ) ||
[ + + ]
1122 [ + + ][ + + ]: 1568 : ( best_outside_facet && !outside_facet && ( dist < big_dist || best_facet == 0L /*!best_facet*/ ) ) )
[ + - ]
1123 : : {
1124 : 2236 : mindist = dist;
1125 : 2236 : best_point = close_point;
1126 : 2236 : best_facet = facet;
1127 : 2236 : best_areacoord = areacoord;
1128 : 2236 : best_outside_facet = outside_facet;
1129 : :
1130 [ - + ]: 2236 : if( dist < compareTol ) { break; }
1131 : 2236 : big_dist = 10.0 * mindist;
1132 : : }
1133 : : // facet->marked(1);
1134 : : // used_facet_list.append(facet);
1135 : : }
1136 : :
1137 [ + + ]: 1777 : if( normal_ptr )
1138 : : {
1139 [ + - ]: 14 : CartVect normal;
1140 [ + - ][ - + ]: 14 : if( eval_bezier_patch_normal( best_facet, best_areacoord, normal ) != MB_SUCCESS ) { return MB_FAILURE; }
1141 : 14 : *normal_ptr = normal;
1142 : : }
1143 : :
1144 [ + + ]: 1777 : if( closest_point_ptr ) { *closest_point_ptr = best_point; }
1145 : :
1146 : 1777 : outside = best_outside_facet;
1147 : 1777 : lastFacet = best_facet;
1148 : :
1149 : 1777 : return MB_SUCCESS;
1150 : : // end copy
1151 : : }
1152 : :
1153 : : //===========================================================================
1154 : : // Function Name: project_to_patch
1155 : : //
1156 : : // Member Type: PUBLIC
1157 : : // Description: Project a point to a bezier patch. Pass in the areacoord
1158 : : // of the point projected to the linear facet. Function
1159 : : // assumes that the point is contained within the patch -
1160 : : // if not, it will project to one of its edges.
1161 : : //===========================================================================
1162 : 2680 : ErrorCode SmoothFace::project_to_patch( EntityHandle facet, // (IN) the facet where the patch is defined
1163 : : CartVect& ac, // (IN) area coordinate initial guess (from linear facet)
1164 : : CartVect& pt, // (IN) point we are projecting to patch
1165 : : CartVect& eval_pt, // (OUT) The projected point
1166 : : CartVect* eval_norm, // (OUT) normal at evaluated point
1167 : : bool& outside, // (OUT) the closest point on patch to pt is on an edge
1168 : : double compare_tol, // (IN) comparison tolerance
1169 : : int edge_id ) // (IN) only used if this is to be projected to one
1170 : : // of the edges. Otherwise, should be -1
1171 : : {
1172 : 2680 : ErrorCode status = MB_SUCCESS;
1173 : :
1174 : : // see if we are at a vertex
1175 : :
1176 : : #define INCR 0.01
1177 : 2680 : const double tol = compare_tol;
1178 : :
1179 [ + - ][ - + ]: 2680 : if( is_at_vertex( facet, pt, ac, compare_tol, eval_pt, eval_norm ) )
1180 : : {
1181 : 0 : outside = false;
1182 : 0 : return MB_SUCCESS;
1183 : : }
1184 : :
1185 : : // check if the start ac is inside the patch -if not, then move it there
1186 : :
1187 : 2680 : int nout = 0;
1188 : 2680 : const double atol = 0.001;
1189 [ + - ][ + + ]: 2680 : if( move_ac_inside( ac, atol ) ) nout++;
1190 : :
1191 : 2680 : int diverge = 0;
1192 : 2680 : int iter = 0;
1193 [ + - ]: 2680 : CartVect newpt;
1194 [ + - ]: 2680 : eval_bezier_patch( facet, ac, newpt );
1195 [ + - ]: 2680 : CartVect move = pt - newpt;
1196 [ + - ]: 2680 : double lastdist = move.length();
1197 : 2680 : double bestdist = lastdist;
1198 : 2680 : CartVect bestac = ac;
1199 : 2680 : CartVect bestpt = newpt;
1200 [ + - ]: 2680 : CartVect bestnorm( 0, 0, 0 );
1201 : :
1202 : : // If we are already close enough, then return now
1203 : :
1204 [ - + ][ # # ]: 2680 : if( lastdist <= tol && !eval_norm && nout == 0 )
[ # # ]
1205 : : {
1206 : 0 : eval_pt = pt;
1207 : 0 : outside = false;
1208 : 0 : return status;
1209 : : }
1210 : :
1211 : : double ratio, mag, umove, vmove, det, distnew, movedist;
1212 : 2680 : CartVect lastpt = newpt;
1213 : 2680 : CartVect lastac = ac;
1214 [ + - ]: 2680 : CartVect norm;
1215 [ + - ][ + - ]: 2680 : CartVect xpt, ypt, zpt, xac, yac, zac, xvec, yvec, zvec;
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1216 [ + - ][ + - ]: 2680 : CartVect du, dv, newac;
[ + - ]
1217 : 2680 : bool done = false;
1218 [ + + ]: 14150 : while( !done )
1219 : : {
1220 : :
1221 : : // We will be locating the projected point within the u,v,w coordinate
1222 : : // system of the triangular bezier patch. Since u+v+w=1, the components
1223 : : // are not linearly independent. We will choose only two of the
1224 : : // coordinates to use and compute the third.
1225 : :
1226 : : int system;
1227 [ + - ][ + - ]: 11470 : if( lastac[0] >= lastac[1] && lastac[0] >= lastac[2] ) { system = 0; }
[ + + ][ + - ]
[ + - ][ + + ]
[ + + ]
1228 [ + - ][ + - ]: 7641 : else if( lastac[1] >= lastac[2] )
[ + + ]
1229 : : {
1230 : 4011 : system = 1;
1231 : : }
1232 : : else
1233 : : {
1234 : 3630 : system = 2;
1235 : : }
1236 : :
1237 : : // compute the surface derivatives with respect to each
1238 : : // of the barycentric coordinates
1239 : :
1240 [ + + ][ + + ]: 11470 : if( system == 1 || system == 2 )
1241 : : {
1242 [ + - ][ + - ]: 7641 : xac[0] = lastac[0] + INCR; // xac.x( lastac.x() + INCR );
1243 [ + - ][ + - ]: 7641 : if( lastac[1] + lastac[2] == 0.0 ) return MB_FAILURE;
[ - + ]
1244 [ + - ][ + - ]: 7641 : ratio = lastac[2] / ( lastac[1] + lastac[2] ); // ratio = lastac.z() / (lastac.y() + lastac.z());
[ + - ]
1245 [ + - ][ + - ]: 7641 : xac[1] = ( 1.0 - xac[0] ) * ( 1.0 - ratio ); // xac.y( (1.0 - xac.x()) * (1.0 - ratio) );
1246 [ + - ][ + - ]: 7641 : xac[2] = 1.0 - xac[0] - xac[1]; // xac.z( 1.0 - xac.x() - xac.y() );
[ + - ]
1247 [ + - ]: 7641 : eval_bezier_patch( facet, xac, xpt );
1248 [ + - ]: 7641 : xvec = xpt - lastpt;
1249 [ + - ]: 7641 : xvec /= INCR;
1250 : : }
1251 [ + + ][ + + ]: 11470 : if( system == 0 || system == 2 )
1252 : : {
1253 [ + - ][ + - ]: 7459 : yac[1] = ( lastac[1] + INCR ); // yac.y( lastac.y() + INCR );
1254 [ + - ][ + - ]: 7459 : if( lastac[0] + lastac[2] == 0.0 ) // if (lastac.x() + lastac.z() == 0.0)
[ - + ]
1255 : 0 : return MB_FAILURE;
1256 [ + - ][ + - ]: 7459 : ratio = lastac[2] / ( lastac[0] + lastac[2] ); // ratio = lastac.z() / (lastac.x() + lastac.z());
[ + - ]
1257 [ + - ][ + - ]: 7459 : yac[0] = ( ( 1.0 - yac[1] ) * ( 1.0 - ratio ) ); // yac.x( (1.0 - yac.y()) * (1.0 - ratio) );
1258 [ + - ][ + - ]: 7459 : yac[2] = ( 1.0 - yac[0] - yac[1] ); // yac.z( 1.0 - yac.x() - yac.y() );
[ + - ]
1259 [ + - ]: 7459 : eval_bezier_patch( facet, yac, ypt );
1260 [ + - ]: 7459 : yvec = ypt - lastpt;
1261 [ + - ]: 7459 : yvec /= INCR;
1262 : : }
1263 [ + + ][ + + ]: 11470 : if( system == 0 || system == 1 )
1264 : : {
1265 [ + - ][ + - ]: 7840 : zac[2] = ( lastac[2] + INCR ); // zac.z( lastac.z() + INCR );
1266 [ + - ][ + - ]: 7840 : if( lastac[0] + lastac[1] == 0.0 ) // if (lastac.x() + lastac.y() == 0.0)
[ - + ]
1267 : 0 : return MB_FAILURE;
1268 [ + - ][ + - ]: 7840 : ratio = lastac[1] / ( lastac[0] + lastac[1] ); // ratio = lastac.y() / (lastac.x() + lastac.y());
[ + - ]
1269 [ + - ][ + - ]: 7840 : zac[0] = ( ( 1.0 - zac[2] ) * ( 1.0 - ratio ) ); // zac.x( (1.0 - zac.z()) * (1.0 - ratio) );
1270 [ + - ][ + - ]: 7840 : zac[1] = ( 1.0 - zac[0] - zac[2] ); // zac.y( 1.0 - zac.x() - zac.z() );
[ + - ]
1271 [ + - ]: 7840 : eval_bezier_patch( facet, zac, zpt );
1272 [ + - ]: 7840 : zvec = zpt - lastpt;
1273 [ + - ]: 7840 : zvec /= INCR;
1274 : : }
1275 : :
1276 : : // compute the surface normal
1277 : :
1278 [ + + + - ]: 11470 : switch( system )
1279 : : {
1280 : : case 0:
1281 : 3829 : du = yvec;
1282 : 3829 : dv = zvec;
1283 : 3829 : break;
1284 : : case 1:
1285 : 4011 : du = zvec;
1286 : 4011 : dv = xvec;
1287 : 4011 : break;
1288 : : case 2:
1289 : 3630 : du = xvec;
1290 : 3630 : dv = yvec;
1291 : 3630 : break;
1292 : : }
1293 [ + - ]: 11470 : norm = du * dv;
1294 [ + - ]: 11470 : mag = norm.length();
1295 [ - + ]: 11470 : if( mag < DBL_EPSILON )
1296 : : {
1297 : 0 : return MB_FAILURE;
1298 : : // do something else here (it is likely a flat triangle -
1299 : : // so try evaluating just an edge of the bezier patch)
1300 : : }
1301 [ + - ]: 11470 : norm /= mag;
1302 [ + + ]: 11470 : if( iter == 0 ) bestnorm = norm;
1303 : :
1304 : : // project the move vector to the tangent plane
1305 : :
1306 [ + - ][ + - ]: 11470 : move = ( norm * move ) * norm;
1307 : :
1308 : : // compute an equivalent u-v-w vector
1309 : :
1310 [ + - ][ + - ]: 11470 : CartVect absnorm( fabs( norm[0] ), fabs( norm[1] ), fabs( norm[2] ) );
[ + - ][ + - ]
1311 [ + - ][ + - ]: 11470 : if( absnorm[2] >= absnorm[1] && absnorm[2] >= absnorm[0] )
[ + + ][ + - ]
[ + - ][ + + ]
[ + + ]
1312 : : {
1313 [ + - ][ + - ]: 10674 : det = du[0] * dv[1] - dv[0] * du[1];
[ + - ][ + - ]
1314 [ - + ]: 10674 : if( fabs( det ) <= DBL_EPSILON )
1315 : : {
1316 : 0 : return MB_FAILURE; // do something else here
1317 : : }
1318 [ + - ][ + - ]: 10674 : umove = ( move[0] * dv[1] - dv[0] * move[1] ) / det;
[ + - ][ + - ]
1319 [ + - ][ + - ]: 10674 : vmove = ( du[0] * move[1] - move[0] * du[1] ) / det;
[ + - ][ + - ]
1320 : : }
1321 [ + - ][ + - ]: 796 : else if( absnorm[1] >= absnorm[2] && absnorm[1] >= absnorm[0] )
[ + + ][ + - ]
[ + - ][ + + ]
[ + + ]
1322 : : {
1323 [ + - ][ + - ]: 351 : det = du[0] * dv[2] - dv[0] * du[2];
[ + - ][ + - ]
1324 [ - + ]: 351 : if( fabs( det ) <= DBL_EPSILON ) { return MB_FAILURE; }
1325 [ + - ][ + - ]: 351 : umove = ( move[0] * dv[2] - dv[0] * move[2] ) / det;
[ + - ][ + - ]
1326 [ + - ][ + - ]: 351 : vmove = ( du[0] * move[2] - move[0] * du[2] ) / det;
[ + - ][ + - ]
1327 : : }
1328 : : else
1329 : : {
1330 [ + - ][ + - ]: 445 : det = du[1] * dv[2] - dv[1] * du[2];
[ + - ][ + - ]
1331 [ - + ]: 445 : if( fabs( det ) <= DBL_EPSILON ) { return MB_FAILURE; }
1332 [ + - ][ + - ]: 445 : umove = ( move[1] * dv[2] - dv[1] * move[2] ) / det;
[ + - ][ + - ]
1333 [ + - ][ + - ]: 445 : vmove = ( du[1] * move[2] - move[1] * du[2] ) / det;
[ + - ][ + - ]
1334 : : }
1335 : :
1336 : : /* === compute the new u-v coords and evaluate surface at new location */
1337 : :
1338 [ + + + - ]: 11470 : switch( system )
1339 : : {
1340 : : case 0:
1341 [ + - ][ + - ]: 3829 : newac[1] = ( lastac[1] + umove ); // newac.y( lastac.y() + umove );
1342 [ + - ][ + - ]: 3829 : newac[2] = ( lastac[2] + vmove ); // newac.z( lastac.z() + vmove );
1343 [ + - ][ + - ]: 3829 : newac[0] = ( 1.0 - newac[1] - newac[2] ); // newac.x( 1.0 - newac.y() - newac.z() );
[ + - ]
1344 : 3829 : break;
1345 : : case 1:
1346 [ + - ][ + - ]: 4011 : newac[2] = ( lastac[2] + umove ); // newac.z( lastac.z() + umove );
1347 [ + - ][ + - ]: 4011 : newac[0] = ( lastac[0] + vmove ); // newac.x( lastac.x() + vmove );
1348 [ + - ][ + - ]: 4011 : newac[1] = ( 1.0 - newac[2] - newac[0] ); // newac.y( 1.0 - newac.z() - newac.x() );
[ + - ]
1349 : 4011 : break;
1350 : : case 2:
1351 [ + - ][ + - ]: 3630 : newac[0] = ( lastac[0] + umove ); // newac.x( lastac.x() + umove );
1352 [ + - ][ + - ]: 3630 : newac[1] = ( lastac[1] + vmove ); // newac.y( lastac.y() + vmove );
1353 [ + - ][ + - ]: 3630 : newac[2] = ( 1.0 - newac[0] - newac[1] ); // newac.z( 1.0 - newac.x() - newac.y() );
[ + - ]
1354 : 3630 : break;
1355 : : }
1356 : :
1357 : : // Keep it inside the patch
1358 : :
1359 [ + - ][ + + ]: 11470 : if( newac[0] >= -atol && newac[1] >= -atol && newac[2] >= -atol ) { nout = 0; }
[ + - ][ + + ]
[ + - ][ + + ]
[ + + ]
1360 : : else
1361 : : {
1362 [ + - ][ + - ]: 2110 : if( move_ac_inside( newac, atol ) ) nout++;
1363 : : }
1364 : :
1365 : : // Evaluate at the new location
1366 : :
1367 [ - + ][ # # ]: 11470 : if( edge_id != -1 ) ac_at_edge( newac, newac, edge_id ); // move to edge first
1368 [ + - ]: 11470 : eval_bezier_patch( facet, newac, newpt );
1369 : :
1370 : : // Check for convergence
1371 : :
1372 [ + - ][ + - ]: 11470 : distnew = ( pt - newpt ).length(); // pt.distance_between(newpt);
1373 [ + - ]: 11470 : move = newpt - lastpt;
1374 [ + - ]: 11470 : movedist = move.length();
1375 [ + + ][ - + ]: 11470 : if( movedist < tol || distnew < tol )
1376 : : {
1377 : 2543 : done = true;
1378 [ + + ]: 3269 : if( distnew < bestdist )
1379 : : {
1380 : 726 : bestdist = distnew;
1381 : 726 : bestac = newac;
1382 : 726 : bestpt = newpt;
1383 : 726 : bestnorm = norm;
1384 : : }
1385 : : }
1386 : : else
1387 : : {
1388 : :
1389 : : // don't allow more than 30 iterations
1390 : :
1391 : 8927 : iter++;
1392 [ - + ]: 8927 : if( iter > 30 )
1393 : : {
1394 : : // if (movedist > tol * 100.0) nout=1;
1395 : 0 : done = true;
1396 : : }
1397 : :
1398 : : // Check for divergence - don't allow more than 5 divergent
1399 : : // iterations
1400 : :
1401 [ + + ]: 8927 : if( distnew > lastdist )
1402 : : {
1403 : 2177 : diverge++;
1404 [ + + ]: 2177 : if( diverge > 10 )
1405 : : {
1406 : 4 : done = true;
1407 : : // if (movedist > tol * 100.0) nout=1;
1408 : : }
1409 : : }
1410 : :
1411 : : // Check if we are continuing to project outside the facet.
1412 : : // If so, then stop now
1413 : :
1414 [ + + ]: 8927 : if( nout > 3 ) { done = true; }
1415 : :
1416 : : // set up for next iteration
1417 : :
1418 [ + + ]: 8927 : if( !done )
1419 : : {
1420 [ + + ]: 8790 : if( distnew < bestdist )
1421 : : {
1422 : 5980 : bestdist = distnew;
1423 : 5980 : bestac = newac;
1424 : 5980 : bestpt = newpt;
1425 : 5980 : bestnorm = norm;
1426 : : }
1427 : 8790 : lastdist = distnew;
1428 : 8790 : lastpt = newpt;
1429 : 8790 : lastac = newac;
1430 [ + - ]: 11470 : move = pt - lastpt;
1431 : : }
1432 : : }
1433 : : }
1434 : :
1435 : 2680 : eval_pt = bestpt;
1436 [ - + ]: 2680 : if( eval_norm ) { *eval_norm = bestnorm; }
1437 : 2680 : outside = ( nout > 0 ) ? true : false;
1438 : 2680 : ac = bestac;
1439 : :
1440 : 2680 : return status;
1441 : : }
1442 : :
1443 : : //===========================================================================
1444 : : // Function Name: ac_at_edge
1445 : : //
1446 : : // Member Type: PRIVATE
1447 : : // Description: determine the area coordinate of the facet at the edge
1448 : : //===========================================================================
1449 : 0 : void SmoothFace::ac_at_edge( CartVect& fac, // facet area coordinate
1450 : : CartVect& eac, // edge area coordinate
1451 : : int edge_id ) // id of edge
1452 : : {
1453 : : double u, v, w;
1454 [ # # # # ]: 0 : switch( edge_id )
1455 : : {
1456 : : case 0:
1457 : 0 : u = 0.0;
1458 : 0 : v = fac[1] / ( fac[1] + fac[2] ); // v = fac.y() / (fac.y() + fac.z());
1459 : 0 : w = 1.0 - v;
1460 : 0 : break;
1461 : : case 1:
1462 : 0 : u = fac[0] / ( fac[0] + fac[2] ); // u = fac.x() / (fac.x() + fac.z());
1463 : 0 : v = 0.0;
1464 : 0 : w = 1.0 - u;
1465 : 0 : break;
1466 : : case 2:
1467 : 0 : u = fac[0] / ( fac[0] + fac[1] ); // u = fac.x() / (fac.x() + fac.y());
1468 : 0 : v = 1.0 - u;
1469 : 0 : w = 0.0;
1470 : 0 : break;
1471 : : default:
1472 : 0 : assert( 0 );
1473 : : u = -1; // needed to eliminate warnings about used before set
1474 : : v = -1; // needed to eliminate warnings about used before set
1475 : : w = -1; // needed to eliminate warnings about used before set
1476 : : break;
1477 : : }
1478 : 0 : eac[0] = u;
1479 : 0 : eac[1] = v;
1480 : 0 : eac[2] = w; //= CartVect(u, v, w);
1481 : 0 : }
1482 : :
1483 : : //===========================================================================
1484 : : // Function Name: project_to_facet
1485 : : //
1486 : : // Member Type: PUBLIC
1487 : : // Description: project to a single facet. Uses the input areacoord as
1488 : : // a starting guess.
1489 : : //===========================================================================
1490 : 2680 : ErrorCode SmoothFace::project_to_facet( EntityHandle facet, CartVect& pt, CartVect& areacoord, CartVect& close_point,
1491 : : bool& outside_facet, double compare_tol )
1492 : : {
1493 : 2680 : const EntityHandle* conn3 = NULL;
1494 : 2680 : int nnodes = 0;
1495 [ + - ]: 2680 : _mb->get_connectivity( facet, conn3, nnodes );
1496 : : //
1497 : : // double coords[9]; // store the coordinates for the nodes
1498 : : //_mb->get_coords(conn3, 3, coords);
1499 [ + - ][ + + ]: 10720 : CartVect p[3];
1500 [ + - ]: 2680 : _mb->get_coords( conn3, 3, (double*)&p[0] );
1501 : :
1502 : 2680 : int edge_id = -1;
1503 [ + - ]: 2680 : ErrorCode stat = project_to_patch( facet, areacoord, pt, close_point, NULL, outside_facet, compare_tol, edge_id );
1504 : : /* }
1505 : : break;
1506 : : }*/
1507 : :
1508 : 2680 : return stat;
1509 : : }
1510 : :
1511 : : //===========================================================================
1512 : : // Function Name: is_at_vertex
1513 : : //
1514 : : // Member Type: PRIVATE
1515 : : // Description: determine if the point is at one of the facet's vertices
1516 : : //===========================================================================
1517 : 2680 : bool SmoothFace::is_at_vertex( EntityHandle facet, // (IN) facet we are evaluating
1518 : : CartVect& pt, // (IN) the point
1519 : : CartVect& ac, // (IN) the ac of the point on the facet plane
1520 : : double compare_tol, // (IN) return TRUE of closer than this
1521 : : CartVect& eval_pt, // (OUT) location at vertex if TRUE
1522 : : CartVect* eval_norm_ptr ) // (OUT) normal at vertex if TRUE
1523 : : {
1524 : : double dist;
1525 [ + - ]: 2680 : CartVect vert_loc;
1526 : 2680 : const double actol = 0.1;
1527 : : // get coordinates get_coords
1528 : 2680 : const EntityHandle* conn3 = NULL;
1529 : 2680 : int nnodes = 0;
1530 [ + - ]: 2680 : _mb->get_connectivity( facet, conn3, nnodes );
1531 : : //
1532 : : // double coords[9]; // store the coordinates for the nodes
1533 : : //_mb->get_coords(conn3, 3, coords);
1534 [ + - ][ + + ]: 10720 : CartVect p[3];
1535 [ + - ]: 2680 : _mb->get_coords( conn3, 3, (double*)&p[0] );
1536 : : // also get the normals at nodes
1537 [ + - ][ + + ]: 10720 : CartVect NN[3];
1538 [ + - ]: 2680 : _mb->tag_get_data( _gradientTag, conn3, 3, (double*)&NN[0] );
1539 [ + - ][ + + ]: 2680 : if( fabs( ac[0] ) < actol && fabs( ac[1] ) < actol )
[ + - ][ + + ]
[ + + ]
1540 : : {
1541 : 154 : vert_loc = p[2];
1542 [ + - ][ + - ]: 154 : dist = ( pt - vert_loc ).length(); // pt.distance_between( vert_loc );
1543 [ - + ]: 154 : if( dist <= compare_tol )
1544 : : {
1545 : 0 : eval_pt = vert_loc;
1546 [ # # ]: 0 : if( eval_norm_ptr ) { *eval_norm_ptr = NN[2]; }
1547 : 0 : return true;
1548 : : }
1549 : : }
1550 : :
1551 [ + - ][ + + ]: 2680 : if( fabs( ac[0] ) < actol && fabs( ac[2] ) < actol )
[ + - ][ + + ]
[ + + ]
1552 : : {
1553 : 145 : vert_loc = p[1];
1554 [ + - ][ + - ]: 145 : dist = ( pt - vert_loc ).length(); // pt.distance_between( vert_loc );
1555 [ - + ]: 145 : if( dist <= compare_tol )
1556 : : {
1557 : 0 : eval_pt = vert_loc;
1558 [ # # ]: 0 : if( eval_norm_ptr )
1559 : : {
1560 : 0 : *eval_norm_ptr = NN[1]; // facet->point(1)->normal( facet );
1561 : : }
1562 : 0 : return true;
1563 : : }
1564 : : }
1565 : :
1566 [ + - ][ + + ]: 2680 : if( fabs( ac[1] ) < actol && fabs( ac[2] ) < actol )
[ + - ][ + + ]
[ + + ]
1567 : : {
1568 : 129 : vert_loc = p[0];
1569 [ + - ][ + - ]: 129 : dist = ( pt - vert_loc ).length(); // pt.distance_between( vert_loc );
1570 [ - + ]: 129 : if( dist <= compare_tol )
1571 : : {
1572 : 0 : eval_pt = vert_loc;
1573 [ # # ]: 0 : if( eval_norm_ptr ) { *eval_norm_ptr = NN[0]; }
1574 : 0 : return true;
1575 : : }
1576 : : }
1577 : :
1578 : 2680 : return false;
1579 : : }
1580 : :
1581 : : //===========================================================================
1582 : : // Function Name: move_ac_inside
1583 : : //
1584 : : // Member Type: PRIVATE
1585 : : // Description: find the closest area coordinate to the boundary of the
1586 : : // patch if any of its components are < 0
1587 : : // Return if the ac was modified.
1588 : : //===========================================================================
1589 : 4790 : bool SmoothFace::move_ac_inside( CartVect& ac, double tol )
1590 : : {
1591 : 4790 : int nout = 0;
1592 [ + + ]: 4790 : if( ac[0] < -tol )
1593 : : {
1594 : 600 : ac[0] = 0.0;
1595 : 600 : ac[1] = ac[1] / ( ac[1] + ac[2] ); //( ac.y() / (ac.y() + ac.z()) ;
1596 : 600 : ac[2] = 1. - ac[1]; // ac.z( 1.0 - ac.y() );
1597 : 600 : nout++;
1598 : : }
1599 [ + + ]: 4790 : if( ac[1] < -tol )
1600 : : {
1601 : 794 : ac[1] = 0.; // ac.y( 0.0 );
1602 : 794 : ac[0] = ac[0] / ( ac[0] + ac[2] ); // ac.x( ac.x() / (ac.x() + ac.z()) );
1603 : 794 : ac[2] = 1. - ac[0]; // ac.z( 1.0 - ac.x() );
1604 : 794 : nout++;
1605 : : }
1606 [ + + ]: 4790 : if( ac[2] < -tol )
1607 : : {
1608 : 732 : ac[2] = 0.; // ac.z( 0.0 );
1609 : 732 : ac[0] = ac[0] / ( ac[0] + ac[1] ); // ac.x( ac.x() / (ac.x() + ac.y()) );
1610 : 732 : ac[1] = 1. - ac[0]; // ac.y( 1.0 - ac.x() );
1611 : 732 : nout++;
1612 : : }
1613 : 4790 : return ( nout > 0 ) ? true : false;
1614 : : }
1615 : :
1616 : : //===========================================================================
1617 : : // Function Name: hodograph
1618 : : //
1619 : : // Member Type: PUBLIC
1620 : : // Description: get the hodograph control points for the facet
1621 : : // Note: This is a triangle cubic patch that is defined by the
1622 : : // normals of quartic facet control point lattice. Returned coordinates
1623 : : // in Nijk are defined by the following diagram
1624 : : //
1625 : : //
1626 : : // *9 index polar
1627 : : // / \ 0 300 point(0)
1628 : : // / \ 1 210
1629 : : // 7*-----*8 2 120
1630 : : // / \ / \ 3 030 point(1)
1631 : : // / \ / \ 4 201
1632 : : // 4*----5*-----*6 5 111
1633 : : // / \ / \ / \ 6 021
1634 : : // / \ / \ / \ 7 102
1635 : : // *-----*-----*-----* 8 012
1636 : : // 0 1 2 3 9 003 point(2)
1637 : : //
1638 : :
1639 : : //===========================================================================
1640 : : // Function Name: eval_bezier_patch_normal
1641 : : //
1642 : : // Member Type: PRIVATE
1643 : : // Description: evaluate the Bezier patch defined at a facet
1644 : : //===========================================================================
1645 : 14 : ErrorCode SmoothFace::eval_bezier_patch_normal( EntityHandle facet, CartVect& areacoord, CartVect& normal )
1646 : : {
1647 : : // interpolate internal control points
1648 : :
1649 [ + - ][ + + ]: 98 : CartVect gctrl_pts[6];
1650 : : // facet->get_control_points( gctrl_pts );
1651 [ + - ]: 14 : ErrorCode rval = _mb->tag_get_data( _facetCtrlTag, &facet, 1, &gctrl_pts[0] );
1652 [ - + ]: 14 : assert( rval == MB_SUCCESS );
1653 [ - + ]: 14 : if( MB_SUCCESS != rval ) return rval;
1654 : : // _gradientTag
1655 : : // get normals at points
1656 : 14 : const EntityHandle* conn3 = NULL;
1657 : 14 : int nnodes = 0;
1658 [ + - ]: 14 : rval = _mb->get_connectivity( facet, conn3, nnodes );
1659 [ - + ]: 14 : if( MB_SUCCESS != rval ) return rval;
1660 : :
1661 [ + - ][ + + ]: 56 : CartVect NN[3];
1662 [ + - ]: 14 : rval = _mb->tag_get_data( _gradientTag, conn3, 3, &NN[0] );
1663 [ - + ]: 14 : assert( rval == MB_SUCCESS );
1664 [ - + ]: 14 : if( MB_SUCCESS != rval ) return rval;
1665 : :
1666 [ + - ][ + - ]: 14 : if( fabs( areacoord[1] + areacoord[2] ) < 1.0e-6 )
[ - + ]
1667 : : {
1668 : 0 : normal = NN[0];
1669 : 0 : return MB_SUCCESS;
1670 : : }
1671 [ + - ][ + - ]: 14 : if( fabs( areacoord[0] + areacoord[2] ) < 1.0e-6 )
[ - + ]
1672 : : {
1673 : 0 : normal = NN[1]; // facet->point(1)->normal(facet);
1674 : 0 : return MB_SUCCESS;
1675 : : }
1676 [ + - ][ + - ]: 14 : if( fabs( areacoord[0] + areacoord[1] ) < 1.0e-6 )
[ + + ]
1677 : : {
1678 : 1 : normal = NN[2]; // facet->point(2)->normal(facet);
1679 : 1 : return MB_SUCCESS;
1680 : : }
1681 : :
1682 : : // compute the hodograph of the quartic Gregory patch
1683 : :
1684 [ + - ][ + + ]: 143 : CartVect Nijk[10];
1685 : : // hodograph(facet,areacoord,Nijk);
1686 : : // start copy from hodograph
1687 : : // CubitVector gctrl_pts[6];
1688 : : // facet->get_control_points( gctrl_pts );
1689 [ + - ][ + + ]: 52 : CartVect P_facet[3];
1690 : :
1691 : : // 2,1,1
1692 : : /*P_facet[0] = (1.0e0 / (areacoord.y() + areacoord.z())) *
1693 : : (areacoord.y() * gctrl_pts[3] +
1694 : : areacoord.z() * gctrl_pts[4]);*/
1695 : : P_facet[0] =
1696 [ + - ][ + - ]: 13 : ( 1.0e0 / ( areacoord[1] + areacoord[2] ) ) * ( areacoord[1] * gctrl_pts[3] + areacoord[2] * gctrl_pts[4] );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
1697 : : // 1,2,1
1698 : : /*P_facet[1] = (1.0e0 / (areacoord.x() + areacoord.z())) *
1699 : : (areacoord.x() * gctrl_pts[0] +
1700 : : areacoord.z() * gctrl_pts[5]);*/
1701 : : P_facet[1] =
1702 [ + - ][ + - ]: 13 : ( 1.0e0 / ( areacoord[0] + areacoord[2] ) ) * ( areacoord[0] * gctrl_pts[0] + areacoord[2] * gctrl_pts[5] );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
1703 : : // 1,1,2
1704 : : /*P_facet[2] = (1.0e0 / (areacoord.x() + areacoord.y())) *
1705 : : (areacoord.x() * gctrl_pts[1] +
1706 : : areacoord.y() * gctrl_pts[2]);*/
1707 : : P_facet[2] =
1708 [ + - ][ + - ]: 13 : ( 1.0e0 / ( areacoord[0] + areacoord[1] ) ) * ( areacoord[0] * gctrl_pts[1] + areacoord[1] * gctrl_pts[2] );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
1709 : :
1710 : : // corner control points are just the normals at the points
1711 : :
1712 : : // 3, 0, 0
1713 : 13 : Nijk[0] = NN[0];
1714 : : // 0, 3, 0
1715 : 13 : Nijk[3] = NN[1];
1716 : : // 0, 0, 3
1717 : 13 : Nijk[9] = NN[2]; // facet->point(2)->normal(facet);
1718 : :
1719 : : // fill in the boundary control points. Define as the normal to the local
1720 : : // triangle formed by the quartic control point lattice
1721 : :
1722 : : // store here again the 9 control points on the edges
1723 [ + - ][ + + ]: 130 : CartVect CP[9]; // 9 control points on the edges,
1724 [ + - ]: 13 : rval = _mb->tag_get_data( _facetEdgeCtrlTag, &facet, 1, &CP[0] );
1725 [ - + ]: 13 : if( MB_SUCCESS != rval ) return rval;
1726 : : // there are 3 CP for each edge, 0, 1, 2; first edge is 1-2
1727 : : // CubitFacetEdge *edge;
1728 : : // edge = facet->edge( 2 );
1729 : : // CubitVector ctrl_pts[5];
1730 : : // edge->control_points(facet, ctrl_pts);
1731 : :
1732 : : // 2, 1, 0
1733 : : // Nijk[1] = (ctrl_pts[2] - ctrl_pts[1]) * (P_facet[0] - ctrl_pts[1]);
1734 [ + - ][ + - ]: 13 : Nijk[1] = ( CP[7] - CP[6] ) * ( P_facet[0] - CP[6] );
[ + - ]
1735 [ + - ]: 13 : Nijk[1].normalize();
1736 : :
1737 : : // 1, 2, 0
1738 : : // Nijk[2] = (ctrl_pts[3] - ctrl_pts[2]) * (P_facet[1] - ctrl_pts[2]);
1739 [ + - ][ + - ]: 13 : Nijk[2] = ( CP[8] - CP[7] ) * ( P_facet[1] - CP[7] );
[ + - ]
1740 [ + - ]: 13 : Nijk[2].normalize();
1741 : :
1742 : : // edge = facet->edge( 0 );
1743 : : // edge->control_points(facet, ctrl_pts);
1744 : :
1745 : : // 0, 2, 1
1746 : : // Nijk[6] = (ctrl_pts[1] - P_facet[1]) * (ctrl_pts[2] - P_facet[1]);
1747 [ + - ][ + - ]: 13 : Nijk[6] = ( CP[0] - P_facet[1] ) * ( CP[1] - P_facet[1] );
[ + - ]
1748 [ + - ]: 13 : Nijk[6].normalize();
1749 : :
1750 : : // 0, 1, 2
1751 : : // Nijk[8] = (ctrl_pts[2] - P_facet[2]) * (ctrl_pts[3] - P_facet[2]);
1752 [ + - ][ + - ]: 13 : Nijk[8] = ( CP[1] - P_facet[2] ) * ( CP[2] - P_facet[2] );
[ + - ]
1753 [ + - ]: 13 : Nijk[8].normalize();
1754 : :
1755 : : // edge = facet->edge( 1 );
1756 : : // edge->control_points(facet, ctrl_pts);
1757 : :
1758 : : // 1, 0, 2
1759 : : // Nijk[7] = (P_facet[2] - ctrl_pts[2]) * (ctrl_pts[1] - ctrl_pts[2]);
1760 [ + - ][ + - ]: 13 : Nijk[7] = ( P_facet[2] - CP[4] ) * ( CP[3] - CP[4] );
[ + - ]
1761 [ + - ]: 13 : Nijk[7].normalize();
1762 : :
1763 : : // 2, 0, 1
1764 : : // Nijk[4] = (P_facet[0] - ctrl_pts[3]) * (ctrl_pts[2] - ctrl_pts[3]);
1765 [ + - ][ + - ]: 13 : Nijk[4] = ( P_facet[0] - CP[5] ) * ( CP[4] - CP[5] );
[ + - ]
1766 [ + - ]: 13 : Nijk[4].normalize();
1767 : :
1768 : : // 1, 1, 1
1769 [ + - ][ + - ]: 13 : Nijk[5] = ( P_facet[1] - P_facet[0] ) * ( P_facet[2] - P_facet[0] );
[ + - ]
1770 [ + - ]: 13 : Nijk[5].normalize();
1771 : : // end copy from hodograph
1772 : :
1773 : : // sum the contribution from each of the control points
1774 : :
1775 [ + - ]: 13 : normal = CartVect( 0.0e0, 0.0e0, 0.0e0 );
1776 : :
1777 : : // i=3; j=0; k=0;
1778 : : // double Bsum = 0.0;
1779 [ + - ][ + - ]: 13 : double B = mbcube( areacoord[0] );
[ + - ]
1780 : : // Bsum += B;
1781 [ + - ][ + - ]: 13 : normal += B * Nijk[0];
1782 : :
1783 : : // i=2; j=1; k=0;
1784 [ + - ][ + - ]: 13 : B = 3.0 * mbsqr( areacoord[0] ) * areacoord[1];
[ + - ]
1785 : : // Bsum += B;
1786 [ + - ][ + - ]: 13 : normal += B * Nijk[1];
1787 : :
1788 : : // i=1; j=2; k=0;
1789 [ + - ][ + - ]: 13 : B = 3.0 * areacoord[0] * mbsqr( areacoord[1] );
[ + - ]
1790 : : // Bsum += B;
1791 [ + - ][ + - ]: 13 : normal += B * Nijk[2];
1792 : :
1793 : : // i=0; j=3; k=0;
1794 [ + - ][ + - ]: 13 : B = mbcube( areacoord[1] );
[ + - ]
1795 : : // Bsum += B;
1796 [ + - ][ + - ]: 13 : normal += B * Nijk[3];
1797 : :
1798 : : // i=2; j=0; k=1;
1799 [ + - ][ + - ]: 13 : B = 3.0 * mbsqr( areacoord[0] ) * areacoord[2];
[ + - ]
1800 : : // Bsum += B;
1801 [ + - ][ + - ]: 13 : normal += B * Nijk[4];
1802 : :
1803 : : // i=1; j=1; k=1;
1804 [ + - ][ + - ]: 13 : B = 6.0 * areacoord[0] * areacoord[1] * areacoord[2];
[ + - ]
1805 : : // Bsum += B;
1806 [ + - ][ + - ]: 13 : normal += B * Nijk[5];
1807 : :
1808 : : // i=0; j=2; k=1;
1809 [ + - ][ + - ]: 13 : B = 3.0 * mbsqr( areacoord[1] ) * areacoord[2];
[ + - ]
1810 : : // Bsum += B;
1811 [ + - ][ + - ]: 13 : normal += B * Nijk[6];
1812 : :
1813 : : // i=1; j=0; k=2;
1814 [ + - ][ + - ]: 13 : B = 3.0 * areacoord[0] * mbsqr( areacoord[2] );
[ + - ]
1815 : : // Bsum += B;
1816 [ + - ][ + - ]: 13 : normal += B * Nijk[7];
1817 : :
1818 : : // i=0; j=1; k=2;
1819 [ + - ][ + - ]: 13 : B = 3.0 * areacoord[1] * mbsqr( areacoord[2] );
[ + - ]
1820 : : // Bsum += B;
1821 [ + - ][ + - ]: 13 : normal += B * Nijk[8];
1822 : :
1823 : : // i=0; j=0; k=3;
1824 [ + - ][ + - ]: 13 : B = mbcube( areacoord[2] );
[ + - ]
1825 : : // Bsum += B;
1826 [ + - ][ + - ]: 13 : normal += B * Nijk[9];
1827 : :
1828 : : // assert(fabs(Bsum - 1.0) < 1e-9);
1829 : :
1830 [ + - ]: 13 : normal.normalize();
1831 : :
1832 : 14 : return MB_SUCCESS;
1833 : : }
1834 : :
1835 : 2667 : ErrorCode SmoothFace::get_normals_for_vertices( const EntityHandle* conn2, CartVect N[2] )
1836 : : // this method will be called to retrieve the normals needed in the calculation of control edge
1837 : : // points..
1838 : : {
1839 : : // CartVect N[2];
1840 : : //_mb->tag_get_data(_gradientTag, conn2, 2, normalVec);
1841 : 2667 : ErrorCode rval = _mb->tag_get_data( _gradientTag, conn2, 2, (double*)&N[0] );
1842 : 2667 : return rval;
1843 : : }
1844 : :
1845 : 4 : ErrorCode SmoothFace::ray_intersection_correct( EntityHandle, // (IN) the facet where the patch is defined
1846 : : CartVect& pt, // (IN) shoot from
1847 : : CartVect& ray, // (IN) ray direction
1848 : : CartVect& eval_pt, // (INOUT) The intersection point
1849 : : double& distance, // (IN OUT) the new distance
1850 : : bool& outside )
1851 : : {
1852 : : // find a point on the smooth surface
1853 : 4 : CartVect currentPoint = eval_pt;
1854 : 4 : int numIter = 0;
1855 : 4 : double improvement = 1.e20;
1856 [ + - ]: 4 : CartVect diff;
1857 [ + - ][ + + ]: 10 : while( numIter++ < 5 && improvement > 0.01 )
[ + + ]
1858 : : {
1859 [ + - ]: 6 : CartVect newPos;
1860 : :
1861 : 6 : bool trim = false; // is it needed?
1862 : 6 : outside = true;
1863 [ + - ]: 6 : CartVect closestPoint;
1864 [ + - ]: 6 : CartVect normal;
1865 : :
1866 [ + - ]: 6 : ErrorCode rval = project_to_facets_main( currentPoint, trim, outside, &newPos, &normal );
1867 [ - + ]: 6 : if( MB_SUCCESS != rval ) return rval;
1868 [ - + ]: 6 : assert( rval == MB_SUCCESS );
1869 [ + - ]: 6 : diff = newPos - currentPoint;
1870 [ + - ]: 6 : improvement = diff.length();
1871 : : // ( pt + t * ray - closest ) % normal = 0;
1872 : : // intersect tangent plane that goes through closest point with the direction
1873 : : // t = normal%(closest-pt) / normal%ray;
1874 [ + - ]: 6 : double dot = normal % ray; // if it is 0, get out while we can
1875 [ - + ]: 6 : if( dot < 0.00001 )
1876 : : {
1877 : : // bad convergence, get out, do not modify anything
1878 : 0 : return MB_SUCCESS;
1879 : : }
1880 [ + - ][ + - ]: 6 : double t = ( ( newPos - pt ) % normal ) / ( dot );
1881 [ + - ][ + - ]: 6 : currentPoint = pt + t * ray;
1882 : : }
1883 : 4 : eval_pt = currentPoint;
1884 [ + - ]: 4 : diff = currentPoint - pt;
1885 [ + - ]: 4 : distance = diff.length();
1886 : 4 : return MB_SUCCESS;
1887 : : }
1888 [ + - ][ + - ]: 44 : } // namespace moab
|