cgma
|
00001 //------------------------------------------------------------------------- 00002 //- Filename: CollapseAngleTool 00003 //- Purpose: To collapse small angle for preparing for mesh 00004 //- "collapse angle less than <angle> mesh_size <length> [preview]\n", 00005 //- "collapse angle at vertex <id> curve <id> [arc_length <length>] curve 00006 //- <id> [arc_length <length> | perpendicular | same_size | tangent] 00007 //- [preview]\n" 00008 //- 00009 //- Creator: Jiangtao Hu 00010 //- Creation date: 02/09/2005 00011 //------------------------------------------------------------------------- 00012 00013 // ********** BEGIN STANDARD INCLUDES ********** 00014 // ********** END STANDARD INCLUDES ********** 00015 00016 // ********** BEGIN MOTIF INCLUDES ********** 00017 // ********** END MOTIF INCLUDES ********** 00018 00019 // ********** BEGIN CUBIT INCLUDES ********** 00020 00021 #include "GMem.hpp" 00022 #include "GeometryQueryTool.hpp" 00023 #include "GeomMeasureTool.hpp" 00024 #include "RefVolume.hpp" 00025 #include "RefEdge.hpp" 00026 #include "RefFace.hpp" 00027 #include "RefVertex.hpp" 00028 #include "CollapseAngleTool.hpp" 00029 #include "Point.hpp" 00030 #include "CubitBox.hpp" 00031 #include "GfxDebug.hpp" 00032 #include "PartitionTool.hpp" 00033 #include "CubitUtil.hpp" 00034 #include "CompositeTool.hpp" 00035 #include "CubitUndo.hpp" 00036 // ********** END CUBIT INCLUDES ********** 00037 00038 CollapseAngleTool *CollapseAngleTool::instance_ = NULL; 00039 // ********** BEGIN PUBLIC FUNCTIONS ********** 00040 CollapseAngleTool *CollapseAngleTool::instance() 00041 { 00042 if (instance_ == NULL) instance_ = new CollapseAngleTool(); 00043 00044 return instance_; 00045 } 00046 00047 void CollapseAngleTool::collapse_one_angle(RefVertex *vex_ptr, 00048 RefEdge *edge_to_remove, 00049 RefEdge *the_other_edge, 00050 double length1, 00051 double length2, 00052 CubitBoolean get_position, 00053 CubitVector &position, 00054 CubitBoolean preview, 00055 CubitBoolean if_comp_vertex, 00056 double angle) 00057 { 00058 if (CUBIT_TRUE == preview) 00059 draw_preview(vex_ptr, edge_to_remove, the_other_edge, length1, 00060 length2, get_position, position); 00061 else 00062 { 00063 CubitStatus result = CUBIT_SUCCESS; 00064 DLIList<RefFace*> ref_faces; 00065 edge_to_remove->ref_faces(ref_faces); 00066 RefFace *common_face = NULL; 00067 DLIList<RefFace*> common_face_list; 00068 int nfaces = edge_to_remove->num_of_common_ref_face(the_other_edge); 00069 00070 if( nfaces == 0 ) 00071 return; 00072 00073 if (nfaces == 1) 00074 common_face = edge_to_remove->common_ref_face(the_other_edge); 00075 else 00076 edge_to_remove->common_ref_faces(the_other_edge, common_face_list); 00077 00078 if(common_face) 00079 common_face_list.append_unique( common_face ); 00080 00081 bool undo_on = false; 00082 DLIList<Body*> bodies_to_note; 00083 if( CubitUndo::get_undo_enabled() ) 00084 { 00085 for( int k=0; k<common_face_list.size(); k++ ) 00086 bodies_to_note.append_unique( common_face_list[k]->body() ); 00087 00088 CubitUndo::save_state_with_cubit_file( bodies_to_note ); 00089 undo_on = true; 00090 CubitUndo::set_undo_enabled( false ); 00091 } 00092 00093 CubitStatus status = collapse_angle( vex_ptr, edge_to_remove, the_other_edge, 00094 length1, length2, get_position, position); 00095 00096 if( CUBIT_FAILURE == status && undo_on ) 00097 { 00098 CubitUndo::set_undo_enabled( true ); 00099 CubitUndo::remove_last_undo(); 00100 return; 00101 } 00102 00103 if (if_comp_vertex) 00104 { 00105 DLIList<RefEdge*> edge_list; 00106 vex_ptr->ref_edges(edge_list); 00107 if (edge_list.size() == 2) 00108 { 00109 DLIList<RefEdge*> composite_edges; 00110 angle *= (CUBIT_PI / 180); 00111 int id = vex_ptr->id(); 00112 CompositeTool::instance()->composite(edge_list, composite_edges, 00113 NULL, angle); 00114 if (composite_edges.size() > 0) 00115 { 00116 DLIList<int> id_list; 00117 id_list.append(id); 00118 CubitUtil::list_entity_ids("Composite out of vertex ", id_list); 00119 } 00120 } 00121 } 00122 00123 if( undo_on ) 00124 CubitUndo::set_undo_enabled( true ); 00125 00126 if( CubitUndo::get_undo_enabled() && CUBIT_SUCCESS == result ) 00127 CubitUndo::note_result_bodies( bodies_to_note ); 00128 else if( CubitUndo::get_undo_enabled() && CUBIT_FAILURE == result ) 00129 CubitUndo::remove_last_undo(); 00130 } 00131 } 00132 00133 CubitStatus CollapseAngleTool::auto_collapse(double length, 00134 double angle, 00135 CubitBoolean preview, 00136 CubitBoolean if_comp_vertex, 00137 double max_angle) 00138 { 00139 //clear out the partly_drawn_curve list 00140 partly_drawn_curve.clean_out(); 00141 //finding all angles less than 'angle' 00142 DLIList<RefEntity*> entity_list; 00143 DLIList<RefVolume*> volume_list; 00144 RefVolume * ref_volume; 00145 DLIList <RefEdge *> large_edge_angles_list; 00146 DLIList <RefEdge *> small_edge_angles_list; 00147 DLIList <double> large_angles_list; 00148 DLIList <double> small_angles_list; 00149 int total_interior; 00150 int total_fuzzy; 00151 CubitStatus result = CUBIT_SUCCESS; 00152 00153 // get an instance of GeometryQueryTool 00154 GeometryQueryTool *gqt = GeometryQueryTool::instance(); 00155 00156 volume_list.clean_out(); 00157 result = gqt->ref_entity_list("volume", entity_list); 00158 if (result == CUBIT_FAILURE || entity_list.size() < 1) 00159 { 00160 PRINT_ERROR("This command is prepared for volume mesh only.\n" 00161 "The angles must reside on volumes.\n"); 00162 return result; 00163 } 00164 00165 CAST_LIST(entity_list, volume_list, RefVolume); 00166 00167 int i; 00168 small_edge_angles_list.clean_out(); 00169 for (i=0; i < volume_list.size(); i++) 00170 { 00171 ref_volume = volume_list.get_and_step(); 00172 assert (ref_volume != NULL); 00173 GeomMeasureTool::find_interior_curve_angles(ref_volume, 00174 360, 00175 angle, 00176 large_edge_angles_list, 00177 small_edge_angles_list, 00178 large_angles_list, 00179 small_angles_list, 00180 total_interior, 00181 total_fuzzy); 00182 } 00183 00184 //collapse small angles, use perpendicular to the second curve. 00185 int size = small_edge_angles_list.size(); 00186 int init_size = size+1; 00187 int index = 0; 00188 RefVertex *vex_ptr = NULL; 00189 RefEdge *edge_to_remove = NULL; 00190 RefEdge *the_other_edge = NULL; 00191 double length1 = -1.0, length2 = -1.0; 00192 CubitVector position; 00193 00194 CubitBoolean if_step_over = CUBIT_FALSE; 00195 while (size != 0) 00196 { 00197 if (init_size <= size) 00198 break; 00199 init_size = size; 00200 small_edge_angles_list.reset(); 00201 assert (size%2 == 0); 00202 double angle1, angle2; 00203 if (CUBIT_TRUE == preview || CUBIT_TRUE == if_step_over) 00204 { 00205 if_step_over = CUBIT_FALSE; 00206 for (i=0; i<index; i++) 00207 small_edge_angles_list.step(); 00208 } 00209 00210 //find the vertex for each edge pair. 00211 edge_to_remove = small_edge_angles_list.get_and_step(); 00212 the_other_edge = small_edge_angles_list.get_and_step(); 00213 index += 2; 00214 assert (edge_to_remove != NULL && the_other_edge != NULL); 00215 vex_ptr = edge_to_remove->common_ref_vertex(the_other_edge); 00216 if (vex_ptr == NULL) 00217 { 00218 size -= 2; 00219 if_step_over = CUBIT_TRUE; 00220 continue; 00221 } 00222 00223 //check to make sure there's one common refface between the edges. 00224 if(edge_to_remove->num_of_common_ref_face(the_other_edge) != 1) 00225 { 00226 PRINT_INFO("Curves %d and %d are not candidates for collapsing because\n", 00227 edge_to_remove->id(), the_other_edge->id()); 00228 PRINT_INFO("the two curves need to have exactly one common face.\n"); 00229 size -= 2; 00230 if_step_over = CUBIT_TRUE; 00231 continue; 00232 } 00233 00234 //find the true to_be_removed edge 00235 angle1 = the_surface_angle(edge_to_remove, vex_ptr, length); 00236 angle2 = the_surface_angle(the_other_edge, vex_ptr, length); 00237 if (angle1 != -1.0 && angle2 != -1.0 && 00238 (fabs(angle1 - CUBIT_PI) > fabs(angle2 - CUBIT_PI))) 00239 exchange_edges(edge_to_remove, the_other_edge); 00240 else if (angle1 == -1.0 || angle2 == -1.0 || 00241 (fabs(angle1 - CUBIT_PI) == fabs(angle2 - CUBIT_PI))) 00242 { 00243 //curved curve has higher priority than straight curve. 00244 if ((edge_to_remove->geometry_type() == STRAIGHT_CURVE_TYPE) 00245 &&(the_other_edge->geometry_type() != STRAIGHT_CURVE_TYPE)) 00246 exchange_edges(edge_to_remove, the_other_edge); 00247 00248 //shorter curve has higher priority than longer curve. 00249 else if (((edge_to_remove->geometry_type() != STRAIGHT_CURVE_TYPE) 00250 &&(the_other_edge->geometry_type() != STRAIGHT_CURVE_TYPE)) || 00251 ((edge_to_remove->geometry_type() == STRAIGHT_CURVE_TYPE) 00252 &&(the_other_edge->geometry_type() == STRAIGHT_CURVE_TYPE))) 00253 { 00254 if (edge_to_remove->get_arc_length() > 00255 the_other_edge->get_arc_length()) 00256 exchange_edges(edge_to_remove, the_other_edge); 00257 } 00258 }//else if 00259 00260 // determine the length1 00261 if (length >= (edge_to_remove->get_arc_length() - GEOMETRY_RESABS)) 00262 length1 = -1.0; 00263 00264 else 00265 length1 = length; 00266 //determine the position on curve2 00267 RefVertex * tmp_vertex = edge_to_remove->other_vertex(vex_ptr); 00268 CubitVector tmp_vec = tmp_vertex->coordinates(); 00269 if (length1 != -1.0) 00270 { 00271 result = position_from_length(edge_to_remove, vex_ptr, length1, tmp_vec); 00272 } 00273 00274 the_other_edge->closest_point(tmp_vec, position); 00275 00276 //check if position is within the_other_edge 00277 CubitBox position_box(position); 00278 CubitBox edge_box = the_other_edge->bounding_box(); 00279 00280 // check if it's a preview command. 00281 if (CUBIT_TRUE == preview) 00282 { 00283 if (!position_box.overlap(0, edge_box)) 00284 draw_preview(vex_ptr, edge_to_remove, the_other_edge, 00285 length1, -1.0, CUBIT_FALSE, position); 00286 00287 else 00288 draw_preview(vex_ptr, edge_to_remove, the_other_edge, 00289 length1, -1.0, CUBIT_TRUE, position); 00290 size -= 2; 00291 continue; 00292 } 00293 00294 //collapse angle 00295 else if (!position_box.overlap(0, edge_box)) 00296 result = collapse_angle( vex_ptr, edge_to_remove, the_other_edge, 00297 length1, -1.0, CUBIT_FALSE, position); 00298 else 00299 result = collapse_angle( vex_ptr, edge_to_remove, the_other_edge, 00300 length1, length2, CUBIT_TRUE, position); 00301 if (result != CUBIT_SUCCESS) 00302 { 00303 result = CUBIT_SUCCESS; 00304 continue ; 00305 } 00306 00307 if (if_comp_vertex) 00308 { 00309 DLIList<RefEdge*> edge_list; 00310 vex_ptr->ref_edges(edge_list); 00311 int id = vex_ptr->id(); 00312 if (edge_list.size() == 2) 00313 { 00314 DLIList<RefEdge*> composite_edges; 00315 max_angle *= (CUBIT_PI / 180); 00316 CompositeTool::instance()->composite(edge_list, composite_edges, 00317 NULL, max_angle); 00318 if (composite_edges.size() > 0) 00319 { 00320 DLIList<int> id_list; 00321 id_list.append(id); 00322 CubitUtil::list_entity_ids("Composite out of vertex ", id_list); 00323 } 00324 } 00325 } 00326 00327 small_edge_angles_list.clean_out(); 00328 for (i=0; i < volume_list.size(); i++) 00329 { 00330 ref_volume = volume_list.get_and_step(); 00331 assert (ref_volume != NULL); 00332 GeomMeasureTool::find_interior_curve_angles(ref_volume, 00333 360, 00334 angle, 00335 large_edge_angles_list, 00336 small_edge_angles_list, 00337 large_angles_list, 00338 small_angles_list, 00339 total_interior, 00340 total_fuzzy); 00341 } 00342 size = small_edge_angles_list.size(); 00343 }//while 00344 return result; 00345 } 00346 00347 // ********** END PUBLIC FUNCTIONS ********** 00348 00349 // ********** BEGIN PROTECTED FUNCTIONS ********** 00350 // ********** END PROTECTED FUNCTIONS ********** 00351 00352 // ********** BEGIN PRIVATE FUNCTIONS ********** 00353 CollapseAngleTool::CollapseAngleTool() 00354 { 00355 } 00356 00357 CollapseAngleTool::~CollapseAngleTool() 00358 { 00359 } 00360 00361 void CollapseAngleTool::exchange_edges(RefEdge *&edge, 00362 RefEdge *&the_other_edge) 00363 { 00364 RefEdge* temp_edge; 00365 temp_edge = edge; 00366 edge = the_other_edge; 00367 the_other_edge = temp_edge; 00368 } 00369 00370 double CollapseAngleTool::the_surface_angle(RefEdge *edge, 00371 RefVertex *root_vertex, 00372 double length) 00373 { 00374 DLIList <RefFace *> ref_faces; 00375 double arc_length = length/2; 00376 double fraction; 00377 00378 if (length > edge->get_arc_length()) 00379 arc_length = edge->get_arc_length()/2; 00380 00381 fraction = edge->fraction_from_arc_length(root_vertex, arc_length); 00382 00383 edge->ref_faces(ref_faces); 00384 if (ref_faces.size() != 2) 00385 return -1.0; 00386 00387 double angle = GeometryQueryTool::instance()-> 00388 surface_angle(ref_faces.get_and_step(),ref_faces.get(), 00389 edge, NULL, fraction); 00390 return angle; 00391 } 00392 00393 CubitStatus CollapseAngleTool::position_from_length(RefEdge *edge, 00394 RefVertex *root_vertex, 00395 double arc_length, 00396 CubitVector& v_new) 00397 { 00398 CubitStatus result; 00399 double sense = 1.0; 00400 if (root_vertex != edge->start_vertex()) 00401 sense = -1.0; 00402 CubitVector v_root = root_vertex->get_point_ptr()->coordinates(); 00403 result = edge->point_from_arc_length(v_root, arc_length*sense, v_new); 00404 return result; 00405 } 00406 00407 //Only change new_vertex when the partition succeeds. 00408 CubitStatus CollapseAngleTool::partition_curve(RefEdge *&edge, 00409 RefVertex *root_vertex, 00410 double arc_length, 00411 RefVertex *&new_vertex) 00412 { 00413 CubitStatus result = CUBIT_SUCCESS; 00414 CubitVector v_new; 00415 result = position_from_length(edge, root_vertex, arc_length, v_new); 00416 if (result == CUBIT_SUCCESS) 00417 result = partition_curve(edge, root_vertex, v_new, new_vertex); 00418 return result; 00419 } 00420 00421 00422 //Only change new_vertex when the partition succeeds. 00423 CubitStatus CollapseAngleTool::partition_curve(RefEdge *&edge, 00424 RefVertex *root_vertex, 00425 CubitVector &position, 00426 RefVertex *&new_vertex) 00427 { 00428 CubitStatus result = CUBIT_SUCCESS; 00429 DLIList<CubitVector*> vect_list; 00430 vect_list.append( new CubitVector( position ) ); 00431 DLIList<RefVertex*> vertex_list; 00432 RefVertex* the_vertex = NULL; 00433 edge->ref_vertices(vertex_list); 00434 if (vertex_list.size() == 1) 00435 the_vertex = vertex_list.get(); 00436 00437 DLIList<RefEdge*> tmp_list; 00438 result = PartitionTool::instance()-> 00439 partition( edge, vect_list, tmp_list ); 00440 delete vect_list.pop(); 00441 if (!result) 00442 { 00443 PRINT_ERROR("Split of curve %d failed.\n", edge->id()); 00444 return result; 00445 } 00446 //Only change new_vertex when the partition succeeds. 00447 RefEdge *temp_edge = tmp_list.get_and_step(); 00448 if (NULL != the_vertex) 00449 { 00450 new_vertex = temp_edge->other_vertex(the_vertex); 00451 double len1 = temp_edge->get_arc_length(); 00452 double len2 = tmp_list.get()->get_arc_length(); 00453 if (len1 > len2) 00454 edge = tmp_list.get(); 00455 else 00456 edge = temp_edge; 00457 } 00458 else if (temp_edge != edge) 00459 { 00460 new_vertex = edge->common_ref_vertex(temp_edge); 00461 if (root_vertex && edge->start_vertex() != root_vertex && 00462 edge->end_vertex() != root_vertex) 00463 edge = temp_edge; 00464 } 00465 else 00466 { 00467 new_vertex = edge->common_ref_vertex(tmp_list.get()); 00468 if (root_vertex && edge->start_vertex() != root_vertex && 00469 edge->end_vertex() != root_vertex) 00470 edge = tmp_list.get(); 00471 } 00472 00473 return result; 00474 } 00475 00476 CubitStatus CollapseAngleTool::partition_surface(RefFace *common_face, 00477 RefEdge *&edge_to_remove, 00478 RefVertex *root, 00479 RefVertex *vertex1, 00480 RefVertex *vertex2, 00481 RefFace *&result_face) 00482 { 00483 CubitStatus result = CUBIT_SUCCESS; 00484 DLIList<CubitVector*> positions; 00485 positions.append(new CubitVector(vertex1->get_point_ptr()->coordinates())); 00486 positions.append(new CubitVector(vertex2->get_point_ptr()->coordinates())); 00487 00488 DLIList<RefEdge*> new_edges; 00489 result_face = PartitionTool::instance()-> 00490 insert_edge( common_face, positions, CUBIT_FALSE, new_edges ); 00491 00492 // make sure that we actually get something out of insert_edge 00493 if (new_edges.size() == 0) 00494 { 00495 if (positions[0]) 00496 delete positions[0]; 00497 if (positions[1]) 00498 delete positions[1]; 00499 return CUBIT_FAILURE; 00500 } 00501 00502 RefEdge *new_edge = new_edges.get(); 00503 if(new_edge) 00504 { 00505 RefVertex * start = new_edge->start_vertex(); 00506 RefVertex * end = new_edge->end_vertex(); 00507 if (start != vertex1 && end != vertex1) 00508 edge_to_remove = root->common_ref_edge(start == vertex2 ? end : start); 00509 } 00510 00511 delete positions.get_and_step(); 00512 delete positions.get(); 00513 if( result_face == NULL ) 00514 result = CUBIT_FAILURE; 00515 00516 return result; 00517 } 00518 00519 CubitStatus CollapseAngleTool::draw_preview(RefVertex *vex_ptr, 00520 RefEdge *edge_to_remove, 00521 RefEdge *the_other_edge, 00522 double length1, 00523 double length2, 00524 CubitBoolean get_position, 00525 CubitVector &position) 00526 { 00527 CubitStatus result = CUBIT_SUCCESS; 00528 00529 //flush out previous drawing 00530 GfxDebug::display_all(); 00531 00532 //wireframe display of future composite surface per design review. 00533 DLIList<RefFace*> ref_faces; 00534 edge_to_remove-> ref_faces(ref_faces); 00535 RefFace *common_face = edge_to_remove->common_ref_face(the_other_edge); 00536 assert(ref_faces.size() == 2); 00537 00538 RefFace *highlight_surf = ref_faces.get_and_step(); 00539 if (highlight_surf == common_face) 00540 highlight_surf = ref_faces.get(); 00541 00542 DLIList<RefEdge*> ref_edges; 00543 highlight_surf->ref_edges(ref_edges); 00544 ref_edges.remove(edge_to_remove); 00545 00546 int i; 00547 for (i = 0; i < partly_drawn_curve.size(); i++) 00548 ref_edges.remove(partly_drawn_curve.get_and_step()); 00549 00550 for(i = 0; i < ref_edges.size(); i++) 00551 GfxDebug::draw_ref_entity(ref_edges.get_and_step(), CUBIT_BLUE_INDEX); 00552 00553 //check if there will be a cutting edge 00554 CubitBoolean if_partition = if_partition_surf(vex_ptr, edge_to_remove, 00555 common_face); 00556 if (length1 == -1.0 && !get_position && length2 == -1.0 && !if_partition) 00557 { 00558 ref_edges.clean_out(); 00559 common_face->ref_edges(ref_edges); 00560 ref_edges.remove(edge_to_remove); 00561 00562 for (i = 0; i < partly_drawn_curve.size(); i++) 00563 ref_edges.remove(partly_drawn_curve.get_and_step()); 00564 00565 for(i = 0; i < ref_edges.size(); i++) 00566 GfxDebug::draw_ref_entity(ref_edges.get_and_step(), CUBIT_BLUE_INDEX); 00567 return result; 00568 } 00569 00570 CubitVector location, location2, location3; 00571 if (length1 == -1.0) 00572 location = edge_to_remove->other_vertex(vex_ptr)->coordinates(); 00573 00574 if (length1 != -1.0) 00575 result = position_from_length(edge_to_remove, vex_ptr, 00576 length1, location); 00577 00578 if ( !get_position && length2 == -1.0 && 00579 (length1 != -1.0 || 00580 (length1 == -1.0 && if_partition))) 00581 location2=the_other_edge->other_vertex(vex_ptr)->coordinates(); 00582 00583 else if(get_position) 00584 location2 = position; 00585 00586 else if (length2 != -1.0) 00587 result = position_from_length(the_other_edge, vex_ptr, length2, location2); 00588 00589 GfxDebug::draw_line(location, location2, CUBIT_BLUE_INDEX); 00590 00591 //Draw part of curves 00592 double length; 00593 CubitVector temp_vex; 00594 GPoint pts[5]; 00595 location3 = vex_ptr->coordinates(); 00596 00597 partly_drawn_curve.append(the_other_edge); 00598 partly_drawn_curve.append(edge_to_remove); 00599 if (the_other_edge->geometry_type() == STRAIGHT_CURVE_TYPE) 00600 GfxDebug::draw_line(location3, location2, CUBIT_BLUE_INDEX); 00601 00602 else 00603 { 00604 length = the_other_edge->get_arc_length(location2, location3); 00605 pts[0].x = location3.x(); 00606 pts[0].y = location3.y(); 00607 pts[0].z = location3.z(); 00608 pts[4].x = location2.x(); 00609 pts[4].y = location2.y(); 00610 pts[4].z = location2.z(); 00611 position_from_length(the_other_edge, vex_ptr, length/4, temp_vex); 00612 pts[1].x = temp_vex.x(); 00613 pts[1].y = temp_vex.y(); 00614 pts[1].z = temp_vex.z(); 00615 position_from_length(the_other_edge, vex_ptr, length/2, temp_vex); 00616 pts[2].x = temp_vex.x(); 00617 pts[2].y = temp_vex.y(); 00618 pts[2].z = temp_vex.z(); 00619 position_from_length(the_other_edge, vex_ptr, length*0.75, temp_vex); 00620 pts[3].x = temp_vex.x(); 00621 pts[3].y = temp_vex.y(); 00622 pts[3].z = temp_vex.z(); 00623 GfxDebug::draw_polyline(pts, 5, CUBIT_BLUE_INDEX); 00624 } 00625 00626 RefVertex *vertex = edge_to_remove->other_vertex(vex_ptr); 00627 location3 = vertex->coordinates(); 00628 if (edge_to_remove->geometry_type() == STRAIGHT_CURVE_TYPE) 00629 GfxDebug::draw_line(location3, location, CUBIT_BLUE_INDEX); 00630 00631 else 00632 { 00633 length = edge_to_remove->get_arc_length(location, location3); 00634 pts[0].x = location3.x(); 00635 pts[0].y = location3.y(); 00636 pts[0].z = location3.z(); 00637 pts[4].x = location.x(); 00638 pts[4].y = location.y(); 00639 pts[4].z = location.z(); 00640 00641 position_from_length(edge_to_remove, vertex, length/4, temp_vex); 00642 pts[1].x = temp_vex.x(); 00643 pts[1].y = temp_vex.y(); 00644 pts[1].z = temp_vex.z(); 00645 position_from_length(edge_to_remove, vertex, length/2, temp_vex); 00646 pts[2].x = temp_vex.x(); 00647 pts[2].y = temp_vex.y(); 00648 pts[2].z = temp_vex.z(); 00649 position_from_length(edge_to_remove, vertex, length*0.75, temp_vex); 00650 pts[3].x = temp_vex.x(); 00651 pts[3].y = temp_vex.y(); 00652 pts[3].z = temp_vex.z(); 00653 GfxDebug::draw_polyline(pts, 5, CUBIT_BLUE_INDEX); 00654 } 00655 00656 GfxDebug::flush(); 00657 00658 return result; 00659 } 00660 00661 CubitBoolean CollapseAngleTool::if_partition_surf(RefVertex *vex_ptr, 00662 RefEdge *edge_to_remove, 00663 RefFace *common_face) 00664 { 00665 CubitBoolean partition_surface_ =CUBIT_FALSE; 00666 RefVertex *temp_vtx = NULL; 00667 RefEdge * temp_edge = NULL; 00668 if (edge_to_remove->start_vertex() == vex_ptr) 00669 temp_vtx = edge_to_remove->end_vertex(); 00670 else 00671 temp_vtx = edge_to_remove->start_vertex(); 00672 00673 temp_edge = edge_to_remove->get_other_curve(temp_vtx, common_face); 00674 00675 if (temp_edge->num_of_common_ref_face(edge_to_remove) > 1) 00676 partition_surface_ = CUBIT_TRUE; 00677 00678 return partition_surface_; 00679 } 00680 00681 CubitStatus CollapseAngleTool::collapse_angle(RefVertex *vex_ptr, 00682 RefEdge *edge_to_remove, 00683 RefEdge *the_other_edge, 00684 double length1, 00685 double length2, 00686 CubitBoolean get_position, 00687 CubitVector &position) 00688 { 00689 CubitStatus result = CUBIT_SUCCESS; 00690 RefVertex *new_vertex1 = edge_to_remove->other_vertex(vex_ptr); 00691 RefVertex *new_vertex2 = the_other_edge->other_vertex(vex_ptr); 00692 DLIList<RefFace*> ref_faces; 00693 edge_to_remove-> ref_faces(ref_faces); 00694 RefFace *common_face = NULL; 00695 DLIList<RefFace*> common_face_list; 00696 int nfaces = edge_to_remove->num_of_common_ref_face(the_other_edge); 00697 00698 if (nfaces == 1) 00699 common_face = edge_to_remove->common_ref_face(the_other_edge); 00700 else 00701 { 00702 assert (nfaces == 2); 00703 edge_to_remove->common_ref_faces(the_other_edge, common_face_list); 00704 } 00705 00706 if (length1 != -1.0) 00707 { 00708 result = partition_curve(edge_to_remove, vex_ptr, length1, new_vertex1); 00709 if (result != CUBIT_SUCCESS) 00710 { 00711 PRINT_ERROR("Operation failed at vertex %d, curve %d and curve %d.\n", 00712 vex_ptr->id(), edge_to_remove->id(), the_other_edge->id()); 00713 return result; 00714 } 00715 } 00716 00717 if (get_position) 00718 { 00719 result = partition_curve(the_other_edge, NULL, position, new_vertex2); 00720 if (result != CUBIT_SUCCESS) 00721 { 00722 PRINT_ERROR("Operation failed at vertex %d, curve %d and curve %d.\n", 00723 vex_ptr->id(), edge_to_remove->id(), the_other_edge->id()); 00724 return result; 00725 } 00726 } 00727 00728 else if (!get_position && length2 != -1.0) 00729 { 00730 result = partition_curve(the_other_edge, vex_ptr, length2, new_vertex2); 00731 if (result != CUBIT_SUCCESS) 00732 { 00733 PRINT_ERROR("Operation failed at vertex %d, curve %d and curve %d.\n", 00734 vex_ptr->id(), edge_to_remove->id(), the_other_edge->id()); 00735 return result; 00736 } 00737 } 00738 00739 if (nfaces > 1) //determine the common face. 00740 { 00741 CubitBox edge_box(new_vertex1->coordinates()); 00742 edge_box |= new_vertex2->bounding_box(); 00743 CubitBox face_box1, face_box2; 00744 RefFace *face1, *face2; 00745 face1 = common_face_list.get_and_step(); 00746 face2 = common_face_list.get(); 00747 face_box1 = face1->bounding_box(); 00748 face_box2 = face2->bounding_box(); 00749 if(edge_box.overlap(0, face_box1)) 00750 { 00751 // Face 1 overlaps with the partition points. 00752 if(edge_box.overlap(0, face_box2)) 00753 { 00754 // Both face 1 and face 2 overlap with the parition points. 00755 // We must do a further check to try to choose the best one. 00756 // Take the mid point between the two vertices and calculate 00757 // the distance from both faces. Choose the one with the 00758 // smaller distance. This approach was chosen because there 00759 // was a case where one of the potential common faces was 00760 // actually a composite that had a 90 degree turn in it 00761 // so that the end points of the edge that would be used 00762 // to partition it fell on the composite surface but the 00763 // rest of the interior of the edge didn't lie on the surface. 00764 // However, the edge completely lied on the other potential 00765 // surface and so it was the better candidate. 00766 CubitVector mid_pos = (new_vertex1->coordinates() + 00767 new_vertex2->coordinates())/2; 00768 Surface *surf1 = face1->get_surface_ptr(); 00769 Surface *surf2 = face2->get_surface_ptr(); 00770 if(surf1 && surf2) 00771 { 00772 CubitVector pos1, pos2; 00773 surf1->closest_point(mid_pos, &pos1); 00774 surf2->closest_point(mid_pos, &pos2); 00775 if((mid_pos - pos1).length_squared() < 00776 (mid_pos - pos2).length_squared()) 00777 { 00778 common_face = face1; 00779 } 00780 else 00781 { 00782 common_face = face2; 00783 } 00784 } 00785 else 00786 { 00787 PRINT_ERROR("Operation failed because one of the potential common faces doesn't have a surface.\n"); 00788 return CUBIT_FAILURE; 00789 } 00790 } 00791 else 00792 { 00793 // Only face 1 overlaps so use it as the common face. 00794 common_face = face1; 00795 } 00796 } 00797 else if(edge_box.overlap(0, face_box2)) 00798 { 00799 // Only face 2 overlaps so use it as the common face. 00800 common_face = face2; 00801 } 00802 else 00803 { 00804 // Neither face overlaps so throw an error. 00805 PRINT_ERROR("Operation failed to find a valid common face for partitioning.\n"); 00806 return CUBIT_FAILURE; 00807 } 00808 } 00809 00810 CubitBoolean partition_surface_ = CUBIT_FALSE; 00811 // check if edge_to_remove is the only one that shares the two surfaces. 00812 if (length1 == -1.0) 00813 partition_surface_ = if_partition_surf(vex_ptr, edge_to_remove, 00814 common_face); 00815 00816 RefFace * face_to_remove = common_face; 00817 if (length1 != -1.0 || get_position || length2 != -1.0 || partition_surface_) 00818 { 00819 RefFace *result_face; 00820 result = partition_surface(common_face, edge_to_remove, vex_ptr, 00821 new_vertex1, new_vertex2, result_face); 00822 if (result != CUBIT_SUCCESS) 00823 { 00824 PRINT_ERROR("Split of surface %d failed.\n", common_face->id()); 00825 PRINT_ERROR("Operation failed at vertex %d, curve %d and curve %d.\n", 00826 vex_ptr->id(), edge_to_remove->id(), the_other_edge->id()); 00827 return result; 00828 } 00829 00830 DLIList<RefEdge*> ref_edges; 00831 result_face->ref_edges(ref_edges); 00832 int i; 00833 for (i = 0; i <ref_edges.size(); i++) 00834 if (ref_edges.get_and_step() == edge_to_remove) 00835 { 00836 face_to_remove = result_face; 00837 break; 00838 } 00839 } 00840 00841 if (face_to_remove != common_face) 00842 { 00843 ref_faces.remove(common_face); 00844 ref_faces.append(face_to_remove); 00845 } 00846 00847 DLIList<RefFace*> result_faces; 00848 CompositeTool::instance()->composite(ref_faces, result_faces); 00849 00850 if( result_faces.size() > 0 ) 00851 { 00852 DLIList<int> id_list; 00853 int e; 00854 for( e = 0; e < result_faces.size(); e++) 00855 { 00856 id_list.append( result_faces.get_and_step()->id() ); 00857 CubitUtil::list_entity_ids("Created composite surfaces ", id_list ); 00858 } 00859 } 00860 00861 else 00862 { 00863 PRINT_ERROR("Operation failed at vertex %d, curve %d and curve %d.\n", 00864 vex_ptr->id(), edge_to_remove->id(), the_other_edge->id()); 00865 result = CUBIT_FAILURE; 00866 } 00867 00868 //composite out new_vertex1 00869 DLIList<RefEdge*> edge_list; 00870 RefEdge* composite_edge = NULL; 00871 int id = new_vertex1->id(); 00872 new_vertex1->ref_edges(edge_list); 00873 if (edge_list.size() == 2) 00874 composite_edge = CompositeTool::instance()->composite(edge_list); 00875 if (composite_edge) 00876 { 00877 DLIList<int> id_list; 00878 id_list.append(id); 00879 CubitUtil::list_entity_ids("Composite out of vertex ", id_list); 00880 } 00881 00882 return result; 00883 }