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