- IFC reader regenerated from schema to include IfcArbitraryProfileDefWithVoids
- implemented IfcArbitraryProfileDefWithVoids to fix solar panel covers in test\models-nonbsd\IFC\rac_basic_sample_project.ifc - warning: another dirty hack on top of dirty hacks - one day all these CSG implementations will blow up in our faces. Mark my words.pull/533/head
parent
b5e3e18bf0
commit
806d3ac8e1
|
@ -522,43 +522,23 @@ IfcMatrix3 DerivePlaneCoordinateSpace(const TempMesh& curmesh, bool& ok, IfcVect
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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,
|
||||||
void ProcessExtrudedAreaSolid(const IfcExtrudedAreaSolid& solid, TempMesh& result,
|
const IfcVector3& extrusionDir, TempMesh& result, ConversionData &conv, bool collect_openings)
|
||||||
ConversionData& conv, bool collect_openings)
|
|
||||||
{
|
{
|
||||||
TempMesh meshout;
|
// Outline: 'curve' is now a list of vertex points forming the underlying profile, extrude along the given axis,
|
||||||
|
// forming new triangles.
|
||||||
// First read the profile description
|
const bool has_area = solid.SweptArea->ProfileType == "AREA" && curve.verts.size() > 2;
|
||||||
if(!ProcessProfile(*solid.SweptArea,meshout,conv) || meshout.verts.size()<=1) {
|
if( solid.Depth < 1e-6 ) {
|
||||||
return;
|
if( has_area ) {
|
||||||
}
|
result.Append(curve);
|
||||||
|
|
||||||
IfcVector3 dir;
|
|
||||||
ConvertDirection(dir,solid.ExtrudedDirection);
|
|
||||||
|
|
||||||
dir *= solid.Depth; /*
|
|
||||||
if(conv.collect_openings && !conv.apply_openings) {
|
|
||||||
dir *= 1000.0;
|
|
||||||
} */
|
|
||||||
|
|
||||||
// Outline: assuming that `meshout.verts` is now a list of vertex points forming
|
|
||||||
// the underlying profile, extrude along the given axis, forming new
|
|
||||||
// triangles.
|
|
||||||
|
|
||||||
std::vector<IfcVector3>& in = meshout.verts;
|
|
||||||
const size_t size=in.size();
|
|
||||||
|
|
||||||
const bool has_area = solid.SweptArea->ProfileType == "AREA" && size>2;
|
|
||||||
if(solid.Depth < 1e-6) {
|
|
||||||
if(has_area) {
|
|
||||||
result = meshout;
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
result.verts.reserve(size*(has_area?4:2));
|
result.verts.reserve(curve.verts.size()*(has_area ? 4 : 2));
|
||||||
result.vertcnt.reserve(meshout.vertcnt.size()+2);
|
result.vertcnt.reserve(curve.verts.size() + 2);
|
||||||
|
std::vector<IfcVector3> in = curve.verts;
|
||||||
|
|
||||||
// First step: transform all vertices into the target coordinate space
|
// First step: transform all vertices into the target coordinate space
|
||||||
IfcMatrix4 trafo;
|
IfcMatrix4 trafo;
|
||||||
|
@ -566,7 +546,7 @@ void ProcessExtrudedAreaSolid(const IfcExtrudedAreaSolid& solid, TempMesh& resul
|
||||||
|
|
||||||
IfcVector3 vmin, vmax;
|
IfcVector3 vmin, vmax;
|
||||||
MinMaxChooser<IfcVector3>()(vmin, vmax);
|
MinMaxChooser<IfcVector3>()(vmin, vmax);
|
||||||
BOOST_FOREACH(IfcVector3& v,in) {
|
BOOST_FOREACH(IfcVector3& v, in) {
|
||||||
v *= trafo;
|
v *= trafo;
|
||||||
|
|
||||||
vmin = std::min(vmin, v);
|
vmin = std::min(vmin, v);
|
||||||
|
@ -575,14 +555,12 @@ void ProcessExtrudedAreaSolid(const IfcExtrudedAreaSolid& solid, TempMesh& resul
|
||||||
|
|
||||||
vmax -= vmin;
|
vmax -= vmin;
|
||||||
const IfcFloat diag = vmax.Length();
|
const IfcFloat diag = vmax.Length();
|
||||||
|
IfcVector3 dir = IfcMatrix3(trafo) * extrusionDir;
|
||||||
IfcVector3 min = in[0];
|
|
||||||
dir *= IfcMatrix3(trafo);
|
|
||||||
|
|
||||||
// reverse profile polygon if it's winded in the wrong direction in relation to the extrusion direction
|
// reverse profile polygon if it's winded in the wrong direction in relation to the extrusion direction
|
||||||
IfcVector3 profileNormal = TempMesh::ComputePolygonNormal( in.data(), in.size());
|
IfcVector3 profileNormal = TempMesh::ComputePolygonNormal(in.data(), in.size());
|
||||||
if( profileNormal * dir < 0.0 )
|
if( profileNormal * dir < 0.0 )
|
||||||
std::reverse( in.begin(), in.end());
|
std::reverse(in.begin(), in.end());
|
||||||
|
|
||||||
std::vector<IfcVector3> nors;
|
std::vector<IfcVector3> nors;
|
||||||
const bool openings = !!conv.apply_openings && conv.apply_openings->size();
|
const bool openings = !!conv.apply_openings && conv.apply_openings->size();
|
||||||
|
@ -590,25 +568,24 @@ void ProcessExtrudedAreaSolid(const IfcExtrudedAreaSolid& solid, TempMesh& resul
|
||||||
// Compute the normal vectors for all opening polygons as a prerequisite
|
// Compute the normal vectors for all opening polygons as a prerequisite
|
||||||
// to TryAddOpenings_Poly2Tri()
|
// to TryAddOpenings_Poly2Tri()
|
||||||
// XXX this belongs into the aforementioned function
|
// XXX this belongs into the aforementioned function
|
||||||
if (openings) {
|
if( openings ) {
|
||||||
|
|
||||||
if (!conv.settings.useCustomTriangulation) {
|
if( !conv.settings.useCustomTriangulation ) {
|
||||||
// it is essential to apply the openings in the correct spatial order. The direction
|
// it is essential to apply the openings in the correct spatial order. The direction
|
||||||
// doesn't matter, but we would screw up if we started with e.g. a door in between
|
// doesn't matter, but we would screw up if we started with e.g. a door in between
|
||||||
// two windows.
|
// two windows.
|
||||||
std::sort(conv.apply_openings->begin(),conv.apply_openings->end(),
|
std::sort(conv.apply_openings->begin(), conv.apply_openings->end(), TempOpening::DistanceSorter(in[0]));
|
||||||
TempOpening::DistanceSorter(min));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nors.reserve(conv.apply_openings->size());
|
nors.reserve(conv.apply_openings->size());
|
||||||
BOOST_FOREACH(TempOpening& t,*conv.apply_openings) {
|
BOOST_FOREACH(TempOpening& t, *conv.apply_openings) {
|
||||||
TempMesh& bounds = *t.profileMesh.get();
|
TempMesh& bounds = *t.profileMesh.get();
|
||||||
|
|
||||||
if (bounds.verts.size() <= 2) {
|
if( bounds.verts.size() <= 2 ) {
|
||||||
nors.push_back(IfcVector3());
|
nors.push_back(IfcVector3());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
nors.push_back(((bounds.verts[2]-bounds.verts[0])^(bounds.verts[1]-bounds.verts[0]) ).Normalize());
|
nors.push_back(((bounds.verts[2] - bounds.verts[0]) ^ (bounds.verts[1] - bounds.verts[0])).Normalize());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -618,18 +595,18 @@ void ProcessExtrudedAreaSolid(const IfcExtrudedAreaSolid& solid, TempMesh& resul
|
||||||
std::vector<IfcVector3>& out = curmesh.verts;
|
std::vector<IfcVector3>& out = curmesh.verts;
|
||||||
|
|
||||||
size_t sides_with_openings = 0;
|
size_t sides_with_openings = 0;
|
||||||
for(size_t i = 0; i < size; ++i) {
|
for( size_t i = 0; i < in.size(); ++i ) {
|
||||||
const size_t next = (i+1)%size;
|
const size_t next = (i + 1) % in.size();
|
||||||
|
|
||||||
curmesh.vertcnt.push_back(4);
|
curmesh.vertcnt.push_back(4);
|
||||||
|
|
||||||
out.push_back(in[i]);
|
out.push_back(in[i]);
|
||||||
out.push_back(in[next]);
|
out.push_back(in[next]);
|
||||||
out.push_back(in[next]+dir);
|
out.push_back(in[next] + dir);
|
||||||
out.push_back(in[i]+dir);
|
out.push_back(in[i] + dir);
|
||||||
|
|
||||||
if(openings) {
|
if( openings ) {
|
||||||
if((in[i]-in[next]).Length() > diag * 0.1 && GenerateOpenings(*conv.apply_openings,nors,temp,true, true, dir)) {
|
if( (in[i] - in[next]).Length() > diag * 0.1 && GenerateOpenings(*conv.apply_openings, nors, temp, true, true, dir) ) {
|
||||||
++sides_with_openings;
|
++sides_with_openings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -638,9 +615,9 @@ void ProcessExtrudedAreaSolid(const IfcExtrudedAreaSolid& solid, TempMesh& resul
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(openings) {
|
if( openings ) {
|
||||||
BOOST_FOREACH(TempOpening& opening, *conv.apply_openings) {
|
BOOST_FOREACH(TempOpening& opening, *conv.apply_openings) {
|
||||||
if (!opening.wallPoints.empty()) {
|
if( !opening.wallPoints.empty() ) {
|
||||||
IFCImporter::LogError("failed to generate all window caps");
|
IFCImporter::LogError("failed to generate all window caps");
|
||||||
}
|
}
|
||||||
opening.wallPoints.clear();
|
opening.wallPoints.clear();
|
||||||
|
@ -648,20 +625,21 @@ void ProcessExtrudedAreaSolid(const IfcExtrudedAreaSolid& solid, TempMesh& resul
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t sides_with_v_openings = 0;
|
size_t sides_with_v_openings = 0;
|
||||||
if(has_area) {
|
if( has_area ) {
|
||||||
|
|
||||||
for(size_t n = 0; n < 2; ++n) {
|
for( size_t n = 0; n < 2; ++n ) {
|
||||||
if( n > 0 ) {
|
if( n > 0 ) {
|
||||||
for(size_t i = 0; i < size; ++i )
|
for( size_t i = 0; i < in.size(); ++i )
|
||||||
out.push_back(in[i]+dir);
|
out.push_back(in[i] + dir);
|
||||||
} else {
|
}
|
||||||
for(size_t i = size; i--; )
|
else {
|
||||||
|
for( size_t i = in.size(); i--; )
|
||||||
out.push_back(in[i]);
|
out.push_back(in[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
curmesh.vertcnt.push_back(size);
|
curmesh.vertcnt.push_back(in.size());
|
||||||
if(openings && size > 2) {
|
if( openings && in.size() > 2 ) {
|
||||||
if(GenerateOpenings(*conv.apply_openings,nors,temp,true, true, dir)) {
|
if( GenerateOpenings(*conv.apply_openings, nors, temp, true, true, dir) ) {
|
||||||
++sides_with_v_openings;
|
++sides_with_v_openings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -671,7 +649,7 @@ void ProcessExtrudedAreaSolid(const IfcExtrudedAreaSolid& solid, TempMesh& resul
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(openings && ((sides_with_openings == 1 && sides_with_openings) || (sides_with_v_openings == 2 && sides_with_v_openings))) {
|
if( openings && ((sides_with_openings == 1 && sides_with_openings) || (sides_with_v_openings == 2 && sides_with_v_openings)) ) {
|
||||||
IFCImporter::LogWarn("failed to resolve all openings, presumably their topology is not supported by Assimp");
|
IFCImporter::LogWarn("failed to resolve all openings, presumably their topology is not supported by Assimp");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -679,19 +657,60 @@ void ProcessExtrudedAreaSolid(const IfcExtrudedAreaSolid& solid, TempMesh& resul
|
||||||
|
|
||||||
// If this is an opening element, store both the extruded mesh and the 2D profile mesh
|
// If this is an opening element, store both the extruded mesh and the 2D profile mesh
|
||||||
// it was created from. Return an empty mesh to the caller.
|
// it was created from. Return an empty mesh to the caller.
|
||||||
if(collect_openings && !result.IsEmpty()) {
|
if( collect_openings && !result.IsEmpty() ) {
|
||||||
ai_assert(conv.collect_openings);
|
ai_assert(conv.collect_openings);
|
||||||
boost::shared_ptr<TempMesh> profile = boost::shared_ptr<TempMesh>(new TempMesh());
|
boost::shared_ptr<TempMesh> profile = boost::shared_ptr<TempMesh>(new TempMesh());
|
||||||
profile->Swap(result);
|
profile->Swap(result);
|
||||||
|
|
||||||
boost::shared_ptr<TempMesh> profile2D = boost::shared_ptr<TempMesh>(new TempMesh());
|
boost::shared_ptr<TempMesh> profile2D = boost::shared_ptr<TempMesh>(new TempMesh());
|
||||||
profile2D->Swap(meshout);
|
profile2D->verts.insert(profile2D->verts.end(), in.begin(), in.end());
|
||||||
conv.collect_openings->push_back(TempOpening(&solid,dir,profile, profile2D));
|
profile2D->vertcnt.push_back(in.size());
|
||||||
|
conv.collect_openings->push_back(TempOpening(&solid, dir, profile, profile2D));
|
||||||
|
|
||||||
ai_assert(result.IsEmpty());
|
ai_assert(result.IsEmpty());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void ProcessExtrudedAreaSolid(const IfcExtrudedAreaSolid& solid, TempMesh& result,
|
||||||
|
ConversionData& conv, bool collect_openings)
|
||||||
|
{
|
||||||
|
TempMesh meshout;
|
||||||
|
|
||||||
|
// First read the profile description.
|
||||||
|
if(!ProcessProfile(*solid.SweptArea,meshout,conv) || meshout.verts.size()<=1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
IfcVector3 dir;
|
||||||
|
ConvertDirection(dir,solid.ExtrudedDirection);
|
||||||
|
dir *= solid.Depth;
|
||||||
|
|
||||||
|
// Some profiles bring their own holes, for which we need to provide a container. This all is somewhat backwards,
|
||||||
|
// and there's still so many corner cases uncovered - we really need a generic solution to all of this hole carving.
|
||||||
|
std::vector<TempOpening> fisherPriceMyFirstOpenings;
|
||||||
|
std::vector<TempOpening>* oldApplyOpenings = conv.apply_openings;
|
||||||
|
if( const IfcArbitraryProfileDefWithVoids* const cprofile = solid.SweptArea->ToPtr<IfcArbitraryProfileDefWithVoids>() ) {
|
||||||
|
if( !cprofile->InnerCurves.empty() ) {
|
||||||
|
// read all inner curves and extrude them to form proper openings.
|
||||||
|
std::vector<TempOpening>* oldCollectOpenings = conv.collect_openings;
|
||||||
|
conv.collect_openings = &fisherPriceMyFirstOpenings;
|
||||||
|
|
||||||
|
BOOST_FOREACH(const IfcCurve* curve, cprofile->InnerCurves) {
|
||||||
|
TempMesh curveMesh, tempMesh;
|
||||||
|
ProcessCurve(*curve, curveMesh, conv);
|
||||||
|
ProcessExtrudedArea(solid, curveMesh, dir, tempMesh, conv, true);
|
||||||
|
}
|
||||||
|
// and then apply those to the geometry we're about to generate
|
||||||
|
conv.apply_openings = conv.collect_openings;
|
||||||
|
conv.collect_openings = oldCollectOpenings;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ProcessExtrudedArea(solid, meshout, dir, result, conv, collect_openings);
|
||||||
|
conv.apply_openings = oldApplyOpenings;
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void ProcessSweptAreaSolid(const IfcSweptAreaSolid& swept, TempMesh& meshout,
|
void ProcessSweptAreaSolid(const IfcSweptAreaSolid& swept, TempMesh& meshout,
|
||||||
ConversionData& conv)
|
ConversionData& conv)
|
||||||
|
@ -784,7 +803,7 @@ bool ProcessGeometricItem(const IfcRepresentationItem& geo, unsigned int matid,
|
||||||
meshtmp->RemoveDegenerates();
|
meshtmp->RemoveDegenerates();
|
||||||
|
|
||||||
if(fix_orientation) {
|
if(fix_orientation) {
|
||||||
meshtmp->FixupFaceOrientation();
|
// meshtmp->FixupFaceOrientation();
|
||||||
}
|
}
|
||||||
|
|
||||||
aiMesh* const mesh = meshtmp->ToMesh();
|
aiMesh* const mesh = meshtmp->ToMesh();
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
7292
code/IFCReaderGen.h
7292
code/IFCReaderGen.h
File diff suppressed because it is too large
Load Diff
|
@ -271,6 +271,7 @@ IfcFloat ConvertSIPrefix(const std::string& prefix);
|
||||||
|
|
||||||
// IFCProfile.cpp
|
// IFCProfile.cpp
|
||||||
bool ProcessProfile(const IfcProfileDef& prof, TempMesh& meshout, ConversionData& conv);
|
bool ProcessProfile(const IfcProfileDef& prof, TempMesh& meshout, ConversionData& conv);
|
||||||
|
bool ProcessCurve(const IfcCurve& curve, TempMesh& meshout, ConversionData& conv);
|
||||||
|
|
||||||
// IFCMaterial.cpp
|
// IFCMaterial.cpp
|
||||||
unsigned int ProcessMaterials(uint64_t id, unsigned int prevMatId, ConversionData& conv, bool forceDefaultMat);
|
unsigned int ProcessMaterials(uint64_t id, unsigned int prevMatId, ConversionData& conv, bool forceDefaultMat);
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
IfcAnnotation
|
IfcAnnotation
|
||||||
IfcArbitraryClosedProfileDef
|
IfcArbitraryClosedProfileDef
|
||||||
IfcArbitraryOpenProfileDef
|
IfcArbitraryOpenProfileDef
|
||||||
|
IfcArbitraryProfileDefWithVoids
|
||||||
IfcAxis1Placement
|
IfcAxis1Placement
|
||||||
IfcAxis2Placement
|
IfcAxis2Placement
|
||||||
IfcAxis2Placement2D
|
IfcAxis2Placement2D
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue