mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-22 05:20:51 +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:
@@ -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)
|
||||
{
|
||||
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()) {
|
||||
materials.add(material);
|
||||
|
||||
std::string material_name = materials.getMaterialUri(material);
|
||||
material_references.push_back(material_name);
|
||||
}
|
||||
|
||||
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);
|
||||
deferreds.push_back(std::make_unique<ifcopenshell::geom::triangulation_element>(*o));
|
||||
}
|
||||
|
||||
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 (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) {
|
||||
if (geometries_written.find(it->representation_id) != geometries_written.end()) {
|
||||
for (const auto& object_pointer : deferreds) {
|
||||
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;
|
||||
}
|
||||
geometries_written.insert(it->representation_id);
|
||||
geometries.write(it->representation_id, it->type, it->vertices, it->normals, it->faces, it->edges,
|
||||
it->material_ids, it->materials, it->uvs, it->material_references);
|
||||
geometries_written.insert(representation_id);
|
||||
const auto& mesh = object.geometry();
|
||||
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();
|
||||
|
||||
for (std::vector<deferred_object>::const_iterator it = deferreds.begin(); it != deferreds.end(); ++it){
|
||||
const std::string object_name = it->unique_id;
|
||||
for (const auto& object_pointer : deferreds) {
|
||||
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)
|
||||
{
|
||||
size_t parentsNumber = it->parents_.size();
|
||||
const auto& parents = object.parents();
|
||||
size_t parentsNumber = parents.size();
|
||||
bool finished = false;
|
||||
|
||||
// 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 (serializer->parentStackId.size() <= parentsNumber)
|
||||
{
|
||||
if (serializer->parentStackId.empty()) { scene.addParent(*(it->parents_.at(0))); }
|
||||
if (serializer->parentStackId.empty()) { scene.addParent(*parents.at(0)); }
|
||||
else
|
||||
{
|
||||
size_t diff = parentsNumber - serializer->parentStackId.size();
|
||||
|
||||
// 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();
|
||||
} else {
|
||||
// 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) { 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
|
||||
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.
|
||||
|
||||
@@ -70,7 +70,6 @@ private:
|
||||
{}
|
||||
void addFloatSource(const std::string& mesh_id, const std::string& suffix,
|
||||
const std::vector<double>& floats, const char* coords = "XYZ");
|
||||
/// @todo pass simply deferred_object?
|
||||
void write(
|
||||
const std::string &mesh_id, const std::string &default_material_name,
|
||||
const std::vector<double>& positions, const std::vector<double>& normals,
|
||||
@@ -138,59 +137,6 @@ private:
|
||||
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;
|
||||
COLLADASW::StreamWriter stream;
|
||||
collada_scene scene;
|
||||
@@ -209,7 +155,7 @@ private:
|
||||
collada_materials materials;
|
||||
collada_geometries geometries;
|
||||
collada_serializer *serializer;
|
||||
std::vector<deferred_object> deferreds;
|
||||
std::vector<std::unique_ptr<ifcopenshell::geom::triangulation_element>> deferreds;
|
||||
virtual ~collada_exporter() {}
|
||||
void startDocument(const std::string& unit_name, float unit_magnitude);
|
||||
void write(const ifcopenshell::geom::triangulation_element* o);
|
||||
|
||||
Reference in New Issue
Block a user