Branch data Line data Source code
1 : : #include "FacetProjectTool.hpp"
2 : : #include "PST_Data.hpp"
3 : : #include "GeometryDefines.h"
4 : : #include "CubitMessage.hpp"
5 : : #include "CubitPlane.hpp"
6 : :
7 : : #include "GfxDebug.hpp" /* for debugging output */
8 : :
9 : : const int VG_FACET_DEBUG = 145;
10 : : const int VG_FACET_BOUNDARY_COLOR = CUBIT_RED_INDEX;
11 : : const int VG_FACET_FACET_COLOR = CUBIT_GREEN_INDEX;
12 : : const int VG_FACET_IMPRINT_COLOR = CUBIT_WHITE_INDEX;
13 : : const int VG_FACET_SEGMENT_COLOR = CUBIT_CYAN_INDEX;
14 : : #define VG_FACET_PRINT PRINT_DEBUG(VG_FACET_DEBUG)
15 : :
16 : :
17 : : //-------------------------------------------------------------------------
18 : : // Purpose : Constructor
19 : : //
20 : : // Special Notes :
21 : : //
22 : : // Creator : Jason Kraftcheck
23 : : //
24 : : // Creation Date : 05/11/02
25 : : //-------------------------------------------------------------------------
26 [ # # ][ # # ]: 0 : FacetProjectTool::FacetProjectTool( )
[ # # ][ # # ]
[ # # ]
27 : 0 : { }
28 : :
29 : :
30 : 0 : static int parent_compare_facets( PST_Face*& f1, PST_Face*& f2 )
31 : : {
32 : 0 : return (f1->parent < f2->parent) ? -1 :
33 [ # # ][ # # ]: 0 : (f1->parent > f2->parent) ? 1 : 0;
34 : : }
35 : 0 : static int sequence_compare_pts( PST_Point*& p1, PST_Point*& p2 )
36 : : {
37 : 0 : return (p1->sequence < p2->sequence) ? -1 :
38 [ # # ][ # # ]: 0 : (p1->sequence > p2->sequence) ? 1 : 0;
39 : : }
40 : :
41 : : //-------------------------------------------------------------------------
42 : : // Purpose : takes a list of edge segments and a surface and returns
43 : : // the new facets, dudded facets, new points, and new edges
44 : : // Special Notes :
45 : : //
46 : : //
47 : : // Creator : John Fowler
48 : : //
49 : : // Creation Date : 12/03/02
50 : : //-------------------------------------------------------------------------
51 : 0 : CubitStatus FacetProjectTool::project(
52 : : DLIList<CubitVector*>& segments, // in
53 : : const std::vector<double>& coordinates, // in
54 : : const std::vector<int>& connections, // in
55 : : std::vector<int>& duddedFacets, // out
56 : : std::vector<int>& newFacets, // out
57 : : std::vector<int>& newFacetsIndex, // out
58 : : std::vector<double>& newPoints, // out
59 : : std::vector<int>& edges, // out
60 : : std::vector<int>& segmentPoints,
61 : : const double *tolerance_length
62 : : )
63 : : {
64 : : int i;
65 : : // const double TOL_SQR = GEOMETRY_RESABS*GEOMETRY_RESABS;
66 : :
67 [ # # ][ # # ]: 0 : assert(connections.size()%3 == 0); // For triangles these must be triples
68 [ # # ][ # # ]: 0 : assert(coordinates.size()%3 == 0); // Coordinates must come in triples
69 [ # # ]: 0 : DLIList<PST_Edge*> facet_edges;
70 : :
71 : : // make the PST edges and faces from the coordinates and connections.
72 [ # # ]: 0 : PST_Edge::make_facets( coordinates, connections, GEOMETRY_RESABS, facet_edges );
73 [ # # ][ # # ]: 0 : DLIList<PST_Face*> faces;
74 : :
75 : 0 : CubitStatus success = CUBIT_SUCCESS;
76 [ # # ][ # # ]: 0 : if(facet_edges.size() > 0)
77 : : {
78 : :
79 [ # # ]: 0 : PST_Edge::faces( facet_edges, faces );
80 [ # # ]: 0 : populate_data(faces);
81 : :
82 : : // Order the orignal points by sequence number. New points
83 : : // will be appended in order.
84 [ # # ]: 0 : pointList.sort(&sequence_compare_pts);
85 : :
86 : : // Do the work
87 : : CubitBoolean point_changed;
88 [ # # ]: 0 : success = do_projection(segments, point_changed, tolerance_length);
89 : :
90 : 0 : bool debug = false;
91 [ # # ]: 0 : if( debug )
92 : : {
93 [ # # ]: 0 : GfxDebug::clear();
94 [ # # ][ # # ]: 0 : for( int j=0; j<facetList.size(); j++ )
95 [ # # ][ # # ]: 0 : facetList.get_and_step()->debug_draw( CUBIT_CYAN_INDEX );
96 [ # # ]: 0 : GfxDebug::mouse_xforms();
97 : : }
98 : :
99 : : // fill in segmentPoints
100 : : // assert (segPoints.size() == segments.size());
101 [ # # ][ # # ]: 0 : segmentPoints.resize( segPoints.size() );
102 [ # # ]: 0 : segPoints.reset();
103 [ # # ][ # # ]: 0 : for ( i = 0; i < segPoints.size(); i++ )
104 : : {
105 [ # # ]: 0 : PST_Point* pt = segPoints.get_and_step();
106 [ # # ][ # # ]: 0 : segmentPoints[i] = pt ? pt->sequence : -1;
107 [ # # ]: 0 : if (point_changed)
108 : 0 : success = CUBIT_FAILURE;
109 : : }
110 : : }
111 : : else
112 : 0 : success = CUBIT_FAILURE;
113 : :
114 [ # # ]: 0 : if (!success)
115 : : {
116 [ # # ]: 0 : cleanup();
117 : 0 : return success;
118 : : }
119 : :
120 : : // Now put the points with sequence > coordinates.size()/3 in newPoints.
121 [ # # ]: 0 : int orig_num_points = coordinates.size()/3;
122 [ # # ]: 0 : int num_new_points = pointList.size() - orig_num_points;
123 [ # # ]: 0 : pointList.reset();
124 [ # # ]: 0 : pointList.step(orig_num_points);
125 [ # # ]: 0 : newPoints.resize(num_new_points*3);
126 [ # # ]: 0 : std::vector<double>::iterator ditor = newPoints.begin();
127 [ # # ]: 0 : while( num_new_points-- ) {
128 [ # # ]: 0 : PST_Point* pt = pointList.get_and_step();
129 [ # # ][ # # ]: 0 : *ditor++ = pt->x();
[ # # ]
130 [ # # ][ # # ]: 0 : *ditor++ = pt->y();
[ # # ]
131 [ # # ][ # # ]: 0 : *ditor++ = pt->z();
[ # # ]
132 : : }
133 : :
134 [ # # ][ # # ]: 0 : if ( facetList.size() > 1 ) { // If only one facet, skip finding dudded facets
135 : : // Sort (group) facets by parent.
136 [ # # ]: 0 : facetList.sort(&parent_compare_facets);
137 : :
138 : : // Fill in the duddedFacets, newFacets, and newFacetsIndex vectors.
139 : :
140 : : #ifndef NDEBUG
141 [ # # ]: 0 : int orig_num_facets = connections.size()/3;
142 : : #endif
143 : 0 : int new_facet_index = 0;
144 [ # # ]: 0 : DLIList<PST_Point*> facet_pts(3);
145 : :
146 [ # # ]: 0 : facetList.reset();
147 [ # # ]: 0 : duddedFacets.clear();
148 [ # # ]: 0 : newFacetsIndex.clear();
149 [ # # ]: 0 : newFacets.clear();
150 : :
151 [ # # ][ # # ]: 0 : for ( i = facetList.size(); i > 0; ) {
152 : 0 : PST_Face* dudded_facet = 0;
153 [ # # ][ # # ]: 0 : if( facetList.get()->parent != facetList.next()->parent ) {
[ # # ]
154 : :
155 : : // unmodified original facet - skip it
156 : : #ifndef NDEBUG
157 [ # # ]: 0 : PST_Face* facet = facetList.get();
158 [ # # ]: 0 : assert(facet->sequence < orig_num_facets &&
159 [ # # ]: 0 : facet->sequence == facet->parent);
160 : : #endif
161 [ # # ]: 0 : facetList.step();
162 : 0 : i--;
163 : : }
164 : : else {
165 : : // new facets
166 : :
167 : : // put all new facets split from the
168 : : // same original facet (having same parent),
169 : : // including the orignal facet which was
170 : : // recycled, into newFacets
171 : 0 : PST_Face* facet = 0;
172 [ # # ]: 0 : do {
173 [ # # ]: 0 : facet = facetList.get_and_step();
174 : 0 : i--;
175 : :
176 [ # # ]: 0 : if ( facet->parent == facet->sequence ) {
177 [ # # ]: 0 : assert(!dudded_facet);
178 : 0 : dudded_facet = facet;
179 : : }
180 : :
181 [ # # ]: 0 : facet_pts.clean_out();
182 [ # # ]: 0 : facet->append_points(facet_pts);
183 [ # # ]: 0 : facet_pts.reset();
184 [ # # ][ # # ]: 0 : newFacets.push_back(facet_pts.get_and_step()->sequence);
185 [ # # ][ # # ]: 0 : newFacets.push_back(facet_pts.get_and_step()->sequence);
186 [ # # ][ # # ]: 0 : newFacets.push_back(facet_pts.get_and_step()->sequence);
187 : 0 : new_facet_index += 3;
188 [ # # ][ # # ]: 0 : } while ( (facet->parent == facetList.get()->parent) && (i > 0) );
[ # # ]
189 : :
190 : : // add replaced facet to duddedFacets
191 [ # # ][ # # ]: 0 : assert(dudded_facet && dudded_facet->sequence < orig_num_facets);
192 [ # # ]: 0 : duddedFacets.push_back(dudded_facet->sequence);
193 : : // add end position in new_facets for the
194 : : // set of replacement facets to newFacetsIndex
195 [ # # ]: 0 : newFacetsIndex.push_back(new_facet_index);
196 : : }
197 [ # # ]: 0 : }
198 : : }
199 : :
200 [ # # ][ # # ]: 0 : DLIList<PST_CoEdge*> coedge_list;
201 [ # # ]: 0 : edges.clear();
202 [ # # ]: 0 : finalize_results();
203 [ # # ][ # # ]: 0 : while( get_result_set(coedge_list) ) {
204 : :
205 : : // add count and first point
206 [ # # ]: 0 : coedge_list.reset();
207 [ # # ][ # # ]: 0 : edges.push_back(coedge_list.size() + 1);
208 [ # # ][ # # ]: 0 : PST_Point* pt = coedge_list.get()->start_point();
209 [ # # ]: 0 : edges.push_back(pt->sequence);
210 : :
211 : : // add all other points
212 [ # # ][ # # ]: 0 : for( i = coedge_list.size(); i--; ) {
213 [ # # ][ # # ]: 0 : pt = coedge_list.get_and_step()->end_point();
214 [ # # ]: 0 : edges.push_back(pt->sequence);
215 : : }
216 : :
217 : : // clean up for next iteration
218 [ # # ]: 0 : coedge_list.clean_out();
219 : : }
220 [ # # ]: 0 : edges.push_back(0); // terminating zero for next segment length
221 : :
222 [ # # ]: 0 : cleanup();
223 [ # # ]: 0 : return CUBIT_SUCCESS;
224 : : }
225 : :
226 : :
227 : : //-------------------------------------------------------------------------
228 : : // Purpose : fills in the data
229 : : //
230 : : // Special Notes : populate private data lists and set marks on facet
231 : : // entities
232 : : //
233 : : // Creator : Jason Kraftcheck, modified by John Fowler --
234 : : // used to be the class constructor
235 : : //
236 : : // Creation Date : 05/11/02, 12/03/02
237 : : //-------------------------------------------------------------------------
238 : 0 : CubitStatus FacetProjectTool::populate_data( const DLIList<PST_Face*>& facets )
239 : : {
240 : 0 : facetList = facets;
241 : : int i;
242 : :
243 : : // Mark all connected edges with a 3, and initialize
244 : : // parent number to sequence number.
245 : 0 : facetList.last();
246 [ # # ]: 0 : for( i = facetList.size(); i--; )
247 : : {
248 : 0 : PST_Face* face = facetList.step_and_get();
249 : 0 : face->parent = face->sequence;
250 : 0 : PST_CoEdge* coe = face->first_coedge();
251 [ # # ]: 0 : do
252 : : {
253 : 0 : coe->edge()->mark = 3;
254 : 0 : coe = coe->next();
255 : 0 : } while( coe != face->first_coedge() );
256 : : }
257 : :
258 : : // Decrement the edge mark by one for each
259 : : // face that contains the edge.
260 [ # # ]: 0 : for( i = facetList.size(); i--; )
261 : : {
262 : 0 : PST_Face* face = facetList.step_and_get();
263 : 0 : PST_CoEdge* coe = face->first_coedge();
264 [ # # ]: 0 : do
265 : : {
266 : 0 : coe->edge()->mark--;
267 : 0 : coe = coe->next();
268 : 0 : } while( coe != face->first_coedge() );
269 : : }
270 : :
271 : : // Populate edgeList and boundaryList with edges
272 [ # # ]: 0 : for( i = facetList.size(); i--; )
273 : : {
274 : 0 : PST_Face* face = facetList.step_and_get();
275 : 0 : PST_CoEdge* coe = face->first_coedge();
276 [ # # ]: 0 : do
277 : : {
278 [ # # ]: 0 : PST_Edge* edge = coe->edge();
279 : : // If mark is 2, edge was only in one face in the
280 : : // passed list, and is thus on the boundary of the
281 : : // passed patch of faces.
282 [ # # ]: 0 : if( edge->mark == 2 )
283 : : {
284 [ # # ]: 0 : boundaryList.append( edge );
285 [ # # ]: 0 : edgeList.append( edge );
286 : 0 : edge->mark = 0;
287 : : }
288 : : // If mark is 1, the edge is an interior edge in the
289 : : // patch of faces
290 [ # # ]: 0 : else if( edge->mark == 1 )
291 : : {
292 [ # # ]: 0 : edgeList.append( edge );
293 : 0 : edge->mark = 0;
294 : : }
295 : : // If the mark on the edge is zero, we have already
296 : : // added it to the list(s).
297 : : else
298 : : {
299 [ # # ]: 0 : assert( edge->mark == 0 );
300 : : }
301 : :
302 [ # # ]: 0 : coe = coe->next();
303 : 0 : } while( coe != face->first_coedge() );
304 : : }
305 : :
306 : : // Get all the points
307 : 0 : PST_Edge::points( edgeList, pointList );
308 : :
309 : : // Clear marks on all faces connected to our edge
310 : : // list (the passed faces and any faces connected
311 : : // at the boundary edges.)
312 [ # # ]: 0 : for( i = edgeList.size(); i--; )
313 : : {
314 : 0 : PST_Edge* edge = edgeList.step_and_get();
315 : 0 : edge->mark = 0;
316 [ # # ]: 0 : if( edge->forward()->face() )
317 : 0 : edge->forward()->face()->mark = 0;
318 [ # # ]: 0 : if( edge->reverse()->face() )
319 : 0 : edge->reverse()->face()->mark = 0;
320 : : }
321 : :
322 : : // clear marks on faces
323 [ # # ]: 0 : for( i = facetList.size(); i--; )
324 : 0 : facetList.step_and_get()->mark = 0;
325 : : // Set mark to 1 on boundary edges
326 [ # # ]: 0 : for( i = boundaryList.size(); i--; )
327 : 0 : boundaryList.step_and_get()->mark = 1;
328 : :
329 [ # # ]: 0 : if( DEBUG_FLAG( VG_FACET_DEBUG ) )
330 : : {
331 : : // PST_Face::draw_faces( facetList, VG_FACET_FACET_COLOR, false );
332 : 0 : PST_Edge::debug_draw_edges( boundaryList, VG_FACET_BOUNDARY_COLOR );
333 : : }
334 : :
335 : 0 : return CUBIT_SUCCESS;
336 : : }
337 : :
338 : : //-------------------------------------------------------------------------
339 : : // Purpose : Find the face for which the projection of the passed
340 : : // position onto the face is closest to the passed
341 : : // position.
342 : : //
343 : : // Special Notes :
344 : : //
345 : : // Creator : Jason Kraftcheck
346 : : //
347 : : // Creation Date : 05/11/02
348 : : //-------------------------------------------------------------------------
349 : 0 : PST_Face* FacetProjectTool::closest_face( const CubitVector& position )
350 : : {
351 : 0 : PST_Face* result = 0;
352 : 0 : double dist_sqr = 0;
353 [ # # ]: 0 : CubitVector projected;
354 : :
355 [ # # ][ # # ]: 0 : for( int i = facetList.size(); i--; )
356 : : {
357 [ # # ]: 0 : PST_Face* facet = facetList.step_and_get();
358 [ # # ][ # # ]: 0 : if( project_to_face( facet, position, projected ) )
359 : : {
360 [ # # ][ # # ]: 0 : double d = (projected - position).length_squared();
361 [ # # ][ # # ]: 0 : if( !result || d < dist_sqr )
362 : : {
363 : 0 : result = facet;
364 : 0 : dist_sqr = d;
365 : : }
366 : : }
367 : : }
368 : :
369 : 0 : return result;
370 : : }
371 : :
372 : :
373 : : //-------------------------------------------------------------------------
374 : : // Purpose : Find the edge for which the projection of the passed
375 : : // position onto the edge is closest to the passed
376 : : // position.
377 : : //
378 : : // Special Notes :
379 : : //
380 : : // Creator : Jason Kraftcheck
381 : : //
382 : : // Creation Date : 05/11/02
383 : : //-------------------------------------------------------------------------
384 : 0 : PST_Edge* FacetProjectTool::closest_edge( const CubitVector& position )
385 : : {
386 : 0 : PST_Edge* result = 0;
387 : 0 : double dist_sqr = 0;
388 : :
389 [ # # ]: 0 : for( int i = edgeList.size(); i--; )
390 : : {
391 : 0 : PST_Edge* edge = edgeList.step_and_get();
392 : :
393 : 0 : double t = edge->closest_on_line( position );
394 [ # # ][ # # ]: 0 : if( (t > -CUBIT_RESABS) && (t < (1.0 + CUBIT_RESABS)) )
395 : : {
396 [ # # ][ # # ]: 0 : double d = (edge->position(t) - position).length_squared();
397 [ # # ][ # # ]: 0 : if( !result || d < dist_sqr )
398 : : {
399 : 0 : result = edge;
400 : 0 : dist_sqr = d;
401 : : }
402 : : }
403 : : }
404 : :
405 : 0 : return result;
406 : : }
407 : :
408 : : //-------------------------------------------------------------------------
409 : : // Purpose : Find the point closest to the passed position.
410 : : //
411 : : // Special Notes :
412 : : //
413 : : // Creator : Jason Kraftcheck
414 : : //
415 : : // Creation Date : 05/11/02
416 : : //-------------------------------------------------------------------------
417 : 0 : PST_Point* FacetProjectTool::closest_point( const CubitVector& position )
418 : : {
419 : 0 : PST_Point* result = 0;
420 : 0 : double dist_sqr = 0;
421 : :
422 [ # # ]: 0 : for( int i = pointList.size(); i--; )
423 : : {
424 : 0 : PST_Point* pt = pointList.step_and_get();
425 [ # # ]: 0 : double d = (position - *pt).length_squared();
426 [ # # ][ # # ]: 0 : if( !result || d < dist_sqr )
427 : : {
428 : 0 : dist_sqr = d;
429 : 0 : result = pt;
430 : : }
431 : : }
432 : :
433 : 0 : return result;
434 : : }
435 : :
436 : :
437 : : //-------------------------------------------------------------------------
438 : : // Purpose : Project the passed position onto the plane of the
439 : : // passed facet. Returns false if projection is outside
440 : : // the facet.
441 : : //
442 : : // Special Notes : "result" is unchanged if false is returned.
443 : : //
444 : : // Creator : Jason Kraftcheck
445 : : //
446 : : // Creation Date : 05/11/02
447 : : //-------------------------------------------------------------------------
448 : 0 : bool FacetProjectTool::project_to_face( PST_Face* triangle,
449 : : const CubitVector& position,
450 : : CubitVector& result )
451 : : {
452 : : // First check if projection of the point will be within
453 : : // the bounds of the triangle.
454 [ # # ]: 0 : if( ! inside_face( triangle, position ) )
455 : 0 : return false;
456 : :
457 : : // Calculate the actual projection
458 [ # # ]: 0 : result = triangle->plane().project( position );
459 : 0 : return true;
460 : : }
461 : :
462 : : //-------------------------------------------------------------------------
463 : : // Purpose : Destructor. Clear marks on all facet entities.
464 : : //
465 : : // Special Notes :
466 : : //
467 : : // Creator : Jason Kraftcheck
468 : : //
469 : : // Creation Date : 05/11/02
470 : : //-------------------------------------------------------------------------
471 [ # # ][ # # ]: 0 : FacetProjectTool::~FacetProjectTool()
[ # # ][ # # ]
[ # # ]
472 : : {
473 [ # # ]: 0 : cleanup();
474 : 0 : }
475 : :
476 : :
477 : : //-------------------------------------------------------------------------
478 : : // Purpose : clean out internal data
479 : : //
480 : : // Special Notes :
481 : : //
482 : : // Creator : Jason Kraftcheck
483 : : //
484 : : // Creation Date : 02/13/03
485 : : //-------------------------------------------------------------------------
486 : 0 : void FacetProjectTool::cleanup()
487 : : {
488 [ # # ]: 0 : while( pointList.size() )
489 [ # # ]: 0 : delete pointList.pop();
490 : 0 : facetList.clean_out();
491 : 0 : edgeList.clean_out();
492 : 0 : boundaryList.clean_out();
493 : 0 : imprintResult.clean_out();
494 : 0 : segPoints.clean_out();
495 : 0 : }
496 : :
497 : :
498 : : //-------------------------------------------------------------------------
499 : : // Purpose : Inset a point in the interior of a facet.
500 : : //
501 : : // Special Notes : Assumes input facet is a triangle, and splits facet
502 : : // as necessary to ensure that resulting facets are tris.
503 : : //
504 : : // Creator : Jason Kraftcheck
505 : : //
506 : : // Creation Date : 05/11/02
507 : : //-------------------------------------------------------------------------
508 : 0 : PST_Point* FacetProjectTool::insert_in_face( PST_Face* face,
509 : : const CubitVector& position )
510 : : {
511 [ # # ][ # # ]: 0 : PST_Point* new_point = new PST_Point( position );
512 [ # # ]: 0 : PST_CoEdge* ce1 = face->first_coedge();
513 [ # # ]: 0 : PST_CoEdge* ce2 = ce1->next();
514 [ # # ]: 0 : PST_CoEdge* ce3 = ce2->next();
515 : :
516 : : // insert non-mainifold edge in face after ce1
517 [ # # ]: 0 : PST_Edge* edge1 = PST_Edge::insert_in_face( new_point, ce1 );
518 [ # # ]: 0 : if( ! edge1 )
519 : : {
520 [ # # ][ # # ]: 0 : delete new_point;
521 : 0 : return 0;
522 : : }
523 [ # # ]: 0 : new_point->sequence = pointList.size();
524 [ # # ]: 0 : pointList.append(new_point);
525 [ # # ]: 0 : edgeList.append( edge1 );
526 [ # # ][ # # ]: 0 : if( DEBUG_FLAG( VG_FACET_DEBUG ) )
[ # # ]
527 [ # # ]: 0 : edge1->debug_draw( VG_FACET_FACET_COLOR );
528 : :
529 : : // connect non-manifold edge to opposite side of the face
530 : : // to make manifold topology.
531 [ # # ]: 0 : PST_Edge* edge2 = PST_Edge::split_face( ce2, edge1->start_point() == new_point ?
532 [ # # ][ # # ]: 0 : edge1->reverse() : edge1->forward() );
[ # # ][ # # ]
533 [ # # ]: 0 : if( ! edge2 ) return new_point;
534 [ # # ]: 0 : edgeList.append( edge2 );
535 [ # # ]: 0 : PST_Face* new_face = edge2->other(face);
536 [ # # ]: 0 : new_face->sequence = facetList.size();
537 : 0 : new_face->parent = face->parent;
538 [ # # ]: 0 : facetList.append( new_face );
539 [ # # ][ # # ]: 0 : if( face->owner() )
540 [ # # ][ # # ]: 0 : face->owner()->notify_split( face, new_face );
541 : :
542 [ # # ][ # # ]: 0 : if( DEBUG_FLAG( VG_FACET_DEBUG ) )
[ # # ]
543 [ # # ]: 0 : edge2->debug_draw( VG_FACET_FACET_COLOR );
544 : :
545 : : // Split face so that all faces are triangles.
546 [ # # ]: 0 : PST_Face* split_face = ce3->face();
547 [ # # ][ # # ]: 0 : PST_Edge* edge3 = PST_Edge::split_face( new_point, ce3->end_point(), split_face );
548 [ # # ]: 0 : if( edge3 )
549 : : {
550 [ # # ]: 0 : edgeList.append( edge3 );
551 [ # # ]: 0 : new_face = edge3->other(split_face);
552 [ # # ]: 0 : new_face->sequence = facetList.size();
553 : 0 : new_face->parent = face->parent;
554 [ # # ]: 0 : facetList.append( new_face );
555 [ # # ][ # # ]: 0 : if( split_face->owner() )
556 [ # # ][ # # ]: 0 : split_face->owner()->notify_split( split_face, new_face );
557 : : }
558 : :
559 : 0 : return new_point;
560 : : }
561 : :
562 : :
563 : : //-------------------------------------------------------------------------
564 : : // Purpose : Add a point where the passed position is projected
565 : : // into the facet patch.
566 : : //
567 : : // Special Notes : May return NULL if projection does not lie within
568 : : // facet patch.
569 : : //
570 : : // Creator : Jason Kraftcheck
571 : : //
572 : : // Creation Date : 05/11/02
573 : : //-------------------------------------------------------------------------
574 : 0 : PST_Point* FacetProjectTool::project( const CubitVector& pos,
575 : : const double* tolerance_length )
576 : : {
577 [ # # ]: 0 : PST_Point* point = closest_point( pos );
578 [ # # ]: 0 : PST_Edge * edge = closest_edge ( pos );
579 [ # # ]: 0 : PST_Face * face = closest_face ( pos );
580 : :
581 : : // find closest facet
582 : 0 : double face_dist = CUBIT_DBL_MAX;
583 [ # # ]: 0 : CubitVector face_pos;
584 [ # # ]: 0 : if( face )
585 : : {
586 [ # # ]: 0 : project_to_face( face, pos, face_pos );
587 [ # # ][ # # ]: 0 : face_dist = (pos - face_pos).length_squared();
588 : : }
589 : :
590 : : // find closest edge
591 : 0 : double edge_dist = CUBIT_DBL_MAX;
592 : 0 : double edge_pos = CUBIT_DBL_MAX;
593 [ # # ]: 0 : if( edge )
594 : : {
595 [ # # ]: 0 : edge_pos = edge->closest_on_edge( pos );
596 [ # # ][ # # ]: 0 : edge_dist = (pos - edge->position(edge_pos)).length_squared();
[ # # ]
597 : : }
598 : :
599 : : // find closest point
600 : 0 : double point_dist = CUBIT_DBL_MAX;
601 [ # # ]: 0 : if( point )
602 : : {
603 [ # # ][ # # ]: 0 : point_dist = (pos - *point).length_squared();
604 : : }
605 : :
606 : : // if the position is closer to a facet than a point or edge...
607 [ # # ][ # # ]: 0 : if( face && (face_dist < point_dist) && (face_dist < edge_dist) )
[ # # ]
608 : : {
609 : : // get a tolerance based on a sample face size. I attempted
610 : : // to do this with a representative facet size but still
611 : : // ended up with problems. While this is slower is more
612 : : // robust. KGM
613 : : double facet_length;
614 : :
615 [ # # ]: 0 : if(tolerance_length)
616 : : {
617 : 0 : facet_length = *tolerance_length;
618 : : }
619 : : else
620 : : {
621 [ # # ]: 0 : facet_length = face->bounding_length();
622 : : }
623 : :
624 : : // use the square of the facet length times an arbitrary factor to
625 : : // determine the tolerance
626 : 0 : double tol_sqr = facet_length*facet_length*.00001;
627 : :
628 : : // check if projected position is within tolerance of
629 : : // any bounding edge of the face.
630 [ # # ]: 0 : PST_CoEdge* coe = face->first_coedge();
631 : 0 : bool insert = true;
632 [ # # ]: 0 : do {
633 [ # # ]: 0 : PST_Edge* e = coe->edge();
634 [ # # ][ # # ]: 0 : CubitVector p = e->position( e->closest_on_line( face_pos ) );
635 [ # # ][ # # ]: 0 : double d = (p - face_pos).length_squared();
636 : :
637 : : // use a relative tolerance here - KGM
638 [ # # ]: 0 : if( d < tol_sqr )
639 : : {
640 : 0 : edge = e;
641 [ # # ]: 0 : edge_pos = edge->closest_on_edge( pos );
642 : 0 : face_dist = d;
643 : 0 : edge_dist = d;
644 : 0 : insert = false;
645 : : }
646 [ # # ]: 0 : coe = coe->next();
647 [ # # ]: 0 : } while( coe != face->first_coedge() );
648 : :
649 : : // If projected position was sufficiently far from the edges
650 : : // of the facet, insert an interior point in the facet. Otherwise
651 : : // fall through and split edge.
652 [ # # ]: 0 : if( insert )
653 : : {
654 [ # # ]: 0 : return insert_in_face( face, face_pos );
655 : : }
656 : : }
657 : :
658 : : // If the point was closer to an edge than a point
659 [ # # ][ # # ]: 0 : if( edge && (edge_dist <= point_dist) )
660 : : {
661 : : // If within tolerance of an end point of the edge, return
662 : : // the end point.
663 [ # # ]: 0 : CubitVector pt = edge->position( edge_pos );
664 [ # # ][ # # ]: 0 : if( (pt - *edge->start_point()).length_squared() < GEOMETRY_RESABS*GEOMETRY_RESABS )
[ # # ][ # # ]
665 [ # # ]: 0 : point = edge->start_point();
666 [ # # ][ # # ]: 0 : else if( (pt - *edge->end_point()).length_squared() < GEOMETRY_RESABS*GEOMETRY_RESABS )
[ # # ][ # # ]
667 [ # # ]: 0 : point = edge->end_point();
668 : : // Otherwise split the edge at the projected position
669 [ # # ]: 0 : else point = split_edge( edge, edge_pos );
670 : : }
671 : :
672 [ # # ][ # # ]: 0 : if( DEBUG_FLAG( VG_FACET_DEBUG ) && point )
[ # # ][ # # ]
[ # # ]
673 [ # # ]: 0 : point->debug_draw( VG_FACET_IMPRINT_COLOR );
674 : :
675 : : // If this was not set in the above if-block, then it is either
676 : : // the closest point in the facet patch or NULL if the position
677 : : // projected outside the facet patch.
678 : 0 : return point;
679 : : }
680 : :
681 : : //-------------------------------------------------------------------------
682 : : // Purpose : Split an edge at the specified parameter value on the
683 : : // edge. Splits connected facets to maintain triangular
684 : : // facets.
685 : : //
686 : : // Special Notes :
687 : : //
688 : : // Creator : Jason Kraftcheck
689 : : //
690 : : // Creation Date : 05/11/02
691 : : //-------------------------------------------------------------------------
692 : 0 : PST_Point* FacetProjectTool::split_edge( PST_Edge* edge, double t )
693 : : {
694 [ # # ][ # # ]: 0 : assert( t > 0.0 && t < 1.0 );
695 : :
696 : : // create point
697 [ # # ][ # # ]: 0 : PST_Point* point = new PST_Point( edge->position(t) );
[ # # ]
698 : :
699 : : // get connected faces
700 [ # # ][ # # ]: 0 : PST_Face* face1 = edge->forward()->face();
701 [ # # ][ # # ]: 0 : PST_Face* face2 = edge->reverse()->face();
702 : :
703 : : // point on each triangle opposite the edge to be split
704 [ # # ][ # # ]: 0 : PST_Point* face1_pt = face1 ? edge->forward()->next()->end_point() : 0;
[ # # ][ # # ]
705 [ # # ][ # # ]: 0 : PST_Point* face2_pt = face2 ? edge->reverse()->next()->end_point() : 0;
[ # # ][ # # ]
706 : :
707 : 0 : PST_Edge* face1_edge = 0, *face2_edge = 0;
708 : :
709 : : // split edge edge
710 [ # # ]: 0 : PST_Edge* split_edge = edge->split( point );
711 [ # # ][ # # ]: 0 : if( edge->owner() )
712 [ # # ][ # # ]: 0 : edge->owner()->notify_split( edge, split_edge );
713 : : // if we split a boundary edge, put the new edge in the
714 : : // list of boundary edges too.
715 [ # # ]: 0 : if( edge->mark )
716 : : {
717 : 0 : split_edge->mark = edge->mark;
718 [ # # ]: 0 : boundaryList.append( split_edge );
719 : : }
720 : : // add edge to our list of edges
721 [ # # ]: 0 : edgeList.append( split_edge );
722 : : // If the first face was not a boundary face (different
723 : : // than the boundary of our patch of facets), then split
724 : : // it so that it remains a triangle.
725 [ # # ]: 0 : if( face1 )
726 : : {
727 [ # # ]: 0 : face1_edge = PST_Edge::split_face( point, face1_pt, face1 );
728 : :
729 [ # # ]: 0 : if( face1_edge )
730 : : {
731 [ # # ][ # # ]: 0 : if( DEBUG_FLAG( VG_FACET_DEBUG ) )
[ # # ]
732 [ # # ]: 0 : face1_edge->debug_draw( VG_FACET_FACET_COLOR );
733 : :
734 [ # # ]: 0 : edgeList.append( face1_edge );
735 [ # # ]: 0 : PST_Face* new_face = face1_edge->other(face1);
736 [ # # ]: 0 : new_face->sequence = facetList.size();
737 : 0 : new_face->parent = face1->parent;
738 [ # # ]: 0 : facetList.append(new_face );
739 : :
740 [ # # ][ # # ]: 0 : if( face1->owner() )
741 [ # # ][ # # ]: 0 : face1->owner()->notify_split( face1, face1_edge->other(face1) );
[ # # ]
742 : : }
743 : : }
744 : : // If the second face is not a boundary face, split it
745 : : // so that we still have triangles.
746 [ # # ]: 0 : if( face2 )
747 : : {
748 [ # # ]: 0 : face2_edge = PST_Edge::split_face( point, face2_pt, face2 );
749 [ # # ]: 0 : if( face2_edge )
750 : : {
751 [ # # ][ # # ]: 0 : if( DEBUG_FLAG( VG_FACET_DEBUG ) )
[ # # ]
752 [ # # ]: 0 : face2_edge->debug_draw( VG_FACET_FACET_COLOR );
753 : :
754 [ # # ]: 0 : edgeList.append( face2_edge );
755 [ # # ]: 0 : PST_Face* new_face = face2_edge->other(face2);
756 [ # # ]: 0 : new_face->sequence = facetList.size();
757 : 0 : new_face->parent = face2->parent;
758 [ # # ]: 0 : facetList.append( new_face );
759 : :
760 [ # # ][ # # ]: 0 : if( face2->owner() )
761 [ # # ][ # # ]: 0 : face2->owner()->notify_split( face2, face2_edge->other(face2) );
[ # # ]
762 : : }
763 : : }
764 [ # # ]: 0 : point->sequence = pointList.size();
765 [ # # ]: 0 : pointList.append(point);
766 : :
767 : 0 : return point;
768 : : }
769 : :
770 : : //-------------------------------------------------------------------------
771 : : // Purpose : This is the main or outer-loop function for the
772 : : // polyline projection. It is called after the input data
773 : : // is converted to the working representation. The passed
774 : : // list of CubitVectors is the polyline.
775 : : //
776 : : // Special Notes :
777 : : //
778 : : // Creator : Jason Kraftcheck
779 : : //
780 : : // Creation Date : ??
781 : : //-------------------------------------------------------------------------
782 : :
783 : : CubitStatus
784 : 0 : FacetProjectTool::do_projection( const DLIList<CubitVector*>& passed_list,
785 : : CubitBoolean & point_changed,
786 : : const double *tolerance_length)
787 : : {
788 : 0 : const double TOL_SQR = GEOMETRY_RESABS*GEOMETRY_RESABS;
789 : 0 : point_changed = CUBIT_FALSE;
790 [ # # ]: 0 : DLIList<CubitVector*> segments( passed_list );
791 : :
792 : 0 : bool first_and_last_points_coincident = false;
793 [ # # ][ # # ]: 0 : if( segments[0]->distance_between_squared( *(segments[ segments.size()-1]) ) < TOL_SQR )
[ # # ][ # # ]
[ # # ]
794 : 0 : first_and_last_points_coincident = true;
795 : :
796 [ # # ]: 0 : segments.reset();
797 [ # # ][ # # ]: 0 : CubitVector end = *(segments.get_and_step());
798 : 0 : PST_Point* last_point = 0;
799 : :
800 : 0 : bool did_any_projection = false;
801 : :
802 : : int where_is_last_pt;
803 : : int where_is_end_pt;
804 : :
805 : 0 : bool debug = false;
806 : :
807 [ # # ][ # # ]: 0 : for( int i = segments.size(); i > 1; i-- )
808 : : {
809 [ # # ]: 0 : CubitVector start(end);
810 [ # # ][ # # ]: 0 : end = *(segments.get_and_step());
811 : :
812 [ # # ]: 0 : if( debug )
813 : : {
814 [ # # ]: 0 : GfxDebug::clear();
815 [ # # ][ # # ]: 0 : for( int j=facetList.size(); j--; )
816 [ # # ][ # # ]: 0 : facetList.get_and_step()->debug_draw( CUBIT_CYAN_INDEX+j, false );
817 [ # # ]: 0 : GfxDebug::draw_point( start, CUBIT_GREEN_INDEX );
818 [ # # ]: 0 : GfxDebug::draw_point( end, CUBIT_RED_INDEX );
819 [ # # ]: 0 : GfxDebug::flush();
820 [ # # ]: 0 : GfxDebug::mouse_xforms();
821 : : }
822 : :
823 [ # # ][ # # ]: 0 : if( DEBUG_FLAG( VG_FACET_DEBUG ) )
[ # # ]
824 : : {
825 : : GfxDebug::draw_line(
826 [ # # ][ # # ]: 0 : (float)start.x(), (float)start.y(), (float)start.z(),
[ # # ]
827 [ # # ][ # # ]: 0 : (float)end.x() , (float)end.y() , (float)end.z(),
[ # # ]
828 [ # # ]: 0 : VG_FACET_SEGMENT_COLOR );
829 [ # # ]: 0 : GfxDebug::flush();
830 [ # # ]: 0 : GfxDebug::mouse_xforms();
831 : : }
832 : :
833 [ # # ]: 0 : double facet_dist_tol = start.distance_between_squared( end );
834 : 0 : facet_dist_tol *= 0.0001;
835 : :
836 : : //determine if start is on/off/on-boundary of facets
837 [ # # ]: 0 : if( !last_point )
838 : : {
839 [ # # ]: 0 : where_is_last_pt = point_on_facets( &start, facet_dist_tol );
840 : :
841 [ # # ][ # # ]: 0 : if( 1 == where_is_last_pt ||
842 : : 2 == where_is_last_pt )
843 : : {
844 [ # # ]: 0 : last_point = project( start, tolerance_length );
845 : :
846 [ # # ]: 0 : segPoints.append(last_point);
847 [ # # ]: 0 : start = *last_point;
848 : :
849 [ # # ]: 0 : if( first_and_last_points_coincident )
850 [ # # ][ # # ]: 0 : *(segments[segments.size()-1]) = start;
[ # # ]
851 : : }
852 : : else
853 [ # # ]: 0 : segPoints.append(NULL); //it's not on the facets
854 : : }
855 : :
856 [ # # ]: 0 : where_is_end_pt = point_on_facets( &end, facet_dist_tol );
857 : :
858 : : //both points off the facets
859 : : //or one-on, one-off
860 : 0 : PST_Point *end_pt = NULL;
861 : :
862 : : //both points off
863 : : //one-point-on && one-point-off
864 [ # # ][ # # ]: 0 : if( (0 == where_is_last_pt && 0 == where_is_end_pt ) ||
[ # # ]
865 [ # # ][ # # ]: 0 : (0 == where_is_last_pt && 1 == where_is_end_pt ) ||
866 [ # # ]: 0 : (1 == where_is_last_pt && 0 == where_is_end_pt ) )
867 : : {
868 : : //see if segment intersects boundary
869 [ # # ]: 0 : CubitVector int_pt;
870 [ # # ]: 0 : CubitStatus my_status = find_closest_int_point_with_boundary( start, end, int_pt );
871 [ # # ]: 0 : if( CUBIT_FAILURE == my_status )
872 : : {
873 [ # # ]: 0 : segPoints.append( NULL );
874 : 0 : continue;
875 : : }
876 : :
877 [ # # ]: 0 : if( 0 == where_is_last_pt )
878 : : {
879 [ # # ]: 0 : last_point = project( int_pt, tolerance_length );
880 : :
881 [ # # ]: 0 : if( 0 == where_is_end_pt )
882 : : {
883 [ # # ]: 0 : my_status = find_closest_int_point_with_boundary( end, *last_point, int_pt );
884 [ # # ]: 0 : if( CUBIT_SUCCESS == my_status )
885 : : {
886 [ # # ]: 0 : end_pt = project( int_pt, tolerance_length );
887 : 0 : i++;
888 [ # # ]: 0 : segments.back();
889 : : }
890 : : }
891 : : else
892 : : {
893 [ # # ]: 0 : end_pt = project( end, tolerance_length );
894 [ # # ]: 0 : segPoints.append( end_pt );
895 : : }
896 : : }
897 [ # # ]: 0 : else if( 0 == where_is_end_pt )
898 : : {
899 [ # # ]: 0 : end_pt = project( int_pt, tolerance_length );
900 : 0 : i++;
901 [ # # ]: 0 : segments.back();
902 : 0 : }
903 : : }
904 [ # # ][ # # ]: 0 : else if( (1 == where_is_last_pt || 2 == where_is_last_pt) &&
[ # # ]
905 [ # # ]: 0 : (1 == where_is_end_pt || 2 == where_is_end_pt) )
906 : : {
907 [ # # ]: 0 : end_pt = project( end, tolerance_length );
908 [ # # ]: 0 : segPoints.append( end_pt );
909 : : }
910 [ # # ][ # # ]: 0 : else if( (0 == where_is_last_pt && 2 == where_is_end_pt ) ||
[ # # ]
911 [ # # ]: 0 : (2 == where_is_last_pt && 0 == where_is_end_pt ) )
912 : : {
913 [ # # ][ # # ]: 0 : if( 0 == where_is_last_pt && 2 == where_is_end_pt )
914 : : {
915 : : //see if segment intersects boundary
916 [ # # ]: 0 : CubitVector int_pt;
917 [ # # ]: 0 : CubitStatus my_status = find_closest_int_point_with_boundary( start, end, int_pt );
918 [ # # ]: 0 : if( CUBIT_SUCCESS == my_status )
919 : : {
920 [ # # ]: 0 : end_pt = project( end, tolerance_length );
921 [ # # ]: 0 : last_point = project( int_pt, tolerance_length );
922 [ # # ]: 0 : segPoints.append( end_pt );
923 : : }
924 : : else
925 : : {
926 [ # # ]: 0 : segPoints.append(NULL);
927 : 0 : continue;
928 : 0 : }
929 : : }
930 : : else
931 : : {
932 : : //see if segment intersects boundary
933 [ # # ]: 0 : CubitVector int_pt;
934 [ # # ]: 0 : CubitStatus my_status = find_closest_int_point_with_boundary( end, start, int_pt );
935 : :
936 [ # # ]: 0 : if( CUBIT_SUCCESS == my_status )
937 : : {
938 [ # # ]: 0 : end_pt = project( int_pt, tolerance_length );
939 [ # # ]: 0 : segPoints.append( NULL );
940 : : }
941 : : else
942 : : {
943 [ # # ]: 0 : segPoints.append( NULL );
944 : 0 : continue;
945 : : }
946 : : }
947 : : }
948 : :
949 : :
950 : 0 : PST_Point* start_point = last_point;
951 : 0 : PST_Point* end_point = end_pt;
952 : :
953 [ # # ]: 0 : if( debug )
954 : : {
955 [ # # ]: 0 : GfxDebug::draw_line( *last_point, *end_pt, CUBIT_MAGENTA_INDEX );
956 [ # # ]: 0 : GfxDebug::flush();
957 [ # # ]: 0 : GfxDebug::mouse_xforms();
958 : : }
959 : :
960 [ # # ][ # # ]: 0 : if(project( last_point, end_pt ) == CUBIT_SUCCESS)
961 : : {
962 : 0 : did_any_projection = true;
963 [ # # ][ # # ]: 0 : if ((*start_point - *last_point).length_squared() > TOL_SQR)
[ # # ]
964 : : {
965 [ # # ]: 0 : segPoints.move_to(start_point);
966 [ # # ]: 0 : segPoints.change_to(last_point);
967 : 0 : point_changed = CUBIT_TRUE;
968 : : }
969 [ # # ][ # # ]: 0 : if ((*end_pt - *end_point).length_squared() > TOL_SQR)
[ # # ]
970 : : {
971 [ # # ]: 0 : segPoints.move_to(end_point);
972 [ # # ]: 0 : segPoints.change_to(end_pt);
973 : 0 : point_changed = CUBIT_TRUE;
974 : : }
975 : : }
976 : :
977 : 0 : last_point = end_pt;
978 : 0 : where_is_last_pt = where_is_end_pt;
979 : :
980 : : } // end for( i = segments )
981 : :
982 [ # # ]: 0 : if( !did_any_projection )
983 : 0 : return CUBIT_FAILURE;
984 : :
985 [ # # ]: 0 : return CUBIT_SUCCESS;
986 : : }
987 : :
988 : : //-------------------------------------------------------------------------
989 : : // Purpose : Determines if a position is off/on/on-boundary of the
990 : : // facets in this tool. For off/on/on-boundary returns
991 : : // 0, 1, and 2 respectively. The passed in tolerance_sq is
992 : : // used as a coincidence tolerance.
993 : : //
994 : : // Special Notes :
995 : : //
996 : : // Creator : Corey Ernst
997 : : //
998 : : // Creation Date : 24-April-2013
999 : : //-------------------------------------------------------------------------
1000 : :
1001 : 0 : int FacetProjectTool::point_on_facets(
1002 : : CubitVector *pos,
1003 : : double tolerance_sq )
1004 : : {
1005 : : //Return Values:
1006 : : //0 is outside of facets
1007 : : //1 is inside of facets
1008 : : //2 is on boundary of facets
1009 : :
1010 [ # # ]: 0 : PST_Point* point = closest_point( *pos );
1011 [ # # ]: 0 : PST_Edge * edge = closest_edge ( *pos );
1012 [ # # ]: 0 : PST_Face * face = closest_face ( *pos );
1013 : :
1014 : : // find closest facet
1015 : 0 : double face_dist = CUBIT_DBL_MAX;
1016 [ # # ]: 0 : CubitVector face_pos;
1017 [ # # ]: 0 : if( face )
1018 : : {
1019 [ # # ]: 0 : project_to_face( face, *pos, face_pos );
1020 [ # # ][ # # ]: 0 : face_dist = (*pos - face_pos).length_squared();
1021 : : }
1022 : :
1023 : : // find closest edge
1024 : 0 : double edge_dist = CUBIT_DBL_MAX;
1025 : 0 : double edge_pos = CUBIT_DBL_MAX;
1026 [ # # ]: 0 : if( edge )
1027 : : {
1028 [ # # ]: 0 : edge_pos = edge->closest_on_edge( *pos );
1029 [ # # ][ # # ]: 0 : edge_dist = (*pos - edge->position(edge_pos)).length_squared();
[ # # ]
1030 : : }
1031 : :
1032 : : // find closest point
1033 : 0 : double point_dist = CUBIT_DBL_MAX;
1034 [ # # ]: 0 : if( point )
1035 : : {
1036 [ # # ][ # # ]: 0 : point_dist = (*pos - *point).length_squared();
1037 : : }
1038 : :
1039 : : // if the position is closer to a facet than a point or edge...
1040 [ # # ][ # # ]: 0 : if( face && (face_dist < point_dist) && (face_dist < edge_dist) )
[ # # ]
1041 : : {
1042 : : // check if projected position is within tolerance of
1043 : : // any bounding edge of the face.
1044 [ # # ]: 0 : PST_CoEdge* coe = face->first_coedge();
1045 : 0 : bool edge_closer = false;
1046 [ # # ]: 0 : do {
1047 [ # # ]: 0 : PST_Edge* e = coe->edge();
1048 [ # # ][ # # ]: 0 : CubitVector p = e->position( e->closest_on_line( face_pos ) );
1049 [ # # ][ # # ]: 0 : double d = (p - face_pos).length_squared();
1050 : :
1051 [ # # ]: 0 : if( d < tolerance_sq )
1052 : : {
1053 : 0 : edge = e;
1054 [ # # ]: 0 : edge_pos = edge->closest_on_edge( *pos );
1055 : 0 : face_dist = d;
1056 : 0 : edge_dist = d;
1057 : 0 : edge_closer = true;
1058 : : }
1059 [ # # ]: 0 : coe = coe->next();
1060 [ # # ]: 0 : } while( coe != face->first_coedge() );
1061 : :
1062 [ # # ]: 0 : if( edge_closer )
1063 : : {
1064 [ # # ][ # # ]: 0 : if( boundaryList.is_in_list( edge ) )
1065 : 0 : return 2;
1066 : : else
1067 : 0 : return 1;
1068 : : }
1069 : : else
1070 : 0 : return 1;
1071 : :
1072 : : return 0;
1073 : : }
1074 : :
1075 : : // If the point was closer to an edge than a point
1076 [ # # ][ # # ]: 0 : if( edge && (edge_dist < point_dist) )
1077 : : {
1078 [ # # ]: 0 : if( edge_dist < tolerance_sq )
1079 : : {
1080 [ # # ][ # # ]: 0 : if( boundaryList.is_in_list( edge ) )
1081 : 0 : return 2;
1082 : : else
1083 : 0 : return 1;
1084 : : }
1085 : : else
1086 : 0 : return 0;
1087 : : }
1088 : :
1089 [ # # ]: 0 : PST_Edge *first_edge = point->edge();
1090 : 0 : PST_Edge *tmp_edge = first_edge;
1091 [ # # ]: 0 : if( point_dist < tolerance_sq )
1092 : : {
1093 [ # # ]: 0 : do
1094 : : {
1095 [ # # ][ # # ]: 0 : if( boundaryList.is_in_list( tmp_edge ) )
1096 : 0 : return 2;
1097 [ # # ]: 0 : tmp_edge = point->next( tmp_edge );
1098 : : }
1099 : 0 : while( first_edge != tmp_edge );
1100 : :
1101 : 0 : return 1;
1102 : : }
1103 : 0 : return 0;
1104 : : }
1105 : :
1106 : :
1107 : : //-------------------------------------------------------------------------
1108 : : // Purpose : Finds the closest intersection point to 'start_pt'
1109 : : // between the boundary facet edges in this tool and a line
1110 : : // segement defined by 'start_pt' and 'end_pt'. The
1111 : : // intersection must be at or between the two end points
1112 : : // of the segment.
1113 : : //
1114 : : // Special Notes :
1115 : : //
1116 : : // Creator : Corey Ernst
1117 : : //
1118 : : // Creation Date : 24-April-2013
1119 : : //-------------------------------------------------------------------------
1120 : 0 : CubitStatus FacetProjectTool::find_closest_int_point_with_boundary(
1121 : : CubitVector &start_pt, CubitVector &end_pt, CubitVector &closest_pt )
1122 : : {
1123 [ # # ]: 0 : CubitVector seg_direction = end_pt - start_pt;
1124 [ # # ]: 0 : double seg_length_sq = seg_direction.length_squared();
1125 : 0 : double shortest_length = CUBIT_DBL_MAX;
1126 : :
1127 : 0 : const double TOL_SQR = GEOMETRY_RESABS*GEOMETRY_RESABS;
1128 : :
1129 : 0 : bool debug = false;
1130 : :
1131 : : //find the farthest boundary edge that is on the line segment
1132 [ # # ]: 0 : CubitVector split_position;
1133 [ # # ][ # # ]: 0 : for( int k=boundaryList.size(); k--; )
1134 : : {
1135 [ # # ]: 0 : PST_Edge *tmp_edge = boundaryList.get_and_step();
1136 : :
1137 : : //if lines are parallel
1138 [ # # ]: 0 : CubitVector tmp_vec1 = end_pt - start_pt;
1139 [ # # ][ # # ]: 0 : CubitVector tmp_vec2 = tmp_edge->end_coord() - tmp_edge->start_coord();
[ # # ]
1140 [ # # ]: 0 : tmp_vec1 *= tmp_vec2;
1141 [ # # ][ # # ]: 0 : if( tmp_vec1.length_squared() < TOL_SQR )
1142 : 0 : continue;
1143 : :
1144 [ # # ][ # # ]: 0 : double t1 = tmp_edge->closest_on_line( start_pt, end_pt - start_pt );
1145 : :
1146 : : //ignore points that are coincident with start_pt or end_pt
1147 [ # # ]: 0 : CubitVector position_on_edge = tmp_edge->position( t1 );
1148 [ # # ]: 0 : double dist_sq_start = position_on_edge.distance_between_squared( start_pt );
1149 [ # # ]: 0 : double dist_sq_end = position_on_edge.distance_between_squared( end_pt );
1150 [ # # ][ # # ]: 0 : if( dist_sq_start < TOL_SQR || dist_sq_end < TOL_SQR )
1151 : 0 : continue;
1152 : :
1153 [ # # ][ # # ]: 0 : if( t1 >= 0 && t1 <= 1 )
1154 : : {
1155 [ # # ]: 0 : if( debug )
1156 : : {
1157 [ # # ]: 0 : GfxDebug::draw_line( start_pt, end_pt, CUBIT_MAGENTA_INDEX );
1158 [ # # ][ # # ]: 0 : PRINT_INFO("t1 = %f\n", t1 );
[ # # ][ # # ]
1159 [ # # ]: 0 : tmp_edge->debug_draw( CUBIT_YELLOW_INDEX );
1160 : : }
1161 : :
1162 [ # # ]: 0 : CubitVector tmp_pos = tmp_edge->position( t1 );
1163 : :
1164 : : //This checks if the intersection between the edge and segment
1165 : : //is not within the segment.
1166 [ # # ][ # # ]: 0 : if( tmp_pos.distance_between_squared( start_pt ) > seg_length_sq ||
[ # # ][ # # ]
1167 [ # # ]: 0 : tmp_pos.distance_between_squared( end_pt ) > seg_length_sq )
1168 : 0 : continue;
1169 : :
1170 [ # # ]: 0 : if( debug )
1171 : : {
1172 [ # # ]: 0 : GfxDebug::draw_point( tmp_pos, CUBIT_RED_INDEX );
1173 [ # # ]: 0 : GfxDebug::flush();
1174 [ # # ]: 0 : GfxDebug::mouse_xforms();
1175 : : }
1176 : :
1177 [ # # ]: 0 : double tmp_dist = tmp_pos.distance_between( start_pt );
1178 : :
1179 [ # # ]: 0 : if( tmp_dist < shortest_length )
1180 : : {
1181 : 0 : shortest_length = tmp_dist;
1182 [ # # ]: 0 : closest_pt = tmp_pos;
1183 : : }
1184 : : }
1185 : : }
1186 : :
1187 [ # # ]: 0 : if( shortest_length == CUBIT_DBL_MAX )
1188 : 0 : return CUBIT_FAILURE;
1189 : :
1190 : 0 : return CUBIT_SUCCESS;
1191 : : }
1192 : :
1193 : :
1194 : : //-------------------------------------------------------------------------
1195 : : // Purpose : Given two existing points in a triangulation, add edges
1196 : : // to the triangulation to connect those two points by the
1197 : : // most direct path that does not leave the triangulation.
1198 : : //
1199 : : // Special Notes : Thisis the second step of the facet-polyline projection
1200 : : // algorithm. First each point of the polyline is
1201 : : // projected onto the facetting. Second this function is
1202 : : // called to find/create the set of facet edges connecting
1203 : : // those points.
1204 : : //
1205 : : // Creator : Jason Kraftcheck
1206 : : //
1207 : : // Creation Date : ??
1208 : : //-------------------------------------------------------------------------
1209 : 0 : CubitStatus FacetProjectTool::project( PST_Point* &start, PST_Point* &end )
1210 : : {
1211 : 0 : PST_Edge* edge,* closest_edge, *last_closest_edge=NULL;
1212 : : PST_Face* closest_face;
1213 : : PST_Point* point;
1214 : 0 : PST_Point* start_point = start;
1215 : : CubitStatus stat;
1216 : :
1217 : 0 : const double TOL_SQR = GEOMETRY_RESABS*GEOMETRY_RESABS;
1218 : :
1219 [ # # ]: 0 : while( start_point != end )
1220 : : {
1221 : : // If the points share an edge, that edge is the result.
1222 : : // Return it.
1223 : : CubitBoolean is_boundary_edge;
1224 [ # # ][ # # ]: 0 : if( (edge = start_point->common( end )) )
1225 : : {
1226 [ # # ]: 0 : PST_CoEdge* coedge = edge->end_point() == end ?
1227 [ # # ][ # # ]: 0 : edge->forward() : edge->reverse();
[ # # ]
1228 [ # # ]: 0 : imprintResult.append( coedge );
1229 : :
1230 [ # # ][ # # ]: 0 : if( DEBUG_FLAG( VG_FACET_DEBUG ) )
[ # # ]
1231 : : {
1232 [ # # ]: 0 : edge->debug_draw( VG_FACET_IMPRINT_COLOR );
1233 : : }
1234 : :
1235 : 0 : return CUBIT_SUCCESS;
1236 : : }
1237 : :
1238 : : // Draw the current segment
1239 [ # # ][ # # ]: 0 : if( DEBUG_FLAG( VG_FACET_DEBUG ) )
[ # # ]
1240 : : {
1241 : : GfxDebug::draw_line(
1242 [ # # ][ # # ]: 0 : (float)start_point->x(), (float)start_point->y(),
1243 [ # # ]: 0 : (float)start_point->z(),
1244 [ # # ][ # # ]: 0 : (float)end->x() , (float)end->y() , (float)end->z(),
[ # # ]
1245 [ # # ]: 0 : VG_FACET_SEGMENT_COLOR );
1246 [ # # ]: 0 : GfxDebug::flush();
1247 [ # # ]: 0 : GfxDebug::mouse_xforms();
1248 : : }
1249 : :
1250 : : // Get face or edge adjacent to start and closest to the polyline segment
1251 : : stat = next_around_point( start_point, *end, closest_face, closest_edge,
1252 [ # # ]: 0 : is_boundary_edge, last_closest_edge );
1253 : :
1254 [ # # ]: 0 : if(closest_edge)
1255 : 0 : last_closest_edge = closest_edge;
1256 : :
1257 [ # # ][ # # ]: 0 : if (!stat || (closest_face && closest_edge))
[ # # ]
1258 : : {
1259 : : // assert(false);
1260 : 0 : return stat;
1261 : : }
1262 : :
1263 [ # # ]: 0 : const CubitVector seg_tan = *end - *start_point;
1264 : 0 : double t_seg = 0.0;
1265 : 0 : point = 0;
1266 : :
1267 [ # # ]: 0 : if (closest_face)
1268 : : {
1269 : : // calculate intersection with triangle edge opposite
1270 : : // 'start_point'.
1271 : : double t_edge;
1272 [ # # ]: 0 : edge = closest_face->opposite(start_point);
1273 [ # # ]: 0 : PST_Point* edge_start = edge->start_point();
1274 [ # # ]: 0 : PST_Point* edge_end = edge->end_point();
1275 [ # # ]: 0 : closest_on_lines( *edge_start, *edge_end - *edge_start,
1276 [ # # ]: 0 : *start_point, seg_tan, t_edge, t_seg);
1277 : :
1278 [ # # ][ # # ]: 0 : const CubitVector seg_pt = *start_point + t_seg * seg_tan;
1279 [ # # ]: 0 : const CubitVector edge_pt = (1.0 - t_edge) * *edge_start
1280 [ # # ][ # # ]: 0 : + t_edge * *edge_end;
1281 : :
1282 : : // if line segment intersects opposite edge of triangle...
1283 [ # # ][ # # ]: 0 : if ( (t_seg < 1.0) || ((seg_pt - edge_pt).length_squared() < TOL_SQR) )
[ # # ][ # # ]
[ # # ]
[ # # # # ]
1284 : : {
1285 : : // Check if intersection is near start of opposite edge
1286 [ # # ][ # # ]: 0 : if ((t_edge <= 0.0) ||
1287 [ # # ][ # # ]: 0 : ((*edge_start - edge_pt).length_squared() < TOL_SQR) ||
[ # # ][ # # ]
[ # # ][ # # ]
1288 [ # # ][ # # ]: 0 : ((*edge_start - seg_pt ).length_squared() < TOL_SQR) )
[ # # ][ # # ]
1289 : 0 : point = edge_start;
1290 : : // Check if intersection is near end of opposite edge
1291 [ # # ][ # # ]: 0 : else if ((t_edge >= 1.0) ||
1292 [ # # ][ # # ]: 0 : ((*edge_end - edge_pt).length_squared() < TOL_SQR) ||
[ # # ][ # # ]
[ # # ][ # # ]
1293 [ # # ][ # # ]: 0 : ((*edge_end - seg_pt).length_squared() < TOL_SQR))
[ # # ][ # # ]
1294 : 0 : point = edge_end;
1295 : : // Otherwise intersection is in the interior of the edge
1296 : : else
1297 [ # # ]: 0 : point = split_edge(edge, t_edge);
1298 : : }
1299 : : // otherwise segment end is inside triangle
1300 : : else
1301 : : {
1302 : 0 : t_seg = 1.0;
1303 [ # # ][ # # ]: 0 : const CubitVector proj = closest_face->plane().project(*end);
1304 : : PST_Edge *edge1, *edge2;
1305 [ # # ]: 0 : closest_face->two_edges (start_point, edge1, edge2);
1306 : : // Too close to start position - skip segment
1307 [ # # ][ # # ]: 0 : if ( (*start_point - proj).length_squared() < TOL_SQR )
[ # # ]
1308 : 0 : point = start_point;
1309 : : // If close to side of triangle, fall through to edge
1310 : : // handling code
1311 [ # # ][ # # ]: 0 : else if (within_tolerance(edge1, *end, GEOMETRY_RESABS) ||
[ # # ][ # # ]
1312 [ # # ]: 0 : within_tolerance(edge1, proj, GEOMETRY_RESABS))
1313 : 0 : closest_edge = edge1;
1314 : : // If close to side of triangle, fall through to edge
1315 : : // handling code
1316 [ # # ][ # # ]: 0 : else if (within_tolerance(edge2, *end, GEOMETRY_RESABS) ||
[ # # ][ # # ]
1317 [ # # ]: 0 : within_tolerance(edge2, proj, GEOMETRY_RESABS))
1318 : 0 : closest_edge = edge2;
1319 : : // Insert new point in triangle interior...
1320 : : else
1321 [ # # ]: 0 : point = insert_in_face (closest_face, proj);
1322 : : }
1323 : : } // if(closest_face)
1324 : :
1325 [ # # ]: 0 : if (closest_edge)
1326 : : {
1327 [ # # ]: 0 : PST_Point *const edge_end = closest_edge->other(start_point);
1328 : : // If edge and segment ends are equal...
1329 [ # # ][ # # ]: 0 : if ( (*edge_end - *end).length_squared() < TOL_SQR )
[ # # ]
1330 : : {
1331 : 0 : point = edge_end;
1332 : 0 : edge = closest_edge;
1333 [ # # ]: 0 : if (is_boundary_edge)
1334 : 0 : end = edge_end;
1335 : : }
1336 : : // Otherwise calculate closest point
1337 : : else
1338 : : {
1339 : : // edge and segment share a start point so just need
1340 : : // to calculate the projection of each on the other.
1341 [ # # ]: 0 : const CubitVector edge_tan = *edge_end - *start_point;
1342 [ # # ]: 0 : const double dot_prod = seg_tan % edge_tan;
1343 [ # # ]: 0 : const double t_seg = dot_prod / seg_tan.length_squared();
1344 [ # # ]: 0 : const double t_edge = dot_prod / edge_tan.length_squared();
1345 : :
1346 [ # # ][ # # ]: 0 : const CubitVector seg_pt = *start_point + t_seg * seg_tan;
1347 [ # # ][ # # ]: 0 : const CubitVector edge_pt = *start_point + t_edge * edge_tan;
1348 : :
1349 : : // Too close to start point -- skip segment
1350 [ # # ][ # # ]: 0 : if (t_edge <= 0.0 || t_seg <= 0.0 ||
[ # # ]
1351 [ # # ][ # # ]: 0 : (*start_point - edge_pt).length_squared() < TOL_SQR ||
[ # # ][ # # ]
[ # # ][ # # ]
1352 [ # # ][ # # ]: 0 : (*start_point - seg_pt).length_squared() < TOL_SQR )
[ # # ][ # # ]
1353 : 0 : point = start_point;
1354 : : // If segment end is near or passed edge end,
1355 : : // then the edge end is the intersection with this triangle
1356 [ # # ][ # # ]: 0 : else if (t_edge > 1.0 ||
1357 [ # # ][ # # ]: 0 : (*edge_end - edge_pt).length_squared() < TOL_SQR ||
[ # # ][ # # ]
[ # # ][ # # ]
1358 [ # # ][ # # ]: 0 : (*edge_end - seg_pt).length_squared() < TOL_SQR)
[ # # ][ # # ]
1359 : : {
1360 : : //make sure the facet edge is not a boundary edge.
1361 [ # # ][ # # ]: 0 : if (is_boundary_edge && start_point == start)
1362 : 0 : start = edge_end;
1363 : 0 : point = edge_end;
1364 : : }
1365 : : // Otherwise closest point to segment end is in the interior
1366 : : // of the edge -- split the edge.
1367 : : else
1368 : : {
1369 [ # # ][ # # ]: 0 : if(start_point != closest_edge->start_point())
1370 [ # # ]: 0 : point = split_edge( closest_edge, 1.0 - t_edge );
1371 : : else
1372 [ # # ]: 0 : point = split_edge( closest_edge, t_edge );
1373 : : }
1374 : : }
1375 : : } // if(closest_edge)
1376 : :
1377 [ # # ]: 0 : if (point == start_point) // skip perpendicular or very short segment
1378 : 0 : continue;
1379 : :
1380 [ # # ]: 0 : edge = start_point->common( point );
1381 [ # # ]: 0 : if (!edge)
1382 : : {
1383 : 0 : assert(false);
1384 : : continue;
1385 : : }
1386 : :
1387 [ # # ][ # # ]: 0 : if ( !is_boundary_edge || start_point != start )
1388 : : {
1389 [ # # ]: 0 : PST_CoEdge* coedge = edge->end_point() == point ?
1390 [ # # ][ # # ]: 0 : edge->forward() : edge->reverse();
[ # # ]
1391 [ # # ]: 0 : imprintResult.append(coedge);
1392 : : }
1393 : :
1394 [ # # ][ # # ]: 0 : if( DEBUG_FLAG( VG_FACET_DEBUG ) )
[ # # ]
1395 : : {
1396 [ # # ]: 0 : edge->debug_draw( VG_FACET_IMPRINT_COLOR );
1397 [ # # ]: 0 : point->debug_draw( VG_FACET_IMPRINT_COLOR );
1398 : : }
1399 : 0 : start_point = point;
1400 : : }
1401 : :
1402 : 0 : return CUBIT_SUCCESS;
1403 : : }
1404 : :
1405 : : //-------------------------------------------------------------------------
1406 : : // Purpose : Check if a point is within the passed tolerance
1407 : : // of a bounded edge.
1408 : : //
1409 : : // Special Notes :
1410 : : //
1411 : : // Creator : Jason Kraftcheck
1412 : : //
1413 : : // Creation Date : 09/04/03
1414 : : //-------------------------------------------------------------------------
1415 : 0 : bool FacetProjectTool::within_tolerance( PST_Edge* edge,
1416 : : const CubitVector& point,
1417 : : double tolerance )
1418 : : {
1419 [ # # ]: 0 : const double t_edge = edge->closest_on_edge( point );
1420 [ # # ]: 0 : const CubitVector edge_pos = edge->position(t_edge);
1421 [ # # ][ # # ]: 0 : return (edge_pos - point).length_squared() < tolerance*tolerance;
1422 : : }
1423 : :
1424 : : //-------------------------------------------------------------------------
1425 : : // Purpose : Given a line segment beginning at a point in the
1426 : : // triangulation, find the face or edge adjacent to the
1427 : : // point and closest to the line segment.
1428 : : //
1429 : : // Special Notes :
1430 : : //
1431 : : // Creator : Jason Kraftcheck
1432 : : //
1433 : : // Creation Date : 09/04/03
1434 : : //-------------------------------------------------------------------------
1435 : 0 : CubitStatus FacetProjectTool::next_around_point ( PST_Point*& start,
1436 : : const CubitVector& seg_end,
1437 : : PST_Face*& closest_face,
1438 : : PST_Edge*& closest_edge,
1439 : : CubitBoolean & is_boundary_edge,
1440 : : PST_Edge *last_closest_edge)
1441 : : {
1442 [ # # ]: 0 : DLIList<PST_Face*> face_list;
1443 [ # # ][ # # ]: 0 : DLIList<PST_Edge*> boundary_edges;
1444 : 0 : is_boundary_edge = CUBIT_FALSE;
1445 : 0 : double shortest_dist_sqr = CUBIT_DBL_MAX;
1446 : 0 : closest_face = 0;
1447 : 0 : closest_edge = 0;
1448 : :
1449 : : //const double TOL_SQR = GEOMETRY_RESABS*GEOMETRY_RESABS;
1450 : :
1451 [ # # ]: 0 : const CubitVector tangent = seg_end - *start;
1452 : :
1453 : : // To traverse the edges in clockwise order about the point,
1454 : : // it is necessary to start with the appropriate boundary edge
1455 : : // if there is one. If this point is not on the boundary of
1456 : : // the facet patch, any edge is acceptable.
1457 : :
1458 : : // First mark all faces adjacent to the vertex. This is to make
1459 : : // sure disjoint sets of faces (sets of faces with no edges in
1460 : : // common) are not missed when traversing edge-face adjacencies.
1461 [ # # ]: 0 : start->faces( &face_list );
1462 [ # # ][ # # ]: 0 : for (int i = face_list.size(); i--; )
1463 [ # # ]: 0 : face_list.step_and_get()->mark = true;
1464 : :
1465 : : // Loop until all faces in face_list have been un-marked
1466 [ # # ]: 0 : boundary_edges.clean_out();
1467 : 0 : closest_edge = 0;
1468 : 0 : closest_face = 0;
1469 [ # # ][ # # ]: 0 : while (face_list.size())
1470 : : {
1471 [ # # ]: 0 : PST_Face* face = face_list.pop();
1472 [ # # ]: 0 : if (!face->mark)
1473 : 0 : continue;
1474 : :
1475 [ # # ]: 0 : PST_CoEdge* coedge = face->first_coedge();
1476 [ # # ][ # # ]: 0 : if (coedge->edge()->other(start) == 0)
[ # # ]
1477 [ # # ]: 0 : coedge = coedge->next();
1478 : :
1479 : : // search for the 'first' coedge in the clockwise list.
1480 : 0 : PST_CoEdge* first = coedge;
1481 [ # # ][ # # ]: 0 : while (coedge->face())
1482 : : {
1483 [ # # ][ # # ]: 0 : if (coedge->end_point() == start)
1484 [ # # ]: 0 : coedge = coedge->other();
1485 : : else
1486 [ # # ]: 0 : coedge = coedge->previous();
1487 : :
1488 [ # # ]: 0 : if (coedge == first) // no start, point is not on boundary
1489 : 0 : break;
1490 : : }
1491 : :
1492 : : // keep boundary edges encountered for later
1493 [ # # ][ # # ]: 0 : if (!coedge->face())
1494 [ # # ][ # # ]: 0 : boundary_edges.append(coedge->edge());
1495 : :
1496 : : // Of the two edges on the face that are adjacent to the
1497 : : // point, begin with the one that is first in clockwise
1498 : : // order around the point.
1499 [ # # ][ # # ]: 0 : if (coedge->start_point() == start)
1500 [ # # ]: 0 : coedge = coedge->other();
1501 : 0 : first = coedge;
1502 : :
1503 : : // Traverse adjacent facets in clockwise order
1504 : : // around point.
1505 : 0 : bool clockwise_of_prev = false;
1506 [ # # ][ # # ]: 0 : while ( (face = coedge->face()) )
1507 : : {
1508 : 0 : face->mark = false;
1509 : :
1510 : : // get vectors for edges of face pointing outwards
1511 : : // from vertex.
1512 [ # # ][ # # ]: 0 : assert(coedge->end_point() == start && coedge->next()->start_point() == start);
[ # # ][ # # ]
[ # # ]
1513 [ # # ][ # # ]: 0 : CubitVector prev = coedge->other()->direction();
1514 [ # # ][ # # ]: 0 : CubitVector next = coedge->next()->direction();
1515 : :
1516 : : // calculate if segment is to the 'inside' of each
1517 : : // adjacent edge.
1518 [ # # ]: 0 : CubitVector normal = next * prev; // ccw
1519 [ # # ][ # # ]: 0 : bool inside_prev = ((tangent * prev) % normal) >= 0.0;
1520 [ # # ][ # # ]: 0 : bool inside_next = ((next * tangent) % normal) >= 0.0;
1521 : :
1522 : : // If edge is inside face, check distance from face
1523 [ # # ][ # # ]: 0 : if( (inside_prev && inside_next) )
1524 : : {
1525 : : // calculate distance from end point to plane of face
1526 [ # # ]: 0 : const double plane_coeff = normal % *start;
1527 [ # # ]: 0 : const double end_coeff = normal % seg_end;
1528 : 0 : const double numerator = end_coeff - plane_coeff;
1529 [ # # ]: 0 : const double dist_sqr = (numerator * numerator) / normal.length_squared();
1530 : :
1531 [ # # ]: 0 : if (dist_sqr < shortest_dist_sqr)
1532 : : {
1533 : 0 : closest_face = face;
1534 : 0 : closest_edge = 0;
1535 : 0 : shortest_dist_sqr = dist_sqr;
1536 : : }
1537 : :
1538 : 0 : clockwise_of_prev = false;
1539 : : }
1540 : : // If the edge is above a peak formed by the shared edge of two faces
1541 [ # # ][ # # ]: 0 : else if (inside_next && clockwise_of_prev)
1542 : : {
1543 : : // calculate distance from end of segment to line of facet edge
1544 [ # # ]: 0 : const double dot_prod = tangent % prev;
1545 : : const double dist_sqr =
1546 [ # # ][ # # ]: 0 : tangent.length_squared() - dot_prod * dot_prod / prev.length_squared();
1547 : :
1548 [ # # ][ # # ]: 0 : if (dist_sqr <= shortest_dist_sqr && coedge->edge() != last_closest_edge)
[ # # ][ # # ]
1549 : : {
1550 : 0 : closest_face = 0;
1551 [ # # ]: 0 : closest_edge = coedge->edge();
1552 : 0 : shortest_dist_sqr = dist_sqr;
1553 : : }
1554 : 0 : clockwise_of_prev = false;
1555 : : }
1556 : : // If clockwise of the face, note for next iteration
1557 [ # # ]: 0 : else if (inside_prev)
1558 : : {
1559 : 0 : clockwise_of_prev = true;
1560 : : }
1561 : : else
1562 : : {
1563 : 0 : clockwise_of_prev = false;
1564 : : }
1565 : :
1566 [ # # ][ # # ]: 0 : coedge = coedge->next()->other();
1567 [ # # ]: 0 : if (coedge == first)
1568 : 0 : break;
1569 : : } // while(coedge->face())
1570 : :
1571 [ # # ][ # # ]: 0 : if (!coedge->face())
1572 [ # # ][ # # ]: 0 : boundary_edges.append(coedge->edge());
1573 : :
1574 : : } // while(face_list.size())
1575 : :
1576 : : // If a closest entity was found, then done.
1577 [ # # ][ # # ]: 0 : if (closest_face || closest_edge)
1578 : 0 : return CUBIT_SUCCESS;
1579 : :
1580 : :
1581 : : //Here we try to intersect the segment with the boundary
1582 : : //facet edge closest to 'start' (farthest from 'end')
1583 : 0 : bool debug = false;
1584 [ # # ]: 0 : if( !closest_edge )
1585 : : {
1586 [ # # ]: 0 : CubitVector seg_direction = seg_end - *start;
1587 [ # # ]: 0 : double seg_length = seg_direction.length();
1588 : 0 : double longest_length = 0;
1589 : :
1590 [ # # ]: 0 : if( debug )
1591 : : {
1592 [ # # ]: 0 : GfxDebug::clear();
1593 [ # # ]: 0 : start->debug_draw(CUBIT_GREEN_INDEX);
1594 [ # # ]: 0 : GfxDebug::draw_point( seg_end, CUBIT_RED_INDEX );
1595 [ # # ][ # # ]: 0 : for( int j=facetList.size(); j--; )
1596 [ # # ][ # # ]: 0 : facetList.get_and_step()->debug_draw( CUBIT_CYAN_INDEX );
1597 [ # # ]: 0 : GfxDebug::mouse_xforms();
1598 : : }
1599 : :
1600 : : //find the farthest boundary edge that is on the line segment
1601 [ # # ]: 0 : CubitVector split_position;
1602 [ # # ][ # # ]: 0 : for( int k=boundaryList.size(); k--; )
1603 : : {
1604 [ # # ]: 0 : PST_Edge *tmp_edge = boundaryList.get_and_step();
1605 : :
1606 [ # # ][ # # ]: 0 : if( tmp_edge->start_point() == start ||
[ # # ][ # # ]
1607 [ # # ]: 0 : tmp_edge->end_point() == start )
1608 : 0 : continue;
1609 : :
1610 [ # # ][ # # ]: 0 : double t1 = tmp_edge->closest_on_line( *start, seg_end - *start );
1611 : :
1612 [ # # ][ # # ]: 0 : if( t1 > 1e-6 && t1 < 1 )
1613 : : {
1614 [ # # ]: 0 : CubitVector tmp_pos = tmp_edge->position( t1 );
1615 : :
1616 [ # # ]: 0 : if( debug )
1617 : : {
1618 [ # # ]: 0 : GfxDebug::draw_line( *start, seg_end, CUBIT_MAGENTA_INDEX );
1619 [ # # ][ # # ]: 0 : PRINT_INFO("t1 = %f\n", t1 );
[ # # ][ # # ]
1620 [ # # ]: 0 : tmp_edge->debug_draw( CUBIT_YELLOW_INDEX );
1621 [ # # ]: 0 : GfxDebug::draw_point( tmp_pos, CUBIT_RED_INDEX );
1622 [ # # ]: 0 : GfxDebug::flush();
1623 [ # # ]: 0 : GfxDebug::mouse_xforms();
1624 : : }
1625 : :
1626 [ # # ]: 0 : double tmp_dist = tmp_pos.distance_between( seg_end );
1627 : :
1628 [ # # ][ # # ]: 0 : if( tmp_dist > longest_length && tmp_dist < seg_length )
1629 : : {
1630 : 0 : longest_length = tmp_dist;
1631 : 0 : closest_edge = tmp_edge;
1632 [ # # ]: 0 : split_position = tmp_pos;
1633 : : }
1634 : : }
1635 : : }
1636 : :
1637 [ # # ]: 0 : if( closest_edge )
1638 : : {
1639 [ # # ]: 0 : start = project( split_position );
1640 : :
1641 : : CubitStatus my_stat = next_around_point( start, seg_end, closest_face,
1642 [ # # ]: 0 : closest_edge, is_boundary_edge, last_closest_edge );
1643 : :
1644 [ # # ]: 0 : if( CUBIT_FAILURE == my_stat )
1645 : 0 : return CUBIT_FAILURE;
1646 : :
1647 [ # # ]: 0 : return closest_face ? CUBIT_SUCCESS : CUBIT_FAILURE;
1648 : : }
1649 : : }
1650 : :
1651 [ # # ][ # # ]: 0 : return closest_edge ? CUBIT_SUCCESS : CUBIT_FAILURE;
1652 : : }
1653 : :
1654 : :
1655 : :
1656 : :
1657 : :
1658 : :
1659 : : //-------------------------------------------------------------------------
1660 : : // Purpose : Remove duplciate edges from results if input polyline
1661 : : // was self-intersecting.
1662 : : //
1663 : : // Special Notes :
1664 : : //
1665 : : // Creator : Jason Kraftcheck
1666 : : //
1667 : : // Creation Date : ??
1668 : : //-------------------------------------------------------------------------
1669 : 0 : void FacetProjectTool::finalize_results()
1670 : : {
1671 : 0 : imprintResult.reset();
1672 [ # # ]: 0 : for ( int i = imprintResult.size(); i--; )
1673 : : {
1674 : 0 : PST_Edge* edge = imprintResult.step_and_get()->edge();
1675 [ # # ]: 0 : if (edge->mark)
1676 : 0 : imprintResult.change_to(0);
1677 : : else
1678 : 0 : edge->mark = 1;
1679 : : }
1680 [ # # ]: 0 : imprintResult.remove_all_with_value(0);
1681 : 0 : imprintResult.reset();
1682 : 0 : }
1683 : :
1684 : : //-------------------------------------------------------------------------
1685 : : // Purpose : Return non-intersecting chains of result edges, in the
1686 : : // same sequence as the input polyline and with the same
1687 : : // orientation.
1688 : : //
1689 : : // Special Notes : This is called after the projection is done to get the
1690 : : // resulting facet edge chains.
1691 : : //
1692 : : // Creator : Jason Kraftcheck
1693 : : //
1694 : : // Creation Date : 09/04/03
1695 : : //-------------------------------------------------------------------------
1696 : 0 : CubitStatus FacetProjectTool::get_result_set( DLIList<PST_CoEdge*>& coedges )
1697 : : {
1698 [ # # ][ # # ]: 0 : if ( !imprintResult.size() )
1699 : 0 : return CUBIT_FAILURE;
1700 : :
1701 [ # # ]: 0 : imprintResult.reset();
1702 [ # # ]: 0 : PST_CoEdge* prev = imprintResult.get();
1703 [ # # ]: 0 : imprintResult.change_to(0);
1704 [ # # ]: 0 : coedges.append(prev);
1705 : :
1706 [ # # ][ # # ]: 0 : for ( int i = imprintResult.size() - 1; i--; )
1707 : : {
1708 [ # # ]: 0 : PST_CoEdge* coedge = imprintResult.step_and_get();
1709 [ # # ]: 0 : PST_Point* pt = prev->end_point();
1710 [ # # ][ # # ]: 0 : if (pt != coedge->start_point())
1711 : 0 : break;
1712 : :
1713 : 0 : int count = 1;
1714 [ # # ][ # # ]: 0 : for (PST_Edge* pt_edge = pt->next(coedge->edge());
[ # # ][ # # ]
1715 [ # # ]: 0 : pt_edge != coedge->edge();
1716 : : pt_edge = pt->next(pt_edge))
1717 : : {
1718 [ # # ]: 0 : if (pt_edge->mark)
1719 : 0 : count++;
1720 : : }
1721 : :
1722 [ # # ]: 0 : if (count != 2)
1723 : 0 : break;
1724 : :
1725 [ # # ]: 0 : coedges.append(coedge);
1726 : 0 : prev = coedge;
1727 [ # # ]: 0 : imprintResult.change_to(0);
1728 : : }
1729 : :
1730 [ # # ]: 0 : imprintResult.remove_all_with_value(0);
1731 : 0 : return CUBIT_SUCCESS;
1732 : : }
1733 : :
1734 : :
1735 : 0 : double FacetProjectTool::closest_on_line( const CubitVector& B,
1736 : : const CubitVector& M,
1737 : : const CubitVector& P )
1738 : : {
1739 : 0 : const double dist_tol_sqr = GEOMETRY_RESABS*GEOMETRY_RESABS;
1740 : 0 : double D = M.length_squared();
1741 [ # # ][ # # ]: 0 : return (D < dist_tol_sqr ) ? 0.0 : (M % (P - B)) / D;
[ # # ][ # # ]
[ # # ]
1742 : : }
1743 : :
1744 : :
1745 : 0 : void FacetProjectTool::closest_on_lines( const CubitVector& B1,
1746 : : const CubitVector& M1,
1747 : : const CubitVector& B2,
1748 : : const CubitVector& M2,
1749 : : double& t1, double& t2 )
1750 : : {
1751 [ # # ][ # # ]: 0 : CubitVector N = M2 * (M2 * M1);
1752 [ # # ]: 0 : double d = N % M1;
1753 [ # # ]: 0 : if( fabs(d) < CUBIT_RESABS ) //parallel lines
1754 : 0 : t1 = 0.0;
1755 : : else
1756 [ # # ][ # # ]: 0 : t1 = ((N % B2) - (N % B1)) / d;
1757 : :
1758 [ # # ][ # # ]: 0 : t2 = closest_on_line( B2, M2, B1 + t1 * M1 );
[ # # ]
1759 : 0 : }
1760 : :
1761 : :
1762 : 0 : bool FacetProjectTool::inside_face( PST_Face* face, const CubitVector& pos )
1763 : : {
1764 : : // This code checks if the position is in the interior of
1765 : : // the prism formed by sweeping the facet infinetly in the
1766 : : // direction of, and opposite direction of the facet normal.
1767 : 0 : PST_CoEdge* coe = face->first_coedge();
1768 [ # # ]: 0 : do {
1769 [ # # ]: 0 : CubitVector vect( pos );
1770 [ # # ][ # # ]: 0 : vect -= *coe->start_point();
1771 [ # # ][ # # ]: 0 : vect *= coe->direction();
1772 [ # # ][ # # ]: 0 : if( vect % face->normal() > -CUBIT_RESABS )
[ # # ]
1773 : 0 : return false;
1774 [ # # ]: 0 : coe = coe->next();
1775 : 0 : } while( coe != face->first_coedge() );
1776 : 0 : return true;
1777 : : }
1778 : :
1779 : : /*
1780 : : static void draw_pt( const std::vector<double>& list, int index, int color )
1781 : : {
1782 : : GfxDebug::draw_point(
1783 : : (float)list[index], (float)list[index+1], (float)list[index+2], color );
1784 : : }
1785 : :
1786 : : static void draw_edge( const std::vector<double>& list, int i1, int i2, int color )
1787 : : {
1788 : : i1 *= 3; i2 *= 3;
1789 : : GfxDebug::draw_line(
1790 : : (float)list[i1], (float)list[i1+1], (float)list[i1+2],
1791 : : (float)list[i2], (float)list[i2+1], (float)list[i2+2],
1792 : : color );
1793 : : }
1794 : :
1795 : : static void draw_tri( const std::vector<double>& pts,
1796 : : const std::vector<int>& tris, int index,
1797 : : const std::vector<int>& seq, int color )
1798 : : {
1799 : : for ( int i = 0; i < 3; i++ )
1800 : : {
1801 : : int i1 = tris[index + i];
1802 : : int i2 = tris[index + (i + 1) % 3];
1803 : : if ( !seq[i1] || !seq[i2] || abs(seq[i1]-seq[i2]) != 1 )
1804 : : draw_edge( pts, i1, i2, color );
1805 : : }
1806 : : }
1807 : : */
1808 : :
1809 : 0 : void FacetProjectTool::debug( DLIList<CubitVector*>& segments,
1810 : : std::vector<double>& coordinates,
1811 : : std::vector<int>& connections )
1812 : : {
1813 : : #if 1 /* test with old interface */
1814 [ # # ]: 0 : DLIList<PST_Edge*> edges;
1815 [ # # ]: 0 : PST_Edge::make_facets(coordinates, connections, GEOMETRY_RESABS, edges);
1816 : :
1817 [ # # ][ # # ]: 0 : DLIList<PST_Face*> faces;
1818 [ # # ]: 0 : PST_Edge::faces( edges, faces );
1819 [ # # ]: 0 : populate_data(faces);
1820 : :
1821 : : CubitBoolean point_changed;
1822 [ # # ]: 0 : do_projection( segments, point_changed );
1823 : :
1824 [ # # ]: 0 : PST_Edge::debug_draw_edges( edgeList, CUBIT_BLUE_INDEX );
1825 : :
1826 [ # # ][ # # ]: 0 : DLIList<PST_CoEdge*> coedges;
1827 [ # # ]: 0 : finalize_results();
1828 [ # # ][ # # ]: 0 : while( get_result_set( coedges ) ) {
1829 [ # # ]: 0 : edges.clean_out();
1830 [ # # ]: 0 : coedges.reverse();
1831 [ # # ][ # # ]: 0 : while (coedges.size()) edges.append(coedges.pop()->edge());
[ # # ][ # # ]
[ # # ]
1832 [ # # ]: 0 : PST_Edge::debug_draw_edges( edges, CUBIT_WHITE_INDEX );
1833 [ # # ]: 0 : PST_Edge::debug_draw_points( edges, CUBIT_WHITE_INDEX );
1834 : : }
1835 : :
1836 : : #else /* test with new interface */
1837 : :
1838 : : int i, j;
1839 : :
1840 : : // do projection
1841 : : std::vector<double> new_pts;
1842 : : std::vector<int> dudded, new_facets, facet_index, polyline;
1843 : : if( !project( segments, coordinates, connections, dudded,
1844 : : new_facets, facet_index, new_pts, polyline ) )
1845 : : {
1846 : : PRINT_ERROR("FacetProjectTool::project returned CUBIT_FAILURE\n");
1847 : : return;
1848 : : }
1849 : :
1850 : : assert( connections.size() % 3 == 0 );
1851 : : assert( coordinates.size() % 3 == 0 );
1852 : : assert( new_facets.size() % 3 == 0 );
1853 : : assert( new_pts.size() % 3 == 0 );
1854 : : assert( dudded.size() == facet_index.size() );
1855 : : int num_old_tri = connections.size() / 3;
1856 : : int num_new_tri = new_facets.size() / 3;
1857 : : int num_old_pts = coordinates.size() / 3;
1858 : : int num_new_pts = new_pts.size() / 3;
1859 : : int num_tot_tri = num_new_tri + num_old_tri;
1860 : : int num_tot_pts = num_new_pts + num_old_pts;
1861 : :
1862 : : PRINT_INFO("%d input triangles using %d points.\n", num_old_tri, num_old_pts );
1863 : : PRINT_INFO("%d new triangles and %d new poitns.\n", num_new_tri, num_new_pts );
1864 : : PRINT_INFO("%d total triangles using %d total points.\n", num_tot_tri, num_tot_pts );
1865 : : PRINT_INFO("connections.size() = %d\n", (int)connections.size());
1866 : : PRINT_INFO("coordinates.size() = %d\n", (int)coordinates.size());
1867 : : PRINT_INFO("dudded.size() = %d\n", (int)dudded.size());
1868 : : PRINT_INFO("new_facets.size() = %d\n", (int)new_facets.size());
1869 : : PRINT_INFO("facet_index.size() = %d\n", (int)facet_index.size());
1870 : : PRINT_INFO("new_pts.size() = %d\n", (int)new_pts.size());
1871 : : PRINT_INFO("polyline.size() = %d\n", (int)polyline.size());
1872 : :
1873 : : for ( i = 0; i < (int)new_facets.size(); i++ )
1874 : : if ( new_facets[i] >= num_tot_pts || new_facets[i] < 0 )
1875 : : PRINT_ERROR("Invalid value %d at new_facets[%d]\n", new_facets[i], i);
1876 : : for ( i = 0; i < (int)dudded.size(); i++ )
1877 : : if ( dudded[i] >= num_old_tri || dudded[i] < 0 )
1878 : : PRINT_ERROR("Invalid value %d at dudded[%d]\n", dudded[i], i);
1879 : : for ( i = 0; i < (int)polyline.size()-1; )
1880 : : {
1881 : : int count = polyline[i];
1882 : : if ( count < 2 )
1883 : : PRINT_ERROR("Invalid polyline length %d at polyline[%d]\n", count, i );
1884 : : i++;
1885 : : for ( j = 0; j < count; j++, i++ )
1886 : : {
1887 : : if( i >= (int)polyline.size() )
1888 : : PRINT_ERROR("Ran out of indices in polyline.\n");
1889 : : if ( polyline[i] >= num_tot_pts || polyline[i] < 0 )
1890 : : PRINT_ERROR("Invalid value %d at dudded[%d]\n", dudded[i], i);
1891 : : }
1892 : : }
1893 : :
1894 : : // draw original points
1895 : : for ( i = 0; i < (int)coordinates.size(); i += 3 )
1896 : : draw_pt( coordinates, i, CUBIT_BLUE_INDEX );
1897 : : /*
1898 : : // draw new points
1899 : : for ( i = 0; i < (int)new_pts.size(); i += 3 )
1900 : : draw_pt( new_pts, i, CUBIT_RED_INDEX );
1901 : : */
1902 : : // concatenate point lists
1903 : : for ( i = 0; i < (int)new_pts.size(); i++ )
1904 : : coordinates.push_back(new_pts[i]);
1905 : :
1906 : : // make reverse mapping for dudded facets
1907 : : std::vector<bool> dead(connections.size()/3);
1908 : : for ( i = 0; i < (int)dead.size(); i++ )
1909 : : dead[i] = false;
1910 : : for ( i = 0; i < (int)dudded.size(); i++ )
1911 : : dead[dudded[i]] = true;
1912 : :
1913 : : // make polyline sequence list (this won't work quite
1914 : : // right for self-intersecting polylines -- *shrug*)
1915 : : std::vector<int> sequence(coordinates.size() / 3);
1916 : : for ( i = 0; i < (int)sequence.size(); i++ )
1917 : : sequence[i] = 0;
1918 : : j = 0;
1919 : : for ( i = 0; i < (int)polyline.size(); i++ )
1920 : : sequence[polyline[i]] = ++j;
1921 : :
1922 : :
1923 : : // draw orginal facets
1924 : : for ( i = 0; i < (int)dead.size(); i++ )
1925 : : if( ! dead[i] )
1926 : : draw_tri( coordinates, connections, 3*i, sequence, CUBIT_BLUE_INDEX );
1927 : :
1928 : : // draw new facets
1929 : : for ( i = 0; i < (int)new_facets.size(); i += 3 )
1930 : : draw_tri( coordinates, new_facets, i, sequence, CUBIT_RED_INDEX );
1931 : :
1932 : : // draw polyline
1933 : : for ( i = 0; i < (int)polyline.size()-1; i++)
1934 : : {
1935 : : int count = polyline[i];
1936 : : if ( count < 2 )
1937 : : PRINT_ERROR("Invalid polyline length %d at polyline[%d]\n", count, i );
1938 : : int first = ++i;
1939 : : for ( j = 0; j < count-1; j++, i++ )
1940 : : {
1941 : : draw_edge( coordinates, polyline[i], polyline[i+1], CUBIT_WHITE_INDEX );
1942 : : }
1943 : : if( polyline[first] == polyline[i] )
1944 : : PRINT_INFO("Polyline is closed.\n");
1945 : : }
1946 : :
1947 : : GfxDebug::flush();
1948 : : #endif
1949 [ # # ][ # # ]: 0 : cleanup();
1950 [ + - ][ + - ]: 6540 : }
1951 : :
|