mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-10-02 04:59:52 +00:00
Linearizing the use of IfcGeomIterator by integrating it into IfcConvert in full, atm it does not build.
This commit is contained in:
+553
-54
@@ -49,6 +49,10 @@
|
||||
#include <set>
|
||||
#include <time.h>
|
||||
|
||||
#include <future>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
|
||||
#if USE_VLD
|
||||
#include <vld.h>
|
||||
#endif
|
||||
@@ -75,6 +79,29 @@ const std::string TEMP_FILE_EXTENSION = ".tmp";
|
||||
|
||||
namespace po = boost::program_options;
|
||||
|
||||
|
||||
|
||||
|
||||
struct IfcproductRepresentation
|
||||
{
|
||||
int index;
|
||||
IfcSchema::IfcRepresentation *representation;
|
||||
IfcSchema::IfcProduct *product;
|
||||
IfcGeom::Element<real_t> *geom_object;
|
||||
IfcGeom::BRepElement<real_t> *element;
|
||||
};
|
||||
|
||||
struct Bounds
|
||||
{
|
||||
gp_XYZ min;
|
||||
gp_XYZ max;
|
||||
};
|
||||
|
||||
bool reuse_ok_(SerializerSettings settings, const IfcSchema::IfcProduct::list::ptr &products, IfcGeom::Kernel kernel);
|
||||
void create_element(SerializerSettings &settings,IfcproductRepresentation &rep);
|
||||
Bounds compute_bounds(IfcParse::IfcFile* ifc_file, IfcGeom::Kernel kernel);
|
||||
|
||||
|
||||
void print_version()
|
||||
{
|
||||
cout_ << "IfcOpenShell " << IfcSchema::Identifier << " IfcConvert " << IFCOPENSHELL_VERSION << " (OCC " << OCC_VERSION_STRING_EXT << ")\n";
|
||||
@@ -115,6 +142,7 @@ void print_options(const po::options_description& options)
|
||||
cout_ << std::endl;
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
T change_extension(const T& fn, const T& ext) {
|
||||
typename T::size_type dot = fn.find_last_of('.');
|
||||
@@ -560,12 +588,18 @@ int main(int argc, char** argv) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (!entity_filter.values.empty()) { entity_filter.update_description(); Logger::Notice(entity_filter.description); }
|
||||
if (!layer_filter.values.empty()) { layer_filter.update_description(); Logger::Notice(layer_filter.description); }
|
||||
if (!guid_filter.values.empty()) { guid_filter.update_description(); Logger::Notice(guid_filter.description); }
|
||||
if (!name_filter.values.empty()) { name_filter.update_description(); Logger::Notice(name_filter.description); }
|
||||
if (!desc_filter.values.empty()) { desc_filter.update_description(); Logger::Notice(desc_filter.description); }
|
||||
if (!tag_filter.values.empty()) { tag_filter.update_description(); Logger::Notice(tag_filter.description); }
|
||||
if (!entity_filter.values.empty()) {
|
||||
entity_filter.update_description(); Logger::Notice(entity_filter.description); }
|
||||
if (!layer_filter.values.empty()) {
|
||||
layer_filter.update_description(); Logger::Notice(layer_filter.description); }
|
||||
if (!guid_filter.values.empty()) {
|
||||
guid_filter.update_description(); Logger::Notice(guid_filter.description); }
|
||||
if (!name_filter.values.empty()) {
|
||||
name_filter.update_description(); Logger::Notice(name_filter.description); }
|
||||
if (!desc_filter.values.empty()) {
|
||||
desc_filter.update_description(); Logger::Notice(desc_filter.description); }
|
||||
if (!tag_filter.values.empty()) {
|
||||
tag_filter.update_description(); Logger::Notice(tag_filter.description); }
|
||||
|
||||
#ifdef _MSC_VER
|
||||
if (output_extension == DAE || output_extension == STP || output_extension == IGS) {
|
||||
@@ -600,8 +634,6 @@ int main(int argc, char** argv) {
|
||||
settings.set(IfcGeom::IteratorSettings::SEARCH_FLOOR, use_element_hierarchy);
|
||||
settings.set(IfcGeom::IteratorSettings::SITE_LOCAL_PLACEMENT, site_local_placement);
|
||||
settings.set(IfcGeom::IteratorSettings::BUILDING_LOCAL_PLACEMENT, building_local_placement);
|
||||
|
||||
|
||||
settings.set(SerializerSettings::USE_ELEMENT_NAMES, use_element_names);
|
||||
settings.set(SerializerSettings::USE_ELEMENT_GUIDS, use_element_guids);
|
||||
settings.set(SerializerSettings::USE_MATERIAL_NAMES, use_material_names);
|
||||
@@ -610,17 +642,25 @@ int main(int argc, char** argv) {
|
||||
settings.set_deflection_tolerance(deflection_tolerance);
|
||||
settings.precision = precision;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Set up serializer
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
boost::shared_ptr<GeometrySerializer> serializer; /**< @todo use std::unique_ptr when possible */
|
||||
if (output_extension == OBJ) {
|
||||
|
||||
if (output_extension == OBJ)
|
||||
{
|
||||
// Do not use temp file for MTL as it's such a small file.
|
||||
const path_t mtl_filename = change_extension(output_filename, MTL);
|
||||
if (!use_world_coords) {
|
||||
if (!use_world_coords)
|
||||
{
|
||||
Logger::Notice("Using world coords when writing WaveFront OBJ files");
|
||||
settings.set(IfcGeom::IteratorSettings::USE_WORLD_COORDS, true);
|
||||
}
|
||||
serializer = boost::make_shared<WaveFrontOBJSerializer>(IfcUtil::path::to_utf8(output_temp_filename), IfcUtil::path::to_utf8(mtl_filename), settings);
|
||||
#ifdef WITH_OPENCOLLADA
|
||||
} else if (output_extension == DAE) {
|
||||
} else if (output_extension == DAE)
|
||||
{
|
||||
serializer = boost::make_shared<ColladaSerializer>(IfcUtil::path::to_utf8(output_temp_filename), settings);
|
||||
#endif
|
||||
} else if (output_extension == STP) {
|
||||
@@ -684,20 +724,196 @@ int main(int argc, char** argv) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// initialize geometry
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
serializer->setFile(&ifc_file);
|
||||
|
||||
IfcGeom::Iterator<real_t> context_iterator(settings, &ifc_file, filter_funcs);
|
||||
if (!context_iterator.initialize()) {
|
||||
/// @todo It would be nice to know and print separate error prints for a case where we found no entities
|
||||
/// and for a case we found no entities that satisfy our filtering criteria.
|
||||
IfcGeom::Kernel kernel;
|
||||
std::string unit_name = "METER" ;
|
||||
double unit_magnitude = 1.f;
|
||||
IfcSchema::IfcRepresentation::list::ptr ok_mapped_representations;
|
||||
IfcSchema::IfcRepresentation::list::ptr representations =
|
||||
IfcSchema::IfcRepresentation::list::ptr(new IfcSchema::IfcRepresentation::list);
|
||||
IfcSchema::IfcRepresentation::list::it representation_iterator;
|
||||
|
||||
|
||||
try {
|
||||
|
||||
// constructor
|
||||
// TriangulationElement<P>* current_triangulation =0 ;
|
||||
// BRepElement<P>* current_shape_model = 0;
|
||||
// SerializedElement<P>* current_serialization = 0;
|
||||
kernel.setValue(IfcGeom::Kernel::GV_MAX_FACES_TO_SEW, settings.get(IfcGeom::IteratorSettings::SEW_SHELLS) ? 1000 : -1);
|
||||
kernel.setValue(IfcGeom::Kernel::GV_DIMENSIONALITY, (settings.get(IfcGeom::IteratorSettings::INCLUDE_CURVES)
|
||||
? (settings.get(IfcGeom::IteratorSettings::EXCLUDE_SOLIDS_AND_SURFACES) ? -1. : 0.) : +1.));
|
||||
if (settings.get(IfcGeom::IteratorSettings::BUILDING_LOCAL_PLACEMENT)) {
|
||||
if (settings.get(IfcGeom::IteratorSettings::SITE_LOCAL_PLACEMENT)) {
|
||||
Logger::Message(Logger::LOG_WARNING, "building-local-placement takes precedence over site-local-placement");
|
||||
}
|
||||
kernel.set_conversion_placement_rel_to(IfcSchema::Type::IfcBuilding);
|
||||
} else if (settings.get(IfcGeom::IteratorSettings::SITE_LOCAL_PLACEMENT)) {
|
||||
kernel.set_conversion_placement_rel_to(IfcSchema::Type::IfcSite);
|
||||
}
|
||||
|
||||
// initialize()
|
||||
// initunits()
|
||||
IfcSchema::IfcProject::list::ptr projects = ifc_file.entitiesByType<IfcSchema::IfcProject>();
|
||||
std::set<std::string> allowed_context_types;
|
||||
std::set<std::string> context_types;
|
||||
double lowest_precision_encountered = std::numeric_limits<double>::infinity();
|
||||
bool any_precision_encountered = false;
|
||||
|
||||
if (projects->size() == 1) {
|
||||
IfcSchema::IfcProject* project = *projects->begin();
|
||||
std::pair<std::string, double> length_unit = kernel.initializeUnits(project->UnitsInContext());
|
||||
unit_name = length_unit.first;
|
||||
unit_magnitude = length_unit.second;
|
||||
} else {
|
||||
Logger::Error("A single IfcProject is expected (encountered " + boost::lexical_cast<std::string>(projects->size()) + "); unable to read unit information.");
|
||||
}
|
||||
|
||||
allowed_context_types.insert("model");
|
||||
allowed_context_types.insert("plan");
|
||||
allowed_context_types.insert("notdefined");
|
||||
if (!settings.get(IfcGeom::IteratorSettings::EXCLUDE_SOLIDS_AND_SURFACES)) {
|
||||
// Really this should only be 'Model', as per
|
||||
// the standard 'Design' is deprecated. So,
|
||||
// just for backwards compatibility:
|
||||
context_types.insert("model");
|
||||
context_types.insert("design");
|
||||
// Some earlier (?) versions DDS-CAD output their own ContextTypes
|
||||
context_types.insert("model view");
|
||||
context_types.insert("detail view");
|
||||
}
|
||||
if (settings.get(IfcGeom::IteratorSettings::INCLUDE_CURVES)) {
|
||||
context_types.insert("plan");
|
||||
}
|
||||
|
||||
representations = IfcSchema::IfcRepresentation::list::ptr(new IfcSchema::IfcRepresentation::list);
|
||||
ok_mapped_representations = IfcSchema::IfcRepresentation::list::ptr(new IfcSchema::IfcRepresentation::list);
|
||||
|
||||
IfcSchema::IfcGeometricRepresentationContext::list::it it;
|
||||
IfcSchema::IfcGeometricRepresentationSubContext::list::it jt;
|
||||
IfcSchema::IfcGeometricRepresentationContext::list::ptr contexts =
|
||||
ifc_file.entitiesByType<IfcSchema::IfcGeometricRepresentationContext>();
|
||||
|
||||
IfcSchema::IfcGeometricRepresentationContext::list::ptr filtered_contexts (new IfcSchema::IfcGeometricRepresentationContext::list);
|
||||
|
||||
for (it = contexts->begin(); it != contexts->end(); ++it) {
|
||||
IfcSchema::IfcGeometricRepresentationContext* context = *it;
|
||||
if (context->is(IfcSchema::Type::IfcGeometricRepresentationSubContext)) {
|
||||
// Continue, as the list of subcontexts will be considered
|
||||
// by the parent's context inverse attributes.
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
if (context->hasContextType()) {
|
||||
std::string context_type = context->ContextType();
|
||||
boost::to_lower(context_type);
|
||||
if (allowed_context_types.find(context_type) == allowed_context_types.end()) {
|
||||
Logger::Message(Logger::LOG_ERROR, std::string("ContextType '") + context->ContextType() + "' not allowed:", context->entity);
|
||||
} // == allowed_context_types.end()
|
||||
if (context_types.find(context_type) != context_types.end()) {
|
||||
filtered_contexts->push(context);
|
||||
} // != context_types.end()
|
||||
} // hasContextType()
|
||||
} catch (const std::exception& e) {
|
||||
Logger::Error(e);
|
||||
}
|
||||
} // end iterating contexts
|
||||
|
||||
// In case no contexts are identified based on their ContextType, all contexts are
|
||||
// considered. Note that sub contexts are excluded as they are considered later on.
|
||||
if (filtered_contexts->size() == 0) {
|
||||
for (it = contexts->begin(); it != contexts->end(); ++it) {
|
||||
IfcSchema::IfcGeometricRepresentationContext* context = *it;
|
||||
if (!context->is(IfcSchema::Type::IfcGeometricRepresentationSubContext)) {
|
||||
filtered_contexts->push(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (it = filtered_contexts->begin(); it != filtered_contexts->end(); ++it) {
|
||||
IfcSchema::IfcGeometricRepresentationContext* context = *it;
|
||||
|
||||
representations->push(context->RepresentationsInContext());
|
||||
try {
|
||||
if (context->hasPrecision() && context->Precision() < lowest_precision_encountered) {
|
||||
lowest_precision_encountered = context->Precision();
|
||||
any_precision_encountered = true;
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
Logger::Error(e);
|
||||
}
|
||||
|
||||
IfcSchema::IfcGeometricRepresentationSubContext::list::ptr sub_contexts = context->HasSubContexts();
|
||||
for (jt = sub_contexts->begin(); jt != sub_contexts->end(); ++jt) {
|
||||
representations->push((*jt)->RepresentationsInContext());
|
||||
}
|
||||
// There is no need for full recursion as the following is governed by the schema:
|
||||
// WR31: The parent context shall not be another geometric representation sub context.
|
||||
} // end iterating filtered_contexts
|
||||
|
||||
if (any_precision_encountered) {
|
||||
// Some arbitrary factor that has proven to work better for the models in the set of test files.
|
||||
lowest_precision_encountered *= 10.;
|
||||
lowest_precision_encountered *= unit_magnitude;
|
||||
if (lowest_precision_encountered < 1.e-7) {
|
||||
Logger::Message(Logger::LOG_WARNING, "Precision lower than 0.0000001 meter not enforced");
|
||||
kernel.setValue(IfcGeom::Kernel::GV_PRECISION, 1.e-7);
|
||||
} else {
|
||||
kernel.setValue(IfcGeom::Kernel::GV_PRECISION, lowest_precision_encountered);
|
||||
}
|
||||
} else {
|
||||
kernel.setValue(IfcGeom::Kernel::GV_PRECISION, 1.e-5);
|
||||
}
|
||||
|
||||
if (representations->size() == 0) {
|
||||
Logger::Message(Logger::LOG_ERROR, "No representations encountered in relevant contexts, using all");
|
||||
representations = ifc_file.entitiesByType<IfcSchema::IfcRepresentation>();
|
||||
}
|
||||
|
||||
if (representations->size() == 0) {
|
||||
Logger::Message(Logger::LOG_ERROR, "No representations encountered, aborting");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// representation_iterator = representations->begin();
|
||||
// ifcproducts.reset();
|
||||
|
||||
// if (!create()) {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// done = 0;
|
||||
// total = representations->size();
|
||||
|
||||
// return true;
|
||||
} catch (const std::exception& e) {
|
||||
Logger::Error(e);
|
||||
Logger::Error("No geometrical entities found");
|
||||
IfcUtil::path::delete_file(IfcUtil::path::to_utf8(output_temp_filename));
|
||||
write_log(!quiet);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
serializer->setFile(context_iterator.getFile());
|
||||
//replaces:
|
||||
// if (!context_iterator.initialize()) {
|
||||
// /// @todo It would be nice to know and print separate error prints for a case where we found no entities
|
||||
// /// and for a case we found no entities that satisfy our filtering criteria.
|
||||
// Logger::Error("No geometrical entities found");
|
||||
// IfcUtil::path::delete_file(IfcUtil::path::to_utf8(output_temp_filename));
|
||||
// write_log(!quiet);
|
||||
// return EXIT_FAILURE;
|
||||
// }
|
||||
|
||||
if (convert_back_units) {
|
||||
serializer->setUnitNameAndMagnitude(context_iterator.getUnitName(), static_cast<float>(context_iterator.getUnitMagnitude()));
|
||||
// serializer->setUnitNameAndMagnitude(context_iterator.getUnitName(), static_cast<float>(context_iterator.getUnitMagnitude()));
|
||||
serializer->setUnitNameAndMagnitude(unit_name, static_cast<float>(unit_magnitude));
|
||||
} else {
|
||||
serializer->setUnitNameAndMagnitude("METER", 1.0f);
|
||||
}
|
||||
@@ -705,7 +921,7 @@ int main(int argc, char** argv) {
|
||||
serializer->writeHeader();
|
||||
|
||||
int old_progress = quiet ? 0 : -1;
|
||||
|
||||
Bounds model_bounds;
|
||||
if (is_tesselated && (center_model || model_offset)) {
|
||||
double* offset = serializer->settings().offset;
|
||||
if (center_model) {
|
||||
@@ -715,10 +931,10 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
|
||||
if (!quiet) Logger::Status("Computing bounds...");
|
||||
context_iterator.compute_bounds();
|
||||
model_bounds = compute_bounds( &ifc_file, kernel );
|
||||
if (!quiet) Logger::Status("Done!");
|
||||
|
||||
gp_XYZ center = (context_iterator.bounds_min() + context_iterator.bounds_max()) * 0.5;
|
||||
gp_XYZ center = (model_bounds.min + model_bounds.max) * 0.5;
|
||||
offset[0] = -center.X();
|
||||
offset[1] = -center.Y();
|
||||
offset[2] = -center.Z();
|
||||
@@ -752,50 +968,218 @@ int main(int argc, char** argv) {
|
||||
// available.
|
||||
size_t num_created = 0;
|
||||
|
||||
do {
|
||||
IfcGeom::Element<real_t> *geom_object = context_iterator.get();
|
||||
|
||||
if (is_tesselated)
|
||||
////////////////////////////////////////////////////////////
|
||||
// start initializing elements for threading
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
std::vector<IfcproductRepresentation> IfcproductRepresentations;
|
||||
|
||||
// do {
|
||||
// IfcGeom::Element<real_t> *geom_object = context_iterator.get();
|
||||
|
||||
// if (is_tesselated)
|
||||
// {
|
||||
// serializer->write(static_cast<const IfcGeom::TriangulationElement<real_t>*>(geom_object));
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// serializer->write(static_cast<const IfcGeom::BRepElement<real_t>*>(geom_object));
|
||||
// }
|
||||
|
||||
// if (!no_progress) {
|
||||
// if (quiet) {
|
||||
// const int progress = context_iterator.progress();
|
||||
// for (; old_progress < progress; ++old_progress) {
|
||||
// std::cout << ".";
|
||||
// if (stderr_progress)
|
||||
// std::cerr << ".";
|
||||
// }
|
||||
// std::cout << std::flush;
|
||||
// if (stderr_progress)
|
||||
// std::cerr << std::flush;
|
||||
// } else {
|
||||
// const int progress = context_iterator.progress() / 2;
|
||||
// if (old_progress != progress) Logger::ProgressBar(progress);
|
||||
// old_progress = progress;
|
||||
// }
|
||||
// }
|
||||
// } while (++num_created, context_iterator.next());
|
||||
|
||||
// if (!no_progress && quiet) {
|
||||
// for (; old_progress < 100; ++old_progress) {
|
||||
// std::cout << ".";
|
||||
// if (stderr_progress)
|
||||
// std::cerr << ".";
|
||||
// }
|
||||
// std::cout << std::flush;
|
||||
// if (stderr_progress)
|
||||
// std::cerr << std::flush;
|
||||
// } else {
|
||||
// Logger::Status("\rDone creating geometry (" + boost::lexical_cast<std::string>(num_created) +
|
||||
// " objects) ");
|
||||
// }
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Copy/Paste from IfcInfo, fine-tooth comb over vars
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/////// find products associated with representations (... ?)
|
||||
////////////////////////////////////////////////////////////
|
||||
IfcSchema::IfcProduct::list::ptr ifcproducts;
|
||||
IfcSchema::IfcProduct::list::it ifcproduct_iterator;
|
||||
std::vector<IfcGeom::filter_t> filters_;
|
||||
|
||||
IfcGeom::layer_filter layer_filter;
|
||||
IfcGeom::entity_filter entity_filter;
|
||||
IfcGeom::string_arg_filter guid_filter(IfcSchema::Type::IfcRoot, 0);
|
||||
IfcGeom::string_arg_filter name_filter(IfcSchema::Type::IfcRoot, 2);
|
||||
IfcGeom::string_arg_filter desc_filter(IfcSchema::Type::IfcRoot, 3);
|
||||
IfcGeom::string_arg_filter tag_filter(IfcSchema::Type::IfcProxy, 8,
|
||||
IfcSchema::Type::IfcElement,
|
||||
7);
|
||||
filters_.emplace_back(boost::ref(layer_filter));
|
||||
filters_.emplace_back(boost::ref(entity_filter));
|
||||
filters_.emplace_back(boost::ref(guid_filter));
|
||||
filters_.emplace_back(boost::ref(name_filter));
|
||||
filters_.emplace_back(boost::ref(desc_filter));
|
||||
filters_.emplace_back(boost::ref(tag_filter));
|
||||
bool geometry_reuse_ok_for_current_representation_;
|
||||
|
||||
// functor
|
||||
struct filter_match
|
||||
{
|
||||
serializer->write(static_cast<const IfcGeom::TriangulationElement<real_t>*>(geom_object));
|
||||
filter_match(IfcSchema::IfcProduct *prod) : product(prod) {}
|
||||
bool operator()(const IfcGeom::filter_t &filter) const { return filter(product); }
|
||||
IfcSchema::IfcProduct *product;
|
||||
};
|
||||
|
||||
Logger::Status("starting to iterate over representations ");
|
||||
|
||||
start = std::chrono::system_clock::now();
|
||||
int index_count = 0;
|
||||
for (representation_iterator = representations->begin();
|
||||
representation_iterator != representations->end(); representation_iterator++)
|
||||
{
|
||||
IfcSchema::IfcRepresentation *representation = *representation_iterator;
|
||||
ifcproducts.reset();
|
||||
ifcproducts = IfcSchema::IfcProduct::list::ptr(new IfcSchema::IfcProduct::list);
|
||||
IfcSchema::IfcProduct::list::ptr unfiltered_products =
|
||||
kernel.products_represented_by(representation);
|
||||
geometry_reuse_ok_for_current_representation_ = reuse_ok_(settings, unfiltered_products);
|
||||
IfcSchema::IfcRepresentationMap::list::ptr maps = representation->RepresentationMap();
|
||||
if (!geometry_reuse_ok_for_current_representation_ && maps->size() == 1)
|
||||
{
|
||||
// unfiltered_products contains products represented by this representation by means of
|
||||
// mapped items. For example because of openings applied to products, reuse might not be
|
||||
// acceptable and then the products will be processed by means of their immediate
|
||||
// representation and not the mapped representation.
|
||||
|
||||
// IfcRepresentationMaps are also used for IfcTypeProducts, so an additional check is
|
||||
// performed whether the map is indeed used by IfcMappedItems.
|
||||
IfcSchema::IfcRepresentationMap *map = *maps->begin();
|
||||
if (map->MapUsage()->size() > 0)
|
||||
{
|
||||
// _nextShape();
|
||||
// continue;
|
||||
// NOTE(sander): is this equivalent to _nextShape() ?
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
bool representation_processed_as_mapped_item = false;
|
||||
IfcSchema::IfcRepresentation *representation_mapped_to =
|
||||
kernel.representation_mapped_to(representation);
|
||||
if (representation_mapped_to)
|
||||
{
|
||||
// Check if this representation has (or will be) processed as part its mapped
|
||||
// representation
|
||||
bool contains = ok_mapped_representations->contains(representation_mapped_to);
|
||||
bool reuse = reuse_ok_(settings, kernel.products_represented_by(representation_mapped_to));
|
||||
representation_processed_as_mapped_item = contains || reuse;
|
||||
}
|
||||
if (representation_processed_as_mapped_item)
|
||||
{
|
||||
ok_mapped_representations->push(representation_mapped_to);
|
||||
// _nextShape();
|
||||
// continue;
|
||||
continue;
|
||||
}
|
||||
// Filter the products based on the set of entities and/or names being included or excluded
|
||||
// for processing.
|
||||
for (IfcSchema::IfcProduct::list::it jt = unfiltered_products->begin();
|
||||
jt != unfiltered_products->end(); ++jt)
|
||||
{
|
||||
IfcSchema::IfcProduct *prod = *jt;
|
||||
if (boost::all(filters_, filter_match(prod)))
|
||||
{
|
||||
ifcproducts->push(prod);
|
||||
}
|
||||
} // end for unfiltered_products
|
||||
|
||||
for (ifcproduct_iterator = ifcproducts->begin(); ifcproduct_iterator != ifcproducts->end();
|
||||
ifcproduct_iterator++)
|
||||
{
|
||||
IfcproductRepresentation ir;
|
||||
ir.index = index_count;
|
||||
ir.product = *ifcproduct_iterator;
|
||||
ir.representation = representation;
|
||||
IfcproductRepresentations.push_back(ir);
|
||||
index_count++;
|
||||
} // end for ifcproducts
|
||||
|
||||
} // for representation in representations
|
||||
end = std::chrono::system_clock::now();
|
||||
elapsed_seconds = end - start;
|
||||
Logger::Status("iterated over representations: " + std::to_string(elapsed_seconds.count()));
|
||||
Logger::Status("count: " + std::to_string(index_count));
|
||||
|
||||
const unsigned int conc_threads = std::thread::hardware_concurrency();
|
||||
std::cout << "amount of threads available for use on this machine: " << conc_threads << std::endl;
|
||||
std::vector<std::future<void>> threadpool;
|
||||
count = 0;
|
||||
for (int j = 0; j < (int)IfcproductRepresentations.size();)
|
||||
{
|
||||
IfcproductRepresentation &r = IfcproductRepresentations[j];
|
||||
if (threadpool.size() < conc_threads)
|
||||
{
|
||||
std::future<void> fu = std::async(std::launch::async, create_element, std::ref(settings), std::ref(r));
|
||||
threadpool.emplace_back(std::move(fu));
|
||||
j++;
|
||||
}
|
||||
else
|
||||
{
|
||||
serializer->write(static_cast<const IfcGeom::BRepElement<real_t>*>(geom_object));
|
||||
bool waiting = true;
|
||||
while (waiting)
|
||||
{
|
||||
for (int i = 0; i < (int)threadpool.size(); i++)
|
||||
{
|
||||
std::future<void> &fu = threadpool[i];
|
||||
std::future_status status;
|
||||
status = fu.wait_for(std::chrono::seconds(0));
|
||||
if (status == std::future_status::ready)
|
||||
{
|
||||
fu.get();
|
||||
threadpool.erase(threadpool.begin() + i);
|
||||
waiting = false;
|
||||
} // if
|
||||
} // for
|
||||
} // while
|
||||
} // else
|
||||
}
|
||||
|
||||
if (!no_progress) {
|
||||
if (quiet) {
|
||||
const int progress = context_iterator.progress();
|
||||
for (; old_progress < progress; ++old_progress) {
|
||||
std::cout << ".";
|
||||
if (stderr_progress)
|
||||
std::cerr << ".";
|
||||
for (std::future<void> &fu : threadpool)
|
||||
{
|
||||
fu.get();
|
||||
}
|
||||
std::cout << std::flush;
|
||||
if (stderr_progress)
|
||||
std::cerr << std::flush;
|
||||
} else {
|
||||
const int progress = context_iterator.progress() / 2;
|
||||
if (old_progress != progress) Logger::ProgressBar(progress);
|
||||
old_progress = progress;
|
||||
}
|
||||
}
|
||||
} while (++num_created, context_iterator.next());
|
||||
|
||||
if (!no_progress && quiet) {
|
||||
for (; old_progress < 100; ++old_progress) {
|
||||
std::cout << ".";
|
||||
if (stderr_progress)
|
||||
std::cerr << ".";
|
||||
}
|
||||
std::cout << std::flush;
|
||||
if (stderr_progress)
|
||||
std::cerr << std::flush;
|
||||
} else {
|
||||
Logger::Status("\rDone creating geometry (" + boost::lexical_cast<std::string>(num_created) +
|
||||
" objects) ");
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
serializer->finalize();
|
||||
// Make sure the dtor is explicitly run here (e.g. output files are closed before renaming them).
|
||||
@@ -1068,3 +1452,118 @@ std::vector<IfcGeom::filter_t> setup_filters(const std::vector<geom_filter>& fil
|
||||
|
||||
return filter_funcs;
|
||||
}
|
||||
bool reuse_ok_(SerializerSettings settings, const IfcSchema::IfcProduct::list::ptr &products, IfcGeom::Kernel kernel)
|
||||
{
|
||||
// IfcGeom::Kernel kernel;
|
||||
|
||||
// With world coords enabled, object transformations are directly applied to
|
||||
// the BRep. There is no way to re-use the geometry for multiple products.
|
||||
if (settings.get(IfcGeom::IteratorSettings::USE_WORLD_COORDS))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::set<const IfcSchema::IfcMaterial *> associated_single_materials;
|
||||
|
||||
for (IfcSchema::IfcProduct::list::it it = products->begin(); it != products->end(); ++it)
|
||||
{
|
||||
IfcSchema::IfcProduct *product = *it;
|
||||
if (!settings.get(IfcGeom::IteratorSettings::DISABLE_OPENING_SUBTRACTIONS) &&
|
||||
kernel.find_openings(product)->size())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (settings.get(IfcGeom::IteratorSettings::APPLY_LAYERSETS))
|
||||
{
|
||||
IfcSchema::IfcRelAssociates::list::ptr associations = product->HasAssociations();
|
||||
for (IfcSchema::IfcRelAssociates::list::it jt = associations->begin();
|
||||
jt != associations->end(); ++jt)
|
||||
{
|
||||
IfcSchema::IfcRelAssociatesMaterial *assoc =
|
||||
(*jt)->as<IfcSchema::IfcRelAssociatesMaterial>();
|
||||
if (assoc)
|
||||
{
|
||||
if (assoc->RelatingMaterial()->is(IfcSchema::Type::IfcMaterialLayerSetUsage))
|
||||
{
|
||||
// TODO: Check whether single layer?
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Note that this can be a nullptr (!), but the fact that set size should be one still holds
|
||||
associated_single_materials.insert(kernel.get_single_material_association(product));
|
||||
if (associated_single_materials.size() > 1)
|
||||
return false;
|
||||
}
|
||||
return associated_single_materials.size() == 1;
|
||||
}
|
||||
|
||||
void create_element(SerializerSettings &settings, IfcproductRepresentation &rep)
|
||||
{
|
||||
Logger::Status("processing item #: " + std::to_string(rep.index));
|
||||
IfcGeom::Kernel kernel;
|
||||
IfcSchema::IfcRepresentation *representation= rep.representation;
|
||||
IfcSchema::IfcProduct *product = rep.product;
|
||||
// IfcGeom::BRepElement<real_t> *element;
|
||||
rep.element =
|
||||
kernel.create_brep_for_representation_and_product<real_t>(settings, representation, product);
|
||||
//if(geometry_reuse_ok_for_current_representation_)
|
||||
// {
|
||||
// // element = kernel.create_brep_for_processed_representation(settings, representation,
|
||||
// // product,
|
||||
// // current_shape_model);
|
||||
// }
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//@todo MOVE this include
|
||||
#include <gp_GTrsf.hxx>
|
||||
|
||||
Bounds compute_bounds(IfcParse::IfcFile* ifc_file, IfcGeom::Kernel kernel)
|
||||
{
|
||||
gp_XYZ bounds_min_;
|
||||
gp_XYZ bounds_max_;
|
||||
Bounds bounds;
|
||||
|
||||
for (int i = 1; i < 4; ++i) {
|
||||
bounds_min_.SetCoord(i, std::numeric_limits<double>::infinity());
|
||||
bounds_max_.SetCoord(i, -std::numeric_limits<double>::infinity());
|
||||
}
|
||||
|
||||
IfcSchema::IfcProduct::list::ptr products = ifc_file->entitiesByType<IfcSchema::IfcProduct>();
|
||||
for (IfcSchema::IfcProduct::list::it iter = products->begin(); iter != products->end(); ++iter) {
|
||||
IfcSchema::IfcProduct* product = *iter;
|
||||
if (product->hasObjectPlacement()) {
|
||||
// Use a fresh trsf every time in order to prevent the result to be concatenated
|
||||
gp_Trsf trsf;
|
||||
bool success = false;
|
||||
|
||||
try {
|
||||
success = kernel.convert(product->ObjectPlacement(), trsf);
|
||||
} catch (const std::exception& e) {
|
||||
Logger::Error(e);
|
||||
} catch (...) {
|
||||
Logger::Error("Failed to construct placement");
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const gp_XYZ& pos = trsf.TranslationPart();
|
||||
bounds_min_.SetX(std::min(bounds_min_.X(), pos.X()));
|
||||
bounds_min_.SetY(std::min(bounds_min_.Y(), pos.Y()));
|
||||
bounds_min_.SetZ(std::min(bounds_min_.Z(), pos.Z()));
|
||||
bounds_max_.SetX(std::max(bounds_max_.X(), pos.X()));
|
||||
bounds_max_.SetY(std::max(bounds_max_.Y(), pos.Y()));
|
||||
bounds_max_.SetZ(std::max(bounds_max_.Z(), pos.Z()));
|
||||
}
|
||||
}
|
||||
bounds.min = bounds_min_;
|
||||
bounds.max = bounds_max_;
|
||||
return bounds;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user