2
0
Эх сурвалжийг харах

- IFC: implement the IfcRevolvedAreaSolid and IfcCircleProfileDef entities. Improve vertical extrusion code.

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@998 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
aramis_acg 14 жил өмнө
parent
commit
f64f0446db

+ 228 - 43
code/IFCLoader.cpp

@@ -93,6 +93,7 @@ struct ConversionData
 {
 	ConversionData(const STEP::DB& db, const IFC::IfcProject& proj, aiScene* out,const IFCImporter::Settings& settings)
 		: len_scale(1.0)
+		, angle_scale(1.0)
 		, db(db)
 		, proj(proj)
 		, out(out)
@@ -104,7 +105,8 @@ struct ConversionData
 		std::for_each(materials.begin(),materials.end(),delete_fun<aiMaterial>());
 	}
 
-	float len_scale;
+	float len_scale, angle_scale;
+	bool plane_angle_in_radians;
 
 	const STEP::DB& db;
 	const IFC::IfcProject& proj;
@@ -172,6 +174,7 @@ void ProcessSpatialStructures(ConversionData& conv);
 aiNode* ProcessSpatialStructure(aiNode* parent, const IFC::IfcProduct& el ,ConversionData& conv);
 void ProcessProductRepresentation(const IFC::IfcProduct& el, aiNode* nd, ConversionData& conv);
 void MakeTreeRelative(ConversionData& conv);
+void ConvertUnit(const EXPRESS::DataType* dt,ConversionData& conv);
 
 } // anon
 
@@ -369,25 +372,61 @@ float ConvertSIPrefix(const std::string& prefix)
 }
 
 // ------------------------------------------------------------------------------------------------
