mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-16 10:34:31 +00:00
Merge remote-tracking branch 'origin/v0.8.0' into ifcviewer-wgpu
This commit is contained in:
@@ -17,6 +17,23 @@
|
||||
# #
|
||||
################################################################################
|
||||
|
||||
cmake_minimum_required(VERSION 3.21)
|
||||
|
||||
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
|
||||
project(IfcOpenShellPython LANGUAGES CXX)
|
||||
set(IFCOPENSHELL_IFCWRAP_STANDALONE ON)
|
||||
else()
|
||||
set(IFCOPENSHELL_IFCWRAP_STANDALONE OFF)
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED CMAKE_CXX_STANDARD)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
endif()
|
||||
if(CMAKE_CXX_STANDARD LESS 17)
|
||||
message(FATAL_ERROR "C++17 or newer is required.")
|
||||
endif()
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
if(POLICY CMP0148) # 3.27
|
||||
cmake_policy(SET CMP0148 OLD)
|
||||
endif()
|
||||
@@ -24,9 +41,38 @@ if(POLICY CMP0177) # 3.31
|
||||
cmake_policy(SET CMP0177 OLD)
|
||||
endif()
|
||||
|
||||
FIND_PACKAGE(SWIG)
|
||||
IF(NOT SWIG_FOUND)
|
||||
MESSAGE(
|
||||
set(_ifcwrap_feature_definitions "")
|
||||
if(IFCOPENSHELL_IFCWRAP_STANDALONE)
|
||||
get_filename_component(_ifcwrap_repo_root "${CMAKE_CURRENT_SOURCE_DIR}/../.." ABSOLUTE)
|
||||
list(PREPEND CMAKE_MODULE_PATH "${_ifcwrap_repo_root}/cmake")
|
||||
|
||||
find_package(IfcOpenShell REQUIRED)
|
||||
|
||||
set(WITH_OPENCASCADE "${IFCOPENSHELL_WITH_OPENCASCADE}")
|
||||
set(WITH_CGAL "${IFCOPENSHELL_WITH_CGAL}")
|
||||
set(SWIG_DEFINES "")
|
||||
|
||||
if(IFCOPENSHELL_WITH_OPENCASCADE)
|
||||
list(APPEND SWIG_DEFINES -DIFOPSH_WITH_OPENCASCADE)
|
||||
list(APPEND _ifcwrap_feature_definitions IFOPSH_WITH_OPENCASCADE)
|
||||
endif()
|
||||
if(IFCOPENSHELL_WITH_CGAL)
|
||||
list(APPEND SWIG_DEFINES -DIFOPSH_WITH_CGAL)
|
||||
list(APPEND _ifcwrap_feature_definitions IFOPSH_WITH_CGAL)
|
||||
endif()
|
||||
if(IFCOPENSHELL_IFCXML)
|
||||
list(APPEND SWIG_DEFINES -DWITH_IFCXML)
|
||||
list(APPEND _ifcwrap_feature_definitions WITH_IFCXML)
|
||||
endif()
|
||||
if(IFCOPENSHELL_WITH_ROCKSDB)
|
||||
list(APPEND SWIG_DEFINES -DIFOPSH_WITH_ROCKSDB)
|
||||
list(APPEND _ifcwrap_feature_definitions IFOPSH_WITH_ROCKSDB)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
find_package(SWIG)
|
||||
if(NOT SWIG_FOUND)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"BUILD_IFCPYTHON enabled, but unable to find SWIG. Disable BUILD_IFCPYTHON or fix SWIG paths to proceed. "
|
||||
"Likely SWIG_EXECUTABLE is missing (current value - '${SWIG_EXECUTABLE}')."
|
||||
@@ -64,7 +110,19 @@ INCLUDE_DIRECTORIES(BEFORE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
SET(CMAKE_SWIG_FLAGS ${SWIG_DEFINES})
|
||||
|
||||
SET_SOURCE_FILES_PROPERTIES(IfcPython.i PROPERTIES CPLUSPLUS ON)
|
||||
if(WITH_CGAL)
|
||||
if(IFCOPENSHELL_IFCWRAP_STANDALONE)
|
||||
if(TARGET IfcOpenShell::svgfill)
|
||||
set(LIBSVGFILL IfcOpenShell::svgfill)
|
||||
else()
|
||||
message(FATAL_ERROR "IfcOpenShell was built with CGAL, but the exported svgfill target was not found.")
|
||||
endif()
|
||||
else()
|
||||
set(LIBSVGFILL svgfill)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set_source_files_properties(IfcPython.i PROPERTIES CPLUSPLUS ON)
|
||||
# Rebuild on changes in other .i files.
|
||||
SET_PROPERTY(
|
||||
SOURCE IfcPython.i
|
||||
@@ -122,8 +180,23 @@ endif()
|
||||
if(WITH_ROCKSDB)
|
||||
target_link_libraries(ifcopenshell_wrapper PRIVATE document_serializer_rdb)
|
||||
endif()
|
||||
SET_PROPERTY(TARGET ifcopenshell_wrapper PROPERTY SWIG_DEPENDS ${IFCOPENSHELL_LIBRARIES})
|
||||
if (WASM_BUILD)
|
||||
|
||||
if(_ifcwrap_feature_definitions)
|
||||
target_compile_definitions(ifcopenshell_wrapper PRIVATE ${_ifcwrap_feature_definitions})
|
||||
endif()
|
||||
if(IFCOPENSHELL_IFCWRAP_STANDALONE)
|
||||
set(_ifcwrap_ifcopenshell_libraries ${IFCOPENSHELL_LIBRARIES})
|
||||
set(_ifcwrap_geometry_libraries ${IFCOPENSHELL_GEOMETRY_LIBRARIES})
|
||||
set(_ifcwrap_cgal_libraries "")
|
||||
set(_ifcwrap_swig_depends "")
|
||||
else()
|
||||
set(_ifcwrap_ifcopenshell_libraries ${IFCOPENSHELL_LIBRARIES})
|
||||
set(_ifcwrap_geometry_libraries IfcGeom ${kernel_libraries})
|
||||
set(_ifcwrap_cgal_libraries ${CGAL_LIBRARIES})
|
||||
set(_ifcwrap_swig_depends ${IFCOPENSHELL_LIBRARIES})
|
||||
endif()
|
||||
set_property(TARGET ifcopenshell_wrapper PROPERTY SWIG_DEPENDS ${_ifcwrap_swig_depends})
|
||||
if(WASM_BUILD)
|
||||
# SIDE_MODULE=1 - add to .so all symbols from linked archives (default used by pyodide).
|
||||
# Since currently libIfcGeom.a seems to be linked twice it results in duplicated symbols and compilation errors.
|
||||
# Possibly in the future we can clean up linked libs and try `=1`.
|
||||
@@ -147,7 +220,7 @@ target_link_libraries(ifcopenshell_wrapper PRIVATE IfcGeom IfcParse ${Boost_LIBR
|
||||
if(schema_libraries OR kernel_libraries OR tree_libraries OR mapping_libraries OR geometry_serializer_libraries OR document_serializer_libraries OR linework_processing_libraries)
|
||||
add_dependencies(ifcopenshell_wrapper ${schema_libraries} ${kernel_libraries} ${tree_libraries} ${mapping_libraries} ${geometry_serializer_libraries} ${document_serializer_libraries} ${linework_processing_libraries})
|
||||
endif()
|
||||
if(NOT WIN32)
|
||||
if((NOT WIN32) AND BUILD_SHARED_LIBS AND COMMAND SET_INSTALL_RPATHS)
|
||||
SET_INSTALL_RPATHS(ifcopenshell_wrapper "${IFCDIRS};${OCC_LIBRARY_DIR}")
|
||||
endif()
|
||||
|
||||
@@ -194,8 +267,17 @@ IF(Python_Interpreter_FOUND OR PYTHON_MODULE_INSTALL_DIR)
|
||||
MESSAGE(WARNING "Unable to locate Python site-package directory, unable to install the Python wrapper")
|
||||
ELSE()
|
||||
message(STATUS "Python wrapper will be installed to '${python_package_dir}'.")
|
||||
FILE(GLOB_RECURSE sourcefiles
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../ifcopenshell-python/ifcopenshell/*"
|
||||
file(GLOB_RECURSE sourcefiles "${CMAKE_CURRENT_SOURCE_DIR}/../ifcopenshell-python/ifcopenshell/*")
|
||||
foreach(file ${sourcefiles})
|
||||
file(RELATIVE_PATH relative "${CMAKE_CURRENT_SOURCE_DIR}/../ifcopenshell-python/ifcopenshell/" "${file}")
|
||||
get_filename_component(dir "${relative}" DIRECTORY)
|
||||
if(NOT IS_DIRECTORY "${file}")
|
||||
install(FILES "${file}" DESTINATION "${python_package_dir}/ifcopenshell/${dir}")
|
||||
endif()
|
||||
endforeach()
|
||||
install(
|
||||
FILES "${CMAKE_CURRENT_BINARY_DIR}/ifcopenshell_wrapper.py"
|
||||
DESTINATION "${python_package_dir}/ifcopenshell"
|
||||
)
|
||||
FOREACH(file ${sourcefiles})
|
||||
FILE(RELATIVE_PATH relative "${CMAKE_CURRENT_SOURCE_DIR}/../ifcopenshell-python/ifcopenshell/" "${file}")
|
||||
|
||||
+305
-217
@@ -81,16 +81,9 @@
|
||||
%newobject IfcGeom::ConversionResultShape::moved;
|
||||
%newobject IfcGeom::ConversionResultShape::wrap_in_compound;
|
||||
|
||||
%newobject IfcGeom::ConversionResultShape::area;
|
||||
%newobject IfcGeom::ConversionResultShape::volume;
|
||||
%newobject IfcGeom::ConversionResultShape::length;
|
||||
|
||||
%newobject nary_union;
|
||||
|
||||
%newobject IfcGeom::OpaqueNumber::operator+;
|
||||
%newobject IfcGeom::OpaqueNumber::operator-;
|
||||
%newobject IfcGeom::OpaqueNumber::operator*;
|
||||
%newobject IfcGeom::OpaqueNumber::operator/;
|
||||
|
||||
%inline %{
|
||||
template <typename T>
|
||||
@@ -260,149 +253,149 @@ namespace {
|
||||
%include "../ifcgeom/ConversionSettings.h"
|
||||
%include "../ifcgeom/IfcGeomElement.h"
|
||||
%include "../ifcgeom/IfcGeomRepresentation.h"
|
||||
%include "../ifcgeom/Iterator.h"
|
||||
%include "../ifcgeom/GeometrySerializer.h"
|
||||
%include "../ifcgeom/taxonomy.h"
|
||||
%include "../ifcgeom/function_item_evaluator.h"
|
||||
|
||||
%{
|
||||
#include "../serializers/geometry_serializer_plugin.h"
|
||||
|
||||
class PythonPluginGeometrySerializer : public GeometrySerializer {
|
||||
public:
|
||||
PythonPluginGeometrySerializer(
|
||||
const std::string& extension,
|
||||
const std::string& output_filename,
|
||||
const std::string& output_temp_filename,
|
||||
ifcopenshell::geometry::Settings& geometry_settings,
|
||||
const ifcopenshell::geometry::SerializerSettings& serializer_settings
|
||||
)
|
||||
: GeometrySerializer(geometry_settings, serializer_settings)
|
||||
{
|
||||
ifcopenshell::serializers::geometry_serializer_context context{
|
||||
output_filename,
|
||||
output_temp_filename.empty() ? output_filename : output_temp_filename,
|
||||
geometry_settings,
|
||||
serializer_settings
|
||||
};
|
||||
|
||||
initialize_serializer(extension, context);
|
||||
}
|
||||
|
||||
PythonPluginGeometrySerializer(
|
||||
const std::string& extension,
|
||||
const stream_or_filename& output_filename,
|
||||
const stream_or_filename& output_temp_filename,
|
||||
ifcopenshell::geometry::Settings& geometry_settings,
|
||||
const ifcopenshell::geometry::SerializerSettings& serializer_settings
|
||||
)
|
||||
: GeometrySerializer(geometry_settings, serializer_settings)
|
||||
{
|
||||
const auto output_filename_string = output_filename.filename().value_or("");
|
||||
const auto output_temp_filename_string = output_temp_filename.filename().value_or(output_filename_string);
|
||||
ifcopenshell::serializers::geometry_serializer_context context{
|
||||
output_filename_string,
|
||||
output_temp_filename_string,
|
||||
geometry_settings,
|
||||
serializer_settings,
|
||||
&output_filename,
|
||||
&output_temp_filename
|
||||
};
|
||||
|
||||
initialize_serializer(extension, context);
|
||||
}
|
||||
|
||||
private:
|
||||
void initialize_serializer(
|
||||
const std::string& extension,
|
||||
ifcopenshell::serializers::geometry_serializer_context& context
|
||||
) {
|
||||
auto& registry = ifcopenshell::serializers::geometry_serializer_registry_instance();
|
||||
registry.configure(extension, context);
|
||||
geometry_settings_ = context.geometry_settings;
|
||||
serializer_ = registry.create(extension, context);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
bool ready() override {
|
||||
return serializer_->ready();
|
||||
}
|
||||
|
||||
bool is_streaming() const override {
|
||||
return serializer_->is_streaming();
|
||||
}
|
||||
|
||||
void writeHeader() override {
|
||||
serializer_->writeHeader();
|
||||
}
|
||||
|
||||
void finalize() override {
|
||||
serializer_->finalize();
|
||||
}
|
||||
|
||||
void setFile(ifcopenshell::file* file) override {
|
||||
serializer_->setFile(file);
|
||||
}
|
||||
|
||||
bool isTesselated() const override {
|
||||
return serializer_->isTesselated();
|
||||
}
|
||||
|
||||
void write(const IfcGeom::TriangulationElement* element) override {
|
||||
serializer_->write(element);
|
||||
}
|
||||
|
||||
void write(const IfcGeom::BRepElement* element) override {
|
||||
serializer_->write(element);
|
||||
}
|
||||
|
||||
void setUnitNameAndMagnitude(const std::string& name, float magnitude) override {
|
||||
serializer_->setUnitNameAndMagnitude(name, magnitude);
|
||||
}
|
||||
|
||||
IfcGeom::Element* read(
|
||||
ifcopenshell::file& file,
|
||||
const std::string& guid,
|
||||
const std::string& representation_id,
|
||||
read_type rt = READ_BREP
|
||||
) override {
|
||||
return serializer_->read(file, guid, representation_id, rt);
|
||||
}
|
||||
|
||||
std::string object_id(const IfcGeom::Element* element) override {
|
||||
return serializer_->object_id(element);
|
||||
}
|
||||
|
||||
private:
|
||||
boost::shared_ptr<GeometrySerializer> serializer_;
|
||||
};
|
||||
%}
|
||||
|
||||
%extend GeometrySerializer {
|
||||
bool ready() {
|
||||
return $self->ready();
|
||||
}
|
||||
|
||||
bool is_streaming() const {
|
||||
return $self->is_streaming();
|
||||
}
|
||||
|
||||
void writeHeader() {
|
||||
$self->writeHeader();
|
||||
}
|
||||
|
||||
void finalize() {
|
||||
$self->finalize();
|
||||
}
|
||||
|
||||
void setFile(ifcopenshell::file* file) {
|
||||
$self->setFile(file);
|
||||
}
|
||||
}
|
||||
|
||||
%extend ifcopenshell::geometry::taxonomy::style {
|
||||
size_t instance_id() const {
|
||||
%include "../ifcgeom/Iterator.h"
|
||||
%include "../ifcgeom/GeometrySerializer.h"
|
||||
%include "../ifcgeom/taxonomy.h"
|
||||
%include "../ifcgeom/function_item_evaluator.h"
|
||||
|
||||
%{
|
||||
#include "../serializers/geometry_serializer_plugin.h"
|
||||
|
||||
class PythonPluginGeometrySerializer : public GeometrySerializer {
|
||||
public:
|
||||
PythonPluginGeometrySerializer(
|
||||
const std::string& extension,
|
||||
const std::string& output_filename,
|
||||
const std::string& output_temp_filename,
|
||||
ifcopenshell::geometry::Settings& geometry_settings,
|
||||
const ifcopenshell::geometry::SerializerSettings& serializer_settings
|
||||
)
|
||||
: GeometrySerializer(geometry_settings, serializer_settings)
|
||||
{
|
||||
ifcopenshell::serializers::geometry_serializer_context context{
|
||||
output_filename,
|
||||
output_temp_filename.empty() ? output_filename : output_temp_filename,
|
||||
geometry_settings,
|
||||
serializer_settings
|
||||
};
|
||||
|
||||
initialize_serializer(extension, context);
|
||||
}
|
||||
|
||||
PythonPluginGeometrySerializer(
|
||||
const std::string& extension,
|
||||
const stream_or_filename& output_filename,
|
||||
const stream_or_filename& output_temp_filename,
|
||||
ifcopenshell::geometry::Settings& geometry_settings,
|
||||
const ifcopenshell::geometry::SerializerSettings& serializer_settings
|
||||
)
|
||||
: GeometrySerializer(geometry_settings, serializer_settings)
|
||||
{
|
||||
const auto output_filename_string = output_filename.filename().value_or("");
|
||||
const auto output_temp_filename_string = output_temp_filename.filename().value_or(output_filename_string);
|
||||
ifcopenshell::serializers::geometry_serializer_context context{
|
||||
output_filename_string,
|
||||
output_temp_filename_string,
|
||||
geometry_settings,
|
||||
serializer_settings,
|
||||
&output_filename,
|
||||
&output_temp_filename
|
||||
};
|
||||
|
||||
initialize_serializer(extension, context);
|
||||
}
|
||||
|
||||
private:
|
||||
void initialize_serializer(
|
||||
const std::string& extension,
|
||||
ifcopenshell::serializers::geometry_serializer_context& context
|
||||
) {
|
||||
auto& registry = ifcopenshell::serializers::geometry_serializer_registry_instance();
|
||||
registry.configure(extension, context);
|
||||
geometry_settings_ = context.geometry_settings;
|
||||
serializer_ = registry.create(extension, context);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
bool ready() override {
|
||||
return serializer_->ready();
|
||||
}
|
||||
|
||||
bool is_streaming() const override {
|
||||
return serializer_->is_streaming();
|
||||
}
|
||||
|
||||
void writeHeader() override {
|
||||
serializer_->writeHeader();
|
||||
}
|
||||
|
||||
void finalize() override {
|
||||
serializer_->finalize();
|
||||
}
|
||||
|
||||
void setFile(ifcopenshell::file* file) override {
|
||||
serializer_->setFile(file);
|
||||
}
|
||||
|
||||
bool isTesselated() const override {
|
||||
return serializer_->isTesselated();
|
||||
}
|
||||
|
||||
void write(const IfcGeom::TriangulationElement* element) override {
|
||||
serializer_->write(element);
|
||||
}
|
||||
|
||||
void write(const IfcGeom::BRepElement* element) override {
|
||||
serializer_->write(element);
|
||||
}
|
||||
|
||||
void setUnitNameAndMagnitude(const std::string& name, float magnitude) override {
|
||||
serializer_->setUnitNameAndMagnitude(name, magnitude);
|
||||
}
|
||||
|
||||
IfcGeom::Element* read(
|
||||
ifcopenshell::file& file,
|
||||
const std::string& guid,
|
||||
const std::string& representation_id,
|
||||
read_type rt = READ_BREP
|
||||
) override {
|
||||
return serializer_->read(file, guid, representation_id, rt);
|
||||
}
|
||||
|
||||
std::string object_id(const IfcGeom::Element* element) override {
|
||||
return serializer_->object_id(element);
|
||||
}
|
||||
|
||||
private:
|
||||
boost::shared_ptr<GeometrySerializer> serializer_;
|
||||
};
|
||||
%}
|
||||
|
||||
%extend GeometrySerializer {
|
||||
bool ready() {
|
||||
return $self->ready();
|
||||
}
|
||||
|
||||
bool is_streaming() const {
|
||||
return $self->is_streaming();
|
||||
}
|
||||
|
||||
void writeHeader() {
|
||||
$self->writeHeader();
|
||||
}
|
||||
|
||||
void finalize() {
|
||||
$self->finalize();
|
||||
}
|
||||
|
||||
void setFile(ifcopenshell::file* file) {
|
||||
$self->setFile(file);
|
||||
}
|
||||
}
|
||||
|
||||
%extend ifcopenshell::geometry::taxonomy::style {
|
||||
size_t instance_id() const {
|
||||
if (!self->instance) {
|
||||
return 0;
|
||||
}
|
||||
@@ -515,16 +508,16 @@ assign_matrix_access(revolve);
|
||||
void set_(const std::string& name, const std::set<int>& val) {
|
||||
return $self->set(name, val);
|
||||
}
|
||||
void set_(const std::string& name, const std::vector<double>& val) {
|
||||
return $self->set(name, val);
|
||||
}
|
||||
void set_(const std::string& name, const std::vector<std::string>& val) {
|
||||
// Python sequences cannot distinguish std::vector<std::string> from std::set<std::string>.
|
||||
if ($self->get_type(name) == "std::set<std::string>") {
|
||||
return $self->set(name, std::set<std::string>(val.begin(), val.end()));
|
||||
}
|
||||
return $self->set(name, val);
|
||||
}
|
||||
void set_(const std::string& name, const std::vector<double>& val) {
|
||||
return $self->set(name, val);
|
||||
}
|
||||
void set_(const std::string& name, const std::vector<std::string>& val) {
|
||||
// Python sequences cannot distinguish std::vector<std::string> from std::set<std::string>.
|
||||
if ($self->get_type(name) == "std::set<std::string>") {
|
||||
return $self->set(name, std::set<std::string>(val.begin(), val.end()));
|
||||
}
|
||||
return $self->set(name, val);
|
||||
}
|
||||
ifcopenshell::geometry::Settings::value_variant_t get_(const std::string& name) {
|
||||
return $self->get(name);
|
||||
}
|
||||
@@ -671,70 +664,76 @@ struct ShapeRTTI : public boost::static_visitor<PyObject*>
|
||||
$result = std::visit(ShapeRTTI(), (std::variant<IfcGeom::Element*, IfcGeom::Representation::Representation*, IfcGeom::Transformation*>) $1);
|
||||
}
|
||||
|
||||
%newobject construct_iterator;
|
||||
%newobject construct_iterator_with_include_exclude;
|
||||
%newobject construct_iterator_with_include_exclude_globalid;
|
||||
%newobject construct_iterator_with_include_exclude_id;
|
||||
%newobject create_geometry_serializer;
|
||||
|
||||
// I couldn't get the vector<string> typemap to be applied when %extending Iterator constructor.
|
||||
// anyway it does not matter as SWIG generates C code without actual constructors
|
||||
%inline %{
|
||||
GeometrySerializer* create_geometry_serializer(
|
||||
const std::string& extension,
|
||||
const std::string& output_filename,
|
||||
const std::string& output_temp_filename,
|
||||
ifcopenshell::geometry::Settings& geometry_settings,
|
||||
const ifcopenshell::geometry::SerializerSettings& serializer_settings
|
||||
) {
|
||||
return new PythonPluginGeometrySerializer(
|
||||
extension,
|
||||
output_filename,
|
||||
output_temp_filename,
|
||||
geometry_settings,
|
||||
serializer_settings
|
||||
);
|
||||
}
|
||||
|
||||
GeometrySerializer* create_geometry_serializer(
|
||||
const std::string& extension,
|
||||
const stream_or_filename& output_filename,
|
||||
const stream_or_filename& output_temp_filename,
|
||||
ifcopenshell::geometry::Settings& geometry_settings,
|
||||
const ifcopenshell::geometry::SerializerSettings& serializer_settings
|
||||
) {
|
||||
return new PythonPluginGeometrySerializer(
|
||||
extension,
|
||||
output_filename,
|
||||
output_temp_filename,
|
||||
geometry_settings,
|
||||
serializer_settings
|
||||
);
|
||||
}
|
||||
|
||||
IfcGeom::Iterator* construct_iterator(const std::string& geometry_library, ifcopenshell::geometry::Settings settings, ifcopenshell::file* file, int num_threads) {
|
||||
return new IfcGeom::Iterator(ifcopenshell::geometry::kernels::construct(file, geometry_library, settings), settings, file, num_threads);
|
||||
}
|
||||
%newobject construct_iterator;
|
||||
%newobject construct_iterator_with_include_exclude;
|
||||
%newobject construct_iterator_with_include_exclude_globalid;
|
||||
%newobject construct_iterator_with_include_exclude_id;
|
||||
%newobject create_geometry_serializer;
|
||||
|
||||
IfcGeom::Iterator* construct_iterator_with_include_exclude(const std::string& geometry_library, ifcopenshell::geometry::Settings settings, ifcopenshell::file* file, std::vector<std::string> elems, bool include, int num_threads) {
|
||||
std::set<std::string> elems_set(elems.begin(), elems.end());
|
||||
IfcGeom::entity_filter ef{ include, false, elems_set };
|
||||
return new IfcGeom::Iterator(ifcopenshell::geometry::kernels::construct(file, geometry_library, settings), settings, file, {ef}, num_threads);
|
||||
// I couldn't get the vector<string> typemap to be applied when %extending Iterator constructor.
|
||||
// anyway it does not matter as SWIG generates C code without actual constructors
|
||||
%inline %{
|
||||
GeometrySerializer* create_geometry_serializer(
|
||||
const std::string& extension,
|
||||
const std::string& output_filename,
|
||||
const std::string& output_temp_filename,
|
||||
ifcopenshell::geometry::Settings& geometry_settings,
|
||||
const ifcopenshell::geometry::SerializerSettings& serializer_settings
|
||||
) {
|
||||
return new PythonPluginGeometrySerializer(
|
||||
extension,
|
||||
output_filename,
|
||||
output_temp_filename,
|
||||
geometry_settings,
|
||||
serializer_settings
|
||||
);
|
||||
}
|
||||
|
||||
IfcGeom::Iterator* construct_iterator_with_include_exclude_globalid(const std::string& geometry_library, ifcopenshell::geometry::Settings settings, ifcopenshell::file* file, std::vector<std::string> elems, bool include, int num_threads) {
|
||||
GeometrySerializer* create_geometry_serializer(
|
||||
const std::string& extension,
|
||||
const stream_or_filename& output_filename,
|
||||
const stream_or_filename& output_temp_filename,
|
||||
ifcopenshell::geometry::Settings& geometry_settings,
|
||||
const ifcopenshell::geometry::SerializerSettings& serializer_settings
|
||||
) {
|
||||
return new PythonPluginGeometrySerializer(
|
||||
extension,
|
||||
output_filename,
|
||||
output_temp_filename,
|
||||
geometry_settings,
|
||||
serializer_settings
|
||||
);
|
||||
}
|
||||
|
||||
IfcGeom::Iterator* construct_iterator(const std::string& geometry_library, ifcopenshell::geometry::Settings settings, ifcopenshell::file* file, int num_threads) {
|
||||
return new IfcGeom::Iterator(ifcopenshell::geometry::kernels::construct(file, geometry_library, settings), settings, file, num_threads);
|
||||
}
|
||||
|
||||
// I couldn't get the vector<string> typemap to be applied when %extending Iterator constructor.
|
||||
// anyway it does not matter as SWIG generates C code without actual constructors
|
||||
IfcGeom::Iterator* construct_iterator(const std::string& geometry_library, ifcopenshell::geometry::Settings settings, ifcopenshell::file* file, int num_threads, Logger& logger = Logger::Root()) {
|
||||
return new IfcGeom::Iterator(ifcopenshell::geometry::kernels::construct(file, geometry_library, settings, logger), settings, file, num_threads, logger);
|
||||
}
|
||||
|
||||
IfcGeom::Iterator* construct_iterator_with_include_exclude(const std::string& geometry_library, ifcopenshell::geometry::Settings settings, ifcopenshell::file* file, std::vector<std::string> elems, bool include, int num_threads, Logger& logger = Logger::Root()) {
|
||||
std::set<std::string> elems_set(elems.begin(), elems.end());
|
||||
IfcGeom::entity_filter ef{ include, false, elems_set };
|
||||
return new IfcGeom::Iterator(ifcopenshell::geometry::kernels::construct(file, geometry_library, settings, logger), settings, file, {ef}, num_threads, logger);
|
||||
}
|
||||
|
||||
IfcGeom::Iterator* construct_iterator_with_include_exclude_globalid(const std::string& geometry_library, ifcopenshell::geometry::Settings settings, ifcopenshell::file* file, std::vector<std::string> elems, bool include, int num_threads, Logger& logger = Logger::Root()) {
|
||||
std::set<std::string> elems_set(elems.begin(), elems.end());
|
||||
IfcGeom::attribute_filter af;
|
||||
af.attribute_name = "GlobalId";
|
||||
af.populate(elems_set);
|
||||
af.include = include;
|
||||
return new IfcGeom::Iterator(ifcopenshell::geometry::kernels::construct(file, geometry_library, settings), settings, file, {af}, num_threads);
|
||||
return new IfcGeom::Iterator(ifcopenshell::geometry::kernels::construct(file, geometry_library, settings, logger), settings, file, {af}, num_threads, logger);
|
||||
}
|
||||
|
||||
IfcGeom::Iterator* construct_iterator_with_include_exclude_id(const std::string& geometry_library, ifcopenshell::geometry::Settings settings, ifcopenshell::file* file, std::vector<int> elems, bool include, int num_threads) {
|
||||
IfcGeom::Iterator* construct_iterator_with_include_exclude_id(const std::string& geometry_library, ifcopenshell::geometry::Settings settings, ifcopenshell::file* file, std::vector<int> elems, bool include, int num_threads, Logger& logger = Logger::Root()) {
|
||||
std::set<int> elems_set(elems.begin(), elems.end());
|
||||
IfcGeom::instance_id_filter af(include, false, elems_set);
|
||||
return new IfcGeom::Iterator(ifcopenshell::geometry::kernels::construct(file, geometry_library, settings), settings, file, {af}, num_threads);
|
||||
return new IfcGeom::Iterator(ifcopenshell::geometry::kernels::construct(file, geometry_library, settings, logger), settings, file, {af}, num_threads, logger);
|
||||
}
|
||||
%}
|
||||
|
||||
@@ -956,7 +955,7 @@ struct ShapeRTTI : public boost::static_visitor<PyObject*>
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
static std::variant<IfcGeom::Element*, IfcGeom::Representation::Representation*, IfcGeom::Transformation*> helper_fn_create_shape(const std::string& geometry_library, ifcopenshell::geometry::Settings& st, const express::Base& instance, const express::Base& representation = express::Base()) {
|
||||
static std::variant<IfcGeom::Element*, IfcGeom::Representation::Representation*, IfcGeom::Transformation*> helper_fn_create_shape(Logger& logger, const std::string& geometry_library, ifcopenshell::geometry::Settings& st, const express::Base& instance, const express::Base& representation = express::Base()) {
|
||||
ifcopenshell::file* file = instance.file();
|
||||
|
||||
ifcopenshell::geometry::Converter kernel(ifcopenshell::geometry::kernels::construct(file, geometry_library, st), file, st);
|
||||
@@ -1070,12 +1069,12 @@ ifcopenshell::geometry::taxonomy::item::ptr try_upcast(PyObject* obj0, swig_type
|
||||
%}
|
||||
|
||||
%inline %{
|
||||
static std::variant<IfcGeom::Element*, IfcGeom::Representation::Representation*, IfcGeom::Transformation*> create_shape(ifcopenshell::geometry::Settings& settings, const express::Base& instance, const express::Base& representation, const char* const geometry_library="opencascade") {
|
||||
static std::variant<IfcGeom::Element*, IfcGeom::Representation::Representation*, IfcGeom::Transformation*> create_shape(ifcopenshell::geometry::Settings& settings, const express::Base& instance, const express::Base& representation, const char* const geometry_library="opencascade", Logger& logger = Logger::Root()) {
|
||||
return helper_fn_create_shape(geometry_library, settings, instance, representation);
|
||||
}
|
||||
|
||||
// Manual definition of overload without representation argument
|
||||
static std::variant<IfcGeom::Element*, IfcGeom::Representation::Representation*, IfcGeom::Transformation*> create_shape(ifcopenshell::geometry::Settings& settings, const express::Base& instance, const char* const geometry_library="opencascade") {
|
||||
static std::variant<IfcGeom::Element*, IfcGeom::Representation::Representation*, IfcGeom::Transformation*> create_shape(ifcopenshell::geometry::Settings& settings, const express::Base& instance, const char* const geometry_library="opencascade", Logger& logger = Logger::Root()) {
|
||||
return create_shape(settings, instance, express::Base(), geometry_library);
|
||||
}
|
||||
%}
|
||||
@@ -1209,6 +1208,95 @@ ifcopenshell::geometry::taxonomy::item::ptr try_upcast(PyObject* obj0, swig_type
|
||||
%template(svg_loop) std::vector<std::array<double, 2>>;
|
||||
%template(svg_loops) std::vector<std::vector<std::array<double, 2>>>;
|
||||
|
||||
%extend IfcGeom::OpaqueCoordinate {
|
||||
%pythoncode %{
|
||||
__len__ = size
|
||||
def __iter__(self):
|
||||
yield from (self.get(i) for i in range(len(self)))
|
||||
%}
|
||||
}
|
||||
|
||||
%extend IfcGeom::OpaqueNumber {
|
||||
%pythoncode %{
|
||||
__abs__ = abs
|
||||
%}
|
||||
}
|
||||
|
||||
%template(OpaqueCoordinate_3) IfcGeom::OpaqueCoordinate<3>;
|
||||
%template(OpaqueCoordinate_4) IfcGeom::OpaqueCoordinate<4>;
|
||||
|
||||
%inline %{
|
||||
IfcGeom::OpaqueNumber create_epeck(int i) {
|
||||
return ifcopenshell::geometry::NumberEpeck(i);
|
||||
}
|
||||
IfcGeom::OpaqueNumber create_epeck(double d) {
|
||||
return ifcopenshell::geometry::NumberEpeck(d);
|
||||
}
|
||||
IfcGeom::OpaqueNumber create_epeck(const std::string& s) {
|
||||
return ifcopenshell::geometry::NumberEpeck(typename CGAL::Epeck::FT::ET(s));
|
||||
}
|
||||
%}
|
||||
|
||||
%inline %{
|
||||
IfcGeom::ConversionResultShape* nary_union(PyObject* sequence) {
|
||||
std::vector<const CGAL::Nef_polyhedron_3<CGAL::Epeck>*> nefs;
|
||||
for(Py_ssize_t i = 0; i < PySequence_Size(sequence); ++i) {
|
||||
PyObject* element = PySequence_GetItem(sequence, i);
|
||||
void* argp1 = nullptr;
|
||||
auto res1 = SWIG_ConvertPtr(element, &argp1, SWIGTYPE_p_IfcGeom__ConversionResultShape, 0);
|
||||
if (SWIG_IsOK(res1)) {
|
||||
auto arg1 = reinterpret_cast<IfcGeom::ConversionResultShape*>(argp1);
|
||||
auto cgs = dynamic_cast<ifcopenshell::geometry::CgalShape*>(arg1);
|
||||
if (cgs) {
|
||||
nefs.push_back(&cgs->nef());
|
||||
}
|
||||
}
|
||||
}
|
||||
ifcopenshell::geometry::CgalShape* shp;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
CGAL::Nef_nary_union_3< CGAL::Nef_polyhedron_3<CGAL::Epeck> > accum;
|
||||
for (auto& n : nefs) {
|
||||
accum.add_polyhedron(*n);
|
||||
}
|
||||
shp = new ifcopenshell::geometry::CgalShape(accum.get_union());
|
||||
Py_END_ALLOW_THREADS;
|
||||
return shp;
|
||||
}
|
||||
%}
|
||||
|
||||
%extend IfcGeom::ConversionResultShape {
|
||||
std::string serialize_obj() {
|
||||
std::ostringstream result;
|
||||
auto cgs = dynamic_cast<ifcopenshell::geometry::CgalShape*>($self);
|
||||
if (cgs) {
|
||||
write_to_obj(cgs->nef(), result, std::numeric_limits<size_t>::max());
|
||||
}
|
||||
return result.str();
|
||||
}
|
||||
|
||||
void convex_tag(bool b) {
|
||||
auto cgs = dynamic_cast<ifcopenshell::geometry::CgalShape*>($self);
|
||||
if (cgs) {
|
||||
cgs->convex_tag() = b;
|
||||
}
|
||||
}
|
||||
|
||||
std::string serialize() {
|
||||
std::string result;
|
||||
ifcopenshell::geometry::taxonomy::matrix4 iden;
|
||||
$self->Serialize(iden, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
ConversionResultShape* solid_mt() {
|
||||
IfcGeom::ConversionResultShape* r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = $self->solid();
|
||||
Py_END_ALLOW_THREADS;
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
%naturalvar svgfill::polygon_2::boundary;
|
||||
%naturalvar svgfill::polygon_2::inner_boundaries;
|
||||
%naturalvar svgfill::polygon_2::point_inside;
|
||||
@@ -1243,9 +1331,9 @@ ifcopenshell::geometry::taxonomy::item::ptr try_upcast(PyObject* obj0, swig_type
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<svgfill::polygon_2> arrange_polygons(svgfill::arrange_polygon_settings settings, const std::vector<svgfill::polygon_2>& polygons) {
|
||||
std::vector<svgfill::polygon_2> arrange_polygons(svgfill::arrange_polygon_settings settings, const std::vector<svgfill::polygon_2>& polygons, Logger& logger = Logger::Root()) {
|
||||
std::vector<svgfill::polygon_2> r;
|
||||
if (svgfill::arrange_polygons(settings, polygons, r)) {
|
||||
if (svgfill::arrange_polygons(settings, polygons, r, logger)) {
|
||||
return r;
|
||||
} else {
|
||||
throw std::runtime_error("Failed to arrange polygons");
|
||||
|
||||
@@ -112,6 +112,47 @@ PyObject* get_feature(const std::string& x) {
|
||||
|
||||
%{
|
||||
|
||||
#include <fstream>
|
||||
#include <random>
|
||||
|
||||
// Atomic IFC/STEP write (issue #4797): serialize to a temporary file next to
|
||||
// the destination, then atomically rename it onto the destination. If the
|
||||
// process is interrupted mid-write, the destination is never truncated or
|
||||
// left with dangling STEP references; at most a stray temp file remains, which
|
||||
// the caller can safely ignore. Keeping the temp in the same directory means
|
||||
// the rename stays on a single filesystem and is therefore atomic. The temp
|
||||
// path never leaks into the FILE_NAME header, which is derived from the model
|
||||
// header, not the output path.
|
||||
template <typename T>
|
||||
static void helper_fn_atomic_write(T& file_obj, const std::string& fn) {
|
||||
std::random_device rd;
|
||||
const std::string temp_fn = fn + "." + std::to_string(rd()) + ".tmp";
|
||||
{
|
||||
// Same open mode as a plain write so the bytes are identical.
|
||||
std::ofstream f(IfcUtil::path::from_utf8(temp_fn).c_str());
|
||||
if (!f.good()) {
|
||||
// The temp file could not be created (e.g. directory not
|
||||
// writable). Nothing was touched; report as a normal write error.
|
||||
throw std::runtime_error("Failed to write to path: '" + fn + "', check folder and file permissions.");
|
||||
}
|
||||
f << file_obj;
|
||||
f.flush();
|
||||
if (!f.good()) {
|
||||
// Serialization failed (e.g. disk full). Clean up the partial temp
|
||||
// and abort. The existing destination is left intact.
|
||||
f.close();
|
||||
IfcUtil::path::delete_file(temp_fn);
|
||||
throw std::runtime_error("Failed to write to path: '" + fn + "', the file may be incomplete.");
|
||||
}
|
||||
// The ofstream destructor at the end of this scope closes the stream.
|
||||
// On Windows the file must be closed before it can be renamed.
|
||||
}
|
||||
if (!IfcUtil::path::atomic_rename_file(temp_fn, fn)) {
|
||||
IfcUtil::path::delete_file(temp_fn);
|
||||
throw std::runtime_error("Failed to write to path: '" + fn + "', could not replace the existing file.");
|
||||
}
|
||||
}
|
||||
|
||||
static const std::string& helper_fn_declaration_get_name(const ifcopenshell::declaration* decl) {
|
||||
return decl->name();
|
||||
}
|
||||
@@ -221,11 +262,10 @@ private:
|
||||
}
|
||||
|
||||
void _write(const std::string& fn) {
|
||||
std::ofstream f(ifcopenshell::path::from_utf8(fn).c_str());
|
||||
if (!f.good()) {
|
||||
throw std::runtime_error("Failed to write to path: '" + fn + "', check folder and file permissions.");
|
||||
}
|
||||
f << (*$self);
|
||||
// Atomic write: serialize to a temp file next to the target, then
|
||||
// atomically rename it into place, so an interrupted write can never
|
||||
// corrupt the destination (issue #4797).
|
||||
helper_fn_atomic_write(*$self, fn);
|
||||
}
|
||||
|
||||
std::string to_string() {
|
||||
@@ -947,6 +987,7 @@ object = _old_object
|
||||
|
||||
%include "../ifcparse/schema.h"
|
||||
%include "../serializers/RocksDbSerializer.h"
|
||||
%include "../ifcparse/IfcLogger.h"
|
||||
|
||||
// The file* returned by open() is to be freed by SWIG/Python
|
||||
%newobject open;
|
||||
@@ -954,10 +995,10 @@ object = _old_object
|
||||
%newobject stream_from_string;
|
||||
|
||||
%inline %{
|
||||
ifcopenshell::file* open(const std::string& fn, bool readonly=false) {
|
||||
ifcopenshell::file* open(const std::string& fn, bool readonly=false, Logger& logger=Logger::Root()) {
|
||||
ifcopenshell::file* f;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
f = new ifcopenshell::file(fn, ifcopenshell::FT_AUTODETECT, readonly);
|
||||
f = new ifcopenshell::file(fn, ifcopenshell::FT_AUTODETECT, readonly, logger);
|
||||
Py_END_ALLOW_THREADS;
|
||||
return f;
|
||||
}
|
||||
@@ -1115,7 +1156,7 @@ object = _old_object
|
||||
static std::stringstream ifcopenshell_log_stream;
|
||||
%}
|
||||
%init %{
|
||||
logger::set_output(0, &ifcopenshell_log_stream);
|
||||
Logger::Root().SetOutput(0, &ifcopenshell_log_stream);
|
||||
%}
|
||||
%inline %{
|
||||
std::string get_log() {
|
||||
@@ -1124,20 +1165,20 @@ object = _old_object
|
||||
return log;
|
||||
}
|
||||
void turn_on_detailed_logging() {
|
||||
logger::set_output(&std::cout, &std::cout);
|
||||
logger::verbosity(logger::LOG_DEBUG);
|
||||
Logger::Root().SetOutput(&std::cout, &std::cout);
|
||||
Logger::Root().Verbosity(Logger::LOG_DEBUG);
|
||||
}
|
||||
void turn_off_detailed_logging() {
|
||||
logger::set_output(0, &ifcopenshell_log_stream);
|
||||
logger::verbosity(logger::LOG_WARNING);
|
||||
Logger::Root().SetOutput(0, &ifcopenshell_log_stream);
|
||||
Logger::Root().Verbosity(Logger::LOG_WARNING);
|
||||
}
|
||||
void set_log_format_json() {
|
||||
ifcopenshell_log_stream.str("");
|
||||
logger::output_format(logger::FMT_JSON);
|
||||
Logger::Root().OutputFormat(Logger::FMT_JSON);
|
||||
}
|
||||
void set_log_format_text() {
|
||||
ifcopenshell_log_stream.str("");
|
||||
logger::output_format(logger::FMT_PLAIN);
|
||||
Logger::Root().OutputFormat(Logger::FMT_PLAIN);
|
||||
}
|
||||
%}
|
||||
|
||||
@@ -1447,4 +1488,31 @@ object = _old_object
|
||||
return d;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
%extend Logger {
|
||||
%pythoncode %{
|
||||
def __iter__(self):
|
||||
return iter(self.log_messages())
|
||||
%}
|
||||
}
|
||||
|
||||
%extend log_message {
|
||||
std::string severity_string() const {
|
||||
static const char* const severity_strings[] = {"PERF", "DEBUG", "NOTICE", "WARNING", "ERROR"};
|
||||
return severity_strings[(int)$self->severity];
|
||||
}
|
||||
%pythoncode %{
|
||||
severity_string = property(severity_string)
|
||||
def to_dict(self):
|
||||
keys = ("timestamp", "severity", "code", "message", "instance", "product")
|
||||
return dict(zip(keys, self.to_tuple()))
|
||||
def to_tuple(self):
|
||||
return self.timestamp, self.severity_string, self.code, self.message, self.instance, self.product
|
||||
def __eq__(self, other):
|
||||
return type(self) == type(other) and self.to_tuple() == other.to_tuple()
|
||||
def __hash__(self):
|
||||
return hash(self.to_tuple())
|
||||
def __repr__(self):
|
||||
return "<log_message '[%s] [%s] %s'>" % (self.severity_string, self.code, self.message)
|
||||
%}
|
||||
}
|
||||
|
||||
@@ -59,7 +59,6 @@
|
||||
%}
|
||||
%template(DoubleArray3) std::array<double, 3>;
|
||||
|
||||
%ignore IfcGeom::NumberNativeDouble;
|
||||
%ignore ifcopenshell::geometry::Converter;
|
||||
|
||||
// Not relevant for python: new_IfcBaseClass() calls instantiate()
|
||||
|
||||
@@ -57,9 +57,19 @@
|
||||
if (PySequence_Size(aggregate) == -1) return false;
|
||||
for(Py_ssize_t i = 0; i < PySequence_Size(aggregate); ++i) {
|
||||
PyObject* element = PySequence_GetItem(aggregate, i);
|
||||
// This is equivalent to the PyFloat_CheckExact macro. This means
|
||||
// that direct instances of int, float, str, etc. need to be used.
|
||||
bool b = element->ob_type == type_obj;
|
||||
// Accept the exact type or, for the numeric types, a subclass such
|
||||
// as a numpy scalar (numpy.float64 subclasses float), so that numpy
|
||||
// arrays can be assigned. The REAL vs INTEGER distinction is kept: a
|
||||
// float is not accepted where an int is expected and vice versa, and
|
||||
// bool (a subclass of int) is still rejected for INTEGER. See #5873.
|
||||
bool b;
|
||||
if (type_obj == static_cast<void*>(&PyFloat_Type)) {
|
||||
b = PyFloat_Check(element);
|
||||
} else if (type_obj == static_cast<void*>(&PyLong_Type)) {
|
||||
b = PyLong_Check(element) && !PyBool_Check(element);
|
||||
} else {
|
||||
b = element->ob_type == type_obj;
|
||||
}
|
||||
Py_DECREF(element);
|
||||
if (!b) {
|
||||
return false;
|
||||
@@ -249,6 +259,7 @@
|
||||
PyObject* pythonize(const ifcopenshell::inverse_attribute* t) { return SWIG_NewPointerObj(SWIG_as_voidptr(t), SWIGTYPE_p_ifcopenshell__inverse_attribute, 0); }
|
||||
PyObject* pythonize(const ifcopenshell::entity* t) { return SWIG_NewPointerObj(SWIG_as_voidptr(t), SWIGTYPE_p_ifcopenshell__entity, 0); }
|
||||
PyObject* pythonize(const ifcopenshell::declaration* t) { return SWIG_NewPointerObj(SWIG_as_voidptr(t), declaration_type_to_swig(t), 0); }
|
||||
PyObject* pythonize(const log_message& t) { return SWIG_NewPointerObj(SWIG_as_voidptr(&t), SWIGTYPE_p_log_message, 0); }
|
||||
// @nb ownership
|
||||
PyObject* pythonize(const IfcGeom::ConversionResultShape* t) { return SWIG_NewPointerObj(SWIG_as_voidptr(t), SWIGTYPE_p_IfcGeom__ConversionResultShape, SWIG_POINTER_OWN); }
|
||||
// PyObject* pythonize(const IfcGeom::ConversionResultShape* t) { return SWIG_NewPointerObj(SWIG_as_voidptr(t), SWIGTYPE_p_IfcGeom__ConversionResultShape, 0); }
|
||||
|
||||
@@ -356,3 +356,21 @@ CREATE_OPTIONAL_TYPEMAP_IN(std::string, string, str)
|
||||
|
||||
CREATE_SET_TYPEMAP_IN(int)
|
||||
CREATE_SET_TYPEMAP_IN(std::string)
|
||||
|
||||
// for the logger codes
|
||||
%typemap(typecheck, precedence=SWIG_TYPECHECK_STRING) SWIGTYPE &code_prefix {
|
||||
$1 = PyUnicode_Check($input);
|
||||
}
|
||||
%typemap(in) SWIGTYPE &code_prefix (char tmp[4]) {
|
||||
Py_ssize_t len = 0;
|
||||
const char *s = PyUnicode_AsUTF8AndSize($input, &len);
|
||||
|
||||
if (!s || len != 3) {
|
||||
SWIG_exception_fail(SWIG_ValueError, "Expected Python str of length 3");
|
||||
}
|
||||
|
||||
memcpy(tmp, s, 3);
|
||||
tmp[3] = '\0';
|
||||
|
||||
$1 = &tmp;
|
||||
}
|
||||
@@ -95,6 +95,7 @@ CREATE_VECTOR_TYPEMAP_OUT(ifcopenshell::inverse_attribute const *)
|
||||
CREATE_VECTOR_TYPEMAP_OUT(ifcopenshell::entity const *)
|
||||
CREATE_VECTOR_TYPEMAP_OUT(ifcopenshell::declaration const *)
|
||||
CREATE_VECTOR_TYPEMAP_OUT(IfcGeom::ConversionResultShape *)
|
||||
CREATE_VECTOR_TYPEMAP_OUT(log_message)
|
||||
|
||||
%typemap(out) ifcopenshell::geometry::Settings::value_variant_t {
|
||||
pythonizing_visitor vis;
|
||||
|
||||
Reference in New Issue
Block a user