Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Selection representation context #1201

Open
wants to merge 4 commits into
base: v0.7.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
45 changes: 39 additions & 6 deletions src/ifcconvert/IfcConvert.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ struct geom_filter
{
geom_filter(bool include, bool traverse) : type(UNUSED), include(include), traverse(traverse) {}
geom_filter() : type(UNUSED), include(false), traverse(false) {}
enum filter_type { UNUSED, ENTITY_TYPE, LAYER_NAME, ENTITY_ARG };
enum filter_type { UNUSED, ENTITY_TYPE, LAYER_NAME, ENTITY_ARG};
filter_type type;
bool include;
bool traverse;
Expand All @@ -169,6 +169,8 @@ struct inclusion_filter : public geom_filter { inclusion_filter() : geom_filter(
struct inclusion_traverse_filter : public geom_filter { inclusion_traverse_filter() : geom_filter(true, true) {} };
struct exclusion_filter : public geom_filter { exclusion_filter() : geom_filter(false, false) {} };
struct exclusion_traverse_filter : public geom_filter { exclusion_traverse_filter() : geom_filter(false, true) {} };
//struct geometricRepresentationContext_filter : public geom_filter { geometricRepresentationContext_filter() : geom_filter(true, false) {} };
std::vector<std::string> include_geometricRepresentationContext_filter;

size_t read_filters_from_file(const std::string&, inclusion_filter&, inclusion_traverse_filter&, exclusion_filter&, exclusion_traverse_filter&);
void parse_filter(geom_filter &, const std::vector<std::string>&);
Expand All @@ -184,6 +186,20 @@ struct verbosity_counter {
}
};

bool initialize_iterator(IfcGeom::Iterator<real_t> &localIterator)
{
if (!include_geometricRepresentationContext_filter.empty())
{
std::set<std::string> tempSet;
tempSet.insert(include_geometricRepresentationContext_filter.begin(), include_geometricRepresentationContext_filter.end());
return localIterator.initialize(tempSet);
}
else
{
return localIterator.initialize();
}
}

#if defined(_MSC_VER) && defined(_UNICODE)
int wmain(int argc, wchar_t** argv) {
typedef po::wcommand_line_parser command_line_parser;
Expand Down Expand Up @@ -318,6 +334,10 @@ int main(int argc, char** argv) {
("exclude+", po::value<exclusion_traverse_filter>(&exclude_traverse_filter)->multitoken(),
"Same as --exclude but applies filtering also to the decomposition and/or containment "
"of the filtered entity. See --include+ for more details.")
("geometricRepresentationContext", po::value<std::vector<std::string>>(&include_geometricRepresentationContext_filter)->multitoken(),
"Select the IfcGeometricRepresentation(Sub)Contexts for the geometries, which shall be exported. "
"All selected constexts must be of type 'model'. Includes all subcontexts. "
"If empty, all contexts of type 'model' are used for export.")
("filter-file", new po::typed_value<path_t, char_t>(&filter_filename),
"Specifies a filter file that describes the used filtering criteria. Supported formats "
"are '--include=arg GlobalId ...' and 'include arg GlobalId ...'. Spaces and tabs can be used as delimiters."
Expand Down Expand Up @@ -859,11 +879,24 @@ int main(int argc, char** argv) {
time(&start);
if (!quiet) Logger::Status("Computing bounds...");

/*if (!tmp_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::Notice("No geometrical elements found or none succesfully converted");
serializer.reset();
IfcUtil::path::delete_file(IfcUtil::path::to_utf8(output_temp_filename));
write_log(!quiet);
return EXIT_FAILURE;
}*/

if (center_model_geometry) {
if (!tmp_context_iterator.initialize()) {
std::set<std::string> tempSet;
tempSet.insert(include_geometricRepresentationContext_filter.begin (), include_geometricRepresentationContext_filter.end());
if (!initialize_iterator(tmp_context_iterator)) {
/// @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::Notice("No geometrical elements found or none succesfully converted");
Logger::Notice("No geometrical elements found or none succesfully converted. "
"Check the Name of the geometric representation context");
serializer.reset();
IfcUtil::path::delete_file(IfcUtil::path::to_utf8(output_temp_filename));
write_log(!quiet);
Expand Down Expand Up @@ -895,7 +928,7 @@ int main(int argc, char** argv) {
}

IfcGeom::Iterator<real_t> context_iterator(settings, ifc_file, filter_funcs, num_threads);
if (!context_iterator.initialize()) {
if (!initialize_iterator(context_iterator)) {
/// @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::Notice("No geometrical elements found or none succesfully converted");
Expand Down Expand Up @@ -1271,7 +1304,7 @@ std::vector<IfcGeom::filter_t> setup_filters(const std::vector<geom_filter>& fil
attribute_filter.traverse = f.traverse;
attribute_filter.attribute_name = f.arg;
attribute_filter.populate(f.values);
}
}
}

// If no entity names are specified these are the defaults to skip from output
Expand Down Expand Up @@ -1395,7 +1428,7 @@ void fix_quantities(IfcParse::IfcFile& f, bool no_progress, bool quiet, bool std

IfcGeom::Iterator<double> context_iterator(settings, &f);

if (!context_iterator.initialize()) {
if (!initialize_iterator(context_iterator)) {
return;
}

Expand Down
45 changes: 35 additions & 10 deletions src/ifcgeom/IfcGeomIteratorImplementation.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ namespace IfcGeom {
std::vector<IfcGeom::BRepElement<P, PP>*> all_processed_native_elements_;
typename std::vector<IfcGeom::Element<P, PP>*>::const_iterator task_result_iterator_;
typename std::vector<IfcGeom::BRepElement<P, PP>*>::const_iterator native_task_result_iterator_;
std::set<std::string> allowed_context_identifiers;

MAKE_TYPE_NAME(IteratorImplementation_)(const MAKE_TYPE_NAME(IteratorImplementation_)&); // N/I
MAKE_TYPE_NAME(IteratorImplementation_)& operator=(const MAKE_TYPE_NAME(IteratorImplementation_)&); // N/I
Expand Down Expand Up @@ -248,6 +249,11 @@ namespace IfcGeom {

boost::optional<bool> initialization_outcome_;

bool initialize(std::set<std::string> allowed_context_ids) {
allowed_context_identifiers.insert(allowed_context_ids.begin(), allowed_context_ids.end());
return initialize();
}

bool initialize() {
if (initialization_outcome_) {
return *initialization_outcome_;
Expand Down Expand Up @@ -307,8 +313,14 @@ namespace IfcGeom {
if (allowed_context_types.find(context_type) == allowed_context_types.end()) {
Logger::Warning(std::string("ContextType '") + context->ContextType() + "' not allowed:", context);
}

if (context_types.find(context_type) != context_types.end()) {
filtered_contexts->push(context);
std::string context_name = context->ContextIdentifier();
if (allowed_context_identifiers.empty() //Additional filtering if user aims for special context
|| allowed_context_identifiers.find(context_name) != allowed_context_identifiers.end())
{
filtered_contexts->push(context);
}
}
}
} catch (const std::exception& e) {
Expand All @@ -330,19 +342,32 @@ namespace IfcGeom {
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;
std::string context_name = context->ContextIdentifier();
if (allowed_context_identifiers.empty() //Additional filtering if user aims for special context
|| allowed_context_identifiers.find(context_name) != allowed_context_identifiers.end())
{
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);
}
} catch (const std::exception& e) {
Logger::Error(e);
}


//Hier muss eingegriffen werden. Falls eine Liste mit erlaubten Kontexten �bergeben --> Filtern
IfcSchema::IfcGeometricRepresentationSubContext::list::ptr sub_contexts = context->HasSubContexts();
for (jt = sub_contexts->begin(); jt != sub_contexts->end(); ++jt) {
representations->push((*jt)->RepresentationsInContext());
std::string sub_context_name = (*jt)->ContextIdentifier();
if (allowed_context_identifiers.empty()
|| allowed_context_identifiers.find(context_name) != allowed_context_identifiers.end()
|| allowed_context_identifiers.find(sub_context_name) != allowed_context_identifiers.end())
{
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.
Expand Down
11 changes: 10 additions & 1 deletion src/ifcgeom_schema_agnostic/IfcGeomIterator.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
* orientation and translation of the mesh in relation to the world origin *
* *
* IfcGeom::Iterator::initialize() *
* finds the most suitable representation contexts. Returns true iff *
* finds the most suitable representation contexts. Returns true if *
* at least a single representation will process successfully *
* *
* IfcGeom::Iterator::get() *
Expand Down Expand Up @@ -116,6 +116,15 @@ namespace IfcGeom {
}
}

bool initialize(std::set<std::string> allowed_context_ids) {
if (implementation_) {
return implementation_->initialize(allowed_context_ids);
}
else {
return false;
}
}

int progress() const { return implementation_->progress(); }

void compute_bounds(bool with_geometry) { implementation_->compute_bounds(with_geometry); }
Expand Down
1 change: 1 addition & 0 deletions src/ifcgeom_schema_agnostic/IteratorImplementation.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ namespace IfcGeom {
class IteratorImplementation {
public:
virtual bool initialize() = 0;
virtual bool initialize(std::set<std::string> allowed_context_ids) = 0;
virtual void compute_bounds(bool with_geometry) = 0;
virtual const gp_XYZ& bounds_min() const = 0;
virtual const gp_XYZ& bounds_max() const = 0;
Expand Down
39 changes: 39 additions & 0 deletions src/ifcgeom_schema_agnostic/Kernel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -207,8 +207,26 @@ namespace {
}
return layers;
}

template <typename Schema>
static std::map<std::string, IfcUtil::IfcBaseEntity*> get_representationContext_impl(typename Schema::IfcProduct* prod) {
std::map<std::string, IfcUtil::IfcBaseEntity*> representationContexts;
if (prod->hasRepresentation()) {
IfcEntityList::ptr r = IfcParse::traverse(prod->Representation());
typename Schema::IfcRepresentation::list::ptr representations = r->as<typename Schema::IfcRepresentation>();
for (typename Schema::IfcRepresentation::list::it it = representations->begin(); it != representations->end(); ++it) {
typename Schema::IfcPresentationLayerAssignment::list::ptr a = (*it)->LayerAssignments();
for (typename Schema::IfcPresentationLayerAssignment::list::it jt = a->begin(); jt != a->end(); ++jt) {
representationContexts[(*jt)->Name()] = *jt;
}
}
}
return representationContexts;
}
}



std::map<std::string, IfcUtil::IfcBaseEntity*> IfcGeom::Kernel::get_layers(IfcUtil::IfcBaseEntity* inst) {
if (inst->as<Ifc2x3::IfcProduct>()) {
return get_layers_impl<Ifc2x3>(inst->as<Ifc2x3::IfcProduct>());
Expand All @@ -225,6 +243,27 @@ std::map<std::string, IfcUtil::IfcBaseEntity*> IfcGeom::Kernel::get_layers(IfcUt
}
}

std::map<std::string, IfcUtil::IfcBaseEntity*> IfcGeom::Kernel::get_representationContexts(IfcUtil::IfcBaseEntity* inst) {
if (inst->as<Ifc2x3::IfcProduct>()) {
return get_layers_impl<Ifc2x3>(inst->as<Ifc2x3::IfcProduct>());
}
else if (inst->as<Ifc4::IfcProduct>()) {
return get_layers_impl<Ifc4>(inst->as<Ifc4::IfcProduct>());
}
else if (inst->as<Ifc4x1::IfcProduct>()) {
return get_layers_impl<Ifc4x1>(inst->as<Ifc4x1::IfcProduct>());
}
else if (inst->as<Ifc4x2::IfcProduct>()) {
return get_layers_impl<Ifc4x2>(inst->as<Ifc4x2::IfcProduct>());
}
else if (inst->as<Ifc4x3_rc1::IfcProduct>()) {
return get_layers_impl<Ifc4x3_rc1>(inst->as<Ifc4x3_rc1::IfcProduct>());
}
else {
throw IfcParse::IfcException("Unexpected entity " + inst->declaration().name());
}
}

bool IfcGeom::Kernel::is_manifold(const TopoDS_Shape& a) {
if (a.ShapeType() == TopAbs_COMPOUND || a.ShapeType() == TopAbs_SOLID) {
TopoDS_Iterator it(a);
Expand Down
1 change: 1 addition & 0 deletions src/ifcgeom_schema_agnostic/Kernel.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ namespace IfcGeom {
static bool is_manifold(const TopoDS_Shape& a);
static IfcUtil::IfcBaseEntity* get_decomposing_entity(IfcUtil::IfcBaseEntity*, bool include_openings=true);
static std::map<std::string, IfcUtil::IfcBaseEntity*> get_layers(IfcUtil::IfcBaseEntity*);
static std::map<std::string, IfcUtil::IfcBaseEntity*> get_representationContexts(IfcUtil::IfcBaseEntity*);
};

namespace impl {
Expand Down
32 changes: 31 additions & 1 deletion win/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@ another batch file, and/or while the Visual Studio ("MSVC") environment variable
files that can also be invoked e.g. by double-clicking in the File Explorer. `.sh` files are for MSYS**2** + MinGW ("MSYS"
) compilation.

## Recommendations for building

To build IfcOpenShell, we recommend the following software:

- [Git](https://git-scm.com/downloads)
- [CMake 3.19](https://cmake.org/files/v3.19/)
- [Visual Studio 2017](https://my.visualstudio.com/Downloads?q=visual%20studio%202017&wt.mc_id=o~msft~vscom~older-downloads) with C++ Workload (see Visual Studio Installer)
- Windows Powershell (shipped with Windows 8 and newer)
- Windows SDK 10.0.18362 (See Visual Studio Installer)

Usage Instructions
------------------
### MSYS
Expand All @@ -18,7 +28,7 @@ of the shell scripts before using them. Note that contrary to MSVC, with MSYS al
built or used as static libraries. Currently Release build is used for all libraries.

### MSVC
Execute `build-deps.cmd` to fetch, build and install the dependencies. The batch file will print the requirements for
Use the `Developer Command prompt for Visual Studio 2017` to execute all mentioned commands. This command prompt comes together with Visual Studio and inherits all necessary environment variables. Execute `build-deps.cmd` to fetch, build and install the dependencies. The batch file will print the requirements for
a successful execution. The script allows a few user-configurable build options which are listed in the usage
instructions. Either edit the script file or set these values before running the script.

Expand All @@ -29,15 +39,29 @@ deduced from the MSVC environment variables. User-friendly VS generator shorthan
(`Build`, `Rebuild`, or `Clean`, defaults to `Build`) can be provided as `%3`. See `vs-cfg.cmd` if you wish to change
the defaults. The batch file will create `deps\` and `deps-vs<VERSION>-<ARCHITECTURE>-installed\` directories to the
project root. Debug and release builds of the dependencies can co-exist by simply running

```
> build-deps.cmd <GENERATOR> Debug
> build-deps.cmd <GENERATOR> <Release|RelWithDebInfo|MinSizeRel>
```

If you want to build IfcOpenShell 32 bit release with Visual Studio 2017 with MSVC use the following command line

```
> build-deps.cmd "Visual Studio 15 2017" Release
```

Use the next command line below if you need the 64 bit version

```
> build-deps.cmd "Visual Studio 15 2017 Win64" Release
```

After the dependencies are build, execute `run-cmake.bat`. The batch file expects a CMake generator as `%1` and the
rest of possible parameters are passed as is. If a generator is not provided, the generator is read from the
BuildDepsCache file, or tried to be deduced from the location of `cl.exe`. If passing build options for the script,
the generator must be always passed as the first option:

```
> run-cmake.bat vs2015-x64 -DUSE_IFC4=1 -DBUILD_IFCPYTHON=0
```
Expand All @@ -56,6 +80,12 @@ files expect `%1` and `%2` in same fashion as above and possible extra parameter
or regular Command Prompt if BuildDepsCache file exists (the last modified version is used). Running the scripts without extra
parameters reads the build options from an existing CMakeCache.txt.

You can use the command line below to Build the IfcOpenShell.

```
> build-ifcopenshell.bat "Visual Studio 15 2017 Win 64" Release
```

The project will be installed to `installed-vs<VERSION>-<ARCHITECTURE>\` folder in the project's root folder and the
required IfcOpenShell-Python parts are deployed to the `<PYTHONHOME>\Lib\site-packages\` folder. The 3ds Max plug-in,
`IfcMax.dli`, needs to be copied manually to the 3ds Max's `plugins` folder.
Expand Down