From efe765f71f562a23b17681fdc692ff136d81cab3 Mon Sep 17 00:00:00 2001 From: Xsoiou <32762440+Xsoiou@users.noreply.github.com> Date: Fri, 15 Dec 2017 07:58:10 +0100 Subject: [PATCH 01/60] Changed from http to https on ICU download --- win/build-deps.cmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/win/build-deps.cmd b/win/build-deps.cmd index a46c4e2641..b2ac9a721c 100644 --- a/win/build-deps.cmd +++ b/win/build-deps.cmd @@ -192,7 +192,7 @@ set DEPENDENCY_DIR=N/A set ICU_VER=58.2 set ICU_ZIP=icu-%ICU_VER%-vs%VS_VER%.7z cd "%DEPS_DIR%" -call :DownloadFile http://www.npcglib.org/~stathis/downloads/%ICU_ZIP% "%DEPS_DIR%" %ICU_ZIP% +call :DownloadFile https://www.npcglib.org/~stathis/downloads/%ICU_ZIP% "%DEPS_DIR%" %ICU_ZIP% IF NOT %ERRORLEVEL%==0 GOTO :Error call :ExtractArchive %ICU_ZIP% "%DEPS_DIR%" "%INSTALL_DIR%\icu" IF NOT %ERRORLEVEL%==0 GOTO :Error From b7992d6a12e5ec8262d56c8e05e67f05f5257461 Mon Sep 17 00:00:00 2001 From: Xsoiou <32762440+Xsoiou@users.noreply.github.com> Date: Fri, 15 Dec 2017 10:25:13 +0100 Subject: [PATCH 02/60] This closes #309 and it also fixes #310 --- win/build-deps.cmd | 1 + 1 file changed, 1 insertion(+) diff --git a/win/build-deps.cmd b/win/build-deps.cmd index b2ac9a721c..38caf1f09b 100644 --- a/win/build-deps.cmd +++ b/win/build-deps.cmd @@ -280,6 +280,7 @@ if exist "%DEPS_DIR%\%OCCT_FILENAME%" ( if not exist "%DEPS_DIR%\%OCCT_FILENAME%\OCCT_LGPL_EXCEPTION.txt". rd /s/q "%DEPS_DIR%\%OCCT_FILENAME%" ) + call :ExtractArchive %OCCT_FILENAME%.tar.gz "%DEPS_DIR%" "%DEPENDENCY_DIR%" if not %ERRORLEVEL%==0 goto :Error call :ExtractArchive %OCCT_FILENAME%.tar "%DEPS_DIR%" "%DEPENDENCY_DIR%" From 4e28caaf8dce64b04aa48fcea887119b54599913 Mon Sep 17 00:00:00 2001 From: civilx64 <26513472+civilx64@users.noreply.github.com> Date: Sun, 17 Dec 2017 22:53:43 -0500 Subject: [PATCH 03/60] Corrected name of *nix build script. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d77372219f..c5b0dfab5e 100644 --- a/README.md +++ b/README.md @@ -77,7 +77,7 @@ or Clang 3.5 has been confirmed to work. ### Compiling on *nix -The following instructions are for Ubuntu, modify as required for other operating systems. [nix/build-all.sh] script +The following instructions are for Ubuntu, modify as required for other operating systems. [nix/build-all.py] script can be experimented with and studied for pointers for other operating systems, but note that this script is not currently meant to be used for a typical IfcOpenShell workspace setup. @@ -214,4 +214,4 @@ Usage examples [Visual C++ Build Tools]: http://landinghub.visualstudio.com/visual-cpp-build-tools "Visual C++ Build Tools" [MSYS2]: https://msys2.github.io/ "MSYS2" [win/readme.md]: https://github.com/IfcOpenShell/IfcOpenShell/tree/master/win/readme.md "win/readme.md" -[nix/build-all.sh]: https://github.com/IfcOpenShell/IfcOpenShell/tree/master/nix/build-all.sh "nix/build-all.sh" \ No newline at end of file +[nix/build-all.sh]: https://github.com/IfcOpenShell/IfcOpenShell/tree/master/nix/build-all.sh "nix/build-all.sh" From c4e56f670d3c58547548239ac2d13a8788bddd2f Mon Sep 17 00:00:00 2001 From: civilx64 <26513472+civilx64@users.noreply.github.com> Date: Sun, 17 Dec 2017 23:06:39 -0500 Subject: [PATCH 04/60] Corrected name of *nix build script. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c5b0dfab5e..ff4f29d83a 100644 --- a/README.md +++ b/README.md @@ -214,4 +214,4 @@ Usage examples [Visual C++ Build Tools]: http://landinghub.visualstudio.com/visual-cpp-build-tools "Visual C++ Build Tools" [MSYS2]: https://msys2.github.io/ "MSYS2" [win/readme.md]: https://github.com/IfcOpenShell/IfcOpenShell/tree/master/win/readme.md "win/readme.md" -[nix/build-all.sh]: https://github.com/IfcOpenShell/IfcOpenShell/tree/master/nix/build-all.sh "nix/build-all.sh" +[nix/build-all.py]: https://github.com/IfcOpenShell/IfcOpenShell/tree/master/nix/build-all.py "nix/build-all.py" From 01d261e168311122aa3376ebab9e02f3b4ce9662 Mon Sep 17 00:00:00 2001 From: Xsoiou <32762440+Xsoiou@users.noreply.github.com> Date: Tue, 19 Dec 2017 12:10:19 +0100 Subject: [PATCH 05/60] SVG storey elevation (#315) IfcConvert SVG does not generate for IfcSpace. #313 --- src/ifcconvert/SvgSerializer.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ifcconvert/SvgSerializer.cpp b/src/ifcconvert/SvgSerializer.cpp index 7821cf519b..2b7413ad26 100644 --- a/src/ifcconvert/SvgSerializer.cpp +++ b/src/ifcconvert/SvgSerializer.cpp @@ -366,12 +366,15 @@ void SvgSerializer::write(const IfcGeom::BRepElement* o) double cut_z; if (section_height) { cut_z = section_height.get(); - } else if (storey_elevation) { + } else if (storey_elevation && !(zmin > *storey_elevation || zmax < *storey_elevation)) { cut_z = storey_elevation.get() + 1.; } else { cut_z = zmin + 1.; } + if (zmin > cut_z || zmax < cut_z) continue; + + // Create a horizontal cross section 1 meter above the bottom point of the shape TopoDS_Shape result = BRepAlgoAPI_Section(moved_shape, gp_Pln(gp_Pnt(0, 0, cut_z), gp::DZ())); From e3a7e6137d1862b10bb0a4949da29d69e498a554 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Tue, 19 Dec 2017 14:58:56 +0100 Subject: [PATCH 06/60] Update SvgSerializer.cpp --- src/ifcconvert/SvgSerializer.cpp | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/src/ifcconvert/SvgSerializer.cpp b/src/ifcconvert/SvgSerializer.cpp index 2b7413ad26..0a895ff29d 100644 --- a/src/ifcconvert/SvgSerializer.cpp +++ b/src/ifcconvert/SvgSerializer.cpp @@ -352,17 +352,14 @@ void SvgSerializer::write(const IfcGeom::BRepElement* o) if (pnt.Z() < zmin) { zmin = pnt.Z(); } if (pnt.Z() > zmax) { zmax = pnt.Z(); } }} - - if (section_height) { - if (zmin > section_height || zmax < section_height) continue; - } else { - if (zmin == inf || (zmax - zmin) < 1.) continue; - } - - // Priority: - // 1) section_height - // 2) Storey elevation + 1m - // 3) zmin + 1m + + // Empty geometry, no vertices encountered + if (zmin == inf) continue; + + // Determine slicing plane z coordinate, priority: + // 1) explicitly set global section height + // 2) containing building storey elevation + 1m + // 3) zmin (from geometry bounding box) + 1m double cut_z; if (section_height) { cut_z = section_height.get(); @@ -372,10 +369,10 @@ void SvgSerializer::write(const IfcGeom::BRepElement* o) cut_z = zmin + 1.; } + // No intersection with bounding box, fail early if (zmin > cut_z || zmax < cut_z) continue; - - // Create a horizontal cross section 1 meter above the bottom point of the shape + // Evaluate cross section geometry TopoDS_Shape result = BRepAlgoAPI_Section(moved_shape, gp_Pln(gp_Pnt(0, 0, cut_z), gp::DZ())); Handle(TopTools_HSequenceOfShape) edges = new TopTools_HSequenceOfShape(); From 5bf7f53fd800052cfa8837a47786ac6df3aa1cf5 Mon Sep 17 00:00:00 2001 From: stefkeB Date: Fri, 22 Dec 2017 09:57:59 +0100 Subject: [PATCH 07/60] BaseQuantities support in IfcConvert XmlSerializer Added the export of BaseQuantities in the XML export of IfcConvert. Very similar to the export of properties. --- src/ifcconvert/XmlSerializer.cpp | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/ifcconvert/XmlSerializer.cpp b/src/ifcconvert/XmlSerializer.cpp index c9c99d8976..1bc02c4593 100644 --- a/src/ifcconvert/XmlSerializer.cpp +++ b/src/ifcconvert/XmlSerializer.cpp @@ -258,6 +258,9 @@ ptree& descend(IfcObjectDefinition* product, ptree& tree) { if (pset->is(Type::IfcPropertySet)) { format_entity_instance(pset, child, true); } + if (pset->is(Type::IfcElementQuantity)) { + format_entity_instance(pset, child, true); + } } #ifdef USE_IFC4 @@ -314,6 +317,14 @@ void format_properties(IfcProperty::list::ptr properties, ptree& node) { } } +// Format IfcElementQuantity instances and insert into the DOM. +void format_quantities(IfcPhysicalQuantity::list::ptr quantities, ptree& node) { + for (IfcPhysicalQuantity::list::it it = quantities->begin(); it != quantities->end(); ++it) { + IfcPhysicalQuantity* p = *it; + format_entity_instance(p, node); + } +} + } // ~unnamed namespace void XmlSerializer::finalize() { @@ -326,7 +337,7 @@ void XmlSerializer::finalize() { } IfcProject* project = *projects->begin(); - ptree root, header, units, decomposition, properties, types, layers, materials; + ptree root, header, units, decomposition, properties, quantities, types, layers, materials; // Write the SPF header as XML nodes. foreach(const std::string& s, file->header().file_description().description()) { @@ -358,6 +369,15 @@ void XmlSerializer::finalize() { ptree& node = format_entity_instance(pset, properties); format_properties(pset->HasProperties(), node); } + + // Write all quantities and values as XML nodes. + IfcElementQuantity::list::ptr qtosets = file->entitiesByType(); + for (IfcElementQuantity::list::it it = qtosets->begin(); it != qtosets->end(); ++it) { + IfcElementQuantity* qto = *it; + ptree& node = format_entity_instance(qto, quantities); + format_quantities(qto->Quantities(), node); + } + // Write all type objects as XML nodes. IfcTypeObject::list::ptr type_objects = file->entitiesByType(); @@ -439,8 +459,9 @@ void XmlSerializer::finalize() { root.add_child("ifc.header", header); root.add_child("ifc.units", units); root.add_child("ifc.properties", properties); + root.add_child("ifc.quantities", quantities); root.add_child("ifc.types", types); - root.add_child("ifc.layers", layers); + root.add_child("ifc.layers", layers); root.add_child("ifc.materials", materials); root.add_child("ifc.decomposition", decomposition); From 162b665d073be260d06b742734ab40ff1e72a5cc Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Mon, 15 Jan 2018 11:00:25 +0100 Subject: [PATCH 08/60] Update blender addon for str geometry.id --- src/ifcblender/io_import_scene_ifc/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ifcblender/io_import_scene_ifc/__init__.py b/src/ifcblender/io_import_scene_ifc/__init__.py index 6b14f2a99d..dee3adb560 100644 --- a/src/ifcblender/io_import_scene_ifc/__init__.py +++ b/src/ifcblender/io_import_scene_ifc/__init__.py @@ -92,7 +92,8 @@ def import_ifc(filename, use_names, process_relations, blender_booleans): faces = [[f[i], f[i + 1], f[i + 2]] \ for i in range(0, len(f), 3)] - me = bpy.data.meshes.new('mesh%d' % ob.geometry.id) + # Depending on version, geometry.id will be either int or str + me = bpy.data.meshes.new('mesh-%r' % ob.geometry.id) me.from_pydata(verts, [], faces) me.validate() From 8a316e45eddb2d507d67b3597c921910cda76367 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Granskogen=20Bj=C3=B8rnstad?= Date: Wed, 14 Feb 2018 15:17:37 +0100 Subject: [PATCH 09/60] IfcConvert: Add --building-local-placement argument Similar to --site-local-placement. Motivated by dealing with at least two examples where IFC files for the same construction site have inconsistent ObjectPlacement hierarchy: - MEP models exported from MagiCAD for Revit: ObjectPlacement.PlacementRelTo of IfcBuilding is empty - Regular construction models exported from Revit: ObjectPlacement.PlacementRelTo of IfcBuilding is pointing to IfcSite's placement --- src/ifcconvert/IfcConvert.cpp | 9 +++++++-- src/ifcgeom/IfcGeomIterator.h | 7 ++++++- src/ifcgeom/IfcGeomIteratorSettings.h | 6 ++++-- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/ifcconvert/IfcConvert.cpp b/src/ifcconvert/IfcConvert.cpp index 31708c6a9c..8d386b8b04 100644 --- a/src/ifcconvert/IfcConvert.cpp +++ b/src/ifcconvert/IfcConvert.cpp @@ -298,6 +298,8 @@ int main(int argc, char** argv) ("site-local-placement", "Place elements locally in the IfcSite coordinate system, instead of placing " "them in the IFC global coords. Applicable for OBJ and DAE output.") + ("building-local-placement", + "Similar to --site-local-placement, but placing elements in locally in the parent IfcBuilding coord system") ("precision", po::value(&precision)->default_value(SerializerSettings::DEFAULT_PRECISION), "Sets the precision to be used to format floating-point values, 15 by default. " "Use a negative value to use the system's default precision (should be 6 typically). " @@ -370,6 +372,7 @@ int main(int argc, char** argv) const bool center_model = vmap.count("center-model") != 0 ; const bool model_offset = vmap.count("model-offset") != 0 ; const bool site_local_placement = vmap.count("site-local-placement") != 0 ; + const bool building_local_placement = vmap.count("building-local-placement") != 0 ; const bool generate_uvs = vmap.count("generate-uvs") != 0 ; #ifdef HAVE_ICU @@ -504,6 +507,8 @@ int main(int argc, char** argv) settings.set(IfcGeom::IteratorSettings::GENERATE_UVS, generate_uvs); 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); @@ -614,8 +619,8 @@ int main(int argc, char** argv) if (center_model || model_offset) { double* offset = serializer->settings().offset; if (center_model) { - if (site_local_placement) { - Logger::Error("Cannot use --center-model together with --site-local-placement"); + if (site_local_placement || building_local_placement) { + Logger::Error("Cannot use --center-model together with --{site,building}-local-placement"); delete serializer; return EXIT_FAILURE; } diff --git a/src/ifcgeom/IfcGeomIterator.h b/src/ifcgeom/IfcGeomIterator.h index cabe628ad6..66c2a43af7 100644 --- a/src/ifcgeom/IfcGeomIterator.h +++ b/src/ifcgeom/IfcGeomIterator.h @@ -683,7 +683,12 @@ namespace IfcGeom { kernel.setValue(IfcGeom::Kernel::GV_MAX_FACES_TO_SEW, settings.get(IteratorSettings::SEW_SHELLS) ? 1000 : -1); kernel.setValue(IfcGeom::Kernel::GV_DIMENSIONALITY, (settings.get(IteratorSettings::INCLUDE_CURVES) ? (settings.get(IteratorSettings::EXCLUDE_SOLIDS_AND_SURFACES) ? -1. : 0.) : +1.)); - if (settings.get(IteratorSettings::SITE_LOCAL_PLACEMENT)) { + if (settings.get(IteratorSettings::BUILDING_LOCAL_PLACEMENT)) { + if (settings.get(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(IteratorSettings::SITE_LOCAL_PLACEMENT)) { kernel.set_conversion_placement_rel_to(IfcSchema::Type::IfcSite); } } diff --git a/src/ifcgeom/IfcGeomIteratorSettings.h b/src/ifcgeom/IfcGeomIteratorSettings.h index 1a765a37a3..8a601c4e55 100644 --- a/src/ifcgeom/IfcGeomIteratorSettings.h +++ b/src/ifcgeom/IfcGeomIteratorSettings.h @@ -82,8 +82,10 @@ namespace IfcGeom SEARCH_FLOOR = 1 << 14, /// SITE_LOCAL_PLACEMENT = 1 << 15, - /// Number of different setting flags. - NUM_SETTINGS = 15 + /// + BUILDING_LOCAL_PLACEMENT = 1 << 16, + /// Number of different setting flags. + NUM_SETTINGS = 16 }; /// Used to store logical OR combination of setting flags. typedef unsigned SettingField; From 5d0c04a0770be81fc8efe2f39cda440d0550284d Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Wed, 21 Feb 2018 14:54:38 +0100 Subject: [PATCH 10/60] Fix geometry reuse in case of IfcTypeProducts with maps --- src/ifcgeom/IfcGeomIterator.h | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/ifcgeom/IfcGeomIterator.h b/src/ifcgeom/IfcGeomIterator.h index 66c2a43af7..28650cbe12 100644 --- a/src/ifcgeom/IfcGeomIterator.h +++ b/src/ifcgeom/IfcGeomIterator.h @@ -407,12 +407,20 @@ namespace IfcGeom { geometry_reuse_ok_for_current_representation_ = reuse_ok_(unfiltered_products); - if (!geometry_reuse_ok_for_current_representation_ && representation->RepresentationMap()->size() == 1) { + 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. - _nextShape(); - continue; + + // 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; + } } bool representation_processed_as_mapped_item = false; From 1a7a4bdc3e3534f058123675801e32d113f771b9 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Tue, 27 Feb 2018 18:09:43 +0100 Subject: [PATCH 11/60] Update boost download path --- win/build-deps.cmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/win/build-deps.cmd b/win/build-deps.cmd index 38caf1f09b..c811df35ba 100644 --- a/win/build-deps.cmd +++ b/win/build-deps.cmd @@ -154,7 +154,7 @@ set BOOST_LIBRARYDIR=%DEPS_DIR%\boost\stage\%VS_PLATFORM%\lib set ZIP_EXT=7z set BOOST_ZIP=boost_%BOOST_VER%.%ZIP_EXT% -call :DownloadFile http://downloads.sourceforge.net/project/boost/boost/%BOOST_VERSION%/%BOOST_ZIP% "%DEPS_DIR%" %BOOST_ZIP% +call :DownloadFile https://dl.bintray.com/boostorg/release/%BOOST_VERSION%/source/%BOOST_ZIP% "%DEPS_DIR%" %BOOST_ZIP% IF NOT %ERRORLEVEL%==0 GOTO :Error call :ExtractArchive %BOOST_ZIP% "%DEPS_DIR%" "%DEPS_DIR%\boost" From 092011617846162753644bb40e92fce481d25d95 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Sun, 4 Mar 2018 10:45:05 +0100 Subject: [PATCH 12/60] Fix prompt --- win/build-deps.cmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/win/build-deps.cmd b/win/build-deps.cmd index c811df35ba..34d31f493d 100644 --- a/win/build-deps.cmd +++ b/win/build-deps.cmd @@ -124,7 +124,7 @@ echo. call cecho.cmd black cyan "If you are not ready with the above: type `'n`' in the prompt below. Build proceeds on all other inputs!" set /p do_continue="> " -if "%do_continue%"==n goto :Finish +if "%do_continue%"=="n" goto :Finish :: Cache last used CMake generator for other scripts to use if defined GEN_SHORTHAND echo GEN_SHORTHAND=%GEN_SHORTHAND%>"%~dp0\BuildDepsCache-%TARGET_ARCH%.txt" From 27e335343e50786fb15406d8026fee8c8be020e3 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Sun, 4 Mar 2018 10:45:44 +0100 Subject: [PATCH 13/60] Win build script occt7.2 --- win/build-deps.cmd | 41 +- win/patches/88af392_CMakeLists.txt | 1127 +++++++++++++++++ .../88af392_adm-cmake-occt_defs_flags.cmake | 158 +++ .../88af392_adm-cmake-occt_toolkit.cmake | 346 +++++ 4 files changed, 1662 insertions(+), 10 deletions(-) create mode 100644 win/patches/88af392_CMakeLists.txt create mode 100644 win/patches/88af392_adm-cmake-occt_defs_flags.cmake create mode 100644 win/patches/88af392_adm-cmake-occt_toolkit.cmake diff --git a/win/build-deps.cmd b/win/build-deps.cmd index 34d31f493d..4cdeb8cb9c 100644 --- a/win/build-deps.cmd +++ b/win/build-deps.cmd @@ -267,11 +267,13 @@ if not %ERRORLEVEL%==0 goto :Error call :InstallCMakeProject "%DEPENDENCY_DIR%\%BUILD_DIR%" %BUILD_CFG% if not %ERRORLEVEL%==0 goto :Error -set DEPENDENCY_NAME=Open CASCADE 7.1.0 -set OCCT_FILENAME=occt-89aebde +set OCCT_HASH=88af392 +set OCCT_VERSION=7.2.0 +set DEPENDENCY_NAME=Open CASCADE %OCCT_VERSION% +set OCCT_FILENAME=occt-%OCCT_HASH% set DEPENDENCY_DIR=%DEPS_DIR%\%OCCT_FILENAME% cd "%DEPS_DIR%" -call :DownloadFile "http://git.dev.opencascade.org/gitweb/?p=occt.git;a=snapshot;h=89aebde;sf=tgz" "%DEPS_DIR%" %OCCT_FILENAME%.tar.gz +call :DownloadFile "http://git.dev.opencascade.org/gitweb/?p=occt.git;a=snapshot;h=%OCCT_HASH%;sf=tgz" "%DEPS_DIR%" %OCCT_FILENAME%.tar.gz if not %ERRORLEVEL%==0 goto :Error if exist "%DEPS_DIR%\%OCCT_FILENAME%" ( @@ -289,24 +291,43 @@ if not %ERRORLEVEL%==0 goto :Error set DEPENDENCY_NAME=Additional files :: Somehow these two files are not present in the downloaded :: snapshot. Path names being too long for gitweb snapshot? -call :DownloadFile "http://git.dev.opencascade.org/gitweb/?p=occt.git;a=blob_plain;hb=89aebdea8d6f4d15cfc50e9458cd8e2e25022326;f=src/RWStepVisual/RWStepVisual_RWCharacterizedObjectAndCharacterizedRepresentationAndDraughtingModelAndRepresentation.cxx" "%OCCT_FILENAME%\src\RWStepVisual" RWStepVisual_RWCharacterizedObjectAndCharacterizedRepresentationAndDraughtingModelAndRepresentation.cxx + +call :DownloadFile "http://git.dev.opencascade.org/gitweb/?p=occt.git;a=blob_plain;hb=%OCCT_HASH%;f=src/RWStepVisual/RWStepVisual_RWCharacterizedObjectAndCharacterizedRepresentationAndDraughtingModelAndRepresentation.cxx" "%OCCT_FILENAME%\src\RWStepVisual" RWStepVisual_RWCharacterizedObjectAndCharacterizedRepresentationAndDraughtingModelAndRepresentation.cxx if not %ERRORLEVEL%==0 goto :Error -call :DownloadFile "http://git.dev.opencascade.org/gitweb/?p=occt.git;a=blob_plain;hb=89aebdea8d6f4d15cfc50e9458cd8e2e25022326;f=src/RWStepVisual/RWStepVisual_RWCharacterizedObjectAndCharacterizedRepresentationAndDraughtingModelAndRepresentation.hxx" "%OCCT_FILENAME%\src\RWStepVisual" RWStepVisual_RWCharacterizedObjectAndCharacterizedRepresentationAndDraughtingModelAndRepresentation.hxx + +call :DownloadFile "http://git.dev.opencascade.org/gitweb/?p=occt.git;a=blob_plain;hb=%OCCT_HASH%;f=src/RWStepVisual/RWStepVisual_RWCharacterizedObjectAndCharacterizedRepresentationAndDraughtingModelAndRepresentation.hxx" "%OCCT_FILENAME%\src\RWStepVisual" RWStepVisual_RWCharacterizedObjectAndCharacterizedRepresentationAndDraughtingModelAndRepresentation.hxx if not %ERRORLEVEL%==0 goto :Error -set DEPENDENCY_NAME=Open CASCADE 7.1.0 + +if "%OCCT_VERSION%"=="7.2.0" ( + +call :DownloadFile "http://git.dev.opencascade.org/gitweb/?p=occt.git;a=blob_plain;hb=%OCCT_HASH%;f=src/StepVisual/StepVisual_AnnotationCurveOccurrenceAndAnnotationOccurrenceAndGeomReprItemAndReprItemAndStyledItem.cxx" "%OCCT_FILENAME%\src\StepVisual" StepVisual_AnnotationCurveOccurrenceAndAnnotationOccurrenceAndGeomReprItemAndReprItemAndStyledItem.cxx +if not %ERRORLEVEL%==0 goto :Error + +call :DownloadFile "http://git.dev.opencascade.org/gitweb/?p=occt.git;a=blob_plain;hb=%OCCT_HASH%;f=src/RWStepVisual/RWStepVisual_RWAnnotationCurveOccurrenceAndAnnotationOccurrenceAndGeomReprItemAndReprItemAndStyledItem.cxx" "%OCCT_FILENAME%\src\RWStepVisual" RWStepVisual_RWAnnotationCurveOccurrenceAndAnnotationOccurrenceAndGeomReprItemAndReprItemAndStyledItem.cxx +if not %ERRORLEVEL%==0 goto :Error + +call :DownloadFile "http://git.dev.opencascade.org/gitweb/?p=occt.git;a=blob_plain;hb=%OCCT_HASH%;f=src/StepVisual/StepVisual_AnnotationCurveOccurrenceAndAnnotationOccurrenceAndGeomReprItemAndReprItemAndStyledItem.hxx" "%OCCT_FILENAME%\src\StepVisual" StepVisual_AnnotationCurveOccurrenceAndAnnotationOccurrenceAndGeomReprItemAndReprItemAndStyledItem.hxx +if not %ERRORLEVEL%==0 goto :Error + +call :DownloadFile "http://git.dev.opencascade.org/gitweb/?p=occt.git;a=blob_plain;hb=%OCCT_HASH%;f=src/RWStepVisual/RWStepVisual_RWAnnotationCurveOccurrenceAndAnnotationOccurrenceAndGeomReprItemAndReprItemAndStyledItem.hxx" "%OCCT_FILENAME%\src\RWStepVisual" RWStepVisual_RWAnnotationCurveOccurrenceAndAnnotationOccurrenceAndGeomReprItemAndReprItemAndStyledItem.hxx +if not %ERRORLEVEL%==0 goto :Error + +) + +set DEPENDENCY_NAME=Open CASCADE %OCCT_VERSION% :: Patching always blindly would trigger a rebuild each time findstr IfcOpenShell "%DEPENDENCY_DIR%\CMakeLists.txt">NUL if not %ERRORLEVEL%==0 ( echo Patching %DEPENDENCY_NAME%'s CMake files REM OCCT insists on finding FreeType DLL even if using static FreeType build + define HAVE_NO_DLL - copy /y "%~dp0patches\89aebde_CMakeLists.txt" "%DEPENDENCY_DIR%\CMakeLists.txt" + if exist "%~dp0patches\%OCCT_HASH%_CMakeLists.txt" copy /y "%~dp0patches\%OCCT_HASH%_CMakeLists.txt" "%DEPENDENCY_DIR%\CMakeLists.txt" REM Patch OCCT to be built against the static MSVC run-time. - copy /y "%~dp0patches\89aebde_adm-cmake-occt_defs_flags.cmake" "%DEPENDENCY_DIR%\adm\cmake\occt_defs_flags.cmake" + if exist "%~dp0patches\%OCCT_HASH%_adm-cmake-occt_defs_flags.cmake" copy /y "%~dp0patches\%OCCT_HASH%_adm-cmake-occt_defs_flags.cmake" "%DEPENDENCY_DIR%\adm\cmake\occt_defs_flags.cmake" REM OCCT tries to deploy PDBs from the bin directory even if static build is used. - copy /y "%~dp0patches\89aebde_adm-cmake-occt_toolkit.cmake" "%DEPENDENCY_DIR%\adm\cmake\occt_toolkit.cmake" + if exist "%~dp0patches\%OCCT_HASH%_adm-cmake-occt_toolkit.cmake" copy /y "%~dp0patches\%OCCT_HASH%_adm-cmake-occt_toolkit.cmake" "%DEPENDENCY_DIR%\adm\cmake\occt_toolkit.cmake" REM Patch header file for HAVE_NO_DLL - copy /y "%~dp0patches\89aebde_Standard_Macro.hxx" "%DEPENDENCY_DIR%\src\Standard\Standard_Macro.hxx" + if exist "%~dp0patches\%OCCT_HASH%_Standard_Macro.hxx" copy /y "%~dp0patches\%OCCT_HASH%_Standard_Macro.hxx" "%DEPENDENCY_DIR%\src\Standard\Standard_Macro.hxx" REM NOTE If adding a new patch, adjust the checks above and below accordingly ) findstr IfcOpenShell "%DEPENDENCY_DIR%\CMakeLists.txt">NUL diff --git a/win/patches/88af392_CMakeLists.txt b/win/patches/88af392_CMakeLists.txt new file mode 100644 index 0000000000..f21a84f7c2 --- /dev/null +++ b/win/patches/88af392_CMakeLists.txt @@ -0,0 +1,1127 @@ +cmake_minimum_required (VERSION 2.8.12 FATAL_ERROR) + +set (CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/adm/cmake") + +set (CMAKE_SUPPRESS_REGENERATION TRUE) + +set (CMAKE_CONFIGURATION_TYPES Release Debug RelWithDebInfo CACHE INTERNAL "" FORCE) + +# macro: include patched file if it exists +macro (OCCT_INCLUDE_CMAKE_FILE BEING_INCLUDED_FILE) + if (BUILD_PATCH AND EXISTS "${BUILD_PATCH}/${BEING_INCLUDED_FILE}.cmake") + include (${BUILD_PATCH}/${BEING_INCLUDED_FILE}.cmake) + else() + include (${CMAKE_SOURCE_DIR}/${BEING_INCLUDED_FILE}.cmake) + endif() +endmacro() + +# include variable description +OCCT_INCLUDE_CMAKE_FILE ("adm/cmake/vardescr") + +# set type of OCCT libraries +if (NOT BUILD_LIBRARY_TYPE) + set (BUILD_LIBRARY_TYPE "Shared" CACHE STRING "${BUILD_LIBRARY_TYPE_DESCR}" FORCE) + SET_PROPERTY(CACHE BUILD_LIBRARY_TYPE PROPERTY STRINGS Shared Static) +endif() + +if ("${BUILD_LIBRARY_TYPE}" STREQUAL "Shared") + set (BUILD_SHARED_LIBS ON) + + if (NOT DEFINED BUILD_SHARED_LIBRARY_NAME_POSTFIX) + set (BUILD_SHARED_LIBRARY_NAME_POSTFIX "" CACHE STRING "${BUILD_SHARED_LIBRARY_NAME_POSTFIX_DESCR}" FORCE) + endif() +else() + unset (BUILD_SHARED_LIBS) + message (STATUS "Info: Only 3rdparty's header files are used for building of static OCCT libraries") + unset (BUILD_SHARED_LIBRARY_NAME_POSTFIX) +endif() + +# the name of the project +project (OCCT) + +if (WIN32) + add_definitions(-DUNICODE) + add_definitions(-D_UNICODE) +endif() + +# include occt macros +OCCT_INCLUDE_CMAKE_FILE ("adm/cmake/occt_macros") + +# Solution folder property +set_property (GLOBAL PROPERTY USE_FOLDERS ON) + +# get current OCCT version +OCC_VERSION (OCC_VERSION_MAJOR OCC_VERSION_MINOR OCC_VERSION_MAINTENANCE OCC_VERSION_DEVELOPMENT OCC_VERSION_STRING_EXT) + +set_property (GLOBAL PROPERTY OCC_VERSION_MAJOR ${OCC_VERSION_MAJOR}) +set_property (GLOBAL PROPERTY OCC_VERSION_MINOR ${OCC_VERSION_MINOR}) +set_property (GLOBAL PROPERTY OCC_VERSION_MAINTENANCE ${OCC_VERSION_MAINTENANCE}) + +set (INSTALL_TEST_CASES OFF CACHE BOOL "${INSTALL_TEST_CASES_DESCR}") + +# Regeneration of OCCT resource files +set (BUILD_RESOURCES OFF CACHE BOOL "${BUILD_RESOURCES_DESCR}") + +# single-configuration generator +set (SINGLE_GENERATOR OFF) +if (CMAKE_BUILD_TYPE) + set (SINGLE_GENERATOR ON) +endif() + +# a single-configuration generator like the Makefile generator defines CMAKE_BUILD_TYPE variable +# check this variable and set if it's required +if (DEFINED CMAKE_BUILD_TYPE AND NOT CMAKE_BUILD_TYPE) # single-configuration generator. + set (CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build, options are: None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel." FORCE) +endif() + +# enable extended messages of many OCCT algorithms +if (((SINGLE_GENERATOR AND "${CMAKE_BUILD_TYPE}" STREQUAL "Debug") OR NOT SINGLE_GENERATOR) AND (NOT "${CMAKE_SYSTEM_NAME}" STREQUAL "WindowsStore")) + if (NOT BUILD_WITH_DEBUG) + set (BUILD_WITH_DEBUG OFF CACHE BOOL "${BUILD_WITH_DEBUG_DESCR}") + endif() +else() + OCCT_CHECK_AND_UNSET (BUILD_WITH_DEBUG) +endif() + +if (BUILD_WITH_DEBUG) + set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS $<$:OCCT_DEBUG>) +endif() + +# option to enable or disable use of precompiled headers +if (NOT DEFINED BUILD_USE_PCH) + set (BUILD_USE_PCH OFF CACHE BOOL "${BUILD_USE_PCH_DESCR}") +endif() + +if (BUILD_USE_PCH) + + # Load Cotire tool for accelerating build procedure + include(cotire) + + # Set Cotire to ignore lxx, pxx, gxx + set (COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_EXTENSIONS "lxx;pxx;gxx" CACHE STRING "Set Cotire to ignore OCCT specific files that can be #included" FORCE) + + # Set priority for inclusion of system headers in PCH to reduce problems + # due to incomplete inclusion or wrong order. + if (WIN32) + # on Windows, assume that SDK (windows.h) is in default location + set(ProgramFilesX86 "ProgramFiles(x86)") + file(TO_CMAKE_PATH "$ENV{${ProgramFilesX86}}" ProgramFilesX86) + set_property (DIRECTORY PROPERTY COTIRE_PREFIX_HEADER_INCLUDE_PRIORITY_PATH "${ProgramFilesX86}") + unset(ProgramFilesX86) + endif() + +endif() + +# copy samples to install directory +set (INSTALL_SAMPLES OFF CACHE BOOL "${INSTALL_SAMPLES_DESCR}") + +# install dir of the project +if (NOT DEFINED INSTALL_DIR) + # set default install directory for Windows + if (WIN32 AND NOT DEFINED CMAKE_INSTALL_PREFIX) + set (CMAKE_INSTALL_PREFIX "C:/opencascade-${OCC_VERSION_STRING_EXT}") + endif() + set (INSTALL_DIR "${CMAKE_INSTALL_PREFIX}" CACHE PATH "${INSTALL_DIR_DESCR}") +else() + file (TO_CMAKE_PATH "${INSTALL_DIR}" INSTALL_DIR) + set (INSTALL_DIR "${INSTALL_DIR}" CACHE PATH "${INSTALL_DIR_DESCR}" FORCE) +endif() + +# choose a variant of the layout of the install paths +if (NOT INSTALL_DIR_LAYOUT) + if (WIN32) + set (INSTALL_DIR_LAYOUT "Windows" CACHE STRING "${INSTALL_DIR_LAYOUT_DESCR}" FORCE) + else() + set (INSTALL_DIR_LAYOUT "Unix" CACHE STRING "${INSTALL_DIR_LAYOUT_DESCR}" FORCE) + endif() + SET_PROPERTY(CACHE INSTALL_DIR_LAYOUT PROPERTY STRINGS Windows Unix) +endif() + +# check INSTALL_DIR_LAYOUT changes and update INSTALL_DIR_* paths if necessary +if (NOT DEFINED INSTALL_DIR_LAYOUT_PREV) + set (INSTALL_DIR_LAYOUT_PREV "${INSTALL_DIR_LAYOUT}" CACHE INTERNAL "" FORCE) +elseif (NOT "${INSTALL_DIR_LAYOUT_PREV}" STREQUAL "${INSTALL_DIR_LAYOUT}") + set (INSTALL_DIR_LAYOUT_PREV "${INSTALL_DIR_LAYOUT}" CACHE INTERNAL "" FORCE) + # The structure of install folder should be reset due to changed layout + OCCT_CHECK_AND_UNSET_INSTALL_DIR_SUBDIRS () + + # Unset INSTALL_DIR_WITH_VERSION on windows + if ("${INSTALL_DIR_LAYOUT}" STREQUAL "Windows") + OCCT_CHECK_AND_UNSET (INSTALL_DIR_WITH_VERSION) + else() + if (NOT DEFINED INSTALL_DIR_WITH_VERSION) + set (INSTALL_DIR_WITH_VERSION OFF CACHE BOOL "${INSTALL_DIR_WITH_VERSION_DESCR}") + endif() + endif() +endif() + +# check CMAKE_INSTALL_PREFIX changes and update INSTALL_DIR if necessary +if (NOT DEFINED CMAKE_INSTALL_PREFIX_PREV) + set (CMAKE_INSTALL_PREFIX_PREV "${CMAKE_INSTALL_PREFIX}" CACHE INTERNAL "" FORCE) +elseif (NOT "${CMAKE_INSTALL_PREFIX_PREV}" STREQUAL "${CMAKE_INSTALL_PREFIX}") + # CMAKE_INSTALL_PREFIX has been changed at previous step + set (CMAKE_INSTALL_PREFIX_PREV "${CMAKE_INSTALL_PREFIX}" CACHE INTERNAL "" FORCE) + + # INSTALL_DIR is required to be updated + set (INSTALL_DIR "${CMAKE_INSTALL_PREFIX}" CACHE PATH "${INSTALL_DIR_DESCR}" FORCE) +endif() + +# check INSTALL_DIR changes and update CMAKE_INSTALL_PREFIX if necessary +if (NOT DEFINED INSTALL_DIR_PREV) + set (INSTALL_DIR_PREV "${INSTALL_DIR}" CACHE INTERNAL "" FORCE) +elseif (NOT "${INSTALL_DIR_PREV}" STREQUAL "${INSTALL_DIR}") + # INSTALL_DIR has been changed at previous step + set (INSTALL_DIR_PREV "${INSTALL_DIR}" CACHE INTERNAL "" FORCE) + + # sync CMAKE_INSTALL_PREFIX with INSTALL_DIR + set (CMAKE_INSTALL_PREFIX "${INSTALL_DIR}" CACHE INTERNAL "" FORCE) + + # set CMAKE_INSTALL_PREFIX_PREV to avoid the reset of structure of the install folder + set (CMAKE_INSTALL_PREFIX_PREV "${INSTALL_DIR}" CACHE INTERNAL "" FORCE) +endif() + +if ("${INSTALL_DIR_LAYOUT}" STREQUAL "Unix") + if (NOT DEFINED INSTALL_DIR_WITH_VERSION_PREV) + set (INSTALL_DIR_WITH_VERSION_PREV "${INSTALL_DIR_WITH_VERSION}" CACHE INTERNAL "" FORCE) + elseif (NOT "${INSTALL_DIR_WITH_VERSION_PREV}" STREQUAL "${INSTALL_DIR_WITH_VERSION}") + # INSTALL_DIR_WITH_VERSION has been changed at previous step + set (INSTALL_DIR_WITH_VERSION_PREV "${INSTALL_DIR_WITH_VERSION}" CACHE INTERNAL "" FORCE) + + OCCT_CHECK_AND_UNSET_INSTALL_DIR_SUBDIRS () + endif() +endif() + +# hide CMAKE_INSTALL_PREFIX from a user +set (CMAKE_INSTALL_PREFIX "${INSTALL_DIR}" CACHE INTERNAL "" FORCE) + +set (BIN_LETTER "") +if ("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") + set (BIN_LETTER "d") +elseif ("${CMAKE_BUILD_TYPE}" STREQUAL "RelWithDebInfo") + set (BIN_LETTER "i") +endif() + +# Get all used variables: OS_WITH_BIT, COMPILER +OCCT_MAKE_OS_WITH_BITNESS() +OCCT_MAKE_COMPILER_SHORT_NAME() + +# do not define INSTALL_DIR_BIN for win. +# Leave library structure for win: /win64/vc10/bin(d) +if (NOT DEFINED INSTALL_DIR_BIN) + if ("${INSTALL_DIR_LAYOUT}" STREQUAL "Unix") + set (INSTALL_DIR_BIN "bin" CACHE PATH "${INSTALL_DIR_BIN_DESCR}") + else() + set (INSTALL_DIR_BIN "${OS_WITH_BIT}/${COMPILER}/bin" CACHE PATH "${INSTALL_DIR_BIN_DESCR}") + endif() +endif() + +# define folder contaning all shell/batch scripts +if (NOT DEFINED INSTALL_DIR_SCRIPT) + if ("${INSTALL_DIR_LAYOUT}" STREQUAL "Unix") + set (INSTALL_DIR_SCRIPT "${INSTALL_DIR_BIN}" CACHE PATH "${INSTALL_DIR_SCRIPT_DESCR}") + else() + set (INSTALL_DIR_SCRIPT "." CACHE PATH "${INSTALL_DIR_SCRIPT_DESCR}") + endif() +endif() + +# place the libraries to /lib folder for unix and leave old structure for windows +if (NOT DEFINED INSTALL_DIR_LIB) + if ("${INSTALL_DIR_LAYOUT}" STREQUAL "Unix") + set (INSTALL_DIR_LIB "lib" CACHE PATH "${INSTALL_DIR_LIB_DESCR}") + else() + set (INSTALL_DIR_LIB "${OS_WITH_BIT}/${COMPILER}/lib" CACHE PATH "${INSTALL_DIR_LIB_DESCR}") + endif() +endif() + +# OCCT headers: /inc for windows, +# /include/opencascade-7.0.0 for unix +if (NOT DEFINED INSTALL_DIR_INCLUDE) + if ("${INSTALL_DIR_LAYOUT}" STREQUAL "Unix") + set (INSTALL_DIR_INCLUDE "include/opencascade" CACHE PATH "${INSTALL_DIR_INCLUDE_DESCR}") + if (INSTALL_DIR_WITH_VERSION) + set (INSTALL_DIR_INCLUDE "include/opencascade-${OCC_VERSION_STRING_EXT}" CACHE PATH "${INSTALL_DIR_INCLUDE_DESCR}" FORCE) + endif() + else() + set (INSTALL_DIR_INCLUDE "inc" CACHE PATH "${INSTALL_DIR_INCLUDE_DESCR}") + endif() +endif() + +# OCCT resources: /src for windows, +# /share/opencascade-7.0.0/resources for unix +if (NOT DEFINED INSTALL_DIR_RESOURCE) + if ("${INSTALL_DIR_LAYOUT}" STREQUAL "Unix") + set (INSTALL_DIR_RESOURCE "share/opencascade/resources" CACHE PATH "${INSTALL_DIR_RESOURCE_DESCR}") + if (INSTALL_DIR_WITH_VERSION) + set (INSTALL_DIR_RESOURCE "share/opencascade-${OCC_VERSION_STRING_EXT}/resources" CACHE PATH "${INSTALL_DIR_RESOURCE_DESCR}" FORCE) + endif() + else() + set (INSTALL_DIR_RESOURCE "src" CACHE PATH "${INSTALL_DIR_RESOURCE_DESCR}") + endif() +endif() + +# OCCT data +if (NOT DEFINED INSTALL_DIR_DATA) + if ("${INSTALL_DIR_LAYOUT}" STREQUAL "Unix") + set (INSTALL_DIR_DATA "share/opencascade/data" CACHE PATH "${INSTALL_DIR_DATA_DESCR}") + if (INSTALL_DIR_WITH_VERSION) + set (INSTALL_DIR_DATA "share/opencascade-${OCC_VERSION_STRING_EXT}/data" CACHE PATH "${INSTALL_DIR_DATA_DESCR}" FORCE) + endif() + else() + set (INSTALL_DIR_DATA "data" CACHE PATH "${INSTALL_DIR_DATA_DESCR}") + endif() +endif() + +# OCCT samples +if (NOT DEFINED INSTALL_DIR_SAMPLES) + if ("${INSTALL_DIR_LAYOUT}" STREQUAL "Unix") + set (INSTALL_DIR_SAMPLES "share/opencascade/samples" CACHE PATH "${INSTALL_DIR_SAMPLES_DESCR}") + if (INSTALL_DIR_WITH_VERSION) + set (INSTALL_DIR_SAMPLES "share/opencascade-${OCC_VERSION_STRING_EXT}/samples" CACHE PATH "${INSTALL_DIR_SAMPLES_DESCR}" FORCE) + endif() + else() + set (INSTALL_DIR_SAMPLES "samples" CACHE PATH "${INSTALL_DIR_SAMPLES_DESCR}") + endif() +endif() + +# OCCT tests +if (NOT DEFINED INSTALL_DIR_TESTS) + if ("${INSTALL_DIR_LAYOUT}" STREQUAL "Unix") + set (INSTALL_DIR_TESTS "share/opencascade/tests" CACHE PATH "${INSTALL_DIR_TESTS_DESCR}") + if (INSTALL_DIR_WITH_VERSION) + set (INSTALL_DIR_TESTS "share/opencascade-${OCC_VERSION_STRING_EXT}/tests" CACHE PATH "${INSTALL_DIR_TESTS_DESCR}" FORCE) + endif() + else() + set (INSTALL_DIR_TESTS "tests" CACHE PATH "${INSTALL_DIR_TESTS_DESCR}") + endif() +endif() + +# OCCT doc +if (NOT DEFINED INSTALL_DIR_DOC) + if ("${INSTALL_DIR_LAYOUT}" STREQUAL "Unix") + set (INSTALL_DIR_DOC "share/doc/opencascade" CACHE PATH "${INSTALL_DIR_DOC_DESCR}") + if (INSTALL_DIR_WITH_VERSION) + set (INSTALL_DIR_DOC "share/doc/opencascade-${OCC_VERSION_STRING_EXT}" CACHE PATH "${INSTALL_DIR_DOC_DESCR}" FORCE) + endif() + else() + set (INSTALL_DIR_DOC "doc" CACHE PATH "${INSTALL_DIR_DOC_DESCR}") + endif() +endif() + +# define folder contaning CMake configuration files +if (NOT DEFINED INSTALL_DIR_CMAKE) + if ("${INSTALL_DIR_LAYOUT}" STREQUAL "Unix") + if (INSTALL_DIR_WITH_VERSION) + set (INSTALL_DIR_CMAKE "lib/cmake/opencascade-${OCC_VERSION_STRING_EXT}" CACHE PATH "${INSTALL_DIR_CMAKE_DESCR}") + else() + set (INSTALL_DIR_CMAKE "lib/cmake/opencascade" CACHE PATH "${INSTALL_DIR_CMAKE_DESCR}") + endif() + else() + set (INSTALL_DIR_CMAKE "cmake" CACHE PATH "${INSTALL_DIR_CMAKE_DESCR}") + endif() +endif() + +# include occt macros +OCCT_INCLUDE_CMAKE_FILE ("adm/cmake/occt_resources") + +# install LICENSE_LGPL_21.txt and OCCT_LGPL_EXCEPTION.txt files +if ("${INSTALL_DIR_LAYOUT}" STREQUAL "Unix") + OCCT_INSTALL_FILE_OR_DIR ("LICENSE_LGPL_21.txt" "${INSTALL_DIR_DOC}") + OCCT_INSTALL_FILE_OR_DIR ("OCCT_LGPL_EXCEPTION.txt" "${INSTALL_DIR_DOC}") +else() + OCCT_INSTALL_FILE_OR_DIR ("LICENSE_LGPL_21.txt" ".") + OCCT_INSTALL_FILE_OR_DIR ("OCCT_LGPL_EXCEPTION.txt" ".") +endif() + +if(APPLE) + set (INSTALL_NAME_DIR "" CACHE STRING "install_name library suffix on OS X (e.g. @executable_path/../Frameworks)") +endif() + +# a directory recognized as a 'patch' for OCCT +set (BUILD_PATCH "" CACHE PATH "${BUILD_PATCH_DESCR}") + +# the list of being built toolkits +set (BUILD_ADDITIONAL_TOOLKITS "" CACHE STRING "${BUILD_ADDITIONAL_TOOLKITS_DESCR}") +separate_arguments (BUILD_ADDITIONAL_TOOLKITS) + +if (MSVC) + set (BUILD_MODULE_MfcSamples OFF CACHE BOOL "${BUILD_MODULE_MfcSamples_DESCR}") +endif() + +set (BUILD_Inspector OFF CACHE BOOL "${BUILD_Inspector_DESCR}") + +# uwp sample +if (MSVC) + if ("${CMAKE_SYSTEM_NAME}" STREQUAL "WindowsStore") + set (BUILD_MODULE_UwpSample OFF CACHE BOOL "${BUILD_MODULE_UwpSample_DESCR}") + else() + unset (BUILD_MODULE_UwpSample) + endif() +endif() + +# whether use optional 3rdparty or not +if (APPLE) + set (USE_GLX OFF CACHE BOOL "${USE_GLX_DESCR}") +endif() + +if (WIN32) + set (USE_D3D OFF CACHE BOOL "${USE_D3D_DESCR}") +endif() + +# Enable/Disable the floating point exceptions (FPE) during runtime. +if (NOT BUILD_ENABLE_FPE_SIGNAL_HANDLER) + set (BUILD_ENABLE_FPE_SIGNAL_HANDLER OFF CACHE BOOL "${BUILD_ENABLE_FPE_SIGNAL_HANDLER_DESCR}" FORCE) +endif() + +if (BUILD_ENABLE_FPE_SIGNAL_HANDLER) + set (BUILD_ENABLE_FPE_SIGNAL_HANDLER 1) +else() + set (BUILD_ENABLE_FPE_SIGNAL_HANDLER 0) +endif() + +# include the patched or original list of modules +# list _TOOLKITS is created foreach module and contains its toolkits +# list will contain all modules +OCCT_MODULES_AND_TOOLKITS (OCCT_MODULES) + +foreach (OCCT_MODULE ${OCCT_MODULES}) + BUILD_MODULE (${OCCT_MODULE}) +endforeach() + +if (ANDROID AND BUILD_MODULE_Draw) + message (STATUS "Info. Draw module is turned off due to it is not supported on Android") + set (BUILD_MODULE_Draw OFF CACHE BOOL "${BUILD_MODULE_Draw_DESCR}" FORCE) +endif() +if ("${CMAKE_SYSTEM_NAME}" STREQUAL "WindowsStore" AND BUILD_MODULE_Draw) + message (STATUS "Info. Draw module is turned off due to it is not supported on UWP") + set (BUILD_MODULE_Draw OFF CACHE BOOL "${BUILD_MODULE_Draw_DESCR}" FORCE) +endif() + +# Overview +if (NOT DEFINED BUILD_DOC_Overview) + set (DO_ONLY_CHECK_FOR_DOXYGEN ON) + OCCT_INCLUDE_CMAKE_FILE ("adm/cmake/doxygen") + set (DO_ONLY_CHECK_FOR_DOXYGEN OFF) + + if (CAN_DOXYGEN_BE_USED) + message (STATUS "Info. Overview building is turned on") + endif() + + set (BUILD_DOC_Overview ${CAN_DOXYGEN_BE_USED} CACHE BOOL "${BUILD_DOC_Overview_DESCR}") +endif() + +if (NOT USE_D3D) + list (REMOVE_ITEM Visualization_TOOLKITS TKD3DHost) +endif() + +# accumulate used toolkits (first level) in BUILD_TOOLKITS variable +list (APPEND BUILD_TOOLKITS ${BUILD_ADDITIONAL_TOOLKITS}) + +foreach (OCCT_MODULE ${OCCT_MODULES}) + if (BUILD_MODULE_${OCCT_MODULE}) + list (APPEND BUILD_TOOLKITS ${${OCCT_MODULE}_TOOLKITS}) + endif() +endforeach() + +# DRAWEXE excluded when library build is static +if (NOT BUILD_SHARED_LIBS) + list (REMOVE_ITEM BUILD_TOOLKITS DRAWEXE) + message (STATUS "Info: DRAWEXE is not included due to ${BUILD_LIBRARY_TYPE} build library type") + # IfcOpenShell begin + add_definitions(-DHAVE_NO_DLL) + # IfcOpenShell end +endif() + +# accumulate all used toolkits +list (REMOVE_DUPLICATES BUILD_TOOLKITS) +set (RAW_BUILD_TOOLKITS) +foreach (BUILD_TOOLKIT ${BUILD_TOOLKITS}) + OCCT_TOOLKIT_FULL_DEP (${BUILD_TOOLKIT} TOOLKIT_FULL_DEPS) + list (APPEND RAW_BUILD_TOOLKITS ${BUILD_TOOLKIT} ${TOOLKIT_FULL_DEPS}) +endforeach() + +list (REMOVE_DUPLICATES RAW_BUILD_TOOLKITS) +set (BUILD_TOOLKITS ${RAW_BUILD_TOOLKITS}) + +# include the patched or original list of definitions and flags +OCCT_INCLUDE_CMAKE_FILE ("adm/cmake/occt_defs_flags") + +OCCT_INCLUDE_CMAKE_FILE ("adm/cmake/3rdparty_macro") + +# search for TKIVtk and TKIVtkDraw in BUILD_TOOLKITS +list (FIND BUILD_TOOLKITS TKIVtk CAN_USE_VTK) +if (CAN_USE_VTK EQUAL -1) + list (FIND BUILD_TOOLKITS TKIVtkDraw CAN_USE_VTK) +endif() + +if (NOT CAN_USE_VTK EQUAL -1) + if (NOT DEFINED USE_VTK) + set (USE_VTK OFF CACHE BOOL "${USE_VTK_DESCR}") + endif() +else() + OCCT_CHECK_AND_UNSET (USE_VTK) +endif() + +# Rebuild *.yacc and *.lex files that are contained by TKMath toolkit +list (FIND BUILD_TOOLKITS TKMath CAN_REBUILD_PDC_FOR_TKMATH) +list (FIND BUILD_TOOLKITS StepFile CAN_REBUILD_PDC_FOR_STEPFILE) + +if (NOT ${CAN_REBUILD_PDC_FOR_TKMATH} EQUAL -1 OR NOT ${CAN_REBUILD_PDC_FOR_STEPFILE} EQUAL -1) + set (BUILD_YACCLEX OFF CACHE BOOL "${BUILD_YACCLEX_DESCR}") +else() + OCCT_CHECK_AND_UNSET (BUILD_YACCLEX) +endif() + +if (NOT DEFINED 3RDPARTY_DIR) + set (3RDPARTY_DIR "" CACHE PATH ${3RDPARTY_DIR_DESCR}) + get_filename_component (3RDPARTY_DIR "${3RDPARTY_DIR}" ABSOLUTE) +else() + file (TO_CMAKE_PATH "${3RDPARTY_DIR}" 3RDPARTY_DIR) + set (3RDPARTY_DIR "${3RDPARTY_DIR}" CACHE PATH "${3RDPARTY_DIR_DESCR}" FORCE) +endif() + +# search for CSF variable in EXTERNLIB of each being used toolkit +OCCT_IS_PRODUCT_REQUIRED (CSF_FreeImagePlus CAN_USE_FREEIMAGE) +OCCT_IS_PRODUCT_REQUIRED (CSF_TclLibs USE_TCL) +OCCT_IS_PRODUCT_REQUIRED (CSF_FREETYPE USE_FREETYPE) +OCCT_IS_PRODUCT_REQUIRED (CSF_OpenGlLibs CAN_USE_GLES2) +OCCT_IS_PRODUCT_REQUIRED (CSF_GL2PS CAN_USE_GL2PS) +OCCT_IS_PRODUCT_REQUIRED (CSF_TBB CAN_USE_TBB) +OCCT_IS_PRODUCT_REQUIRED (CSF_EIGEN CAN_USE_EIGEN) + +# define CSF variable +OCCT_INCLUDE_CMAKE_FILE ("adm/cmake/occt_csf") + +if (USE_TCL) + message (STATUS "Info: TCL is used by OCCT") + OCCT_INCLUDE_CMAKE_FILE ("adm/cmake/tcl") + + message (STATUS "Info: TK is used by OCCT") + OCCT_INCLUDE_CMAKE_FILE ("adm/cmake/tk") +else() + OCCT_CHECK_AND_UNSET_GROUP ("3RDPARTY_TCL") + OCCT_CHECK_AND_UNSET_GROUP ("3RDPARTY_TK") + + OCCT_CHECK_AND_UNSET ("INSTALL_TCL") + OCCT_CHECK_AND_UNSET ("INSTALL_TK") +endif() + +if (USE_FREETYPE) + message (STATUS "Info: Freetype is used by OCCT") + OCCT_INCLUDE_CMAKE_FILE ("adm/cmake/freetype") +else() + OCCT_CHECK_AND_UNSET_GROUP ("3RDPARTY_FREETYPE") + OCCT_CHECK_AND_UNSET ("3RDPARTY_FREETYPE_INCLUDE_DIR_freetype2") + OCCT_CHECK_AND_UNSET ("3RDPARTY_FREETYPE_INCLUDE_DIR_ft2build") + OCCT_CHECK_AND_UNSET ("INSTALL_FREETYPE") +endif() + +# VTK +if (USE_VTK) + add_definitions (-DHAVE_VTK) + set (OCCT_VTK_USED_TARGETS "" CACHE INTERNAL "" FORCE) + OCCT_INCLUDE_CMAKE_FILE ("adm/cmake/vtk") +else() + OCCT_CHECK_AND_UNSET_GROUP ("3RDPARTY_VTK") + + if (NOT CAN_USE_VTK EQUAL -1) + message (STATUS "Info: TKIVtk and TKIVtkDraw toolkits excluded due to VTK usage is disabled") + + list (REMOVE_ITEM BUILD_TOOLKITS TKIVtk) + list (REMOVE_ITEM BUILD_TOOLKITS TKIVtkDraw) + endif() +endif() + +# D3D +if (USE_D3D) + add_definitions (-DHAVE_D3D) + #if(MSVC_VERSION LESS 1700) + #OCCT_INCLUDE_CMAKE_FILE ("adm/cmake/d3d") + #endif() +endif() + +# GLX +if (USE_GLX) + add_definitions (-DMACOSX_USE_GLX) + OCCT_INCLUDE_CMAKE_FILE ("adm/cmake/glx") +endif() + +# FREEIMAGE + +if (CAN_USE_FREEIMAGE) + set (USE_FREEIMAGE OFF CACHE BOOL "${USE_FREEIMAGE_DESCR}") + + if (USE_FREEIMAGE) + add_definitions (-DHAVE_FREEIMAGE) + OCCT_INCLUDE_CMAKE_FILE ("adm/cmake/freeimage") + else() + OCCT_CHECK_AND_UNSET_GROUP ("3RDPARTY_FREEIMAGE") + OCCT_CHECK_AND_UNSET ("INSTALL_FREEIMAGE") + endif() +else() + OCCT_CHECK_AND_UNSET ("USE_FREEIMAGE") + + OCCT_CHECK_AND_UNSET_GROUP ("3RDPARTY_FREEIMAGE") + OCCT_CHECK_AND_UNSET ("INSTALL_FREEIMAGE") +endif() + +# FFmpeg +# search for CSF_FFmpeg variable in EXTERNLIB of each being used toolkit +OCCT_IS_PRODUCT_REQUIRED (CSF_FFmpeg CAN_USE_FFMPEG) + +if (CAN_USE_FFMPEG) + set (USE_FFMPEG OFF CACHE BOOL "${USE_FFMPEG_DESCR}") + + if (USE_FFMPEG) + add_definitions (-DHAVE_FFMPEG) + OCCT_INCLUDE_CMAKE_FILE ("adm/cmake/ffmpeg") + else() + OCCT_CHECK_AND_UNSET_GROUP ("3RDPARTY_FFMPEG") + OCCT_CHECK_AND_UNSET ("INSTALL_FFMPEG") + endif() +else() + OCCT_CHECK_AND_UNSET ("USE_FFMPEG") + + OCCT_CHECK_AND_UNSET_GROUP ("3RDPARTY_FFMPEG") + OCCT_CHECK_AND_UNSET ("INSTALL_FFMPEG") +endif() + +# OpenGL ES 2.0 +if (WIN32 AND CAN_USE_GLES2) + if ("${CMAKE_SYSTEM_NAME}" STREQUAL "WindowsStore") + set (USE_GLES2 ON) + else() + set (USE_GLES2 OFF CACHE BOOL "${USE_GLES2_DESCR}") + endif() + + if (USE_GLES2) + add_definitions (-DHAVE_GLES2) + OCCT_INCLUDE_CMAKE_FILE ("adm/cmake/egl") + OCCT_INCLUDE_CMAKE_FILE ("adm/cmake/gles2") + else() + OCCT_CHECK_AND_UNSET_GROUP ("3RDPARTY_EGL") + OCCT_CHECK_AND_UNSET_GROUP ("3RDPARTY_GLES2") + OCCT_CHECK_AND_UNSET ("INSTALL_EGL") + OCCT_CHECK_AND_UNSET ("INSTALL_GLES2") + endif() +else() + OCCT_CHECK_AND_UNSET ("USE_GLES2") + + OCCT_CHECK_AND_UNSET_GROUP ("3RDPARTY_EGL") + OCCT_CHECK_AND_UNSET_GROUP ("3RDPARTY_GLES2") + OCCT_CHECK_AND_UNSET ("INSTALL_EGL") + OCCT_CHECK_AND_UNSET ("INSTALL_GLES2") +endif() + +# GL2PS +if (NOT DEFINED ANDROID AND CAN_USE_GL2PS) + set (USE_GL2PS OFF CACHE BOOL "${USE_GL2PS_DESCR}") + + if (USE_GL2PS) + add_definitions (-DHAVE_GL2PS) + OCCT_INCLUDE_CMAKE_FILE ("adm/cmake/gl2ps") + else() + OCCT_CHECK_AND_UNSET_GROUP ("3RDPARTY_GL2PS") + OCCT_CHECK_AND_UNSET ("INSTALL_GL2PS") + endif() +else() + OCCT_CHECK_AND_UNSET ("USE_GL2PS") + + OCCT_CHECK_AND_UNSET_GROUP ("3RDPARTY_GL2PS") + OCCT_CHECK_AND_UNSET ("INSTALL_GL2PS") +endif() + +# TBB +if (NOT DEFINED ANDROID AND CAN_USE_TBB) + set (USE_TBB OFF CACHE BOOL "${USE_TBB_DESCR}") + + if (USE_TBB) + add_definitions (-DHAVE_TBB) + OCCT_INCLUDE_CMAKE_FILE ("adm/cmake/tbb") + else() + OCCT_CHECK_AND_UNSET_GROUP ("3RDPARTY_TBB") + OCCT_CHECK_AND_UNSET_GROUP ("3RDPARTY_TBBMALLOC") + OCCT_CHECK_AND_UNSET ("INSTALL_TBB") + endif() +else() + OCCT_CHECK_AND_UNSET ("USE_TBB") + + OCCT_CHECK_AND_UNSET_GROUP ("3RDPARTY_TBB") + OCCT_CHECK_AND_UNSET_GROUP ("3RDPARTY_TBBMALLOC") + OCCT_CHECK_AND_UNSET ("INSTALL_TBB") +endif() + +# EIGEN +if (CAN_USE_EIGEN) + set (USE_EIGEN OFF CACHE BOOL "${USE_EIGEN_DESCR}") + + if (USE_EIGEN) + add_definitions (-DHAVE_EIGEN) + OCCT_INCLUDE_CMAKE_FILE ("adm/cmake/eigen") + else() + OCCT_CHECK_AND_UNSET_GROUP ("3RDPARTY_EIGEN") + OCCT_CHECK_AND_UNSET ("INSTALL_EIGEN") + endif() +else() + OCCT_CHECK_AND_UNSET ("USE_EIGEN") + + OCCT_CHECK_AND_UNSET_GROUP ("3RDPARTY_EIGEN") + OCCT_CHECK_AND_UNSET ("INSTALL_EIGEN") +endif() + +# Doxygen +if (BUILD_DOC_Overview) + if (NOT DEFINED INSTALL_DOC_Overview) + set (INSTALL_DOC_Overview OFF CACHE BOOL "${INSTALL_DOC_Overview_DESCR}") + endif() + + if (INSTALL_DOC_Overview) + install (DIRECTORY "${CMAKE_BINARY_DIR}/doc/overview" DESTINATION "${INSTALL_DIR_DOC}") + + # create overview.html only for windows + if (WIN32 AND "${INSTALL_DIR_LAYOUT}" STREQUAL "Windows") + OCCT_INSTALL_FILE_OR_DIR ("dox/resources/overview.html" "${INSTALL_DIR_DOC}/..") + endif() + endif() + + OCCT_INCLUDE_CMAKE_FILE ("adm/cmake/doxygen") +else() + OCCT_CHECK_AND_UNSET ("INSTALL_DOC_Overview") + + OCCT_CHECK_AND_UNSET ("3RDPARTY_DOXYGEN_EXECUTABLE") + OCCT_CHECK_AND_UNSET ("3RDPARTY_DOT_EXECUTABLE") +endif() + +# bison +if (BUILD_YACCLEX) + OCCT_INCLUDE_CMAKE_FILE ("adm/cmake/bison") +else() + OCCT_CHECK_AND_UNSET ("3RDPARTY_BISON_EXECUTABLE") +endif() + +# flex +if (BUILD_YACCLEX) + OCCT_INCLUDE_CMAKE_FILE ("adm/cmake/flex") +else() + OCCT_CHECK_AND_UNSET ("3RDPARTY_FLEX_EXECUTABLE") +endif() + +string (REGEX REPLACE ";" " " 3RDPARTY_NOT_INCLUDED "${3RDPARTY_NOT_INCLUDED}") + +# check all 3rdparty paths +if (3RDPARTY_NOT_INCLUDED) + message (FATAL_ERROR "NOT FOUND: ${3RDPARTY_NOT_INCLUDED}" ) +endif() + +if (3RDPARTY_INCLUDE_DIRS) + list (REMOVE_DUPLICATES 3RDPARTY_INCLUDE_DIRS) + string (REGEX REPLACE ";" "\n\t" 3RDPARTY_INCLUDE_DIRS_WITH_ENDS "${3RDPARTY_INCLUDE_DIRS}") + message (STATUS "Info: The directories of 3rdparty headers: \n\t${3RDPARTY_INCLUDE_DIRS_WITH_ENDS}") + include_directories (${3RDPARTY_INCLUDE_DIRS}) +endif() + +# include /inc +include_directories (${CMAKE_BINARY_DIR}/${INSTALL_DIR_INCLUDE}) + +if (3RDPARTY_LIBRARY_DIRS AND BUILD_SHARED_LIBS) + list (REMOVE_DUPLICATES 3RDPARTY_LIBRARY_DIRS) + string (REGEX REPLACE ";" "\n\t" 3RDPARTY_LIBRARY_DIRS_WITH_ENDS "${3RDPARTY_LIBRARY_DIRS}") + message (STATUS "Info: The directories of 3rdparty libraries: \n\t${3RDPARTY_LIBRARY_DIRS_WITH_ENDS}") + link_directories (${3RDPARTY_LIBRARY_DIRS}) +endif() + +# build directories +if (SINGLE_GENERATOR) + set (CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/lib${BIN_LETTER}") + set (CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/bin${BIN_LETTER}") + set (CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/lib${BIN_LETTER}") + if (WIN32) + set (CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/bin${BIN_LETTER}") + endif() +endif() + +set (CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/lib") +set (CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/bin") +set (CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/lib") + +set (CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/libi") +set (CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/bini") +set (CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/libi") + +set (CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/libd") +set (CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/bind") +set (CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/libd") + +if (WIN32) + set (CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/bin") + set (CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/bini") + set (CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/bind") +endif() + +string(TIMESTAMP CURRENT_TIME "%H:%M:%S") +message (STATUS "\nInfo: \(${CURRENT_TIME}\) Start collecting all OCCT header files into ${CMAKE_BINARY_DIR}/inc ...") + +# collect all the headers to /inc folder +COLLECT_AND_INSTALL_OCCT_HEADER_FILES ("${CMAKE_BINARY_DIR}" "${BUILD_TOOLKITS}" "${CMAKE_SOURCE_DIR}/src" "${INSTALL_DIR_INCLUDE}") + +string(TIMESTAMP CURRENT_TIME "%H:%M:%S") +message (STATUS "Info: \(${CURRENT_TIME}\) End the collecting") + +list (FIND BUILD_TOOLKITS DRAWEXE DRAWEXE_INDEX) +if (${DRAWEXE_INDEX} GREATER -1) + OCCT_INSTALL_FILE_OR_DIR ("data/" "${INSTALL_DIR_DATA}") + OCCT_INSTALL_FILE_OR_DIR ("samples/tcl" "${INSTALL_DIR_SAMPLES}") +endif() + +if (WIN32) + set (SCRIPT_EXT bat) +else() + set (SCRIPT_EXT sh) +endif() + +# OCCT tools +# include the patched or original list of tools +# list _TOOLKITS is created foreach tool and contains its toolkits +# list will contain all tools +if (NOT BUILD_Inspector) + OCCT_CHECK_AND_UNSET_GROUP ("3RDPARTY_QT") + OCCT_CHECK_AND_UNSET_GROUP ("3RDPARTY_TQTMALLOC") + OCCT_CHECK_AND_UNSET ("INSTALL_QT") +else() + OCCT_TOOLS_AND_TOOLKITS (OCCT_TOOLS) + foreach (OCCT_TOOL ${OCCT_TOOLS}) + list (APPEND BUILD_TOOL_TOOLKITS ${${OCCT_TOOL}_TOOL_TOOLKITS}) + endforeach() + + # collect all the headers to /inc folder + string(TIMESTAMP CURRENT_TIME "%H:%M:%S") + message (STATUS "\nInfo: \(${CURRENT_TIME}\) Start collecting all OCCT tool header files into ${CMAKE_BINARY_DIR}/tools/inc ...") + COLLECT_AND_INSTALL_OCCT_HEADER_FILES ("${CMAKE_BINARY_DIR}" "${BUILD_TOOL_TOOLKITS}" "${CMAKE_SOURCE_DIR}/tools" "${INSTALL_DIR_INCLUDE}/inspector") + + + # check qt 3rdparty path + add_definitions (-DHAVE_QT) + OCCT_INCLUDE_CMAKE_FILE ("adm/cmake/qt") + message (STATUS "Info: Qt is used by OCCT") +endif() + +# OCCT samples +# get absolute path from INSTALL_DIR +set (INSTALL_DIR_ABSOLUTE "${INSTALL_DIR}") +if(NOT IS_ABSOLUTE "${INSTALL_DIR_ABSOLUTE}") + get_filename_component(INSTALL_DIR_ABSOLUTE "${CMAKE_BINARY_DIR}/${INSTALL_DIR}" ABSOLUTE) +endif() + +if (INSTALL_SAMPLES) + OCCT_CONFIGURE ("adm/templates/env.samples.${SCRIPT_EXT}.in" "env.samples.${SCRIPT_EXT}") + if (WIN32) + OCCT_INSTALL_FILE_OR_DIR ("samples/CSharp" "${INSTALL_DIR_SAMPLES}") + OCCT_INSTALL_FILE_OR_DIR ("samples/mfc" "${INSTALL_DIR_SAMPLES}") + + if ("${CMAKE_SYSTEM_NAME}" STREQUAL "WindowsStore") + OCCT_INSTALL_FILE_OR_DIR ("samples/xaml" "${INSTALL_DIR_SAMPLES}") + endif() + + install (FILES "${CMAKE_BINARY_DIR}/env.samples.${SCRIPT_EXT}" DESTINATION "${INSTALL_DIR_SAMPLES}/CSharp" RENAME "env.${SCRIPT_EXT}") + install (FILES "${CMAKE_BINARY_DIR}/env.samples.${SCRIPT_EXT}" DESTINATION "${INSTALL_DIR_SAMPLES}/mfc/standard" RENAME "env.${SCRIPT_EXT}") + endif() + + OCCT_INSTALL_FILE_OR_DIR ("samples/java" "${INSTALL_DIR_SAMPLES}") + OCCT_INSTALL_FILE_OR_DIR ("samples/ocafsamples" "${INSTALL_DIR_SAMPLES}") + OCCT_INSTALL_FILE_OR_DIR ("samples/qt" "${INSTALL_DIR_SAMPLES}") + + install (FILES "${CMAKE_BINARY_DIR}/env.samples.${SCRIPT_EXT}" DESTINATION "${INSTALL_DIR_SAMPLES}/qt/FuncDemo" RENAME "env.${SCRIPT_EXT}") + install (FILES "${CMAKE_BINARY_DIR}/env.samples.${SCRIPT_EXT}" DESTINATION "${INSTALL_DIR_SAMPLES}/qt/IESample" RENAME "env.${SCRIPT_EXT}") + install (FILES "${CMAKE_BINARY_DIR}/env.samples.${SCRIPT_EXT}" DESTINATION "${INSTALL_DIR_SAMPLES}/qt/Tutorial" RENAME "env.${SCRIPT_EXT}") +endif() + +if (INSTALL_TEST_CASES) + OCCT_INSTALL_FILE_OR_DIR ("tests/" "${INSTALL_DIR_TESTS}") +endif() + +list (FIND BUILD_TOOLKITS DRAWEXE DRAWEXE_INDEX) +if (${DRAWEXE_INDEX} GREATER -1) + # copy data and samples/tcl folders to install script folder + OCCT_INSTALL_FILE_OR_DIR ("data/" "${INSTALL_DIR_DATA}") + OCCT_INSTALL_FILE_OR_DIR ("samples/tcl" "${INSTALL_DIR_SAMPLES}") + + # copy draw script to install script folder + if (BUILD_PATCH AND EXISTS "${BUILD_PATCH}/adm/templates/draw.${SCRIPT_EXT}") + install (FILES "${BUILD_PATCH}/adm/templates/draw.${SCRIPT_EXT}" DESTINATION "${INSTALL_DIR_SCRIPT}" + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_WRITE GROUP_EXECUTE WORLD_READ WORLD_WRITE WORLD_EXECUTE) + else() + install (FILES "${CMAKE_SOURCE_DIR}/adm/templates/draw.${SCRIPT_EXT}" DESTINATION "${INSTALL_DIR_SCRIPT}" + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_WRITE GROUP_EXECUTE WORLD_READ WORLD_WRITE WORLD_EXECUTE) + endif() + + # copy draw script to CMake binary folder + OCCT_COPY_FILE_OR_DIR ("adm/templates/draw.${SCRIPT_EXT}" "${CMAKE_BINARY_DIR}") +endif() + +set (SUB_CUSTOM_NAME "custom_${COMPILER}_${COMPILER_BITNESS}.${SCRIPT_EXT}") + +if (WIN32) + set (ADDITIONAL_CUSTOM_CONTENT "\nif exist \"%~dp0${SUB_CUSTOM_NAME}\" (\n call \"%~dp0${SUB_CUSTOM_NAME}\" %1 %2 %3 \n)") +else() + set (ADDITIONAL_CUSTOM_CONTENT "\nif [ -e \"\${aScriptPath}/${SUB_CUSTOM_NAME}\" ]; then\n source \"\${aScriptPath}/${SUB_CUSTOM_NAME}\" \"\$1\" \"\$2\" \nfi") +endif() + + # change custom.bat/sh +if (EXISTS "${INSTALL_DIR}/${INSTALL_DIR_SCRIPT}/custom.${SCRIPT_EXT}") + file (READ "${INSTALL_DIR}/${INSTALL_DIR_SCRIPT}/custom.${SCRIPT_EXT}" CUSTOM_CONTENT) + + set (CUSTOM_CONTENT "${CUSTOM_CONTENT} ${ADDITIONAL_CUSTOM_CONTENT}") + + file (WRITE "${INSTALL_DIR}/${INSTALL_DIR_SCRIPT}/custom.${SCRIPT_EXT}" "${CUSTOM_CONTENT}") +else() + OCCT_CONFIGURE_AND_INSTALL ("adm/templates/custom.${SCRIPT_EXT}.main" "custom.${SCRIPT_EXT}" "custom.${SCRIPT_EXT}" "${INSTALL_DIR_SCRIPT}") +endif() + +if (WIN32) + set (THIRDPARTY_DIR_REPLACE "%THIRDPARTY_DIR%") +else() + set (THIRDPARTY_DIR_REPLACE "\${THIRDPARTY_DIR}") +endif() +get_cmake_property(USED_3RDPARTY_CACHE_VARIABLES VARIABLES) +string (REGEX MATCHALL "(^|;)USED_3RDPARTY_[^;]+_DIR[^;]*" USED_3RDPARTY_CACHE_VARIABLES "${USED_3RDPARTY_CACHE_VARIABLES}") +file (TO_CMAKE_PATH "${3RDPARTY_DIR}" 3RDPARTY_DIR) +foreach (USED_3RDPARTY_CACHE_VARIABLE ${USED_3RDPARTY_CACHE_VARIABLES}) + file (TO_CMAKE_PATH "${${USED_3RDPARTY_CACHE_VARIABLE}}" ${USED_3RDPARTY_CACHE_VARIABLE}) + string (REPLACE "${3RDPARTY_DIR}" "${THIRDPARTY_DIR_REPLACE}" ${USED_3RDPARTY_CACHE_VARIABLE} "${${USED_3RDPARTY_CACHE_VARIABLE}}") + if (NOT WIN32) + string (REGEX REPLACE ";" ":" ${USED_3RDPARTY_CACHE_VARIABLE} "${${USED_3RDPARTY_CACHE_VARIABLE}}") + endif() +endforeach() + +# write current custom.bat/sh (for install directory) +set (SUB_CUSTOM_BUILD_NAME "custom_${COMPILER}_${COMPILER_BITNESS}.install.${SCRIPT_EXT}") +OCCT_CONFIGURE_AND_INSTALL ("adm/templates/custom.install.${SCRIPT_EXT}.in" "${SUB_CUSTOM_BUILD_NAME}" "${SUB_CUSTOM_NAME}" "${INSTALL_DIR_SCRIPT}") + +# write current custom.bat/sh (for build directory) +OCCT_CONFIGURE ("adm/templates/custom.build.${SCRIPT_EXT}.in" "${SUB_CUSTOM_NAME}") + +if (BUILD_MODULE_MfcSamples) + OCCT_INSTALL_FILE_OR_DIR ("adm/templates/sample.bat" "${INSTALL_DIR_SCRIPT}") + OCCT_COPY_FILE_OR_DIR ("adm/templates/sample.bat" "${CMAKE_BINARY_DIR}") +endif() + +# env script for draw in building environment +OCCT_CONFIGURE ("adm/templates/env.${SCRIPT_EXT}.in" "env.${SCRIPT_EXT}") + +# install env script +install (FILES "${CMAKE_BINARY_DIR}/env.${SCRIPT_EXT}" DESTINATION "${INSTALL_DIR_SCRIPT}") + +# copy DrawAppliInit from OCCT source to build directory +if (NOT EXISTS "${CMAKE_BINARY_DIR}/DrawAppliInit") + OCCT_COPY_FILE_OR_DIR (DrawAppliInit "${CMAKE_BINARY_DIR}") +endif() + +# RESOURCES +FILE_TO_LIST ("adm/RESOURCES" RESOURCES) +foreach(RESOURCE ${RESOURCES}) + get_filename_component(RESOURCE_FOLDER ${RESOURCE} DIRECTORY) + if(NOT "${RESOURCE_FOLDER}" STREQUAL "") + get_filename_component(RESOURCE_FOLDER ${RESOURCE_FOLDER} NAME) + OCCT_INSTALL_FILE_OR_DIR ("src/${RESOURCE}" "${INSTALL_DIR_RESOURCE}/${RESOURCE_FOLDER}") + else() + OCCT_INSTALL_FILE_OR_DIR ("src/${RESOURCE}" "${INSTALL_DIR_RESOURCE}") + endif() +endforeach() + +# patch installed DrawDefault file if BUILD_SHARED_LIBRARY_NAME_POSTFIX is changed +if (NOT "${BUILD_SHARED_LIBRARY_NAME_POSTFIX}" STREQUAL "") + OCCT_UPDATE_DRAW_DEFAULT_FILE() +endif() + +# include patched toolkit projects or original ones +foreach (BUILD_TOOLKIT ${BUILD_TOOLKITS}) + OCCT_ADD_SUBDIRECTORY ("src/${BUILD_TOOLKIT}") +endforeach() + +if (BUILD_DOC_Overview) + OCCT_ADD_SUBDIRECTORY (dox) +endif() + +# patch DRAWEXE +if (MSVC AND 3RDPARTY_DLL_DIRS) + list (FIND BUILD_TOOLKITS DRAWEXE DRAWEXE_INDEX) + if (${DRAWEXE_INDEX} GREATER -1) + list (REMOVE_DUPLICATES 3RDPARTY_DLL_DIRS) + set (3RDPARTY_DLL_DIRS_FOR_PATH "") + + foreach (3RDPARTY_DLL_DIR ${3RDPARTY_DLL_DIRS}) + set (3RDPARTY_DLL_DIRS_FOR_PATH "${3RDPARTY_DLL_DIRS_FOR_PATH};${3RDPARTY_DLL_DIR}") + endforeach() + + OCCT_MAKE_COMPILER_BITNESS() + set (X_COMPILER_BITNESS "x64") + if ("${COMPILER_BITNESS}" STREQUAL "32") + set (X_COMPILER_BITNESS "Win32") + endif() + + OCCT_CONFIGURE ("adm/templates/DRAWEXE.vcxproj.user.in" "${CMAKE_BINARY_DIR}/src/DRAWEXE/DRAWEXE.vcxproj.user") + endif() +endif() + +# include patched toolkit projects or original ones +if (BUILD_TOOL_TOOLKITS) + foreach (BUILD_TOOL_TOOLKIT ${BUILD_TOOL_TOOLKITS}) + OCCT_ADD_SUBDIRECTORY ("tools/${BUILD_TOOL_TOOLKIT}") + endforeach() +endif() + +message (STATUS "Info: \(${CURRENT_TIME}\) OCCT toolkits processed") +# samples do not support patch usage +if (BUILD_MODULE_MfcSamples) + set (OCCT_ROOT ${CMAKE_SOURCE_DIR}) + + set (MFC_STANDARD_SAMPLES_DIR ${OCCT_ROOT}/samples/mfc/standard) + set (COMMON_WINMAIN_FILE ${MFC_STANDARD_SAMPLES_DIR}/Common/Winmain.cpp) + + add_subdirectory(samples/mfc/standard/mfcsample) + add_subdirectory(samples/mfc/standard/01_Geometry) + add_subdirectory(samples/mfc/standard/02_Modeling) + add_subdirectory(samples/mfc/standard/03_Viewer2d) + add_subdirectory(samples/mfc/standard/04_Viewer3d) + add_subdirectory(samples/mfc/standard/05_ImportExport) + add_subdirectory(samples/mfc/standard/06_Ocaf) + add_subdirectory(samples/mfc/standard/07_Triangulation) + add_subdirectory(samples/mfc/standard/08_HLR) + add_subdirectory(samples/mfc/standard/09_Animation) + add_subdirectory(samples/mfc/standard/10_Convert) + + message (STATUS "Info: \(${CURRENT_TIME}\) MFC Sample projects added") +endif() + +if (BUILD_MODULE_UwpSample) + add_subdirectory(samples/xaml) +endif() + +if (BUILD_TOOL_TOOLKITS) + # copy tinspector script to install script folder + if (BUILD_PATCH AND EXISTS "${BUILD_PATCH}/adm/templates/inspector.${SCRIPT_EXT}") + install (FILES "${BUILD_PATCH}/adm/templates/inspector.${SCRIPT_EXT}" DESTINATION "${INSTALL_DIR_SCRIPT}" + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_WRITE GROUP_EXECUTE WORLD_READ WORLD_WRITE WORLD_EXECUTE) + else() + install (FILES "${CMAKE_SOURCE_DIR}/adm/templates/inspector.${SCRIPT_EXT}" DESTINATION "${INSTALL_DIR_SCRIPT}" + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_WRITE GROUP_EXECUTE WORLD_READ WORLD_WRITE WORLD_EXECUTE) + endif() + + set (BUILD_SAMPLE_TOOLKITS TInspectorEXE) + foreach (BUILD_SAMPLE_TOOL_TOOLKIT ${BUILD_SAMPLE_TOOLKITS}) + OCCT_ADD_SUBDIRECTORY ("samples/tools/${BUILD_SAMPLE_TOOL_TOOLKIT}") + endforeach() + + # patch TInspectorEXE + OCCT_CONFIGURE ("adm/templates/TInspectorEXE.vcxproj.user.in" "${CMAKE_BINARY_DIR}/samples/tools/TInspectorEXE/TInspectorEXE.vcxproj.user") +endif() + +# Prepare variables for configuration of OpenCASCADE cmake config file +set (OCCT_MODULES_ENABLED) +set (OCCT_LIBRARIES) +set (SET_OpenCASCADE_MODULES_TOOLKITS "\n# List of available OpenCASCADE libraries for each module\n") +set (OCCT_COMPILE_DEFINITIONS) + +foreach (OCCT_TOOLKIT ${BUILD_TOOLKITS}) + if (TARGET ${OCCT_TOOLKIT}) + + # get all libraries + get_target_property (${OCCT_TOOLKIT}_TYPE ${OCCT_TOOLKIT} "TYPE") + if ("${${OCCT_TOOLKIT}_TYPE}" STREQUAL "STATIC_LIBRARY" OR "${${OCCT_TOOLKIT}_TYPE}" STREQUAL "SHARED_LIBRARY" ) + list (APPEND OCCT_LIBRARIES ${OCCT_TOOLKIT}) + + # get all modules + get_target_property (${OCCT_TOOLKIT}_MODULE ${OCCT_TOOLKIT} "MODULE") + list (APPEND OCCT_MODULES_ENABLED ${${OCCT_TOOLKIT}_MODULE}) + list (APPEND OpenCASCADE_${${OCCT_TOOLKIT}_MODULE}_TOOLKITS ${OCCT_TOOLKIT}) + + # get compile definitions of target directory + get_directory_property (COMPILE_DEFINITIONS DIRECTORY "${${OCCT_TOOLKIT}_SOURCE_DIR}" "COMPILE_DEFINITIONS") + list (APPEND OCCT_COMPILE_DEFINITIONS ${COMPILE_DEFINITIONS}) + endif() + endif() +endforeach() +list (REMOVE_DUPLICATES OCCT_MODULES_ENABLED) +list (REMOVE_DUPLICATES OCCT_COMPILE_DEFINITIONS) + +# export compile definitions and C/C++ flags for each configuration to OpenCASCADE config files +foreach (OCCT_CONFIGURATION ${CMAKE_CONFIGURATION_TYPES}) + set (SET_OpenCASCADE_COMPILE_DEFINITIONS) + string (TOUPPER "${OCCT_CONFIGURATION}" OCCT_CONFIGURATION_UPPER) + string (TOLOWER "${OCCT_CONFIGURATION}" OCCT_CONFIGURATION_LOWER) + foreach(COMPILE_DEFINITION ${OCCT_COMPILE_DEFINITIONS}) + string(REPLACE "(" "\\(" COMPILE_DEFINITION "${COMPILE_DEFINITION}") + string(REPLACE ")" "\\)" COMPILE_DEFINITION "${COMPILE_DEFINITION}") + set (SET_OpenCASCADE_COMPILE_DEFINITIONS "${SET_OpenCASCADE_COMPILE_DEFINITIONS}set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS $<$:${COMPILE_DEFINITION}>)\n") + endforeach() + set (SET_OpenCASCADE_CMAKE_C_FLAGS "${CMAKE_C_FLAGS_${OCCT_CONFIGURATION_UPPER}}") + set (SET_OpenCASCADE_CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS_${OCCT_CONFIGURATION_UPPER}}") + configure_file("${CMAKE_SOURCE_DIR}/adm/templates/OpenCASCADECompileDefinitionsAndFlags.cmake.in" "OpenCASCADECompileDefinitionsAndFlags-${OCCT_CONFIGURATION_LOWER}.cmake" @ONLY) +endforeach() +# install OpenCASCADE config file with compile definitions and C/C++ flags ONLY for current configuration +install (CODE "string (TOLOWER \"\${CMAKE_INSTALL_CONFIG_NAME}\" CMAKE_INSTALL_CONFIG_NAME_LOWER)") +install (CODE "configure_file(\"${CMAKE_BINARY_DIR}/OpenCASCADECompileDefinitionsAndFlags-\${CMAKE_INSTALL_CONFIG_NAME_LOWER}.cmake\" \"${INSTALL_DIR}/${INSTALL_DIR_CMAKE}/OpenCASCADECompileDefinitionsAndFlags-\${CMAKE_INSTALL_CONFIG_NAME_LOWER}.cmake\" COPYONLY)") + +foreach (OCCT_MODULE ${OCCT_MODULES}) + if (BUILD_MODULE_${OCCT_MODULE}) + set (SET_OpenCASCADE_MODULES_TOOLKITS "${SET_OpenCASCADE_MODULES_TOOLKITS}set (OpenCASCADE_${OCCT_MODULE}_LIBRARIES ${OpenCASCADE_${OCCT_MODULE}_TOOLKITS})\n") + endif() + + # sort enabled modules for correct work of OpenCASCADE config file + list(FIND OCCT_MODULES_ENABLED "${OCCT_MODULE}" OCCT_MODULE_INDEX) + if (NOT ${OCCT_MODULE_INDEX} EQUAL -1) + list (APPEND OCCT_MODULES_ENABLED_SORTED ${OCCT_MODULE}) + endif() +endforeach() +set (OCCT_MODULES_ENABLED ${OCCT_MODULES_ENABLED_SORTED}) + +# Add all targets to the build-tree export set +export (TARGETS ${OCCT_LIBRARIES} FILE "${CMAKE_BINARY_DIR}/OpenCASCADETargets.cmake") + +# Export the package for use from the build-tree +# (this registers the build-tree with a global CMake-registry) +export(PACKAGE OpenCASCADE) + +if (CMAKE_BUILD_TYPE) + set (SET_OpenCASCADE_BUILD_TYPE "set (OpenCASCADE_BUILD_TYPE \"${CMAKE_BUILD_TYPE}\")") +endif() + +if (BUILD_SHARED_LIBS) + set (SET_OpenCASCADE_LINKER_FLAGS "set (OpenCASCADE_LINKER_FLAGS \"${CMAKE_SHARED_LINKER_FLAGS}\")") +else() + set (SET_OpenCASCADE_LINKER_FLAGS "set (OpenCASCADE_LINKER_FLAGS \"${CMAKE_STATIC_LINKER_FLAGS}\")") +endif() + +if (WIN32) + set (SET_OpenCASCADE_WITH_D3D "set (OpenCASCADE_WITH_D3D ${USE_D3D})") +endif() +if (APPLE) + set (SET_OpenCASCADE_WITH_GLX "set (OpenCASCADE_WITH_GLX ${USE_GLX})") +endif() + +if (NOT SINGLE_GENERATOR) + OCCT_INSERT_CODE_FOR_TARGET() +endif() + +# Configure and install cmake config file +configure_file("${CMAKE_SOURCE_DIR}/adm/templates/OpenCASCADEConfig.cmake.in" "OpenCASCADEConfig.cmake" @ONLY) +install(FILES "${CMAKE_BINARY_DIR}/OpenCASCADEConfig.cmake" DESTINATION "${INSTALL_DIR_CMAKE}") + +# Configure cmake version file +include(CMakePackageConfigHelpers) +write_basic_package_version_file( ${CMAKE_BINARY_DIR}/OpenCASCADEConfigVersion.cmake + VERSION ${OCC_VERSION_MAJOR}.${OCC_VERSION_MINOR}.${OCC_VERSION_MAINTENANCE} + COMPATIBILITY ExactVersion ) + +# Install cmake version file +install (FILES "${CMAKE_BINARY_DIR}/OpenCASCADEConfigVersion.cmake" DESTINATION "${INSTALL_DIR_CMAKE}") + +# Install the export set for use with the install-tree for each configuration +foreach (OCCT_MODULE ${OCCT_MODULES_ENABLED}) + install(EXPORT OpenCASCADE${OCCT_MODULE}Targets DESTINATION "${INSTALL_DIR_CMAKE}") +endforeach() + +# Update generated OpenCASCADETargets-*.cmake files +# to have correct paths to libraries depending on the configuration +OCCT_UPDATE_TARGET_FILE () + +message (STATUS "Info: \(${CURRENT_TIME}\) OCCT configuration files prepared") diff --git a/win/patches/88af392_adm-cmake-occt_defs_flags.cmake b/win/patches/88af392_adm-cmake-occt_defs_flags.cmake new file mode 100644 index 0000000000..cd4c46531b --- /dev/null +++ b/win/patches/88af392_adm-cmake-occt_defs_flags.cmake @@ -0,0 +1,158 @@ +## + +if(FLAGS_ALREADY_INCLUDED) + return() +endif() +set(FLAGS_ALREADY_INCLUDED 1) + +# force option /fp:precise for Visual Studio projects. +# +# Note that while this option is default for MSVC compiler, Visual Studio +# project can be switched later to use Intel Compiler (ICC). +# Enforcing -fp:precise ensures that in such case ICC will use correct +# option instead of its default -fp:fast which is harmful for OCCT. +if (MSVC) + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fp:precise") + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /fp:precise") +endif() + +# set compiler short name and choose SSE2 option for appropriate MSVC compilers +# ONLY for 32-bit +if (NOT CMAKE_SIZEOF_VOID_P EQUAL 8) + if (MSVC80 OR MSVC90 OR MSVC10) + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /arch:SSE2") + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /arch:SSE2") + endif() +endif() + +if (WIN32) + add_definitions (-D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE) +else() + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexceptions -fPIC") + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fexceptions -fPIC") + add_definitions(-DOCC_CONVERT_SIGNALS) +endif() + +# enable structured exceptions for MSVC +string (REGEX MATCH "EHsc" ISFLAG "${CMAKE_CXX_FLAGS}") +if (ISFLAG) + string (REGEX REPLACE "EHsc" "EHa" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") +elseif (MSVC) + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHa") +endif() + +# remove _WINDOWS flag if it exists +string (REGEX MATCH "/D_WINDOWS" IS_WINDOWSFLAG "${CMAKE_CXX_FLAGS}") +if (IS_WINDOWSFLAG) + message (STATUS "Info: /D_WINDOWS has been removed from CMAKE_CXX_FLAGS") + string (REGEX REPLACE "/D_WINDOWS" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") +endif() + +# remove WIN32 flag if it exists +string (REGEX MATCH "/DWIN32" IS_WIN32FLAG "${CMAKE_CXX_FLAGS}") +if (IS_WIN32FLAG) + message (STATUS "Info: /DWIN32 has been removed from CMAKE_CXX_FLAGS") + string (REGEX REPLACE "/DWIN32" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") +endif() + +# remove _WINDOWS flag if it exists +string (REGEX MATCH "/D_WINDOWS" IS_WINDOWSFLAG "${CMAKE_C_FLAGS}") +if (IS_WINDOWSFLAG) + message (STATUS "Info: /D_WINDOWS has been removed from CMAKE_C_FLAGS") + string (REGEX REPLACE "/D_WINDOWS" "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") +endif() + +# remove WIN32 flag if it exists +string (REGEX MATCH "/DWIN32" IS_WIN32FLAG "${CMAKE_C_FLAGS}") +if (IS_WIN32FLAG) + message (STATUS "Info: /DWIN32 has been removed from CMAKE_C_FLAGS") + string (REGEX REPLACE "/DWIN32" "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") +endif() + +# remove DEBUG flag if it exists +string (REGEX MATCH "-DDEBUG" IS_DEBUG_CXX "${CMAKE_CXX_FLAGS_DEBUG}") +if (IS_DEBUG_CXX) + message (STATUS "Info: -DDEBUG has been removed from CMAKE_CXX_FLAGS_DEBUG") + string (REGEX REPLACE "-DDEBUG" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") +endif() + +string (REGEX MATCH "-DDEBUG" IS_DEBUG_C "${CMAKE_C_FLAGS_DEBUG}") +if (IS_DEBUG_C) + message (STATUS "Info: -DDEBUG has been removed from CMAKE_C_FLAGS_DEBUG") + string (REGEX REPLACE "-DDEBUG" "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}") +endif() +# enable parallel compilation on MSVC 9 and above +if (MSVC AND NOT MSVC70 AND NOT MSVC80) + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP") +endif() + +# generate a single response file which enlist all of the object files +SET(CMAKE_C_USE_RESPONSE_FILE_FOR_OBJECTS 1) +SET(CMAKE_CXX_USE_RESPONSE_FILE_FOR_OBJECTS 1) +# increase compiler warnings level (-W4 for MSVC, -Wextra for GCC) +if (MSVC) + if (CMAKE_CXX_FLAGS MATCHES "/W[0-4]") + string (REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + else() + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4") + endif() +elseif (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra") + if (BUILD_SHARED_LIBS) + if (APPLE) + set (CMAKE_SHARED_LINKER_FLAGS "-lm ${CMAKE_SHARED_LINKER_FLAGS}") + elseif(NOT WIN32) + set (CMAKE_SHARED_LINKER_FLAGS "-lm ${CMAKE_SHARED_LINKER_FLAGS}") + endif() + endif() +endif() + +if(MINGW) + # Set default release optimization option to O2 instead of O3, since in + # some OCCT related examples, this gives significantly smaller binaries + # at comparable performace with MinGW-w64. + string (REGEX MATCH "-O3" IS_O3_CXX "${CMAKE_CXX_FLAGS_RELEASE}") + if (IS_O3_CXX) + string (REGEX REPLACE "-O3" "-O2" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") + else() + set (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O2") + endif() + + set (CMAKE_CXX_FLAGS "-std=gnu++0x ${CMAKE_CXX_FLAGS}") + add_definitions(-D_WIN32_WINNT=0x0501) + # workaround bugs in mingw with vtable export + set (CMAKE_SHARED_LINKER_FLAGS "-Wl,--export-all-symbols") +elseif ("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xClang") + if (APPLE) + # CLang can be used with both libstdc++ and libc++, however on OS X libstdc++ is outdated. + set (CMAKE_CXX_FLAGS "-std=c++0x -stdlib=libc++ ${CMAKE_CXX_FLAGS}") + else() + set (CMAKE_CXX_FLAGS "-std=c++0x ${CMAKE_CXX_FLAGS}") + endif() +elseif (DEFINED CMAKE_COMPILER_IS_GNUCXX) + set (CMAKE_CXX_FLAGS "-std=c++0x ${CMAKE_CXX_FLAGS}") +endif() + +# Optimize size of binaries +if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX OR MINGW) + set (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -s") + set (CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -s") +endif() + +set (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DNo_Exception") +set (CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -DNo_Exception") + +# IfcOpenShell begin +if (MSVC) + foreach(flag CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_MINSIZEREL + CMAKE_CXX_FLAGS_RELWITHDEBINFO CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE + CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO) + if (${flag} MATCHES "/MD") + string(REGEX REPLACE "/MD" "/MT" ${flag} "${${flag}}") + endif() + if (${flag} MATCHES "/MDd") + string(REGEX REPLACE "/MDd" "/MTd" ${flag} "${${flag}}") + endif() + endforeach() +endif() +# IfcOpenShell end diff --git a/win/patches/88af392_adm-cmake-occt_toolkit.cmake b/win/patches/88af392_adm-cmake-occt_toolkit.cmake new file mode 100644 index 0000000000..6d27487f57 --- /dev/null +++ b/win/patches/88af392_adm-cmake-occt_toolkit.cmake @@ -0,0 +1,346 @@ +# script for each OCCT toolkit + +# parce PACKAGES file +if ("${PROJECT_NAME}" STREQUAL DRAWEXE) + set (USED_PACKAGES DRAWEXE) +else() + FILE_TO_LIST ("src/${PROJECT_NAME}/PACKAGES" USED_PACKAGES) +endif() + +set (PRECOMPILED_DEFS) + +if (NOT BUILD_SHARED_LIBS) + list (APPEND PRECOMPILED_DEFS "-DOCCT_NO_PLUGINS") +endif() + +# Get all used packages from toolkit +foreach (OCCT_PACKAGE ${USED_PACKAGES}) + + # TKService contains platform-dependent packages: Xw and WNT + if ((WIN32 AND "${OCCT_PACKAGE}" STREQUAL "Xw") OR (NOT WIN32 AND "${OCCT_PACKAGE}" STREQUAL "WNT")) + # do nothing + else() + + if (WIN32) + list (APPEND PRECOMPILED_DEFS "-D__${OCCT_PACKAGE}_DLL") + endif() + + set (SOURCE_FILES) + set (HEADER_FILES) + + # Generate Flex and Bison files + if (${BUILD_YACCLEX}) + + # flex files + OCCT_ORIGIN_AND_PATCHED_FILES ("src/${OCCT_PACKAGE}" "*[.]lex" SOURCE_FILES_FLEX) + list (LENGTH SOURCE_FILES_FLEX SOURCE_FILES_FLEX_LEN) + + # bison files + OCCT_ORIGIN_AND_PATCHED_FILES ("src/${OCCT_PACKAGE}" "*[.]yacc" SOURCE_FILES_BISON) + list (LENGTH SOURCE_FILES_BISON SOURCE_FILES_BISON_LEN) + + if (${SOURCE_FILES_FLEX_LEN} EQUAL ${SOURCE_FILES_BISON_LEN} AND NOT ${SOURCE_FILES_FLEX_LEN} EQUAL 0) + + list (SORT SOURCE_FILES_FLEX) + list (SORT SOURCE_FILES_BISON) + + math (EXPR SOURCE_FILES_FLEX_LEN "${SOURCE_FILES_FLEX_LEN} - 1") + foreach (FLEX_FILE_INDEX RANGE ${SOURCE_FILES_FLEX_LEN}) + + list (GET SOURCE_FILES_FLEX ${FLEX_FILE_INDEX} CURRENT_FLEX_FILE) + get_filename_component (CURRENT_FLEX_FILE_NAME ${CURRENT_FLEX_FILE} NAME_WE) + + list (GET SOURCE_FILES_BISON ${FLEX_FILE_INDEX} CURRENT_BISON_FILE) + get_filename_component (CURRENT_BISON_FILE_NAME ${CURRENT_BISON_FILE} NAME_WE) + + string (COMPARE EQUAL ${CURRENT_FLEX_FILE_NAME} ${CURRENT_BISON_FILE_NAME} ARE_FILES_EQUAL) + + if (EXISTS "${CURRENT_FLEX_FILE}" AND EXISTS "${CURRENT_BISON_FILE}" AND ${ARE_FILES_EQUAL}) + set (BISON_OUTPUT_FILE ${CURRENT_BISON_FILE_NAME}.tab.c) + set (FLEX_OUTPUT_FILE lex.${CURRENT_FLEX_FILE_NAME}.c) + BISON_TARGET (Parser_${CURRENT_BISON_FILE_NAME} ${CURRENT_BISON_FILE} ${CMAKE_SOURCE_DIR}/src/${OCCT_PACKAGE}/${BISON_OUTPUT_FILE} COMPILE_FLAGS "-p ${CURRENT_BISON_FILE_NAME}") + FLEX_TARGET (Scanner_${CURRENT_FLEX_FILE_NAME} ${CURRENT_FLEX_FILE} ${CMAKE_SOURCE_DIR}/src/${OCCT_PACKAGE}/${FLEX_OUTPUT_FILE} COMPILE_FLAGS "-P${CURRENT_FLEX_FILE_NAME}") + ADD_FLEX_BISON_DEPENDENCY (Scanner_${CURRENT_FLEX_FILE_NAME} Parser_${CURRENT_BISON_FILE_NAME}) + + list (APPEND SOURCE_FILES ${BISON_OUTPUT_FILE} ${FLEX_OUTPUT_FILE}) + endif() + endforeach() + endif() + endif() + + # header files + if (BUILD_PATCH AND EXISTS "${BUILD_PATCH}/src/${OCCT_PACKAGE}/FILES") + file (STRINGS "${BUILD_PATCH}/src/${OCCT_PACKAGE}/FILES" HEADER_FILES_M REGEX ".+[.]h") + file (STRINGS "${BUILD_PATCH}/src/${OCCT_PACKAGE}/FILES" HEADER_FILES_LXX REGEX ".+[.]lxx") + file (STRINGS "${BUILD_PATCH}/src/${OCCT_PACKAGE}/FILES" HEADER_FILES_GXX REGEX ".+[.]gxx") + + file (STRINGS "${BUILD_PATCH}/src/${OCCT_PACKAGE}/FILES" SOURCE_FILES_C REGEX ".+[.]c") + if(APPLE) + file (STRINGS "${BUILD_PATCH}/src/${OCCT_PACKAGE}/FILES" SOURCE_FILES_M REGEX ".+[.]mm") + endif() + else() + file (STRINGS "${CMAKE_SOURCE_DIR}/src/${OCCT_PACKAGE}/FILES" HEADER_FILES_M REGEX ".+[.]h") + file (STRINGS "${CMAKE_SOURCE_DIR}/src/${OCCT_PACKAGE}/FILES" HEADER_FILES_LXX REGEX ".+[.]lxx") + file (STRINGS "${CMAKE_SOURCE_DIR}/src/${OCCT_PACKAGE}/FILES" HEADER_FILES_GXX REGEX ".+[.]gxx") + + file (STRINGS "${CMAKE_SOURCE_DIR}/src/${OCCT_PACKAGE}/FILES" SOURCE_FILES_C REGEX ".+[.]c") + if(APPLE) + file (STRINGS "${CMAKE_SOURCE_DIR}/src/${OCCT_PACKAGE}/FILES" SOURCE_FILES_M REGEX ".+[.]mm") + endif() + endif() + + list (APPEND HEADER_FILES ${HEADER_FILES_M} ${HEADER_FILES_LXX} ${SOURCE_FILES_GXX}) + list (APPEND SOURCE_FILES ${SOURCE_FILES_C}) + if(APPLE) + list (APPEND SOURCE_FILES ${SOURCE_FILES_M}) + endif() + + foreach(HEADER_FILE ${HEADER_FILES}) + if (BUILD_PATCH AND EXISTS "${BUILD_PATCH}/src/${OCCT_PACKAGE}/${HEADER_FILE}") + message (STATUS "Info: consider patched file: ${BUILD_PATCH}/src/${OCCT_PACKAGE}/${HEADER_FILE}") + list (APPEND USED_INCFILES "${BUILD_PATCH}/src/${OCCT_PACKAGE}/${HEADER_FILE}") + SOURCE_GROUP ("Header Files\\${OCCT_PACKAGE}" FILES "${BUILD_PATCH}/src/${OCCT_PACKAGE}/${HEADER_FILE}") + else() + list (APPEND USED_INCFILES "${CMAKE_SOURCE_DIR}/src/${OCCT_PACKAGE}/${HEADER_FILE}") + SOURCE_GROUP ("Header Files\\${OCCT_PACKAGE}" FILES "${CMAKE_SOURCE_DIR}/src/${OCCT_PACKAGE}/${HEADER_FILE}") + endif() + endforeach() + + foreach(SOURCE_FILE ${SOURCE_FILES}) + if (BUILD_PATCH AND EXISTS "${BUILD_PATCH}/src/${OCCT_PACKAGE}/${SOURCE_FILE}") + message (STATUS "Info: consider patched file: ${BUILD_PATCH}/src/${OCCT_PACKAGE}/${SOURCE_FILE}") + list (APPEND USED_SRCFILES "${BUILD_PATCH}/src/${OCCT_PACKAGE}/${SOURCE_FILE}") + SOURCE_GROUP ("Source Files\\${OCCT_PACKAGE}" FILES "${BUILD_PATCH}/src/${OCCT_PACKAGE}/${SOURCE_FILE}") + else() + list (APPEND USED_SRCFILES "${CMAKE_SOURCE_DIR}/src/${OCCT_PACKAGE}/${SOURCE_FILE}") + SOURCE_GROUP ("Source Files\\${OCCT_PACKAGE}" FILES "${CMAKE_SOURCE_DIR}/src/${OCCT_PACKAGE}/${SOURCE_FILE}") + endif() + endforeach() + endif() +endforeach() +string (REGEX REPLACE ";" " " PRECOMPILED_DEFS "${PRECOMPILED_DEFS}") + +set (USED_RCFILE "") +if (MSVC) + set (USED_RCFILE "${CMAKE_BINARY_DIR}/resources/${PROJECT_NAME}.rc") + + if (APPLY_OCCT_PATCH_DIR AND EXISTS "${APPLY_OCCT_PATCH_DIR}/adm/templates/occt_toolkit.rc.in") + configure_file("${APPLY_OCCT_PATCH_DIR}/adm/templates/occt_toolkit.rc.in" "${USED_RCFILE}" @ONLY) + else() + configure_file("${CMAKE_SOURCE_DIR}/adm/templates/occt_toolkit.rc.in" "${USED_RCFILE}" @ONLY) + endif() +endif() + +set (CURRENT_MODULE) +foreach (OCCT_MODULE ${OCCT_MODULES}) + list (FIND ${OCCT_MODULE}_TOOLKITS ${PROJECT_NAME} CURRENT_PROJECT_IS_BUILT) + if (NOT ${CURRENT_PROJECT_IS_BUILT} EQUAL -1) + set (CURRENT_MODULE ${OCCT_MODULE}) + endif() +endforeach() + +if (NOT SINGLE_GENERATOR) + OCCT_INSERT_CODE_FOR_TARGET () +endif() + +if ("${PROJECT_NAME}" STREQUAL "DRAWEXE") + add_executable (${PROJECT_NAME} ${USED_SRCFILES} ${USED_INCFILES} ${USED_RCFILE}) + + install (TARGETS ${PROJECT_NAME} + DESTINATION "${INSTALL_DIR_BIN}\${OCCT_INSTALL_BIN_LETTER}") +else() + add_library (${PROJECT_NAME} ${USED_SRCFILES} ${USED_INCFILES} ${USED_RCFILE}) + + # IfcOpenShell begin + if (BUILD_SHARED_LIBS) + if (MSVC) + install (FILES ${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/bin\${OCCT_INSTALL_BIN_LETTER}/${PROJECT_NAME}.pdb + CONFIGURATIONS Debug RelWithDebInfo + DESTINATION "${INSTALL_DIR_BIN}\${OCCT_INSTALL_BIN_LETTER}") + endif() + else() + if (MSVC) + set_target_properties (${PROJECT_NAME} PROPERTIES + COMPILE_PDB_NAME ${PROJECT_NAME} + COMPILE_PDB_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/pdb/ + ) + + install (FILES ${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/pdb/\${CMAKE_INSTALL_CONFIG_NAME}/${PROJECT_NAME}.pdb + CONFIGURATIONS Debug RelWithDebInfo + DESTINATION "${INSTALL_DIR_LIB}\${OCCT_INSTALL_BIN_LETTER}") + endif() + endif() + # IfcOpenShell end + + if (BUILD_SHARED_LIBS AND NOT "${BUILD_SHARED_LIBRARY_NAME_POSTFIX}" STREQUAL "") + set (CMAKE_SHARED_LIBRARY_SUFFIX_DEFAULT ${CMAKE_SHARED_LIBRARY_SUFFIX}) + set (CMAKE_SHARED_LIBRARY_SUFFIX "${BUILD_SHARED_LIBRARY_NAME_POSTFIX}${CMAKE_SHARED_LIBRARY_SUFFIX}") + endif() + + install (TARGETS ${PROJECT_NAME} + EXPORT OpenCASCADE${CURRENT_MODULE}Targets + RUNTIME DESTINATION "${INSTALL_DIR_BIN}\${OCCT_INSTALL_BIN_LETTER}" + ARCHIVE DESTINATION "${INSTALL_DIR_LIB}\${OCCT_INSTALL_BIN_LETTER}" + LIBRARY DESTINATION "${INSTALL_DIR_LIB}\${OCCT_INSTALL_BIN_LETTER}") + + if (NOT WIN32) + if (BUILD_SHARED_LIBS AND NOT "${BUILD_SHARED_LIBRARY_NAME_POSTFIX}" STREQUAL "") + set (LINK_NAME "${INSTALL_DIR}/${INSTALL_DIR_LIB}\${OCCT_INSTALL_BIN_LETTER}/lib${PROJECT_NAME}${CMAKE_SHARED_LIBRARY_SUFFIX_DEFAULT}") + set (LIBRARY_NAME "${INSTALL_DIR}/${INSTALL_DIR_LIB}\${OCCT_INSTALL_BIN_LETTER}/lib${PROJECT_NAME}${CMAKE_SHARED_LIBRARY_SUFFIX}") + OCCT_CREATE_SYMLINK_TO_FILE (${LIBRARY_NAME} ${LINK_NAME}) + endif() + endif() +endif() + +if (CURRENT_MODULE) + set_target_properties (${PROJECT_NAME} PROPERTIES FOLDER "Modules/${CURRENT_MODULE}") + set_target_properties (${PROJECT_NAME} PROPERTIES MODULE "${CURRENT_MODULE}") + if (APPLE) + if (NOT "${INSTALL_NAME_DIR}" STREQUAL "") + set_target_properties (${PROJECT_NAME} PROPERTIES BUILD_WITH_INSTALL_RPATH 1 INSTALL_NAME_DIR "${INSTALL_NAME_DIR}") + endif() + endif() +endif() + +get_property (OCC_VERSION_MAJOR GLOBAL PROPERTY OCC_VERSION_MAJOR) +get_property (OCC_VERSION_MINOR GLOBAL PROPERTY OCC_VERSION_MINOR) +get_property (OCC_VERSION_MAINTENANCE GLOBAL PROPERTY OCC_VERSION_MAINTENANCE) + +if (ANDROID) + # do not append version to the filename + set_target_properties (${PROJECT_NAME} PROPERTIES COMPILE_FLAGS "${PRECOMPILED_DEFS}") +else() + set_target_properties (${PROJECT_NAME} PROPERTIES COMPILE_FLAGS "${PRECOMPILED_DEFS}" + SOVERSION "${OCC_VERSION_MAJOR}" + VERSION "${OCC_VERSION_MAJOR}.${OCC_VERSION_MINOR}.${OCC_VERSION_MAINTENANCE}") +endif() + +set (USED_TOOLKITS_BY_CURRENT_PROJECT) +set (USED_EXTERNAL_LIBS_BY_CURRENT_PROJECT) + +# parce EXTERNLIB file +FILE_TO_LIST ("src/${PROJECT_NAME}/EXTERNLIB" USED_EXTERNLIB_AND_TOOLKITS) +foreach (USED_ITEM ${USED_EXTERNLIB_AND_TOOLKITS}) + string (REGEX MATCH "^ *#" COMMENT_FOUND ${USED_ITEM}) + if (NOT COMMENT_FOUND) + string (REGEX MATCH "^TK" TK_FOUND ${USED_ITEM}) + string (REGEX MATCH "^vtk" VTK_FOUND ${USED_ITEM}) + + if (NOT "${TK_FOUND}" STREQUAL "" OR NOT "${VTK_FOUND}" STREQUAL "") + list (APPEND USED_TOOLKITS_BY_CURRENT_PROJECT ${USED_ITEM}) + if (NOT "${VTK_FOUND}" STREQUAL "" AND BUILD_SHARED_LIBS AND INSTALL_VTK AND COMMAND OCCT_INSTALL_VTK) + OCCT_INSTALL_VTK(${USED_ITEM}) + endif() + else() + string (REGEX MATCH "^CSF_" CSF_FOUND ${USED_ITEM}) + if ("${CSF_FOUND}" STREQUAL "") + message (STATUS "Info: ${USED_ITEM} from ${PROJECT_NAME} skipped due to it is empty") + else() # get CSF_ value + set (CURRENT_CSF ${${USED_ITEM}}) + if (NOT "x${CURRENT_CSF}" STREQUAL "x") + set (LIBRARY_FROM_CACHE 0) + separate_arguments (CURRENT_CSF) + foreach (CSF_LIBRARY ${CURRENT_CSF}) + string (TOLOWER "${CSF_LIBRARY}" CSF_LIBRARY) + string (REPLACE "+" "[+]" CSF_LIBRARY "${CSF_LIBRARY}") + string (REPLACE "." "" CSF_LIBRARY "${CSF_LIBRARY}") + get_cmake_property(ALL_CACHE_VARIABLES CACHE_VARIABLES) + string (REGEX MATCHALL "(^|;)3RDPARTY_[^;]+_LIBRARY[^;]*" ALL_CACHE_VARIABLES "${ALL_CACHE_VARIABLES}") + foreach (CACHE_VARIABLE ${ALL_CACHE_VARIABLES}) + set (CURRENT_CACHE_LIBRARY ${${CACHE_VARIABLE}}) + string (TOLOWER "${CACHE_VARIABLE}" CACHE_VARIABLE) + + if (EXISTS "${CURRENT_CACHE_LIBRARY}" AND NOT IS_DIRECTORY "${CURRENT_CACHE_LIBRARY}") + string (REGEX MATCH "_${CSF_LIBRARY}$" IS_ENDING "${CACHE_VARIABLE}") + string (REGEX MATCH "^([a-z]+)" CSF_WO_VERSION "${CSF_LIBRARY}") + string (REGEX MATCH "_${CSF_WO_VERSION}$" IS_ENDING_WO_VERSION "${CACHE_VARIABLE}") + if ("3rdparty_${CSF_LIBRARY}_library" STREQUAL "${CACHE_VARIABLE}" OR + "3rdparty_${CSF_WO_VERSION}_library" STREQUAL "${CACHE_VARIABLE}" OR + NOT "x${IS_ENDING}" STREQUAL "x" OR + NOT "x${IS_ENDING_WO_VERSION}" STREQUAL "x") + list (APPEND USED_EXTERNAL_LIBS_BY_CURRENT_PROJECT "${CURRENT_CACHE_LIBRARY}") + set (LIBRARY_FROM_CACHE 1) + endif() + endif() + endforeach() + endforeach() + + if (NOT ${LIBRARY_FROM_CACHE}) + # prepare a list from a string with whitespaces + separate_arguments (CURRENT_CSF) + list (APPEND USED_EXTERNAL_LIBS_BY_CURRENT_PROJECT ${CURRENT_CSF}) + endif() + endif() + endif() + endif() + endif() +endforeach() + +if (APPLE) + list (FIND USED_EXTERNAL_LIBS_BY_CURRENT_PROJECT X11 IS_X11_FOUND) + if (NOT ${IS_X11_FOUND} EQUAL -1) + find_package (X11 COMPONENTS X11 Xext Xmu Xi) + if (NOT X11_FOUND) + message (STATUS "Warning: X11 is not found. It's required to install The XQuartz project: http://www.xquartz.org") + endif() + endif() +endif() + +# Update list of used VTK libraries if OpenGL2 Rendering BackEnd is used. +# Add VTK_OPENGL2_BACKEND definition. +if("${VTK_RENDERING_BACKEND}" STREQUAL "OpenGL2") + add_definitions(-DVTK_OPENGL2_BACKEND) + foreach (VTK_EXCLUDE_LIBRARY vtkRenderingOpenGL vtkRenderingFreeTypeOpenGL) + list (FIND USED_TOOLKITS_BY_CURRENT_PROJECT "${VTK_EXCLUDE_LIBRARY}" IS_VTK_OPENGL_FOUND) + if (NOT ${IS_VTK_OPENGL_FOUND} EQUAL -1) + list (REMOVE_ITEM USED_TOOLKITS_BY_CURRENT_PROJECT ${VTK_EXCLUDE_LIBRARY}) + if (${VTK_EXCLUDE_LIBRARY} STREQUAL vtkRenderingOpenGL) + list (APPEND USED_TOOLKITS_BY_CURRENT_PROJECT vtkRenderingOpenGL2) + endif() + endif() + endforeach() +endif() + +if (BUILD_SHARED_LIBS) + target_link_libraries (${PROJECT_NAME} ${USED_TOOLKITS_BY_CURRENT_PROJECT} ${USED_EXTERNAL_LIBS_BY_CURRENT_PROJECT}) +endif() + +# suppress deprecation warnings inside OCCT itself for old gcc versions with unavailable Standard_DISABLE_DEPRECATION_WARNINGS +if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) + if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.6.0) + add_definitions("-DOCCT_NO_DEPRECATED") + message (STATUS "Warning: internal deprecation warnings by Standard_DEPRECATED have been disabled due to old gcc version being used") + endif() +endif() + +# use Cotire to accelerate build via usage of precompiled headers +if (BUILD_USE_PCH) + if (WIN32) + # prevent definition of min and max macros through inclusion of Windows.h + # (for cotire builds) + add_definitions("-DNOMINMAX") + # avoid warnings on deprecated names from standard C library (see strsafe.h) + add_definitions("-DSTRSAFE_NO_DEPRECATE") + # avoid "std::Equal1" warning in QANCollection_Stl.cxx in debug mode + # suggesting using msvc "Checked Iterators" + add_definitions("-D_SCL_SECURE_NO_WARNINGS") + endif() + + # Exclude system-provided glext.h. + # These macros are already defined within OpenGl_GlFunctions.hxx, + # however we have to duplicate them here for building TKOpenGl with PCH. + add_definitions("-DGL_GLEXT_LEGACY") + add_definitions("-DGLX_GLXEXT_LEGACY") + + # workaround for old gcc + if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) + add_definitions("-D__STDC_CONSTANT_MACROS") + add_definitions("-D__STDC_FORMAT_MACROS") + endif() + + # unity builds are not used since they do not add speed but cause conflicts + # in TKV3d + set_target_properties(${PROJECT_NAME} PROPERTIES COTIRE_ADD_UNITY_BUILD FALSE) + + cotire(${PROJECT_NAME}) +endif() From e87a1a0b32cacbbecb7b3cc428bdb2d3f362e148 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Fri, 9 Mar 2018 10:41:22 +0100 Subject: [PATCH 14/60] #329 Only auto close IfcCompositeCurve when used for profile --- src/ifcgeom/IfcGeomWires.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/ifcgeom/IfcGeomWires.cpp b/src/ifcgeom/IfcGeomWires.cpp index ec59436e20..6323df02df 100644 --- a/src/ifcgeom/IfcGeomWires.cpp +++ b/src/ifcgeom/IfcGeomWires.cpp @@ -253,14 +253,18 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcCompositeCurve* l, TopoDS_Wire wire_last_vertex = edge_last_vertex; } - gp_Pnt first = BRep_Tool::Pnt(edge_last_vertex); - gp_Pnt last = BRep_Tool::Pnt(wire_first_vertex); + IfcEntityList::ptr profile = l->entity->getInverse(IfcSchema::Type::IfcProfileDef, -1); - Standard_Real distance = first.SquareDistance(last); - if (distance > precision_sq_2) { - w.Add(BRepBuilderAPI_MakeEdge(edge_last_vertex, wire_first_vertex)); + if (profile && profile->size() > 0) { + gp_Pnt first = BRep_Tool::Pnt(edge_last_vertex); + gp_Pnt last = BRep_Tool::Pnt(wire_first_vertex); - Logger::Message(Logger::LOG_ERROR, "Closed gap on:", l->entity); + Standard_Real distance = first.SquareDistance(last); + if (distance > precision_sq_2) { + w.Add(BRepBuilderAPI_MakeEdge(edge_last_vertex, wire_first_vertex)); + + Logger::Message(Logger::LOG_ERROR, "Closed gap on:", l->entity); + } } wire = w.Wire(); From 14be6b49fecb80e632821d84ad796b107db2562b Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Fri, 16 Mar 2018 11:03:02 +0100 Subject: [PATCH 15/60] #348 --- src/ifcconvert/XmlSerializer.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/ifcconvert/XmlSerializer.cpp b/src/ifcconvert/XmlSerializer.cpp index 1bc02c4593..cf1f97cfe8 100644 --- a/src/ifcconvert/XmlSerializer.cpp +++ b/src/ifcconvert/XmlSerializer.cpp @@ -432,8 +432,11 @@ void XmlSerializer::finalize() { emitted_materials.insert(mat); ptree node; node.put(".id", qualify_unrooted_instance(mat)); - if (mat->as()) { - IfcMaterialLayerSet* layerset = mat->as()->ForLayerSet(); + if (mat->as() || mat->as()) { + IfcMaterialLayerSet* layerset = mat->as(); + if (!layerset) { + layerset = mat->as()->ForLayerSet(); + } if (layerset->hasLayerSetName()) { node.put(".LayerSetName", layerset->LayerSetName()); } From 93cca8f7b70445eaafa3b05ba699a1a66d37fd2f Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Fri, 16 Mar 2018 16:36:36 +0100 Subject: [PATCH 16/60] Update README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ff4f29d83a..a327b26b03 100644 --- a/README.md +++ b/README.md @@ -81,6 +81,8 @@ The following instructions are for Ubuntu, modify as required for other operatin can be experimented with and studied for pointers for other operating systems, but note that this script is not currently meant to be used for a typical IfcOpenShell workspace setup. +Note: where `make -j` is written, add a number roughly equal to the amount of CPU cores + 1. + **1)** Install most of the prerequisites and dependencies: $ sudo apt-get install git cmake gcc g++ libboost-all-dev libicu-dev @@ -103,7 +105,7 @@ meant to be used for a typical IfcOpenShell workspace setup. **3)** For building IfcConvert with COLLADA (.dae) support (on by default), OpenCOLLADA is needed: - $ sudo apt-get install libpcre3-dev + $ sudo apt-get install libpcre3-dev libxml2-dev $ git clone https://github.com/KhronosGroup/OpenCOLLADA.git $ cd OpenCOLLADA Using a known good revision, but HEAD should work too: From 42c09deb8c413d50ab64584c3ccaaccade6f475f Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Wed, 11 Apr 2018 12:26:01 +0200 Subject: [PATCH 17/60] #354 loose faces in SewedShape --- src/ifcgeom/IfcGeomFunctions.cpp | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/ifcgeom/IfcGeomFunctions.cpp b/src/ifcgeom/IfcGeomFunctions.cpp index b665e5b7dd..cd598f14a0 100644 --- a/src/ifcgeom/IfcGeomFunctions.cpp +++ b/src/ifcgeom/IfcGeomFunctions.cpp @@ -188,8 +188,10 @@ bool IfcGeom::Kernel::create_solid_from_faces(const TopTools_ListOfShape& face_l } if (valid_shell) { + TopoDS_Shape complete_shape; TopExp_Explorer exp(shape, TopAbs_SHELL); + for (; exp.More(); exp.Next()) { TopoDS_Shape result_shape = exp.Current(); @@ -234,12 +236,28 @@ bool IfcGeom::Kernel::create_solid_from_faces(const TopTools_ListOfShape& face_l B.MakeCompound(C); B.Add(C, complete_shape); complete_shape = C; - Logger::Message(Logger::LOG_WARNING, "Multiple components in IfcConnectedFaceSet"); + Logger::Message(Logger::LOG_ERROR, "Multiple components in IfcConnectedFaceSet"); } B.Add(complete_shape, result_shape); } } + + TopExp_Explorer loose_faces(shape, TopAbs_FACE, TopAbs_SHELL); + + for (; loose_faces.More(); loose_faces.Next()) { + BRep_Builder B; + if (complete_shape.ShapeType() != TopAbs_COMPOUND) { + TopoDS_Compound C; + B.MakeCompound(C); + B.Add(C, complete_shape); + complete_shape = C; + Logger::Message(Logger::LOG_ERROR, "Loose faces in IfcConnectedFaceSet"); + } + B.Add(complete_shape, loose_faces.Current()); + } + shape = complete_shape; + } else { Logger::Message(Logger::LOG_WARNING, "Failed to sew faceset"); } From 9f55444d2ee770e191e18fcaae4c246668f9df4f Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Sun, 15 Apr 2018 09:27:16 +0200 Subject: [PATCH 18/60] win: apply patch for HLR --- win/build-deps.cmd | 2 + ...af392_src-HLRBRep-HLRBRep_InternalAlgo.cxx | 938 ++++++++++++++++++ 2 files changed, 940 insertions(+) create mode 100644 win/patches/88af392_src-HLRBRep-HLRBRep_InternalAlgo.cxx diff --git a/win/build-deps.cmd b/win/build-deps.cmd index 4cdeb8cb9c..6869363633 100644 --- a/win/build-deps.cmd +++ b/win/build-deps.cmd @@ -328,6 +328,8 @@ if not %ERRORLEVEL%==0 ( if exist "%~dp0patches\%OCCT_HASH%_adm-cmake-occt_toolkit.cmake" copy /y "%~dp0patches\%OCCT_HASH%_adm-cmake-occt_toolkit.cmake" "%DEPENDENCY_DIR%\adm\cmake\occt_toolkit.cmake" REM Patch header file for HAVE_NO_DLL if exist "%~dp0patches\%OCCT_HASH%_Standard_Macro.hxx" copy /y "%~dp0patches\%OCCT_HASH%_Standard_Macro.hxx" "%DEPENDENCY_DIR%\src\Standard\Standard_Macro.hxx" + REM https://tracker.dev.opencascade.org/view.php?id=28248 + if exist "%~dp0patches\%OCCT_HASH%_src-HLRBRep-HLRBRep_InternalAlgo.cxx" copy /y "%~dp0patches\%OCCT_HASH%_src-HLRBRep-HLRBRep_InternalAlgo.cxx" "%DEPENDENCY_DIR%\src\HLRBRep\HLRBRep_InternalAlgo.cxx" REM NOTE If adding a new patch, adjust the checks above and below accordingly ) findstr IfcOpenShell "%DEPENDENCY_DIR%\CMakeLists.txt">NUL diff --git a/win/patches/88af392_src-HLRBRep-HLRBRep_InternalAlgo.cxx b/win/patches/88af392_src-HLRBRep-HLRBRep_InternalAlgo.cxx new file mode 100644 index 0000000000..c13cb06b8e --- /dev/null +++ b/win/patches/88af392_src-HLRBRep-HLRBRep_InternalAlgo.cxx @@ -0,0 +1,938 @@ +// Created on: 1997-04-17 +// Created by: Christophe MARION +// Copyright (c) 1997-1999 Matra Datavision +// Copyright (c) 1999-2014 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +IMPLEMENT_STANDARD_RTTIEXT(HLRBRep_InternalAlgo,Standard_Transient) + +extern Standard_Integer nbPtIntersection; // total P.I. +extern Standard_Integer nbSegIntersection; // total S.I +extern Standard_Integer nbClassification; // total classification +extern Standard_Integer nbOkIntersection; // pairs of intersecting edges +extern Standard_Integer nbCal1Intersection; // pairs of unrejected edges +extern Standard_Integer nbCal2Intersection; // true intersections (not vertex) +extern Standard_Integer nbCal3Intersection; // curve-surface intersections + +static Standard_Integer HLRBRep_InternalAlgo_TRACE = Standard_True; +static Standard_Integer HLRBRep_InternalAlgo_TRACE10 = Standard_True; + +//======================================================================= +//function : HLRBRep_InternalAlgo +//purpose : +//======================================================================= + +HLRBRep_InternalAlgo::HLRBRep_InternalAlgo () : +myDebug (Standard_False) +{ +} + +//======================================================================= +//function : HLRBRep_InternalAlgo +//purpose : +//======================================================================= + +HLRBRep_InternalAlgo:: +HLRBRep_InternalAlgo (const Handle(HLRBRep_InternalAlgo)& A) +{ + myDS = A->DataStructure(); + myProj = A->Projector(); + myShapes = A->SeqOfShapeBounds(); + myDebug = A->Debug(); +} + +//======================================================================= +//function : Projector +//purpose : +//======================================================================= + +void HLRBRep_InternalAlgo::Projector (const HLRAlgo_Projector& P) +{ + myProj = P; +} + +//======================================================================= +//function : Projector +//purpose : +//======================================================================= + +HLRAlgo_Projector & HLRBRep_InternalAlgo::Projector () +{ return myProj; } + +//======================================================================= +//function : Update +//purpose : +//======================================================================= + +void HLRBRep_InternalAlgo::Update () +{ + if (!myShapes.IsEmpty()) { + Standard_Integer n = myShapes.Length(); + Handle(HLRBRep_Data) *DS = new Handle(HLRBRep_Data) [n]; + + Standard_Integer i,dv,de,df,nv=0,ne=0,nf=0; + + for (i = 1; i <= n; i++) { + HLRBRep_ShapeBounds& SB = myShapes(i); + try { + OCC_CATCH_SIGNALS + DS[i-1] = HLRBRep_ShapeToHLR::Load(SB.Shape(), + myProj, + myMapOfShapeTool, + SB.NbOfIso()); + dv = DS[i-1]->NbVertices(); + de = DS[i-1]->NbEdges (); + df = DS[i-1]->NbFaces (); + } + catch(Standard_Failure const& anException) { + if (myDebug) + { + cout << "An exception was catched when preparing the Shape " << i; + cout << " and computing its OutLines " << endl; + cout << anException << endl; + } + DS[i-1] = new HLRBRep_Data(0,0,0); + dv = 0; + de = 0; + df = 0; + } + + SB = HLRBRep_ShapeBounds + (SB.Shape(),SB.ShapeData(),SB.NbOfIso(),1,dv,1,de,1,df); + nv += dv; + ne += de; + nf += df; + } + + if (n == 1) myDS = DS[0]; + else { + myDS = new HLRBRep_Data(nv,ne,nf); + nv = 0; + ne = 0; + nf = 0; + + for (i = 1; i <= n; i++) { + HLRBRep_ShapeBounds& SB = myShapes(i); + SB.Sizes(dv,de,df); + SB.Translate(nv,ne,nf); + myDS->Write(DS[i-1],nv,ne,nf); + nv += dv; + ne += de; + nf += df; + } + } + + delete [] DS; + + myDS->Update(myProj); + + HLRAlgo_EdgesBlock::MinMaxIndices ShapMin, ShapMax, MinMaxShap; + HLRAlgo_EdgesBlock::MinMaxIndices TheMin, TheMax; + HLRBRep_Array1OfEData& aEDataArray = myDS->EDataArray(); + HLRBRep_Array1OfFData& aFDataArray = myDS->FDataArray(); + + for (i = 1; i <= n; i++) { + Standard_Boolean FirstTime = Standard_True; + HLRBRep_ShapeBounds& SB = myShapes(i); + Standard_Integer v1,v2,e1,e2,f1,f2; + SB.Bounds(v1,v2,e1,e2,f1,f2); + + for (Standard_Integer e = e1; e <= e2; e++) { + HLRBRep_EdgeData& ed = aEDataArray.ChangeValue(e); + HLRAlgo::DecodeMinMax(ed.MinMax(), TheMin, TheMax); + if (FirstTime) { + FirstTime = Standard_False; + HLRAlgo::CopyMinMax(TheMin, TheMax, ShapMin, ShapMax); + } + else + HLRAlgo::AddMinMax(TheMin, TheMax, ShapMin, ShapMax); + } + + for (Standard_Integer f = f1; f <= f2; f++) { + HLRBRep_FaceData& fd = aFDataArray.ChangeValue(f); + HLRAlgo::DecodeMinMax(fd.Wires()->MinMax(), TheMin, TheMax); + HLRAlgo::AddMinMax(TheMin, TheMax, ShapMin, ShapMax); + } + HLRAlgo::EncodeMinMax(ShapMin, ShapMax, MinMaxShap); + SB.UpdateMinMax(MinMaxShap); + } + } +} + +//======================================================================= +//function : Load +//purpose : +//======================================================================= + +void HLRBRep_InternalAlgo::Load (const Handle(HLRTopoBRep_OutLiner)& S, + const Handle(Standard_Transient)& SData, + const Standard_Integer nbIso) +{ + myShapes.Append(HLRBRep_ShapeBounds(S,SData,nbIso,0,0,0,0,0,0)); + myDS.Nullify(); +} + +//======================================================================= +//function : Load +//purpose : +//======================================================================= + +void HLRBRep_InternalAlgo::Load (const Handle(HLRTopoBRep_OutLiner)& S, + const Standard_Integer nbIso) +{ + myShapes.Append(HLRBRep_ShapeBounds(S,nbIso,0,0,0,0,0,0)); + myDS.Nullify(); +} + +//======================================================================= +//function : Index +//purpose : +//======================================================================= + +Standard_Integer HLRBRep_InternalAlgo:: +Index (const Handle(HLRTopoBRep_OutLiner)& S) const +{ + Standard_Integer n = myShapes.Length(); + + for (Standard_Integer i = 1; i <= n; i++) + if (myShapes(i).Shape() == S) return i; + + return 0; +} + +//======================================================================= +//function : Remove +//purpose : +//======================================================================= + +void HLRBRep_InternalAlgo::Remove (const Standard_Integer I) +{ + Standard_OutOfRange_Raise_if + (I == 0 || I > myShapes.Length(), + "HLRBRep_InternalAlgo::Remove : unknown Shape"); + myShapes.Remove(I); + + myMapOfShapeTool.Clear(); + myDS.Nullify(); +} + +//======================================================================= +//function : ShapeData +//purpose : +//======================================================================= + +void HLRBRep_InternalAlgo::ShapeData (const Standard_Integer I, + const Handle(Standard_Transient)& SData) +{ + Standard_OutOfRange_Raise_if + (I == 0 || I > myShapes.Length(), + "HLRBRep_InternalAlgo::ShapeData : unknown Shape"); + + myShapes(I).ShapeData(SData); +} + +//======================================================================= +//function : SeqOfShapeBounds +//purpose : +//======================================================================= + +HLRBRep_SeqOfShapeBounds & HLRBRep_InternalAlgo::SeqOfShapeBounds () +{ + return myShapes; +} + +//======================================================================= +//function : NbShapes +//purpose : +//======================================================================= + +Standard_Integer HLRBRep_InternalAlgo::NbShapes () const +{ return myShapes.Length(); } + +//======================================================================= +//function : ShapeBounds +//purpose : +//======================================================================= + +HLRBRep_ShapeBounds & HLRBRep_InternalAlgo:: +ShapeBounds (const Standard_Integer I) +{ + Standard_OutOfRange_Raise_if + (I == 0 || I > myShapes.Length(), + "HLRBRep_InternalAlgo::ShapeBounds : unknown Shape"); + + return myShapes(I); +} + +//======================================================================= +//function : InitEdgeStatus +//purpose : +//======================================================================= + +void HLRBRep_InternalAlgo::InitEdgeStatus () +{ + Standard_Boolean visible; + HLRBRep_FaceIterator faceIt; + + HLRBRep_Array1OfEData& aEDataArray = myDS->EDataArray(); + HLRBRep_Array1OfFData& aFDataArray = myDS->FDataArray(); + Standard_Integer ne = myDS->NbEdges(); + Standard_Integer nf = myDS->NbFaces(); + + for (Standard_Integer e = 1; e <= ne; e++) { + HLRBRep_EdgeData& ed = aEDataArray.ChangeValue(e); + if (ed.Selected()) ed.Status().ShowAll(); + } +// for (Standard_Integer f = 1; f <= nf; f++) { + Standard_Integer f; + for ( f = 1; f <= nf; f++) { + HLRBRep_FaceData& fd = aFDataArray.ChangeValue(f); + if (fd.Selected()) { + + for (faceIt.InitEdge(fd); + faceIt.MoreEdge(); + faceIt.NextEdge()) { + HLRBRep_EdgeData* edf = &(myDS->EDataArray().ChangeValue(faceIt.Edge())); + if (edf->Selected()) edf->Status().HideAll(); + } + } + } + + for (f = 1; f <= nf; f++) { + HLRBRep_FaceData& fd = aFDataArray.ChangeValue(f); + visible = Standard_True; + if (fd.Selected() && fd.Closed()) { + if ( fd.Side()) visible = Standard_False; + else if ( !fd.WithOutL()) { + switch (fd.Orientation()) { + case TopAbs_REVERSED : visible = fd.Back() ; break; + case TopAbs_FORWARD : visible = !fd.Back() ; break; + case TopAbs_EXTERNAL : + case TopAbs_INTERNAL : visible = Standard_True; break; + } + } + } + if (visible) { + + for (faceIt.InitEdge(fd); + faceIt.MoreEdge(); + faceIt.NextEdge()) { + Standard_Integer E = faceIt.Edge(); + HLRBRep_EdgeData* edf = &(myDS->EDataArray().ChangeValue(E)); + if ( edf->Selected() && + !edf->Vertical()) + edf->Status().ShowAll(); + } + } + } +} + +//======================================================================= +//function : Select +//purpose : +//======================================================================= + +void HLRBRep_InternalAlgo::Select () +{ + if (!myDS.IsNull()) { + HLRBRep_Array1OfEData& aEDataArray = myDS->EDataArray(); + HLRBRep_Array1OfFData& aFDataArray = myDS->FDataArray(); + Standard_Integer ne = myDS->NbEdges(); + Standard_Integer nf = myDS->NbFaces(); + + for (Standard_Integer e = 1; e <= ne; e++) { + HLRBRep_EdgeData& ed = aEDataArray.ChangeValue(e); + ed.Selected(Standard_True); + } + + for (Standard_Integer f = 1; f <= nf; f++) { + HLRBRep_FaceData& fd = aFDataArray.ChangeValue(f); + fd.Selected(Standard_True); + } + } +} + +//======================================================================= +//function : Select +//purpose : +//======================================================================= + +void HLRBRep_InternalAlgo::Select (const Standard_Integer I) +{ + if (!myDS.IsNull()) { + Standard_OutOfRange_Raise_if + (I == 0 || I > myShapes.Length(), + "HLRBRep_InternalAlgo::Select : unknown Shape"); + + Standard_Integer v1,v2,e1,e2,f1,f2; + myShapes(I).Bounds(v1,v2,e1,e2,f1,f2); + + HLRBRep_Array1OfEData& aEDataArray = myDS->EDataArray(); + HLRBRep_Array1OfFData& aFDataArray = myDS->FDataArray(); + Standard_Integer ne = myDS->NbEdges(); + Standard_Integer nf = myDS->NbFaces(); + + for (Standard_Integer e = 1; e <= ne; e++) { + HLRBRep_EdgeData& ed = aEDataArray.ChangeValue(e); + ed.Selected(e >= e1 && e <= e2); + } + + for (Standard_Integer f = 1; f <= nf; f++) { + HLRBRep_FaceData& fd = aFDataArray.ChangeValue(f); + fd.Selected(f >= f1 && f <= f2); + } + } +} + +//======================================================================= +//function : SelectEdge +//purpose : +//======================================================================= + +void HLRBRep_InternalAlgo::SelectEdge (const Standard_Integer I) +{ + if (!myDS.IsNull()) { + Standard_OutOfRange_Raise_if + (I == 0 || I > myShapes.Length(), + "HLRBRep_InternalAlgo::SelectEdge : unknown Shape"); + + Standard_Integer v1,v2,e1,e2,f1,f2; + myShapes(I).Bounds(v1,v2,e1,e2,f1,f2); + + HLRBRep_Array1OfEData& aEDataArray = myDS->EDataArray(); + Standard_Integer ne = myDS->NbEdges(); + + for (Standard_Integer e = 1; e <= ne; e++) { + HLRBRep_EdgeData& ed = aEDataArray.ChangeValue(e); + ed.Selected(e >= e1 && e <= e2); + } + } +} + +//======================================================================= +//function : SelectFace +//purpose : +//======================================================================= + +void HLRBRep_InternalAlgo::SelectFace (const Standard_Integer I) +{ + if (!myDS.IsNull()) { + Standard_OutOfRange_Raise_if + (I == 0 || I > myShapes.Length(), + "HLRBRep_InternalAlgo::SelectFace : unknown Shape"); + + Standard_Integer v1,v2,e1,e2,f1,f2; + myShapes(I).Bounds(v1,v2,e1,e2,f1,f2); + + HLRBRep_Array1OfFData& aFDataArray = myDS->FDataArray(); + Standard_Integer nf = myDS->NbFaces(); + + for (Standard_Integer f = 1; f <= nf; f++) { + HLRBRep_FaceData& fd = aFDataArray.ChangeValue(f); + fd.Selected(f >= f1 && f <= f2); + } + } +} + +//======================================================================= +//function : ShowAll +//purpose : +//======================================================================= + +void HLRBRep_InternalAlgo::ShowAll () +{ + if (!myDS.IsNull()) { + HLRBRep_Array1OfEData& aEDataArray = myDS->EDataArray(); + Standard_Integer ne = myDS->NbEdges(); + + for (Standard_Integer ie = 1; ie <= ne; ie++) { + HLRBRep_EdgeData& ed = aEDataArray.ChangeValue(ie); + ed.Status().ShowAll(); + } + } +} + +//======================================================================= +//function : ShowAll +//purpose : +//======================================================================= + +void HLRBRep_InternalAlgo::ShowAll (const Standard_Integer I) +{ + if (!myDS.IsNull()) { + Standard_OutOfRange_Raise_if + (I == 0 || I > myShapes.Length(), + "HLRBRep_InternalAlgo::ShowAll : unknown Shape"); + + Select(I); + + HLRBRep_Array1OfEData& aEDataArray = myDS->EDataArray(); + Standard_Integer ne = myDS->NbEdges(); + + for (Standard_Integer e = 1; e <= ne; e++) { + HLRBRep_EdgeData& ed = aEDataArray.ChangeValue(e); + if (ed.Selected()) ed.Status().ShowAll(); + } + } +} + +//======================================================================= +//function : HideAll +//purpose : +//======================================================================= + +void HLRBRep_InternalAlgo::HideAll () +{ + if (!myDS.IsNull()) { + HLRBRep_Array1OfEData& aEDataArray = myDS->EDataArray(); + Standard_Integer ne = myDS->NbEdges(); + + for (Standard_Integer ie = 1; ie <= ne; ie++) { + HLRBRep_EdgeData& ed = aEDataArray.ChangeValue(ie); + ed.Status().HideAll(); + } + } +} + +//======================================================================= +//function : HideAll +//purpose : +//======================================================================= + +void HLRBRep_InternalAlgo::HideAll (const Standard_Integer I) +{ + if (!myDS.IsNull()) { + Standard_OutOfRange_Raise_if + (I == 0 || I > myShapes.Length(), + "HLRBRep_InternalAlgo::HideAll : unknown Shape"); + + Select(I); + + HLRBRep_Array1OfEData& aEDataArray = myDS->EDataArray(); + Standard_Integer ne = myDS->NbEdges(); + + for (Standard_Integer e = 1; e <= ne; e++) { + HLRBRep_EdgeData& ed = aEDataArray.ChangeValue(e); + if (ed.Selected()) ed.Status().HideAll(); + } + } +} + +//======================================================================= +//function : PartialHide +//purpose : +//======================================================================= + +void HLRBRep_InternalAlgo::PartialHide () +{ + if (!myDS.IsNull()) { + Standard_Integer i,n = myShapes.Length(); + + if (myDebug) + cout << " Partial hiding" << endl << endl; + + for (i = 1; i <= n; i++) + Hide(i); + + Select(); + } +} + +//======================================================================= +//function : Hide +//purpose : +//======================================================================= + +void HLRBRep_InternalAlgo::Hide () +{ + if (!myDS.IsNull()) { + Standard_Integer i,j,n = myShapes.Length(); + + if (myDebug) + cout << " Total hiding" << endl; + + for (i = 1; i <= n; i++) + Hide(i); + + for (i = 1; i <= n; i++) + for (j = 1; j <= n; j++) + if (i != j) Hide(i,j); + + Select(); + } +} + +//======================================================================= +//function : Hide +//purpose : +//======================================================================= + +void HLRBRep_InternalAlgo::Hide (const Standard_Integer I) +{ + if (!myDS.IsNull()) { + Standard_OutOfRange_Raise_if + (I == 0 || I > myShapes.Length(), + "HLRBRep_InternalAlgo::Hide : unknown Shape"); + + if (myDebug) + cout << " hiding the shape " << I << " by itself" << endl; + + Select(I); + InitEdgeStatus(); + HideSelected(I,Standard_True); + } +} + +//======================================================================= +//function : Hide +//purpose : +//======================================================================= + +void HLRBRep_InternalAlgo::Hide (const Standard_Integer I, + const Standard_Integer J) +{ + if (!myDS.IsNull()) { + Standard_OutOfRange_Raise_if + (I == 0 || I > myShapes.Length() || + J == 0 || J > myShapes.Length(), + "HLRBRep_InternalAlgo::Hide : unknown Shapes"); + + if (I == J) Hide(I); + else { + HLRAlgo_EdgesBlock::MinMaxIndices* MinMaxShBI = &myShapes(I).MinMax(); + HLRAlgo_EdgesBlock::MinMaxIndices* MinMaxShBJ = &myShapes(J).MinMax(); + if (((MinMaxShBJ->Max[0] - MinMaxShBI->Min[0]) & 0x80008000) == 0 && + ((MinMaxShBI->Max[0] - MinMaxShBJ->Min[0]) & 0x80008000) == 0 && + ((MinMaxShBJ->Max[1] - MinMaxShBI->Min[1]) & 0x80008000) == 0 && + ((MinMaxShBI->Max[1] - MinMaxShBJ->Min[1]) & 0x80008000) == 0 && + ((MinMaxShBJ->Max[2] - MinMaxShBI->Min[2]) & 0x80008000) == 0 && + ((MinMaxShBI->Max[2] - MinMaxShBJ->Min[2]) & 0x80008000) == 0 && + ((MinMaxShBJ->Max[3] - MinMaxShBI->Min[3]) & 0x80008000) == 0 && + ((MinMaxShBI->Max[3] - MinMaxShBJ->Min[3]) & 0x80008000) == 0 && + ((MinMaxShBJ->Max[4] - MinMaxShBI->Min[4]) & 0x80008000) == 0 && + ((MinMaxShBI->Max[4] - MinMaxShBJ->Min[4]) & 0x80008000) == 0 && + ((MinMaxShBJ->Max[5] - MinMaxShBI->Min[5]) & 0x80008000) == 0 && + ((MinMaxShBI->Max[5] - MinMaxShBJ->Min[5]) & 0x80008000) == 0 && + ((MinMaxShBJ->Max[6] - MinMaxShBI->Min[6]) & 0x80008000) == 0 && + ((MinMaxShBJ->Max[7] - MinMaxShBI->Min[7]) & 0x80008000) == 0) { + if (myDebug) { + cout << " hiding the shape " << I; + cout << " by the shape : " << J << endl; + } + SelectEdge(I); + SelectFace(J); + HideSelected(I,Standard_False); + } + } + } +} + +//======================================================================= +//function : HideSelected +//purpose : +//======================================================================= + +void HLRBRep_InternalAlgo::HideSelected (const Standard_Integer I, + const Standard_Boolean SideFace) +{ + Standard_Integer e,f,j,nbVisEdges,nbSelEdges,nbSelFaces,nbCache; + Standard_Integer nbFSide,nbFSimp; + +#ifdef OCCT_DEBUG + if (myDebug) { + nbPtIntersection = 0; + nbSegIntersection = 0; + nbOkIntersection = 0; + nbClassification = 0; + nbCal1Intersection = 0; + nbCal2Intersection = 0; + nbCal3Intersection = 0; + } +#endif + + HLRBRep_ShapeBounds& SB = myShapes(I); + Standard_Integer v1,v2,e1,e2,f1,f2; + SB.Bounds(v1,v2,e1,e2,f1,f2); + + if (e2 >= e1) { + myDS->InitBoundSort(SB.MinMax(),e1,e2); + HLRBRep_Hider Cache(myDS); + HLRBRep_Array1OfEData& aEDataArray = myDS->EDataArray(); + HLRBRep_Array1OfFData& aFDataArray = myDS->FDataArray(); + Standard_Integer ne = myDS->NbEdges(); + Standard_Integer nf = myDS->NbFaces(); + + if (myDebug) { + nbVisEdges = 0; + nbSelEdges = 0; + nbSelFaces = 0; + nbCache = 0; + nbFSide = 0; + nbFSimp = 0; + + for (e = 1; e <= ne; e++) { + HLRBRep_EdgeData& ed = aEDataArray.ChangeValue(e); + if (ed.Selected()) { + nbSelEdges++; + if (!ed.Status().AllHidden()) nbVisEdges++; + } + } + + for (f = 1; f <= nf; f++) { + HLRBRep_FaceData& fd = aFDataArray.ChangeValue(f); + if (fd.Selected()) { + nbSelFaces++; + if (fd.Hiding()) nbCache++; + if (fd.Side ()) nbFSide++; + if (fd.Simple()) nbFSimp++; + } + } + + if (myDebug) + { + cout << endl; + cout << "Vertices : " << setw(5) << myDS->NbVertices() << endl; + cout << "Edges : " << setw(5) << myDS->NbEdges() << " , "; + cout << "Selected : " << setw(5) << nbSelEdges << " , "; + cout << "Visibles : " << setw(5) << nbVisEdges << endl; + cout << "Faces : " << setw(5) << myDS->NbFaces() << " , "; + cout << "Selected : " << setw(5) << nbSelFaces << " , "; + cout << "Simple : " << setw(5) << nbFSimp << endl; + if (SideFace) + cout << "Side : " << setw(5) << nbFSide << " , "; + cout << "Cachantes : " << setw(5) << nbCache << endl << endl; + } + } + + if (nf == 0) + return; + + Standard_Integer QWE=0,QWEQWE; + QWEQWE=nf/10; + + if (SideFace) { + j = 0; + + for (f = 1; f <= nf; f++) { + HLRBRep_FaceData& fd = aFDataArray.ChangeValue(f); + if (fd.Selected()) { + if (fd.Side()) { + if(HLRBRep_InternalAlgo_TRACE10) { + if(++QWE>QWEQWE) { + QWE=0; + if (myDebug) + cout<<"*"; + } + } + else { + if (myDebug && HLRBRep_InternalAlgo_TRACE) { + j++; + cout << " OwnHiding " << j << " of face : " << f << endl; + } + } + Cache.OwnHiding(f); + } + } + } + } + + +//-- + TColStd_Array1OfInteger Val(1, nf); + TColStd_Array1OfReal Size(1, nf); + TColStd_Array1OfInteger Index(1, nf); + + + for (f = 1; f <= nf; f++) { + HLRBRep_FaceData& fd = aFDataArray.ChangeValue(f); + if (fd.Plane()) Val(f) = 10; + else if(fd.Cylinder()) Val(f)=9; + else if(fd.Cone()) Val(f)=8; + else if(fd.Sphere()) Val(f)=7; + else if(fd.Torus()) Val(f)=6; + else Val(f)=0; + if(fd.Cut()) Val(f)-=10; + if(fd.Side()) Val(f)-=100; + if(fd.WithOutL()) Val(f)-=20; + + Size(f)=fd.Size(); + } + + for(Standard_Integer tt=1;tt<=nf;tt++) { + Index(tt)=tt; + } + + //-- ====================================================================== +/* Standard_Boolean TriOk; //-- a refaire + do { + Standard_Integer t,tp1; + TriOk=Standard_True; + for(t=1,tp1=2;t2) { + Standard_Integer i,ir,k,l; + Standard_Integer rra; + l=(nf>>1)+1; + ir=nf; + for(;;) { + if(l>1) { + rra=Index(--l); + } + else { + rra=Index(ir); + Index(ir)=Index(1); + if(--ir == 1) { + Index(1)=rra; + break; + } + } + i=l; + k=l+l; + while(k<=ir) { + if(k Val(Index(k+1))) + k++; + else if(Val(Index(k)) == Val(Index(k+1))) { + if(Size(Index(k)) > Size(Index(k+1))) + k++; + } + } + if(Val(rra) > Val(Index(k))) { + Index(i)=Index(k); + i=k; + k<<=1; + } + else if((Val(rra) == Val(Index(k))) && (Size(rra) > Size(Index(k)))) { + Index(i)=Index(k); + i=k; + k<<=1; + } + else { + k=ir+1; + } + } + Index(i)=rra; + } + } + + j = 0; + + QWE=0; + for (f = 1; f <= nf; f++) { + Standard_Integer fi = Index(f); + HLRBRep_FaceData& fd = aFDataArray.ChangeValue(fi); + if (fd.Selected()) { + if (fd.Hiding()) { + if(HLRBRep_InternalAlgo_TRACE10 && HLRBRep_InternalAlgo_TRACE==Standard_False) { + if(++QWE>QWEQWE) { + if (myDebug) + cout<<"."; + QWE=0; + } + } + else if (myDebug && HLRBRep_InternalAlgo_TRACE) { + static int rty=0; + j++; + printf("%6d",fi); fflush(stdout); + if(++rty>25) { rty=0; printf("\n"); } + } + Cache.Hide(fi,myMapOfShapeTool); + } + } + } + +#ifdef OCCT_DEBUG + if (myDebug) { + nbFSimp = 0; + + for (f = 1; f <= nf; f++) { + HLRBRep_FaceData& fd = aFDataArray.ChangeValue(f); + if (fd.Selected() && fd.Simple()) + nbFSimp++; + } + + cout << "\n"; + cout << "Simple Faces : "; + cout << nbFSimp << "\n"; + cout << "Intersections calculees : "; + cout << nbCal2Intersection << "\n"; + cout << "Intersections Ok : "; + cout << nbOkIntersection << "\n"; + cout << "Points : "; + cout << nbPtIntersection << "\n"; + cout << "Segments : "; + cout << nbSegIntersection << "\n"; + cout << "Classification : "; + cout << nbClassification << "\n"; + cout << "Intersections curve-surface : "; + cout << nbCal3Intersection << "\n"; + cout << endl << endl; + } +#endif + } +} + +//======================================================================= +//function : Debug +//purpose : +//======================================================================= + +void HLRBRep_InternalAlgo::Debug (const Standard_Boolean deb) +{ myDebug = deb; } + +//======================================================================= +//function : Debug +//purpose : +//======================================================================= + +Standard_Boolean HLRBRep_InternalAlgo::Debug () const +{ return myDebug; } + +//======================================================================= +//function : DataStructure +//purpose : +//======================================================================= + +Handle(HLRBRep_Data) HLRBRep_InternalAlgo::DataStructure () const +{ return myDS; } From e21277e80acf63dc0437435a0021251cdcfd853d Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Sun, 15 Apr 2018 14:01:37 +0200 Subject: [PATCH 19/60] nix: use and patch occt 7.2 --- nix/build-all.py | 40 ++++++++++++++++++++++++---------- nix/patches/occt/88af392.patch | 32 +++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 12 deletions(-) create mode 100644 nix/patches/occt/88af392.patch diff --git a/nix/build-all.py b/nix/build-all.py index ce50c82065..68ca5506c9 100644 --- a/nix/build-all.py +++ b/nix/build-all.py @@ -59,8 +59,10 @@ logger.addHandler(ch) PROJECT_NAME="IfcOpenShell" OCE_VERSION="0.18" -OCCT_VERSION="7.1.0" -OCCT_HASH="89aebde" +# OCCT_VERSION="7.1.0" +# OCCT_HASH="89aebde" +OCCT_VERSION="7.2.0" +OCCT_HASH="88af392" PYTHON_VERSIONS=["2.7.12", "3.2.6", "3.3.6", "3.4.6", "3.5.3", "3.6.2"] BOOST_VERSION="1.59.0" PCRE_VERSION="8.39" @@ -183,7 +185,7 @@ cecho(""" - How many compiler processes may be run in parallel. # Check that required tools are in PATH -for cmd in [git, bunzip2, tar, cc, cplusplus, autoconf, automake, yacc, make]: +for cmd in [git, bunzip2, tar, cc, cplusplus, autoconf, automake, yacc, make, "patch"]: if which(cmd) is None: raise ValueError("Required tool '%s' not installed or not added to PATH" % (cmd,)) @@ -284,7 +286,7 @@ def git_clone(clone_url, target_dir, revision=None): if revision != None: __check_call__([git, "checkout", revision], cwd=target_dir) -def build_dependency(name, mode, build_tool_args, download_url, download_name, download_tool=download_tool_default, revision=None, additional_files={}, no_append_name=False): +def build_dependency(name, mode, build_tool_args, download_url, download_name, download_tool=download_tool_default, revision=None, patch=None, additional_files={}, no_append_name=False): """Handles building of dependencies with different tools (which are distinguished with the `mode` argument. `build_tool_args` is expected to be a list which is necessary in order to not mess up quoting of compiler and @@ -347,6 +349,14 @@ def build_dependency(name, mode, build_tool_args, download_url, download_name, d if not os.path.exists(path): urllib.urlretrieve(url, os.path.join(extract_dir, path)) + if patch is not None: + patch_abs = os.path.abspath(os.path.join(os.path.dirname(__file__), patch)) + if os.path.exists(patch_abs): + try: __check_call__(["patch", "-p1", "--batch", "--forward", "-i", patch_abs], cwd=extract_dir) + except Exception as e: + # Assert that the patch has already been applied + __check_call__(["patch", "-p1", "--batch", "--reverse", "--dry-run", "-i", patch_abs], cwd=extract_dir) + if mode != "bjam": extract_build_dir = os.path.join(extract_dir, "build") if os.path.exists(extract_build_dir): @@ -457,7 +467,15 @@ build_dependency(name="pcre-%s" % (PCRE_VERSION,), mode="autoconf", build_tool_a build_dependency(name="swig", mode="autoconf", build_tool_args=["--with-pcre-prefix=%s/install/pcre-%s" % (DEPS_DIR, PCRE_VERSION)], download_url="https://github.com/swig/swig.git", download_name="swig", download_tool=download_tool_git, revision="rel-%s" % SWIG_VERSION) if USE_OCCT: - long_filename = "src/RWStepVisual/RWStepVisual_RWCharacterizedObjectAndCharacterizedRepresentationAndDraughtingModelAndRepresentation" + long_filenames = ["src/RWStepVisual/RWStepVisual_RWCharacterizedObjectAndCharacterizedRepresentationAndDraughtingModelAndRepresentation"] + if OCCT_VERSION == "7.2.0": + long_filenames += [ + "src/StepVisual/StepVisual_AnnotationCurveOccurrenceAndAnnotationOccurrenceAndGeomReprItemAndReprItemAndStyledItem", + "src/RWStepVisual/RWStepVisual_RWAnnotationCurveOccurrenceAndAnnotationOccurrenceAndGeomReprItemAndReprItemAndStyledItem" + ] + long_filenames_ext = [("%s.hxx" % fn) for fn in long_filenames] + [("%s.cxx" % fn) for fn in long_filenames] + patch_filename = "patches/occt/%s.patch" % OCCT_HASH + occt_gitweb = "http://git.dev.opencascade.org/gitweb/?p=occt.git" build_dependency( name="occt-%s" % OCCT_VERSION, @@ -467,13 +485,11 @@ if USE_OCCT: "-DBUILD_LIBRARY_TYPE=Static", "-DBUILD_MODULE_Draw=0", ], - download_url="%s;a=snapshot;h=%s;sf=tgz" % (occt_gitweb, OCCT_HASH), - additional_files = { - "%s.hxx" % (long_filename): "%s;a=blob_plain;hb=%s;f=%s.hxx" % (occt_gitweb, OCCT_HASH, long_filename), - "%s.cxx" % (long_filename): "%s;a=blob_plain;hb=%s;f=%s.cxx" % (occt_gitweb, OCCT_HASH, long_filename) - }, - download_name="occt-%s.tar.gz" % OCCT_HASH, - no_append_name=True) + download_url = "%s;a=snapshot;h=%s;sf=tgz" % (occt_gitweb, OCCT_HASH), + additional_files = {fn: "%s;a=blob_plain;hb=%s;f=%s.hxx" % (occt_gitweb, OCCT_HASH, fn) for fn in long_filenames_ext}, + patch = patch_filename, + download_name = "occt-%s.tar.gz" % OCCT_HASH, + no_append_name = True) else: build_dependency(name="oce-%s" % (OCE_VERSION,), mode="cmake", build_tool_args=["-DOCE_DISABLE_TKSERVICE_FONT=ON", "-DOCE_TESTING=OFF", "-DOCE_BUILD_SHARED_LIB=OFF", "-DOCE_DISABLE_X11=ON", "-DOCE_VISUALISATION=OFF", "-DOCE_OCAF=OFF", "-DOCE_INSTALL_PREFIX=%s/install/oce-%s" % (DEPS_DIR, OCE_VERSION)], download_url="https://github.com/tpaviot/oce/archive/", download_name="OCE-%s.tar.gz" % (OCE_VERSION,)) diff --git a/nix/patches/occt/88af392.patch b/nix/patches/occt/88af392.patch new file mode 100644 index 0000000000..72c72287c0 --- /dev/null +++ b/nix/patches/occt/88af392.patch @@ -0,0 +1,32 @@ +http://git.dev.opencascade.org/gitweb/?p=occt.git;a=commitdiff;h=0ab4e621833f4eae945a3762c9a29ee12e2eec53#patch1 +diff --git a/src/HLRBRep/HLRBRep_InternalAlgo.cxx b/src/HLRBRep/HLRBRep_InternalAlgo.cxx +index ca885ca..c13cb06 100644 (file) +--- a/src/HLRBRep/HLRBRep_InternalAlgo.cxx ++++ b/src/HLRBRep/HLRBRep_InternalAlgo.cxx +@@ -165,7 +165,7 @@ void HLRBRep_InternalAlgo::Update () + SB.Bounds(v1,v2,e1,e2,f1,f2); + + for (Standard_Integer e = e1; e <= e2; e++) { +- HLRBRep_EdgeData ed = aEDataArray.ChangeValue(e); ++ HLRBRep_EdgeData& ed = aEDataArray.ChangeValue(e); + HLRAlgo::DecodeMinMax(ed.MinMax(), TheMin, TheMax); + if (FirstTime) { + FirstTime = Standard_False; +@@ -307,7 +307,7 @@ void HLRBRep_InternalAlgo::InitEdgeStatus () + Standard_Integer nf = myDS->NbFaces(); + + for (Standard_Integer e = 1; e <= ne; e++) { +- HLRBRep_EdgeData ed = aEDataArray.ChangeValue(e); ++ HLRBRep_EdgeData& ed = aEDataArray.ChangeValue(e); + if (ed.Selected()) ed.Status().ShowAll(); + } + // for (Standard_Integer f = 1; f <= nf; f++) { +@@ -368,7 +368,7 @@ void HLRBRep_InternalAlgo::Select () + Standard_Integer nf = myDS->NbFaces(); + + for (Standard_Integer e = 1; e <= ne; e++) { +- HLRBRep_EdgeData ed = aEDataArray.ChangeValue(e); ++ HLRBRep_EdgeData& ed = aEDataArray.ChangeValue(e); + ed.Selected(Standard_True); + } + From 656346741e65b0afb655161ead82f114e7cfc7e9 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Wed, 18 Apr 2018 11:33:57 +0200 Subject: [PATCH 20/60] #288 #297 --- src/ifcgeom/IfcGeom.h | 2 + src/ifcgeom/IfcGeomFunctions.cpp | 231 ++++++++++++++++++++++++++++++- src/ifcgeom/IfcGeomWires.cpp | 24 +++- 3 files changed, 253 insertions(+), 4 deletions(-) diff --git a/src/ifcgeom/IfcGeom.h b/src/ifcgeom/IfcGeom.h index 2bee3fef6c..88b05f0cb6 100644 --- a/src/ifcgeom/IfcGeom.h +++ b/src/ifcgeom/IfcGeom.h @@ -231,6 +231,8 @@ public: bool approximate_plane_through_wire(const TopoDS_Wire&, gp_Pln&); bool flatten_wire(TopoDS_Wire&); bool triangulate_wire(const TopoDS_Wire&, TopTools_ListOfShape&); + bool wire_intersections(const TopoDS_Wire & wire, TopTools_ListOfShape & wires); + void select_largest(const TopTools_ListOfShape& shapes, TopoDS_Shape& largest); static double shape_volume(const TopoDS_Shape& s); static double face_area(const TopoDS_Face& f); diff --git a/src/ifcgeom/IfcGeomFunctions.cpp b/src/ifcgeom/IfcGeomFunctions.cpp index cd598f14a0..6cf81104dd 100644 --- a/src/ifcgeom/IfcGeomFunctions.cpp +++ b/src/ifcgeom/IfcGeomFunctions.cpp @@ -95,6 +95,7 @@ #include #include +#include #include #include @@ -131,6 +132,8 @@ #include +#include + #include #include "../ifcparse/IfcSIPrefix.h" @@ -614,7 +617,15 @@ bool IfcGeom::Kernel::convert_openings_fast(const IfcSchema::IfcProduct* entity, } #endif -bool IfcGeom::Kernel::convert_wire_to_face(const TopoDS_Wire& wire, TopoDS_Face& face) { +bool IfcGeom::Kernel::convert_wire_to_face(const TopoDS_Wire& w, TopoDS_Face& face) { + TopoDS_Wire wire = w; + + TopTools_ListOfShape results; + if (wire_intersections(wire, results)) { + Logger::Error("Self-intersections with " + boost::lexical_cast(results.Extent()) + " cycles detected"); + select_largest(results, wire); + } + ShapeFix_ShapeTolerance FTol; FTol.SetTolerance(wire, getValue(GV_PRECISION), TopAbs_WIRE); @@ -2767,6 +2778,224 @@ TopoDS_Shape IfcGeom::Kernel::apply_transformation(const TopoDS_Shape& s, const } } +namespace { + + /* + * A small helper utility to wrap around a numeric range + */ + class bounded_int { + private: + int i; + size_t n; + public: + bounded_int(int i, size_t n) : i(i), n(n) {} + + bounded_int& operator--() { + --i; + if (i == -1) { + i = n - 1; + } + return *this; + } + + bounded_int& operator++() { + ++i; + if (i == n) { + i = 0; + } + return *this; + } + + operator int() { return i; } + }; + + std::string format_pnt(const gp_Pnt& p) { + std::stringstream ss; + ss << std::fixed << std::setprecision(4) << p.X() << " " << p.Y() << " " << p.Z(); + return ss.str(); + } + + std::string format_edge(const TopoDS_Edge& e) { + std::stringstream ss; + TopoDS_Vertex v1, v2; + TopExp::Vertices(e, v1, v2); + gp_Pnt p1 = BRep_Tool::Pnt(v1); + gp_Pnt p2 = BRep_Tool::Pnt(v2); + ss << "edge " << format_pnt(p1) << " -> " << format_pnt(p2); + return ss.str(); + } + +} + +bool IfcGeom::Kernel::wire_intersections(const TopoDS_Wire& wire, TopTools_ListOfShape& wires) { + if (!wire.Closed()) { + wires.Append(wire); + return false; + } + + int n = count(wire, TopAbs_EDGE); + if (n < 3) { + wires.Append(wire); + return false; + } + + // Note: initialize empty + Handle(ShapeExtend_WireData) wd = new ShapeExtend_WireData(); + + // ... to be sure to get consecutive edges + int i = 0; + BRepTools_WireExplorer exp(wire); + for (; exp.More(); exp.Next()) { + wd->Add(exp.Current()); + } + + bool intersected = false; + + // tfk: Extrema on infinite curves proved to be more robust. + // TopoDS_Face face = BRepBuilderAPI_MakeFace(wire, true).Face(); + // ShapeAnalysis_Wire saw(wd, face, getValue(GV_PRECISION)); + + for (int i = 2; i < n; ++i) { + for (int j = 0; j < i - 1; ++j) { + if (i == n - 1 && j == 0) continue; + + bool unbounded_intersects; + const double eps = getValue(GV_PRECISION) * 10.; + + double u11, u12, u21, u22, U1, U2; + GeomAPI_ExtremaCurveCurve ecc( + BRep_Tool::Curve(wd->Edge(i + 1), u11, u12), + BRep_Tool::Curve(wd->Edge(j + 1), u21, u22) + ); + + if ((unbounded_intersects = (ecc.NbExtrema() == 1 && ecc.Distance(1) < eps))) { + ecc.Parameters(1, U1, U2); + } + + if (u11 > u12) { + std::swap(u11, u12); + } + if (u21 > u22) { + std::swap(u21, u22); + } + + /// @todo: tfk: probably need different thresholds on non-linear curves + u11 -= eps; + u12 += eps; + u21 -= eps; + u22 += eps; + + // tfk: code below is for ShapeAnalysis_Wire::CheckIntersectingEdges() + // IntRes2d_SequenceOfIntersectionPoint points2d; + // TColgp_SequenceOfPnt points3d; + // TColStd_SequenceOfReal errors; + // if (saw.CheckIntersectingEdges(i + 1, j + 1, points2d, points3d, errors)) { + + if (unbounded_intersects && u11 < U1 && U1 < u12 && u21 < U2 && U2 < u22) { + + intersected = true; + + // Explore a forward and backward cycle from the intersection point + for (int fb = 0; fb <= 1; ++fb) { + const bool forward = fb == 0; + + BRepBuilderAPI_MakeWire mw; + bool first = true; + + for (bounded_int k(j, n);;) { + bool intersecting = k == j || k == i; + if (intersecting) { + TopoDS_Edge e = wd->Edge(k + 1); + + TopoDS_Vertex v1, v2; + TopExp::Vertices(e, v1, v2); + const TopoDS_Vertex* v = first == forward ? &v2 : &v1; + + // gp_Pnt p2 = points3d.Value(1); + + gp_Pnt p1 = BRep_Tool::Pnt(*v); + gp_Pnt pp1, pp2; + ecc.Points(1, pp1, pp2); + const gp_Pnt& p2 = k == i ? pp1 : pp2; + + // Substitute with a new edge from/to the intersection point + if (p1.Distance(p2) > getValue(GV_PRECISION) * 2) { + double _, __; + Handle_Geom_Curve crv = BRep_Tool::Curve(e, _, __); + BRepBuilderAPI_MakeEdge me(crv, p1, p2); + TopoDS_Edge ed = me.Edge(); + mw.Add(ed); + } + + first = false; + } else { + // Re-use original edge + mw.Add(wd->Edge(k+1)); + } + + if (k == i) { + break; + } + + if (forward) { + ++k; + } else { + --k; + } + } + + // Recursively process both cuts + wire_intersections(mw.Wire(), wires); + } + + return true; + } + } + } + + // No intersections found, append original wire + if (!intersected) { + wires.Append(wire); + } + + return intersected; +} + +void IfcGeom::Kernel::select_largest(const TopTools_ListOfShape& shapes, TopoDS_Shape& largest) { + double mass = 0.; + TopTools_ListIteratorOfListOfShape it(shapes); + for (; it.More(); it.Next()) { + /* + // tfk: bounding box is more efficient probably + const TopoDS_Wire& w = TopoDS::Wire(it.Value()); + TopoDS_Face face = BRepBuilderAPI_MakeFace(w).Face(); + const double m = face_area(face); + */ + + Bnd_Box bb; + BRepBndLib::AddClose(it.Value(), bb); + double xyz_min[3], xyz_max[3]; + bb.Get(xyz_min[0], xyz_min[1], xyz_min[2], xyz_max[0], xyz_max[1], xyz_max[2]); + const double eps = getValue(GV_PRECISION); + + double m = 1.; + for (int i = 0; i < 3; ++i) { + if (Precision::IsNegativeInfinite(xyz_min[i])) { + xyz_min[i] = 0.; + } + if (Precision::IsInfinite(xyz_max[i])) { + xyz_max[i] = 0.; + } + m *= (xyz_max[i] + eps) - (xyz_min[i] - eps); + } + + if (m > mass) { + mass = m; + largest = it.Value(); + } + } +} + #if OCC_VERSION_HEX < 0x60900 bool IfcGeom::Kernel::boolean_operation(const TopoDS_Shape& a, const TopTools_ListOfShape& b, BOPAlgo_Operation op, TopoDS_Shape& result) { result = a; diff --git a/src/ifcgeom/IfcGeomWires.cpp b/src/ifcgeom/IfcGeomWires.cpp index 6323df02df..82435e29f2 100644 --- a/src/ifcgeom/IfcGeomWires.cpp +++ b/src/ifcgeom/IfcGeomWires.cpp @@ -397,14 +397,24 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcPolyline* l, TopoDS_Wire& resu polygon.Append(pnt); } + const double eps = getValue(GV_PRECISION) * 10; + const bool closed_by_proximity = polygon.Length() >= 2 && polygon.First().Distance(polygon.Last()) < eps; + if (closed_by_proximity) { + polygon.Remove(polygon.Upper()); + } + // Remove points that are too close to one another - remove_duplicate_points_from_loop(polygon, false); + remove_duplicate_points_from_loop(polygon, closed_by_proximity, eps); BRepBuilderAPI_MakePolygon w; for (int i = 1; i <= polygon.Length(); ++i) { w.Add(polygon.Value(i)); } + if (closed_by_proximity) { + w.Close(); + } + result = w.Wire(); return true; } @@ -428,7 +438,8 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcPolyLoop* l, TopoDS_Wire& resu } // Remove points that are too close to one another - remove_duplicate_points_from_loop(polygon, true); + const double eps = getValue(GV_PRECISION) * 10; + remove_duplicate_points_from_loop(polygon, true, eps); int count = polygon.Length(); if (original_count - count != 0) { @@ -447,7 +458,14 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcPolyLoop* l, TopoDS_Wire& resu } w.Close(); - result = w.Wire(); + result = w.Wire(); + + TopTools_ListOfShape results; + if (wire_intersections(result, results)) { + Logger::Error("Self-intersections with " + boost::lexical_cast(results.Extent()) + " cycles detected", l->entity); + select_largest(results, result); + } + return true; } From 120ff2f629318566516851502a3cd6ece078a132 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Wed, 18 Apr 2018 11:50:59 +0200 Subject: [PATCH 21/60] Fix download of occt in nix build --- nix/build-all.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/build-all.py b/nix/build-all.py index 68ca5506c9..28c3cf4838 100644 --- a/nix/build-all.py +++ b/nix/build-all.py @@ -486,7 +486,7 @@ if USE_OCCT: "-DBUILD_MODULE_Draw=0", ], download_url = "%s;a=snapshot;h=%s;sf=tgz" % (occt_gitweb, OCCT_HASH), - additional_files = {fn: "%s;a=blob_plain;hb=%s;f=%s.hxx" % (occt_gitweb, OCCT_HASH, fn) for fn in long_filenames_ext}, + additional_files = {fn: "%s;a=blob_plain;hb=%s;f=%s" % (occt_gitweb, OCCT_HASH, fn) for fn in long_filenames_ext}, patch = patch_filename, download_name = "occt-%s.tar.gz" % OCCT_HASH, no_append_name = True) From 1f68d9d5bcfda6ce6b7ff6e86733faf835247242 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Wed, 18 Apr 2018 11:57:38 +0200 Subject: [PATCH 22/60] TColgp_SequenceOfPnt::Upper() does not exist on all versions of occt --- src/ifcgeom/IfcGeomWires.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ifcgeom/IfcGeomWires.cpp b/src/ifcgeom/IfcGeomWires.cpp index 82435e29f2..e1e2ed4781 100644 --- a/src/ifcgeom/IfcGeomWires.cpp +++ b/src/ifcgeom/IfcGeomWires.cpp @@ -400,7 +400,8 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcPolyline* l, TopoDS_Wire& resu const double eps = getValue(GV_PRECISION) * 10; const bool closed_by_proximity = polygon.Length() >= 2 && polygon.First().Distance(polygon.Last()) < eps; if (closed_by_proximity) { - polygon.Remove(polygon.Upper()); + // tfk: note 1-based + polygon.Remove(polygon.Length()); } // Remove points that are too close to one another From c748c8dcea03f6f5ff261b119e4d51dd53a65c75 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Mon, 23 Apr 2018 10:51:59 +0200 Subject: [PATCH 23/60] Better instance not found error messages --- src/ifcparse/IfcParse.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ifcparse/IfcParse.cpp b/src/ifcparse/IfcParse.cpp index e17635ae70..d5f50d90f9 100644 --- a/src/ifcparse/IfcParse.cpp +++ b/src/ifcparse/IfcParse.cpp @@ -1806,7 +1806,7 @@ IfcEntityList::ptr IfcFile::entitiesByReference(int t) { IfcUtil::IfcBaseClass* IfcFile::entityById(int id) { entity_by_id_t::const_iterator it = byid.find(id); if (it == byid.end()) { - throw IfcException("Entity not found"); + throw IfcException("Instance #" + boost::lexical_cast(id) + " not found"); } return it->second; } @@ -1814,7 +1814,7 @@ IfcUtil::IfcBaseClass* IfcFile::entityById(int id) { IfcSchema::IfcRoot* IfcFile::entityByGuid(const std::string& guid) { entity_by_guid_t::const_iterator it = byguid.find(guid); if ( it == byguid.end() ) { - throw IfcException("Entity not found"); + throw IfcException("Instance with GlobalId '" + guid + "' not found"); } else { return it->second; } From 6ee283dbae2f8597880882635d94d84eb8461cc3 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Fri, 4 May 2018 10:25:57 +0200 Subject: [PATCH 24/60] Don't fail on parse errors while resolving inverse attributes --- src/ifcparse/IfcParse.cpp | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/ifcparse/IfcParse.cpp b/src/ifcparse/IfcParse.cpp index d5f50d90f9..860f1398db 100644 --- a/src/ifcparse/IfcParse.cpp +++ b/src/ifcparse/IfcParse.cpp @@ -1896,15 +1896,20 @@ IfcEntityList::ptr IfcFile::getInverse(int instance_id, IfcSchema::Type::Enum ty for(IfcEntityList::it it = all->begin(); it != all->end(); ++it) { bool valid = type == IfcSchema::Type::UNDEFINED || (*it)->is(type); if (valid && attribute_index >= 0) { - Argument* arg = (*it)->entity->getArgument(attribute_index); - if (arg->type() == IfcUtil::Argument_ENTITY_INSTANCE) { - valid = instance == *arg; - } else if (arg->type() == IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE) { - IfcEntityList::ptr li = *arg; - valid = li->contains(instance); - } else if (arg->type() == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE) { - IfcEntityListList::ptr li = *arg; - valid = li->contains(instance); + try { + Argument* arg = (*it)->entity->getArgument(attribute_index); + if (arg->type() == IfcUtil::Argument_ENTITY_INSTANCE) { + valid = instance == *arg; + } else if (arg->type() == IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE) { + IfcEntityList::ptr li = *arg; + valid = li->contains(instance); + } else if (arg->type() == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE) { + IfcEntityListList::ptr li = *arg; + valid = li->contains(instance); + } + } catch (IfcException& e) { + valid = false; + Logger::Error(e); } } if (valid) { From 161f24d8044c608ec7ac369a609ef2b9cc59f691 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Sat, 5 May 2018 16:09:12 +0200 Subject: [PATCH 25/60] Copy operands prior to boolean operation --- src/ifcgeom/IfcGeomFunctions.cpp | 27 ++++++++++++++++++++++----- src/ifcparse/IfcParse.cpp | 2 +- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/ifcgeom/IfcGeomFunctions.cpp b/src/ifcgeom/IfcGeomFunctions.cpp index 6cf81104dd..4957bf40db 100644 --- a/src/ifcgeom/IfcGeomFunctions.cpp +++ b/src/ifcgeom/IfcGeomFunctions.cpp @@ -106,6 +106,7 @@ #include #include +#include #include #include @@ -586,9 +587,12 @@ bool IfcGeom::Kernel::convert_openings_fast(const IfcSchema::IfcProduct* entity, } for ( unsigned int i = 0; i < opening_shapes.size(); ++ i ) { + TopoDS_Shape opening_shape_solid; + const TopoDS_Shape& opening_shape_unlocated = ensure_fit_for_subtraction(opening_shapes[i].Shape(), opening_shape_solid); + gp_GTrsf gtrsf = opening_shapes[i].Placement(); gtrsf.PreMultiply(opening_trsf); - TopoDS_Shape opening_shape = apply_transformation(opening_shapes[i].Shape(), gtrsf); + TopoDS_Shape opening_shape = apply_transformation(opening_shape_unlocated, gtrsf); opening_shapelist.Append(opening_shape); } @@ -2800,7 +2804,7 @@ namespace { bounded_int& operator++() { ++i; - if (i == n) { + if (i == (int) n) { i = 0; } return *this; @@ -2843,7 +2847,6 @@ bool IfcGeom::Kernel::wire_intersections(const TopoDS_Wire& wire, TopTools_ListO Handle(ShapeExtend_WireData) wd = new ShapeExtend_WireData(); // ... to be sure to get consecutive edges - int i = 0; BRepTools_WireExplorer exp(wire); for (; exp.More(); exp.Next()) { wd->Add(exp.Current()); @@ -3054,6 +3057,20 @@ bool IfcGeom::Kernel::boolean_operation(const TopoDS_Shape& a, const TopoDS_Shap return succesful; } #else + +TopTools_ListOfShape copy_operand(const TopTools_ListOfShape& l) { + TopTools_ListOfShape r; + TopTools_ListIteratorOfListOfShape it(l); + for (; it.More(); it.Next()) { + r.Append(BRepBuilderAPI_Copy(it.Value())); + } + return r; +} + +TopoDS_Shape copy_operand(const TopoDS_Shape& s) { + return BRepBuilderAPI_Copy(s); +} + bool IfcGeom::Kernel::boolean_operation(const TopoDS_Shape& a, const TopTools_ListOfShape& b, BOPAlgo_Operation op, TopoDS_Shape& result, double fuzziness) { bool success = false; BRepAlgoAPI_BooleanOperation* builder; @@ -3070,10 +3087,10 @@ bool IfcGeom::Kernel::boolean_operation(const TopoDS_Shape& a, const TopTools_Li fuzziness = getValue(GV_PRECISION); } TopTools_ListOfShape s1s; - s1s.Append(a); + s1s.Append(copy_operand(a)); builder->SetFuzzyValue(fuzziness); builder->SetArguments(s1s); - builder->SetTools(b); + builder->SetTools(copy_operand(b)); builder->Build(); if (builder->IsDone()) { TopoDS_Shape r = *builder; diff --git a/src/ifcparse/IfcParse.cpp b/src/ifcparse/IfcParse.cpp index 860f1398db..bbe32e46e0 100644 --- a/src/ifcparse/IfcParse.cpp +++ b/src/ifcparse/IfcParse.cpp @@ -1907,7 +1907,7 @@ IfcEntityList::ptr IfcFile::getInverse(int instance_id, IfcSchema::Type::Enum ty IfcEntityListList::ptr li = *arg; valid = li->contains(instance); } - } catch (IfcException& e) { + } catch (const IfcException& e) { valid = false; Logger::Error(e); } From 452ba651d03b96692aa8f81b0b1fcdbd21e8a6c7 Mon Sep 17 00:00:00 2001 From: thorade Date: Mon, 23 Apr 2018 12:50:16 +0200 Subject: [PATCH 26/60] update SF.net download URL --- win/build-deps.cmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/win/build-deps.cmd b/win/build-deps.cmd index 6869363633..226fe9eb7d 100644 --- a/win/build-deps.cmd +++ b/win/build-deps.cmd @@ -432,7 +432,7 @@ set DEPENDENCY_NAME=SWIG %SWIG_VERSION% set DEPENDENCY_DIR=N/A set SWIG_ZIP=swigwin-%SWIG_VERSION%.zip cd "%DEPS_DIR%" -call :DownloadFile http://sourceforge.net/projects/swig/files/swigwin/swigwin-%SWIG_VERSION%/%SWIG_ZIP% "%DEPS_DIR%" %SWIG_ZIP% +call :DownloadFile https://datapacket.dl.sourceforge.net/project/swig/swigwin/swigwin-%SWIG_VERSION%/%SWIG_ZIP% "%DEPS_DIR%" %SWIG_ZIP% IF NOT %ERRORLEVEL%==0 GOTO :Error call :ExtractArchive %SWIG_ZIP% "%DEPS_DIR%" "%DEPS_DIR%\swigwin" IF NOT %ERRORLEVEL%==0 GOTO :Error From a24333486a20726a9cdff022ab0a289310321520 Mon Sep 17 00:00:00 2001 From: thorade Date: Mon, 23 Apr 2018 13:03:17 +0200 Subject: [PATCH 27/60] use SF instead of mirror --- win/build-deps.cmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/win/build-deps.cmd b/win/build-deps.cmd index 226fe9eb7d..390e4929da 100644 --- a/win/build-deps.cmd +++ b/win/build-deps.cmd @@ -432,7 +432,7 @@ set DEPENDENCY_NAME=SWIG %SWIG_VERSION% set DEPENDENCY_DIR=N/A set SWIG_ZIP=swigwin-%SWIG_VERSION%.zip cd "%DEPS_DIR%" -call :DownloadFile https://datapacket.dl.sourceforge.net/project/swig/swigwin/swigwin-%SWIG_VERSION%/%SWIG_ZIP% "%DEPS_DIR%" %SWIG_ZIP% +call :DownloadFile https://downloads.sourceforge.net/project/swig/swigwin/swigwin-%SWIG_VERSION%/%SWIG_ZIP% "%DEPS_DIR%" %SWIG_ZIP% IF NOT %ERRORLEVEL%==0 GOTO :Error call :ExtractArchive %SWIG_ZIP% "%DEPS_DIR%" "%DEPS_DIR%\swigwin" IF NOT %ERRORLEVEL%==0 GOTO :Error From baa021156258f169a6cea211b7d07abf8a836ca8 Mon Sep 17 00:00:00 2001 From: thorade Date: Mon, 23 Apr 2018 13:07:49 +0200 Subject: [PATCH 28/60] append download to the URL https://sourceforge.net/p/forge/documentation/Downloading%20files%20via%20the%20command%20line/ --- win/build-deps.cmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/win/build-deps.cmd b/win/build-deps.cmd index 390e4929da..7679a06701 100644 --- a/win/build-deps.cmd +++ b/win/build-deps.cmd @@ -432,7 +432,7 @@ set DEPENDENCY_NAME=SWIG %SWIG_VERSION% set DEPENDENCY_DIR=N/A set SWIG_ZIP=swigwin-%SWIG_VERSION%.zip cd "%DEPS_DIR%" -call :DownloadFile https://downloads.sourceforge.net/project/swig/swigwin/swigwin-%SWIG_VERSION%/%SWIG_ZIP% "%DEPS_DIR%" %SWIG_ZIP% +call :DownloadFile https://sourceforge.net/project/swig/swigwin/swigwin-%SWIG_VERSION%/%SWIG_ZIP%/download "%DEPS_DIR%" %SWIG_ZIP% IF NOT %ERRORLEVEL%==0 GOTO :Error call :ExtractArchive %SWIG_ZIP% "%DEPS_DIR%" "%DEPS_DIR%\swigwin" IF NOT %ERRORLEVEL%==0 GOTO :Error From 7994bcbb80a8221df30fa4b39859fafe1fdea62f Mon Sep 17 00:00:00 2001 From: thorade Date: Tue, 24 Apr 2018 13:34:33 +0200 Subject: [PATCH 29/60] https plus original URL --- win/build-deps.cmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/win/build-deps.cmd b/win/build-deps.cmd index 7679a06701..a993c26a6f 100644 --- a/win/build-deps.cmd +++ b/win/build-deps.cmd @@ -432,7 +432,7 @@ set DEPENDENCY_NAME=SWIG %SWIG_VERSION% set DEPENDENCY_DIR=N/A set SWIG_ZIP=swigwin-%SWIG_VERSION%.zip cd "%DEPS_DIR%" -call :DownloadFile https://sourceforge.net/project/swig/swigwin/swigwin-%SWIG_VERSION%/%SWIG_ZIP%/download "%DEPS_DIR%" %SWIG_ZIP% +call :DownloadFile https://sourceforge.net/projects/swig/files/swigwin/swigwin-%SWIG_VERSION%/%SWIG_ZIP% "%DEPS_DIR%" %SWIG_ZIP% IF NOT %ERRORLEVEL%==0 GOTO :Error call :ExtractArchive %SWIG_ZIP% "%DEPS_DIR%" "%DEPS_DIR%\swigwin" IF NOT %ERRORLEVEL%==0 GOTO :Error From bd9875fae5bcd299e8744edce9db484a40a8d943 Mon Sep 17 00:00:00 2001 From: thorade Date: Wed, 25 Apr 2018 14:28:18 +0200 Subject: [PATCH 30/60] set TLS to 1.2 --- win/build-deps.cmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/win/build-deps.cmd b/win/build-deps.cmd index a993c26a6f..cd85e0b4af 100644 --- a/win/build-deps.cmd +++ b/win/build-deps.cmd @@ -488,7 +488,7 @@ exit /b %IFCOS_SCRIPT_RET% pushd "%2" if not exist "%~3". ( call cecho.cmd 0 13 "Downloading %DEPENDENCY_NAME% into %~2." - powershell -Command "$webClient = new-object System.Net.WebClient; $webClient.Proxy.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials; $webClient.DownloadFile('%1', '%3')" + powershell -Command "[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12; $webClient = new-object System.Net.WebClient; $webClient.Proxy.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials; $webClient.DownloadFile('%1', '%3')" REM Old wget version in case someone has problem with PowerShell: wget --no-check-certificate %1 ) else ( call cecho.cmd 0 13 "%DEPENDENCY_NAME% already downloaded. Skipping." From 8ffc12e6cd5cb93430f055370ba0c80f84789c6b Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Tue, 8 May 2018 09:41:19 +0200 Subject: [PATCH 31/60] Reduce radius on wire intersections --- src/ifcgeom/IfcGeomFunctions.cpp | 2 +- src/ifcgeom/IfcGeomWires.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ifcgeom/IfcGeomFunctions.cpp b/src/ifcgeom/IfcGeomFunctions.cpp index 4957bf40db..f0401ad7fd 100644 --- a/src/ifcgeom/IfcGeomFunctions.cpp +++ b/src/ifcgeom/IfcGeomFunctions.cpp @@ -2863,7 +2863,7 @@ bool IfcGeom::Kernel::wire_intersections(const TopoDS_Wire& wire, TopTools_ListO if (i == n - 1 && j == 0) continue; bool unbounded_intersects; - const double eps = getValue(GV_PRECISION) * 10.; + const double eps = getValue(GV_PRECISION) * 2.; double u11, u12, u21, u22, U1, U2; GeomAPI_ExtremaCurveCurve ecc( diff --git a/src/ifcgeom/IfcGeomWires.cpp b/src/ifcgeom/IfcGeomWires.cpp index e1e2ed4781..935aeedfd6 100644 --- a/src/ifcgeom/IfcGeomWires.cpp +++ b/src/ifcgeom/IfcGeomWires.cpp @@ -397,7 +397,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcPolyline* l, TopoDS_Wire& resu polygon.Append(pnt); } - const double eps = getValue(GV_PRECISION) * 10; + const double eps = getValue(GV_PRECISION) * 2.; const bool closed_by_proximity = polygon.Length() >= 2 && polygon.First().Distance(polygon.Last()) < eps; if (closed_by_proximity) { // tfk: note 1-based @@ -439,7 +439,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcPolyLoop* l, TopoDS_Wire& resu } // Remove points that are too close to one another - const double eps = getValue(GV_PRECISION) * 10; + const double eps = getValue(GV_PRECISION) * 2.; remove_duplicate_points_from_loop(polygon, true, eps); int count = polygon.Length(); From 589f4bda2ecdd02366225b541376576c04a2da27 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Tue, 8 May 2018 16:19:47 +0200 Subject: [PATCH 32/60] ... but keep close point removal at 10 times precision --- src/ifcgeom/IfcGeomWires.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ifcgeom/IfcGeomWires.cpp b/src/ifcgeom/IfcGeomWires.cpp index 935aeedfd6..e1e2ed4781 100644 --- a/src/ifcgeom/IfcGeomWires.cpp +++ b/src/ifcgeom/IfcGeomWires.cpp @@ -397,7 +397,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcPolyline* l, TopoDS_Wire& resu polygon.Append(pnt); } - const double eps = getValue(GV_PRECISION) * 2.; + const double eps = getValue(GV_PRECISION) * 10; const bool closed_by_proximity = polygon.Length() >= 2 && polygon.First().Distance(polygon.Last()) < eps; if (closed_by_proximity) { // tfk: note 1-based @@ -439,7 +439,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcPolyLoop* l, TopoDS_Wire& resu } // Remove points that are too close to one another - const double eps = getValue(GV_PRECISION) * 2.; + const double eps = getValue(GV_PRECISION) * 10; remove_duplicate_points_from_loop(polygon, true, eps); int count = polygon.Length(); From 7786b8926952cb02c4f8409e0fd89370eace55af Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Sat, 12 May 2018 20:12:25 +0200 Subject: [PATCH 33/60] Machine readable progress with -q and --log-format json --- src/ifcconvert/IfcConvert.cpp | 163 +++++++++++++++++++++------------- src/ifcparse/IfcLogger.cpp | 57 ++++++++++-- src/ifcparse/IfcLogger.h | 8 +- 3 files changed, 157 insertions(+), 71 deletions(-) diff --git a/src/ifcconvert/IfcConvert.cpp b/src/ifcconvert/IfcConvert.cpp index 8d386b8b04..65de7f2a30 100644 --- a/src/ifcconvert/IfcConvert.cpp +++ b/src/ifcconvert/IfcConvert.cpp @@ -113,7 +113,7 @@ bool rename_file(const std::string& old_filename, const std::string& new_filenam } static std::stringstream log_stream; -void write_log(); +void write_log(bool); /// @todo make the filters non-global IfcGeom::entity_filter entity_filter; // Entity filter is used always by default. @@ -152,13 +152,16 @@ bool init_input_file(const std::string& filename, IfcParse::IfcFile& ifc_file, b int main(int argc, char** argv) { + std::string log_format; po::options_description generic_options("Command line options"); generic_options.add_options() ("help,h", "display usage information") ("version", "display version information") - ("verbose,v", "more verbose output") - ("yes,y", "answer 'yes' automatically to possible confirmation queries (e.g. overwriting an existing output file)") - ("no-progress", "Suppress possible progress bar type of prints that use carriage return."); + ("verbose,v", "more verbose log messages") + ("quiet,q", "less status and progress output") + ("yes,y", "answer 'yes' automatically to possible confirmation queries (e.g. overwriting an existing output file)") + ("no-progress", "suppress possible progress bar type of prints that use carriage return") + ("log-format", po::value(&log_format), "log format: plain or json"); po::options_description fileio_options; fileio_options.add_options() @@ -174,7 +177,7 @@ int main(int argc, char** argv) inclusion_traverse_filter include_traverse_filter; exclusion_filter exclude_filter; exclusion_traverse_filter exclude_traverse_filter; - std::string filter_filename; + std::string filter_filename; po::options_description geom_options("Geometry options"); geom_options.add_options() @@ -336,7 +339,36 @@ int main(int argc, char** argv) po::notify(vmap); - print_version(); + const bool mmap = vmap.count("mmap") != 0; + const bool verbose = vmap.count("verbose") != 0; + const bool no_progress = vmap.count("no-progress") != 0; + const bool quiet = vmap.count("quiet") != 0; + const bool weld_vertices = vmap.count("weld-vertices") != 0; + const bool use_world_coords = vmap.count("use-world-coords") != 0; + const bool convert_back_units = vmap.count("convert-back-units") != 0; + const bool sew_shells = vmap.count("sew-shells") != 0; +#if OCC_VERSION_HEX < 0x60900 + const bool merge_boolean_operands = vmap.count("merge-boolean-operands") != 0; +#endif + const bool disable_opening_subtractions = vmap.count("disable-opening-subtractions") != 0; + const bool include_plan = vmap.count("plan") != 0; + const bool include_model = vmap.count("model") != 0 || (!include_plan); + const bool enable_layerset_slicing = vmap.count("enable-layerset-slicing") != 0; + const bool use_element_names = vmap.count("use-element-names") != 0; + const bool use_element_guids = vmap.count("use-element-guids") != 0; + const bool use_material_names = vmap.count("use-material-names") != 0; + const bool use_element_types = vmap.count("use-element-types") != 0; + const bool use_element_hierarchy = vmap.count("use-element-hierarchy") != 0; + const bool no_normals = vmap.count("no-normals") != 0; + const bool center_model = vmap.count("center-model") != 0; + const bool model_offset = vmap.count("model-offset") != 0; + const bool site_local_placement = vmap.count("site-local-placement") != 0; + const bool building_local_placement = vmap.count("building-local-placement") != 0; + const bool generate_uvs = vmap.count("generate-uvs") != 0; + + if (!quiet || vmap.count("version")) { + print_version(); + } if (vmap.count("version")) { return EXIT_SUCCESS; @@ -349,31 +381,6 @@ int main(int argc, char** argv) print_usage(); return EXIT_FAILURE; } - const bool mmap = vmap.count("mmap") != 0; - const bool verbose = vmap.count("verbose") != 0; - const bool no_progress = vmap.count("no-progress") != 0; - const bool weld_vertices = vmap.count("weld-vertices") != 0; - const bool use_world_coords = vmap.count("use-world-coords") != 0; - const bool convert_back_units = vmap.count("convert-back-units") != 0; - const bool sew_shells = vmap.count("sew-shells") != 0; -#if OCC_VERSION_HEX < 0x60900 - const bool merge_boolean_operands = vmap.count("merge-boolean-operands") != 0; -#endif - const bool disable_opening_subtractions = vmap.count("disable-opening-subtractions") != 0; - const bool include_plan = vmap.count("plan") != 0; - const bool include_model = vmap.count("model") != 0 || (!include_plan); - const bool enable_layerset_slicing = vmap.count("enable-layerset-slicing") != 0; - const bool use_element_names = vmap.count("use-element-names") != 0; - const bool use_element_guids = vmap.count("use-element-guids") != 0 ; - const bool use_material_names = vmap.count("use-material-names") != 0; - const bool use_element_types = vmap.count("use-element-types") != 0; - const bool use_element_hierarchy = vmap.count("use-element-hierarchy") != 0; - const bool no_normals = vmap.count("no-normals") != 0 ; - const bool center_model = vmap.count("center-model") != 0 ; - const bool model_offset = vmap.count("model-offset") != 0 ; - const bool site_local_placement = vmap.count("site-local-placement") != 0 ; - const bool building_local_placement = vmap.count("building-local-placement") != 0 ; - const bool generate_uvs = vmap.count("generate-uvs") != 0 ; #ifdef HAVE_ICU if (!unicode_mode.empty()) { @@ -438,12 +445,25 @@ int main(int argc, char** argv) Logger::SetOutput(&std::cout, &log_stream); Logger::Verbosity(verbose ? Logger::LOG_NOTICE : Logger::LOG_ERROR); + if (vmap.count("log-format") == 1) { + boost::to_lower(log_format); + if (log_format == "plain") { + Logger::OutputFormat(Logger::FMT_PLAIN); + } else if (log_format == "json") { + Logger::OutputFormat(Logger::FMT_JSON); + } else { + std::cerr << "[Error] --log-format should be either plain or json" << std::endl; + print_usage(); + return EXIT_FAILURE; + } + } + IfcParse::IfcFile ifc_file; if (output_extension == ".xml") { int exit_code = EXIT_FAILURE; try { - if (init_input_file(input_filename, ifc_file, no_progress, mmap)) { + if (init_input_file(input_filename, ifc_file, no_progress || quiet, mmap)) { XmlSerializer s(output_temp_filename); s.setFile(&ifc_file); Logger::Status("Writing XML output..."); @@ -455,7 +475,7 @@ int main(int argc, char** argv) } catch (const std::exception& e) { Logger::Error(e); } - write_log(); + write_log(!quiet); return exit_code; } @@ -548,7 +568,7 @@ int main(int argc, char** argv) } } else { std::cerr << "[Error] Unknown output filename extension '" + output_extension + "'\n"; - write_log(); + write_log(!quiet); print_usage(); return EXIT_FAILURE; } @@ -557,7 +577,7 @@ int main(int argc, char** argv) if (use_element_hierarchy && output_extension != ".dae") { std::cerr << "[Error] --use-element-hierarchy can be used only with .dae output.\n"; - write_log(); + write_log(!quiet); print_usage(); delete serializer; std::remove(output_temp_filename.c_str()); /**< @todo Windows Unicode support */ @@ -582,14 +602,14 @@ int main(int argc, char** argv) if (!serializer->ready()) { delete serializer; std::remove(output_temp_filename.c_str()); /**< @todo Windows Unicode support */ - write_log(); + write_log(!quiet); return EXIT_FAILURE; } time_t start,end; time(&start); - if (!init_input_file(input_filename, ifc_file, no_progress, mmap)) { + if (!init_input_file(input_filename, ifc_file, no_progress || quiet, mmap)) { return EXIT_FAILURE; } @@ -600,7 +620,7 @@ int main(int argc, char** argv) Logger::Error("No geometrical entities found"); delete serializer; std::remove(output_temp_filename.c_str()); /**< @todo Windows Unicode support */ - write_log(); + write_log(!quiet); return EXIT_FAILURE; } @@ -614,7 +634,7 @@ int main(int argc, char** argv) serializer->writeHeader(); - int old_progress = -1; + int old_progress = quiet ? 0 : -1; if (center_model || model_offset) { double* offset = serializer->settings().offset; @@ -643,7 +663,9 @@ int main(int argc, char** argv) Logger::Notice(msg.str()); } - Logger::Status("Creating geometry..."); + if (!quiet) { + Logger::Status("Creating geometry..."); + } // The functions IfcGeom::Iterator::get() and IfcGeom::Iterator::next() // wrap an iterator of all geometrical products in the Ifc file. @@ -670,14 +692,28 @@ int main(int argc, char** argv) } if (!no_progress) { - const int progress = context_iterator.progress() / 2; - if (old_progress != progress) Logger::ProgressBar(progress); - old_progress = progress; + if (quiet) { + const int progress = context_iterator.progress(); + for (; old_progress < progress; ++old_progress) { + std::cout << "."; + } + std::cout << 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()); - Logger::Status("\rDone creating geometry (" + boost::lexical_cast(num_created) + - " objects) "); + if (!no_progress && quiet) { + for (; old_progress < 100; ++old_progress) { + std::cout << "."; + } + } else { + Logger::Status("\rDone creating geometry (" + boost::lexical_cast(num_created) + + " objects) "); + } serializer->finalize(); delete serializer; @@ -690,34 +726,39 @@ int main(int argc, char** argv) output_temp_filename + "' for the conversion result."); } - write_log(); + write_log(!quiet); time(&end); - int seconds = (int)difftime(end, start); - std::stringstream msg; - int minutes = seconds / 60; - seconds = seconds % 60; - msg << "\nConversion took"; - if (minutes > 0) { - msg << " " << minutes << " minute"; - if (minutes > 1) { + if (!quiet) { + int seconds = (int)difftime(end, start); + std::stringstream msg; + int minutes = seconds / 60; + seconds = seconds % 60; + msg << "\nConversion took"; + if (minutes > 0) { + msg << " " << minutes << " minute"; + if (minutes > 1) { + msg << "s"; + } + } + msg << " " << seconds << " second"; + if (seconds > 1) { msg << "s"; } + Logger::Status(msg.str()); } - msg << " " << seconds << " second"; - if (seconds > 1) { - msg << "s"; - } - Logger::Status(msg.str()); return successful ? EXIT_SUCCESS : EXIT_FAILURE; } -void write_log() { +void write_log(bool header) { std::string log = log_stream.str(); if (!log.empty()) { - std::cout << "\nLog:\n" << log << std::endl; + if (header) { + std::cout << "\nLog:\n"; + } + std::cout << log << std::endl; } } diff --git a/src/ifcparse/IfcLogger.cpp b/src/ifcparse/IfcLogger.cpp index 4fe538365e..2fcc9d3c2f 100644 --- a/src/ifcparse/IfcLogger.cpp +++ b/src/ifcparse/IfcLogger.cpp @@ -23,13 +23,47 @@ #include #include +#include +#include +#include + #include #include +using boost::property_tree::ptree; + +namespace { + static const char* severity_strings[] = {"Notice", "Warning", "Error"}; + + void plain_text_message(std::ostream& os, const boost::optional& current_product, Logger::Severity type, const std::string& message, IfcEntityInstanceData* entity) { + os << "[" << severity_strings[type] << "] "; + if (current_product) { + os << "{" << (*current_product)->GlobalId() << "} "; + } + os << message << std::endl; + if (entity) { + os << entity->toString() << std::endl; + } + } + + void json_message(std::ostream& os, const boost::optional& current_product, Logger::Severity type, const std::string& message, IfcEntityInstanceData* entity) { + ptree pt; + pt.put("level", severity_strings[type]); + if (current_product) { + pt.put("product", (**current_product).entity->toString()); + } + pt.put("message", message); + if (entity) { + pt.put("instance", entity); + } + boost::property_tree::write_json(os, pt, false); + } +} void Logger::SetProduct(boost::optional product) { current_product = product; } + void Logger::SetOutput(std::ostream* l1, std::ostream* l2) { log1 = l1; log2 = l2; @@ -39,13 +73,12 @@ void Logger::SetOutput(std::ostream* l1, std::ostream* l2) { } void Logger::Message(Logger::Severity type, const std::string& message, IfcEntityInstanceData* entity) { - if ( log2 && type >= verbosity ) { - (*log2) << "[" << severity_strings[type] << "] "; - if ( current_product ) { - (*log2) << "{" << (*current_product)->GlobalId() << "} "; + if (log2 && type >= verbosity) { + if (format == FMT_PLAIN) { + plain_text_message(*log2, current_product, type, message, entity); + } else if (format == FMT_JSON) { + json_message(*log2, current_product, type, message, entity); } - (*log2) << message << std::endl; - if ( entity ) (*log2) << entity->toString() << std::endl; } } @@ -54,26 +87,32 @@ void Logger::Message(Logger::Severity type, const std::exception& exception, Ifc } void Logger::Status(const std::string& message, bool new_line) { - if ( log1 ) { + if (log1) { (*log1) << message; if ( new_line ) (*log1) << std::endl; else (*log1) << std::flush; } } + void Logger::ProgressBar(int progress) { - if ( log1 ) { + if (log1) { Status("\r[" + std::string(progress,'#') + std::string(50 - progress,' ') + "]", false); } } + std::string Logger::GetLog() { return log_stream.str(); } + void Logger::Verbosity(Logger::Severity v) { verbosity = v; } Logger::Severity Logger::Verbosity() { return verbosity; } +void Logger::OutputFormat(Format f) { format = f; } +Logger::Format Logger::OutputFormat() { return format; } + std::ostream* Logger::log1 = 0; std::ostream* Logger::log2 = 0; std::stringstream Logger::log_stream; Logger::Severity Logger::verbosity = Logger::LOG_NOTICE; -const char* Logger::severity_strings[] = { "Notice","Warning","Error" }; +Logger::Format Logger::format = Logger::FMT_PLAIN; boost::optional Logger::current_product; \ No newline at end of file diff --git a/src/ifcparse/IfcLogger.h b/src/ifcparse/IfcLogger.h index f5e6f9c0ee..ce13ee7558 100644 --- a/src/ifcparse/IfcLogger.h +++ b/src/ifcparse/IfcLogger.h @@ -40,20 +40,26 @@ class IFC_PARSE_API Logger { public: typedef enum { LOG_NOTICE, LOG_WARNING, LOG_ERROR } Severity; + typedef enum { FMT_PLAIN, FMT_JSON } Format; private: static std::ostream* log1; static std::ostream* log2; static std::stringstream log_stream; static Severity verbosity; - static const char* severity_strings[]; + static Format format; static boost::optional current_product; public: static void SetProduct(boost::optional product); /// Determines to what stream respectively progress and errors are logged static void SetOutput(std::ostream* l1, std::ostream* l2); + /// Determines the types of log messages to get logged static void Verbosity(Severity v); static Severity Verbosity(); + + /// Determines output format: plain text or sequence of JSON objects + static void OutputFormat(Format f); + static Format OutputFormat(); /// Log a message to the output stream static void Message(Severity type, const std::string& message, IfcEntityInstanceData* entity=0); From 089bb95c9f1f7552d6e5b8e423f2d2b98b66a77d Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Sun, 13 May 2018 08:45:33 +0200 Subject: [PATCH 34/60] Fix previous commit on gcc --- src/ifcconvert/ColladaSerializer.cpp | 6 +++--- src/ifcconvert/IfcConvert.cpp | 2 +- src/ifcconvert/XmlSerializer.cpp | 9 +++++---- src/ifcgeom/IfcGeomFilter.h | 17 +++++++++-------- src/ifcparse/Argument.h | 4 ---- 5 files changed, 18 insertions(+), 20 deletions(-) diff --git a/src/ifcconvert/ColladaSerializer.cpp b/src/ifcconvert/ColladaSerializer.cpp index 0596829b42..827ee924c4 100644 --- a/src/ifcconvert/ColladaSerializer.cpp +++ b/src/ifcconvert/ColladaSerializer.cpp @@ -225,7 +225,7 @@ void ColladaSerializer::ColladaExporter::ColladaScene::add( node.addMatrix(matrix_array); COLLADASW::InstanceGeometry instanceGeometry(mSW); instanceGeometry.setUrl ("#" + geom_name); - foreach(std::string material_name, material_ids) { + BOOST_FOREACH(std::string material_name, material_ids) { /// @todo This is done 6 times in this file, try to perform this once and be done with the material naming for the export. collada_id(material_name); COLLADASW::InstanceMaterial material (material_name, "#" + material_name); @@ -364,7 +364,7 @@ bool ColladaSerializer::ColladaExporter::ColladaMaterials::contains(const IfcGeo void ColladaSerializer::ColladaExporter::ColladaMaterials::write() { effects.close(); - foreach(const IfcGeom::Material& material, materials) { + BOOST_FOREACH(const IfcGeom::Material& material, materials) { std::string material_name = (serializer->settings().get(SerializerSettings::USE_MATERIAL_NAMES) ? material.original_name() : material.name()); std::string material_name_unescaped = material_name; // workaround double-escaping that would occur in addInstanceEffect() @@ -410,7 +410,7 @@ void ColladaSerializer::ColladaExporter::write(const IfcGeom::TriangulationEleme collada_id(representation_id); std::vector material_references; - foreach(const IfcGeom::Material& material, mesh.materials()) { + BOOST_FOREACH(const IfcGeom::Material& material, mesh.materials()) { if (!materials.contains(material)) { materials.add(material); } diff --git a/src/ifcconvert/IfcConvert.cpp b/src/ifcconvert/IfcConvert.cpp index 65de7f2a30..9fed6f79f5 100644 --- a/src/ifcconvert/IfcConvert.cpp +++ b/src/ifcconvert/IfcConvert.cpp @@ -913,7 +913,7 @@ void validate(boost::any& v, const std::vector& values, exclusion_t std::vector setup_filters(const std::vector& filters, const std::string& output_extension) { std::vector filter_funcs; - foreach(const geom_filter& f, filters) { + BOOST_FOREACH(const geom_filter& f, filters) { if (f.type == geom_filter::ENTITY_TYPE) { entity_filter.include = f.include; entity_filter.traverse = f.traverse; diff --git a/src/ifcconvert/XmlSerializer.cpp b/src/ifcconvert/XmlSerializer.cpp index cf1f97cfe8..eb5105dffc 100644 --- a/src/ifcconvert/XmlSerializer.cpp +++ b/src/ifcconvert/XmlSerializer.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include "XmlSerializer.h" @@ -340,16 +341,16 @@ void XmlSerializer::finalize() { ptree root, header, units, decomposition, properties, quantities, types, layers, materials; // Write the SPF header as XML nodes. - foreach(const std::string& s, file->header().file_description().description()) { + BOOST_FOREACH(const std::string& s, file->header().file_description().description()) { header.add_child("file_description.description", ptree(s)); } - foreach(const std::string& s, file->header().file_name().author()) { + BOOST_FOREACH(const std::string& s, file->header().file_name().author()) { header.add_child("file_name.author", ptree(s)); } - foreach(const std::string& s, file->header().file_name().organization()) { + BOOST_FOREACH(const std::string& s, file->header().file_name().organization()) { header.add_child("file_name.organization", ptree(s)); } - foreach(const std::string& s, file->header().file_schema().schema_identifiers()) { + BOOST_FOREACH(const std::string& s, file->header().file_schema().schema_identifiers()) { header.add_child("file_schema.schema_identifiers", ptree(s)); } header.put("file_description.implementation_level", file->header().file_description().implementation_level()); diff --git a/src/ifcgeom/IfcGeomFilter.h b/src/ifcgeom/IfcGeomFilter.h index 043de7639a..d766f2b463 100644 --- a/src/ifcgeom/IfcGeomFilter.h +++ b/src/ifcgeom/IfcGeomFilter.h @@ -25,6 +25,7 @@ #include "IfcGeom.h" +#include #include #include #include @@ -87,7 +88,7 @@ namespace IfcGeom void populate(const std::set& patterns) { values.clear(); - foreach(const std::string &pattern, patterns) { + BOOST_FOREACH(const std::string &pattern, patterns) { values.insert(wildcard_string_to_regex(pattern)); } } @@ -96,7 +97,7 @@ namespace IfcGeom static bool match_values(const std::set& values, const std::string &str) { - foreach(const boost::regex& r, values) { + BOOST_FOREACH(const boost::regex& r, values) { if (boost::regex_match(str, r)) { return true; } @@ -108,7 +109,7 @@ namespace IfcGeom { // Escape all non-"*?" regex special chars static const std::string special_chars = "\\^.$|()[]+/"; - foreach(char c, special_chars) { + BOOST_FOREACH(char c, special_chars) { std::string char_str(1, c); boost::replace_all(str, char_str, "\\" + char_str); } @@ -180,7 +181,7 @@ namespace IfcGeom ss << (traverse ? "traverse " : "") << (include ? "include" : "exclude"); std::vector patterns; - foreach(const boost::regex& r, values) { + BOOST_FOREACH(const boost::regex& r, values) { patterns.push_back("\"" + r.str() + "\""); } @@ -237,7 +238,7 @@ namespace IfcGeom std::stringstream ss; ss << (traverse ? "traverse " : "") << (include ? "include" : "exclude") << " layers"; std::vector str_values; - foreach(const boost::regex& r, values) { + BOOST_FOREACH(const boost::regex& r, values) { str_values.push_back(" \"" + r.str() + "\""); } ss << boost::algorithm::join(str_values, " "); @@ -259,7 +260,7 @@ namespace IfcGeom void populate(const std::set& types) { values.clear(); - foreach(const std::string& type, types) { + BOOST_FOREACH(const std::string& type, types) { IfcSchema::Type::Enum ty; try { ty = IfcSchema::Type::FromString(boost::to_upper_copy(type)); @@ -274,7 +275,7 @@ namespace IfcGeom bool match(IfcSchema::IfcProduct* prod) const { // The set is iterated over to able to filter on subtypes. - foreach(IfcSchema::Type::Enum type, values) { + BOOST_FOREACH(IfcSchema::Type::Enum type, values) { if (prod->is(type)) { return true; } @@ -291,7 +292,7 @@ namespace IfcGeom { std::stringstream ss; ss << (traverse ? "traverse " : "") << (include ? "include" : "exclude") << " entities"; - foreach(IfcSchema::Type::Enum type, values) { + BOOST_FOREACH(IfcSchema::Type::Enum type, values) { ss << " " << IfcSchema::Type::ToString(type); } description = ss.str(); diff --git a/src/ifcparse/Argument.h b/src/ifcparse/Argument.h index 69860f4425..ef7787ac52 100644 --- a/src/ifcparse/Argument.h +++ b/src/ifcparse/Argument.h @@ -38,10 +38,6 @@ #include #include -#include - -#define foreach BOOST_FOREACH -#define rforeach BOOST_REVERSE_FOREACH class Argument; class IfcEntityList; From ef7a1ab421a362e62f971c3c5752f2d7104301d1 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Sun, 13 May 2018 09:15:06 +0200 Subject: [PATCH 35/60] Limit boolean fuzz to edge length --- src/ifcgeom/IfcGeomFunctions.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/ifcgeom/IfcGeomFunctions.cpp b/src/ifcgeom/IfcGeomFunctions.cpp index f0401ad7fd..c9dcc1577e 100644 --- a/src/ifcgeom/IfcGeomFunctions.cpp +++ b/src/ifcgeom/IfcGeomFunctions.cpp @@ -3086,9 +3086,22 @@ bool IfcGeom::Kernel::boolean_operation(const TopoDS_Shape& a, const TopTools_Li if (fuzziness < 0.) { fuzziness = getValue(GV_PRECISION); } + + double min_edge_len = std::numeric_limits::infinity(); + // ... to be sure to get consecutive edges + TopExp_Explorer exp(a, TopAbs_EDGE); + for (; exp.More(); exp.Next()) { + GProp_GProps prop; + BRepGProp::LinearProperties(exp.Current(), prop); + double l = prop.Mass(); + if (l < min_edge_len) { + min_edge_len = l; + } + } + TopTools_ListOfShape s1s; s1s.Append(copy_operand(a)); - builder->SetFuzzyValue(fuzziness); + builder->SetFuzzyValue((std::min)(min_edge_len / 3., fuzziness)); builder->SetArguments(s1s); builder->SetTools(copy_operand(b)); builder->Build(); @@ -3112,7 +3125,7 @@ bool IfcGeom::Kernel::boolean_operation(const TopoDS_Shape& a, const TopTools_Li delete builder; if (!success) { const double new_fuzziness = fuzziness * 10.; - if (new_fuzziness + 1e-15 <= getValue(GV_PRECISION) * 1000.) { + if (new_fuzziness + 1e-15 <= getValue(GV_PRECISION) * 1000. && new_fuzziness < min_edge_len) { return boolean_operation(a, b, op, result, new_fuzziness); } } From 966e57e94ac8d59549319ca75a0ca3d0205d5208 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Sun, 13 May 2018 14:41:39 +0200 Subject: [PATCH 36/60] #332 --- src/ifcgeom/IfcGeomWires.cpp | 254 +++++++++++++++++++++++------------ 1 file changed, 171 insertions(+), 83 deletions(-) diff --git a/src/ifcgeom/IfcGeomWires.cpp b/src/ifcgeom/IfcGeomWires.cpp index e1e2ed4781..99d0332c0c 100644 --- a/src/ifcgeom/IfcGeomWires.cpp +++ b/src/ifcgeom/IfcGeomWires.cpp @@ -85,9 +85,161 @@ #include #include +#include + #include "../ifcgeom/IfcGeom.h" +namespace { + // Returns the other vertex of an edge + TopoDS_Vertex other(const TopoDS_Edge& e, const TopoDS_Vertex& v) { + TopoDS_Vertex a, b; + TopExp::Vertices(e, a, b); + return v.IsSame(b) ? a : b; + } + + // Returns new wire with the edge replaced by a linear edge with the vertex v moved to p + TopoDS_Wire adjust(const TopoDS_Wire& w, const TopoDS_Edge& e, const TopoDS_Vertex& v, const gp_Pnt& p) { + gp_Pnt p1 = p; + gp_Pnt p2 = BRep_Tool::Pnt(other(e, v)); + + if (e.Orientation() == TopAbs_REVERSED) { + std::swap(p1, p2); + } + + // Already asserted this is a replacement for a linear edge + TopoDS_Edge new_edge = BRepBuilderAPI_MakeEdge(p1, p2).Edge(); + new_edge.Orientation(e.Orientation()); + + ShapeBuild_ReShape reshape; + reshape.Replace(e, new_edge); + + return TopoDS::Wire(reshape.Apply(w)); + } + + // A wrapper around BRepBuilderAPI_MakeWire that makes sure segments are connected either by moving end points or by adding intermediate segments + class wire_builder { + private: + BRepBuilderAPI_MakeWire mw_; + double p_; + bool skip_next_; + const IfcUtil::IfcBaseClass* inst_; + + public: + wire_builder(double p, const IfcUtil::IfcBaseClass* inst = 0) : p_(p), skip_next_(false), inst_(inst) {} + + void operator()(const TopoDS_Shape& a) { + if (skip_next_) { + // tfk: not ideal, adjusting both start and end points not supported now. + skip_next_ = false; + return; + } + + mw_.Add(TopoDS::Wire(a)); + } + + void operator()(const TopoDS_Shape& a, const TopoDS_Shape& b, bool last) { + if (skip_next_) { + // tfk: not ideal, adjusting both start and end points not supported now. + skip_next_ = false; + return; + } + + const TopoDS_Wire& w1 = TopoDS::Wire(a); + const TopoDS_Wire& w2 = TopoDS::Wire(b); + + TopoDS_Vertex w11, w12, w21, w22; + TopExp::Vertices(w1, w11, w12); + TopExp::Vertices(w2, w21, w22); + + gp_Pnt p1 = BRep_Tool::Pnt(w12); + gp_Pnt p2 = BRep_Tool::Pnt(w21); + + double dist = p1.Distance(p2); + TopTools_IndexedDataMapOfShapeListOfShape wmap1, wmap2; + + // Distance is within 2p, this is fine + if (dist < 2. * p_) { + mw_.Add(w1); + goto check; + } + + // Distance is too large for attempting to move end points, add intermediate edge + if (dist > 1000. * p_) { + mw_.Add(w1); + mw_.Add(BRepBuilderAPI_MakeEdge(p1, p2)); + Logger::Message(Logger::LOG_ERROR, "Added additional segment to close gap with length " + boost::lexical_cast(dist) + " to:", inst_->entity); + goto check; + } + + // Find edges connected to end- and begin vertex + TopExp::MapShapesAndAncestors(w1, TopAbs_VERTEX, TopAbs_EDGE, wmap1); + TopExp::MapShapesAndAncestors(w2, TopAbs_VERTEX, TopAbs_EDGE, wmap2); + + const TopTools_ListOfShape& last_edges = wmap1.FindFromKey(w12); + const TopTools_ListOfShape& first_edges = wmap2.FindFromKey(w21); + + double _, __; + if (last_edges.Extent() == 1 && first_edges.Extent() == 1) { + Handle(Geom_Curve) c1 = BRep_Tool::Curve(TopoDS::Edge(last_edges.First()), _, __); + Handle(Geom_Curve) c2 = BRep_Tool::Curve(TopoDS::Edge(first_edges.First()), _, __); + + const bool is_line1 = c1->DynamicType() == STANDARD_TYPE(Geom_Line); + const bool is_line2 = c2->DynamicType() == STANDARD_TYPE(Geom_Line); + + // Adjust the segment that is linear + if (is_line1) { + mw_.Add(adjust(w1, TopoDS::Edge(last_edges.First()), w12, p2)); + Logger::Message(Logger::LOG_ERROR, "Adjusted edge end-point with distance " + boost::lexical_cast(dist) + " on:", inst_->entity); + } else if (is_line2 && !last) { + // tfk: not ideal, begin point of first edge cannot be adjusted now for cyclic wires + mw_.Add(w1); + mw_.Add(adjust(w1, TopoDS::Edge(last_edges.First()), w12, p2)); + skip_next_ = true; + Logger::Message(Logger::LOG_ERROR, "Adjusted edge end-point with distance " + boost::lexical_cast(dist) + " on:", inst_->entity); + } else { + // If both aren't linear an edge is added + mw_.Add(w1); + mw_.Add(BRepBuilderAPI_MakeEdge(p1, p2)); + Logger::Message(Logger::LOG_ERROR, "Added additional segment to close gap with length " + boost::lexical_cast(dist) + " to:", inst_->entity); + } + } else { + Logger::Error("Internal error, inconsistent wire segments", inst_->entity); + mw_.Add(w1); + } + + check: + if (mw_.Error() == BRepBuilderAPI_NonManifoldWire) { + Logger::Error("Non-manifold curve segments:", inst_->entity); + } else if (mw_.Error() == BRepBuilderAPI_DisconnectedWire) { + Logger::Error("Failed to join curve segments:", inst_->entity); + } + } + + const TopoDS_Wire& wire() { return mw_.Wire(); } + }; + + template + void shape_pair_enumerate(TopTools_ListIteratorOfListOfShape& it, Fn& fn, bool closed) { + bool is_first = true; + TopoDS_Shape first, previous, current; + for (; it.More(); it.Next(), is_first = false) { + current = it.Value(); + if (is_first) { + first = current; + } else { + fn(previous, current, false); + } + previous = current; + } + if (closed) { + fn(current, first, true); + } else { + fn(current); + } + } +} + bool IfcGeom::Kernel::convert(const IfcSchema::IfcCompositeCurve* l, TopoDS_Wire& wire) { if ( getValue(GV_PLANEANGLE_UNIT)<0 ) { Logger::Message(Logger::LOG_WARNING,"Creating a composite curve without unit information:",l->entity); @@ -165,109 +317,45 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcCompositeCurve* l, TopoDS_Wire return use_radians || use_degrees; } - BRepBuilderAPI_MakeWire w; - TopoDS_Vertex wire_first_vertex, wire_last_vertex, edge_first_vertex, edge_last_vertex; + IfcSchema::IfcCompositeCurveSegment::list::ptr segments = l->Segments(); - const double precision_sq_2 = 2 * getValue(GV_PRECISION) * getValue(GV_PRECISION); + TopTools_ListOfShape converted_segments; - for(IfcSchema::IfcCompositeCurveSegment::list::it it = segments->begin(); it != segments->end(); ++it) { - + for (IfcSchema::IfcCompositeCurveSegment::list::it it = segments->begin(); it != segments->end(); ++it) { + IfcSchema::IfcCurve* curve = (*it)->ParentCurve(); TopoDS_Wire segment; - + if (!convert_wire(curve, segment)) { Logger::Message(Logger::LOG_ERROR, "Failed to convert curve:", curve->entity); continue; } - + if (!(*it)->SameSense()) { segment.Reverse(); } - + ShapeFix_ShapeTolerance FTol; FTol.SetTolerance(segment, getValue(GV_PRECISION), TopAbs_WIRE); - - TopExp::Vertices(segment, edge_first_vertex, edge_last_vertex); - if (it == segments->begin()) { - wire_first_vertex = edge_first_vertex; - } else { - gp_Pnt first = BRep_Tool::Pnt(edge_first_vertex); - gp_Pnt last = BRep_Tool::Pnt(wire_last_vertex); + converted_segments.Append(segment); - Standard_Real distance = first.SquareDistance(last); - if (distance > precision_sq_2) { - w.Add(BRepBuilderAPI_MakeEdge(wire_last_vertex, edge_first_vertex)); - - Logger::Message(Logger::LOG_ERROR, "Closed gap on:", l->entity); - } - } - - w.Add(segment); - - if ( w.Error() != BRepBuilderAPI_WireDone ) { - if (w.Error() == BRepBuilderAPI_NonManifoldWire) { - - Logger::Message(Logger::LOG_ERROR, "Non-manifold curve segments:", l->entity); - - } else if (w.Error() == BRepBuilderAPI_DisconnectedWire) { - - Logger::Message(Logger::LOG_ERROR, "Failed to join curve segments:", l->entity); - - gp_Pnt p1, p2; - int precision = 4; - double d = 0.; - - if (!wire_last_vertex.IsNull()) { - p1 = BRep_Tool::Pnt(wire_last_vertex); - } - if (!edge_first_vertex.IsNull()) { - p2 = BRep_Tool::Pnt(edge_first_vertex); - } - if (!wire_last_vertex.IsNull() && !edge_first_vertex.IsNull()) { - d = p1.Distance(p2); - precision = ceil(-log10(d)) + 3; - } - - if (!wire_last_vertex.IsNull()) { - std::stringstream ss; - ss << std::setprecision(precision) << "Last vertex at (" << p1.X() << " " << p1.Y() << " " << p1.Z() << ")"; - Logger::Message(Logger::LOG_NOTICE, ss.str()); - } - - if (!edge_first_vertex.IsNull()) { - std::stringstream ss; - ss << std::setprecision(precision) << "Segment starts at (" << p2.X() << " " << p2.Y() << " " << p2.Z() << ")"; - if (d > 0.) { - ss << ", distance " << d << " > precision " << std::fixed << getValue(GV_PRECISION) / 10.; - } - ss << " for:"; - Logger::Message(Logger::LOG_NOTICE, ss.str(), (*it)->entity); - } - } - - return false; - } - - wire_last_vertex = edge_last_vertex; } + BRepBuilderAPI_MakeWire w; + TopoDS_Vertex wire_first_vertex, wire_last_vertex, edge_first_vertex, edge_last_vertex; + + const double precision_sq_2 = 2 * getValue(GV_PRECISION) * getValue(GV_PRECISION); + + TopTools_ListIteratorOfListOfShape it(converted_segments); + IfcEntityList::ptr profile = l->entity->getInverse(IfcSchema::Type::IfcProfileDef, -1); + const bool force_close = profile && profile->size() > 0; - if (profile && profile->size() > 0) { - gp_Pnt first = BRep_Tool::Pnt(edge_last_vertex); - gp_Pnt last = BRep_Tool::Pnt(wire_first_vertex); - - Standard_Real distance = first.SquareDistance(last); - if (distance > precision_sq_2) { - w.Add(BRepBuilderAPI_MakeEdge(edge_last_vertex, wire_first_vertex)); - - Logger::Message(Logger::LOG_ERROR, "Closed gap on:", l->entity); - } - } - - wire = w.Wire(); + wire_builder bld(getValue(GV_PRECISION), l); + shape_pair_enumerate(it, bld, force_close); + wire = bld.wire(); return true; } From 495ad75b14fce02824fe70394a55e99bca20ac6f Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Sun, 13 May 2018 15:30:20 +0200 Subject: [PATCH 37/60] Proper scope around goto labels --- src/ifcgeom/IfcGeomWires.cpp | 61 +++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/src/ifcgeom/IfcGeomWires.cpp b/src/ifcgeom/IfcGeomWires.cpp index 99d0332c0c..7082b236f5 100644 --- a/src/ifcgeom/IfcGeomWires.cpp +++ b/src/ifcgeom/IfcGeomWires.cpp @@ -155,8 +155,7 @@ namespace { gp_Pnt p1 = BRep_Tool::Pnt(w12); gp_Pnt p2 = BRep_Tool::Pnt(w21); - double dist = p1.Distance(p2); - TopTools_IndexedDataMapOfShapeListOfShape wmap1, wmap2; + double dist = p1.Distance(p2); // Distance is within 2p, this is fine if (dist < 2. * p_) { @@ -172,40 +171,44 @@ namespace { goto check; } - // Find edges connected to end- and begin vertex - TopExp::MapShapesAndAncestors(w1, TopAbs_VERTEX, TopAbs_EDGE, wmap1); - TopExp::MapShapesAndAncestors(w2, TopAbs_VERTEX, TopAbs_EDGE, wmap2); + { + TopTools_IndexedDataMapOfShapeListOfShape wmap1, wmap2; - const TopTools_ListOfShape& last_edges = wmap1.FindFromKey(w12); - const TopTools_ListOfShape& first_edges = wmap2.FindFromKey(w21); + // Find edges connected to end- and begin vertex + TopExp::MapShapesAndAncestors(w1, TopAbs_VERTEX, TopAbs_EDGE, wmap1); + TopExp::MapShapesAndAncestors(w2, TopAbs_VERTEX, TopAbs_EDGE, wmap2); - double _, __; - if (last_edges.Extent() == 1 && first_edges.Extent() == 1) { - Handle(Geom_Curve) c1 = BRep_Tool::Curve(TopoDS::Edge(last_edges.First()), _, __); - Handle(Geom_Curve) c2 = BRep_Tool::Curve(TopoDS::Edge(first_edges.First()), _, __); + const TopTools_ListOfShape& last_edges = wmap1.FindFromKey(w12); + const TopTools_ListOfShape& first_edges = wmap2.FindFromKey(w21); - const bool is_line1 = c1->DynamicType() == STANDARD_TYPE(Geom_Line); - const bool is_line2 = c2->DynamicType() == STANDARD_TYPE(Geom_Line); + double _, __; + if (last_edges.Extent() == 1 && first_edges.Extent() == 1) { + Handle(Geom_Curve) c1 = BRep_Tool::Curve(TopoDS::Edge(last_edges.First()), _, __); + Handle(Geom_Curve) c2 = BRep_Tool::Curve(TopoDS::Edge(first_edges.First()), _, __); - // Adjust the segment that is linear - if (is_line1) { - mw_.Add(adjust(w1, TopoDS::Edge(last_edges.First()), w12, p2)); - Logger::Message(Logger::LOG_ERROR, "Adjusted edge end-point with distance " + boost::lexical_cast(dist) + " on:", inst_->entity); - } else if (is_line2 && !last) { - // tfk: not ideal, begin point of first edge cannot be adjusted now for cyclic wires - mw_.Add(w1); - mw_.Add(adjust(w1, TopoDS::Edge(last_edges.First()), w12, p2)); - skip_next_ = true; - Logger::Message(Logger::LOG_ERROR, "Adjusted edge end-point with distance " + boost::lexical_cast(dist) + " on:", inst_->entity); + const bool is_line1 = c1->DynamicType() == STANDARD_TYPE(Geom_Line); + const bool is_line2 = c2->DynamicType() == STANDARD_TYPE(Geom_Line); + + // Adjust the segment that is linear + if (is_line1) { + mw_.Add(adjust(w1, TopoDS::Edge(last_edges.First()), w12, p2)); + Logger::Message(Logger::LOG_ERROR, "Adjusted edge end-point with distance " + boost::lexical_cast(dist) + " on:", inst_->entity); + } else if (is_line2 && !last) { + // tfk: not ideal, begin point of first edge cannot be adjusted now for cyclic wires + mw_.Add(w1); + mw_.Add(adjust(w1, TopoDS::Edge(last_edges.First()), w12, p2)); + skip_next_ = true; + Logger::Message(Logger::LOG_ERROR, "Adjusted edge end-point with distance " + boost::lexical_cast(dist) + " on:", inst_->entity); + } else { + // If both aren't linear an edge is added + mw_.Add(w1); + mw_.Add(BRepBuilderAPI_MakeEdge(p1, p2)); + Logger::Message(Logger::LOG_ERROR, "Added additional segment to close gap with length " + boost::lexical_cast(dist) + " to:", inst_->entity); + } } else { - // If both aren't linear an edge is added + Logger::Error("Internal error, inconsistent wire segments", inst_->entity); mw_.Add(w1); - mw_.Add(BRepBuilderAPI_MakeEdge(p1, p2)); - Logger::Message(Logger::LOG_ERROR, "Added additional segment to close gap with length " + boost::lexical_cast(dist) + " to:", inst_->entity); } - } else { - Logger::Error("Internal error, inconsistent wire segments", inst_->entity); - mw_.Add(w1); } check: From c1635d65eb3a1ed3446162b99138b99e91ef1e84 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Sun, 13 May 2018 16:04:15 +0200 Subject: [PATCH 38/60] Add include, missing depending on occt version --- src/ifcgeom/IfcGeomWires.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ifcgeom/IfcGeomWires.cpp b/src/ifcgeom/IfcGeomWires.cpp index 7082b236f5..ae28b0c3fb 100644 --- a/src/ifcgeom/IfcGeomWires.cpp +++ b/src/ifcgeom/IfcGeomWires.cpp @@ -86,7 +86,7 @@ #include #include #include - +#include #include "../ifcgeom/IfcGeom.h" From 2ed2e9cf86e2782fd0af0fed94c6564959a0173e Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Sun, 13 May 2018 18:52:53 +0200 Subject: [PATCH 39/60] Add include, missing depending on occt version --- src/ifcgeom/IfcGeomWires.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ifcgeom/IfcGeomWires.cpp b/src/ifcgeom/IfcGeomWires.cpp index ae28b0c3fb..d6f6b630ca 100644 --- a/src/ifcgeom/IfcGeomWires.cpp +++ b/src/ifcgeom/IfcGeomWires.cpp @@ -87,6 +87,7 @@ #include #include #include +#include #include "../ifcgeom/IfcGeom.h" From 637d3e2eb63fd2f34e148cd88215eeefaa68ff22 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Mon, 14 May 2018 11:06:07 +0200 Subject: [PATCH 40/60] Optimize generation of faces with large (n > 128) number of edges. --- src/ifcgeom/IfcGeomFaces.cpp | 10 +++++++++- src/ifcgeom/IfcGeomFunctions.cpp | 5 ++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/ifcgeom/IfcGeomFaces.cpp b/src/ifcgeom/IfcGeomFaces.cpp index 0b5b2e3b8c..b0ea4dd278 100644 --- a/src/ifcgeom/IfcGeomFaces.cpp +++ b/src/ifcgeom/IfcGeomFaces.cpp @@ -213,7 +213,15 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcFace* l, TopoDS_Shape& face) { process_wire: if (face_surface.IsNull()) { - mf = new BRepBuilderAPI_MakeFace(wire); + if (count(wire, TopAbs_EDGE) > 128) { + // tfk: optimization find the underlying surface ourselves since it's going + // to be planar in IFC if no explicit surface is given. Should we always do this? + gp_Pln pln; + approximate_plane_through_wire(wire, pln); + mf = new BRepBuilderAPI_MakeFace(pln, wire, true); + } else { + mf = new BRepBuilderAPI_MakeFace(wire); + } } else { /// @todo check necessity of false here mf = new BRepBuilderAPI_MakeFace(face_surface, wire, false); diff --git a/src/ifcgeom/IfcGeomFunctions.cpp b/src/ifcgeom/IfcGeomFunctions.cpp index c9dcc1577e..ffe67d8959 100644 --- a/src/ifcgeom/IfcGeomFunctions.cpp +++ b/src/ifcgeom/IfcGeomFunctions.cpp @@ -2838,7 +2838,10 @@ bool IfcGeom::Kernel::wire_intersections(const TopoDS_Wire& wire, TopTools_ListO } int n = count(wire, TopAbs_EDGE); - if (n < 3) { + if (n < 3 || n > 128) { + if (n > 128) { + Logger::Notice("Too many segments for detection of self-intersections"); + } wires.Append(wire); return false; } From 37460d3df9b7e6d14fff54cb39bf13ba9e77a51d Mon Sep 17 00:00:00 2001 From: Otso Alho Date: Thu, 12 Apr 2018 16:42:46 +0300 Subject: [PATCH 41/60] do not calculate reuse_ok multiple times for mapped representations --- src/ifcgeom/IfcGeomIterator.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/ifcgeom/IfcGeomIterator.h b/src/ifcgeom/IfcGeomIterator.h index 28650cbe12..ca80a77f7b 100644 --- a/src/ifcgeom/IfcGeomIterator.h +++ b/src/ifcgeom/IfcGeomIterator.h @@ -116,6 +116,9 @@ namespace IfcGeom { IfcSchema::IfcProduct::list::ptr ifcproducts; IfcSchema::IfcProduct::list::it ifcproduct_iterator; + + IfcSchema::IfcRepresentation::list::ptr ok_mapped_representations; + int done; int total; @@ -187,6 +190,7 @@ namespace IfcGeom { bool any_precision_encountered = false; 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; @@ -384,6 +388,7 @@ namespace IfcGeom { // 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; @@ -428,10 +433,12 @@ namespace IfcGeom { IfcSchema::IfcRepresentation* representation_mapped_to = kernel.representation_mapped_to(representation); if (representation_mapped_to) { // Check if this represenation has (or will be) processed as part its mapped representation - representation_processed_as_mapped_item = reuse_ok_(kernel.products_represented_by(representation_mapped_to)); + representation_processed_as_mapped_item = ok_mapped_representations->contains(representation_mapped_to) || + reuse_ok_(kernel.products_represented_by(representation_mapped_to)); } if (representation_processed_as_mapped_item) { + ok_mapped_representations->push(representation_mapped_to); _nextShape(); continue; } From 1014049b0570c53df15177f9af835d0b28c01558 Mon Sep 17 00:00:00 2001 From: Otso Alho Date: Fri, 13 Apr 2018 12:48:42 +0300 Subject: [PATCH 42/60] use unordered map for entity by id --- src/ifcparse/IfcFile.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ifcparse/IfcFile.h b/src/ifcparse/IfcFile.h index 8b2137514a..85db1dea0b 100644 --- a/src/ifcparse/IfcFile.h +++ b/src/ifcparse/IfcFile.h @@ -22,6 +22,7 @@ #include #include +#include #include "ifc_parse_api.h" @@ -35,7 +36,7 @@ namespace IfcParse { class IFC_PARSE_API IfcFile { public: typedef std::map entities_by_type_t; - typedef std::map entity_by_id_t; + typedef boost::unordered_map entity_by_id_t; typedef std::map entity_by_guid_t; typedef std::map > entities_by_ref_t; typedef entity_by_id_t::const_iterator const_iterator; From 2d59f9d53ae13d22dff2125bb1681c3bd953f5c0 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Mon, 14 May 2018 13:08:27 -0300 Subject: [PATCH 43/60] Removed one last remaining BOPCol_ListOfShapes Replaced one last remaining BOPCol_ListOfShapes with TopTools_ListOfShapes (deprecated in OCC7.3) --- src/ifcgeom/IfcGeomFunctions.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ifcgeom/IfcGeomFunctions.cpp b/src/ifcgeom/IfcGeomFunctions.cpp index ffe67d8959..761452a20c 100644 --- a/src/ifcgeom/IfcGeomFunctions.cpp +++ b/src/ifcgeom/IfcGeomFunctions.cpp @@ -2437,7 +2437,7 @@ bool IfcGeom::Kernel::split_solid_by_shell(const TopoDS_Shape& input, const Topo } apply_tolerance(solid, getValue(GV_PRECISION)); - BOPCol_ListOfShape shapes; + TopTools_ListOfShape shapes; shapes.Append(input); shapes.Append(solid); BOPAlgo_PaveFiller filler(new NCollection_IncAllocator); // TODO: Does this need to be freed? From 127bcaf96ece1217f8caba00e0c5c1608ca3214d Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Wed, 16 May 2018 10:11:00 -0300 Subject: [PATCH 44/60] adding exception for OCCT 7.3 --- src/ifcgeom/IfcGeomFunctions.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ifcgeom/IfcGeomFunctions.cpp b/src/ifcgeom/IfcGeomFunctions.cpp index 761452a20c..099e4ec61f 100644 --- a/src/ifcgeom/IfcGeomFunctions.cpp +++ b/src/ifcgeom/IfcGeomFunctions.cpp @@ -2437,7 +2437,11 @@ bool IfcGeom::Kernel::split_solid_by_shell(const TopoDS_Shape& input, const Topo } apply_tolerance(solid, getValue(GV_PRECISION)); +#if OCC_VERSION_HEX >= 0x70300 TopTools_ListOfShape shapes; +#else + BOPCol_ListOfShape shapes; +#endif shapes.Append(input); shapes.Append(solid); BOPAlgo_PaveFiller filler(new NCollection_IncAllocator); // TODO: Does this need to be freed? From 7e6b7584508a6aae48213c03adf9dfbbbf9c5892 Mon Sep 17 00:00:00 2001 From: civilx64 <26513472+civilx64@users.noreply.github.com> Date: Wed, 16 May 2018 23:05:07 -0400 Subject: [PATCH 45/60] Add instructions for install via conda. --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index a327b26b03..122b40c7af 100644 --- a/README.md +++ b/README.md @@ -137,6 +137,15 @@ If all worked out correctly you can now use IfcOpenShell. See the examples below $ sudo make install +Installing IfcOpenShell with Conda +---------------------------------- +Another option for building and installing IfcOpenShell is to use the popular +[Anaconda Python Distribution](https://www.anaconda.com/download). +The requirements are spread across a number of channels. +You can add these channels to your configuration, or specify them all on the command line: + + $ conda install -c conda-forge -c oce -c dlr-sc -c ifcopenshell ifcopenshell + Usage examples -------------- From 33635c2c4041aacf24e6886b3f78c1858c3edf75 Mon Sep 17 00:00:00 2001 From: civilx64 <26513472+civilx64@users.noreply.github.com> Date: Thu, 17 May 2018 00:11:09 -0400 Subject: [PATCH 46/60] Port viewer app to PyQt5 --- .../ifcopenshell/geom/app.py | 85 ++++++++++--------- 1 file changed, 45 insertions(+), 40 deletions(-) diff --git a/src/ifcopenshell-python/ifcopenshell/geom/app.py b/src/ifcopenshell-python/ifcopenshell/geom/app.py index 8f0e6738fd..7a8d2c8771 100644 --- a/src/ifcopenshell-python/ifcopenshell/geom/app.py +++ b/src/ifcopenshell-python/ifcopenshell/geom/app.py @@ -12,18 +12,24 @@ import OCC.AIS from collections import defaultdict, Iterable, OrderedDict -os.environ['QT_API'] = 'pyqt4' +try: + QString = unicode +except NameError: + # Python 3 + QString = str + +os.environ['QT_API'] = 'pyqt5' try: from pyqode.qt import QtCore except BaseException: pass -from PyQt4 import QtGui, QtCore +from PyQt5 import QtCore, QtGui, QtWidgets from .code_editor_pane import code_edit try: - from OCC.Display.pyqt4Display import qtViewer3d + from OCC.Display.pyqt5Display import qtViewer3d except BaseException: import OCC.Display @@ -33,9 +39,9 @@ except BaseException: pass try: - OCC.Display.backend.get_backend("qt-pyqt4") + OCC.Display.backend.get_backend("qt-pyqt5") except BaseException: - OCC.Display.backend.load_backend("qt-pyqt4") + OCC.Display.backend.load_backend("qt-pyqt5") from OCC.Display.qtDisplay import qtViewer3d @@ -47,7 +53,6 @@ from .. import get_supertype # Depending on Python version and what not there may or may not be a QString try: - from PyQt4.QtCore import QString except ImportError: QString = str @@ -113,11 +118,11 @@ if selection: return OrderedDict([(k, self.config_decode(self.config.get(s, k))) for k in self.config.options(s)]) -class application(QtGui.QApplication): +class application(QtWidgets.QApplication): """A pythonOCC, PyQt based IfcOpenShell application with two tree views and a graphical 3d view""" - class abstract_treeview(QtGui.QTreeWidget): + class abstract_treeview(QtWidgets.QTreeWidget): """Base class for the two treeview controls""" @@ -126,7 +131,7 @@ class application(QtGui.QApplication): instanceDisplayModeChanged = QtCore.pyqtSignal([object, int]) def __init__(self): - QtGui.QTreeView.__init__(self) + QtWidgets.QTreeView.__init__(self) self.setColumnCount(len(self.ATTRIBUTES)) self.setHeaderLabels(self.ATTRIBUTES) self.children = defaultdict(list) @@ -140,14 +145,14 @@ class application(QtGui.QApplication): return c def contextMenuEvent(self, event): - menu = QtGui.QMenu(self) + menu = QtWidgets.QMenu(self) visibility = [menu.addAction("Show"), menu.addAction("Hide")] displaymode = [menu.addAction("Solid"), menu.addAction("Wireframe")] action = menu.exec_(self.mapToGlobal(event.pos())) index = self.selectionModel().currentIndex() inst = index.data(QtCore.Qt.UserRole) if hasattr(inst, 'toPyObject'): - inst = inst.toPyObject() + inst = inst if action in visibility: self.instanceVisibilityChanged.emit(inst, visibility.index(action)) elif action in displaymode: @@ -156,7 +161,7 @@ class application(QtGui.QApplication): def clicked(self, index): inst = index.data(QtCore.Qt.UserRole) if hasattr(inst, 'toPyObject'): - inst = inst.toPyObject() + inst = inst if inst: self.instanceSelected.emit(inst) @@ -165,7 +170,7 @@ class application(QtGui.QApplication): if itm is None: return self.selectionModel().setCurrentIndex(itm, - QtGui.QItemSelectionModel.SelectCurrent | QtGui.QItemSelectionModel.Rows) + QtCore.QItemSelectionModel.SelectCurrent | QtCore.QItemSelectionModel.Rows) class decomposition_treeview(abstract_treeview): @@ -206,11 +211,11 @@ class application(QtGui.QApplication): sl.append(product.is_a()) else: sl.append(getattr(product, attr) or '') - itm = items[product] = QtGui.QTreeWidgetItem(items.get(parent, self), sl) + itm = items[product] = QtWidgets.QTreeWidgetItem(items.get(parent, self), sl) itm.setData(0, QtCore.Qt.UserRole, product) self.children[parent].append(product) self.product_to_item = dict(zip(items.keys(), map(self.indexFromItem, items.values()))) - self.connect(self, QtCore.SIGNAL("clicked(const QModelIndex &)"), self.clicked) + self.clicked[QModelIndex].connect(self.clicked) self.expandAll() class type_treeview(abstract_treeview): @@ -230,7 +235,7 @@ class application(QtGui.QApplication): add(s) s2, t2 = map(QString, (s, t)) if t2 not in items: - itm = items[t2] = QtGui.QTreeWidgetItem(items.get(s2, self), [t2]) + itm = items[t2] = QtWidgets.QTreeWidgetItem(items.get(s2, self), [t2]) itm.setData(0, QtCore.Qt.UserRole, t2) self.children[s2].append(t2) @@ -238,25 +243,25 @@ class application(QtGui.QApplication): for p in products: t = QString(p.is_a()) - itm = items[p] = QtGui.QTreeWidgetItem(items.get(t, self), [p.Name or '']) + itm = items[p] = QtWidgets.QTreeWidgetItem(items.get(t, self), [p.Name or '']) itm.setData(0, QtCore.Qt.UserRole, t) self.children[t].append(p) self.product_to_item = dict(zip(items.keys(), map(self.indexFromItem, items.values()))) - self.connect(self, QtCore.SIGNAL("clicked(const QModelIndex &)"), self.clicked) + self.clicked[QModelIndex].connect(self.clicked) self.expandAll() - class property_table(QtGui.QWidget): + class property_table(QtWidgets.QWidget): def __init__(self): - QtGui.QWidget.__init__(self) - self.layout = QtGui.QVBoxLayout(self) + QtWidgets.QWidget.__init__(self) + self.layout = QtWidgets.QVBoxLayout(self) self.setLayout(self.layout) - self.scroll = QtGui.QScrollArea(self) + self.scroll = QtWidgets.QScrollArea(self) self.layout.addWidget(self.scroll) self.scroll.setWidgetResizable(True) - self.scrollContent = QtGui.QWidget(self.scroll) - self.scrollLayout = QtGui.QVBoxLayout(self.scrollContent) + self.scrollContent = QtWidgets.QWidget(self.scroll) + self.scrollLayout = QtWidgets.QVBoxLayout(self.scrollContent) self.scrollContent.setLayout(self.scrollLayout) self.scroll.setWidget(self.scrollContent) self.prop_dict = {} @@ -271,17 +276,17 @@ class application(QtGui.QApplication): if child.widget() is not None: child.widget().deleteLater() - self.scroll = QtGui.QScrollArea() + self.scroll = QtWidgets.QScrollArea() self.scroll.setWidgetResizable(True) prop_sets = self.prop_dict.get(str(product)) if prop_sets is not None: for k, v in prop_sets: - group_box = QtGui.QGroupBox() + group_box = QtWidgets.QGroupBox() group_box.setTitle(k) - group_layout = QtGui.QVBoxLayout() + group_layout = QtWidgets.QVBoxLayout() group_box.setLayout(group_layout) for name, value in v.items(): @@ -300,7 +305,7 @@ class application(QtGui.QApplication): type_str = " (%s)" % value.is_a() else: type_str = "" - label = QtGui.QLabel("%s: %s%s" % (prop_name, value_str, type_str)) + label = QtWidgets.QLabel("%s: %s%s" % (prop_name, value_str, type_str)) group_layout.addWidget(label) group_layout.addStretch() @@ -308,7 +313,7 @@ class application(QtGui.QApplication): self.scrollLayout.addStretch() else: - label = QtGui.QLabel("No IfcPropertySets asscociated with selected entity instance") + label = QtWidgets.QLabel("No IfcPropertySets asscociated with selected entity instance") self.scrollLayout.addWidget(label) def load_file(self, f, **kwargs): @@ -431,7 +436,7 @@ class application(QtGui.QApplication): self.ais_to_product[self.counter] = product self.product_to_ais[product] = ais self.counter += 1 - QtGui.QApplication.processEvents() + QtWidgets.QApplication.processEvents() if product.is_a() in {'IfcSpace', 'IfcOpeningElement'}: v.Context.Erase(ais, True) progress = it.progress() // 2 @@ -493,14 +498,14 @@ class application(QtGui.QApplication): inst = self.ais_to_product[ais.GetObject().SelectionPriority()] self.instanceSelected.emit(inst) - class window(QtGui.QMainWindow): + class window(QtWidgets.QMainWindow): TITLE = "IfcOpenShell IFC viewer" window_closed = QtCore.pyqtSignal([]) def __init__(self): - QtGui.QMainWindow.__init__(self) + QtWidgets.QMainWindow.__init__(self) self.setWindowTitle(self.TITLE) self.menu = self.menuBar() self.menus = {} @@ -515,9 +520,9 @@ class application(QtGui.QApplication): self.menus[menu] = m if icon: - a = QtGui.QAction(QtGui.QIcon(icon), label, self) + a = QtWidgets.QAction(QtGui.QIcon(icon), label, self) else: - a = QtGui.QAction(label, self) + a = QtWidgets.QAction(label, self) if shortcut: a.setShortcut(shortcut) @@ -534,20 +539,20 @@ class application(QtGui.QApplication): return handler def __init__(self, settings=None): - QtGui.QApplication.__init__(self, sys.argv) + QtWidgets.QApplication.__init__(self, sys.argv) self.window = application.window() self.tree = application.decomposition_treeview() self.tree2 = application.type_treeview() self.propview = self.property_table() self.canvas = application.viewer(self.window) - self.tabs = QtGui.QTabWidget() + self.tabs = QtWidgets.QTabWidget() self.window.resize(800, 600) - splitter = QtGui.QSplitter(QtCore.Qt.Horizontal) + splitter = QtWidgets.QSplitter(QtCore.Qt.Horizontal) splitter.addWidget(self.tabs) self.tabs.addTab(self.tree, 'Decomposition') self.tabs.addTab(self.tree2, 'Types') self.tabs.addTab(self.propview, "Properties") - splitter2 = QtGui.QSplitter(QtCore.Qt.Vertical) + splitter2 = QtWidgets.QSplitter(QtCore.Qt.Vertical) splitter2.addWidget(self.canvas) self.editor = code_edit(self.canvas, configuration().options('snippets')) splitter2.addWidget(self.editor) @@ -585,8 +590,8 @@ class application(QtGui.QApplication): sys.exit(self.exec_()) def browse(self): - filename = QtGui.QFileDialog.getOpenFileName(self.window, 'Open file', ".", - "Industry Foundation Classes (*.ifc)") + filename = QtWidgets.QFileDialog.getOpenFileName(self.window, 'Open file', ".", + "Industry Foundation Classes (*.ifc)")[0] self.load(filename) def clear(self): From 6b772d18b85221f45559473b508df2e0ac760e54 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Thu, 17 May 2018 15:53:40 +0200 Subject: [PATCH 47/60] Fixes to qt5 port of viewer app --- .../ifcopenshell/geom/app.py | 19 ++++++++-------- .../ifcopenshell/geom/code_editor_pane.py | 22 ++++++++----------- 2 files changed, 18 insertions(+), 23 deletions(-) diff --git a/src/ifcopenshell-python/ifcopenshell/geom/app.py b/src/ifcopenshell-python/ifcopenshell/geom/app.py index 7a8d2c8771..9fcd3191a0 100644 --- a/src/ifcopenshell-python/ifcopenshell/geom/app.py +++ b/src/ifcopenshell-python/ifcopenshell/geom/app.py @@ -49,13 +49,11 @@ from .main import settings, iterator from .occ_utils import display_shape from .. import open as open_ifc_file -from .. import get_supertype - -# Depending on Python version and what not there may or may not be a QString -try: -except ImportError: - QString = str +from .. import version as ifcopenshell_version +if ifcopenshell_version < "0.6": + # not yet ported + from .. import get_supertype class configuration(object): def __init__(self): @@ -158,7 +156,7 @@ class application(QtWidgets.QApplication): elif action in displaymode: self.instanceDisplayModeChanged.emit(inst, displaymode.index(action)) - def clicked(self, index): + def clicked_(self, index): inst = index.data(QtCore.Qt.UserRole) if hasattr(inst, 'toPyObject'): inst = inst @@ -215,7 +213,7 @@ class application(QtWidgets.QApplication): itm.setData(0, QtCore.Qt.UserRole, product) self.children[parent].append(product) self.product_to_item = dict(zip(items.keys(), map(self.indexFromItem, items.values()))) - self.clicked[QModelIndex].connect(self.clicked) + self.clicked.connect(self.clicked_) self.expandAll() class type_treeview(abstract_treeview): @@ -239,7 +237,8 @@ class application(QtWidgets.QApplication): itm.setData(0, QtCore.Qt.UserRole, t2) self.children[s2].append(t2) - add(t) + if ifcopenshell_version < "0.6": + add(t) for p in products: t = QString(p.is_a()) @@ -248,7 +247,7 @@ class application(QtWidgets.QApplication): self.children[t].append(p) self.product_to_item = dict(zip(items.keys(), map(self.indexFromItem, items.values()))) - self.clicked[QModelIndex].connect(self.clicked) + self.clicked.connect(self.clicked) self.expandAll() class property_table(QtWidgets.QWidget): diff --git a/src/ifcopenshell-python/ifcopenshell/geom/code_editor_pane.py b/src/ifcopenshell-python/ifcopenshell/geom/code_editor_pane.py index e4306cd1a7..760f36b76f 100644 --- a/src/ifcopenshell-python/ifcopenshell/geom/code_editor_pane.py +++ b/src/ifcopenshell-python/ifcopenshell/geom/code_editor_pane.py @@ -7,10 +7,10 @@ import sys import logging from code import InteractiveConsole -from PyQt4 import QtCore, QtGui +from PyQt5 import QtCore, QtGui, QtWidgets try: - from PyQt4 import QtWidgets + from PyQt5 import QtWidgets except BaseException: QtWidgets = QtGui @@ -48,7 +48,7 @@ class StdoutRedirector(object): self.widget.moveCursor(QtGui.QTextCursor.End) -class code_edit(QtGui.QWidget): +class code_edit(QtWidgets.QWidget): class Console(InteractiveConsole): def __init__(*args): InteractiveConsole.__init__(*args) @@ -73,18 +73,15 @@ class code_edit(QtGui.QWidget): self.c = self.Console({'model': self.model, 'viewer': self.viewer, 'selection': product}) def __init__(self, viewer, snippets=None): - self.model = None self.viewer = viewer - QtGui.QWidget.__init__(self) - self.layout = QtGui.QVBoxLayout(self) + QtWidgets.QWidget.__init__(self) + self.layout = QtWidgets.QVBoxLayout(self) self.setLayout(self.layout) self.c = None - - self.tools = QtGui.QHBoxLayout(self) + self.tools = QtWidgets.QHBoxLayout(self) self.layout.addLayout(self.tools) - - self.runbutton = QtGui.QPushButton("Run") + self.runbutton = QtWidgets.QPushButton("Run") width = self.runbutton.fontMetrics().boundingRect("Run").width() + 20 self.runbutton.setMaximumWidth(width) self.tools.addWidget(self.runbutton) @@ -129,11 +126,10 @@ class code_edit(QtGui.QWidget): for snip_name in self.snippets.keys(): self.list.addItem(snip_name) self.tools.addWidget(self.list) - QtCore.QObject.connect(self.list, QtCore.SIGNAL("currentIndexChanged(int)"), self.replace_snippet) + self.list.currentIndexChanged[int].connect(self.replace_snippet) self.layout.addWidget(self.editor) - - self.output = QtGui.QTextEdit() + self.output = QtWidgets.QTextEdit() self.output.setReadOnly(True) self.output.setStyleSheet('font-size: 10pt; font-family: Consolas, Courier; background-color: #444;') self.layout.addWidget(self.output) From fd821d08cddeed253ea50672fce588d4942855aa Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Thu, 17 May 2018 15:54:12 +0200 Subject: [PATCH 48/60] Dont fail on missing AIS_MultipleConnectedShape in earlier versions of pyocc --- src/ifcopenshell-python/ifcopenshell/geom/occ_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ifcopenshell-python/ifcopenshell/geom/occ_utils.py b/src/ifcopenshell-python/ifcopenshell/geom/occ_utils.py index ec4d83b7ac..bba90da5bc 100644 --- a/src/ifcopenshell-python/ifcopenshell/geom/occ_utils.py +++ b/src/ifcopenshell-python/ifcopenshell/geom/occ_utils.py @@ -133,7 +133,7 @@ def display_shape(shape, clr=None, viewer_handle=None): if isinstance(clr, tuple) and len(clr) == 4 and clr[3] < 1.: ais.SetTransparency(1. - clr[3]) - elif representation: + elif representation and hasattr(OCC.AIS, "AIS_MultipleConnectedShape"): default_style_applied = None ais = OCC.AIS.AIS_MultipleConnectedShape(shape) From 20cd383504a69e3024ff26fddf99ea8f928c4d7e Mon Sep 17 00:00:00 2001 From: thorade Date: Mon, 27 Nov 2017 15:10:56 +0100 Subject: [PATCH 49/60] triple double-quoted docstring and do not use builtin names for variables --- .../ifcopenshell/geom/code_editor_pane.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ifcopenshell-python/ifcopenshell/geom/code_editor_pane.py b/src/ifcopenshell-python/ifcopenshell/geom/code_editor_pane.py index 760f36b76f..b64787f32b 100644 --- a/src/ifcopenshell-python/ifcopenshell/geom/code_editor_pane.py +++ b/src/ifcopenshell-python/ifcopenshell/geom/code_editor_pane.py @@ -32,19 +32,19 @@ except BaseException: class StdoutRedirector(object): - '''A class for redirecting stdout to this Text widget.''' + """A class for redirecting stdout to this Text widget.""" def __init__(self, widget): self.widget = widget self.isError = False - def write(self, str): + def write(self, myStr): self.widget.moveCursor(QtGui.QTextCursor.End) if self.isError: self.widget.setTextColor(QtCore.Qt.red) else: self.widget.setTextColor(QtCore.Qt.white) - self.widget.insertPlainText(str) + self.widget.insertPlainText(myStr) self.widget.moveCursor(QtGui.QTextCursor.End) From 6c1ad47481de5d2ffae1c9c24e49366f380db5ca Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Fri, 1 Jun 2018 15:38:08 +0200 Subject: [PATCH 50/60] Additional improvements for comp curve wire building --- src/ifcgeom/IfcGeomWires.cpp | 70 ++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 34 deletions(-) diff --git a/src/ifcgeom/IfcGeomWires.cpp b/src/ifcgeom/IfcGeomWires.cpp index d6f6b630ca..3c04914b76 100644 --- a/src/ifcgeom/IfcGeomWires.cpp +++ b/src/ifcgeom/IfcGeomWires.cpp @@ -99,21 +99,22 @@ namespace { return v.IsSame(b) ? a : b; } + TopoDS_Edge first_edge(const TopoDS_Wire& w) { + TopoDS_Vertex v1, v2; + TopExp::Vertices(w, v1, v2); + TopTools_IndexedDataMapOfShapeListOfShape wm; + TopExp::MapShapesAndAncestors(w, TopAbs_VERTEX, TopAbs_EDGE, wm); + return TopoDS::Edge(wm.FindFromKey(v1).First()); + } + // Returns new wire with the edge replaced by a linear edge with the vertex v moved to p - TopoDS_Wire adjust(const TopoDS_Wire& w, const TopoDS_Edge& e, const TopoDS_Vertex& v, const gp_Pnt& p) { - gp_Pnt p1 = p; - gp_Pnt p2 = BRep_Tool::Pnt(other(e, v)); - - if (e.Orientation() == TopAbs_REVERSED) { - std::swap(p1, p2); - } - - // Already asserted this is a replacement for a linear edge - TopoDS_Edge new_edge = BRepBuilderAPI_MakeEdge(p1, p2).Edge(); - new_edge.Orientation(e.Orientation()); + TopoDS_Wire adjust(const TopoDS_Wire& w, const TopoDS_Vertex& v, const gp_Pnt& p) { + BRep_Builder b; + TopoDS_Vertex v2; + b.MakeVertex(v2, p, BRep_Tool::Tolerance(v)); ShapeBuild_ReShape reshape; - reshape.Replace(e, new_edge); + reshape.Replace(v.Oriented(TopAbs_FORWARD), v2); return TopoDS::Wire(reshape.Apply(w)); } @@ -123,32 +124,34 @@ namespace { private: BRepBuilderAPI_MakeWire mw_; double p_; - bool skip_next_; + bool override_next_; + gp_Pnt next_override_; const IfcUtil::IfcBaseClass* inst_; public: - wire_builder(double p, const IfcUtil::IfcBaseClass* inst = 0) : p_(p), skip_next_(false), inst_(inst) {} + wire_builder(double p, const IfcUtil::IfcBaseClass* inst = 0) : p_(p), override_next_(false), inst_(inst) {} void operator()(const TopoDS_Shape& a) { - if (skip_next_) { - // tfk: not ideal, adjusting both start and end points not supported now. - skip_next_ = false; - return; - } - - mw_.Add(TopoDS::Wire(a)); + const TopoDS_Wire& w = TopoDS::Wire(a); + if (override_next_) { + override_next_ = false; + TopoDS_Edge e = first_edge(w); + mw_.Add(adjust(w, TopExp::FirstVertex(e, true), next_override_)); + } else { + mw_.Add(w); + } } void operator()(const TopoDS_Shape& a, const TopoDS_Shape& b, bool last) { - if (skip_next_) { - // tfk: not ideal, adjusting both start and end points not supported now. - skip_next_ = false; - return; - } - - const TopoDS_Wire& w1 = TopoDS::Wire(a); + TopoDS_Wire w1 = TopoDS::Wire(a); const TopoDS_Wire& w2 = TopoDS::Wire(b); + if (override_next_) { + override_next_ = false; + TopoDS_Edge e = first_edge(w1); + w1 = adjust(w1, TopExp::FirstVertex(e, true), next_override_); + } + TopoDS_Vertex w11, w12, w21, w22; TopExp::Vertices(w1, w11, w12); TopExp::Vertices(w2, w21, w22); @@ -156,10 +159,10 @@ namespace { gp_Pnt p1 = BRep_Tool::Pnt(w12); gp_Pnt p2 = BRep_Tool::Pnt(w21); - double dist = p1.Distance(p2); + double dist = p1.Distance(p2); // Distance is within 2p, this is fine - if (dist < 2. * p_) { + if (dist < p_) { mw_.Add(w1); goto check; } @@ -192,13 +195,12 @@ namespace { // Adjust the segment that is linear if (is_line1) { - mw_.Add(adjust(w1, TopoDS::Edge(last_edges.First()), w12, p2)); + mw_.Add(adjust(w1, w12, p2)); Logger::Message(Logger::LOG_ERROR, "Adjusted edge end-point with distance " + boost::lexical_cast(dist) + " on:", inst_->entity); } else if (is_line2 && !last) { - // tfk: not ideal, begin point of first edge cannot be adjusted now for cyclic wires mw_.Add(w1); - mw_.Add(adjust(w1, TopoDS::Edge(last_edges.First()), w12, p2)); - skip_next_ = true; + override_next_ = true; + next_override_ = p1; Logger::Message(Logger::LOG_ERROR, "Adjusted edge end-point with distance " + boost::lexical_cast(dist) + " on:", inst_->entity); } else { // If both aren't linear an edge is added From 3ac83791872f7cf36f7951166dad92622aa0a2db Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Fri, 8 Jun 2018 14:12:01 +0200 Subject: [PATCH 51/60] Set precision on fix after boolean op --- src/ifcgeom/IfcGeomFunctions.cpp | 52 +++++++++++++++++++------------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/src/ifcgeom/IfcGeomFunctions.cpp b/src/ifcgeom/IfcGeomFunctions.cpp index 099e4ec61f..8b3ffe7ce4 100644 --- a/src/ifcgeom/IfcGeomFunctions.cpp +++ b/src/ifcgeom/IfcGeomFunctions.cpp @@ -3065,17 +3065,33 @@ bool IfcGeom::Kernel::boolean_operation(const TopoDS_Shape& a, const TopoDS_Shap } #else -TopTools_ListOfShape copy_operand(const TopTools_ListOfShape& l) { - TopTools_ListOfShape r; - TopTools_ListIteratorOfListOfShape it(l); - for (; it.More(); it.Next()) { - r.Append(BRepBuilderAPI_Copy(it.Value())); +namespace { + TopTools_ListOfShape copy_operand(const TopTools_ListOfShape& l) { + TopTools_ListOfShape r; + TopTools_ListIteratorOfListOfShape it(l); + for (; it.More(); it.Next()) { + r.Append(BRepBuilderAPI_Copy(it.Value())); + } + return r; } - return r; -} -TopoDS_Shape copy_operand(const TopoDS_Shape& s) { - return BRepBuilderAPI_Copy(s); + TopoDS_Shape copy_operand(const TopoDS_Shape& s) { + return BRepBuilderAPI_Copy(s); + } + + double min_edge_length(const TopoDS_Shape& a) { + double min_edge_len = std::numeric_limits::infinity(); + TopExp_Explorer exp(a, TopAbs_EDGE); + for (; exp.More(); exp.Next()) { + GProp_GProps prop; + BRepGProp::LinearProperties(exp.Current(), prop); + double l = prop.Mass(); + if (l < min_edge_len) { + min_edge_len = l; + } + } + return min_edge_len; + } } bool IfcGeom::Kernel::boolean_operation(const TopoDS_Shape& a, const TopTools_ListOfShape& b, BOPAlgo_Operation op, TopoDS_Shape& result, double fuzziness) { @@ -3094,21 +3110,12 @@ bool IfcGeom::Kernel::boolean_operation(const TopoDS_Shape& a, const TopTools_Li fuzziness = getValue(GV_PRECISION); } - double min_edge_len = std::numeric_limits::infinity(); - // ... to be sure to get consecutive edges - TopExp_Explorer exp(a, TopAbs_EDGE); - for (; exp.More(); exp.Next()) { - GProp_GProps prop; - BRepGProp::LinearProperties(exp.Current(), prop); - double l = prop.Mass(); - if (l < min_edge_len) { - min_edge_len = l; - } - } + const double min_edge_len = min_edge_length(a); + const double fuzz = (std::min)(min_edge_len / 3., fuzziness); TopTools_ListOfShape s1s; s1s.Append(copy_operand(a)); - builder->SetFuzzyValue((std::min)(min_edge_len / 3., fuzziness)); + builder->SetFuzzyValue(fuzz); builder->SetArguments(s1s); builder->SetTools(copy_operand(b)); builder->Build(); @@ -3117,6 +3124,9 @@ bool IfcGeom::Kernel::boolean_operation(const TopoDS_Shape& a, const TopTools_Li ShapeFix_Shape fix(r); try { + fix.SetMinTolerance(fuzz); + fix.SetMaxTolerance(fuzz); + fix.SetPrecision(fuzz); fix.Perform(); r = fix.Shape(); } catch (...) { From 136ec5b2247991661c875f5bcd6ef21b657a1f8a Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Tue, 12 Jun 2018 16:15:12 +0200 Subject: [PATCH 52/60] 'nondestructive' boolean ops --- src/ifcgeom/IfcGeomFunctions.cpp | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/src/ifcgeom/IfcGeomFunctions.cpp b/src/ifcgeom/IfcGeomFunctions.cpp index 8b3ffe7ce4..d5f8f98d02 100644 --- a/src/ifcgeom/IfcGeomFunctions.cpp +++ b/src/ifcgeom/IfcGeomFunctions.cpp @@ -3066,19 +3066,6 @@ bool IfcGeom::Kernel::boolean_operation(const TopoDS_Shape& a, const TopoDS_Shap #else namespace { - TopTools_ListOfShape copy_operand(const TopTools_ListOfShape& l) { - TopTools_ListOfShape r; - TopTools_ListIteratorOfListOfShape it(l); - for (; it.More(); it.Next()) { - r.Append(BRepBuilderAPI_Copy(it.Value())); - } - return r; - } - - TopoDS_Shape copy_operand(const TopoDS_Shape& s) { - return BRepBuilderAPI_Copy(s); - } - double min_edge_length(const TopoDS_Shape& a) { double min_edge_len = std::numeric_limits::infinity(); TopExp_Explorer exp(a, TopAbs_EDGE); @@ -3114,10 +3101,11 @@ bool IfcGeom::Kernel::boolean_operation(const TopoDS_Shape& a, const TopTools_Li const double fuzz = (std::min)(min_edge_len / 3., fuzziness); TopTools_ListOfShape s1s; - s1s.Append(copy_operand(a)); + s1s.Append(a); + builder->SetNonDestructive(true); builder->SetFuzzyValue(fuzz); builder->SetArguments(s1s); - builder->SetTools(copy_operand(b)); + builder->SetTools(b); builder->Build(); if (builder->IsDone()) { TopoDS_Shape r = *builder; From 6d25047c6ba74062c133394175d8bb9345e16e6d Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Tue, 12 Jun 2018 16:15:28 +0200 Subject: [PATCH 53/60] higher fuzz on half spaces --- src/ifcgeom/IfcGeomShapes.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/ifcgeom/IfcGeomShapes.cpp b/src/ifcgeom/IfcGeomShapes.cpp index b3c09014f2..579d886a1b 100644 --- a/src/ifcgeom/IfcGeomShapes.cpp +++ b/src/ifcgeom/IfcGeomShapes.cpp @@ -549,7 +549,12 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcBooleanResult* l, TopoDS_Shape return false; } +#if OCC_VERSION_HEX < 0x60900 bool valid_result = boolean_operation(s1, s2, occ_op, shape); +#else + const double fuzz = is_halfspace ? getValue(GV_PRECISION) * 10. : -1.; + bool valid_result = boolean_operation(s1, s2, occ_op, shape, fuzz); +#endif if (op == IfcSchema::IfcBooleanOperator::IfcBooleanOperator_DIFFERENCE) { // In case of a subtraction, a check on volume is performed. From 4cfb2f102797cf563107c1939e48e6fcd4d7e9d0 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Fri, 15 Jun 2018 12:39:29 +0200 Subject: [PATCH 54/60] SetNonDestructive does not exist prior to OCCT 7.0 --- src/ifcgeom/IfcGeomFunctions.cpp | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/src/ifcgeom/IfcGeomFunctions.cpp b/src/ifcgeom/IfcGeomFunctions.cpp index d5f8f98d02..64ab7e59fa 100644 --- a/src/ifcgeom/IfcGeomFunctions.cpp +++ b/src/ifcgeom/IfcGeomFunctions.cpp @@ -3066,6 +3066,30 @@ bool IfcGeom::Kernel::boolean_operation(const TopoDS_Shape& a, const TopoDS_Shap #else namespace { + TopTools_ListOfShape copy_operand(const TopTools_ListOfShape& l) { +#if OCC_VERSION_HEX < 0x70000 + TopTools_ListOfShape r; + TopTools_ListIteratorOfListOfShape it(l); + for (; it.More(); it.Next()) { + r.Append(BRepBuilderAPI_Copy(it.Value())); + } + return r; +#else + // On OCCT 7.0 and higher BRepAlgoAPI_BuilderAlgo::SetNonDestructive(true) is + // called. Not entirely sure on the behaviour before 7.0, so overcautiously + // create copies. + return l; +#endif + } + + TopoDS_Shape copy_operand(const TopoDS_Shape& s) { +#if OCC_VERSION_HEX < 0x70000 + return BRepBuilderAPI_Copy(s); +#else + return s; +#endif + } + double min_edge_length(const TopoDS_Shape& a) { double min_edge_len = std::numeric_limits::infinity(); TopExp_Explorer exp(a, TopAbs_EDGE); @@ -3101,11 +3125,13 @@ bool IfcGeom::Kernel::boolean_operation(const TopoDS_Shape& a, const TopTools_Li const double fuzz = (std::min)(min_edge_len / 3., fuzziness); TopTools_ListOfShape s1s; - s1s.Append(a); + s1s.Append(copy_operand(a)); +#if OCC_VERSION_HEX >= 0x70000 builder->SetNonDestructive(true); +#endif builder->SetFuzzyValue(fuzz); builder->SetArguments(s1s); - builder->SetTools(b); + builder->SetTools(copy_operand(b)); builder->Build(); if (builder->IsDone()) { TopoDS_Shape r = *builder; From 11d0c6ef5690c40e9481cc38e4567253b689b18c Mon Sep 17 00:00:00 2001 From: Victor Haefner Date: Fri, 8 Jun 2018 15:25:33 +0300 Subject: [PATCH 55/60] compiles under ubuntu 18.04 --- cmake/CMakeLists.txt | 3 ++- src/ifcparse/IfcCharacterDecoder.cpp | 6 +++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index b157cd56eb..ad286ec85e 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -549,8 +549,9 @@ if(NOT MSVC) message(FATAL_ERROR "OCCT7 requires a compiler with C++11 support") endif() else() - add_definitions(-std=c++03) + add_definitions(-std=c++0x) endif() + endif() set(IFCOPENSHELL_LIBRARIES IfcParse IfcGeom) diff --git a/src/ifcparse/IfcCharacterDecoder.cpp b/src/ifcparse/IfcCharacterDecoder.cpp index cbf8e2f6f8..41638366a8 100644 --- a/src/ifcparse/IfcCharacterDecoder.cpp +++ b/src/ifcparse/IfcCharacterDecoder.cpp @@ -70,6 +70,10 @@ using namespace IfcParse; using namespace IfcWrite; +#ifdef HAVE_ICU +#include +#endif + void IfcCharacterDecoder::addChar(std::stringstream& s,const UChar32& ch) { #ifdef HAVE_ICU if ( destination ) { @@ -386,4 +390,4 @@ IfcCharacterEncoder::operator std::string() { #ifdef HAVE_ICU UErrorCode IfcCharacterEncoder::status = U_ZERO_ERROR; UConverter* IfcCharacterEncoder::converter = 0; -#endif \ No newline at end of file +#endif From 8c0bcc4ce75e933b11a8fdd460c339a42ade0a3b Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Sat, 30 Jun 2018 10:21:11 +0200 Subject: [PATCH 56/60] Silent extraction in build-deps.cmd --- win/build-deps.cmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/win/build-deps.cmd b/win/build-deps.cmd index cd85e0b4af..a37eabcca5 100644 --- a/win/build-deps.cmd +++ b/win/build-deps.cmd @@ -502,7 +502,7 @@ exit /b %RET% :ExtractArchive if not exist "%~3". ( call cecho.cmd 0 13 "Extracting %DEPENDENCY_NAME% into %~2." - 7za x %1 -y -o%2 + 7za x %1 -y -o%2 > nul ) else ( call cecho.cmd 0 13 "%DEPENDENCY_NAME% already extracted into %~3. Skipping." ) From 1b809ed849b234403180473bd74d505a29f3a008 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Sat, 30 Jun 2018 15:36:51 +0200 Subject: [PATCH 57/60] Update boost version --- nix/build-all.py | 4 ++-- win/build-deps.cmd | 35 +++++++++++++++++++++-------------- win/run-cmake.bat | 9 ++++++--- 3 files changed, 29 insertions(+), 19 deletions(-) diff --git a/nix/build-all.py b/nix/build-all.py index 28c3cf4838..6a89eb3602 100644 --- a/nix/build-all.py +++ b/nix/build-all.py @@ -64,10 +64,10 @@ OCE_VERSION="0.18" OCCT_VERSION="7.2.0" OCCT_HASH="88af392" PYTHON_VERSIONS=["2.7.12", "3.2.6", "3.3.6", "3.4.6", "3.5.3", "3.6.2"] -BOOST_VERSION="1.59.0" +BOOST_VERSION="1.67.0" PCRE_VERSION="8.39" LIBXML_VERSION="2.9.3" -CMAKE_VERSION="3.4.1" +CMAKE_VERSION="3.11.4" ICU_VERSION="56.1" SWIG_VERSION="3.0.12" diff --git a/win/build-deps.cmd b/win/build-deps.cmd index a37eabcca5..0e00db8dda 100644 --- a/win/build-deps.cmd +++ b/win/build-deps.cmd @@ -85,6 +85,14 @@ FOR %%i IN (powershell git cmake) DO ( where.exe %%i 1> NUL 2> NUL || call cecho.cmd 0 12 "Required tool `'%%i`' not installed or not added to PATH" && goto :ErrorAndPrintUsage ) +cmake --version | findstr version > temp.txt +set /p CMAKE_VERSION= Date: Sat, 30 Jun 2018 18:53:16 +0200 Subject: [PATCH 58/60] Correct accidentally committed lines --- win/build-deps.cmd | 2 -- 1 file changed, 2 deletions(-) diff --git a/win/build-deps.cmd b/win/build-deps.cmd index 0e00db8dda..28edffc9f8 100644 --- a/win/build-deps.cmd +++ b/win/build-deps.cmd @@ -191,8 +191,6 @@ call .\b2 toolset=msvc%BOOST_VC_VER% runtime-link=static address-model=%ARCH_BIT variant=%DEBUG_OR_RELEASE_LOWERCASE% %BOOST_LIBS% stage --stagedir=stage/vs%VS_VER%-%VS_PLATFORM% IF NOT %ERRORLEVEL%==0 GOTO :Error -goto :Successful - :ICU set DEPENDENCY_NAME=ICU set DEPENDENCY_DIR=N/A From 8428b93451d2150f4f4364154b8fffd170c95667 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Sun, 1 Jul 2018 09:16:34 +0200 Subject: [PATCH 59/60] nix cmake download url --- nix/build-all.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/build-all.py b/nix/build-all.py index 6a89eb3602..0b1fd1830d 100644 --- a/nix/build-all.py +++ b/nix/build-all.py @@ -242,7 +242,7 @@ def __check_output__(cmds, cwd=None): BOOST_VERSION_UNDERSCORE=BOOST_VERSION.replace(".", "_") ICU_VERSION_UNDERSCORE=ICU_VERSION.replace(".", "_") -CMAKE_VERSION_2=CMAKE_VERSION[0:3] +CMAKE_VERSION_2=CMAKE_VERSION[:CMAKE_VERSION.rindex('.')] OCE_LOCATION="https://github.com/tpaviot/oce/archive/OCE-%s.tar.gz" % (OCE_VERSION,) BOOST_LOCATION="http://downloads.sourceforge.net/project/boost/boost/%s/boost_%s.tar.bz2" % (BOOST_VERSION, BOOST_VERSION_UNDERSCORE) From 6fdd2049a2a62e754009e2c5089a04804f1e9078 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Sun, 1 Jul 2018 11:37:36 +0200 Subject: [PATCH 60/60] Restore previous boost version on nix --- nix/build-all.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nix/build-all.py b/nix/build-all.py index 0b1fd1830d..3c8f81bf52 100644 --- a/nix/build-all.py +++ b/nix/build-all.py @@ -64,10 +64,10 @@ OCE_VERSION="0.18" OCCT_VERSION="7.2.0" OCCT_HASH="88af392" PYTHON_VERSIONS=["2.7.12", "3.2.6", "3.3.6", "3.4.6", "3.5.3", "3.6.2"] -BOOST_VERSION="1.67.0" +BOOST_VERSION="1.59.0" PCRE_VERSION="8.39" LIBXML_VERSION="2.9.3" -CMAKE_VERSION="3.11.4" +CMAKE_VERSION="3.4.1" ICU_VERSION="56.1" SWIG_VERSION="3.0.12"