- Ifc: move some utility functions to TempMesh. Add TempMesh::RemoveDegenerates() method.
git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@1318 67173fc5-114c-0410-ac8e-9d2fd5bffc1fpull/6/merge
parent
7ed1400c68
commit
33a50f515a
|
@ -98,86 +98,6 @@ bool ProcessPolyloop(const IfcPolyLoop& loop, TempMesh& meshout, ConversionData&
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
void ComputePolygonNormals(const TempMesh& meshout, std::vector<IfcVector3>& normals, bool normalize = true, size_t ofs = 0)
|
|
||||||
{
|
|
||||||
size_t max_vcount = 0;
|
|
||||||
std::vector<unsigned int>::const_iterator begin=meshout.vertcnt.begin()+ofs, end=meshout.vertcnt.end(), iit;
|
|
||||||
for(iit = begin; iit != end; ++iit) {
|
|
||||||
max_vcount = std::max(max_vcount,static_cast<size_t>(*iit));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<IfcFloat> temp((max_vcount+2)*4);
|
|
||||||
normals.reserve( normals.size() + meshout.vertcnt.size()-ofs );
|
|
||||||
|
|
||||||
// `NewellNormal()` currently has a relatively strange interface and need to
|
|
||||||
// re-structure things a bit to meet them.
|
|
||||||
size_t vidx = std::accumulate(meshout.vertcnt.begin(),begin,0);
|
|
||||||
for(iit = begin; iit != end; vidx += *iit++) {
|
|
||||||
if (!*iit) {
|
|
||||||
normals.push_back(IfcVector3());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for(size_t vofs = 0, cnt = 0; vofs < *iit; ++vofs) {
|
|
||||||
const IfcVector3& v = meshout.verts[vidx+vofs];
|
|
||||||
temp[cnt++] = v.x;
|
|
||||||
temp[cnt++] = v.y;
|
|
||||||
temp[cnt++] = v.z;
|
|
||||||
#ifdef _DEBUG
|
|
||||||
temp[cnt] = std::numeric_limits<IfcFloat>::quiet_NaN();
|
|
||||||
#endif
|
|
||||||
++cnt;
|
|
||||||
}
|
|
||||||
|
|
||||||
normals.push_back(IfcVector3());
|
|
||||||
NewellNormal<4,4,4>(normals.back(),*iit,&temp[0],&temp[1],&temp[2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(normalize) {
|
|
||||||
BOOST_FOREACH(IfcVector3& n, normals) {
|
|
||||||
n.Normalize();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
// Compute the normal of the last polygon in the given mesh
|
|
||||||
IfcVector3 ComputePolygonNormal(const TempMesh& inmesh, bool normalize = true)
|
|
||||||
{
|
|
||||||
size_t total = inmesh.vertcnt.back(), vidx = inmesh.verts.size() - total;
|
|
||||||
std::vector<IfcFloat> temp((total+2)*3);
|
|
||||||
for(size_t vofs = 0, cnt = 0; vofs < total; ++vofs) {
|
|
||||||
const IfcVector3& v = inmesh.verts[vidx+vofs];
|
|
||||||
temp[cnt++] = v.x;
|
|
||||||
temp[cnt++] = v.y;
|
|
||||||
temp[cnt++] = v.z;
|
|
||||||
}
|
|
||||||
IfcVector3 nor;
|
|
||||||
NewellNormal<3,3,3>(nor,total,&temp[0],&temp[1],&temp[2]);
|
|
||||||
return normalize ? nor.Normalize() : nor;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
void FixupFaceOrientation(TempMesh& result)
|
|
||||||
{
|
|
||||||
const IfcVector3 vavg = result.Center();
|
|
||||||
|
|
||||||
std::vector<IfcVector3> normals;
|
|
||||||
ComputePolygonNormals(result,normals);
|
|
||||||
|
|
||||||
size_t c = 0, ofs = 0;
|
|
||||||
BOOST_FOREACH(unsigned int cnt, result.vertcnt) {
|
|
||||||
if (cnt>2){
|
|
||||||
const IfcVector3& thisvert = result.verts[c];
|
|
||||||
if (normals[ofs]*(thisvert-vavg) < 0) {
|
|
||||||
std::reverse(result.verts.begin()+c,result.verts.begin()+cnt+c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
c += cnt;
|
|
||||||
++ofs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void ProcessPolygonBoundaries(TempMesh& result, const TempMesh& inmesh, size_t master_bounds = (size_t)-1)
|
void ProcessPolygonBoundaries(TempMesh& result, const TempMesh& inmesh, size_t master_bounds = (size_t)-1)
|
||||||
{
|
{
|
||||||
|
@ -206,7 +126,7 @@ void ProcessPolygonBoundaries(TempMesh& result, const TempMesh& inmesh, size_t m
|
||||||
// first compute newell normals for all polygons
|
// first compute newell normals for all polygons
|
||||||
// do not normalize 'normals', we need the original length for computing the polygon area
|
// do not normalize 'normals', we need the original length for computing the polygon area
|
||||||
std::vector<IfcVector3> normals;
|
std::vector<IfcVector3> normals;
|
||||||
ComputePolygonNormals(inmesh,normals,false);
|
inmesh.ComputePolygonNormals(normals,false);
|
||||||
|
|
||||||
// One of the polygons might be a IfcFaceOuterBound (in which case `master_bounds`
|
// One of the polygons might be a IfcFaceOuterBound (in which case `master_bounds`
|
||||||
// is its index). Sadly we can't rely on it, the docs say 'At most one of the bounds
|
// is its index). Sadly we can't rely on it, the docs say 'At most one of the bounds
|
||||||
|
@ -1931,7 +1851,7 @@ void ProcessBooleanExtrudedAreaSolidDifference(const IfcExtrudedAreaSolid* as, T
|
||||||
|
|
||||||
// ComputePolygonNormal returns the Newell normal, so the
|
// ComputePolygonNormal returns the Newell normal, so the
|
||||||
// length of the normal is the area of the polygon.
|
// length of the normal is the area of the polygon.
|
||||||
const IfcVector3& normal = ComputePolygonNormal(temp, false);
|
const IfcVector3& normal = temp.ComputeLastPolygonNormal(false);
|
||||||
if (normal.SquareLength() < static_cast<IfcFloat>(1e-5)) {
|
if (normal.SquareLength() < static_cast<IfcFloat>(1e-5)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -2048,7 +1968,7 @@ bool ProcessGeometricItem(const IfcRepresentationItem& geo, std::vector<unsigned
|
||||||
meshtmp.RemoveAdjacentDuplicates();
|
meshtmp.RemoveAdjacentDuplicates();
|
||||||
|
|
||||||
if(fix_orientation) {
|
if(fix_orientation) {
|
||||||
FixupFaceOrientation(meshtmp);
|
meshtmp.FixupFaceOrientation();
|
||||||
}
|
}
|
||||||
|
|
||||||
aiMesh* const mesh = meshtmp.ToMesh();
|
aiMesh* const mesh = meshtmp.ToMesh();
|
||||||
|
|
109
code/IFCUtil.cpp
109
code/IFCUtil.cpp
|
@ -45,7 +45,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "AssimpPCH.h"
|
#include "AssimpPCH.h"
|
||||||
|
|
||||||
#ifndef ASSIMP_BUILD_NO_IFC_IMPORTER
|
#ifndef ASSIMP_BUILD_NO_IFC_IMPORTER
|
||||||
|
|
||||||
#include "IFCUtil.h"
|
#include "IFCUtil.h"
|
||||||
|
#include "PolyTools.h"
|
||||||
#include "ProcessHelper.h"
|
#include "ProcessHelper.h"
|
||||||
|
|
||||||
namespace Assimp {
|
namespace Assimp {
|
||||||
|
@ -127,6 +129,113 @@ void TempMesh::Append(const TempMesh& other)
|
||||||
vertcnt.insert(vertcnt.end(),other.vertcnt.begin(),other.vertcnt.end());
|
vertcnt.insert(vertcnt.end(),other.vertcnt.begin(),other.vertcnt.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void TempMesh::RemoveDegenerates()
|
||||||
|
{
|
||||||
|
// The strategy is simple: walk the mesh and compute normals using
|
||||||
|
// Newell's algorithm. The length of the normals gives the area
|
||||||
|
// of the polygons, which is close to zero for lines.
|
||||||
|
|
||||||
|
std::vector<IfcVector3> normals;
|
||||||
|
ComputePolygonNormals(normals);
|
||||||
|
|
||||||
|
std::vector<IfcVector3>::const_iterator vit = verts.begin();
|
||||||
|
for (std::vector<unsigned int>::const_iterator it = vertcnt.begin(); it != vertcnt.end();) {
|
||||||
|
const unsigned int pcount = *it;
|
||||||
|
|
||||||
|
if (normals[std::distance(static_cast<std::vector<unsigned int>::const_iterator>(vertcnt.begin()),it)].SquareLength() < 1e-5f) {
|
||||||
|
it = vertcnt.erase(it);
|
||||||
|
vit = verts.erase(vit, vit + pcount);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
vit += pcount;
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void TempMesh::ComputePolygonNormals(std::vector<IfcVector3>& normals,
|
||||||
|
bool normalize,
|
||||||
|
size_t ofs) const
|
||||||
|
{
|
||||||
|
size_t max_vcount = 0;
|
||||||
|
std::vector<unsigned int>::const_iterator begin = vertcnt.begin()+ofs, end = vertcnt.end(), iit;
|
||||||
|
for(iit = begin; iit != end; ++iit) {
|
||||||
|
max_vcount = std::max(max_vcount,static_cast<size_t>(*iit));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<IfcFloat> temp((max_vcount+2)*4);
|
||||||
|
normals.reserve( normals.size() + vertcnt.size()-ofs );
|
||||||
|
|
||||||
|
// `NewellNormal()` currently has a relatively strange interface and need to
|
||||||
|
// re-structure things a bit to meet them.
|
||||||
|
size_t vidx = std::accumulate(vertcnt.begin(),begin,0);
|
||||||
|
for(iit = begin; iit != end; vidx += *iit++) {
|
||||||
|
if (!*iit) {
|
||||||
|
normals.push_back(IfcVector3());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for(size_t vofs = 0, cnt = 0; vofs < *iit; ++vofs) {
|
||||||
|
const IfcVector3& v = verts[vidx+vofs];
|
||||||
|
temp[cnt++] = v.x;
|
||||||
|
temp[cnt++] = v.y;
|
||||||
|
temp[cnt++] = v.z;
|
||||||
|
#ifdef _DEBUG
|
||||||
|
temp[cnt] = std::numeric_limits<IfcFloat>::quiet_NaN();
|
||||||
|
#endif
|
||||||
|
++cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
normals.push_back(IfcVector3());
|
||||||
|
NewellNormal<4,4,4>(normals.back(),*iit,&temp[0],&temp[1],&temp[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(normalize) {
|
||||||
|
BOOST_FOREACH(IfcVector3& n, normals) {
|
||||||
|
n.Normalize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
// Compute the normal of the last polygon in the given mesh
|
||||||
|
IfcVector3 TempMesh::ComputeLastPolygonNormal(bool normalize) const
|
||||||
|
{
|
||||||
|
size_t total = vertcnt.back(), vidx = verts.size() - total;
|
||||||
|
std::vector<IfcFloat> temp((total+2)*3);
|
||||||
|
for(size_t vofs = 0, cnt = 0; vofs < total; ++vofs) {
|
||||||
|
const IfcVector3& v = verts[vidx+vofs];
|
||||||
|
temp[cnt++] = v.x;
|
||||||
|
temp[cnt++] = v.y;
|
||||||
|
temp[cnt++] = v.z;
|
||||||
|
}
|
||||||
|
IfcVector3 nor;
|
||||||
|
NewellNormal<3,3,3>(nor,total,&temp[0],&temp[1],&temp[2]);
|
||||||
|
return normalize ? nor.Normalize() : nor;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void TempMesh::FixupFaceOrientation()
|
||||||
|
{
|
||||||
|
const IfcVector3 vavg = Center();
|
||||||
|
|
||||||
|
std::vector<IfcVector3> normals;
|
||||||
|
ComputePolygonNormals(normals);
|
||||||
|
|
||||||
|
size_t c = 0, ofs = 0;
|
||||||
|
BOOST_FOREACH(unsigned int cnt, vertcnt) {
|
||||||
|
if (cnt>2){
|
||||||
|
const IfcVector3& thisvert = verts[c];
|
||||||
|
if (normals[ofs]*(thisvert-vavg) < 0) {
|
||||||
|
std::reverse(verts.begin()+c,verts.begin()+cnt+c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c += cnt;
|
||||||
|
++ofs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void TempMesh::RemoveAdjacentDuplicates()
|
void TempMesh::RemoveAdjacentDuplicates()
|
||||||
{
|
{
|
||||||
|
|
|
@ -183,7 +183,15 @@ struct TempMesh
|
||||||
void Transform(const IfcMatrix4& mat);
|
void Transform(const IfcMatrix4& mat);
|
||||||
IfcVector3 Center() const;
|
IfcVector3 Center() const;
|
||||||
void Append(const TempMesh& other);
|
void Append(const TempMesh& other);
|
||||||
|
|
||||||
void RemoveAdjacentDuplicates();
|
void RemoveAdjacentDuplicates();
|
||||||
|
void RemoveDegenerates();
|
||||||
|
|
||||||
|
void FixupFaceOrientation();
|
||||||
|
IfcVector3 ComputeLastPolygonNormal(bool normalize = true) const;
|
||||||
|
void ComputePolygonNormals(std::vector<IfcVector3>& normals,
|
||||||
|
bool normalize = true,
|
||||||
|
size_t ofs = 0) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue