Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/ifcgeom/IfcGeom.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ class IFC_GEOM_API Kernel {
bool closest(const gp_Pnt&, const std::vector<gp_Pnt>&, gp_Pnt&);
bool project(const Handle_Geom_Curve&, const gp_Pnt&, gp_Pnt& p, double& u, double& d);
bool project(const Handle_Geom_Surface&, const TopoDS_Shape&, double& u1, double& v1, double& u2, double& v2, double widen=0.1);
int count(const TopoDS_Shape&, TopAbs_ShapeEnum);
static int count(const TopoDS_Shape&, TopAbs_ShapeEnum);

bool find_wall_end_points(const IfcSchema::IfcWall*, gp_Pnt& start, gp_Pnt& end);

Expand Down
2 changes: 1 addition & 1 deletion src/ifcgeom/IfcGeomIterator.h
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,7 @@ namespace IfcGeom {
IfcSchema::IfcProductRepresentation::list::ptr prodreps = representation_mapped_to->OfProductRepresentation();

bool all_product_without_openings = true;
IfcSchema::IfcProduct::list::ptr products;
IfcSchema::IfcProduct::list::ptr products(new IfcSchema::IfcProduct::list);

for (IfcSchema::IfcProductRepresentation::list::it it = prodreps->begin(); it != prodreps->end(); ++it) {
IfcSchema::IfcProduct::list::ptr products_of_prodrep = (*it)->entity->getInverse(IfcSchema::Type::IfcProduct, -1)->as<IfcSchema::IfcProduct>();
Expand Down
29 changes: 17 additions & 12 deletions src/ifcgeom/IfcGeomRepresentation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,8 @@ IfcGeom::Representation::Serialization::Serialization(const BRep& brep)
: Representation(brep.settings())
, id_(brep.id())
{
TopoDS_Compound compound;
BRep_Builder builder;
builder.MakeCompound(compound);
TopoDS_Compound compound = brep.as_compound();
for (IfcGeom::IfcRepresentationShapeItems::const_iterator it = brep.begin(); it != brep.end(); ++ it) {
const TopoDS_Shape& s = it->Shape();
gp_GTrsf trsf = it->Placement();

if (it->hasStyle() && it->Style().Diffuse()) {
const IfcGeom::SurfaceStyle::ColorComponent& clr = *it->Style().Diffuse();
surface_styles_.push_back(clr.R());
Expand All @@ -53,18 +48,28 @@ IfcGeom::Representation::Serialization::Serialization(const BRep& brep)
} else {
surface_styles_.push_back(1.);
}

}
std::stringstream sstream;
BRepTools::Write(compound,sstream);
brep_data_ = sstream.str();
}

TopoDS_Compound IfcGeom::Representation::BRep::as_compound() const {
TopoDS_Compound compound;
BRep_Builder builder;
builder.MakeCompound(compound);
for (IfcGeom::IfcRepresentationShapeItems::const_iterator it = begin(); it != end(); ++it) {
const TopoDS_Shape& s = it->Shape();
gp_GTrsf trsf = it->Placement();

if (settings().get(IteratorSettings::CONVERT_BACK_UNITS)) {
gp_Trsf scale;
scale.SetScaleFactor(1.0 / settings().unit_magnitude());
trsf.PreMultiply(scale);
}

const TopoDS_Shape moved_shape = IfcGeom::Kernel::apply_transformation(s, trsf);

const TopoDS_Shape moved_shape = IfcGeom::Kernel::apply_transformation(s, trsf);
builder.Add(compound, moved_shape);
}
std::stringstream sstream;
BRepTools::Write(compound,sstream);
brep_data_ = sstream.str();
return compound;
}
3 changes: 3 additions & 0 deletions src/ifcgeom/IfcGeomRepresentation.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
#include "../ifcgeom/IfcGeomMaterial.h"
#include "../ifcgeom/IfcRepresentationShapeItem.h"

#include <TopoDS_Compound.hxx>

namespace IfcGeom {

namespace Representation {
Expand Down Expand Up @@ -72,6 +74,7 @@ namespace IfcGeom {
IfcGeom::IfcRepresentationShapeItems::const_iterator end() const { return shapes_.end(); }
const IfcGeom::IfcRepresentationShapeItems& shapes() const { return shapes_; }
const std::string& id() const { return id_; }
TopoDS_Compound as_compound() const;
};

class IFC_GEOM_API Serialization : public Representation {
Expand Down
278 changes: 278 additions & 0 deletions src/ifcgeom/IfcGeomTree.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,278 @@
/********************************************************************************
* *
* This file is part of IfcOpenShell. *
* *
* IfcOpenShell is free software: you can redistribute it and/or modify *
* it under the terms of the Lesser GNU General Public License as published by *
* the Free Software Foundation, either version 3.0 of the License, or *
* (at your option) any later version. *
* *
* IfcOpenShell is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* Lesser GNU General Public License for more details. *
* *
* You should have received a copy of the Lesser GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/

#ifndef IFCGEOMTREE_H
#define IFCGEOMTREE_H

#include "../ifcparse/IfcFile.h"
#include "../ifcgeom/IfcGeomIterator.h"

#include <NCollection_UBTree.hxx>
#include <BRepBndLib.hxx>
#include <Bnd_Box.hxx>
#include <BRepAlgoAPI_Common.hxx>
#include <BRepAlgoAPI_Cut.hxx>
#include <BRepClass3d_SolidClassifier.hxx>

namespace IfcGeom {

namespace impl {
template <typename T>
class tree {

public:

void add(const T& t, const Bnd_Box& b) {
tree_.Add(t, b);
}

void add(const T& t, const TopoDS_Shape& s) {
Bnd_Box b;
BRepBndLib::AddClose(s, b);
add(t, b);
shapes_[t] = s;
}

std::vector<T> select_box(const T& t, bool completely_within = false, double extend=-1.e-5) const {
typename map_t::const_iterator it = shapes_.find(t);
if (it == shapes_.end()) {
return std::vector<T>();
}

Bnd_Box b;
BRepBndLib::AddClose(it->second, b);

// Gap is assumed to be positive throughout the codebase,
// but at least for IsOut() in the selector a negative
// Gap should work as well.
b.SetGap(b.GetGap() + extend);

return select_box(b, completely_within);
}

std::vector<T> select_box(const gp_Pnt& p) const {
Bnd_Box b;
b.Add(p);
return select_box(b);
}

std::vector<T> select_box(const Bnd_Box& b, bool completely_within = false) const {
selector s(b);
tree_.Select(s);
if (completely_within) {
std::vector<T> ts = s.results();
std::vector<T> ts_filtered;
ts_filtered.reserve(ts.size());
typename std::vector<T>::const_iterator it = ts.begin();
for (; it != ts.end(); ++it) {
const TopoDS_Shape& shp = shapes_.find(*it)->second;
Bnd_Box B;
BRepBndLib::AddClose(shp, B);

// BndBox::CornerMin() /-Max() introduced in OCCT 6.8
double x1, y1, z1, x2, y2, z2;
b.Get(x1, y1, z1, x2, y2, z2);
double gap = B.GetGap();
gp_Pnt p1(x1 - gap, y1 - gap, z1 - gap);
gp_Pnt p2(x2 + gap, y2 + gap, z2 + gap);

if (!b.IsOut(p1) && !b.IsOut(p2)) {
ts_filtered.push_back(*it);
}
}
return ts_filtered;
} else {
return s.results();
}
}

std::vector<T> select(const T& t, bool completely_within = false) const {
std::vector<T> ts = select_box(t);
if (ts.empty()) {
return ts;
}

std::vector<T> ts_filtered;

const TopoDS_Shape& A = shapes_.find(t)->second;
if (IfcGeom::Kernel::count(A, TopAbs_SHELL) == 0) {
return ts_filtered;
}

ts_filtered.reserve(ts.size());

typename std::vector<T>::const_iterator it = ts.begin();
for (it = ts.begin(); it != ts.end(); ++it) {
const TopoDS_Shape& B = shapes_.find(*it)->second;
if (IfcGeom::Kernel::count(B, TopAbs_SHELL) == 0) {
continue;
}

if (completely_within) {
BRepAlgoAPI_Cut cut(B, A);
if (cut.IsDone()) {
if (IfcGeom::Kernel::count(cut.Shape(), TopAbs_SHELL) == 0) {
ts_filtered.push_back(*it);
}
}
} else {
BRepAlgoAPI_Common common(A, B);
if (common.IsDone()) {
if (IfcGeom::Kernel::count(common.Shape(), TopAbs_SHELL) > 0) {
ts_filtered.push_back(*it);
}
}
}
}

return ts_filtered;
}

std::vector<T> select(const TopoDS_Shape& s) const {
Bnd_Box bb;
BRepBndLib::AddClose(s, bb);

std::vector<T> ts;

if (IfcGeom::Kernel::count(s, TopAbs_SHELL) == 0) {
return ts;
}

ts = select_box(bb);

if (ts.empty()) {
return ts;
}

std::vector<T> ts_filtered;
ts_filtered.reserve(ts.size());

typename std::vector<T>::const_iterator it = ts.begin();
for (it = ts.begin(); it != ts.end(); ++it) {
const TopoDS_Shape& B = shapes_.find(*it)->second;

if (IfcGeom::Kernel::count(B, TopAbs_SHELL) == 0) {
continue;
}

BRepAlgoAPI_Common common(s, B);
if (common.IsDone()) {
if (IfcGeom::Kernel::count(common.Shape(), TopAbs_SHELL) > 0) {
ts_filtered.push_back(*it);
}
}
}

return ts_filtered;
}

std::vector<T> select(const gp_Pnt& p) const {
std::vector<T> ts = select_box(p);
if (ts.empty()) {
return ts;
}

std::vector<T> ts_filtered;
ts_filtered.reserve(ts.size());

typename std::vector<T>::const_iterator it = ts.begin();
for (it = ts.begin(); it != ts.end(); ++it) {
const TopoDS_Shape& B = shapes_.find(*it)->second;
TopExp_Explorer exp(B, TopAbs_SOLID);
for (; exp.More(); exp.Next()) {
BRepClass3d_SolidClassifier cls(exp.Current(), p, 1e-5);
if (cls.State() != TopAbs_OUT) {
ts_filtered.push_back(*it);
break;
}
}
}

return ts_filtered;
}

protected:

typedef NCollection_UBTree<T, Bnd_Box> tree_t;
typedef std::map<T, TopoDS_Shape> map_t;
tree_t tree_;
map_t shapes_;

class selector : public tree_t::Selector
{
public:
selector(const Bnd_Box& b)
: tree_t::Selector()
, bounds_(b)
{}

Standard_Boolean Reject(const Bnd_Box& b) const {
return bounds_.IsOut(b);
}

Standard_Boolean Accept(const T& o) {
results_.push_back(o);
return Standard_True;
}

const std::vector<T>& results() const {
return results_;
}

private:
std::vector<T> results_;
const Bnd_Box& bounds_;
};

};
}

class tree : public impl::tree<IfcSchema::IfcProduct*> {
public:

tree() {};

tree(IfcParse::IfcFile& f) {
add_file(f, IfcGeom::IteratorSettings());
}

tree(IfcParse::IfcFile& f, const IfcGeom::IteratorSettings& settings) {
add_file(f, settings);
}

void add_file(IfcParse::IfcFile& f, const IfcGeom::IteratorSettings& settings) {
IfcGeom::IteratorSettings settings_ = settings;
settings_.set(IfcGeom::IteratorSettings::DISABLE_TRIANGULATION, true);
settings_.set(IfcGeom::IteratorSettings::USE_WORLD_COORDS, true);
settings_.set(IfcGeom::IteratorSettings::SEW_SHELLS, true);

IfcGeom::Iterator<double> it(settings_, &f);

if (it.initialize()) {
do {
IfcGeom::BRepElement<double>* elem = (IfcGeom::BRepElement<double>*)it.get();
add((IfcSchema::IfcProduct*)f.entityById(elem->id()), elem->geometry().as_compound());
} while (it.next());
}
}
};

}

#endif
Loading