cgma
AutoMidsurfaceTool.cpp
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines