@@ -915,6 +915,20 @@ void IfcParse::IfcFile::register_inverse(unsigned id_from, Token t) {
915915 byref[t.value_int ].push_back (id_from);
916916}
917917
918+ void IfcParse::IfcFile::register_inverse (unsigned id_from, IfcUtil::IfcBaseClass* inst) {
919+ byref[inst->entity ->id ()].push_back (id_from);
920+ }
921+
922+ void IfcParse::IfcFile::unregister_inverse (unsigned id_from, IfcUtil::IfcBaseClass* inst) {
923+ std::vector<unsigned int >& ids = byref[inst->entity ->id ()];
924+ std::vector<unsigned int >::const_iterator it = std::find (ids.begin (), ids.end (), id_from);
925+ if (it == ids.end ()) {
926+ throw IfcParse::IfcException (" Instance not found among inverses" );
927+ } else {
928+ ids.erase (it);
929+ }
930+ }
931+
918932//
919933// Returns a string representation of the entity
920934// Note that this initializes the entity if it is not initialized
@@ -1008,6 +1022,97 @@ Argument* IfcEntityInstanceData::getArgument(unsigned int i) const {
10081022 }
10091023}
10101024
1025+ class unregister_inverse_visitor {
1026+ private:
1027+ IfcFile& file_;
1028+ const IfcEntityInstanceData& data_;
1029+
1030+ public:
1031+ unregister_inverse_visitor (IfcFile& file, const IfcEntityInstanceData& data)
1032+ : file_(file), data_(data)
1033+ {}
1034+
1035+ void operator ()(IfcUtil::IfcBaseClass* inst) {
1036+ file_.unregister_inverse (data_.id (), inst);
1037+ }
1038+ };
1039+
1040+ class register_inverse_visitor {
1041+ private:
1042+ IfcFile& file_;
1043+ const IfcEntityInstanceData& data_;
1044+
1045+ public:
1046+ register_inverse_visitor (IfcFile& file, const IfcEntityInstanceData& data)
1047+ : file_(file), data_(data)
1048+ {}
1049+
1050+ void operator ()(IfcUtil::IfcBaseClass* inst) {
1051+ file_.register_inverse (data_.id (), inst);
1052+ }
1053+ };
1054+
1055+ class add_to_instance_list_visitor {
1056+ private:
1057+ IfcEntityList::ptr& list_;
1058+
1059+ public:
1060+ add_to_instance_list_visitor (IfcEntityList::ptr& list)
1061+ : list_(list)
1062+ {}
1063+
1064+ void operator ()(IfcUtil::IfcBaseClass* inst) {
1065+ list_->push (inst);
1066+ }
1067+ };
1068+
1069+ class apply_individual_instance_visitor {
1070+ private:
1071+ Argument* attribute_;
1072+ IfcEntityInstanceData* data_;
1073+
1074+ template <typename T>
1075+ void apply_attribute_ (T& t, Argument* attr) const {
1076+ if (attr->type () == IfcUtil::Argument_ENTITY_INSTANCE) {
1077+ IfcUtil::IfcBaseClass* inst = *attr;
1078+ t (inst);
1079+ } else if (attr->type () == IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE) {
1080+ IfcEntityList::ptr entity_list_attribute = *attr;
1081+ for (IfcEntityList::it it = entity_list_attribute->begin (); it != entity_list_attribute->end (); ++it) {
1082+ t (*it);
1083+ }
1084+ } else if (attr->type () == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE) {
1085+ IfcEntityListList::ptr entity_list_attribute = *attr;
1086+ for (IfcEntityListList::outer_it it = entity_list_attribute->begin (); it != entity_list_attribute->end (); ++it) {
1087+ for (IfcEntityListList::inner_it jt = it->begin (); jt != it->end (); ++jt) {
1088+ t (*jt);
1089+ }
1090+ }
1091+ }
1092+ };
1093+ public:
1094+ apply_individual_instance_visitor (Argument* attribute)
1095+ : attribute_(attribute), data_(0 )
1096+ {}
1097+
1098+ apply_individual_instance_visitor (IfcEntityInstanceData* data)
1099+ : attribute_(0 ), data_(data)
1100+ {}
1101+
1102+ template <typename T>
1103+ void apply (T& t) const {
1104+ if (attribute_) {
1105+ apply_attribute_ (t, attribute_);
1106+ } else {
1107+ for (unsigned i = 0 ; i < data_->getArgumentCount (); ++i) {
1108+ Argument* attr = data_->getArgument (i);
1109+ apply_attribute_ (t, attr);
1110+ }
1111+ }
1112+ };
1113+
1114+ };
1115+
10111116void IfcEntityInstanceData::setArgument (unsigned int i, Argument* a, IfcUtil::ArgumentType attr_type) {
10121117 if (!initialized_) {
10131118 load ();
@@ -1017,10 +1122,6 @@ void IfcEntityInstanceData::setArgument(unsigned int i, Argument* a, IfcUtil::Ar
10171122 attributes_.push_back (new NullArgument ());
10181123 }
10191124
1020- if (i < attributes_.size ()) {
1021- delete attributes_[i];
1022- }
1023-
10241125 if (attr_type == IfcUtil::Argument_UNKNOWN) {
10251126 attr_type = a->type ();
10261127 }
@@ -1117,6 +1218,20 @@ void IfcEntityInstanceData::setArgument(unsigned int i, Argument* a, IfcUtil::Ar
11171218 break ;
11181219 }
11191220
1221+ if (i < attributes_.size ()) {
1222+ Argument* current_attribute = attributes_[i];
1223+ if (this ->file ) {
1224+ unregister_inverse_visitor visitor (*this ->file , *this );
1225+ apply_individual_instance_visitor (current_attribute).apply (visitor);
1226+ }
1227+ delete attributes_[i];
1228+ }
1229+
1230+ if (this ->file ) {
1231+ register_inverse_visitor visitor (*this ->file , *this );
1232+ apply_individual_instance_visitor (copy).apply (visitor);
1233+ }
1234+
11201235 if (i < attributes_.size ()) {
11211236 attributes_[i] = copy;
11221237 } else {
@@ -1271,25 +1386,8 @@ void traverse_(IfcUtil::IfcBaseClass* instance, std::set<IfcUtil::IfcBaseClass*>
12711386
12721387 if (level >= max_level && max_level > 0 ) return ;
12731388
1274- for (unsigned i = 0 ; i < instance->getArgumentCount (); ++i) {
1275- Argument* arg = instance->getArgument (i);
1276-
1277- if (arg->type () == IfcUtil::Argument_ENTITY_INSTANCE) {
1278- traverse_ (*arg, visited, list, level + 1 , max_level);
1279- } else if (arg->type () == IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE) {
1280- IfcEntityList::ptr entity_list_attribute = *arg;
1281- for (IfcEntityList::it it = entity_list_attribute->begin (); it != entity_list_attribute->end (); ++it) {
1282- traverse_ (*it, visited, list, level + 1 , max_level);
1283- }
1284- } else if (arg->type () == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE) {
1285- IfcEntityListList::ptr entity_list_attribute = *arg;
1286- for (IfcEntityListList::outer_it it = entity_list_attribute->begin (); it != entity_list_attribute->end (); ++it) {
1287- for (IfcEntityListList::inner_it jt = it->begin (); jt != it->end (); ++jt) {
1288- traverse_ (*jt, visited, list, level + 1 , max_level);
1289- }
1290- }
1291- }
1292- }
1389+ add_to_instance_list_visitor visit (list);
1390+ apply_individual_instance_visitor (instance->entity ).apply (visit);
12931391}
12941392
12951393IfcEntityList::ptr IfcParse::traverse (IfcUtil::IfcBaseClass* instance, int max_level) {
0 commit comments