cgma
|
00001 //------------------------------------------------------------------------- 00002 // Filename : AutoMidsurfaceTool.cpp 00003 // 00004 // Purpose : 00005 // Create a midsurface of a body/volume given a thickness range. If no thickness range is given 00006 // then make a educated guess at the thickness (using something like Volume/Surface Area). 00007 // 00008 // Create Midsurface Volume <id_list> auto [<min_thickness> <max_thickness>] 00009 // 00010 // Creator : Sam Showman 00011 // 00012 // Creation Date : 05/10/2008 00013 //------------------------------------------------------------------------- 00014 #include "AutoMidsurfaceTool.hpp" 00015 #include "GeometryModifyEngine.hpp" 00016 #include "GeometryQueryTool.hpp" 00017 #include "BodySM.hpp" 00018 #include "Body.hpp" 00019 #include "GeometryModifyTool.hpp" 00020 #include "RefFace.hpp" 00021 #include "Surface.hpp" 00022 #include "Curve.hpp" 00023 #include "RefEntity.hpp" 00024 #include "SurfaceOverlapTool.hpp" 00025 #include "CubitPlane.hpp" 00026 #include "GfxPreview.hpp" 00027 #include "GfxDebug.hpp" 00028 #include "RefVertex.hpp" 00029 #include "ProgressTool.hpp" 00030 #include "AppUtil.hpp" 00031 #include "BoundingBoxTool.hpp" 00032 #include "GeomMeasureTool.hpp" 00033 00034 // Constructor - nothing going on here 00035 AutoMidsurfaceTool::AutoMidsurfaceTool() 00036 { 00037 } 00038 00039 // The main midsurface function 00040 // lower_tol, upper_tol and preview are optional 00041 CubitStatus AutoMidsurfaceTool::midsurface( 00042 DLIList<Body*> &body_list_in, 00043 DLIList<BodySM*> &body_list_out, 00044 DLIList<Body*> &old_bodies_midsurfaced, 00045 DLIList<double> &thickness_out, 00046 double lower_limit, 00047 double upper_limit, 00048 CubitBoolean delete_midsurfaced, 00049 CubitBoolean preview) 00050 { 00051 if(lower_limit == CUBIT_DBL_MAX)// no limit set 00052 lower_limit = -CUBIT_DBL_MAX; 00053 double lower_tol = CUBIT_DBL_MAX; 00054 double upper_tol = CUBIT_DBL_MAX; 00055 const double auto_thickness_margin = 0.05; // if the user wants to automatically find the search 00056 // thickness then this var give the search margin around the 00057 // guess 00058 ProgressTool* prog_tool = 0; 00059 if(body_list_in.size()>5) 00060 prog_tool = AppUtil::instance()->progress_tool(); 00061 00062 // At lease one body must be provided 00063 if(body_list_in.size() < 1) 00064 { 00065 PRINT_ERROR( "No bodies given for midsurfacing\n" ); 00066 return CUBIT_FAILURE; 00067 } 00068 00069 // The surfaceOverlapTool is persistent so we need to save the 00070 // max_gap and such to restore them at the end or if we error out 00071 // save current settings 00072 double max_gap_save = SurfaceOverlapTool::instance()->get_gap_max(); 00073 double min_gap_save = SurfaceOverlapTool::instance()->get_gap_min(); 00074 int normal_type = SurfaceOverlapTool::instance()->get_normal_type(); 00075 CubitBoolean cubit_bool_save = SurfaceOverlapTool::instance()->get_check_within_bodies(); 00076 CubitBoolean skip_facing_surfaces = SurfaceOverlapTool::instance()->get_skip_facing_surfaces(); 00077 00078 // we want to only find overlap within a body 00079 SurfaceOverlapTool::instance()->set_check_within_bodies(CUBIT_TRUE); 00080 // 1=any, 2=opposite, 3=same - we want to find only the overlaps that normals 00081 // pointing in the opposite directions 00082 SurfaceOverlapTool::instance()->set_normal_type(2); 00083 // Don't pickup surfaces that face each other 00084 SurfaceOverlapTool::instance()->set_skip_facing_surfaces(CUBIT_TRUE); 00085 00086 // list of bodies that fail to midsurface 00087 DLIList<Body*> failing_bodies; 00088 00089 GeometryModifyEngine* gme = 0; 00090 GeometryQueryEngine* gqe = 0; 00091 00092 // loop over every body and try to create midsurface(s) 00093 int i = 0; 00094 CubitStatus return_status = CUBIT_FAILURE; 00095 00096 if(prog_tool) 00097 prog_tool->start(0,body_list_in.size()); 00098 00099 for(i = body_list_in.size();i--;) 00100 { 00101 if(prog_tool) 00102 prog_tool->step(); 00103 00104 Body* cur_body = body_list_in[i]; 00105 if(!cur_body) 00106 continue; 00107 00108 BodySM* body_sm = cur_body->get_body_sm_ptr(); 00109 if(!body_sm) 00110 continue; 00111 00112 if(cur_body->is_sheet_body()) 00113 { 00114 PRINT_INFO("Body %d is a sheet body.\n",cur_body->id()); 00115 continue; 00116 } 00117 00118 // Grab the geometrymodify and geometryquery engines to use later 00119 gqe = cur_body->get_geometry_query_engine(); 00120 gme = GeometryModifyTool::instance()->get_engine(body_sm); 00121 00122 if(!gqe || !gme) 00123 continue; 00124 00125 // Here are the steps to finding/creating the midsurface 00126 // 1. If the user did not give a thickness range to search then 00127 // make an educated guess at the proper thickness range. The assumption 00128 // is that the midsurface is a square and the thickness is constant. 00129 // The resulting equation is a third order polynomial that is solved using 00130 // a few newton iterations. The initial thickness guess is Volume/Area 00131 // 2. Using the given search distances use the SurfaceOverlapTool to find 00132 // surface pairs. 00133 // 3. If there is only one surface pair then use the existing midsurface commands 00134 // 4. Find if the surface pairs represent two surface patches 00135 // 5. If there are only two surface patches try to offset one of the patches 00136 // 6. (this step is commented out for now) - If 5 fails or there are more than 00137 // two surface patches then try the following: 00138 // - Use the manual midsurface creation function to create midsurfaces for each 00139 // pair of surfaces. 00140 // - Unite all of the created midsurfaces together 00141 // - remove any surfaces that have a curve touching a surface pair 00142 // - Regularize the resulting body 00143 // 7. Done 00144 00145 { 00146 PRINT_DEBUG_198("AUTOMATICALLY calculating search range\n"); 00147 DLIList<RefVolume*> vol_list; 00148 cur_body->ref_volumes(vol_list); 00149 double total_vol = 0; 00150 double total_vol_bb = 0; 00151 for(int vol_cnt = 0; vol_cnt < vol_list.size(); vol_cnt++) 00152 { 00153 CubitVector cg; 00154 double temp_volume; 00155 vol_list[vol_cnt]->mass_properties(cg,temp_volume); 00156 CubitBox vol_bb = vol_list[vol_cnt]->bounding_box(); 00157 total_vol += temp_volume; 00158 total_vol_bb += vol_bb.x_range()*vol_bb.y_range()*vol_bb.z_range(); 00159 } 00160 00161 if(total_vol<0 || total_vol > total_vol_bb) 00162 { 00163 PRINT_INFO("Could not midsurface Body %d - try healing the body.\n",cur_body->id()); 00164 failing_bodies.append(cur_body); 00165 continue; 00166 } 00167 00168 PRINT_DEBUG_198("Volume of %f\n",total_vol); 00169 00170 DLIList<RefFace*> face_list; 00171 cur_body->ref_faces(face_list); 00172 double total_surf = 0; 00173 for(int surf_cnt = 0; surf_cnt < face_list.size(); surf_cnt++) 00174 total_surf += face_list[surf_cnt]->area(); 00175 PRINT_DEBUG_198("Area of %f\n",total_surf); 00176 00177 double t_g = total_vol/(total_surf/2.0); 00178 double initial_guess = t_g; 00179 PRINT_DEBUG_198("Initial guess of thickness %f\n",t_g); 00180 // use a newton solver to get a more accurate estimate the thickness of the volume 00181 for(int n_i = 0;n_i<100;n_i++) 00182 { 00183 double tol_newton = GEOMETRY_RESABS; 00184 double t_gn = t_g + tol_newton; 00185 double f_prime = ((2.0*total_vol + sqrt(total_vol*t_g*t_g*t_g)*4.0 - total_surf*t_g) 00186 -(2.0*total_vol + sqrt(total_vol*t_gn*t_gn*t_gn)*4.0 - total_surf*t_gn))/ 00187 (t_g-t_gn); 00188 00189 // avoid divide by zero 00190 if(fabs(f_prime)<tol_newton) 00191 break; 00192 00193 double t_old = t_g; 00194 t_g = t_g - (2.0*total_vol + sqrt(total_vol*t_g*t_g*t_g)*4.0 - total_surf*t_g)/f_prime; 00195 00196 PRINT_DEBUG_198("Guess %d Thickness %f\n",n_i,t_g); 00197 if(fabs(t_g-t_old)<tol_newton) 00198 { 00199 PRINT_DEBUG_198("Converged with thickness of %f in %d steps\n",t_g,n_i); 00200 break; 00201 } 00202 if(t_g<0.0) 00203 { 00204 PRINT_DEBUG_198("thickness less than zero setting back to initial guess\n"); 00205 t_g = fabs(initial_guess); 00206 break; 00207 } 00208 } 00209 upper_tol = t_g + t_g*auto_thickness_margin; 00210 lower_tol = t_g - t_g*auto_thickness_margin; 00211 upper_tol = upper_tol <= upper_limit?upper_tol:upper_limit; 00212 lower_tol = lower_tol >= lower_limit?lower_tol:lower_limit; 00213 00214 PRINT_DEBUG_198("Guessing a thickness of %f to %f\n",lower_tol,upper_tol); 00215 } 00216 00217 // set the lower and upper search distances 00218 SurfaceOverlapTool::instance()->set_gap_max(upper_tol); 00219 SurfaceOverlapTool::instance()->set_gap_min(lower_tol); 00220 00221 DLIList<RefFace*> ref_face_list,list1,list2; 00222 DLIList<RefEntity*> faces_to_draw; 00223 cur_body->ref_faces(ref_face_list); 00224 // find the surface pairs 00225 SurfaceOverlapTool::instance()->find_overlapping_surfaces(ref_face_list,list1,list2,faces_to_draw); 00226 00227 int tweak_iters = 4; 00228 for(int tweak = 0;tweak<tweak_iters;tweak++) 00229 { 00230 // if we didn't find anything then the part may be long and selender so grow the search thickness 00231 if(list1.size()==0 && list2.size() == 0) 00232 { 00233 if(tweak == tweak_iters-1 && lower_limit != -CUBIT_DBL_MAX && upper_limit != CUBIT_DBL_MAX) 00234 { 00235 // on the last try use the user defined limits 00236 lower_tol = lower_limit; 00237 upper_tol = upper_limit; 00238 } 00239 else 00240 { 00241 lower_tol = (upper_tol + lower_tol)/2.0; 00242 upper_tol += lower_tol*auto_thickness_margin*2; 00243 upper_tol = upper_tol <= upper_limit?upper_tol:upper_limit; 00244 lower_tol = lower_tol >= lower_limit?lower_tol:lower_limit; 00245 } 00246 00247 PRINT_DEBUG_198("Guessing again with thickness of %f to %f\n",lower_tol,upper_tol); 00248 SurfaceOverlapTool::instance()->set_gap_max(upper_tol); 00249 SurfaceOverlapTool::instance()->set_gap_min(lower_tol); 00250 SurfaceOverlapTool::instance()->find_overlapping_surfaces(ref_face_list,list1,list2,faces_to_draw); 00251 } 00252 00253 DLIList<RefFace*> check_list; 00254 check_list += list1; 00255 check_list += list2; 00256 00257 if(check_list.size() == 0 ) 00258 continue; 00259 00260 // make sure the pairs will match the solid within 10% or so 00261 if(!check_surf_pairs(lower_tol,upper_tol,check_list,cur_body)) 00262 { 00263 list1.clean_out(); 00264 list2.clean_out(); 00265 continue; 00266 } 00267 break; 00268 } 00269 00270 if(list1.size() != list2.size()) 00271 { 00272 PRINT_INFO("Could not find workable surface pairs for Body %d - try using the Sheet Offset command. \n",cur_body->id()); 00273 failing_bodies.append(cur_body); 00274 continue; 00275 } 00276 else if(list1.size() == 0 || list2.size() == 0) 00277 { 00278 PRINT_INFO("No surface pairs found for Body %d - try changing the search range\n",cur_body->id()); 00279 failing_bodies.append(cur_body); 00280 continue; 00281 } 00282 00283 // get the first pair and see if there are only two patches 00284 DLIList<RefFace*> red_faces; 00285 red_faces.append(list1[0]); 00286 DLIList<RefFace*> yellow_faces; 00287 yellow_faces.append(list2[0]); 00288 DLIList<RefFace*> paired_faces; 00289 paired_faces += list1; 00290 paired_faces += list2; 00291 paired_faces.uniquify_unordered(); 00292 00293 // red surfaces 00294 while(1) 00295 { 00296 int start_cnt = red_faces.size(); 00297 DLIList<RefEdge*> red_edges; 00298 int j = 0; 00299 for(j =0;j<red_faces.size();j++) 00300 red_faces[j]->ref_edges(red_edges); 00301 red_edges.uniquify_unordered(); 00302 for(j =0;j<red_edges.size();j++) 00303 red_edges[j]->ref_faces(red_faces); 00304 red_faces.uniquify_unordered(); 00305 red_faces.intersect_unordered(paired_faces); 00306 if(start_cnt == red_faces.size()) 00307 break; 00308 } 00309 00310 // yellow surfaces 00311 while(1) 00312 { 00313 int start_cnt = yellow_faces.size(); 00314 DLIList<RefEdge*> yellow_edges; 00315 int j = 0; 00316 for(j =0;j<yellow_faces.size();j++) 00317 yellow_faces[j]->ref_edges(yellow_edges); 00318 yellow_edges.uniquify_unordered(); 00319 for(j =0;j<yellow_edges.size();j++) 00320 yellow_edges[j]->ref_faces(yellow_faces); 00321 yellow_faces.uniquify_unordered(); 00322 yellow_faces.intersect_unordered(paired_faces); 00323 if(start_cnt == yellow_faces.size()) 00324 break; 00325 } 00326 00327 DLIList<BodySM*> results; 00328 bool midsurface_done = false; 00329 00330 if(DEBUG_FLAG(198)) 00331 { 00332 int j = 0; 00333 PRINT_INFO("Trying surface offset to create the mid_surface\n"); 00334 PRINT_INFO("Red surface "); 00335 for(j = 0;j < red_faces.size();j++) 00336 { 00337 GfxDebug::draw_ref_face(red_faces[j],CUBIT_RED_INDEX); 00338 PRINT_INFO("%d ",red_faces[j]->id()); 00339 } 00340 00341 PRINT_INFO("\nYellow surface "); 00342 for(j = 0;j < yellow_faces.size();j++) 00343 { 00344 GfxDebug::draw_ref_face(yellow_faces[j],CUBIT_YELLOW_INDEX); 00345 PRINT_INFO("%d ",yellow_faces[j]->id()); 00346 } 00347 00348 PRINT_INFO("\n"); 00349 } 00350 00351 // first check to see if we can use the simple midsurface functions 00352 if(red_faces.size() == 1 && yellow_faces.size() == 1 && 00353 paired_faces.size() == red_faces.size() + yellow_faces.size()) 00354 { 00355 RefFace* face_1 = red_faces[0]; 00356 RefFace* face_2 = yellow_faces[0]; 00357 midsurface_done = false; 00358 00359 if(face_1->geometry_type() == face_2->geometry_type()) 00360 { 00361 Surface* surf_1 = face_1->get_surface_ptr(); 00362 Surface* surf_2 = face_2->get_surface_ptr(); 00363 BodySM* result_body; 00364 // grab the distance between surfaces 00365 CubitVector temp_vec0; 00366 CubitVector temp_vec1; 00367 double temp_dist = 0; 00368 gqe->entity_entity_distance( 00369 face_1->get_surface_ptr(), 00370 face_2->get_surface_ptr(), 00371 temp_vec0,temp_vec1,temp_dist); 00372 00373 switch(face_1->geometry_type()) 00374 { 00375 case CONE_SURFACE_TYPE: 00376 if(gme->get_conic_mid_surface(surf_1,surf_2,body_sm,result_body) == CUBIT_SUCCESS) 00377 { 00378 midsurface_done = true; 00379 results.append(result_body); 00380 thickness_out.append(fabs(temp_dist)); 00381 } 00382 break; 00383 case PLANE_SURFACE_TYPE: 00384 if(get_planar_mid_surface(face_1,face_2,body_sm,result_body,gme) == CUBIT_SUCCESS) 00385 { 00386 midsurface_done = true; 00387 results.append(result_body); 00388 thickness_out.append(fabs(temp_dist)); 00389 } 00390 break; 00391 case SPHERE_SURFACE_TYPE: 00392 if(gme->get_spheric_mid_surface(surf_1,surf_2,body_sm,result_body) == CUBIT_SUCCESS) 00393 { 00394 midsurface_done = true; 00395 results.append(result_body); 00396 thickness_out.append(fabs(temp_dist)); 00397 } 00398 break; 00399 case TORUS_SURFACE_TYPE: 00400 if(gme->get_toric_mid_surface(surf_1,surf_2,body_sm,result_body) == CUBIT_SUCCESS) 00401 { 00402 midsurface_done = true; 00403 results.append(result_body); 00404 thickness_out.append(fabs(temp_dist)); 00405 } 00406 break; 00407 case CYLINDER_SURFACE_TYPE: 00408 if(gme->get_conic_mid_surface(surf_1,surf_2,body_sm,result_body) == CUBIT_SUCCESS) 00409 { 00410 midsurface_done = true; 00411 results.append(result_body); 00412 thickness_out.append(fabs(temp_dist)); 00413 } 00414 break; 00415 default: 00416 break; 00417 } 00418 } 00419 } 00420 00421 if(!midsurface_done && 00422 paired_faces.size() == red_faces.size() + yellow_faces.size()) // just do the offset 00423 { 00424 int j = 0; 00425 DLIList<double> offset_distances; 00426 for(j = 0;j<list1.size();j++) 00427 { 00428 CubitVector temp_vec0; 00429 CubitVector temp_vec1; 00430 double temp_dist = 0; 00431 if(!gqe->entity_entity_distance( 00432 list1[j]->get_surface_ptr(), 00433 list2[j]->get_surface_ptr(), 00434 temp_vec0,temp_vec1,temp_dist)) 00435 { 00436 break; 00437 } 00438 offset_distances.append(-temp_dist*.5); 00439 } 00440 00441 DLIList<Surface*> red_surfs; 00442 for(j = 0;j<red_faces.size();j++) 00443 red_surfs.append(red_faces[j]->get_surface_ptr()); 00444 00445 DLIList<Surface*> yellow_surfs; 00446 for(j = 0;j<yellow_faces.size();j++) 00447 yellow_surfs.append(yellow_faces[j]->get_surface_ptr()); 00448 00449 // all of the surfaces are offset the same distance 00450 double offset_distance = offset_distances[0]; 00451 bool old_error_flag = GET_ERROR_FLAG(); 00452 SET_ERROR_FLAG(false); // don't throw any gme errors 00453 if( gme->create_offset_sheet(red_surfs,offset_distance, 00454 NULL,NULL,results)) 00455 { 00456 midsurface_done = true; 00457 for(j = 0;j<results.size();j++) // for every body add a thickness 00458 thickness_out.append(fabs(offset_distance*2.)); 00459 } 00460 else if( gme->create_offset_sheet(yellow_surfs,offset_distance, 00461 NULL,NULL,results)) // try the other direction 00462 { 00463 midsurface_done = true; 00464 for(j = 0;j<results.size();j++) // for every body add a thickness 00465 thickness_out.append(fabs(offset_distance*2.)); 00466 } 00467 else 00468 { 00469 PRINT_INFO("Could not create midsurface for Body %d - try using the surface offset command\n",cur_body->id()); 00470 failing_bodies.append(cur_body); 00471 } 00472 SET_ERROR_FLAG(old_error_flag); // turn errors back on 00473 } 00474 00475 if(!midsurface_done && paired_faces.size() != red_faces.size() + yellow_faces.size()) 00476 { 00477 PRINT_INFO("Could not find workable surface pairs for Body %d - try changing the search range or \n" 00478 " using the Sheet Offset command.\n",cur_body->id()); 00479 } 00480 00481 /*if(!midsurface_done) 00482 { 00483 if(DEBUG_FLAG(198)) 00484 PRINT_INFO("Trying the extend, unite, and trim method\n"); 00485 00486 // okay now remove duplicate pairs and unsupported pairs 00487 DLIList<Surface*> surf_list1; 00488 DLIList<Surface*> surf_list2; 00489 bool delete_and_exit = false; 00490 for(int j = 0;j<list1.size();j++) 00491 { 00492 RefFace* face_1 = list1[j]; 00493 RefFace* face_2 = list2[j]; 00494 00495 if(DEBUG_FLAG(198)) 00496 { 00497 PRINT_INFO("Red surface "); 00498 GfxDebug::draw_ref_face(face_1,CUBIT_RED_INDEX); 00499 PRINT_INFO("%d ",face_1->id()); 00500 00501 PRINT_INFO("\nYellow surface "); 00502 GfxDebug::draw_ref_face(face_2,CUBIT_YELLOW_INDEX); 00503 PRINT_INFO("%d ",face_2->id()); 00504 00505 PRINT_INFO("\n"); 00506 } 00507 00508 if(face_1->geometry_type() != face_2->geometry_type()) 00509 continue; 00510 00511 Surface* surf_1 = face_1->get_surface_ptr(); 00512 surf_list1.append(surf_1); 00513 Surface* surf_2 = face_2->get_surface_ptr(); 00514 surf_list2.append(surf_2); 00515 BodySM* result_body; 00516 switch(face_1->geometry_type()) 00517 { 00518 case CONE_SURFACE_TYPE: 00519 if(gme->get_conic_mid_surface(surf_1,surf_2,body_sm,result_body) == CUBIT_SUCCESS) 00520 results.append(result_body); 00521 else 00522 delete_and_exit = true; 00523 break; 00524 case PLANE_SURFACE_TYPE: 00525 if(get_planar_mid_surface(face_1,face_2,body_sm,result_body,gme) == CUBIT_SUCCESS) 00526 results.append(result_body); 00527 else 00528 delete_and_exit = true; 00529 break; 00530 case SPHERE_SURFACE_TYPE: 00531 if(gme->get_spheric_mid_surface(surf_1,surf_2,body_sm,result_body) == CUBIT_SUCCESS) 00532 results.append(result_body); 00533 else 00534 delete_and_exit = true; 00535 break; 00536 case TORUS_SURFACE_TYPE: 00537 if(gme->get_toric_mid_surface(surf_1,surf_2,body_sm,result_body) == CUBIT_SUCCESS) 00538 results.append(result_body); 00539 else 00540 delete_and_exit = true; 00541 break; 00542 case CYLINDER_SURFACE_TYPE: 00543 if(gme->get_conic_mid_surface(surf_1,surf_2,body_sm,result_body) == CUBIT_SUCCESS) 00544 results.append(result_body); 00545 else 00546 delete_and_exit = true; 00547 break; 00548 default: 00549 delete_and_exit = true; 00550 break; 00551 } 00552 00553 if(delete_and_exit) 00554 { 00555 PRINT_WARNING("Failed to pair surface %d with surface %d\n",face_1->id(),face_2->id()); 00556 break; 00557 } 00558 } 00559 00560 if(delete_and_exit) 00561 { 00562 failing_bodies.append(cur_body); 00563 gqe->delete_solid_model_entities(results); 00564 continue; 00565 } 00566 00567 DLIList<BodySM*> unite_results; 00568 if(results.size()>1) 00569 { 00570 bool reg_result = GeometryModifyTool::instance()->boolean_regularize(); 00571 GeometryModifyTool::instance()->boolean_regularize(true); 00572 if(gme->unite(results,unite_results)== CUBIT_SUCCESS) 00573 { 00574 // if the unite works just add them to the result list 00575 results = unite_results; 00576 } 00577 else 00578 { 00579 // clean up the created surfaces and move on to the next 00580 // body 00581 failing_bodies.append(cur_body); 00582 gqe->delete_solid_model_entities(results); 00583 GeometryModifyTool::instance()->boolean_regularize(reg_result); 00584 continue; 00585 } 00586 00587 GeometryModifyTool::instance()->boolean_regularize(reg_result); 00588 } 00589 00590 // trim the hanging surfaces 00591 DLIList<Surface*> paired_surfs; 00592 paired_surfs += surf_list1; 00593 paired_surfs += surf_list2; 00594 00595 DLIList<Curve*> all_curves; 00596 00597 int k = 0; 00598 for(k = 0;k<results.size();k++) 00599 results[k]->curves(all_curves); 00600 00601 all_curves.uniquify_unordered(); 00602 00603 DLIList<Surface*> remove_surfs; 00604 for(k = 0;k<all_curves.size();k++) 00605 for(int m = 0;m<paired_surfs.size();m++) 00606 if(curve_in_surface(all_curves[k],paired_surfs[m])) 00607 all_curves[k]->surfaces(remove_surfs); 00608 00609 remove_surfs.uniquify_unordered(); 00610 00611 body_list_out += results; 00612 DLIList<BodySM*> tweak_results; 00613 if(gme->tweak_remove(remove_surfs,tweak_results,CUBIT_FALSE)) 00614 { 00615 results = tweak_results; 00616 } 00617 else 00618 { 00619 // clean up the created surfaces and move on to the next 00620 // body 00621 failing_bodies.append(cur_body); 00622 gqe->delete_solid_model_entities(results); 00623 continue; 00624 } 00625 00626 DLIList<BodySM*> regularize_results; 00627 // regularize the results 00628 for(k = 0;k < results.size();k++) 00629 { 00630 BodySM* new_body = 0; 00631 if(gme->regularize_body(results[k],new_body)) 00632 regularize_results.append(new_body); 00633 else if(DEBUG_FLAG(198)) 00634 PRINT_INFO("Regularize failure\n"); 00635 } 00636 results = regularize_results; 00637 }*/ 00638 00639 if(!midsurface_done) 00640 { 00641 failing_bodies.append(cur_body); 00642 continue; 00643 } 00644 00645 old_bodies_midsurfaced.append(cur_body); 00646 00647 if(delete_midsurfaced && !preview) 00648 GeometryQueryTool::instance()->delete_Body(cur_body); 00649 00650 return_status = CUBIT_SUCCESS; 00651 body_list_out += results; 00652 } 00653 00654 if(prog_tool) 00655 prog_tool->end(); 00656 00657 PRINT_INFO("Successfully midsurface %d of %d bodies\n",body_list_out.size(),body_list_in.size()); 00658 if(preview) 00659 { 00660 for(int k = 0;k<body_list_out.size();k++) 00661 { 00662 DLIList<Surface*> preview_surfaces; 00663 body_list_out[k]->surfaces(preview_surfaces); 00664 for(int p = 0;p<preview_surfaces.size();p++) 00665 GfxPreview::draw_surface_facets_shaded(preview_surfaces[p],CUBIT_BLUE_INDEX); 00666 } 00667 GfxPreview::flush(); 00668 if(gqe) 00669 gqe->delete_solid_model_entities(body_list_out); 00670 body_list_out.clean_out(); 00671 } 00672 00673 if(failing_bodies.size() > 0) 00674 { 00675 PRINT_INFO("\n"); 00676 PRINT_INFO("Failed to midsurface Body "); 00677 for(i = 0;i<failing_bodies.size();i++) 00678 PRINT_INFO("%d ",failing_bodies[i]->id()); 00679 PRINT_INFO("\n"); 00680 } 00681 00682 if(DEBUG_FLAG(198)) 00683 GfxDebug::flush(); 00684 00685 SurfaceOverlapTool::instance()->set_check_within_bodies(cubit_bool_save); 00686 SurfaceOverlapTool::instance()->set_gap_max(max_gap_save); 00687 SurfaceOverlapTool::instance()->set_normal_type(normal_type); 00688 SurfaceOverlapTool::instance()->set_gap_min(min_gap_save); 00689 SurfaceOverlapTool::instance()->set_skip_facing_surfaces(skip_facing_surfaces); 00690 00691 return return_status; 00692 } 00693 00694 00695 CubitStatus AutoMidsurfaceTool::get_planar_mid_surface( RefFace* ref_face1, 00696 RefFace* ref_face2, 00697 BodySM* body_sm_to_trim_to, 00698 BodySM*& midsurface_body_sm, 00699 GeometryModifyEngine *gme_ptr ) 00700 { 00701 CubitVector normal_1, normal_2, point_1, point_2, point_3; 00702 CubitPlane plane_1, plane_2; 00703 CubitVector p_mid, n_mid; 00704 00705 point_1 = ref_face1->center_point(); 00706 point_2 = ref_face2->center_point(); 00707 00708 normal_1 = ref_face1->normal_at(point_1); 00709 normal_2 = ref_face2->normal_at(point_2); 00710 00711 plane_1 = CubitPlane(normal_1,point_1); 00712 plane_2 = CubitPlane(normal_2,point_2); 00713 00714 if(point_1 == point_2) 00715 { 00716 PRINT_ERROR( "In GeometryModifyTool:: get_planar_mid_surface\n" 00717 " Since both surfaces share the same point, the midsurface is not well-defined\n"); 00718 return CUBIT_FAILURE; 00719 } 00720 else 00721 { 00722 CubitVector temp1 = point_2; 00723 temp1 = plane_1.project(temp1); 00724 temp1 -= point_2; 00725 if ( temp1.length_squared() < GEOMETRY_RESABS*GEOMETRY_RESABS ) 00726 { 00727 PRINT_ERROR("In GeometryModifyTool:: get_planar_mid_surface\n" 00728 " Since both planes are the same, the midsurface is not well-defined.\n"); 00729 return CUBIT_FAILURE; 00730 } 00731 } 00732 00733 if ( ( normal_1.about_equal( normal_2 ) ) || ( (-normal_1).about_equal( normal_2 ) ) ) 00734 { 00735 p_mid = (point_1+point_2)/2; 00736 n_mid = plane_1.normal(); 00737 } 00738 else 00739 { 00740 CubitVector direction_of_line; 00741 plane_1.intersect(plane_2,p_mid,direction_of_line); 00742 direction_of_line.normalize(); 00743 00744 // Find if point_1 and point_2 are on the line of intersection 00745 // If they are, then the mid-plane is not well-defined 00746 CubitVector p1 = point_1-p_mid; 00747 CubitVector p2 = point_2-p_mid; 00748 p1.normalize(); 00749 p2.normalize(); 00750 00751 if(p1==direction_of_line || p1==-direction_of_line) 00752 { 00753 PRINT_ERROR("In GeometryModifyTool:: get_planar_mid_surface\n" 00754 " P1 is on the line of intersection.\n"); 00755 return CUBIT_FAILURE; 00756 } 00757 00758 if(p2==direction_of_line || p2==-direction_of_line) 00759 { 00760 PRINT_ERROR("In GeometryModifyTool:: get_planar_mid_surface\n" 00761 " P2 is on the line of intersection.\n"); 00762 return CUBIT_FAILURE; 00763 } 00764 00765 CubitVector v1 = p1 - (p1%direction_of_line)*direction_of_line; 00766 v1.normalize(); 00767 00768 CubitVector v2 = p2 - (p2%direction_of_line)*direction_of_line; 00769 v2.normalize(); 00770 00771 n_mid = v1 - v2; 00772 n_mid.normalize(); 00773 } 00774 00775 CubitPlane mid_plane(n_mid, p_mid); 00776 point_1 = p_mid; 00777 00778 //find three points that will define the infinite plane from the 00779 //mid plane.through the point in any direction just not along the 00780 //normal direction 00781 CubitVector Xdir(1,0,0), Ydir(0,1,0); 00782 CubitVector direction1; 00783 00784 if ( ( ! n_mid.about_equal( Xdir ) ) && ( ! (-n_mid).about_equal( Xdir ) ) ) 00785 direction1 = Xdir + n_mid; 00786 else 00787 direction1 = Ydir + n_mid; 00788 00789 point_2 = p_mid + direction1; 00790 point_2 = mid_plane.project(point_2); 00791 00792 direction1 = point_2-point_1; 00793 CubitVector direction2 = direction1*n_mid; 00794 point_3 = point_1 + direction2; 00795 00796 CubitStatus ret = gme_ptr->get_mid_plane(point_1, point_2, point_3, 00797 body_sm_to_trim_to, midsurface_body_sm ); 00798 return ret; 00799 } 00800 00801 CubitBoolean AutoMidsurfaceTool::curve_in_surface(Curve *curve_in, Surface *surf_in) 00802 { 00803 CubitVector loc_0; 00804 CubitVector loc_1; 00805 CubitVector loc_2; 00806 00807 curve_in->position_from_fraction(0.1,loc_0); 00808 curve_in->position_from_fraction(0.5,loc_1); 00809 curve_in->position_from_fraction(0.9,loc_2); 00810 00811 GeometryQueryEngine* gqe = surf_in->get_geometry_query_engine(); 00812 double tol = gqe->get_sme_resabs_tolerance(); 00813 CubitVector cl_pnt_0; 00814 CubitVector cl_pnt_1; 00815 CubitVector cl_pnt_2; 00816 surf_in->closest_point(loc_0,&cl_pnt_0); 00817 surf_in->closest_point(loc_1,&cl_pnt_1); 00818 surf_in->closest_point(loc_2,&cl_pnt_2); 00819 00820 if(cl_pnt_0.distance_between(loc_0)<tol && 00821 cl_pnt_1.distance_between(loc_1)<tol && 00822 cl_pnt_2.distance_between(loc_2)<tol) 00823 { 00824 return CUBIT_TRUE; 00825 } 00826 00827 return CUBIT_FALSE; 00828 } 00829 00830 CubitStatus AutoMidsurfaceTool::find_offset_pair_patches( 00831 DLIList<RefFace*> pairs_list_0, 00832 DLIList<RefFace*> pairs_list_1, 00833 DLIList<RefFace*>& red_faces, 00834 DLIList<RefFace*>& yellow_faces, 00835 DLIList<double>& offset_distances) 00836 { 00837 return CUBIT_FAILURE; 00838 } 00839 00840 CubitStatus AutoMidsurfaceTool::random_loc_on_surface( Surface* face_ptr, CubitVector &loc ) 00841 { 00842 GMem g_mem; 00843 GeometryQueryEngine* gqe = face_ptr->get_geometry_query_engine(); 00844 unsigned short norm_tol = 10; 00845 double dist_tol = -1.0; 00846 gqe->get_graphics( face_ptr, &g_mem, norm_tol, dist_tol ); 00847 00848 if(g_mem.fListCount < 1) 00849 { 00850 // Decrease tolerance and try again (we can get this for small features) 00851 norm_tol /= 2; 00852 gqe->get_graphics( face_ptr, &g_mem, norm_tol, dist_tol); 00853 } 00854 00855 if(g_mem.fListCount < 1) 00856 { 00857 // Lets give up 00858 PRINT_ERROR( "Unable to find location on a surface\n" ); 00859 return CUBIT_FAILURE; 00860 } 00861 00862 // Use the first triangle 00863 GPoint p[3]; 00864 GPoint* plist = g_mem.point_list(); 00865 int* facet_list = g_mem.facet_list(); 00866 int c = 0; 00867 00868 p[0] = plist[facet_list[++c]]; 00869 p[2] = plist[facet_list[++c]]; 00870 p[1] = plist[facet_list[++c]]; 00871 00872 // Get centroid 00873 CubitVector p1( p[0].x, p[0].y, p[0].z ); 00874 CubitVector p2( p[2].x, p[2].y, p[2].z ); 00875 CubitVector p3( p[1].x, p[1].y, p[1].z ); 00876 00877 CubitVector center = (p1 + p2 + p3)/3.0; 00878 00879 face_ptr->closest_point_trimmed(center,loc); 00880 00881 return CUBIT_SUCCESS; 00882 } 00883 00884 CubitBoolean AutoMidsurfaceTool::check_surf_pairs(double min_thick, double max_thick, 00885 DLIList<RefFace*> check_list, Body* body_in ) 00886 { 00887 double total_area = 0.0; 00888 DLIList<RefVolume*> vol_list; 00889 body_in->ref_volumes(vol_list); 00890 double total_vol = 0; 00891 for(int vol_cnt = 0; vol_cnt < vol_list.size(); vol_cnt++) 00892 { 00893 CubitVector cg; 00894 double temp_volume; 00895 vol_list[vol_cnt]->mass_properties(cg,temp_volume); 00896 total_vol += temp_volume; 00897 } 00898 00899 for(int i = 0;i<check_list.size();i++) 00900 total_area += check_list[i]->area(); 00901 00902 total_area/=2.0; 00903 00904 if(min_thick*total_area < total_vol && max_thick*total_area > total_vol) 00905 return CUBIT_TRUE; 00906 00907 return CUBIT_FALSE; 00908 }