More work on isolating into plug-ins

This commit is contained in:
Thomas Krijnen
2026-04-18 15:46:21 +02:00
parent d2cc66fdf0
commit b599ee1040
34 changed files with 1818 additions and 606 deletions
+30 -8
View File
@@ -110,7 +110,21 @@ jobs:
run: | run: |
VERSION=v`cat VERSION` VERSION=v`cat VERSION`
cd ./build/`uname`/*/10.15/install/ifcopenshell cd ./build/`uname`/*/10.15/install/ifcopenshell
mkdir ~/output mkdir -p ~/output
install_root="$PWD"
stage_runtime_payload() {
dest="$1"
mkdir -p "$dest"
while IFS= read -r runtime_file; do
cp -L "$runtime_file" "$dest/"
done < <(
for runtime_dir in "$install_root/bin" "$install_root/lib"; do
[ -d "$runtime_dir" ] || continue
find "$runtime_dir" -type f \( -name "*.so" -o -name "*.so.*" -o -name "*.dylib" -o -name "*.dll" \)
done
)
}
ls -d python-* | while read py_version; do ls -d python-* | while read py_version; do
postfix=`echo ${py_version: -1} | sed s/[0-9]//` postfix=`echo ${py_version: -1} | sed s/[0-9]//`
@@ -125,18 +139,26 @@ jobs:
fi fi
[ -d ifcopenshell/__pycache__ ] && rm -rf ifcopenshell/__pycache__ [ -d ifcopenshell/__pycache__ ] && rm -rf ifcopenshell/__pycache__
find ifcopenshell -name "*.pyc" -delete find ifcopenshell -name "*.pyc" -delete
zip -r -qq ifcopenshell-${py_version_major}-${VERSION}-${GITHUB_SHA:0:7}-macos${{ matrix.oldarch }}64.zip ifcopenshell/* stage_runtime_payload ifcopenshell
zip -r -qq ifcopenshell-${py_version_major}-${VERSION}-${GITHUB_SHA:0:7}-macos${{ matrix.oldarch }}64.zip ifcopenshell
mv *.zip ~/output mv *.zip ~/output
popd > /dev/null popd > /dev/null
done done
cd bin rm -f "$install_root"/bin/*.zip
rm *.zip || true find "$install_root/bin" -maxdepth 1 -type f -perm /111 ! -name "*.zip" ! -name "*.so" ! -name "*.so.*" ! -name "*.dylib" ! -name "*.dll" | while read exe_path; do
ls | while read exe; do exe=`basename "$exe_path"`
zip -qq -r ${exe}-${VERSION}-${GITHUB_SHA:0:7}-macos${{ matrix.oldarch }}64.zip $exe package_dir="$install_root/.package-${exe}"
rm -rf "$package_dir"
mkdir -p "$package_dir"
cp "$exe_path" "$package_dir/"
stage_runtime_payload "$package_dir"
pushd "$package_dir" > /dev/null
zip -qq -r "$install_root/bin/${exe}-${VERSION}-${GITHUB_SHA:0:7}-macos${{ matrix.oldarch }}64.zip" .
popd > /dev/null
rm -rf "$package_dir"
done done
mv *.zip ~/output mv "$install_root"/bin/*.zip ~/output
cd ..
- name: Configure AWS credentials - name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v5 uses: aws-actions/configure-aws-credentials@v5
+30 -8
View File
@@ -89,7 +89,21 @@ jobs:
run: | run: |
VERSION=v`cat VERSION` VERSION=v`cat VERSION`
cd ./build/`uname`/*/install/ifcopenshell cd ./build/`uname`/*/install/ifcopenshell
mkdir ~/output mkdir -p ~/output
install_root="$PWD"
stage_runtime_payload() {
dest="$1"
mkdir -p "$dest"
while IFS= read -r runtime_file; do
cp -L "$runtime_file" "$dest/"
done < <(
for runtime_dir in "$install_root/bin" "$install_root/lib"; do
[ -d "$runtime_dir" ] || continue
find "$runtime_dir" -type f \( -name "*.so" -o -name "*.so.*" -o -name "*.dylib" -o -name "*.dll" \)
done
)
}
ls -d python-* | while read py_version; do ls -d python-* | while read py_version; do
postfix=`echo ${py_version: -1} | sed s/[0-9]//` postfix=`echo ${py_version: -1} | sed s/[0-9]//`
@@ -104,18 +118,26 @@ jobs:
fi fi
[ -d ifcopenshell/__pycache__ ] && rm -rf ifcopenshell/__pycache__ [ -d ifcopenshell/__pycache__ ] && rm -rf ifcopenshell/__pycache__
find ifcopenshell -name "*.pyc" -delete find ifcopenshell -name "*.pyc" -delete
zip -r -qq ifcopenshell-${py_version_major}-${VERSION}-${GITHUB_SHA:0:7}-linux64.zip ifcopenshell/* stage_runtime_payload ifcopenshell
zip -r -qq ifcopenshell-${py_version_major}-${VERSION}-${GITHUB_SHA:0:7}-linux64.zip ifcopenshell
mv *.zip ~/output mv *.zip ~/output
popd > /dev/null popd > /dev/null
done done
cd bin rm -f "$install_root"/bin/*.zip
rm *.zip || true find "$install_root/bin" -maxdepth 1 -type f -perm /111 ! -name "*.zip" ! -name "*.so" ! -name "*.so.*" ! -name "*.dylib" ! -name "*.dll" | while read exe_path; do
ls | while read exe; do exe=`basename "$exe_path"`
zip -qq -r ${exe}-${VERSION}-${GITHUB_SHA:0:7}-linux64.zip $exe package_dir="$install_root/.package-${exe}"
rm -rf "$package_dir"
mkdir -p "$package_dir"
cp "$exe_path" "$package_dir/"
stage_runtime_payload "$package_dir"
pushd "$package_dir" > /dev/null
zip -qq -r "$install_root/bin/${exe}-${VERSION}-${GITHUB_SHA:0:7}-linux64.zip" .
popd > /dev/null
rm -rf "$package_dir"
done done
mv *.zip ~/output mv "$install_root"/bin/*.zip ~/output
cd ..
- name: Configure AWS credentials - name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v5 uses: aws-actions/configure-aws-credentials@v5
+30 -8
View File
@@ -89,7 +89,21 @@ jobs:
run: | run: |
VERSION=v`cat VERSION` VERSION=v`cat VERSION`
cd ./build/`uname`/*/install/ifcopenshell cd ./build/`uname`/*/install/ifcopenshell
mkdir ~/output mkdir -p ~/output
install_root="$PWD"
stage_runtime_payload() {
dest="$1"
mkdir -p "$dest"
while IFS= read -r runtime_file; do
cp -L "$runtime_file" "$dest/"
done < <(
for runtime_dir in "$install_root/bin" "$install_root/lib"; do
[ -d "$runtime_dir" ] || continue
find "$runtime_dir" -type f \( -name "*.so" -o -name "*.so.*" -o -name "*.dylib" -o -name "*.dll" \)
done
)
}
ls -d python-* | while read py_version; do ls -d python-* | while read py_version; do
postfix=`echo ${py_version: -1} | sed s/[0-9]//` postfix=`echo ${py_version: -1} | sed s/[0-9]//`
@@ -104,18 +118,26 @@ jobs:
fi fi
[ -d ifcopenshell/__pycache__ ] && rm -rf ifcopenshell/__pycache__ [ -d ifcopenshell/__pycache__ ] && rm -rf ifcopenshell/__pycache__
find ifcopenshell -name "*.pyc" -delete find ifcopenshell -name "*.pyc" -delete
zip -r -qq ifcopenshell-${py_version_major}-${VERSION}-${GITHUB_SHA:0:7}-linuxarm64.zip ifcopenshell/* stage_runtime_payload ifcopenshell
zip -r -qq ifcopenshell-${py_version_major}-${VERSION}-${GITHUB_SHA:0:7}-linuxarm64.zip ifcopenshell
mv *.zip ~/output mv *.zip ~/output
popd > /dev/null popd > /dev/null
done done
cd bin rm -f "$install_root"/bin/*.zip
rm *.zip || true find "$install_root/bin" -maxdepth 1 -type f -perm /111 ! -name "*.zip" ! -name "*.so" ! -name "*.so.*" ! -name "*.dylib" ! -name "*.dll" | while read exe_path; do
ls | while read exe; do exe=`basename "$exe_path"`
zip -qq -r ${exe}-${VERSION}-${GITHUB_SHA:0:7}-linuxarm64.zip $exe package_dir="$install_root/.package-${exe}"
rm -rf "$package_dir"
mkdir -p "$package_dir"
cp "$exe_path" "$package_dir/"
stage_runtime_payload "$package_dir"
pushd "$package_dir" > /dev/null
zip -qq -r "$install_root/bin/${exe}-${VERSION}-${GITHUB_SHA:0:7}-linuxarm64.zip" .
popd > /dev/null
rm -rf "$package_dir"
done done
mv *.zip ~/output mv "$install_root"/bin/*.zip ~/output
cd ..
- name: Configure AWS credentials - name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v5 uses: aws-actions/configure-aws-credentials@v5
+58
View File
@@ -52,6 +52,64 @@ jobs:
cd win cd win
python build-all-win.py python build-all-win.py
- name: Repack .zip Archives With Runtime Plugins
shell: powershell
run: |
$version = (Get-Content VERSION | Select-Object -First 1).Trim()
$sha = $env:GITHUB_SHA.Substring(0, 7)
$outputDir = Join-Path $env:USERPROFILE "output"
$installDir = Get-ChildItem -Path . -Directory | Where-Object { $_.Name -like "_installed*" } | Select-Object -First 1
if (-not $installDir) {
throw "Install directory not found."
}
$runtimeFiles = @()
foreach ($runtimeDir in @((Join-Path $installDir.FullName "bin"), (Join-Path $installDir.FullName "lib"))) {
if (Test-Path $runtimeDir) {
$runtimeFiles += Get-ChildItem -Path $runtimeDir -Recurse -File | Where-Object { $_.Extension -ieq ".dll" }
}
}
$runtimeFiles = $runtimeFiles | Sort-Object FullName -Unique
Get-ChildItem -Path $outputDir -Filter *.zip -ErrorAction SilentlyContinue | Remove-Item -Force
$binDir = Join-Path $installDir.FullName "bin"
foreach ($exe in Get-ChildItem -Path $binDir -File -Filter *.exe) {
$stageDir = Join-Path $env:RUNNER_TEMP ("package-" + $exe.BaseName)
Remove-Item -Path $stageDir -Recurse -Force -ErrorAction SilentlyContinue
New-Item -ItemType Directory -Path $stageDir | Out-Null
Copy-Item -Path $exe.FullName -Destination $stageDir
foreach ($runtimeFile in $runtimeFiles) {
Copy-Item -Path $runtimeFile.FullName -Destination $stageDir -Force
}
$zipPath = Join-Path $outputDir ("{0}-v{1}-{2}-win64.zip" -f $exe.BaseName, $version, $sha)
Compress-Archive -Path (Join-Path $stageDir '*') -DestinationPath $zipPath -Force
}
$depsRoot = Join-Path (Get-Location) "_deps"
if (Test-Path $depsRoot) {
foreach ($pythonRoot in Get-ChildItem -Path $depsRoot -Directory | Where-Object { $_.Name -like "python.*" }) {
$pythonVersion = $pythonRoot.Name.Substring("python.".Length)
$pythonVersionMajorMinor = ($pythonVersion.Split(".")[0..1] -join "")
$sitePackages = Join-Path $pythonRoot.FullName "tools\\Lib\\site-packages"
$packagePath = Join-Path $sitePackages "ifcopenshell"
if (!(Test-Path $packagePath)) {
continue
}
Get-ChildItem -Path $packagePath -Recurse -Filter *.pyc -ErrorAction SilentlyContinue | Remove-Item -Force
foreach ($runtimeFile in $runtimeFiles) {
Copy-Item -Path $runtimeFile.FullName -Destination $packagePath -Force
}
$zipPath = Join-Path $outputDir ("ifcopenshell-python-{0}-v{1}-{2}-win64.zip" -f $pythonVersionMajorMinor, $version, $sha)
Push-Location $sitePackages
try {
Compress-Archive -Path "ifcopenshell" -DestinationPath $zipPath -Force
} finally {
Pop-Location
}
}
}
- name: Pack Dependencies - name: Pack Dependencies
run: | run: |
cd _deps-vs2022-x64-installed cd _deps-vs2022-x64-installed
+23 -3
View File
@@ -1,9 +1,29 @@
# IfcConvert # IfcConvert
add_executable(IfcConvert IfcConvert.cpp) add_executable(IfcConvert IfcConvert.cpp)
target_link_libraries(IfcConvert IfcGeom IfcParse Serializers ${OpenCASCADE_LIBRARIES} ${Boost_LIBRARIES} ${HDF5_LIBRARIES} ${USD_LIBRARIES}) target_link_libraries(IfcConvert PRIVATE IfcGeom IfcParse ${OpenCASCADE_LIBRARIES} ${Boost_LIBRARIES} ${HDF5_LIBRARIES} ${USD_LIBRARIES})
if(kernel_libraries OR mapping_libraries OR document_serializer_libraries) if(TARGET geometry_serializer_hdf)
add_dependencies(IfcConvert ${kernel_libraries} ${mapping_libraries} ${document_serializer_libraries}) target_link_libraries(IfcConvert PRIVATE geometry_serializer_hdf)
endif()
if(kernel_libraries OR mapping_libraries OR geometry_serializer_libraries OR document_serializer_libraries)
add_dependencies(IfcConvert ${kernel_libraries} ${mapping_libraries} ${geometry_serializer_libraries} ${document_serializer_libraries})
endif() endif()
set(_plugin_targets
${kernel_libraries}
${mapping_libraries}
${geometry_serializer_libraries}
${document_serializer_libraries}
)
set(_plugin_paths "")
foreach(t IN LISTS _plugin_targets)
string(APPEND _plugin_paths ";$<TARGET_FILE_DIR:${t}>")
endforeach()
set_target_properties(IfcConvert PROPERTIES
VS_DEBUGGER_ENVIRONMENT
"PATH=%PATH%;$<JOIN:$<TARGET_RUNTIME_DLL_DIRS:IfcConvert>,;>;${_plugin_paths}"
)
install(TARGETS IfcConvert) install(TARGETS IfcConvert)
+102 -326
View File
@@ -30,18 +30,8 @@
// error C2589: '(': illegal token on right side of '::' // error C2589: '(': illegal token on right side of '::'
#define NOMINMAX #define NOMINMAX
#include "../serializers/ColladaSerializer.h" #include "../serializers/document_serializer_plugin.h"
#include "../serializers/GltfSerializer.h" #include "../serializers/geometry_serializer_plugin.h"
#include "../serializers/HdfSerializer.h"
#include "../serializers/IgesSerializer.h"
#include "../serializers/StepSerializer.h"
#include "../serializers/WavefrontObjSerializer.h"
#include "../serializers/XmlSerializer.h"
#include "../serializers/SvgSerializer.h"
#include "../serializers/USDSerializer.h"
#include "../serializers/TtlWktSerializer.h"
#include "../serializers/RocksDbSerializer.h"
#include "../serializers/JsonSerializer.h"
#include "../ifcgeom/IfcGeomFilter.h" #include "../ifcgeom/IfcGeomFilter.h"
#include "../ifcgeom/Iterator.h" #include "../ifcgeom/Iterator.h"
@@ -54,10 +44,6 @@
#include <Standard_Version.hxx> #include <Standard_Version.hxx>
#if OCC_VERSION_HEX < 0x60900
#include <IGESControl_Controller.hxx>
#endif
#endif #endif
#include <boost/program_options.hpp> #include <boost/program_options.hpp>
@@ -352,14 +338,6 @@ int main(int argc, char** argv) {
std::string unicode_mode; std::string unicode_mode;
#endif #endif
short precision; short precision;
double section_height;
std::string svg_scale, svg_center;
std::string section_ref, elevation_ref, elevation_ref_guid;
// "none", "full" or "left"
std::string storey_height_display;
#ifdef IFOPSH_WITH_OPENCASCADE
SvgSerializer::storey_height_display_types svg_storey_height_display = SvgSerializer::SH_NONE;
#endif
ifcopenshell::geometry::SerializerSettings serializer_settings; ifcopenshell::geometry::SerializerSettings serializer_settings;
@@ -370,52 +348,6 @@ int main(int argc, char** argv) {
"Specifies the Unicode handling behavior when parsing the IFC file. " "Specifies the Unicode handling behavior when parsing the IFC file. "
"Accepted values 'utf8' (the default) and 'escape'.") "Accepted values 'utf8' (the default) and 'escape'.")
#endif #endif
("bounds", po::value<std::string>(&bounds),
"Specifies the bounding rectangle, for example 512x512, to which the "
"output will be scaled. Only used when converting to SVG.")
("scale", po::value<std::string>(&svg_scale),
"Interprets SVG bounds in mm, centers layout and draw elements to scale. "
"Only used when converting to SVG. Example 1:100.")
("center", po::value<std::string>(&svg_center),
"When using --scale, specifies the location in the range [0 1]x[0 1] around which"
"to center the drawings. Example 0.5x0.5 (default).")
("section-ref", po::value<std::string>(&section_ref),
"Element at which cross sections should be created")
("elevation-ref", po::value<std::string>(&elevation_ref),
"Element at which drawings should be created")
("elevation-ref-guid", po::value<std::string>(&elevation_ref_guid),
"Element guids at which drawings should be created")
("auto-section",
"Creates SVG cross section drawings automatically based on model extents")
("auto-elevation",
"Creates SVG elevation drawings automatically based on model extents")
("draw-storey-heights",
po::value<std::string>(&storey_height_display)->default_value("none")->implicit_value("full"),
"Draws a horizontal line at the height of building storeys in vertical drawings")
("storey-height-line-length", po::value<double>(),
"Length of the line when --draw-storey-heights=left")
("svg-xmlns",
"Stores name and guid in a separate namespace as opposed to data-name, data-guid")
("svg-poly",
"Uses the polygonal algorithm for hidden line rendering")
("svg-prefilter",
"Prefilter faces and shapes before feeding to HLR algorithm")
("svg-segment-projection",
"Segment result of projection wrt original products")
("svg-write-poly",
"Approximate every curve as polygonal in SVG output")
("svg-project",
"Always enable hidden line rendering instead of only on elevations")
("svg-without-storeys", "Don't emit drawings for building storeys")
("svg-no-css", "Don't emit CSS style declarations")
("door-arcs", "Draw door openings arcs for IfcDoor elements")
("section-height", po::value<double>(&section_height),
"Specifies the cut section height for SVG 2D geometry.")
("section-height-from-storeys", "Derives section height from storey elevation. Use --section-height to override default offset of 1.2")
("print-space-names", "Prints IfcSpace LongName and Name in the geometry output. Applicable for SVG output")
("print-space-areas", "Prints calculated IfcSpace areas in square meters. Applicable for SVG output")
("space-name-transform", po::value<std::string>(),
"Additional transform to the space labels in SVG")
; ;
serializer_settings.define_options(serializer_options); serializer_settings.define_options(serializer_options);
@@ -476,24 +408,6 @@ int main(int argc, char** argv) {
return EXIT_FAILURE; return EXIT_FAILURE;
} }
#ifdef IFOPSH_WITH_OPENCASCADE
if (vmap.count("draw-storey-heights")) {
boost::to_lower(storey_height_display);
if (storey_height_display == "none") {
svg_storey_height_display = SvgSerializer::SH_NONE;
} else if (storey_height_display == "full") {
svg_storey_height_display = SvgSerializer::SH_FULL;
} else if (storey_height_display == "left") {
svg_storey_height_display = SvgSerializer::SH_LEFT;
} else {
cerr_ << "[error] --draw-storey-heights should be none|full|left" << std::endl;
print_usage();
return EXIT_FAILURE;
}
}
#endif
if (num_threads <= 0) { if (num_threads <= 0) {
num_threads = std::thread::hardware_concurrency(); num_threads = std::thread::hardware_concurrency();
logger::notice("Using " + std::to_string(num_threads) + " threads"); logger::notice("Using " + std::to_string(num_threads) + " threads");
@@ -546,32 +460,6 @@ int main(int argc, char** argv) {
} }
} }
boost::optional<double> bounding_width, bounding_height, relative_center_x, relative_center_y;
if (vmap.count("bounds") == 1) {
int w, h;
if (sscanf(bounds.c_str(), "%ux%u", &w, &h) == 2 && w > 0 && h > 0) {
bounding_width = w;
bounding_height = h;
} else {
cerr_ << "[error] Invalid use of --bounds" << std::endl;
print_options(serializer_options);
return EXIT_FAILURE;
}
}
if (vmap.count("center") == 1) {
double cx, cy;
if (sscanf(svg_center.c_str(), "%lfx%lf", &cx, &cy) == 2 && cx >= 0. && cy >= 0. && cx <= 1. && cy <= 1.) {
relative_center_x = cx;
relative_center_y = cy;
} else {
cerr_ << "[error] Invalid use of --bounds" << std::endl;
print_options(serializer_options);
return EXIT_FAILURE;
}
}
const path_t input_filename = vmap["input-file"].as<path_t>(); const path_t input_filename = vmap["input-file"].as<path_t>();
/* /*
// todo also allow rocksdb dir // todo also allow rocksdb dir
@@ -640,53 +528,58 @@ int main(int argc, char** argv) {
path_t output_extension = dot + ext; path_t output_extension = dot + ext;
boost::to_lower(output_extension); boost::to_lower(output_extension);
const auto output_extension_utf8 = ifcopenshell::path::to_utf8(output_extension);
ifcopenshell::file* ifc_file = 0; ifcopenshell::file* ifc_file = 0;
boost::optional<std::list<IfcGeom::Element*>> elems_from_adaptor; boost::optional<std::list<IfcGeom::Element*>> elems_from_adaptor;
const path_t OBJ = ifcopenshell::path::from_utf8(".obj"), const path_t CACHE = ifcopenshell::path::from_utf8(".cache"),
MTL = ifcopenshell::path::from_utf8(".mtl"),
DAE = ifcopenshell::path::from_utf8(".dae"),
GLB = ifcopenshell::path::from_utf8(".glb"),
STP = ifcopenshell::path::from_utf8(".stp"),
IGS = ifcopenshell::path::from_utf8(".igs"),
SVG = ifcopenshell::path::from_utf8(".svg"),
CACHE = ifcopenshell::path::from_utf8(".cache"),
HDF = ifcopenshell::path::from_utf8(".h5"), HDF = ifcopenshell::path::from_utf8(".h5"),
XML = ifcopenshell::path::from_utf8(".xml"), IFC = ifcopenshell::path::from_utf8(".ifc");
JSON = ifcopenshell::path::from_utf8(".json"),
// @todo this is just temporary as it doesn't make sense to require an extension for a DB
RDB = ifcopenshell::path::from_utf8(".rdb"),
IFC = ifcopenshell::path::from_utf8(".ifc"),
USD = ifcopenshell::path::from_utf8(".usd"),
USDA = ifcopenshell::path::from_utf8(".usda"),
USDC = ifcopenshell::path::from_utf8(".usdc"),
TTL = ifcopenshell::path::from_utf8(".ttl");
// @todo clean up serializer selection auto& document_serializer_registry = ifcopenshell::serializers::document_serializer_registry_instance();
// @todo detect program options that conflict with the chosen serializer const auto* document_serializer_info = document_serializer_registry.find(output_extension_utf8);
if (output_extension == XML || output_extension == JSON) { if (document_serializer_info) {
int exit_code = EXIT_FAILURE; int exit_code = EXIT_FAILURE;
try { try {
if (init_input_file(ifcopenshell::path::to_utf8(input_filename), ifc_file, no_progress || quiet, mmap)) { const bool use_input_filename = vmap.count("stream") && document_serializer_info->supports_input_filename;
if (!use_input_filename && !document_serializer_info->supports_ifc_file) {
throw ifcopenshell::exception("Selected document serializer requires --stream");
}
if (use_input_filename || init_input_file(ifcopenshell::path::to_utf8(input_filename), ifc_file, no_progress || quiet, mmap)) {
if (!use_input_filename) {
document_serializer_info = document_serializer_registry.find(output_extension_utf8, ifc_file->schema()->name());
if (!document_serializer_info) {
throw ifcopenshell::exception("No document serializer registered for " + output_extension_utf8 + " and schema " + ifc_file->schema()->name());
}
}
time_t start, end; time_t start, end;
time(&start); time(&start);
if (output_extension == XML) {
XmlSerializer s(ifc_file, ifcopenshell::path::to_utf8(output_temp_filename)); ifcopenshell::serializers::document_serializer_context context;
logger::status("Writing XML output..."); context.file = ifc_file;
s.finalize(); context.input_filename = ifcopenshell::path::to_utf8(input_filename);
} else { context.output_filename = ifcopenshell::path::to_utf8(document_serializer_info->writes_final_output ? output_filename : output_temp_filename);
#ifdef WITH_GLTF context.schema_name = ifc_file ? ifc_file->schema()->name() : document_serializer_info->schema_name;
JsonSerializer s(ifc_file, ifcopenshell::path::to_utf8(output_temp_filename), JsonSerializer::JSON_DIALECT_CREOOX); context.stream = use_input_filename;
logger::status("Writing JSON output...");
s.finalize(); boost::shared_ptr<Serializer> serializer = document_serializer_registry.create(output_extension_utf8, context);
#endif logger::status("Writing " + boost::to_upper_copy(document_serializer_info->format) + " output...");
} serializer->finalize();
serializer.reset();
time(&end); time(&end);
logger::status("Done! Conversion took " + format_duration(start, end)); logger::status("Done! Conversion took " + format_duration(start, end));
ifcopenshell::path::rename_file(ifcopenshell::path::to_utf8(output_temp_filename), ifcopenshell::path::to_utf8(output_filename)); if (!document_serializer_info->writes_final_output &&
!ifcopenshell::path::rename_file(ifcopenshell::path::to_utf8(output_temp_filename), ifcopenshell::path::to_utf8(output_filename))) {
throw ifcopenshell::exception(
"Unable to write output file '" + ifcopenshell::path::to_utf8(output_filename) +
"', see '" + ifcopenshell::path::to_utf8(output_temp_filename) + "' for the conversion result");
}
exit_code = EXIT_SUCCESS; exit_code = EXIT_SUCCESS;
} }
} catch (const std::exception& e) { } catch (const std::exception& e) {
@@ -719,38 +612,15 @@ int main(int argc, char** argv) {
write_log(!quiet); write_log(!quiet);
return exit_code; return exit_code;
} }
#ifdef WITH_ROCKSDB
else if (output_extension == RDB) { auto& geometry_serializer_registry = ifcopenshell::serializers::geometry_serializer_registry_instance();
int exit_code = EXIT_FAILURE; const auto* geometry_serializer_info = geometry_serializer_registry.find(output_extension_utf8);
try { if (!geometry_serializer_info) {
if (vmap.count("stream")) { cerr_ << "[error] Unknown output filename extension '" << output_extension << "'\n";
time_t start, end;
time(&start);
RocksDbSerializer s(ifcopenshell::path::to_utf8(input_filename), ifcopenshell::path::to_utf8(output_filename), true);
logger::status("Populating RocksDB Key-Value store...");
s.finalize();
time(&end);
logger::status("Done! Conversion took " + format_duration(start, end));
exit_code = EXIT_SUCCESS;
} else {
if (init_input_file(ifcopenshell::path::to_utf8(input_filename), ifc_file, no_progress || quiet, mmap)) {
time_t start, end;
time(&start);
RocksDbSerializer s(ifc_file, ifcopenshell::path::to_utf8(output_filename));
logger::status("Populating RocksDB Key-Value store...");
s.finalize();
time(&end);
logger::status("Done! Conversion took " + format_duration(start, end));
exit_code = EXIT_SUCCESS;
}
}
} catch (const std::exception& e) {
logger::error(e);
}
write_log(!quiet); write_log(!quiet);
return exit_code; print_usage();
return EXIT_FAILURE;
} }
#endif
/// @todo Clean up this filter code further. /// @todo Clean up this filter code further.
std::vector<geom_filter> used_filters; std::vector<geom_filter> used_filters;
@@ -769,11 +639,7 @@ int main(int argc, char** argv) {
if (!layer_filter.values.empty()) { layer_filter.update_description(); logger::notice(layer_filter.description); } if (!layer_filter.values.empty()) { layer_filter.update_description(); logger::notice(layer_filter.description); }
if (!attribute_filter.attribute_name.empty()) { attribute_filter.update_description(); logger::notice(attribute_filter.description); } if (!attribute_filter.attribute_name.empty()) { attribute_filter.update_description(); logger::notice(attribute_filter.description); }
#ifdef _MSC_VER if (geometry_serializer_info && geometry_serializer_info->requires_ascii_temp_file) {
if (output_extension == DAE || output_extension == STP || output_extension == IGS) {
#else
if (output_extension == DAE) {
#endif
// These serializers do not support opening unicode paths. Therefore // These serializers do not support opening unicode paths. Therefore
// a random temp file is generated using only ASCII characters instead. // a random temp file is generated using only ASCII characters instead.
std::random_device rng; std::random_device rng;
@@ -798,15 +664,6 @@ int main(int argc, char** argv) {
geometry_settings.get<ifcopenshell::geometry::settings::NoParallelMapping>().value = true; geometry_settings.get<ifcopenshell::geometry::settings::NoParallelMapping>().value = true;
} }
if (geometry_settings.get<ifcopenshell::geometry::settings::UseElementHierarchy>().get() && output_extension != DAE && output_extension != USD && output_extension != USDA && output_extension != USDC && output_extension != GLB) {
cerr_ << "[error] --use-element-hierarchy can be used only with .dae or .usd or .glb output.\n";
/// @todo Lots of duplicate error-and-exit code.
write_log(!quiet);
print_usage();
ifcopenshell::path::delete_file(ifcopenshell::path::to_utf8(output_temp_filename));
return EXIT_FAILURE;
}
if (vmap[ifcopenshell::geometry::settings::WeldVertices::name].defaulted()) { if (vmap[ifcopenshell::geometry::settings::WeldVertices::name].defaulted()) {
geometry_settings.get<ifcopenshell::geometry::settings::WeldVertices>().value = false; geometry_settings.get<ifcopenshell::geometry::settings::WeldVertices>().value = false;
} }
@@ -815,60 +672,31 @@ int main(int argc, char** argv) {
IfcGeom::update_default_style("IfcSpace")->transparency = geometry_settings.get<ifcopenshell::geometry::settings::ForceSpaceTransparency>().get(); IfcGeom::update_default_style("IfcSpace")->transparency = geometry_settings.get<ifcopenshell::geometry::settings::ForceSpaceTransparency>().get();
} }
if (output_extension == OBJ || output_extension == STP || output_extension == IGS) { if (geometry_settings.get<ifcopenshell::geometry::settings::UseElementHierarchy>().get() &&
geometry_settings.get<ifcopenshell::geometry::settings::UseWorldCoords>().value = true; !geometry_serializer_info->supports_user_element_hierarchy) {
} cerr_ << "[error] --use-element-hierarchy is not supported by the selected geometry serializer.\n";
if (output_extension == TTL) {
geometry_settings.get<ifcopenshell::geometry::settings::TriangulationType>().value = ifcopenshell::geometry::settings::TriangulationMethod::POLYHEDRON_WITH_HOLES;
}
if (output_extension == SVG) {
// SVG serialiazation depends on element hierarchy now to look up the parent
geometry_settings.get<ifcopenshell::geometry::settings::UseElementHierarchy>().value = true;
}
boost::shared_ptr<GeometrySerializer> serializer; /**< @todo use std::unique_ptr when possible */
if (output_extension == OBJ) {
// Do not use temp file for MTL as it's such a small file.
const path_t mtl_filename = change_extension(output_filename, MTL);
serializer = boost::make_shared<WaveFrontOBJSerializer>(ifcopenshell::path::to_utf8(output_temp_filename), ifcopenshell::path::to_utf8(mtl_filename), geometry_settings, serializer_settings);
#ifdef WITH_OPENCOLLADA
} else if (output_extension == DAE) {
serializer = boost::make_shared<ColladaSerializer>(ifcopenshell::path::to_utf8(output_temp_filename), geometry_settings, serializer_settings);
#endif
#ifdef WITH_GLTF
} else if (output_extension == GLB) {
serializer = boost::make_shared<GltfSerializer>(ifcopenshell::path::to_utf8(output_temp_filename), geometry_settings, serializer_settings);
#endif
#ifdef WITH_USD
} else if (output_extension == USD || output_extension == USDA || output_extension == USDC) {
serializer = boost::make_shared<USDSerializer>(ifcopenshell::path::to_utf8(output_filename), geometry_settings, serializer_settings);
#endif
#ifdef IFOPSH_WITH_OPENCASCADE
} else if (output_extension == STP) {
serializer = boost::make_shared<StepSerializer>(ifcopenshell::path::to_utf8(output_temp_filename), geometry_settings, serializer_settings);
} else if (output_extension == IGS) {
#if OCC_VERSION_HEX < 0x60900
// According to https://tracker.dev.opencascade.org/view.php?id=25689 something has been fixed in 6.9.0
IGESControl_Controller::Init(); // work around Open Cascade bug
#endif
serializer = boost::make_shared<IgesSerializer>(ifcopenshell::path::to_utf8(output_temp_filename), geometry_settings, serializer_settings);
} else if (output_extension == SVG) {
geometry_settings.get<ifcopenshell::geometry::settings::IteratorOutput>().value = ifcopenshell::geometry::settings::NATIVE;
serializer = boost::make_shared<SvgSerializer>(ifcopenshell::path::to_utf8(output_temp_filename), geometry_settings, serializer_settings);
#ifdef WITH_HDF5
} else if (output_extension == HDF) {
geometry_settings.get<ifcopenshell::geometry::settings::IteratorOutput>().value = ifcopenshell::geometry::settings::NATIVE;
serializer = boost::make_shared<HdfSerializer>(ifcopenshell::path::to_utf8(output_temp_filename), geometry_settings, serializer_settings);
#endif
#endif
} else if (output_extension == TTL) {
serializer = boost::make_shared<TtlWktSerializer>(ifcopenshell::path::to_utf8(output_temp_filename), geometry_settings, serializer_settings);
} else {
cerr_ << "[error] Unknown output filename extension '" << output_extension << "'\n";
write_log(!quiet); write_log(!quiet);
print_usage(); print_usage();
ifcopenshell::path::delete_file(ifcopenshell::path::to_utf8(output_temp_filename));
return EXIT_FAILURE;
}
ifcopenshell::serializers::geometry_serializer_context serializer_context{
ifcopenshell::path::to_utf8(output_filename),
ifcopenshell::path::to_utf8(output_temp_filename),
geometry_settings,
serializer_settings
};
boost::shared_ptr<GeometrySerializer> serializer; /**< @todo use std::unique_ptr when possible */
try {
geometry_serializer_registry.configure(output_extension_utf8, serializer_context);
serializer = geometry_serializer_registry.create(output_extension_utf8, serializer_context);
} catch (const std::exception& e) {
cerr_ << "[error] " << e.what() << std::endl;
write_log(!quiet);
print_options(serializer_options);
ifcopenshell::path::delete_file(ifcopenshell::path::to_utf8(output_temp_filename));
return EXIT_FAILURE; return EXIT_FAILURE;
} }
@@ -897,9 +725,9 @@ int main(int argc, char** argv) {
time(&start); time(&start);
// @nb last argument true -> bypass_properties which are not read by any of the geometry serializers // @nb last argument true -> bypass_properties which are not read by any of the geometry serializers
// XML, RocksDB, IFC are already special-cased above // Document serializers and IFC are already special-cased above
// SVG requires properties for IfcAnnotation/DRAWING properties // SVG requires properties for IfcAnnotation/DRAWING properties
if (!init_input_file(ifcopenshell::path::to_utf8(input_filename), ifc_file, no_progress || quiet, mmap, output_extension != SVG)) { if (!init_input_file(ifcopenshell::path::to_utf8(input_filename), ifc_file, no_progress || quiet, mmap, geometry_serializer_info->bypass_properties)) {
write_log(!quiet); write_log(!quiet);
serializer.reset(); serializer.reset();
ifcopenshell::path::delete_file(ifcopenshell::path::to_utf8(output_temp_filename)); /**< @todo Windows Unicode support */ ifcopenshell::path::delete_file(ifcopenshell::path::to_utf8(output_temp_filename)); /**< @todo Windows Unicode support */
@@ -1003,12 +831,37 @@ int main(int argc, char** argv) {
} }
#if defined(WITH_HDF5) && defined(IFOPSH_WITH_OPENCASCADE) #if defined(WITH_HDF5) && defined(IFOPSH_WITH_OPENCASCADE)
std::unique_ptr<HdfSerializer> cache; boost::shared_ptr<GeometrySerializer> cache;
if (context_iterator && vmap.count("cache-file") || vmap.count("cache")) { const bool use_cache = context_iterator && (vmap.count("cache-file") || vmap.count("cache"));
if (use_cache) {
if (!vmap.count("cache-file")) { if (!vmap.count("cache-file")) {
cache_file = input_filename + CACHE + HDF; cache_file = input_filename + CACHE + HDF;
} }
cache.reset(new HdfSerializer(ifcopenshell::path::to_utf8(cache_file), geometry_settings, serializer_settings));
try {
ifcopenshell::serializers::geometry_serializer_context cache_context{
ifcopenshell::path::to_utf8(cache_file),
ifcopenshell::path::to_utf8(cache_file),
geometry_settings,
serializer_settings
};
cache = geometry_serializer_registry.create(".h5", cache_context);
} catch (const std::exception& e) {
cerr_ << "[error] Unable to initialize geometry cache: " << e.what() << std::endl;
serializer.reset();
ifcopenshell::path::delete_file(ifcopenshell::path::to_utf8(output_temp_filename));
write_log(!quiet);
return EXIT_FAILURE;
}
if (!cache || !cache->ready()) {
cerr_ << "[error] Unable to initialize geometry cache serializer\n";
serializer.reset();
ifcopenshell::path::delete_file(ifcopenshell::path::to_utf8(output_temp_filename));
write_log(!quiet);
return EXIT_FAILURE;
}
context_iterator->set_cache(cache.get()); context_iterator->set_cache(cache.get());
} }
#endif #endif
@@ -1027,83 +880,6 @@ int main(int argc, char** argv) {
serializer->setFile(ifc_file); serializer->setFile(ifc_file);
#ifdef IFOPSH_WITH_OPENCASCADE
if (output_extension == SVG) {
// @todo turn these all into proper settings
if (vmap.count("section-height-from-storeys") != 0) {
if (vmap.count("section-height")) {
static_cast<SvgSerializer*>(serializer.get())->setSectionHeightsFromStoreys(section_height);
} else {
static_cast<SvgSerializer*>(serializer.get())->setSectionHeightsFromStoreys();
}
} else if (vmap.count("section-height") != 0) {
logger::notice("Overriding section height");
static_cast<SvgSerializer*>(serializer.get())->setSectionHeight(section_height);
}
if (vmap.count("print-space-names") != 0) {
static_cast<SvgSerializer*>(serializer.get())->setPrintSpaceNames(true);
}
if (vmap.count("print-space-areas") != 0) {
static_cast<SvgSerializer*>(serializer.get())->setPrintSpaceAreas(true);
}
if (vmap.count("draw-storey-heights") != 0) {
static_cast<SvgSerializer*>(serializer.get())->setDrawStoreyHeights(svg_storey_height_display);
}
if (bounding_width.is_initialized() && bounding_height.is_initialized()) {
static_cast<SvgSerializer*>(serializer.get())->setBoundingRectangle(bounding_width.get(), bounding_height.get());
}
if (vmap.count("door-arcs")) {
static_cast<SvgSerializer*>(serializer.get())->setDrawDoorArcs(true);
}
if (vmap.count("scale")) {
int s0, s1;
if (sscanf(svg_scale.c_str(), "%u:%u", &s0, &s1) == 2 && s0 > 0 && s1 > 0) {
static_cast<SvgSerializer*>(serializer.get())->setScale((double)s0 / s1);
} else {
cerr_ << "[error] Invalid use of --scale" << std::endl;
print_options(serializer_options);
return EXIT_FAILURE;
}
}
if (vmap.count("section-ref")) {
static_cast<SvgSerializer*>(serializer.get())->setSectionRef(section_ref);
}
if (vmap.count("elevation-ref")) {
static_cast<SvgSerializer*>(serializer.get())->setElevationRef(elevation_ref);
}
if (vmap.count("elevation-ref-guid")) {
static_cast<SvgSerializer*>(serializer.get())->setElevationRefGuid(elevation_ref_guid);
}
if (vmap.count("auto-section")) {
static_cast<SvgSerializer*>(serializer.get())->setAutoSection(true);
}
if (vmap.count("auto-elevation")) {
static_cast<SvgSerializer*>(serializer.get())->setAutoElevation(true);
}
static_cast<SvgSerializer*>(serializer.get())->setUseNamespace(vmap.count("svg-xmlns") > 0);
static_cast<SvgSerializer*>(serializer.get())->setUseHlrPoly(vmap.count("svg-poly") > 0);
static_cast<SvgSerializer*>(serializer.get())->setUsePrefiltering(vmap.count("svg-prefilter") > 0);
static_cast<SvgSerializer*>(serializer.get())->setSegmentProjection(vmap.count("svg-segment-projection") > 0);
static_cast<SvgSerializer*>(serializer.get())->setPolygonal(vmap.count("svg-write-poly") > 0);
static_cast<SvgSerializer*>(serializer.get())->setAlwaysProject(vmap.count("svg-project") > 0);
static_cast<SvgSerializer*>(serializer.get())->setWithoutStoreys(vmap.count("svg-without-storeys") > 0);
static_cast<SvgSerializer*>(serializer.get())->setNoCSS(vmap.count("svg-no-css") > 0);
if (relative_center_x && relative_center_y) {
static_cast<SvgSerializer*>(serializer.get())->setDrawingCenter(*relative_center_x, *relative_center_y);
}
if (vmap.count("storey-height-line-length")) {
static_cast<SvgSerializer*>(serializer.get())->setStoreyHeightLineLength(
vmap["storey-height-line-length"].as<double>()
);
}
if (vmap.count("space-name-transform")) {
static_cast<SvgSerializer*>(serializer.get())->setSpaceNameTransform(
vmap["space-name-transform"].as<std::string>()
);
}
}
#endif
if (context_iterator && geometry_settings.get<ifcopenshell::geometry::settings::ConvertBackUnits>().get()) { if (context_iterator && geometry_settings.get<ifcopenshell::geometry::settings::ConvertBackUnits>().get()) {
serializer->setUnitNameAndMagnitude(context_iterator->unit_name(), static_cast<float>(context_iterator->unit_magnitude())); serializer->setUnitNameAndMagnitude(context_iterator->unit_name(), static_cast<float>(context_iterator->unit_magnitude()));
} else { } else {
@@ -1203,7 +979,7 @@ int main(int argc, char** argv) {
logger::message(logger::LOG_PERF, "done file geometry conversion"); logger::message(logger::LOG_PERF, "done file geometry conversion");
bool successful; bool successful;
if(output_extension == USD || output_extension == USDC || output_extension == USDA) { if (geometry_serializer_info->writes_final_output) {
// No need to rename the file // No need to rename the file
successful = true; successful = true;
} }
+6 -2
View File
@@ -4,12 +4,16 @@ set(mapping_libraries ${mapping_libraries} PARENT_SCOPE)
# IfcGeom (schema agnostic) # IfcGeom (schema agnostic)
file(GLOB SCHEMA_AGNOSTIC_H_FILES *.h) file(GLOB SCHEMA_AGNOSTIC_H_FILES *.h)
file(GLOB SCHEMA_AGNOSTIC_CPP_FILES *.cpp) file(GLOB SCHEMA_AGNOSTIC_CPP_FILES *.cpp)
set(SCHEMA_AGNOSTIC_FILES ${SCHEMA_AGNOSTIC_H_FILES} ${SCHEMA_AGNOSTIC_CPP_FILES}) set(SERIALIZER_RUNTIME_CPP_FILES
../serializers/document_serializer_plugin.cpp
../serializers/geometry_serializer_plugin.cpp
)
set(SCHEMA_AGNOSTIC_FILES ${SCHEMA_AGNOSTIC_H_FILES} ${SCHEMA_AGNOSTIC_CPP_FILES} ${SERIALIZER_RUNTIME_CPP_FILES})
add_library(IfcGeom ${SCHEMA_AGNOSTIC_FILES}) add_library(IfcGeom ${SCHEMA_AGNOSTIC_FILES})
add_library(geometry ALIAS IfcGeom) add_library(geometry ALIAS IfcGeom)
set_target_properties(IfcGeom PROPERTIES COMPILE_FLAGS -DIFC_GEOM_EXPORTS VERSION "${PROJECT_VERSION}" SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}") set_target_properties(IfcGeom PROPERTIES COMPILE_FLAGS -DIFC_GEOM_EXPORTS VERSION "${PROJECT_VERSION}" SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}")
target_compile_definitions(IfcGeom PRIVATE BOOST_DLL_USE_STD_FS) target_compile_definitions(IfcGeom PRIVATE BOOST_DLL_USE_STD_FS SERIALIZERS_EXPORTS)
if(UNIX) if(UNIX)
find_package(Threads) find_package(Threads)
+169 -1
View File
@@ -93,11 +93,179 @@ inline namespace settings {
static constexpr const char* const description = "Introduce a separate Z-Up node into the GlTF hierarchy instead of multiplying the transform into the root node matrices"; static constexpr const char* const description = "Introduce a separate Z-Up node into the GlTF hierarchy instead of multiplying the transform into the root node matrices";
static constexpr bool defaultvalue = false; static constexpr bool defaultvalue = false;
}; };
struct SvgBounds : public SettingBase<SvgBounds, std::string> {
static constexpr const char* const name = "bounds";
static constexpr const char* const description = "Specifies the bounding rectangle, for example 512x512, to which the output will be scaled. Only used when converting to SVG.";
};
struct SvgScale : public SettingBase<SvgScale, std::string> {
static constexpr const char* const name = "scale";
static constexpr const char* const description = "Interprets SVG bounds in mm, centers layout and draw elements to scale. Only used when converting to SVG. Example 1:100.";
};
struct SvgCenter : public SettingBase<SvgCenter, std::string> {
static constexpr const char* const name = "center";
static constexpr const char* const description = "When using --scale, specifies the location in the range [0 1]x[0 1] around which to center the drawings. Example 0.5x0.5.";
};
struct SvgSectionRef : public SettingBase<SvgSectionRef, std::string> {
static constexpr const char* const name = "section-ref";
static constexpr const char* const description = "Element at which cross sections should be created.";
};
struct SvgElevationRef : public SettingBase<SvgElevationRef, std::string> {
static constexpr const char* const name = "elevation-ref";
static constexpr const char* const description = "Element at which drawings should be created.";
};
struct SvgElevationRefGuid : public SettingBase<SvgElevationRefGuid, std::string> {
static constexpr const char* const name = "elevation-ref-guid";
static constexpr const char* const description = "Element guids at which drawings should be created.";
};
struct SvgAutoSection : public SettingBase<SvgAutoSection, bool> {
static constexpr const char* const name = "auto-section";
static constexpr const char* const description = "Creates SVG cross section drawings automatically based on model extents.";
static constexpr bool defaultvalue = false;
};
struct SvgAutoElevation : public SettingBase<SvgAutoElevation, bool> {
static constexpr const char* const name = "auto-elevation";
static constexpr const char* const description = "Creates SVG elevation drawings automatically based on model extents.";
static constexpr bool defaultvalue = false;
};
struct SvgDrawStoreyHeights : public SettingBase<SvgDrawStoreyHeights, std::string> {
static constexpr const char* const name = "draw-storey-heights";
static constexpr const char* const description = "Draws a horizontal line at the height of building storeys in vertical drawings. Accepted values are none, full, and left.";
};
struct SvgStoreyHeightLineLength : public SettingBase<SvgStoreyHeightLineLength, double> {
static constexpr const char* const name = "storey-height-line-length";
static constexpr const char* const description = "Length of the line when --draw-storey-heights=left.";
};
struct SvgUseNamespace : public SettingBase<SvgUseNamespace, bool> {
static constexpr const char* const name = "svg-xmlns";
static constexpr const char* const description = "Stores name and guid in a separate namespace as opposed to data-name, data-guid.";
static constexpr bool defaultvalue = false;
};
struct SvgUseHlrPoly : public SettingBase<SvgUseHlrPoly, bool> {
static constexpr const char* const name = "svg-poly";
static constexpr const char* const description = "Uses the polygonal algorithm for hidden line rendering.";
static constexpr bool defaultvalue = false;
};
struct SvgUsePrefiltering : public SettingBase<SvgUsePrefiltering, bool> {
static constexpr const char* const name = "svg-prefilter";
static constexpr const char* const description = "Prefilter faces and shapes before feeding to the hidden-line algorithm.";
static constexpr bool defaultvalue = false;
};
struct SvgSegmentProjection : public SettingBase<SvgSegmentProjection, bool> {
static constexpr const char* const name = "svg-segment-projection";
static constexpr const char* const description = "Segment result of projection with respect to original products.";
static constexpr bool defaultvalue = false;
};
struct SvgPolygonal : public SettingBase<SvgPolygonal, bool> {
static constexpr const char* const name = "svg-write-poly";
static constexpr const char* const description = "Approximate every curve as polygonal in SVG output.";
static constexpr bool defaultvalue = false;
};
struct SvgAlwaysProject : public SettingBase<SvgAlwaysProject, bool> {
static constexpr const char* const name = "svg-project";
static constexpr const char* const description = "Always enable hidden line rendering instead of only on elevations.";
static constexpr bool defaultvalue = false;
};
struct SvgWithoutStoreys : public SettingBase<SvgWithoutStoreys, bool> {
static constexpr const char* const name = "svg-without-storeys";
static constexpr const char* const description = "Do not emit drawings for building storeys.";
static constexpr bool defaultvalue = false;
};
struct SvgNoCss : public SettingBase<SvgNoCss, bool> {
static constexpr const char* const name = "svg-no-css";
static constexpr const char* const description = "Do not emit CSS style declarations.";
static constexpr bool defaultvalue = false;
};
struct SvgDoorArcs : public SettingBase<SvgDoorArcs, bool> {
static constexpr const char* const name = "door-arcs";
static constexpr const char* const description = "Draw door opening arcs for IfcDoor elements.";
static constexpr bool defaultvalue = false;
};
struct SvgSectionHeight : public SettingBase<SvgSectionHeight, double> {
static constexpr const char* const name = "section-height";
static constexpr const char* const description = "Specifies the cut section height for SVG 2D geometry.";
};
struct SvgSectionHeightFromStoreys : public SettingBase<SvgSectionHeightFromStoreys, bool> {
static constexpr const char* const name = "section-height-from-storeys";
static constexpr const char* const description = "Derives section height from storey elevation. Use --section-height to override the default offset of 1.2.";
static constexpr bool defaultvalue = false;
};
struct SvgPrintSpaceNames : public SettingBase<SvgPrintSpaceNames, bool> {
static constexpr const char* const name = "print-space-names";
static constexpr const char* const description = "Prints IfcSpace LongName and Name in the geometry output. Applicable for SVG output.";
static constexpr bool defaultvalue = false;
};
struct SvgPrintSpaceAreas : public SettingBase<SvgPrintSpaceAreas, bool> {
static constexpr const char* const name = "print-space-areas";
static constexpr const char* const description = "Prints calculated IfcSpace areas in square meters. Applicable for SVG output.";
static constexpr bool defaultvalue = false;
};
struct SvgSpaceNameTransform : public SettingBase<SvgSpaceNameTransform, std::string> {
static constexpr const char* const name = "space-name-transform";
static constexpr const char* const description = "Additional transform to the space labels in SVG.";
};
} }
class SerializerSettings : public SettingsContainer < class SerializerSettings : public SettingsContainer <
// @todo should we use tuple_cat here to unify the settings into a single class? // @todo should we use tuple_cat here to unify the settings into a single class?
std::tuple<UseElementNames, UseElementGuids, UseElementStepIds, UseElementTypes, UseYUp, WriteGltfEcef, FloatingPointDigits, BaseUri, WktUseSection, SeparateZUpNode>> std::tuple<
UseElementNames,
UseElementGuids,
UseElementStepIds,
UseElementTypes,
UseYUp,
WriteGltfEcef,
FloatingPointDigits,
BaseUri,
WktUseSection,
SeparateZUpNode,
SvgBounds,
SvgScale,
SvgCenter,
SvgSectionRef,
SvgElevationRef,
SvgElevationRefGuid,
SvgAutoSection,
SvgAutoElevation,
SvgDrawStoreyHeights,
SvgStoreyHeightLineLength,
SvgUseNamespace,
SvgUseHlrPoly,
SvgUsePrefiltering,
SvgSegmentProjection,
SvgPolygonal,
SvgAlwaysProject,
SvgWithoutStoreys,
SvgNoCss,
SvgDoorArcs,
SvgSectionHeight,
SvgSectionHeightFromStoreys,
SvgPrintSpaceNames,
SvgPrintSpaceAreas,
SvgSpaceNameTransform>>
{}; {};
} }
+6
View File
@@ -147,6 +147,12 @@ target_link_libraries(ifcopenshell_wrapper PRIVATE ${IFCOPENSHELL_LIBRARIES} ${O
else() else()
target_link_libraries(ifcopenshell_wrapper PRIVATE ${IFCOPENSHELL_LIBRARIES} ${LIBSVGFILL}) target_link_libraries(ifcopenshell_wrapper PRIVATE ${IFCOPENSHELL_LIBRARIES} ${LIBSVGFILL})
endif() endif()
if(geometry_serializer_libraries)
target_link_libraries(ifcopenshell_wrapper PRIVATE ${geometry_serializer_libraries})
endif()
if(TARGET document_serializer_rdb)
target_link_libraries(ifcopenshell_wrapper PRIVATE document_serializer_rdb)
endif()
if(kernel_libraries OR tree_libraries OR mapping_libraries OR geometry_serializer_libraries OR document_serializer_libraries) if(kernel_libraries OR tree_libraries OR mapping_libraries OR geometry_serializer_libraries OR document_serializer_libraries)
add_dependencies(ifcopenshell_wrapper ${kernel_libraries} ${tree_libraries} ${mapping_libraries} ${geometry_serializer_libraries} ${document_serializer_libraries}) add_dependencies(ifcopenshell_wrapper ${kernel_libraries} ${tree_libraries} ${mapping_libraries} ${geometry_serializer_libraries} ${document_serializer_libraries})
endif() endif()
-3
View File
@@ -163,9 +163,6 @@
%ignore ApplyOffset; %ignore ApplyOffset;
%ignore SeparateZUpNode; %ignore SeparateZUpNode;
%ignore XmlSerializerFactory;
%ignore JsonSerializerFactory;
// Triangulated representation helper struct // Triangulated representation helper struct
%ignore EdgeKey; %ignore EdgeKey;
+73 -21
View File
@@ -1,34 +1,87 @@
add_subdirectory(schema_dependent) set(document_serializer_plugin_runtime_dir "${CMAKE_BINARY_DIR}/serializers/$<CONFIG>")
set(geometry_serializer_plugin_runtime_dir "${CMAKE_BINARY_DIR}/serializers/$<CONFIG>")
file(GLOB SERIALIZERS_H_FILES *.h) file(GLOB SERIALIZERS_H_FILES *.h)
file(GLOB SERIALIZERS_CPP_FILES *.cpp)
file(GLOB SERIALIZERS_S_H_FILES schema_dependent/*.h) file(GLOB SERIALIZERS_S_H_FILES schema_dependent/*.h)
set(SERIALIZERS_FILES ${SERIALIZERS_H_FILES} ${SERIALIZERS_CPP_FILES})
add_library(Serializers ${SERIALIZERS_FILES}) function(add_document_serializer_plugin target output_name)
add_library(serialization ALIAS Serializers) cmake_parse_arguments(PLUGIN "" "" "SOURCES;LIBRARIES" ${ARGN})
set_target_properties(Serializers PROPERTIES COMPILE_FLAGS "-DSERIALIZERS_EXPORTS" VERSION "${PROJECT_VERSION}" SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}")
if(WITH_PROJ) add_library(${target} SHARED ${PLUGIN_SOURCES})
find_package(proj REQUIRED) target_compile_definitions(${target} PRIVATE SERIALIZERS_EXPORTS BOOST_DLL_USE_STD_FS)
target_compile_definitions(Serializers PRIVATE "WITH_PROJ") target_link_libraries(${target} PRIVATE plugin IfcGeom IfcParse ${PLUGIN_LIBRARIES})
if(PROJ_STATIC) set_target_properties(${target} PROPERTIES
target_compile_definitions(Serializers PRIVATE "PROJ_DLL=") OUTPUT_NAME "${output_name}"
RUNTIME_OUTPUT_DIRECTORY "${document_serializer_plugin_runtime_dir}"
LIBRARY_OUTPUT_DIRECTORY "${document_serializer_plugin_runtime_dir}"
)
list(APPEND document_serializer_libraries ${target})
set(document_serializer_libraries ${document_serializer_libraries} PARENT_SCOPE)
endfunction()
function(add_geometry_serializer_plugin target output_name)
cmake_parse_arguments(PLUGIN "" "" "SOURCES;LIBRARIES" ${ARGN})
add_library(${target} SHARED ${PLUGIN_SOURCES})
target_compile_definitions(${target} PRIVATE SERIALIZERS_EXPORTS BOOST_DLL_USE_STD_FS)
target_link_libraries(${target} PRIVATE plugin IfcGeom IfcParse ${PLUGIN_LIBRARIES})
if(WITH_PROJ)
find_package(proj REQUIRED)
target_compile_definitions(${target} PRIVATE "WITH_PROJ")
if(PROJ_STATIC)
target_compile_definitions(${target} PRIVATE "PROJ_DLL=")
endif()
target_link_libraries(${target} PRIVATE proj::proj)
endif() endif()
target_link_libraries(Serializers PRIVATE proj::proj) set_target_properties(${target} PROPERTIES
OUTPUT_NAME "${output_name}"
RUNTIME_OUTPUT_DIRECTORY "${geometry_serializer_plugin_runtime_dir}"
LIBRARY_OUTPUT_DIRECTORY "${geometry_serializer_plugin_runtime_dir}"
)
list(APPEND geometry_serializer_libraries ${target})
set(geometry_serializer_libraries ${geometry_serializer_libraries} PARENT_SCOPE)
endfunction()
if(WITH_ROCKSDB)
add_document_serializer_plugin(document_serializer_rdb "document.rdb" SOURCES document_rdb_plugin.cpp RocksDbSerializer.cpp LIBRARIES RocksDB::rocksdb)
endif() endif()
target_link_libraries(Serializers add_subdirectory(schema_dependent)
PRIVATE
plugin ${OPENCOLLADA_LIBRARIES} ${USD_LIBRARIES} set(ttl_geometry_serializer_libraries)
IfcGeom ${OpenCASCADE_LIBRARIES} IfcParse if(WITH_OPENCASCADE)
) set(ttl_geometry_serializer_libraries geometry_kernel_opencascade ${OpenCASCADE_LIBRARIES})
endif()
add_geometry_serializer_plugin(geometry_serializer_obj "geometry.obj" SOURCES geometry_obj_plugin.cpp WavefrontObjSerializer.cpp)
add_geometry_serializer_plugin(geometry_serializer_ttl "geometry.ttl" SOURCES geometry_ttl_plugin.cpp TtlWktSerializer.cpp LIBRARIES ${ttl_geometry_serializer_libraries})
if(OPENCOLLADA_FOUND)
add_geometry_serializer_plugin(geometry_serializer_dae "geometry.dae" SOURCES geometry_dae_plugin.cpp ColladaSerializer.cpp LIBRARIES ${OPENCOLLADA_LIBRARIES})
endif()
if(GLTF_SUPPORT)
add_geometry_serializer_plugin(geometry_serializer_glb "geometry.glb" SOURCES geometry_glb_plugin.cpp GltfSerializer.cpp)
endif()
if(USD_SUPPORT)
add_geometry_serializer_plugin(geometry_serializer_usd "geometry.usd" SOURCES geometry_usd_plugin.cpp USDSerializer.cpp LIBRARIES ${USD_LIBRARIES})
endif()
if(WITH_OPENCASCADE) if(WITH_OPENCASCADE)
target_link_libraries(Serializers PRIVATE geometry_kernel_opencascade) set(opencascade_geometry_serializer_libraries geometry_kernel_opencascade ${OpenCASCADE_LIBRARIES})
add_geometry_serializer_plugin(geometry_serializer_stp "geometry.stp" SOURCES geometry_stp_plugin.cpp OpenCascadeBasedSerializer.cpp LIBRARIES ${opencascade_geometry_serializer_libraries})
add_geometry_serializer_plugin(geometry_serializer_igs "geometry.igs" SOURCES geometry_igs_plugin.cpp OpenCascadeBasedSerializer.cpp LIBRARIES ${opencascade_geometry_serializer_libraries})
add_geometry_serializer_plugin(geometry_serializer_svg "geometry.svg" SOURCES geometry_svg_plugin.cpp SvgSerializer.cpp util.cpp LIBRARIES ${opencascade_geometry_serializer_libraries})
if(HDF5_SUPPORT)
add_geometry_serializer_plugin(geometry_serializer_hdf "geometry.hdf" SOURCES geometry_hdf_plugin.cpp HdfSerializer.cpp LIBRARIES ${opencascade_geometry_serializer_libraries} ${HDF5_LIBRARIES})
endif()
endif() endif()
install(TARGETS Serializers ${document_serializer_libraries}) install(TARGETS ${document_serializer_libraries} ${geometry_serializer_libraries})
install(FILES ${SERIALIZERS_H_FILES} install(FILES ${SERIALIZERS_H_FILES}
DESTINATION ${INCLUDEDIR}/serializers/ DESTINATION ${INCLUDEDIR}/serializers/
@@ -38,6 +91,5 @@ install(FILES ${SERIALIZERS_S_H_FILES}
DESTINATION ${INCLUDEDIR}/serializers/schema_dependent DESTINATION ${INCLUDEDIR}/serializers/schema_dependent
) )
set(IFCOPENSHELL_LIBRARIES ${IFCOPENSHELL_LIBRARIES} Serializers)
set(IFCOPENSHELL_LIBRARIES ${IFCOPENSHELL_LIBRARIES} PARENT_SCOPE)
set(document_serializer_libraries ${document_serializer_libraries} PARENT_SCOPE) set(document_serializer_libraries ${document_serializer_libraries} PARENT_SCOPE)
set(geometry_serializer_libraries ${geometry_serializer_libraries} PARENT_SCOPE)
-56
View File
@@ -1,56 +0,0 @@
/********************************************************************************
* *
* This file is part of IfcOpenShell. *
* *
* IfcOpenShell is free software: you can redistribute it and/or modify *
* it under the terms of the Lesser GNU General Public License as published by *
* the Free Software Foundation, either version 3.0 of the License, or *
* (at your option) any later version. *
* *
* IfcOpenShell is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* Lesser GNU General Public License for more details. *
* *
* You should have received a copy of the Lesser GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
#ifdef WITH_GLTF
#include "JsonSerializer.h"
#include "document_serializer_plugin.h"
#include <boost/algorithm/string/case_conv.hpp>
JsonSerializerFactory::Factory::Factory() {
ifcopenshell::serializers::load_document_serializer_plugins(*this, "json");
}
void JsonSerializerFactory::Factory::bind(const std::string& schema_name, fn f, const ifcopenshell::plugin::module& module) {
const std::string schema_name_lower = boost::to_lower_copy(schema_name);
entries_[schema_name_lower] = { f, module };
}
JsonSerializer* JsonSerializerFactory::Factory::construct(const std::string& schema_name, ifcopenshell::file* file, std::string json_filename, JsonSerializer::Dialect dialect) {
const std::string schema_name_lower = boost::to_lower_copy(schema_name);
auto it = entries_.find(schema_name_lower);
if (it == entries_.end()) {
throw ifcopenshell::exception("No Json serializer registered for " + schema_name);
}
return it->second.fn_(file, json_filename, dialect);
}
JsonSerializer::JsonSerializer(ifcopenshell::file* file, const std::string& json_filename, JsonSerializer::Dialect dialect) {
if (file) {
implementation_ = JsonSerializerFactory::implementations().construct(file->schema()->name(), file, json_filename, dialect);
}
}
JsonSerializerFactory::Factory& JsonSerializerFactory::implementations() {
static JsonSerializerFactory::Factory impl;
return impl;
}
#endif
+25 -27
View File
@@ -7,55 +7,53 @@
#include "../ifcparse/file.h" #include "../ifcparse/file.h"
#include "../plugin/plugin.h" #include "../plugin/plugin.h"
#include "../serializers/serializers_api.h" #include "../serializers/serializers_api.h"
#include "../serializers/document_serializer_plugin.h"
#include <boost/function.hpp> #include <boost/shared_ptr.hpp>
#include <map>
class SERIALIZERS_API JsonSerializer : public Serializer { class JsonSerializer : public Serializer {
public: public:
enum Dialect { enum Dialect {
JSON_DIALECT_CREOOX JSON_DIALECT_CREOOX
}; };
private: private:
JsonSerializer* implementation_ = nullptr; boost::shared_ptr<Serializer> implementation_;
protected: protected:
std::string json_filename; std::string json_filename;
Dialect dialect_; Dialect dialect_;
public: public:
JsonSerializer(ifcopenshell::file* file, const std::string& json_filename, Dialect dialect = Dialect::JSON_DIALECT_CREOOX); JsonSerializer(ifcopenshell::file* file, const std::string& json_filename, Dialect dialect = Dialect::JSON_DIALECT_CREOOX)
: json_filename(json_filename)
, dialect_(dialect)
{
if (!file) {
return;
}
ifcopenshell::serializers::document_serializer_context context;
context.file = file;
context.output_filename = json_filename;
context.schema_name = file->schema()->name();
context.dialect = static_cast<int>(dialect);
implementation_ = ifcopenshell::serializers::document_serializer_registry_instance().create("json", context);
}
virtual ~JsonSerializer() {} virtual ~JsonSerializer() {}
bool ready() { return true; } bool ready() { return true; }
void writeHeader() {} void writeHeader() {}
void finalize() { implementation_->finalize(); } void finalize() {
if (!implementation_) {
throw ifcopenshell::exception("No JSON serializer implementation constructed");
}
implementation_->finalize();
}
void setFile(ifcopenshell::file*) { throw ifcopenshell::exception("Should be supplied on construction"); } void setFile(ifcopenshell::file*) { throw ifcopenshell::exception("Should be supplied on construction"); }
}; };
struct SERIALIZERS_API JsonSerializerFactory {
typedef boost::function3<JsonSerializer*, ifcopenshell::file*, std::string, JsonSerializer::Dialect> fn;
class SERIALIZERS_API Factory {
public:
Factory();
void bind(const std::string& schema_name, fn, const ifcopenshell::plugin::module& module = ifcopenshell::plugin::module());
JsonSerializer* construct(const std::string& schema_name, ifcopenshell::file*, std::string, JsonSerializer::Dialect);
private:
struct entry {
fn fn_;
ifcopenshell::plugin::module module_;
};
std::map<std::string, entry> entries_;
};
static Factory& implementations();
};
#endif #endif
#endif #endif
+115
View File
@@ -86,17 +86,132 @@
#include "../ifcgeom/kernels/opencascade/OpenCascadeConversionResult.h" #include "../ifcgeom/kernels/opencascade/OpenCascadeConversionResult.h"
#include <boost/algorithm/string/case_conv.hpp>
#include <boost/format.hpp> #include <boost/format.hpp>
#include <boost/tokenizer.hpp> #include <boost/tokenizer.hpp>
#include "SvgSerializer.h" #include "SvgSerializer.h"
namespace {
const double PI2 = M_PI * 2.; const double PI2 = M_PI * 2.;
std::pair<double, double> parse_svg_bounds(const std::string& value) {
unsigned int width = 0;
unsigned int height = 0;
if (std::sscanf(value.c_str(), "%ux%u", &width, &height) == 2 && width > 0 && height > 0) {
return { static_cast<double>(width), static_cast<double>(height) };
}
throw std::runtime_error("Invalid use of --bounds");
}
std::pair<double, double> parse_svg_center(const std::string& value) {
double center_x = 0.;
double center_y = 0.;
if (std::sscanf(value.c_str(), "%lfx%lf", &center_x, &center_y) == 2 &&
center_x >= 0. && center_y >= 0. &&
center_x <= 1. && center_y <= 1.) {
return { center_x, center_y };
}
throw std::runtime_error("Invalid use of --center");
}
double parse_svg_scale(const std::string& value) {
unsigned int numerator = 0;
unsigned int denominator = 0;
if (std::sscanf(value.c_str(), "%u:%u", &numerator, &denominator) == 2 &&
numerator > 0 && denominator > 0) {
return static_cast<double>(numerator) / denominator;
}
throw std::runtime_error("Invalid use of --scale");
}
SvgSerializer::storey_height_display_types parse_storey_height_display(const std::string& value) {
const auto display = boost::to_lower_copy(value);
if (display == "none") {
return SvgSerializer::SH_NONE;
}
if (display == "full") {
return SvgSerializer::SH_FULL;
}
if (display == "left") {
return SvgSerializer::SH_LEFT;
}
throw std::runtime_error("Invalid use of --draw-storey-heights, expected none|full|left");
}
}
bool SvgSerializer::ready() { bool SvgSerializer::ready() {
return true; return true;
} }
void SvgSerializer::apply_settings() {
using namespace ifcopenshell::geometry::settings;
if (settings().get<SvgBounds>().has()) {
const auto bounds = parse_svg_bounds(settings().get<SvgBounds>().get());
setBoundingRectangle(bounds.first, bounds.second);
}
if (settings().get<SvgScale>().has()) {
setScale(parse_svg_scale(settings().get<SvgScale>().get()));
}
if (settings().get<SvgCenter>().has()) {
const auto center = parse_svg_center(settings().get<SvgCenter>().get());
setDrawingCenter(center.first, center.second);
}
if (settings().get<SvgSectionHeightFromStoreys>().get()) {
if (settings().get<SvgSectionHeight>().has()) {
setSectionHeightsFromStoreys(settings().get<SvgSectionHeight>().get());
} else {
setSectionHeightsFromStoreys();
}
} else if (settings().get<SvgSectionHeight>().has()) {
setSectionHeight(settings().get<SvgSectionHeight>().get());
}
setPrintSpaceNames(settings().get<SvgPrintSpaceNames>().get());
setPrintSpaceAreas(settings().get<SvgPrintSpaceAreas>().get());
setDrawDoorArcs(settings().get<SvgDoorArcs>().get());
setAutoSection(settings().get<SvgAutoSection>().get());
setAutoElevation(settings().get<SvgAutoElevation>().get());
setUseNamespace(settings().get<SvgUseNamespace>().get());
setUseHlrPoly(settings().get<SvgUseHlrPoly>().get());
setUsePrefiltering(settings().get<SvgUsePrefiltering>().get());
setSegmentProjection(settings().get<SvgSegmentProjection>().get());
setPolygonal(settings().get<SvgPolygonal>().get());
setAlwaysProject(settings().get<SvgAlwaysProject>().get());
setWithoutStoreys(settings().get<SvgWithoutStoreys>().get());
setNoCSS(settings().get<SvgNoCss>().get());
if (settings().get<SvgDrawStoreyHeights>().has()) {
setDrawStoreyHeights(parse_storey_height_display(settings().get<SvgDrawStoreyHeights>().get()));
}
if (settings().get<SvgStoreyHeightLineLength>().has()) {
setStoreyHeightLineLength(settings().get<SvgStoreyHeightLineLength>().get());
}
if (settings().get<SvgSpaceNameTransform>().has()) {
setSpaceNameTransform(settings().get<SvgSpaceNameTransform>().get());
}
if (settings().get<SvgSectionRef>().has()) {
setSectionRef(settings().get<SvgSectionRef>().get());
}
if (settings().get<SvgElevationRef>().has()) {
setElevationRef(settings().get<SvgElevationRef>().get());
}
if (settings().get<SvgElevationRefGuid>().has()) {
setElevationRefGuid(settings().get<SvgElevationRefGuid>().get());
}
}
void SvgSerializer::write(path_object& p, const TopoDS_Shape& comp_or_wire, std::optional<std::vector<double>> dash_array) { void SvgSerializer::write(path_object& p, const TopoDS_Shape& comp_or_wire, std::optional<std::vector<double>> dash_array) {
/* ShapeFix_Wire fix; /* ShapeFix_Wire fix;
Handle(ShapeExtend_WireData) data = new ShapeExtend_WireData; Handle(ShapeExtend_WireData) data = new ShapeExtend_WireData;
+4 -1
View File
@@ -589,6 +589,7 @@ protected:
Bnd_Box bnd_; Bnd_Box bnd_;
void draw_hlr(const gp_Pln& pln, const drawing_key& drawing_name); void draw_hlr(const gp_Pln& pln, const drawing_key& drawing_name);
void apply_settings();
subtract_before_project subtraction_settings_; subtract_before_project subtraction_settings_;
@@ -627,7 +628,9 @@ public:
, hlr(nullptr) , hlr(nullptr)
, namespace_prefix_("data-") , namespace_prefix_("data-")
, subtraction_settings_(ON_SLABS_AT_FLOORPLANS) , subtraction_settings_(ON_SLABS_AT_FLOORPLANS)
{} {
apply_settings();
}
void addXCoordinate(const boost::shared_ptr<util::string_buffer::float_item>& fi) { xcoords.push_back(fi); } void addXCoordinate(const boost::shared_ptr<util::string_buffer::float_item>& fi) { xcoords.push_back(fi); }
void addYCoordinate(const boost::shared_ptr<util::string_buffer::float_item>& fi) { ycoords.push_back(fi); } void addYCoordinate(const boost::shared_ptr<util::string_buffer::float_item>& fi) { ycoords.push_back(fi); }
void addSizeComponent(const boost::shared_ptr<util::string_buffer::float_item>& fi) { radii.push_back(fi); } void addSizeComponent(const boost::shared_ptr<util::string_buffer::float_item>& fi) { radii.push_back(fi); }
-33
View File
@@ -1,33 +0,0 @@
#include "XmlSerializer.h"
#include "document_serializer_plugin.h"
#include <boost/algorithm/string/case_conv.hpp>
XmlSerializerFactory::Factory::Factory() {
ifcopenshell::serializers::load_document_serializer_plugins(*this, "xml");
}
void XmlSerializerFactory::Factory::bind(const std::string& schema_name, fn f, const ifcopenshell::plugin::module& module) {
const std::string schema_name_lower = boost::to_lower_copy(schema_name);
entries_[schema_name_lower] = { f, module };
}
XmlSerializer* XmlSerializerFactory::Factory::construct(const std::string& schema_name, ifcopenshell::file* file, std::string xml_filename) {
const std::string schema_name_lower = boost::to_lower_copy(schema_name);
auto it = entries_.find(schema_name_lower);
if (it == entries_.end()) {
throw ifcopenshell::exception("No XML serializer registered for " + schema_name);
}
return it->second.fn_(file, xml_filename);
}
XmlSerializer::XmlSerializer(ifcopenshell::file* file, const std::string& xml_filename) {
if (file) {
implementation_ = XmlSerializerFactory::implementations().construct(file->schema()->name(), file, xml_filename);
}
}
XmlSerializerFactory::Factory& XmlSerializerFactory::implementations() {
static XmlSerializerFactory::Factory impl;
return impl;
}
+23 -28
View File
@@ -7,49 +7,44 @@
#include "../ifcgeom/Serializer.h" #include "../ifcgeom/Serializer.h"
#include "../ifcparse/file.h" #include "../ifcparse/file.h"
#include "../plugin/plugin.h" #include "../plugin/plugin.h"
#include "../serializers/document_serializer_plugin.h"
#include <boost/function.hpp> #include <boost/shared_ptr.hpp>
#include <map> class XmlSerializer : public Serializer {
class SERIALIZERS_API XmlSerializer : public Serializer {
private: private:
XmlSerializer* implementation_ = nullptr; boost::shared_ptr<Serializer> implementation_;
protected: protected:
std::string xml_filename; std::string xml_filename;
public: public:
XmlSerializer(ifcopenshell::file* file, const std::string& xml_filename); XmlSerializer(ifcopenshell::file* file, const std::string& xml_filename)
: xml_filename(xml_filename)
{
if (!file) {
return;
}
ifcopenshell::serializers::document_serializer_context context;
context.file = file;
context.output_filename = xml_filename;
context.schema_name = file->schema()->name();
implementation_ = ifcopenshell::serializers::document_serializer_registry_instance().create("xml", context);
}
virtual ~XmlSerializer() {} virtual ~XmlSerializer() {}
bool ready() { return true; } bool ready() { return true; }
void writeHeader() {} void writeHeader() {}
void finalize() { implementation_->finalize(); } void finalize() {
if (!implementation_) {
throw ifcopenshell::exception("No XML serializer implementation constructed");
}
implementation_->finalize();
}
void setFile(ifcopenshell::file*) { throw ifcopenshell::exception("Should be supplied on construction"); } void setFile(ifcopenshell::file*) { throw ifcopenshell::exception("Should be supplied on construction"); }
}; };
struct SERIALIZERS_API XmlSerializerFactory {
typedef boost::function2<XmlSerializer*, ifcopenshell::file*, std::string> fn;
class SERIALIZERS_API Factory {
public:
Factory();
void bind(const std::string& schema_name, fn, const ifcopenshell::plugin::module& module = ifcopenshell::plugin::module());
XmlSerializer* construct(const std::string& schema_name, ifcopenshell::file*, std::string);
private:
struct entry {
fn fn_;
ifcopenshell::plugin::module module_;
};
std::map<std::string, entry> entries_;
};
static Factory& implementations();
};
#endif #endif
+68
View File
@@ -0,0 +1,68 @@
/********************************************************************************
* *
* This file is part of IfcOpenShell. *
* *
* IfcOpenShell is free software: you can redistribute it and/or modify *
* it under the terms of the Lesser GNU General Public License as published by *
* the Free Software Foundation, either version 3.0 of the License, or *
* (at your option) any later version. *
* *
* IfcOpenShell is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* Lesser GNU General Public License for more details. *
* *
* You should have received a copy of the Lesser GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
#include "document_serializer_plugin.h"
#include "RocksDbSerializer.h"
#ifdef IFOPSH_WITH_ROCKSDB
#include <boost/dll/alias.hpp>
#include <boost/make_shared.hpp>
namespace {
boost::shared_ptr<Serializer> create_serializer(const ifcopenshell::serializers::document_serializer_context& context) {
if (!context.stream || context.input_filename.empty()) {
throw ifcopenshell::exception("RocksDB document serializer requires --stream input");
}
return boost::make_shared<RocksDbSerializer>(context.input_filename, context.output_filename, true);
}
}
namespace ifcopenshell {
namespace serializers {
namespace rdb_document_serializer_plugin {
plugin::abi_info plugin_abi() {
return plugin::host_abi();
}
plugin::metadata plugin_metadata() {
return document_serializer_plugin_metadata("rdb");
}
void register_plugin(document_serializer_registry& registry, const plugin::module& module) {
document_serializer_info info;
info.format = "rdb";
info.supports_ifc_file = false;
info.supports_input_filename = true;
info.writes_final_output = true;
registry.bind(info, create_serializer, module);
}
}
}
}
BOOST_DLL_ALIAS(ifcopenshell::serializers::rdb_document_serializer_plugin::plugin_abi, ifcopenshell_plugin_abi_v1)
BOOST_DLL_ALIAS(ifcopenshell::serializers::rdb_document_serializer_plugin::plugin_metadata, ifcopenshell_plugin_metadata_v1)
BOOST_DLL_ALIAS(ifcopenshell::serializers::rdb_document_serializer_plugin::register_plugin, ifcopenshell_register_document_serializer_plugin_v1)
#endif
+130 -27
View File
@@ -21,35 +21,117 @@
#include <boost/algorithm/string/case_conv.hpp> #include <boost/algorithm/string/case_conv.hpp>
#include "../ifcparse/logger.h"
#include <mutex>
#include <set>
namespace { namespace {
std::string document_serializer_plugin_prefix(const std::string& format) { std::string document_serializer_key(const std::string& format) {
return "document." + boost::to_lower_copy(format) + "."; if (format.empty()) {
return format;
}
auto key = boost::to_lower_copy(format);
if (key.front() == '.') {
key.erase(key.begin());
}
return key;
} }
template <typename registry_t, typename register_plugin_t> std::string document_serializer_schema_key(const std::string& schema_name) {
void load_document_serializer_plugins_impl(registry_t& registry, const std::string& format) { return boost::to_upper_copy(schema_name);
ifcopenshell::plugin::manager manager; }
manager.add_search_path(ifcopenshell::serializers::document_serializer_plugin_directory());
const auto format_lower = boost::to_lower_copy(format); std::string document_serializer_plugin_prefix(const std::string& format = std::string()) {
const auto prefix = document_serializer_plugin_prefix(format_lower); const auto format_key = document_serializer_key(format);
for (const auto& path : manager.discover(prefix)) { return format_key.empty() ? "document." : "document." + format_key;
auto module = manager.load(path); }
if (module.meta().kind_ != ifcopenshell::plugin::kind::document_serializer) {
continue;
}
if (boost::to_lower_copy(module.meta().format) != format_lower) {
continue;
}
auto register_plugin = module.get_alias<register_plugin_t>(ifcopenshell::serializers::document_serializer_plugin_registration_symbol()); void add_document_serializer_search_paths(ifcopenshell::plugin::manager& manager) {
register_plugin(registry, module); const auto directory = ifcopenshell::serializers::document_serializer_plugin_directory();
manager.add_search_path(directory);
const auto sibling_directory = directory.parent_path().parent_path() / "serializers" / directory.filename();
if (sibling_directory != directory && std::filesystem::exists(sibling_directory)) {
manager.add_search_path(sibling_directory);
} }
} }
} }
void ifcopenshell::serializers::document_serializer_registry::bind(const document_serializer_info& info, create_fn create, const plugin::module& module) {
entry entry;
entry.info_ = info;
entry.info_.format = document_serializer_key(entry.info_.format);
entry.info_.schema_name = document_serializer_schema_key(entry.info_.schema_name);
entry.create_ = create;
entry.module_ = module.meta().id.empty() ? plugin::module(document_serializer_plugin_metadata(entry.info_.format, entry.info_.schema_name)) : module;
entries_[entry.info_.format].push_back(entry);
}
const ifcopenshell::serializers::document_serializer_registry::entry* ifcopenshell::serializers::document_serializer_registry::find_entry_(const std::string& format, const std::string& schema_name) const {
const auto format_key = document_serializer_key(format);
const auto iter = entries_.find(format_key);
if (iter == entries_.end()) {
return nullptr;
}
const auto schema_key = document_serializer_schema_key(schema_name);
const entry* fallback = nullptr;
for (const auto& candidate : iter->second) {
if (candidate.info_.schema_name.empty()) {
if (!fallback) {
fallback = &candidate;
}
continue;
}
if (!schema_key.empty() && candidate.info_.schema_name == schema_key) {
return &candidate;
}
if (schema_key.empty() && !fallback) {
fallback = &candidate;
}
}
return fallback;
}
const ifcopenshell::serializers::document_serializer_info* ifcopenshell::serializers::document_serializer_registry::find(const std::string& format, const std::string& schema_name) const {
const auto* entry = find_entry_(format, schema_name);
return entry ? &entry->info_ : nullptr;
}
boost::shared_ptr<Serializer> ifcopenshell::serializers::document_serializer_registry::create(const std::string& format, const document_serializer_context& context) const {
const auto schema_name = !context.schema_name.empty() ? context.schema_name :
(context.file ? context.file->schema()->name() : std::string());
const auto* entry = find_entry_(format, schema_name);
if (!entry) {
throw ifcopenshell::exception("No document serializer registered for " + format + (schema_name.empty() ? std::string() : " and schema " + schema_name));
}
return entry->create_(context);
}
std::vector<ifcopenshell::serializers::document_serializer_info> ifcopenshell::serializers::document_serializer_registry::serializers() const {
std::vector<document_serializer_info> result;
std::set<std::string> seen;
for (const auto& pair : entries_) {
for (const auto& entry : pair.second) {
const auto key = entry.info_.format + "|" + entry.info_.schema_name;
if (!seen.insert(key).second) {
continue;
}
result.push_back(entry.info_);
}
}
return result;
}
const char* ifcopenshell::serializers::document_serializer_plugin_registration_symbol() { const char* ifcopenshell::serializers::document_serializer_plugin_registration_symbol() {
return "ifcopenshell_register_document_serializer_plugin_v1"; return "ifcopenshell_register_document_serializer_plugin_v1";
} }
@@ -57,9 +139,12 @@ const char* ifcopenshell::serializers::document_serializer_plugin_registration_s
ifcopenshell::plugin::metadata ifcopenshell::serializers::document_serializer_plugin_metadata(const std::string& format, const std::string& schema_name) { ifcopenshell::plugin::metadata ifcopenshell::serializers::document_serializer_plugin_metadata(const std::string& format, const std::string& schema_name) {
plugin::metadata metadata; plugin::metadata metadata;
metadata.kind_ = plugin::kind::document_serializer; metadata.kind_ = plugin::kind::document_serializer;
metadata.id = document_serializer_plugin_prefix(format) + boost::to_lower_copy(schema_name); metadata.id = document_serializer_plugin_prefix(format);
metadata.schema = boost::to_upper_copy(schema_name); if (!schema_name.empty()) {
metadata.format = boost::to_lower_copy(format); metadata.id += "." + boost::to_lower_copy(schema_name);
}
metadata.schema = document_serializer_schema_key(schema_name);
metadata.format = document_serializer_key(format);
return metadata; return metadata;
} }
@@ -67,12 +152,30 @@ std::filesystem::path ifcopenshell::serializers::document_serializer_plugin_dire
return plugin::module_directory(reinterpret_cast<const void*>(&ifcopenshell::serializers::document_serializer_plugin_directory)); return plugin::module_directory(reinterpret_cast<const void*>(&ifcopenshell::serializers::document_serializer_plugin_directory));
} }
void ifcopenshell::serializers::load_document_serializer_plugins(XmlSerializerFactory::Factory& registry, const std::string& format) { void ifcopenshell::serializers::load_document_serializer_plugins(document_serializer_registry& registry) {
load_document_serializer_plugins_impl<XmlSerializerFactory::Factory, register_xml_document_serializer_plugin_fn>(registry, format); ifcopenshell::plugin::manager manager;
add_document_serializer_search_paths(manager);
for (const auto& path : manager.discover(document_serializer_plugin_prefix())) {
ifcopenshell::plugin::module module;
try {
module = manager.load(path);
} catch (const std::exception& e) {
logger::error(e);
continue;
}
if (module.meta().kind_ != ifcopenshell::plugin::kind::document_serializer) {
continue;
}
auto register_plugin = module.get_alias<register_document_serializer_plugin_fn>(document_serializer_plugin_registration_symbol());
register_plugin(registry, module);
}
} }
#ifdef WITH_GLTF ifcopenshell::serializers::document_serializer_registry& ifcopenshell::serializers::document_serializer_registry_instance() {
void ifcopenshell::serializers::load_document_serializer_plugins(JsonSerializerFactory::Factory& registry, const std::string& format) { static document_serializer_registry registry;
load_document_serializer_plugins_impl<JsonSerializerFactory::Factory, register_json_document_serializer_plugin_fn>(registry, format); static std::once_flag once;
std::call_once(once, load_document_serializer_plugins, std::ref(registry));
return registry;
} }
#endif
+50 -13
View File
@@ -20,30 +20,67 @@
#ifndef IFCOPENSHELL_DOCUMENT_SERIALIZER_PLUGIN_H #ifndef IFCOPENSHELL_DOCUMENT_SERIALIZER_PLUGIN_H
#define IFCOPENSHELL_DOCUMENT_SERIALIZER_PLUGIN_H #define IFCOPENSHELL_DOCUMENT_SERIALIZER_PLUGIN_H
#include "XmlSerializer.h" #include "../serializers/serializers_api.h"
#include "../ifcgeom/Serializer.h"
#include "../ifcparse/file.h"
#include "../plugin/plugin.h"
#ifdef WITH_GLTF #include <boost/function.hpp>
#include "JsonSerializer.h" #include <boost/shared_ptr.hpp>
#endif
#include <filesystem> #include <filesystem>
#include <map>
#include <string> #include <string>
#include <vector>
namespace ifcopenshell { namespace ifcopenshell {
namespace serializers { namespace serializers {
typedef void register_xml_document_serializer_plugin_fn(XmlSerializerFactory::Factory&, const ifcopenshell::plugin::module&); struct SERIALIZERS_API document_serializer_info {
std::string format;
std::string schema_name;
bool supports_ifc_file = true;
bool supports_input_filename = false;
bool writes_final_output = false;
};
struct SERIALIZERS_API document_serializer_context {
ifcopenshell::file* file = nullptr;
std::string input_filename;
std::string output_filename;
std::string schema_name;
bool stream = false;
int dialect = 0;
};
class SERIALIZERS_API document_serializer_registry {
public:
typedef boost::function<boost::shared_ptr<Serializer>(const document_serializer_context&)> create_fn;
void bind(const document_serializer_info& info, create_fn create, const ifcopenshell::plugin::module& module = ifcopenshell::plugin::module());
const document_serializer_info* find(const std::string& format, const std::string& schema_name = std::string()) const;
boost::shared_ptr<Serializer> create(const std::string& format, const document_serializer_context& context) const;
std::vector<document_serializer_info> serializers() const;
private:
struct entry {
document_serializer_info info_;
create_fn create_;
ifcopenshell::plugin::module module_;
};
const entry* find_entry_(const std::string& format, const std::string& schema_name) const;
std::map<std::string, std::vector<entry>> entries_;
};
typedef void register_document_serializer_plugin_fn(document_serializer_registry&, const ifcopenshell::plugin::module&);
SERIALIZERS_API const char* document_serializer_plugin_registration_symbol(); SERIALIZERS_API const char* document_serializer_plugin_registration_symbol();
SERIALIZERS_API ifcopenshell::plugin::metadata document_serializer_plugin_metadata(const std::string& format, const std::string& schema_name); SERIALIZERS_API ifcopenshell::plugin::metadata document_serializer_plugin_metadata(const std::string& format, const std::string& schema_name = std::string());
SERIALIZERS_API std::filesystem::path document_serializer_plugin_directory(); SERIALIZERS_API std::filesystem::path document_serializer_plugin_directory();
SERIALIZERS_API void load_document_serializer_plugins(XmlSerializerFactory::Factory& registry, const std::string& format); SERIALIZERS_API void load_document_serializer_plugins(document_serializer_registry& registry);
SERIALIZERS_API document_serializer_registry& document_serializer_registry_instance();
#ifdef WITH_GLTF
typedef void register_json_document_serializer_plugin_fn(JsonSerializerFactory::Factory&, const ifcopenshell::plugin::module&);
SERIALIZERS_API void load_document_serializer_plugins(JsonSerializerFactory::Factory& registry, const std::string& format);
#endif
} }
} }
+62
View File
@@ -0,0 +1,62 @@
/********************************************************************************
* *
* This file is part of IfcOpenShell. *
* *
* IfcOpenShell is free software: you can redistribute it and/or modify *
* it under the terms of the Lesser GNU General Public License as published by *
* the Free Software Foundation, either version 3.0 of the License, or *
* (at your option) any later version. *
* *
* IfcOpenShell is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* Lesser GNU General Public License for more details. *
* *
* You should have received a copy of the Lesser GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
#ifdef WITH_OPENCOLLADA
#include "ColladaSerializer.h"
#include "geometry_serializer_plugin.h"
#include <boost/dll/alias.hpp>
#include <boost/make_shared.hpp>
namespace ifcopenshell {
namespace serializers {
namespace geometry_dae_plugin {
plugin::abi_info plugin_abi() {
return plugin::host_abi();
}
plugin::metadata plugin_metadata() {
return geometry_serializer_plugin_metadata("dae");
}
boost::shared_ptr<GeometrySerializer> create_serializer(const geometry_serializer_context& context) {
return boost::make_shared<ColladaSerializer>(context.output_temp_filename, context.geometry_settings, context.serializer_settings);
}
void register_plugin(geometry_serializer_registry& registry, const plugin::module& module) {
geometry_serializer_info info;
info.format = "dae";
info.extensions = { ".dae" };
info.supports_triangulation = true;
info.supports_user_element_hierarchy = true;
info.requires_ascii_temp_file = true;
registry.bind(info, create_serializer, geometry_serializer_registry::configure_fn(), module);
}
}
}
}
BOOST_DLL_ALIAS(ifcopenshell::serializers::geometry_dae_plugin::plugin_abi, ifcopenshell_plugin_abi_v1)
BOOST_DLL_ALIAS(ifcopenshell::serializers::geometry_dae_plugin::plugin_metadata, ifcopenshell_plugin_metadata_v1)
BOOST_DLL_ALIAS(ifcopenshell::serializers::geometry_dae_plugin::register_plugin, ifcopenshell_register_geometry_serializer_plugin_v1)
#endif
+61
View File
@@ -0,0 +1,61 @@
/********************************************************************************
* *
* This file is part of IfcOpenShell. *
* *
* IfcOpenShell is free software: you can redistribute it and/or modify *
* it under the terms of the Lesser GNU General Public License as published by *
* the Free Software Foundation, either version 3.0 of the License, or *
* (at your option) any later version. *
* *
* IfcOpenShell is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* Lesser GNU General Public License for more details. *
* *
* You should have received a copy of the Lesser GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
#ifdef WITH_GLTF
#include "geometry_serializer_plugin.h"
#include "GltfSerializer.h"
#include <boost/dll/alias.hpp>
#include <boost/make_shared.hpp>
namespace ifcopenshell {
namespace serializers {
namespace geometry_glb_plugin {
plugin::abi_info plugin_abi() {
return plugin::host_abi();
}
plugin::metadata plugin_metadata() {
return geometry_serializer_plugin_metadata("glb");
}
boost::shared_ptr<GeometrySerializer> create_serializer(const geometry_serializer_context& context) {
return boost::make_shared<GltfSerializer>(context.output_temp_filename, context.geometry_settings, context.serializer_settings);
}
void register_plugin(geometry_serializer_registry& registry, const plugin::module& module) {
geometry_serializer_info info;
info.format = "glb";
info.extensions = { ".glb" };
info.supports_triangulation = true;
info.supports_user_element_hierarchy = true;
registry.bind(info, create_serializer, geometry_serializer_registry::configure_fn(), module);
}
}
}
}
BOOST_DLL_ALIAS(ifcopenshell::serializers::geometry_glb_plugin::plugin_abi, ifcopenshell_plugin_abi_v1)
BOOST_DLL_ALIAS(ifcopenshell::serializers::geometry_glb_plugin::plugin_metadata, ifcopenshell_plugin_metadata_v1)
BOOST_DLL_ALIAS(ifcopenshell::serializers::geometry_glb_plugin::register_plugin, ifcopenshell_register_geometry_serializer_plugin_v1)
#endif
+66
View File
@@ -0,0 +1,66 @@
/********************************************************************************
* *
* This file is part of IfcOpenShell. *
* *
* IfcOpenShell is free software: you can redistribute it and/or modify *
* it under the terms of the Lesser GNU General Public License as published by *
* the Free Software Foundation, either version 3.0 of the License, or *
* (at your option) any later version. *
* *
* IfcOpenShell is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* Lesser GNU General Public License for more details. *
* *
* You should have received a copy of the Lesser GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
#if defined(WITH_HDF5) && defined(IFOPSH_WITH_OPENCASCADE)
#include "geometry_serializer_plugin.h"
#include "HdfSerializer.h"
#include <boost/dll/alias.hpp>
#include <boost/make_shared.hpp>
namespace ifcopenshell {
namespace serializers {
namespace geometry_hdf_plugin {
plugin::abi_info plugin_abi() {
return plugin::host_abi();
}
plugin::metadata plugin_metadata() {
return geometry_serializer_plugin_metadata("hdf");
}
boost::shared_ptr<GeometrySerializer> create_serializer(const geometry_serializer_context& context) {
return boost::make_shared<HdfSerializer>(context.output_temp_filename, context.geometry_settings, context.serializer_settings);
}
void configure_serializer(geometry_serializer_context& context) {
context.geometry_settings.get<ifcopenshell::geometry::settings::IteratorOutput>().value = ifcopenshell::geometry::settings::NATIVE;
}
void register_plugin(geometry_serializer_registry& registry, const plugin::module& module) {
geometry_serializer_info info;
info.format = "hdf";
info.extensions = { ".h5" };
info.kernel_ids = { "opencascade" };
info.supports_triangulation = true;
info.supports_brep = true;
registry.bind(info, create_serializer, configure_serializer, module);
}
}
}
}
BOOST_DLL_ALIAS(ifcopenshell::serializers::geometry_hdf_plugin::plugin_abi, ifcopenshell_plugin_abi_v1)
BOOST_DLL_ALIAS(ifcopenshell::serializers::geometry_hdf_plugin::plugin_metadata, ifcopenshell_plugin_metadata_v1)
BOOST_DLL_ALIAS(ifcopenshell::serializers::geometry_hdf_plugin::register_plugin, ifcopenshell_register_geometry_serializer_plugin_v1)
#endif
+76
View File
@@ -0,0 +1,76 @@
/********************************************************************************
* *
* This file is part of IfcOpenShell. *
* *
* IfcOpenShell is free software: you can redistribute it and/or modify *
* it under the terms of the Lesser GNU General Public License as published by *
* the Free Software Foundation, either version 3.0 of the License, or *
* (at your option) any later version. *
* *
* IfcOpenShell is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* Lesser GNU General Public License for more details. *
* *
* You should have received a copy of the Lesser GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
#ifdef IFOPSH_WITH_OPENCASCADE
#include "geometry_serializer_plugin.h"
#include "IgesSerializer.h"
#include <boost/dll/alias.hpp>
#include <boost/make_shared.hpp>
#include <Standard_Version.hxx>
#if OCC_VERSION_HEX < 0x60900
#include <IGESControl_Controller.hxx>
#endif
namespace ifcopenshell {
namespace serializers {
namespace geometry_igs_plugin {
plugin::abi_info plugin_abi() {
return plugin::host_abi();
}
plugin::metadata plugin_metadata() {
return geometry_serializer_plugin_metadata("igs");
}
boost::shared_ptr<GeometrySerializer> create_serializer(const geometry_serializer_context& context) {
#if OCC_VERSION_HEX < 0x60900
IGESControl_Controller::Init();
#endif
return boost::make_shared<IgesSerializer>(context.output_temp_filename, context.geometry_settings, context.serializer_settings);
}
void configure_serializer(geometry_serializer_context& context) {
context.geometry_settings.get<ifcopenshell::geometry::settings::UseWorldCoords>().value = true;
context.geometry_settings.get<ifcopenshell::geometry::settings::IteratorOutput>().value = ifcopenshell::geometry::settings::NATIVE;
}
void register_plugin(geometry_serializer_registry& registry, const plugin::module& module) {
geometry_serializer_info info;
info.format = "igs";
info.extensions = { ".igs" };
info.kernel_ids = { "opencascade" };
info.supports_brep = true;
info.requires_ascii_temp_file = true;
registry.bind(info, create_serializer, configure_serializer, module);
}
}
}
}
BOOST_DLL_ALIAS(ifcopenshell::serializers::geometry_igs_plugin::plugin_abi, ifcopenshell_plugin_abi_v1)
BOOST_DLL_ALIAS(ifcopenshell::serializers::geometry_igs_plugin::plugin_metadata, ifcopenshell_plugin_metadata_v1)
BOOST_DLL_ALIAS(ifcopenshell::serializers::geometry_igs_plugin::register_plugin, ifcopenshell_register_geometry_serializer_plugin_v1)
#endif
+74
View File
@@ -0,0 +1,74 @@
/********************************************************************************
* *
* This file is part of IfcOpenShell. *
* *
* IfcOpenShell is free software: you can redistribute it and/or modify *
* it under the terms of the Lesser GNU General Public License as published by *
* the Free Software Foundation, either version 3.0 of the License, or *
* (at your option) any later version. *
* *
* IfcOpenShell is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* Lesser GNU General Public License for more details. *
* *
* You should have received a copy of the Lesser GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
#include "geometry_serializer_plugin.h"
#include "WavefrontObjSerializer.h"
#include "../ifcparse/utils.h"
#include <boost/dll/alias.hpp>
#include <boost/make_shared.hpp>
#include <filesystem>
namespace {
std::string obj_mtl_filename(const std::string& output_filename) {
std::filesystem::path path(ifcopenshell::path::from_utf8(output_filename));
path.replace_extension(ifcopenshell::path::from_utf8(".mtl"));
return ifcopenshell::path::to_utf8(path.native());
}
}
namespace ifcopenshell {
namespace serializers {
namespace geometry_obj_plugin {
plugin::abi_info plugin_abi() {
return plugin::host_abi();
}
plugin::metadata plugin_metadata() {
return geometry_serializer_plugin_metadata("obj");
}
boost::shared_ptr<GeometrySerializer> create_serializer(const geometry_serializer_context& context) {
return boost::make_shared<WaveFrontOBJSerializer>(context.output_temp_filename, obj_mtl_filename(context.output_filename), context.geometry_settings, context.serializer_settings);
}
void configure_serializer(geometry_serializer_context& context) {
context.geometry_settings.get<ifcopenshell::geometry::settings::UseWorldCoords>().value = true;
}
void register_plugin(geometry_serializer_registry& registry, const plugin::module& module) {
geometry_serializer_info info;
info.format = "obj";
info.extensions = { ".obj" };
info.supports_triangulation = true;
registry.bind(info, create_serializer, configure_serializer, module);
}
}
}
}
BOOST_DLL_ALIAS(ifcopenshell::serializers::geometry_obj_plugin::plugin_abi, ifcopenshell_plugin_abi_v1)
BOOST_DLL_ALIAS(ifcopenshell::serializers::geometry_obj_plugin::plugin_metadata, ifcopenshell_plugin_metadata_v1)
BOOST_DLL_ALIAS(ifcopenshell::serializers::geometry_obj_plugin::register_plugin, ifcopenshell_register_geometry_serializer_plugin_v1)
@@ -0,0 +1,160 @@
/********************************************************************************
* *
* This file is part of IfcOpenShell. *
* *
* IfcOpenShell is free software: you can redistribute it and/or modify *
* it under the terms of the Lesser GNU General Public License as published by *
* the Free Software Foundation, either version 3.0 of the License, or *
* (at your option) any later version. *
* *
* IfcOpenShell is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* Lesser GNU General Public License for more details. *
* *
* You should have received a copy of the Lesser GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
#include "geometry_serializer_plugin.h"
#include <boost/algorithm/string/case_conv.hpp>
#include <mutex>
#include <set>
namespace {
std::string geometry_serializer_plugin_prefix(const std::string& format = std::string()) {
const auto format_lower = boost::to_lower_copy(format);
return format_lower.empty() ? "geometry." : "geometry." + format_lower;
}
std::string geometry_serializer_key(const std::string& extension) {
if (extension.empty()) {
return extension;
}
auto key = boost::to_lower_copy(extension);
if (key.front() != '.') {
key.insert(key.begin(), '.');
}
return key;
}
void add_geometry_serializer_search_paths(ifcopenshell::plugin::manager& manager) {
const auto directory = ifcopenshell::serializers::geometry_serializer_plugin_directory();
manager.add_search_path(directory);
const auto sibling_directory = directory.parent_path().parent_path() / "serializers" / directory.filename();
if (sibling_directory != directory && std::filesystem::exists(sibling_directory)) {
manager.add_search_path(sibling_directory);
}
}
}
void ifcopenshell::serializers::geometry_serializer_registry::bind(const geometry_serializer_info& info, create_fn create, configure_fn configure, const plugin::module& module) {
entry entry;
entry.info_ = info;
entry.info_.format = boost::to_lower_copy(entry.info_.format);
entry.create_ = create;
entry.configure_ = configure;
entry.module_ = module.meta().id.empty() ? plugin::module(geometry_serializer_plugin_metadata(entry.info_.format)) : module;
if (entry.info_.extensions.empty() && !entry.info_.format.empty()) {
entry.info_.extensions.push_back("." + entry.info_.format);
}
for (auto& extension : entry.info_.extensions) {
extension = geometry_serializer_key(extension);
entries_[extension] = entry;
}
}
bool ifcopenshell::serializers::geometry_serializer_registry::has(const std::string& extension) const {
return entries_.find(geometry_serializer_key(extension)) != entries_.end();
}
const ifcopenshell::serializers::geometry_serializer_info* ifcopenshell::serializers::geometry_serializer_registry::find(const std::string& extension) const {
const auto iter = entries_.find(geometry_serializer_key(extension));
if (iter == entries_.end()) {
return nullptr;
}
return &iter->second.info_;
}
void ifcopenshell::serializers::geometry_serializer_registry::configure(const std::string& extension, geometry_serializer_context& context) const {
const auto iter = entries_.find(geometry_serializer_key(extension));
if (iter == entries_.end()) {
throw ifcopenshell::exception("No geometry serializer registered for " + extension);
}
if (iter->second.configure_) {
iter->second.configure_(context);
}
}
boost::shared_ptr<GeometrySerializer> ifcopenshell::serializers::geometry_serializer_registry::create(const std::string& extension, const geometry_serializer_context& context) const {
const auto iter = entries_.find(geometry_serializer_key(extension));
if (iter == entries_.end()) {
throw ifcopenshell::exception("No geometry serializer registered for " + extension);
}
return iter->second.create_(context);
}
std::vector<ifcopenshell::serializers::geometry_serializer_info> ifcopenshell::serializers::geometry_serializer_registry::serializers() const {
std::vector<geometry_serializer_info> result;
std::set<std::string> seen_formats;
for (const auto& pair : entries_) {
if (!seen_formats.insert(pair.second.info_.format).second) {
continue;
}
result.push_back(pair.second.info_);
}
return result;
}
const char* ifcopenshell::serializers::geometry_serializer_plugin_registration_symbol() {
return "ifcopenshell_register_geometry_serializer_plugin_v1";
}
ifcopenshell::plugin::metadata ifcopenshell::serializers::geometry_serializer_plugin_metadata(const std::string& format) {
plugin::metadata metadata;
metadata.kind_ = plugin::kind::geometry_serializer;
metadata.id = geometry_serializer_plugin_prefix(format);
metadata.format = boost::to_lower_copy(format);
return metadata;
}
std::filesystem::path ifcopenshell::serializers::geometry_serializer_plugin_directory() {
return plugin::module_directory(reinterpret_cast<const void*>(&ifcopenshell::serializers::geometry_serializer_plugin_directory));
}
void ifcopenshell::serializers::load_geometry_serializer_plugins(geometry_serializer_registry& registry) {
ifcopenshell::plugin::manager manager;
add_geometry_serializer_search_paths(manager);
for (const auto& path : manager.discover(geometry_serializer_plugin_prefix())) {
ifcopenshell::plugin::module module;
try {
module = manager.load(path);
} catch (const std::exception& e) {
logger::error(e);
continue;
}
if (module.meta().kind_ != ifcopenshell::plugin::kind::geometry_serializer) {
continue;
}
auto register_plugin = module.get_alias<register_geometry_serializer_plugin_fn>(geometry_serializer_plugin_registration_symbol());
register_plugin(registry, module);
}
}
ifcopenshell::serializers::geometry_serializer_registry& ifcopenshell::serializers::geometry_serializer_registry_instance() {
static geometry_serializer_registry registry;
static std::once_flag once;
std::call_once(once, load_geometry_serializer_plugins, std::ref(registry));
return registry;
}
@@ -0,0 +1,91 @@
/********************************************************************************
* *
* This file is part of IfcOpenShell. *
* *
* IfcOpenShell is free software: you can redistribute it and/or modify *
* it under the terms of the Lesser GNU General Public License as published by *
* the Free Software Foundation, either version 3.0 of the License, or *
* (at your option) any later version. *
* *
* IfcOpenShell is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* Lesser GNU General Public License for more details. *
* *
* You should have received a copy of the Lesser GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
#ifndef IFCOPENSHELL_GEOMETRY_SERIALIZER_PLUGIN_H
#define IFCOPENSHELL_GEOMETRY_SERIALIZER_PLUGIN_H
#include "../serializers/serializers_api.h"
#include "../ifcgeom/GeometrySerializer.h"
#include "../plugin/plugin.h"
#include <boost/function.hpp>
#include <boost/shared_ptr.hpp>
#include <filesystem>
#include <map>
#include <string>
#include <vector>
namespace ifcopenshell {
namespace serializers {
struct SERIALIZERS_API geometry_serializer_info {
std::string format;
std::vector<std::string> extensions;
std::vector<std::string> kernel_ids;
bool supports_triangulation = false;
bool supports_brep = false;
bool supports_user_element_hierarchy = false;
bool bypass_properties = true;
bool requires_ascii_temp_file = false;
bool writes_final_output = false;
};
struct SERIALIZERS_API geometry_serializer_context {
std::string output_filename;
std::string output_temp_filename;
ifcopenshell::geometry::Settings& geometry_settings;
const ifcopenshell::geometry::SerializerSettings& serializer_settings;
};
class SERIALIZERS_API geometry_serializer_registry {
public:
typedef boost::function<boost::shared_ptr<GeometrySerializer>(const geometry_serializer_context&)> create_fn;
typedef boost::function<void(geometry_serializer_context&)> configure_fn;
void bind(const geometry_serializer_info& info, create_fn create, configure_fn configure = configure_fn(), const ifcopenshell::plugin::module& module = ifcopenshell::plugin::module());
bool has(const std::string& extension) const;
const geometry_serializer_info* find(const std::string& extension) const;
void configure(const std::string& extension, geometry_serializer_context& context) const;
boost::shared_ptr<GeometrySerializer> create(const std::string& extension, const geometry_serializer_context& context) const;
std::vector<geometry_serializer_info> serializers() const;
private:
struct entry {
geometry_serializer_info info_;
create_fn create_;
configure_fn configure_;
ifcopenshell::plugin::module module_;
};
std::map<std::string, entry> entries_;
};
typedef void register_geometry_serializer_plugin_fn(geometry_serializer_registry&, const ifcopenshell::plugin::module&);
SERIALIZERS_API const char* geometry_serializer_plugin_registration_symbol();
SERIALIZERS_API ifcopenshell::plugin::metadata geometry_serializer_plugin_metadata(const std::string& format);
SERIALIZERS_API std::filesystem::path geometry_serializer_plugin_directory();
SERIALIZERS_API void load_geometry_serializer_plugins(geometry_serializer_registry& registry);
SERIALIZERS_API geometry_serializer_registry& geometry_serializer_registry_instance();
}
}
#endif
+67
View File
@@ -0,0 +1,67 @@
/********************************************************************************
* *
* This file is part of IfcOpenShell. *
* *
* IfcOpenShell is free software: you can redistribute it and/or modify *
* it under the terms of the Lesser GNU General Public License as published by *
* the Free Software Foundation, either version 3.0 of the License, or *
* (at your option) any later version. *
* *
* IfcOpenShell is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* Lesser GNU General Public License for more details. *
* *
* You should have received a copy of the Lesser GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
#ifdef IFOPSH_WITH_OPENCASCADE
#include "geometry_serializer_plugin.h"
#include "StepSerializer.h"
#include <boost/dll/alias.hpp>
#include <boost/make_shared.hpp>
namespace ifcopenshell {
namespace serializers {
namespace geometry_stp_plugin {
plugin::abi_info plugin_abi() {
return plugin::host_abi();
}
plugin::metadata plugin_metadata() {
return geometry_serializer_plugin_metadata("stp");
}
boost::shared_ptr<GeometrySerializer> create_serializer(const geometry_serializer_context& context) {
return boost::make_shared<StepSerializer>(context.output_temp_filename, context.geometry_settings, context.serializer_settings);
}
void configure_serializer(geometry_serializer_context& context) {
context.geometry_settings.get<ifcopenshell::geometry::settings::UseWorldCoords>().value = true;
context.geometry_settings.get<ifcopenshell::geometry::settings::IteratorOutput>().value = ifcopenshell::geometry::settings::NATIVE;
}
void register_plugin(geometry_serializer_registry& registry, const plugin::module& module) {
geometry_serializer_info info;
info.format = "stp";
info.extensions = { ".stp" };
info.kernel_ids = { "opencascade" };
info.supports_brep = true;
info.requires_ascii_temp_file = true;
registry.bind(info, create_serializer, configure_serializer, module);
}
}
}
}
BOOST_DLL_ALIAS(ifcopenshell::serializers::geometry_stp_plugin::plugin_abi, ifcopenshell_plugin_abi_v1)
BOOST_DLL_ALIAS(ifcopenshell::serializers::geometry_stp_plugin::plugin_metadata, ifcopenshell_plugin_metadata_v1)
BOOST_DLL_ALIAS(ifcopenshell::serializers::geometry_stp_plugin::register_plugin, ifcopenshell_register_geometry_serializer_plugin_v1)
#endif
+67
View File
@@ -0,0 +1,67 @@
/********************************************************************************
* *
* This file is part of IfcOpenShell. *
* *
* IfcOpenShell is free software: you can redistribute it and/or modify *
* it under the terms of the Lesser GNU General Public License as published by *
* the Free Software Foundation, either version 3.0 of the License, or *
* (at your option) any later version. *
* *
* IfcOpenShell is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* Lesser GNU General Public License for more details. *
* *
* You should have received a copy of the Lesser GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
#ifdef IFOPSH_WITH_OPENCASCADE
#include "geometry_serializer_plugin.h"
#include "SvgSerializer.h"
#include <boost/dll/alias.hpp>
#include <boost/make_shared.hpp>
namespace ifcopenshell {
namespace serializers {
namespace geometry_svg_plugin {
plugin::abi_info plugin_abi() {
return plugin::host_abi();
}
plugin::metadata plugin_metadata() {
return geometry_serializer_plugin_metadata("svg");
}
boost::shared_ptr<GeometrySerializer> create_serializer(const geometry_serializer_context& context) {
return boost::make_shared<SvgSerializer>(context.output_temp_filename, context.geometry_settings, context.serializer_settings);
}
void configure_serializer(geometry_serializer_context& context) {
context.geometry_settings.get<ifcopenshell::geometry::settings::UseElementHierarchy>().value = true;
context.geometry_settings.get<ifcopenshell::geometry::settings::IteratorOutput>().value = ifcopenshell::geometry::settings::NATIVE;
}
void register_plugin(geometry_serializer_registry& registry, const plugin::module& module) {
geometry_serializer_info info;
info.format = "svg";
info.extensions = { ".svg" };
info.kernel_ids = { "opencascade" };
info.supports_brep = true;
info.bypass_properties = false;
registry.bind(info, create_serializer, configure_serializer, module);
}
}
}
}
BOOST_DLL_ALIAS(ifcopenshell::serializers::geometry_svg_plugin::plugin_abi, ifcopenshell_plugin_abi_v1)
BOOST_DLL_ALIAS(ifcopenshell::serializers::geometry_svg_plugin::plugin_metadata, ifcopenshell_plugin_metadata_v1)
BOOST_DLL_ALIAS(ifcopenshell::serializers::geometry_svg_plugin::register_plugin, ifcopenshell_register_geometry_serializer_plugin_v1)
#endif
+64
View File
@@ -0,0 +1,64 @@
/********************************************************************************
* *
* This file is part of IfcOpenShell. *
* *
* IfcOpenShell is free software: you can redistribute it and/or modify *
* it under the terms of the Lesser GNU General Public License as published by *
* the Free Software Foundation, either version 3.0 of the License, or *
* (at your option) any later version. *
* *
* IfcOpenShell is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* Lesser GNU General Public License for more details. *
* *
* You should have received a copy of the Lesser GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
#include "geometry_serializer_plugin.h"
#include "TtlWktSerializer.h"
#include <boost/dll/alias.hpp>
#include <boost/make_shared.hpp>
namespace ifcopenshell {
namespace serializers {
namespace geometry_ttl_plugin {
plugin::abi_info plugin_abi() {
return plugin::host_abi();
}
plugin::metadata plugin_metadata() {
return geometry_serializer_plugin_metadata("ttl");
}
boost::shared_ptr<GeometrySerializer> create_serializer(const geometry_serializer_context& context) {
return boost::make_shared<TtlWktSerializer>(context.output_temp_filename, context.geometry_settings, context.serializer_settings);
}
void configure_serializer(geometry_serializer_context& context) {
context.geometry_settings.get<ifcopenshell::geometry::settings::TriangulationType>().value = ifcopenshell::geometry::settings::POLYHEDRON_WITH_HOLES;
if (context.serializer_settings.get<ifcopenshell::geometry::settings::WktUseSection>().get()) {
context.geometry_settings.get<ifcopenshell::geometry::settings::IteratorOutput>().value = ifcopenshell::geometry::settings::NATIVE;
}
}
void register_plugin(geometry_serializer_registry& registry, const plugin::module& module) {
geometry_serializer_info info;
info.format = "ttl";
info.extensions = { ".ttl" };
info.supports_triangulation = true;
info.supports_brep = true;
registry.bind(info, create_serializer, configure_serializer, module);
}
}
}
}
BOOST_DLL_ALIAS(ifcopenshell::serializers::geometry_ttl_plugin::plugin_abi, ifcopenshell_plugin_abi_v1)
BOOST_DLL_ALIAS(ifcopenshell::serializers::geometry_ttl_plugin::plugin_metadata, ifcopenshell_plugin_metadata_v1)
BOOST_DLL_ALIAS(ifcopenshell::serializers::geometry_ttl_plugin::register_plugin, ifcopenshell_register_geometry_serializer_plugin_v1)
+62
View File
@@ -0,0 +1,62 @@
/********************************************************************************
* *
* This file is part of IfcOpenShell. *
* *
* IfcOpenShell is free software: you can redistribute it and/or modify *
* it under the terms of the Lesser GNU General Public License as published by *
* the Free Software Foundation, either version 3.0 of the License, or *
* (at your option) any later version. *
* *
* IfcOpenShell is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* Lesser GNU General Public License for more details. *
* *
* You should have received a copy of the Lesser GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
#ifdef WITH_USD
#include "geometry_serializer_plugin.h"
#include "USDSerializer.h"
#include <boost/dll/alias.hpp>
#include <boost/make_shared.hpp>
namespace ifcopenshell {
namespace serializers {
namespace geometry_usd_plugin {
plugin::abi_info plugin_abi() {
return plugin::host_abi();
}
plugin::metadata plugin_metadata() {
return geometry_serializer_plugin_metadata("usd");
}
boost::shared_ptr<GeometrySerializer> create_serializer(const geometry_serializer_context& context) {
return boost::make_shared<USDSerializer>(context.output_filename, context.geometry_settings, context.serializer_settings);
}
void register_plugin(geometry_serializer_registry& registry, const plugin::module& module) {
geometry_serializer_info info;
info.format = "usd";
info.extensions = { ".usd", ".usda", ".usdc" };
info.supports_triangulation = true;
info.supports_user_element_hierarchy = true;
info.writes_final_output = true;
registry.bind(info, create_serializer, geometry_serializer_registry::configure_fn(), module);
}
}
}
}
BOOST_DLL_ALIAS(ifcopenshell::serializers::geometry_usd_plugin::plugin_abi, ifcopenshell_plugin_abi_v1)
BOOST_DLL_ALIAS(ifcopenshell::serializers::geometry_usd_plugin::plugin_metadata, ifcopenshell_plugin_metadata_v1)
BOOST_DLL_ALIAS(ifcopenshell::serializers::geometry_usd_plugin::register_plugin, ifcopenshell_register_geometry_serializer_plugin_v1)
#endif
@@ -1,26 +1,10 @@
set(document_serializer_plugin_runtime_dir "${CMAKE_BINARY_DIR}/serializers/$<CONFIG>")
foreach(schema ${SCHEMA_VERSIONS}) foreach(schema ${SCHEMA_VERSIONS})
add_library(document_serializer_xml_ifc${schema} SHARED XmlSerializer.cpp xml_plugin.cpp) add_document_serializer_plugin(document_serializer_xml_ifc${schema} "document.xml.ifc${schema}" SOURCES XmlSerializer.cpp xml_plugin.cpp)
target_link_libraries(document_serializer_xml_ifc${schema} PRIVATE plugin Serializers IfcGeom IfcParse) target_compile_definitions(document_serializer_xml_ifc${schema} PRIVATE IfcSchema=Ifc${schema})
set_target_properties(document_serializer_xml_ifc${schema} PROPERTIES
COMPILE_FLAGS "-DIfcSchema=Ifc${schema}"
OUTPUT_NAME "document.xml.ifc${schema}"
RUNTIME_OUTPUT_DIRECTORY "${document_serializer_plugin_runtime_dir}"
LIBRARY_OUTPUT_DIRECTORY "${document_serializer_plugin_runtime_dir}"
)
list(APPEND document_serializer_libraries document_serializer_xml_ifc${schema})
if(WITH_GLTF) if(GLTF_SUPPORT)
add_library(document_serializer_json_ifc${schema} SHARED JsonSerializer.cpp json_plugin.cpp) add_document_serializer_plugin(document_serializer_json_ifc${schema} "document.json.ifc${schema}" SOURCES JsonSerializer.cpp json_plugin.cpp)
target_link_libraries(document_serializer_json_ifc${schema} PRIVATE plugin Serializers IfcGeom IfcParse) target_compile_definitions(document_serializer_json_ifc${schema} PRIVATE IfcSchema=Ifc${schema})
set_target_properties(document_serializer_json_ifc${schema} PROPERTIES
COMPILE_FLAGS "-DIfcSchema=Ifc${schema}"
OUTPUT_NAME "document.json.ifc${schema}"
RUNTIME_OUTPUT_DIRECTORY "${document_serializer_plugin_runtime_dir}"
LIBRARY_OUTPUT_DIRECTORY "${document_serializer_plugin_runtime_dir}"
)
list(APPEND document_serializer_libraries document_serializer_json_ifc${schema})
endif() endif()
endforeach() endforeach()
@@ -25,16 +25,16 @@
#include "../../ifcparse/macros.h" #include "../../ifcparse/macros.h"
#include <boost/dll/alias.hpp> #include <boost/dll/alias.hpp>
#include <boost/make_shared.hpp>
namespace { namespace {
struct factory_t { boost::shared_ptr<Serializer> create_serializer(const ifcopenshell::serializers::document_serializer_context& context) {
JsonSerializer* operator()(ifcopenshell::file* file, const std::string& json_filename, JsonSerializer::Dialect dialect) const { return boost::make_shared<POSTFIX_SCHEMA(JsonSerializer)>(
auto* serializer = new POSTFIX_SCHEMA(JsonSerializer)(file, json_filename, dialect); context.file,
serializer->setFile(file); context.output_filename,
return serializer; static_cast<JsonSerializer::Dialect>(context.dialect));
} }
};
} }
@@ -50,9 +50,11 @@ plugin::metadata plugin_metadata() {
return document_serializer_plugin_metadata("json", STRINGIFY(IfcSchema)); return document_serializer_plugin_metadata("json", STRINGIFY(IfcSchema));
} }
void register_plugin(JsonSerializerFactory::Factory& registry, const plugin::module& module) { void register_plugin(document_serializer_registry& registry, const plugin::module& module) {
factory_t factory; document_serializer_info info;
registry.bind(STRINGIFY(IfcSchema), factory, module); info.format = "json";
info.schema_name = STRINGIFY(IfcSchema);
registry.bind(info, create_serializer, module);
} }
} }
@@ -23,16 +23,13 @@
#include "../../ifcparse/macros.h" #include "../../ifcparse/macros.h"
#include <boost/dll/alias.hpp> #include <boost/dll/alias.hpp>
#include <boost/make_shared.hpp>
namespace { namespace {
struct factory_t { boost::shared_ptr<Serializer> create_serializer(const ifcopenshell::serializers::document_serializer_context& context) {
XmlSerializer* operator()(ifcopenshell::file* file, const std::string& xml_filename) const { return boost::make_shared<POSTFIX_SCHEMA(XmlSerializer)>(context.file, context.output_filename);
auto* serializer = new POSTFIX_SCHEMA(XmlSerializer)(file, xml_filename); }
serializer->setFile(file);
return serializer;
}
};
} }
@@ -48,9 +45,11 @@ plugin::metadata plugin_metadata() {
return document_serializer_plugin_metadata("xml", STRINGIFY(IfcSchema)); return document_serializer_plugin_metadata("xml", STRINGIFY(IfcSchema));
} }
void register_plugin(XmlSerializerFactory::Factory& registry, const plugin::module& module) { void register_plugin(document_serializer_registry& registry, const plugin::module& module) {
factory_t factory; document_serializer_info info;
registry.bind(STRINGIFY(IfcSchema), factory, module); info.format = "xml";
info.schema_name = STRINGIFY(IfcSchema);
registry.bind(info, create_serializer, module);
} }
} }