cgma
CAEntityId.cpp
Go to the documentation of this file.
00001 //- File:           CAEntityId.cpp
00002 //- Owner:          Dong Zhu
00003 //- Description:    Cubit Attribute for entity ids.
00004 //- Checked By:
00005 //- Version:
00006 
00007 
00008 #include "CAEntityId.hpp"
00009 #include "CAMergePartner.hpp"
00010 #include "TDUniqueId.hpp"
00011 #include "TopologyBridge.hpp"
00012 #include "RefEntity.hpp"
00013 #include "RefVertex.hpp"
00014 #include "RefEdge.hpp"
00015 #include "RefFace.hpp"
00016 #include "CastTo.hpp"
00017 #include "MergeTool.hpp"
00018 #include "RefEntityFactory.hpp"
00019 #include "GeometryQueryTool.hpp"
00020 #include "GSaveOpen.hpp"
00021 #include "CADeferredAttrib.hpp"
00022 #include "BasicTopologyEntity.hpp"
00023 #include "GeometryEntity.hpp"
00024 
00025 CubitAttrib* CAEntityId_creator(RefEntity* entity, const CubitSimpleAttrib &p_csa)
00026 {
00027   return new CAEntityId(entity, p_csa);
00028 }
00029 
00030 CAEntityId::CAEntityId(RefEntity* new_attrib_owner,
00031                        const CubitSimpleAttrib &csa_ptr)
00032         : CubitAttrib(new_attrib_owner)
00033 {
00034   entityId = 0;
00035   boundingUid = CUBIT_INT_MIN;
00036   boundingSense = CUBIT_UNKNOWN;
00037   boundingXYZ = NULL;
00038 
00039   if(!csa_ptr.isEmpty())
00040   {
00041    PRINT_DEBUG_94( "Creating ENTITY_ID attribute from CSA for %s %d\n",
00042       (attribOwnerEntity ? attribOwnerEntity->class_name() : "(none)"),
00043       (attribOwnerEntity ? attribOwnerEntity->id() : 0));
00044    
00045    const std::vector<int>& i_list = csa_ptr.int_data_list();
00046 
00047    assert(i_list.size() > 0);
00048    entityId = i_list[0];
00049 
00050    if (i_list.size() > 1) {
00051      boundingUid = i_list[1];
00052      boundingSense = (CubitSense) (i_list[2]);
00053    }
00054    else {
00055      boundingUid = CUBIT_INT_MIN;
00056      boundingSense = CUBIT_UNKNOWN;
00057    }
00058 
00059    const std::vector<double>& d_list = csa_ptr.double_data_list();
00060    if (d_list.size() > 0) {
00061      assert(d_list.size() == 3);
00062      RefEdge *edge = CAST_TO(new_attrib_owner, RefEdge);
00063      if (edge) {
00064        assert(edge->start_vertex() == edge->end_vertex());
00065      }
00066      else {
00067        PRINT_ERROR("Unexpected NULL pointer for edge.\n");
00068      }
00069      boundingXYZ = new CubitVector(d_list[0],
00070                                    d_list[1],
00071                                    d_list[2]);
00072    }
00073    else boundingXYZ = NULL;
00074   }
00075 }
00076 
00077 CAEntityId::~CAEntityId()
00078 {
00079   if ( boundingXYZ ) delete boundingXYZ;
00080 }
00081 
00082 
00083 CubitStatus CAEntityId::actuate()
00084 {
00085   if ( hasActuated)
00086     return CUBIT_SUCCESS;
00087   
00088   if ( !attribOwnerEntity )
00089     return CUBIT_FAILURE;
00090 
00091   int this_owner_id = attribOwnerEntity->id();
00092 
00093   deleteAttrib = CUBIT_FALSE;
00094 
00095   // First, check to see if we are importing a Cubit file, in which
00096   // case we may need to add an increment to the CAEntityId id, for
00097   // consistency.  In the Cubit file restore, mesh gets reattached to
00098   // geometry based on the geometry id.  When importing into an 
00099   // existing session of Cubit (where a model already exists), we 
00100   // need to use a consistent id increment so that the mesh gets 
00101   // restored to the proper geometry entity.
00102   int id_inc = 0;
00103   if( GSaveOpen::gso_sets_ids() )
00104   {
00105     id_inc = GSaveOpen::get_id_inc( attribOwnerEntity );
00106     if( id_inc == -1 )
00107       id_inc = 0;
00108   }
00109     
00110     // three possibilities:
00111 
00112     // 1) owner entity id is the same as this attrib id
00113   if (entityId == this_owner_id+id_inc) {
00114     hasActuated = CUBIT_TRUE;
00115     PRINT_DEBUG_102("CAEntityId::actuate: already have id for %s %d\n",
00116                     attribOwnerEntity->class_name(), this_owner_id+id_inc);
00117     return CUBIT_SUCCESS;
00118   }
00119 
00120   RefEntity *other_entity = 
00121     GeometryQueryTool::instance()->get_ref_entity(attribOwnerEntity->class_name(), 
00122                                                   entityId+id_inc);
00123 
00124   // Check to make sure the other entity has a valid topology bridge.  If 
00125   // it doesn't it may be a ref entity hanging around that still needs
00126   // to be cleaned up so don't consider it in the checks below.
00127   TopologyEntity *te = dynamic_cast<TopologyEntity*>(other_entity);
00128   if(te && !te->bridge_manager()->topology_bridge())
00129     other_entity = NULL;
00130 
00131     // 2) already an entity with the new id;
00132   if (other_entity) {
00133       // 2a) if other entity has a CAMP attribute, this owner has one too,
00134       //     and they both have the same unique id, these entities will
00135       //     get merged together; need to make sure we assign the lower id
00136       //     to the entity with the correct sense or direction
00137     DLIList<CubitAttrib*> att_list;
00138     other_entity->find_cubit_attrib_type(CA_MERGE_PARTNER, att_list);
00139     CAMergePartner *camp_ptr_other = NULL;
00140     CAMergePartner *camp_ptr_this = NULL;
00141     if (att_list.size() > 0) camp_ptr_other = CAST_TO(att_list.get(), CAMergePartner);
00142     att_list.clean_out();
00143     attribOwnerEntity->find_cubit_attrib_type(CA_MERGE_PARTNER, att_list);
00144     if (att_list.size() > 0) camp_ptr_this = CAST_TO(att_list.get(), CAMergePartner);
00145     
00146     if (camp_ptr_other && camp_ptr_this &&
00147         camp_ptr_other->merge_id()+id_inc == camp_ptr_this->merge_id()+id_inc) {
00148       PRINT_DEBUG_102("CAEntityId::actuate: another entity with same id & merge partner,"
00149                       " this = %s %d, other = %s %d\n",
00150                       attribOwnerEntity->class_name(), this_owner_id+id_inc, other_entity->class_name(),
00151                       entityId+id_inc);
00152 
00153       if (boundingUid != CUBIT_INT_MIN) {
00154           // check the sense of the *other* entity; can't check sense of this
00155           // entity yet, because the topology hasn't been filled yet
00156         RefEdge *edge = CAST_TO(other_entity, RefEdge);
00157         RefFace *face = CAST_TO(other_entity, RefFace);
00158         CubitBoolean switch_ids = CUBIT_FALSE;
00159         
00160         if (edge) {
00161           
00162           if (edge->start_vertex() != edge->end_vertex()) {
00163               // check the start vertex of the other entity
00164             ToolDataUser *tdu = TDUniqueId::find_td_unique_id(boundingUid, other_entity);
00165             RefVertex *vert = CAST_TO(tdu, RefVertex);
00166             assert(vert != 0);
00167             if (vert != edge->start_vertex()) 
00168                 // other entity doesn't have the right sense, so we'll have to switch
00169                 // (we don't know whether this one will have the right sense, and can't
00170                 // check 'cuz this one's topology hasn't been completed yet)
00171 
00172                 // only switch if other entity's id is lower, so that it's not the one kept
00173               if (entityId+id_inc > this_owner_id+id_inc) switch_ids = CUBIT_TRUE;
00174           }
00175           else if (boundingXYZ) {
00176               // else we have a single-vertex curve and an xyz value; 
00177               // check position of 1/3 parameter 
00178             const double ONE_THIRD = 1.0/3.0;
00179             CubitVector test_vec;
00180             /*CubitStatus result = */
00181             edge->position_from_fraction( ONE_THIRD, test_vec);
00182                                                                
00183             if (!GeometryQueryTool::instance()->about_spatially_equal(*boundingXYZ, test_vec)) {
00184               
00185                 // only switch if other entity's id is lower, so that it's not the one kept
00186               if (entityId+id_inc > this_owner_id+id_inc) switch_ids = CUBIT_TRUE;
00187             }
00188           }
00189         }
00190         
00191         else if (face) {
00192             // check sense of other face wrt bounding uid entity; other face should be
00193             // fully constructed by now
00194           ToolDataUser *tdu = TDUniqueId::find_td_unique_id(boundingUid, other_entity);
00195 
00196           edge = CAST_TO(tdu, RefEdge);
00197           if (!edge) 
00198             PRINT_WARNING("CAEntityId::actuate: didn't find edge with uid %d for face %d.\n",
00199                           boundingUid, face->id());
00200           else if (edge->sense(face) != boundingSense && entityId+id_inc > this_owner_id+id_inc) 
00201             switch_ids = CUBIT_TRUE;
00202         }
00203 
00204         if (switch_ids) {
00205           attribOwnerEntity->set_id(0, CUBIT_FALSE);
00206           other_entity->set_id(this_owner_id+id_inc);
00207           PRINT_DEBUG_102("CAEntityId::actuate: other entity with same id, merge partner, and correct sense;"
00208                           " switching id's, this = %s %d, other = %s %d\n",
00209                           attribOwnerEntity->class_name(), this_owner_id+id_inc, other_entity->class_name(),
00210                           entityId+id_inc);
00211           attribOwnerEntity->set_id (entityId+id_inc, CUBIT_FALSE);
00212 //          attribOwnerEntity->color(CUBIT_DEFAULT_COLOR_INDEX);
00213         }
00214       }
00215       
00216       hasActuated = CUBIT_TRUE;
00217       return CUBIT_SUCCESS;
00218     }
00219     
00220       // 2b) if other entity has a CAEID attribute, check to make sure it's not
00221       //     the same, and if not, switch real ids with it (it will get changed later);
00222       //     otherwise, print a warning
00223     other_entity->find_cubit_attrib_type(CA_ENTITY_ID, att_list);
00224     CAEntityId *other_caeid = (att_list.size() ?  CAST_TO(att_list.get(), CAEntityId)
00225                                : NULL);
00226     if (other_caeid && other_caeid->id()+id_inc != entityId+id_inc)
00227     {
00228         // need to reset owner entity id first, so that we don't have
00229         // two identical ids active at the same time (messes up the
00230         // graphics)
00231       
00232       attribOwnerEntity->set_id(0, CUBIT_FALSE);
00233       other_entity->set_id(this_owner_id+id_inc);
00234       PRINT_DEBUG_102("CAEntityId::actuate: other entity with same id, NO merge partner;"
00235                       " switching id's, this = %s %d, other = %s %d\n",
00236                       attribOwnerEntity->class_name(), this_owner_id+id_inc, other_entity->class_name(),
00237                       entityId+id_inc);
00238     }
00239   
00240     else if( camp_ptr_other )
00241     {
00242       DLIList<RefEntity*> merge_partners;
00243       camp_ptr_other->merge_prepare( merge_partners );
00244       int lowest_id = entityId + id_inc;
00245       for( int i = merge_partners.size(); i--; )
00246         if( merge_partners.step_and_get()->id() < lowest_id )
00247           lowest_id = merge_partners.get()->id();
00248       
00249       if( lowest_id < entityId+id_inc )
00250         // Entity will merge later and loose its current Id,
00251         // so we can take the Id for this entity.
00252       {
00253         attribOwnerEntity->set_id(0, CUBIT_FALSE);
00254         other_entity->set_id( this_owner_id + id_inc );
00255       }
00256     
00257     }
00258   }
00259 
00260       // 2b) else print an error and don't actuate
00261   if( other_entity && other_entity->id() == (entityId+id_inc) )
00262   {
00263 //    PRINT_WARNING ( "Duplicate entity id attribute on %s %d; duplicated id = %d.\n"
00264 //                    "This sometimes happens when id attributes are exported without exporting"
00265 //                    " merge attribute.\n",
00266 //                    attribOwnerEntity->class_name(), this_owner_id+id_inc, entityId+id_inc);
00267 //    hasActuated = CUBIT_TRUE;
00268     CADeferredAttrib::add_unactuated_ca(this);
00269     return CUBIT_FAILURE;
00270   }
00271   
00272   else PRINT_DEBUG_102("CAEntityId::actuate: setting id of %s %d; new id = %d\n",
00273                        attribOwnerEntity->class_name(), this_owner_id+id_inc, entityId+id_inc);
00274   
00275     // ok, now set the id and return
00276   attribOwnerEntity->set_id (entityId+id_inc, CUBIT_FALSE);
00277 //  attribOwnerEntity->color(CUBIT_DEFAULT_COLOR_INDEX);
00278   BasicTopologyEntity *bte = CAST_TO( attribOwnerEntity, BasicTopologyEntity );
00279   if( bte )
00280   {
00281     //if doesn't already have an id, set it, otherwise, leave it alone.
00282     if( 0 == bte->get_geometry_entity_ptr()->get_saved_id() )
00283     bte->get_geometry_entity_ptr()->set_saved_id(entityId+id_inc);
00284   }
00285 
00286   hasActuated = CUBIT_TRUE;
00287 
00288   return CUBIT_SUCCESS;
00289 }
00290 
00291 CubitStatus CAEntityId::update()
00292 {
00293   if ( hasUpdated ) 
00294      return CUBIT_SUCCESS;
00295 
00296   if ( !attribOwnerEntity)
00297     return CUBIT_FAILURE;
00298 
00299   entityId = attribOwnerEntity->id ( );
00300 
00301     // set the updated flag
00302   hasUpdated = CUBIT_TRUE;
00303 
00304     // set the sense data
00305   TopologyEntity *topo_entity = CAST_TO(attribOwnerEntity, TopologyEntity);
00306   assert(topo_entity != 0);
00307   if (MergeTool::instance()->entity_merged(topo_entity) == CUBIT_FALSE)
00308     return CUBIT_SUCCESS;
00309   
00310     // get the uid of the first child entity
00311   RefEdge *edge;
00312   RefFace *face;
00313   if ((edge = CAST_TO(attribOwnerEntity, RefEdge)) != NULL) {
00314     RefVertex *vert = edge->start_vertex();
00315     boundingUid = TDUniqueId::get_unique_id(vert);
00316     boundingSense = CUBIT_FORWARD;
00317 
00318       // need to check for single-vertex curves
00319     if (vert == edge->end_vertex()) {
00320         // if it is one, store the xyz of 1/3 down the curve
00321       const double ONE_THIRD = 1.0/3.0;
00322         // Find the point 1/3 along *this*
00323       if (!boundingXYZ) boundingXYZ = new CubitVector();
00324       CubitStatus result = edge->position_from_fraction( ONE_THIRD,
00325                                                          *boundingXYZ);
00326       if ( result != CUBIT_SUCCESS )
00327       {
00328         PRINT_ERROR("Error in CAEntityId::update;"
00329                     "Can't find position 1/3 along curve.\n");
00330         return CUBIT_FAILURE;
00331       }
00332     }
00333   }
00334 
00335   else if ((face = CAST_TO(attribOwnerEntity, RefFace)) != NULL) {
00336     DLIList<RefEdge*> edges;
00337     face->ref_edges(edges);
00338     if (edges.size()) {
00339       edge = edges.get_and_step();
00340       boundingUid = TDUniqueId::get_unique_id(edge);
00341       boundingSense = edge->sense(face); 
00342       return CUBIT_SUCCESS;
00343     }
00344   }
00345     
00346   return CUBIT_SUCCESS;
00347 }
00348 
00349 void CAEntityId::merge_owner(CubitAttrib *deletable_attrib)
00350 {
00351     // take the id with the lowest value
00352   CAEntityId *other_caeid = CAST_TO(deletable_attrib, CAEntityId);
00353   
00354   if (other_caeid &&
00355       (entityId == 0 || entityId > other_caeid->id()))
00356     entityId = other_caeid->id();
00357 }
00358 
00359 CubitSimpleAttrib CAEntityId::cubit_simple_attrib()
00360 {
00361   std::vector<CubitString> cs_list;
00362   std::vector<double> d_list;
00363   std::vector<int> i_list;
00364 
00365   i_list.push_back ( entityId );
00366   i_list.push_back ( boundingUid );
00367   i_list.push_back ( boundingSense );
00368   if (boundingXYZ) {
00369     d_list.push_back ( boundingXYZ->x() );
00370     d_list.push_back ( boundingXYZ->y() );
00371     d_list.push_back ( boundingXYZ->z() );
00372   }
00373     
00374   cs_list.push_back(att_internal_name());
00375 
00376   return CubitSimpleAttrib(&cs_list, &d_list, &i_list);
00377 }
00378 
00379 void CAEntityId::print()
00380 {
00381     // print info on this attribute
00382   
00383   PRINT_INFO("CAEntityId: owner = %s %d:   id=%d, color=%d\n",
00384              attribOwnerEntity->class_name(), attribOwnerEntity->id(),
00385              entityId, 0);
00386 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines