diff --git a/README.md b/README.md index d77372219f..122b40c7af 100644 --- a/README.md +++ b/README.md @@ -77,10 +77,12 @@ 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. +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: @@ -135,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 -------------- @@ -214,4 +225,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.py]: https://github.com/IfcOpenShell/IfcOpenShell/tree/master/nix/build-all.py "nix/build-all.py" diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 62dfbaff6a..a905c52f95 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -554,8 +554,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_ifc2x3 IfcGeom_ifc4 IfcGeom IfcGeom_ifc2x3 IfcGeom_ifc4 IfcGeom Serializers_ifc2x3 Serializers_ifc4 Serializers Serializers_ifc2x3 Serializers_ifc4 Serializers) diff --git a/nix/build-all.py b/nix/build-all.py index ce50c82065..3c8f81bf52 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,)) @@ -240,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) @@ -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" % (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); + } + 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() diff --git a/src/ifcconvert/IfcConvert.cpp b/src/ifcconvert/IfcConvert.cpp index c276a2e8e6..0a46961a3d 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 /* @@ -154,13 +154,16 @@ bool init_input_file(const std::string& filename, IfcParse::IfcFile*& ifc_file, 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() @@ -305,6 +308,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). " @@ -341,7 +346,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; @@ -354,30 +388,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 generate_uvs = vmap.count("generate-uvs") != 0 ; #ifdef HAVE_ICU if (!unicode_mode.empty()) { @@ -442,12 +452,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 = 0; 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(ifc_file, output_temp_filename); Logger::Status("Writing XML output..."); s.finalize(); @@ -458,7 +481,7 @@ int main(int argc, char** argv) } catch (const std::exception& e) { Logger::Error(e); } - write_log(); + write_log(!quiet); return exit_code; } @@ -512,6 +535,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); @@ -551,7 +576,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; } @@ -560,7 +585,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 */ @@ -585,14 +610,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; } @@ -603,7 +628,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; } @@ -617,13 +642,13 @@ 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; 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; } @@ -649,7 +674,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. @@ -676,14 +703,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; @@ -696,34 +737,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; } } @@ -881,7 +927,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/ifcgeom/IfcGeom.h b/src/ifcgeom/IfcGeom.h index 52c8a185a0..bf8550bfd8 100644 --- a/src/ifcgeom/IfcGeom.h +++ b/src/ifcgeom/IfcGeom.h @@ -202,6 +202,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/IfcGeomFaces.cpp b/src/ifcgeom/IfcGeomFaces.cpp index de09110692..8f45340761 100644 --- a/src/ifcgeom/IfcGeomFaces.cpp +++ b/src/ifcgeom/IfcGeomFaces.cpp @@ -215,7 +215,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/IfcGeomFilter.h b/src/ifcgeom/IfcGeomFilter.h index 31d44f55d7..0efd7839ae 100644 --- a/src/ifcgeom/IfcGeomFilter.h +++ b/src/ifcgeom/IfcGeomFilter.h @@ -25,6 +25,7 @@ #include "IfcGeom.h" +#include #include #include #include @@ -90,7 +91,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)); } } @@ -99,7 +100,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; } @@ -111,7 +112,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); } @@ -184,7 +185,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() + "\""); } @@ -247,7 +248,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, " "); @@ -271,7 +272,7 @@ namespace IfcGeom // TODO #if 0 values.clear(); - foreach(const std::string& type, types) { + BOOST_FOREACH(const std::string& type, types) { const IfcParse::declaration* ty; try { ty = IfcSchema::FromString::Class()(boost::to_upper_copy(type)); @@ -287,7 +288,7 @@ namespace IfcGeom bool match(IfcSchema::IfcProduct* prod) const { // The set is iterated over to able to filter on subtypes. - foreach(const IfcParse::declaration* type, values) { + BOOST_FOREACH(const IfcParse::declaration* type, values) { if (prod->declaration().is(*type)) { return true; } @@ -306,7 +307,7 @@ namespace IfcGeom #if 0 std::stringstream ss; ss << (traverse ? "traverse " : "") << (include ? "include" : "exclude") << " entities"; - foreach(IfcSchema::Enum::Class() type, values) { + BOOST_FOREACH(IfcSchema::Enum::Class() type, values) { ss << " " << IfcSchema::ToString::Class()(type); } description = ss.str(); diff --git a/src/ifcgeom/IfcGeomFunctions.cpp b/src/ifcgeom/IfcGeomFunctions.cpp index 1918c39b47..a7d9d8c487 100644 --- a/src/ifcgeom/IfcGeomFunctions.cpp +++ b/src/ifcgeom/IfcGeomFunctions.cpp @@ -95,6 +95,7 @@ #include #include +#include #include #include @@ -105,6 +106,7 @@ #include #include +#include #include #include @@ -131,6 +133,8 @@ #include +#include + #include #include "../ifcparse/macros.h" @@ -249,8 +253,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(); @@ -295,12 +301,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"); } @@ -626,9 +648,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); } @@ -657,7 +682,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); @@ -2429,7 +2462,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? @@ -2774,6 +2811,226 @@ 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 == (int) 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 || n > 128) { + if (n > 128) { + Logger::Notice("Too many segments for detection of self-intersections"); + } + wires.Append(wire); + return false; + } + + // Note: initialize empty + Handle(ShapeExtend_WireData) wd = new ShapeExtend_WireData(); + + // ... to be sure to get consecutive edges + 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) * 2.; + + 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; @@ -2832,6 +3089,47 @@ bool IfcGeom::Kernel::boolean_operation(const TopoDS_Shape& a, const TopoDS_Shap return succesful; } #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); + 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) { bool success = false; BRepAlgoAPI_BooleanOperation* builder; @@ -2847,17 +3145,27 @@ bool IfcGeom::Kernel::boolean_operation(const TopoDS_Shape& a, const TopTools_Li if (fuzziness < 0.) { fuzziness = getValue(GV_PRECISION); } + + const double min_edge_len = min_edge_length(a); + const double fuzz = (std::min)(min_edge_len / 3., fuzziness); + TopTools_ListOfShape s1s; - s1s.Append(a); - builder->SetFuzzyValue(fuzziness); + 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; ShapeFix_Shape fix(r); try { + fix.SetMinTolerance(fuzz); + fix.SetMaxTolerance(fuzz); + fix.SetPrecision(fuzz); fix.Perform(); r = fix.Shape(); } catch (...) { @@ -2873,7 +3181,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); } } diff --git a/src/ifcgeom/IfcGeomIteratorImplementation.h b/src/ifcgeom/IfcGeomIteratorImplementation.h index b13c7b0782..33092b63c7 100644 --- a/src/ifcgeom/IfcGeomIteratorImplementation.h +++ b/src/ifcgeom/IfcGeomIteratorImplementation.h @@ -119,6 +119,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; @@ -192,6 +195,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; @@ -389,6 +393,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; @@ -412,12 +417,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; @@ -425,10 +438,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; } @@ -688,7 +703,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::IfcBuilding::Class()); + } else if (settings.get(IteratorSettings::SITE_LOCAL_PLACEMENT)) { kernel.set_conversion_placement_rel_to(&IfcSchema::IfcSite::Class()); } } 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; diff --git a/src/ifcgeom/IfcGeomShapes.cpp b/src/ifcgeom/IfcGeomShapes.cpp index d0a6723045..81f6063b96 100644 --- a/src/ifcgeom/IfcGeomShapes.cpp +++ b/src/ifcgeom/IfcGeomShapes.cpp @@ -551,7 +551,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. diff --git a/src/ifcgeom/IfcGeomWires.cpp b/src/ifcgeom/IfcGeomWires.cpp index b5ace50216..35b0a51d2b 100644 --- a/src/ifcgeom/IfcGeomWires.cpp +++ b/src/ifcgeom/IfcGeomWires.cpp @@ -85,11 +85,169 @@ #include #include +#include +#include +#include #include "../ifcgeom/IfcGeom.h" #define Kernel MAKE_TYPE_NAME(Kernel) +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; + } + + 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_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(v.Oriented(TopAbs_FORWARD), v2); + + 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 override_next_; + gp_Pnt next_override_; + const IfcUtil::IfcBaseClass* inst_; + + public: + wire_builder(double p, const IfcUtil::IfcBaseClass* inst = 0) : p_(p), override_next_(false), inst_(inst) {} + + void operator()(const TopoDS_Shape& 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) { + 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); + + gp_Pnt p1 = BRep_Tool::Pnt(w12); + gp_Pnt p2 = BRep_Tool::Pnt(w21); + + double dist = p1.Distance(p2); + + // Distance is within 2p, this is fine + if (dist < 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_); + goto check; + } + + { + TopTools_IndexedDataMapOfShapeListOfShape wmap1, wmap2; + + // 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, w12, p2)); + Logger::Message(Logger::LOG_ERROR, "Adjusted edge end-point with distance " + boost::lexical_cast(dist) + " on:", inst_); + } else if (is_line2 && !last) { + mw_.Add(w1); + override_next_ = true; + next_override_ = p1; + Logger::Message(Logger::LOG_ERROR, "Adjusted edge end-point with distance " + boost::lexical_cast(dist) + " on:", inst_); + } 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_); + } + } else { + Logger::Error("Internal error, inconsistent wire segments", inst_); + mw_.Add(w1); + } + } + + check: + if (mw_.Error() == BRepBuilderAPI_NonManifoldWire) { + Logger::Error("Non-manifold curve segments:", inst_); + } else if (mw_.Error() == BRepBuilderAPI_DisconnectedWire) { + Logger::Error("Failed to join curve segments:", inst_); + } + } + + 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); @@ -167,105 +325,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); 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); - } - } - - w.Add(segment); - - if ( w.Error() != BRepBuilderAPI_WireDone ) { - if (w.Error() == BRepBuilderAPI_NonManifoldWire) { - - Logger::Message(Logger::LOG_ERROR, "Non-manifold curve segments:", l); - - } else if (w.Error() == BRepBuilderAPI_DisconnectedWire) { - - Logger::Message(Logger::LOG_ERROR, "Failed to join curve segments:", l); - - 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)); - } - } - - return false; - } - - wire_last_vertex = edge_last_vertex; } - gp_Pnt first = BRep_Tool::Pnt(edge_last_vertex); - gp_Pnt last = BRep_Tool::Pnt(wire_first_vertex); + BRepBuilderAPI_MakeWire w; + TopoDS_Vertex wire_first_vertex, wire_last_vertex, edge_first_vertex, edge_last_vertex; - Standard_Real distance = first.SquareDistance(last); - if (distance > precision_sq_2) { - w.Add(BRepBuilderAPI_MakeEdge(edge_last_vertex, wire_first_vertex)); + const double precision_sq_2 = 2 * getValue(GV_PRECISION) * getValue(GV_PRECISION); - Logger::Message(Logger::LOG_ERROR, "Closed gap on:", l); - } + TopTools_ListIteratorOfListOfShape it(converted_segments); - wire = w.Wire(); + IfcEntityList::ptr profile = l->data().getInverse(&IfcSchema::IfcProfileDef::Class(), -1); + const bool force_close = profile && profile->size() > 0; + + wire_builder bld(getValue(GV_PRECISION), l); + shape_pair_enumerate(it, bld, force_close); + wire = bld.wire(); return true; } @@ -395,14 +493,25 @@ 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) { + // tfk: note 1-based + polygon.Remove(polygon.Length()); + } + // 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; } @@ -426,7 +535,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) { @@ -445,7 +555,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); + select_largest(results, result); + } + return true; } diff --git a/src/ifcopenshell-python/ifcopenshell/geom/app.py b/src/ifcopenshell-python/ifcopenshell/geom/app.py index 8f0e6738fd..9fcd3191a0 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 @@ -43,14 +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: - from PyQt4.QtCore import QString -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): @@ -113,11 +116,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 +129,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,23 +143,23 @@ 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: 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.toPyObject() + inst = inst if inst: self.instanceSelected.emit(inst) @@ -165,7 +168,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 +209,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.connect(self.clicked_) self.expandAll() class type_treeview(abstract_treeview): @@ -230,33 +233,34 @@ 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) - add(t) + if ifcopenshell_version < "0.6": + add(t) 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.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 +275,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 +304,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 +312,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 +435,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 +497,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 +519,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 +538,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 +589,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): diff --git a/src/ifcopenshell-python/ifcopenshell/geom/code_editor_pane.py b/src/ifcopenshell-python/ifcopenshell/geom/code_editor_pane.py index e4306cd1a7..b64787f32b 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 @@ -32,23 +32,23 @@ 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) -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) 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) 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; 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 diff --git a/src/ifcparse/IfcEntityInstanceData.h b/src/ifcparse/IfcEntityInstanceData.h index 1719606ab1..67412ed08f 100644 --- a/src/ifcparse/IfcEntityInstanceData.h +++ b/src/ifcparse/IfcEntityInstanceData.h @@ -65,7 +65,7 @@ public: virtual ~IfcEntityInstanceData(); - boost::shared_ptr getInverse(const IfcParse::declaration* type, int attribute_index); + boost::shared_ptr getInverse (const IfcParse::declaration* type, int attribute_index) const; Argument* getArgument(unsigned int i) const; diff --git a/src/ifcparse/IfcFile.h b/src/ifcparse/IfcFile.h index f1efb72b4b..789716073b 100644 --- a/src/ifcparse/IfcFile.h +++ b/src/ifcparse/IfcFile.h @@ -22,6 +22,7 @@ #include #include +#include #include "ifc_parse_api.h" @@ -36,7 +37,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; diff --git a/src/ifcparse/IfcLogger.cpp b/src/ifcparse/IfcLogger.cpp index 6a7a9044ef..b2389b3de0 100644 --- a/src/ifcparse/IfcLogger.cpp +++ b/src/ifcparse/IfcLogger.cpp @@ -25,9 +25,44 @@ #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, const IfcUtil::IfcBaseClass* instance) { + os << "[" << severity_strings[type] << "] "; + if (current_product) { + std::string global_id = *(**current_product).data().getArgument((**current_product).declaration().as_entity()->attribute_index("GlobalId")); + os << "{" << global_id << "} "; + } + os << message << std::endl; + if (instance) { + os << instance->data().toString() << std::endl; + } + } + + void json_message(std::ostream& os, const boost::optional& current_product, Logger::Severity type, const std::string& message, const IfcUtil::IfcBaseClass* instance) { + ptree pt; + pt.put("level", severity_strings[type]); + if (current_product) { + pt.put("product", (**current_product).data().toString()); + } + pt.put("message", message); + if (instance) { + pt.put("instance", instance->data().toString()); + } + boost::property_tree::write_json(os, pt, false); + } +} + void Logger::SetOutput(std::ostream* l1, std::ostream* l2) { log1 = l1; log2 = l2; @@ -37,15 +72,11 @@ void Logger::SetOutput(std::ostream* l1, std::ostream* l2) { } void Logger::Message(Logger::Severity type, const std::string& message, const IfcUtil::IfcBaseClass* instance) { - if ( log2 && type >= verbosity ) { - (*log2) << "[" << severity_strings[type] << "] "; - if ( current_product ) { - std::string global_id = *(**current_product).data().getArgument((**current_product).declaration().as_entity()->attribute_index("GlobalId")); - (*log2) << "{" << global_id << "} "; - } - (*log2) << message << std::endl; - if (instance) { - (*log2) << instance->data().toString() << std::endl; + if (log2 && type >= verbosity) { + if (format == FMT_PLAIN) { + plain_text_message(*log2, current_product, type, message, instance); + } else if (format == FMT_JSON) { + json_message(*log2, current_product, type, message, instance); } } } @@ -55,26 +86,32 @@ void Logger::Message(Logger::Severity type, const std::exception& exception, con } 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; diff --git a/src/ifcparse/IfcLogger.h b/src/ifcparse/IfcLogger.h index a403240c58..30a9171374 100644 --- a/src/ifcparse/IfcLogger.h +++ b/src/ifcparse/IfcLogger.h @@ -36,12 +36,13 @@ 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: @@ -51,9 +52,14 @@ public: /// 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, const IfcUtil::IfcBaseClass* instance = 0); diff --git a/src/ifcparse/IfcParse.cpp b/src/ifcparse/IfcParse.cpp index ebbc6ca6d2..a9b7c52337 100644 --- a/src/ifcparse/IfcParse.cpp +++ b/src/ifcparse/IfcParse.cpp @@ -988,7 +988,7 @@ unsigned IfcEntityInstanceData::set_id(boost::optional i) { // // Returns the entities of Entity type that have this entity in their ArgumentList // -IfcEntityList::ptr IfcEntityInstanceData::getInverse(const IfcParse::declaration* type, int attribute_index) { +IfcEntityList::ptr IfcEntityInstanceData::getInverse(const IfcParse::declaration* type, int attribute_index) const { return file->getInverse(id_, type, attribute_index); } @@ -1891,7 +1891,7 @@ IfcEntityList::ptr IfcFile::instances_by_reference(int t) { IfcUtil::IfcBaseClass* IfcFile::instance_by_id(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; } @@ -1899,7 +1899,7 @@ IfcUtil::IfcBaseClass* IfcFile::instance_by_id(int id) { IfcUtil::IfcBaseClass* IfcFile::instance_by_guid(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; } @@ -1980,15 +1980,20 @@ IfcEntityList::ptr IfcFile::getInverse(int instance_id, const IfcParse::declarat for(IfcEntityList::it it = all->begin(); it != all->end(); ++it) { bool valid = type == 0 || (*it)->declaration().is(*type); if (valid && attribute_index >= 0) { - Argument* arg = (*it)->data().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)->data().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 (const IfcException& e) { + valid = false; + Logger::Error(e); } } if (valid) { diff --git a/src/serializers/ColladaSerializer.cpp b/src/serializers/ColladaSerializer.cpp index 71e01f768b..2349a8f31b 100644 --- a/src/serializers/ColladaSerializer.cpp +++ b/src/serializers/ColladaSerializer.cpp @@ -21,6 +21,8 @@ #include "ColladaSerializer.h" +#include + #include #include #include @@ -223,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); @@ -362,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() @@ -408,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/serializers/SvgSerializer.cpp b/src/serializers/SvgSerializer.cpp index 60423066e0..26ecef0eb8 100644 --- a/src/serializers/SvgSerializer.cpp +++ b/src/serializers/SvgSerializer.cpp @@ -360,26 +360,26 @@ 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(); - } 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.; } + // 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 TopoDS_Shape result = BRepAlgoAPI_Section(subshape, gp_Pln(gp_Pnt(0, 0, cut_z), gp::DZ())); diff --git a/src/serializers/schema_dependent/XmlSerializer.cpp b/src/serializers/schema_dependent/XmlSerializer.cpp index e2317ec308..656452c069 100644 --- a/src/serializers/schema_dependent/XmlSerializer.cpp +++ b/src/serializers/schema_dependent/XmlSerializer.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include "XmlSerializer.h" @@ -279,6 +280,9 @@ ptree& descend(IfcSchema::IfcObjectDefinition* product, ptree& tree) { if (pset->declaration().is(IfcSchema::IfcElementQuantity::Class())) { format_entity_instance(pset, child, true); } + if (pset->declaration().is(IfcSchema::IfcElementQuantity::Class())) { + format_entity_instance(pset, child, true); + } } #ifdef USE_IFC4 @@ -358,16 +362,16 @@ void MAKE_TYPE_NAME(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()); @@ -450,8 +454,11 @@ void MAKE_TYPE_NAME(XmlSerializer)::finalize() { emitted_materials.insert(mat); ptree node; node.put(".id", qualify_unrooted_instance(mat)); - if (mat->as()) { - IfcSchema::IfcMaterialLayerSet* layerset = mat->as()->ForLayerSet(); + if (mat->as() || mat->as()) { + IfcSchema::IfcMaterialLayerSet* layerset = mat->as(); + if (!layerset) { + layerset = mat->as()->ForLayerSet(); + } if (layerset->hasLayerSetName()) { node.put(".LayerSetName", layerset->LayerSetName()); } diff --git a/win/build-deps.cmd b/win/build-deps.cmd index a46c4e2641..28edffc9f8 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="%~dp0\BuildDepsCache-%TARGET_ARCH%.txt" @@ -141,31 +149,28 @@ cd "%DEPS_DIR%" :: by modifying this file and using goto. :Boost :: NOTE Boost < 1.64 doesn't work without tricks if the user has only VS 2017 installed and no earlier versions. -set BOOST_VERSION=1.65.1 -:: DEPENDENCY_NAME is used for logging and DEPENDENCY_DIR for saving from some redundant typing -set DEPENDENCY_NAME=Boost %BOOST_VERSION% -set DEPENDENCY_DIR="%DEPS_DIR%\boost" +set BOOST_VERSION=1.67.0 :: Version string with underscores instead of dots. set BOOST_VER=%BOOST_VERSION:.=_% -REM set BOOST_ROOT=%DEPS_DIR%\boost -REM set BOOST_INCLUDEDIR=%DEPS_DIR%\boost -set BOOST_LIBRARYDIR=%DEPS_DIR%\boost\stage\%VS_PLATFORM%\lib +:: DEPENDENCY_NAME is used for logging and DEPENDENCY_DIR for saving from some redundant typing +set DEPENDENCY_NAME=Boost %BOOST_VERSION% +set DEPENDENCY_DIR="%DEPS_DIR%\boost_%BOOST_VER%" +set BOOST_LIBRARYDIR=%DEPENDENCY_DIR%\stage\%VS_PLATFORM%\lib :: NOTE Also zip download exists, if encountering problems with 7z for some reason. 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" +call :ExtractArchive %BOOST_ZIP% "%DEPS_DIR%" "%DEPENDENCY_DIR%" IF NOT %ERRORLEVEL%==0 GOTO :Error :: Build Boost build script -if not exist "%DEPS_DIR%\boost\project-config.jam". ( +if not exist "%DEPENDENCY_DIR%\project-config.jam". ( cd "%DEPS_DIR%" - ren boost_%BOOST_VER% boost - IF NOT EXIST "%DEPS_DIR%\boost\boost.css" GOTO :Error - cd "%DEPS_DIR%\boost" + IF NOT EXIST "%DEPENDENCY_DIR%\boost.css" GOTO :Error + cd "%DEPENDENCY_DIR%" call cecho.cmd 0 13 "Building Boost build script." call bootstrap msvc IF NOT %ERRORLEVEL%==0 GOTO :Error @@ -173,9 +178,9 @@ if not exist "%DEPS_DIR%\boost\project-config.jam". ( set BOOST_LIBS=--with-system --with-regex --with-thread --with-program_options --with-date_time --with-iostreams --with-filesystem :: NOTE Boost is fast to build with limited set of libraries so build it always. -cd "%DEPS_DIR%\boost" +cd "%DEPENDENCY_DIR%" call cecho.cmd 0 13 "Building %DEPENDENCY_NAME% %BOOST_LIBS% Please be patient, this will take a while." -IF EXIST "%DEPS_DIR%\boost\bin.v2\project-cache.jam" del "%DEPS_DIR%\boost\bin.v2\project-cache.jam" +IF EXIST "%DEPENDENCY_DIR%\bin.v2\project-cache.jam" del "%DEPS_DIR%\boost\bin.v2\project-cache.jam" :: BOOST_VC_VER can be empty (or needs to be) for newer VS versions set BOOST_VC_VER= if %VS_VER% LSS 2017 ( @@ -192,7 +197,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 @@ -267,11 +272,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%" ( @@ -280,6 +287,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%" @@ -288,24 +296,45 @@ 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 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 @@ -408,7 +437,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://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 @@ -464,7 +493,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." @@ -478,7 +507,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." ) 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() 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; } diff --git a/win/run-cmake.bat b/win/run-cmake.bat index 1e62f6a61a..c72996a699 100755 --- a/win/run-cmake.bat +++ b/win/run-cmake.bat @@ -58,9 +58,12 @@ popd IF NOT EXIST ..\%BUILD_DIR%. mkdir ..\%BUILD_DIR% pushd ..\%BUILD_DIR% -set BOOST_ROOT=%DEPS_DIR%\boost -REM set BOOST_INCLUDEDIR=%DEPS_DIR%\boost\boost -set BOOST_LIBRARYDIR=%DEPS_DIR%\boost\stage\vs%VS_VER%-%VS_PLATFORM%\lib +:: tfk: todo remove duplication +set BOOST_VERSION=1.67.0 +set BOOST_VER=%BOOST_VERSION:.=_% + +set BOOST_ROOT=%DEPS_DIR%\boost_%BOOST_VER% +set BOOST_LIBRARYDIR=%BOOST_ROOT%\stage\vs%VS_VER%-%VS_PLATFORM%\lib set ICU_INCLUDE_DIR=%INSTALL_DIR%\icu\include set ICU_LIBRARY_DIR=%INSTALL_DIR%\icu\lib if not defined OCC_INCLUDE_DIR set OCC_INCLUDE_DIR=%INSTALL_DIR%\oce\include\oce