-void SetUnits(ConversionData& conv)
+void ConvertUnit(const IFC::IfcNamedUnit& unit,ConversionData& conv)
 {
-	// see if we can determine the coordinate space used to express
-	for(size_t i = 0; i <  conv.proj.UnitsInContext->Units.size(); ++i ) {
-		try {
-			const EXPRESS::ENTITY& e = conv.proj.UnitsInContext->Units[i]->To<IFC::ENTITY>();
-			const IFC::IfcSIUnit& si = conv.db.MustGetObject(e).To<IFC::IfcSIUnit>(); 
+	if(const IFC::IfcSIUnit* const si = unit.ToPtr<IFC::IfcSIUnit>()) {
 
-			if(si.UnitType == "LENGTHUNIT" && si.Prefix) {
-				conv.len_scale = ConvertSIPrefix(si.Prefix);
-				IFCImporter::LogDebug("got units used for lengths");
+		if(si->UnitType == "LENGTHUNIT") { 
+			conv.len_scale = si->Prefix ? ConvertSIPrefix(si->Prefix) : 1.f;
+			IFCImporter::LogDebug("got units used for lengths");
+		}
+		if(si->UnitType == "PLANEANGLEUNIT") { 
+			if (si->Name != "RADIAN") {
+				IFCImporter::LogWarn("expected base unit for angles to be radian");
 			}
 		}
-		catch(std::bad_cast&) {
-			// not SI unit, not implemented
-			continue;
+	}
+	else if(const IFC::IfcConversionBasedUnit* const convu = unit.ToPtr<IFC::IfcConversionBasedUnit>()) {
+
+		if(convu->UnitType == "PLANEANGLEUNIT") { 
+			try {
+				conv.angle_scale = convu->ConversionFactor->ValueComponent->To<EXPRESS::REAL>();
+				ConvertUnit(convu->ConversionFactor->UnitComponent,conv);
+				IFCImporter::LogDebug("got units used for angles");
+			}
+			catch(std::bad_cast&) {
+				IFCImporter::LogError("skipping unknown IfcConversionBasedUnit.ValueComponent entry - expected REAL");
+			}
+		}
+	}
+}
+
+// ------------------------------------------------------------------------------------------------
+void ConvertUnit(const EXPRESS::DataType* dt,ConversionData& conv)
+{
+	try {
+		const EXPRESS::ENTITY& e = dt->To<IFC::ENTITY>();
+
+		const IFC::IfcNamedUnit& unit = e.ResolveSelect<IFC::IfcNamedUnit>(conv.db);
+		if(unit.UnitType != "LENGTHUNIT" && unit.UnitType != "PLANEANGLEUNIT") {
+			return;
 		}
+
+		ConvertUnit(unit,conv);
+	}
+	catch(std::bad_cast&) {
+		// not entity, somehow
+		IFCImporter::LogError("skipping unknown IfcUnit entry - expected entity");
 	}
+}
 
+// ------------------------------------------------------------------------------------------------
+void SetUnits(ConversionData& conv)
+{
+	// see if we can determine the coordinate space used to express. 
+	for(size_t i = 0; i <  conv.proj.UnitsInContext->Units.size(); ++i ) {
+		ConvertUnit(conv.proj.UnitsInContext->Units[i],conv);
+	}
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -502,6 +541,18 @@ void ConvertAxisPlacement(aiMatrix4x4& out, const IFC::IfcAxis2Placement2D& in,
 	AssignMatrixAxes(out,x,y,aiVector3D(0.f,0.f,1.f));
 }
 
+// ------------------------------------------------------------------------------------------------
+void ConvertAxisPlacement(aiVector3D& axis, aiVector3D& pos, const IFC::IfcAxis1Placement& in, ConversionData& conv)
+{
+	ConvertCartesianPoint(pos,in.Location);
+	if (in.Axis) {
+		ConvertDirection(axis,in.Axis.Get());
+	}
+	else {
+		axis = aiVector3D(0.f,0.f,1.f);
+	}
+}
+
 // ------------------------------------------------------------------------------------------------
 void ConvertAxisPlacement(aiMatrix4x4& out, const IFC::IfcAxis2Placement& in, ConversionData& conv)
 {
@@ -790,7 +841,7 @@ void ProcessOpenProfile(const IFC::IfcArbitraryOpenProfileDef& def, TempMesh& me
 // ------------------------------------------------------------------------------------------------
 void ProcessParametrizedProfile(const IFC::IfcParameterizedProfileDef& def, TempMesh& meshout, ConversionData& conv)
 {
-	if(const IFC::IfcRectangleProfileDef* cprofile = def.ToPtr<IFC::IfcRectangleProfileDef>()) {
+	if(const IFC::IfcRectangleProfileDef* const cprofile = def.ToPtr<IFC::IfcRectangleProfileDef>()) {
 		const float x = cprofile->XDim*0.5f, y = cprofile->YDim*0.5f;
 
 		meshout.verts.reserve(meshout.verts.size()+4);
@@ -800,6 +851,22 @@ void ProcessParametrizedProfile(const IFC::IfcParameterizedProfileDef& def, Temp
 		meshout.verts.push_back( aiVector3D( x,-y, 0.f ));
 		meshout.vertcnt.push_back(4);
 	}
+	else if( const IFC::IfcCircleProfileDef* const circle = def.ToPtr<IFC::IfcCircleProfileDef>()) {
+		if( const IFC::IfcCircleHollowProfileDef* const hollow = def.ToPtr<IFC::IfcCircleHollowProfileDef>()) {
+			// TODO
+		}
+		const size_t segments = 32;
+		const float delta = AI_MATH_TWO_PI_F/segments, radius = circle->Radius;
+
+		meshout.verts.reserve(segments);
+
+		float angle = 0.f;
+		for(size_t i = 0; i < segments; ++i, angle += delta) {
+			meshout.verts.push_back( aiVector3D( cos(angle)*radius, sin(angle)*radius, 0.f ));
+		}
+	
+		meshout.vertcnt.push_back(segments);
+	}
 	else {
 		IFCImporter::LogWarn("skipping unknown IfcParameterizedProfileDef entity, type is " + def.GetClassName());
 		return;
@@ -814,24 +881,145 @@ void ProcessParametrizedProfile(const IFC::IfcParameterizedProfileDef& def, Temp
 }
 
 // ------------------------------------------------------------------------------------------------
-void ProcessExtrudedAreaSolid(const IFC::IfcExtrudedAreaSolid& solid, TempMesh& result, ConversionData& conv)
+bool ProcessProfile(const IFC::IfcProfileDef& prof, TempMesh& meshout, ConversionData& conv) 
 {
-	TempMesh meshout;
-	if(const IFC::IfcArbitraryClosedProfileDef* cprofile = solid.SweptArea->ToPtr<IFC::IfcArbitraryClosedProfileDef>()) {
+	if(const IFC::IfcArbitraryClosedProfileDef* const cprofile = prof.ToPtr<IFC::IfcArbitraryClosedProfileDef>()) {
 		ProcessClosedProfile(*cprofile,meshout,conv);
 	}
-	else if(const IFC::IfcArbitraryOpenProfileDef* copen = solid.SweptArea->ToPtr<IFC::IfcArbitraryOpenProfileDef>()) {
+	else if(const IFC::IfcArbitraryOpenProfileDef* const copen = prof.ToPtr<IFC::IfcArbitraryOpenProfileDef>()) {
 		ProcessOpenProfile(*copen,meshout,conv);
 	}
-	else if(const IFC::IfcParameterizedProfileDef* cparam = solid.SweptArea->ToPtr<IFC::IfcParameterizedProfileDef>()) {
+	else if(const IFC::IfcParameterizedProfileDef* const cparam = prof.ToPtr<IFC::IfcParameterizedProfileDef>()) {
 		ProcessParametrizedProfile(*cparam,meshout,conv);
 	}
 	else {
-		IFCImporter::LogWarn("skipping unknown IfcProfileDef entity, type is " + solid.SweptArea->GetClassName());
+		IFCImporter::LogWarn("skipping unknown IfcProfileDef entity, type is " + prof.GetClassName());
+		return false;
+	}
+	return true;
+}
+
+// ------------------------------------------------------------------------------------------------
+void FixupFaceOrientation(TempMesh& result)
+{
+	aiVector3D vavg;
+	BOOST_FOREACH(aiVector3D& v, result.verts) {
+		vavg += v;
+	}
+
+	// fixup face orientation.
+	vavg /= static_cast<float>( result.verts.size() );
+
+	size_t c = 0;
+	BOOST_FOREACH(unsigned int cnt, result.vertcnt) {
+		if (cnt>2){
+			const aiVector3D& thisvert = result.verts[c];
+			const aiVector3D normal((thisvert-result.verts[c+1])^(thisvert-result.verts[c+2]));
+			if (normal*(thisvert-vavg) < 0) {
+				std::reverse(result.verts.begin()+c,result.verts.begin()+cnt+c);
+			}
+		}
+		c += cnt;
+	}
+}
+
+// ------------------------------------------------------------------------------------------------
+void ProcessRevolvedAreaSolid(const IFC::IfcRevolvedAreaSolid& solid, TempMesh& result, ConversionData& conv)
+{
+	TempMesh meshout;
+
+	// first read the profile description
+	if(!ProcessProfile(*solid.SweptArea,meshout,conv) || meshout.verts.size()<=1) {
 		return;
 	}
 
-	if(meshout.verts.size()<=1) {
+	aiVector3D axis, pos;
+	ConvertAxisPlacement(axis,pos,solid.Axis,conv);
+
+	aiMatrix4x4 tb0,tb1;
+	aiMatrix4x4::Translation(pos,tb0);
+	aiMatrix4x4::Translation(-pos,tb1);
+
+	const std::vector<aiVector3D>& in = meshout.verts;
+	const size_t size=in.size();
+	
+	bool has_area = solid.SweptArea->ProfileType == "AREA" && size>2;
+	const float max_angle = solid.Angle*conv.angle_scale;
+	if(fabs(max_angle) < 1e-3) {
+		if(has_area) {
+			result = meshout;
+		}
+		return;
+	}
+
+	const unsigned int cnt_segments = std::max(2u,static_cast<unsigned int>(16 * fabs(max_angle)/AI_MATH_HALF_PI_F));
+	const float delta = max_angle/cnt_segments;
+
+	has_area = has_area && fabs(max_angle) < AI_MATH_TWO_PI_F*0.99;
+	
+	result.verts.reserve(size*((cnt_segments+1)*4+(has_area?2:0)));
+	result.vertcnt.reserve(size*cnt_segments+2);
+
+	aiMatrix4x4 rot;
+	rot = tb0 * aiMatrix4x4::Rotation(delta,axis,rot) * tb1;
+
+	size_t base = 0;
+	std::vector<aiVector3D>& out = result.verts;
+
+	// dummy data to simplify later processing
+	for(size_t i = 0; i < size; ++i) {
+		out.insert(out.end(),4,in[i]);
+	}
+
+	for(unsigned int seg = 0; seg < cnt_segments; ++seg) {
+		for(size_t i = 0; i < size; ++i) {
+			const size_t next = (i+1)%size;
+
+			result.vertcnt.push_back(4);
+			const aiVector3D& base_0 = out[base+i*4+3],base_1 = out[base+next*4+3];
+
+			out.push_back(base_0);
+			out.push_back(base_1);
+			out.push_back(rot*base_1);
+			out.push_back(rot*base_0);
+		}
+		base += size*4;
+	}
+
+	out.erase(out.begin(),out.begin()+size*4);
+
+	if(has_area) {
+		// leave the triangulation of the profile area to the ear cutting 
+		// implementation in aiProcess_Triangulate - for now we just
+		// feed in two huge polygons.
+		base -= size*8;
+		for(size_t i = size; i--; ) {
+			out.push_back(out[base+i*4+3]);
+		}
+		for(size_t i = 0; i < size; ++i ) {
+			out.push_back(out[i*4]);
+		}
+		result.vertcnt.push_back(size);
+		result.vertcnt.push_back(size);
+	}
+
+	aiMatrix4x4 trafo;
+	ConvertAxisPlacement(trafo, solid.Position,conv);
+	BOOST_FOREACH(aiVector3D& v, out) {
+		v *= trafo;
+	}
+
+	FixupFaceOrientation(result);
+	IFCImporter::LogDebug("generate mesh procedurally by radial extrusion (IfcRevolvedAreaSolid)");
+}
+
+// ------------------------------------------------------------------------------------------------
+void ProcessExtrudedAreaSolid(const IFC::IfcExtrudedAreaSolid& solid, TempMesh& result, ConversionData& conv)
+{
+	TempMesh meshout;
+	
+	// first read the profile description
+	if(!ProcessProfile(*solid.SweptArea,meshout,conv) || meshout.verts.size()<=1) {
 		return;
 	}
 
@@ -848,6 +1036,12 @@ void ProcessExtrudedAreaSolid(const IFC::IfcExtrudedAreaSolid& solid, TempMesh&
 	const size_t size=in.size();
 
 	const bool has_area = solid.SweptArea->ProfileType == "AREA" && size>2;
+	if(solid.Depth < 1e-3) {
+		if(has_area) {
+			meshout = result;
+		}
+		return;
+	}
 
 	result.verts.reserve(size*(has_area?4:2));
 	result.vertcnt.reserve(meshout.vertcnt.size()+2);
@@ -866,7 +1060,7 @@ void ProcessExtrudedAreaSolid(const IFC::IfcExtrudedAreaSolid& solid, TempMesh&
 	if(has_area) {
 		// leave the triangulation of the profile area to the ear cutting 
 		// implementation in aiProcess_Triangulate - for now we just
-		// feed in a possibly huge polygon.
+		// feed in two huge polygons.
 		for(size_t i = size; i--; ) {
 			result.verts.push_back(in[i]+dir);
 		}
@@ -880,36 +1074,23 @@ void ProcessExtrudedAreaSolid(const IFC::IfcExtrudedAreaSolid& solid, TempMesh&
 	aiMatrix4x4 trafo;
 	ConvertAxisPlacement(trafo, solid.Position,conv);
 
-	aiVector3D vavg;
 	BOOST_FOREACH(aiVector3D& v, result.verts) {
 		v *= trafo;
-		vavg += v;
-	}
-
-	// fixup face orientation.
-	vavg /= static_cast<float>( result.verts.size() );
-
-	size_t c = 0;
-	BOOST_FOREACH(unsigned int cnt, result.vertcnt) {
-		if (cnt>2){
-			const aiVector3D& thisvert = result.verts[c];
-			const aiVector3D normal((thisvert-result.verts[c+1])^(thisvert-result.verts[c+2]));
-			if (normal*(thisvert-vavg) < 0) {
-				std::reverse(result.verts.begin()+c,result.verts.begin()+cnt+c);
-			}
-		}
-		c += cnt;
 	}
 
+	FixupFaceOrientation(result);
 	IFCImporter::LogDebug("generate mesh procedurally by extrusion (IfcExtrudedAreaSolid)");
 }
 
 // ------------------------------------------------------------------------------------------------
 void ProcessSweptAreaSolid(const IFC::IfcSweptAreaSolid& swept, TempMesh& meshout, ConversionData& conv)
 {
-	if(const IFC::IfcExtrudedAreaSolid* solid = swept.ToPtr<IFC::IfcExtrudedAreaSolid>()) {
+	if(const IFC::IfcExtrudedAreaSolid* const solid = swept.ToPtr<IFC::IfcExtrudedAreaSolid>()) {
 		ProcessExtrudedAreaSolid(*solid,meshout,conv);
 	}
+	else if(const IFC::IfcRevolvedAreaSolid* const rev = swept.ToPtr<IFC::IfcRevolvedAreaSolid>()) {
+		ProcessRevolvedAreaSolid(*rev,meshout,conv);
+	}
 	else {
 		IFCImporter::LogWarn("skipping unknown IfcSweptAreaSolid entity, type is " + swept.GetClassName());
 	}
@@ -923,7 +1104,7 @@ void ProcessBoolean(const IFC::IfcBooleanResult& boolean, TempMesh& meshout, Con
 			ProcessBoolean(*op0,meshout,conv);
 		}
 		else if (const IFC::IfcSweptAreaSolid* const swept = clip->FirstOperand->ResolveSelectPtr<IFC::IfcSweptAreaSolid>(conv.db)) {
-			//ProcessSweptAreaSolid(*swept,meshout,conv);
+			ProcessSweptAreaSolid(*swept,meshout,conv);
 			// XXX
 		}
 	}
@@ -1081,7 +1262,6 @@ bool ProcessGeometricItem(const IFC::IfcGeometricRepresentationItem& geo, std::v
 			}
 			catch(std::bad_cast&) {
 				IFCImporter::LogWarn("unexpected type error, IfcShell ought to inherit from IfcConnectedFaceSet");
-				continue;
 			}
 		}
 	}
@@ -1091,6 +1271,11 @@ bool ProcessGeometricItem(const IFC::IfcGeometricRepresentationItem& geo, std::v
 	else if(const IFC::IfcManifoldSolidBrep* brep = geo.ToPtr<IFC::IfcManifoldSolidBrep>()) {
 		ProcessConnectedFaceSet(brep->Outer,meshtmp,conv);
 	}
+	else if(const IFC::IfcFaceBasedSurfaceModel* surf = geo.ToPtr<IFC::IfcFaceBasedSurfaceModel>()) {
+		BOOST_FOREACH(const IFC::IfcConnectedFaceSet& fc, surf->FbsmFaces) {
+			ProcessConnectedFaceSet(fc,meshtmp,conv);
+		}
+	}
 	else if(const IFC::IfcBooleanResult* boolean = geo.ToPtr<IFC::IfcBooleanResult>()) {
 		ProcessBoolean(*boolean,meshtmp,conv);
 	}
@@ -1214,7 +1399,7 @@ void ProcessMappedItem(const IFC::IfcMappedItem& mapped, aiNode* nd_src, std::ve
 	const IFC::IfcRepresentation& repr = mapped.MappingSource->MappedRepresentation;
 	BOOST_FOREACH(const IFC::IfcRepresentationItem& item, repr.Items) {
 		if(!ProcessRepresentationItem(item,meshes,conv)) {
-			IFCImporter::LogWarn("skipping unknown IfcMappedItem entity, type is " + item.GetClassName());
+			IFCImporter::LogWarn("skipping unknown mapped entity, type is " + item.GetClassName());
 		}
 	}
 	AssignAddedMeshes(meshes,nd.get(),conv);

+ 61 - 6
code/IFCReaderGen.cpp

@@ -501,7 +501,7 @@ namespace {
 ,		SchemaEntry("ifcfaceouterbound",&STEP::ObjectHelper<IfcFaceOuterBound,0>::Construct )
 ,		SchemaEntry("ifcfeatureelementaddition",&STEP::ObjectHelper<IfcFeatureElementAddition,0>::Construct )
 ,		SchemaEntry("ifcnamedunit",&STEP::ObjectHelper<IfcNamedUnit,2>::Construct )
-,		SchemaEntry("ifcconversionbasedunit",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+,		SchemaEntry("ifcconversionbasedunit",&STEP::ObjectHelper<IfcConversionBasedUnit,2>::Construct )
 ,		SchemaEntry("ifcstructuralloadsingleforce",&STEP::ObjectHelper<NotImplemented,0>::Construct )
 ,		SchemaEntry("ifcheatexchangertype",&STEP::ObjectHelper<IfcHeatExchangerType,1>::Construct )
 ,		SchemaEntry("ifcpresentationstyleassignment",&STEP::ObjectHelper<IfcPresentationStyleAssignment,1>::Construct )
@@ -637,7 +637,7 @@ namespace {
 ,		SchemaEntry("ifcdampertype",&STEP::ObjectHelper<IfcDamperType,1>::Construct )
 ,		SchemaEntry("ifcsiunit",&STEP::ObjectHelper<IfcSIUnit,2>::Construct )
 ,		SchemaEntry("ifcsurfacestylelighting",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-,		SchemaEntry("ifcmeasurewithunit",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+,		SchemaEntry("ifcmeasurewithunit",&STEP::ObjectHelper<IfcMeasureWithUnit,2>::Construct )
 ,		SchemaEntry("ifcmateriallayerset",&STEP::ObjectHelper<NotImplemented,0>::Construct )
 ,		SchemaEntry("ifcdistributionelement",&STEP::ObjectHelper<IfcDistributionElement,0>::Construct )
 ,		SchemaEntry("ifcdistributioncontrolelement",&STEP::ObjectHelper<IfcDistributionControlElement,1>::Construct )
@@ -1740,6 +1740,22 @@ template <> size_t GenericFill<IfcNamedUnit>(const DB& db, const LIST& params, I
 	return base;
 }
 // -----------------------------------------------------------------------------------------------------------
+template <> size_t GenericFill<IfcConversionBasedUnit>(const DB& db, const LIST& params, IfcConversionBasedUnit* in)
+{
+	size_t base = GenericFill(db,params,static_cast<IfcNamedUnit*>(in));
+	if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcConversionBasedUnit"); }    do { // convert the 'Name' argument
+        const DataType* arg = params[base++];
+        try { GenericConvert( in->Name, *arg, db ); break; } 
+        catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcConversionBasedUnit to be a `IfcLabel`")); }
+    } while(0);
+    do { // convert the 'ConversionFactor' argument
+        const DataType* arg = params[base++];
+        try { GenericConvert( in->ConversionFactor, *arg, db ); break; } 
+        catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcConversionBasedUnit to be a `IfcMeasureWithUnit`")); }
+    } while(0);
+	return base;
+}
+// -----------------------------------------------------------------------------------------------------------
 template <> size_t GenericFill<IfcHeatExchangerType>(const DB& db, const LIST& params, IfcHeatExchangerType* in)
 {
 	size_t base = GenericFill(db,params,static_cast<IfcEnergyConversionDeviceType*>(in));
@@ -1998,7 +2014,12 @@ template <> size_t GenericFill<IfcBoundedCurve>(const DB& db, const LIST& params
 template <> size_t GenericFill<IfcAxis1Placement>(const DB& db, const LIST& params, IfcAxis1Placement* in)
 {
 	size_t base = GenericFill(db,params,static_cast<IfcPlacement*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
+	if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcAxis1Placement"); }    do { // convert the 'Axis' argument
+        const DataType* arg = params[base++];
+        if (dynamic_cast<const UNSET*>(&*arg)) break;
+        try { GenericConvert( in->Axis, *arg, db ); break; } 
+        catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcAxis1Placement to be a `IfcDirection`")); }
+    } while(0);
 	return base;
 }
 // -----------------------------------------------------------------------------------------------------------
@@ -2420,7 +2441,12 @@ template <> size_t GenericFill<IfcSanitaryTerminalType>(const DB& db, const LIST
 template <> size_t GenericFill<IfcCircleProfileDef>(const DB& db, const LIST& params, IfcCircleProfileDef* in)
 {
 	size_t base = GenericFill(db,params,static_cast<IfcParameterizedProfileDef*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
+	if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcCircleProfileDef"); }    do { // convert the 'Radius' argument
+        const DataType* arg = params[base++];
+        if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcCircleProfileDef,1>::aux_is_derived[0]=true; break; }
+        try { GenericConvert( in->Radius, *arg, db ); break; } 
+        catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcCircleProfileDef to be a `IfcPositiveLengthMeasure`")); }
+    } while(0);
 	return base;
 }
 // -----------------------------------------------------------------------------------------------------------
@@ -2516,6 +2542,22 @@ template <> size_t GenericFill<IfcSIUnit>(const DB& db, const LIST& params, IfcS
 	return base;
 }
 // -----------------------------------------------------------------------------------------------------------
+template <> size_t GenericFill<IfcMeasureWithUnit>(const DB& db, const LIST& params, IfcMeasureWithUnit* in)
+{
+	size_t base = 0;
+	if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcMeasureWithUnit"); }    do { // convert the 'ValueComponent' argument
+        const DataType* arg = params[base++];
+        try { GenericConvert( in->ValueComponent, *arg, db ); break; } 
+        catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcMeasureWithUnit to be a `IfcValue`")); }
+    } while(0);
+    do { // convert the 'UnitComponent' argument
+        const DataType* arg = params[base++];
+        try { GenericConvert( in->UnitComponent, *arg, db ); break; } 
+        catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcMeasureWithUnit to be a `IfcUnit`")); }
+    } while(0);
+	return base;
+}
+// -----------------------------------------------------------------------------------------------------------
 template <> size_t GenericFill<IfcDistributionElement>(const DB& db, const LIST& params, IfcDistributionElement* in)
 {
 	size_t base = GenericFill(db,params,static_cast<IfcElement*>(in));
@@ -3000,7 +3042,11 @@ template <> size_t GenericFill<IfcSurfaceStyleRendering>(const DB& db, const LIS
 template <> size_t GenericFill<IfcCircleHollowProfileDef>(const DB& db, const LIST& params, IfcCircleHollowProfileDef* in)
 {
 	size_t base = GenericFill(db,params,static_cast<IfcCircleProfileDef*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
+	if (params.GetSize() < 5) { throw STEP::TypeError("expected 5 arguments to IfcCircleHollowProfileDef"); }    do { // convert the 'WallThickness' argument
+        const DataType* arg = params[base++];
+        try { GenericConvert( in->WallThickness, *arg, db ); break; } 
+        catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 4 to IfcCircleHollowProfileDef to be a `IfcPositiveLengthMeasure`")); }
+    } while(0);
 	return base;
 }
 // -----------------------------------------------------------------------------------------------------------
@@ -4195,7 +4241,16 @@ template <> size_t GenericFill<IfcFlowStorageDevice>(const DB& db, const LIST& p
 template <> size_t GenericFill<IfcRevolvedAreaSolid>(const DB& db, const LIST& params, IfcRevolvedAreaSolid* in)
 {
 	size_t base = GenericFill(db,params,static_cast<IfcSweptAreaSolid*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
+	if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcRevolvedAreaSolid"); }    do { // convert the 'Axis' argument
+        const DataType* arg = params[base++];
+        try { GenericConvert( in->Axis, *arg, db ); break; } 
+        catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcRevolvedAreaSolid to be a `IfcAxis1Placement`")); }
+    } while(0);
+    do { // convert the 'Angle' argument
+        const DataType* arg = params[base++];
+        try { GenericConvert( in->Angle, *arg, db ); break; } 
+        catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcRevolvedAreaSolid to be a `IfcPlaneAngleMeasure`")); }
+    } while(0);
 	return base;
 }
 // -----------------------------------------------------------------------------------------------------------

+ 17 - 3
code/IFCReaderGen.h

@@ -841,7 +841,7 @@ namespace IFC {
 	struct IfcFaceOuterBound;
 	struct IfcFeatureElementAddition;
 	struct IfcNamedUnit;
-	typedef NotImplemented IfcConversionBasedUnit; // (not currently used by Assimp)
+	struct IfcConversionBasedUnit;
 	typedef NotImplemented IfcStructuralLoadSingleForce; // (not currently used by Assimp)
 	struct IfcHeatExchangerType;
 	struct IfcPresentationStyleAssignment;
@@ -977,7 +977,7 @@ namespace IFC {
 	struct IfcDamperType;
 	struct IfcSIUnit;
 	typedef NotImplemented IfcSurfaceStyleLighting; // (not currently used by Assimp)
-	typedef NotImplemented IfcMeasureWithUnit; // (not currently used by Assimp)
+	struct IfcMeasureWithUnit;
 	typedef NotImplemented IfcMaterialLayerSet; // (not currently used by Assimp)
 	struct IfcDistributionElement;
 	struct IfcDistributionControlElement;
@@ -1813,6 +1813,12 @@ namespace IFC {
 		IfcUnitEnum::Out UnitType;
     };
 
+    // C++ wrapper for IfcConversionBasedUnit
+    struct IfcConversionBasedUnit : IfcNamedUnit, ObjectHelper<IfcConversionBasedUnit,2> { IfcConversionBasedUnit() : Object("IfcConversionBasedUnit") {}
+		IfcLabel::Out Name;
+		Lazy< IfcMeasureWithUnit > ConversionFactor;
+    };
+
     // C++ wrapper for IfcHeatExchangerType
     struct IfcHeatExchangerType : IfcEnergyConversionDeviceType, ObjectHelper<IfcHeatExchangerType,1> { IfcHeatExchangerType() : Object("IfcHeatExchangerType") {}
 		IfcHeatExchangerTypeEnum::Out PredefinedType;
@@ -2246,7 +2252,7 @@ namespace IFC {
 		Maybe< IfcIdentifier::Out > ResourceIdentifier;
 		Maybe< IfcLabel::Out > ResourceGroup;
 		Maybe< IfcResourceConsumptionEnum::Out > ResourceConsumption;
-		Maybe< Lazy< NotImplemented > > BaseQuantity;
+		Maybe< Lazy< IfcMeasureWithUnit > > BaseQuantity;
     };
 
     // C++ wrapper for IfcConstructionEquipmentResource
@@ -2310,6 +2316,12 @@ namespace IFC {
 		IfcSIUnitName::Out Name;
     };
 
+    // C++ wrapper for IfcMeasureWithUnit
+    struct IfcMeasureWithUnit :  ObjectHelper<IfcMeasureWithUnit,2> { IfcMeasureWithUnit() : Object("IfcMeasureWithUnit") {}
+		IfcValue::Out ValueComponent;
+		IfcUnit::Out UnitComponent;
+    };
+
     // C++ wrapper for IfcDistributionElement
     struct IfcDistributionElement : IfcElement, ObjectHelper<IfcDistributionElement,0> { IfcDistributionElement() : Object("IfcDistributionElement") {}
 
@@ -3866,6 +3878,7 @@ namespace STEP {
 	DECL_CONV_STUB(IfcFaceOuterBound);
 	DECL_CONV_STUB(IfcFeatureElementAddition);
 	DECL_CONV_STUB(IfcNamedUnit);
+	DECL_CONV_STUB(IfcConversionBasedUnit);
 	DECL_CONV_STUB(IfcHeatExchangerType);
 	DECL_CONV_STUB(IfcPresentationStyleAssignment);
 	DECL_CONV_STUB(IfcFlowTreatmentDeviceType);
@@ -3957,6 +3970,7 @@ namespace STEP {
 	DECL_CONV_STUB(IfcLinearDimension);
 	DECL_CONV_STUB(IfcDamperType);
 	DECL_CONV_STUB(IfcSIUnit);
+	DECL_CONV_STUB(IfcMeasureWithUnit);
 	DECL_CONV_STUB(IfcDistributionElement);
 	DECL_CONV_STUB(IfcDistributionControlElement);
 	DECL_CONV_STUB(IfcTransformerType);

+ 5 - 0
scripts/IFCImporter/entitylist.txt

@@ -8,6 +8,11 @@
 # code generator. Also, the names of all used entities need to be present 
 # in the source code for this to work.
 
+IfcAxis1Placement
+IfcMeasureWithUnit
+IfcConversionBasedUnit
+IfcRevolvedAreaSolid
+IfcCircleHollowProfileDef
 IfcRepresentationMap
 IfcProductRepresentation
 IfcUnitAssignment