cgma
|
00001 //------------------------------------------------------------------------- 00002 // Filename : SplitSurfaceTool.cpp 00003 // 00004 // Purpose : Split a single or chain of surfaces (e.g., split a fillet 00005 // down the middle so that a mesh sweep can occur, or split 00006 // across a surface). Used by the "split surface" commands. 00007 // 00008 // Split Surface <id> Across [Pair] Location <options multiple locs> 00009 // [Preview [Create]] 00010 // Split Surface <id> Across Location <multiple locs> Onto Curve <id> 00011 // [Preview [Create]] 00012 // Split Surface <id_list> Extend [Vertex <id_list> | Auto] [Preview [Create]] 00013 // 00014 // Split Surface <id_list> [Corner Vertex <id_list>] [Direction Curve <id>] 00015 // [Segment <val> | Fraction|Distance <val> [From Curve <id>]] 00016 // [Through Vertex <id_list>] [Parametric <on|OFF>] [Tolerance <value>] 00017 // [Preview [Create]] 00018 // 00019 // Special Notes : 00020 // 00021 // Creator : Steve Storm 00022 // 00023 // Creation Date : 10/06/2002 00024 //------------------------------------------------------------------------- 00025 00026 #include "SplitSurfaceTool.hpp" 00027 #include "AnalyticGeometryTool.hpp" 00028 #include "Body.hpp" 00029 #include "RefFace.hpp" 00030 #include "Point.hpp" 00031 #include "Curve.hpp" 00032 #include "Surface.hpp" 00033 #include "Loop.hpp" 00034 #include "CubitMessage.hpp" 00035 #include "GeometryModifyTool.hpp" 00036 #include "GeometryModifyEngine.hpp" 00037 #include "GeometryQueryTool.hpp" 00038 #include "CubitUtil.hpp" 00039 #include "DLIList.hpp" 00040 #include "TDSplitSurface.hpp" 00041 #include "GfxDebug.hpp" 00042 #include "GfxPreview.hpp" 00043 #include "Cubit2DPoint.hpp" 00044 #include "GMem.hpp" 00045 #include "SettingHandler.hpp" 00046 00047 CubitBoolean SplitSurfaceTool::parametricFlg = CUBIT_FALSE; 00048 double SplitSurfaceTool::splitTolerance = 1.0; 00049 CubitBoolean SplitSurfaceTool::autoDetectTriangles = CUBIT_TRUE; 00050 double SplitSurfaceTool::sideAngleThreshold = 27.0; // From 180 00051 double SplitSurfaceTool::pointAngleThreshold = 45.0; // Below is a point 00052 double SplitSurfaceTool::extendGapThreshold = CUBIT_DBL_MAX; 00053 CubitBoolean SplitSurfaceTool::extendNormalFlg = CUBIT_FALSE; 00054 double SplitSurfaceTool::extendTolerance = .1; 00055 00056 SplitSurfaceTool::SplitSurfaceTool() 00057 { 00058 int i; 00059 for(i=0; i<4; i++) 00060 { 00061 sideInterval[i] = 0; 00062 cornerCoEdge[i] = NULL; 00063 } 00064 isLoop = CUBIT_FALSE; 00065 } 00066 00067 //Initialize all settings in this class 00068 void 00069 SplitSurfaceTool::initialize_settings() 00070 { 00071 SettingHandler::instance()->add_setting("Split Surface Tolerance", 00072 SplitSurfaceTool::set_tolerance, 00073 SplitSurfaceTool::get_tolerance); 00074 00075 SettingHandler::instance()->add_setting("Split Surface Parametric", 00076 SplitSurfaceTool::set_parametric_flg, 00077 SplitSurfaceTool::get_parametric_flg); 00078 00079 SettingHandler::instance()->add_setting("Split Surface Auto Detect Triangles", 00080 SplitSurfaceTool::set_auto_detect_triangles_flg, 00081 SplitSurfaceTool::get_auto_detect_triangles_flg); 00082 00083 SettingHandler::instance()->add_setting("Split Surface Side Angle Threshold", 00084 SplitSurfaceTool::set_side_angle_threshold, 00085 SplitSurfaceTool::get_side_angle_threshold); 00086 00087 SettingHandler::instance()->add_setting("Split Surface Point Angle Threshold", 00088 SplitSurfaceTool::set_point_angle_threshold, 00089 SplitSurfaceTool::get_point_angle_threshold); 00090 00091 SettingHandler::instance()->add_setting("Split Surface Extend Gap Threshold", 00092 SplitSurfaceTool::set_extend_gap_threshold, 00093 SplitSurfaceTool::get_extend_gap_threshold); 00094 00095 SettingHandler::instance()->add_setting("Split Surface Extend Tolerance", 00096 SplitSurfaceTool::set_extend_tolerance, 00097 SplitSurfaceTool::get_extend_tolerance); 00098 00099 SettingHandler::instance()->add_setting("Split Surface Extend Normal", 00100 SplitSurfaceTool::set_extend_normal_flg, 00101 SplitSurfaceTool::get_extend_normal_flg); 00102 } 00103 00104 CubitStatus 00105 SplitSurfaceTool::preview( RefFace *ref_face_ptr, 00106 DLIList<CubitVector*> &locations, 00107 DLIList<DLIList<CubitVector*>*> &vec_lists, 00108 CubitBoolean create_ref_edges_flg, 00109 CubitBoolean clear_previous_previews ) 00110 { 00111 // Create curves from the input vec_lists (locations are just the original 00112 // locations the user specified - these need to be drawn) 00113 int i, j; 00114 Curve *curve_ptr; 00115 DLIList<CubitVector*> *vec_list_ptr; 00116 vec_lists.reset(); 00117 DLIList<Surface*> surfs; 00118 00119 Surface *surf_ptr = ref_face_ptr->get_surface_ptr(); 00120 00121 // Support composite surfaces by getting the surfaces underlying 00122 // the composite and creating split curves for them individually. 00123 GeometryQueryEngine *gqe = surf_ptr->get_geometry_query_engine(); 00124 DLIList<TopologyBridge*> tbs; 00125 gqe->get_underlying_surfaces(surf_ptr, tbs); 00126 if(tbs.size() > 0) 00127 { 00128 for(j=tbs.size(); j>0; j--) 00129 surfs.append(dynamic_cast<Surface*>(tbs.get_and_step())); 00130 } 00131 else 00132 surfs.append(surf_ptr); 00133 00134 // Clear previous previews if necessary 00135 if( clear_previous_previews == CUBIT_TRUE ) 00136 GfxPreview::clear(); 00137 00138 for( i=vec_lists.size(); i--; ) 00139 { 00140 vec_list_ptr = vec_lists.get_and_step(); 00141 00142 vec_list_ptr->reset(); 00143 if( vec_list_ptr->size() < 2 ) 00144 { 00145 PRINT_ERROR( "Unable to create a curve from less than two locations.\n" ); 00146 continue; 00147 } 00148 00149 for(j=surfs.size(); j>0; j--) 00150 { 00151 Surface *cur_surf = surfs.get_and_step(); 00152 curve_ptr = create_curve( *vec_list_ptr, cur_surf ); 00153 00154 if( curve_ptr ) 00155 { 00156 if( create_ref_edges_flg == CUBIT_TRUE ) 00157 { 00158 RefEdge *ref_edge_ptr; 00159 ref_edge_ptr = GeometryQueryTool::instance()->make_free_RefEdge(curve_ptr); 00160 if( ref_edge_ptr ) 00161 PRINT_INFO( "Created new curve %d\n", ref_edge_ptr->id() ); 00162 } 00163 else 00164 { 00165 draw_preview( curve_ptr, CUBIT_FALSE ); 00166 curve_ptr->get_geometry_query_engine()->delete_solid_model_entities(curve_ptr ); 00167 } 00168 } 00169 } 00170 } 00171 00172 // Draw locations too 00173 draw_points( locations, CUBIT_BLUE_INDEX ); 00174 00175 return CUBIT_SUCCESS; 00176 } 00177 00178 CubitStatus 00179 SplitSurfaceTool::preview( DLIList<RefFace*> &ref_face_list, 00180 DLIList<CubitVector*> &locations, 00181 DLIList<DLIList<DLIList<CubitVector*>*>*> &list_of_vec_lists, 00182 CubitBoolean create_ref_edges_flg, 00183 CubitBoolean clear_previous_previews ) 00184 { 00185 //Reset ref_face_list and list_of_vec_lists (just in case) 00186 ref_face_list.reset(); 00187 list_of_vec_lists.reset(); 00188 00189 // Clear previous previews if necessary 00190 if( clear_previous_previews == CUBIT_TRUE ) 00191 GfxPreview::clear(); 00192 00193 int qq; 00194 for( qq = ref_face_list.size(); qq > 0 ; qq--) 00195 { 00196 //Initialize the values to be used upon each iteration 00197 RefFace* ref_face_ptr = ref_face_list.get_and_step(); 00198 DLIList<DLIList<CubitVector*>*> vec_lists = *( list_of_vec_lists.get_and_step() ); 00199 00200 int i, j; 00201 Curve *curve_ptr; 00202 DLIList<CubitVector*> *vec_list_ptr; 00203 vec_lists.reset(); 00204 DLIList<Surface*> surfs; 00205 00206 Surface *surf_ptr = ref_face_ptr->get_surface_ptr(); 00207 00208 // Support composite surfaces by getting the surfaces underlying 00209 // the composite and creating split curves for them individually. 00210 GeometryQueryEngine *gqe = surf_ptr->get_geometry_query_engine(); 00211 DLIList<TopologyBridge*> tbs; 00212 gqe->get_underlying_surfaces(surf_ptr, tbs); 00213 if(tbs.size() > 0) 00214 { 00215 for(j=tbs.size(); j>0; j--) 00216 surfs.append(dynamic_cast<Surface*>(tbs.get_and_step())); 00217 } 00218 else 00219 surfs.append(surf_ptr); 00220 00221 for( i=vec_lists.size(); i--; ) 00222 { 00223 vec_list_ptr = vec_lists.get_and_step(); 00224 00225 vec_list_ptr->reset(); 00226 if( vec_list_ptr->size() < 2 ) 00227 { 00228 PRINT_ERROR( "Unable to create a curve from less than two locations.\n" ); 00229 continue; 00230 } 00231 00232 for(j=surfs.size(); j>0; j--) 00233 { 00234 Surface *cur_surf = surfs.get_and_step(); 00235 curve_ptr = create_curve( *vec_list_ptr, cur_surf ); 00236 00237 if( curve_ptr ) 00238 { 00239 if( create_ref_edges_flg == CUBIT_TRUE ) 00240 { 00241 RefEdge *ref_edge_ptr; 00242 ref_edge_ptr = GeometryQueryTool::instance()->make_free_RefEdge(curve_ptr); 00243 if( ref_edge_ptr ) 00244 PRINT_INFO( "Created new curve %d\n", ref_edge_ptr->id() ); 00245 } 00246 else 00247 { 00248 draw_preview( curve_ptr, CUBIT_FALSE ); 00249 curve_ptr->get_geometry_query_engine()->delete_solid_model_entities(curve_ptr ); 00250 } 00251 } 00252 } 00253 } 00254 } 00255 00256 // Draw locations too 00257 draw_points( locations, CUBIT_BLUE_INDEX ); 00258 00259 return CUBIT_SUCCESS; 00260 } 00261 00262 // Create the curves used by the splitting algorithm. 00263 // Note: calling code is responsible for cleaning up the 00264 // created curves when it is done with them. 00265 CubitStatus 00266 SplitSurfaceTool::calculate_split_curves( RefFace *ref_face_ptr, 00267 DLIList<DLIList<CubitVector*>*> &vec_lists, 00268 DLIList<Curve*>& curve_list ) 00269 { 00270 Surface *surf_ptr = ref_face_ptr->get_surface_ptr(); 00271 00272 return calculate_split_curves(surf_ptr, vec_lists, curve_list); 00273 } 00274 00275 CubitStatus 00276 SplitSurfaceTool::calculate_split_curves( Surface *surf_ptr, 00277 DLIList<DLIList<CubitVector*>*> &vec_lists, 00278 DLIList<Curve*>& curve_list ) 00279 { 00280 int i; 00281 Curve *curve_ptr; 00282 DLIList<CubitVector*> *vec_list_ptr; 00283 vec_lists.reset(); 00284 00285 for( i=vec_lists.size(); i--; ) 00286 { 00287 vec_list_ptr = vec_lists.get_and_step(); 00288 00289 vec_list_ptr->reset(); 00290 if( vec_list_ptr->size() < 2 ) 00291 { 00292 PRINT_ERROR( "Unable to create a curve from less than two locations.\n" ); 00293 continue; 00294 } 00295 00296 curve_ptr = create_curve( *vec_list_ptr, surf_ptr ); 00297 00298 if( curve_ptr ) 00299 { 00300 curve_list.append( curve_ptr ); 00301 if( DEBUG_FLAG( 100 ) ) 00302 draw_preview( curve_ptr, CUBIT_TRUE, CUBIT_RED_INDEX ); 00303 } 00304 } 00305 00306 if( !curve_list.size() ) 00307 return CUBIT_FAILURE; 00308 00309 return CUBIT_SUCCESS; 00310 } 00311 00312 CubitStatus 00313 SplitSurfaceTool::split_surface( RefFace *ref_face_ptr, DLIList<Curve*> &curve_list) 00314 { 00315 // Count number of surfaces in owning body prior to split - this is used to 00316 // determine if split is actually successful. 00317 Body *body_ptr; 00318 int num_surfaces_prior = count_surfaces_in_owning_body( ref_face_ptr, body_ptr ); 00319 int num_curves_prior = count_curves_in_body( body_ptr ); 00320 00321 if( num_surfaces_prior == -1 ) 00322 { 00323 PRINT_ERROR( "Cannot split a surface that is not part of a volume\n" ); 00324 return CUBIT_FAILURE; 00325 } 00326 else if( num_surfaces_prior == -2 ) 00327 { 00328 PRINT_ERROR( "Cannot split a surface that is contained by multiple volumes\n" ); 00329 return CUBIT_FAILURE; 00330 } 00331 00332 // Clear any previews 00333 GfxPreview::clear(); 00334 00335 // Perform the split on the real (e.g. OCC) geometry. 00336 Surface *surf_ptr = ref_face_ptr->get_surface_ptr(); 00337 00338 DLIList<Surface*> surface_list; 00339 surface_list.append( surf_ptr ); 00340 DLIList<DLIList<Curve*>*> curve_lists_list; 00341 curve_lists_list.append( &curve_list ); 00342 00343 Body *new_body_ptr; 00344 00345 if( GeometryModifyTool::instance()->imprint( surface_list, 00346 curve_lists_list, new_body_ptr ) == CUBIT_FAILURE ) 00347 { 00348 while( curve_list.size() ) 00349 delete curve_list.pop(); 00350 return CUBIT_FAILURE; 00351 } 00352 00353 while( curve_list.size() ) 00354 delete curve_list.pop(); 00355 00356 // Draw locations too 00357 // draw_points( locations, CUBIT_BLUE_INDEX ); 00358 00359 int num_surfaces_after = count_surfaces_in_body( body_ptr ); 00360 00361 if( num_surfaces_after > num_surfaces_prior ) 00362 return CUBIT_SUCCESS; 00363 else 00364 { 00365 int num_curves_after = count_curves_in_body( body_ptr ); 00366 if( num_curves_after > num_curves_prior ) 00367 return CUBIT_SUCCESS; 00368 } 00369 00370 PRINT_ERROR( "Split failed - surface %d was not split\n", ref_face_ptr->id() ); 00371 return CUBIT_FAILURE; 00372 } 00373 00374 CubitStatus 00375 SplitSurfaceTool::split_surface( RefFace *ref_face_ptr, 00376 DLIList<DLIList<CubitVector*>*> &vec_lists ) 00377 { 00378 // Count number of surfaces in owning body prior to split - this is used to 00379 // determine if split is actually successful. 00380 Body *body_ptr; 00381 int num_surfaces_prior = count_surfaces_in_owning_body( ref_face_ptr, body_ptr ); 00382 if( num_surfaces_prior == -1 ) 00383 { 00384 PRINT_ERROR( "Cannot split a surface that is not part of a volume\n" ); 00385 return CUBIT_FAILURE; 00386 } 00387 else if( num_surfaces_prior == -2 ) 00388 { 00389 PRINT_ERROR( "Cannot split a surface that is contained by multiple volumes\n" ); 00390 return CUBIT_FAILURE; 00391 } 00392 int num_curves_prior = count_curves_in_body( body_ptr ); 00393 00394 int original_id = ref_face_ptr->id(); 00395 Surface *surf_ptr = ref_face_ptr->get_surface_ptr(); 00396 00397 // Clear any previews 00398 GfxPreview::clear(); 00399 00400 // Find the splitting curves 00401 DLIList<DLIList<Curve*>*> curve_lists_list; 00402 00403 // Support composite surfaces by getting the surfaces underlying 00404 // the composite and creating split curves for them individually. 00405 GeometryQueryEngine *gqe = surf_ptr->get_geometry_query_engine(); 00406 DLIList<TopologyBridge*> tbs; 00407 gqe->get_underlying_surfaces(surf_ptr, tbs); 00408 CubitStatus err = CUBIT_SUCCESS; 00409 if(tbs.size() > 0) 00410 { 00411 err = CUBIT_FAILURE; 00412 for(int k=tbs.size(); k>0; k--) 00413 { 00414 Surface *srf = dynamic_cast<Surface*>(tbs.get_and_step()); 00415 if(srf) 00416 { 00417 DLIList<Curve*> *curve_list = new DLIList<Curve*>; 00418 CubitStatus tmp_status = calculate_split_curves( srf, vec_lists, *curve_list ); 00419 // If at least one split is successful return success. We anticipate that some curves 00420 // won't imprint on some of the underlying surfaces of the composite surface. Because 00421 // we are allowing success this way there are sometimes errors that get printed even 00422 // though we are calling it a success. Need to find a good way to fix this. 00423 if(tmp_status) 00424 err = CUBIT_SUCCESS; 00425 curve_lists_list.append(curve_list); 00426 } 00427 } 00428 } 00429 else 00430 { 00431 DLIList<Curve*> *curve_list = new DLIList<Curve*>; 00432 err = calculate_split_curves( ref_face_ptr, vec_lists, *curve_list ); 00433 curve_lists_list.append(curve_list); 00434 } 00435 00436 if( err == CUBIT_FAILURE ) 00437 { 00438 while(curve_lists_list.size()) 00439 { 00440 DLIList<Curve*> *cur_list = curve_lists_list.pop(); 00441 while(cur_list->size()) 00442 { 00443 Curve* curve_ptr = cur_list->pop(); 00444 curve_ptr->get_geometry_query_engine()->delete_solid_model_entities(curve_ptr ); 00445 } 00446 delete cur_list; 00447 } 00448 return CUBIT_FAILURE; 00449 } 00450 00451 // Perform the split on the real (e.g. OCC) geometry. 00452 DLIList<Surface*> surface_list; 00453 surface_list.append( surf_ptr ); 00454 00455 Body *new_body_ptr; 00456 00457 if( GeometryModifyTool::instance()->imprint( surface_list, 00458 curve_lists_list, new_body_ptr ) == CUBIT_FAILURE ) 00459 { 00460 while(curve_lists_list.size()) 00461 { 00462 DLIList<Curve*> *cur_list = curve_lists_list.pop(); 00463 while(cur_list->size()) 00464 { 00465 Curve* curve_ptr = cur_list->pop(); 00466 curve_ptr->get_geometry_query_engine()->delete_solid_model_entities(curve_ptr ); 00467 } 00468 delete cur_list; 00469 } 00470 return CUBIT_FAILURE; 00471 } 00472 00473 while(curve_lists_list.size()) 00474 { 00475 DLIList<Curve*> *cur_list = curve_lists_list.pop(); 00476 while(cur_list->size()) 00477 { 00478 Curve* curve_ptr = cur_list->pop(); 00479 curve_ptr->get_geometry_query_engine()->delete_solid_model_entities(curve_ptr ); 00480 } 00481 delete cur_list; 00482 } 00483 00484 // Draw locations too 00485 //draw_points( locations, CUBIT_BLUE_INDEX ); 00486 00487 int num_surfaces_after = count_surfaces_in_body( body_ptr ); 00488 00489 if( num_surfaces_after > num_surfaces_prior ) 00490 return CUBIT_SUCCESS; 00491 else 00492 { 00493 int num_curves_after = count_curves_in_body( body_ptr ); 00494 if( num_curves_after > num_curves_prior ) 00495 return CUBIT_SUCCESS; 00496 } 00497 00498 PRINT_ERROR( "Split failed - surface %d was not split\n", original_id ); 00499 return CUBIT_FAILURE; 00500 } 00501 //ADDED BY GJS (CAT) 6/26/08 @ 11:00am 00502 CubitStatus 00503 SplitSurfaceTool::split_surface( DLIList<RefFace*> &ref_face_list, 00504 DLIList<DLIList<DLIList<CubitVector*>*>*> &list_of_vec_lists ) 00505 { 00506 //Initialize inputs to imprint function call 00507 DLIList<Surface*> surface_list; 00508 DLIList<DLIList<Curve*>*> curve_lists_list; 00509 00510 // Clear any previews 00511 GfxPreview::clear(); 00512 00513 //Reset all lists 00514 ref_face_list.reset(); 00515 list_of_vec_lists.reset(); 00516 00517 int hh; 00518 for( hh = ref_face_list.size() ; hh > 0 ; hh--) 00519 { 00520 // Count number of surfaces in owning body prior to split - this is used to 00521 // determine if split is actually successful. 0 00522 RefFace* ref_face_ptr = ref_face_list.get_and_step(); 00523 Body* body_ptr; 00524 00525 int num_surfaces_prior = count_surfaces_in_owning_body( ref_face_ptr, body_ptr ); 00526 if( num_surfaces_prior == -1 ) 00527 { 00528 PRINT_ERROR( "Cannot split a surface that is not part of a volume\n" ); 00529 return CUBIT_FAILURE; 00530 } 00531 else if( num_surfaces_prior == -2 ) 00532 { 00533 PRINT_ERROR( "Cannot split a surface that is contained by multiple volumes\n" ); 00534 return CUBIT_FAILURE; 00535 } 00536 ref_face_ptr->id(); 00537 Surface *surf_ptr = ref_face_ptr->get_surface_ptr(); 00538 00539 00540 00541 // Support composite surfaces by getting the surfaces underlying 00542 // the composite and creating split curves for them individually. 00543 GeometryQueryEngine *gqe = surf_ptr->get_geometry_query_engine(); 00544 DLIList<TopologyBridge*> tbs; 00545 gqe->get_underlying_surfaces(surf_ptr, tbs); 00546 CubitStatus err = CUBIT_SUCCESS; 00547 if(tbs.size() > 0) 00548 { 00549 err = CUBIT_FAILURE; 00550 for(int k=tbs.size(); k>0; k--) 00551 { 00552 Surface *srf = dynamic_cast<Surface*>(tbs.get_and_step()); 00553 if(srf) 00554 { 00555 DLIList<Curve*> *curve_list = new DLIList<Curve*>; 00556 DLIList<DLIList<CubitVector*>*> temp_vec_lists = *( list_of_vec_lists.get_and_step() ); 00557 CubitStatus tmp_status = calculate_split_curves( srf, temp_vec_lists, *curve_list ); 00558 // If at least one split is successful return success. We anticipate that some curves 00559 // won't imprint on some of the underlying surfaces of the composite surface. Because 00560 // we are allowing success this way there are sometimes errors that get printed even 00561 // though we are calling it a success. Need to find a good way to fix this. 00562 if(tmp_status) 00563 err = CUBIT_SUCCESS; 00564 curve_lists_list.append(curve_list); 00565 } 00566 } 00567 } 00568 else 00569 { 00570 DLIList<Curve*> *curve_list = new DLIList<Curve*>; 00571 DLIList<DLIList<CubitVector*>*> temp_vec_lists = *( list_of_vec_lists.get_and_step() ); 00572 err = calculate_split_curves( ref_face_ptr, temp_vec_lists, *curve_list ); 00573 curve_lists_list.append(curve_list); 00574 } 00575 00576 if( err == CUBIT_FAILURE ) 00577 { 00578 while(curve_lists_list.size()) 00579 { 00580 DLIList<Curve*> *cur_list = curve_lists_list.pop(); 00581 while(cur_list->size()) 00582 delete cur_list->pop(); 00583 delete cur_list; 00584 } 00585 return CUBIT_FAILURE; 00586 } 00587 00588 surface_list.append( surf_ptr ); 00589 } 00590 00591 // Perform the split on the real (e.g. OCC) geometry. 00592 Body *new_body_ptr; 00593 00594 if( GeometryModifyTool::instance()->imprint( surface_list, 00595 curve_lists_list, new_body_ptr ) == CUBIT_FAILURE ) 00596 { 00597 while(curve_lists_list.size()) 00598 { 00599 DLIList<Curve*> *cur_list = curve_lists_list.pop(); 00600 while(cur_list->size()) 00601 delete cur_list->pop(); 00602 delete cur_list; 00603 } 00604 return CUBIT_FAILURE; 00605 } 00606 00607 while(curve_lists_list.size()) 00608 { 00609 DLIList<Curve*> *cur_list = curve_lists_list.pop(); 00610 while(cur_list->size()) 00611 delete cur_list->pop(); 00612 delete cur_list; 00613 } 00614 00615 //NOTE: current assumption is failure will not occur since user does not 00616 // control input parameters to this function (may need to fix). 00617 //int num_surfaces_after = count_surfaces_in_body( body_ptr ); 00618 00619 //if( num_surfaces_after > num_surfaces_prior ) 00620 // return CUBIT_SUCCESS; 00621 //else 00622 //{ 00623 // int num_curves_after = count_curves_in_body( body_ptr ); 00624 // if( num_curves_after > num_curves_prior ) 00625 // return CUBIT_SUCCESS; 00626 //} 00627 00628 //PRINT_ERROR( "Split failed - surface %d was not split\n", original_id ); 00629 //return CUBIT_FAILURE; 00630 00631 return CUBIT_SUCCESS; 00632 } 00633 00634 CubitStatus 00635 SplitSurfaceTool::draw_points( DLIList<CubitVector*> &pnt_list, int color, 00636 int flush ) 00637 { 00638 int i; 00639 for( i=pnt_list.size(); i--; ) 00640 { 00641 CubitVector *pnt_ptr = pnt_list.get_and_step(); 00642 draw_point( *pnt_ptr, color ); 00643 } 00644 00645 if( flush ) 00646 { 00647 GfxPreview::flush(); 00648 } 00649 00650 return CUBIT_SUCCESS; 00651 } 00652 00653 CubitStatus 00654 SplitSurfaceTool::draw_point( CubitVector &pnt, int color, int flush ) 00655 { 00656 GfxPreview::draw_point( pnt, color ); 00657 if( flush ) 00658 { 00659 GfxPreview::flush(); 00660 } 00661 return CUBIT_SUCCESS; 00662 } 00663 00664 CubitStatus 00665 SplitSurfaceTool::split_surfaces( DLIList<RefFace*> &ref_face_list, 00666 int num_segs, 00667 double fraction, 00668 double distance, 00669 RefEdge *from_curve_ptr, 00670 DLIList<RefVertex*> &corner_vertex_list, 00671 DLIList<RefVertex*> &through_vertex_list, 00672 RefEdge *curve_dir_ptr, 00673 CubitBoolean preview_flg, 00674 CubitBoolean create_ref_edges_flg ) 00675 { 00676 CubitStatus status; 00677 00678 CubitBoolean just_curves_flg = CUBIT_FALSE; 00679 DLIList<DLIList<Curve*>*> curve_lists_list; 00680 00681 // Clear any previous previews 00682 GfxPreview::clear(); 00683 00684 // Call the primary function 00685 status = split_surfaces( ref_face_list, num_segs, fraction, distance, 00686 from_curve_ptr, corner_vertex_list, 00687 through_vertex_list, curve_dir_ptr, 00688 preview_flg, create_ref_edges_flg, 00689 just_curves_flg, curve_lists_list ); 00690 00691 free_curves_lists( curve_lists_list ); 00692 00693 return status; 00694 } 00695 00696 CubitStatus 00697 SplitSurfaceTool::split_surfaces( DLIList<RefFace*> &ref_face_list, 00698 int num_segs, 00699 double fraction, 00700 double distance, 00701 RefEdge *from_curve_ptr, 00702 DLIList<RefVertex*> &corner_vertex_list, 00703 DLIList<RefVertex*> &through_vertex_list, 00704 RefEdge *curve_dir_ptr, 00705 DLIList<DLIList<Curve*>*> &curve_lists_list ) 00706 { 00707 CubitStatus status; 00708 CubitBoolean preview_flg = CUBIT_FALSE; 00709 CubitBoolean create_ref_edges_flg = CUBIT_FALSE; 00710 CubitBoolean just_curves_flg = CUBIT_TRUE; 00711 00712 // Call the primary function 00713 status = split_surfaces( ref_face_list, num_segs, fraction, distance, 00714 from_curve_ptr, corner_vertex_list, 00715 through_vertex_list, curve_dir_ptr, 00716 preview_flg, create_ref_edges_flg, 00717 just_curves_flg, curve_lists_list ); 00718 00719 return status; 00720 } 00721 00722 CubitStatus 00723 SplitSurfaceTool::split_surfaces( DLIList<RefFace*> &ref_face_list, 00724 int num_segs, 00725 double fraction, 00726 double distance, 00727 RefEdge *from_curve_ptr, 00728 DLIList<RefVertex*> &corner_vertex_list, 00729 DLIList<RefVertex*> &through_vertex_list, 00730 RefEdge *curve_dir_ptr, 00731 DLIList<Curve*> &curve_list ) 00732 { 00733 CubitStatus status; 00734 CubitBoolean preview_flg = CUBIT_FALSE; 00735 CubitBoolean create_ref_edges_flg = CUBIT_FALSE; 00736 CubitBoolean just_curves_flg = CUBIT_TRUE; 00737 DLIList<DLIList<Curve*>*> curve_lists_list; 00738 00739 // Call the primary function 00740 status = split_surfaces( ref_face_list, num_segs, fraction, distance, 00741 from_curve_ptr, corner_vertex_list, 00742 through_vertex_list, curve_dir_ptr, 00743 preview_flg, create_ref_edges_flg, 00744 just_curves_flg, curve_lists_list ); 00745 00746 // Convert the curves to the simple curve_list 00747 int i, j; 00748 curve_lists_list.reset(); 00749 for( i=curve_lists_list.size(); i--; ) 00750 { 00751 DLIList<Curve*> *curve_list_ptr = curve_lists_list.get_and_step(); 00752 00753 curve_list_ptr->reset(); 00754 for( j=curve_list_ptr->size(); j--; ) 00755 { 00756 Curve *curve_ptr = curve_list_ptr->get_and_step(); 00757 curve_list.append( curve_ptr ); 00758 } 00759 } 00760 00761 free_curves_lists( curve_lists_list, CUBIT_FALSE ); 00762 00763 return status; 00764 } 00765 00766 CubitStatus 00767 SplitSurfaceTool::calculate_split_curves( DLIList<RefFace*> &ref_face_list, 00768 int num_segs, 00769 double fraction, 00770 double distance, 00771 RefEdge *from_curve_ptr, 00772 DLIList<RefVertex*> &corner_vertex_list, 00773 DLIList<RefVertex*> &through_vertex_list, 00774 RefEdge *curve_dir_ptr, 00775 CubitBoolean preview_flg, 00776 CubitBoolean create_ref_edges_flg, 00777 CubitBoolean just_curves_flg, 00778 DLIList<DLIList<Curve*>*> &curve_lists_list ) 00779 { 00780 int i; 00781 refFaceChain = ref_face_list; 00782 throughVertexList = through_vertex_list; 00783 00784 // Get tolerance and parametric_flg from member variables 00785 double tolerance = splitTolerance; 00786 CubitBoolean parametric_flg = parametricFlg; 00787 00788 // Check for valid fraction 00789 if( fraction<0.0 || fraction>1.0 ) 00790 { 00791 PRINT_ERROR( "Fraction must be between 0.0 and 1.0 - aborting.\n" ); 00792 return CUBIT_FAILURE; 00793 } 00794 00795 // Check for valid number of segments 00796 if( num_segs < 2 ) 00797 { 00798 PRINT_ERROR( "Number of specified segments must be >= 2\n" ); 00799 return CUBIT_FAILURE; 00800 } 00801 00802 // Not valid to specify through vertices with multiple segments 00803 if( num_segs > 2 && throughVertexList.size() ) 00804 { 00805 PRINT_ERROR( "Through vertices specified - not valid if number of segments > 2\n" ); 00806 return CUBIT_FAILURE; 00807 } 00808 00809 // Check number of through vertices 00810 if( throughVertexList.size() > refFaceChain.size()+1 ) 00811 { 00812 PRINT_ERROR( "Too many 'through' vertices specified.\n" 00813 " Can only be equal to one more than the number of surfaces to split.\n" ); 00814 return CUBIT_FAILURE; 00815 } 00816 00817 // If a distance was specified, set the parametric flag to FALSE 00818 if( distance != -1.0 ) 00819 parametric_flg = CUBIT_FALSE; 00820 00821 // Check the individual surfaces for errors (multiple loops, hardlines) 00822 if( check_valid_faces() == CUBIT_FAILURE ) 00823 return CUBIT_FAILURE; 00824 00825 // Order the face list from one end of the chain to the other. This function 00826 // also checks for the isLoop condition. 00827 if( order_face_list() == CUBIT_FAILURE ) 00828 return CUBIT_FAILURE; 00829 if( DEBUG_FLAG(154) ) 00830 { 00831 DLIList<CubitEntity*> cubit_faces; 00832 CAST_LIST(refFaceChain, cubit_faces, CubitEntity); 00833 CubitUtil::list_entity_ids( "\nOrdered surface list: ", 00834 cubit_faces, 80, "\n", CUBIT_FALSE ); 00835 } 00836 00837 // Get all the outer loops, in the proper order. This also makes sure 00838 // they start at the beginning of the first surface in the chain. 00839 if( get_outer_loops() == CUBIT_FAILURE ) 00840 return CUBIT_FAILURE; 00841 00842 // Make sure direction and from curves are valid, if specified 00843 if( curve_dir_ptr && !is_curve_in_outer_loop( curve_dir_ptr ) ) 00844 { 00845 PRINT_ERROR( "Specified direction curve %d not found on side of logical rectangle\n", 00846 curve_dir_ptr->id() ); 00847 return CUBIT_FAILURE; 00848 } 00849 if( from_curve_ptr && !is_curve_in_outer_loop( from_curve_ptr ) ) 00850 { 00851 PRINT_ERROR( "Specified from curve %d not found on side of logical rectangle\n", 00852 from_curve_ptr->id() ); 00853 return CUBIT_FAILURE; 00854 } 00855 00856 // Find the corners 00857 if( corner_vertex_list.size() ) 00858 { 00859 if( corner_vertex_list.size() != 4 ) 00860 { 00861 PRINT_ERROR( "You must select exactly 4 corner vertices\n" ); 00862 return CUBIT_FAILURE; 00863 } 00864 00865 if( isLoop ) 00866 { 00867 PRINT_WARNING( "Ignoring specified corners since continuous loop situation\n" ); 00868 } 00869 else 00870 { 00871 // Now order these vertices properly w/respect to the outerCoEdgeLoop 00872 if( order_selected_corners( corner_vertex_list ) == CUBIT_FAILURE ) 00873 return CUBIT_FAILURE; 00874 } 00875 } 00876 else 00877 { 00878 // Pick the corners based on angle criteria 00879 if( refFaceChain.size() > 1 ) 00880 { 00881 if( pick_4_corners() == CUBIT_FAILURE ) 00882 return CUBIT_FAILURE; 00883 } 00884 else 00885 { 00886 // Single surface case 00887 if( pick_4_corners_simple() == CUBIT_FAILURE ) 00888 return CUBIT_FAILURE; 00889 } 00890 } 00891 00892 // Adjust the surface to the split direction. This function also adjusts 00893 // and checks for errors if a throughVertexList was specified. 00894 if( adjust_for_split_direction( curve_dir_ptr, from_curve_ptr, corner_vertex_list ) 00895 == CUBIT_FAILURE ) 00896 return CUBIT_FAILURE; 00897 00898 // If previewing, draw the corners in RED 00899 if( preview_flg == CUBIT_TRUE ) 00900 { 00901 CubitVector temp_vec = start_vertex(cornerCoEdge[0])->coordinates(); 00902 00903 draw_point( temp_vec, CUBIT_RED_INDEX ); 00904 temp_vec = start_vertex(cornerCoEdge[1])->coordinates(); 00905 draw_point( temp_vec, CUBIT_RED_INDEX ); 00906 temp_vec = start_vertex(cornerCoEdge[2])->coordinates(); 00907 draw_point( temp_vec, CUBIT_RED_INDEX ); 00908 temp_vec = start_vertex(cornerCoEdge[3])->coordinates(); 00909 draw_point( temp_vec, CUBIT_RED_INDEX, CUBIT_TRUE ); 00910 } 00911 00912 if( DEBUG_FLAG(154) ) 00913 { 00914 DLIList<RefEdge*> curve_list; 00915 get_outer_curves( curve_list ); 00916 DLIList<CubitEntity*> cubit_edges; 00917 CAST_LIST(curve_list, cubit_edges, CubitEntity); 00918 CubitUtil::list_entity_ids( "Ordered curves outer loop: ", 00919 cubit_edges, 80, "\n", CUBIT_FALSE ); 00920 00921 PRINT_INFO( "Best corner 1 = Vertex %d\n", start_vertex(cornerCoEdge[0])->id() ); 00922 PRINT_INFO( "Best corner 2 = Vertex %d\n", start_vertex(cornerCoEdge[1])->id() ); 00923 PRINT_INFO( "Best corner 3 = Vertex %d\n", start_vertex(cornerCoEdge[2])->id() ); 00924 PRINT_INFO( "Best corner 4 = Vertex %d\n", start_vertex(cornerCoEdge[3])->id() ); 00925 00926 PRINT_INFO( "Side interval #1 = %d\n", sideInterval[0] ); 00927 PRINT_INFO( "Side interval #2 = %d\n", sideInterval[1] ); 00928 PRINT_INFO( "Side interval #3 = %d\n", sideInterval[2] ); 00929 PRINT_INFO( "Side interval #4 = %d\n", sideInterval[3] ); 00930 } 00931 00932 // Add a tooldata to each surface for later use 00933 RefFace *ref_face_ptr; 00934 refFaceChain.reset(); 00935 for( i=refFaceChain.size(); i--; ) 00936 { 00937 ref_face_ptr = refFaceChain.get_and_step(); 00938 ref_face_ptr->add_TD( new TDSplitSurface( ref_face_ptr ) ); 00939 } 00940 00941 // Add curve loops to each tooldata. These curve loops will form the 00942 // boundary of a mapped mesh algorithm that will find the interior 00943 // points for the split locations. 00944 if( populate_curve_loops() == CUBIT_FAILURE ) 00945 { 00946 delete_surf_tooldatas( refFaceChain ); 00947 return CUBIT_FAILURE; 00948 } 00949 00950 // Now build up the coordinates and get the curve(s) for each surface 00951 // curve_lists_list will contain a list of curve lists for each surface 00952 00953 // Keep track of new RefEdges created 00954 DLIList<RefEdge*> new_ref_edge_list; 00955 00956 TDSplitSurface *tdss; 00957 refFaceChain.reset(); 00958 for(i=refFaceChain.size(); i--; ) 00959 { 00960 ref_face_ptr = refFaceChain.get_and_step(); 00961 tdss = (TDSplitSurface *)ref_face_ptr-> 00962 get_TD(&TDSplitSurface::is_split_surface); 00963 00964 // Setup matched curve tessellations on all curves (the tessellations 00965 // are "matched" from side to side - the points on each side are 00966 // at identical parameter values along the side). This is not a 00967 // perfect solution but seems to work okay for the typical geometry 00968 // types this tool is used on. 00969 if( tdss->tessellate_sides( tolerance, fraction, distance, num_segs, 00970 throughVertexList ) == CUBIT_FAILURE ) 00971 { 00972 delete_vertex_tooldatas( through_vertex_list ); 00973 delete_surf_tooldatas( refFaceChain ); 00974 return CUBIT_FAILURE; 00975 } 00976 00977 // curve_list_ptr will contain a list of curves for the individual surface 00978 DLIList<Curve*> *curve_list_ptr = new DLIList<Curve*>; 00979 curve_lists_list.append( curve_list_ptr ); 00980 00981 // Use a mapping concept to get the spline coordinates of the curve to 00982 // split with. The function find_spline_curves will populate curve_list_ptr 00983 // with potentially multiple curves (typically there will only be one curve 00984 // though). 00985 if( find_spline_curves( ref_face_ptr, num_segs, distance, curve_list_ptr, 00986 tolerance, parametric_flg, preview_flg, 00987 create_ref_edges_flg ) == CUBIT_FAILURE ) 00988 { 00989 delete_vertex_tooldatas( throughVertexList ); 00990 delete_surf_tooldatas( refFaceChain ); 00991 return CUBIT_FAILURE; 00992 } 00993 00994 if( just_curves_flg == CUBIT_TRUE ) 00995 continue; 00996 00997 if( preview_flg == CUBIT_TRUE ) 00998 { 00999 if( create_ref_edges_flg == CUBIT_FALSE ) 01000 draw_preview( *curve_list_ptr ); 01001 else 01002 { 01003 create_ref_edges( *curve_list_ptr, new_ref_edge_list ); 01004 01005 // This just draws each curve as we go, same as preview does 01006 GfxPreview::flush(); 01007 } 01008 } 01009 } 01010 01011 // Let the user know if new curves were created 01012 if( preview_flg == CUBIT_TRUE && create_ref_edges_flg == CUBIT_TRUE 01013 && new_ref_edge_list.size() ) 01014 { 01015 DLIList<CubitEntity*> cubit_entity_list; 01016 CAST_LIST( new_ref_edge_list, cubit_entity_list, CubitEntity ); 01017 CubitUtil::list_entity_ids( "Created new curves: ", cubit_entity_list ); 01018 } 01019 01020 // Determine if all of the 'through' vertices were used - if not give a warning 01021 if( throughVertexList.size() ) 01022 { 01023 DLIList<RefVertex*> non_used_through_vertex_list; 01024 RefVertex *ref_vertex_ptr; 01025 throughVertexList.reset(); 01026 for( i=throughVertexList.size(); i--; ) 01027 { 01028 ref_vertex_ptr = throughVertexList.get_and_step(); 01029 tdss = (TDSplitSurface *)ref_vertex_ptr-> 01030 get_TD(&TDSplitSurface::is_split_surface); 01031 if( !tdss ) 01032 non_used_through_vertex_list.append( ref_vertex_ptr ); 01033 } 01034 01035 if( non_used_through_vertex_list.size() ) 01036 { 01037 DLIList<CubitEntity*> cubit_verts; 01038 CAST_LIST(non_used_through_vertex_list, cubit_verts, CubitEntity); 01039 CubitUtil::list_entity_ids( "WARNING - unused 'through' vertices: ", 01040 cubit_verts, 80, "\n", CUBIT_FALSE ); 01041 PRINT_INFO(" They were not found on the split path.\n" ); 01042 } 01043 } 01044 01045 // Remove tooldatas 01046 delete_vertex_tooldatas( throughVertexList ); 01047 delete_surf_tooldatas( refFaceChain ); 01048 01049 return CUBIT_SUCCESS; 01050 } 01051 01052 //- Begin Private Functions 01053 CubitStatus 01054 SplitSurfaceTool::split_surfaces( DLIList<RefFace*> &ref_face_list, 01055 int num_segs, 01056 double fraction, 01057 double distance, 01058 RefEdge *from_curve_ptr, 01059 DLIList<RefVertex*> &corner_vertex_list, 01060 DLIList<RefVertex*> &through_vertex_list, 01061 RefEdge *curve_dir_ptr, 01062 CubitBoolean preview_flg, 01063 CubitBoolean create_ref_edges_flg, 01064 CubitBoolean just_curves_flg, 01065 DLIList<DLIList<Curve*>*> &curve_lists_list ) 01066 { 01067 01068 // Find the splitting curves 01069 if( calculate_split_curves( ref_face_list, num_segs, fraction, distance, 01070 from_curve_ptr, corner_vertex_list, through_vertex_list, 01071 curve_dir_ptr, preview_flg, create_ref_edges_flg, 01072 just_curves_flg, curve_lists_list ) == CUBIT_FAILURE ) 01073 return CUBIT_FAILURE; 01074 01075 // Do the splitting 01076 if( preview_flg==CUBIT_FALSE && just_curves_flg==CUBIT_FALSE ) 01077 { 01078 int i; 01079 DLIList<Surface*> surface_list; 01080 refFaceChain.reset(); 01081 for( i=refFaceChain.size(); i--; ) 01082 surface_list.append( refFaceChain.get_and_step()->get_surface_ptr() ); 01083 01084 Body *new_body_ptr; 01085 if( GeometryModifyTool::instance()->imprint( surface_list, 01086 curve_lists_list, new_body_ptr ) == CUBIT_FAILURE ) 01087 { 01088 return CUBIT_FAILURE; 01089 } 01090 } 01091 01092 return CUBIT_SUCCESS; 01093 } 01094 01095 void 01096 SplitSurfaceTool::free_curves_lists( DLIList<DLIList<Curve*>*> &curve_lists_list, 01097 CubitBoolean free_curves_flg) 01098 { 01099 while( curve_lists_list.size() ) 01100 { 01101 DLIList<Curve*> *curve_list_ptr = curve_lists_list.pop(); 01102 01103 if( free_curves_flg == CUBIT_TRUE ) 01104 { 01105 while( curve_list_ptr->size() ) 01106 { 01107 Curve *curve_ptr = curve_list_ptr->pop(); 01108 01109 // If there is no RefEdge attached to this Curve, delete it 01110 RefEdge* ref_edge_ptr = dynamic_cast<RefEdge*>(curve_ptr->topology_entity()); 01111 if( !ref_edge_ptr ) 01112 curve_ptr->get_geometry_query_engine()->delete_solid_model_entities(curve_ptr ); 01113 } 01114 } 01115 01116 delete curve_list_ptr; 01117 } 01118 } 01119 01120 void 01121 SplitSurfaceTool::delete_surf_tooldatas( DLIList<RefFace*> &ref_face_list ) 01122 { 01123 int i; 01124 for( i=ref_face_list.size(); i--; ) 01125 { 01126 RefFace *ref_face_ptr = ref_face_list.get_and_step(); 01127 ref_face_ptr->delete_TD( &TDSplitSurface::is_split_surface ); 01128 } 01129 } 01130 01131 void 01132 SplitSurfaceTool::delete_coedge_tooldatas( DLIList<CoEdge*> &co_edge_list ) 01133 { 01134 int i; 01135 for( i=co_edge_list.size(); i--; ) 01136 { 01137 CoEdge *co_edge_ptr = co_edge_list.get_and_step(); 01138 co_edge_ptr->delete_TD( &TDSplitSurface::is_split_surface ); 01139 } 01140 } 01141 01142 void 01143 SplitSurfaceTool::delete_vertex_tooldatas( DLIList<RefVertex*> &ref_vertex_list ) 01144 { 01145 int i; 01146 for( i=ref_vertex_list.size(); i--; ) 01147 { 01148 RefVertex *ref_vertex_ptr = ref_vertex_list.get_and_step(); 01149 ref_vertex_ptr->delete_TD( &TDSplitSurface::is_split_surface ); 01150 } 01151 } 01152 01153 CubitStatus 01154 SplitSurfaceTool::check_valid_faces() 01155 { 01156 // Make sure each face doesn't have multiple loops or hardlines 01157 int i; 01158 RefFace *ref_face_ptr; 01159 CubitBoolean is_loop; 01160 refFaceChain.reset(); 01161 for( i=refFaceChain.size(); i--; ) 01162 { 01163 ref_face_ptr = refFaceChain.get_and_step(); 01164 if( check_face_loop( ref_face_ptr, is_loop ) == CUBIT_FAILURE ) 01165 return CUBIT_FAILURE; 01166 01167 if( refFaceChain.size()>1 && is_loop==CUBIT_TRUE ) 01168 { 01169 PRINT_ERROR( "Surface %d loops back on itself - cannot split chain.\n", 01170 ref_face_ptr->id() ); 01171 return CUBIT_FAILURE; 01172 } 01173 } 01174 return CUBIT_SUCCESS; 01175 } 01176 01177 CubitStatus 01178 SplitSurfaceTool::order_face_list() 01179 { 01180 int i; 01181 RefFace *ref_face_ptr = NULL; 01182 01183 if( refFaceChain.size() > 1 ) 01184 { 01185 // First make sure surfaces are at least connected 01186 refFaceChain.reset(); 01187 for( i=refFaceChain.size(); i--; ) 01188 { 01189 ref_face_ptr = refFaceChain.get_and_step(); 01190 01191 DLIList<RefFace*> neighbor_ref_faces; 01192 get_neighbors( ref_face_ptr, refFaceChain, neighbor_ref_faces ); 01193 if( neighbor_ref_faces.size() == 0 ) 01194 { 01195 PRINT_ERROR( "You must select a continuous chain of surfaces.\n" 01196 " Surface %d is not attached to the other surfaces.\n", 01197 ref_face_ptr->id() ); 01198 return CUBIT_FAILURE; 01199 } 01200 } 01201 } 01202 01203 if( refFaceChain.size() < 3 ) 01204 { 01205 if( refFaceChain.size() == 1 ) 01206 { 01207 // Check for isLoop situation. Assume we have a loop if some of 01208 // the RefEdges have 2 CoEdges that don't immediately loop back 01209 // on themselves (this is a hardline). 01210 ref_face_ptr = refFaceChain.get(); 01211 if( check_face_loop( ref_face_ptr, isLoop ) == CUBIT_FAILURE ) 01212 return CUBIT_FAILURE; 01213 01214 return CUBIT_SUCCESS; 01215 } 01216 01217 if( refFaceChain.size() == 2 ) 01218 { 01219 // Check for isLoop situation. Assume we have a loop if two separate 01220 // chains of curves from the first surface are shared by the second 01221 // surface. 01222 refFaceChain.reset(); 01223 RefFace *ref_face_ptr1 = refFaceChain.get_and_step(); 01224 RefFace *ref_face_ptr2 = refFaceChain.get(); 01225 CoEdge *start_co_edge_ptr = NULL; // Dummy 01226 if( check_for_loop( ref_face_ptr1, ref_face_ptr2, isLoop, start_co_edge_ptr ) 01227 == CUBIT_FAILURE ) 01228 return CUBIT_FAILURE; 01229 } 01230 return CUBIT_SUCCESS; 01231 } 01232 01233 // Get the face list going from one end to the other 01234 DLIList<RefFace*> ordered_face_list; 01235 01236 // Find an end - would have only one attached face 01237 int found = 0; 01238 refFaceChain.reset(); 01239 for( i=refFaceChain.size(); i--; ) 01240 { 01241 ref_face_ptr = refFaceChain.get_and_step(); 01242 01243 DLIList<RefFace*> neighbor_ref_faces; 01244 get_neighbors( ref_face_ptr, refFaceChain, neighbor_ref_faces ); 01245 if( neighbor_ref_faces.size() == 1 ) 01246 { 01247 found = 1; 01248 break; 01249 } 01250 else if( neighbor_ref_faces.size() == 0 ) 01251 { 01252 PRINT_ERROR( "You must select a continuous chain of surfaces.\n" 01253 " Surface %d is not attached to the other surfaces.\n", 01254 ref_face_ptr->id() ); 01255 return CUBIT_FAILURE; 01256 } 01257 } 01258 01259 // Check for continuous loop of surfaces 01260 if( !found ) 01261 { 01262 // This is a continuous loop of surfaces - just use the first one the 01263 // user picked as starting surface of the patch. 01264 isLoop = CUBIT_TRUE; 01265 refFaceChain.reset(); 01266 ref_face_ptr = refFaceChain.get(); 01267 } 01268 01269 // Walk across the surfaces 01270 ordered_face_list.append( ref_face_ptr ); 01271 DLIList<RefFace*> remaining_face_list = refFaceChain; 01272 remaining_face_list.remove( ref_face_ptr ); 01273 remaining_face_list.reset(); 01274 int num_faces = refFaceChain.size()-1; 01275 01276 for( i=num_faces; i--; ) 01277 { 01278 DLIList<RefFace*> neighbor_ref_faces; 01279 get_neighbors( ref_face_ptr, remaining_face_list, neighbor_ref_faces ); 01280 if( (!isLoop && neighbor_ref_faces.size() != 1) || 01281 (i==num_faces-1 && isLoop && neighbor_ref_faces.size() != 2) || 01282 (i!=num_faces-1 && isLoop && neighbor_ref_faces.size() != 1) ) 01283 { 01284 PRINT_ERROR( "Selected surfaces do not appear to form logical rectangle\n" ); 01285 return CUBIT_FAILURE; 01286 } 01287 neighbor_ref_faces.reset(); 01288 ref_face_ptr = neighbor_ref_faces.get(); 01289 ordered_face_list.append( ref_face_ptr ); 01290 remaining_face_list.remove( ref_face_ptr ); 01291 } 01292 01293 refFaceChain.clean_out(); 01294 ordered_face_list.reset(); 01295 refFaceChain = ordered_face_list; 01296 01297 return CUBIT_SUCCESS; 01298 } 01299 01300 CubitStatus 01301 SplitSurfaceTool::check_face_loop( RefFace *ref_face_ptr, CubitBoolean &is_loop ) 01302 { 01303 is_loop = CUBIT_FALSE; 01304 01305 // Get list of coedges for this surface 01306 DLIList<CoEdge*> co_edge_list; 01307 if( ordered_co_edges( ref_face_ptr, co_edge_list ) == CUBIT_FAILURE ) 01308 return CUBIT_FAILURE; 01309 01310 int i; 01311 co_edge_list.reset(); 01312 CoEdge *co_edge_ptr; 01313 DLIList<RefEdge*> ref_edge_list; 01314 RefEdge *ref_edge_ptr; 01315 int prev_i = -99; 01316 RefEdge *prev_ref_edge_ptr = NULL; 01317 for( i=co_edge_list.size(); i--; ) 01318 { 01319 co_edge_ptr = co_edge_list.get_and_step(); 01320 ref_edge_ptr = co_edge_ptr->get_ref_edge_ptr(); 01321 01322 if( ref_edge_list.is_in_list( ref_edge_ptr ) ) 01323 { 01324 // This may be a loop. 01325 is_loop = CUBIT_TRUE; 01326 01327 // Make sure it is not a hardline. Check for situation where loop 01328 // turns back on itself. 01329 01330 if( ref_edge_ptr==prev_ref_edge_ptr && prev_i==i+1 ) 01331 { 01332 PRINT_ERROR( "Detected hardline in Surface %d - cannot split.\n", 01333 ref_face_ptr->id() ); 01334 return CUBIT_FAILURE; 01335 } 01336 } 01337 01338 prev_i = i; 01339 prev_ref_edge_ptr = ref_edge_ptr; 01340 01341 ref_edge_list.append( ref_edge_ptr ); 01342 } 01343 01344 return CUBIT_SUCCESS; 01345 } 01346 01347 CubitStatus 01348 SplitSurfaceTool::check_for_loop( RefFace *ref_face_ptr1, RefFace *ref_face_ptr2, 01349 CubitBoolean &is_loop, CoEdge *&start_co_edge_ptr ) 01350 { 01351 // This algorithm is not perfect, but should cover most cases. 01352 RefEdge *ref_edge_ptr; 01353 01354 is_loop = CUBIT_FALSE; 01355 01356 // Get list of coedges for the first surface 01357 DLIList<CoEdge*> co_edge_list1; 01358 if( ordered_co_edges( ref_face_ptr1, co_edge_list1 ) == CUBIT_FAILURE ) 01359 return CUBIT_FAILURE; 01360 01361 // Get list of refedges for the second surface 01362 DLIList<RefEdge*> ref_edge_list2; 01363 DLIList<Loop*> loop_list; 01364 ref_face_ptr2->ordered_loops( loop_list ); 01365 if( loop_list.size() > 1 ) 01366 { 01367 PRINT_ERROR( "Only surfaces with a single loop are allowed.\n" 01368 " Surface %d has %d loops.\n", ref_face_ptr2->id(), 01369 loop_list.size() ); 01370 return CUBIT_FAILURE; 01371 } 01372 loop_list.get()->ordered_ref_edges( ref_edge_list2 ); 01373 01374 // Walk around the first surface 01375 01376 // First, position the list at a starting coedge - one that is shared with 01377 // the other surface. 01378 int i, j; 01379 co_edge_list1.reset(); 01380 for( i=0; i<co_edge_list1.size(); i++ ) 01381 { 01382 ref_edge_ptr = co_edge_list1.get()->get_ref_edge_ptr(); 01383 01384 if( ref_edge_list2.is_in_list( ref_edge_ptr ) ) 01385 { 01386 if( i==0 ) // Backup until we are at the start 01387 { 01388 for( j=co_edge_list1.size(); j--; ) 01389 { 01390 co_edge_list1.back(); 01391 ref_edge_ptr = co_edge_list1.get()->get_ref_edge_ptr(); 01392 if( ref_edge_list2.is_in_list( ref_edge_ptr ) ) 01393 continue; 01394 co_edge_list1.step(); 01395 } 01396 } 01397 break; 01398 } 01399 co_edge_list1.step(); 01400 } 01401 01402 // Now the list is positioned at the start of one of the shared chains of 01403 // curves. 01404 start_co_edge_ptr = co_edge_list1.get(); 01405 01406 // Walk along the first surface 01407 int found_break = 0; 01408 for( i=co_edge_list1.size(); i--; ) 01409 { 01410 ref_edge_ptr = co_edge_list1.get_and_step()->get_ref_edge_ptr(); 01411 01412 if( found_break && ref_edge_list2.is_in_list( ref_edge_ptr ) ) 01413 { 01414 is_loop = CUBIT_TRUE; 01415 return CUBIT_SUCCESS; 01416 } 01417 01418 if( !ref_edge_list2.is_in_list( ref_edge_ptr ) ) 01419 found_break = 1; 01420 } 01421 01422 return CUBIT_SUCCESS; 01423 } 01424 01425 CubitStatus 01426 SplitSurfaceTool::get_neighbors( RefFace *seed_ref_face, 01427 DLIList<RefFace*> &input_ref_faces, 01428 DLIList<RefFace*> &neighbor_ref_faces ) 01429 { 01430 int i, j; 01431 01432 // Copy the input_ref_faces_copy list so as to not change it 01433 DLIList<RefFace*> input_ref_faces_copy(input_ref_faces.size()); 01434 input_ref_faces_copy = input_ref_faces; 01435 01436 // Get the edges 01437 DLIList<RefEdge*> ref_edge_list; 01438 seed_ref_face->ref_edges( ref_edge_list ); 01439 01440 // Get all ref_faces attached to these edges 01441 RefEdge *ref_edge_ptr; 01442 RefFace *ref_face_ptr; 01443 for( i=ref_edge_list.size(); i--; ) 01444 { 01445 ref_edge_ptr = ref_edge_list.get_and_step(); 01446 01447 DLIList<RefFace*> attached_ref_faces; 01448 ref_edge_ptr->ref_faces( attached_ref_faces ); 01449 01450 for( j=attached_ref_faces.size(); j--; ) 01451 { 01452 ref_face_ptr = attached_ref_faces.get_and_step(); 01453 01454 if( ref_face_ptr == seed_ref_face ) 01455 continue; 01456 01457 // Don't consider ref_faces that aren't in the input list 01458 if( input_ref_faces_copy.is_in_list( ref_face_ptr ) ) 01459 { 01460 neighbor_ref_faces.append_unique( ref_face_ptr ); 01461 } 01462 } 01463 } 01464 01465 // Respect the incoming order of ref_faces 01466 if( neighbor_ref_faces.size() == 2 ) 01467 { 01468 input_ref_faces_copy.reset(); 01469 neighbor_ref_faces.reset(); 01470 RefFace *first_neighbor = neighbor_ref_faces.get_and_step(); 01471 RefFace *second_neighbor = neighbor_ref_faces.get_and_step(); 01472 for( i=input_ref_faces_copy.size(); i--; ) 01473 { 01474 ref_face_ptr = input_ref_faces_copy.get_and_step(); 01475 if( ref_face_ptr == first_neighbor ) 01476 break; 01477 else if( ref_face_ptr == second_neighbor ) 01478 { 01479 // Reverse the order 01480 neighbor_ref_faces.reverse(); 01481 break; 01482 } 01483 } 01484 } 01485 01486 return CUBIT_SUCCESS; 01487 } 01488 01489 CubitStatus 01490 SplitSurfaceTool::get_outer_loops() 01491 { 01492 // Get the outer curve loop 01493 if( get_outer_coedge_loop() == CUBIT_FAILURE ) 01494 return CUBIT_FAILURE; 01495 01496 // If we found a loop, we already setup the rest of the datastructures 01497 if( isLoop ) 01498 return CUBIT_SUCCESS; 01499 01500 // Make sure the loop has at least 3 vertices, to form at least a 01501 // degenerate rectangle 01502 if( outerCoEdgeLoop.size() < 3 ) 01503 { 01504 PRINT_ERROR( "Selected surfaces do not appear to form logical rectangle\n" ); 01505 return CUBIT_FAILURE; 01506 } 01507 01508 // Orient the loops so they start at the first CoEdge of the 01509 // starting RefFace in the chain 01510 if( refFaceChain.size() > 1 ) 01511 { 01512 refFaceChain.reset(); 01513 RefFace *first_ref_face = refFaceChain.get(); 01514 01515 // Move forward in the vertex list until we are on a surface 01516 // other than the first one 01517 int i; 01518 CoEdge *co_edge_ptr = NULL; 01519 outerCoEdgeLoop.reset(); 01520 for( i=outerCoEdgeLoop.size(); i--; ) 01521 { 01522 co_edge_ptr = outerCoEdgeLoop.get_and_step(); 01523 if( co_edge_ptr->get_ref_face() != first_ref_face ) 01524 break; 01525 } 01526 01527 // Now move forward in the list until we are on the first surface 01528 for( i=outerCoEdgeLoop.size(); i--; ) 01529 { 01530 co_edge_ptr = outerCoEdgeLoop.get(); 01531 if( co_edge_ptr->get_ref_face() == first_ref_face ) 01532 break; 01533 outerCoEdgeLoop.step(); 01534 } 01535 01536 PRINT_DEBUG_154( "First vertex on first surface = %d\n", start_vertex( co_edge_ptr )->id() ); 01537 PRINT_DEBUG_154( "Index of vertex list = %d\n", outerCoEdgeLoop.get_index() ); 01538 01539 // Reorient the lists appropriately 01540 reorient_loop( outerCoEdgeLoop.get_index() ); 01541 01542 if( DEBUG_FLAG(154) ) 01543 { 01544 DLIList<RefVertex*> ref_vertex_list; 01545 get_outer_vertices( ref_vertex_list ); 01546 DLIList<CubitEntity*> cubit_verts; 01547 CAST_LIST(ref_vertex_list, cubit_verts, CubitEntity); 01548 CubitUtil::list_entity_ids( "New vertex list: ", 01549 cubit_verts, 80, "\n", CUBIT_FALSE ); 01550 } 01551 } 01552 01553 return CUBIT_SUCCESS; 01554 } 01555 01556 CubitStatus 01557 SplitSurfaceTool::get_outer_coedge_loop() 01558 { 01559 01560 // Walk around the loop 01561 01562 // Start by gathering a list of all coedges 01563 int i; 01564 DLIList<CoEdge*> co_edge_list; 01565 01566 RefFace *ref_face_ptr; 01567 refFaceChain.reset(); 01568 for( i=refFaceChain.size(); i--; ) 01569 { 01570 ref_face_ptr = refFaceChain.get_and_step(); 01571 if( ordered_co_edges( ref_face_ptr, co_edge_list ) == CUBIT_FAILURE ) 01572 return CUBIT_FAILURE; 01573 } 01574 01575 // PRINT_INFO( "Entire coedge loop, starting at beginning -\n" ); 01576 // PRINT_INFO( "-------------------------------------------\n" ); 01577 // co_edge_list.reset(); 01578 // for( i=co_edge_list.size(); i--; ) 01579 // { 01580 // CoEdge *co_edge_ptr = co_edge_list.get_and_step(); 01581 // PRINT_INFO( " Curve %d on Surface %d\n", 01582 // co_edge_ptr->get_ref_edge_ptr()->id(), 01583 // co_edge_ptr->get_ref_face()->id() ); 01584 // } 01585 01586 CoEdge *start_co_edge_ptr; 01587 if( find_loop_start( start_co_edge_ptr ) == CUBIT_FAILURE ) 01588 { 01589 PRINT_ERROR( "Unable to find loop start\n" ); // TODO: better message 01590 return CUBIT_FAILURE; 01591 } 01592 01593 // PRINT_INFO( "Loop start = Curve %d on Surface %d\n", 01594 // start_co_edge_ptr->get_ref_edge_ptr()->id(), 01595 // start_co_edge_ptr->get_ref_face()->id() ); 01596 01597 // Remove CoEdges on curves shared between surfaces (except for the starting 01598 // chain for isLoop situation). For isLoop, lets create a list of those to 01599 // be added back in later (keep_co_edge_list). 01600 DLIList<CoEdge*> keep_co_edge_list; 01601 CoEdge *shared_co_edge_ptr; 01602 CoEdge *co_edge_ptr; 01603 if( isLoop ) 01604 { 01605 // Method - traverse co_edge_list, adding coedges to keep_co_edge_list 01606 // until we don't find a coedge that shares a RefEdge with another coedge. 01607 // We use the term "complimentary" CoEdge to refer to the other CoEdge that 01608 // shares the common RefEdge. 01609 // 01610 // To illustrate, in the diagram below, assume S1 is the first surface and 01611 // S2 is the last surface in the surface loop we are splitting (note that 01612 // S1 can equal S2). C1, C2 and C3 make up the "chain" of curvs, or "seam" 01613 // that is between S1 and S2. Note that C1 has 2 CoEdges, one owned by S1 01614 // and one owned by S2. So, starting at C1 on S1, we step through the list 01615 // until we encounter a CoEdge that does not have a "complimentary" CoEdge. 01616 // Just keep track of the CoEdges as we go. 01617 // 01618 // ------------+------------ 01619 // . | . 01620 // . |C1 . 01621 // . | . 01622 // . ^ + | . 01623 // . | | | . 01624 // . S2 | |C2 | S1 . 01625 // . | | v . 01626 // . + . 01627 // . | . 01628 // . |C3 . 01629 // . | . 01630 // ------------+------------ 01631 01632 // For this code, it is important that all the ordered coedges from the 01633 // starting surface are at the beginning of the co_edge_list (otherwise, we 01634 // will traverse partway up the first chain and then back). So we rebuild 01635 // co_edge_list - putting all the ordered coedges from the first surface at 01636 // the beginning of co_edge_list. 01637 DLIList<CoEdge*> temp_co_edge_list = co_edge_list; 01638 temp_co_edge_list.move_to( start_co_edge_ptr ); 01639 co_edge_list.clean_out(); 01640 01641 RefFace *start_ref_face_ptr = start_co_edge_ptr->get_ref_face(); 01642 01643 for( i=temp_co_edge_list.size(); i--; ) 01644 { 01645 co_edge_ptr = temp_co_edge_list.get(); 01646 if( co_edge_ptr->get_ref_face() == start_ref_face_ptr ) 01647 { 01648 co_edge_list.append( co_edge_ptr ); 01649 temp_co_edge_list.change_to( NULL ); 01650 } 01651 temp_co_edge_list.step(); 01652 } 01653 temp_co_edge_list.remove_all_with_value( NULL ); 01654 01655 co_edge_list += temp_co_edge_list; 01656 01657 // PRINT_INFO( "Entire coedge loop -\n" ); 01658 // PRINT_INFO( "--------------------\n" ); 01659 // co_edge_list.reset(); 01660 // for( i=co_edge_list.size(); i--; ) 01661 // { 01662 // CoEdge *co_edge_ptr = co_edge_list.get_and_step(); 01663 // PRINT_INFO( " Curve %d on Surface %d\n", 01664 // co_edge_ptr->get_ref_edge_ptr()->id(), 01665 // co_edge_ptr->get_ref_face()->id() ); 01666 // } 01667 01668 // PRINT_INFO( "Coedges to keep - \n" ); 01669 co_edge_list.reset(); 01670 co_edge_ptr = co_edge_list.get(); 01671 RefFace *ref_ref_face_ptr = co_edge_ptr->get_ref_face(); 01672 RefFace *shared_ref_face_ptr; 01673 shared_co_edge_ptr = get_complimentary_co_edge( co_edge_ptr, co_edge_list ); 01674 RefFace *ref_shared_ref_face_ptr = shared_co_edge_ptr->get_ref_face(); 01675 for( i=co_edge_list.size(); i--; ) 01676 { 01677 // Keep track of the starting and ending chain which we will lose in the 01678 // code below that removes all coedges that share a refedge. To do this, 01679 // add coedges until we don't find a shared one, or the reference surfaces 01680 // change (ref_ref_face_ptr || ref_shared_ref_face_ptr). Why look at 01681 // the reference surfaces? Because there could be a triangle as in the 01682 // diagram below. 01683 // 01684 // ------------+------------- 01685 // . | . 01686 // . |C1 . 01687 // . | . 01688 // . ^ + | S1 . 01689 // . | | | . 01690 // . S2 | |C2 | / . 01691 // . | | v / . 01692 // . + / . 01693 // . | / . 01694 // . |C3 / S3 . 01695 // . | / . 01696 // ------------+------------- 01697 co_edge_ptr = co_edge_list.get_and_step(); 01698 ref_face_ptr = co_edge_ptr->get_ref_face(); 01699 shared_co_edge_ptr = get_complimentary_co_edge( co_edge_ptr, co_edge_list ); 01700 if( !shared_co_edge_ptr ) 01701 break; 01702 shared_ref_face_ptr = shared_co_edge_ptr->get_ref_face(); 01703 if( ref_face_ptr==ref_ref_face_ptr && 01704 shared_ref_face_ptr==ref_shared_ref_face_ptr ) 01705 { 01706 keep_co_edge_list.append( co_edge_ptr ); 01707 // PRINT_INFO( " Keeping Curve %d on Surface %d\n", 01708 // co_edge_ptr->get_ref_edge_ptr()->id(), 01709 // co_edge_ptr->get_ref_face()->id() ); 01710 keep_co_edge_list.append( shared_co_edge_ptr ); 01711 // PRINT_INFO( " Keeping Curve %d on Surface %d\n", 01712 // shared_co_edge_ptr->get_ref_edge_ptr()->id(), 01713 // shared_co_edge_ptr->get_ref_face()->id() ); 01714 } 01715 else 01716 break; 01717 } 01718 } 01719 01720 // Remove all coedges that share a RefEdge 01721 for( i=co_edge_list.size(); i--; ) 01722 { 01723 // Add coedges until we don't find a shared one - this adds just the 01724 // first chain. 01725 co_edge_ptr = co_edge_list.get(); 01726 if( co_edge_ptr == NULL ) 01727 { 01728 co_edge_list.step(); 01729 continue; 01730 } 01731 shared_co_edge_ptr = get_complimentary_co_edge( co_edge_ptr, co_edge_list ); 01732 if( shared_co_edge_ptr ) 01733 { 01734 // This is not very efficient, but okay since we have relatively short 01735 // lists. 01736 co_edge_list.move_to( shared_co_edge_ptr ); 01737 // PRINT_INFO( " Removing Curve %d on Surface %d\n", 01738 // shared_co_edge_ptr->get_ref_edge_ptr()->id(), 01739 // shared_co_edge_ptr->get_ref_face()->id() ); 01740 01741 co_edge_list.change_to( NULL ); 01742 co_edge_list.move_to( co_edge_ptr ); 01743 // PRINT_INFO( " Removing Curve %d on Surface %d\n", 01744 // co_edge_ptr->get_ref_edge_ptr()->id(), 01745 // co_edge_ptr->get_ref_face()->id() ); 01746 01747 co_edge_list.change_to( NULL ); 01748 } 01749 co_edge_list.step(); 01750 } 01751 01752 co_edge_list.remove_all_with_value( NULL ); 01753 01754 // Add back in the removed coedges if isLoop 01755 if( isLoop ) 01756 { 01757 // Put them at the beginning for a slight efficiency gain 01758 DLIList<CoEdge*> temp_co_edge_list = co_edge_list; 01759 co_edge_list.clean_out(); 01760 co_edge_list += keep_co_edge_list; 01761 co_edge_list += temp_co_edge_list; 01762 } 01763 01764 // Walk around the loop until we encounter the start coedge again. 01765 // Note loop is positioned at starting coedge. 01766 CoEdge *prev_co_edge_ptr = start_co_edge_ptr; 01767 outerCoEdgeLoop.append( start_co_edge_ptr ); 01768 for( i=co_edge_list.size(); i--; ) 01769 { 01770 co_edge_ptr = get_next_co_edge( prev_co_edge_ptr, co_edge_list ); 01771 01772 if( co_edge_ptr == NULL ) 01773 { 01774 PRINT_ERROR( "Selected surfaces do not appear to form logical rectangle\n" ); 01775 return CUBIT_FAILURE; 01776 } 01777 01778 if( co_edge_ptr == start_co_edge_ptr ) // We're done 01779 break; 01780 01781 outerCoEdgeLoop.append( co_edge_ptr ); 01782 prev_co_edge_ptr = co_edge_ptr; 01783 co_edge_list.remove( co_edge_ptr ); 01784 } 01785 01786 // Set the corners and such if isLoop 01787 if( isLoop ) 01788 { 01789 // Start of first curve is first corner 01790 int best_corner_1, best_corner_2, best_corner_3=-1, best_corner_4=-1; 01791 01792 best_corner_1 = 0; 01793 best_corner_2 = keep_co_edge_list.size()/2; 01794 outerCoEdgeLoop.reset(); 01795 for( i=0; i<outerCoEdgeLoop.size()+1; i++ ) 01796 { 01797 co_edge_ptr = outerCoEdgeLoop.get_and_step(); 01798 if( i == best_corner_1 ) 01799 { 01800 cornerCoEdge[0] = co_edge_ptr; 01801 continue; 01802 } 01803 01804 if( i == best_corner_2 ) 01805 { 01806 cornerCoEdge[1] = co_edge_ptr; 01807 continue; 01808 } 01809 01810 if( start_vertex(co_edge_ptr) == start_vertex(cornerCoEdge[1]) ) 01811 { 01812 best_corner_3 = i; 01813 cornerCoEdge[2] = co_edge_ptr; 01814 continue; 01815 } 01816 01817 if( start_vertex(co_edge_ptr) == start_vertex(cornerCoEdge[0]) ) 01818 { 01819 if( i==outerCoEdgeLoop.size() ) 01820 best_corner_4 = i-1; 01821 else 01822 best_corner_4 = i; 01823 cornerCoEdge[3] = co_edge_ptr; 01824 break; 01825 } 01826 } 01827 01828 if( best_corner_3==-1 || best_corner_4==-1 ) 01829 { 01830 PRINT_ERROR( "unable to find corners\n" ); 01831 return CUBIT_FAILURE; 01832 } 01833 01834 fill_side_intervals( best_corner_1, best_corner_2, best_corner_3, best_corner_4 ); 01835 } 01836 01837 return CUBIT_SUCCESS; 01838 } 01839 01840 CubitStatus 01841 SplitSurfaceTool::find_loop_start( CoEdge *&start_co_edge_ptr ) 01842 { 01843 // For non-isLoop situation, start of loop will be first non-shared curve 01844 // on surface loop 01845 01846 int i, j; 01847 RefFace *ref_face_ptr; 01848 if( !isLoop ) 01849 { 01850 // First, get the outer curve loop of the surfaces 01851 refFaceChain.reset(); 01852 ref_face_ptr = refFaceChain.get_and_step(); 01853 01854 DLIList<CoEdge*> co_edge_list; 01855 if( ordered_co_edges( ref_face_ptr, co_edge_list ) == CUBIT_FAILURE ) 01856 return CUBIT_FAILURE; 01857 01858 // If we have one surface just return 01859 co_edge_list.reset(); 01860 if( refFaceChain.size() == 1 ) 01861 { 01862 start_co_edge_ptr = co_edge_list.get(); 01863 return CUBIT_SUCCESS; 01864 } 01865 01866 // Get the list of coedges in the next surface in the chain 01867 ref_face_ptr = refFaceChain.get(); 01868 DLIList<CoEdge*> next_co_edge_list; 01869 if( ordered_co_edges( ref_face_ptr, next_co_edge_list ) == CUBIT_FAILURE ) 01870 return CUBIT_FAILURE; 01871 01872 // Find a coedge on first surface that shares a curve with the next surface 01873 CoEdge *co_edge_ptr; 01874 RefEdge *ref_edge_ptr; 01875 co_edge_list.reset(); 01876 int found = 0; 01877 for( i=co_edge_list.size(); i--; ) 01878 { 01879 co_edge_ptr = co_edge_list.get_and_step(); 01880 ref_edge_ptr = co_edge_ptr->get_ref_edge_ptr(); 01881 if( is_edge_in_list( ref_edge_ptr, next_co_edge_list ) ) 01882 { 01883 found = 1; 01884 break; 01885 } 01886 } 01887 01888 // This should never happen 01889 if( !found ) 01890 { 01891 PRINT_ERROR( "Unable to find curves shared between surfaces\n" ); 01892 return CUBIT_FAILURE; 01893 } 01894 01895 // Loop until we find a curve not shared with the other surface - this 01896 // is the start 01897 for( i=co_edge_list.size(); i--; ) 01898 { 01899 co_edge_ptr = co_edge_list.get_and_step(); 01900 ref_edge_ptr = co_edge_ptr->get_ref_edge_ptr(); 01901 if( !is_edge_in_list( ref_edge_ptr, next_co_edge_list ) ) 01902 { 01903 start_co_edge_ptr = co_edge_ptr; 01904 return CUBIT_SUCCESS; 01905 } 01906 } 01907 01908 // This should never happen 01909 PRINT_ERROR( "Unable to find start of loop - please report this\n" ); 01910 return CUBIT_FAILURE; 01911 } 01912 01913 // isLoop situation 01914 if( refFaceChain.size() == 1 ) 01915 { 01916 // Find first edge that has two coedges on this surface - this is the 01917 // start of the list 01918 refFaceChain.reset(); 01919 ref_face_ptr = refFaceChain.get_and_step(); 01920 01921 DLIList<CoEdge*> co_edge_list; 01922 if( ordered_co_edges( ref_face_ptr, co_edge_list ) == CUBIT_FAILURE ) 01923 return CUBIT_FAILURE; 01924 01925 co_edge_list.reset(); 01926 for( i=0; i<co_edge_list.size(); i++ ) 01927 { 01928 RefEdge *ref_edge_ptr = co_edge_list.get()->get_ref_edge_ptr(); 01929 if( number_coedges( ref_edge_ptr, ref_face_ptr ) == 2 ) 01930 { 01931 if( i==0 ) // Backup until we are at the start 01932 { 01933 for( j=co_edge_list.size(); j--; ) 01934 { 01935 co_edge_list.back(); 01936 ref_edge_ptr = co_edge_list.get()->get_ref_edge_ptr(); 01937 if( number_coedges( ref_edge_ptr, ref_face_ptr ) == 1 ) 01938 break; 01939 co_edge_list.step(); 01940 } 01941 } 01942 break; 01943 } 01944 co_edge_list.step(); 01945 } 01946 01947 start_co_edge_ptr = co_edge_list.get(); 01948 return CUBIT_SUCCESS; 01949 } 01950 01951 if( refFaceChain.size() == 2 ) 01952 { 01953 refFaceChain.reset(); 01954 RefFace *ref_face_ptr1 = refFaceChain.get_and_step(); 01955 RefFace *ref_face_ptr2 = refFaceChain.get(); 01956 CubitBoolean is_loop; // Dummy 01957 return check_for_loop( ref_face_ptr1, ref_face_ptr2, is_loop, start_co_edge_ptr ); 01958 } 01959 01960 // Case refFaceChain.size() > 2 01961 01962 // Use first and last surfaces. Also, adjust order of refFaceChain to 01963 // account for user's selection of start and end vertex, if selected. 01964 refFaceChain.reset(); 01965 RefFace *start_surf = refFaceChain.get_and_back(); 01966 RefFace *end_surf = refFaceChain.get(); 01967 01968 // Get list of coedges for the first surface 01969 DLIList<CoEdge*> start_co_edge_list; 01970 if( ordered_co_edges( start_surf, start_co_edge_list ) == CUBIT_FAILURE ) 01971 return CUBIT_FAILURE; 01972 01973 // Get list of refedges for the last surface 01974 DLIList<RefEdge*> end_ref_edge_list; 01975 DLIList<Loop*> loop_list; 01976 end_surf->ordered_loops( loop_list ); 01977 loop_list.get()->ordered_ref_edges( end_ref_edge_list ); 01978 01979 // Walk around the first surface 01980 RefEdge *ref_edge_ptr; 01981 01982 // First, position the list at a starting coedge - one that is shared with 01983 // the other surface. 01984 start_co_edge_list.reset(); 01985 for( i=0; i<start_co_edge_list.size(); i++ ) 01986 { 01987 ref_edge_ptr = start_co_edge_list.get()->get_ref_edge_ptr(); 01988 01989 if( end_ref_edge_list.is_in_list( ref_edge_ptr ) ) 01990 { 01991 if( i==0 ) // Backup until we are at the start 01992 { 01993 for( j=start_co_edge_list.size(); j--; ) 01994 { 01995 start_co_edge_list.back(); 01996 ref_edge_ptr = start_co_edge_list.get()->get_ref_edge_ptr(); 01997 if( end_ref_edge_list.is_in_list( ref_edge_ptr ) ) 01998 continue; 01999 start_co_edge_list.step(); 02000 } 02001 } 02002 break; 02003 } 02004 start_co_edge_list.step(); 02005 } 02006 02007 // Now the list is positioned at the start of one of the shared chains of 02008 // curves. 02009 start_co_edge_ptr = start_co_edge_list.get(); 02010 02011 return CUBIT_SUCCESS; 02012 } 02013 02014 CubitStatus 02015 SplitSurfaceTool::get_outer_vertices( DLIList<RefVertex*> &ref_vertex_list ) 02016 { 02017 int i; 02018 02019 outerCoEdgeLoop.reset(); 02020 for( i=outerCoEdgeLoop.size(); i--; ) 02021 ref_vertex_list.append( start_vertex( outerCoEdgeLoop.get_and_step() ) ); 02022 02023 return CUBIT_SUCCESS; 02024 } 02025 02026 CubitStatus 02027 SplitSurfaceTool::get_outer_curves( DLIList<RefEdge*> &ref_edge_list ) 02028 { 02029 int i; 02030 02031 outerCoEdgeLoop.reset(); 02032 for( i=outerCoEdgeLoop.size(); i--; ) 02033 ref_edge_list.append( outerCoEdgeLoop.get_and_step()->get_ref_edge_ptr() ); 02034 02035 return CUBIT_SUCCESS; 02036 } 02037 02038 CubitStatus 02039 SplitSurfaceTool::populate_curve_loops() 02040 { 02041 int i; 02042 RefFace *ref_face_ptr; 02043 TDSplitSurface *tdss; 02044 02045 if( refFaceChain.size() == 1 ) 02046 { 02047 ref_face_ptr = refFaceChain.get(); 02048 tdss = (TDSplitSurface *)ref_face_ptr->get_TD(&TDSplitSurface::is_split_surface); 02049 tdss->add_coedges( outerCoEdgeLoop, sideInterval ); 02050 return CUBIT_SUCCESS; 02051 } 02052 02053 // Steps 02054 // 1. Go through each CoEdge on outside, adding TD to each CoEdge 02055 // (with data for the start vertex of the CoEdge), marking them 02056 // per the code in the diagram below. 02057 // 02058 // 6 5 4 02059 // +----+---+ 02060 // | | 02061 // | | 02062 // 7+ +3 02063 // | | 02064 // 7+----+---+3 02065 // | | 02066 // | | 02067 // 7+ +3 02068 // | | 02069 // 7+-+---+--+3 02070 // | | 02071 // | | 02072 // 7+ +3 02073 // | | 02074 // +---+----+ 02075 // 0 1 2 02076 // 02077 // 02078 // 2. Traverse through the curves in each surface, assigning 02079 // curves to proper side of surface utilizing vertex classification 02080 // from above. 02081 02082 // First gather a list of all coedges 02083 DLIList<CoEdge*> all_co_edge_list; 02084 refFaceChain.reset(); 02085 for( i=refFaceChain.size(); i--; ) 02086 { 02087 ref_face_ptr = refFaceChain.get_and_step(); 02088 ordered_co_edges( ref_face_ptr, all_co_edge_list ); 02089 } 02090 02091 refFaceChain.reset(); 02092 RefFace *start_surf = refFaceChain.get(); 02093 refFaceChain.last(); 02094 RefFace *end_surf = refFaceChain.get(); 02095 02096 // STEP 1 02097 CoEdge *co_edge_ptr; 02098 int type = 0; 02099 outerCoEdgeLoop.reset(); 02100 outerCoEdgeLoop.back(); 02101 CoEdge *prev_co_edge_ptr = outerCoEdgeLoop.get_and_step(); 02102 for( i=0; i<outerCoEdgeLoop.size(); i++ ) 02103 { 02104 co_edge_ptr = outerCoEdgeLoop.get_and_step(); 02105 02106 // Get all CoEdges whose start vertices are attached to the start of this 02107 // CoEdge. 02108 DLIList<CoEdge*> att_co_edge_list; 02109 get_attached_coedges_start( co_edge_ptr, all_co_edge_list, att_co_edge_list ); 02110 // This should never happen, but check anyway 02111 if( att_co_edge_list.size() == 0 ) 02112 { 02113 PRINT_ERROR( "Unable to find any curves attached to the start of Curve %d\n", 02114 co_edge_ptr->get_ref_edge_ptr()->id() ); 02115 delete_coedge_tooldatas( all_co_edge_list ); 02116 return CUBIT_FAILURE; 02117 } 02118 02119 // Remove CoEdges from outerCoEdgeLoop 02120 att_co_edge_list -= outerCoEdgeLoop; 02121 02122 // Add back in the current co_edge_ptr 02123 att_co_edge_list.append( co_edge_ptr ); 02124 02125 // Special case - need to remove possible wrong CoEdges. If isLoop remove 02126 // all of the other CoEdges that are on the outerCoEdgeLoop (particularly 02127 // necessary as we traverse up and down the "seam", and at the corners). 02128 // If a corner, we need to deal with a possible triangle there by keeping 02129 // the proper CoEdge. 02130 if( isLoop ) 02131 { 02132 // Find corner number from i 02133 int corner = -1; 02134 if( i == 0 ) 02135 corner = 0; 02136 else if( i == sideInterval[0] ) 02137 corner = 1; 02138 else if( i == sideInterval[0] + sideInterval[1] ) 02139 corner = 2; 02140 else if( i== sideInterval[0] + sideInterval[1] + sideInterval[2] ) 02141 corner = 3; 02142 02143 if( corner != -1 ) 02144 { 02145 // Remove coedges that belong to the other corner shared by this corner 02146 if( remove_other_corner_coedges( prev_co_edge_ptr, co_edge_ptr, 02147 all_co_edge_list, att_co_edge_list ) == CUBIT_FAILURE ) 02148 { 02149 delete_coedge_tooldatas( all_co_edge_list ); 02150 return CUBIT_FAILURE; 02151 } 02152 } 02153 } 02154 02155 // DEBUG 02156 // if( att_co_edge_list.size() > 1 ) 02157 // { 02158 // PRINT_INFO( "Att_co_edge_list.size() = %d\n", att_co_edge_list.size() ); 02159 // att_co_edge_list.reset(); 02160 // for( int k=att_co_edge_list.size(); k--; ) 02161 // PRINT_INFO( " Adding TD to Curve = %d, Surface = %d\n", att_co_edge_list.get()-> 02162 // get_ref_edge_ptr()->id(), att_co_edge_list.get_and_step()->get_ref_face()->id() ); 02163 // } 02164 // else 02165 // PRINT_INFO( " Adding TD to Curve %d on Surface %d\n", 02166 // att_co_edge_list.get()->get_ref_edge_ptr()->id(), 02167 // att_co_edge_list.get()->get_ref_face()->id() ); 02168 02169 switch (type) 02170 { 02171 case 0: 02172 if( add_tooldata( att_co_edge_list, 0 ) == CUBIT_FAILURE ) 02173 { 02174 delete_coedge_tooldatas( all_co_edge_list ); 02175 return CUBIT_FAILURE; 02176 } 02177 if( cornerCoEdge[0] != cornerCoEdge[1] ) 02178 type = 1; 02179 else 02180 type = 3; 02181 break; 02182 case 1: 02183 if( co_edge_ptr != cornerCoEdge[1] ) 02184 { 02185 if( add_tooldata( att_co_edge_list, 1 ) == CUBIT_FAILURE ) 02186 { 02187 delete_coedge_tooldatas( all_co_edge_list ); 02188 return CUBIT_FAILURE; 02189 } 02190 } 02191 else 02192 { 02193 if( add_tooldata( att_co_edge_list, 2 ) == CUBIT_FAILURE ) 02194 { 02195 delete_coedge_tooldatas( all_co_edge_list ); 02196 return CUBIT_FAILURE; 02197 } 02198 if( cornerCoEdge[1] != cornerCoEdge[2] ) 02199 type = 3; 02200 else 02201 type = 5; 02202 } 02203 break; 02204 case 3: 02205 if( co_edge_ptr != cornerCoEdge[2] ) 02206 { 02207 if( add_tooldata( att_co_edge_list, 3 ) == CUBIT_FAILURE ) 02208 { 02209 delete_coedge_tooldatas( all_co_edge_list ); 02210 return CUBIT_FAILURE; 02211 } 02212 } 02213 else 02214 { 02215 if( add_tooldata( att_co_edge_list, 4 ) == CUBIT_FAILURE ) 02216 { 02217 delete_coedge_tooldatas( all_co_edge_list ); 02218 return CUBIT_FAILURE; 02219 } 02220 if( cornerCoEdge[2] != cornerCoEdge[3] ) 02221 type = 5; 02222 else 02223 type = 7; 02224 } 02225 break; 02226 case 5: 02227 if( co_edge_ptr != cornerCoEdge[3] ) 02228 { 02229 if( add_tooldata( att_co_edge_list, 5 ) == CUBIT_FAILURE ) 02230 { 02231 delete_coedge_tooldatas( all_co_edge_list ); 02232 return CUBIT_FAILURE; 02233 } 02234 } 02235 else 02236 { 02237 if( add_tooldata( att_co_edge_list, 6 ) == CUBIT_FAILURE ) 02238 { 02239 delete_coedge_tooldatas( all_co_edge_list ); 02240 return CUBIT_FAILURE; 02241 } 02242 type = 7; 02243 } 02244 break; 02245 case 7: 02246 if( add_tooldata( att_co_edge_list, 7 ) == CUBIT_FAILURE ) 02247 { 02248 delete_coedge_tooldatas( all_co_edge_list ); 02249 return CUBIT_FAILURE; 02250 } 02251 break; 02252 } 02253 02254 prev_co_edge_ptr = co_edge_ptr; 02255 02256 } 02257 02258 // Debug 02259 if( DEBUG_FLAG(154) ) 02260 { 02261 outerCoEdgeLoop.reset(); 02262 for( i=outerCoEdgeLoop.size(); i--; ) 02263 { 02264 co_edge_ptr = outerCoEdgeLoop.get_and_step(); 02265 TDSplitSurface *tdssv = (TDSplitSurface *)co_edge_ptr-> 02266 get_TD(&TDSplitSurface::is_split_surface); 02267 02268 PRINT_INFO( "Vertex %d - type %d\n", start_vertex( co_edge_ptr )->id(), 02269 tdssv->get_type() ); 02270 } 02271 } 02272 02273 // STEP 2 02274 refFaceChain.reset(); 02275 for( i=0; i<refFaceChain.size(); i++ ) 02276 { 02277 ref_face_ptr = refFaceChain.get_and_step(); 02278 tdss = (TDSplitSurface *)ref_face_ptr-> 02279 get_TD(&TDSplitSurface::is_split_surface); 02280 02281 // Get loop of coedges on this surface 02282 DLIList<CoEdge*> co_edge_list; 02283 ordered_co_edges( ref_face_ptr, co_edge_list ); 02284 02285 // Now, get to the start of the loop. This will either be on vertex 0 or 02286 // the last vertex 7 (see diagram above). 02287 position_co_edge_list( i, co_edge_list ); 02288 02289 PRINT_DEBUG_154( "Surface %d: start of loop = curve %d\n", 02290 ref_face_ptr->id(), co_edge_list.get()->get_ref_edge_ptr()->id() ); 02291 02292 // Now that we have the loop positioned properly, we can add the proper 02293 // curves (classified by side) to the TD on the surface. 02294 DLIList<CoEdge*> side_coedges; 02295 int num_so_far = 0; 02296 // Check for special case - side A collapsed - triangle tip at start of 02297 // split 02298 if( ref_face_ptr == start_surf && cornerCoEdge[0] == cornerCoEdge[1] ) 02299 ; 02300 else 02301 get_a_coedges( co_edge_list, side_coedges ); 02302 num_so_far = side_coedges.size(); 02303 02304 // Side A could be collapsed (in case of triangle tip at start of split) 02305 if( side_coedges.size() ) 02306 tdss->add_a_coedges( side_coedges ); 02307 else 02308 tdss->add_a_coedges( side_coedges, start_vertex( cornerCoEdge[0] ) ); 02309 02310 side_coedges.clean_out(); 02311 get_b_coedges( co_edge_list, side_coedges ); 02312 num_so_far += side_coedges.size(); 02313 // Side B could be collapsed (if we are on a triangle) 02314 if( side_coedges.size() ) 02315 tdss->add_b_coedges( side_coedges ); 02316 else 02317 tdss->add_b_coedges( side_coedges, start_vertex( co_edge_list.get() ) ); 02318 02319 side_coedges.clean_out(); 02320 // Check for special case - side C collapsed - triangle tip at end of 02321 // split 02322 if( ref_face_ptr == end_surf && cornerCoEdge[2] == cornerCoEdge[3] ) 02323 ; 02324 else 02325 get_c_coedges( co_edge_list, side_coedges ); 02326 num_so_far += side_coedges.size(); 02327 02328 // Side C could be collapsed (in case of triangle tip at end of split) 02329 if( side_coedges.size() ) 02330 tdss->add_c_coedges( side_coedges ); 02331 else 02332 tdss->add_c_coedges( side_coedges, start_vertex( cornerCoEdge[2] ) ); 02333 02334 side_coedges.clean_out(); 02335 if( get_d_coedges( co_edge_list, num_so_far, 02336 side_coedges ) == CUBIT_FAILURE ) 02337 { 02338 // Remove tooldatas from coedges 02339 delete_coedge_tooldatas( all_co_edge_list ); 02340 return CUBIT_FAILURE; 02341 } 02342 02343 // Side D could be collapsed (if we are on a triangle) 02344 if( side_coedges.size() ) 02345 tdss->add_d_coedges( side_coedges ); 02346 else 02347 tdss->add_d_coedges( side_coedges, start_vertex( co_edge_list.get() ) ); 02348 } 02349 02350 // Remove tooldatas from coedges 02351 delete_coedge_tooldatas( all_co_edge_list ); 02352 02353 return CUBIT_SUCCESS; 02354 } 02355 02356 CubitStatus 02357 SplitSurfaceTool::ordered_co_edges( RefFace *ref_face_ptr, 02358 DLIList<CoEdge*> &co_edge_list ) 02359 { 02360 DLIList<Loop*> loop_list; 02361 ref_face_ptr->ordered_loops( loop_list ); 02362 02363 if( loop_list.size() > 1 ) 02364 { 02365 PRINT_ERROR( "Only surfaces with a single loop are allowed.\n" 02366 " Surface %d has %d loops.\n", ref_face_ptr->id(), 02367 loop_list.size() ); 02368 02369 //if you are splitting a single surface across a vertex pair 02370 //recomment the 'split surface <id> across' command 02371 if( 1 == refFaceChain.size() && 2 == throughVertexList.size() ) 02372 PRINT_INFO("Perhaps try the 'Split Surface <id> Across ...' command instead.\n"); 02373 02374 return CUBIT_FAILURE; 02375 } 02376 02377 if( loop_list.size() == 0 ) 02378 { 02379 PRINT_ERROR( "Surface %d does not contain any loops - cannot split\n", 02380 ref_face_ptr->id() ); 02381 return CUBIT_FAILURE; 02382 } 02383 02384 loop_list.get()->ordered_co_edges( co_edge_list ); 02385 02386 return CUBIT_SUCCESS; 02387 } 02388 02389 CoEdge * 02390 SplitSurfaceTool::get_next_co_edge( CoEdge *prev_co_edge_ptr, 02391 DLIList<CoEdge*> &co_edge_list ) 02392 { 02393 RefVertex *end_vertex_ptr = end_vertex( prev_co_edge_ptr ); 02394 02395 // Find all potential connected coedges 02396 int i; 02397 CoEdge *co_edge_ptr; 02398 DLIList<CoEdge*> connected_co_edge_list; 02399 co_edge_list.reset(); 02400 for( i=co_edge_list.size(); i--; ) 02401 { 02402 co_edge_ptr = co_edge_list.get_and_step(); 02403 if( end_vertex_ptr == start_vertex( co_edge_ptr ) ) 02404 connected_co_edge_list.append( co_edge_ptr ); 02405 } 02406 02407 // We should always have one or two connected coedges - if not error 02408 if( connected_co_edge_list.size() == 0 ) 02409 { 02410 PRINT_ERROR( "Didn't find connected coedge after Curve %d on Surface %d\n", 02411 prev_co_edge_ptr->get_ref_edge_ptr()->id(), 02412 prev_co_edge_ptr->get_ref_face()->id() ); 02413 return NULL; 02414 } 02415 else if( connected_co_edge_list.size() == 1 ) 02416 { 02417 return connected_co_edge_list.get(); 02418 } 02419 else if( connected_co_edge_list.size() > 2 ) 02420 { 02421 PRINT_ERROR( "Found %d coedges after Curve %d on Surface %d\n", 02422 connected_co_edge_list.size(), 02423 prev_co_edge_ptr->get_ref_edge_ptr()->id(), 02424 prev_co_edge_ptr->get_ref_face()->id() ); 02425 return NULL; 02426 } 02427 else if( connected_co_edge_list.size() == 2 ) 02428 { 02429 // Avoid looping back on ourselves 02430 connected_co_edge_list.reset(); 02431 if( prev_co_edge_ptr->get_ref_edge_ptr() == 02432 connected_co_edge_list.get()->get_ref_edge_ptr() ) 02433 return connected_co_edge_list.step_and_get(); 02434 else 02435 return connected_co_edge_list.get(); 02436 } 02437 02438 return NULL; 02439 } 02440 02441 CubitBoolean 02442 SplitSurfaceTool::is_edge_in_list( RefEdge *ref_edge_ptr, DLIList<CoEdge*> &co_edge_list ) 02443 { 02444 int i; 02445 CoEdge *co_edge_ptr; 02446 for( i=co_edge_list.size(); i--; ) 02447 { 02448 co_edge_ptr = co_edge_list.get_and_step(); 02449 if( co_edge_ptr->get_ref_edge_ptr() == ref_edge_ptr ) 02450 return CUBIT_TRUE; 02451 } 02452 return CUBIT_FALSE; 02453 } 02454 02455 RefVertex * 02456 SplitSurfaceTool::start_vertex( CoEdge *co_edge_ptr ) 02457 { 02458 if( co_edge_ptr == NULL ) 02459 return NULL; 02460 02461 RefEdge *ref_edge_ptr = co_edge_ptr->get_ref_edge_ptr(); 02462 02463 if ( co_edge_ptr->get_sense() == CUBIT_REVERSED ) 02464 return ref_edge_ptr->end_vertex(); 02465 else 02466 return ref_edge_ptr->start_vertex(); 02467 } 02468 02469 RefVertex * 02470 SplitSurfaceTool::end_vertex( CoEdge *co_edge_ptr ) 02471 { 02472 if( co_edge_ptr == NULL ) 02473 return NULL; 02474 02475 RefEdge *ref_edge_ptr = co_edge_ptr->get_ref_edge_ptr(); 02476 02477 if ( co_edge_ptr->get_sense() == CUBIT_REVERSED ) 02478 return ref_edge_ptr->start_vertex(); 02479 else 02480 return ref_edge_ptr->end_vertex(); 02481 } 02482 02483 CoEdge * 02484 SplitSurfaceTool::get_complimentary_co_edge( CoEdge *co_edge_ptr, 02485 DLIList<CoEdge*> co_edge_list ) 02486 { 02487 // Note: co_edge_list must be copied so that the calling code's list 02488 // position is not changed. 02489 RefEdge *ref_edge_ptr = co_edge_ptr->get_ref_edge_ptr(); 02490 CoEdge *shared_co_edge_ptr; 02491 int i; 02492 for( i=co_edge_list.size(); i--; ) 02493 { 02494 shared_co_edge_ptr = co_edge_list.get_and_step(); 02495 if( shared_co_edge_ptr == NULL ) 02496 continue; 02497 if( shared_co_edge_ptr == co_edge_ptr ) 02498 continue; 02499 if( shared_co_edge_ptr->get_ref_edge_ptr() == ref_edge_ptr ) 02500 return shared_co_edge_ptr; 02501 } 02502 return NULL; 02503 } 02504 02505 CubitStatus 02506 SplitSurfaceTool::get_attached_coedges_start( CoEdge *co_edge_ptr, 02507 DLIList<CoEdge*> &co_edge_list, 02508 DLIList<CoEdge*> &attached_co_edge_list ) 02509 { 02510 int i; 02511 CoEdge *attached_co_edge_ptr; 02512 02513 RefVertex *start_vertex_ptr; 02514 start_vertex_ptr = start_vertex( co_edge_ptr ); 02515 02516 RefVertex *attached_start_vertex_ptr; 02517 02518 co_edge_list.reset(); 02519 for( i=co_edge_list.size(); i--; ) 02520 { 02521 attached_co_edge_ptr = co_edge_list.get_and_step(); 02522 02523 attached_start_vertex_ptr = start_vertex( attached_co_edge_ptr ); 02524 02525 if( attached_start_vertex_ptr == start_vertex_ptr ) 02526 attached_co_edge_list.append( attached_co_edge_ptr ); 02527 } 02528 02529 return CUBIT_SUCCESS; 02530 } 02531 02532 CubitStatus 02533 SplitSurfaceTool::remove_other_corner_coedges( CoEdge *co_edge_1, 02534 CoEdge *co_edge_2, 02535 DLIList<CoEdge*> &all_co_edge_list, 02536 DLIList<CoEdge*> &att_co_edge_list ) 02537 { 02538 // If only one attached coedge there is nothing to do 02539 if( att_co_edge_list.size() == 1 ) 02540 { 02541 // It should be co_edge_2 02542 if( att_co_edge_list.get() != co_edge_2 ) 02543 { 02544 PRINT_ERROR( "Internal error in split surface function - please report this.\n" ); 02545 PRINT_DEBUG_154( " Function remove_other_coedges.\n" ); 02546 PRINT_DEBUG_154( " Using curves %d and %d on surface %d, got curve %d\n", 02547 co_edge_1->get_ref_edge_ptr()->id(), co_edge_2->get_ref_edge_ptr()->id(), 02548 co_edge_1->get_ref_face()->id(), att_co_edge_list.get()->get_ref_edge_ptr()->id() ); 02549 return CUBIT_FAILURE; 02550 } 02551 return CUBIT_SUCCESS; 02552 } 02553 02554 // If we got this far, there are CoEdges we must examine to determine if they 02555 // belong with this corner or the other corner that shares this vertex. 02556 02557 DLIList<CoEdge*> keep_co_edge_list; 02558 02559 // Always keep co_edge_2 (the tooldata represents the start vertex on this coedge) 02560 keep_co_edge_list.append( co_edge_2 ); 02561 att_co_edge_list.remove( co_edge_2 ); 02562 02563 // Traverse from co_edge_2 02564 DLIList<CoEdge*> keep_co_edge_list2; 02565 int done = 0; 02566 CoEdge *comp_co_edge_ptr = co_edge_2; 02567 CoEdge *co_edge_ptr; 02568 while( !done ) 02569 { 02570 RefFace *ref_face_ptr = comp_co_edge_ptr->get_ref_face(); 02571 DLIList<CoEdge*> co_edge_list; 02572 ordered_co_edges( ref_face_ptr, co_edge_list ); 02573 co_edge_list.move_to( comp_co_edge_ptr ); 02574 co_edge_list.back(); 02575 co_edge_ptr = co_edge_list.get(); 02576 if( co_edge_ptr == co_edge_1 ) 02577 break; 02578 02579 comp_co_edge_ptr = get_complimentary_co_edge( co_edge_ptr, all_co_edge_list ); 02580 02581 keep_co_edge_list2.append( comp_co_edge_ptr ); 02582 02583 // Avoid infinite loop, in case of something we didn't anticipate 02584 if( keep_co_edge_list2.size() > att_co_edge_list.size() ) 02585 { 02586 PRINT_ERROR( "Internal error in split surface function - please report this.\n" ); 02587 PRINT_DEBUG_154( " Function remove_other_coedges #1.\n" ); 02588 return CUBIT_FAILURE; 02589 } 02590 } 02591 02592 int i; 02593 for( i=keep_co_edge_list2.size(); i--; ) 02594 { 02595 co_edge_ptr = keep_co_edge_list2.get_and_step(); 02596 if( !att_co_edge_list.is_in_list( co_edge_ptr ) ) 02597 { 02598 PRINT_ERROR( "Internal error in split surface function - please report this.\n" ); 02599 PRINT_DEBUG_154( " Function remove_other_coedges #2.\n" ); 02600 return CUBIT_FAILURE; 02601 } 02602 } 02603 02604 keep_co_edge_list += keep_co_edge_list2; 02605 02606 att_co_edge_list.clean_out(); 02607 02608 att_co_edge_list = keep_co_edge_list; 02609 02610 return CUBIT_SUCCESS; 02611 } 02612 02613 CubitStatus 02614 SplitSurfaceTool::add_tooldata( DLIList<CoEdge*> &co_edge_list, int vertex_type ) 02615 { 02616 int i; 02617 CoEdge *co_edge_ptr; 02618 for( i=co_edge_list.size(); i--; ) 02619 { 02620 co_edge_ptr = co_edge_list.get_and_step(); 02621 02622 // Something's wrong if we have are trying to put a tooldata on a CoEdge that 02623 // already has one. 02624 if( (TDSplitSurface *)co_edge_ptr->get_TD(&TDSplitSurface::is_split_surface) ) 02625 { 02626 PRINT_ERROR( "Internal error in split surface function - please report this.\n" ); 02627 PRINT_DEBUG_154( " Function add_tooldata.\n" ); 02628 PRINT_DEBUG_154( " Curve = %d on surface %d\n", co_edge_ptr->get_ref_edge_ptr()->id(), 02629 co_edge_ptr->get_ref_face()->id() ); 02630 return CUBIT_FAILURE; 02631 } 02632 02633 co_edge_ptr->add_TD( new TDSplitSurface( vertex_type ) ); 02634 } 02635 return CUBIT_SUCCESS; 02636 } 02637 02638 CubitStatus 02639 SplitSurfaceTool::pick_4_corners() 02640 { 02641 // Special case - for the loop situation the corners are already picked 02642 if( isLoop ) 02643 return CUBIT_SUCCESS; 02644 02645 // Find 4 reasonable corners preferably close to PI/2. We find at least 02646 // 2 corners from the starting surface and 2 from the ending surface. 02647 02648 // Note that at this point, the vertex loop starts at the beginning 02649 // of the first surface in the chain. 02650 02651 // Check for trivial case 02652 if( outerCoEdgeLoop.size() == 4 ) 02653 { 02654 outerCoEdgeLoop.reset(); 02655 cornerCoEdge[0] = outerCoEdgeLoop.get_and_step(); 02656 cornerCoEdge[1] = outerCoEdgeLoop.get_and_step(); 02657 cornerCoEdge[2] = outerCoEdgeLoop.get_and_step(); 02658 cornerCoEdge[3] = outerCoEdgeLoop.get(); 02659 02660 sideInterval[0] = 1; 02661 sideInterval[1] = 1; 02662 sideInterval[2] = 1; 02663 sideInterval[3] = 1; 02664 02665 return CUBIT_SUCCESS; 02666 } 02667 02668 // Initialize variables 02669 refFaceChain.reset(); 02670 RefFace *start_surf = refFaceChain.get(); 02671 refFaceChain.last(); 02672 RefFace *end_surf = refFaceChain.get(); 02673 outerCoEdgeLoop.reset(); 02674 CoEdge *co_edge_ptr; 02675 int A_i=-1, B_i=-1, D_i=-1, E_i=-1; 02676 02677 // Walk along the loop, to find the best corners for the first and last 02678 // surfaces. The leading edge (B) tries to push forward, but the rear (A) 02679 // tries to hang back. Move the lead forward, then check to see if the rear 02680 // should move into it's old spot. 02681 02682 // Note that the outerCoEdgeLoop starts at the first vertex of the starting 02683 // surface (shown after A in this diagram). 02684 // 02685 // Final result for this patch results in corners where the 0's are shown. 02686 02687 // 02688 // E D 02689 // 0-----+-------+------0 02690 // | | | | 02691 // F | | | | 02692 // +------+ | | +------+ 02693 // | | | | ^ 02694 // | End | | Start | | Loop 02695 // | Surface | | Surface | | Direction 02696 // | | | | | 02697 // +------+ | | +------+ 02698 // | | | | C 02699 // | | | | 02700 // 0-----+-------+------0 B 02701 // A 02702 // 02703 02704 double epsilon = .001745; // Angles considered comparable within about .1 degrees. 02705 int offset = 0; 02706 02707 pick_expanded_corners( start_surf, outerCoEdgeLoop, offset, epsilon, A_i, B_i ); 02708 PRINT_DEBUG_154( "First pass picked %d and %d on surf %d\n", 02709 A_i, B_i, start_surf->id() ); 02710 02711 // Advance the vertex and coedge lists until we are on the end_surf 02712 02713 // Special case - if vertices are shared between start and end surface, we 02714 // want the opportunity to use the start vertex on the end surface, even 02715 // though we may have already picked it. We want to consider it again so 02716 // that we can find the best corners on the end surface. Since we will 02717 // always find at least two corners on a surface, if we did not consider 02718 // all vertices on the end surface, we might find a garbage vertex. If 02719 // we do pick up a duplicate, we will clean it out and find the next best 02720 // vertex later. If we did not do this, in the figure below, the first 02721 // pass through pick_expanded corners would find C1 and C2. The next 02722 // pass would find C3 and C4. We don't want C4, but we would pick it 02723 // just because pick_expanded_corners must pick exactly two corners. 02724 // Instead, lets pick C2 and C3 the next time around and pickup the lower 02725 // left corner as a cleanup step later. 02726 // 02727 // C4 02728 // C1 +--------+--------------------+ C3 02729 // | \ | 02730 // | \ | 02731 // | \ end | 02732 // | \ | 02733 // | \ | 02734 // | start \ | 02735 // | \ | 02736 // | \ | 02737 // | \ | 02738 // | \ | 02739 // +--------+--------------------+ C2 02740 02741 // Backup (to consider last vertex again, as explained above) 02742 outerCoEdgeLoop.back(); 02743 offset--; 02744 02745 int i; 02746 for( i=0; i<outerCoEdgeLoop.size(); i++ ) 02747 { 02748 co_edge_ptr = outerCoEdgeLoop.get(); 02749 if( is_vertex_in_surface( start_vertex(co_edge_ptr), end_surf ) ) 02750 break; 02751 02752 offset++; 02753 outerCoEdgeLoop.step(); 02754 } 02755 02756 pick_expanded_corners( end_surf, outerCoEdgeLoop, offset, epsilon, D_i, E_i ); 02757 02758 PRINT_DEBUG_154( "Second pass picked %d and %d on surf %d\n", 02759 D_i, E_i, end_surf->id() ); 02760 02761 if( E_i == outerCoEdgeLoop.size() ) 02762 E_i = 0; 02763 02764 // Error checking 02765 if( A_i==B_i ) 02766 B_i = -1; 02767 if( A_i==D_i ) 02768 D_i = -1; 02769 if( A_i==E_i ) 02770 E_i = -1; 02771 if( B_i==D_i ) 02772 D_i = -1; 02773 if( B_i==E_i ) 02774 E_i = -1; 02775 if( D_i==E_i ) 02776 E_i = -1; 02777 02778 if( A_i==-1 || B_i==-1 || D_i==-1 || E_i==-1 ) 02779 { 02780 // Most likely error case is that we only found three corners. Here 02781 // is an example where this can happen. Notice that the upper left 02782 // corner did not get selected. This is because when processing the 02783 // left surface, the best corners were found that were "expanded out" 02784 // the farthest - thus we missed the "inside" corner. 02785 // 02786 // 02787 // +-----------------------------+ C 02788 // | /| 02789 // | / | 02790 // | / | 02791 // | / | 02792 // | / | 02793 // | / | 02794 // | / | 02795 // | / | 02796 // | / | 02797 // | / | 02798 // C +--------+--------------------+ C 02799 02800 // 02801 // In this case, lets just cop out and find the next best corner(s) 02802 int num = 0; 02803 if( A_i==-1 ) 02804 num++; 02805 if( B_i==-1 ) 02806 num++; 02807 if( D_i==-1 ) 02808 num++; 02809 if( E_i==-1 ) 02810 num++; 02811 02812 if( num>2 ) 02813 { 02814 PRINT_ERROR( "Unable to pick corners - please specify manually.\n" 02815 " Type 'help split surface' for proper syntax\n" ); 02816 return CUBIT_FAILURE; 02817 } 02818 02819 int best_corner_1 = -1, best_corner_2 = -1; 02820 02821 double diff; 02822 double pi2 = CUBIT_PI/2.0; 02823 double min = CUBIT_DBL_MAX; 02824 outerCoEdgeLoop.reset(); 02825 for( i=0; i<outerCoEdgeLoop.size(); i++ ) 02826 { 02827 co_edge_ptr = outerCoEdgeLoop.get(); 02828 02829 if( i==A_i || i==B_i || i==D_i || i==E_i || 02830 (!is_vertex_in_surface( start_vertex(co_edge_ptr), start_surf ) && 02831 !is_vertex_in_surface( start_vertex(co_edge_ptr), end_surf ) ) ) 02832 { 02833 outerCoEdgeLoop.step(); 02834 continue; 02835 } 02836 02837 diff = fabs( pi2 - compute_next_angle( outerCoEdgeLoop ) ); 02838 02839 if( diff < min ) 02840 { 02841 best_corner_1 = i; 02842 min = diff; 02843 } 02844 } 02845 02846 if( best_corner_1 == -1 ) 02847 { 02848 PRINT_ERROR( "Unable to pick corners - please specify manually.\n" 02849 " Type 'help split surface' for proper syntax\n" ); 02850 return CUBIT_FAILURE; 02851 } 02852 02853 if( num>1 ) 02854 { 02855 min = CUBIT_DBL_MAX; 02856 outerCoEdgeLoop.reset(); 02857 for( i=0; i<outerCoEdgeLoop.size(); i++ ) 02858 { 02859 co_edge_ptr = outerCoEdgeLoop.get(); 02860 02861 if( i==A_i || i==B_i || i==D_i || i==E_i || 02862 i==best_corner_1 || 02863 (!is_vertex_in_surface( start_vertex(co_edge_ptr), start_surf ) && 02864 !is_vertex_in_surface( start_vertex(co_edge_ptr), end_surf ) ) ) 02865 { 02866 outerCoEdgeLoop.step(); 02867 continue; 02868 } 02869 02870 diff = fabs( pi2 - compute_next_angle( outerCoEdgeLoop ) ); 02871 02872 if( diff < min ) 02873 { 02874 best_corner_2 = i; 02875 min = diff; 02876 } 02877 } 02878 if( best_corner_2 == -1 ) 02879 { 02880 PRINT_ERROR( "Unable to pick corners - please specify manually.\n" 02881 " Type 'help split surface' for proper syntax\n" ); 02882 return CUBIT_FAILURE; 02883 } 02884 } 02885 02886 int best_corner[6]; 02887 02888 // Find the four corners we have 02889 i = 0; 02890 if( A_i != -1 ) 02891 best_corner[i++] = A_i; 02892 if( B_i != -1 ) 02893 best_corner[i++] = B_i; 02894 if( D_i != -1 ) 02895 best_corner[i++] = D_i; 02896 if( E_i != -1 ) 02897 best_corner[i++] = E_i; 02898 if( best_corner_1 != -1 ) 02899 best_corner[i++] = best_corner_1; 02900 if( best_corner_2 != -1 ) 02901 best_corner[i++] = best_corner_2; 02902 02903 if( i>4 ) 02904 { 02905 PRINT_ERROR( "Internal error in split surface function - please report\n" ); 02906 return CUBIT_FAILURE; 02907 } 02908 02909 order_corners( best_corner[0], best_corner[1], best_corner[2], best_corner[3] ); 02910 02911 A_i = best_corner[0]; 02912 B_i = best_corner[1]; 02913 D_i = best_corner[2]; 02914 E_i = best_corner[3]; 02915 } 02916 02917 // Fill cornerCoEdge array 02918 fill_corners( A_i, B_i, D_i, E_i ); 02919 02920 // Make sure we found at least two vertices on start surf and two vertices 02921 // on end surf 02922 if( !is_vertex_in_surface( start_vertex(cornerCoEdge[0]), start_surf ) || 02923 !is_vertex_in_surface( start_vertex(cornerCoEdge[1]), start_surf ) || 02924 !is_vertex_in_surface( start_vertex(cornerCoEdge[2]), end_surf ) || 02925 !is_vertex_in_surface( start_vertex(cornerCoEdge[3]), end_surf ) ) 02926 { 02927 PRINT_ERROR( "Unable to pick corners - please specify manually.\n" 02928 " Type 'help split surface' for proper syntax\n" ); 02929 return CUBIT_FAILURE; 02930 } 02931 02932 // Fill sideInterval array 02933 fill_side_intervals( A_i, B_i, D_i, E_i ); 02934 02935 // Get loops in proper position (from start) 02936 reorient_loop( A_i ); 02937 02938 if( autoDetectTriangles == CUBIT_TRUE ) 02939 { 02940 // Check to see if any corners are close to 180 and should be removed 02941 // to create a triangle or triangles 02942 if( update_corners_for_triangle() == CUBIT_FAILURE ) 02943 return CUBIT_FAILURE; 02944 } 02945 02946 return CUBIT_SUCCESS; 02947 } 02948 02949 CubitStatus 02950 SplitSurfaceTool::pick_expanded_corners( RefFace *ref_face_ptr, 02951 DLIList<CoEdge*> &co_edge_list, 02952 int &offset, double epsilon, int &A_i, int &B_i ) 02953 { 02954 CoEdge *co_edge_ptr; 02955 double pi2 = CUBIT_PI/2.0; // Target angle (find vertices closest to this) 02956 double A = -1.0, B = -1.0, C; 02957 int old_B_i; 02958 double old_B; 02959 02960 A_i = -1; 02961 B_i = -1; 02962 02963 int initial_offset = offset; 02964 02965 int i; 02966 for( i=0; i<co_edge_list.size(); i++ ) 02967 { 02968 co_edge_ptr = co_edge_list.get(); 02969 02970 // If no longer in the surface we are done 02971 if( !is_vertex_in_surface( start_vertex(co_edge_ptr), ref_face_ptr ) ) 02972 { 02973 A_i += initial_offset; 02974 B_i += initial_offset; 02975 return CUBIT_SUCCESS; 02976 } 02977 02978 // Calculate difference of angle from PI/2. Looking for smaller C as 02979 // compared to previous A & B. This also steps the lists. 02980 C = fabs( pi2 - compute_next_angle( co_edge_list ) ); 02981 02982 if( A == -1.0 ) // Initialization of A 02983 { 02984 A_i = i; 02985 A = C; 02986 } 02987 else if( B == -1.0 ) // Initialization of B 02988 { 02989 B_i = i; 02990 B = C; 02991 } 02992 // Check if B should move forward (it wants to!) 02993 else if( fabs(C - B) < epsilon || C < B ) // C == B || C < B 02994 { // C <= B (effectively) 02995 // Push B forward to C's spot. 02996 old_B = B; 02997 old_B_i = B_i; 02998 B = C; 02999 B_i = i; 03000 03001 // Check if A should move into B's old spot (it doesn't want to!) 03002 if( !(fabs(old_B - A)<epsilon) && old_B < A ) // old_B != A && old_B < A 03003 { // old_B < A (effectively) 03004 // Push A forward to B's old spot 03005 A = old_B; 03006 A_i = old_B_i; 03007 } 03008 } 03009 // Also look for smaller C as compared to A 03010 else if( !(fabs(C - A)<epsilon) && C < A ) // C != A && C < A 03011 { // C < A (effectively) 03012 // Push B forward to C's spot. 03013 old_B = B; 03014 old_B_i = B_i; 03015 B = C; 03016 B_i = i; 03017 03018 // Push A forward to B's old spot 03019 A = old_B; 03020 A_i = old_B_i; 03021 } 03022 offset++; 03023 } 03024 03025 A_i += initial_offset; 03026 B_i += initial_offset; 03027 return CUBIT_SUCCESS; 03028 } 03029 03030 CubitStatus 03031 SplitSurfaceTool::pick_4_corners_simple() 03032 { 03033 // Special case - for the loop situation the corners are already picked 03034 if( isLoop ) 03035 return CUBIT_SUCCESS; 03036 03037 // We simply find the 4 corners closest to PI/2 - used 03038 // when we only have one surface. Results sometimes 03039 // aren't ideal....but user can pick corners in these 03040 // situations. 03041 03042 // Store best quadruple 03043 int best_corner_1, best_corner_2, best_corner_3, best_corner_4; 03044 03045 const int number_vertices = outerCoEdgeLoop.size(); 03046 if( number_vertices == 3 ) 03047 { 03048 // Triangle - special case (default to split to first tip of triangle) 03049 best_corner_1 = 0; 03050 best_corner_2 = 0; 03051 best_corner_3 = 1; 03052 best_corner_4 = 2; 03053 } 03054 else 03055 { 03056 const int num_angles = number_vertices; 03057 03058 // Compute angles 03059 double *angles; 03060 double turn_angle_sum = 0.; 03061 compute_angles( angles, turn_angle_sum ); 03062 03063 // For now just find the 4 vertices that are closest to PI/2 03064 int i; 03065 double diff; 03066 double pi2 = CUBIT_PI/2.0; 03067 double min = CUBIT_DBL_MAX; 03068 for( i=0; i<num_angles; i++ ) 03069 { 03070 diff = fabs( pi2 - angles[i] ); 03071 if( diff < min ) 03072 { 03073 best_corner_1 = i; 03074 min = diff; 03075 } 03076 } 03077 03078 min = CUBIT_DBL_MAX; 03079 for( i=0; i<num_angles; i++ ) 03080 { 03081 diff = fabs( pi2 - angles[i] ); 03082 if( diff < min && i != best_corner_1 ) 03083 { 03084 best_corner_2 = i; 03085 min = diff; 03086 } 03087 } 03088 03089 min = CUBIT_DBL_MAX; 03090 for( i=0; i<num_angles; i++ ) 03091 { 03092 diff = fabs( pi2 - angles[i] ); 03093 if( diff < min && i != best_corner_1 && i != best_corner_2 ) 03094 { 03095 best_corner_3 = i; 03096 min = diff; 03097 } 03098 } 03099 03100 min = CUBIT_DBL_MAX; 03101 for( i=0; i<num_angles; i++ ) 03102 { 03103 diff = fabs( pi2 - angles[i] ); 03104 if( diff < min && i != best_corner_1 && i != best_corner_2 && i != best_corner_3 ) 03105 { 03106 best_corner_4 = i; 03107 min = diff; 03108 } 03109 } 03110 03111 delete [] angles; 03112 03113 order_corners( best_corner_1, best_corner_2, best_corner_3, best_corner_4 ); 03114 } 03115 03116 // Fill cornerCoEdge and sideInterval arrays 03117 fill_corners( best_corner_1, best_corner_2, best_corner_3, best_corner_4 ); 03118 fill_side_intervals( best_corner_1, best_corner_2, best_corner_3, best_corner_4 ); 03119 03120 // Get loops in proper position (from start) 03121 reorient_loop( best_corner_1 ); 03122 03123 if( autoDetectTriangles == CUBIT_TRUE ) 03124 { 03125 // Check to see if any corners are close to 180 and should be removed 03126 // to create a triangle 03127 if( update_corners_for_triangle() == CUBIT_FAILURE ) 03128 return CUBIT_FAILURE; 03129 } 03130 03131 return CUBIT_SUCCESS; 03132 } 03133 03134 CubitStatus 03135 SplitSurfaceTool::update_corners_for_triangle() 03136 { 03137 // Get four angles, in degrees 03138 double angle[4]; 03139 outerCoEdgeLoop.reset(); 03140 angle[0] = 180.0/CUBIT_PI * compute_next_angle( outerCoEdgeLoop ); 03141 outerCoEdgeLoop.step( sideInterval[0]-1 ); 03142 angle[1] = 180.0/CUBIT_PI * compute_next_angle( outerCoEdgeLoop ); 03143 outerCoEdgeLoop.step( sideInterval[1]-1 ); 03144 angle[2] = 180.0/CUBIT_PI * compute_next_angle( outerCoEdgeLoop ); 03145 outerCoEdgeLoop.step( sideInterval[2]-1 ); 03146 angle[3] = 180.0/CUBIT_PI * compute_next_angle( outerCoEdgeLoop ); 03147 03148 if( refFaceChain.size() > 1 ) 03149 { 03150 // If a chain, do for both sides. Check end surface first (otherwise 03151 // arrays could be previously modified when checking the other side) 03152 int corner_to_remove = -1; 03153 int collapsed_corner = -1; 03154 03155 if( fabs(180.0-angle[2])<=sideAngleThreshold && angle[3] <= pointAngleThreshold ) 03156 { 03157 corner_to_remove = 2; 03158 collapsed_corner = 3; 03159 } 03160 else if( fabs(180.0-angle[3])<=sideAngleThreshold && angle[2] <= pointAngleThreshold ) 03161 { 03162 corner_to_remove = 3; 03163 collapsed_corner = 2; 03164 } 03165 03166 if( corner_to_remove != -1 ) 03167 remove_corner( corner_to_remove, collapsed_corner, CUBIT_FALSE ); 03168 03169 // Now check start surface 03170 corner_to_remove = -1; 03171 collapsed_corner = -1; 03172 03173 if( fabs(180.0-angle[0])<=sideAngleThreshold && angle[1] <= pointAngleThreshold ) 03174 { 03175 corner_to_remove = 0; 03176 collapsed_corner = 1; 03177 } 03178 else if( fabs(180.0-angle[1])<=sideAngleThreshold && angle[0] <= pointAngleThreshold ) 03179 { 03180 corner_to_remove = 1; 03181 collapsed_corner = 0; 03182 } 03183 03184 if( corner_to_remove != -1 ) 03185 remove_corner( corner_to_remove, collapsed_corner, CUBIT_TRUE ); 03186 } 03187 else 03188 { 03189 // Determine angle within sideAngleThreshold and closest to 180 03190 double diff = CUBIT_DBL_MAX; 03191 int best_side_corner = -1; 03192 int i; 03193 for( i=0; i<4; i++ ) 03194 { 03195 if( fabs(180.0-angle[i])<=sideAngleThreshold && fabs(180.0-angle[i])<diff ) 03196 { 03197 best_side_corner = i; 03198 diff = fabs(180.0-angle[i]); 03199 } 03200 } 03201 03202 if( best_side_corner == -1 ) 03203 { 03204 //PRINT_INFO( "No angle within criteria above sideAngleThreshold\n" ); 03205 return CUBIT_SUCCESS; 03206 } 03207 03208 //PRINT_INFO( "Best side corner = %d, angle = %f\n", best_side_corner, 03209 // angle[best_side_corner] ); 03210 03211 // Determine angle most below pointAngleThreshold 03212 diff = CUBIT_DBL_MAX; 03213 int best_point_corner = -1; 03214 for( i=0; i<4; i++ ) 03215 { 03216 if( angle[i] <= pointAngleThreshold && (pointAngleThreshold-angle[i]) < diff ) 03217 { 03218 best_point_corner = i; 03219 diff = pointAngleThreshold - angle[i]; 03220 } 03221 } 03222 03223 if( best_point_corner == -1 ) 03224 { 03225 //PRINT_INFO( "No angle within criteria below pointAngleThreshold\n" ); 03226 return CUBIT_SUCCESS; 03227 } 03228 03229 //PRINT_INFO( "Best point corner = %d, angle = %f\n", best_point_corner, 03230 // angle[best_point_corner] ); 03231 03232 if( best_side_corner != -1 && best_point_corner != -1 ) 03233 remove_corner( best_side_corner, best_point_corner, CUBIT_TRUE ); 03234 } 03235 03236 return CUBIT_SUCCESS; 03237 } 03238 03239 CubitStatus 03240 SplitSurfaceTool::remove_corner( int corner_to_remove, int collapsed_corner, 03241 CubitBoolean set_collapsed_first ) 03242 { 03243 // Need to adjust: 03244 // outerCoEdgeLoop 03245 // cornerCoEdge 03246 // sideInterval 03247 03248 // Shuffle the corners so that corner to remove is 2nd corner 03249 switch( corner_to_remove ) 03250 { 03251 case 0: 03252 shuffle_corners_forward(); 03253 shuffle_corners_forward(); 03254 shuffle_corners_forward(); 03255 collapsed_corner += 1; 03256 03257 // Ensure collapsed_corner does not wrap the array (note we could have used 03258 // the remainder function instead, as follows: 03259 // int remainder = 0; 03260 // collapsed_corner = (remainder=collapsed_corner%4) ? remainder : collapsed_corner; 03261 if( collapsed_corner == 4 ) 03262 collapsed_corner = 0; 03263 03264 break; 03265 case 1: 03266 break; 03267 case 2: 03268 shuffle_corners_forward(); 03269 collapsed_corner -= 1; 03270 break; 03271 case 3: 03272 shuffle_corners_forward(); 03273 shuffle_corners_forward(); 03274 collapsed_corner -= 2; 03275 break; 03276 } 03277 03278 if( collapsed_corner < 0 ) 03279 collapsed_corner += 4; 03280 03281 switch( collapsed_corner ) 03282 { 03283 case 0: 03284 sideInterval[1] = sideInterval[0] + sideInterval[1]; 03285 sideInterval[0] = 0; 03286 break; 03287 case 1: 03288 PRINT_ERROR( "Algorithm error in auto-detecting triangle - please report.\n" ); 03289 return CUBIT_FAILURE; 03290 case 2: 03291 sideInterval[0] = sideInterval[0] + sideInterval[1]; 03292 sideInterval[1] = 0; 03293 break; 03294 case 3: 03295 sideInterval[0] = sideInterval[0] + sideInterval[1]; 03296 sideInterval[1] = sideInterval[2]; 03297 sideInterval[2] = 0; 03298 } 03299 03300 // Now redo cornerCoEdge array 03301 outerCoEdgeLoop.reset(); 03302 cornerCoEdge[0] = outerCoEdgeLoop.get(); 03303 outerCoEdgeLoop.step( sideInterval[0] ); 03304 cornerCoEdge[1] = outerCoEdgeLoop.get(); 03305 outerCoEdgeLoop.step( sideInterval[1] ); 03306 cornerCoEdge[2] = outerCoEdgeLoop.get(); 03307 outerCoEdgeLoop.step( sideInterval[2] ); 03308 cornerCoEdge[3] = outerCoEdgeLoop.get(); 03309 03310 if( set_collapsed_first == CUBIT_TRUE ) 03311 { 03312 // Adjust the arrays so that collapsed_corner is at the front 03313 switch( collapsed_corner ) 03314 { 03315 case 2: 03316 shuffle_corners_forward(); 03317 break; 03318 case 3: 03319 shuffle_corners_forward(); 03320 shuffle_corners_forward(); 03321 shuffle_corners_forward(); 03322 } 03323 } 03324 else 03325 { 03326 // Return to original position 03327 switch( corner_to_remove ) 03328 { 03329 case 0: 03330 shuffle_corners_forward(); 03331 break; 03332 case 1: 03333 break; 03334 case 2: 03335 shuffle_corners_forward(); 03336 shuffle_corners_forward(); 03337 shuffle_corners_forward(); 03338 break; 03339 case 3: 03340 shuffle_corners_forward(); 03341 shuffle_corners_forward(); 03342 break; 03343 } 03344 } 03345 03346 return CUBIT_SUCCESS; 03347 } 03348 03349 CubitStatus 03350 SplitSurfaceTool::fill_corners( int best_corner_1, int best_corner_2, 03351 int best_corner_3, int best_corner_4 ) 03352 { 03353 outerCoEdgeLoop.reset(); 03354 outerCoEdgeLoop.step(best_corner_1); 03355 cornerCoEdge[0] = outerCoEdgeLoop.get(); 03356 03357 outerCoEdgeLoop.reset(); 03358 outerCoEdgeLoop.step(best_corner_2); 03359 cornerCoEdge[1] = outerCoEdgeLoop.get(); 03360 03361 outerCoEdgeLoop.reset(); 03362 outerCoEdgeLoop.step(best_corner_3); 03363 cornerCoEdge[2] = outerCoEdgeLoop.get(); 03364 03365 outerCoEdgeLoop.reset(); 03366 outerCoEdgeLoop.step(best_corner_4); 03367 cornerCoEdge[3] = outerCoEdgeLoop.get(); 03368 03369 return CUBIT_SUCCESS; 03370 } 03371 03372 CubitStatus 03373 SplitSurfaceTool::fill_side_intervals( int best_corner_1, int best_corner_2, 03374 int best_corner_3, int best_corner_4 ) 03375 { 03376 sideInterval[0] = best_corner_2 - best_corner_1; 03377 sideInterval[1] = best_corner_3 - best_corner_2; 03378 sideInterval[2] = best_corner_4 - best_corner_3; 03379 sideInterval[3] = best_corner_1 + outerCoEdgeLoop.size() - best_corner_4; 03380 03381 return CUBIT_SUCCESS; 03382 } 03383 03384 CubitStatus 03385 SplitSurfaceTool::compute_angles( double *&angles, double &turn_angle_sum ) 03386 { 03387 const int num_angles = outerCoEdgeLoop.size(); 03388 angles = new double[ num_angles ]; 03389 turn_angle_sum = 0.; 03390 outerCoEdgeLoop.reset(); 03391 int i; 03392 for(i=0; i<num_angles; i++) 03393 { 03394 angles[i] = compute_next_angle( outerCoEdgeLoop ); 03395 //turn_angle_sum += CUBIT_PI - angles[i]; // Not currently used 03396 } 03397 return CUBIT_SUCCESS; 03398 } 03399 03400 double 03401 SplitSurfaceTool::compute_next_angle( DLIList<CoEdge*> &co_edge_list ) 03402 { 03403 CoEdge *co_edge_1 = co_edge_list.prev(); 03404 CoEdge *co_edge_2 = co_edge_list.get_and_step(); 03405 03406 // Coordinates of common point 03407 CubitVector vertex_point = start_vertex( co_edge_2 )->coordinates(); 03408 03409 // Find normal to the the face at the common vertex 03410 RefFace *ref_face1 = co_edge_1->get_ref_face(); 03411 CubitVector normal1 = ref_face1->normal_at(vertex_point, NULL); 03412 03413 RefFace *ref_face2 = co_edge_2->get_ref_face(); 03414 CubitVector normal2 = ref_face2->normal_at(vertex_point, NULL); 03415 03416 CubitVector normal = (normal1 + normal2)/2; // Average 03417 03418 // Find directed tangents to determine interior angle 03419 // Use sense of edge with respect to this face's loop. 03420 CubitVector tangent_1, tangent_2; 03421 co_edge_1->get_ref_edge_ptr()->tangent( vertex_point, tangent_1 ); 03422 co_edge_2->get_ref_edge_ptr()->tangent( vertex_point, tangent_2 ); 03423 03424 if ( co_edge_1->get_sense() == CUBIT_REVERSED ) 03425 tangent_1 = -tangent_1; 03426 if ( co_edge_2->get_sense() == CUBIT_REVERSED ) 03427 tangent_2 = -tangent_2; 03428 03429 // At this point we have the tangents going in the correct loop 03430 // sense. 03431 // Now get tangent pointing away from the center for the correct 03432 // angle 03433 tangent_1 = -tangent_1; 03434 03435 // Return angle from given tangents and normal to face 03436 double angle = normal.vector_angle( tangent_2, tangent_1 ); 03437 03438 PRINT_DEBUG_154( " Angle at vertex %d = %f\n", start_vertex( co_edge_2 )->id(), 03439 angle*180.0/CUBIT_PI ); 03440 return angle; 03441 } 03442 03443 void 03444 SplitSurfaceTool::order_corners( int &corner_1, int &corner_2, 03445 int &corner_3, int &corner_4 ) 03446 { 03447 // sort the corners by indices 03448 int swap_temp; 03449 #define SWAP( a, b ) swap_temp = (a); (a) = (b); (b) = swap_temp 03450 if ( corner_1 > corner_2 ) { 03451 SWAP( corner_1, corner_2 ); 03452 } 03453 if ( corner_2 > corner_3 ) { 03454 SWAP( corner_2, corner_3 ); 03455 } 03456 if ( corner_3 > corner_4 ) { 03457 SWAP( corner_3, corner_4 ); 03458 } 03459 // 4 is now set 03460 order_corners( corner_1, corner_2, corner_3 ); 03461 #undef SWAP 03462 } 03463 03464 void 03465 SplitSurfaceTool::order_corners( int &corner_1, int &corner_2, 03466 int &corner_3 ) 03467 { 03468 // sort the corners by indices 03469 int swap_temp; 03470 #define SWAP( a, b ) swap_temp = (a); (a) = (b); (b) = swap_temp 03471 if ( corner_1 > corner_2 ) { 03472 SWAP( corner_1, corner_2 ); 03473 } 03474 if ( corner_2 > corner_3 ) { 03475 SWAP( corner_2, corner_3 ); 03476 } 03477 // 3 is now set 03478 if ( corner_1 > corner_2 ) { 03479 SWAP( corner_1, corner_2 ); 03480 } 03481 // 2 is now set 03482 // 1 is set as its the only one left 03483 #undef SWAP 03484 } 03485 03486 CubitStatus 03487 SplitSurfaceTool::order_selected_corners( DLIList<RefVertex*> &corner_vertex_list ) 03488 { 03489 int i; 03490 03491 RefVertex *ref_vertex_ptr; 03492 CoEdge *co_edge_ptr; 03493 03494 // Verify that these corners exist in the outerCoEdgeLoop 03495 for( i = corner_vertex_list.size(); i--; ) 03496 { 03497 ref_vertex_ptr = corner_vertex_list.get_and_step(); 03498 03499 if( is_in_outer_loop( ref_vertex_ptr ) == CUBIT_FALSE ) 03500 { 03501 PRINT_ERROR( "Selected corner, Vertex %d, not found in outer loop of patch.\n", 03502 ref_vertex_ptr->id() ); 03503 return CUBIT_FAILURE; 03504 } 03505 } 03506 03507 // We need to start at the first corner the user selected - shuffle the 03508 // lists to do this. 03509 corner_vertex_list.reset(); 03510 RefVertex *start_corner = corner_vertex_list.get(); 03511 03512 int offset = 0; 03513 outerCoEdgeLoop.reset(); 03514 for( i=outerCoEdgeLoop.size(); i--; ) 03515 { 03516 ref_vertex_ptr = start_vertex( outerCoEdgeLoop.get_and_step() ); 03517 if( ref_vertex_ptr == start_corner ) 03518 break; 03519 offset++; 03520 } 03521 03522 // Now shuffle the lists to get them into the proper order 03523 if( offset ) 03524 { 03525 outerCoEdgeLoop.reset(); 03526 DLIList<CoEdge*> outer_co_edge_loop = outerCoEdgeLoop; 03527 03528 outerCoEdgeLoop.clean_out(); 03529 03530 outer_co_edge_loop.reset(); 03531 03532 // Set the loop at start offset 03533 outer_co_edge_loop.step( offset ); 03534 for( i=outer_co_edge_loop.size(); i--; ) 03535 { 03536 outerCoEdgeLoop.append( outer_co_edge_loop.get_and_step() ); 03537 } 03538 } 03539 03540 // Cruise through the outer coedge list to get the proper corner order 03541 int corner = 0; 03542 int num = 0; 03543 int side_interval = 0; 03544 outerCoEdgeLoop.reset(); 03545 03546 co_edge_ptr = outerCoEdgeLoop.get_and_step(); 03547 03548 // Special case for first corner (always at first corner to start) 03549 num = number_in_list( corner_vertex_list, start_vertex(co_edge_ptr) ); 03550 if( num > 2 ) 03551 { 03552 PRINT_ERROR( "Vertex %d was selected for %d of the corners - max is 2\n", 03553 start_vertex(co_edge_ptr)->id(), num ); 03554 return CUBIT_FAILURE; 03555 } 03556 03557 cornerCoEdge[corner++] = co_edge_ptr; 03558 if( num == 2 ) 03559 { 03560 sideInterval[corner-1] = 0; 03561 cornerCoEdge[corner++] = co_edge_ptr; 03562 } 03563 03564 for( i=1; i<outerCoEdgeLoop.size(); i++ ) 03565 { 03566 co_edge_ptr = outerCoEdgeLoop.get_and_step(); 03567 side_interval++; 03568 03569 num = number_in_list( corner_vertex_list, start_vertex(co_edge_ptr) ); 03570 if( num > 2 ) 03571 { 03572 PRINT_ERROR( "Vertex %d was selected for %d of the corners - max is 2\n", 03573 start_vertex(co_edge_ptr)->id(), num ); 03574 return CUBIT_FAILURE; 03575 } 03576 03577 if( num > 0 ) 03578 { 03579 sideInterval[corner-1] = side_interval; 03580 side_interval = 0; 03581 cornerCoEdge[corner++] = co_edge_ptr; 03582 03583 if( num == 2 ) 03584 { 03585 sideInterval[corner-1] = 0; 03586 cornerCoEdge[corner++] = co_edge_ptr; 03587 } 03588 } 03589 } 03590 03591 sideInterval[3] = outerCoEdgeLoop.size() - sideInterval[0] - sideInterval[1] - sideInterval[2]; 03592 03593 return CUBIT_SUCCESS; 03594 } 03595 03596 int 03597 SplitSurfaceTool::number_in_list( DLIList<RefVertex*> &corner_vertex_list, 03598 RefVertex *ref_vertex_ptr ) 03599 { 03600 int num = 0; 03601 int i; 03602 corner_vertex_list.reset(); 03603 RefVertex *check_ptr; 03604 for( i=4; i--; ) 03605 { 03606 check_ptr = corner_vertex_list.get_and_step(); 03607 if( check_ptr == ref_vertex_ptr ) 03608 num++; 03609 } 03610 03611 return num; 03612 } 03613 03614 CubitBoolean 03615 SplitSurfaceTool::is_in_outer_loop( RefVertex *ref_vertex_ptr ) 03616 { 03617 int i; 03618 outerCoEdgeLoop.reset(); 03619 03620 for( i=outerCoEdgeLoop.size(); i--; ) 03621 { 03622 if( ref_vertex_ptr == start_vertex( outerCoEdgeLoop.get_and_step() ) ) 03623 return CUBIT_TRUE; 03624 } 03625 return CUBIT_FALSE; 03626 } 03627 03628 CubitStatus 03629 SplitSurfaceTool::adjust_for_split_direction( RefEdge *curve_dir_ptr, 03630 RefEdge *from_curve_ptr, 03631 DLIList<RefVertex*> &corner_vertex_list ) 03632 { 03633 // Adjust the loops to the split direction. The split direction is 03634 // determined as follows: 03635 // 1) For multiple surfaces - always across the chain. 03636 // 03637 // split direction 03638 // c2 <--------> c1 03639 // +---------+-----------+-----------+ 03640 // | | | | 03641 // |_ _ _ |_ _ _ _ | _ _ _ _| 03642 // | | split | |side 0 03643 // | | | | 03644 // +---------+-----------+-----------+ 03645 // c3 side 3 c0 03646 // 03647 // 2) If a "from" curve is specfied, put the "from" curve on 03648 // side 3, so that the fraction and distance goes from the 03649 // right side. 03650 03651 03652 // For single surfaces, the logic is a little more tricky: 03653 // 1) From optional "direction" curve given by user (parallel to split) 03654 // 2) From optional "from" curve given by user (parallel to split) 03655 // 3) From optional through vertex list given by user. 03656 // 4) From optional corner vertices given by user, if given in a 03657 // sensible order (ie., not criss-crossed). Split direction 03658 // will be perpendicular to the side from first to second 03659 // selected corner (ie., perpendicular to c0-c1 in the 03660 // diagram below). 03661 // 5) From aspect ratio of patch - split along "skinny" direction. 03662 03663 // split direction 03664 // c2 <--------> c1 03665 // +-------------------------------+ 03666 // | | 03667 // |_ _ _ _ _ _ _ _ _ _ _| 03668 // | split | 03669 // | | 03670 // +-------------------------------+ 03671 // c3 c0 03672 // 03673 // In all cases check for incompatible inputs (i.e., conflicting 03674 // "direction" and "from" curves, conflicting "through" vertices 03675 // on single surfaces, etc.) 03676 03677 corner_vertex_list.reset(); 03678 03679 if( refFaceChain.size() > 1 && corner_vertex_list.size() ) 03680 { 03681 refFaceChain.reset(); 03682 RefFace *start_surf = refFaceChain.get(); 03683 refFaceChain.last(); 03684 RefFace *end_surf = refFaceChain.get(); 03685 03686 // We might have to shuffle the selected corners to orient them to split 03687 // across the surfaces. To be valid, we must have the two starting 03688 // corners in the start surface and the two ending corners in the end 03689 // surface. Shuffle the corners until this condition is met. If 03690 // we shuffle three times and the condition is still not met, we have 03691 // been given invalid vertices. 03692 // 03693 // Here is a case we must be able to handle, with corners specified 03694 // as shown. We must shuffle three times. 03695 03696 // C3 C2 03697 // +-----+------------------+ 03698 // |\ \ | 03699 // | \ \ | 03700 // | \ \ end | 03701 // | \ \ | 03702 // | \ \ | 03703 // | \ \ | 03704 // | \ \ | 03705 // | \ \ | 03706 // | \ \ | 03707 // | start \ \ | 03708 // | \ \ | 03709 // | \\| 03710 // +------------------------+ 03711 // C0 C1 03712 03713 if( !is_vertex_in_surface( start_vertex(cornerCoEdge[0]), start_surf ) || 03714 !is_vertex_in_surface( start_vertex(cornerCoEdge[1]), start_surf ) || 03715 !is_vertex_in_surface( start_vertex(cornerCoEdge[2]), end_surf ) || 03716 !is_vertex_in_surface( start_vertex(cornerCoEdge[3]), end_surf ) ) 03717 { 03718 shuffle_corners_forward(); 03719 if( !is_vertex_in_surface( start_vertex(cornerCoEdge[0]), start_surf ) || 03720 !is_vertex_in_surface( start_vertex(cornerCoEdge[1]), start_surf ) || 03721 !is_vertex_in_surface( start_vertex(cornerCoEdge[2]), end_surf ) || 03722 !is_vertex_in_surface( start_vertex(cornerCoEdge[3]), end_surf ) ) 03723 { 03724 shuffle_corners_forward(); 03725 if( !is_vertex_in_surface( start_vertex(cornerCoEdge[0]), start_surf ) || 03726 !is_vertex_in_surface( start_vertex(cornerCoEdge[1]), start_surf ) || 03727 !is_vertex_in_surface( start_vertex(cornerCoEdge[2]), end_surf ) || 03728 !is_vertex_in_surface( start_vertex(cornerCoEdge[3]), end_surf ) ) 03729 { 03730 shuffle_corners_forward(); 03731 if( !is_vertex_in_surface( start_vertex(cornerCoEdge[0]), start_surf ) || 03732 !is_vertex_in_surface( start_vertex(cornerCoEdge[1]), start_surf ) || 03733 !is_vertex_in_surface( start_vertex(cornerCoEdge[2]), end_surf ) || 03734 !is_vertex_in_surface( start_vertex(cornerCoEdge[3]), end_surf ) ) 03735 { 03736 PRINT_ERROR( "Selected vertices are invalid. Two vertices must be on\n" 03737 " start surface and two on end surface of chain.\n" ); 03738 return CUBIT_FAILURE; 03739 } 03740 } 03741 } 03742 } 03743 } 03744 if( refFaceChain.size() > 1 ) 03745 { 03746 if( curve_dir_ptr ) 03747 { 03748 // Check for rare case with two triangles - that case allows a switch in 03749 // direction 03750 if( is_chain_two_triangles() ) 03751 { 03752 if( is_curve_on_side( curve_dir_ptr, 0 ) || 03753 is_curve_on_side( curve_dir_ptr, 2 ) ) 03754 { 03755 shuffle_corners_forward(); 03756 } 03757 03758 if( throughVertexList.size() > 2 ) 03759 { 03760 PRINT_ERROR( "For two triangle case, you can only specify 2 'through' vertices.\n" ); 03761 return CUBIT_FAILURE; 03762 } 03763 03764 // Make sure through vertices (if any) are on side 0 or 2 03765 if( check_through_vertices( "'direction'" ) == CUBIT_FAILURE ) 03766 return CUBIT_FAILURE; 03767 } 03768 else 03769 PRINT_WARNING( "Curve direction ignored - not necessary for a chain of surfaces.\n" ); 03770 } 03771 03772 // Flip sides if user selected a from curve 03773 if( from_curve_ptr ) 03774 { 03775 // Check for rare case with two triangles - that case allows a switch in 03776 // direction 03777 if( is_chain_two_triangles() ) 03778 { 03779 if( is_curve_on_side( from_curve_ptr, 0 ) || 03780 is_curve_on_side( from_curve_ptr, 2 ) ) 03781 { 03782 if( curve_dir_ptr ) 03783 { 03784 PRINT_ERROR( "From curve must be parallel to direction of split.\n" ); 03785 return CUBIT_FAILURE; 03786 } 03787 else 03788 shuffle_corners_forward(); 03789 } 03790 03791 // Next two checks are redundant if a direction was specified, but that 03792 // doesn't hurt anything. 03793 if( throughVertexList.size() > 2 ) 03794 { 03795 PRINT_ERROR( "For two triangle case, you can only specify 2 'through' vertices.\n" ); 03796 return CUBIT_FAILURE; 03797 } 03798 03799 // Make sure through vertices (if any) are on side 0 or 2 03800 if( check_through_vertices( "'from'" ) == CUBIT_FAILURE ) 03801 return CUBIT_FAILURE; 03802 } 03803 else 03804 { 03805 // Make sure this curve is on side 3 03806 if( is_curve_on_side( from_curve_ptr, 0 ) || 03807 is_curve_on_side( from_curve_ptr, 2 ) ) 03808 { 03809 PRINT_ERROR( "From curve must be parallel to direction of split.\n" ); 03810 return CUBIT_FAILURE; 03811 } 03812 if( is_curve_on_side( from_curve_ptr, 1 ) ) 03813 { 03814 shuffle_corners_forward(); 03815 shuffle_corners_forward(); 03816 } 03817 } 03818 } 03819 return CUBIT_SUCCESS; 03820 } 03821 else 03822 // SINGLE surface 03823 { 03824 // Special case for triangle 03825 if( is_triangle() && (curve_dir_ptr || from_curve_ptr ) ) 03826 { 03827 // For a triangle, curve_dir_ptr and from_curve_ptr mean the same 03828 // thing. Do a check. 03829 if( curve_dir_ptr && from_curve_ptr && (from_curve_ptr != curve_dir_ptr) ) 03830 { 03831 PRINT_ERROR( "For triangle case, specifying both a 'direction' and 'from'\n" 03832 " curve is redundant - these have the same meaning.\n" ); 03833 return CUBIT_FAILURE; 03834 } 03835 03836 if( from_curve_ptr && !curve_dir_ptr ) 03837 curve_dir_ptr = from_curve_ptr; 03838 03839 // Desired state: 0 interval side opposite the side that curve_dir_ptr 03840 // is on. Then ensure that side past selected curve is side 0. A 03841 // tricky bit of logic! 03842 03843 // Start out by setting zero side to side 0 03844 if( sideInterval[1] == 0 ) 03845 { 03846 shuffle_corners_forward(); 03847 } 03848 else if (sideInterval[2] == 0 ) 03849 { 03850 shuffle_corners_forward(); 03851 shuffle_corners_forward(); 03852 } 03853 else if( sideInterval[3] == 0 ) 03854 { 03855 shuffle_corners_forward(); 03856 shuffle_corners_forward(); 03857 shuffle_corners_forward(); 03858 } 03859 03860 // Move zero side and ensure that side past selected curve is side 0. 03861 if( is_curve_on_side( curve_dir_ptr, 1 ) ) 03862 { 03863 // Zero side should be 3 03864 shuffle_zero_side_forward(); 03865 shuffle_zero_side_forward(); 03866 03867 shuffle_corners_forward(); 03868 } 03869 else if( is_curve_on_side( curve_dir_ptr, 2 ) ) 03870 { 03871 shuffle_corners_forward(); 03872 shuffle_corners_forward(); 03873 shuffle_corners_forward(); 03874 } 03875 else if( is_curve_on_side( curve_dir_ptr, 3 ) ) 03876 { 03877 shuffle_zero_side_forward(); 03878 } 03879 03880 // Check through vertices to make sure they are valid 03881 if( check_through_vertices( "'direction'" ) == CUBIT_FAILURE ) 03882 return CUBIT_FAILURE; 03883 03884 return CUBIT_SUCCESS; 03885 } 03886 else if( curve_dir_ptr ) 03887 { 03888 // Curve should be on side 1 or 3 - otherwise adjust the loops forward 03889 if( is_curve_on_side( curve_dir_ptr, 0 ) ) 03890 shuffle_corners_forward(); 03891 else if( is_curve_on_side( curve_dir_ptr, 2 ) ) 03892 shuffle_corners_forward(); 03893 03894 // Now check if there is a from curve too, along with curve direction 03895 if( from_curve_ptr ) 03896 { 03897 if( is_curve_on_side( from_curve_ptr, 0 ) || 03898 is_curve_on_side( from_curve_ptr, 2 ) ) 03899 { 03900 PRINT_ERROR( "'Direction' and 'From' curves must be on same or opposite\n" 03901 " sides of logical rectangle\n" ); 03902 return CUBIT_FAILURE; 03903 } 03904 // Must be on side 3 03905 if( is_curve_on_side( from_curve_ptr, 1 ) ) 03906 { 03907 shuffle_corners_forward(); 03908 shuffle_corners_forward(); 03909 } 03910 } 03911 03912 // Check through vertices to make sure they are valid 03913 if( check_through_vertices( "'direction'" ) == CUBIT_FAILURE ) 03914 return CUBIT_FAILURE; 03915 03916 return CUBIT_SUCCESS; 03917 } 03918 03919 // Single surface WITHOUT a direction given 03920 if( from_curve_ptr ) 03921 { 03922 // Curve should be on side 3 - otherwise adjust the loops forward 03923 if( is_curve_on_side( from_curve_ptr, 2 ) ) 03924 { 03925 shuffle_corners_forward(); 03926 shuffle_corners_forward(); 03927 shuffle_corners_forward(); 03928 } 03929 else if( is_curve_on_side( from_curve_ptr, 1 ) ) 03930 { 03931 shuffle_corners_forward(); 03932 shuffle_corners_forward(); 03933 } 03934 else if( is_curve_on_side( from_curve_ptr, 0 ) ) 03935 shuffle_corners_forward(); 03936 03937 // Check through vertices to make sure they are valid 03938 if( check_through_vertices( "'from'" ) == CUBIT_FAILURE ) 03939 return CUBIT_FAILURE; 03940 03941 return CUBIT_SUCCESS; 03942 } 03943 03944 // Single surface WITHOUT a 'direction' or 'from' curve given - if through 03945 // vertices let them determine the split direction. 03946 if( throughVertexList.size() > 2 ) 03947 { 03948 PRINT_ERROR( "For a single surface, you can only specify 2 'through' vertices.\n" ); 03949 return CUBIT_FAILURE; 03950 } 03951 03952 RefVertex *start_vertex_ptr = NULL; 03953 RefVertex *end_vertex_ptr = NULL; 03954 throughVertexList.reset(); 03955 if( throughVertexList.size() > 0 ) 03956 start_vertex_ptr = throughVertexList.get_and_step(); 03957 if( throughVertexList.size() > 1 ) 03958 end_vertex_ptr = throughVertexList.get(); 03959 03960 // First check for start and end vertices 03961 if( start_vertex_ptr || end_vertex_ptr ) 03962 { 03963 if( start_vertex_ptr ) 03964 { 03965 // Check if on side A 03966 if( !is_vertex_on_side( start_vertex_ptr, 0 ) ) 03967 { 03968 // Shuffle forward and check again 03969 shuffle_corners_forward(); 03970 if( !is_vertex_on_side( start_vertex_ptr, 0 ) ) 03971 { 03972 // Shuffle forward and check again 03973 shuffle_corners_forward(); 03974 if( !is_vertex_on_side( start_vertex_ptr, 0 ) ) 03975 { 03976 // Shuffle forward and check again 03977 shuffle_corners_forward(); 03978 if( !is_vertex_on_side( start_vertex_ptr, 0 ) ) 03979 { 03980 PRINT_ERROR( "Specified 'through' vertex %d is not valid\n", 03981 start_vertex_ptr->id() ); 03982 return CUBIT_FAILURE; 03983 } 03984 } 03985 } 03986 } 03987 } 03988 if( end_vertex_ptr ) 03989 { 03990 // Check if on side C 03991 if( !is_vertex_on_side( end_vertex_ptr, 2 ) ) 03992 { 03993 // Shuffle forward and check again 03994 shuffle_corners_forward(); 03995 if( !is_vertex_on_side( end_vertex_ptr, 2 ) ) 03996 { 03997 // Shuffle forward and check again 03998 shuffle_corners_forward(); 03999 if( !is_vertex_on_side( end_vertex_ptr, 2 ) ) 04000 { 04001 // Shuffle forward and check again 04002 shuffle_corners_forward(); 04003 if( !is_vertex_on_side( end_vertex_ptr, 2 ) ) 04004 { 04005 PRINT_ERROR( "Specified 'through' vertex %d is not valid\n", 04006 end_vertex_ptr->id() ); 04007 return CUBIT_FAILURE; 04008 } 04009 } 04010 } 04011 } 04012 } 04013 if( start_vertex_ptr && end_vertex_ptr ) 04014 { 04015 if( !is_vertex_on_side( start_vertex_ptr, 0 ) || 04016 !is_vertex_on_side( end_vertex_ptr, 2 ) ) 04017 { 04018 PRINT_ERROR( "Specified 'through' vertices invalid - both not on split path.\n" ); 04019 return CUBIT_FAILURE; 04020 } 04021 } 04022 04023 return CUBIT_SUCCESS; 04024 04025 } 04026 04027 // If second corner is 1 or 3, use the direction implied. Otherwise, 04028 // user gave corners in a criss-crossed manner and we can't gain any 04029 // implied direction from them. 04030 else if( corner_vertex_list.size() && 04031 corner_vertex_list.step_and_get() == start_vertex( cornerCoEdge[1]) ) 04032 return CUBIT_SUCCESS; 04033 else if( corner_vertex_list.size() && 04034 corner_vertex_list.get() == start_vertex( cornerCoEdge[3]) ) 04035 ; 04036 else 04037 { 04038 // We use aspect ratio to determine split direction. Split along 04039 // narrowest direction. 04040 04041 // Skip if we have a triangle 04042 if( is_triangle() ) 04043 return CUBIT_SUCCESS; 04044 04045 double len0 = get_side_length( 0 ); 04046 double len1 = get_side_length( 1 ); 04047 double len2 = get_side_length( 2 ); 04048 double len3 = get_side_length( 3 ); 04049 04050 double ratio = (len0+len2) / (len1+len3); 04051 PRINT_DEBUG_154( "Ratio = %f\n", ratio ); 04052 04053 if( ratio < 1.0001 ) 04054 return CUBIT_SUCCESS; 04055 else 04056 PRINT_DEBUG_154( "Ratio deems we adjust forward\n" ); 04057 } 04058 04059 // If we got this far, we need to adjust the split direction - move 04060 // loops forward by sideInterval[0] (start at corner 1) 04061 shuffle_corners_forward(); 04062 } 04063 04064 return CUBIT_SUCCESS; 04065 } 04066 04067 CubitBoolean 04068 SplitSurfaceTool::is_chain_two_triangles() 04069 { 04070 if( refFaceChain.size() != 2 ) 04071 return CUBIT_FALSE; 04072 04073 // C3-0-1-2 C2-3-0-1 04074 // +------------------------+ 04075 // |\ | 04076 // | \ | 04077 // | \ end | 04078 // | \ | 04079 // | \ | 04080 // | \ | 04081 // | \ | 04082 // | \ | 04083 // | \ | 04084 // | start \ | 04085 // | \ | 04086 // | \ | 04087 // +------------------------+ 04088 // C0-1-2-3 C1-2-3-0 04089 04090 // 4 possibilities (see diagram above - corners 0-1-2-3 or 1-2-3-0 etc 04091 // going ccw from bottom left) 04092 04093 CoEdge *c0 = cornerCoEdge[0]; 04094 CoEdge *c1 = cornerCoEdge[1]; 04095 CoEdge *c2 = cornerCoEdge[2]; 04096 CoEdge *c3 = cornerCoEdge[3]; 04097 04098 if( (prev_co_edge(c0)->get_ref_face() == c0->get_ref_face() && 04099 prev_co_edge(c1)->get_ref_face() != c1->get_ref_face() && 04100 prev_co_edge(c2)->get_ref_face() == c2->get_ref_face() && 04101 prev_co_edge(c3)->get_ref_face() != c3->get_ref_face() ) || 04102 04103 (prev_co_edge(c1)->get_ref_face() == c1->get_ref_face() && 04104 prev_co_edge(c2)->get_ref_face() != c2->get_ref_face() && 04105 prev_co_edge(c3)->get_ref_face() == c3->get_ref_face() && 04106 prev_co_edge(c0)->get_ref_face() != c0->get_ref_face() ) ) 04107 { 04108 // 2-triangle case 04109 return CUBIT_TRUE; 04110 } 04111 04112 return CUBIT_FALSE; 04113 } 04114 04115 CubitBoolean 04116 SplitSurfaceTool::is_triangle() 04117 { 04118 if( sideInterval[0]==0 || sideInterval[1]==0 || 04119 sideInterval[2]==0 || sideInterval[3]==0 ) 04120 return CUBIT_TRUE; 04121 else 04122 return CUBIT_FALSE; 04123 } 04124 04125 CubitStatus 04126 SplitSurfaceTool::check_through_vertices( const char *type ) 04127 { 04128 if( throughVertexList.size() ) 04129 { 04130 RefVertex *start_vertex_ptr = NULL; 04131 RefVertex *end_vertex_ptr = NULL; 04132 throughVertexList.reset(); 04133 start_vertex_ptr = throughVertexList.get_and_step(); 04134 if( throughVertexList.size() > 1 ) 04135 end_vertex_ptr = throughVertexList.get(); 04136 04137 if( start_vertex_ptr ) 04138 { 04139 if( is_vertex_on_side( start_vertex_ptr, 0 ) || 04140 is_vertex_on_side( start_vertex_ptr, 2 ) ) 04141 ; 04142 else 04143 { 04144 if( throughVertexList.size() == 1 ) 04145 PRINT_ERROR( "Through vertice(s) not compatible with %s curve given\n", 04146 type ); 04147 else 04148 PRINT_ERROR( "Through vertices not compatible with %s curve given\n", 04149 type); 04150 return CUBIT_FAILURE; 04151 } 04152 } 04153 if( end_vertex_ptr ) 04154 { 04155 if( is_vertex_on_side( end_vertex_ptr, 0 ) || 04156 is_vertex_on_side( end_vertex_ptr, 2 ) ) 04157 ; 04158 else 04159 { 04160 PRINT_ERROR( "%s", "Through vertices not compatible with %s curve given\n" ); 04161 return CUBIT_FAILURE; 04162 } 04163 } 04164 } 04165 return CUBIT_SUCCESS; 04166 } 04167 04168 CoEdge * 04169 SplitSurfaceTool::prev_co_edge( CoEdge *co_edge_ptr ) 04170 { 04171 outerCoEdgeLoop.move_to( co_edge_ptr ); 04172 return outerCoEdgeLoop.prev(); 04173 } 04174 04175 double 04176 SplitSurfaceTool::get_side_length( int side ) 04177 { 04178 int i; 04179 RefEdge *ref_edge_ptr; 04180 double length = 0.0; 04181 outerCoEdgeLoop.reset(); 04182 switch( side ) 04183 { 04184 case 0: 04185 for( i=sideInterval[0]; i--; ) 04186 { 04187 ref_edge_ptr = outerCoEdgeLoop.get_and_step()->get_ref_edge_ptr(); 04188 length += ref_edge_ptr->measure(); 04189 } 04190 break; 04191 04192 case 1: 04193 outerCoEdgeLoop.step( sideInterval[0] ); 04194 for( i=sideInterval[1]; i--; ) 04195 { 04196 ref_edge_ptr = outerCoEdgeLoop.get_and_step()->get_ref_edge_ptr(); 04197 length += ref_edge_ptr->measure(); 04198 } 04199 break; 04200 04201 case 2: 04202 04203 outerCoEdgeLoop.step( sideInterval[0]+sideInterval[1] ); 04204 for( i=sideInterval[2]; i--; ) 04205 { 04206 ref_edge_ptr = outerCoEdgeLoop.get_and_step()->get_ref_edge_ptr(); 04207 length += ref_edge_ptr->measure(); 04208 } 04209 break; 04210 04211 case 3: 04212 04213 outerCoEdgeLoop.step( sideInterval[0]+sideInterval[1]+sideInterval[2] ); 04214 for( i=sideInterval[3]; i--; ) 04215 { 04216 ref_edge_ptr = outerCoEdgeLoop.get_and_step()->get_ref_edge_ptr(); 04217 length += ref_edge_ptr->measure(); 04218 } 04219 break; 04220 } 04221 04222 return length; 04223 } 04224 04225 CubitStatus 04226 SplitSurfaceTool::reorient_loop( int start_offset ) 04227 { 04228 if( start_offset == 0 ) 04229 return CUBIT_SUCCESS; 04230 04231 DLIList<CoEdge*> outer_co_edge_loop( outerCoEdgeLoop.size() ); 04232 04233 outerCoEdgeLoop.reset(); 04234 outerCoEdgeLoop.step( start_offset ); 04235 04236 int i; 04237 for( i=outerCoEdgeLoop.size(); i--; ) 04238 outer_co_edge_loop.append( outerCoEdgeLoop.get_and_step() ); 04239 04240 outerCoEdgeLoop.clean_out(); 04241 04242 outer_co_edge_loop.reset(); 04243 04244 outerCoEdgeLoop = outer_co_edge_loop; 04245 04246 return CUBIT_SUCCESS; 04247 } 04248 04249 CubitStatus 04250 SplitSurfaceTool::shuffle_corners_forward() 04251 { 04252 // Simply move loops forward by sideInterval[0] (start at corner 1) 04253 reorient_loop( sideInterval[0] ); 04254 04255 // Shuffle sideInterval and cornerCoEdge too 04256 int side_interval_temp = sideInterval[0]; 04257 sideInterval[0] = sideInterval[1]; 04258 sideInterval[1] = sideInterval[2]; 04259 sideInterval[2] = sideInterval[3]; 04260 sideInterval[3] = side_interval_temp; 04261 04262 CoEdge *corner_coedge_temp = cornerCoEdge[0]; 04263 cornerCoEdge[0] = cornerCoEdge[1]; 04264 cornerCoEdge[1] = cornerCoEdge[2]; 04265 cornerCoEdge[2] = cornerCoEdge[3]; 04266 cornerCoEdge[3] = corner_coedge_temp; 04267 04268 return CUBIT_SUCCESS; 04269 } 04270 04271 CubitStatus 04272 SplitSurfaceTool::shuffle_zero_side_forward() 04273 { 04274 if( sideInterval[0] == 0 ) 04275 { 04276 cornerCoEdge[1] = cornerCoEdge[2]; 04277 sideInterval[0] = sideInterval[1]; 04278 sideInterval[1] = 0; 04279 } 04280 else if( sideInterval[1] == 0 ) 04281 { 04282 cornerCoEdge[2] = cornerCoEdge[3]; 04283 sideInterval[1] = sideInterval[2]; 04284 sideInterval[2] = 0; 04285 } 04286 else if( sideInterval[2] == 0 ) 04287 { 04288 cornerCoEdge[3] = cornerCoEdge[0]; 04289 sideInterval[2] = sideInterval[3]; 04290 sideInterval[3] = 0; 04291 } 04292 else if( sideInterval[3] == 0 ) 04293 { 04294 cornerCoEdge[0] = cornerCoEdge[1]; 04295 sideInterval[3] = sideInterval[0]; 04296 sideInterval[0] = 0; 04297 } 04298 return CUBIT_SUCCESS; 04299 } 04300 04301 CubitBoolean 04302 SplitSurfaceTool::is_vertex_on_side( RefVertex *ref_vertex_ptr, int side ) 04303 { 04304 // Note this will return CUBIT_TRUE if the input vertex is on one of the 04305 // specified corners. 04306 04307 // Position outerCoEdge loop to start of corner (note switch statement 04308 // falls through - case 3 will step 3 times). 04309 outerCoEdgeLoop.reset(); 04310 switch( side ) 04311 { 04312 case 3: 04313 outerCoEdgeLoop.step( sideInterval[2] ); 04314 case 2: 04315 outerCoEdgeLoop.step( sideInterval[1] ); 04316 case 1: 04317 outerCoEdgeLoop.step( sideInterval[0] ); 04318 } 04319 04320 CoEdge *co_edge_ptr = outerCoEdgeLoop.get(); 04321 CubitVector ref_coords = ref_vertex_ptr->coordinates(); 04322 04323 if( sideInterval[side] == 0 ) 04324 { 04325 // Compare coordinates 04326 RefVertex *start_vertex_ptr = start_vertex( co_edge_ptr ); 04327 if( start_vertex_ptr == ref_vertex_ptr ) 04328 return CUBIT_TRUE; 04329 if( ref_coords.about_equal( start_vertex_ptr->coordinates() ) ) 04330 return CUBIT_TRUE; 04331 else 04332 return CUBIT_FALSE; 04333 } 04334 04335 // Check if it is on each coedge 04336 CubitPointContainment pnt_containment; 04337 int i; 04338 for( i=sideInterval[side]; i--; ) 04339 { 04340 co_edge_ptr = outerCoEdgeLoop.get_and_step(); 04341 pnt_containment = co_edge_ptr->get_ref_edge_ptr()-> 04342 point_containment( ref_coords ); 04343 if( pnt_containment == CUBIT_PNT_ON ) 04344 return CUBIT_TRUE; 04345 } 04346 04347 return CUBIT_FALSE; 04348 } 04349 04350 CubitBoolean 04351 SplitSurfaceTool::is_vertex_in_surface( RefVertex *ref_vertex_ptr, 04352 RefFace *ref_face_ptr ) 04353 { 04354 // Base on finding RefFaces since there will typically be fewer RefFaces 04355 // to search than RefVertices 04356 DLIList<RefFace*> ref_face_list; 04357 ref_vertex_ptr->ref_faces( ref_face_list ); 04358 return ref_face_list.is_in_list( ref_face_ptr ); 04359 } 04360 04361 CubitBoolean 04362 SplitSurfaceTool::is_curve_in_outer_loop( RefEdge *ref_edge_ptr ) 04363 { 04364 outerCoEdgeLoop.reset(); 04365 int i; 04366 for( i=outerCoEdgeLoop.size(); i--; ) 04367 { 04368 if( ref_edge_ptr == outerCoEdgeLoop.get_and_step()->get_ref_edge_ptr() ) 04369 return CUBIT_TRUE; 04370 } 04371 return CUBIT_FALSE; 04372 } 04373 04374 CubitBoolean 04375 SplitSurfaceTool::is_curve_on_side( RefEdge *ref_edge_ptr, int side ) 04376 { 04377 if( sideInterval[side] == 0 ) 04378 return CUBIT_FALSE; 04379 04380 // Position outerCoEdge loop to start of corner (note switch statement 04381 // falls through - case 3 will step 3 times). 04382 outerCoEdgeLoop.reset(); 04383 switch( side ) 04384 { 04385 case 3: 04386 outerCoEdgeLoop.step( sideInterval[2] ); 04387 case 2: 04388 outerCoEdgeLoop.step( sideInterval[1] ); 04389 case 1: 04390 outerCoEdgeLoop.step( sideInterval[0] ); 04391 } 04392 04393 // Compare against each coedge on the given side 04394 int i; 04395 for( i=sideInterval[side]; i--; ) 04396 { 04397 if( ref_edge_ptr == outerCoEdgeLoop.get_and_step()->get_ref_edge_ptr() ) 04398 return CUBIT_TRUE; 04399 } 04400 04401 return CUBIT_FALSE; 04402 } 04403 04404 CubitStatus 04405 SplitSurfaceTool::position_co_edge_list( int i, DLIList<CoEdge*> &co_edge_list ) 04406 { 04407 // 6 5 4 04408 // +----+---+ 04409 // | | 04410 // | | 04411 // 7+ +3 04412 // | | 04413 // 7+----+---+3 04414 // | | 04415 // | | 04416 // 7+ +3 04417 // | | 04418 // 7+-+---+--+3 04419 // | | 04420 // | | 04421 // 7+ +3 04422 // | | 04423 // +---+----+ 04424 // 0 1 2 04425 // Now, get to the start of the loop. This will either be on vertex 0 or 04426 // the last vertex 7 (see diagram above). 04427 04428 CoEdge *co_edge_ptr; 04429 CoEdge *next_co_edge_ptr; 04430 co_edge_list.reset(); 04431 for( i=co_edge_list.size(); i--; ) 04432 { 04433 co_edge_ptr = co_edge_list.get_and_step(); 04434 next_co_edge_ptr = co_edge_list.get_and_back(); 04435 04436 // Get the tooldata from the start vertex 04437 TDSplitSurface *tdssv_start = (TDSplitSurface *)co_edge_ptr-> 04438 get_TD(&TDSplitSurface::is_split_surface); 04439 04440 if( tdssv_start ) 04441 { 04442 if( tdssv_start->get_type() == 0 ) 04443 break; // This is the start 04444 else if (tdssv_start->get_type() == 7) 04445 { 04446 // Check end of curve - if not a 7 or 0 we are done 04447 TDSplitSurface *tdssv_end = (TDSplitSurface *)next_co_edge_ptr-> 04448 get_TD(&TDSplitSurface::is_split_surface); 04449 if( !tdssv_end ) 04450 break; 04451 if( tdssv_end->get_type() != 7 && tdssv_end->get_type() != 0 ) 04452 break; 04453 } 04454 else if (tdssv_start->get_type() == 6) 04455 { 04456 // Check end of curve - if not a 7 or 0 we are done 04457 // (it will typically be NULL or type 3 - see top surface 04458 // in diagram below) 04459 // 04460 // 6 5 4 04461 // +---+----+ 04462 // | \ | 04463 // | \ | 04464 // | + | 04465 // | \| 04466 // 7+-+---+--+3 04467 // | | 04468 // | | 04469 // 7+ +3 04470 // | | 04471 // +---+----+ 04472 // 0 1 2 04473 04474 TDSplitSurface *tdssv_end = (TDSplitSurface *)next_co_edge_ptr-> 04475 get_TD(&TDSplitSurface::is_split_surface); 04476 if( !tdssv_end ) 04477 break; 04478 if( tdssv_end->get_type() != 7 && tdssv_end->get_type() != 0 ) 04479 break; 04480 } 04481 } 04482 co_edge_list.step(); 04483 } 04484 04485 return CUBIT_SUCCESS; 04486 } 04487 04488 CubitStatus 04489 SplitSurfaceTool::get_a_coedges( DLIList<CoEdge*> &co_edge_list, 04490 DLIList<CoEdge*> &a_coedges ) 04491 { 04492 // Get all curves until end vertex type = 2 or 3 or 4 (3 or 4 in case of triangle) 04493 int i; 04494 CoEdge *co_edge_ptr; 04495 CoEdge *next_co_edge_ptr; 04496 for( i=co_edge_list.size(); i--; ) 04497 { 04498 co_edge_ptr = co_edge_list.get_and_step(); 04499 a_coedges.append( co_edge_ptr ); 04500 04501 next_co_edge_ptr = co_edge_list.get(); 04502 04503 // Get the tooldata from the next coedge (need value on end vertex of 04504 // first coedge). 04505 TDSplitSurface *tdss = (TDSplitSurface *)next_co_edge_ptr-> 04506 get_TD(&TDSplitSurface::is_split_surface); 04507 04508 if( !tdss ) 04509 continue; 04510 04511 if( tdss->get_type() == 2 || tdss->get_type() == 3 04512 || tdss->get_type() == 4 ) 04513 break; 04514 } 04515 return CUBIT_SUCCESS; 04516 } 04517 04518 CubitStatus 04519 SplitSurfaceTool::get_b_coedges( DLIList<CoEdge*> &co_edge_list, 04520 DLIList<CoEdge*> &b_coedges ) 04521 { 04522 // Keep getting curves as long as end vertex type = 3 or 4 (stop at 4) 04523 int i; 04524 CoEdge *co_edge_ptr; 04525 CoEdge *next_co_edge_ptr; 04526 for( i=co_edge_list.size(); i--; ) 04527 { 04528 co_edge_ptr = co_edge_list.get_and_step(); 04529 next_co_edge_ptr = co_edge_list.get_and_back(); 04530 04531 // Get the tooldata from the end vertex 04532 TDSplitSurface *tdss = (TDSplitSurface *)next_co_edge_ptr-> 04533 get_TD(&TDSplitSurface::is_split_surface); 04534 04535 if( !tdss ) 04536 return CUBIT_SUCCESS; 04537 04538 if( tdss->get_type() == 4 ) 04539 { 04540 b_coedges.append( co_edge_ptr ); 04541 co_edge_list.step(); 04542 return CUBIT_SUCCESS; 04543 } 04544 04545 if( tdss->get_type() == 3 ) 04546 { 04547 b_coedges.append( co_edge_ptr ); 04548 co_edge_list.step(); 04549 continue; 04550 } 04551 04552 return CUBIT_SUCCESS; 04553 } 04554 return CUBIT_SUCCESS; 04555 } 04556 04557 CubitStatus 04558 SplitSurfaceTool::get_c_coedges( DLIList<CoEdge*> &co_edge_list, 04559 DLIList<CoEdge*> &c_coedges ) 04560 { 04561 // Keep getting curves until end vertex type = 6 or 7 or 0 (for triangle) 04562 int i; 04563 CoEdge *co_edge_ptr; 04564 CoEdge *next_co_edge_ptr; 04565 for( i=co_edge_list.size(); i--; ) 04566 { 04567 co_edge_ptr = co_edge_list.get_and_step(); 04568 next_co_edge_ptr = co_edge_list.get_and_back(); 04569 04570 // Get the tooldata from the end vertex 04571 TDSplitSurface *tdss = (TDSplitSurface *)next_co_edge_ptr-> 04572 get_TD(&TDSplitSurface::is_split_surface); 04573 04574 if( !tdss ) 04575 { 04576 c_coedges.append( co_edge_ptr ); 04577 co_edge_list.step(); 04578 continue; 04579 } 04580 04581 if( tdss->get_type() == 6 || tdss->get_type() == 7 || 04582 tdss->get_type() == 0 ) 04583 { 04584 c_coedges.append( co_edge_ptr ); 04585 co_edge_list.step(); 04586 return CUBIT_SUCCESS; 04587 } 04588 04589 c_coedges.append( co_edge_ptr ); 04590 co_edge_list.step(); 04591 04592 } 04593 return CUBIT_SUCCESS; 04594 } 04595 04596 CubitStatus 04597 SplitSurfaceTool::get_d_coedges( DLIList<CoEdge*> &co_edge_list, 04598 int num_so_far, DLIList<CoEdge*> &d_coedges ) 04599 { 04600 // Get remaining curves 04601 if( co_edge_list.size() == num_so_far ) 04602 return CUBIT_SUCCESS; 04603 04604 if( num_so_far > co_edge_list.size() ) 04605 { 04606 PRINT_ERROR( "Unexpected error in algorithm; aborting.\n" ); 04607 PRINT_DEBUG_154( " Surface = %d, num_so_far = %d\n", 04608 co_edge_list.get()->get_ref_face()->id(), num_so_far ); 04609 return CUBIT_FAILURE; 04610 } 04611 04612 int i; 04613 CoEdge *co_edge_ptr; 04614 for( i=co_edge_list.size()-num_so_far; i--; ) 04615 { 04616 co_edge_ptr = co_edge_list.get_and_step(); 04617 d_coedges.append( co_edge_ptr ); 04618 } 04619 04620 return CUBIT_SUCCESS; 04621 } 04622 04623 void 04624 SplitSurfaceTool::list_sides_debug() 04625 { 04626 if( !DEBUG_FLAG(154) ) 04627 return; 04628 04629 int i, j; 04630 RefFace *ref_face_ptr; 04631 TDSplitSurface *tdss; 04632 04633 refFaceChain.reset(); 04634 for( i=refFaceChain.size(); i--; ) 04635 { 04636 ref_face_ptr = refFaceChain.get_and_step(); 04637 tdss = (TDSplitSurface *)ref_face_ptr-> 04638 get_TD(&TDSplitSurface::is_split_surface); 04639 04640 PRINT_INFO( "Surface %d:\n", ref_face_ptr->id() ); 04641 04642 DLIList<CoEdge*> *side_co_edge_list; 04643 side_co_edge_list = tdss->get_a_coedges(); 04644 DLIList<RefEdge*> side_ref_edge_list; 04645 side_co_edge_list->reset(); 04646 for( j=side_co_edge_list->size(); j--; ) 04647 side_ref_edge_list.append( side_co_edge_list->get_and_step()->get_ref_edge_ptr() ); 04648 04649 DLIList<CubitEntity*> cubit_edges; 04650 CAST_LIST(side_ref_edge_list, cubit_edges, CubitEntity); 04651 CubitUtil::list_entity_ids( "Side 0: ", 04652 cubit_edges, 80, "\n", CUBIT_FALSE ); 04653 04654 side_co_edge_list = tdss->get_b_coedges(); 04655 side_ref_edge_list.clean_out(); 04656 side_co_edge_list->reset(); 04657 for( j=side_co_edge_list->size(); j--; ) 04658 side_ref_edge_list.append( side_co_edge_list->get_and_step()->get_ref_edge_ptr() ); 04659 04660 CAST_LIST(side_ref_edge_list, cubit_edges, CubitEntity); 04661 CubitUtil::list_entity_ids( "Side 1: ", 04662 cubit_edges, 80, "\n", CUBIT_FALSE ); 04663 04664 side_co_edge_list = tdss->get_c_coedges(); 04665 side_ref_edge_list.clean_out(); 04666 side_co_edge_list->reset(); 04667 for( j=side_co_edge_list->size(); j--; ) 04668 side_ref_edge_list.append( side_co_edge_list->get_and_step()->get_ref_edge_ptr() ); 04669 04670 CAST_LIST(side_ref_edge_list, cubit_edges, CubitEntity); 04671 CubitUtil::list_entity_ids( "Side 2: ", 04672 cubit_edges, 80, "\n", CUBIT_FALSE ); 04673 04674 side_co_edge_list = tdss->get_d_coedges(); 04675 side_ref_edge_list.clean_out(); 04676 side_co_edge_list->reset(); 04677 for( j=side_co_edge_list->size(); j--; ) 04678 side_ref_edge_list.append( side_co_edge_list->get_and_step()->get_ref_edge_ptr() ); 04679 04680 CAST_LIST(side_ref_edge_list, cubit_edges, CubitEntity); 04681 CubitUtil::list_entity_ids( "Side 3: ", 04682 cubit_edges, 80, "\n", CUBIT_FALSE ); 04683 } 04684 } 04685 04686 CubitStatus 04687 SplitSurfaceTool::find_spline_curves( RefFace *ref_face_ptr, int num_segs, 04688 double distance, 04689 DLIList<Curve*> *curve_list_ptr, 04690 double tolerance, 04691 CubitBoolean parametric_flg, 04692 CubitBoolean preview_flg, 04693 CubitBoolean create_ref_edges_flg ) 04694 { 04695 int i, j; 04696 04697 TDSplitSurface *tdss = (TDSplitSurface *)ref_face_ptr-> 04698 get_TD(&TDSplitSurface::is_split_surface); 04699 04700 TopologyBridge* bridge = 0; 04701 // GeometryModifyEngine* gme = 04702 GeometryModifyTool::instance()->get_engine( ref_face_ptr, &bridge ); 04703 Surface* surf_ptr = dynamic_cast<Surface*>(bridge); 04704 04705 // Interpolate to find the spline points 04706 // 04707 // sideC 04708 // a[nr-1][i] 04709 // _________________________________________ 04710 // (0,1)| |(1,1) 04711 // | | 04712 // | | 04713 // | | 04714 // | | 04715 // | | 04716 // a[j][0] | | 04717 // | | a[j][nc-1] 04718 // sideD | | 04719 // | ada (row) | sideB 04720 // | ^ | 04721 // | | | 04722 // | | (tse,ada) | 04723 // | | | 04724 // | +----->tse (column) | 04725 // (0,0)|_________________________________________|(1,0) 04726 // a[0][i] 04727 // sideA 04728 04729 // Split direction is vertical in the above diagram. 04730 04731 if( ref_face_ptr->is_parametric() && parametric_flg==CUBIT_TRUE ) 04732 { 04733 PRINT_DEBUG_154( "Using 2D mapping to find interior points\n" ); 04734 // Do the mapping in parametric space - we have found this is 04735 // more accurate (especially since we don't have the benefit of 04736 // any elemental smoothing when we are done). However, we have 04737 // also found that occasionally, especially on conic surfaces, 04738 // the mapping will create points in the wrong space of the 04739 // surface (i.e., on the "other side".). For this reason we 04740 // default to 3D mapping. 04741 // Allocate a matrix of CubitVector pointers 04742 int nr = tdss->coord_list_size_b(); // number of rows 04743 int nc = num_segs+1; // number of columns 04744 Cubit2DPoint ***coords; 04745 coords = new Cubit2DPoint **[nr]; 04746 04747 for( j=0; j<nr; j++ ) 04748 coords[j] = new Cubit2DPoint *[nc]; 04749 04750 // Initialize 04751 for( i=0; i<nr; i++ ) 04752 { 04753 for( j=0; j<nc; j++ ) 04754 coords[i][j] = NULL; 04755 } 04756 04757 // Fill the boundary coordinates into coords 04758 fill_boundary_coords( tdss, nr, nc, coords ); 04759 04760 // Fill the interior coords 04761 fill_interior_coords( tdss, nr, nc, coords ); 04762 04763 // Generate the 3D vectors 04764 CubitVector vec; 04765 04766 for( j=1; j<nc-1; j++ ) 04767 { 04768 DLIList<CubitVector*> spline_points; 04769 for( i=0; i<nr; i++ ) 04770 { 04771 vec = ref_face_ptr->position_from_u_v( coords[i][j]->x(), coords[i][j]->y() ); 04772 spline_points.append( new CubitVector( vec ) ); 04773 } 04774 04775 // Create the curve from the vectors 04776 CubitBoolean project_curve = CUBIT_TRUE; 04777 if( preview_flg == CUBIT_TRUE && create_ref_edges_flg == CUBIT_FALSE ) 04778 project_curve = CUBIT_FALSE; 04779 Curve *curve_ptr = create_curve( spline_points, surf_ptr, tolerance, 04780 CUBIT_TRUE, preview_flg, project_curve ); 04781 04782 // Free spline points 04783 while( spline_points.size() ) delete spline_points.pop(); 04784 04785 if( curve_ptr == NULL ) 04786 { 04787 // Just fail if a curve can't be created 04788 PRINT_ERROR( "Unable to create curve on Surface %d\n", ref_face_ptr->id() ); 04789 while( curve_list_ptr->size() ) delete curve_list_ptr->pop(); 04790 return CUBIT_FAILURE; 04791 } 04792 else 04793 { 04794 curve_list_ptr->append( curve_ptr ); 04795 } 04796 } 04797 04798 // Free memory - all of the Cubit2DPoints were allocated 04799 for( i=0; i<nr; i++ ) 04800 { 04801 for( j=0; j<nc; j++ ) 04802 delete coords[i][j]; 04803 } 04804 04805 // Free matrix memory 04806 for( i=0; i<nr; i++ ) 04807 delete []coords[i]; 04808 delete []coords; 04809 coords = NULL; 04810 } 04811 else 04812 { 04813 // Need to do the mapping in 3D space and project back to surface 04814 PRINT_DEBUG_154( "Using 3D mapping to find interior points\n" ); 04815 04816 // Allocate a matrix of CubitVector pointers 04817 int nr = tdss->coord_list_size_b(); // number of rows 04818 int nc = num_segs+1; // number of columns 04819 CubitVector ***coords; 04820 coords = new CubitVector **[nr]; 04821 04822 for( i=0; i<nr; i++ ) 04823 coords[i] = new CubitVector *[nc]; 04824 04825 // Initialize 04826 for( i=0; i<nr; i++ ) 04827 { 04828 for( j=0; j<nc; j++ ) 04829 coords[i][j] = NULL; 04830 } 04831 04832 // Fill the boundary coordinates into coords 04833 fill_boundary_coords( tdss, nr, nc, coords ); 04834 04835 // Fill the interior coords 04836 fill_interior_coords( tdss, nr, nc, coords ); 04837 04838 // Smooth the 3D points (note - don't check result - the function only gives 04839 // a warning if it fails). 04840 smooth_interior_coords( ref_face_ptr, tdss, tolerance, nr, nc, distance, coords ); 04841 04842 // Create split curves 04843 for( j=1; j<nc-1; j++ ) 04844 { 04845 DLIList<CubitVector*> spline_points; 04846 for( i=0; i<nr; i++ ) 04847 { 04848 ref_face_ptr->move_to_surface( *(coords[i][j]) ); 04849 spline_points.append( new CubitVector( *(coords[i][j]) ) ); 04850 } 04851 04852 // Create the curve from the vectors 04853 CubitBoolean project_curve = CUBIT_TRUE; 04854 if( preview_flg == CUBIT_TRUE && create_ref_edges_flg == CUBIT_FALSE ) 04855 project_curve = CUBIT_FALSE; 04856 Curve *curve_ptr = create_curve( spline_points, surf_ptr, tolerance, 04857 CUBIT_TRUE, preview_flg, project_curve ); 04858 04859 // Free spline points 04860 while( spline_points.size() ) delete spline_points.pop(); 04861 04862 if( curve_ptr == NULL ) 04863 { 04864 // Just fail if a curve can't be created 04865 PRINT_ERROR( "Unable to create curve on Surface %d\n", ref_face_ptr->id() ); 04866 while( curve_list_ptr->size() ) delete curve_list_ptr->pop(); 04867 return CUBIT_FAILURE; 04868 } 04869 else 04870 curve_list_ptr->append( curve_ptr ); 04871 } 04872 04873 // Free interior points (the boundary locations were not allocated for 04874 // the matrix) 04875 for( i=1; i<nr-1; i++ ) 04876 { 04877 for( j=1; j<nc-1; j++ ) 04878 delete coords[i][j]; 04879 } 04880 04881 // Free matrix memory 04882 for( i=0; i<nr; i++ ) 04883 delete []coords[i]; 04884 delete []coords; 04885 coords = NULL; 04886 } 04887 04888 return CUBIT_SUCCESS; 04889 } 04890 04891 CubitStatus 04892 SplitSurfaceTool::fill_boundary_coords( TDSplitSurface *tdss, int nr, 04893 int nc, CubitVector ***coords ) 04894 { 04895 // sideC 04896 // coords[nr-1][c] 04897 // _________________________________________ 04898 // (0,1)| |(1,1) 04899 // | | 04900 // | | 04901 // | | 04902 // | | 04903 // | | 04904 // coords[r][0] | | 04905 // | | coords[r][nc-1] 04906 // sideD | | 04907 // | ada (row) | sideB 04908 // | ^ | 04909 // | | | 04910 // | | (tse,ada) | 04911 // | | | 04912 // | +----->tse (column) | 04913 // (0,0)|_________________________________________|(1,0) 04914 // coords[0][c] 04915 // sideA 04916 04917 // Split direction is vertical in the above diagram. 04918 04919 // Debug (with DEBUG_FLAG_154) 04920 draw_boundary_coords( tdss ); 04921 04922 int r, c; 04923 04924 // Note: sideB and sideD contain the corner coords (sideA and sideC just 04925 // contain the interior coords) 04926 tdss->coord_list_reset_a(); 04927 tdss->coord_list_reset_b(); 04928 tdss->coord_list_last_c(); // Will need to be traversed backwards 04929 tdss->coord_list_last_d(); // Will need to be traversed backwards 04930 04931 for( r=0; r<nr; r++ ) 04932 { 04933 // Rows go up B and D (note these contain the corner coords) 04934 coords[r][0] = tdss->coord_list_get_and_back_d(); 04935 coords[r][nc-1] = tdss->coord_list_get_and_step_b(); 04936 } 04937 04938 for( c=1; c<nc-1; c++ ) 04939 { 04940 // Columns go up A and C (note these DO NOT contain the corner coords) 04941 coords[0][c] = tdss->coord_list_get_and_step_a(); 04942 coords[nr-1][c] = tdss->coord_list_get_and_back_c(); 04943 } 04944 04945 return CUBIT_SUCCESS; 04946 } 04947 04948 // Debug function 04949 CubitStatus 04950 SplitSurfaceTool::draw_boundary_coords( TDSplitSurface *tdss ) 04951 { 04952 if( !DEBUG_FLAG(154) ) 04953 return CUBIT_SUCCESS; 04954 04955 int i; 04956 CubitVector *vec_ptr; 04957 CoEdge *co_edge_ptr; 04958 DLIList<CoEdge*> *co_edge_list_ptr; 04959 DLIList<RefEdge*> curve_list; 04960 DLIList<CubitEntity*> cubit_curves; 04961 04962 // Note: sideB and sideD contain the corner coords (sideA and sideC just 04963 // contain the interior coords) 04964 04965 PRINT_INFO( "Surface %d, Side A, %d coords, YELLOW\n", 04966 tdss->ref_face_ptr()->id(), tdss->coord_list_size_a() ); 04967 04968 co_edge_list_ptr = tdss->get_a_coedges(); 04969 co_edge_list_ptr->reset(); 04970 for( i=co_edge_list_ptr->size(); i--; ) 04971 { 04972 co_edge_ptr = co_edge_list_ptr->get_and_step(); 04973 curve_list.append( co_edge_ptr->get_ref_edge_ptr() ); 04974 } 04975 CAST_LIST(curve_list, cubit_curves, CubitEntity); 04976 CubitUtil::list_entity_ids( " Curves: ", 04977 cubit_curves, 80, "\n", CUBIT_FALSE ); 04978 04979 tdss->coord_list_reset_a(); 04980 for( i=tdss->coord_list_size_a(); i--; ) 04981 { 04982 vec_ptr = tdss->coord_list_get_and_step_a(); 04983 PRINT_DEBUG_100( " create vertex %f %f %f color yellow\n", vec_ptr->x(), 04984 vec_ptr->y(), vec_ptr->z() ); 04985 GfxDebug::draw_point( *vec_ptr, CUBIT_YELLOW_INDEX ); 04986 } 04987 04988 PRINT_INFO( "Surface %d, Side B, %d coords, MAGENTA\n", 04989 tdss->ref_face_ptr()->id(), tdss->coord_list_size_b() ); 04990 04991 co_edge_list_ptr = tdss->get_b_coedges(); 04992 co_edge_list_ptr->reset(); 04993 curve_list.clean_out(); 04994 for( i=co_edge_list_ptr->size(); i--; ) 04995 { 04996 co_edge_ptr = co_edge_list_ptr->get_and_step(); 04997 curve_list.append( co_edge_ptr->get_ref_edge_ptr() ); 04998 } 04999 cubit_curves.clean_out(); 05000 CAST_LIST(curve_list, cubit_curves, CubitEntity); 05001 CubitUtil::list_entity_ids( " Curves: ", 05002 cubit_curves, 80, "\n", CUBIT_FALSE ); 05003 05004 tdss->coord_list_reset_b(); 05005 for( i=tdss->coord_list_size_b(); i--; ) 05006 { 05007 vec_ptr = tdss->coord_list_get_and_step_b(); 05008 PRINT_DEBUG_100( " create vertex %f %f %f color magenta\n", vec_ptr->x(), 05009 vec_ptr->y(), vec_ptr->z() ); 05010 GfxDebug::draw_point( *vec_ptr, CUBIT_MAGENTA_INDEX ); 05011 } 05012 05013 PRINT_INFO( "Surface %d, Side C, %d coords, GREEN\n", 05014 tdss->ref_face_ptr()->id(), tdss->coord_list_size_c() ); 05015 05016 co_edge_list_ptr = tdss->get_c_coedges(); 05017 co_edge_list_ptr->reset(); 05018 curve_list.clean_out(); 05019 for( i=co_edge_list_ptr->size(); i--; ) 05020 { 05021 co_edge_ptr = co_edge_list_ptr->get_and_step(); 05022 curve_list.append( co_edge_ptr->get_ref_edge_ptr() ); 05023 } 05024 cubit_curves.clean_out(); 05025 CAST_LIST(curve_list, cubit_curves, CubitEntity); 05026 CubitUtil::list_entity_ids( " Curves: ", 05027 cubit_curves, 80, "\n", CUBIT_FALSE ); 05028 05029 tdss->coord_list_reset_c(); 05030 for( i=tdss->coord_list_size_c(); i--; ) 05031 { 05032 vec_ptr = tdss->coord_list_get_and_step_c(); 05033 PRINT_DEBUG_100( " create vertex %f %f %f color green\n", vec_ptr->x(), 05034 vec_ptr->y(), vec_ptr->z() ); 05035 GfxDebug::draw_point( *vec_ptr, CUBIT_GREEN_INDEX ); 05036 } 05037 05038 PRINT_INFO( "Surface %d, Side D, %d coords, RED\n", 05039 tdss->ref_face_ptr()->id(), tdss->coord_list_size_d() ); 05040 05041 co_edge_list_ptr = tdss->get_d_coedges(); 05042 co_edge_list_ptr->reset(); 05043 curve_list.clean_out(); 05044 for( i=co_edge_list_ptr->size(); i--; ) 05045 { 05046 co_edge_ptr = co_edge_list_ptr->get_and_step(); 05047 curve_list.append( co_edge_ptr->get_ref_edge_ptr() ); 05048 } 05049 cubit_curves.clean_out(); 05050 CAST_LIST(curve_list, cubit_curves, CubitEntity); 05051 CubitUtil::list_entity_ids( " Curves: ", 05052 cubit_curves, 80, "\n", CUBIT_FALSE ); 05053 05054 tdss->coord_list_reset_d(); 05055 for( i=tdss->coord_list_size_d(); i--; ) 05056 { 05057 vec_ptr = tdss->coord_list_get_and_step_d(); 05058 PRINT_DEBUG_100( " create vertex %f %f %f color red\n", vec_ptr->x(), 05059 vec_ptr->y(), vec_ptr->z() ); 05060 GfxDebug::draw_point( *vec_ptr, CUBIT_RED_INDEX ); 05061 } 05062 05063 GfxDebug::flush(); 05064 05065 return CUBIT_SUCCESS; 05066 } 05067 05068 // Cloned from MapToolSupport, except MapToolSupport does not accurately 05069 // calculate ada and tse 05070 CubitStatus 05071 SplitSurfaceTool::fill_interior_coords( TDSplitSurface *tdss, 05072 int nr, int nc, CubitVector ***coords ) 05073 { 05074 int r, c; 05075 05076 int ada_ints = nr-1; 05077 int tse_ints = nc-1; 05078 05079 double ada, tse; 05080 05081 DLIList<double> tse_array; 05082 if( get_tse_array( tdss, tse_ints, tse_array ) == CUBIT_FAILURE ) 05083 return CUBIT_FAILURE; 05084 05085 // Create all the new coords in the interior of the array 05086 if( tdss ) 05087 { 05088 // Initialize list position 05089 05090 // Must use side that is not collapsed 05091 if( tdss->is_b_collapsed() && tdss->is_d_collapsed() ) 05092 ; // Nothing to do 05093 else if( tdss->is_b_collapsed() == CUBIT_FALSE ) 05094 { 05095 tdss->param_list_reset_b(); 05096 ada = tdss->param_list_get_and_step_b(); 05097 } 05098 else 05099 { 05100 // Must go backwards on this list 05101 tdss->param_list_last_d(); 05102 ada = tdss->param_list_get_and_back_d(); 05103 } 05104 } 05105 for( r=1; r<ada_ints; r++ ) 05106 { 05107 if( tdss ) 05108 { 05109 if( tdss->is_b_collapsed() && tdss->is_d_collapsed() ) 05110 ada = (double)r/(double)ada_ints; 05111 else if( tdss->is_b_collapsed() ) 05112 ada = tdss->param_list_get_and_back_d()/tdss->length_d(); 05113 else 05114 ada = tdss->param_list_get_and_step_b()/tdss->length_b(); 05115 } 05116 else 05117 { 05118 ada = (double)r/(double)ada_ints; 05119 } 05120 05121 tse_array.reset(); 05122 for( c=1; c<tse_ints; c++ ) 05123 { 05124 tse = tse_array.get_and_step(); 05125 05126 // Create a new coord at the mapped location on the face 05127 coords[r][c] = make_interior_coord( coords, nr, nc, ada, tse, r, c ); 05128 } 05129 } 05130 05131 return CUBIT_SUCCESS; 05132 } 05133 05134 CubitStatus 05135 SplitSurfaceTool::smooth_interior_coords( RefFace *ref_face_ptr, 05136 TDSplitSurface *tdss, 05137 double tolerance, 05138 int nr, int nc, double distance, 05139 CubitVector ***coords ) 05140 { 05141 int r, c; // Row, Column 05142 CubitVector *vec_ptr; 05143 05144 // Preserve original coordinates and restore to those if there is an error 05145 // (just give warning). 05146 DLIList<CubitVector*> backup_coords( nr*nc ); 05147 for( r=0; r<nr; r++ ) 05148 { 05149 for( c=0; c<nc; c++ ) 05150 backup_coords.append( new CubitVector( *coords[r][c] ) ); 05151 } 05152 05153 // Problem: after doing a 3D map, when the interior coordinates are projected 05154 // back to the surface they may not lie at the correct percentage across the 05155 // surface (thus a fillet may not be split exactly in the middle). 05156 05157 // Solution: create spline curves on the surface (perpendicular to the split 05158 // direction) at each coordinate. Move the coordinate to the proper fraction 05159 // distance along the spline curve. The trick is to find the proper fraction 05160 // distance - we use a mapping concept to determine the fraction. The real 05161 // need for the "fraction map" is that point A and point B in the diagram 05162 // below can be at different percentages along sideA and sideC, so the 05163 // internal fractions need to be "smoothed out". An alternative to this 05164 // "spline" technique might be to do something like real Winslow smoothing, 05165 // but that would require a lot more work to implement... 05166 05167 // Setup fraction "map" (actual surface split is vertical in diagram below) - 05168 // note the splines perpendicular to the split direction). 05169 // 05170 // sideC A 05171 // _________________________+________+____________ 05172 // (0,1)| |(1,1) 05173 // | | 05174 // | | 05175 // +............spline......+........+.............+ 05176 // | | 05177 // | | 05178 // | | 05179 // | | 05180 // sideD +............spline.....+........+..............+ 05181 // | | 05182 // | y (row) | sideB (tessellations) 05183 // | ^ | 05184 // | | | 05185 // | | (x,y) | 05186 // | | | 05187 // | +----->x (column) B | 05188 // (0,0)|_____________________+________ +______________ |(1,0) 05189 // 05190 // sideA (split locations) 05191 05192 Cubit2DPoint ***frac_coords; 05193 frac_coords = new Cubit2DPoint **[nr]; 05194 05195 for( r=0; r<nr; r++ ) 05196 frac_coords[r] = new Cubit2DPoint *[nc]; 05197 05198 // Initialize 05199 for( r=0; r<nr; r++ ) 05200 { 05201 for( c=0; c<nc; c++ ) 05202 frac_coords[r][c] = NULL; 05203 } 05204 05205 // Fill the boundary "fractions" into frac_coords 05206 05207 frac_coords[0][0] = new Cubit2DPoint( 0.0, 0.0 ); 05208 frac_coords[0][nc-1] = new Cubit2DPoint( 1.0, 0.0 ); 05209 frac_coords[nr-1][0] = new Cubit2DPoint( 0.0, 1.0 ); 05210 frac_coords[nr-1][nc-1] = new Cubit2DPoint( 1.0, 1.0 ); 05211 05212 // Note: sideB and sideD contain the corner coords (sideA and sideC just 05213 // contain the interior coord) 05214 tdss->param_list_reset_a(); 05215 tdss->param_list_reset_b(); 05216 tdss->param_list_get_and_step_b(); // Move off the corner 05217 tdss->param_list_last_c(); // Will need to be traversed backwards 05218 tdss->param_list_last_d(); // Will need to be traversed backwards 05219 tdss->param_list_get_and_back_d(); // Move off the corner 05220 05221 double frac_a, frac_b, frac_c, frac_d; 05222 05223 for( r=1; r<nr-1; r++ ) 05224 { 05225 // Rows go up B and D (note these contain the corner coords) 05226 if( tdss->is_b_collapsed() && tdss->is_d_collapsed() ) 05227 { 05228 frac_b = double(r)/double(nr-1); 05229 frac_d = frac_b; 05230 } 05231 else if( tdss->is_d_collapsed() ) 05232 { 05233 // Use B for both sides 05234 frac_b = tdss->param_list_get_and_step_b()/tdss->length_b(); 05235 frac_d = frac_b; 05236 } 05237 else if( tdss->is_b_collapsed() ) 05238 { 05239 // Use D for both sides 05240 frac_d = (tdss->length_d()-tdss->param_list_get_and_back_d())/tdss->length_d(); 05241 frac_b = frac_d; 05242 } 05243 else 05244 { 05245 frac_b = tdss->param_list_get_and_step_b()/tdss->length_b(); 05246 frac_d = (tdss->length_d()-tdss->param_list_get_and_back_d())/tdss->length_d(); 05247 } 05248 05249 frac_coords[r][0] = new Cubit2DPoint( 0.0, frac_d ); 05250 frac_coords[r][nc-1] = new Cubit2DPoint( 1.0, frac_b ); 05251 05252 // PRINT_INFO( "frac_coords[%d][0] = %f, %f\n", r, frac_coords[r][0]->x(), 05253 // frac_coords[r][0]->y() ); 05254 // PRINT_INFO( "frac_coords[%d][%d] = %f, %f\n", r, nc-1, frac_coords[r][nc-1]->x(), 05255 // frac_coords[r][nc-1]->y() ); 05256 } 05257 05258 for( c=1; c<nc-1; c++ ) 05259 { 05260 // Columns go up A and C (note these DO NOT contain the corner coords) 05261 if( tdss->is_a_collapsed() && tdss->is_c_collapsed() ) 05262 { 05263 frac_a = double(c)/double(nc-1); 05264 frac_c = frac_a; 05265 } 05266 else if( tdss->is_a_collapsed() ) 05267 { 05268 // Use C for both sides 05269 frac_c = (tdss->length_c()-tdss->param_list_get_and_back_c())/tdss->length_c(); 05270 frac_a = frac_c; 05271 } 05272 else if( tdss->is_c_collapsed() ) 05273 { 05274 // Use A for both sides 05275 frac_a = tdss->param_list_get_and_step_a()/tdss->length_a(); 05276 frac_c = frac_a; 05277 } 05278 else 05279 { 05280 frac_a = tdss->param_list_get_and_step_a()/tdss->length_a(); 05281 frac_c = (tdss->length_c()-tdss->param_list_get_and_back_c())/tdss->length_c(); 05282 } 05283 05284 frac_coords[0][c] = new Cubit2DPoint( frac_a, 0.0 ); 05285 frac_coords[nr-1][c] = new Cubit2DPoint( frac_c, 1.0 ); 05286 05287 // PRINT_INFO( "frac_coords[0][%d] = %f, %f\n", c, frac_coords[0][c]->x(), 05288 // frac_coords[0][c]->y() ); 05289 // PRINT_INFO( "frac_coords[%d][%d] = %f, %f\n", nr-1, c, frac_coords[nr-1][c]->x(), 05290 // frac_coords[nr-1][c]->y() ); 05291 } 05292 05293 // Fill interior coordinates 05294 fill_interior_coords( tdss, nr, nc, frac_coords ); 05295 05296 // Now create the splines 05297 05298 TopologyBridge* bridge = 0; 05299 GeometryModifyEngine* gme = 05300 GeometryModifyTool::instance()->get_engine( ref_face_ptr, &bridge ); 05301 // Surface* surf_ptr = dynamic_cast<Surface*>(bridge); 05302 05303 for( r=1; r<nr-1; r++ ) 05304 { 05305 // Move interior points to surface 05306 for( c=1; c<nc-1; c++ ) 05307 ref_face_ptr->move_to_surface( *(coords[r][c]) ); 05308 05309 // Make a spline across the surface 05310 DLIList<CubitVector*> spline_points; 05311 for( c=0; c<nc; c++ ) 05312 spline_points.append( coords[r][c] ); 05313 05314 spline_points.reset(); 05315 CubitVector *start_pnt = spline_points.get_and_back(); 05316 CubitVector *end_pnt = spline_points.get(); 05317 05318 TBPoint *start_Point = gme->make_Point( *start_pnt ); 05319 TBPoint *end_Point = gme->make_Point( *end_pnt ); 05320 if( start_Point == NULL || end_Point == NULL ) 05321 { 05322 PRINT_WARNING( "Unable to adjust split positions - split may be inaccurate\n" ); 05323 05324 // Restore ALL original points & move to surface 05325 backup_coords.reset(); 05326 for( r=0; r<nr; r++ ) 05327 { 05328 for( c=0; c<nc; c++ ) 05329 { 05330 vec_ptr = backup_coords.get_and_step(); 05331 ref_face_ptr->move_to_surface( *vec_ptr ); 05332 coords[r][c]->set( *vec_ptr ); 05333 delete vec_ptr; 05334 } 05335 } 05336 05337 // Free memory 05338 if( start_Point ) start_Point->get_geometry_query_engine()->delete_solid_model_entities(start_Point); 05339 if( end_Point ) end_Point->get_geometry_query_engine()->delete_solid_model_entities(end_Point); 05340 for( r=0; r<nr; r++ ) 05341 { 05342 for( c=0; c<nc; c++ ) 05343 delete frac_coords[r][c]; 05344 } 05345 for( r=0; r<nr; r++ ) 05346 delete []frac_coords[r]; 05347 delete []frac_coords; 05348 frac_coords = NULL; 05349 05350 return CUBIT_FAILURE; 05351 } 05352 05353 // Here, note it is not necessary to create the curve on the surface 05354 Curve *curve_ptr = gme->make_Curve( SPLINE_CURVE_TYPE, start_Point, end_Point, 05355 spline_points ); 05356 05357 // Debug 05358 if( DEBUG_FLAG( 100 ) ) 05359 draw_preview( curve_ptr, CUBIT_TRUE, CUBIT_RED_INDEX ); 05360 05361 if( curve_ptr == NULL ) 05362 { 05363 PRINT_WARNING( "Unable to adjust split positions - split may be inaccurate\n" ); 05364 05365 // Restore ALL original points & move to surface 05366 backup_coords.reset(); 05367 for( r=0; r<nr; r++ ) 05368 { 05369 for( c=0; c<nc; c++ ) 05370 { 05371 vec_ptr = backup_coords.get_and_step(); 05372 ref_face_ptr->move_to_surface( *vec_ptr ); 05373 coords[r][c]->set( *vec_ptr ); 05374 delete vec_ptr; 05375 } 05376 } 05377 05378 // Free memory 05379 for( r=0; r<nr; r++ ) 05380 { 05381 for( c=0; c<nc; c++ ) 05382 delete frac_coords[r][c]; 05383 } 05384 for( r=0; r<nr; r++ ) 05385 delete []frac_coords[r]; 05386 delete []frac_coords; 05387 frac_coords = NULL; 05388 05389 return CUBIT_FAILURE; 05390 } 05391 05392 // Space interior points along the Curve per the original fractions 05393 spline_points.reset(); 05394 spline_points.step(); 05395 double curve_length = curve_ptr->measure(); 05396 for ( c=1; c<nc-1; c++ ) 05397 { 05398 vec_ptr = spline_points.get_and_step(); 05399 05400 // Find total length of curve and multiply by the fraction 05401 double mv_distance; 05402 if( distance == -1.0 ) 05403 mv_distance = curve_length*(frac_coords[r][c]->x()); 05404 else 05405 mv_distance = distance; 05406 05407 CubitVector curve_position; 05408 if( curve_ptr->point_from_arc_length ( *start_pnt, mv_distance, curve_position ) 05409 == CUBIT_FAILURE ) 05410 { 05411 PRINT_WARNING( "Unable to adjust split positions - split may be inaccurate\n" ); 05412 05413 // Restore ALL original points & move to surface 05414 backup_coords.reset(); 05415 for( r=0; r<nr; r++ ) 05416 { 05417 for( c=0; c<nc; c++ ) 05418 { 05419 vec_ptr = backup_coords.get_and_step(); 05420 ref_face_ptr->move_to_surface( *vec_ptr ); 05421 coords[r][c]->set( *vec_ptr ); 05422 delete vec_ptr; 05423 } 05424 } 05425 05426 // Free memory 05427 for( r=0; r<nr; r++ ) 05428 { 05429 for( c=0; c<nc; c++ ) 05430 delete frac_coords[r][c]; 05431 } 05432 05433 // Free matrix memory 05434 for( r=0; r<nr; r++ ) 05435 delete []frac_coords[r]; 05436 delete []frac_coords; 05437 frac_coords = NULL; 05438 05439 // Free spline 05440 curve_ptr->get_geometry_query_engine()->delete_solid_model_entities(curve_ptr ); 05441 return CUBIT_FAILURE; 05442 } 05443 05444 vec_ptr->set( curve_position ); 05445 } 05446 05447 curve_ptr->get_geometry_query_engine()->delete_solid_model_entities(curve_ptr ); 05448 //GeometryQueryTool::instance()->make_free_RefEdge(curve_ptr); 05449 } 05450 05451 // Free memory - all of the frac_coords were allocated 05452 for( r=0; r<nr; r++ ) 05453 { 05454 for( c=0; c<nc; c++ ) 05455 delete frac_coords[r][c]; 05456 } 05457 05458 // Free matrix memory 05459 for( r=0; r<nr; r++ ) 05460 delete []frac_coords[r]; 05461 delete []frac_coords; 05462 frac_coords = NULL; 05463 05464 // Free backup coords 05465 while( backup_coords.size() ) 05466 delete backup_coords.pop(); 05467 05468 return CUBIT_SUCCESS; 05469 } 05470 05471 CubitVector* 05472 SplitSurfaceTool::make_interior_coord( CubitVector ***coords, 05473 int nr, int nc, 05474 double ada, double tse, 05475 int r, int c ) 05476 { 05477 double temp_x, temp_y, temp_z; 05478 CubitVector *vec; 05479 int ada_ints = nr-1; 05480 int tse_ints = nc-1; 05481 05482 temp_x = (1.0 - ada)*coords[0][c]->x() 05483 + ada*coords[ada_ints][c]->x() 05484 + (1.0 - tse)*coords[r][0]->x() 05485 + tse*coords[r][tse_ints]->x() 05486 - (1.0 - tse)*(1.0 - ada)*coords[0][0]->x() 05487 - (1.0 - tse)*ada*coords[ada_ints][0]->x() 05488 - tse*(1.0 - ada)*coords[0][tse_ints]->x() 05489 - tse*ada*coords[ada_ints][tse_ints]->x(); 05490 05491 temp_y = (1.0 - ada)*coords[0][c]->y() 05492 + ada*coords[ada_ints][c]->y() 05493 + (1.0 - tse)*coords[r][0]->y() 05494 + tse*coords[r][tse_ints]->y() 05495 - (1.0 - tse)*(1.0 - ada)*coords[0][0]->y() 05496 - (1.0 - tse)*ada*coords[ada_ints][0]->y() 05497 - tse*(1.0 - ada)*coords[0][tse_ints]->y() 05498 - tse*ada*coords[ada_ints][tse_ints]->y(); 05499 05500 temp_z = (1.0 - ada)*coords[0][c]->z() 05501 + ada*coords[ada_ints][c]->z() 05502 + (1.0 - tse)*coords[r][0]->z() 05503 + tse*coords[r][tse_ints]->z() 05504 - (1.0 - tse)*(1.0 - ada)*coords[0][0]->z() 05505 - (1.0 - tse)*ada*coords[ada_ints][0]->z() 05506 - tse*(1.0 - ada)*coords[0][tse_ints]->z() 05507 - tse*ada*coords[ada_ints][tse_ints]->z(); 05508 05509 vec = new CubitVector( temp_x, temp_y, temp_z ); 05510 05511 return vec; 05512 } 05513 05514 CubitStatus 05515 SplitSurfaceTool::fill_boundary_coords( TDSplitSurface *tdss, int nr, 05516 int nc, Cubit2DPoint ***coords ) 05517 { 05518 // sideC 05519 // coords[nr-1][c] 05520 // _________________________________________ 05521 // (0,1)| |(1,1) 05522 // | | 05523 // | | 05524 // | | 05525 // | | 05526 // | | 05527 // coords[r][0] | | 05528 // | | coords[r][nc-1] 05529 // sideD | | 05530 // | ada (row) | sideB 05531 // | ^ | 05532 // | | | 05533 // | | (tse,ada) | 05534 // | | | 05535 // | +----->tse (column) | 05536 // (0,0)|_________________________________________|(1,0) 05537 // coords[0][c] 05538 // sideA 05539 05540 // Split direction is vertical in the above diagram. 05541 05542 // Debug (with DEBUG_FLAG_154) 05543 draw_boundary_coords( tdss ); 05544 05545 int r, c; 05546 RefFace *ref_face_ptr = tdss->ref_face_ptr(); 05547 05548 // Note: sideB and sideD contain the corner coords (sideA and sideC just 05549 // contain the interior coords) 05550 tdss->coord_list_reset_a(); 05551 tdss->coord_list_reset_b(); 05552 tdss->coord_list_last_c(); // Will need to be traversed backwards 05553 tdss->coord_list_last_d(); // Will need to be traversed backwards 05554 05555 for( r=0; r<nr; r++ ) 05556 { 05557 // Rows go up B and D (note these contain the corner coords) 05558 coords[r][0] = get_uv_point( ref_face_ptr, tdss->coord_list_get_and_back_d() ); 05559 coords[r][nc-1] = get_uv_point( ref_face_ptr, tdss->coord_list_get_and_step_b() ); 05560 } 05561 05562 for( c=1; c<nc-1; c++ ) 05563 { 05564 // Columns go up A and C (note these DO NOT contain the corner coords) 05565 coords[0][c] = get_uv_point( ref_face_ptr, tdss->coord_list_get_and_step_a() ); 05566 coords[nr-1][c] = get_uv_point( ref_face_ptr, tdss->coord_list_get_and_back_c() ); 05567 } 05568 05569 return CUBIT_SUCCESS; 05570 } 05571 05572 Cubit2DPoint * 05573 SplitSurfaceTool::get_uv_point( RefFace *ref_face_ptr, CubitVector *vec_ptr ) 05574 { 05575 double u, v; 05576 ref_face_ptr->u_v_from_position( *vec_ptr, u, v ); 05577 return( new Cubit2DPoint( u, v ) ); 05578 } 05579 05580 // Cloned from MapToolSupport, except MapToolSupport does not accurately 05581 // calculate ada and tse 05582 CubitStatus 05583 SplitSurfaceTool::fill_interior_coords( TDSplitSurface *tdss, 05584 int nr, int nc, Cubit2DPoint ***coords ) 05585 { 05586 int r, c; 05587 05588 int ada_ints = nr-1; 05589 int tse_ints = nc-1; 05590 05591 double ada, tse; 05592 05593 DLIList<double> tse_array; 05594 if( get_tse_array( tdss, tse_ints, tse_array ) == CUBIT_FAILURE ) 05595 return CUBIT_FAILURE; 05596 05597 // Create all the new coords in the interior of the array 05598 if( tdss ) 05599 { 05600 // Initialize list position 05601 05602 // Must use side that is not collapsed 05603 if( tdss->is_b_collapsed() && tdss->is_d_collapsed() ) 05604 ; // Nothing to do 05605 else if( tdss->is_b_collapsed() == CUBIT_FALSE ) 05606 { 05607 tdss->param_list_reset_b(); 05608 ada = tdss->param_list_get_and_step_b(); 05609 } 05610 else 05611 { 05612 // Must go backwards on this list 05613 tdss->param_list_last_d(); 05614 ada = tdss->param_list_get_and_back_d(); 05615 } 05616 } 05617 for( r=1; r<ada_ints; r++ ) 05618 { 05619 if( tdss ) 05620 { 05621 if( tdss->is_b_collapsed() && tdss->is_d_collapsed() ) 05622 ada = (double)r/(double)ada_ints; 05623 else if( tdss->is_b_collapsed() ) 05624 ada = tdss->param_list_get_and_back_d()/tdss->length_d(); 05625 else 05626 ada = tdss->param_list_get_and_step_b()/tdss->length_b(); 05627 } 05628 else 05629 { 05630 ada = (double)r/(double)ada_ints; 05631 } 05632 05633 tse_array.reset(); 05634 for( c=1; c<tse_ints; c++ ) 05635 { 05636 tse = tse_array.get_and_step(); 05637 05638 // Create a new coord at the mapped location on the face 05639 coords[r][c] = make_interior_coord( coords, nr, nc, ada, tse, r, c ); 05640 } 05641 } 05642 05643 return CUBIT_SUCCESS; 05644 } 05645 05646 CubitStatus 05647 SplitSurfaceTool::get_tse_array( TDSplitSurface *tdss, int tse_ints, 05648 DLIList<double> &tse_array ) 05649 { 05650 int c; 05651 double tse; 05652 05653 tdss->param_list_reset_a(); 05654 tdss->param_list_last_c(); 05655 05656 for( c = 1; c < tse_ints; c++ ) 05657 { 05658 if( tdss ) 05659 { 05660 if( tdss->is_a_collapsed() && tdss->is_c_collapsed() ) 05661 { 05662 tse = (double)c/(double)tse_ints; 05663 } 05664 else if( tdss->is_a_collapsed() ) 05665 { 05666 // Just use C (go backwards on side C) 05667 tse = tdss->param_list_get_and_back_c()/tdss->length_c(); 05668 } 05669 else if( tdss->is_c_collapsed() ) 05670 { 05671 // Just use A 05672 tse = tdss->param_list_get_and_step_a()/tdss->length_a(); 05673 } 05674 else 05675 { 05676 // Take average fractional location across the surface 05677 tse = (tdss->param_list_get_and_step_a()/tdss->length_a() + 1.0 - 05678 tdss->param_list_get_and_back_c()/tdss->length_c())/2.0; 05679 } 05680 } 05681 else 05682 { 05683 tse = (double)c/(double)tse_ints; 05684 } 05685 05686 tse_array.append( tse ); 05687 05688 } 05689 05690 return CUBIT_SUCCESS; 05691 } 05692 05693 Cubit2DPoint* 05694 SplitSurfaceTool::make_interior_coord( Cubit2DPoint ***coords, 05695 int nr, int nc, 05696 double ada, double tse, 05697 int r, int c ) 05698 { 05699 double temp_x, temp_y; 05700 Cubit2DPoint *pnt; 05701 int ada_ints = nr-1; 05702 int tse_ints = nc-1; 05703 05704 temp_x = (1.0 - ada)*coords[0][c]->x() 05705 + ada*coords[ada_ints][c]->x() 05706 + (1.0 - tse)*coords[r][0]->x() 05707 + tse*coords[r][tse_ints]->x() 05708 - (1.0 - tse)*(1.0 - ada)*coords[0][0]->x() 05709 - (1.0 - tse)*ada*coords[ada_ints][0]->x() 05710 - tse*(1.0 - ada)*coords[0][tse_ints]->x() 05711 - tse*ada*coords[ada_ints][tse_ints]->x(); 05712 05713 temp_y = (1.0 - ada)*coords[0][c]->y() 05714 + ada*coords[ada_ints][c]->y() 05715 + (1.0 - tse)*coords[r][0]->y() 05716 + tse*coords[r][tse_ints]->y() 05717 - (1.0 - tse)*(1.0 - ada)*coords[0][0]->y() 05718 - (1.0 - tse)*ada*coords[ada_ints][0]->y() 05719 - tse*(1.0 - ada)*coords[0][tse_ints]->y() 05720 - tse*ada*coords[ada_ints][tse_ints]->y(); 05721 05722 pnt = new Cubit2DPoint( temp_x, temp_y ); 05723 05724 return pnt; 05725 } 05726 05727 CubitStatus 05728 SplitSurfaceTool::draw_preview( DLIList<Curve*> &curve_list, int color ) 05729 { 05730 int i; 05731 Curve *curve_ptr; 05732 curve_list.reset(); 05733 05734 for( i=curve_list.size(); i--; ) 05735 { 05736 curve_ptr = curve_list.get_and_step(); 05737 draw_preview( curve_ptr, CUBIT_FALSE, color ); 05738 } 05739 05740 GfxPreview::flush(); 05741 05742 return CUBIT_SUCCESS; 05743 } 05744 05745 CubitStatus 05746 SplitSurfaceTool::draw_preview( Curve *curve_ptr, CubitBoolean flush, 05747 int color ) 05748 { 05749 CubitStatus result; 05750 GMem g_mem; 05751 05752 // get the graphics 05753 result = curve_ptr->get_geometry_query_engine()-> 05754 get_graphics( curve_ptr, &g_mem ); 05755 05756 if (result==CUBIT_FAILURE || g_mem.pointListCount == 0) 05757 { 05758 PRINT_WARNING("Unable to preview a curve\n" ); 05759 } 05760 05761 // Draw the polyline 05762 GfxPreview::draw_polyline( g_mem.point_list(), g_mem.pointListCount, color ); 05763 if( flush ) 05764 GfxPreview::flush(); 05765 05766 return CUBIT_SUCCESS; 05767 } 05768 05769 CubitStatus 05770 SplitSurfaceTool::create_ref_edges( DLIList<Curve*> &curve_list, 05771 DLIList<RefEdge*> &ref_edge_list ) 05772 { 05773 int i; 05774 Curve *curve_ptr; 05775 RefEdge *ref_edge_ptr; 05776 curve_list.reset(); 05777 for( i=curve_list.size(); i--; ) 05778 { 05779 curve_ptr = curve_list.get_and_step(); 05780 ref_edge_ptr = GeometryQueryTool::instance()->make_free_RefEdge(curve_ptr); 05781 if( ref_edge_ptr ) ref_edge_list.append( ref_edge_ptr ); 05782 } 05783 return CUBIT_SUCCESS; 05784 } 05785 05786 int 05787 SplitSurfaceTool::number_coedges( RefEdge *ref_edge_ptr, RefFace *ref_face_ptr ) 05788 { 05789 DLIList<CoEdge*> co_edge_list; 05790 ref_edge_ptr->get_co_edges( co_edge_list, ref_face_ptr ); 05791 return co_edge_list.size(); 05792 } 05793 05794 Curve * 05795 SplitSurfaceTool::create_curve( DLIList<CubitVector*> &vec_list, 05796 Surface *surf_ptr, 05797 double tolerance, 05798 CubitBoolean iterate, 05799 CubitBoolean draw_pnts, 05800 CubitBoolean project_curve ) 05801 { 05802 Curve *curve_ptr = NULL; 05803 05804 if( vec_list.size() < 2 ) 05805 { 05806 PRINT_ERROR( "Unable to create a curve from less than two locations.\n" ); 05807 return NULL; 05808 } 05809 05810 GeometryModifyEngine* gme = 05811 GeometryModifyTool::instance()->get_engine( surf_ptr ); 05812 05813 if (NULL == gme) 05814 { 05815 PRINT_ERROR("No geometry modify engine available. Unable to create split curve.\n"); 05816 return NULL; 05817 } 05818 05819 GeometryQueryEngine* gqe = surf_ptr->get_geometry_query_engine(); 05820 // Note the user can set the following value through 05821 // set geometry accuracy <val> 05822 double resabs = gqe->get_sme_resabs_tolerance(); 05823 05824 // Find start and end locations 05825 vec_list.reset(); 05826 CubitVector *start_pnt = vec_list.get_and_back(); 05827 CubitVector *end_pnt = vec_list.get(); 05828 05829 // Check to see if a simple straight line should be created. Use 1/2 the 05830 // tolerance because points can deviate on either side of the straight line 05831 // (unless tolerance is resabs - then just use it). 05832 if( check_points_straight( surf_ptr, vec_list, 05833 tolerance==resabs ? resabs : 0.5*tolerance ) ) 05834 { 05835 // Create a straight line on the surface 05836 TBPoint *start_Point = gme->make_Point( *start_pnt ); 05837 TBPoint *end_Point = gme->make_Point( *end_pnt ); 05838 if( start_Point == NULL || end_Point == NULL ) 05839 { 05840 if( start_Point ) start_Point->get_geometry_query_engine()->delete_solid_model_entities(start_Point); 05841 if( end_Point ) end_Point->get_geometry_query_engine()->delete_solid_model_entities(end_Point); 05842 return NULL; 05843 } 05844 curve_ptr = gme->make_Curve( start_Point, end_Point, surf_ptr ); 05845 if( draw_pnts == CUBIT_TRUE ) 05846 { 05847 // Drawing here is a bit of a hack but it saves storing the point 05848 // list 05849 draw_point( *start_pnt, CUBIT_BLUE_INDEX ); 05850 draw_point( *end_pnt, CUBIT_BLUE_INDEX ); 05851 } 05852 05853 // Free memory 05854 // start_Point->get_geometry_query_engine()->delete_solid_model_entities(start_Point ); 05855 // end_Point->get_geometry_query_engine()->delete_solid_model_entities(end_Point ); 05856 05857 return curve_ptr; 05858 } 05859 05860 // Check to see if an arc should be created. Use 1/2 the tolerance because 05861 // points can deviate on either side of the arc (unless tolerance is resabs - 05862 // then just use resabs). 05863 if( (curve_ptr = check_points_arc( surf_ptr, gme, vec_list, resabs, 05864 tolerance==resabs ? resabs : 0.5*tolerance ) ) != NULL ) 05865 { 05866 if( draw_pnts == CUBIT_TRUE ) 05867 { 05868 // Drawing here is a bit of a hack but it saves storing the point 05869 // lists 05870 draw_point( *start_pnt, CUBIT_BLUE_INDEX ); 05871 draw_point( *end_pnt, CUBIT_BLUE_INDEX ); 05872 } 05873 return curve_ptr; 05874 } 05875 05876 // Ok - its not a straight line or arc, so create a spline 05877 05878 // Copy the vectors since we are going to add to the list 05879 DLIList<CubitVector*> spline_points; 05880 int i; 05881 vec_list.reset(); 05882 for( i=vec_list.size(); i--; ) 05883 spline_points.append( new CubitVector(*vec_list.get_and_step()) ); 05884 05885 int times_through_loop = 0; 05886 int done = 0; 05887 while( !done ) 05888 { 05889 times_through_loop++; 05890 05891 // Create a spline. Do not create on the surface since that can be 05892 // computationally expensive and we are going to iterate. Later we 05893 // will project the final result to the surface. Note: the preceeding 05894 // statement is not true - the gme->make_Curve function would not 05895 // actually create the curve on the surface - it only projects the 05896 // points to the surface then makes a free spline - this is puzzling. 05897 TBPoint *start_Point = gme->make_Point( *start_pnt ); 05898 TBPoint *end_Point = gme->make_Point( *end_pnt ); 05899 if( start_Point == NULL || end_Point == NULL ) 05900 { 05901 while( spline_points.size() ) delete spline_points.pop(); 05902 if( start_Point ) start_Point->get_geometry_query_engine()->delete_solid_model_entities(start_Point); 05903 if( end_Point ) end_Point->get_geometry_query_engine()->delete_solid_model_entities(end_Point); 05904 return NULL; 05905 } 05906 05907 if( spline_points.size() == 2 ) 05908 curve_ptr = gme->make_Curve( STRAIGHT_CURVE_TYPE, start_Point, end_Point, NULL ); 05909 else 05910 curve_ptr = gme->make_Curve( SPLINE_CURVE_TYPE, start_Point, end_Point, 05911 spline_points ); 05912 05913 if( curve_ptr == NULL ) 05914 { 05915 while( spline_points.size() ) delete spline_points.pop(); 05916 start_Point->get_geometry_query_engine()->delete_solid_model_entities(start_Point); 05917 end_Point->get_geometry_query_engine()->delete_solid_model_entities(end_Point); 05918 return NULL; 05919 } 05920 05921 if( iterate == CUBIT_FALSE ) 05922 break; 05923 05924 // Check to see if spline is close enough 05925 CubitVector *start_vec_ptr, *end_vec_ptr; 05926 spline_points.reset(); 05927 CubitVector mid_vec; 05928 double dist; 05929 int insert_num = 0; 05930 for( i=spline_points.size()-1; i--; ) 05931 { 05932 start_vec_ptr = spline_points.get_and_step(); 05933 end_vec_ptr = spline_points.get(); 05934 mid_vec = (*start_vec_ptr + *end_vec_ptr)/2.0; 05935 05936 // Check distance from mid_vec to Curve 05937 CubitVector mid_vec_crv; 05938 curve_ptr->closest_point( mid_vec, mid_vec_crv ); 05939 05940 double x2 = mid_vec.x()-mid_vec_crv.x(); 05941 x2 = x2*x2; 05942 double y2 = mid_vec.y()-mid_vec_crv.y(); 05943 y2 = y2*y2; 05944 double z2 = mid_vec.z()-mid_vec_crv.z(); 05945 z2 = z2*z2; 05946 05947 dist = sqrt( x2+y2+z2 ); 05948 05949 if( dist > tolerance ) 05950 { 05951 // Insert the midpoint location into the list 05952 spline_points.back(); 05953 spline_points.insert( new CubitVector( mid_vec ) ); 05954 insert_num++; 05955 } 05956 05957 } 05958 05959 if( insert_num == 0 ) 05960 done++; 05961 05962 if( times_through_loop > 100 ) 05963 { 05964 PRINT_WARNING( "Unable to closely approximate spline\n" ); 05965 done++; 05966 } 05967 05968 if( !done ) 05969 { 05970 curve_ptr->get_geometry_query_engine()->delete_solid_model_entities(curve_ptr ); 05971 } 05972 05973 if( insert_num > 0 ) { 05974 PRINT_DEBUG_154( "Inserted %d points when creating spline\n", insert_num ); 05975 } 05976 } 05977 05978 // Project the spline to the surface (if the surface is not planar) 05979 DLIList<Surface*> surf_list; 05980 surf_list.append( surf_ptr ); 05981 DLIList<Curve*> curve_list; 05982 curve_list.append( curve_ptr ); 05983 DLIList<Curve*> curve_list_new; 05984 05985 if( gme->project_edges( surf_list, curve_list, curve_list_new ) == CUBIT_FAILURE ) 05986 { 05987 PRINT_WARNING( "Unable to project curve to surface - split may fail\n" ); 05988 } 05989 else 05990 { 05991 curve_ptr->get_geometry_query_engine()->delete_solid_model_entities(curve_ptr ); 05992 curve_ptr = curve_list_new.get(); 05993 } 05994 05995 if( curve_ptr && draw_pnts == CUBIT_TRUE ) 05996 { 05997 // Drawing here is a bit of a hack but it saves storing the point 05998 // lists 05999 draw_points( spline_points, CUBIT_BLUE_INDEX, CUBIT_FALSE ); 06000 } 06001 06002 // Free memory 06003 while( spline_points.size() ) delete spline_points.pop(); 06004 06005 return curve_ptr; 06006 } 06007 06008 CubitBoolean 06009 SplitSurfaceTool::check_points_straight( Surface *surf_ptr, 06010 DLIList<CubitVector*> &point_list, 06011 double tolerance ) 06012 { 06013 GeometryType geom_type = surf_ptr->geometry_type(); 06014 06015 // Get start and end point 06016 point_list.reset(); 06017 CubitVector start_pnt( *point_list.get_and_back() ); 06018 CubitVector end_pnt( *point_list.get() ); 06019 06020 // If 2 or 3 points, check points along a straight line to make sure they 06021 // lie on the surface. If we only have 2 points and we meet this criteria 06022 // we are done. 06023 if( point_list.size() < 4 ) 06024 { 06025 if( point_list.size()==2 && geom_type == PLANE_SURFACE_TYPE ) 06026 return CUBIT_TRUE; 06027 06028 // Check several points on the straight line - see if on surface 06029 06030 CubitVector check_pnt; 06031 check_pnt.set( start_pnt.x() + .25 * (end_pnt.x() - start_pnt.x()), 06032 start_pnt.y() + .25 * (end_pnt.y() - start_pnt.y()), 06033 start_pnt.z() + .25 * (end_pnt.z() - start_pnt.z()) ); 06034 if( is_point_on_surface( surf_ptr, check_pnt, GEOMETRY_RESABS ) == CUBIT_FALSE ) 06035 return CUBIT_FALSE; 06036 06037 check_pnt.set( start_pnt.x() + .5 * (end_pnt.x() - start_pnt.x()), 06038 start_pnt.y() + .5 * (end_pnt.y() - start_pnt.y()), 06039 start_pnt.z() + .5 * (end_pnt.z() - start_pnt.z()) ); 06040 if( is_point_on_surface( surf_ptr, check_pnt, GEOMETRY_RESABS ) == CUBIT_FALSE ) 06041 return CUBIT_FALSE; 06042 06043 check_pnt.set( start_pnt.x() + .75 * (end_pnt.x() - start_pnt.x()), 06044 start_pnt.y() + .75 * (end_pnt.y() - start_pnt.y()), 06045 start_pnt.z() + .75 * (end_pnt.z() - start_pnt.z()) ); 06046 if( is_point_on_surface( surf_ptr, check_pnt, GEOMETRY_RESABS ) == CUBIT_FALSE ) 06047 return CUBIT_FALSE; 06048 06049 if( point_list.size() == 2 ) 06050 return CUBIT_TRUE; 06051 } 06052 06053 // Get vector along the line 06054 CubitVector ln_vec = end_pnt - start_pnt; 06055 ln_vec.normalize(); 06056 06057 int i; 06058 point_list.reset(); 06059 point_list.step(); 06060 for( i=point_list.size()-2; i--; ) 06061 { 06062 CubitVector *pnt = point_list.get_and_step(); 06063 06064 // Get vector from point to line origin 06065 CubitVector vec = *pnt - start_pnt; 06066 06067 // Calculate distance from point to origin 06068 double distpnt_orig = vec.length(); 06069 06070 // Take dot product of vec & unit vector to get distance to intersection 06071 // along the line 06072 double dot = fabs( vec % ln_vec ); 06073 06074 // Calculate distance from point to line w/sqrt (use fabs to account for 06075 // tiny roundoff error that could result in a negative number) 06076 double distance = sqrt(fabs(distpnt_orig*distpnt_orig - dot*dot)); 06077 06078 if( distance > tolerance ) 06079 return CUBIT_FALSE; 06080 06081 if( geom_type != PLANE_SURFACE_TYPE ) 06082 { 06083 // Find the actual intersection point and determine if it is within 06084 // GEOMETRY_RESABS of the surface 06085 06086 // Travel along the line to get the intersection point 06087 CubitVector int_pnt; 06088 start_pnt.next_point( ln_vec, dot, int_pnt ); 06089 06090 // Find the closest point on the surface 06091 CubitVector closest_loc_on_surf; 06092 if( surf_ptr->closest_point( int_pnt, &closest_loc_on_surf ) == CUBIT_FAILURE ) 06093 { 06094 return CUBIT_FALSE; 06095 } 06096 06097 // Find the distance between these two points 06098 double dist = int_pnt.distance_between( closest_loc_on_surf ); 06099 if( dist > GEOMETRY_RESABS ) 06100 return CUBIT_FALSE; 06101 } 06102 } 06103 06104 return CUBIT_TRUE; 06105 } 06106 06107 Curve * 06108 SplitSurfaceTool:: check_points_arc( Surface *surf_ptr, 06109 GeometryModifyEngine *gme, 06110 DLIList<CubitVector*> &point_list, 06111 double resabs, 06112 double tolerance ) 06113 { 06114 if( point_list.size() < 2 ) 06115 return 0; 06116 06117 point_list.reset(); 06118 CubitVector start_pnt( *point_list.get_and_back() ); 06119 CubitVector end_pnt( *point_list.get() ); 06120 06121 if( point_list.size() == 2 ) 06122 return create_arc_two( gme, surf_ptr, start_pnt, end_pnt, resabs, 06123 tolerance ); 06124 06125 // Get a mid point location 06126 CubitVector mid_pnt; 06127 int mid = point_list.size()/2; 06128 point_list.reset(); 06129 point_list.step( mid ); 06130 mid_pnt = *point_list.get(); 06131 06132 // Check if 3 points are colinear 06133 double a = (start_pnt-mid_pnt).length(); 06134 double b = (mid_pnt-end_pnt).length(); 06135 double c = (end_pnt-start_pnt).length(); 06136 06137 double denom = sqrt((a+b+c)*(b+c-a)*(c+a-b)*(a+b-c)); 06138 if( denom < GEOMETRY_RESABS ) 06139 return 0; 06140 06141 // Special case if 3 points 06142 if( point_list.size() == 3 ) 06143 return create_arc_three( gme, surf_ptr, start_pnt, mid_pnt, end_pnt, resabs ); 06144 06145 // Get a potentially more accurate arc mid_pnt 06146 get_arc_mid_pnt( surf_ptr, start_pnt, end_pnt, mid_pnt, tolerance ); 06147 06148 // Create an actual arc and do some comparisons 06149 double deviation; 06150 Curve *curve_ptr = check_if_arc( gme, surf_ptr, point_list, start_pnt, 06151 mid_pnt, end_pnt, resabs, tolerance, deviation ); 06152 06153 if( curve_ptr ) 06154 return curve_ptr; 06155 06156 // Try harder to find an arc - use each point as the center point 06157 int i; 06158 point_list.reset(); 06159 point_list.step(); 06160 CubitVector *mid_pnt_ptr; 06161 for( i=point_list.size()-2; i--; ) 06162 { 06163 mid_pnt_ptr = point_list.get_and_step(); 06164 06165 curve_ptr = check_if_arc( gme, surf_ptr, point_list, start_pnt, 06166 *mid_pnt_ptr, end_pnt, resabs, tolerance, 06167 deviation ); 06168 06169 if( curve_ptr ) 06170 return curve_ptr; 06171 06172 if( deviation > tolerance ) 06173 { 06174 return 0; 06175 } 06176 } 06177 06178 return 0; 06179 } 06180 06181 CubitStatus 06182 SplitSurfaceTool::get_arc_mid_pnt( Surface *surf_ptr, 06183 CubitVector &start_pnt, 06184 CubitVector &end_pnt, 06185 CubitVector &mid_pnt, 06186 double tolerance ) 06187 { 06188 // Possible Surface types. 06189 // CONE_SURFACE_TYPE 06190 // PLANE_SURFACE_TYPE 06191 // SPHERE_SURFACE_TYPE 06192 // SPLINE_SURFACE_TYPE 06193 // TORUS_SURFACE_TYPE 06194 // BEST_FIT_SURFACE_TYPE 06195 // FACET_SURFACE_TYPE 06196 // UNDEFINED_SURFACE_TYPE 06197 GeometryType geom_type = surf_ptr->geometry_type(); 06198 06199 // If surface is a cone, sphere or torus, we will *try* to get a more accurate 06200 // mid point location. This can often result in a better arc. 06201 if( (geom_type == CONE_SURFACE_TYPE || 06202 geom_type == SPHERE_SURFACE_TYPE || 06203 geom_type == TORUS_SURFACE_TYPE) && 06204 surf_ptr->is_parametric() ) 06205 { 06206 // Determine if arc traverses approximately along the uv space of the surface 06207 // Using the surface uv space to create the arc should be the most accurate 06208 // method of creating the arc. 06209 06210 double start_u, start_v; 06211 if( surf_ptr->u_v_from_position ( start_pnt, start_u, start_v ) 06212 == CUBIT_FAILURE ) 06213 return CUBIT_FAILURE; 06214 06215 double end_u, end_v; 06216 if( surf_ptr->u_v_from_position ( end_pnt, end_u, end_v ) 06217 == CUBIT_FAILURE ) 06218 return CUBIT_FAILURE; 06219 06220 // Use average. Note this could go to the opposite side of the surface 06221 // - I'm not sure how to handle this other than checking the resultant 06222 // point and flipping to the other side if it is off. 06223 double mid_u, mid_v; 06224 mid_u = (start_u+end_u)/2.0; 06225 mid_v = (start_v+end_v)/2.0; 06226 06227 CubitVector new_mid_pnt = surf_ptr->position_from_u_v( mid_u, mid_v ); 06228 06229 CubitPointContainment pnt_on_flg; 06230 pnt_on_flg = surf_ptr->point_containment( mid_u, mid_v ); 06231 if( pnt_on_flg == CUBIT_PNT_OUTSIDE || 06232 pnt_on_flg == CUBIT_PNT_UNKNOWN ) 06233 { 06234 CubitVector mid_pnt_ref; 06235 06236 if( reflect_arc_pnt( start_pnt, new_mid_pnt, end_pnt, new_mid_pnt, mid_pnt_ref ) == 06237 CUBIT_SUCCESS ) 06238 { 06239 // Make sure the point is on the surface 06240 CubitVector mid_pnt_ref_on; 06241 surf_ptr->closest_point( mid_pnt_ref, &mid_pnt_ref_on ); 06242 if( mid_pnt_ref.distance_between( mid_pnt_ref_on ) < tolerance ) 06243 { 06244 pnt_on_flg = surf_ptr->point_containment( mid_pnt_ref ); 06245 if( pnt_on_flg == CUBIT_PNT_INSIDE || 06246 pnt_on_flg == CUBIT_PNT_BOUNDARY ) 06247 { 06248 mid_pnt = mid_pnt_ref_on; 06249 return CUBIT_SUCCESS; 06250 } 06251 } 06252 } 06253 } 06254 else 06255 { 06256 mid_pnt = new_mid_pnt; 06257 return CUBIT_SUCCESS; 06258 } 06259 } 06260 06261 return CUBIT_FAILURE; 06262 } 06263 06264 Curve* 06265 SplitSurfaceTool::create_arc_two( GeometryModifyEngine *gme, 06266 Surface *surf_ptr, 06267 CubitVector &start_pnt, 06268 CubitVector &end_pnt, 06269 double resabs, 06270 double tolerance ) 06271 { 06272 CubitVector mid_pnt; 06273 if( get_arc_mid_pnt( surf_ptr, start_pnt, end_pnt, mid_pnt, tolerance ) 06274 == CUBIT_FAILURE ) 06275 return 0; 06276 06277 // Check if 3 points are colinear 06278 double a = (start_pnt-mid_pnt).length(); 06279 double b = (mid_pnt-end_pnt).length(); 06280 double c = (end_pnt-start_pnt).length(); 06281 06282 double denom = sqrt((a+b+c)*(b+c-a)*(c+a-b)*(a+b-c)); 06283 if( denom < GEOMETRY_RESABS ) 06284 return 0; 06285 06286 TBPoint *start_Point = gme->make_Point( start_pnt ); 06287 TBPoint *end_Point = gme->make_Point( end_pnt ); 06288 TBPoint *mid_Point = gme->make_Point( mid_pnt ); 06289 if( start_Point == NULL || mid_Point == NULL || end_Point == NULL ) 06290 { 06291 if( start_Point ) start_Point->get_geometry_query_engine()->delete_solid_model_entities(start_Point); 06292 if( mid_Point ) mid_Point->get_geometry_query_engine()->delete_solid_model_entities(mid_Point); 06293 if( end_Point ) end_Point->get_geometry_query_engine()->delete_solid_model_entities(end_Point); 06294 return 0; 06295 } 06296 06297 // Create a 3-pt arc with the GeometryModifyEngine 06298 Curve *curve_ptr = gme->create_arc_three( start_Point, 06299 mid_Point, 06300 end_Point ); 06301 06302 if( mid_Point ) mid_Point->get_geometry_query_engine()->delete_solid_model_entities(mid_Point); 06303 06304 if( !curve_ptr ) 06305 { 06306 if( start_Point ) start_Point->get_geometry_query_engine()->delete_solid_model_entities(start_Point); 06307 if( end_Point ) end_Point->get_geometry_query_engine()->delete_solid_model_entities(end_Point); 06308 return 0; 06309 } 06310 06311 // Check 1/4 and 3/4 location - make sure on surface 06312 CubitVector check_loc; 06313 if( curve_ptr->position_from_fraction( .25, check_loc ) == CUBIT_FAILURE ) 06314 { 06315 curve_ptr->get_geometry_query_engine()->delete_solid_model_entities(curve_ptr ); 06316 return 0; 06317 } 06318 06319 // Now make sure within GEOMETRY_RESABS to the surface 06320 if( is_point_on_surface( surf_ptr, check_loc, resabs ) == CUBIT_FALSE ) 06321 { 06322 curve_ptr->get_geometry_query_engine()->delete_solid_model_entities(curve_ptr ); 06323 return 0; 06324 } 06325 06326 if( curve_ptr->position_from_fraction( .75, check_loc ) == CUBIT_FAILURE ) 06327 { 06328 curve_ptr->get_geometry_query_engine()->delete_solid_model_entities(curve_ptr ); 06329 return 0; 06330 } 06331 06332 // Now make sure within GEOMETRY_RESABS to the surface 06333 if( is_point_on_surface( surf_ptr, check_loc, resabs ) == CUBIT_FALSE ) 06334 { 06335 curve_ptr->get_geometry_query_engine()->delete_solid_model_entities(curve_ptr ); 06336 return 0; 06337 } 06338 06339 return curve_ptr; 06340 } 06341 06342 Curve* 06343 SplitSurfaceTool::create_arc_three( GeometryModifyEngine *gme, 06344 Surface *surf_ptr, 06345 CubitVector &start_pnt, 06346 CubitVector &mid_pnt, 06347 CubitVector &end_pnt, 06348 double resabs ) 06349 { 06350 TBPoint *start_Point = gme->make_Point( start_pnt ); 06351 TBPoint *end_Point = gme->make_Point( end_pnt ); 06352 TBPoint *mid_Point = gme->make_Point( mid_pnt ); 06353 if( start_Point == NULL || mid_Point == NULL || end_Point == NULL ) 06354 { 06355 if( start_Point ) start_Point->get_geometry_query_engine()->delete_solid_model_entities(start_Point); 06356 if( mid_Point ) mid_Point->get_geometry_query_engine()->delete_solid_model_entities(mid_Point); 06357 if( end_Point ) end_Point->get_geometry_query_engine()->delete_solid_model_entities(end_Point); 06358 return 0; 06359 } 06360 06361 // Create a 3-pt arc with the GeometryModifyEngine 06362 Curve *curve_ptr = gme->create_arc_three( start_Point, 06363 mid_Point, 06364 end_Point ); 06365 06366 if( mid_Point ) mid_Point->get_geometry_query_engine()->delete_solid_model_entities(mid_Point); 06367 06368 if( !curve_ptr ) 06369 { 06370 if( start_Point ) start_Point->get_geometry_query_engine()->delete_solid_model_entities(start_Point); 06371 if( end_Point ) end_Point->get_geometry_query_engine()->delete_solid_model_entities(end_Point); 06372 return 0; 06373 } 06374 06375 // Check 1/4 and 3/4 location - make sure on surface 06376 CubitVector check_loc; 06377 if( curve_ptr->position_from_fraction( .25, check_loc ) == CUBIT_FAILURE ) 06378 { 06379 curve_ptr->get_geometry_query_engine()->delete_solid_model_entities(curve_ptr ); 06380 return 0; 06381 } 06382 06383 // Now make sure within GEOMETRY_RESABS to the surface 06384 if( is_point_on_surface( surf_ptr, check_loc, resabs ) == CUBIT_FALSE ) 06385 { 06386 curve_ptr->get_geometry_query_engine()->delete_solid_model_entities(curve_ptr ); 06387 return 0; 06388 } 06389 06390 if( curve_ptr->position_from_fraction( .75, check_loc ) == CUBIT_FAILURE ) 06391 { 06392 curve_ptr->get_geometry_query_engine()->delete_solid_model_entities(curve_ptr ); 06393 return 0; 06394 } 06395 06396 // Now make sure within GEOMETRY_RESABS to the surface 06397 if( is_point_on_surface( surf_ptr, check_loc, resabs ) == CUBIT_FALSE ) 06398 { 06399 curve_ptr->get_geometry_query_engine()->delete_solid_model_entities(curve_ptr ); 06400 return 0; 06401 } 06402 06403 return curve_ptr; 06404 } 06405 06406 Curve * 06407 SplitSurfaceTool::check_if_arc( GeometryModifyEngine *gme, 06408 Surface *surf_ptr, 06409 DLIList<CubitVector*> &point_list, 06410 CubitVector &start_pnt, 06411 CubitVector &mid_pnt, 06412 CubitVector &end_pnt, 06413 double resabs, 06414 double tolerance, 06415 double &deviation ) 06416 { 06417 // Check if 3 points are colinear 06418 double a = (start_pnt-mid_pnt).length(); 06419 double b = (mid_pnt-end_pnt).length(); 06420 double c = (end_pnt-start_pnt).length(); 06421 06422 double denom = sqrt((a+b+c)*(b+c-a)*(c+a-b)*(a+b-c)); 06423 if( denom < GEOMETRY_RESABS ) 06424 { 06425 deviation = 99999.0; 06426 return 0; 06427 } 06428 06429 // Create an actual arc and do some comparisons 06430 06431 TBPoint *start_Point = gme->make_Point( start_pnt ); 06432 TBPoint *end_Point = gme->make_Point( end_pnt ); 06433 TBPoint *mid_Point = gme->make_Point( mid_pnt ); 06434 if( start_Point == NULL || mid_Point == NULL || end_Point == NULL ) 06435 { 06436 if( start_Point ) start_Point->get_geometry_query_engine()->delete_solid_model_entities(start_Point); 06437 if( mid_Point ) mid_Point->get_geometry_query_engine()->delete_solid_model_entities(mid_Point); 06438 if( end_Point ) end_Point->get_geometry_query_engine()->delete_solid_model_entities(end_Point); 06439 return 0; 06440 } 06441 06442 // Create a 3-pt arc with the GeometryModifyEngine 06443 Curve *curve_ptr = gme->create_arc_three( start_Point, 06444 mid_Point, 06445 end_Point ); 06446 06447 if( mid_Point ) mid_Point->get_geometry_query_engine()->delete_solid_model_entities(mid_Point); 06448 06449 if( curve_ptr == NULL ) 06450 { 06451 if( start_Point ) start_Point->get_geometry_query_engine()->delete_solid_model_entities(start_Point); 06452 if( end_Point ) end_Point->get_geometry_query_engine()->delete_solid_model_entities(end_Point); 06453 return 0; 06454 } 06455 06456 // Now check all points to see if they are within tolerance to the arc 06457 // At the same time, check to make sure that each point on the arc is 06458 // within GEOMETRY_RESABS of the surface (otherwise an imprint will likely 06459 // not occur). 06460 int i; 06461 CubitVector closest_loc; 06462 point_list.reset(); 06463 double max_deviation = -1.0; 06464 for( i=point_list.size(); i--; ) 06465 { 06466 CubitVector *vec_ptr = point_list.get_and_step(); 06467 if( curve_ptr->closest_point( *vec_ptr, closest_loc ) == CUBIT_FAILURE ) 06468 { 06469 curve_ptr->get_geometry_query_engine()->delete_solid_model_entities(curve_ptr ); 06470 return 0; 06471 } 06472 06473 deviation = vec_ptr->distance_between( closest_loc ); 06474 if( deviation > max_deviation ) 06475 max_deviation = deviation; 06476 06477 if( deviation > tolerance ) 06478 { 06479 curve_ptr->get_geometry_query_engine()->delete_solid_model_entities(curve_ptr ); 06480 return 0; 06481 } 06482 06483 // Now make sure within GEOMETRY_RESABS (actually resbas) to the surface 06484 if( is_point_on_surface( surf_ptr, closest_loc, resabs ) == CUBIT_FALSE ) 06485 { 06486 curve_ptr->get_geometry_query_engine()->delete_solid_model_entities(curve_ptr ); 06487 return 0; 06488 } 06489 } 06490 06491 deviation = max_deviation; 06492 return curve_ptr; 06493 } 06494 06495 CubitStatus 06496 SplitSurfaceTool::reflect_arc_pnt( CubitVector &vec1, 06497 CubitVector &vec2, 06498 CubitVector &vec3, 06499 CubitVector &pnt_to_reflect, 06500 CubitVector &out_pnt ) 06501 06502 { 06503 double a = (vec1-vec2).length(); 06504 double b = (vec2-vec3).length(); 06505 double c = (vec3-vec1).length(); 06506 06507 double denom = sqrt((a+b+c)*(b+c-a)*(c+a-b)*(a+b-c)); 06508 if(denom < GEOMETRY_RESABS ) 06509 return CUBIT_FAILURE; 06510 06511 AnalyticGeometryTool *agt = AnalyticGeometryTool::instance(); 06512 06513 // Find the circle radius 06514 double rad = (a*b*c)/denom; 06515 06516 // Find a coordinate system in the plane of the arc 06517 // Start by getting normal to arc 06518 CubitVector z = (vec1-vec2)*(vec2-vec3); 06519 z.normalize(); 06520 CubitVector x; 06521 CubitVector y; 06522 z.orthogonal_vectors( x,y ); 06523 06524 // Now we are going to transform the points to a local coordinate 06525 // system in the plane of the arc - thats where we can work to 06526 // determine the equation of the circle (in 2D). 06527 double mtx_global_to_local[4][4]; 06528 double mtx_local_to_global[4][4]; 06529 06530 double xt[3], yt[3], zt[3], origint[3]; 06531 agt->copy_pnt( x, xt ); 06532 agt->copy_pnt( y, yt ); 06533 agt->copy_pnt( z, zt ); 06534 agt->copy_pnt( vec1, origint ); 06535 06536 agt->vecs_to_mtx( xt, yt, zt, origint, mtx_local_to_global ); 06537 agt->inv_trans_mtx( mtx_local_to_global, mtx_global_to_local ); 06538 06539 double vec1_loc[3], vec2_loc[3], vec3_loc[3]; 06540 agt->copy_pnt( vec1, vec1_loc ); 06541 agt->copy_pnt( vec2, vec2_loc ); 06542 agt->copy_pnt( vec3, vec3_loc ); 06543 06544 agt->transform_pnt( mtx_global_to_local, vec1_loc, vec1_loc ); 06545 agt->transform_pnt( mtx_global_to_local, vec2_loc, vec2_loc ); 06546 agt->transform_pnt( mtx_global_to_local, vec3_loc, vec3_loc ); 06547 06548 // PRINT_INFO( "vec1_loc = %f, %f, %f\n", vec1_loc[0], vec1_loc[1], vec1_loc[2] ); 06549 // PRINT_INFO( "vec2_loc = %f, %f, %f\n", vec2_loc[0], vec2_loc[1], vec2_loc[2] ); 06550 // PRINT_INFO( "vec3_loc = %f, %f, %f\n", vec3_loc[0], vec3_loc[1], vec3_loc[2] ); 06551 06552 double x_1 = vec1_loc[0]; 06553 double y_1 = vec1_loc[1]; 06554 double x_2 = vec2_loc[0]; 06555 double y_2 = vec2_loc[1]; 06556 double x_3 = vec3_loc[0]; 06557 double y_3 = vec3_loc[1]; 06558 06559 double N_1_mat[2][2]; 06560 N_1_mat[0][0] = (x_2*x_2 + y_2*y_2-(x_1*x_1 + y_1*y_1)); 06561 N_1_mat[0][1] = y_2-y_1; 06562 N_1_mat[1][0] = (x_3*x_3 + y_3*y_3-(x_1*x_1 + y_1*y_1)); 06563 N_1_mat[1][1] = y_3-y_1; 06564 double N_2_mat[2][2]; 06565 N_2_mat[0][0] = x_2-x_1; 06566 N_2_mat[0][1] = (x_2*x_2 + y_2*y_2-(x_1*x_1 + y_1*y_1)); 06567 N_2_mat[1][0] = x_3-x_1; 06568 N_2_mat[1][1] = (x_3*x_3 + y_3*y_3-(x_1*x_1 + y_1*y_1)); 06569 double D_mat[2][2]; 06570 D_mat[0][0] = x_2-x_1; 06571 D_mat[0][1] = y_2-y_1; 06572 D_mat[1][0] = x_3-x_1; 06573 D_mat[1][1] = y_3-y_1; 06574 06575 double N_1 = N_1_mat[0][0]*N_1_mat[1][1] - N_1_mat[0][1]*N_1_mat[1][0]; 06576 double N_2 = N_2_mat[0][0]*N_2_mat[1][1] - N_2_mat[0][1]*N_2_mat[1][0]; 06577 double D = D_mat[0][0]*D_mat[1][1] - D_mat[0][1]*D_mat[1][0]; 06578 06579 double center_loc[3]; 06580 center_loc[0] = N_1/(2.0*D); 06581 center_loc[1] = N_2/(2.0*D); 06582 center_loc[2] = 0.0; 06583 06584 // double centert[3]; 06585 // agt->transform_pnt( mtx_local_to_global, center_loc, centert ); 06586 // 06587 // CubitVector center( centert ); 06588 // PRINT_INFO( "Arc Center = %f, %f, %f\n", center.x(), center.y(), center.z() ); 06589 // 06590 // GfxDebug::draw_point( center, CUBIT_BLUE_INDEX ); 06591 06592 // Now that we have the center, it is simple matter to find the reflected 06593 // point from pnt_to_reflect by traversing 2*rad along a vector from 06594 // pnt_to_reflect to center. 06595 double pnt_to_reflectt[3]; 06596 agt->copy_pnt( pnt_to_reflect, pnt_to_reflectt ); 06597 double pnt_to_reflect_loc[3]; 06598 agt->transform_pnt( mtx_global_to_local, pnt_to_reflectt, pnt_to_reflect_loc ); 06599 double trav_vec[3]; 06600 if( agt->get_vec( pnt_to_reflect_loc, center_loc, trav_vec ) == CUBIT_FAILURE ) 06601 return CUBIT_FAILURE; 06602 06603 agt->unit_vec( trav_vec, trav_vec ); 06604 06605 double ref_pnt_loc[3]; 06606 agt->next_pnt( pnt_to_reflect_loc, trav_vec, 2.0*rad, ref_pnt_loc ); 06607 06608 // Now transform this point to the global csys 06609 double ref_pntt[3]; 06610 agt->transform_pnt( mtx_local_to_global, ref_pnt_loc, ref_pntt ); 06611 06612 out_pnt.set( ref_pntt[0], ref_pntt[1], ref_pntt[2] ); 06613 06614 return CUBIT_SUCCESS; 06615 } 06616 06617 CubitBoolean 06618 SplitSurfaceTool::is_point_on_surface( Surface *surf_ptr, CubitVector &pnt, 06619 double resabs ) 06620 { 06621 // Make sure within GEOMETRY_RESABS to the surface 06622 CubitVector closest_loc_on_surf; 06623 if( surf_ptr->closest_point( pnt, &closest_loc_on_surf ) == CUBIT_FAILURE ) 06624 return CUBIT_FALSE; 06625 06626 double dist = pnt.distance_between( closest_loc_on_surf ); 06627 if( dist > resabs ) // Was GEOMETRY_RESABS 06628 return CUBIT_FALSE; 06629 06630 return CUBIT_TRUE; 06631 } 06632 06633 int 06634 SplitSurfaceTool::count_surfaces_in_owning_body( RefFace *ref_face_ptr, 06635 Body *&body_ptr ) 06636 { 06637 // Returns: Number of surfaces in the owning body of the RefFace 06638 // -1 - RefFace is free (no owning body) 06639 // -2 - RefFace is owned by more than one body 06640 body_ptr = 0; 06641 DLIList<Body*> body_list; 06642 06643 ref_face_ptr->bodies( body_list ); 06644 if( body_list.size() == 0 ) 06645 return -1; 06646 else if( body_list.size() > 1 ) 06647 return -2; 06648 06649 body_ptr = body_list.get(); 06650 DLIList<RefFace*> ref_face_list; 06651 body_ptr->ref_faces( ref_face_list ); 06652 return ref_face_list.size(); 06653 } 06654 06655 int 06656 SplitSurfaceTool::count_surfaces_in_body( Body *body_ptr ) 06657 { 06658 // Return number of surfaces in the body 06659 DLIList<RefFace*> ref_face_list; 06660 body_ptr->ref_faces( ref_face_list ); 06661 return ref_face_list.size(); 06662 } 06663 06664 int 06665 SplitSurfaceTool::count_curves_in_body( Body *body_ptr ) 06666 { 06667 // Return number of edges in the body 06668 DLIList<RefEdge*> ref_edge_list; 06669 body_ptr->ref_edges( ref_edge_list ); 06670 return ref_edge_list.size(); 06671 } 06672 06673 CubitStatus 06674 SplitSurfaceTool::split_surfaces_extend( DLIList<RefFace*> &ref_face_list, 06675 DLIList<RefVertex*> &ref_vertex_list, 06676 CubitBoolean preview_flg, 06677 CubitBoolean create_ref_edges_flg ) 06678 { 06679 // In the below code, "manual" mode refers to when vertices are passed in. In 06680 // this mode, an extension must occur from each given vertex for success. 06681 // "Auto" mode refers to when no vertices are passed in. In this mode the 06682 // vertices (curves to extend) are found automatically - the ends of 06683 // hardlines. Only in auto mode are the gap threshold and normal settings 06684 // valid. 06685 int i, j; 06686 RefFace *ref_face_ptr = NULL; 06687 RefVertex *ref_vertex_ptr = NULL; 06688 GeometryModifyEngine *gme = NULL; 06689 TDSplitSurfaceExtend *tdsse = NULL; 06690 06691 // Clear previous graphics previews 06692 GfxPreview::clear(); 06693 06694 CubitBoolean auto_flg = CUBIT_TRUE; 06695 if( ref_vertex_list.size() ) 06696 auto_flg = CUBIT_FALSE; 06697 06698 // Copy input face list since we don't want to modify it 06699 DLIList<RefFace*> copied_ref_face_list = ref_face_list; 06700 06701 // Check for errors 06702 copied_ref_face_list.reset(); 06703 for( i=copied_ref_face_list.size(); i--; ) 06704 { 06705 ref_face_ptr = copied_ref_face_list.get(); 06706 06707 // Check for free and merged surfaces... for both manual and auto cases. 06708 // (we make this fatal for the auto case too since the user can correct 06709 // these and may not even know about them) 06710 DLIList<Body*> body_list; 06711 ref_face_ptr->bodies( body_list ); 06712 if( body_list.size()==0 ) 06713 { 06714 PRINT_ERROR( "Surface %d is not contained within a parent body.\n" 06715 " It cannot be split.\n", ref_face_ptr->id() ); 06716 return CUBIT_FAILURE; 06717 } 06718 else if( body_list.size() > 1 ) 06719 { 06720 PRINT_ERROR( "Surface %d is merged and cannot be split.\n", 06721 ref_face_ptr->id() ); 06722 return CUBIT_FAILURE; 06723 } 06724 06725 // Check for nonplanar surface. For auto case, just remove these, but 06726 // for manual case, give a fatal error. 06727 if( ref_face_ptr->is_planar() == CUBIT_FALSE ) 06728 { 06729 if( auto_flg == CUBIT_TRUE ) 06730 { 06731 copied_ref_face_list.change_to( NULL ); 06732 copied_ref_face_list.step(); 06733 continue; 06734 } 06735 else 06736 { 06737 // Error out 06738 PRINT_ERROR( "The 'split across extend' command only works on planar surfaces.\n" 06739 " Surface %d is nonplanar\n", ref_face_ptr->id() ); 06740 return CUBIT_FAILURE; 06741 } 06742 } 06743 copied_ref_face_list.step(); 06744 } 06745 06746 copied_ref_face_list.remove_all_with_value( NULL ); 06747 06748 // If we don't have any faces left, we exit (could only occur for auto case... 06749 // make this a warning instead of an error). 06750 if( !copied_ref_face_list.size() ) 06751 { 06752 PRINT_WARNING( "No valid surfaces found to be split. Note to be split, they\n" 06753 " must be nonplanar, contained in a body, and not merged.\n" ); 06754 return CUBIT_SUCCESS; 06755 } 06756 06757 // Mark each of the input vertices with a tooldata 06758 ref_vertex_list.reset(); 06759 for( i=ref_vertex_list.size(); i--; ) 06760 { 06761 ref_vertex_ptr = ref_vertex_list.get_and_step(); 06762 ref_vertex_ptr->add_TD( new TDSplitSurfaceExtend() ); 06763 } 06764 06765 // Store list of faces and new curves sorted by body and face 06766 DLIList<DLIList<Surface*>*> body_surf_list_list; 06767 DLIList<DLIList<DLIList<Curve*>*>*> curve_lists_lists_list; 06768 06769 // Store ids of Curves that are extended 06770 DLIList<int> ext_curve_ids; 06771 06772 // Operate by common body - pull faces out of the input face list that are 06773 // from a common Body and place them in a separate list (split_face_list). 06774 Body *curr_Body_ptr; 06775 while( copied_ref_face_list.size() ) 06776 { 06777 DLIList<RefFace*> split_face_list; // Holds faces from common body 06778 06779 // Store new curves for this body, sorted by face 06780 DLIList<DLIList<Curve*>*> *curve_lists_list_ptr; 06781 curve_lists_list_ptr = new DLIList<DLIList<Curve*>*>; 06782 curve_lists_lists_list.append( curve_lists_list_ptr ); 06783 06784 curr_Body_ptr = NULL; 06785 06786 copied_ref_face_list.reset(); 06787 for( i=copied_ref_face_list.size(); i--; ) 06788 { 06789 ref_face_ptr = copied_ref_face_list.get(); 06790 06791 DLIList<Body*> body_list; 06792 ref_face_ptr->bodies( body_list ); 06793 06794 if( curr_Body_ptr == NULL ) 06795 curr_Body_ptr = body_list.get(); 06796 06797 if( curr_Body_ptr == body_list.get() ) 06798 { 06799 split_face_list.append( ref_face_ptr ); 06800 copied_ref_face_list.change_to( NULL ); 06801 } 06802 06803 copied_ref_face_list.step(); 06804 } 06805 06806 copied_ref_face_list.remove_all_with_value( NULL ); 06807 06808 DLIList<Surface*> *body_surf_list_ptr; 06809 body_surf_list_ptr = new DLIList<Surface*>; 06810 body_surf_list_list.append( body_surf_list_ptr ); 06811 06812 // Loop through each face on the common body 06813 RefFace *split_face_ptr; 06814 DLIList<Curve*> *curve_list_ptr; 06815 split_face_list.reset(); 06816 for( i=split_face_list.size(); i--; ) 06817 { 06818 split_face_ptr = split_face_list.get_and_step(); 06819 body_surf_list_ptr->append( split_face_ptr->get_surface_ptr() ); 06820 06821 curve_list_ptr = new DLIList<Curve*>; 06822 curve_lists_list_ptr->append( curve_list_ptr ); 06823 06824 // Get the RefEdges to fire a ray at (from surface) 06825 DLIList<RefEdge*> ref_edge_list; 06826 split_face_ptr->ref_edges( ref_edge_list ); 06827 DLIList<RefEntity*> at_entity_list; 06828 CAST_LIST( ref_edge_list, at_entity_list, RefEntity ); 06829 06830 // Fire a ray from each vertex in an outward direction from the tangent 06831 // of the owning curve at the at_entity_list 06832 DLIList<RefVertex*> tmp_vertex_list; 06833 split_face_ptr->ref_vertices( tmp_vertex_list ); 06834 06835 tmp_vertex_list.reset(); 06836 for( j=tmp_vertex_list.size(); j--; ) 06837 { 06838 ref_vertex_ptr = tmp_vertex_list.get_and_step(); 06839 06840 // The vertex must be part of the surface being considered, plus 06841 // the attached curve must be on the surface. We must have one and 06842 // only one attached curve. This curve must be linear. 06843 06844 // For manual case, only consider vertices that are in the input list 06845 if( auto_flg == CUBIT_FALSE ) 06846 { 06847 tdsse = (TDSplitSurfaceExtend *)ref_vertex_ptr-> 06848 get_TD(&TDSplitSurfaceExtend::is_split_surface_extend); 06849 if( !tdsse ) continue; 06850 } 06851 06852 // Get attached RefEdges to this vertex 06853 DLIList<RefEdge*> att_ref_edge_list; 06854 ref_vertex_ptr->ref_edges( att_ref_edge_list ); 06855 06856 RefEdge *extend_edge_ptr = 0; 06857 RefEdge *ref_edge_ptr; 06858 int k; 06859 for( k=att_ref_edge_list.size(); k--; ) 06860 { 06861 ref_edge_ptr = att_ref_edge_list.get_and_step(); 06862 if( ref_edge_ptr->is_directly_related( split_face_ptr ) ) 06863 { 06864 if( !extend_edge_ptr ) 06865 extend_edge_ptr = ref_edge_ptr; 06866 else 06867 { 06868 extend_edge_ptr = 0; 06869 break; 06870 } 06871 } 06872 } 06873 06874 if( !extend_edge_ptr ) 06875 continue; 06876 06877 // For now, limit this to linear curves. Technically, we should be able 06878 // to extend non-linear curves though. 06879 Curve *curve_ptr = extend_edge_ptr->get_curve_ptr(); 06880 if( curve_ptr->geometry_type() != STRAIGHT_CURVE_TYPE ) 06881 continue; 06882 06883 RefVertex *start_vertex_ptr, *end_vertex_ptr; 06884 06885 start_vertex_ptr = extend_edge_ptr->start_vertex(); 06886 end_vertex_ptr = extend_edge_ptr->end_vertex(); 06887 06888 DLIList<double> ray_params; 06889 CubitVector start_loc = ref_vertex_ptr->coordinates(); 06890 06891 // Find direction to fire ray 06892 CubitVector ray_dir; 06893 06894 if( ref_vertex_ptr == start_vertex_ptr ) 06895 ray_dir = start_vertex_ptr->coordinates() - 06896 end_vertex_ptr->coordinates(); 06897 else 06898 ray_dir = end_vertex_ptr->coordinates() - 06899 start_vertex_ptr->coordinates(); 06900 06901 ray_dir.normalize(); 06902 06903 // Remove the curve being extended from the at_entity_list 06904 DLIList<RefEntity*> tmp_at_entity_list = at_entity_list; 06905 tmp_at_entity_list.remove_all_with_value( extend_edge_ptr ); 06906 06907 // Fire the ray, asking for only one hit 06908 DLIList<RefEntity*> hit_entity_list; 06909 if( GeometryQueryTool::instance()->fire_ray( start_loc, ray_dir, 06910 tmp_at_entity_list, ray_params, 1, 0.0, &hit_entity_list ) 06911 == CUBIT_FAILURE || 06912 ray_params.size() == 0 || ray_params.get() == 0.0 ) 06913 continue; 06914 06915 //PRINT_INFO( "Got hit from vertex %d on surface %d at distance %lf\n", 06916 // ref_vertex_ptr->id(), split_face_ptr->id(), ray_params.get() ) 06917 06918 CubitVector end_loc; 06919 double ray_param = ray_params.get(); 06920 06921 // Note the hit entity could be a curve or a vertex 06922 RefEntity *hit_entity_ptr = 0; 06923 RefEdge *hit_edge_ptr = 0; 06924 if( hit_entity_list.size() ) // In case fire_ray didn't return hit ents 06925 { 06926 hit_entity_ptr = hit_entity_list.get(); 06927 hit_edge_ptr = CAST_TO( hit_entity_ptr, RefEdge ); 06928 } 06929 06930 if( extendNormalFlg == CUBIT_TRUE ) 06931 { 06932 // Try going normal to the curve hit. 06933 double norm_dist = CUBIT_DBL_MAX; 06934 06935 if( hit_edge_ptr ) 06936 { 06937 hit_edge_ptr->closest_point( start_loc, end_loc ); 06938 06939 // Only valid if end_loc is ON the curve 06940 CubitPointContainment contain = hit_edge_ptr-> 06941 point_containment( end_loc ); 06942 06943 if( contain != CUBIT_PNT_ON ) 06944 { 06945 // find the nearest curve which the vertex can be extended to and normal 06946 RefEdge* new_edge_ptr = NULL; 06947 CubitVector new_end_loc; 06948 find_nearest_curve_for_normal_projection( 06949 hit_edge_ptr, start_loc, split_face_ptr, ray_dir, new_edge_ptr, new_end_loc); 06950 06951 if (new_edge_ptr) 06952 { 06953 hit_edge_ptr = new_edge_ptr; 06954 end_loc = new_end_loc; 06955 } 06956 } 06957 06958 norm_dist = start_loc.distance_between( end_loc ); 06959 } 06960 06961 // Use shortest distance between closest normal and ray_param 06962 if( ray_param < norm_dist ) 06963 start_loc.next_point( ray_dir, ray_param, end_loc ); 06964 } 06965 else 06966 // Use ray_dir along ray 06967 start_loc.next_point( ray_dir, ray_param, end_loc ); 06968 06969 // For auto mode, check to see if we are out of the extendGapThreshold 06970 if( auto_flg && 06971 ( start_loc.distance_between( end_loc ) > extendGapThreshold ) ) 06972 continue; 06973 06974 // Check for close vertex 06975 if( hit_edge_ptr ) 06976 { 06977 double arc_length; 06978 06979 // Check distance to start of curve 06980 arc_length = hit_edge_ptr->get_arc_length( end_loc, 0 ); 06981 06982 if( arc_length <= extendTolerance ) 06983 { 06984 end_loc = hit_edge_ptr->start_coordinates(); 06985 PRINT_INFO( "Snapping to close vertex for curve %d extended from vertex %d\n", 06986 extend_edge_ptr->id(), ref_vertex_ptr->id() ); 06987 } 06988 else 06989 { 06990 // Check distance to end of curve 06991 arc_length = hit_edge_ptr->get_arc_length( end_loc, 1 ); 06992 06993 if( arc_length <= extendTolerance ) 06994 { 06995 end_loc = hit_edge_ptr->end_coordinates(); 06996 PRINT_INFO( "Snapping to close vertex for curve %d extended from vertex %d\n", 06997 extend_edge_ptr->id(), ref_vertex_ptr->id() ); 06998 } 06999 } 07000 } 07001 07002 curve_ptr = NULL; 07003 07004 // Create curve (from start_vec to end_vec) 07005 Surface *surf_ptr = split_face_ptr->get_surface_ptr(); 07006 07007 gme = GeometryModifyTool::instance()->get_engine( surf_ptr ); 07008 if( gme == NULL ) 07009 { 07010 PRINT_ERROR("No geometry modify engine available for surface %d\n" 07011 " Unable to create split curve.\n", split_face_ptr->id()); 07012 // Remove tooldatas and free memory 07013 cleanup_for_extend_op( ref_vertex_list, body_surf_list_list, 07014 curve_lists_lists_list ); 07015 return CUBIT_FAILURE; 07016 } 07017 07018 // Create a straight line on the surface 07019 TBPoint *start_Point = gme->make_Point( start_loc ); 07020 TBPoint *end_Point = gme->make_Point( end_loc ); 07021 if( start_Point == NULL || end_Point == NULL ) 07022 { 07023 PRINT_ERROR("Unable to create points for curve on surface %d\n", 07024 split_face_ptr->id() ); 07025 // Remove tooldatas and free memory 07026 cleanup_for_extend_op( ref_vertex_list, body_surf_list_list, 07027 curve_lists_lists_list ); 07028 return CUBIT_FAILURE; 07029 } 07030 curve_ptr = gme->make_Curve( start_Point, end_Point, surf_ptr ); 07031 if( !curve_ptr ) 07032 { 07033 PRINT_ERROR( "Unable to create split curve from vertex %d on surface %d\n", 07034 ref_vertex_ptr->id(), split_face_ptr->id() ); 07035 // Remove tooldatas and free memory 07036 cleanup_for_extend_op( ref_vertex_list, body_surf_list_list, 07037 curve_lists_lists_list ); 07038 return CUBIT_FAILURE; 07039 } 07040 07041 curve_list_ptr->append( curve_ptr ); 07042 07043 // Keep track of which curves are extended 07044 ext_curve_ids.append( extend_edge_ptr->id() ); 07045 07046 if( tdsse ) 07047 tdsse->set_success(); 07048 } 07049 07050 } 07051 07052 curr_Body_ptr = 0; 07053 } 07054 07055 // For manual mode, check to make sure that all vertices had success, 07056 // otherwise, this is an error. Note... vertices seem to live through 07057 // these operations. 07058 DLIList<int> vertex_id_list; 07059 for( i=ref_vertex_list.size(); i--; ) 07060 { 07061 ref_vertex_ptr = ref_vertex_list.get_and_step(); 07062 07063 tdsse = (TDSplitSurfaceExtend *)ref_vertex_ptr-> 07064 get_TD(&TDSplitSurfaceExtend::is_split_surface_extend); 07065 07066 if( !tdsse ) continue; 07067 07068 if( !tdsse->is_success() ) 07069 vertex_id_list.append( ref_vertex_ptr->id() ); 07070 } 07071 if( vertex_id_list.size() ) 07072 { 07073 if( vertex_id_list.size() == 1 ) 07074 PRINT_ERROR( "Unable to extend from vertex %d\n", ref_vertex_ptr->id() ); 07075 else 07076 { 07077 PRINT_ERROR( "Unable to extend from vertices\n" ); 07078 CubitUtil::list_entity_ids( " Problem vertices: ", vertex_id_list ); 07079 } 07080 PRINT_INFO( " Vertices must be at the end of only one curve on the surface to split,\n" 07081 " extended curves must be linear, and surfaces to split must be planar.\n" ); 07082 07083 // Remove tooldatas and free memory 07084 cleanup_for_extend_op( ref_vertex_list, body_surf_list_list, 07085 curve_lists_lists_list ); 07086 return CUBIT_FAILURE; 07087 } 07088 07089 // Give message as to which curves were extended 07090 char msg[50]; 07091 if( ext_curve_ids.size() ) 07092 { 07093 // Remove duplicates (curves extended from both ends) 07094 ext_curve_ids.uniquify_ordered(); 07095 07096 // Give a nice message 07097 if( ext_curve_ids.size() == 1 ) 07098 CubitUtil::list_entity_ids( "1 curve extended: ", ext_curve_ids ); 07099 else 07100 { 07101 sprintf( msg, "%d curves extended: ", ext_curve_ids.size() ); 07102 CubitUtil::list_entity_ids( msg, ext_curve_ids ); 07103 } 07104 } 07105 else 07106 { 07107 // Might as well exit 07108 PRINT_INFO( "No curves found to extend\n" ); 07109 // Remove tooldatas and free memory 07110 cleanup_for_extend_op( ref_vertex_list, body_surf_list_list, 07111 curve_lists_lists_list ); 07112 return CUBIT_SUCCESS; 07113 } 07114 07115 // Do the splitting 07116 DLIList<Surface*> *surf_list_ptr; 07117 DLIList<DLIList<Curve*>*> *curve_lists_list_ptr; 07118 body_surf_list_list.reset(); 07119 curve_lists_lists_list.reset(); 07120 if( preview_flg==CUBIT_FALSE && create_ref_edges_flg==CUBIT_FALSE ) 07121 { 07122 for( i=body_surf_list_list.size(); i--; ) 07123 { 07124 surf_list_ptr = body_surf_list_list.get_and_step(); 07125 curve_lists_list_ptr = curve_lists_lists_list.get_and_step(); 07126 07127 Body *new_body_ptr; 07128 if( GeometryModifyTool::instance()->imprint( *surf_list_ptr, 07129 *curve_lists_list_ptr, new_body_ptr ) == CUBIT_FAILURE ) 07130 { 07131 // Remove tooldatas and free memory 07132 cleanup_for_extend_op( ref_vertex_list, body_surf_list_list, 07133 curve_lists_lists_list ); 07134 return CUBIT_FAILURE; 07135 } 07136 } 07137 } 07138 else if( preview_flg==CUBIT_TRUE && create_ref_edges_flg==CUBIT_TRUE ) 07139 { 07140 // Just create the RefEdges 07141 DLIList<RefEdge*> new_ref_edge_list; 07142 curve_lists_lists_list.reset(); 07143 07144 for( i=curve_lists_lists_list.size(); i--; ) 07145 { 07146 curve_lists_list_ptr = curve_lists_lists_list.get_and_step(); 07147 07148 curve_lists_list_ptr->reset(); 07149 for( j=curve_lists_list_ptr->size(); j--; ) 07150 { 07151 DLIList<Curve*> *curve_list_ptr = curve_lists_list_ptr->get_and_step(); 07152 curve_list_ptr->reset(); 07153 07154 create_ref_edges( *curve_list_ptr, new_ref_edge_list ); 07155 } 07156 } 07157 // Let the user know about the new curves created 07158 if( new_ref_edge_list.size() ) 07159 { 07160 DLIList<CubitEntity*> cubit_entity_list; 07161 CAST_LIST( new_ref_edge_list, cubit_entity_list, CubitEntity ); 07162 CubitUtil::list_entity_ids( "Created new curves: ", cubit_entity_list ); 07163 } 07164 } 07165 else 07166 { 07167 // Just preview 07168 for( i=body_surf_list_list.size(); i--; ) 07169 { 07170 curve_lists_list_ptr = curve_lists_lists_list.get_and_step(); 07171 07172 curve_lists_list_ptr->reset(); 07173 for( j=curve_lists_list_ptr->size(); j--; ) 07174 { 07175 DLIList<Curve*> *curve_list_ptr = curve_lists_list_ptr->get_and_step(); 07176 07177 // Draw the curves 07178 draw_preview( *curve_list_ptr ); 07179 } 07180 } 07181 } 07182 07183 // Flush the graphics 07184 GfxPreview::flush(); 07185 07186 // Remove tooldatas and free memory 07187 cleanup_for_extend_op( ref_vertex_list, body_surf_list_list, 07188 curve_lists_lists_list ); 07189 07190 return CUBIT_SUCCESS; 07191 } 07192 07193 void 07194 SplitSurfaceTool::cleanup_for_extend_op( DLIList<RefVertex*> &ref_vertex_list, 07195 DLIList<DLIList<Surface*>*> &body_surf_list_list, 07196 DLIList<DLIList<DLIList<Curve*>*>*> &curve_lists_lists_list, 07197 CubitBoolean free_curves_flg ) 07198 { 07199 int i; 07200 RefVertex *ref_vertex_ptr; 07201 07202 // Remove tooldatas from vertices 07203 ref_vertex_list.reset(); 07204 for( i=ref_vertex_list.size(); i--; ) 07205 { 07206 ref_vertex_ptr = ref_vertex_list.get_and_step(); 07207 ref_vertex_ptr->delete_TD( &TDSplitSurfaceExtend::is_split_surface_extend ); 07208 } 07209 07210 // Free allocated lists in body_surf_list_list 07211 while( body_surf_list_list.size() ) delete body_surf_list_list.pop(); 07212 07213 // Free allocated lists in curve_list_lists_list, as well as Curves (if not 07214 // attached to RefEdges). 07215 DLIList<DLIList<Curve*>*> *curve_list_lists_ptr; 07216 for( i=curve_lists_lists_list.size(); i--; ) 07217 { 07218 curve_list_lists_ptr = curve_lists_lists_list.get(); 07219 07220 free_curves_lists( *curve_list_lists_ptr ); 07221 delete curve_list_lists_ptr; 07222 07223 curve_lists_lists_list.step(); 07224 } 07225 07226 return; 07227 } 07228 07229 void SplitSurfaceTool::find_nearest_curve_for_normal_projection( 07230 RefEdge* hit_edge_ptr, CubitVector& start_loc, 07231 RefFace* face, CubitVector& ray_dir, RefEdge*& new_edge_ptr, 07232 CubitVector& new_end_loc) 07233 { 07234 // traverse the curves in the surface and find the closest curve to the hardline 07235 // which the hardline can extend normal to 07236 07237 DLIList<RefEdge*> edge_list; 07238 face->ref_edges(edge_list); 07239 07240 std::map<double, std::pair<RefEdge*, CubitVector> > potential_curves_map; 07241 07242 // maybe traverse all curves all of the time, and use the one closest to the point 07243 int i; 07244 for (i=edge_list.size(); i--;) 07245 { 07246 RefEdge* edge = edge_list.get_and_step(); 07247 07248 if (edge == hit_edge_ptr) 07249 continue; 07250 07251 CubitVector closest_point; 07252 edge->closest_point(start_loc, closest_point); 07253 07254 // Only valid if location is ON the curve 07255 CubitPointContainment contain = edge->point_containment( closest_point ); 07256 if( contain == CUBIT_PNT_ON ) 07257 { 07258 // check to make sure angle isn't too bad 07259 // have a user setting for this in the future 07260 // but for now, use 90 degrees 07261 CubitVector split_direction = closest_point - start_loc; 07262 if (split_direction.length_squared() <= GEOMETRY_RESABS) //ignore self 07263 continue; 07264 07265 double angle = ray_dir.interior_angle(split_direction); 07266 if (fabs(angle) <= 90.0) 07267 { 07268 double dist = start_loc.distance_between(closest_point); 07269 potential_curves_map.insert(std::map<double, std::pair<RefEdge*, CubitVector> >::value_type( 07270 dist, std::make_pair(edge, closest_point))); 07271 } 07272 } 07273 } 07274 07275 if (potential_curves_map.size()) 07276 { 07277 std::map<double, std::pair<RefEdge*, CubitVector> >::iterator iter = potential_curves_map.begin(); 07278 new_edge_ptr = (iter->second).first; 07279 new_end_loc = (iter->second).second; 07280 } 07281 07282 return; 07283 }