Branch data Line data Source code
1 : : //- Class: FacetDataUtil
2 : : //- Description: static library of general functions for querying and/or
3 : : //- modifying facet entities
4 : : //- Owner: Steve Owen
5 : : //- Checked by:
6 : : //- Version:
7 : :
8 : : #include "FacetDataUtil.hpp"
9 : : #include "FacetEvalTool.hpp"
10 : : #include "CubitFacet.hpp"
11 : : #include "CubitFacetEdge.hpp"
12 : : #include "CubitPoint.hpp"
13 : : #include "CubitPointData.hpp"
14 : : #include "CubitFacetData.hpp"
15 : : #include "CubitFacetEdgeData.hpp"
16 : : #include "CubitQuadFacet.hpp"
17 : : #include "GeometryDefines.h"
18 : : #include "ChollaDebug.hpp"
19 : : #include "GfxDebug.hpp"
20 : : #include "KDDTree.hpp"
21 : :
22 : : //===========================================================================
23 : : //Function Name: edges_by_count
24 : : //Description: find edges that are shared by "count" number of facets
25 : : //Author: bwhanks
26 : : //Date: 2003
27 : : //===========================================================================
28 : 0 : void FacetDataUtil::edges_by_count(DLIList<CubitFacet*> &facets,
29 : : unsigned int count,
30 : : DLIList<CubitFacetEdge*> &edges)
31 : : {
32 : : int i;
33 : : int j;
34 : :
35 : : // get a list of all edges from the facets
36 [ # # ]: 0 : DLIList<CubitFacetEdge*> edge_list;
37 [ # # ]: 0 : facets.reset();
38 [ # # ][ # # ]: 0 : for (i=facets.size(); i>0; i--)
39 : : {
40 [ # # ]: 0 : CubitFacet* p_facet = facets.get_and_step();
41 [ # # ]: 0 : for (j=0; j<3; j++)
42 : : {
43 [ # # ][ # # ]: 0 : edge_list.append(p_facet->edge(j));
44 : : }
45 : : }
46 : :
47 : : // reset edge marks
48 [ # # ]: 0 : edge_list.reset();
49 [ # # ][ # # ]: 0 : for (i=edge_list.size(); i>0; i--)
50 [ # # ][ # # ]: 0 : edge_list.get_and_step()->marked(0);
51 : :
52 : : // mark with the hit count
53 [ # # ]: 0 : edge_list.reset();
54 [ # # ][ # # ]: 0 : for (i=edge_list.size(); i>0; i--)
55 : : {
56 [ # # ]: 0 : CubitFacetEdge* p_edge = edge_list.get_and_step();
57 [ # # ][ # # ]: 0 : p_edge->marked(p_edge->marked() + 1);
58 : : }
59 : :
60 : : // create the output list of edges hit the number of times passed in
61 [ # # ]: 0 : edge_list.reset();
62 [ # # ][ # # ]: 0 : for (i=edge_list.size(); i>0; i--)
63 : : {
64 [ # # ]: 0 : CubitFacetEdge* p_edge = edge_list.get_and_step();
65 [ # # ][ # # ]: 0 : if (static_cast<unsigned>(p_edge->marked()) == count)
66 [ # # ]: 0 : edges.append(p_edge);
67 : : }
68 : :
69 : : // reset edge marks
70 [ # # ]: 0 : edge_list.reset();
71 [ # # ][ # # ]: 0 : for (i=edge_list.size(); i>0; i--)
72 [ # # ][ # # ]: 0 : edge_list.get_and_step()->marked(0);
[ # # ]
73 : 0 : }
74 : :
75 : : //===========================================================================
76 : : //Function Name: ordered_point_edge_bdry
77 : : //Description: get an ordered list of points and edges around the boundary
78 : : // of a set of facets. The output "chain" consists of point -
79 : : // edge - point - edge - ... around the boundary of the input
80 : : // facets. Having the ordered points as well as the edges
81 : : // helps provides sense information for the bounding edges.
82 : : //Author: bwhanks
83 : : //Date: 2003
84 : : //===========================================================================
85 : 0 : void FacetDataUtil::ordered_point_edge_bdry(DLIList<CubitFacet*> &facets,
86 : : DLIList<FacetEntity*> &point_edge_chain)
87 : : {
88 [ # # ][ # # ]: 0 : assert(point_edge_chain.size() == 0);
89 [ # # ]: 0 : DLIList<CubitFacetEdge*> unordered_edges;
90 : :
91 : 0 : int use_count = 1; // get boundary edges (used only once by facets in the facet list)
92 [ # # ]: 0 : FacetDataUtil::edges_by_count(facets, use_count, unordered_edges);
93 : :
94 : : // Adds the start_edge to the list of boundary_edges and then attempts to find the
95 : : // next edge by getting all of the edges belonging to the second point on this
96 : : // edge and searching for an unmarked (-1) boundary edge. Does this until it can't
97 : : // find another edge.
98 : :
99 : :
100 : : // mark all edges connected to points of boundary edges with -2
101 : : // NOTE: using negative marks, since as boundary edges are added to the ordered list they
102 : : // get marked with the order in which they are found
103 : :
104 : : // TODO - this seems very inefficient
105 : : int i;
106 : : int j;
107 : : int k;
108 [ # # ][ # # ]: 0 : DLIList<CubitFacetEdge*> pt_edge_list;
109 : : CubitFacetEdge* cur_edge;
110 [ # # ]: 0 : unordered_edges.reset();
111 [ # # ][ # # ]: 0 : for (i=unordered_edges.size(); i>0; i--)
112 : : {
113 [ # # ]: 0 : cur_edge = unordered_edges.get_and_step();
114 [ # # ]: 0 : for (j=0; j<2; j++)
115 : : {
116 [ # # ]: 0 : pt_edge_list.clean_out();
117 [ # # ][ # # ]: 0 : cur_edge->point(j)->edges(pt_edge_list);
118 [ # # ]: 0 : pt_edge_list.reset();
119 [ # # ][ # # ]: 0 : for (k=pt_edge_list.size(); k>0; k--)
120 [ # # ][ # # ]: 0 : pt_edge_list.get_and_step()->marked(-2);
121 : : }
122 : : }
123 : :
124 : : // mark all boundary edges with -1
125 [ # # ]: 0 : unordered_edges.reset();
126 [ # # ][ # # ]: 0 : for (i=unordered_edges.size(); i>0; i--)
127 [ # # ][ # # ]: 0 : unordered_edges.get_and_step()->marked(-1);
128 : :
129 : :
130 : :
131 : :
132 : : CubitPoint *edge_pt1, *edge_pt2, *pt2, *originalpt1;
133 : : CubitFacetEdge *start_edge;
134 : : CubitFacetEdge *this_edge;
135 : : CubitBoolean keepgoing;
136 : :
137 : 0 : int i_found_some = 0;
138 [ # # ]: 0 : unordered_edges.reset();
139 [ # # ]: 0 : start_edge = unordered_edges.get();
140 : :
141 : : // find the orientation of the first edge with respect to one of the facets
142 : : // then order the edges accordingly
143 [ # # ]: 0 : facets.reset();
144 : : int e_index;
145 : 0 : int start_edge_sense = 0;
146 [ # # ][ # # ]: 0 : for (i=facets.size(); i>0; i--)
147 : : {
148 [ # # ]: 0 : CubitFacet* p_facet = facets.get_and_step();
149 [ # # ][ # # ]: 0 : if ( (e_index = p_facet->edge_index(start_edge)) >= 0 )
150 : : {
151 [ # # ]: 0 : start_edge_sense = p_facet->edge_use(e_index);
152 : 0 : break;
153 : : }
154 : : }
155 : :
156 : :
157 [ # # ]: 0 : start_edge->marked(i_found_some);
158 : 0 : i_found_some += 1;
159 [ # # ]: 0 : if (1 == start_edge_sense)
160 : : {
161 [ # # ]: 0 : originalpt1 = start_edge->point(0);
162 [ # # ]: 0 : point_edge_chain.append(originalpt1);
163 [ # # ]: 0 : point_edge_chain.append(start_edge);
164 [ # # ]: 0 : pt2 = start_edge->point(1);
165 : : }
166 : : else
167 : : {
168 [ # # ]: 0 : assert(-1 == start_edge_sense);
169 [ # # ]: 0 : originalpt1 = start_edge->point(1);
170 [ # # ]: 0 : point_edge_chain.append(originalpt1);
171 [ # # ]: 0 : point_edge_chain.append(start_edge);
172 [ # # ]: 0 : pt2 = start_edge->point(0);
173 : : }
174 : :
175 : :
176 : : // Look for an edge having pt2 as a point and also being on the boundary.
177 [ # # ]: 0 : pt_edge_list.clean_out();
178 [ # # ]: 0 : pt2->edges(pt_edge_list);
179 : :
180 : 0 : keepgoing = CUBIT_TRUE;
181 [ # # ]: 0 : pt_edge_list.reset();
182 [ # # ]: 0 : while ( keepgoing == CUBIT_TRUE ) {
183 : 0 : keepgoing = CUBIT_FALSE;
184 [ # # ][ # # ]: 0 : for ( i = pt_edge_list.size(); i > 0; i-- ) {
185 [ # # ]: 0 : this_edge = pt_edge_list.get_and_step();
186 [ # # ][ # # ]: 0 : if ( this_edge->marked() == -1 ) {
187 : 0 : i_found_some += 1;
188 [ # # ]: 0 : this_edge->marked(i_found_some);
189 [ # # ]: 0 : point_edge_chain.append(pt2);
190 [ # # ]: 0 : point_edge_chain.append(this_edge);
191 : :
192 [ # # ]: 0 : edge_pt1 = this_edge->point(0);
193 [ # # ]: 0 : edge_pt2 = this_edge->point(1);
194 [ # # ]: 0 : if (pt2 == edge_pt1)
195 : : {
196 : 0 : pt2 = edge_pt2;
197 : : }
198 : : else
199 : : {
200 [ # # ]: 0 : assert(pt2 == edge_pt2);
201 : 0 : pt2 = edge_pt1;
202 : : }
203 : :
204 : :
205 : 0 : keepgoing = CUBIT_TRUE;
206 [ # # ]: 0 : pt_edge_list.clean_out();
207 [ # # ]: 0 : pt2->edges(pt_edge_list);
208 : 0 : break;
209 : : }
210 : : }
211 : : }
212 : :
213 : : // clear marks
214 [ # # ][ # # ]: 0 : for (i=unordered_edges.size(); i>0; i--)
215 : : {
216 [ # # ]: 0 : cur_edge = unordered_edges.get_and_step();
217 [ # # ]: 0 : for (j=0; j<2; j++)
218 : : {
219 [ # # ]: 0 : pt_edge_list.clean_out();
220 [ # # ][ # # ]: 0 : cur_edge->point(j)->edges(pt_edge_list);
221 [ # # ]: 0 : pt_edge_list.reset();
222 [ # # ][ # # ]: 0 : for (k=pt_edge_list.size(); k>0; k--)
223 [ # # ][ # # ]: 0 : pt_edge_list.get_and_step()->marked(0);
224 : : }
225 : : }
226 : :
227 [ # # ][ # # ]: 0 : assert(pt2 == originalpt1);
228 : 0 : }
229 : :
230 : : //===========================================================================
231 : : //Function Name: partial_chain
232 : : //Description: given an ordered point - edge boundary and a start and end
233 : : // point on the boundary, return the point - edge chain between
234 : : // the two points, inclusive.
235 : : //Author: bwhanks
236 : : //Date: 2003
237 : : //===========================================================================
238 : 0 : CubitStatus FacetDataUtil::partial_chain(DLIList<FacetEntity*> &point_edge_chain,
239 : : FacetEntity* point1,
240 : : FacetEntity* point2,
241 : : DLIList<FacetEntity*> &chain_between)
242 : : {
243 : : // make sure the edges_between list is empty
244 [ # # ]: 0 : assert(chain_between.size() == 0);
245 [ # # ]: 0 : assert(point1 != point2);
246 : :
247 : : // find the start point in the list
248 : 0 : int pt1_index = point_edge_chain.where_is_item(point1);
249 : :
250 [ # # ]: 0 : if (-1 == pt1_index)
251 : 0 : return CUBIT_FAILURE;
252 : :
253 : 0 : point_edge_chain.reset();
254 : 0 : point_edge_chain.step(pt1_index);
255 : :
256 : 0 : CubitBoolean b_done = CUBIT_FALSE;
257 [ # # ]: 0 : while (!b_done)
258 : : {
259 [ # # ]: 0 : if (point_edge_chain.get() == point2)
260 : 0 : b_done = CUBIT_TRUE;
261 : :
262 : 0 : chain_between.append(point_edge_chain.get_and_step());
263 : : }
264 : :
265 : 0 : return CUBIT_SUCCESS;
266 : : }
267 : :
268 : : //===========================================================================
269 : : //Function Name: get_facet_points
270 : : //Description: return a unique list of the points from a given set of facets
271 : : //Author: bwhanks
272 : : //Date: 2003
273 : : //===========================================================================
274 : 0 : void FacetDataUtil::get_facet_points(DLIList<CubitFacet*> &cubit_facets,
275 : : DLIList<CubitPoint*> &facet_points)
276 : : {
277 : : int i;
278 [ # # ][ # # ]: 0 : DLIList<CubitPoint*> cubit_points(cubit_facets.size() * 3);
279 [ # # ][ # # ]: 0 : for( i = cubit_facets.size(); i--; )
280 : : {
281 [ # # ]: 0 : CubitFacet* facet = cubit_facets.step_and_get();
282 [ # # ]: 0 : for( int j = 0; j < 3; j++ )
283 : : {
284 [ # # ]: 0 : CubitPoint* pt = dynamic_cast<CubitPoint*>(facet->point(j));
285 [ # # ]: 0 : assert(!!pt);
286 [ # # ]: 0 : pt->marked(0);
287 [ # # ]: 0 : cubit_points.append(pt);
288 : : }
289 : : }
290 [ # # ][ # # ]: 0 : for( i = cubit_points.size(); i--; )
291 : : {
292 [ # # ]: 0 : CubitPoint* pt = cubit_points.step_and_get();
293 [ # # ][ # # ]: 0 : pt->marked( pt->marked() + 1);
294 : : }
295 [ # # ][ # # ]: 0 : for( i = cubit_points.size(); i--; )
296 : : {
297 [ # # ]: 0 : CubitPoint* pt = cubit_points.step_and_get();
298 [ # # ][ # # ]: 0 : pt->marked( pt->marked() - 1 );
299 [ # # ][ # # ]: 0 : if( pt->marked() > 0 )
300 [ # # ]: 0 : cubit_points.change_to(0);
301 : : }
302 [ # # ]: 0 : cubit_points.remove_all_with_value(0);
303 : :
304 [ # # ][ # # ]: 0 : facet_points = cubit_points;
305 : 0 : }
306 : :
307 : : //===========================================================================
308 : : //Function Name: get_boundary_points
309 : : //Description: return the boundary points from a list of facets (unordered)
310 : : // assumes edges exist on the facets
311 : : //Author: bwhanks
312 : : //Date: 2003
313 : : //===========================================================================
314 : 0 : void FacetDataUtil::get_boundary_points(DLIList<CubitFacet*> &facet_list,
315 : : DLIList<CubitPoint*> &point_list)
316 : : {
317 : : int ii, jj;
318 : : CubitPoint *pt;
319 : : CubitFacetEdge *edge;
320 : : CubitFacet *facet;
321 [ # # ]: 0 : DLIList<CubitFacetEdge *>edge_list;
322 [ # # ][ # # ]: 0 : for(ii=0; ii<facet_list.size(); ii++)
323 : : {
324 [ # # ]: 0 : facet = facet_list.get_and_step();
325 [ # # ]: 0 : for(jj=0; jj<3; jj++)
326 : : {
327 [ # # ]: 0 : edge = facet->edge( jj );
328 [ # # ][ # # ]: 0 : if (1 == edge->num_adj_facets())
329 : : {
330 [ # # ]: 0 : edge_list.append(edge);
331 [ # # ][ # # ]: 0 : edge->point( 0 )->marked( 0 );
332 [ # # ][ # # ]: 0 : edge->point( 1 )->marked( 0 );
333 : : }
334 : : }
335 : : }
336 [ # # ][ # # ]: 0 : for(ii=0; ii<edge_list.size(); ii++)
337 : : {
338 [ # # ]: 0 : edge = edge_list.get_and_step();
339 [ # # ]: 0 : pt = edge->point( 0 );
340 [ # # ][ # # ]: 0 : if (pt->marked() == 0)
341 : : {
342 [ # # ]: 0 : pt->marked( 1 );
343 [ # # ]: 0 : point_list.append( pt );
344 : : }
345 [ # # ]: 0 : pt = edge->point( 1 );
346 [ # # ][ # # ]: 0 : if (pt->marked() == 0)
347 : : {
348 [ # # ]: 0 : pt->marked( 1 );
349 [ # # ]: 0 : point_list.append( pt );
350 : : }
351 : : }
352 [ # # ][ # # ]: 0 : for(ii=0; ii<point_list.size(); ii++)
353 [ # # ][ # # ]: 0 : point_list.get_and_step()->marked(0);
[ # # ]
354 : :
355 : 0 : }
356 : :
357 : : //===========================================================================
358 : : //Function Name: get_boundary_edges
359 : : //Description: return an unordered list of edges at the boundary of a
360 : : // set of facets
361 : : //Author: sjowen
362 : : //Date: 1/19/2004
363 : : //===========================================================================
364 : 0 : void FacetDataUtil::get_boundary_edges(DLIList<CubitFacet*> &facet_list,
365 : : DLIList<CubitFacetEdge*> &edge_list)
366 : : {
367 : : int ii, jj;
368 : : CubitFacetEdge *edge;
369 : : CubitFacet *facet;
370 [ # # ][ # # ]: 0 : for(ii=0; ii<facet_list.size(); ii++)
371 : : {
372 [ # # ]: 0 : facet = facet_list.get_and_step();
373 [ # # ]: 0 : for(jj=0; jj<3; jj++)
374 : : {
375 [ # # ]: 0 : edge = facet->edge( jj );
376 [ # # ][ # # ]: 0 : if (1 == edge->num_adj_facets())
377 : : {
378 [ # # ]: 0 : edge_list.append(edge);
379 : : }
380 : : }
381 : : }
382 : 0 : }
383 : :
384 : : //===========================================================================
385 : : //Function Name: get_points
386 : : //Description: get a unique set of points from facets
387 : : //Author: sjowen
388 : : //Date: 9/11/03
389 : : //===========================================================================
390 : 44 : void FacetDataUtil::get_points(DLIList<CubitFacet*> &facet_list,
391 : : DLIList<CubitPoint*> &point_list)
392 : : {
393 : : CubitFacet *facet;
394 : : CubitPoint *pt;
395 : : int ii, jj;
396 [ + - ][ + + ]: 396 : for(ii=0; ii<facet_list.size(); ii++)
397 : : {
398 [ + - ]: 352 : facet = facet_list.get_and_step();
399 [ + - ][ + - ]: 352 : facet->point( 0 )->marked( 0 );
400 [ + - ][ + - ]: 352 : facet->point( 1 )->marked( 0 );
401 [ + - ][ + - ]: 352 : facet->point( 2 )->marked( 0 );
402 : : }
403 : :
404 [ + - ][ + + ]: 396 : for (ii=0; ii<facet_list.size(); ii++)
405 : : {
406 [ + - ]: 352 : facet = facet_list.get_and_step();
407 [ + + ]: 1408 : for(jj=0; jj<3; jj++)
408 : : {
409 [ + - ]: 1056 : pt = facet->point(jj);
410 [ + - ][ + + ]: 1056 : if (pt->marked() == 0)
411 : : {
412 [ + - ]: 352 : pt->marked(1);
413 [ + - ]: 352 : point_list.append(pt);
414 : : }
415 : : }
416 : : }
417 : :
418 [ + - ][ + + ]: 396 : for(ii=0; ii<facet_list.size(); ii++)
419 : : {
420 [ + - ]: 352 : facet = facet_list.get_and_step();
421 [ + - ][ + - ]: 352 : facet->point( 0 )->marked( 0 );
422 [ + - ][ + - ]: 352 : facet->point( 1 )->marked( 0 );
423 [ + - ][ + - ]: 352 : facet->point( 2 )->marked( 0 );
424 : : }
425 : 44 : }
426 : :
427 : : //===========================================================================
428 : : //Function Name: copy_facets
429 : : //Description: make a complete copy of facets, points and edges
430 : : //Note: copies edges and points with their "feature" flag
431 : : //Author: sjowen
432 : : //Date: 9/11/03
433 : : //===========================================================================
434 : 0 : void FacetDataUtil::copy_facets(DLIList<CubitFacet*> &old_facet_list,
435 : : DLIList<CubitFacet*> &new_facet_list,
436 : : DLIList<CubitPoint*> &new_point_list,
437 : : DLIList<CubitFacetEdge*> &new_edge_list)
438 : : {
439 : : // get a unique set of points from the facets
440 : :
441 [ # # ]: 0 : DLIList<CubitPoint *> old_point_list;
442 [ # # ]: 0 : get_points(old_facet_list, old_point_list);
443 [ # # ][ # # ]: 0 : CubitPoint **point_array = new CubitPoint* [old_point_list.size()];
[ # # ]
444 : :
445 : : //- copy the points
446 : :
447 : : int ii;
448 [ # # ]: 0 : old_point_list.reset();
449 : : CubitPoint *new_point, *the_point;
450 [ # # ][ # # ]: 0 : for(ii=0; ii<old_point_list.size(); ii++)
451 : : {
452 [ # # ]: 0 : the_point = old_point_list.get_and_step();
453 [ # # ][ # # ]: 0 : new_point = new CubitPointData( the_point->coordinates() );
[ # # ]
454 [ # # ]: 0 : the_point->marked( ii );
455 [ # # ]: 0 : new_point_list.append( new_point );
456 : 0 : point_array[ii] = new_point;
457 [ # # ][ # # ]: 0 : if (the_point->is_feature())
458 [ # # ]: 0 : new_point->set_as_feature();
459 : : }
460 : :
461 : : //- copy the facets
462 : :
463 : : int jj, idx;
464 : : CubitFacet *new_facet, *the_facet;
465 : : CubitPoint *points[3];
466 : :
467 [ # # ]: 0 : old_facet_list.reset();
468 [ # # ][ # # ]: 0 : for (ii=0; ii<old_facet_list.size(); ii++)
469 : : {
470 [ # # ]: 0 : the_facet = old_facet_list.get_and_step();
471 [ # # ]: 0 : for (jj=0; jj<3; jj++)
472 : : {
473 [ # # ][ # # ]: 0 : idx = the_facet->point(jj)->marked();
474 : 0 : points[jj] = point_array[idx];
475 : : }
476 [ # # ][ # # ]: 0 : new_facet = new CubitFacetData( points[0], points[1], points[2] );
477 [ # # ]: 0 : new_facet_list.append( new_facet );
478 : : }
479 : :
480 : : //- copy the edges
481 : :
482 : : int idx0, idx1;
483 : : CubitFacetEdge *new_edge;
484 : : CubitFacetEdge *old_edge;
485 [ # # ][ # # ]: 0 : DLIList<CubitFacetEdge *>old_edge_list;
486 [ # # ]: 0 : get_edges(old_facet_list, old_edge_list);
487 [ # # ][ # # ]: 0 : for(ii=0; ii<old_edge_list.size(); ii++)
488 : : {
489 [ # # ]: 0 : old_edge = old_edge_list.get_and_step();
490 [ # # ][ # # ]: 0 : idx0 = old_edge->point(0)->marked();
491 [ # # ][ # # ]: 0 : idx1 = old_edge->point(1)->marked();
492 [ # # ][ # # ]: 0 : new_edge = new CubitFacetEdgeData( point_array[idx0], point_array[idx1] );
493 [ # # ][ # # ]: 0 : if (old_edge->is_feature())
494 [ # # ]: 0 : new_edge->set_as_feature();
495 [ # # ]: 0 : new_edge_list.append( new_edge );
496 : : }
497 : :
498 [ # # ][ # # ]: 0 : delete [] point_array;
499 : :
500 : 0 : }
501 : :
502 : : //===========================================================================
503 : : //Function Name: get_edges
504 : : //Description: Populates the edge list from the list of facets - creates the
505 : : // edges if necessary
506 : : //Author: sjowen
507 : : //Date: 9/11/03
508 : : //===========================================================================
509 : 198 : void FacetDataUtil::get_edges(
510 : : DLIList<CubitFacet *> &facet_list,
511 : : DLIList<CubitFacetEdge *> &edge_list )
512 : : {
513 : : int i, j;
514 : : CubitPoint *p0, *p1;
515 : : CubitFacet *facet_ptr;
516 : : CubitFacetEdge *edge_ptr;
517 [ + - ]: 198 : DLIList<CubitFacet *> adj_facet_list;
518 : :
519 : : // mark the edges and create any that are missing
520 [ + - ]: 198 : facet_list.reset(); //have to reset this list to that the CubitFacetEdgeData's
521 : : //get constructed correctly
522 [ + - ][ + + ]: 2574 : for ( i = 0; i < facet_list.size(); i++)
523 : : {
524 [ + - ]: 2376 : facet_ptr = facet_list.get_and_step();
525 [ + + ]: 9504 : for (j=0; j<3; j++) {
526 [ + - ]: 7128 : edge_ptr = facet_ptr->edge(j);
527 [ + + ]: 7128 : if (!(edge_ptr))
528 : : {
529 [ + - ]: 1694 : facet_ptr->get_edge_pts(j, p0, p1);
530 [ + - ][ + - ]: 1694 : edge_ptr = (CubitFacetEdge *) new CubitFacetEdgeData( p0, p1 );
531 : : }
532 [ + - ]: 7128 : edge_ptr->set_flag( 0 );
533 : : }
534 : : }
535 : :
536 : : // create a unique list of edges
537 : :
538 [ + - ][ + + ]: 2574 : for ( i = 0; i < facet_list.size(); i++)
539 : : {
540 [ + - ]: 2376 : facet_ptr = facet_list.get_and_step();
541 [ + + ]: 9504 : for (j=0; j<3; j++)
542 : : {
543 [ + - ]: 7128 : edge_ptr = facet_ptr->edge(j);
544 [ + - ][ + - ]: 7128 : if(edge_ptr && 0 == edge_ptr->get_flag())
[ + + ][ + + ]
545 : : {
546 [ + - ]: 3784 : edge_ptr->set_flag( 1 );
547 [ + - ]: 3784 : edge_list.append( edge_ptr );
548 : : }
549 : : }
550 : : }
551 : :
552 : : // reset the flags on the edges
553 : :
554 [ + - ][ + + ]: 2574 : for ( i = 0; i < facet_list.size(); i++)
555 : : {
556 [ + - ]: 2376 : facet_ptr = facet_list.get_and_step();
557 [ + + ]: 9504 : for (j=0; j<3; j++)
558 : : {
559 [ + - ]: 7128 : edge_ptr = facet_ptr->edge(j);
560 [ + - ]: 7128 : if( edge_ptr )
561 [ + - ]: 7128 : edge_ptr->set_flag( 0 );
562 : : }
563 [ + - ]: 198 : }
564 : 198 : }
565 : :
566 : : //============================================================================
567 : : // Function: quality
568 : : // Author: sjowen
569 : : // Description: this is the S.H. Lo metric for triangles that also takes into
570 : : // account a surface normal.
571 : : // Date: 2/2003
572 : : //============================================================================
573 : 0 : double FacetDataUtil::quality(CubitVector &c1, CubitVector &c2, CubitVector &c3,
574 : : CubitVector &surf_normal)
575 : : {
576 : : #define TWO_ROOT_THREE 3.46410161514
577 : : double area2, alpha;
578 : : double length1, length2, length3;
579 [ # # ][ # # ]: 0 : CubitVector edge1, edge2, edge3;
[ # # ]
580 : :
581 : : // create edges from the vertices
582 : :
583 [ # # ][ # # ]: 0 : edge1 = c3 - c2;
584 [ # # ][ # # ]: 0 : edge2 = c3 - c1;
585 [ # # ][ # # ]: 0 : edge3 = c2 - c1;
586 : :
587 : : // compute twice the area
588 : :
589 [ # # ]: 0 : CubitVector normal = edge3 * edge2;
590 [ # # ]: 0 : area2 = normal.length();
591 : :
592 [ # # ]: 0 : length1 = edge1.length_squared();
593 [ # # ]: 0 : length2 = edge2.length_squared();
594 [ # # ]: 0 : length3 = edge3.length_squared();
595 : :
596 : 0 : alpha = TWO_ROOT_THREE * area2 / (length1 + length2 + length3);
597 : :
598 : : // modify the alpha metric by the dot product of the triangle normal
599 : : // with the surface normal.
600 : :
601 [ # # ]: 0 : if (fabs(area2) < CUBIT_RESABS)
602 : 0 : alpha = 0.0;
603 : : else
604 : : {
605 [ # # ]: 0 : normal /= area2;
606 [ # # ]: 0 : double dot = normal % surf_normal;
607 : 0 : double penalty = pow(dot, 5);
608 : 0 : alpha *= penalty;
609 : : }
610 : :
611 : 0 : return alpha;
612 : : }
613 : :
614 : : //================================================================================
615 : : // Description: compares length of two edges.
616 : : // Notes: used for DLIList sort
617 : : // Author : Steve Owen
618 : : // Date : 9/27/2003
619 : : //================================================================================
620 : 0 : int FacetDataUtil::edge_compare(CubitFacetEdge *&ea, CubitFacetEdge *&eb)
621 : : {
622 : 0 : double la = ea->length();
623 : 0 : double lb = eb->length();
624 [ # # ]: 0 : if (la < lb)
625 : 0 : return -1;
626 [ # # ]: 0 : else if (lb < la)
627 : 0 : return 1;
628 : 0 : return 0;
629 : : }
630 : :
631 : : //================================================================================
632 : : // Description: collapse edges that are smaller than 10% the average length
633 : : // Notes: non_manifold_only=true indicates that only edges that are attached
634 : : // to more than two edges will be candidates for collapse.
635 : : // Author : Steve Owen
636 : : // Date : 9/27/2003
637 : : //================================================================================
638 : 11 : CubitStatus FacetDataUtil::collapse_short_edges(
639 : : DLIList<CubitFacet*> &facet_list,
640 : : CubitBoolean non_manifold_only)
641 : : {
642 : : #define COLLAPSE_TOLERANCE 0.3
643 : :
644 : 11 : CubitStatus rv = CUBIT_SUCCESS;
645 : 11 : int ncollapse = 0;
646 : :
647 : : // get the edges
648 : :
649 [ + - ]: 11 : DLIList <CubitFacetEdge *>edge_list;
650 [ + - ][ + - ]: 22 : DLIList <CubitPoint *> point_list;
651 [ + - ][ + - ]: 22 : DLIList <CubitFacet *> one_facet;
652 [ + - ][ + - ]: 22 : DLIList <CubitFacetEdge *> facet_edges;
653 [ + - ]: 11 : FacetDataUtil::get_edges( facet_list, edge_list );
654 [ + - ]: 11 : FacetDataUtil::get_points( facet_list, point_list );
655 : :
656 : : // determine average length and get the collapse threshold
657 : :
658 : : int ii, jj, kk;
659 : : double len;
660 : 11 : double tot_len = 0.0;
661 [ + - ][ + + ]: 99 : for(ii=0; ii<point_list.size(); ii++)
662 [ + - ][ + - ]: 88 : point_list.get_and_step()->marked(0);
663 : : CubitFacetEdge *edge;
664 [ + - ][ + + ]: 209 : for(ii=0; ii<edge_list.size(); ii++)
665 : : {
666 [ + - ]: 198 : edge = edge_list.get_and_step();
667 [ + - ]: 198 : len = edge->length();
668 : 198 : tot_len += len;
669 [ + - ]: 198 : edge->marked(0);
670 : : }
671 [ + - ]: 11 : len = tot_len / edge_list.size();
672 : 11 : double collapse_tol = COLLAPSE_TOLERANCE * len;
673 : : //check(edge_list, facet_list);
674 : :
675 : : // get a list of the edges that qualify for collapse
676 : :
677 [ + - ][ + - ]: 22 : DLIList<CubitFacetEdge *>short_edges;
678 [ + - ][ + + ]: 209 : for(ii=0; ii<edge_list.size(); ii++)
679 : : {
680 [ + - ]: 198 : edge = edge_list.get_and_step();
681 [ + - ][ + - ]: 198 : if (non_manifold_only && edge->num_adj_facets() == 2)
[ + - ][ + - ]
682 : 198 : continue;
683 [ # # ]: 0 : len = edge->length();
684 [ # # ]: 0 : if (len < collapse_tol)
685 : : {
686 [ # # ]: 0 : short_edges.append(edge);
687 : : }
688 : : }
689 : : //sort them
690 : :
691 [ + - ]: 11 : short_edges.sort(FacetDataUtil::edge_compare);
692 : :
693 : : // main loop
694 : :
695 [ + - ]: 11 : int nedges = short_edges.size();
696 [ - + ]: 11 : for(ii=0; ii<nedges; ii++)
697 : : {
698 [ # # ]: 0 : edge = short_edges.get_and_step();
699 [ # # ][ # # ]: 0 : if (edge->marked() == 1)
700 : 0 : continue;
701 [ # # ]: 0 : len = edge->length();
702 : :
703 : 0 : bool collapse = true;
704 : : CubitPoint *pt[2];
705 : : CubitPoint *pt1, *pt2;
706 [ # # ]: 0 : pt[0] = edge->point(0);
707 [ # # ]: 0 : pt[1] = edge->point(1);
708 : :
709 : : // compute a new candidate location for the merged points
710 : :
711 [ # # ]: 0 : CubitVector new_location;
712 [ # # ][ # # ]: 0 : CubitVector cpt[2];
713 [ # # ][ # # ]: 0 : cpt[0] = pt[0]->coordinates();
714 [ # # ][ # # ]: 0 : cpt[1] = pt[1]->coordinates();
715 [ # # ][ # # ]: 0 : new_location = (cpt[0] + cpt[1]) * 0.5;
[ # # ]
716 : :
717 [ # # ][ # # ]: 0 : for (jj=0; jj<2 && collapse; jj++)
718 : : {
719 [ # # ]: 0 : DLIList<CubitFacet *> adjfacets;
720 [ # # ]: 0 : pt[jj]->facets( adjfacets );
721 : :
722 : : // check all facets adjacent this point that don't contain the edge
723 : : // to make sure the resulting facet will be valid (we aren't inverting anything)
724 : :
725 [ # # ][ # # ]: 0 : for(kk=0; kk<adjfacets.size() && collapse; kk++)
[ # # ][ # # ]
726 : : {
727 [ # # ]: 0 : CubitFacet *facet = adjfacets.get_and_step();
728 [ # # ]: 0 : pt1 = facet->next_node( pt[jj] );
729 [ # # ]: 0 : pt2 = facet->next_node( pt1 );
730 [ # # ]: 0 : int eidx = facet->edge_index( edge );
731 [ # # ]: 0 : if (eidx < 0)
732 : : // don't check facets that have the current edge - they'll be deleted anyway
733 : : {
734 : :
735 [ # # ]: 0 : CubitVector cpt1 = pt1->coordinates();
736 [ # # ]: 0 : CubitVector cpt2 = pt2->coordinates();
737 [ # # ]: 0 : CubitVector norm = facet->normal();
738 [ # # ]: 0 : double q0 = FacetDataUtil::quality(cpt[jj], cpt1, cpt2, norm);
739 [ # # ]: 0 : double q1 = FacetDataUtil::quality(new_location, cpt1, cpt2, norm);
740 [ # # ][ # # ]: 0 : if (!(q1 > 0.0 || q1 > q0))
741 : : {
742 : 0 : collapse = false;
743 : : }
744 : : }
745 : : }
746 [ # # ]: 0 : }
747 : :
748 [ # # ]: 0 : if (collapse)
749 : : {
750 [ # # ]: 0 : DLIList<CubitFacet *> new_facets;
751 : 0 : CubitPoint *collpt = pt[0];
752 : 0 : CubitPoint *delpt = pt[1];
753 [ # # ][ # # ]: 0 : DLIList<CubitFacetEdge *> adjedges;
754 : : CubitFacetEdge *adjedge;
755 [ # # ]: 0 : delpt->edges( adjedges );
756 : : CubitFacet *facet;
757 : :
758 : :
759 : 0 : int mydebug = 0;
760 [ # # ]: 0 : if (mydebug)
761 : : {
762 [ # # ]: 0 : dcolor(4);
763 [ # # ]: 0 : draw_edge( edge );
764 [ # # ]: 0 : dview();
765 : : }
766 : :
767 [ # # ]: 0 : collpt->set(new_location);
768 : :
769 : : // delete all facets adjacent to the delpt.
770 : :
771 [ # # ][ # # ]: 0 : DLIList<CubitFacet *> adjfacets;
772 [ # # ]: 0 : delpt->facets( adjfacets );
773 : :
774 [ # # ][ # # ]: 0 : for(jj=0; jj<adjfacets.size(); jj++)
775 : : {
776 [ # # ]: 0 : facet = adjfacets.get_and_step();
777 [ # # ]: 0 : pt1 = facet->next_node(delpt);
778 [ # # ]: 0 : pt2 = facet->next_node(pt1);
779 [ # # ]: 0 : int eidx = facet->edge_index( edge );
780 [ # # ]: 0 : facet_list.move_to(facet);
781 [ # # ][ # # ]: 0 : delete facet;
782 : 0 : facet = NULL;
783 [ # # ]: 0 : if (eidx >= 0)
784 : : {
785 : : //if this facet is adjecnt the edge, then just remove it from the list
786 [ # # ]: 0 : facet_list.extract();
787 : : }
788 : : else
789 : : {
790 : :
791 : : // get or create edges as needed
792 : :
793 : : CubitFacetEdge *e[3];
794 [ # # ]: 0 : e[0] = collpt->get_edge( pt1 );
795 [ # # ]: 0 : e[1] = pt1->get_edge( pt2 );
796 [ # # ]: 0 : e[2] = pt2->get_edge( collpt );
797 [ # # ]: 0 : for (kk=0; kk<3; kk++)
798 : : {
799 [ # # ]: 0 : if (!(e[kk]))
800 : : {
801 [ # # # # ]: 0 : switch (kk)
802 : : {
803 [ # # ][ # # ]: 0 : case 0: e[kk] = (CubitFacetEdge *) new CubitFacetEdgeData( collpt, pt1 ); break;
804 [ # # ][ # # ]: 0 : case 1: e[kk] = (CubitFacetEdge *) new CubitFacetEdgeData( pt1, pt2 ); break;
805 [ # # ][ # # ]: 0 : case 2: e[kk] = (CubitFacetEdge *) new CubitFacetEdgeData( pt2, collpt ); break;
806 : : }
807 [ # # ]: 0 : edge_list.append( e[kk] );
808 : : }
809 : : }
810 : :
811 : : // create a new facet with the points from the old facet and the collpt
812 : :
813 [ # # ][ # # ]: 0 : facet = new CubitFacetData( e[0], e[1], e[2] );
814 [ # # ]: 0 : new_facets.append(facet);
815 : :
816 : : // create edges on the facet
817 : :
818 [ # # ]: 0 : facet_list.change_to( facet );
819 : : }
820 : : }
821 : :
822 [ # # ][ # # ]: 0 : for(jj=0; jj<adjedges.size(); jj++)
823 : : {
824 [ # # ]: 0 : adjedge = adjedges.get_and_step();
825 [ # # ]: 0 : adjedge->marked(1); // mark it for deletion later
826 [ # # ][ # # ]: 0 : assert(adjedge->num_adj_facets() == 0);
827 : : }
828 [ # # ][ # # ]: 0 : assert(delpt->num_adj_facets() == 0);
829 [ # # ]: 0 : ncollapse++;
830 : :
831 : : //check(edge_list, facet_list);
832 : : }
833 : :
834 : : }
835 : :
836 [ + - ][ + - ]: 11 : PRINT_INFO("Collapsed %d short edges in triangulation\n", ncollapse);
[ + - ][ + - ]
837 : :
838 : : // delete points and edges that aren't used
839 [ - + ]: 11 : if (ncollapse > 0)
840 : : {
841 [ # # ][ # # ]: 0 : for(ii=0; ii<edge_list.size(); ii++)
842 : : {
843 [ # # ]: 0 : edge = edge_list.get_and_step();
844 [ # # ][ # # ]: 0 : if (edge->marked())
845 : : {
846 [ # # ][ # # ]: 0 : assert(edge->num_adj_facets() == 0);
847 [ # # ][ # # ]: 0 : delete edge;
848 : : }
849 [ # # ][ # # ]: 0 : else if(edge->num_adj_facets() < 2){
850 [ # # ][ # # ]: 0 : PRINT_ERROR("Unexpected result while collapsing an edge.\n");
[ # # ][ # # ]
851 : 0 : return CUBIT_FAILURE;
852 : : //assert(edge->num_adj_facets() >= 2);
853 : : }
854 : : }
855 : : CubitPoint *point;
856 [ # # ][ # # ]: 0 : for(ii=0; ii<point_list.size(); ii++)
857 : : {
858 [ # # ]: 0 : point = point_list.get_and_step();
859 [ # # ][ # # ]: 0 : if (point->num_adj_facets() == 0)
860 : : {
861 [ # # ][ # # ]: 0 : delete point;
862 : : }
863 : : }
864 : : }
865 : :
866 [ + - ]: 22 : return rv;
867 : : }
868 : :
869 : : //===========================================================================
870 : : // Function: check
871 : : // Purpose: debugging only
872 : : // Date: 10/2003
873 : : // Author: sjowen
874 : : //===========================================================================
875 : 0 : void FacetDataUtil::check(DLIList<CubitFacetEdge *> &edge_list,
876 : : DLIList<CubitFacet *> &facet_list)
877 : : {
878 : :
879 [ # # ]: 0 : CubitBox box;
880 : : CubitFacetEdge *edge;
881 : : int ii;
882 : 0 : int nedges = 0;
883 [ # # ][ # # ]: 0 : for(ii=0; ii<edge_list.size(); ii++)
884 : : {
885 [ # # ]: 0 : edge = edge_list.get_and_step();
886 [ # # ][ # # ]: 0 : if (edge->marked() == 1)
887 : 0 : continue;
888 [ # # ]: 0 : int nadj = edge->num_adj_facets();
889 [ # # ]: 0 : if (nadj <= 1)
890 : : {
891 [ # # ][ # # ]: 0 : CubitVector v0 = edge->point(0)->coordinates();
892 [ # # ][ # # ]: 0 : CubitVector v1 = edge->point(1)->coordinates();
893 [ # # ][ # # ]: 0 : CubitVector min(CUBIT_MIN(v0.x(), v1.x()), CUBIT_MIN(v0.y(), v1.y()), CUBIT_MIN(v0.z(), v1.z()));
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
894 [ # # ][ # # ]: 0 : CubitVector max(CUBIT_MAX(v0.x(), v1.x()), CUBIT_MAX(v0.y(), v1.y()), CUBIT_MAX(v0.z(), v1.z()));
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
895 [ # # ]: 0 : CubitBox ebox(min, max);
896 [ # # ]: 0 : if (nedges == 0)
897 [ # # ]: 0 : box.reset(min, max);
898 : : else
899 [ # # ]: 0 : box |= ebox;
900 : : // dcolor(3);
901 : : // dfldraw(facet_list);
902 [ # # ]: 0 : dcolor(4);
903 [ # # ]: 0 : dedraw(edge);
904 [ # # ]: 0 : dpoint(v0);
905 [ # # ]: 0 : dpoint(v1);
906 [ # # ]: 0 : nedges++;
907 : : }
908 : : }
909 [ # # ]: 0 : if (nedges > 0)
910 : : {
911 [ # # ]: 0 : dzoom(box);
912 [ # # ]: 0 : dview();
913 [ # # ]: 0 : }
914 : 0 : }
915 : :
916 : : //===========================================================================
917 : : // Function: draw_edge
918 : : // Purpose:
919 : : // Date: 10/2003
920 : : // Author: sjowen
921 : : //===========================================================================
922 : 0 : void FacetDataUtil::draw_edge( CubitFacetEdge *edge )
923 : : {
924 [ # # ]: 0 : DLIList<CubitFacet *>adjfacets;
925 [ # # ]: 0 : edge->facets( adjfacets );
926 : : int ii,jj;
927 : : CubitFacet *facet;
928 [ # # ][ # # ]: 0 : CubitBox box;
929 [ # # ]: 0 : for(jj=0; jj<2; jj++)
930 : : {
931 [ # # ]: 0 : CubitPoint *p = edge->point(jj);
932 [ # # ]: 0 : adjfacets.clean_out();
933 [ # # ]: 0 : p->facets( adjfacets );
934 [ # # ][ # # ]: 0 : for(ii=0; ii<adjfacets.size(); ii++)
935 : : {
936 [ # # ]: 0 : facet = adjfacets.get_and_step();
937 [ # # ][ # # ]: 0 : if (jj==0 && ii==0)
938 [ # # ][ # # ]: 0 : box = facet->bounding_box();
939 : : else
940 [ # # ][ # # ]: 0 : box |= facet->bounding_box();
941 [ # # ]: 0 : dfdraw(facet);
942 : : }
943 [ # # ][ # # ]: 0 : dpoint(p->coordinates());
944 [ # # ][ # # ]: 0 : dpoint(p->coordinates());
945 : : }
946 [ # # ][ # # ]: 0 : dzoom(box);
947 : 0 : }
948 : :
949 : : //=============================================================================
950 : : //Function: is_point_in_polyhedron
951 : : //Description: point-in-polyhedron test; polyhedron must be water-tight,
952 : : // manifold, triangle-tiled. Casts a random ray in positive
953 : : // x, y, and z. Counts crossings. Starts over with a recast
954 : : // if a triangle is perpendicular to the ray or if the ray
955 : : // hits a triangle edge or vertex.
956 : : // Also tests for point on polyhedron.
957 : : //Author: John Fowler
958 : : //Date: 9/30/03
959 : : //=============================================================================
960 : 0 : CubitStatus FacetDataUtil::is_point_in_polyhedron(
961 : : DLIList<CubitFacet *> &tfacet_list,
962 : : CubitVector &point_coords,
963 : : CubitPointContainment &is_point_in)
964 : : {
965 : : unsigned int i;
966 [ # # ]: 0 : CubitBox bbox;
967 : : CubitFacet *facet;
968 [ # # ][ # # ]: 0 : CubitVector bbox_min, bbox_max, ray;
[ # # ]
969 : : CubitStatus status;
970 : : CubitPointContainment pt_status;
971 : : bool is_outside, recast, is_on_plane;
972 : : double xpt, ypt, zpt;
973 : : double rayx, rayy, rayz;
974 : : int number_of_recasts;
975 : :
976 [ # # ]: 0 : point_coords.get_xyz(xpt, ypt, zpt);
977 : 0 : recast = true;
978 : 0 : number_of_recasts = 0;
979 [ # # ][ # # ]: 0 : while ( (recast == true) && (number_of_recasts < 10) ) {
980 : 0 : recast = false;
981 : 0 : is_outside = true;
982 [ # # ]: 0 : random_positive_ray(ray); // a random positively-pointing ray
983 [ # # ]: 0 : ray.get_xyz(rayx,rayy,rayz);
984 [ # # ][ # # ]: 0 : for ( i = tfacet_list.size(); i > 0; i-- ) {
985 [ # # ]: 0 : facet = tfacet_list.get_and_step();
986 [ # # ][ # # ]: 0 : bbox = facet->bounding_box();
987 [ # # ][ # # ]: 0 : bbox_min = bbox.minimum();
988 [ # # ][ # # ]: 0 : bbox_max = bbox.maximum();
989 : : // Because the ray is positive in direction, discard bounding boxes
990 : : // that are entirely < the starting point.
991 [ # # ][ # # ]: 0 : if ( (xpt-bbox_max.x()) > CUBIT_RESABS ) continue;
992 [ # # ][ # # ]: 0 : if ( (ypt-bbox_max.y()) > CUBIT_RESABS ) continue;
993 [ # # ][ # # ]: 0 : if ( (zpt-bbox_max.z()) > CUBIT_RESABS ) continue;
994 [ # # ][ # # ]: 0 : if ( ray_intersects_boundingbox(point_coords,ray,bbox) == false )
995 : 0 : continue;
996 [ # # ][ # # ]: 0 : CubitPlane plane = facet->plane();
997 [ # # ][ # # ]: 0 : CubitVector normal = plane.normal();
998 : : double xnorm, ynorm, znorm;
999 [ # # ]: 0 : xnorm = normal.x();
1000 [ # # ]: 0 : ynorm = normal.y();
1001 [ # # ]: 0 : znorm = normal.z();
1002 : : // Intersect the ray with the facet plane. If ray is perpendicular to
1003 : : // facet plane and point is on it, recast the ray and try again.
1004 : 0 : double denominator = rayx*xnorm + rayy*ynorm + rayz*znorm;
1005 [ # # ]: 0 : double distanc = xnorm*xpt + ynorm*ypt + znorm*zpt + plane.coefficient();
1006 [ # # ]: 0 : if ( fabs(denominator) < GEOMETRY_RESABS )
1007 : : {
1008 [ # # ]: 0 : if ( fabs(distanc) < GEOMETRY_RESABS ) {
1009 : 0 : recast = true;
1010 : 0 : break;
1011 : 0 : } else continue; // point is not on plane and ray is parallel to plane
1012 : : }
1013 : : double t, xintpt, yintpt, zintpt;
1014 : 0 : t = -distanc;
1015 : 0 : t /= denominator;
1016 [ # # ]: 0 : if ( fabs(t) < GEOMETRY_RESABS ) is_on_plane = true;
1017 [ # # ]: 0 : else if ( t < GEOMETRY_RESABS ) continue;
1018 : 0 : else is_on_plane = false;
1019 : 0 : xintpt = xpt + t*rayx;
1020 : 0 : yintpt = ypt + t*rayy;
1021 : 0 : zintpt = zpt + t*rayz;
1022 : : CubitPoint *pt;
1023 : : // We need to project the triangle onto 2D. Use the smaller components of
1024 : : // the normal to detemine a good projection.
1025 : : double x0, y0, x1, y1, x2, y2;
1026 [ # # ][ # # ]: 0 : if ( (fabs(xnorm) >= fabs(ynorm)) && (fabs(xnorm) >= fabs(znorm)) ){ // Use y,z
1027 [ # # ]: 0 : pt = facet->point(0);
1028 [ # # ][ # # ]: 0 : x0 = pt->y(); y0 = pt->z();
1029 [ # # ]: 0 : pt = facet->point(1);
1030 [ # # ][ # # ]: 0 : x1 = pt->y(); y1 = pt->z();
1031 [ # # ]: 0 : pt = facet->point(2);
1032 [ # # ][ # # ]: 0 : x2 = pt->y(); y2 = pt->z();
1033 [ # # ]: 0 : status = pt_in_tri_2d(yintpt,zintpt,x0,y0,x1,y1,x2,y2,pt_status);
1034 [ # # ]: 0 : } else if (fabs(ynorm) >= fabs(znorm)) { // Use z,x
1035 [ # # ]: 0 : pt = facet->point(0);
1036 [ # # ][ # # ]: 0 : x0 = pt->x(); y0 = pt->z();
1037 [ # # ]: 0 : pt = facet->point(1);
1038 [ # # ][ # # ]: 0 : x1 = pt->x(); y1 = pt->z();
1039 [ # # ]: 0 : pt = facet->point(2);
1040 [ # # ][ # # ]: 0 : x2 = pt->x(); y2 = pt->z();
1041 [ # # ]: 0 : status = pt_in_tri_2d(xintpt,zintpt,x0,y0,x1,y1,x2,y2,pt_status);
1042 : : } else { // Use x,y
1043 [ # # ]: 0 : pt = facet->point(0);
1044 [ # # ][ # # ]: 0 : x0 = pt->x(); y0 = pt->y();
1045 [ # # ]: 0 : pt = facet->point(1);
1046 [ # # ][ # # ]: 0 : x1 = pt->x(); y1 = pt->y();
1047 [ # # ]: 0 : pt = facet->point(2);
1048 [ # # ][ # # ]: 0 : x2 = pt->x(); y2 = pt->y();
1049 [ # # ]: 0 : status = pt_in_tri_2d(xintpt,yintpt,x0,y0,x1,y1,x2,y2,pt_status);
1050 : : }
1051 : :
1052 [ # # ]: 0 : if ( status == CUBIT_FAILURE ) {
1053 : 0 : recast = true;
1054 : 0 : break;
1055 : : }
1056 [ # # ]: 0 : if ( pt_status == CUBIT_PNT_OUTSIDE ) continue;
1057 : : // Is the point on the triangle?
1058 [ # # ]: 0 : if ( is_on_plane == true ) {
1059 : 0 : is_point_in = CUBIT_PNT_BOUNDARY;
1060 : 0 : return CUBIT_SUCCESS;
1061 : : }
1062 [ # # ]: 0 : if ( pt_status == CUBIT_PNT_INSIDE ) is_outside = ! is_outside;
1063 [ # # ]: 0 : else if ( pt_status == CUBIT_PNT_BOUNDARY ) {
1064 : 0 : recast = true;
1065 : 0 : break;
1066 : : }
1067 : : }
1068 [ # # ]: 0 : if ( recast == true ) {
1069 [ # # ]: 0 : tfacet_list.reset();
1070 : 0 : number_of_recasts += 1;
1071 : : }
1072 : : }
1073 [ # # ]: 0 : if ( recast == true ) {
1074 [ # # ][ # # ]: 0 : PRINT_ERROR("Number of recasts in point-in-polygon exceeded 10.\n");
[ # # ][ # # ]
1075 : 0 : return CUBIT_FAILURE;
1076 : : }
1077 [ # # ]: 0 : if ( is_outside == false ) is_point_in = CUBIT_PNT_INSIDE;
1078 : 0 : else is_point_in = CUBIT_PNT_OUTSIDE;
1079 : :
1080 [ # # ]: 0 : return CUBIT_SUCCESS;
1081 : : }
1082 : :
1083 : : //===========================================================================
1084 : : // Function: pt_in_tri_2d
1085 : : // Purpose:
1086 : : // Date: 10/2003
1087 : : // Author: John Fowler
1088 : : //===========================================================================
1089 : 0 : CubitStatus FacetDataUtil::pt_in_tri_2d(double xpt, double ypt,
1090 : : double x0, double y0,
1091 : : double x1, double y1,
1092 : : double x2, double y2,
1093 : : CubitPointContainment &is_point_in)
1094 : : {
1095 : : // From Schneider & Eberly, "Geometric Tools for COmputer Graphics",
1096 : : // Chap. 13.3.1. If triangle is needle-thin, CUBIT_FAILURE might be
1097 : : // returned, in wich case is_point_in is undefined.
1098 : :
1099 : : double c0, c1, c2;
1100 : : double e0x, e1x, e2x, e0y, e1y, e2y;
1101 : : double n0x, n1x, n2x, n0y, n1y, n2y;
1102 : : double denom0, denom1, denom2;
1103 : :
1104 : 0 : e0x = x1 - x0; e0y = y1 - y0;
1105 : 0 : e1x = x2 - x1; e1y = y2 - y1;
1106 : 0 : e2x = x0 - x2; e2y = y0 - y2;
1107 : 0 : n0x = e0y; n0y = -e0x;
1108 : 0 : n1x = e1y; n1y = -e1x;
1109 : 0 : n2x = e2y; n2y = -e2x;
1110 : 0 : denom0 = n1x*e0x + n1y*e0y;
1111 [ # # ]: 0 : if ( fabs(denom0) < CUBIT_RESABS ) {
1112 [ # # ][ # # ]: 0 : PRINT_ERROR("Failure in pt_in_tri_2d; needle-thin triangle encountered.\n");
1113 : 0 : return CUBIT_FAILURE;
1114 : : }
1115 : 0 : denom1 = n2x*e1x + n2y*e1y;
1116 [ # # ]: 0 : if ( fabs(denom1) < CUBIT_RESABS ) {
1117 [ # # ][ # # ]: 0 : PRINT_ERROR("Failure in pt_in_tri_2d; needle-thin triangle encountered.\n");
1118 : 0 : return CUBIT_FAILURE;
1119 : : }
1120 : 0 : denom2 = n0x*e2x + n0y*e2y;
1121 [ # # ]: 0 : if ( fabs(denom2) < CUBIT_RESABS ) {
1122 [ # # ][ # # ]: 0 : PRINT_ERROR("Failure in pt_in_tri_2d; needle-thin triangle encountered.\n");
1123 : 0 : return CUBIT_FAILURE;
1124 : : }
1125 : :
1126 : 0 : c0 = -( n1x*(xpt-x1) + n1y*(ypt-y1) )/denom0;
1127 : 0 : c1 = -( n2x*(xpt-x2) + n2y*(ypt-y2) )/denom1;
1128 : 0 : c2 = -( n0x*(xpt-x0) + n0y*(ypt-y0) )/denom2;
1129 : :
1130 [ # # ][ # # ]: 0 : if ( (c0 > 0.0) && (c1 > 0.0) && (c2 > 0.0) ) is_point_in = CUBIT_PNT_INSIDE;
[ # # ]
1131 [ # # ][ # # ]: 0 : else if ( (c0 < 0.0) || (c1 < 0.0) || (c2 < 0.0) ) is_point_in = CUBIT_PNT_OUTSIDE;
[ # # ]
1132 : 0 : else is_point_in = CUBIT_PNT_BOUNDARY;
1133 : :
1134 : 0 : return CUBIT_SUCCESS;
1135 : :
1136 : : }
1137 : :
1138 : : //===========================================================================
1139 : : // Function: random_positive_ray
1140 : : // Purpose:
1141 : : // Date: 10/2003
1142 : : // Author: John Fowler
1143 : : //===========================================================================
1144 : 0 : void FacetDataUtil::random_positive_ray(CubitVector& ray)
1145 : : {
1146 : : double temp;
1147 : 0 : double rayx = 0.0, rayy = 0.0, rayz = 0.0;
1148 : :
1149 : 0 : temp = 0.0;
1150 [ # # ]: 0 : while ( temp < 1.e-6 ) {
1151 : 0 : rayx = (double(rand())/(RAND_MAX+1.0));
1152 : 0 : rayy = (double(rand())/(RAND_MAX+1.0));
1153 : 0 : rayz = (double(rand())/(RAND_MAX+1.0));
1154 : 0 : temp = sqrt(rayx*rayx + rayy*rayy + rayz*rayz);
1155 : : }
1156 : 0 : rayx /= temp;
1157 : 0 : rayy /= temp;
1158 : 0 : rayz /= temp;
1159 : :
1160 : 0 : ray.set(rayx,rayy,rayz);
1161 : :
1162 : 0 : }
1163 : :
1164 : : //===========================================================================
1165 : : // Function: ray_intersects_boundingbox
1166 : : // Purpose:
1167 : : // Date: 10/2003
1168 : : // Author: John Fowler
1169 : : //===========================================================================
1170 : 0 : bool FacetDataUtil::ray_intersects_boundingbox(CubitVector& point, CubitVector& ray, const CubitBox& bbox)
1171 : : {
1172 : : double t, xtest, ytest, ztest;
1173 : : double xdir, ydir, zdir, xpt, ypt, zpt, xmin, ymin, zmin, xmax, ymax, zmax;
1174 [ # # ][ # # ]: 0 : CubitVector bbox_min, bbox_max;
1175 : :
1176 [ # # ]: 0 : point.get_xyz(xpt,ypt,zpt);
1177 [ # # ]: 0 : ray.get_xyz(xdir,ydir,zdir);
1178 [ # # ][ # # ]: 0 : bbox_min = bbox.minimum();
1179 [ # # ][ # # ]: 0 : bbox_max = bbox.maximum();
1180 [ # # ]: 0 : bbox_min.get_xyz(xmin,ymin,zmin);
1181 [ # # ]: 0 : bbox_max.get_xyz(xmax,ymax,zmax);
1182 : 0 : xmin -= GEOMETRY_RESABS; // So we don't miss any.
1183 : 0 : ymin -= GEOMETRY_RESABS;
1184 : 0 : zmin -= GEOMETRY_RESABS;
1185 : 0 : xmax += GEOMETRY_RESABS;
1186 : 0 : ymax += GEOMETRY_RESABS;
1187 : 0 : zmax += GEOMETRY_RESABS;
1188 : :
1189 : : // Notice that we are only interested in bboxes on the non-negative side of t.
1190 [ # # ]: 0 : if ( fabs(xdir) > CUBIT_RESABS ) {
1191 : : // test xmin plane
1192 : 0 : t = (xmin - xpt)/xdir;
1193 [ # # ]: 0 : if ( t >= 0.0 ) {
1194 : 0 : ytest = ypt + t*ydir;
1195 : 0 : ztest = zpt + t*zdir;
1196 [ # # ][ # # ]: 0 : if ( (ytest >= ymin) && (ytest <= ymax) && (ztest >= zmin) && (ztest <= zmax) )
[ # # ][ # # ]
1197 : 0 : return true;
1198 : : }
1199 : : // test xmax plane
1200 : 0 : t = (xmax - xpt)/xdir;
1201 [ # # ]: 0 : if ( t > 0.0 ) {
1202 : 0 : ytest = ypt + t*ydir;
1203 : 0 : ztest = zpt + t*zdir;
1204 [ # # ][ # # ]: 0 : if ( (ytest >= ymin) && (ytest <= ymax) && (ztest >= zmin) && (ztest <= zmax) )
[ # # ][ # # ]
1205 : 0 : return true;
1206 : : }
1207 : : }
1208 [ # # ]: 0 : if ( fabs(ydir) > CUBIT_RESABS ) {
1209 : : // test ymin plane
1210 : 0 : t = (ymin - ypt)/ydir;
1211 [ # # ]: 0 : if ( t >= 0.0 ) {
1212 : 0 : xtest = xpt + t*xdir;
1213 : 0 : ztest = zpt + t*zdir;
1214 [ # # ][ # # ]: 0 : if ( (xtest >= xmin) && (xtest <= xmax) && (ztest >= zmin) && (ztest <= zmax) )
[ # # ][ # # ]
1215 : 0 : return true;
1216 : : }
1217 : : // test ymax plane
1218 : :
1219 : 0 : t = (ymax - ypt)/ydir;
1220 [ # # ]: 0 : if ( t > 0.0 ) {
1221 : 0 : xtest = xpt + t*xdir;
1222 : 0 : ztest = zpt + t*zdir;
1223 [ # # ][ # # ]: 0 : if ( (xtest >= xmin) && (xtest <= xmax) && (ztest >= zmin) && (ztest <= zmax) )
[ # # ][ # # ]
1224 : 0 : return true;
1225 : : }
1226 : : }
1227 [ # # ]: 0 : if ( fabs(zdir) > CUBIT_RESABS ) {
1228 : : // test zmin plane
1229 : 0 : t = (zmin - zpt)/zdir;
1230 [ # # ]: 0 : if ( t > 0.0 ) {
1231 : 0 : xtest = xpt + t*xdir;
1232 : 0 : ytest = ypt + t*ydir;
1233 [ # # ][ # # ]: 0 : if ( (xtest >= xmin) && (xtest <= xmax) && (ytest >= ymin) && (ytest <= ymax) )
[ # # ][ # # ]
1234 : 0 : return true;
1235 : : }
1236 : : // test zmax plane
1237 : 0 : t = (zmax - zpt)/zdir;
1238 [ # # ]: 0 : if ( t > 0.0 ) {
1239 : 0 : xtest = xpt + t*xdir;
1240 : 0 : ytest = ypt + t*ydir;
1241 [ # # ][ # # ]: 0 : if ( (xtest >= xmin) && (xtest <= xmax) && (ytest >= ymin) && (ytest <= ymax) )
[ # # ][ # # ]
1242 : 0 : return true;
1243 : : }
1244 : : }
1245 : :
1246 : 0 : return false;
1247 : : }
1248 : :
1249 : : //===========================================================================
1250 : : // Function: write_facets
1251 : : // Purpose: write a list of facets to a cubit facet file
1252 : : // Date: 11/28/2002
1253 : : // Author: sjowen
1254 : : //===========================================================================
1255 : 0 : CubitStatus FacetDataUtil::write_facets( const char *file_name, DLIList<CubitFacet *> &facet_list)
1256 : : {
1257 [ # # ]: 0 : FILE *fp = fopen(file_name, "w");
1258 [ # # ]: 0 : if (!fp)
1259 : : {
1260 [ # # ][ # # ]: 0 : PRINT_ERROR("Couldn't open file %s for writing a facet file.\n", file_name);
[ # # ][ # # ]
1261 : 0 : return CUBIT_FAILURE;
1262 : : }
1263 : :
1264 [ # # ]: 0 : DLIList<CubitPoint*> point_list;
1265 [ # # ]: 0 : get_points(facet_list, point_list);
1266 : :
1267 [ # # ][ # # ]: 0 : fprintf(fp, "%d %d\n", point_list.size(), facet_list.size());
[ # # ]
1268 : : CubitPoint *pt;
1269 : : int ii;
1270 [ # # ][ # # ]: 0 : for (ii=1; ii<=point_list.size(); ii++)
1271 : : {
1272 [ # # ]: 0 : pt = point_list.get_and_step();
1273 [ # # ]: 0 : pt->set_id(ii);
1274 [ # # ][ # # ]: 0 : fprintf(fp, "%d %f %f %f\n", ii, pt->x(), pt->y(), pt->z() );
[ # # ][ # # ]
1275 : : }
1276 : :
1277 : : CubitFacet *facet;
1278 [ # # ][ # # ]: 0 : for (ii=1; ii<=facet_list.size(); ii++)
1279 : : {
1280 [ # # ]: 0 : facet = facet_list.get_and_step();
1281 [ # # ]: 0 : fprintf(fp, "%d %d %d %d\n", ii, facet->point(0)->id(),
1282 [ # # ][ # # ]: 0 : facet->point(1)->id(), facet->point(2)->id());
[ # # ][ # # ]
[ # # ][ # # ]
1283 : : }
1284 : :
1285 [ # # ]: 0 : fclose(fp);
1286 [ # # ]: 0 : return CUBIT_SUCCESS;
1287 : :
1288 : : }
1289 : :
1290 : : //=============================================================================
1291 : : //Function: split_into_shells (PUBLIC)
1292 : : //Description: split this set of facets into multiple surfaces where there are
1293 : : // may be disjoint regions.
1294 : : //Author: sjowen
1295 : : //Date: 8/27/2003
1296 : : //=============================================================================
1297 : 11 : CubitStatus FacetDataUtil::split_into_shells(
1298 : : DLIList<CubitFacet *> &tfacet_list,
1299 : : DLIList<CubitQuadFacet *> &qfacet_list,
1300 : : DLIList<DLIList<CubitFacet *> *> &shell_list,
1301 : : CubitBoolean &is_water_tight)
1302 : : {
1303 : 11 : CubitStatus stat = CUBIT_SUCCESS;
1304 : : //need to init this variable otherwise the caller must have.
1305 : 11 : is_water_tight = CUBIT_TRUE;
1306 : :
1307 : : // combine the quads and tri lists
1308 : :
1309 [ + - ]: 11 : DLIList <CubitFacet *> facet_list = tfacet_list;
1310 : : int ii;
1311 : : CubitQuadFacet *qfacet_ptr;
1312 [ + - ][ - + ]: 11 : for (ii=0; ii<qfacet_list.size(); ii++)
1313 : : {
1314 [ # # ]: 0 : qfacet_ptr = qfacet_list.get_and_step();
1315 [ # # ][ # # ]: 0 : facet_list.append(qfacet_ptr->get_tri_facet( 0 ));
1316 [ # # ][ # # ]: 0 : facet_list.append(qfacet_ptr->get_tri_facet( 1 ));
1317 : : }
1318 : :
1319 : : // mark all the facets to begin with
1320 : :
1321 : : CubitFacet *facet_ptr;
1322 [ + - ][ + + ]: 143 : for (ii=0; ii<facet_list.size(); ii++)
1323 : : {
1324 [ + - ]: 132 : facet_ptr = facet_list.get_and_step();
1325 [ + - ]: 132 : facet_ptr->marked( 1 );
1326 : : }
1327 : :
1328 : : // populate the facet edge lists
1329 : :
1330 [ + - ][ + - ]: 22 : DLIList<CubitFacetEdge *> edge_list;
1331 [ + - ]: 11 : FacetDataUtil::get_edges( facet_list, edge_list );
1332 : :
1333 : : // some debug stuff to draw the facets
1334 : :
1335 : 11 : int mydebug=0;
1336 [ - + ]: 11 : if (mydebug)
1337 : : {
1338 [ # # ][ # # ]: 0 : for (ii=0; ii<facet_list.size(); ii++)
1339 : : {
1340 [ # # ]: 0 : facet_ptr = facet_list.get_and_step();
1341 [ # # ]: 0 : GfxDebug::draw_facet(facet_ptr,CUBIT_YELLOW_INDEX);
1342 : : }
1343 [ # # ]: 0 : GfxDebug::flush();
1344 [ # # ]: 0 : GfxDebug::mouse_xforms();
1345 : : }
1346 : :
1347 : : // Go through the surfaceElemList and pull facets off one by one as we
1348 : : // determine which surface it belongs to. Continue until we have depleted
1349 : : // the list
1350 : :
1351 : : int jj;
1352 : 11 : int num_surfs_created = 0;
1353 [ + - ]: 11 : int num_facets_remaining = facet_list.size();
1354 [ + + ]: 22 : while( num_facets_remaining > 0)
1355 : : {
1356 : : // create a new shell to hold the face info
1357 : :
1358 : 11 : num_surfs_created++;
1359 [ + - ][ + - ]: 11 : DLIList<CubitFacet *> *shell_ptr = new DLIList<CubitFacet *>;
1360 : :
1361 : : // start with the first facet and create a list of all elements
1362 : : // attached to the facet
1363 : :
1364 : 11 : CubitBoolean shell_is_water_tight = CUBIT_TRUE;
1365 [ + - ]: 11 : CubitFacet *start_facet_ptr = facet_list.get_and_step();
1366 : : stat = get_adj_facets_on_shell( start_facet_ptr, shell_ptr,
1367 [ + - ]: 11 : shell_is_water_tight, mydebug );
1368 [ - + ]: 11 : if (stat != CUBIT_SUCCESS)
1369 : 0 : return stat;
1370 [ - + ]: 11 : if (!shell_is_water_tight)
1371 : 0 : is_water_tight = CUBIT_FALSE;
1372 : :
1373 [ + - ]: 11 : shell_list.append( shell_ptr );
1374 : :
1375 : : // remove the facets in this shell from the facet list
1376 : :
1377 [ + - ][ + + ]: 143 : for( jj = facet_list.size(); jj > 0; jj-- )
1378 : : {
1379 [ + - ]: 132 : facet_ptr = facet_list.get();
1380 [ + - ][ + - ]: 132 : if (facet_ptr->marked() == 0)
1381 : : {
1382 [ + - ]: 132 : facet_list.change_to( NULL );
1383 : : }
1384 [ + - ]: 132 : facet_list.step();
1385 : : }
1386 [ + - ]: 11 : facet_list.remove_all_with_value( NULL );
1387 [ + - ]: 11 : num_facets_remaining = facet_list.size();
1388 : : }
1389 : :
1390 [ + - ]: 22 : return CUBIT_SUCCESS;
1391 : : }
1392 : :
1393 : : //=============================================================================
1394 : : //Function: get_adj_facets_on_shell (PRIVATE)
1395 : : //Description: non recursive function that creates a list of all facets connected
1396 : : // the passed in face that are on the same surface
1397 : : //Author: sjowen
1398 : : //Date: 12/22/00
1399 : : //=============================================================================
1400 : 11 : CubitStatus FacetDataUtil::get_adj_facets_on_shell(
1401 : : CubitFacet *start_facet_ptr,
1402 : : DLIList<CubitFacet *> *shell_ptr,
1403 : : CubitBoolean &is_water_tight,
1404 : : int mydebug)
1405 : : {
1406 : 11 : int found = 0;
1407 : : int ii, jj;
1408 : 11 : CubitStatus stat = CUBIT_SUCCESS;
1409 [ + - ]: 11 : DLIList<CubitFacet*> temp_list;
1410 : 11 : CubitFacet *facet_ptr = NULL;
1411 : 11 : CubitFacet *adj_facet_ptr = NULL;
1412 [ + - ][ + - ]: 22 : DLIList<CubitFacetEdge *>edge_list;
1413 : 11 : CubitFacetEdge *edge_ptr = NULL;
1414 [ + - ][ + - ]: 22 : DLIList<CubitFacet *>adj_facet_list;
1415 : :
1416 : : // add this facet to the list
1417 : :
1418 [ + - ]: 11 : temp_list.append( start_facet_ptr );
1419 [ + - ]: 11 : start_facet_ptr->marked( 0 );
1420 : :
1421 [ + - ][ + + ]: 143 : while (temp_list.size())
1422 : : {
1423 [ + - ]: 132 : facet_ptr = temp_list.pop();
1424 [ + - ][ + - ]: 132 : if (facet_ptr->marked() == 0)
1425 : : {
1426 [ + - ]: 132 : shell_ptr->append( facet_ptr );
1427 [ - + ]: 132 : if (mydebug)
1428 : : {
1429 [ # # ]: 0 : GfxDebug::draw_facet(facet_ptr, CUBIT_RED_INDEX);
1430 [ # # ]: 0 : GfxDebug::flush();
1431 : : }
1432 [ + - ]: 132 : edge_list.clean_out();
1433 [ + - ]: 132 : facet_ptr->edges( edge_list );
1434 [ + - ][ + + ]: 528 : for (ii=0; ii<edge_list.size(); ii++)
1435 : : {
1436 [ + - ]: 396 : edge_ptr = edge_list.get_and_step();
1437 [ + - ]: 396 : adj_facet_list.clean_out();
1438 [ + - ]: 396 : edge_ptr->facets( adj_facet_list );
1439 : 396 : found = 0;
1440 : :
1441 [ + - ][ + + ]: 1155 : for (jj=0; jj<adj_facet_list.size() && !found; jj++)
[ + + ][ + + ]
1442 : : {
1443 [ + - ]: 759 : adj_facet_ptr = adj_facet_list.get_and_step();
1444 [ + + ]: 759 : if (adj_facet_ptr != facet_ptr)
1445 : : {
1446 : :
1447 : : // go to its neighbor if it is part of the surface
1448 : :
1449 [ + - ][ + + ]: 396 : if (adj_facet_ptr->marked() == 1)
1450 : : {
1451 [ + - ]: 121 : temp_list.append( adj_facet_ptr );
1452 [ + - ]: 121 : adj_facet_ptr->marked( 0 );
1453 : 121 : found = 1;
1454 : : }
1455 : : }
1456 : :
1457 : : }
1458 [ + - ][ + - ]: 396 : if (is_water_tight && adj_facet_list.size() == 1)
[ - + ][ - + ]
1459 : : {
1460 : 0 : is_water_tight = CUBIT_FALSE;
1461 : : }
1462 : : }
1463 : : }
1464 : : }
1465 : :
1466 [ + - ]: 11 : return stat;
1467 : : }
1468 : :
1469 : : //=============================================================================
1470 : : //Function: stitch_facets (PRIVATE)
1471 : : //Description: attempt to merge facets to form a watertight model
1472 : : //Author: sjowen
1473 : : //Date: 9/9/03
1474 : : //=============================================================================
1475 : 0 : CubitStatus FacetDataUtil::stitch_facets(
1476 : : DLIList<DLIList<CubitFacet *> *> &shell_list,
1477 : : double tol,
1478 : : CubitBoolean &is_water_tight,
1479 : : CubitBoolean write_result)
1480 : : {
1481 : :
1482 : 0 : CubitStatus rv = CUBIT_SUCCESS;
1483 : 0 : int npmerge = 0;
1484 : 0 : int nemerge = 0;
1485 [ # # ]: 0 : DLIList<CubitPoint*> unmerged_points;
1486 : 0 : is_water_tight = CUBIT_FALSE;
1487 : :
1488 [ # # ]: 0 : rv = merge_coincident_vertices( shell_list, tol, npmerge, nemerge, unmerged_points );
1489 [ # # ]: 0 : if (rv != CUBIT_SUCCESS)
1490 : 0 : return rv;
1491 : :
1492 [ # # ]: 0 : int nnomerge = unmerged_points.size();
1493 [ # # ]: 0 : if (nnomerge == 0)
1494 : : {
1495 : 0 : is_water_tight = CUBIT_TRUE;
1496 : : }
1497 : : else
1498 : : {
1499 : : rv = merge_colinear_vertices( shell_list, tol, unmerged_points,
1500 [ # # ]: 0 : npmerge, nemerge, nnomerge );
1501 [ # # ]: 0 : if (rv != CUBIT_SUCCESS)
1502 : 0 : return rv;
1503 : :
1504 [ # # ]: 0 : if (nnomerge == 0)
1505 : : {
1506 : 0 : is_water_tight = CUBIT_TRUE;
1507 : 0 : int mydebug = 0;
1508 [ # # ]: 0 : if (mydebug) // make sure its really water-tight
1509 : : {
1510 : : DLIList<CubitFacet *> *shell_ptr;
1511 [ # # ]: 0 : DLIList<CubitFacetEdge *>boundary_edges;
1512 [ # # ][ # # ]: 0 : for (int ii=0; ii<shell_list.size(); ii++)
1513 : : {
1514 [ # # ]: 0 : shell_ptr = shell_list.get_and_step();
1515 [ # # ]: 0 : FacetDataUtil::get_boundary_edges(*shell_ptr, boundary_edges);
1516 : : }
1517 [ # # ][ # # ]: 0 : if (boundary_edges.size() > 0)
1518 : : {
1519 [ # # ][ # # ]: 0 : PRINT_ERROR("Not Water-tight!\n");
[ # # ][ # # ]
1520 [ # # ]: 0 : }
1521 : : }
1522 : : }
1523 : : }
1524 : :
1525 [ # # ]: 0 : if (write_result)
1526 : : {
1527 [ # # ][ # # ]: 0 : if (npmerge > 0 || nemerge > 0)
1528 : : {
1529 [ # # ][ # # ]: 0 : PRINT_INFO("%d facet vertices and %d facet edges were successfully merged.\n",
[ # # ]
1530 [ # # ]: 0 : npmerge, nemerge);
1531 : : }
1532 [ # # ]: 0 : if (is_water_tight)
1533 : : {
1534 [ # # ][ # # ]: 0 : PRINT_INFO("Facets are water-tight.\n");
[ # # ][ # # ]
1535 : : }
1536 : : else
1537 : : {
1538 [ # # ][ # # ]: 0 : PRINT_INFO("%d facet vertices on model boundary detected that could not be merged.\n", nnomerge);
[ # # ][ # # ]
1539 : : }
1540 : : }
1541 : :
1542 [ # # ]: 0 : return rv;
1543 : : }
1544 : :
1545 : : //=============================================================================
1546 : : //Function: merge_colinear_vertices (PRIVATE)
1547 : : //Description: check if any vertices fall on a free facet edge. If so - split
1548 : : // the adjacent facet to merge
1549 : : //Author: sjowen
1550 : : //Date: 1/19/2004
1551 : : //=============================================================================
1552 : 0 : CubitStatus FacetDataUtil::merge_colinear_vertices(
1553 : : DLIList<DLIList<CubitFacet *> *> &shell_list,
1554 : : double tol,
1555 : : DLIList<CubitPoint *> &merge_point_list, // points to attempt to merge
1556 : : int &npmerge, // return number of vertices merged
1557 : : int &nemerge, // return number of edges merged
1558 : : int &nnomerge) // return number of vertices in list NOT merged
1559 : : {
1560 : 0 : nnomerge = 0;
1561 : 0 : int mydebug = 0;
1562 : :
1563 : : int ii, jj, kk, ll, mm, pt_shell_id, edge_shell_id;
1564 [ # # ]: 0 : RTree <CubitFacetEdge*> r_tree(tol);
1565 [ # # ]: 0 : shell_list.reset();
1566 : 0 : DLIList<CubitFacet *> *shell_ptr = NULL;
1567 : : CubitPoint *pt;
1568 : : CubitFacetEdge *edge;
1569 [ # # ][ # # ]: 0 : DLIList<CubitFacetEdge *>boundary_edges;
1570 [ # # ][ # # ]: 0 : for (ii=0; ii<shell_list.size(); ii++)
1571 : : {
1572 [ # # ]: 0 : shell_ptr = shell_list.get_and_step();
1573 : :
1574 : : // get the boundary edges from the shell - these are candidates for merging.
1575 : : // note that this won't merge internal facets
1576 : :
1577 [ # # ]: 0 : DLIList<CubitFacetEdge *>shell_boundary_edges;
1578 [ # # ]: 0 : FacetDataUtil::get_boundary_edges(*shell_ptr, shell_boundary_edges);
1579 : :
1580 : : // mark each of the edges with a shell id so we know when to merge shells
1581 : : // and add them to the kdtree for fast spatial searching
1582 : 0 : edge_shell_id = ii+1;
1583 [ # # ][ # # ]: 0 : for(jj=0; jj<shell_boundary_edges.size(); jj++)
1584 : : {
1585 [ # # ]: 0 : edge = shell_boundary_edges.get_and_step();
1586 [ # # ][ # # ]: 0 : edge->point(0)->marked(edge_shell_id);
1587 [ # # ][ # # ]: 0 : edge->point(1)->marked(edge_shell_id);
1588 [ # # ]: 0 : edge->marked(edge_shell_id);
1589 [ # # ]: 0 : r_tree.add(edge);
1590 [ # # ]: 0 : boundary_edges.append(edge);
1591 : : }
1592 [ # # ][ # # ]: 0 : for(jj=0; jj<shell_ptr->size(); jj++)
1593 [ # # ][ # # ]: 0 : shell_ptr->get_and_step()->marked( edge_shell_id );
1594 [ # # ]: 0 : }
1595 : :
1596 : : // find points in merge_point_list that are colinear with edges in boundary_edges
1597 : :
1598 [ # # ][ # # ]: 0 : CubitBox ptbox;
1599 [ # # ][ # # ]: 0 : CubitVector ptmin, ptmax, coord;
[ # # ]
1600 [ # # ][ # # ]: 0 : DLIList<CubitFacetEdge *>close_edges;
1601 : : CubitFacetEdge *close_edge;
1602 : : CubitFacet *facet;
1603 : : CubitPoint *p0, *p1;
1604 [ # # ][ # # ]: 0 : DLIList<CubitPoint*>adj_pt_list;
1605 [ # # ][ # # ]: 0 : DLIList<CubitPoint*>del_points;
1606 [ # # ][ # # ]: 0 : for(ii=0; ii<merge_point_list.size(); ii++)
1607 : : {
1608 [ # # ]: 0 : pt = merge_point_list.get_and_step();
1609 [ # # ][ # # ]: 0 : if (pt->marked() < 0) // has already been merged
1610 : 0 : continue;
1611 : :
1612 : : // find the closest edges in the rtree
1613 : :
1614 [ # # ][ # # ]: 0 : coord = pt->coordinates();
1615 [ # # ][ # # ]: 0 : ptmin.set( coord.x() - tol, coord.y() - tol, coord.z() - tol );
[ # # ][ # # ]
1616 [ # # ][ # # ]: 0 : ptmax.set( coord.x() + tol, coord.y() + tol, coord.z() + tol );
[ # # ][ # # ]
1617 [ # # ]: 0 : ptbox.reset( ptmin, ptmax );
1618 [ # # ]: 0 : close_edges.clean_out();
1619 [ # # ]: 0 : r_tree.find(ptbox, close_edges);
1620 : :
1621 : :
1622 : : //remove any close edges that already share the merge point
1623 [ # # ]: 0 : DLIList<CubitFacetEdge*> adj_edges;
1624 [ # # ][ # # ]: 0 : for (jj=close_edges.size(); jj--; )
1625 : : {
1626 [ # # ]: 0 : close_edge = close_edges.get();
1627 : :
1628 [ # # ][ # # ]: 0 : if (close_edge->point(0) == pt || close_edge->point(1) == pt)
[ # # ][ # # ]
[ # # ]
1629 : : {
1630 [ # # ]: 0 : close_edges.change_to( NULL );
1631 [ # # ]: 0 : adj_edges.append( close_edge );
1632 : : }
1633 : :
1634 [ # # ]: 0 : close_edges.step();
1635 : : }
1636 [ # # ]: 0 : close_edges.remove_all_with_value( NULL );
1637 : :
1638 [ # # ][ # # ]: 0 : if( close_edges.size() == 0 && adj_edges.size() > 0 )
[ # # ][ # # ]
[ # # ]
1639 : : {
1640 : : //use a coareser tolerance to get some edges
1641 : : //one tenth the average length of attached edges
1642 : 0 : double temp_tol = 0;
1643 [ # # ][ # # ]: 0 : for( int i=adj_edges.size(); i--; )
1644 [ # # ][ # # ]: 0 : temp_tol += adj_edges.get_and_step()->length();
1645 : :
1646 [ # # ]: 0 : temp_tol /= adj_edges.size();
1647 : 0 : temp_tol *= 0.1;
1648 : :
1649 : : //bump up tolerance to get more edges
1650 [ # # ][ # # ]: 0 : ptmin.set( coord.x() - temp_tol, coord.y() - temp_tol, coord.z() - temp_tol );
[ # # ][ # # ]
1651 [ # # ][ # # ]: 0 : ptmax.set( coord.x() + temp_tol, coord.y() + temp_tol, coord.z() + temp_tol );
[ # # ][ # # ]
1652 [ # # ]: 0 : ptbox.reset( ptmin, ptmax );
1653 [ # # ]: 0 : close_edges.clean_out();
1654 [ # # ]: 0 : r_tree.find(ptbox, close_edges);
1655 : : }
1656 : :
1657 : :
1658 : : // We did find something - go try to merge
1659 : :
1660 : 0 : CubitBoolean was_merged = CUBIT_FALSE;
1661 [ # # ][ # # ]: 0 : for (jj=0; jj<close_edges.size() && !was_merged; jj++)
[ # # ][ # # ]
1662 : : {
1663 : : // test the next edge on the list
1664 : :
1665 [ # # ]: 0 : close_edge = close_edges.get_and_step();
1666 : :
1667 : : // make sure the edge does not contain the merge point
1668 : :
1669 [ # # ][ # # ]: 0 : if (close_edge->point(0) == pt || close_edge->point(1) == pt)
[ # # ][ # # ]
[ # # ]
1670 : 0 : continue;
1671 : :
1672 : : // check to see if the edge is within tolerance of the merge point
1673 : :
1674 [ # # ]: 0 : CubitVector loc_on_edge;
1675 : : CubitBoolean is_outside_edge;
1676 : 0 : double dist = close_edge->dist_to_edge(pt->coordinates(),
1677 [ # # ][ # # ]: 0 : loc_on_edge, is_outside_edge);
1678 : :
1679 : : // allow for some surface curvature. permit the point to be close to
1680 : : // the edge but not on. May want to modify this factor if it not closing
1681 : : // the facets correctly. If it's too big, it may get edges that aren't
1682 : : // really adjacent.
1683 [ # # ]: 0 : double edge_tol = 0.1 * close_edge->length();
1684 [ # # ][ # # ]: 0 : if (is_outside_edge || dist > edge_tol)
1685 : 0 : continue;
1686 : :
1687 : : // go merge the point with the edge
1688 : 0 : was_merged = CUBIT_TRUE;
1689 : :
1690 [ # # ]: 0 : if (mydebug)
1691 : : {
1692 [ # # ]: 0 : DLIList<CubitFacet *> fl;
1693 [ # # ]: 0 : pt->facets( fl );
1694 [ # # ]: 0 : dcolor(CUBIT_YELLOW_INDEX);
1695 [ # # ]: 0 : dfldraw(fl);
1696 [ # # ]: 0 : dcolor(CUBIT_BLUE_INDEX);
1697 [ # # ][ # # ]: 0 : dpoint(pt->coordinates());
1698 [ # # ]: 0 : CubitFacet *f = close_edge->adj_facet(0);
1699 [ # # ]: 0 : dcolor(CUBIT_RED_INDEX);
1700 [ # # ]: 0 : dfdraw(f);
1701 [ # # ][ # # ]: 0 : dview();
1702 : : }
1703 : :
1704 : : // remove close_edge from the rtree
1705 : :
1706 [ # # ]: 0 : r_tree.remove( close_edge );
1707 [ # # ]: 0 : edge_shell_id = close_edge->marked();
1708 [ # # ]: 0 : close_edge->marked(0);
1709 : :
1710 : : // split the edge
1711 : :
1712 [ # # ][ # # ]: 0 : assert(1 == close_edge->num_adj_facets()); // assumes we are splitting a boundary facet
1713 [ # # ]: 0 : facet = close_edge->adj_facet(0);
1714 [ # # ]: 0 : CubitFacetData *dfacet = dynamic_cast<CubitFacetData *>(facet);
1715 : 0 : CubitPoint *new_pt = dfacet->split_edge(close_edge->point(0),
1716 : 0 : close_edge->point(1),
1717 [ # # ][ # # ]: 0 : pt->coordinates());
[ # # ][ # # ]
1718 [ # # ]: 0 : int facet_tool_id = facet->tool_id();
1719 [ # # ]: 0 : new_pt->marked(edge_shell_id);
1720 : :
1721 : : // add any new facets to the shell and create missing edges
1722 : :
1723 [ # # ]: 0 : for (ll=0; ll<edge_shell_id; ll++)
1724 [ # # ]: 0 : shell_ptr = shell_list.get_and_step();
1725 [ # # ]: 0 : DLIList<CubitFacet *>adj_facets;
1726 [ # # ]: 0 : new_pt->facets( adj_facets );
1727 [ # # ][ # # ]: 0 : for (ll=0; ll<adj_facets.size(); ll++)
1728 : : {
1729 [ # # ]: 0 : facet = adj_facets.get_and_step();
1730 [ # # ][ # # ]: 0 : if (!facet->marked())
1731 : : {
1732 [ # # ]: 0 : facet->marked(edge_shell_id);
1733 [ # # ]: 0 : shell_ptr->append(facet);
1734 [ # # ]: 0 : for (mm=0; mm<3; mm++) {
1735 [ # # ][ # # ]: 0 : if (!(edge = facet->edge(mm)))
1736 : : {
1737 [ # # ]: 0 : facet->get_edge_pts(mm, p0, p1);
1738 [ # # ][ # # ]: 0 : edge = (CubitFacetEdge *) new CubitFacetEdgeData( p0, p1 );
1739 [ # # ]: 0 : edge->marked( 0 );
1740 : : }
1741 : : }
1742 [ # # ]: 0 : facet->set_tool_id(facet_tool_id);
1743 : : }
1744 : : }
1745 : :
1746 : : // merge the points,
1747 : :
1748 [ # # ]: 0 : merge_points( pt, new_pt, nemerge, &r_tree );
1749 : 0 : npmerge++;
1750 : :
1751 : : // add any new edges to the rtree
1752 : :
1753 [ # # ][ # # ]: 0 : DLIList<CubitFacetEdge *> adj_edges;
[ # # ]
1754 [ # # ]: 0 : pt->edges( adj_edges );
1755 [ # # ][ # # ]: 0 : for (kk=0; kk<adj_edges.size(); kk++)
1756 : : {
1757 [ # # ]: 0 : CubitFacetEdge *adj_edge = adj_edges.get_and_step();
1758 [ # # ][ # # ]: 0 : if (!adj_edge->marked() && adj_edge->num_adj_facets() == 1)
[ # # ][ # # ]
[ # # ]
1759 : : {
1760 [ # # ][ # # ]: 0 : adj_edge->marked(pt->marked());
1761 [ # # ]: 0 : r_tree.add(adj_edge);
1762 : : }
1763 : : }
1764 : :
1765 : : // see if shells need to merge and then merge
1766 : :
1767 [ # # ]: 0 : pt_shell_id = pt->marked();
1768 [ # # ]: 0 : if (pt_shell_id != edge_shell_id)
1769 : : {
1770 : :
1771 : : // get the shell containing the close point. Nullify the
1772 : : // pointer in the shell list and move all of its facets
1773 : : // to the other shell.
1774 : :
1775 : 0 : int delete_shell = edge_shell_id;
1776 : 0 : DLIList<CubitFacet *> *delete_shell_ptr = NULL;
1777 [ # # ]: 0 : shell_list.reset();
1778 [ # # ]: 0 : for (ll=0; ll<delete_shell; ll++)
1779 [ # # ]: 0 : delete_shell_ptr = shell_list.get_and_step();
1780 [ # # ]: 0 : shell_list.back();
1781 [ # # ]: 0 : shell_list.change_to(NULL);
1782 : :
1783 [ # # ]: 0 : if(!delete_shell_ptr)
1784 : 0 : return CUBIT_FAILURE;
1785 : :
1786 : : // mark all the points on the delete_shell as now being part of
1787 : : // the other shell.
1788 : :
1789 [ # # ][ # # ]: 0 : for(ll=0; ll<delete_shell_ptr->size(); ll++)
1790 : : {
1791 [ # # ]: 0 : facet = delete_shell_ptr->get_and_step();
1792 [ # # ]: 0 : facet->marked( pt_shell_id );
1793 [ # # ][ # # ]: 0 : facet->point( 0 )->marked( pt_shell_id );
1794 [ # # ][ # # ]: 0 : facet->point( 1 )->marked( pt_shell_id );
1795 [ # # ][ # # ]: 0 : facet->point( 2 )->marked( pt_shell_id );
1796 [ # # ][ # # ]: 0 : facet->edge( 0 )->marked( pt_shell_id );
1797 [ # # ][ # # ]: 0 : facet->edge( 1 )->marked( pt_shell_id );
1798 [ # # ][ # # ]: 0 : facet->edge( 2 )->marked( pt_shell_id );
1799 : : }
1800 : :
1801 : : // append the two lists together
1802 : :
1803 [ # # ]: 0 : shell_list.reset();
1804 [ # # ]: 0 : for (ll=0; ll<pt_shell_id; ll++)
1805 [ # # ]: 0 : shell_ptr = shell_list.get_and_step();
1806 [ # # ]: 0 : *shell_ptr += (*delete_shell_ptr);
1807 [ # # ][ # # ]: 0 : delete delete_shell_ptr;
1808 : : }
1809 : :
1810 : : // set the marked flag to negative to indicate that it has been
1811 : : // merged and it needs to be deleted.
1812 : :
1813 [ # # ]: 0 : del_points.append(new_pt);
1814 [ # # ][ # # ]: 0 : new_pt->marked( -new_pt->marked() );
1815 [ # # ][ # # ]: 0 : pt->marked( -pt->marked() );
[ # # ][ # # ]
1816 : 0 : } // close_edges
1817 : :
1818 [ # # ]: 0 : if (!was_merged)
1819 : : {
1820 : 0 : nnomerge++;
1821 [ # # ]: 0 : if (mydebug)
1822 : : {
1823 [ # # ]: 0 : dcolor(CUBIT_BLUE_INDEX);
1824 [ # # ]: 0 : dpdraw(pt);
1825 [ # # ]: 0 : dcolor(CUBIT_RED_INDEX);
1826 [ # # ]: 0 : CubitVector mmin(-1e10, -1e10, -1e10);
1827 [ # # ]: 0 : CubitVector mmax(1e10, 1e10, 1e10);
1828 [ # # ]: 0 : ptbox.reset(mmin, mmax);
1829 [ # # ]: 0 : r_tree.find(ptbox, close_edges);
1830 [ # # ][ # # ]: 0 : for(int zz=0; zz<close_edges.size(); zz++)
1831 : : {
1832 [ # # ]: 0 : edge = close_edges.get_and_step();
1833 [ # # ]: 0 : dedraw(edge);
1834 [ # # ]: 0 : CubitVector loc_on_edge;
1835 : : CubitBoolean is_on_edge;
1836 [ # # ][ # # ]: 0 : double dist = edge->dist_to_edge(pt->coordinates(), loc_on_edge, is_on_edge);
1837 [ # # ][ # # ]: 0 : PRINT_INFO("edge %d dist = %f is_on_edge = %d\n", edge->id(), dist, is_on_edge);
[ # # ][ # # ]
[ # # ]
1838 : : }
1839 [ # # ][ # # ]: 0 : dview();
[ # # ]
1840 : : }
1841 : : }
1842 : 0 : } // merge_point_list
1843 : :
1844 : : // compress the shell list
1845 : :
1846 [ # # ]: 0 : shell_list.remove_all_with_value(NULL);
1847 : :
1848 : : // delete points that were merged
1849 : :
1850 [ # # ][ # # ]: 0 : for (ii=0; ii<del_points.size(); ii++)
1851 : : {
1852 [ # # ]: 0 : pt = del_points.get_and_step();
1853 [ # # ][ # # ]: 0 : if (pt->marked() < 0)
1854 : : {
1855 [ # # ][ # # ]: 0 : assert( pt->num_adj_facets() == 0 );
1856 [ # # ][ # # ]: 0 : delete pt;
1857 : : }
1858 : : }
1859 : :
1860 [ # # ]: 0 : return CUBIT_SUCCESS;
1861 : : }
1862 : :
1863 : : //=============================================================================
1864 : : //Function: merge_points (PRIVATE)
1865 : : //Description: merge two cubit points where it has been determined that they
1866 : : // are coincident. Also handle merging their adjacent edges where
1867 : : // appropriate
1868 : : //Author: sjowen
1869 : : //Date: 1/19/2004
1870 : : //=============================================================================
1871 : 0 : CubitStatus FacetDataUtil::merge_points(
1872 : : CubitPoint *pt0, CubitPoint *pt1,
1873 : : int &nemerge, RTree <CubitFacetEdge*> *r_tree) // number of edges we had to merge top do this
1874 : : {
1875 : 0 : int mydebug = 0;
1876 : :
1877 : : // merge the points
1878 : 0 : pt0->merge_points( pt1, CUBIT_TRUE );
1879 : : //pt0->set_as_feature();
1880 : :
1881 [ # # ]: 0 : if (mydebug)
1882 : : {
1883 [ # # ]: 0 : DLIList<CubitFacet *>adj_facets;
1884 [ # # ]: 0 : pt0->facets( adj_facets );
1885 [ # # ]: 0 : dcolor(CUBIT_RED_INDEX);
1886 [ # # ][ # # ]: 0 : dfldraw(adj_facets);
1887 : : }
1888 : :
1889 : : // merge edges
1890 : :
1891 : : int ll, mm;
1892 : : bool edge_merged;
1893 [ # # ]: 0 : do {
1894 : 0 : edge_merged = false;
1895 : : CubitFacetEdge *edge, *other_edge;
1896 : :
1897 [ # # ]: 0 : DLIList<CubitFacetEdge *> adj_edges;
1898 [ # # ]: 0 : pt0->edges( adj_edges );
1899 [ # # ][ # # ]: 0 : for(ll=0; ll<adj_edges.size() && !edge_merged; ll++)
[ # # ][ # # ]
1900 : : {
1901 [ # # ]: 0 : edge = adj_edges.get_and_step();
1902 [ # # ][ # # ]: 0 : for(mm=0; mm<adj_edges.size() && !edge_merged; mm++)
[ # # ][ # # ]
1903 : : {
1904 [ # # ]: 0 : other_edge = adj_edges.get_and_step();
1905 [ # # ][ # # ]: 0 : if (other_edge != edge &&
[ # # ]
1906 [ # # ][ # # ]: 0 : edge->other_point(pt0) == other_edge->other_point(pt0))
1907 : : {
1908 [ # # ]: 0 : CubitFacetEdgeData *dedge = dynamic_cast<CubitFacetEdgeData*>(edge);
1909 [ # # ]: 0 : CubitFacetEdgeData *dother_edge = dynamic_cast<CubitFacetEdgeData*>(other_edge);
1910 : : // mbrewer (11/16/2005 for Bug 5049)
1911 [ # # ]: 0 : if(r_tree){
1912 : : // r_tree->remove(dother_edge);
1913 [ # # ]: 0 : CubitBoolean temp_bool = r_tree->remove(dother_edge);
1914 [ # # ]: 0 : if(!temp_bool){
1915 [ # # ][ # # ]: 0 : PRINT_DEBUG_139("FacetDataUtil: D_OTHER_EDGE did not exist in RTREE.\n");
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1916 : : }
1917 : : }
1918 [ # # ][ # # ]: 0 : if (dedge->merge_edges( dother_edge ) == CUBIT_SUCCESS)
1919 : : {
1920 : 0 : nemerge++;
1921 : 0 : edge_merged = true;
1922 [ # # ]: 0 : dedge->set_as_feature();
1923 : : }
1924 : : }
1925 : : }
1926 [ # # ]: 0 : }
1927 : : } while (edge_merged);
1928 : 0 : return CUBIT_SUCCESS;
1929 : : }
1930 : :
1931 : :
1932 : 0 : CubitStatus FacetDataUtil::merge_coincident_vertices( DLIList<CubitPoint*> &points )
1933 : : {
1934 : 0 : points.reset();
1935 : 0 : CubitPoint *surviving_point = points.pop();
1936 [ # # ]: 0 : while( points.size() )
1937 : : {
1938 : 0 : int nemerge = 0;
1939 [ # # ][ # # ]: 0 : merge_points( surviving_point, points.pop(), nemerge );
1940 : : }
1941 : :
1942 : 0 : return CUBIT_SUCCESS;
1943 : : }
1944 : :
1945 : :
1946 : :
1947 : : //=============================================================================
1948 : : //Function: merge_coincident_vertices (PRIVATE)
1949 : : //Description: merge vertices (and connected facets and edges) if they are
1950 : : // within tolerance.
1951 : : //Author: sjowen
1952 : : //Date: 9/9/03
1953 : : //=============================================================================
1954 : 0 : CubitStatus FacetDataUtil::merge_coincident_vertices(
1955 : : DLIList<DLIList<CubitFacet *> *> &shell_list,
1956 : : double tol,
1957 : : int &npmerge, // return number of vertices merged
1958 : : int &nemerge, // return number of edges merged
1959 : : DLIList<CubitPoint *> &unmerged_points) // return the vertices on boundary NOT merged
1960 : : {
1961 : 0 : int mydebug = 0;
1962 : 0 : npmerge = 0;
1963 : 0 : nemerge = 0;
1964 : : int ii, jj, kk, ll, shell_id;
1965 [ # # ]: 0 : KDDTree <CubitPoint*> kd_tree(tol, false);
1966 [ # # ]: 0 : CubitPoint::set_box_tol( tol );
1967 [ # # ]: 0 : shell_list.reset();
1968 : 0 : DLIList<CubitFacet *> *shell_ptr = NULL;
1969 : : CubitPoint *pt;
1970 [ # # ][ # # ]: 0 : DLIList<CubitPoint *>boundary_points;
1971 [ # # ][ # # ]: 0 : DLIList<CubitPoint *> del_points;
1972 [ # # ][ # # ]: 0 : for (ii=0; ii<shell_list.size(); ii++)
1973 : : {
1974 [ # # ]: 0 : shell_ptr = shell_list.get_and_step();
1975 : :
1976 : : // get the boundary points from the shell - these are candidates for merging.
1977 : : // note that this won't merge internal facets
1978 : :
1979 [ # # ]: 0 : DLIList<CubitPoint *>shell_boundary_points;
1980 [ # # ]: 0 : FacetDataUtil::get_boundary_points(*shell_ptr, shell_boundary_points);
1981 : :
1982 : : // mark each of the points with a shell id so we know when to merge shells
1983 : : // and add them to the kdtree for fast spatial searching
1984 : :
1985 : 0 : shell_id = ii+1;
1986 [ # # ][ # # ]: 0 : for(jj=0; jj<shell_boundary_points.size(); jj++)
1987 : : {
1988 [ # # ]: 0 : pt = shell_boundary_points.get_and_step();
1989 [ # # ]: 0 : pt->marked(shell_id);
1990 [ # # ]: 0 : kd_tree.add(pt);
1991 [ # # ]: 0 : boundary_points.append(pt);
1992 : : }
1993 [ # # ]: 0 : }
1994 [ # # ]: 0 : kd_tree.balance();
1995 : :
1996 : : // find points that are coincident
1997 : :
1998 [ # # ][ # # ]: 0 : CubitBox ptbox;
1999 [ # # ][ # # ]: 0 : CubitVector ptmin, ptmax, coord;
[ # # ]
2000 [ # # ][ # # ]: 0 : DLIList<CubitPoint *>close_points;
2001 : 0 : CubitPoint *close_pt = NULL;
2002 : : CubitFacet *facet;
2003 [ # # ][ # # ]: 0 : DLIList<CubitPoint*>adj_pt_list;
2004 : :
2005 [ # # ][ # # ]: 0 : for(ii=0; ii<boundary_points.size(); ii++)
2006 : : {
2007 [ # # ]: 0 : pt = boundary_points.get_and_step();
2008 [ # # ][ # # ]: 0 : if (pt->marked() < 0) // has already been merged
2009 : 0 : continue;
2010 : :
2011 : : // find the closest points in the kdtree
2012 : :
2013 [ # # ][ # # ]: 0 : coord = pt->coordinates();
2014 [ # # ][ # # ]: 0 : ptmin.set( coord.x() - tol, coord.y() - tol, coord.z() - tol );
[ # # ][ # # ]
2015 [ # # ][ # # ]: 0 : ptmax.set( coord.x() + tol, coord.y() + tol, coord.z() + tol );
[ # # ][ # # ]
2016 [ # # ]: 0 : ptbox.reset( ptmin, ptmax );
2017 [ # # ]: 0 : close_points.clean_out();
2018 [ # # ]: 0 : kd_tree.find(ptbox, close_points);
2019 : :
2020 : : // if it didn't find anything to merge with, then we aren't water-tight
2021 : :
2022 : 0 : CubitBoolean was_merged = CUBIT_FALSE;
2023 : :
2024 : : // We did find something - go try to merge
2025 : :
2026 [ # # ][ # # ]: 0 : for (jj=0; jj<close_points.size(); jj++)
2027 : : {
2028 [ # # ]: 0 : close_pt = close_points.get_and_step();
2029 [ # # ]: 0 : if (close_pt == pt)
2030 : 0 : continue;
2031 [ # # ][ # # ]: 0 : if (close_pt->marked() < 0) // has already been merged
2032 : 0 : continue;
2033 [ # # ][ # # ]: 0 : assert(close_points.size() >= 1);
2034 : :
2035 : : // make sure this point is not already one of its neighbors
2036 : : // so we don't collapse a triangle
2037 : :
2038 : 0 : CubitBoolean is_adjacent = CUBIT_FALSE;
2039 [ # # ]: 0 : adj_pt_list.clean_out();
2040 [ # # ]: 0 : close_pt->adjacent_points( adj_pt_list );
2041 [ # # ][ # # ]: 0 : for (kk=0; kk<adj_pt_list.size() && !is_adjacent; kk++)
[ # # ][ # # ]
2042 : : {
2043 [ # # ][ # # ]: 0 : if (adj_pt_list.get_and_step() == pt)
2044 : 0 : is_adjacent = CUBIT_TRUE;
2045 : : }
2046 [ # # ]: 0 : if (!is_adjacent)
2047 : : {
2048 : : // merge the points
2049 : :
2050 [ # # ]: 0 : merge_points( pt, close_pt, nemerge );
2051 : 0 : npmerge++;
2052 : 0 : was_merged = CUBIT_TRUE;
2053 : :
2054 : : // see if shells need to merge and then merge
2055 : :
2056 [ # # ]: 0 : shell_id = pt->marked();
2057 [ # # ][ # # ]: 0 : if (shell_id != close_pt->marked())
2058 : : {
2059 : :
2060 : : // get the shell containing the close point. Nullify the
2061 : : // pointer in the shell list and move all of its facets
2062 : : // to the other shell.
2063 : :
2064 [ # # ]: 0 : int delete_shell = close_pt->marked();
2065 : 0 : DLIList<CubitFacet *> *delete_shell_ptr = NULL;
2066 [ # # ]: 0 : shell_list.reset();
2067 [ # # ]: 0 : for (ll=0; ll<delete_shell; ll++)
2068 [ # # ]: 0 : delete_shell_ptr = shell_list.get_and_step();
2069 [ # # ]: 0 : shell_list.back();
2070 [ # # ]: 0 : shell_list.change_to(NULL);
2071 : :
2072 : : // mark all the points on the delete_shell as now being part of
2073 : : // the other shell.
2074 : :
2075 [ # # ][ # # ]: 0 : for(ll=0; ll<delete_shell_ptr->size(); ll++)
2076 : : {
2077 [ # # ]: 0 : facet = delete_shell_ptr->get_and_step();
2078 [ # # ][ # # ]: 0 : facet->point( 0 )->marked( shell_id );
2079 [ # # ][ # # ]: 0 : facet->point( 1 )->marked( shell_id );
2080 [ # # ][ # # ]: 0 : facet->point( 2 )->marked( shell_id );
2081 : : }
2082 : :
2083 : : // append the two lists together
2084 : :
2085 [ # # ]: 0 : shell_list.reset();
2086 [ # # ]: 0 : for (ll=0; ll<shell_id; ll++)
2087 [ # # ]: 0 : shell_ptr = shell_list.get_and_step();
2088 [ # # ]: 0 : *shell_ptr += (*delete_shell_ptr);
2089 [ # # ][ # # ]: 0 : delete delete_shell_ptr;
2090 : : }
2091 : :
2092 : : // set the marked flag to negative to indicate that it has been
2093 : : // merged and it need to be deleted.
2094 : :
2095 [ # # ][ # # ]: 0 : if (close_pt->marked() > 0)
2096 [ # # ][ # # ]: 0 : close_pt->marked( -close_pt->marked() );
2097 [ # # ]: 0 : del_points.append( close_pt );
2098 : : }
2099 : : }
2100 [ # # ]: 0 : if (was_merged)
2101 : : {
2102 [ # # ][ # # ]: 0 : if (pt->marked() > 0)
2103 [ # # ][ # # ]: 0 : pt->marked( -pt->marked() );
2104 : : }
2105 : : else
2106 : : {
2107 : : // check to see if it was already merged
2108 [ # # ][ # # ]: 0 : if (close_points.size() == 1 && close_pt == pt)
[ # # ][ # # ]
2109 : : {
2110 : : CubitFacetEdge *edge_ptr;
2111 [ # # ]: 0 : DLIList<CubitFacetEdge *>adj_edges;
2112 [ # # ]: 0 : pt->edges(adj_edges);
2113 : 0 : CubitBoolean on_boundary = CUBIT_FALSE;
2114 [ # # ][ # # ]: 0 : for(kk=0; kk<adj_edges.size() && !on_boundary; kk++)
[ # # ][ # # ]
2115 : : {
2116 [ # # ]: 0 : edge_ptr = adj_edges.get_and_step();
2117 [ # # ][ # # ]: 0 : if (edge_ptr->num_adj_facets() == 1)
2118 : 0 : on_boundary = CUBIT_TRUE;
2119 : : }
2120 [ # # ]: 0 : if (on_boundary)
2121 : : {
2122 : : //PRINT_INFO("Merging 'boundary' points.\n");
2123 : : //if (pt->marked() > 0) pt->marked( -pt->marked() );
2124 [ # # ]: 0 : unmerged_points.append(pt);
2125 : : }
2126 : : else
2127 : : {
2128 [ # # ][ # # ]: 0 : if (pt->marked() > 0) pt->marked( -pt->marked() );
[ # # ][ # # ]
2129 [ # # ]: 0 : }
2130 : : }
2131 : : else
2132 : : {
2133 : : // otherwise save it as an unmerged point to be handled later
2134 [ # # ]: 0 : unmerged_points.append(pt);
2135 : : }
2136 : : }
2137 : : }
2138 : :
2139 : : // compress the shell list
2140 : :
2141 [ # # ]: 0 : shell_list.remove_all_with_value(NULL);
2142 : :
2143 : : // delete points that were merged
2144 : :
2145 [ # # ][ # # ]: 0 : for (ii=0; ii<del_points.size(); ii++)
2146 : : {
2147 [ # # ]: 0 : pt = del_points.get_and_step();
2148 [ # # ][ # # ]: 0 : if (pt->marked() < 0)
2149 : : {
2150 [ # # ][ # # ]: 0 : assert( pt->num_adj_facets() == 0 );
2151 [ # # ][ # # ]: 0 : delete pt;
2152 : : }
2153 : : }
2154 : :
2155 : : //double-check that these are still boundary points.
2156 : : //found case where two shells were tied together by a single facet point.
2157 : : //this point was initially deemed an unmerged boundary point but later
2158 : : //adjacent boundary edges got merged so it should not be a boundary
2159 : : //point anymore.
2160 [ # # ][ # # ]: 0 : for( int k=0; k<unmerged_points.size(); k++ )
2161 : : {
2162 [ # # ]: 0 : DLIList<CubitFacetEdge *>adj_edges;
2163 [ # # ][ # # ]: 0 : unmerged_points[k]->edges(adj_edges);
2164 : 0 : CubitBoolean on_boundary = CUBIT_FALSE;
2165 [ # # ][ # # ]: 0 : for(kk=0; kk<adj_edges.size(); kk++)
2166 : : {
2167 [ # # ]: 0 : CubitFacetEdge *edge_ptr = adj_edges.get_and_step();
2168 [ # # ][ # # ]: 0 : if (edge_ptr->num_adj_facets() == 1)
2169 : : {
2170 : 0 : on_boundary = CUBIT_TRUE;
2171 : 0 : break;
2172 : : }
2173 : : }
2174 [ # # ]: 0 : if( CUBIT_FALSE == on_boundary )
2175 [ # # ]: 0 : unmerged_points[k] = NULL;
2176 [ # # ]: 0 : }
2177 [ # # ]: 0 : unmerged_points.remove_all_with_value(NULL);
2178 : :
2179 [ # # ]: 0 : if (mydebug)
2180 : : {
2181 : : CubitFacetEdge *edge;
2182 [ # # ][ # # ]: 0 : for (ii=0; ii<shell_list.size(); ii++)
2183 : : {
2184 [ # # ]: 0 : shell_ptr = shell_list.get_and_step();
2185 [ # # ]: 0 : dcolor(CUBIT_GREEN_INDEX);
2186 [ # # ]: 0 : dfldraw(*shell_ptr);
2187 [ # # ]: 0 : dcolor(CUBIT_RED_INDEX);
2188 [ # # ][ # # ]: 0 : for(jj=0; jj<shell_ptr->size(); jj++)
2189 : : {
2190 [ # # ]: 0 : facet = shell_ptr->get_and_step();
2191 [ # # ]: 0 : for(kk=0; kk<3; kk++)
2192 : : {
2193 [ # # ]: 0 : edge = facet->edge(kk);
2194 [ # # ]: 0 : DLIList<FacetEntity *> myfacet_list;
2195 [ # # ]: 0 : edge->get_parents( myfacet_list );
2196 [ # # ][ # # ]: 0 : assert(myfacet_list.size() == edge->num_adj_facets());
[ # # ]
2197 [ # # ][ # # ]: 0 : if (myfacet_list.size() != 2)
2198 : : {
2199 [ # # ]: 0 : dedraw( edge );
2200 : : }
2201 [ # # ]: 0 : }
2202 : : }
2203 : : }
2204 [ # # ]: 0 : dcolor(CUBIT_BLUE_INDEX);
2205 [ # # ]: 0 : dpldraw(unmerged_points);
2206 [ # # ]: 0 : dview();
2207 : : }
2208 : :
2209 [ # # ]: 0 : return CUBIT_SUCCESS;
2210 : :
2211 : : }
2212 : :
2213 : : //=============================================================================
2214 : : //Function: delete_facets (PUBLIC)
2215 : : //Description: delete the facets and all associated edges and points from
2216 : : // a list of lists of facets (shell_list)
2217 : : //Author: sjowen
2218 : : //Date: 1/21/2004
2219 : : //=============================================================================
2220 : 0 : void FacetDataUtil::delete_facets(DLIList<DLIList<CubitFacet*>*> &shell_list)
2221 : : {
2222 : : int ii;
2223 [ # # ]: 0 : for (ii=0; ii<shell_list.size(); ii++)
2224 : : {
2225 : 0 : DLIList<CubitFacet*> *facet_list_ptr = shell_list.get_and_step();
2226 : 0 : delete_facets( *facet_list_ptr );
2227 : : }
2228 : 0 : }
2229 : :
2230 : : //=============================================================================
2231 : : //Function: delete_facets (PUBLIC)
2232 : : //Description: delete the facets and all associated edges and points from
2233 : : // a list of facets
2234 : : //Author: sjowen
2235 : : //Date: 1/21/2004
2236 : : //=============================================================================
2237 : 0 : void FacetDataUtil::delete_facets(DLIList<CubitFacet*> &facet_list)
2238 : : {
2239 : : int ii;
2240 : : CubitFacet *facet_ptr;
2241 [ # # ]: 0 : for (ii=0; ii<facet_list.size(); ii++)
2242 : : {
2243 : 0 : facet_ptr = facet_list.get_and_step();
2244 : 0 : delete_facet( facet_ptr );
2245 : : }
2246 : 0 : }
2247 : :
2248 : : //=============================================================================
2249 : : //Function: delete_facet (PUBLIC)
2250 : : //Description: delete a single facet and its underlying edges and points if
2251 : : // they are no longer attached to anything
2252 : : //Author: sjowen
2253 : : //Date: 1/21/2004
2254 : : //=============================================================================
2255 : 0 : void FacetDataUtil::delete_facet(CubitFacet *facet_ptr)
2256 : : {
2257 [ # # ]: 0 : DLIList<CubitPoint *>point_list;
2258 [ # # ][ # # ]: 0 : DLIList<CubitFacetEdge *>edge_list;
2259 [ # # ]: 0 : facet_ptr->points(point_list);
2260 [ # # ]: 0 : facet_ptr->edges(edge_list);
2261 : :
2262 [ # # ][ # # ]: 0 : delete facet_ptr;
2263 : :
2264 : : CubitFacetEdge *edge_ptr;
2265 : : CubitPoint *point_ptr;
2266 : : int ii;
2267 : :
2268 [ # # ][ # # ]: 0 : for (ii=0; ii<edge_list.size(); ii++)
2269 : : {
2270 [ # # ]: 0 : edge_ptr = edge_list.get_and_step();
2271 [ # # ][ # # ]: 0 : if (edge_ptr->num_adj_facets() == 0)
2272 [ # # ][ # # ]: 0 : delete edge_ptr;
2273 : : }
2274 : :
2275 [ # # ]: 0 : for (ii=0; ii<3; ii++)
2276 : : {
2277 [ # # ]: 0 : point_ptr = point_list.get_and_step();
2278 [ # # ][ # # ]: 0 : if (point_ptr->num_adj_facets() == 0)
2279 [ # # ][ # # ]: 0 : delete point_ptr;
2280 [ # # ]: 0 : }
2281 : :
2282 : 0 : }
2283 : :
2284 : :
2285 : 0 : void FacetDataUtil::destruct_facet_no_delete(CubitFacet *facet_ptr)
2286 : : {
2287 [ # # ]: 0 : CubitFacetData* facet_d_ptr = dynamic_cast<CubitFacetData*>(facet_ptr);
2288 [ # # ]: 0 : if(!facet_d_ptr){
2289 [ # # ][ # # ]: 0 : PRINT_ERROR("Can't work with Facet pointer that isn't a facet data object.\n");
[ # # ][ # # ]
2290 : 0 : return;
2291 : : }
2292 : :
2293 [ # # ]: 0 : DLIList<CubitPoint *>point_list;
2294 [ # # ][ # # ]: 0 : DLIList<CubitFacetEdge *>edge_list;
2295 [ # # ]: 0 : facet_ptr->points(point_list);
2296 [ # # ]: 0 : facet_ptr->edges(edge_list);
2297 : :
2298 [ # # ]: 0 : facet_d_ptr->destruct_facet_internals();
2299 : :
2300 : : CubitFacetEdge *edge_ptr;
2301 : : CubitPoint *point_ptr;
2302 : : int ii;
2303 : :
2304 [ # # ][ # # ]: 0 : for (ii=0; ii<edge_list.size(); ii++)
2305 : : {
2306 [ # # ]: 0 : edge_ptr = edge_list.get_and_step();
2307 [ # # ][ # # ]: 0 : if (edge_ptr->num_adj_facets() == 0)
2308 [ # # ][ # # ]: 0 : delete edge_ptr;
2309 : : }
2310 : :
2311 [ # # ]: 0 : for (ii=0; ii<3; ii++)
2312 : : {
2313 [ # # ]: 0 : point_ptr = point_list.get_and_step();
2314 [ # # ][ # # ]: 0 : if (point_ptr->num_adj_facets() == 0)
2315 [ # # ][ # # ]: 0 : delete point_ptr;
2316 [ # # ]: 0 : }
2317 : :
2318 : : }
2319 : :
2320 : : //=============================================================================
2321 : : //Function: intersect_facet (PUBLIC)
2322 : : //Description: determine intersection of a segment with a facet
2323 : : // returns CUBIT_PNT_UNKNOWN: if segment is in plane of facet
2324 : : // CUBIT_PNT_OUTSIDE: if segment does not intersect
2325 : : // CUBIT_PNT_INSIDE: if segment intersects inside facet
2326 : : // CUBIT_PNT_BOUNDARY: if segment intersects a vertex or edge
2327 : : //Author: sjowen
2328 : : //Date: 1/30/2004
2329 : : //=============================================================================
2330 : 0 : CubitPointContainment FacetDataUtil::intersect_facet(
2331 : : CubitVector &start, CubitVector &end, // start and end points of vector
2332 : : CubitFacet *facet_ptr, // the facet to intersect
2333 : : CubitVector &qq, // return the intersection point
2334 : : CubitVector &ac, // area coordinates of qq if is in or on facet
2335 : : CubitBoolean bound) // if true, only check for intersections between the end points.
2336 : : {
2337 : :
2338 [ # # ][ # # ]: 0 : CubitPlane fplane = facet_ptr->plane();
2339 [ # # ]: 0 : double dstart = fplane.distance(start);
2340 [ # # ]: 0 : double dend = fplane.distance(end);
2341 : :
2342 : : // points are both in the plane of the facet - can't handle this case
2343 : :
2344 [ # # ][ # # ]: 0 : if (fabs(dstart) < GEOMETRY_RESABS &&
2345 : 0 : fabs(dend) < GEOMETRY_RESABS)
2346 : : {
2347 : 0 : return CUBIT_PNT_UNKNOWN;
2348 : : }
2349 : :
2350 : : // one point is on the plane
2351 : :
2352 [ # # ]: 0 : if (fabs(dstart) < GEOMETRY_RESABS)
2353 : : {
2354 [ # # ]: 0 : qq = start;
2355 : : }
2356 [ # # ]: 0 : else if (fabs(dend) < GEOMETRY_RESABS)
2357 : : {
2358 [ # # ]: 0 : qq = end;
2359 : : }
2360 : :
2361 : : // points are both on the same side of the plane
2362 [ # # ][ # # ]: 0 : else if(dstart*dend > 0.0 &&
2363 [ # # ]: 0 : (bound || fabs(dstart-dend) < CUBIT_RESABS) )
2364 : : {
2365 : 0 : return CUBIT_PNT_OUTSIDE;
2366 : : }
2367 : : // points are on opposite sides of plane: if bound == false then compute intersection with plane
2368 : :
2369 : : else
2370 : : {
2371 [ # # ]: 0 : CubitVector dir = end-start;
2372 [ # # ]: 0 : dir.normalize();
2373 [ # # ][ # # ]: 0 : qq = fplane.intersect(start, dir);
2374 : : }
2375 : :
2376 [ # # ]: 0 : FacetEvalTool::facet_area_coordinate( facet_ptr, qq, ac );
2377 : :
2378 : : //mod mbrewer ... the original code would call a point
2379 : : // on the boundary if any area coordinate was near
2380 : : // zero, regardless of whether another area coordinate
2381 : : // was negative... making it outside.
2382 : : // if (fabs(ac.x()) < GEOMETRY_RESABS ||
2383 : : // fabs(ac.y()) < GEOMETRY_RESABS ||
2384 : : // fabs(ac.z()) < GEOMETRY_RESABS)
2385 : : // {
2386 : : // return CUBIT_PNT_BOUNDARY;
2387 : : // }
2388 [ # # ][ # # ]: 0 : if ( (fabs(ac.x()) < GEOMETRY_RESABS && (ac.y() > -GEOMETRY_RESABS &&
[ # # ][ # # ]
[ # # ]
2389 [ # # ][ # # ]: 0 : ac.z() > -GEOMETRY_RESABS) )||
2390 [ # # ][ # # ]: 0 : (fabs(ac.y()) < GEOMETRY_RESABS && (ac.x() > -GEOMETRY_RESABS &&
[ # # ][ # # ]
2391 [ # # ][ # # ]: 0 : ac.z() > -GEOMETRY_RESABS) )||
[ # # ]
2392 [ # # ][ # # ]: 0 : (fabs(ac.z()) < GEOMETRY_RESABS && (ac.x() > -GEOMETRY_RESABS &&
[ # # ][ # # ]
2393 [ # # ]: 0 : ac.y() > -GEOMETRY_RESABS) ) ){
2394 : 0 : return CUBIT_PNT_BOUNDARY;
2395 : : }
2396 [ # # ][ # # ]: 0 : else if (ac.x() < 0.0 || ac.y() < 0.0 || ac.z() < 0.0)
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2397 : : {
2398 : 0 : return CUBIT_PNT_OUTSIDE;
2399 : : }
2400 : :
2401 : 0 : return CUBIT_PNT_INSIDE;
2402 : : }
2403 : :
2404 : :
2405 : : //=============================================================================
2406 : : //Function: get_bbox_of_points (PUBLIC)
2407 : : //Description: Find the bounding box of a list of CubitPoints
2408 : : //Author: jdfowle
2409 : : //Date: 12/15/03
2410 : : //=============================================================================
2411 : 0 : CubitStatus FacetDataUtil::get_bbox_of_points(DLIList<CubitPoint*>& point_list, CubitBox& bbox)
2412 : : {
2413 : : double x, y, z, min[3], max[3];
2414 : : int i;
2415 : : CubitPoint *point;
2416 : 0 : min[0] = min[1] = min[2] = CUBIT_DBL_MAX;
2417 : 0 : max[0] = max[1] = max[2] = -CUBIT_DBL_MAX + 1.;
2418 : :
2419 [ # # ][ # # ]: 0 : for ( i = 0; i < point_list.size(); i++ ) {
2420 [ # # ]: 0 : point = point_list.get_and_step();
2421 [ # # ]: 0 : x = point->x();
2422 [ # # ]: 0 : if ( min[0] > x ) min[0] = x;
2423 [ # # ]: 0 : if ( max[0] < x ) max[0] = x;
2424 [ # # ]: 0 : y = point->y();
2425 [ # # ]: 0 : if ( min[1] > y ) min[1] = y;
2426 [ # # ]: 0 : if ( max[1] < y ) max[1] = y;
2427 [ # # ]: 0 : z = point->z();
2428 [ # # ]: 0 : if ( min[2] > z ) min[2] = z;
2429 [ # # ]: 0 : if ( max[2] < z ) max[2] = z;
2430 : : }
2431 [ # # ]: 0 : bbox.reset(min,max);
2432 : :
2433 : 0 : return CUBIT_SUCCESS;
2434 : : }
2435 : :
2436 : : //=============================================================================
2437 : : //Function: squared_distance_to_segment (PUBLIC)
2438 : : //Description: get square of distance from point to closest point on a line segment;
2439 : : // returns closest point. Taken from "Geometric Tools for Computer Graphics",
2440 : : // by Schneider & Eberly, sec. 6.1.
2441 : : //Author: jdfowle
2442 : : //Date: 03/08/03
2443 : : //=============================================================================
2444 : 3740 : CubitVector FacetDataUtil::squared_distance_to_segment(CubitVector &p, CubitVector &p0,
2445 : : CubitVector &p1, double &distance2)
2446 : : {
2447 [ + - ][ + - ]: 3740 : CubitVector YmPO, D;
2448 : : double t;
2449 : :
2450 [ + - ][ + - ]: 3740 : D = p1 - p0;
2451 [ + - ][ + - ]: 3740 : YmPO = p - p0;
2452 [ + - ][ + - ]: 3740 : t = D.x()*YmPO.x() + D.y()*YmPO.y() + D.z()*YmPO.z();
[ + - ][ + - ]
[ + - ][ + - ]
2453 : :
2454 [ + + ]: 3740 : if ( t < 0.0 ) {
2455 [ + - ][ + - ]: 187 : distance2 = YmPO.x()*YmPO.x() + YmPO.y()*YmPO.y() + YmPO.z()*YmPO.z();
[ + - ][ + - ]
[ + - ][ + - ]
2456 [ + - ]: 187 : return p0;
2457 : : }
2458 : :
2459 : : double DdD;
2460 [ + - ][ + - ]: 3553 : DdD = D.x()*D.x() + D.y()*D.y() + D.z()*D.z();
[ + - ][ + - ]
[ + - ][ + - ]
2461 [ + + ]: 3553 : if ( t >= DdD ) {
2462 [ + - ]: 1551 : CubitVector YmP1;
2463 [ + - ][ + - ]: 1551 : YmP1 = p - p1;
2464 [ + - ][ + - ]: 1551 : distance2 = YmP1.x()*YmP1.x() + YmP1.y()*YmP1.y() + YmP1.z()*YmP1.z();
[ + - ][ + - ]
[ + - ][ + - ]
2465 [ + - ]: 1551 : return p1;
2466 : : }
2467 : :
2468 : : // closest point is interior to segment
2469 [ + - ][ + - ]: 2002 : distance2 = YmPO.x()*YmPO.x() + YmPO.y()*YmPO.y() + YmPO.z()*YmPO.z() - t*t/DdD;
[ + - ][ + - ]
[ + - ][ + - ]
2470 [ + - ][ + - ]: 3740 : return p0 + (t/DdD)*(p1 - p0);
[ + - ]
2471 : : }
2472 : :
2473 : : //=============================================================================
2474 : : //Function: get_bbox_intersections (PUBLIC)
2475 : : //Description: Get the intersection of the line defined by point1 and point2 with
2476 : : //bbox. Returns 0,1 or 2 for the number of intersections. A line
2477 : : //in one of the planes of the box will return 0. Returns -1 for failure.
2478 : : //Author mborden
2479 : : //Date: 04/05/07
2480 : : //=============================================================================
2481 : 0 : int FacetDataUtil::get_bbox_intersections(CubitVector& point1,
2482 : : CubitVector& point2,
2483 : : const CubitBox& bbox,
2484 : : CubitVector& intersection_1,
2485 : : CubitVector& intersection_2)
2486 : : {
2487 : 0 : int debug = 0;
2488 [ # # ]: 0 : if( debug )
2489 : : {
2490 [ # # ]: 0 : GfxDebug::draw_point( point1, CUBIT_RED_INDEX );
2491 [ # # ]: 0 : GfxDebug::draw_point( point2, CUBIT_BLUE_INDEX );
2492 [ # # ]: 0 : GfxDebug::flush();
2493 : : }
2494 : :
2495 : : double coords[6];
2496 [ # # ]: 0 : coords[0] = bbox.min_x();
2497 [ # # ]: 0 : coords[1] = bbox.max_x();
2498 [ # # ]: 0 : coords[2] = bbox.min_y();
2499 [ # # ]: 0 : coords[3] = bbox.max_y();
2500 [ # # ]: 0 : coords[4] = bbox.min_z();
2501 [ # # ]: 0 : coords[5] = bbox.max_z();
2502 : :
2503 [ # # ]: 0 : DLIList<CubitVector*> intersections;
2504 : :
2505 : : int ii;
2506 [ # # ]: 0 : for( ii = 0; ii < 3; ii++ )
2507 : : {
2508 : : //Define four points for each plane.
2509 : : double box_points[4][3];
2510 : :
2511 : : //ii = 0 -> x-planes
2512 : : //ii = 1 -> y_planes
2513 : : //ii = 2 -> z_planes
2514 : :
2515 : : //Only the coordinates for the plane we are in
2516 : : //change. The other two are constant for the
2517 : : //jj loops below.
2518 : 0 : box_points[0][(ii + 1) % 3] = coords[((ii*2)+2) % 6];
2519 : 0 : box_points[1][(ii + 1) % 3] = coords[((ii*2)+3) % 6];
2520 : 0 : box_points[2][(ii + 1) % 3] = coords[((ii*2)+3) % 6];
2521 : 0 : box_points[3][(ii + 1) % 3] = coords[((ii*2)+2) % 6];
2522 : :
2523 : 0 : box_points[0][(ii + 2) % 3] = coords[((ii*2)+4) % 6];
2524 : 0 : box_points[1][(ii + 2) % 3] = coords[((ii*2)+4) % 6];
2525 : 0 : box_points[2][(ii + 2) % 3] = coords[((ii*2)+5) % 6];
2526 : 0 : box_points[3][(ii + 2) % 3] = coords[((ii*2)+5) % 6];
2527 : :
2528 : : int jj;
2529 [ # # ]: 0 : for( jj = 0; jj < 2; jj++ )
2530 : : {
2531 : : CubitPoint* points[4];
2532 : : int kk;
2533 [ # # ]: 0 : for( kk = 0; kk < 4; kk++ )
2534 : : {
2535 : 0 : box_points[kk][ii] = coords[(ii*2)+jj];
2536 [ # # ][ # # ]: 0 : points[kk] = new CubitPointData( box_points[kk][0], box_points[kk][1], box_points[kk][2] );
2537 : : }
2538 : :
2539 : : //Create two facets for this plane to check for intersections.
2540 : : CubitFacet* facets[2];
2541 [ # # ][ # # ]: 0 : facets[0] = new CubitFacetData( points[0], points[1], points[3] );
2542 [ # # ][ # # ]: 0 : facets[1] = new CubitFacetData( points[1], points[2], points[3] );
2543 : :
2544 [ # # ]: 0 : for( kk = 0; kk < 2; kk++ )
2545 : : {
2546 [ # # ]: 0 : CubitVector intersection;
2547 [ # # ]: 0 : CubitVector area_coord;
2548 : :
2549 : : //Make sure the points are not parrellel with the facet.
2550 [ # # ]: 0 : CubitVector dir = point2 - point1;
2551 [ # # ]: 0 : CubitVector normal = facets[kk]->normal();
2552 [ # # ][ # # ]: 0 : if( fabs(dir % normal) < CUBIT_RESABS )
2553 : 0 : continue;
2554 : :
2555 : : CubitPointContainment contain = intersect_facet( point1, point2, facets[kk],
2556 [ # # ]: 0 : intersection, area_coord, CUBIT_FALSE );
2557 [ # # ]: 0 : if( CUBIT_PNT_UNKNOWN == contain )
2558 : : {
2559 : : //The points are in a plane. Return 0.
2560 [ # # ][ # # ]: 0 : delete facets[0];
2561 [ # # ][ # # ]: 0 : delete facets[1];
2562 : : int ll;
2563 [ # # ]: 0 : for( ll = 0; ll < 4; ll++ )
2564 [ # # ][ # # ]: 0 : delete points[ll];
2565 [ # # ][ # # ]: 0 : for( ll = intersections.size(); ll > 0; ll-- )
2566 [ # # ]: 0 : delete intersections.get_and_step();
2567 : :
2568 : 0 : return 0;
2569 : : }
2570 [ # # ][ # # ]: 0 : if( CUBIT_PNT_BOUNDARY == contain ||
2571 : : CUBIT_PNT_INSIDE == contain )
2572 : : {
2573 : : //The point intersects the facet so it's inside the box's surface.
2574 [ # # ][ # # ]: 0 : CubitVector* new_intersection = new CubitVector;
2575 [ # # ]: 0 : *new_intersection = intersection;
2576 [ # # ]: 0 : intersections.append( new_intersection );
2577 : :
2578 [ # # ]: 0 : if( debug )
2579 : : {
2580 [ # # ]: 0 : GfxDebug::draw_point( *new_intersection, CUBIT_CYAN_INDEX );
2581 [ # # ]: 0 : GfxDebug::flush();
2582 : : }
2583 : :
2584 : 0 : break;
2585 : : }
2586 : : }
2587 : :
2588 [ # # ][ # # ]: 0 : delete facets[0];
2589 [ # # ][ # # ]: 0 : delete facets[1];
2590 [ # # ]: 0 : for( kk = 0; kk < 4; kk++ )
2591 [ # # ][ # # ]: 0 : delete points[kk];
2592 : : }
2593 : : }
2594 : :
2595 : : //Check for duplicate intersections.
2596 [ # # ]: 0 : intersections.reset();
2597 [ # # ][ # # ]: 0 : for( ii = 0; ii < intersections.size(); ii++ )
2598 : : {
2599 [ # # ]: 0 : CubitVector* base_vec = intersections.next(ii);
2600 [ # # ]: 0 : if( NULL == base_vec )
2601 : 0 : continue;
2602 : :
2603 : : int jj;
2604 [ # # ][ # # ]: 0 : for( jj = ii+1; jj < intersections.size(); jj++ )
2605 : : {
2606 [ # # ]: 0 : CubitVector* compare_vec = intersections.next(jj);
2607 [ # # ]: 0 : if( NULL != compare_vec )
2608 : : {
2609 [ # # ][ # # ]: 0 : if( base_vec->distance_between_squared( *compare_vec ) < GEOMETRY_RESABS * GEOMETRY_RESABS )
2610 : : {
2611 [ # # ]: 0 : intersections.step(jj);
2612 [ # # ]: 0 : delete intersections.get();
2613 [ # # ]: 0 : intersections.change_to( NULL );
2614 [ # # ]: 0 : intersections.reset();
2615 : : }
2616 : : }
2617 : : }
2618 : : }
2619 [ # # ]: 0 : intersections.remove_all_with_value( NULL );
2620 : :
2621 : :
2622 [ # # ][ # # ]: 0 : if( intersections.size() > 2 )
2623 : : {
2624 [ # # ][ # # ]: 0 : assert( intersections.size() <= 2 );
2625 : 0 : return -1;
2626 : : }
2627 [ # # ][ # # ]: 0 : else if( intersections.size() > 0 )
2628 : : {
2629 [ # # ][ # # ]: 0 : intersection_1 = *intersections.get();
2630 [ # # ][ # # ]: 0 : if( intersections.size() > 1 )
2631 [ # # ][ # # ]: 0 : intersection_2 = *intersections.next();
2632 : : }
2633 : :
2634 : : //Delete memory.
2635 [ # # ][ # # ]: 0 : for( ii = intersections.size(); ii > 0; ii-- )
2636 [ # # ]: 0 : delete intersections.get_and_step();
2637 : :
2638 [ # # ][ # # ]: 0 : return intersections.size();
2639 : : }
2640 : :
2641 : :
2642 : : //=============================================================================
2643 : : //Function: mark_facets (PUBLIC)
2644 : : //Description: mark facets and their children. assumes facets have points and edges
2645 : : //Author sjowen
2646 : : //Date: 09/18/09
2647 : : //=============================================================================
2648 : 0 : void FacetDataUtil::mark_facets( DLIList<FacetEntity *> &facet_list, int mark_value )
2649 : : {
2650 : : int ifacet;
2651 : : FacetEntity *facet_ptr;
2652 [ # # ]: 0 : for (ifacet = 0; ifacet<facet_list.size(); ifacet++ )
2653 : : {
2654 : 0 : facet_ptr = facet_list.get_and_step();
2655 [ # # ]: 0 : CubitFacet *cfacet_ptr = dynamic_cast<CubitFacet *> (facet_ptr);
2656 [ # # ]: 0 : if( cfacet_ptr )
2657 : : {
2658 : 0 : cfacet_ptr->marked(mark_value);
2659 [ # # ]: 0 : for (int ii=0; ii<3; ii++)
2660 : : {
2661 : 0 : cfacet_ptr->point(ii)->marked(mark_value);
2662 : 0 : cfacet_ptr->edge(ii)->marked(mark_value);
2663 : : }
2664 : : }
2665 : : else
2666 : : {
2667 [ # # ]: 0 : CubitFacetEdge *edge_ptr = dynamic_cast<CubitFacetEdge*>(facet_ptr);
2668 [ # # ]: 0 : if( edge_ptr )
2669 : : {
2670 : 0 : edge_ptr->marked(mark_value);
2671 [ # # ]: 0 : for (int ii=0; ii<2; ii++)
2672 : 0 : edge_ptr->point(ii)->marked(mark_value);
2673 : : }
2674 : : }
2675 : : }
2676 : 0 : }
2677 : :
2678 : : //==================================================================================
2679 : : // Description: identifies all the facets that contain given two cubit points
2680 : : //
2681 : : //
2682 : : // Notes:
2683 : : // Author: william roshan quadros
2684 : : // Date: 3/30/2011
2685 : : //===================================================================================
2686 : 0 : CubitStatus FacetDataUtil::find_facet( DLIList<CubitFacet *> temp_split_facets, CubitPoint *pnt0, CubitPoint *pnt1, DLIList<CubitFacet *> &select_facets )
2687 : : {
2688 : : int i;
2689 : : CubitFacet *ptr_facet;
2690 [ # # ][ # # ]: 0 : for( i = 0; i < temp_split_facets.size(); i++ )
2691 : : {
2692 [ # # ]: 0 : ptr_facet = temp_split_facets.get_and_step();
2693 : :
2694 [ # # ][ # # ]: 0 : if( ptr_facet->contains( pnt0 ) && ptr_facet->contains( pnt1 ) )
[ # # ][ # # ]
[ # # ]
2695 : : {
2696 [ # # ]: 0 : select_facets.append( ptr_facet);
2697 : : }
2698 : : }
2699 : :
2700 [ # # ][ # # ]: 0 : if( select_facets.size() )
2701 : 0 : return CUBIT_SUCCESS;
2702 : : else
2703 : 0 : return CUBIT_FAILURE;
2704 [ + - ][ + - ]: 6540 : }
2705 : :
2706 : :
2707 : :
|