mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-16 21:42:19 +00:00
Own iterator geometry results
Return independent geometry copies with unique ownership, preserve parent lifetimes, and teach the Python wrapper to own derived results. Keep serializer inputs non-owning and replace Collada's deferred object with copied triangulation elements.\n\nGenerated with the assistance of an AI coding tool.
This commit is contained in:
@@ -933,15 +933,15 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
|
|
||||||
ifcopenshell::geom::element* geom_object = context_iterator->get();
|
auto geom_object = context_iterator->get();
|
||||||
|
|
||||||
if (is_tesselated)
|
if (is_tesselated)
|
||||||
{
|
{
|
||||||
serializer->write(static_cast<const ifcopenshell::geom::triangulation_element*>(geom_object));
|
serializer->write(static_cast<const ifcopenshell::geom::triangulation_element*>(geom_object.get()));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
serializer->write(static_cast<const ifcopenshell::geom::brep_element*>(geom_object));
|
serializer->write(static_cast<const ifcopenshell::geom::brep_element*>(geom_object.get()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!no_progress) {
|
if (!no_progress) {
|
||||||
@@ -1412,7 +1412,7 @@ void fix_quantities(ifcopenshell::file& f, bool no_progress, bool quiet, bool st
|
|||||||
if (num_created) {
|
if (num_created) {
|
||||||
has_more = context_iterator.next();
|
has_more = context_iterator.next();
|
||||||
}
|
}
|
||||||
ifcopenshell::geom::brep_element* geom_object = nullptr;
|
std::unique_ptr<ifcopenshell::geom::brep_element> geom_object;
|
||||||
if (has_more) {
|
if (has_more) {
|
||||||
geom_object = context_iterator.get_native();
|
geom_object = context_iterator.get_native();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ void fix_storeycontainment(ifcopenshell::file& f, bool no_progress, bool quiet,
|
|||||||
if (num_created) {
|
if (num_created) {
|
||||||
has_more = context_iterator.next();
|
has_more = context_iterator.next();
|
||||||
}
|
}
|
||||||
ifcopenshell::geom::brep_element* geom_object = nullptr;
|
std::unique_ptr<ifcopenshell::geom::brep_element> geom_object;
|
||||||
if (has_more) {
|
if (has_more) {
|
||||||
geom_object = context_iterator.get_native();
|
geom_object = context_iterator.get_native();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -477,7 +477,7 @@ struct intersection_validator {
|
|||||||
if (num_created) {
|
if (num_created) {
|
||||||
has_more = context_iterator.next();
|
has_more = context_iterator.next();
|
||||||
}
|
}
|
||||||
ifcopenshell::geom::brep_element* geom_object = nullptr;
|
std::unique_ptr<ifcopenshell::geom::brep_element> geom_object;
|
||||||
if (has_more) {
|
if (has_more) {
|
||||||
geom_object = context_iterator.get_native();
|
geom_object = context_iterator.get_native();
|
||||||
}
|
}
|
||||||
|
|||||||
+27
-11
@@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#include "../ifcparse/argument.h"
|
#include "../ifcparse/argument.h"
|
||||||
#include "../ifcparse/global_id.h"
|
#include "../ifcparse/global_id.h"
|
||||||
@@ -73,8 +74,20 @@ namespace ifcopenshell::geom {
|
|||||||
std::string _context;
|
std::string _context;
|
||||||
std::string _unique_id;
|
std::string _unique_id;
|
||||||
ifcopenshell::geom::transformation _transformation;
|
ifcopenshell::geom::transformation _transformation;
|
||||||
const express::entity product_;
|
const express::entity product_;
|
||||||
std::vector<const ifcopenshell::geom::element*> _parents;
|
std::vector<const ifcopenshell::geom::element*> _parents;
|
||||||
|
std::vector<std::shared_ptr<const ifcopenshell::geom::element>> _parent_storage;
|
||||||
|
|
||||||
|
friend class iterator;
|
||||||
|
virtual std::unique_ptr<element> clone() const { return std::make_unique<element>(*this); }
|
||||||
|
void set_parents(std::vector<std::unique_ptr<ifcopenshell::geom::element>>&& newparents) {
|
||||||
|
_parents.clear();
|
||||||
|
_parent_storage.clear();
|
||||||
|
for (auto& parent : newparents) {
|
||||||
|
_parents.push_back(parent.get());
|
||||||
|
_parent_storage.emplace_back(std::move(parent));
|
||||||
|
}
|
||||||
|
}
|
||||||
public:
|
public:
|
||||||
|
|
||||||
friend bool operator == (const element& element1, const element& element2) {
|
friend bool operator == (const element& element1, const element& element2) {
|
||||||
@@ -108,9 +121,12 @@ namespace ifcopenshell::geom {
|
|||||||
const std::string& context() const { return _context; }
|
const std::string& context() const { return _context; }
|
||||||
const std::string& unique_id() const { return _unique_id; }
|
const std::string& unique_id() const { return _unique_id; }
|
||||||
const ifcopenshell::geom::transformation& transformation() const { return _transformation; }
|
const ifcopenshell::geom::transformation& transformation() const { return _transformation; }
|
||||||
const express::entity& product() const { return product_; }
|
const express::entity& product() const { return product_; }
|
||||||
const std::vector<const ifcopenshell::geom::element*>& parents() const { return _parents; }
|
const std::vector<const ifcopenshell::geom::element*>& parents() const { return _parents; }
|
||||||
void SetParents(std::vector<const ifcopenshell::geom::element*>& newparents) { _parents = newparents; }
|
void SetParents(std::vector<const ifcopenshell::geom::element*>& newparents) {
|
||||||
|
_parent_storage.clear();
|
||||||
|
_parents = newparents;
|
||||||
|
}
|
||||||
|
|
||||||
element(const ifcopenshell::geom::settings& settings, int id, int parent_id, const std::string& name, const std::string& type,
|
element(const ifcopenshell::geom::settings& settings, int id, int parent_id, const std::string& name, const std::string& type,
|
||||||
const std::string& guid, const std::string& context, const ifcopenshell::geom::taxonomy::matrix4::ptr& trsf, const express::entity& product)
|
const std::string& guid, const std::string& context, const ifcopenshell::geom::taxonomy::matrix4::ptr& trsf, const express::entity& product)
|
||||||
@@ -158,9 +174,10 @@ namespace ifcopenshell::geom {
|
|||||||
bool calculate_projected_surface_area(double& along_x, double& along_y, double& along_z) const {
|
bool calculate_projected_surface_area(double& along_x, double& along_y, double& along_z) const {
|
||||||
return geometry().calculate_projected_surface_area(this->transformation().data(), along_x, along_y, along_z);
|
return geometry().calculate_projected_surface_area(this->transformation().data(), along_x, along_y, along_z);
|
||||||
}
|
}
|
||||||
|
brep_element(const brep_element& other) = default;
|
||||||
private:
|
private:
|
||||||
brep_element(const brep_element& other);
|
|
||||||
brep_element& operator=(const brep_element& other);
|
brep_element& operator=(const brep_element& other);
|
||||||
|
std::unique_ptr<element> clone() const override { return std::make_unique<brep_element>(*this); }
|
||||||
};
|
};
|
||||||
|
|
||||||
class triangulation_element : public element {
|
class triangulation_element : public element {
|
||||||
@@ -177,26 +194,25 @@ namespace ifcopenshell::geom {
|
|||||||
: element(source)
|
: element(source)
|
||||||
, _geometry(geometry)
|
, _geometry(geometry)
|
||||||
{}
|
{}
|
||||||
|
triangulation_element(const triangulation_element& other) = default;
|
||||||
private:
|
private:
|
||||||
triangulation_element(const triangulation_element& other);
|
|
||||||
triangulation_element& operator=(const triangulation_element& other);
|
triangulation_element& operator=(const triangulation_element& other);
|
||||||
|
std::unique_ptr<element> clone() const override { return std::make_unique<triangulation_element>(*this); }
|
||||||
};
|
};
|
||||||
|
|
||||||
class serialized_element : public element {
|
class serialized_element : public element {
|
||||||
private:
|
private:
|
||||||
ifcopenshell::geom::Representation::serialization* _geometry;
|
boost::shared_ptr<ifcopenshell::geom::Representation::serialization> _geometry;
|
||||||
public:
|
public:
|
||||||
const ifcopenshell::geom::Representation::serialization& geometry() const { return *_geometry; }
|
const ifcopenshell::geom::Representation::serialization& geometry() const { return *_geometry; }
|
||||||
serialized_element(const brep_element& shape_model)
|
serialized_element(const brep_element& shape_model)
|
||||||
: element(shape_model)
|
: element(shape_model)
|
||||||
, _geometry(new ifcopenshell::geom::Representation::serialization(shape_model.geometry()))
|
, _geometry(boost::shared_ptr<ifcopenshell::geom::Representation::serialization>(new ifcopenshell::geom::Representation::serialization(shape_model.geometry())))
|
||||||
{}
|
{}
|
||||||
virtual ~serialized_element() {
|
serialized_element(const serialized_element& other) = default;
|
||||||
delete _geometry;
|
|
||||||
}
|
|
||||||
private:
|
private:
|
||||||
serialized_element(const serialized_element& other);
|
|
||||||
serialized_element& operator=(const serialized_element& other);
|
serialized_element& operator=(const serialized_element& other);
|
||||||
|
std::unique_ptr<element> clone() const override { return std::make_unique<serialized_element>(*this); }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+15
-16
@@ -301,8 +301,8 @@ void ifcopenshell::geom::iterator::compute_bounds(bool with_geometry)
|
|||||||
if (with_geometry) {
|
if (with_geometry) {
|
||||||
size_t num_created = 0;
|
size_t num_created = 0;
|
||||||
do {
|
do {
|
||||||
ifcopenshell::geom::element* geom_object = get();
|
auto geom_object = get();
|
||||||
const ifcopenshell::geom::triangulation_element* o = static_cast<const ifcopenshell::geom::triangulation_element*>(geom_object);
|
const ifcopenshell::geom::triangulation_element* o = static_cast<const ifcopenshell::geom::triangulation_element*>(geom_object.get());
|
||||||
const ifcopenshell::geom::Representation::triangulation& mesh = o->geometry();
|
const ifcopenshell::geom::Representation::triangulation& mesh = o->geometry();
|
||||||
auto mat = o->transformation().data()->ccomponents();
|
auto mat = o->transformation().data()->ccomponents();
|
||||||
Eigen::Vector4d vec, transformed;
|
Eigen::Vector4d vec, transformed;
|
||||||
@@ -548,7 +548,7 @@ express::base ifcopenshell::geom::iterator::next() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the representation of the current geometrical entity.
|
/// Gets the representation of the current geometrical entity.
|
||||||
ifcopenshell::geom::element* ifcopenshell::geom::iterator::get()
|
std::unique_ptr<ifcopenshell::geom::element> ifcopenshell::geom::iterator::get()
|
||||||
{
|
{
|
||||||
validate_iterator_state();
|
validate_iterator_state();
|
||||||
|
|
||||||
@@ -558,24 +558,24 @@ ifcopenshell::geom::element* ifcopenshell::geom::iterator::get()
|
|||||||
if (settings_.get<ifcopenshell::geom::settings::UseElementHierarchy>().get()) {
|
if (settings_.get<ifcopenshell::geom::settings::UseElementHierarchy>().get()) {
|
||||||
// We are going to build a vector with the element parents.
|
// We are going to build a vector with the element parents.
|
||||||
// First, create the parent vector
|
// First, create the parent vector
|
||||||
std::vector<const ifcopenshell::geom::element*> parents;
|
std::vector<std::unique_ptr<ifcopenshell::geom::element>> parents;
|
||||||
|
|
||||||
// if the element has a parent
|
// if the element has a parent
|
||||||
if (ret->parent_id() != -1) {
|
if (ret->parent_id() != -1) {
|
||||||
const ifcopenshell::geom::element* parent_object = NULL;
|
ifcopenshell::geom::element* parent_object = NULL;
|
||||||
bool hasParent = true;
|
bool hasParent = true;
|
||||||
|
|
||||||
// get the parent
|
// get the parent
|
||||||
try {
|
try {
|
||||||
parent_object = get_object(ret->parent_id());
|
auto parent = get_object(ret->parent_id());
|
||||||
|
parent_object = parent.get();
|
||||||
|
parents.insert(parents.begin(), std::move(parent));
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
logger_.error("GEO", 56, e);
|
logger_.error("GEO", 56, e);
|
||||||
hasParent = false;
|
hasParent = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the previously found parent to the vector
|
// Add the previously found parent to the vector
|
||||||
if (hasParent) parents.insert(parents.begin(), parent_object);
|
|
||||||
|
|
||||||
// We need to find all the parents
|
// We need to find all the parents
|
||||||
while (parent_object != NULL && hasParent && parent_object->parent_id() != -1) {
|
while (parent_object != NULL && hasParent && parent_object->parent_id() != -1) {
|
||||||
// Find the next parent
|
// Find the next parent
|
||||||
@@ -585,7 +585,9 @@ ifcopenshell::geom::element* ifcopenshell::geom::iterator::get()
|
|||||||
hasParent = false;
|
hasParent = false;
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
parent_object = get_object(pid);
|
auto parent = get_object(pid);
|
||||||
|
parent_object = parent.get();
|
||||||
|
parents.insert(parents.begin(), std::move(parent));
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
logger_.error("GEO", 57, e);
|
logger_.error("GEO", 57, e);
|
||||||
hasParent = false;
|
hasParent = false;
|
||||||
@@ -593,20 +595,18 @@ ifcopenshell::geom::element* ifcopenshell::geom::iterator::get()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add the previously found parent to the vector
|
// Add the previously found parent to the vector
|
||||||
if (hasParent) parents.insert(parents.begin(), parent_object);
|
|
||||||
|
|
||||||
hasParent = hasParent && parent_object->parent_id() != -1;
|
hasParent = hasParent && parent_object->parent_id() != -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// when done push the parent list in the element object
|
// when done push the parent list in the element object
|
||||||
ret->SetParents(parents);
|
ret->set_parents(std::move(parents));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret->clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
const ifcopenshell::geom::element* ifcopenshell::geom::iterator::get_object(int id) {
|
std::unique_ptr<ifcopenshell::geom::element> ifcopenshell::geom::iterator::get_object(int id) {
|
||||||
ifcopenshell::geom::taxonomy::matrix4::ptr m4;
|
ifcopenshell::geom::taxonomy::matrix4::ptr m4;
|
||||||
int parent_id = -1;
|
int parent_id = -1;
|
||||||
std::string instance_type, product_name, product_guid;
|
std::string instance_type, product_name, product_guid;
|
||||||
@@ -639,8 +639,7 @@ const ifcopenshell::geom::element* ifcopenshell::geom::iterator::get_object(int
|
|||||||
logger_.error("GEO", 59, "Unknown error returning product");
|
logger_.error("GEO", 59, "Unknown error returning product");
|
||||||
}
|
}
|
||||||
|
|
||||||
element* ifc_object = new element(settings_, id, parent_id, product_name, instance_type, product_guid, "", m4, ifc_product.as<express::entity>());
|
return std::make_unique<element>(settings_, id, parent_id, product_name, instance_type, product_guid, "", m4, ifc_product.as<express::entity>());
|
||||||
return ifc_object;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
express::base ifcopenshell::geom::iterator::create() {
|
express::base ifcopenshell::geom::iterator::create() {
|
||||||
|
|||||||
@@ -44,7 +44,7 @@
|
|||||||
* at least a single representation will process successfully *
|
* at least a single representation will process successfully *
|
||||||
* *
|
* *
|
||||||
* ifcopenshell::geom::iterator::get() *
|
* ifcopenshell::geom::iterator::get() *
|
||||||
* returns a pointer to the current ifcopenshell::geom::element *
|
* returns an owned copy of the current ifcopenshell::geom::element *
|
||||||
* *
|
* *
|
||||||
* ifcopenshell::geom::iterator::next() *
|
* ifcopenshell::geom::iterator::next() *
|
||||||
* returns true iff a following entity is available for a successive call to *
|
* returns true iff a following entity is available for a successive call to *
|
||||||
@@ -291,15 +291,16 @@ namespace ifcopenshell::geom {
|
|||||||
express::base next();
|
express::base next();
|
||||||
|
|
||||||
/// Gets the representation of the current geometrical entity.
|
/// Gets the representation of the current geometrical entity.
|
||||||
element* get();
|
std::unique_ptr<element> get();
|
||||||
|
|
||||||
/// Gets the native (Open Cascade or CGAL) representation of the current geometrical entity.
|
/// Gets the native (Open Cascade or CGAL) representation of the current geometrical entity.
|
||||||
brep_element* get_native()
|
std::unique_ptr<brep_element> get_native()
|
||||||
{
|
{
|
||||||
return *native_task_result_iterator_;
|
validate_iterator_state();
|
||||||
|
return std::make_unique<brep_element>(**native_task_result_iterator_);
|
||||||
}
|
}
|
||||||
|
|
||||||
const element* get_object(int id);
|
std::unique_ptr<element> get_object(int id);
|
||||||
|
|
||||||
express::base create();
|
express::base create();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1496,7 +1496,8 @@ namespace ifcopenshell::geom {
|
|||||||
void add_file(ifcopenshell::geom::iterator& it) {
|
void add_file(ifcopenshell::geom::iterator& it) {
|
||||||
if (it.initialize()) {
|
if (it.initialize()) {
|
||||||
do {
|
do {
|
||||||
add_element(dynamic_cast<ifcopenshell::geom::brep_element*>(it.get()));
|
auto element = it.get();
|
||||||
|
add_element(dynamic_cast<ifcopenshell::geom::brep_element*>(element.get()));
|
||||||
} while (it.next());
|
} while (it.next());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,7 +56,8 @@ namespace ifcopenshell {
|
|||||||
ifcopenshell::geom::iterator iterator(ifcopenshell::geom::kernels::construct(&file, "opencascade", settings_), settings_, &file, {}, 1);
|
ifcopenshell::geom::iterator iterator(ifcopenshell::geom::kernels::construct(&file, "opencascade", settings_), settings_, &file, {}, 1);
|
||||||
if (iterator.initialize()) {
|
if (iterator.initialize()) {
|
||||||
do {
|
do {
|
||||||
add_element(iterator.get());
|
auto element = iterator.get();
|
||||||
|
add_element(element.get());
|
||||||
} while (iterator.next());
|
} while (iterator.next());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -139,7 +140,8 @@ namespace ifcopenshell {
|
|||||||
ifcopenshell::geom::iterator iterator(ifcopenshell::geom::kernels::construct(&file, "opencascade", settings_), settings_, &file, {}, 1);
|
ifcopenshell::geom::iterator iterator(ifcopenshell::geom::kernels::construct(&file, "opencascade", settings_), settings_, &file, {}, 1);
|
||||||
if (iterator.initialize()) {
|
if (iterator.initialize()) {
|
||||||
do {
|
do {
|
||||||
add_element(iterator.get());
|
auto element = iterator.get();
|
||||||
|
add_element(element.get());
|
||||||
} while (iterator.next());
|
} while (iterator.next());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -151,7 +151,8 @@ void ifcopenshell::geom::tree::add_file(ifcopenshell::geom::iterator& iterator)
|
|||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
add_element(iterator.get());
|
auto element = iterator.get();
|
||||||
|
add_element(element.get());
|
||||||
} while (iterator.next());
|
} while (iterator.next());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -617,12 +617,14 @@ int main () {
|
|||||||
exit_code = 1;
|
exit_code = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
const ifcopenshell::geom::triangulation_element* geom = static_cast<const ifcopenshell::geom::triangulation_element*>(iterator->get());
|
auto element = iterator->get();
|
||||||
|
const ifcopenshell::geom::triangulation_element* geom = static_cast<const ifcopenshell::geom::triangulation_element*>(element.get());
|
||||||
|
auto native_element = iterator->get_native();
|
||||||
std::unique_ptr<EntityExtension> eext;
|
std::unique_ptr<EntityExtension> eext;
|
||||||
if (emit_quantities) {
|
if (emit_quantities) {
|
||||||
eext.reset(new QuantityWriter_v1(iterator->get_native()));
|
eext.reset(new QuantityWriter_v1(native_element.get()));
|
||||||
} else {
|
} else {
|
||||||
eext.reset(new QuantityWriter_v0(iterator->get_native()));
|
eext.reset(new QuantityWriter_v0(native_element.get()));
|
||||||
}
|
}
|
||||||
Entity(geom, eext.get()).write(std::cout);
|
Entity(geom, eext.get()).write(std::cout);
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -539,7 +539,8 @@ void GeometryStreamer::run(const std::string& path, int num_threads) {
|
|||||||
do {
|
do {
|
||||||
if (cancel_requested_.load()) break;
|
if (cancel_requested_.load()) break;
|
||||||
|
|
||||||
const ifcopenshell::geom::element* elem = iterator->get();
|
auto element = iterator->get();
|
||||||
|
const ifcopenshell::geom::element* elem = element.get();
|
||||||
if (!elem) continue;
|
if (!elem) continue;
|
||||||
|
|
||||||
const auto* tri_elem = dynamic_cast<const ifcopenshell::geom::triangulation_element*>(elem);
|
const auto* tri_elem = dynamic_cast<const ifcopenshell::geom::triangulation_element*>(elem);
|
||||||
|
|||||||
@@ -103,6 +103,28 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Iterator results are copies owned by the caller. Release the unique pointer
|
||||||
|
// into the most specific Python proxy and transfer deletion to Python.
|
||||||
|
%typemap(out) std::unique_ptr<ifcopenshell::geom::element> {
|
||||||
|
ifcopenshell::geom::element* elem = $1.release();
|
||||||
|
ifcopenshell::geom::serialized_element* serialized_elem = dynamic_cast<ifcopenshell::geom::serialized_element*>(elem);
|
||||||
|
ifcopenshell::geom::triangulation_element* triangulation_elem = dynamic_cast<ifcopenshell::geom::triangulation_element*>(elem);
|
||||||
|
ifcopenshell::geom::brep_element* brep_elem = dynamic_cast<ifcopenshell::geom::brep_element*>(elem);
|
||||||
|
if (triangulation_elem) {
|
||||||
|
$result = SWIG_NewPointerObj(SWIG_as_voidptr(triangulation_elem), SWIGTYPE_p_ifcopenshell__geom__triangulation_element, SWIG_POINTER_OWN);
|
||||||
|
} else if (serialized_elem) {
|
||||||
|
$result = SWIG_NewPointerObj(SWIG_as_voidptr(serialized_elem), SWIGTYPE_p_ifcopenshell__geom__serialized_element, SWIG_POINTER_OWN);
|
||||||
|
} else if (brep_elem) {
|
||||||
|
$result = SWIG_NewPointerObj(SWIG_as_voidptr(brep_elem), SWIGTYPE_p_ifcopenshell__geom__brep_element, SWIG_POINTER_OWN);
|
||||||
|
} else {
|
||||||
|
$result = SWIG_NewPointerObj(SWIG_as_voidptr(elem), SWIGTYPE_p_ifcopenshell__geom__element, SWIG_POINTER_OWN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
%typemap(out) std::unique_ptr<ifcopenshell::geom::brep_element> {
|
||||||
|
$result = SWIG_NewPointerObj(SWIG_as_voidptr($1.release()), SWIGTYPE_p_ifcopenshell__geom__brep_element, SWIG_POINTER_OWN);
|
||||||
|
}
|
||||||
|
|
||||||
%newobject ifcopenshell::geom::Representation::brep::item;
|
%newobject ifcopenshell::geom::Representation::brep::item;
|
||||||
%newobject ifcopenshell::geom::Representation::brep::as_compound;
|
%newobject ifcopenshell::geom::Representation::brep::as_compound;
|
||||||
|
|
||||||
|
|||||||
@@ -387,29 +387,10 @@ void collada_serializer::collada_exporter::startDocument(const std::string& unit
|
|||||||
void collada_serializer::collada_exporter::write(const ifcopenshell::geom::triangulation_element* o)
|
void collada_serializer::collada_exporter::write(const ifcopenshell::geom::triangulation_element* o)
|
||||||
{
|
{
|
||||||
const ifcopenshell::geom::Representation::triangulation& mesh = o->geometry();
|
const ifcopenshell::geom::Representation::triangulation& mesh = o->geometry();
|
||||||
|
|
||||||
std::string name = serializer->object_id(o);
|
|
||||||
collada_id(name);
|
|
||||||
|
|
||||||
std::string representation_id = "representation-" + o->geometry().id();
|
|
||||||
collada_id(representation_id);
|
|
||||||
|
|
||||||
std::vector<std::string> material_references;
|
|
||||||
BOOST_FOREACH(const ifcopenshell::geom::taxonomy::style::ptr& material, mesh.materials()) {
|
BOOST_FOREACH(const ifcopenshell::geom::taxonomy::style::ptr& material, mesh.materials()) {
|
||||||
materials.add(material);
|
materials.add(material);
|
||||||
|
|
||||||
std::string material_name = materials.getMaterialUri(material);
|
|
||||||
material_references.push_back(material_name);
|
|
||||||
}
|
}
|
||||||
|
deferreds.push_back(std::make_unique<ifcopenshell::geom::triangulation_element>(*o));
|
||||||
deferred_object deferred(name, representation_id, o->type(), o->transformation(), mesh.verts(), mesh.normals(),
|
|
||||||
mesh.faces(), mesh.edges(), mesh.material_ids(), mesh.materials(), material_references, mesh.uvs());
|
|
||||||
|
|
||||||
if (serializer->settings().get<ifcopenshell::geom::settings::UseElementHierarchy>().get()) {
|
|
||||||
deferred.parents() = o->parents();
|
|
||||||
}
|
|
||||||
|
|
||||||
deferreds.push_back(deferred);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string collada_serializer::differentiateSlabTypes(const express::entity& slab)
|
std::string collada_serializer::differentiateSlabTypes(const express::entity& slab)
|
||||||
@@ -467,25 +448,53 @@ void collada_serializer::collada_exporter::endDocument() {
|
|||||||
//if the setting USE_ELEMENT_HIERARCHY is in use, we sort the deferreds objects by their parents.
|
//if the setting USE_ELEMENT_HIERARCHY is in use, we sort the deferreds objects by their parents.
|
||||||
|
|
||||||
if (use_hierarchy) {
|
if (use_hierarchy) {
|
||||||
std::sort(deferreds.begin(), deferreds.end());
|
std::sort(deferreds.begin(), deferreds.end(), [](const auto& first, const auto& second) {
|
||||||
|
const auto& first_parents = first->parents();
|
||||||
|
const auto& second_parents = second->parents();
|
||||||
|
const size_t size = (std::min)(first_parents.size(), second_parents.size());
|
||||||
|
size_t index = 0;
|
||||||
|
while (index < size && *first_parents[index] == *second_parents[index]) {
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
return index >= size
|
||||||
|
? first_parents.size() < second_parents.size()
|
||||||
|
: *first_parents[index] < *second_parents[index];
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
for (std::vector<deferred_object>::const_iterator it = deferreds.begin(); it != deferreds.end(); ++it) {
|
for (const auto& object_pointer : deferreds) {
|
||||||
if (geometries_written.find(it->representation_id) != geometries_written.end()) {
|
const auto& object = *object_pointer;
|
||||||
|
std::string representation_id = "representation-" + object.geometry().id();
|
||||||
|
collada_id(representation_id);
|
||||||
|
if (geometries_written.find(representation_id) != geometries_written.end()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
geometries_written.insert(it->representation_id);
|
geometries_written.insert(representation_id);
|
||||||
geometries.write(it->representation_id, it->type, it->vertices, it->normals, it->faces, it->edges,
|
const auto& mesh = object.geometry();
|
||||||
it->material_ids, it->materials, it->uvs, it->material_references);
|
std::vector<std::string> material_references;
|
||||||
|
for (const auto& material : mesh.materials()) {
|
||||||
|
material_references.push_back(materials.getMaterialUri(material));
|
||||||
|
}
|
||||||
|
geometries.write(representation_id, object.type(), mesh.verts(), mesh.normals(), mesh.faces(), mesh.edges(),
|
||||||
|
mesh.material_ids(), mesh.materials(), mesh.uvs(), material_references);
|
||||||
}
|
}
|
||||||
geometries.close();
|
geometries.close();
|
||||||
|
|
||||||
for (std::vector<deferred_object>::const_iterator it = deferreds.begin(); it != deferreds.end(); ++it){
|
for (const auto& object_pointer : deferreds) {
|
||||||
const std::string object_name = it->unique_id;
|
const auto& object = *object_pointer;
|
||||||
|
std::string object_name = serializer->object_id(&object);
|
||||||
|
collada_id(object_name);
|
||||||
|
std::string representation_id = "representation-" + object.geometry().id();
|
||||||
|
collada_id(representation_id);
|
||||||
|
std::vector<std::string> material_references;
|
||||||
|
for (const auto& material : object.geometry().materials()) {
|
||||||
|
material_references.push_back(materials.getMaterialUri(material));
|
||||||
|
}
|
||||||
|
|
||||||
if (use_hierarchy)
|
if (use_hierarchy)
|
||||||
{
|
{
|
||||||
size_t parentsNumber = it->parents_.size();
|
const auto& parents = object.parents();
|
||||||
|
size_t parentsNumber = parents.size();
|
||||||
bool finished = false;
|
bool finished = false;
|
||||||
|
|
||||||
// If we have no parent in the stack and the object has no parent, nothing to do : skip the loop
|
// If we have no parent in the stack and the object has no parent, nothing to do : skip the loop
|
||||||
@@ -496,17 +505,17 @@ void collada_serializer::collada_exporter::endDocument() {
|
|||||||
// If we need to add a parent
|
// If we need to add a parent
|
||||||
if (serializer->parentStackId.size() <= parentsNumber)
|
if (serializer->parentStackId.size() <= parentsNumber)
|
||||||
{
|
{
|
||||||
if (serializer->parentStackId.empty()) { scene.addParent(*(it->parents_.at(0))); }
|
if (serializer->parentStackId.empty()) { scene.addParent(*parents.at(0)); }
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
size_t diff = parentsNumber - serializer->parentStackId.size();
|
size_t diff = parentsNumber - serializer->parentStackId.size();
|
||||||
|
|
||||||
// If we have the wrong parent in the list
|
// If we have the wrong parent in the list
|
||||||
if (serializer->parentStackId.top() != it->parents_.at(parentsNumber - diff - 1)->id()) {
|
if (serializer->parentStackId.top() != parents.at(parentsNumber - diff - 1)->id()) {
|
||||||
scene.closeParent();
|
scene.closeParent();
|
||||||
} else {
|
} else {
|
||||||
// So far we have the right parents, we just need to add the missing ones
|
// So far we have the right parents, we just need to add the missing ones
|
||||||
for (size_t i = parentsNumber - diff; i < parentsNumber; i++) { scene.addParent(*(it->parents_.at(i))); }
|
for (size_t i = parentsNumber - diff; i < parentsNumber; i++) { scene.addParent(*parents.at(i)); }
|
||||||
|
|
||||||
// if diff == 0, we can leave the loop. In fact we have the right number of parents, and the last one is ok
|
// if diff == 0, we can leave the loop. In fact we have the right number of parents, and the last one is ok
|
||||||
if (diff == 0) { finished = true; }
|
if (diff == 0) { finished = true; }
|
||||||
@@ -520,7 +529,7 @@ void collada_serializer::collada_exporter::endDocument() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// @todo redundant information using ID as both ID and Name, maybe omit Name or allow specifying what would be used as the name
|
/// @todo redundant information using ID as both ID and Name, maybe omit Name or allow specifying what would be used as the name
|
||||||
scene.add(object_name, object_name, it->representation_id, it->material_references, it->transformation);
|
scene.add(object_name, object_name, representation_id, material_references, object.transformation());
|
||||||
}
|
}
|
||||||
|
|
||||||
//close the remaining parent tags.
|
//close the remaining parent tags.
|
||||||
|
|||||||
@@ -70,7 +70,6 @@ private:
|
|||||||
{}
|
{}
|
||||||
void addFloatSource(const std::string& mesh_id, const std::string& suffix,
|
void addFloatSource(const std::string& mesh_id, const std::string& suffix,
|
||||||
const std::vector<double>& floats, const char* coords = "XYZ");
|
const std::vector<double>& floats, const char* coords = "XYZ");
|
||||||
/// @todo pass simply deferred_object?
|
|
||||||
void write(
|
void write(
|
||||||
const std::string &mesh_id, const std::string &default_material_name,
|
const std::string &mesh_id, const std::string &default_material_name,
|
||||||
const std::vector<double>& positions, const std::vector<double>& normals,
|
const std::vector<double>& positions, const std::vector<double>& normals,
|
||||||
@@ -138,59 +137,6 @@ private:
|
|||||||
collada_effects effects;
|
collada_effects effects;
|
||||||
};
|
};
|
||||||
|
|
||||||
class deferred_object {
|
|
||||||
|
|
||||||
friend bool operator < (const deferred_object& def_obj1, const deferred_object& def_obj2) {
|
|
||||||
size_t size = (def_obj1.parents_.size() < def_obj2.parents_.size() ? def_obj1.parents_.size() : def_obj2.parents_.size());
|
|
||||||
size_t cpt = 0;
|
|
||||||
|
|
||||||
// Skip the shared parents
|
|
||||||
while (cpt < size && *(def_obj1.parents_.at(cpt)) == *(def_obj2.parents_.at(cpt))) {
|
|
||||||
cpt++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If a parent list container the other one
|
|
||||||
if (cpt >= size) {
|
|
||||||
return def_obj1.parents_.size() < def_obj2.parents_.size();
|
|
||||||
} else {
|
|
||||||
return *(def_obj1.parents_.at(cpt)) < *(def_obj2.parents_.at(cpt));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
std::string unique_id, representation_id, type;
|
|
||||||
ifcopenshell::geom::transformation transformation;
|
|
||||||
std::vector<double> vertices;
|
|
||||||
std::vector<double> normals;
|
|
||||||
std::vector<int> faces;
|
|
||||||
std::vector<int> edges;
|
|
||||||
std::vector<int> material_ids;
|
|
||||||
std::vector<ifcopenshell::geom::taxonomy::style::ptr> materials;
|
|
||||||
std::vector<std::string> material_references;
|
|
||||||
std::vector<double> uvs;
|
|
||||||
std::vector<const ifcopenshell::geom::element*> parents_;
|
|
||||||
|
|
||||||
deferred_object(const std::string& unique_id, const std::string& representation_id, const std::string& type, const ifcopenshell::geom::transformation& transformation,
|
|
||||||
const std::vector<double>& vertices, const std::vector<double>& normals, const std::vector<int>& faces,
|
|
||||||
const std::vector<int>& edges, const std::vector<int>& material_ids, const std::vector<ifcopenshell::geom::taxonomy::style::ptr>& materials,
|
|
||||||
const std::vector<std::string>& material_references, const std::vector<double>& uvs)
|
|
||||||
: unique_id(unique_id)
|
|
||||||
, representation_id(representation_id)
|
|
||||||
, type(type)
|
|
||||||
, transformation(transformation)
|
|
||||||
, vertices(vertices)
|
|
||||||
, normals(normals)
|
|
||||||
, faces(faces)
|
|
||||||
, edges(edges)
|
|
||||||
, material_ids(material_ids)
|
|
||||||
, materials(materials)
|
|
||||||
, material_references(material_references)
|
|
||||||
, uvs(uvs)
|
|
||||||
{}
|
|
||||||
|
|
||||||
std::vector<const ifcopenshell::geom::element*>& parents() { return parents_; }
|
|
||||||
const std::vector<const ifcopenshell::geom::element*>& parents() const { return parents_; }
|
|
||||||
};
|
|
||||||
COLLADABU::NativeString filename;
|
COLLADABU::NativeString filename;
|
||||||
COLLADASW::StreamWriter stream;
|
COLLADASW::StreamWriter stream;
|
||||||
collada_scene scene;
|
collada_scene scene;
|
||||||
@@ -209,7 +155,7 @@ private:
|
|||||||
collada_materials materials;
|
collada_materials materials;
|
||||||
collada_geometries geometries;
|
collada_geometries geometries;
|
||||||
collada_serializer *serializer;
|
collada_serializer *serializer;
|
||||||
std::vector<deferred_object> deferreds;
|
std::vector<std::unique_ptr<ifcopenshell::geom::triangulation_element>> deferreds;
|
||||||
virtual ~collada_exporter() {}
|
virtual ~collada_exporter() {}
|
||||||
void startDocument(const std::string& unit_name, float unit_magnitude);
|
void startDocument(const std::string& unit_name, float unit_magnitude);
|
||||||
void write(const ifcopenshell::geom::triangulation_element* o);
|
void write(const ifcopenshell::geom::triangulation_element* o);
|
||||||
|
|||||||
Reference in New Issue
Block a user