// Extrudes the given polygon along the direction, converts it into an opening or applies all openings as necessary. void ProcessExtrudedArea(const IfcExtrudedAreaSolid& solid, const TempMesh& curve, const IfcVector3& extrusionDir, TempMesh& result, ConversionData &conv, bool collect_openings) { // Outline: 'curve' is now a list of vertex points forming the underlying profile, extrude along the given axis, // forming new triangles. const bool has_area = solid.SweptArea->ProfileType == "AREA" && curve.verts.size() > 2; if( solid.Depth < 1e-6 ) { if( has_area ) { result.Append(curve); } return; } result.verts.reserve(curve.verts.size()*(has_area ? 4 : 2)); result.vertcnt.reserve(curve.verts.size() + 2); std::vector<IfcVector3> in = curve.verts; // First step: transform all vertices into the target coordinate space IfcMatrix4 trafo; ConvertAxisPlacement(trafo, solid.Position); IfcVector3 vmin, vmax; MinMaxChooser<IfcVector3>()(vmin, vmax); BOOST_FOREACH(IfcVector3& v, in) { v *= trafo; vmin = std::min(vmin, v); vmax = std::max(vmax, v); }
// ------------------------------------------------------------------------------------------------ void ProcessParametrizedProfile(const IfcParameterizedProfileDef& def, TempMesh& meshout, ConversionData& conv) { (void)conv; if(const IfcRectangleProfileDef* const cprofile = def.ToPtr<IfcRectangleProfileDef>()) { const IfcFloat x = cprofile->XDim*0.5f, y = cprofile->YDim*0.5f; meshout.verts.reserve(meshout.verts.size()+4); meshout.verts.push_back( IfcVector3( x, y, 0.f )); meshout.verts.push_back( IfcVector3(-x, y, 0.f )); meshout.verts.push_back( IfcVector3(-x,-y, 0.f )); meshout.verts.push_back( IfcVector3( x,-y, 0.f )); meshout.vertcnt.push_back(4); } else if( const IfcCircleProfileDef* const circle = def.ToPtr<IfcCircleProfileDef>()) { if( const IfcCircleHollowProfileDef* const hollow = def.ToPtr<IfcCircleHollowProfileDef>()) { // TODO } const size_t segments = 32; const IfcFloat delta = AI_MATH_TWO_PI_F/segments, radius = circle->Radius; meshout.verts.reserve(segments); IfcFloat angle = 0.f; for(size_t i = 0; i < segments; ++i, angle += delta) { meshout.verts.push_back( IfcVector3( cos(angle)*radius, sin(angle)*radius, 0.f )); } meshout.vertcnt.push_back(segments); } else if( const IfcIShapeProfileDef* const ishape = def.ToPtr<IfcIShapeProfileDef>()) { // construct simplified IBeam shape const IfcFloat offset = (ishape->OverallWidth - ishape->WebThickness) / 2; const IfcFloat inner_height = ishape->OverallDepth - ishape->FlangeThickness * 2; meshout.verts.reserve(12); meshout.verts.push_back(IfcVector3(0,0,0)); meshout.verts.push_back(IfcVector3(0,ishape->FlangeThickness,0)); meshout.verts.push_back(IfcVector3(offset,ishape->FlangeThickness,0)); meshout.verts.push_back(IfcVector3(offset,ishape->FlangeThickness + inner_height,0)); meshout.verts.push_back(IfcVector3(0,ishape->FlangeThickness + inner_height,0)); meshout.verts.push_back(IfcVector3(0,ishape->OverallDepth,0)); meshout.verts.push_back(IfcVector3(ishape->OverallWidth,ishape->OverallDepth,0)); meshout.verts.push_back(IfcVector3(ishape->OverallWidth,ishape->FlangeThickness + inner_height,0)); meshout.verts.push_back(IfcVector3(offset+ishape->WebThickness,ishape->FlangeThickness + inner_height,0)); meshout.verts.push_back(IfcVector3(offset+ishape->WebThickness,ishape->FlangeThickness,0)); meshout.verts.push_back(IfcVector3(ishape->OverallWidth,ishape->FlangeThickness,0)); meshout.verts.push_back(IfcVector3(ishape->OverallWidth,0,0)); meshout.vertcnt.push_back(12); } else { IFCImporter::LogWarn("skipping unknown IfcParameterizedProfileDef entity, type is " + def.GetClassName()); return; } IfcMatrix4 trafo; ConvertAxisPlacement(trafo, *def.Position); meshout.Transform(trafo); }
// ------------------------------------------------------------------------------------------------ bool ProcessProfile(const IfcProfileDef& prof, TempMesh& meshout, ConversionData& conv) { if(const IfcArbitraryClosedProfileDef* const cprofile = prof.ToPtr<IfcArbitraryClosedProfileDef>()) { ProcessClosedProfile(*cprofile,meshout,conv); } else if(const IfcArbitraryOpenProfileDef* const copen = prof.ToPtr<IfcArbitraryOpenProfileDef>()) { ProcessOpenProfile(*copen,meshout,conv); } else if(const IfcParameterizedProfileDef* const cparam = prof.ToPtr<IfcParameterizedProfileDef>()) { ProcessParametrizedProfile(*cparam,meshout,conv); } else { IFCImporter::LogWarn("skipping unknown IfcProfileDef entity, type is " + prof.GetClassName()); return false; } meshout.RemoveAdjacentDuplicates(); if (!meshout.vertcnt.size() || meshout.vertcnt.front() <= 1) { return false; } return true; }
// ------------------------------------------------------------------------------------------------ void ProcessParametrizedProfile(const IfcParameterizedProfileDef& def, TempMesh& meshout, ConversionData& conv) { if(const IfcRectangleProfileDef* const cprofile = def.ToPtr<IfcRectangleProfileDef>()) { const IfcFloat x = cprofile->XDim*0.5f, y = cprofile->YDim*0.5f; meshout.verts.reserve(meshout.verts.size()+4); meshout.verts.push_back( IfcVector3( x, y, 0.f )); meshout.verts.push_back( IfcVector3(-x, y, 0.f )); meshout.verts.push_back( IfcVector3(-x,-y, 0.f )); meshout.verts.push_back( IfcVector3( x,-y, 0.f )); meshout.vertcnt.push_back(4); } else if( const IfcCircleProfileDef* const circle = def.ToPtr<IfcCircleProfileDef>()) { if( const IfcCircleHollowProfileDef* const hollow = def.ToPtr<IfcCircleHollowProfileDef>()) { // TODO } const size_t segments = 32; const IfcFloat delta = AI_MATH_TWO_PI_F/segments, radius = circle->Radius; meshout.verts.reserve(segments); IfcFloat angle = 0.f; for(size_t i = 0; i < segments; ++i, angle += delta) { meshout.verts.push_back( IfcVector3( ::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; } IfcMatrix4 trafo; ConvertAxisPlacement(trafo, *def.Position); meshout.Transform(trafo); }
// ------------------------------------------------------------------------------------------------ void ProcessRevolvedAreaSolid(const IfcRevolvedAreaSolid& solid, TempMesh& result, ConversionData& conv) { TempMesh meshout; // first read the profile description if(!ProcessProfile(*solid.SweptArea,meshout,conv) || meshout.verts.size()<=1) { return; } IfcVector3 axis, pos; ConvertAxisPlacement(axis,pos,solid.Axis); IfcMatrix4 tb0,tb1; IfcMatrix4::Translation(pos,tb0); IfcMatrix4::Translation(-pos,tb1); const std::vector<IfcVector3>& in = meshout.verts; const size_t size=in.size(); bool has_area = solid.SweptArea->ProfileType == "AREA" && size>2; const IfcFloat max_angle = solid.Angle*conv.angle_scale; if(std::fabs(max_angle) < 1e-3) { if(has_area) { result = meshout; } return; } const unsigned int cnt_segments = std::max(2u,static_cast<unsigned int>(16 * std::fabs(max_angle)/AI_MATH_HALF_PI_F)); const IfcFloat delta = max_angle/cnt_segments; has_area = has_area && std::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); IfcMatrix4 rot; rot = tb0 * IfcMatrix4::Rotation(delta,axis,rot) * tb1; size_t base = 0; std::vector<IfcVector3>& 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 IfcVector3& 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); } IfcMatrix4 trafo; ConvertAxisPlacement(trafo, solid.Position); result.Transform(trafo); IFCImporter::LogDebug("generate mesh procedurally by radial extrusion (IfcRevolvedAreaSolid)"); }