mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-21 04:32:23 +00:00
Compare commits
20 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e49c47fbd2 | |||
| d3cef0b1e6 | |||
| 094488ece5 | |||
| 4b11e62edf | |||
| 8739f6c13e | |||
| 973f61c6dc | |||
| f47aa4d81a | |||
| fa9a3383aa | |||
| 104591a80b | |||
| 030e6e5bb4 | |||
| a031310a66 | |||
| 436e3f7b2a | |||
| 335d571854 | |||
| f78b380b71 | |||
| 2cebc3f60b | |||
| 0a8159505d | |||
| 301fba5a8b | |||
| ba90cf220d | |||
| 6318892a97 | |||
| 1a6336bd20 |
@@ -0,0 +1,377 @@
|
||||
# /// script
|
||||
# dependencies = [
|
||||
# "pytest",
|
||||
# ]
|
||||
# ///
|
||||
|
||||
"""Check (and by default fix) whitespace issues in tracked source files:
|
||||
- stray CR, e.g. 'hello\\rworld' -> 'helloworld'
|
||||
- line ending mismatch, e.g. 'hello\\r\\n' -> 'hello\\n' (or vice versa)
|
||||
- missing newline at end of file
|
||||
- extra newline(s) at end of file
|
||||
- trailing whitespace at end of line
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import io
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
from collections.abc import Callable
|
||||
from pathlib import Path
|
||||
from typing import BinaryIO, Literal, cast
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
class C:
|
||||
RED = "\033[31m"
|
||||
GREEN = "\033[32m"
|
||||
YELLOW = "\033[33m"
|
||||
RESET = "\033[0m"
|
||||
|
||||
|
||||
CR = b"\r"
|
||||
CRLF = b"\r\n"
|
||||
LF = b"\n"
|
||||
|
||||
LineSeparator = Literal[b"\r\n", b"\n"]
|
||||
SYSTEM_LINE_SEPARATOR = cast(LineSeparator, os.linesep.encode())
|
||||
|
||||
|
||||
class Checker:
|
||||
def __init__(self, newline: LineSeparator = SYSTEM_LINE_SEPARATOR) -> None:
|
||||
self.newline = newline
|
||||
self.issues = 0
|
||||
|
||||
def report(self, label: str, issue: str) -> None:
|
||||
self.issues += 1
|
||||
print(f"{label}: {C.RED}{issue}{C.RESET}")
|
||||
|
||||
def check_stray_cr(self, filepath: Path, check: bool) -> None:
|
||||
with filepath.open("r+b") as f:
|
||||
self._check_stray_cr(f, str(filepath), check)
|
||||
|
||||
def _check_stray_cr(self, f: BinaryIO, label: str, check: bool) -> None:
|
||||
# a CR is "stray" if it isn't immediately followed by a LF, i.e. not part of a CRLF pair
|
||||
# CRLF/CR mismatch will be reported separately.
|
||||
stray_cr = re.compile(rb"\r(?!\n)")
|
||||
|
||||
content = f.read()
|
||||
matches = list(stray_cr.finditer(content))
|
||||
if not matches:
|
||||
return
|
||||
|
||||
line_numbers = dict.fromkeys(content.count(b"\n", 0, m.start()) + 1 for m in matches)
|
||||
for line_number in line_numbers:
|
||||
self.report(f"{label}:{line_number}", "stray carriage return")
|
||||
if check:
|
||||
return
|
||||
|
||||
f.seek(0)
|
||||
f.write(stray_cr.sub(b"", content))
|
||||
f.truncate()
|
||||
|
||||
def check_line_endings_mismatch(self, filepath: Path, check: bool) -> None:
|
||||
with filepath.open("r+b") as f:
|
||||
self._check_line_endings_mismatch(f, str(filepath), check)
|
||||
|
||||
def _check_line_endings_mismatch(self, f: BinaryIO, label: str, check: bool) -> None:
|
||||
NEWLINE = self.newline
|
||||
|
||||
def get_line_ending(line: bytes) -> LineSeparator | None:
|
||||
if line.endswith(CRLF):
|
||||
return CRLF
|
||||
if line.endswith(LF):
|
||||
return LF
|
||||
# last line with no trailing newline at all; check_eof_newline handles that
|
||||
return None
|
||||
|
||||
changed = False
|
||||
fixed_lines = []
|
||||
for line_number, line in enumerate(f, start=1):
|
||||
found = get_line_ending(line)
|
||||
if found in (NEWLINE, None):
|
||||
fixed_lines.append(line)
|
||||
continue
|
||||
|
||||
self.report(f"{label}:{line_number}", f"line ending mismatch (expected {NEWLINE!r}, found {found!r})")
|
||||
changed = True
|
||||
content = line[: -len(found)]
|
||||
fixed_lines.append(content + NEWLINE)
|
||||
|
||||
if changed and not check:
|
||||
f.seek(0)
|
||||
f.write(b"".join(fixed_lines))
|
||||
f.truncate()
|
||||
|
||||
def check_eof_newline(self, filepath: Path, check: bool) -> None:
|
||||
with filepath.open("r+b") as f:
|
||||
self._check_eof_newline(f, str(filepath), check)
|
||||
|
||||
def _check_eof_newline(self, f: BinaryIO, label: str, check: bool) -> None:
|
||||
NEWLINE = self.newline
|
||||
NEWLINE_SIZE = len(NEWLINE)
|
||||
|
||||
size = f.seek(0, os.SEEK_END)
|
||||
if size == 0:
|
||||
return
|
||||
|
||||
trailing_newlines = 0
|
||||
while True:
|
||||
pos = f.seek((-trailing_newlines - 1) * NEWLINE_SIZE, os.SEEK_END)
|
||||
if f.read(NEWLINE_SIZE) != NEWLINE:
|
||||
break
|
||||
trailing_newlines += 1
|
||||
if pos == 0:
|
||||
break
|
||||
|
||||
if trailing_newlines == 0:
|
||||
self.report(label, "missing newline at end of file")
|
||||
if check:
|
||||
return
|
||||
f.seek(0, os.SEEK_END)
|
||||
f.write(NEWLINE)
|
||||
elif trailing_newlines > 1:
|
||||
self.report(label, f"{trailing_newlines} trailing newlines at end of file")
|
||||
if check:
|
||||
return
|
||||
f.truncate(size - (trailing_newlines - 1) * NEWLINE_SIZE)
|
||||
|
||||
def check_trailing_whitespaces(self, filepath: Path, check: bool) -> None:
|
||||
with filepath.open("r+b") as f:
|
||||
self._check_trailing_whitespaces(f, str(filepath), check)
|
||||
|
||||
def _check_trailing_whitespaces(self, f: BinaryIO, label: str, check: bool) -> None:
|
||||
NEWLINE = self.newline
|
||||
NEWLINE_SIZE = len(NEWLINE)
|
||||
|
||||
changed = False
|
||||
fixed_lines = []
|
||||
for line_number, line in enumerate(f, start=1):
|
||||
has_newline = line.endswith(NEWLINE)
|
||||
content = line[:-NEWLINE_SIZE] if has_newline else line
|
||||
stripped = content.rstrip()
|
||||
if stripped != content:
|
||||
self.report(f"{label}:{line_number}", "trailing whitespace")
|
||||
changed = True
|
||||
fixed_lines.append(stripped + (NEWLINE if has_newline else b""))
|
||||
|
||||
if changed and not check:
|
||||
f.seek(0)
|
||||
f.write(b"".join(fixed_lines))
|
||||
f.truncate()
|
||||
|
||||
|
||||
CheckMethod = Callable[[Checker, BinaryIO, str, bool], None]
|
||||
|
||||
|
||||
class TestChecker:
|
||||
def _assert_check(
|
||||
self,
|
||||
method: CheckMethod,
|
||||
content: bytes,
|
||||
expected_issues: int,
|
||||
fixed: bytes,
|
||||
check: bool,
|
||||
line_ending: LineSeparator,
|
||||
*,
|
||||
transform: bool = True,
|
||||
) -> None:
|
||||
checker = Checker(line_ending)
|
||||
if line_ending == CRLF and transform:
|
||||
content = content.replace(LF, CRLF)
|
||||
fixed = fixed.replace(LF, CRLF)
|
||||
buffer = io.BytesIO(content)
|
||||
method(checker, buffer, "test", check)
|
||||
assert buffer.getvalue() == (content if check else fixed)
|
||||
assert checker.issues == expected_issues
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("content", "expected_issues", "fixed"),
|
||||
(
|
||||
# OK
|
||||
(b"", 0, b""),
|
||||
(b"hello\n", 0, b"hello\n"),
|
||||
(b"line1\r\nline2\n", 0, b"line1\r\nline2\n"),
|
||||
# ERR
|
||||
(b"hello\rworld\n", 1, b"helloworld\n"),
|
||||
(b"a\rb\rc\n", 1, b"abc\n"),
|
||||
(b"hello\r", 1, b"hello"),
|
||||
),
|
||||
)
|
||||
@pytest.mark.parametrize("check", [False, True])
|
||||
def test_check_stray_cr(self, content: bytes, expected_issues: int, fixed: bytes, check: bool) -> None:
|
||||
# Don't parametrize by line endings, since in this case it doesn't matter.
|
||||
self._assert_check(Checker._check_stray_cr, content, expected_issues, fixed, check, LF)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("content", "expected_issues", "fixed", "line_ending"),
|
||||
(
|
||||
# OK
|
||||
(b"", 0, b"", LF),
|
||||
(b"hello\n", 0, b"hello\n", LF),
|
||||
(b"hello\r\n", 0, b"hello\r\n", CRLF),
|
||||
# ERR
|
||||
(b"hello\r\n", 1, b"hello\n", LF),
|
||||
(b"a\nb\r\nc\n", 1, b"a\nb\nc\n", LF),
|
||||
(b"a\r\nb\r\n", 2, b"a\nb\n", LF),
|
||||
(b"hello\n", 1, b"hello\r\n", CRLF),
|
||||
(b"a\r\nb\nc\r\n", 1, b"a\r\nb\r\nc\r\n", CRLF),
|
||||
),
|
||||
)
|
||||
@pytest.mark.parametrize("check", [False, True])
|
||||
def test_check_line_endings_mismatch(
|
||||
self, content: bytes, expected_issues: int, fixed: bytes, line_ending: LineSeparator, check: bool
|
||||
) -> None:
|
||||
self._assert_check(
|
||||
Checker._check_line_endings_mismatch, content, expected_issues, fixed, check, line_ending, transform=False
|
||||
)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("content", "expected_issues", "fixed"),
|
||||
(
|
||||
# OK
|
||||
(b"", 0, b""),
|
||||
(b"hello\n", 0, b"hello\n"),
|
||||
# ERR
|
||||
(b"hello", 1, b"hello\n"),
|
||||
(b"hello\n\n\n", 1, b"hello\n"),
|
||||
(b"\n\n\n", 1, b"\n"),
|
||||
),
|
||||
)
|
||||
@pytest.mark.parametrize("check", [False, True])
|
||||
@pytest.mark.parametrize("line_ending", [LF, CRLF])
|
||||
def test_check_eof_newline(
|
||||
self, content: bytes, expected_issues: int, fixed: bytes, check: bool, line_ending: LineSeparator
|
||||
) -> None:
|
||||
self._assert_check(Checker._check_eof_newline, content, expected_issues, fixed, check, line_ending)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("content", "expected_issues", "fixed"),
|
||||
(
|
||||
# OK
|
||||
(b"", 0, b""),
|
||||
(b"hello\n", 0, b"hello\n"),
|
||||
(b"hello", 0, b"hello"),
|
||||
# ERR
|
||||
(b" ", 1, b""),
|
||||
(b"hello ", 1, b"hello"),
|
||||
),
|
||||
)
|
||||
@pytest.mark.parametrize("check", [False, True])
|
||||
@pytest.mark.parametrize("line_ending", [LF, CRLF])
|
||||
def test_check_trailing_whitespaces(
|
||||
self, content: bytes, expected_issues: int, fixed: bytes, check: bool, line_ending: LineSeparator
|
||||
) -> None:
|
||||
self._assert_check(Checker._check_trailing_whitespaces, content, expected_issues, fixed, check, line_ending)
|
||||
|
||||
@staticmethod
|
||||
def run_tests(extra_args: list[str] | None = None) -> None:
|
||||
pytest.main([__file__, *(extra_args or [])])
|
||||
|
||||
|
||||
def existing_path(value: str) -> Path:
|
||||
path = Path(value)
|
||||
if not path.exists():
|
||||
raise argparse.ArgumentTypeError(f"path not found: {value}")
|
||||
return path
|
||||
|
||||
|
||||
# Python files are covered by `black`.
|
||||
PATTERNS = (
|
||||
"*.cpp",
|
||||
"*.h",
|
||||
"*.i",
|
||||
)
|
||||
|
||||
REPO_ROOT = Path(subprocess.check_output(["git", "rev-parse", "--show-toplevel"], text=True).strip())
|
||||
|
||||
# Generated files; formatted by the express codegen, not by this script.
|
||||
IGNORED_DIRS = (REPO_ROOT / "src/ifcparse/schemas",)
|
||||
|
||||
|
||||
def get_tracked_files(root: Path | None = None) -> list[Path]:
|
||||
output = subprocess.check_output(
|
||||
["git", "ls-files", "--others", "--cached", "--exclude-standard", *PATTERNS],
|
||||
cwd=root,
|
||||
text=True,
|
||||
)
|
||||
base = root if root is not None else Path()
|
||||
filepaths = []
|
||||
for line in output.splitlines():
|
||||
filepath = base / line
|
||||
if not any(filepath.resolve().is_relative_to(d) for d in IGNORED_DIRS):
|
||||
filepaths.append(filepath)
|
||||
return filepaths
|
||||
|
||||
|
||||
def main() -> int:
|
||||
# anything after "--" is forwarded to pytest, e.g. `--test -- --capture=no`
|
||||
argv = sys.argv[1:]
|
||||
if "--" in argv:
|
||||
split = argv.index("--")
|
||||
argv, extra_args = argv[:split], argv[split + 1 :]
|
||||
else:
|
||||
extra_args = []
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
description=__doc__,
|
||||
)
|
||||
parser.add_argument("paths", type=existing_path, nargs="*", help="files or directories to check")
|
||||
parser.add_argument(
|
||||
"--check",
|
||||
action="store_true",
|
||||
help="only check for whitespace issues without applying fixes",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--test",
|
||||
action="store_true",
|
||||
help="run self-tests",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--verbose",
|
||||
action="store_true",
|
||||
help="print each checked path",
|
||||
)
|
||||
args = parser.parse_args(argv)
|
||||
|
||||
if args.test:
|
||||
TestChecker.run_tests(extra_args)
|
||||
return 0
|
||||
|
||||
if args.paths:
|
||||
filepaths: list[Path] = []
|
||||
for path in args.paths:
|
||||
filepaths.extend(get_tracked_files(path) if path.is_dir() else [path])
|
||||
else:
|
||||
filepaths = get_tracked_files()
|
||||
|
||||
# dict.fromkeys() dedupes while preserving order, unlike set().
|
||||
filepaths = list(dict.fromkeys(filepaths))
|
||||
|
||||
checker = Checker()
|
||||
for filepath in filepaths:
|
||||
if args.verbose:
|
||||
print(f"checking {filepath}")
|
||||
checker.check_stray_cr(filepath, args.check)
|
||||
checker.check_line_endings_mismatch(filepath, args.check)
|
||||
checker.check_eof_newline(filepath, args.check)
|
||||
checker.check_trailing_whitespaces(filepath, args.check)
|
||||
print(f"{len(filepaths)} file(s) checked.")
|
||||
if not checker.issues:
|
||||
color = C.GREEN
|
||||
elif args.check:
|
||||
color = C.RED
|
||||
else:
|
||||
color = C.YELLOW
|
||||
outcome = "found" if args.check else "found and fixed"
|
||||
print(f"{color}{checker.issues} issue(s) {outcome}.{C.RESET}")
|
||||
|
||||
return 1 if args.check and checker.issues else 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
@@ -109,6 +109,11 @@ if(BUILD_BONSAIVIEWER AND NOT BUILD_BONSAIVIEWER_WGPU)
|
||||
endif()
|
||||
option(BUILD_PACKAGE "" OFF)
|
||||
|
||||
option(
|
||||
BUILD_FUZZERS
|
||||
"Build libFuzzer security-fuzzing harnesses. Requires a Clang toolchain configured with -fsanitize=fuzzer (typically also address,undefined) via CMAKE_CXX_FLAGS."
|
||||
OFF
|
||||
)
|
||||
option(
|
||||
IFCOPENSHELL_DEPLOY_QT_RUNTIME
|
||||
"Deploy Qt runtime dependencies for installed Qt applications."
|
||||
@@ -758,6 +763,10 @@ if(BUILD_BONSAIVIEWER)
|
||||
add_subdirectory(../src/bonsaiviewer bonsaiviewer)
|
||||
endif()
|
||||
|
||||
if(BUILD_FUZZERS)
|
||||
add_subdirectory(../src/ifcfuzz ifcfuzz)
|
||||
endif()
|
||||
|
||||
# Cmake uninstall target
|
||||
if(NOT TARGET uninstall)
|
||||
configure_file(
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Intended to be run after nix/build-all.py has finished the wasm build."""
|
||||
|
||||
import shutil
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
+13
-5
@@ -6,11 +6,6 @@ version = "0.0.0"
|
||||
|
||||
[tool.black]
|
||||
line-length = 120
|
||||
include = '''
|
||||
src/.*.pyi?$
|
||||
|nix/.*.pyi?$
|
||||
|pyodide/.*.pyi?$
|
||||
'''
|
||||
extend-exclude = '''
|
||||
src/ifcopenshell-python/ifcopenshell/express/rules/*
|
||||
|src/ifcopenshell-python/ifcopenshell/express/express_parser.py
|
||||
@@ -19,6 +14,15 @@ extend-exclude = '''
|
||||
|src/ifc2ca/templates/*
|
||||
|src/svgfill
|
||||
|src/exterior-shell-extractor
|
||||
|choco/bonsai/tools/enable_blenderbim_addon.py
|
||||
|choco/bonsai/tools/disable_blenderbim_addon.py
|
||||
|docs/conf.py
|
||||
|docs/generate_docs.py
|
||||
|aws/lambda/example_handler/__init__.py
|
||||
|conda/update_version_init.py
|
||||
|test/bpy.py
|
||||
|test/tests.py
|
||||
|test/run.py
|
||||
'''
|
||||
|
||||
[tool.pyright]
|
||||
@@ -112,7 +116,9 @@ invalid-assignment = "ignore"
|
||||
invalid-parameter-default = "ignore"
|
||||
missing-override-decorator = "ignore"
|
||||
invalid-yield = "ignore"
|
||||
unsound-yield = "ignore"
|
||||
invalid-return-type = "ignore"
|
||||
unsound-return-statement = "ignore"
|
||||
non-callable-init-subclass = "ignore"
|
||||
not-iterable = "ignore"
|
||||
possibly-missing-attribute = "ignore"
|
||||
@@ -181,6 +187,8 @@ dev-setup.help = "Install repo packages in editable mode"
|
||||
|
||||
ruff = "ruff check"
|
||||
|
||||
check-whitespace = "uv run .github/scripts/check-whitespace.py"
|
||||
|
||||
black = "black ."
|
||||
|
||||
ty.sequence = ["ty-bonsai", "ty-ios"]
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
black==26.3.1
|
||||
ruff==0.16.0
|
||||
poethepoet
|
||||
ty==0.0.63
|
||||
ty==0.0.72
|
||||
gersemi==0.28.0
|
||||
|
||||
@@ -76,12 +76,12 @@ int main() {
|
||||
// By adding a building, a hierarchy has been automatically created that consists of the following
|
||||
// structure: IfcProject > IfcSite > IfcBuilding
|
||||
|
||||
// Lateron changing the name of the IfcProject can be done by obtaining a reference to the
|
||||
// Lateron changing the name of the IfcProject can be done by obtaining a reference to the
|
||||
// project, which has been created automatically.
|
||||
file.getSingle<IfcSchema::IfcProject>().setName("IfcAdvancedHouse"s);
|
||||
|
||||
// To demonstrate the ability to serialize arbitrary opencascade solids a building envelope is
|
||||
// constructed by applying boolean operations. Naturally, in IFC, building elements should be
|
||||
// constructed by applying boolean operations. Naturally, in IFC, building elements should be
|
||||
// modeled separately, with rich parametric and relational semantics. Creating geometry in this
|
||||
// way does not preserve any history and is merely a demonstration of technical capabilities.
|
||||
TopoDS_Shape outer = BRepPrimAPI_MakeBox(gp_Pnt(-5000., -180., -2000.), gp_Pnt(5000., 5180., 3000.)).Shape();
|
||||
@@ -102,7 +102,7 @@ int main() {
|
||||
// to the IFC4 model and with `advanced` set to `true` which introduces IfcAdvancedFace. It would
|
||||
// return `0` otherwise.
|
||||
auto building_shape = ifcopenshell::geom::serialise(file, building_shell, false).as<IfcSchema::IfcProductDefinitionShape>();
|
||||
|
||||
|
||||
file.add_entity(building_shape);
|
||||
auto building_representations = building_shape.Representations();
|
||||
building_representations.front().setContextOfItems(file.getRepresentationContext("model"));
|
||||
@@ -122,7 +122,7 @@ int main() {
|
||||
ground_representation = ifcopenshell::geom::tesselate(file, shape, 100.);
|
||||
}
|
||||
file.getSingle<IfcSchema::IfcSite>().setRepresentation(ground_representation.as<IfcSchema::IfcProductDefinitionShape>());
|
||||
|
||||
|
||||
auto ground_reps = file.getSingle<IfcSchema::IfcSite>().Representation().Representations();
|
||||
for (auto& rep : ground_reps) {
|
||||
rep.setContextOfItems(file.getRepresentationContext("Model"));
|
||||
@@ -175,10 +175,10 @@ void createGroundShape(TopoDS_Shape& shape) {
|
||||
cv.SetValue(4, 4, gp_Pnt( 10000, 10000, -8130));
|
||||
TColStd_Array1OfReal knots(0, 1);
|
||||
knots(0) = 0;
|
||||
knots(1) = 1;
|
||||
knots(1) = 1;
|
||||
TColStd_Array1OfInteger mult(0, 1);
|
||||
mult(0) = 5;
|
||||
mult(1) = 5;
|
||||
mult(1) = 5;
|
||||
Handle(Geom_BSplineSurface) surf = new Geom_BSplineSurface(cv, knots, knots, mult, mult, 4, 4);
|
||||
#if OCC_VERSION_HEX < 0x60502
|
||||
shape = BRepBuilderAPI_MakeFace(surf);
|
||||
|
||||
@@ -70,7 +70,7 @@ Schema::IfcProject setup_project(hierarchy_helper<Schema>& file) {
|
||||
dimensions.setThermodynamicTemperatureExponent(0);
|
||||
dimensions.setAmountOfSubstanceExponent(0);
|
||||
dimensions.setLuminousIntensityExponent(0);
|
||||
|
||||
|
||||
auto conversion_factor = file.create<Schema::IfcMeasureWithUnit>();
|
||||
auto length = file.create<Schema::IfcLengthMeasure>();
|
||||
length.set_attribute_value(0, 304.80);
|
||||
@@ -82,7 +82,7 @@ Schema::IfcProject setup_project(hierarchy_helper<Schema>& file) {
|
||||
conversion_based_unit.setUnitType(Schema::IfcUnitEnum::IfcUnit_LENGTHUNIT);
|
||||
conversion_based_unit.setName("FEET");
|
||||
conversion_based_unit.setConversionFactor(conversion_factor);
|
||||
|
||||
|
||||
units.erase(std::remove(units.begin(), units.end(), unit)); // remove the millimeter unit
|
||||
units.push_back(conversion_based_unit); // add the feet unit
|
||||
units_in_context.setUnits(units); // update the UnitsInContext
|
||||
@@ -386,7 +386,7 @@ int main() {
|
||||
nests_horizontal_segments.setName("Nests horizontal alignment segments with horizontal alignment");
|
||||
nests_horizontal_segments.setRelatingObject(horizontal_alignment);
|
||||
nests_horizontal_segments.setRelatedObjects(horizontal_segments);
|
||||
|
||||
|
||||
//
|
||||
// Create plan view footprint model representation for the horizontal alignment
|
||||
//
|
||||
@@ -403,7 +403,7 @@ int main() {
|
||||
footprint_shape_representation.setRepresentationType("Curve2D");
|
||||
// the composite curve is a representation item
|
||||
footprint_shape_representation.setItems({composite_curve});
|
||||
|
||||
|
||||
//
|
||||
// Define vertical profile segments
|
||||
//
|
||||
@@ -539,7 +539,7 @@ int main() {
|
||||
nests_alignment_layouts.setName("Nest horizontal and vertical alignment layouts with the alignment");
|
||||
nests_alignment_layouts.setRelatingObject(alignment);
|
||||
nests_alignment_layouts.setRelatedObjects({horizontal_alignment, vertical_profile});
|
||||
|
||||
|
||||
// Define the relationship with the project
|
||||
|
||||
// IFC 4.1.4.1.1 "Every IfcAlignment must be related to IfcProject using the IfcRelAggregates relationship"
|
||||
@@ -550,7 +550,7 @@ int main() {
|
||||
aggregate_alignments_with_project.setName("Alignments in project");
|
||||
aggregate_alignments_with_project.setRelatingObject(project);
|
||||
aggregate_alignments_with_project.setRelatedObjects({alignment});
|
||||
|
||||
|
||||
// Define the spatial structure of the alignment with respect to the site
|
||||
|
||||
// IFC 4.1.5.1 alignment is referenced in spatial structure of an IfcSpatialElement. In this case IfcSite is the highest level IfcSpatialElement
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
|
||||
using namespace std::string_literals;
|
||||
|
||||
// Some convenience typedefs and definitions.
|
||||
// Some convenience typedefs and definitions.
|
||||
typedef ifcopenshell::global_id guid;
|
||||
typedef std::pair<double, double> XY;
|
||||
#ifdef SCHEMA_HAS_IfcPresentationStyleAssignment
|
||||
@@ -295,9 +295,9 @@ int main() {
|
||||
west_void.setOwnerHistory(file.getSingle<IfcSchema::IfcOwnerHistory>());
|
||||
west_void.setRelatingBuildingElement(west_wall);
|
||||
west_void.setRelatedOpeningElement(west_opening_copy);
|
||||
|
||||
// Up until now we have only used simple extrusions for the creation of the geometry. For the
|
||||
// ground mesh of the IfcSite we will use a Nurbs surface created in Open Cascade. The surface
|
||||
|
||||
// Up until now we have only used simple extrusions for the creation of the geometry. For the
|
||||
// ground mesh of the IfcSite we will use a Nurbs surface created in Open Cascade. The surface
|
||||
// will be tessellated using the deflection specified.
|
||||
TopoDS_Shape shape;
|
||||
createGroundShape(shape);
|
||||
@@ -325,7 +325,7 @@ int main() {
|
||||
site_prop.setOwnerHistory(file.getSingle<IfcSchema::IfcOwnerHistory>());
|
||||
site_prop.setRelatedObjects({file.getSingle<IfcSchema::IfcSite>()});
|
||||
site_prop.setRelatingPropertyDefinition(pset);
|
||||
|
||||
|
||||
auto ground_reps = file.getSingle<IfcSchema::IfcSite>().Representation().Representations();
|
||||
for (auto& rep : ground_reps) {
|
||||
rep.setContextOfItems(file.getRepresentationContext("Model"));
|
||||
@@ -334,11 +334,11 @@ int main() {
|
||||
setSurfaceColour(file,ground_representation, 0.15, 0.25, 0.05);
|
||||
|
||||
// According to the Ifc2x3 schema an IfcWallStandardCase needs to have an IfcMaterialLayerSet
|
||||
// assigned. Note that this material definition is independent of the surface styles we have
|
||||
// been assigning to the walls already. The surface styles determine the colour in the
|
||||
// assigned. Note that this material definition is independent of the surface styles we have
|
||||
// been assigning to the walls already. The surface styles determine the colour in the
|
||||
// '3D viewport' of most applications.
|
||||
// Some BIM authoring applications, such as Autodesk Revit, ignore the geometrical representation
|
||||
// by and large and construct native walls using the layer thickness and reference line offset
|
||||
// by and large and construct native walls using the layer thickness and reference line offset
|
||||
// provided here.
|
||||
auto material = file.create<IfcSchema::IfcMaterial>();
|
||||
material.setName("Brick");
|
||||
@@ -422,7 +422,7 @@ int main() {
|
||||
#endif
|
||||
|
||||
door.setRepresentation(file.addBox(80, 80, 2120, IfcSchema::IfcAxis2Placement2D{}, file.addPlacement3d(460, 0, 0)));
|
||||
|
||||
|
||||
auto door_representations = door.Representation().Representations();
|
||||
IfcSchema::IfcShapeRepresentation door_body;
|
||||
for (auto& rep : door_representations) {
|
||||
@@ -465,9 +465,9 @@ int main() {
|
||||
#endif
|
||||
|
||||
// Surface styles are assigned to representation items, hence there is no real limitation to
|
||||
// assign different colours within the same representation. However, some viewers have
|
||||
// difficulties rendering products with representation items with different surface styles.
|
||||
// Therefore we will construct the window as a decomposition of beams and a plate, in which
|
||||
// assign different colours within the same representation. However, some viewers have
|
||||
// difficulties rendering products with representation items with different surface styles.
|
||||
// Therefore we will construct the window as a decomposition of beams and a plate, in which
|
||||
// only the plate will have a transparent material assigned.
|
||||
|
||||
// The window frame will consists of four separate beams.
|
||||
@@ -476,7 +476,7 @@ int main() {
|
||||
// match the bounding box of the representation. Furthermore, the window placement needs
|
||||
// to align with the lowerleft corner of the constituent parts.
|
||||
std::vector<IfcSchema::IfcShapeRepresentation> frame_representations;
|
||||
|
||||
|
||||
auto horizontal_bar = file.addEmptyRepresentation();
|
||||
auto vertical_bar = file.addEmptyRepresentation();
|
||||
file.addBox(horizontal_bar, 1860, 90, 90);
|
||||
@@ -498,7 +498,7 @@ int main() {
|
||||
// Because of the duplication the iterator is incremented twice
|
||||
}
|
||||
|
||||
// This window will be placed at five locations within the building. A list of placements is
|
||||
// This window will be placed at five locations within the building. A list of placements is
|
||||
// created and is iterated over to create all window instances.
|
||||
std::vector<IfcSchema::IfcLocalPlacement> window_placements;
|
||||
window_placements.push_back(file.addLocalPlacement(storey_placement, 2*-1770-430-930, -45, 400));
|
||||
@@ -506,7 +506,7 @@ int main() {
|
||||
window_placements.push_back(file.addLocalPlacement(storey_placement, -430-930, -45, 400));
|
||||
window_placements.push_back(file.addLocalPlacement(storey_placement, 3000-930, -45, 400));
|
||||
window_placements.push_back(file.addLocalPlacement(storey_placement, -4855+45, 885-930, 400, 0, 0, 1, 0, 1, 0));
|
||||
|
||||
|
||||
for (auto& place : window_placements) {
|
||||
|
||||
// Create the window at the current location
|
||||
@@ -520,7 +520,7 @@ int main() {
|
||||
window.setPredefinedType(IfcSchema::IfcWindowTypeEnum::IfcWindowType_WINDOW);
|
||||
window.setPartitioningType(IfcSchema::IfcWindowTypePartitioningEnum::IfcWindowTypePartitioning_SINGLE_PANEL);
|
||||
#endif
|
||||
file.addBuildingProduct(window);
|
||||
file.addBuildingProduct(window);
|
||||
|
||||
// Initialize a list of parts for the window to be composed of
|
||||
std::vector<IfcSchema::IfcObjectDefinition> window_parts;
|
||||
@@ -532,7 +532,7 @@ int main() {
|
||||
frame_placements.push_back(file.addLocalPlacement(storey_placement, 930, 45, 1510));
|
||||
frame_placements.push_back(file.addLocalPlacement(storey_placement, -885+930, 45, 90));
|
||||
frame_placements.push_back(file.addLocalPlacement(storey_placement, 885+930, 45, 90));
|
||||
|
||||
|
||||
// Now iterate over the placements and representations of the beam and add them to list of parts
|
||||
std::vector<IfcSchema::IfcLocalPlacement>::const_iterator frame_placement;
|
||||
std::vector<IfcSchema::IfcShapeRepresentation>::const_iterator frame_representation;
|
||||
@@ -565,7 +565,7 @@ int main() {
|
||||
window_parts.push_back(glass_part);
|
||||
file.relatePlacements(window, glass_part);
|
||||
setSurfaceColour(file, glass_part.Representation(), 0.6, 0.7, 0.75, 0.1);
|
||||
|
||||
|
||||
// Now create a decomposition relation between the window and the parts. Most viewers and authoring
|
||||
// tools will consider the window a single entity that can be selected as a whole.
|
||||
{
|
||||
@@ -612,10 +612,10 @@ void createGroundShape(TopoDS_Shape& shape) {
|
||||
cv.SetValue(4, 4, gp_Pnt( 10000, 10000, -8130));
|
||||
TColStd_Array1OfReal knots(0, 1);
|
||||
knots(0) = 0;
|
||||
knots(1) = 1;
|
||||
knots(1) = 1;
|
||||
TColStd_Array1OfInteger mult(0, 1);
|
||||
mult(0) = 5;
|
||||
mult(1) = 5;
|
||||
mult(1) = 5;
|
||||
Handle(Geom_BSplineSurface) surf = new Geom_BSplineSurface(cv, knots, knots, mult, mult, 4, 4);
|
||||
#if OCC_VERSION_HEX < 0x60502
|
||||
shape = BRepBuilderAPI_MakeFace(surf);
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
#include INCLUDE_SCHEMA(ifcparse/schemas, IfcSchema)
|
||||
#include INCLUDE_SCHEMA_DEFINITIONS(ifcparse/schemas, IfcSchema)
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#ifdef _MSC_VER
|
||||
#define strcasecmp _stricmp
|
||||
#endif
|
||||
|
||||
@@ -151,7 +151,7 @@ void process_pset(element_properties& props, const T& inst) {
|
||||
|
||||
template <typename Schema>
|
||||
void get_psets_s(element_properties& props, const typename Schema::IfcObjectDefinition& inst) {
|
||||
// Extracts the property definitions for an IFC instance.
|
||||
// Extracts the property definitions for an IFC instance.
|
||||
if (auto tyob = inst.template as<typename Schema::IfcTypeObject>()) {
|
||||
if (tyob.HasPropertySets()) {
|
||||
auto defs = *tyob.HasPropertySets();
|
||||
|
||||
@@ -336,7 +336,7 @@ int main(int argc, char** argv) {
|
||||
std::string exterior_only_algo;
|
||||
|
||||
ifcopenshell::geom::settings settings;
|
||||
|
||||
|
||||
po::options_description geom_options("Geometry options");
|
||||
geom_options.add_options()
|
||||
("kernel", po::value<std::string>(&geometry_kernel)->default_value(default_kernel),
|
||||
@@ -389,7 +389,7 @@ int main(int argc, char** argv) {
|
||||
("model", "Specifies whether to include surfaces and solids in the output result. "
|
||||
"Typically these are representations of type Body or Facetation. ")
|
||||
;
|
||||
|
||||
|
||||
settings.define_options(geom_options);
|
||||
|
||||
std::string bounds;
|
||||
@@ -466,7 +466,7 @@ int main(int argc, char** argv) {
|
||||
num_threads = std::thread::hardware_concurrency();
|
||||
logger.notice("SYS", 7, "Using " + std::to_string(num_threads) + " threads");
|
||||
}
|
||||
|
||||
|
||||
if (vmap.count("log-format") == 1) {
|
||||
boost::to_lower(log_format);
|
||||
if (log_format == "plain") {
|
||||
@@ -479,7 +479,7 @@ int main(int argc, char** argv) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!filter_filename.empty()) {
|
||||
size_t num_filters = read_filters_from_file(ifcopenshell::path::to_utf8(filter_filename), include_filter, include_traverse_filter, exclude_filter, exclude_traverse_filter);
|
||||
if (num_filters) {
|
||||
@@ -524,10 +524,10 @@ int main(int argc, char** argv) {
|
||||
|
||||
// If no output filename is specified a Wavefront OBJ file will be output
|
||||
// to maintain backwards compatibility with the obsolete IfcObj executable.
|
||||
const path_t output_filename = vmap.count("output-file") == 1
|
||||
const path_t output_filename = vmap.count("output-file") == 1
|
||||
? vmap["output-file"].as<path_t>()
|
||||
: change_extension(input_filename, ifcopenshell::path::from_utf8(DEFAULT_EXTENSION));
|
||||
|
||||
|
||||
if (output_filename.size() < 5) {
|
||||
cerr_ << "[error] Invalid or unsupported output file '" << output_filename << "' given" << std::endl;
|
||||
print_usage();
|
||||
@@ -572,13 +572,13 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
|
||||
path_t output_temp_filename = output_filename + ifcopenshell::path::from_utf8(TEMP_FILE_EXTENSION);
|
||||
|
||||
|
||||
std::vector<path_t> tokens;
|
||||
split(tokens, output_filename, boost::is_any_of("."));
|
||||
std::vector<path_t>::iterator tok_iter;
|
||||
path_t ext = *(tokens.end() - 1);
|
||||
path_t dot;
|
||||
dot = '.';
|
||||
dot = '.';
|
||||
path_t output_extension = dot + ext;
|
||||
|
||||
boost::to_lower(output_extension);
|
||||
@@ -785,7 +785,7 @@ int main(int argc, char** argv) {
|
||||
|
||||
time_t start,end;
|
||||
time(&start);
|
||||
|
||||
|
||||
// @nb last argument true -> bypass_properties which are not read by any of the geometry serializers
|
||||
// Document serializers and IFC are already special-cased above
|
||||
// SVG requires properties for IfcAnnotation/DRAWING properties
|
||||
@@ -839,12 +839,12 @@ int main(int argc, char** argv) {
|
||||
|
||||
settings.get<ifcopenshell::geom::settings::ModelOffset>().value = offset;
|
||||
}
|
||||
|
||||
|
||||
if (is_tesselated && (center_model || center_model_geometry)) {
|
||||
std::vector<double> offset(3);
|
||||
|
||||
ifcopenshell::geom::iterator tmp_context_iterator(ifcopenshell::geom::kernels::construct(ifc_file, geometry_kernel, settings, logger), settings, ifc_file, filter_funcs, num_threads, logger);
|
||||
|
||||
|
||||
time_t bounds_start, bounds_end;
|
||||
time(&bounds_start);
|
||||
if (!quiet) logger.status("Computing bounds...");
|
||||
@@ -860,7 +860,7 @@ int main(int argc, char** argv) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
tmp_context_iterator.compute_bounds(center_model_geometry);
|
||||
|
||||
time(&bounds_end);
|
||||
@@ -919,19 +919,19 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
|
||||
// The functions ifcopenshell::geom::iterator::get() and ifcopenshell::geom::iterator::next()
|
||||
// wrap an iterator of all geometrical products in the Ifc file.
|
||||
// wrap an iterator of all geometrical products in the Ifc file.
|
||||
// ifcopenshell::geom::iterator::get() returns an ifcopenshell::geom::triangulation_element or
|
||||
// -native_element pointer, based on current settings. (see iterator.h
|
||||
// for definition) ifcopenshell::geom::iterator::next() is used to poll whether more
|
||||
// geometrical entities are available. None of these functions throw
|
||||
// exceptions, neither for parsing errors or geometrical errors. Upon
|
||||
// calling next() the entity to be returned has already been processed, a
|
||||
// non-null return value guarantees that a successfully processed product is
|
||||
// available.
|
||||
// geometrical entities are available. None of these functions throw
|
||||
// exceptions, neither for parsing errors or geometrical errors. Upon
|
||||
// calling next() the entity to be returned has already been processed, a
|
||||
// non-null return value guarantees that a successfully processed product is
|
||||
// available.
|
||||
size_t num_created = 0;
|
||||
|
||||
while (true) {
|
||||
|
||||
|
||||
auto geom_object = context_iterator->get();
|
||||
|
||||
if (is_tesselated)
|
||||
@@ -967,7 +967,7 @@ int main(int argc, char** argv) {
|
||||
if (!context_iterator->next()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!no_progress && quiet) {
|
||||
for (; old_progress < 100; ++old_progress) {
|
||||
cout_ << ".";
|
||||
@@ -1086,7 +1086,7 @@ bool init_input_file(const std::string& filename, ifcopenshell::file*& ifc_file,
|
||||
ifc_file->bypass_type("IfcProfileProperties");
|
||||
ifc_file->bypass_type("IfcPhysicalQuantity");
|
||||
}
|
||||
|
||||
|
||||
#ifdef USE_MMAP
|
||||
if (mmap) {
|
||||
ifc_file->initialize(filename, mmap);
|
||||
@@ -1382,20 +1382,20 @@ void fix_quantities(ifcopenshell::file& f, bool no_progress, bool quiet, bool st
|
||||
auto person = latebound_access::create(f, "IfcPerson");
|
||||
latebound_access::set(person, "FamilyName", std::string("IfcOpenShell"));
|
||||
latebound_access::set(person, "GivenName", std::string("IfcOpenShell"));
|
||||
|
||||
|
||||
auto org = latebound_access::create(f, "IfcOrganization");
|
||||
latebound_access::set(org, "Name", std::string("IfcOpenShell"));
|
||||
|
||||
|
||||
auto pando = latebound_access::create(f, "IfcPersonAndOrganization");
|
||||
latebound_access::set(pando, "ThePerson", person);
|
||||
latebound_access::set(pando, "TheOrganization", org);
|
||||
|
||||
|
||||
auto application = latebound_access::create(f, "IfcApplication");
|
||||
latebound_access::set(application, "ApplicationDeveloper", org);
|
||||
latebound_access::set(application, "Version", std::string(IFCOPENSHELL_VERSION));
|
||||
latebound_access::set(application, "ApplicationFullName", std::string("IfcConvert"));
|
||||
latebound_access::set(application, "ApplicationIdentifier", std::string("IfcConvert") + IFCOPENSHELL_VERSION);
|
||||
|
||||
|
||||
auto ownerhist = latebound_access::create(f, "IfcOwnerHistory");
|
||||
latebound_access::set(ownerhist, "OwningUser", pando);
|
||||
latebound_access::set(ownerhist, "OwningApplication", application);
|
||||
@@ -1440,7 +1440,7 @@ void fix_quantities(ifcopenshell::file& f, bool no_progress, bool quiet, bool st
|
||||
latebound_access::set(quantity_area, "AreaValue", a);
|
||||
quantities.push_back(quantity_area);
|
||||
}
|
||||
|
||||
|
||||
if (geom_object->geometry().calculate_volume(a)) {
|
||||
auto quantity_volume = latebound_access::create(f, "IfcQuantityVolume");
|
||||
latebound_access::set(quantity_volume, "Name", std::string("Volume"));
|
||||
@@ -1461,13 +1461,13 @@ void fix_quantities(ifcopenshell::file& f, bool no_progress, bool quiet, bool st
|
||||
|
||||
std::vector<express::base> quantities_2;
|
||||
|
||||
for (auto& part : geom_object->geometry()) {
|
||||
for (auto& part : geom_object->geometry()) {
|
||||
auto quantity_count = latebound_access::create(f, "IfcQuantityCount");
|
||||
latebound_access::set(quantity_count, "Name", std::string("Surface Genus"));
|
||||
latebound_access::set(quantity_count, "Description", '#' + boost::lexical_cast<std::string>(part.ItemId()));
|
||||
latebound_access::set(quantity_count, "CountValue", (int64_t) part.shape()->surface_genus());
|
||||
|
||||
quantities_2.push_back(quantity_count);
|
||||
quantities_2.push_back(quantity_count);
|
||||
}
|
||||
|
||||
latebound_access::set(quantity_complex, "HasQuantities", quantities_2);
|
||||
|
||||
@@ -41,7 +41,7 @@ void fix_storeycontainment(ifcopenshell::file& f, bool no_progress, bool quiet,
|
||||
elem_to_storey[*it] = storey;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
auto storeys = f.instances_by_type("IfcBuildingStorey");
|
||||
std::vector<const ifcopenshell::IfcBaseClass*> storeys_sorted(storeys->begin(), storeys->end());
|
||||
@@ -98,7 +98,7 @@ void fix_storeycontainment(ifcopenshell::file& f, bool no_progress, bool quiet,
|
||||
std::wcout << "---" << std::endl;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
if (!context_iterator.initialize()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ void fix_wallconnectivity(ifcopenshell::file& f, bool no_progress, bool quiet, b
|
||||
settings.get<ifcopenshell::geom::settings::DisableOpeningSubtractions>().value = true;
|
||||
|
||||
settings.get<ifcopenshell::geom::settings::OutputDimensionality>().value = ifcopenshell::geom::settings::CURVES;
|
||||
|
||||
|
||||
ifcopenshell::geom::converter c(ifcopenshell::geom::kernels::construct(&f, "cgal", settings, logger), &f, settings, logger);
|
||||
|
||||
auto rels = f.instances_by_type("IfcRelConnectsPathElements");
|
||||
@@ -54,7 +54,7 @@ void fix_wallconnectivity(ifcopenshell::file& f, bool no_progress, bool quiet, b
|
||||
if (!a_is_relating) {
|
||||
std::swap(a_type, b_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
auto a_poly = ifcopenshell::geom::utils::create_polyhedron(a.handle()->second);
|
||||
@@ -123,7 +123,7 @@ void fix_wallconnectivity(ifcopenshell::file& f, bool no_progress, bool quiet, b
|
||||
} else {
|
||||
auto p0 = boost::get<taxonomy::point3::ptr>(first_vertex);
|
||||
auto p1 = boost::get<taxonomy::point3::ptr>(last_vertex);
|
||||
|
||||
|
||||
auto v0 = taxonomy::cast<taxonomy::geom_item>(item)->matrix->ccomponents() * p0->ccomponents().homogeneous();
|
||||
auto v1 = taxonomy::cast<taxonomy::geom_item>(item)->matrix->ccomponents() * p1->ccomponents().homogeneous();
|
||||
|
||||
@@ -142,7 +142,7 @@ void fix_wallconnectivity(ifcopenshell::file& f, bool no_progress, bool quiet, b
|
||||
|
||||
auto pit = std::minmax_element(parameters.begin(), parameters.end());
|
||||
return std::make_pair(len, std::make_pair(CGAL::to_double(*pit.first), CGAL::to_double(*pit.second)));
|
||||
}
|
||||
}
|
||||
}
|
||||
const auto& nan = std::numeric_limits<double>::quiet_NaN();
|
||||
return std::make_pair(nan, std::make_pair(nan, nan));
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
################################################################################
|
||||
# #
|
||||
# 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/>. #
|
||||
# #
|
||||
################################################################################
|
||||
|
||||
# libFuzzer harness(es) for IfcOpenShell. Only built when BUILD_FUZZERS is ON,
|
||||
# which is expected to be paired with a Clang toolchain configured with
|
||||
# -fsanitize=fuzzer (and typically also address,undefined) in
|
||||
# CMAKE_CXX_FLAGS - this target does not add sanitizer flags itself.
|
||||
|
||||
include_directories("${CMAKE_SOURCE_DIR}/../src")
|
||||
|
||||
add_executable(ifcparse_fuzzer ifcparse_fuzzer.cpp)
|
||||
target_include_directories(ifcparse_fuzzer PRIVATE "${CMAKE_SOURCE_DIR}/../src")
|
||||
target_link_libraries(ifcparse_fuzzer PRIVATE IfcParse)
|
||||
|
||||
# -fsanitize=fuzzer supplies its own main() and libFuzzer's driver, so it
|
||||
# must stay scoped to this one executable rather than going in the global
|
||||
# CMAKE_CXX_FLAGS - every other target (including CMake's own compiler
|
||||
# checks) would otherwise fail to link. ASan/UBSan, by contrast, are applied
|
||||
# globally via CMAKE_CXX_FLAGS so that IfcParse itself is instrumented.
|
||||
target_compile_options(ifcparse_fuzzer PRIVATE -fsanitize=fuzzer)
|
||||
target_link_options(ifcparse_fuzzer PRIVATE -fsanitize=fuzzer)
|
||||
@@ -0,0 +1,91 @@
|
||||
# ifcparse_fuzzer
|
||||
|
||||
A libFuzzer harness for `ifcopenshell::file`. It parses fuzzer input entirely
|
||||
in-memory (no subprocess, no temp files), then walks every parsed instance
|
||||
and calls `to_string()` on it. Constructing the file already tokenizes,
|
||||
type-checks, and resolves every attribute of every instance, so
|
||||
`to_string()` mainly adds coverage of the reserialization/formatting code
|
||||
path rather than the parser itself.
|
||||
|
||||
Disabled by default (`BUILD_FUZZERS=OFF`); building it needs Clang, not GCC.
|
||||
|
||||
## Build
|
||||
|
||||
libFuzzer (`-fsanitize=fuzzer`) is only implemented by Clang, and it
|
||||
supplies its own `main()`, so it has to be built in its own directory,
|
||||
separate from any normal GCC build of IfcOpenShell - putting
|
||||
`-fsanitize=fuzzer` in the global flags would break every other target,
|
||||
including CMake's own compiler check. That's why `BUILD_FUZZERS` only adds
|
||||
`-fsanitize=fuzzer` to this one target (see `CMakeLists.txt`); ASan/UBSan
|
||||
are applied globally instead, so that `IfcParse` itself is instrumented.
|
||||
|
||||
```bash
|
||||
mkdir -p build-fuzz && cd build-fuzz
|
||||
cmake ../cmake \
|
||||
-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ \
|
||||
-DCMAKE_CXX_FLAGS="-fsanitize=address,undefined -fno-sanitize-recover=all -g -O1 -fno-omit-frame-pointer" \
|
||||
-DCMAKE_C_FLAGS="-fsanitize=address,undefined -fno-sanitize-recover=all -g -O1 -fno-omit-frame-pointer" \
|
||||
-DBUILD_FUZZERS=ON -DMINIMAL_BUILD=ON \
|
||||
-DBUILD_IFCGEOM=OFF -DBUILD_CONVERT=OFF -DWITH_OPENCASCADE=OFF \
|
||||
-DSCHEMA_VERSIONS="2x3;4;4x3_add2"
|
||||
cmake --build . --target ifcparse_fuzzer -- -j$(nproc)
|
||||
```
|
||||
|
||||
`-fno-sanitize-recover=all` matters: without it, most UBSan checks just log
|
||||
and continue rather than aborting, so a fuzzing session would run straight
|
||||
past real bugs without ever capturing them as a crash artifact.
|
||||
|
||||
`-DBUILD_IFCGEOM=OFF -DBUILD_CONVERT=OFF -DWITH_OPENCASCADE=OFF
|
||||
-DMINIMAL_BUILD=ON` keep the build scoped to `IfcParse` (the code this
|
||||
harness actually exercises) so it doesn't also have to compile/instrument
|
||||
OpenCASCADE-dependent geometry code.
|
||||
|
||||
## Run
|
||||
|
||||
```bash
|
||||
mkdir -p corpus # or point at your own seed corpus of .ifc files
|
||||
./src/ifcfuzz/run.sh corpus/
|
||||
```
|
||||
|
||||
`run.sh` just sets sane sanitizer defaults and execs the binary - any
|
||||
libFuzzer flag can be passed through, e.g. `-jobs=4 -workers=4` for
|
||||
parallel fuzzing, or `-runs=0 <file>` to run once against a specific input.
|
||||
|
||||
No seed corpus or dictionary ships in this repo. Any small set of valid and
|
||||
invalid `.ifc` files works as a starting corpus; a dictionary of STEP/IFC
|
||||
tokens (`ISO-10303-21`, `HEADER`, common `IFCxxx` entity names, etc.) passed
|
||||
via `-dict=` measurably helps the mutator get past the header boilerplate.
|
||||
|
||||
### Log output
|
||||
|
||||
`Logger` output is only wired up when the binary is run against an explicit
|
||||
file argument (e.g. `-runs=1 <file>`), not during a real campaign against a
|
||||
corpus directory - logging every parse warning on every execution of a
|
||||
fuzzing campaign would dominate the runtime. Repro runs print
|
||||
`[Warning]`/`[Error]` messages to stderr.
|
||||
|
||||
### Leak detection
|
||||
|
||||
`run.sh` sets `ASAN_OPTIONS=detect_leaks=0` by default. A leak that used to
|
||||
fire on almost any malformed header (`IfcSpfLexer` allocated in
|
||||
`in_memory_file_storage::read_from_stream`, not freed if header parsing
|
||||
returned early or threw) has been fixed, but a second, narrower leak
|
||||
remains in entity attribute parsing when a syntactically valid header is
|
||||
followed by malformed entity data. libFuzzer treats a detected leak like a
|
||||
crash and halts the *entire* session on the first occurrence, so leak
|
||||
detection stays off by default until that one's fixed too. Run a separate,
|
||||
short, deliberate pass with `ASAN_OPTIONS=detect_leaks=1` instead if you're
|
||||
specifically hunting for leaks.
|
||||
|
||||
## Minimizing and deduplicating crashes
|
||||
|
||||
Not covered by `run.sh` - use libFuzzer's own flags directly:
|
||||
|
||||
```bash
|
||||
./ifcparse_fuzzer -minimize_crash=1 -max_total_time=60 -exact_artifact_path=minimized crash-input
|
||||
```
|
||||
|
||||
Sanitizer reports for two different bugs can look identical at a glance
|
||||
(same `SUMMARY` line) if the bug is a duplicated code pattern hit from
|
||||
multiple call sites - check the full symbolized stack trace, not just the
|
||||
summary, before assuming two crashes are the same bug.
|
||||
@@ -0,0 +1,89 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* 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/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
// libFuzzer entry point for ifcopenshell::file. Parses the input entirely
|
||||
// in-memory (no subprocess, no temp files) so a coverage-guided fuzzer can
|
||||
// reach the tokenizer and argument parser directly instead of only ever
|
||||
// observing IfcConvert's exit code.
|
||||
|
||||
#include "ifcparse/file.h"
|
||||
#include "ifcparse/logger.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <sstream>
|
||||
#include <sys/stat.h>
|
||||
|
||||
namespace {
|
||||
bool is_regular_file(const char* path) {
|
||||
struct stat st;
|
||||
return ::stat(path, &st) == 0 && S_ISREG(st.st_mode);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// libFuzzer runs in two modes: a real fuzzing campaign (given corpus
|
||||
// directories to mutate from, executed millions of times) and a
|
||||
// single-input repro (given one or more explicit file paths, e.g.
|
||||
// `-runs=1 crashes/<hash>/input`). logger::set_output is only wired up for
|
||||
// the latter -- logging every parse warning to a stream on every execution
|
||||
// of a real campaign would dominate the runtime.
|
||||
extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) {
|
||||
for (int i = 1; i < *argc; ++i) {
|
||||
if (is_regular_file((*argv)[i])) {
|
||||
ifcopenshell::logger::root().set_output(&std::cerr, &std::cerr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
if (size == 0 || size > static_cast<size_t>(std::numeric_limits<int>::max())) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
try {
|
||||
ifcopenshell::file ifc_file(const_cast<void*>(static_cast<const void*>(data)), static_cast<int>(size));
|
||||
|
||||
if (ifc_file.good()) {
|
||||
// Constructing the file already tokenizes and type-checks every
|
||||
// attribute of every instance (and resolves references), so
|
||||
// most tokenizer/argument bugs are reachable without going any
|
||||
// further. to_string() is still exercised here since
|
||||
// reserialization walks a different code path and may surface
|
||||
// additional faults.
|
||||
std::ostringstream discard;
|
||||
for (const auto& entity : ifc_file) {
|
||||
try {
|
||||
entity.second.to_string(discard);
|
||||
} catch (const std::exception&) {
|
||||
// Malformed attributes are expected on fuzzed input.
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (const std::exception&) {
|
||||
// IfcException (and friends) is expected control flow for malformed
|
||||
// input, not a bug. Only crashes caught by ASan/UBSan/libFuzzer
|
||||
// itself - which bypass try/catch - are findings.
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Executable
+36
@@ -0,0 +1,36 @@
|
||||
#!/usr/bin/env bash
|
||||
# Minimal runner for ifcparse_fuzzer. See README.md for build instructions
|
||||
# and an explanation of the ASan/UBSan options set below.
|
||||
#
|
||||
# Usage: run.sh [libFuzzer args...]
|
||||
# FUZZER_BIN=./build-fuzz/ifcfuzz/ifcparse_fuzzer ./run.sh corpus/
|
||||
#
|
||||
# Env overrides:
|
||||
# FUZZER_BIN path to the built harness (default: ./build-fuzz/ifcfuzz/ifcparse_fuzzer)
|
||||
# SYMBOLIZER path to llvm-symbolizer, if not already on PATH
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
BIN="${FUZZER_BIN:-./build-fuzz/ifcfuzz/ifcparse_fuzzer}"
|
||||
|
||||
if [ ! -x "$BIN" ]; then
|
||||
echo "error: fuzzer binary not found or not executable: $BIN" >&2
|
||||
echo "build it first - see README.md in this directory" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SYM_OPT=""
|
||||
if [ -n "${SYMBOLIZER:-}" ] && [ -x "$SYMBOLIZER" ]; then
|
||||
SYM_OPT=":external_symbolizer_path=$SYMBOLIZER"
|
||||
fi
|
||||
|
||||
# detect_leaks defaults OFF: entity attribute parsing can still leak when
|
||||
# malformed entity data follows a syntactically valid header (a narrower
|
||||
# case than the old header-parse leak, which has been fixed). libFuzzer
|
||||
# treats a leak like a crash and halts the whole session on the first one,
|
||||
# so leak detection needs to run as a separate, deliberate, short pass
|
||||
# instead of the default campaign mode.
|
||||
export ASAN_OPTIONS="${ASAN_OPTIONS:-abort_on_error=1:symbolize=1:detect_leaks=0$SYM_OPT}"
|
||||
export UBSAN_OPTIONS="${UBSAN_OPTIONS:-abort_on_error=1:print_stacktrace=1:symbolize=1$SYM_OPT}"
|
||||
|
||||
exec "$BIN" "$@"
|
||||
@@ -37,7 +37,7 @@ inline static bool ALMOST_THE_SAME(const T& a, const T& b, double tolerance = AL
|
||||
return fabs(a - b) < tolerance;
|
||||
}
|
||||
|
||||
namespace ifcopenshell {
|
||||
namespace ifcopenshell {
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
@@ -70,7 +70,7 @@ namespace ifcopenshell {
|
||||
public:
|
||||
bool propagate_exceptions = false;
|
||||
bool partial_success_is_success = true;
|
||||
|
||||
|
||||
abstract_kernel(const std::string& geometry_library, const ifcopenshell::geom::settings& settings, ifcopenshell::logger& logger = ifcopenshell::logger::root())
|
||||
: geometry_library_(geometry_library)
|
||||
, settings_(settings)
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace geom {
|
||||
/// should return true if the geometry for the product is wanted to be included in the output.
|
||||
/// http://www.boost.org/doc/libs/1_62_0/doc/html/function/tutorial.html
|
||||
typedef std::function<bool(const express::base&)> filter_function;
|
||||
|
||||
|
||||
class IFC_GEOM_API abstract_mapping {
|
||||
protected:
|
||||
ifcopenshell::geom::settings settings_;
|
||||
@@ -106,7 +106,7 @@ namespace geom {
|
||||
|
||||
IFC_GEOM_API mapping_factory_implementation& mapping_implementations();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -510,20 +510,20 @@ namespace ifcopenshell::geom {
|
||||
virtual void triangulate(ifcopenshell::geom::settings settings, const ifcopenshell::geom::taxonomy::matrix4& place, triangulation* t, int item_id, int surface_style_id, ifcopenshell::logger& logger = ifcopenshell::logger::root()) const = 0;
|
||||
ifcopenshell::geom::triangulation* triangulate(const ifcopenshell::geom::settings& settings, ifcopenshell::logger& logger = ifcopenshell::logger::root()) const;
|
||||
virtual void serialize(const ifcopenshell::geom::taxonomy::matrix4& place, std::string&) const = 0;
|
||||
|
||||
|
||||
virtual int surface_genus() const = 0;
|
||||
virtual bool is_manifold() const = 0;
|
||||
|
||||
|
||||
virtual int num_vertices() const = 0;
|
||||
virtual int num_edges() const = 0;
|
||||
virtual int num_faces() const = 0;
|
||||
|
||||
|
||||
// @todo choose one prototype
|
||||
virtual double bounding_box(void*&) const = 0;
|
||||
// @todo this must be something with a virtual dtor so that we can delete it.
|
||||
virtual std::pair<opaque_coordinate<3>, opaque_coordinate<3>> bounding_box() const = 0;
|
||||
virtual void set_box(void* b) = 0;
|
||||
|
||||
|
||||
virtual opaque_number length() = 0;
|
||||
virtual opaque_number area() = 0;
|
||||
virtual opaque_number volume() = 0;
|
||||
@@ -550,11 +550,11 @@ namespace ifcopenshell::geom {
|
||||
virtual std::size_t map(opaque_coordinate<4>& from, opaque_coordinate<4>& to) = 0;
|
||||
virtual std::size_t map(const std::vector<opaque_coordinate<4>>& from, const std::vector<opaque_coordinate<4>>& to) = 0;
|
||||
virtual conversion_result_shape* moved(ifcopenshell::geom::taxonomy::matrix4::ptr) const = 0;
|
||||
|
||||
|
||||
virtual bool surface_area_along_direction(double tol, const ifcopenshell::geom::taxonomy::matrix4::ptr&, double& along_x, double& along_y, double& along_z) const = 0;
|
||||
|
||||
virtual ~conversion_result_shape() {}
|
||||
|
||||
|
||||
};
|
||||
|
||||
class IFC_GEOM_API conversion_result {
|
||||
|
||||
@@ -498,7 +498,7 @@ namespace ifcopenshell {
|
||||
static constexpr const char* const description = "Slight variation of --model-offset where large offsets are applied by negating existing large offsets to retain maximum precision. Requires --no-parallel-mapping.";
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
namespace impl {
|
||||
template <typename T>
|
||||
struct readable_name {
|
||||
|
||||
@@ -19,7 +19,7 @@ ifcopenshell::geom::converter::~converter() {
|
||||
|
||||
ifcopenshell::geom::native_element* ifcopenshell::geom::converter::create_brep_for_representation_and_product(taxonomy::ptr representation_node, const express::base product_, const taxonomy::matrix4::ptr& place_) {
|
||||
auto product = product_.as<express::entity>();
|
||||
|
||||
|
||||
std::stringstream representation_id_builder;
|
||||
|
||||
auto place = place_;
|
||||
@@ -32,7 +32,7 @@ ifcopenshell::geom::native_element* ifcopenshell::geom::converter::create_brep_f
|
||||
if (!kernel_->convert(representation_node, shapes)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
if (settings_.get<ifcopenshell::geom::settings::ApplyLayerSets>().get()) {
|
||||
ifcopenshell::geom::layerset_information layerinfo;
|
||||
std::vector<ifcopenshell::geom::endpoint_connection> neighbours;
|
||||
@@ -55,7 +55,7 @@ ifcopenshell::geom::native_element* ifcopenshell::geom::converter::create_brep_f
|
||||
/*
|
||||
if (util::flatten_shape_list(shapes, merge, false, getValue(GV_PRECISION))) {
|
||||
if (util::count(merge, TopAbs_FACE) > 0) {
|
||||
|
||||
|
||||
if (convert_layerset(product, layers, styles, thickness)) {
|
||||
|
||||
IfcSchema::IfcRelAssociates::list::ptr associations = product->HasAssociations();
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace ifcopenshell { namespace geom {
|
||||
ifcopenshell::geom::kernels::abstract_kernel* kernel() { return &*kernel_; }
|
||||
|
||||
converter(std::unique_ptr<ifcopenshell::geom::kernels::abstract_kernel>&& geometry_library, ifcopenshell::file* file, ifcopenshell::geom::settings& settings, ifcopenshell::logger& logger = ifcopenshell::logger::root());
|
||||
|
||||
|
||||
~converter();
|
||||
|
||||
ifcopenshell::geom::abstract_mapping* mapping() const { return mapping_; }
|
||||
|
||||
@@ -53,7 +53,7 @@ namespace ifcopenshell::geom {
|
||||
}
|
||||
}
|
||||
const ifcopenshell::geom::taxonomy::matrix4::ptr& data() const {
|
||||
if (matrix_orig_units_) {
|
||||
if (matrix_orig_units_) {
|
||||
return matrix_orig_units_;
|
||||
}
|
||||
if (matrix_) {
|
||||
@@ -131,7 +131,7 @@ namespace ifcopenshell::geom {
|
||||
const std::string& guid, const std::string& context, const ifcopenshell::geom::taxonomy::matrix4::ptr& trsf, const express::entity& product)
|
||||
: _id(id), _parent_id(parent_id), _name(name), _type(type), _guid(guid), _context(context), _transformation(settings, trsf)
|
||||
, product_(product)
|
||||
{
|
||||
{
|
||||
std::ostringstream oss;
|
||||
|
||||
if (type == "IfcProject") {
|
||||
|
||||
+1
-1
@@ -1,2 +1,2 @@
|
||||
// A purposely empty file so that the unrolled loop
|
||||
// can overflow into an existing empty include file.
|
||||
// can overflow into an existing empty include file.
|
||||
|
||||
@@ -135,7 +135,7 @@ struct cant_fn_evaluator : public fn_evaluator {
|
||||
auto g = gradient_evaluator_.evaluate(u);
|
||||
auto c = cant_evaluator_.evaluate(u);
|
||||
|
||||
|
||||
|
||||
// curvature is stored in row 3 - capture it and remove it from the xy and uz matrices
|
||||
// so the matrix operations (ie multiplication) works correctly
|
||||
auto gradient_curvature = g.row(3);
|
||||
|
||||
@@ -13,8 +13,8 @@ IFC_GEOM_API std::vector<double> helmert_curve_point(double A0, double A1, doubl
|
||||
/// This is intended to be used from python side. Polylines are mapped to a loop, but when
|
||||
/// representing an alignment they need to be a function_item so the can be evaluated by function_item_evaluator.
|
||||
/// On the C++ side, the dcast operator take care of this, but dcast is not accessible on the python side.
|
||||
/// @param loop
|
||||
/// @return
|
||||
/// @param loop
|
||||
/// @return
|
||||
inline taxonomy::function_item::ptr convert_loop_to_function_item(taxonomy::loop::ptr loop) {
|
||||
return ifcopenshell::geom::taxonomy::dcast<taxonomy::function_item>(loop);
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ taxonomy::loft::ptr ifcopenshell::geom::make_loft(const ifcopenshell::geom::sett
|
||||
while (dist_along > *(profile_index + 1)) {
|
||||
profile_index++;
|
||||
if (profile_index == longitudes.end()) {
|
||||
// @todo handle this?
|
||||
// @todo handle this?
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,7 +158,7 @@ taxonomy::loft::ptr ifcopenshell::geom::make_loft(const ifcopenshell::geom::sett
|
||||
}
|
||||
interpolated->matrix->components() = lerp(m4a, m4b, relative_dist_along);
|
||||
}
|
||||
|
||||
|
||||
auto interpolated_offset = lerp(offset_a, offset_b, relative_dist_along);
|
||||
if (rotation_a == rotation_b && rotation_a) {
|
||||
// @todo we don't support an overridden rotation on only one of the placements
|
||||
@@ -215,7 +215,7 @@ taxonomy::loft::ptr ifcopenshell::geom::make_loft(const ifcopenshell::geom::sett
|
||||
std::vector<taxonomy::point3::ptr> points;
|
||||
std::vector<std::set<std::string>> tags;
|
||||
std::vector<std::string>::const_iterator tag_it;
|
||||
|
||||
|
||||
if (!loop->closed.value_or(false)) {
|
||||
points = {std::get<taxonomy::point3::ptr>(loop->children[0]->start)};
|
||||
if (input_tags) {
|
||||
@@ -352,7 +352,7 @@ taxonomy::loft::ptr ifcopenshell::geom::make_loft(const ifcopenshell::geom::sett
|
||||
for (auto& x : tags_for_this_point_on_subsequent_profile) {
|
||||
points.push_back(taxonomy::make<taxonomy::point3>(p3));
|
||||
common_tags_vec.push_back(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (auto tmp__ : boost::combine(w1_points, w2_points)) {
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
namespace ifcopenshell {
|
||||
|
||||
namespace geom {
|
||||
|
||||
|
||||
struct IFC_GEOM_API cross_section {
|
||||
double dist_along;
|
||||
taxonomy::geom_item::ptr section_geometry;
|
||||
|
||||
@@ -624,7 +624,7 @@ std::unique_ptr<ifcopenshell::geom::element> ifcopenshell::geom::iterator::get()
|
||||
hasParent = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Add the previously found parent to the vector
|
||||
hasParent = hasParent && parent_object->parent_id() != -1;
|
||||
}
|
||||
@@ -688,13 +688,13 @@ express::base ifcopenshell::geom::iterator::create() {
|
||||
}
|
||||
|
||||
ifcopenshell::geom::taxonomy::direction3::ptr ifcopenshell::geom::iterator::remove_offset_() {
|
||||
|
||||
|
||||
using namespace ifcopenshell::geom::taxonomy;
|
||||
|
||||
|
||||
if (!settings_.get<ifcopenshell::geom::settings::MaxOffset>().has()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
if (!settings_.get<ifcopenshell::geom::settings::NoParallelMapping>().get()) {
|
||||
throw std::runtime_error("remove_offset() can only be called with defer-processing-first-element and no-parallel-mapping settings");
|
||||
}
|
||||
|
||||
@@ -128,7 +128,7 @@ namespace ifcopenshell::geom {
|
||||
bool task_result_ptr_initialized = false;
|
||||
bool task_result_ptr_exhausted = false;
|
||||
size_t async_elements_returned_ = 0;
|
||||
|
||||
|
||||
ifcopenshell::geom::settings settings_;
|
||||
ifcopenshell::file* ifc_file;
|
||||
std::vector<ifcopenshell::geom::filter_function> filters_;
|
||||
@@ -138,7 +138,7 @@ namespace ifcopenshell::geom {
|
||||
|
||||
// When single-threaded
|
||||
ifcopenshell::geom::converter* converter_;
|
||||
|
||||
|
||||
// When multi-threaded
|
||||
std::vector<ifcopenshell::geom::converter*> kernel_pool;
|
||||
std::vector<std::unique_ptr<ifcopenshell::logger>> worker_loggers_;
|
||||
|
||||
@@ -296,7 +296,7 @@ ifcopenshell::geom::cgal_shape::cgal_shape(const cgal_polyhedron& shape, bool co
|
||||
};
|
||||
|
||||
std::vector<CGAL::Point_2<kernel_>> ps;
|
||||
|
||||
|
||||
for (auto& he1 : CGAL::halfedges_around_face(face->halfedge(), poly)) {
|
||||
const auto& source = he1->vertex()->point();
|
||||
ps.push_back(transform_point(source));
|
||||
@@ -345,7 +345,7 @@ void ifcopenshell::geom::cgal_shape::to_poly() const {
|
||||
CGAL::Polygon_mesh_processing::orient_to_bound_a_volume(poly);
|
||||
}
|
||||
shape_ = poly;
|
||||
|
||||
|
||||
// nef_->convert_to_polyhedron(*shape_);
|
||||
}
|
||||
}
|
||||
@@ -384,7 +384,7 @@ void ifcopenshell::geom::cgal_shape::triangulate(ifcopenshell::geom::settings se
|
||||
}
|
||||
|
||||
const bool setting_use_original_edges = settings.get<ifcopenshell::geom::settings::CgalEmitOriginalEdges>().get();
|
||||
|
||||
|
||||
std::set<std::set<kernel_::Point_3>> original_edges;
|
||||
if (setting_use_original_edges) {
|
||||
for (auto it = shape_to_use->edges_begin(); it != shape_to_use->edges_end(); ++it) {
|
||||
@@ -457,7 +457,7 @@ void ifcopenshell::geom::cgal_shape::triangulate(ifcopenshell::geom::settings se
|
||||
|
||||
// std::map<cgal_vertex_descriptor, kernel_::Vector_3> vertex_normals;
|
||||
// boost::associative_property_map<std::map<cgal_vertex_descriptor, kernel_::Vector_3>> vertex_normals_map(vertex_normals);
|
||||
|
||||
|
||||
// triangulate the shape and compute the normals
|
||||
std::map<facet_const_handle, kernel_::Vector_3> face_normals;
|
||||
boost::associative_property_map<std::map<facet_const_handle, kernel_::Vector_3>> face_normals_map(face_normals);
|
||||
@@ -556,7 +556,7 @@ void ifcopenshell::geom::cgal_shape::triangulate(ifcopenshell::geom::settings se
|
||||
is_face_boundary[i] = setting_use_original_edges
|
||||
? original_edges.find({ current_halfedge->vertex()->point(), current_halfedge->prev()->vertex()->point() }) != original_edges.end()
|
||||
: facet_to_component[face] != facet_to_component[current_halfedge->opposite()->face()];
|
||||
|
||||
|
||||
++i;
|
||||
++num_vertices;
|
||||
++current_halfedge;
|
||||
@@ -764,7 +764,7 @@ opaque_coordinate<3> ifcopenshell::geom::cgal_shape::position()
|
||||
for (auto it = shp.points_begin(); it != shp.points_end(); ++it) {
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
p[i] += it->cartesian(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
kernel_::FT N(static_cast<double>(std::distance(shp.points_begin(), shp.points_end())));
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
|
||||
@@ -84,7 +84,7 @@ CGAL::Polyhedron_3<kernel_> ifcopenshell::geom::utils::create_polyhedron(std::li
|
||||
// fresult.close();
|
||||
return CGAL::Polyhedron_3<kernel_>();
|
||||
}
|
||||
|
||||
|
||||
// std::cout << "After: " << polyhedron.size_of_vertices() << " vertices and " << polyhedron.size_of_facets() << " facets" << std::endl;
|
||||
|
||||
return polyhedron;
|
||||
@@ -223,7 +223,7 @@ bool cgal_kernel::convert(const taxonomy::shell::ptr l, cgal_polyhedron& shape)
|
||||
} else {
|
||||
logger().message(ifcopenshell::logger::LOG_ERROR, "Failed to convert face:", f->instance);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// std::cout << "Face in ConnectedFaceSet: " << std::endl;
|
||||
@@ -673,9 +673,9 @@ namespace {
|
||||
|
||||
namespace {
|
||||
void face_to_poly_with_holes(const cgal_face& face, CGAL::Polygon_with_holes_2<kernel_>& pwh, CGAL::Aff_transformation_3<kernel_>& place) {
|
||||
// static
|
||||
// static
|
||||
kernel_::Vector_3 Z(0, 0, 1);
|
||||
// static
|
||||
// static
|
||||
kernel_::Vector_3 X(1, 0, 0);
|
||||
|
||||
auto refz = newell(face.outer);
|
||||
@@ -912,7 +912,7 @@ bool ifcopenshell::geom::kernels::cgal_kernel::convert_openings(const express::b
|
||||
#else
|
||||
CGAL::Nef_nary_union_3<CGAL::Nef_polyhedron_3<kernel_>> second_operand_collector;
|
||||
size_t second_operand_collector_size = 0;
|
||||
|
||||
|
||||
std::list<std::pair<express::base, std::list<cgal_polyhedron>>> operands;
|
||||
|
||||
std::list<express::base> second_operand_instances;
|
||||
@@ -1483,7 +1483,7 @@ bool cgal_kernel::preprocess_boolean_operand(const express::base& log_reference,
|
||||
for (auto& nef : first_operands_nef) {
|
||||
// @todo eliminate this copy (= to remove const)
|
||||
auto nef_copy = nef;
|
||||
auto tree = build_halfspace_tree_decomposed(nef_copy, planes_fixed);
|
||||
auto tree = build_halfspace_tree_decomposed(nef_copy, planes_fixed);
|
||||
}
|
||||
{
|
||||
// @nb we snap internally as well...
|
||||
@@ -1551,7 +1551,7 @@ bool cgal_kernel::preprocess_boolean_operand(const express::base& log_reference,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
{
|
||||
@@ -2026,7 +2026,7 @@ bool cgal_kernel::convert_impl(const taxonomy::boolean_result::ptr br, std::vect
|
||||
if (!convert(face, fs) || fs.size() != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
auto& w = fs.front().outer;
|
||||
CGAL::Polygon_2<kernel_> ps;
|
||||
for (auto& wire_point : w) {
|
||||
@@ -2037,7 +2037,7 @@ bool cgal_kernel::convert_impl(const taxonomy::boolean_result::ptr br, std::vect
|
||||
continue;
|
||||
}
|
||||
|
||||
// static
|
||||
// static
|
||||
auto z = taxonomy::make<taxonomy::direction3>(0, 0, 1);
|
||||
cgal_polyhedron poly;
|
||||
process_extrusion(fs.front(), z, 200, poly);
|
||||
|
||||
@@ -74,7 +74,7 @@ namespace ifcopenshell {
|
||||
class IFC_GEOMLIBRARY_API cgal_kernel : public abstract_kernel {
|
||||
private:
|
||||
#ifndef IFOPSH_SIMPLE_KERNEL
|
||||
enum boolean_operand_preprocess {
|
||||
enum boolean_operand_preprocess {
|
||||
PP_MINKOWSKY_DILATE,
|
||||
PP_SNAP_POINTS_TO_FIRST_OPERAND,
|
||||
PP_SNAP_PLANES_TO_FIRST_OPERAND,
|
||||
|
||||
@@ -95,7 +95,7 @@ std::string dump_facet(typename CGAL::Nef_polyhedron_3<Kernel>::Halffacet_const_
|
||||
|
||||
const auto& p = h->plane();
|
||||
oss << "Facet plane=" << p << std::endl;
|
||||
|
||||
|
||||
auto fc = h->facet_cycles_begin();
|
||||
auto se = shalfedge_const_handle(fc);
|
||||
CGAL_assertion(se != 0);
|
||||
@@ -187,7 +187,7 @@ plane_map<Kernel> snap_halfspaces(const std::list<CGAL::Plane_3<Kernel>>& planes
|
||||
|
||||
fuzzy_sphere fs(query, search_radius, 0.);
|
||||
// std::cout << "q " << query << std::endl;
|
||||
|
||||
|
||||
std::list<point_d> results_pos, results_neg;
|
||||
kdtree.search(std::back_inserter(results_pos), fs);
|
||||
|
||||
@@ -801,7 +801,7 @@ void bfs(graph<Kernel>& g, size_t start_vertex, Fn& fn) {
|
||||
for (boost::tie(ei, ei_end) = boost::out_edges(cur, g); ei != ei_end; ++ei) {
|
||||
auto s = boost::source(*ei, g);
|
||||
auto t = boost::target(*ei, g);
|
||||
|
||||
|
||||
// @todo is this necessary?
|
||||
if (cur == t) {
|
||||
std::swap(s, t);
|
||||
@@ -863,10 +863,10 @@ std::unique_ptr<halfspace_tree<TreeKernel>> build_halfspace_tree(graph<Kernel>&
|
||||
int largest_component_idx = -1;
|
||||
|
||||
int num_components = 0;
|
||||
|
||||
|
||||
// @nb we don't just randomly start from an arbitrary seed, but we sort planes by d / | abc |
|
||||
// for (size_t i = 0; i < boost::num_vertices(sub_graph_0); ++i) {
|
||||
|
||||
|
||||
std::vector<size_t> sorted_verts;
|
||||
for (size_t i = 0; i < boost::num_vertices(sub_graph_0); ++i) {
|
||||
sorted_verts.push_back(i);
|
||||
@@ -1232,7 +1232,7 @@ std::unique_ptr<halfspace_tree<TreeKernel>> build_halfspace_tree_decomposed(cons
|
||||
// directly, so for now we need to isolate the individual volumes.
|
||||
CGAL::Polyhedron_3<Kernel> P;
|
||||
poly.convert_inner_shell_to_polyhedron(ci->shells_begin(), P);
|
||||
CGAL::Nef_polyhedron_3<Kernel> Pnef(P);
|
||||
CGAL::Nef_polyhedron_3<Kernel> Pnef(P);
|
||||
|
||||
for (auto it = Pnef.halffacets_begin(); it != Pnef.halffacets_end(); ++it) {
|
||||
if (it->incident_volume()->mark()) {
|
||||
@@ -1315,7 +1315,7 @@ size_t edge_contract(graph<Kernel>& G) {
|
||||
bool exists = boost::edge(srcid, tt, G).second;
|
||||
if (!exists) {
|
||||
boost::add_edge(srcid, tt, G);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
++n;
|
||||
|
||||
@@ -19,7 +19,7 @@ struct IFC_GEOMLIBRARY_API manifold_part {
|
||||
auto copy = s;
|
||||
copy.CalculateNormals(3);
|
||||
mesh = copy.GetMeshGL64();
|
||||
solid = s;
|
||||
solid = s;
|
||||
}
|
||||
|
||||
manifold_part(const manifold::MeshGL64& s) : mesh(s) {}
|
||||
|
||||
@@ -114,10 +114,10 @@ namespace {
|
||||
mesh_type build() const {
|
||||
mesh_type mesh;
|
||||
mesh.numProp = 3;
|
||||
|
||||
|
||||
std::vector<size_t> vertex_use_count(vertices.size(), 0);
|
||||
std::vector<Eigen::Vector3d> vertex_normals(vertices.size(), Eigen::Vector3d::Zero());
|
||||
|
||||
|
||||
for (size_t i = 0; i < tri_verts.size(); i += 3) {
|
||||
for (size_t j = 0; j < 3; ++j) {
|
||||
vertex_use_count[tri_verts[i + j]]++;
|
||||
@@ -1242,13 +1242,13 @@ namespace {
|
||||
}
|
||||
|
||||
std::optional<part> part_from_halfspace_solid(halfspace_build_state& state, const taxonomy::solid::ptr& solid, const taxonomy::face::ptr& face,const manifold::Box& reference_box, double precision, double dilation) {
|
||||
|
||||
|
||||
auto plane = taxonomy::cast<taxonomy::plane>(face->basis);
|
||||
|
||||
// @todo verify order
|
||||
const auto transform = matrix_or_identity(solid->matrix) * matrix_or_identity(plane->matrix);
|
||||
const auto extrusion_dir = matrix_or_identity(solid->matrix).col(2).head<3>().eval();
|
||||
|
||||
|
||||
Eigen::Vector3d x = transform.col(0).head<3>();
|
||||
Eigen::Vector3d y = transform.col(1).head<3>();
|
||||
Eigen::Vector3d normal = transform.col(2).head<3>();
|
||||
@@ -1281,7 +1281,7 @@ namespace {
|
||||
const auto delta = corner - origin;
|
||||
const auto u = delta.dot(x);
|
||||
const auto v = delta.dot(y);
|
||||
|
||||
|
||||
u_min = std::min(u_min, u);
|
||||
u_max = std::max(u_max, u);
|
||||
v_min = std::min(v_min, v);
|
||||
|
||||
@@ -58,7 +58,7 @@ double ifcopenshell::geom::util::min_edge_length(const TopoDS_Shape & a) {
|
||||
TopExp_Explorer exp(a, TopAbs_EDGE);
|
||||
for (; exp.More(); exp.Next()) {
|
||||
const TopoDS_Edge& e = TopoDS::Edge(exp.Current());
|
||||
|
||||
|
||||
TopoDS_Vertex v0, v1;
|
||||
TopExp::Vertices(e, v0, v1);
|
||||
if (!v0.IsNull() && !v1.IsNull() && v0.IsSame(v1)) {
|
||||
|
||||
@@ -43,8 +43,8 @@ bool is_intersect_ray_box(const struct ray *ray, const struct box *box) {
|
||||
// https://github.com/NVIDIA-Omniverse/PhysX/blob/main/physx/source/geomutils/src/intersection/GuIntersectionRayTriangle.h
|
||||
// With minor modifications to use gp_Vec type.
|
||||
// More reading: https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm
|
||||
bool intersectRayTriangle( const gp_Vec& orig, const gp_Vec& dir,
|
||||
const gp_Vec& vert0, const gp_Vec& vert1, const gp_Vec& vert2,
|
||||
bool intersectRayTriangle( const gp_Vec& orig, const gp_Vec& dir,
|
||||
const gp_Vec& vert0, const gp_Vec& vert1, const gp_Vec& vert2,
|
||||
double& at, double& au, double& av,
|
||||
bool cull, float enlarge) {
|
||||
// Find vectors for two edges sharing vert0
|
||||
@@ -147,7 +147,7 @@ void edgeEdgeDist(gp_Vec& x, gp_Vec& y, // closest points
|
||||
const double Denom = ADotA*BDotB - ADotB*ADotB;
|
||||
|
||||
double t; // We will clamp result so t is on the segment (p, a)
|
||||
if(Denom!=0.0)
|
||||
if(Denom!=0.0)
|
||||
t = ios_clamp((ADotT*BDotB - BDotT*ADotB) / Denom, 0.0, 1.0);
|
||||
else
|
||||
t = 0.0;
|
||||
@@ -268,7 +268,7 @@ double distanceTriangleTriangleSquared(gp_Vec& cp, gp_Vec& cq, const std::array<
|
||||
if(Tp[2]>Tp[index]) index = 2;
|
||||
}
|
||||
|
||||
if(index >= 0)
|
||||
if(index >= 0)
|
||||
{
|
||||
shown_disjoint = true;
|
||||
|
||||
@@ -297,7 +297,7 @@ double distanceTriangleTriangleSquared(gp_Vec& cp, gp_Vec& cq, const std::array<
|
||||
|
||||
gp_Vec Tn = Tv[0].Crossed(Tv[1]);
|
||||
double Tnl = Tn.Dot(Tn);
|
||||
|
||||
|
||||
if(Tnl>1e-15f)
|
||||
{
|
||||
const std::array<double, 3> Sp = {(q[0] - p[0]).Dot(Tn),
|
||||
@@ -317,7 +317,7 @@ double distanceTriangleTriangleSquared(gp_Vec& cp, gp_Vec& cq, const std::array<
|
||||
}
|
||||
|
||||
if(index >= 0)
|
||||
{
|
||||
{
|
||||
shown_disjoint = true;
|
||||
|
||||
const gp_Vec& pIndex = p[index];
|
||||
@@ -525,11 +525,11 @@ bool trianglesIntersectCoplanar(const gp_Vec& p1_n, const gp_Vec& a1, const gp_V
|
||||
|
||||
const double third = (1.0 / 3.0);
|
||||
|
||||
//A bit of the computations done inside the following functions could be shared but it's kept simple since the
|
||||
//A bit of the computations done inside the following functions could be shared but it's kept simple since the
|
||||
//difference is not very big and the coplanar case is not expected to be the most common case
|
||||
if (linesIntersect(a1, b1, a2, b2, x, y) || linesIntersect(a1, b1, b2, c2, x, y) || linesIntersect(a1, b1, c2, a2, x, y) ||
|
||||
linesIntersect(b1, c1, a2, b2, x, y) || linesIntersect(b1, c1, b2, c2, x, y) || linesIntersect(b1, c1, c2, a2, x, y) ||
|
||||
linesIntersect(c1, a1, a2, b2, x, y) || linesIntersect(c1, a1, b2, c2, x, y) || linesIntersect(c1, a1, c2, a2, x, y) ||
|
||||
linesIntersect(c1, a1, a2, b2, x, y) || linesIntersect(c1, a1, b2, c2, x, y) || linesIntersect(c1, a1, c2, a2, x, y) ||
|
||||
pointInTriangle(a1, b1, c1, third * (a2 + b2 + c2), x, y) || pointInTriangle(a2, b2, c2, third * (a1 + b1 + c1), x, y))
|
||||
return true;
|
||||
|
||||
@@ -557,7 +557,7 @@ bool trianglesIntersect(const gp_Vec& a1, const gp_Vec& b1, const gp_Vec& c1, co
|
||||
|
||||
if ((p1ToA > 0) == (p1ToB > 0) && (p1ToA > 0) == (p1ToC > 0))
|
||||
return false; //All points of triangle 2 on same side of triangle 1 -> no intersection
|
||||
|
||||
|
||||
gp_Dir p2_n((b2 - a2).Crossed(c2 - a2).Normalized());
|
||||
double p2_d = -a2.Dot(p2_n);
|
||||
// const PxPlane p2(a2, b2, c2);
|
||||
@@ -566,7 +566,7 @@ bool trianglesIntersect(const gp_Vec& a1, const gp_Vec& b1, const gp_Vec& c1, co
|
||||
const double p2ToC = c1.Dot(p2_n) + p2_d;
|
||||
|
||||
if ((p2ToA > 0) == (p2ToB > 0) && (p2ToA > 0) == (p2ToC > 0))
|
||||
return false; //All points of triangle 1 on same side of triangle 2 -> no intersection
|
||||
return false; //All points of triangle 1 on same side of triangle 2 -> no intersection
|
||||
|
||||
gp_Vec intersectionDirection = p1_n.Crossed(p2_n);
|
||||
const double l2 = intersectionDirection.SquareMagnitude();
|
||||
|
||||
@@ -20,7 +20,7 @@ struct IFC_GEOMLIBRARY_API box {
|
||||
IFC_GEOMLIBRARY_API bool is_intersect_ray_box(const struct ray *ray, const struct box *box);
|
||||
|
||||
IFC_GEOMLIBRARY_API bool intersectRayTriangle( const gp_Vec& orig, const gp_Vec& dir,
|
||||
const gp_Vec& vert0, const gp_Vec& vert1, const gp_Vec& vert2,
|
||||
const gp_Vec& vert0, const gp_Vec& vert1, const gp_Vec& vert2,
|
||||
double& at, double& au, double& av,
|
||||
bool cull, float enlarge=0.0f);
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ bool open_cascade_kernel::convert(const taxonomy::extrusion::ptr extrusion, Topo
|
||||
|
||||
if (face.ShapeType() == TopAbs_COMPOUND) {
|
||||
|
||||
// For compounds (most likely the result of a IfcCompositeProfileDef)
|
||||
// For compounds (most likely the result of a IfcCompositeProfileDef)
|
||||
// create a compound solid shape.
|
||||
|
||||
TopExp_Explorer exp(face, TopAbs_FACE);
|
||||
|
||||
@@ -247,7 +247,7 @@ namespace {
|
||||
|
||||
auto crv = get_curve(e->basis);
|
||||
result = Handle(Geom_Surface)(new Geom_SurfaceOfRevolution(
|
||||
crv, ax
|
||||
crv, ax
|
||||
));
|
||||
|
||||
result->Transform(tr);
|
||||
|
||||
@@ -70,7 +70,7 @@ namespace ifcopenshell::geom {
|
||||
std::pair<wire_it, wire_it> inner_wires() const {
|
||||
return { wires_.begin() + 1, wires_.end() };
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,7 +163,7 @@ bool open_cascade_kernel::convert(const taxonomy::loft::ptr loft, TopoDS_Shape&
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
NCollection_List<TopoDS_Shape> faces;
|
||||
TopoDS_Compound comp;
|
||||
BRep_Builder BB;
|
||||
@@ -330,7 +330,7 @@ bool open_cascade_kernel::convert(const taxonomy::loft::ptr loft, TopoDS_Shape&
|
||||
std::array<std::vector<std::vector<std::set<std::string>>>::const_iterator, 2> tag_pairs = {
|
||||
all_tags.begin() + std::distance(shps.begin(), it),
|
||||
all_tags.begin() + std::distance(shps.begin(), jt)};
|
||||
|
||||
|
||||
for (size_t i = 0; i < 2; ++i) {
|
||||
NCollection_IndexedDataMap<TopoDS_Shape, NCollection_List<TopoDS_Shape>, TopTools_ShapeMapHasher> ancestors;
|
||||
const auto& wire = wp[i];
|
||||
@@ -357,7 +357,7 @@ bool open_cascade_kernel::convert(const taxonomy::loft::ptr loft, TopoDS_Shape&
|
||||
|
||||
for (NCollection_List<TopoDS_Shape>::Iterator edge_it(incidentEdges); edge_it.More(); edge_it.Next()) {
|
||||
const TopoDS_Edge& e = TopoDS::Edge(edge_it.Value());
|
||||
|
||||
|
||||
TopoDS_Vertex ev0, ev1;
|
||||
TopExp::Vertices(e, ev0, ev1);
|
||||
|
||||
@@ -405,11 +405,11 @@ bool open_cascade_kernel::convert(const taxonomy::loft::ptr loft, TopoDS_Shape&
|
||||
++d;
|
||||
} else {
|
||||
throw std::runtime_error("Unable to construct surface");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& wp : ws) {
|
||||
BRepTools_WireExplorer a(wp[0]);
|
||||
|
||||
@@ -204,7 +204,7 @@ namespace {
|
||||
BRep_Tool::Pnt(v1).DumpJson(oss);
|
||||
auto osss = oss.str();
|
||||
std::wcout << osss.c_str() << std::endl;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
BRep_Builder B;
|
||||
TopoDS_Wire W;
|
||||
|
||||
@@ -75,7 +75,7 @@ void ifcopenshell::geom::open_cascade_shape::triangulate(ifcopenshell::geom::set
|
||||
|
||||
// A 3x3 matrix to rotate the vertex normals
|
||||
std::optional<gp_Mat> rotation_matrix;
|
||||
|
||||
|
||||
if (place.components_) {
|
||||
const auto& m = *place.components_;
|
||||
rotation_matrix.emplace(
|
||||
@@ -84,7 +84,7 @@ void ifcopenshell::geom::open_cascade_shape::triangulate(ifcopenshell::geom::set
|
||||
m(2, 0), m(2, 1), m(2, 2)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// When welding vertices, vertex coords will be shared among faces so we need to per-shape set
|
||||
// to keep track of which edges were already emitted.
|
||||
std::set<std::pair<int, int>> emitted_edges;
|
||||
@@ -119,9 +119,9 @@ void ifcopenshell::geom::open_cascade_shape::triangulate(ifcopenshell::geom::set
|
||||
for (exp.Init(shape_, TopAbs_FACE); exp.More(); exp.Next(), ++num_faces) {
|
||||
TopoDS_Face face = TopoDS::Face(exp.Current());
|
||||
|
||||
size_t num_bounds = 0;
|
||||
size_t num_bounds = 0;
|
||||
for (TopoDS_Iterator it(face); it.More(); it.Next(), ++num_bounds) {}
|
||||
|
||||
|
||||
const bool is_planar = BRep_Tool::Surface(face) && BRep_Tool::Surface(face)->DynamicType() == STANDARD_TYPE(Geom_Plane);
|
||||
const bool has_inner_bounds = num_bounds > 1;
|
||||
|
||||
@@ -314,7 +314,7 @@ void ifcopenshell::geom::open_cascade_shape::triangulate(ifcopenshell::geom::set
|
||||
} else {
|
||||
p = tessellater.Value(i).XYZ();
|
||||
}
|
||||
|
||||
|
||||
auto p_local = p;
|
||||
taxonomy_transform(place.components_, p);
|
||||
|
||||
@@ -582,7 +582,7 @@ conversion_result_shape* ifcopenshell::geom::open_cascade_shape::concat(conversi
|
||||
{
|
||||
TopoDS_Compound compound;
|
||||
BRep_Builder builder;
|
||||
|
||||
|
||||
auto& left = shape_;
|
||||
auto& right = ((ifcopenshell::geom::open_cascade_shape*)other)->shape_;
|
||||
|
||||
@@ -594,7 +594,7 @@ conversion_result_shape* ifcopenshell::geom::open_cascade_shape::concat(conversi
|
||||
builder.MakeCompound(compound);
|
||||
builder.Add(compound, left);
|
||||
}
|
||||
|
||||
|
||||
builder.Add(compound, right);
|
||||
|
||||
return new open_cascade_shape(std::move(compound));
|
||||
|
||||
@@ -84,7 +84,7 @@ bool ifcopenshell::geom::open_cascade_kernel::convert_openings(const express::ba
|
||||
// opening_trsf = relative;
|
||||
|
||||
std::vector<ifcopenshell::geom::conversion_result> opening_shapes;
|
||||
|
||||
|
||||
// @todo
|
||||
abstract_kernel::convert(op.first, opening_shapes);
|
||||
|
||||
@@ -309,13 +309,13 @@ bool ifcopenshell::geom::open_cascade_kernel::convert_impl(const taxonomy::revol
|
||||
|
||||
// IfcSchema::IfcRelVoidsElement::list::ptr ifcopenshell::geom::Kernel::find_openings(IfcSchema::IfcProduct* product) {
|
||||
// std::vector<IfcSchema::IfcRelVoidsElement*> rs;
|
||||
//
|
||||
//
|
||||
// if (product->declaration().is(IfcSchema::IfcElement::Class()) && !product->declaration().is(IfcSchema::IfcOpeningElement::Class())) {
|
||||
// IfcSchema::IfcElement* element = (IfcSchema::IfcElement*)product;
|
||||
// auto rels = element->HasOpenings();
|
||||
// rs.insert(rs.end(), rels->begin(), rels->end());
|
||||
// }
|
||||
//
|
||||
//
|
||||
// // Is the IfcElement a decomposition of an IfcElement with any IfcOpeningElements?
|
||||
// IfcSchema::IfcObjectDefinition* obdef = product->as<IfcSchema::IfcObjectDefinition>();
|
||||
// for (;;) {
|
||||
@@ -327,10 +327,10 @@ bool ifcopenshell::geom::open_cascade_kernel::convert_impl(const taxonomy::revol
|
||||
// auto rels = element->HasOpenings();
|
||||
// rs.insert(rs.end(), rels->begin(), rels->end());
|
||||
// }
|
||||
//
|
||||
//
|
||||
// obdef = rel_obdef;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// // Filter openings in Reference view, solely marked as Reference.
|
||||
// IfcSchema::IfcRelVoidsElement::list::ptr openings(new IfcSchema::IfcRelVoidsElement::list);
|
||||
// std::for_each(rs.begin(), rs.end(), [&openings](IfcSchema::IfcRelVoidsElement* rel) {
|
||||
@@ -341,17 +341,17 @@ bool ifcopenshell::geom::open_cascade_kernel::convert_impl(const taxonomy::revol
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
//
|
||||
//
|
||||
// return openings;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// const IfcSchema::IfcMaterial* ifcopenshell::geom::Kernel::get_single_material_association(const IfcSchema::IfcProduct* product) {
|
||||
// IfcSchema::IfcMaterial* single_material = 0;
|
||||
// IfcSchema::IfcRelAssociatesMaterial::list::ptr associated_materials = product->HasAssociations()->as<IfcSchema::IfcRelAssociatesMaterial>();
|
||||
// if (associated_materials->size() == 1) {
|
||||
// IfcSchema::IfcMaterialSelect* associated_material = (*associated_materials->begin())->RelatingMaterial();
|
||||
// single_material = associated_material->as<IfcSchema::IfcMaterial>();
|
||||
//
|
||||
//
|
||||
// // NB: IfcMaterialLayerSets are also considered, regardless of --enable-layerset-slicing. Picking
|
||||
// // the first material (in accordance with other viewers) when layerset-slicing is disabled.
|
||||
// if (!single_material && associated_material->as<IfcSchema::IfcMaterialLayerSetUsage>()) {
|
||||
@@ -366,21 +366,21 @@ bool ifcopenshell::geom::open_cascade_kernel::convert_impl(const taxonomy::revol
|
||||
// }
|
||||
// return single_material;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// ifcopenshell::geom::native_element* ifcopenshell::geom::Kernel::create_brep_for_representation_and_product(
|
||||
// const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product)
|
||||
// {
|
||||
// std::stringstream representation_id_builder;
|
||||
//
|
||||
//
|
||||
// representation_id_builder << representation->data().id();
|
||||
//
|
||||
//
|
||||
// ifcopenshell::geom::native* shape;
|
||||
// std::vector<ifcopenshell::geom::conversion_result> shapes, shapes2;
|
||||
//
|
||||
//
|
||||
// if (!convert_shapes(representation, shapes)) {
|
||||
// return 0;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// if (settings.get(IteratorSettings::APPLY_LAYERSETS)) {
|
||||
// TopoDS_Shape merge;
|
||||
// if (util::flatten_shape_list(shapes, merge, false, getValue(GV_PRECISION))) {
|
||||
@@ -390,7 +390,7 @@ bool ifcopenshell::geom::open_cascade_kernel::convert_impl(const taxonomy::revol
|
||||
// std::vector< std::vector<Handle_Geom_Surface> > folded_layers;
|
||||
// std::vector<std::shared_ptr<const SurfaceStyle>> styles;
|
||||
// if (convert_layerset(product, layers, styles, thickness)) {
|
||||
//
|
||||
//
|
||||
// IfcSchema::IfcRelAssociates::list::ptr associations = product->HasAssociations();
|
||||
// for (IfcSchema::IfcRelAssociates::list::it it = associations->begin(); it != associations->end(); ++it) {
|
||||
// IfcSchema::IfcRelAssociatesMaterial* associates_material = (**it).as<IfcSchema::IfcRelAssociatesMaterial>();
|
||||
@@ -400,7 +400,7 @@ bool ifcopenshell::geom::open_cascade_kernel::convert_impl(const taxonomy::revol
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//
|
||||
// if (styles.size() > 1) {
|
||||
// // If there's only a single layer there is no need to manipulate geometries.
|
||||
// bool success = true;
|
||||
@@ -415,7 +415,7 @@ bool ifcopenshell::geom::open_cascade_kernel::convert_impl(const taxonomy::revol
|
||||
// success = true;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//
|
||||
// if (!success) {
|
||||
// ifcopenshell::logger::root().error("Failed processing layerset");
|
||||
// }
|
||||
@@ -424,9 +424,9 @@ bool ifcopenshell::geom::open_cascade_kernel::convert_impl(const taxonomy::revol
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//
|
||||
// bool material_style_applied = false;
|
||||
//
|
||||
//
|
||||
// const IfcSchema::IfcMaterial* single_material = get_single_material_association(product);
|
||||
// if (single_material) {
|
||||
// auto s = get_style(single_material);
|
||||
@@ -448,11 +448,11 @@ bool ifcopenshell::geom::open_cascade_kernel::convert_impl(const taxonomy::revol
|
||||
// ifcopenshell::logger::root().warning("No material and surface styles for:", product);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//
|
||||
// if (material_style_applied) {
|
||||
// representation_id_builder << "-material-" << single_material->data().id();
|
||||
// }
|
||||
//
|
||||
//
|
||||
// if (settings.force_space_transparency() >= 0. && product->declaration().is("IfcSpace")) {
|
||||
// for (auto& s : shapes) {
|
||||
// if (s.hasStyle()) {
|
||||
@@ -464,7 +464,7 @@ bool ifcopenshell::geom::open_cascade_kernel::convert_impl(const taxonomy::revol
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//
|
||||
// int parent_id = -1;
|
||||
// try {
|
||||
// express::entity* parent_object = get_decomposing_entity(product);
|
||||
@@ -474,10 +474,10 @@ bool ifcopenshell::geom::open_cascade_kernel::convert_impl(const taxonomy::revol
|
||||
// } catch (const std::exception& e) {
|
||||
// ifcopenshell::logger::root().error(e);
|
||||
// }
|
||||
//
|
||||
//
|
||||
// const std::string name = product->Name().value_or("");
|
||||
// const std::string guid = product->GlobalId();
|
||||
//
|
||||
//
|
||||
// gp_Trsf trsf;
|
||||
// try {
|
||||
// if (product->ObjectPlacement()) {
|
||||
@@ -488,20 +488,20 @@ bool ifcopenshell::geom::open_cascade_kernel::convert_impl(const taxonomy::revol
|
||||
// } catch (...) {
|
||||
// ifcopenshell::logger::root().error("Failed to construct placement");
|
||||
// }
|
||||
//
|
||||
//
|
||||
// // Does the IfcElement have any IfcOpenings?
|
||||
// // Note that openings for IfcOpeningElements are not processed
|
||||
// IfcSchema::IfcRelVoidsElement::list::ptr openings = find_openings(product);
|
||||
//
|
||||
//
|
||||
// const std::string product_type = product->declaration().name();
|
||||
// ElementSettings element_settings(settings, getValue(GV_LENGTH_UNIT), product_type);
|
||||
//
|
||||
//
|
||||
// if (!settings.get(ifcopenshell::geom::IteratorSettings::DISABLE_OPENING_SUBTRACTIONS) && openings && openings->size()) {
|
||||
// representation_id_builder << "-openings";
|
||||
// for (IfcSchema::IfcRelVoidsElement::list::it it = openings->begin(); it != openings->end(); ++it) {
|
||||
// representation_id_builder << "-" << (*it)->data().id();
|
||||
// }
|
||||
//
|
||||
//
|
||||
// std::vector<ifcopenshell::geom::conversion_result> opened_shapes;
|
||||
// bool caught_error = false;
|
||||
// try {
|
||||
@@ -512,11 +512,11 @@ bool ifcopenshell::geom::open_cascade_kernel::convert_impl(const taxonomy::revol
|
||||
// } catch (...) {
|
||||
// ifcopenshell::logger::root().message(ifcopenshell::logger::LOG_ERROR, "error processing openings for:", product);
|
||||
// }
|
||||
//
|
||||
//
|
||||
// if (caught_error && opened_shapes.size() < shapes.size()) {
|
||||
// opened_shapes = shapes;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// if (settings.get(IteratorSettings::USE_WORLD_COORDS)) {
|
||||
// for (std::vector<ifcopenshell::geom::conversion_result>::iterator it = opened_shapes.begin(); it != opened_shapes.end(); ++it) {
|
||||
// it->prepend(trsf);
|
||||
@@ -535,14 +535,14 @@ bool ifcopenshell::geom::open_cascade_kernel::convert_impl(const taxonomy::revol
|
||||
// } else {
|
||||
// shape = new ifcopenshell::geom::native(element_settings, representation_id_builder.str(), shapes);
|
||||
// }
|
||||
//
|
||||
//
|
||||
// std::string context_string = "";
|
||||
// if (representation->RepresentationIdentifier()) {
|
||||
// context_string = *representation->RepresentationIdentifier();
|
||||
// } else if (representation->ContextOfItems()->ContextType()) {
|
||||
// context_string = *representation->ContextOfItems()->ContextType();
|
||||
// }
|
||||
//
|
||||
//
|
||||
// auto elem = new native_element(
|
||||
// product->data().id(),
|
||||
// parent_id,
|
||||
@@ -554,7 +554,7 @@ bool ifcopenshell::geom::open_cascade_kernel::convert_impl(const taxonomy::revol
|
||||
// std::shared_ptr<ifcopenshell::geom::native>(shape),
|
||||
// product
|
||||
// );
|
||||
//
|
||||
//
|
||||
// if (settings.get(IteratorSettings::VALIDATE_QUANTITIES)) {
|
||||
// auto rels = product->IsDefinedBy();
|
||||
// for (auto& rel : *rels) {
|
||||
@@ -623,10 +623,10 @@ bool ifcopenshell::geom::open_cascade_kernel::convert_impl(const taxonomy::revol
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//
|
||||
// return elem;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// IfcSchema::IfcRepresentation* ifcopenshell::geom::Kernel::representation_mapped_to(const IfcSchema::IfcRepresentation* representation) {
|
||||
// IfcSchema::IfcRepresentation* representation_mapped_to = 0;
|
||||
// try {
|
||||
@@ -651,36 +651,36 @@ bool ifcopenshell::geom::open_cascade_kernel::convert_impl(const taxonomy::revol
|
||||
// }
|
||||
// return representation_mapped_to;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// IfcSchema::IfcProduct::list::ptr ifcopenshell::geom::Kernel::products_represented_by(const IfcSchema::IfcRepresentation* representation) {
|
||||
// IfcSchema::IfcProduct::list::ptr products(new IfcSchema::IfcProduct::list);
|
||||
//
|
||||
//
|
||||
// IfcSchema::IfcProductRepresentation::list::ptr prodreps = representation->OfProductRepresentation();
|
||||
//
|
||||
//
|
||||
// for (IfcSchema::IfcProductRepresentation::list::it it = prodreps->begin(); it != prodreps->end(); ++it) {
|
||||
// // http://buildingsmart-tech.org/ifc/IFC2x3/TC1/html/ifcrepresentationresource/lexical/ifcproductrepresentation.htm
|
||||
// // IFC2x Edition 3 NOTE Users should not instantiate the entity IfcProductRepresentation from IFC2x Edition 3 onwards.
|
||||
// // It will be changed into an ABSTRACT supertype in future releases of IFC.
|
||||
//
|
||||
//
|
||||
// // IfcProductRepresentation also lacks the INVERSE relation to IfcProduct
|
||||
// // Let's find the IfcProducts that reference the IfcProductRepresentation anyway
|
||||
// products->push((*it)->data().get_inverse((&IfcSchema::IfcProduct::Class()), -1)->as<IfcSchema::IfcProduct>());
|
||||
// }
|
||||
//
|
||||
//
|
||||
// IfcSchema::IfcRepresentationMap::list::ptr maps = representation->RepresentationMap();
|
||||
//
|
||||
//
|
||||
// if (products->size() && maps->size()) {
|
||||
// ifcopenshell::logger::root().warning("Representation used by IfcRepresentationMap and IfcProductDefinitionShape", representation);
|
||||
// }
|
||||
//
|
||||
//
|
||||
// if (prodreps->size() > 1) {
|
||||
// ifcopenshell::logger::root().warning("Multiple IfcProductDefinitionShapes for representation", representation);
|
||||
// }
|
||||
//
|
||||
//
|
||||
// if (maps->size() > 1) {
|
||||
// ifcopenshell::logger::root().warning("Multiple IfcRepresentationMaps for representation", representation);
|
||||
// }
|
||||
//
|
||||
//
|
||||
// if (maps->size() == 1) {
|
||||
// IfcSchema::IfcRepresentationMap* map = *maps->begin();
|
||||
// if (is_identity_transform(map->MappingOrigin())) {
|
||||
@@ -688,11 +688,11 @@ bool ifcopenshell::geom::open_cascade_kernel::convert_impl(const taxonomy::revol
|
||||
// for (IfcSchema::IfcMappedItem::list::it it = items->begin(); it != items->end(); ++it) {
|
||||
// IfcSchema::IfcMappedptr item = *it;
|
||||
// if (item->StyledByItem()->size() != 0) continue;
|
||||
//
|
||||
//
|
||||
// if (!is_identity_transform(item->MappingTarget())) {
|
||||
// continue;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// IfcSchema::IfcRepresentation::list::ptr reps = item->data().get_inverse((&IfcSchema::IfcRepresentation::Class()), -1)->as<IfcSchema::IfcRepresentation>();
|
||||
// for (IfcSchema::IfcRepresentation::list::it jt = reps->begin(); jt != reps->end(); ++jt) {
|
||||
// IfcSchema::IfcRepresentation* rep = *jt;
|
||||
@@ -706,10 +706,10 @@ bool ifcopenshell::geom::open_cascade_kernel::convert_impl(const taxonomy::revol
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//
|
||||
// return products;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// ifcopenshell::geom::native_element* ifcopenshell::geom::Kernel::create_brep_for_processed_representation(
|
||||
// const IteratorSettings& /*settings*/, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product,
|
||||
// ifcopenshell::geom::native_element* brep)
|
||||
@@ -723,10 +723,10 @@ bool ifcopenshell::geom::open_cascade_kernel::convert_impl(const taxonomy::revol
|
||||
// } catch (const std::exception& e) {
|
||||
// ifcopenshell::logger::root().error(e);
|
||||
// }
|
||||
//
|
||||
//
|
||||
// const std::string name = product->Name().value_or("");
|
||||
// const std::string guid = product->GlobalId();
|
||||
//
|
||||
//
|
||||
// gp_Trsf trsf;
|
||||
// try {
|
||||
// if (product->ObjectPlacement()) {
|
||||
@@ -737,16 +737,16 @@ bool ifcopenshell::geom::open_cascade_kernel::convert_impl(const taxonomy::revol
|
||||
// } catch (...) {
|
||||
// ifcopenshell::logger::root().error("Failed to construct placement");
|
||||
// }
|
||||
//
|
||||
//
|
||||
// std::string context_string = "";
|
||||
// if (representation->RepresentationIdentifier()) {
|
||||
// context_string = *representation->RepresentationIdentifier();
|
||||
// } else if (representation->ContextOfItems()->ContextType()) {
|
||||
// context_string = *representation->ContextOfItems()->ContextType();
|
||||
// }
|
||||
//
|
||||
//
|
||||
// const std::string product_type = product->declaration().name();
|
||||
//
|
||||
//
|
||||
// return new native_element(
|
||||
// product->data().id(),
|
||||
// parent_id,
|
||||
@@ -759,24 +759,24 @@ bool ifcopenshell::geom::open_cascade_kernel::convert_impl(const taxonomy::revol
|
||||
// product
|
||||
// );
|
||||
// }
|
||||
//
|
||||
//
|
||||
// bool ifcopenshell::geom::Kernel::convert_layerset(const IfcSchema::IfcProduct* product, std::vector<Handle_Geom_Surface>& surfaces, std::vector<std::shared_ptr<const SurfaceStyle>>& styles, std::vector<double>& thicknesses) {
|
||||
//
|
||||
//
|
||||
// }
|
||||
//
|
||||
//
|
||||
// bool ifcopenshell::geom::Kernel::find_wall_end_points(const IfcSchema::IfcWall* wall, gp_Pnt& start, gp_Pnt& end) {
|
||||
// IfcSchema::IfcRepresentation* axis_representation = find_representation(wall, "Axis");
|
||||
// if (!axis_representation) {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// std::vector<conversion_result> items;
|
||||
// {
|
||||
// Kernel temp = *this;
|
||||
// temp.setValue(GV_DIMENSIONALITY, -1.);
|
||||
// temp.convert_shapes(axis_representation, items);
|
||||
// }
|
||||
//
|
||||
//
|
||||
// TopoDS_Vertex a, b;
|
||||
// for (std::vector<conversion_result>::const_iterator it = items.begin(); it != items.end(); ++it) {
|
||||
// TopExp_Explorer exp(it->shape(), TopAbs_VERTEX);
|
||||
@@ -787,36 +787,36 @@ bool ifcopenshell::geom::open_cascade_kernel::convert_impl(const taxonomy::revol
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//
|
||||
// if (a.IsNull() || b.IsNull()) {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// start = BRep_Tool::Pnt(a);
|
||||
// end = BRep_Tool::Pnt(b);
|
||||
//
|
||||
//
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// bool ifcopenshell::geom::Kernel::fold_layers(const IfcSchema::IfcWall* wall, const std::vector<conversion_result>& items, const std::vector<Handle_Geom_Surface>& surfaces, const std::vector<double>& thicknesses, std::vector< std::vector<Handle_Geom_Surface> >& result) {
|
||||
// /*
|
||||
// * @todo isn't it easier to do this based on the non-folded surfaces of
|
||||
// * the connected walls and fold both pairs of layersets simultaneously?
|
||||
// */
|
||||
//
|
||||
//
|
||||
// bool folds_made = false;
|
||||
//
|
||||
//
|
||||
// IfcSchema::IfcRelConnectsPathElements::list::ptr connections(new IfcSchema::IfcRelConnectsPathElements::list);
|
||||
// connections->push(wall->ConnectedFrom()->as<IfcSchema::IfcRelConnectsPathElements>());
|
||||
// connections->push(wall->ConnectedTo()->as<IfcSchema::IfcRelConnectsPathElements>());
|
||||
//
|
||||
//
|
||||
// typedef std::vector<Handle_Geom_Surface> surfaces_t;
|
||||
// typedef std::pair<Handle_Geom_Surface, Handle_Geom_Curve> curve_on_surface;
|
||||
// typedef std::vector<curve_on_surface> curves_on_surfaces_t;
|
||||
// typedef std::vector< std::pair< std::pair<IfcSchema::IfcConnectionTypeEnum::Value, IfcSchema::IfcConnectionTypeEnum::Value>, const IfcSchema::IfcProduct*> > endpoint_connections_t;
|
||||
// typedef std::vector< std::vector<Handle_Geom_Surface> > result_t;
|
||||
// endpoint_connections_t endpoint_connections;
|
||||
//
|
||||
//
|
||||
// // Find the semantic connections to other wall elements when they are not connected 'AT_PATH' because
|
||||
// // in that latter case no folds need to be made.
|
||||
// for (IfcSchema::IfcRelConnectsPathElements::list::it it = connections->begin(); it != connections->end(); ++it) {
|
||||
@@ -838,18 +838,18 @@ bool ifcopenshell::geom::open_cascade_kernel::convert_impl(const taxonomy::revol
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//
|
||||
// if (endpoint_connections.size() == 0) {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// // Count how many connections are made AT_START and AT_END respectively
|
||||
// int connection_type_count[2] = { 0,0 };
|
||||
// for (endpoint_connections_t::const_iterator it = endpoint_connections.begin(); it != endpoint_connections.end(); ++it) {
|
||||
// const int idx = it->first.first == IfcSchema::IfcConnectionTypeEnum::IfcConnectionType_ATSTART;
|
||||
// connection_type_count[idx] ++;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// gp_Trsf local;
|
||||
// if (wall->ObjectPlacement()) {
|
||||
// if (!convert(wall->ObjectPlacement(), local)) {
|
||||
@@ -857,7 +857,7 @@ bool ifcopenshell::geom::open_cascade_kernel::convert_impl(const taxonomy::revol
|
||||
// }
|
||||
// }
|
||||
// local.Invert();
|
||||
//
|
||||
//
|
||||
// {
|
||||
// // Copy the unfolded surfaces
|
||||
// result.resize(surfaces.size());
|
||||
@@ -867,25 +867,25 @@ bool ifcopenshell::geom::open_cascade_kernel::convert_impl(const taxonomy::revol
|
||||
// result_it->push_back(*input_it);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//
|
||||
// const double total_thickness = std::accumulate(thicknesses.begin(), thicknesses.end(), 0.);
|
||||
//
|
||||
//
|
||||
// gp_Pnt own_axis_start, own_axis_end;
|
||||
// find_wall_end_points(wall, own_axis_start, own_axis_end);
|
||||
//
|
||||
//
|
||||
// // Sometimes duplicate IfcRelConnectsPathElements exist. These are detected
|
||||
// // and the counts of connections are decremented accordingly.
|
||||
// for (int idx = 0; idx < 2; ++idx) {
|
||||
// if (connection_type_count[idx] <= 1) {
|
||||
// continue;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// /*
|
||||
// IfcSchema::IfcConnectionTypeEnum::Value connection_type = idx == 1
|
||||
// ? IfcSchema::IfcConnectionTypeEnum::IfcConnectionType_ATSTART
|
||||
// : IfcSchema::IfcConnectionTypeEnum::IfcConnectionType_ATEND;
|
||||
// */
|
||||
//
|
||||
//
|
||||
// std::set<const IfcSchema::IfcProduct*> others;
|
||||
// endpoint_connections_t::iterator it = endpoint_connections.begin();
|
||||
// while (it != endpoint_connections.end()) {
|
||||
@@ -899,38 +899,38 @@ bool ifcopenshell::geom::open_cascade_kernel::convert_impl(const taxonomy::revol
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//
|
||||
// // Check whether the end points are of the wall are really ~1 LayerThickness away from each other
|
||||
// /*
|
||||
// for (endpoint_connections_t::const_iterator it = endpoint_connections.begin(); it != endpoint_connections.end(); ++it) {
|
||||
// IfcSchema::IfcConnectionTypeEnum::Value own_type = it->first.first;
|
||||
// IfcSchema::IfcConnectionTypeEnum::Value other_type = it->first.second;
|
||||
//
|
||||
//
|
||||
// gp_Pnt other_axis_start, other_axis_end;
|
||||
// find_wall_end_points(it->second->as<IfcSchema::IfcWall>(), other_axis_start, other_axis_end);
|
||||
//
|
||||
//
|
||||
// gp_Trsf other;
|
||||
// if (!convert(it->second->ObjectPlacement(), other)) {
|
||||
// continue;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// other.Transforms(other_axis_start.ChangeCoord());
|
||||
// local.Transforms(other_axis_start.ChangeCoord());
|
||||
// other.Transforms(other_axis_end.ChangeCoord());
|
||||
// local.Transforms(other_axis_end.ChangeCoord());
|
||||
//
|
||||
//
|
||||
// const gp_Pnt& a = own_type == IfcSchema::IfcConnectionTypeEnum::IfcConnectionType_ATSTART
|
||||
// ? own_axis_start
|
||||
// : own_axis_end;
|
||||
//
|
||||
//
|
||||
// const gp_Pnt& b = other_type == IfcSchema::IfcConnectionTypeEnum::IfcConnectionType_ATSTART
|
||||
// ? other_axis_start
|
||||
// : other_axis_end;
|
||||
//
|
||||
//
|
||||
// const double d = a.Distance(b);
|
||||
// }
|
||||
// */
|
||||
//
|
||||
//
|
||||
// const double length_required = endpoint_connections.size() * total_thickness;
|
||||
// // @todo this is not precisely the distance in case of curved walls. Also, it's safer
|
||||
// // to first reproject the body onto the axis to get the precise curve parametrization
|
||||
@@ -940,20 +940,20 @@ bool ifcopenshell::geom::open_cascade_kernel::convert_impl(const taxonomy::revol
|
||||
// ifcopenshell::logger::root().warning("The wall axis is not long enough to accommodate the fold points");
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// for (endpoint_connections_t::const_iterator it = endpoint_connections.begin(); it != endpoint_connections.end(); ++it) {
|
||||
// IfcSchema::IfcConnectionTypeEnum::Value connection_type = it->first.first;
|
||||
//
|
||||
//
|
||||
// // If more than one wall connects to this start/end -point assume layers do not need to be folded
|
||||
// const int idx = connection_type == IfcSchema::IfcConnectionTypeEnum::IfcConnectionType_ATSTART;
|
||||
// if (connection_type_count[idx] > 1) continue;
|
||||
//
|
||||
//
|
||||
// // Pick the corresponding point from the axis
|
||||
// const gp_Pnt& own_end_point = connection_type == IfcSchema::IfcConnectionTypeEnum::IfcConnectionType_ATEND
|
||||
// ? own_axis_end
|
||||
// : own_axis_start;
|
||||
// const IfcSchema::IfcProduct* other_wall = it->second;
|
||||
//
|
||||
//
|
||||
// gp_Trsf other;
|
||||
// if (other_wall->ObjectPlacement()) {
|
||||
// if (!convert(other_wall->ObjectPlacement(), other)) {
|
||||
@@ -961,32 +961,32 @@ bool ifcopenshell::geom::open_cascade_kernel::convert_impl(const taxonomy::revol
|
||||
// continue;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//
|
||||
// IfcSchema::IfcRepresentation* axis_representation = find_representation(other_wall, "Axis");
|
||||
//
|
||||
//
|
||||
// if (!axis_representation) {
|
||||
// ifcopenshell::logger::root().warning("Joined wall has no axis representation", other_wall);
|
||||
// continue;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// std::vector<conversion_result> axis_items;
|
||||
// {
|
||||
// Kernel temp = *this;
|
||||
// temp.setValue(GV_DIMENSIONALITY, -1.);
|
||||
// temp.convert_shapes(axis_representation, axis_items);
|
||||
// }
|
||||
//
|
||||
//
|
||||
// TopoDS_Shape axis_shape;
|
||||
// util::flatten_shape_list(axis_items, axis_shape, false, getValue(GV_PRECISION));
|
||||
//
|
||||
//
|
||||
// // local and other are IfcLocalPlacements and therefore have a unit
|
||||
// // scale factor that can be applied by means of TopoDS_Shape::Move()
|
||||
// axis_shape.Move(other);
|
||||
// axis_shape.Move(local);
|
||||
//
|
||||
//
|
||||
// TopoDS_Shape body_shape;
|
||||
// util::flatten_shape_list(items, body_shape, false, getValue(GV_PRECISION));
|
||||
//
|
||||
//
|
||||
// // Create a single paremetric range over a single curve
|
||||
// // that represents the entire 1d domain of the other wall
|
||||
// // Sometimes there are multiple edges in the Axis shape
|
||||
@@ -998,19 +998,19 @@ bool ifcopenshell::geom::open_cascade_kernel::convert_impl(const taxonomy::revol
|
||||
// if (!exp.More()) {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// TopoDS_Edge axis_edge = TopoDS::Edge(exp.Current());
|
||||
// other_axis_curve = BRep_Tool::Curve(axis_edge, axis_u1, axis_u2);
|
||||
//
|
||||
//
|
||||
// gp_Pnt other_a_1, other_a_2;
|
||||
// other_axis_curve->D0(axis_u1, other_a_1);
|
||||
// other_axis_curve->D0(axis_u2, other_a_2);
|
||||
//
|
||||
//
|
||||
// if (axis_u2 < axis_u1) {
|
||||
// std::swap(axis_u1, axis_u2);
|
||||
// }
|
||||
// exp.Next();
|
||||
//
|
||||
//
|
||||
// for (; exp.More(); exp.Next()) {
|
||||
// TopoDS_Edge axis_edge2 = TopoDS::Edge(exp.Current());
|
||||
// TopExp_Explorer exp2(axis_edge2, TopAbs_VERTEX);
|
||||
@@ -1025,22 +1025,22 @@ bool ifcopenshell::geom::open_cascade_kernel::convert_impl(const taxonomy::revol
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//
|
||||
// double layer_offset = 0;
|
||||
//
|
||||
//
|
||||
// std::vector<double>::const_iterator thickness = thicknesses.begin();
|
||||
// result_t::iterator result_vector = result.begin() + 1;
|
||||
//
|
||||
//
|
||||
// // nb The first layer is never folded, because it corresponds
|
||||
// // to one of the longitudinal faces of the wall. Hence the +1
|
||||
// for (surfaces_t::const_iterator jt = surfaces.begin() + 1; jt != surfaces.end() - 1; ++jt, ++result_vector) {
|
||||
// layer_offset += *thickness++;
|
||||
//
|
||||
//
|
||||
// bool found_intersection = false, parallel = false;
|
||||
// std::optional<gp_Pnt> point_outside_param_range;
|
||||
//
|
||||
//
|
||||
// const Handle_Geom_Surface& surface = *jt;
|
||||
//
|
||||
//
|
||||
// // Find the intersection point between the layerset surface
|
||||
// // and the other axis curve. If it's within the parametric
|
||||
// // range of the other wall it means the walls are connected
|
||||
@@ -1048,16 +1048,16 @@ bool ifcopenshell::geom::open_cascade_kernel::convert_impl(const taxonomy::revol
|
||||
// GeomAPI_IntCS intersections(other_axis_curve, surface);
|
||||
// if (intersections.IsDone() && intersections.NbPoints() == 1) {
|
||||
// const gp_Pnt& p = intersections.Point(1);
|
||||
//
|
||||
//
|
||||
// double u, v, w;
|
||||
// intersections.Parameters(1, u, v, w);
|
||||
//
|
||||
//
|
||||
// gp_Pnt Pc, Ps;
|
||||
// gp_Vec Vc, Vs1, Vs2;
|
||||
// other_axis_curve->D1(w, Pc, Vc);
|
||||
// surface->D1(u, v, Ps, Vs1, Vs2);
|
||||
// Vs1.Cross(Vs2);
|
||||
//
|
||||
//
|
||||
// if (Vs1.IsNormal(Vc, 1.e-5)) {
|
||||
// ifcopenshell::logger::root().warning("Connected walls are parallel");
|
||||
// parallel = true;
|
||||
@@ -1069,9 +1069,9 @@ bool ifcopenshell::geom::open_cascade_kernel::convert_impl(const taxonomy::revol
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//
|
||||
// if (!parallel && !found_intersection && point_outside_param_range) {
|
||||
//
|
||||
//
|
||||
// /*
|
||||
// Is there a bug in Open Cascade related to the intersection
|
||||
// of offset surfaces constructed from linear extrusions?
|
||||
@@ -1083,13 +1083,13 @@ bool ifcopenshell::geom::open_cascade_kernel::convert_impl(const taxonomy::revol
|
||||
// Handle_Geom_Surface yz2 = new Geom_OffsetSurface(yz, 1.);
|
||||
// intersect(xy, yz2);
|
||||
// */
|
||||
//
|
||||
//
|
||||
// Handle_Geom_Surface plane = new Geom_Plane(*point_outside_param_range, gp::DZ());
|
||||
//
|
||||
//
|
||||
// // vertical edges at wall end point face.
|
||||
// curves_on_surfaces_t layer_ends;
|
||||
// util::intersect(surface, body_shape, layer_ends);
|
||||
//
|
||||
//
|
||||
// Handle_Geom_Curve layer_body_intersection;
|
||||
// Handle_Geom_Surface body_surface;
|
||||
// double mind = std::numeric_limits<double>::infinity();
|
||||
@@ -1111,9 +1111,9 @@ bool ifcopenshell::geom::open_cascade_kernel::convert_impl(const taxonomy::revol
|
||||
// if (d < total_thickness * 3 && d < mind) {
|
||||
// GeomAdaptor_Curve GAC(other_axis_curve);
|
||||
// GeomAdaptor_Surface GAS(kt->first);
|
||||
//
|
||||
//
|
||||
// Extrema_ExtCS x(GAC, GAS, getValue(GV_PRECISION), getValue(GV_PRECISION));
|
||||
//
|
||||
//
|
||||
// if (x.IsParallel()) {
|
||||
// body_surface = kt->first;
|
||||
// layer_body_intersection = kt->second;
|
||||
@@ -1122,16 +1122,16 @@ bool ifcopenshell::geom::open_cascade_kernel::convert_impl(const taxonomy::revol
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//
|
||||
// if (body_surface.IsNull()) {
|
||||
// continue;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// // Intersect vertical edge with ground plane for point.
|
||||
// GeomAPI_IntCS intersection2(layer_body_intersection, plane);
|
||||
// if (intersection2.IsDone() && intersection2.NbPoints() == 1) {
|
||||
// const gp_Pnt& layer_end_point = intersection2.Point(1);
|
||||
//
|
||||
//
|
||||
// // Intersect layerset surface with ground plane
|
||||
// GeomAPI_IntSS intersection3(surface, plane, 1.e-7);
|
||||
// if (intersection3.IsDone() && intersection3.NbLines() == 1) {
|
||||
@@ -1140,14 +1140,14 @@ bool ifcopenshell::geom::open_cascade_kernel::convert_impl(const taxonomy::revol
|
||||
// ShapeAnalysis_Curve sac;
|
||||
// gp_Pnt layer_end_point_projected; double layer_end_point_param;
|
||||
// sac.Project(layer_line, layer_end_point, 1e-3, layer_end_point_projected, layer_end_point_param, false);
|
||||
//
|
||||
//
|
||||
// // Move point inwards by distance from other layerset
|
||||
// GCPnts_AbscissaPoint dst(layer_line_adaptor, layer_offset, layer_end_point_param);
|
||||
// if (dst.IsDone()) {
|
||||
// // Convert parameter to point
|
||||
// gp_Pnt layer_fold_point;
|
||||
// layer_line->D0(dst.Parameter(), layer_fold_point);
|
||||
//
|
||||
//
|
||||
// GeomAPI_IntSS intersection4(body_surface, plane, 1.e-7);
|
||||
// if (intersection4.IsDone() && intersection4.NbLines() == 1) {
|
||||
// Handle_Geom_Curve body_trim_curve = intersection4.Line(1);
|
||||
@@ -1155,7 +1155,7 @@ bool ifcopenshell::geom::open_cascade_kernel::convert_impl(const taxonomy::revol
|
||||
// gp_Pnt layer_fold_point_projected; double layer_fold_point_param;
|
||||
// sac2.Project(body_trim_curve, layer_fold_point, 1.e-7, layer_fold_point_projected, layer_fold_point_param, false);
|
||||
// Handle_Geom_Curve fold_curve = new Geom_OffsetCurve(body_trim_curve->Reversed(), layer_fold_point_projected.Distance(layer_fold_point), gp::DZ());
|
||||
//
|
||||
//
|
||||
// Handle_Geom_Surface fold_surface = new Geom_SurfaceOfLinearExtrusion(fold_curve, gp::DZ());
|
||||
// result_vector->push_back(fold_surface);
|
||||
// folds_made = true;
|
||||
@@ -1163,15 +1163,15 @@ bool ifcopenshell::geom::open_cascade_kernel::convert_impl(const taxonomy::revol
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//
|
||||
// }
|
||||
//
|
||||
//
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//
|
||||
// return folds_made;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// IfcSchema::IfcRepresentation* ifcopenshell::geom::Kernel::find_representation(const IfcSchema::IfcProduct* product, const std::string& identifier) {
|
||||
// if (!product->Representation()) return 0;
|
||||
// IfcSchema::IfcProductRepresentation* prod_rep = product->Representation();
|
||||
@@ -1183,12 +1183,12 @@ bool ifcopenshell::geom::open_cascade_kernel::convert_impl(const taxonomy::revol
|
||||
// }
|
||||
// return 0;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// const IfcSchema::IfcRepresentationptr ifcopenshell::geom::Kernel::find_item_carrying_style(const IfcSchema::IfcRepresentationptr item) {
|
||||
// if (item->StyledByItem()->size()) {
|
||||
// return item;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// while (item->declaration().is(IfcSchema::IfcBooleanResult::Class())) {
|
||||
// // All instantiations of IfcBooleanOperand (type of FirstOperand) are subtypes of
|
||||
// // IfcGeometricRepresentationItem
|
||||
@@ -1197,24 +1197,24 @@ bool ifcopenshell::geom::open_cascade_kernel::convert_impl(const taxonomy::revol
|
||||
// return item;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//
|
||||
// // TODO: Ideally this would be done for other entities (such as IfcCsgSolid) as well.
|
||||
// // But neither are these very prevalent, nor does the current IfcOpenShell style
|
||||
// // mechanism enable to conveniently style subshapes, which would be necessary for
|
||||
// // distinctly styled union operands.
|
||||
//
|
||||
//
|
||||
// return item;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// bool ifcopenshell::geom::Kernel::is_identity_transform(ifcopenshell::IfcBaseInterface* l) {
|
||||
// IfcSchema::IfcAxis2Placement2D* ax2d;
|
||||
// IfcSchema::IfcAxis2Placement3D* ax3d;
|
||||
//
|
||||
//
|
||||
// IfcSchema::IfcCartesianTransformationOperator2D* op2d;
|
||||
// IfcSchema::IfcCartesianTransformationOperator3D* op3d;
|
||||
// IfcSchema::IfcCartesianTransformationOperator2DnonUniform* op2dnonu;
|
||||
// IfcSchema::IfcCartesianTransformationOperator3DnonUniform* op3dnonu;
|
||||
//
|
||||
//
|
||||
// if ((op2dnonu = l->as<IfcSchema::IfcCartesianTransformationOperator2DnonUniform>()) != 0) {
|
||||
// gp_GTrsf2d gtrsf2d;
|
||||
// convert(op2dnonu, gtrsf2d);
|
||||
@@ -1243,18 +1243,18 @@ bool ifcopenshell::geom::open_cascade_kernel::convert_impl(const taxonomy::revol
|
||||
// throw ifcopenshell::exception("Invalid valuation for IfcAxis2Placement / IfcCartesianTransformationOperator");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//
|
||||
// void ifcopenshell::geom::Kernel::set_conversion_placement_rel_to_type(const ifcopenshell::declaration* type) {
|
||||
// placement_rel_to_type_ = type;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// void ifcopenshell::geom::Kernel::set_conversion_placement_rel_to_instance(const express::entity* instance) {
|
||||
// placement_rel_to_instance_ = instance;
|
||||
// }
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
// namespace {
|
||||
//
|
||||
//
|
||||
// bool process_colour(IfcSchema::IfcColourRgb* colour, double* rgb) {
|
||||
// if (colour != 0) {
|
||||
// rgb[0] = colour->Red();
|
||||
@@ -1263,7 +1263,7 @@ bool ifcopenshell::geom::open_cascade_kernel::convert_impl(const taxonomy::revol
|
||||
// }
|
||||
// return colour != 0;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// bool process_colour(IfcSchema::IfcNormalisedRatioMeasure* factor, double* rgb) {
|
||||
// if (factor != 0) {
|
||||
// const double f = *factor;
|
||||
@@ -1271,7 +1271,7 @@ bool ifcopenshell::geom::open_cascade_kernel::convert_impl(const taxonomy::revol
|
||||
// }
|
||||
// return factor != 0;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// bool process_colour(IfcSchema::IfcColourOrFactor* colour_or_factor, double* rgb) {
|
||||
// if (colour_or_factor == 0) {
|
||||
// return false;
|
||||
@@ -1283,11 +1283,11 @@ bool ifcopenshell::geom::open_cascade_kernel::convert_impl(const taxonomy::revol
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//
|
||||
// }
|
||||
//
|
||||
//
|
||||
// #define Kernel POSTFIX_SCHEMA(Kernel)
|
||||
//
|
||||
//
|
||||
// std::shared_ptr<const ifcopenshell::geom::SurfaceStyle> ifcopenshell::geom::Kernel::internalize_surface_style(const std::pair<express::base, express::base>& shading_styles) {
|
||||
// if (shading_styles.second == 0) {
|
||||
// return 0;
|
||||
@@ -1297,22 +1297,22 @@ bool ifcopenshell::geom::open_cascade_kernel::convert_impl(const taxonomy::revol
|
||||
// if (it != style_cache.end()) {
|
||||
// return it->second;
|
||||
// }
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
// IfcSchema::IfcSurfaceStyle* style = shading_styles.first->as<IfcSchema::IfcSurfaceStyle>();
|
||||
// IfcSchema::IfcSurfaceStyleShading* shading = shading_styles.second->as<IfcSchema::IfcSurfaceStyleShading>();
|
||||
//
|
||||
//
|
||||
// std::shared_ptr<SurfaceStyle> surface_style_ptr;
|
||||
//
|
||||
//
|
||||
// if (style->Name()) {
|
||||
// surface_style_ptr.reset(new SurfaceStyle(surface_style_id, *style->Name()));
|
||||
// } else {
|
||||
// surface_style_ptr.reset(new SurfaceStyle(surface_style_id));
|
||||
// }
|
||||
//
|
||||
//
|
||||
// std::shared_ptr<const SurfaceStyle> surface_style_ptr_const = std::const_pointer_cast<const SurfaceStyle>(surface_style_ptr);
|
||||
// SurfaceStyle& surface_style = *surface_style_ptr;
|
||||
//
|
||||
//
|
||||
// double rgb[3];
|
||||
// if (process_colour(shading->SurfaceColour(), rgb)) {
|
||||
// surface_style.Diffuse().reset(SurfaceStyle::ColorComponent(rgb[0], rgb[1], rgb[2]));
|
||||
@@ -1353,11 +1353,11 @@ bool ifcopenshell::geom::open_cascade_kernel::convert_impl(const taxonomy::revol
|
||||
// }
|
||||
// return style_cache[surface_style_id] = surface_style_ptr_const;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// std::shared_ptr<const ifcopenshell::geom::SurfaceStyle> ifcopenshell::geom::Kernel::get_style(const IfcSchema::IfcRepresentationptr item) {
|
||||
// return internalize_surface_style(get_surface_style<IfcSchema::IfcSurfaceStyleShading>(item));
|
||||
// }
|
||||
//
|
||||
//
|
||||
// std::shared_ptr<const ifcopenshell::geom::SurfaceStyle> ifcopenshell::geom::Kernel::get_style(const IfcSchema::IfcMaterial* material) {
|
||||
// IfcSchema::IfcMaterialDefinitionRepresentation::list::ptr defs = material->HasRepresentation();
|
||||
// for (IfcSchema::IfcMaterialDefinitionRepresentation::list::it jt = defs->begin(); jt != defs->end(); ++jt) {
|
||||
@@ -1376,14 +1376,14 @@ bool ifcopenshell::geom::open_cascade_kernel::convert_impl(const taxonomy::revol
|
||||
// auto material_style = std::make_shared<ifcopenshell::geom::SurfaceStyle>(material->data().id(), material->Name());
|
||||
// return style_cache[material->data().id()] = material_style;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// void ifcopenshell::geom::Kernel::apply_layerset(std::vector<ifcopenshell::geom::conversion_result>& r, const ifcopenshell::geom::layerset_information& info) {
|
||||
// convert(info.layers);
|
||||
//
|
||||
//
|
||||
// if (info.layers.empty()) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// if (axis_curve->DynamicType() == STANDARD_TYPE(Geom_Line)) {
|
||||
// Handle_Geom_Line axis_line = Handle_Geom_Line::DownCast(axis_curve);
|
||||
// // @todo note that this creates an offset into the wrong order, the cross product arguments should be
|
||||
@@ -1397,7 +1397,7 @@ bool ifcopenshell::geom::open_cascade_kernel::convert_impl(const taxonomy::revol
|
||||
// ifcopenshell::logger::root().message(ifcopenshell::logger::LOG_ERROR, "Unsupported underlying curve of Axis representation:", product);
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// std::vector<ifcopenshell::geom::conversion_result> r2;
|
||||
// if (ifcopenshell::geom::util::apply_layerset(r, const std::vector<ifcopenshell::geom::taxonomy::style>&, std::vector<conversion_result>& r2, double tol)) {
|
||||
// std::swap(r, r2)
|
||||
|
||||
@@ -90,7 +90,7 @@ private:
|
||||
std::map<std::pair<int, int>, TopoDS_Edge> edges_;
|
||||
double eps_;
|
||||
bool non_manifold_;
|
||||
|
||||
|
||||
void loop_(const ifcopenshell::geom::taxonomy::loop::ptr ps, const std::function<void(int, int, bool)>& callback);
|
||||
public:
|
||||
faceset_helper(open_cascade_kernel* kernel, const ifcopenshell::geom::taxonomy::shell::ptr l);
|
||||
@@ -99,7 +99,7 @@ private:
|
||||
bool non_manifold() const { return non_manifold_; }
|
||||
bool& non_manifold() { return non_manifold_; }
|
||||
double epsilon() const { return eps_; }
|
||||
|
||||
|
||||
bool edge(int A, int B, TopoDS_Edge& e);
|
||||
|
||||
bool wire(const ifcopenshell::geom::taxonomy::loop::ptr loop, TopoDS_Wire& wire);
|
||||
|
||||
@@ -64,8 +64,8 @@ bool open_cascade_kernel::convert(const taxonomy::solid::ptr solid, TopoDS_Shape
|
||||
|
||||
result = halfspace;
|
||||
return true;
|
||||
} else if (solid->children.size() == 1
|
||||
&& solid->children[0]->children.size() == 1
|
||||
} else if (solid->children.size() == 1
|
||||
&& solid->children[0]->children.size() == 1
|
||||
&& solid->children[0]->children[0]->basis
|
||||
&& solid->children[0]->children[0]->basis->kind() == taxonomy::SPHERE)
|
||||
{
|
||||
|
||||
@@ -126,7 +126,7 @@ bool open_cascade_kernel::convert(const taxonomy::sweep_along_curve::ptr scs, To
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Build the wire from curve, which is the directrix offset toward the origin
|
||||
// when applied_temporary_offset is set. Using scs->curve here left the wire
|
||||
// far from the origin yet still translated the result back by +mean, which
|
||||
@@ -155,11 +155,11 @@ bool open_cascade_kernel::convert(const taxonomy::sweep_along_curve::ptr scs, To
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Handle(Geom_Surface) surface;
|
||||
if (scs->surface) {
|
||||
surface = convert_surface(scs->surface);
|
||||
}
|
||||
}
|
||||
|
||||
gp_Trsf directrix;
|
||||
TopoDS_Wire wire = std::get<TopoDS_Wire>(w);
|
||||
|
||||
@@ -201,12 +201,12 @@ namespace ifcopenshell::geom {
|
||||
box.corners[1][1] = static_cast<float>(max_point[1] + 1e-5);
|
||||
box.corners[1][2] = static_cast<float>(max_point[2] + 1e-5);
|
||||
/*
|
||||
std::cout << "Ray "
|
||||
std::cout << "Ray "
|
||||
<< v_ray.origin[0] << " "
|
||||
<< v_ray.origin[1] << " "
|
||||
<< v_ray.origin[2] << " "
|
||||
<< std::endl;
|
||||
std::cout << "Box "
|
||||
std::cout << "Box "
|
||||
<< min_point[0] << " "
|
||||
<< min_point[1] << " "
|
||||
<< min_point[2] << " "
|
||||
@@ -864,7 +864,7 @@ namespace ifcopenshell::geom {
|
||||
if (dss.Value() <= extend) {
|
||||
distances_.push_back(dss.Value());
|
||||
protrusion_distances_.push_back(max_distance_inside(B, A));
|
||||
}
|
||||
}
|
||||
return dss.Value() <= extend;
|
||||
}
|
||||
} else {
|
||||
@@ -925,8 +925,8 @@ namespace ifcopenshell::geom {
|
||||
// Gap is assumed to be positive throughout the codebase,
|
||||
// but at least for IsOut() in the selector a negative
|
||||
// Gap should work as well.
|
||||
b.SetGap(b.GetGap() + extend);
|
||||
|
||||
b.SetGap(b.GetGap() + extend);
|
||||
|
||||
return select_box(b, completely_within);
|
||||
}
|
||||
|
||||
@@ -956,7 +956,7 @@ namespace ifcopenshell::geom {
|
||||
double gap = B.GetGap();
|
||||
gp_Pnt p1(x1 - gap, y1 - gap, z1 - gap);
|
||||
gp_Pnt p2(x2 + gap, y2 + gap, z2 + gap);
|
||||
|
||||
|
||||
if (!b.IsOut(p1) && !b.IsOut(p2)) {
|
||||
ts_filtered.push_back(*it);
|
||||
}
|
||||
@@ -1389,7 +1389,7 @@ namespace ifcopenshell::geom {
|
||||
if (extend > 0.0) {
|
||||
BRepExtrema_DistShapeShape dss(v, B);
|
||||
if (dss.Perform() && dss.NbSolution() >= 1 && dss.Value() <= extend) {
|
||||
distances_.push_back(dss.Value());
|
||||
distances_.push_back(dss.Value());
|
||||
protrusion_distances_.push_back(max_distance_inside(B, v));
|
||||
|
||||
ts_filtered.push_back(*it);
|
||||
@@ -1416,9 +1416,9 @@ namespace ifcopenshell::geom {
|
||||
spatial_tree tree_;
|
||||
shape_map shapes_;
|
||||
std::map<T, Bnd_Box> aabbs_;
|
||||
std::map<T, Bnd_OBB> obbs_;
|
||||
std::map<T, double> max_protrusions_;
|
||||
std::map<T, opencascade::handle<BVH_Tree<double, 3, BVH_BinaryTree>>> bvhs_;
|
||||
std::map<T, Bnd_OBB> obbs_;
|
||||
std::map<T, double> max_protrusions_;
|
||||
std::map<T, opencascade::handle<BVH_Tree<double, 3, BVH_BinaryTree>>> bvhs_;
|
||||
std::unordered_map<T, bool> is_manifold_;
|
||||
std::unordered_map<T, std::vector<std::array<int, 3>>> tris_;
|
||||
std::unordered_map<T, std::vector<gp_Pnt>> verts_;
|
||||
@@ -1433,7 +1433,7 @@ namespace ifcopenshell::geom {
|
||||
std::map<std::string, std::vector<int>> local_faces_;
|
||||
std::map<std::string, std::vector<ifcopenshell::geom::taxonomy::style::ptr>> local_materials_;
|
||||
std::map<std::string, std::vector<int>> local_material_ids_;
|
||||
|
||||
|
||||
bool enable_face_styles_ = false;
|
||||
|
||||
class selector : public spatial_tree::Selector
|
||||
@@ -1480,7 +1480,7 @@ namespace ifcopenshell::geom {
|
||||
|
||||
opencascade_tree(ifcopenshell::geom::iterator& it) {
|
||||
add_file(it);
|
||||
}
|
||||
}
|
||||
|
||||
void add_file(ifcopenshell::file& f, ifcopenshell::geom::settings settings) {
|
||||
ifcopenshell::geom::settings settings_ = settings;
|
||||
@@ -1509,7 +1509,7 @@ namespace ifcopenshell::geom {
|
||||
result.reserve(flat_list.size());
|
||||
|
||||
for (size_t i = 0; i < flat_list.size(); i += 3) {
|
||||
vin <<
|
||||
vin <<
|
||||
flat_list[i],
|
||||
flat_list[i + 1],
|
||||
flat_list[i + 2];
|
||||
@@ -1576,7 +1576,7 @@ namespace ifcopenshell::geom {
|
||||
vs_transformed.push_back(p.Transformed(tr));
|
||||
aabb.Add(vs_transformed.back());
|
||||
}
|
||||
|
||||
|
||||
std::unordered_map<std::tuple<int, int, int>, std::vector<size_t>, boost::hash<std::tuple<int, int, int>>> quantized_normal_counts;
|
||||
|
||||
std::vector<double> tri_areas;
|
||||
@@ -1631,7 +1631,7 @@ namespace ifcopenshell::geom {
|
||||
|
||||
gp_Ax3 ax3;
|
||||
gp_Trsf trsf2;
|
||||
|
||||
|
||||
for (size_t attempt = 0; attempt < 2; ++attempt) {
|
||||
|
||||
if (candidates.empty() || attempt == 1) {
|
||||
@@ -1673,7 +1673,7 @@ namespace ifcopenshell::geom {
|
||||
obb.SetZComponent(ax3.Direction(), halfsize.Z());
|
||||
obb.SetCenter(cent.Transformed(trsf2.Inverted()));
|
||||
}
|
||||
|
||||
|
||||
const auto& t = elem->product();
|
||||
const auto& matrix = elem->transformation().data();
|
||||
const std::vector<double>& elem_verts_local = elem->geometry().verts();
|
||||
@@ -1744,7 +1744,7 @@ namespace ifcopenshell::geom {
|
||||
obbs_[t] = obb;
|
||||
max_protrusions_[t] = std::min(std::min(obb.XHSize(), obb.YHSize()), obb.ZHSize()) * 2;
|
||||
}
|
||||
|
||||
|
||||
void add_element(ifcopenshell::geom::native_element* elem) {
|
||||
if (!elem) {
|
||||
return;
|
||||
@@ -1753,7 +1753,7 @@ namespace ifcopenshell::geom {
|
||||
auto compound_generic = (ifcopenshell::geom::open_cascade_shape*)elem->geometry().as_compound();
|
||||
TopoDS_Shape compound(std::move(compound_generic->shape()));
|
||||
delete compound_generic;
|
||||
|
||||
|
||||
const auto& m = elem->transformation().data()->ccomponents();
|
||||
gp_Trsf tr;
|
||||
tr.SetValues(
|
||||
|
||||
@@ -381,7 +381,7 @@ namespace {
|
||||
bool ifcopenshell::geom::util::wire_intersections(const TopoDS_Wire& wire, NCollection_List<TopoDS_Shape>& wires, const wire_tolerance_settings& settings) {
|
||||
double eps = get_wire_intersection_tolerance(settings, wire);
|
||||
double eps_real = settings.precision;
|
||||
|
||||
|
||||
if (!wire.Closed()) {
|
||||
wires.Append(wire);
|
||||
return false;
|
||||
@@ -576,7 +576,7 @@ void ifcopenshell::geom::util::select_largest(const NCollection_List<TopoDS_Shap
|
||||
BRepBndLib::AddClose(it.Value(), bb);
|
||||
double xyz_min[3], xyz_max[3];
|
||||
bb.Get(xyz_min[0], xyz_min[1], xyz_min[2], xyz_max[0], xyz_max[1], xyz_max[2]);
|
||||
|
||||
|
||||
// @todo hard coded precision.
|
||||
// @todo this is a really strange measure for wire size. Why not use newell's
|
||||
// method to project to plane and then calculate size of the 2d bbox?
|
||||
|
||||
@@ -45,7 +45,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcArbitraryClosedProfileDef& i
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return face;
|
||||
} else {
|
||||
return nullptr;
|
||||
|
||||
@@ -35,7 +35,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcAxis1Placement& inst) {
|
||||
taxonomy::direction3::ptr v = taxonomy::cast<taxonomy::direction3>(map(inst.Axis()));
|
||||
axis = *v->components_;
|
||||
}
|
||||
|
||||
|
||||
// @todo not sure what to do with ref, we're probably never reading it,
|
||||
// because we just created an Axis1 again from it in the kernel, but
|
||||
// to this constructor we need to supply something valid.
|
||||
|
||||
@@ -27,12 +27,12 @@ using namespace ifcopenshell::geom;
|
||||
#ifdef SCHEMA_HAS_IfcBSplineCurveWithKnots
|
||||
taxonomy::ptr mapping::map_impl(const IfcSchema::IfcBSplineCurveWithKnots& inst) {
|
||||
auto bc = taxonomy::make<taxonomy::bspline_curve>();
|
||||
|
||||
|
||||
const std::vector<IfcSchema::IfcCartesianPoint> cps = inst.ControlPointsList();
|
||||
std::vector<taxonomy::point3::ptr> points;
|
||||
std::transform(cps.begin(), cps.end(), std::back_inserter(points), [this](const IfcSchema::IfcCartesianPoint& cp) { return taxonomy::cast<taxonomy::point3>(map(cp)); });
|
||||
bc->control_points = points;
|
||||
|
||||
|
||||
auto knot_multiplicities = inst.KnotMultiplicities();
|
||||
bc->multiplicities.assign(knot_multiplicities.begin(), knot_multiplicities.end());
|
||||
bc->knots = inst.Knots();
|
||||
|
||||
@@ -73,7 +73,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcCenterLineProfileDef&) {
|
||||
mw.Add(BRepBuilderAPI_MakeEdge(c1a, c2a));
|
||||
mw.Add(BRepBuilderAPI_MakeEdge(c2));
|
||||
mw.Add(BRepBuilderAPI_MakeEdge(c2b, c1b));
|
||||
|
||||
|
||||
face = BRepBuilderAPI_MakeFace(mw.Wire());
|
||||
} else {
|
||||
BRepOffsetAPI_MakeOffset offset(BRepBuilderAPI_MakeFace(gp_Pln(gp::Origin(), gp::DZ())));
|
||||
|
||||
@@ -23,7 +23,7 @@ using namespace ifcopenshell::geom;
|
||||
|
||||
taxonomy::ptr mapping::map_impl(const IfcSchema::IfcCircle& inst) {
|
||||
const double r = inst.Radius() * length_unit_;
|
||||
if (r < settings_.get<settings::Precision>().get()) {
|
||||
if (r < settings_.get<settings::Precision>().get()) {
|
||||
logger_.message(ifcopenshell::logger::LOG_ERROR, "GEO", 237, "Radius not greater than zero for:", inst);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcCompositeCurve& inst) {
|
||||
#else
|
||||
std::vector<IfcSchema::IfcCompositeCurveSegment> segments = inst.Segments();
|
||||
#endif
|
||||
|
||||
|
||||
for (auto& segment : segments) {
|
||||
if (segment.as<IfcSchema::IfcCompositeCurveSegment>() && segment.as<IfcSchema::IfcCompositeCurveSegment>().ParentCurve().as<IfcSchema::IfcLine>()) {
|
||||
logger_.notice("GEO", 238, "Infinite IfcLine used as ParentCurve of segment, treating as a segment", segment);
|
||||
|
||||
@@ -25,7 +25,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcCurveBoundedPlane& inst) {
|
||||
taxonomy::plane::ptr pl = taxonomy::cast<taxonomy::plane>(map(inst.BasisSurface()));
|
||||
auto f = taxonomy::make<taxonomy::face>();
|
||||
f->children.push_back(taxonomy::cast<taxonomy::loop>(map(inst.OuterBoundary())));
|
||||
|
||||
|
||||
std::vector<IfcSchema::IfcCurve> boundaries = inst.InnerBoundaries();
|
||||
|
||||
for (auto& b : boundaries) {
|
||||
|
||||
@@ -133,7 +133,7 @@ struct spiral_parent_curve : public parent_curve_function {
|
||||
|
||||
// this is the piecewise curve segment function for horizontal and vertical
|
||||
struct curve_segment_function {
|
||||
curve_segment_function(const Eigen::Matrix4d& curve_segment_placement, const Eigen::Matrix4d& parent_curve_normalization, std::shared_ptr<parent_curve_function> parent_curve_fn) :
|
||||
curve_segment_function(const Eigen::Matrix4d& curve_segment_placement, const Eigen::Matrix4d& parent_curve_normalization, std::shared_ptr<parent_curve_function> parent_curve_fn) :
|
||||
curve_segment_placement_(curve_segment_placement),
|
||||
parent_curve_normalization_(parent_curve_normalization),
|
||||
parent_curve_fn_(parent_curve_fn) {
|
||||
@@ -153,7 +153,7 @@ struct curve_segment_function {
|
||||
|
||||
// this is the piecewise curve segment function for cant
|
||||
struct cant_curve_segment_function {
|
||||
cant_curve_segment_function(const Eigen::Matrix4d& curve_segment_placement, const Eigen::Matrix4d& parent_curve_start_point, std::shared_ptr<parent_curve_function> parent_curve_fn) :
|
||||
cant_curve_segment_function(const Eigen::Matrix4d& curve_segment_placement, const Eigen::Matrix4d& parent_curve_start_point, std::shared_ptr<parent_curve_function> parent_curve_fn) :
|
||||
curve_segment_placement_(curve_segment_placement),
|
||||
parent_curve_start_point_(parent_curve_start_point),
|
||||
parent_curve_fn_(parent_curve_fn) {
|
||||
@@ -354,7 +354,7 @@ class curve_segment_evaluator {
|
||||
} else {
|
||||
// The parent curve function returns the 4x4 matrix for the parent curve.
|
||||
// Normalize the parent curve so that the trim start point and tangent direction at the start point
|
||||
// are aligned with the origin. This is accomplished with a normalization matrix that subtracts the
|
||||
// are aligned with the origin. This is accomplished with a normalization matrix that subtracts the
|
||||
// incremental parent curve start point and applies a rotation. Apply the incremental
|
||||
// translation and rotation to the curve_segment_placement to get the curve_segment_point
|
||||
|
||||
@@ -623,7 +623,7 @@ class curve_segment_evaluator {
|
||||
} else if (segment_type_ == ST_CANT) {
|
||||
std::optional<std::function<double(double)>> super, slope;
|
||||
std::tie(super, slope) = get_superelevation_functions();
|
||||
|
||||
|
||||
auto cant = [constant_term, cosine_term, L](double t) -> double {
|
||||
auto a0 = constant_term.has_value() ? 1 / constant_term.value() : 0.0;
|
||||
auto a1 = (1 / cosine_term) * cos(PI * t / L);
|
||||
@@ -690,7 +690,7 @@ class curve_segment_evaluator {
|
||||
} else if (segment_type_ == ST_CANT) {
|
||||
std::optional<std::function<double(double)>> super, slope;
|
||||
std::tie(super, slope) = get_superelevation_functions();
|
||||
|
||||
|
||||
auto cant = [constant_term, linear_term, sine_term, L](double t) -> double {
|
||||
auto a0 = constant_term.has_value() ? 1 / constant_term.value() : 0.0;
|
||||
auto a1 = linear_term.has_value() ? (linear_term.value()/fabs(linear_term.value())) * pow(1 / linear_term.value(), 2.0) * t : 0.0;
|
||||
@@ -825,7 +825,7 @@ class curve_segment_evaluator {
|
||||
#else
|
||||
A3 = c.QubicTerm();
|
||||
#endif
|
||||
|
||||
|
||||
if (segment_type_ == ST_CANT) {
|
||||
polynomial_cant_spiral(A0, A1, A2, A3, A4, A5, A6, A7);
|
||||
} else {
|
||||
@@ -983,7 +983,7 @@ class curve_segment_evaluator {
|
||||
[](double /*u*/) -> Eigen::Matrix4d { return Eigen::Matrix4d::Identity(); });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void operator()(const IfcSchema::IfcLine& l) {
|
||||
projected_length_ = length_;
|
||||
|
||||
@@ -995,8 +995,8 @@ class curve_segment_evaluator {
|
||||
// 8.9.3.30 IfcDirection https://standards.buildingsmart.org/IFC/RELEASE/IFC4_3/HTML/lexical/IfcDirection.htm
|
||||
// "The IfcDirection does not imply a vector length, and the direction ratios does not have to be normalized."
|
||||
//
|
||||
// Therefore, the direction ratios need to be normalized to compute points on the line.
|
||||
//
|
||||
// Therefore, the direction ratios need to be normalized to compute points on the line.
|
||||
//
|
||||
// Magnitude is not used because it relates to the parameterization of the line, which isn't currently done for IfcCurveSegment
|
||||
// @todo - parameterization was recently added so Magnitude needs to be taking into consideration
|
||||
auto dr = l.Dir().Orientation().DirectionRatios();
|
||||
@@ -1030,7 +1030,7 @@ class curve_segment_evaluator {
|
||||
|
||||
auto pcDZy = curve_segment_placement_ ? (*curve_segment_placement_)(1, 2) : 0.;
|
||||
auto pcDZz = curve_segment_placement_ ? (*curve_segment_placement_)(2, 2) : 1.;
|
||||
|
||||
|
||||
parent_curve_fn_ = std::make_shared<line_parent_curve>(
|
||||
[segment_type = segment_type_,pcX, pcY, pcDXx, pcDXy, pcDZy, pcDZz, convert_u](double u)->Eigen::Matrix4d {
|
||||
u = convert_u(u);
|
||||
|
||||
@@ -56,7 +56,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcExtrudedAreaSolidTapered& in
|
||||
if (has_position) {
|
||||
matrix = taxonomy::cast<taxonomy::matrix4>(map(inst.Position()));
|
||||
}
|
||||
|
||||
|
||||
loft->matrix = matrix;
|
||||
|
||||
return loft;
|
||||
|
||||
@@ -24,7 +24,7 @@ using namespace ifcopenshell::geom;
|
||||
#ifdef SCHEMA_HAS_IfcIndexedPolyCurve
|
||||
|
||||
taxonomy::ptr mapping::map_impl(const IfcSchema::IfcIndexedPolyCurve& inst) {
|
||||
|
||||
|
||||
auto point_list = inst.Points();
|
||||
std::vector< std::vector<double> > coordinates;
|
||||
if (point_list.as<IfcSchema::IfcCartesianPointList2D>()) {
|
||||
@@ -100,7 +100,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcIndexedPolyCurve& inst) {
|
||||
previous = current;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return loop;
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcLShapeProfileDef& inst) {
|
||||
const double x = inst.Width().value_or(inst.Depth()) / 2.0f * length_unit_;
|
||||
const double d = inst.Thickness() * length_unit_;
|
||||
const double slope = inst.LegSlope().value_or(0.) * angle_unit_;
|
||||
|
||||
|
||||
double f1 = 0.0f;
|
||||
double f2 = 0.0f;
|
||||
if (doFillet) {
|
||||
|
||||
@@ -84,11 +84,11 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcOffsetCurveByDistances& inst
|
||||
double pz = first_offset_value.OffsetVertical().value_or(0.0);
|
||||
py *= length_unit_;
|
||||
pz *= length_unit_;
|
||||
|
||||
auto fn = [py, pz](double /*u*/) -> Eigen::Matrix4d {
|
||||
Eigen::Matrix4d m = Eigen::Matrix4d::Identity();
|
||||
m.col(3)(1) = py;
|
||||
m.col(3)(2) = pz;
|
||||
|
||||
auto fn = [py, pz](double /*u*/) -> Eigen::Matrix4d {
|
||||
Eigen::Matrix4d m = Eigen::Matrix4d::Identity();
|
||||
m.col(3)(1) = py;
|
||||
m.col(3)(2) = pz;
|
||||
return m; };
|
||||
offset_spans.emplace_back(taxonomy::make<taxonomy::functor_item>(first_distance, fn));
|
||||
}
|
||||
@@ -146,7 +146,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcOffsetCurveByDistances& inst
|
||||
zn = zn_at_end;
|
||||
}
|
||||
|
||||
|
||||
|
||||
auto fn = [yp, yn, zp, zn, l](double u) -> Eigen::Matrix4d {
|
||||
Eigen::Matrix4d m = Eigen::Matrix4d::Identity();
|
||||
m.col(3)(1) = (l == 0.0 ? yp : (yp + (yn - yp) * u / l));
|
||||
@@ -171,10 +171,10 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcOffsetCurveByDistances& inst
|
||||
py *= length_unit_;
|
||||
pz *= length_unit_;
|
||||
double l = basis_curve_length - last_distance;
|
||||
auto fn = [py, pz](double /*u*/) -> Eigen::Matrix4d {
|
||||
Eigen::Matrix4d m = Eigen::Matrix4d::Identity();
|
||||
m.col(3)(1) = py;
|
||||
m.col(3)(2) = pz;
|
||||
auto fn = [py, pz](double /*u*/) -> Eigen::Matrix4d {
|
||||
Eigen::Matrix4d m = Eigen::Matrix4d::Identity();
|
||||
m.col(3)(1) = py;
|
||||
m.col(3)(2) = pz;
|
||||
return m; };
|
||||
|
||||
offset_spans.emplace_back(taxonomy::make<taxonomy::functor_item>(l, fn));
|
||||
|
||||
@@ -87,7 +87,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcOpenCrossProfileDef& inst) {
|
||||
auto r = taxonomy::loop::ptr((taxonomy::loop*)mapped->clone_());
|
||||
r->closed = false;
|
||||
return r;
|
||||
}*/
|
||||
}*/
|
||||
|
||||
mapped->closed = false;
|
||||
mapped->tags = tags;
|
||||
|
||||
@@ -24,5 +24,5 @@ using namespace ifcopenshell::geom;
|
||||
taxonomy::ptr mapping::map_impl(const IfcSchema::IfcPlane& inst) {
|
||||
auto p = taxonomy::make<taxonomy::plane>();
|
||||
p->matrix = taxonomy::cast<taxonomy::matrix4>(map(inst.Position()));
|
||||
return p;
|
||||
return p;
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcPointByDistanceExpression& i
|
||||
|
||||
if (inst.OffsetLateral().has_value()) {
|
||||
auto offset_lateral = inst.OffsetLateral().value() * length_unit_;
|
||||
auto y = Eigen::Vector3d(m.col(1)(0), m.col(1)(1), m.col(1)(2));
|
||||
auto y = Eigen::Vector3d(m.col(1)(0), m.col(1)(1), m.col(1)(2));
|
||||
o += offset_lateral * y;
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcPolyLoop& inst) {
|
||||
|
||||
int count = polygon.size();
|
||||
if (original_count - count != 0) {
|
||||
std::stringstream ss; ss << (original_count - count) << " edges removed for:";
|
||||
std::stringstream ss; ss << (original_count - count) << " edges removed for:";
|
||||
logger_.message(ifcopenshell::logger::LOG_WARNING, "GEO", 280, ss.str(), inst);
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcPolygonalFaceSet& inst) {
|
||||
for (auto& f : polygonal_faces) {
|
||||
auto fa = taxonomy::make<taxonomy::face>();
|
||||
shell->children.push_back(fa);
|
||||
|
||||
|
||||
{
|
||||
auto loop = taxonomy::make<taxonomy::loop>();
|
||||
fa->children = { loop };
|
||||
|
||||
@@ -44,7 +44,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcProduct& inst) {
|
||||
}
|
||||
|
||||
if (openings->size() && !settings_.get(IteratorSettings::DISABLE_OPENING_SUBTRACTIONS) && use_body) {
|
||||
|
||||
|
||||
Eigen::Matrix4d ci;
|
||||
if (c->matrix.components_) {
|
||||
ci = c->matrix.components_->inverse();
|
||||
@@ -69,7 +69,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcProduct& inst) {
|
||||
c->children = { child };
|
||||
} else {
|
||||
delete c;
|
||||
return nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcRectangleHollowProfileDef& i
|
||||
|
||||
const double r1 = fr1 ? (*inst.OuterFilletRadius()) * length_unit_ : 0.;
|
||||
const double r2 = fr2 ? (*inst.InnerFilletRadius()) * length_unit_ : 0.;
|
||||
|
||||
|
||||
const double tol = settings_.get<settings::Precision>().get();
|
||||
|
||||
if (x < tol || y < tol) {
|
||||
|
||||
@@ -42,7 +42,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcRectangleProfileDef& inst) {
|
||||
if (has_position) {
|
||||
m4 = taxonomy::cast<taxonomy::matrix4>(map(inst.Position()));
|
||||
}
|
||||
|
||||
|
||||
return profile_helper(m4, {
|
||||
{{-x,-y}},
|
||||
{{x,-y}},
|
||||
|
||||
@@ -27,7 +27,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcRevolvedAreaSolid& inst) {
|
||||
const double ang = inst.Angle() * angle_unit_;
|
||||
|
||||
taxonomy::cast<taxonomy::face>(map(inst.SweptArea()));
|
||||
|
||||
|
||||
std::optional<double> angle;
|
||||
|
||||
taxonomy::matrix4::ptr matrix;
|
||||
|
||||
@@ -32,7 +32,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcRightCircularCylinder&) {
|
||||
BRepPrimAPI_MakeCylinder builder(r, h);
|
||||
gp_Trsf trsf;
|
||||
ifcopenshell::geom::Kernel::convert(inst.Position(),trsf);
|
||||
|
||||
|
||||
// IfcCsgPrimitive3D.Position has unit scale factor
|
||||
shape = builder.Solid().Moved(trsf);
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcSectionedSolidHorizontal& in
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
{
|
||||
{
|
||||
auto css = inst.CrossSections();
|
||||
auto csps = inst.CrossSectionPositions();
|
||||
std::vector<taxonomy::face::ptr> faces;
|
||||
@@ -47,7 +47,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcSectionedSolidHorizontal& in
|
||||
// reference frame along a certain curve location (b) the longitude.
|
||||
|
||||
// The longitudes determine the range of the sweep and the offsets are interpolated in between
|
||||
// sweep segments.
|
||||
// sweep segments.
|
||||
std::vector<Eigen::Vector3d> profile_offsets;
|
||||
std::vector<std::optional<Eigen::Matrix3d>> profile_rotations;
|
||||
std::vector<double> longitudes;
|
||||
|
||||
@@ -39,7 +39,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcSectionedSurface& inst) {
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
{
|
||||
auto css = inst.CrossSections();
|
||||
auto csps = inst.CrossSectionPositions();
|
||||
std::vector<taxonomy::geom_item::ptr> faces;
|
||||
@@ -48,7 +48,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcSectionedSurface& inst) {
|
||||
// reference frame along a certain curve location (b) the longitude.
|
||||
|
||||
// The longitudes determine the range of the sweep and the offsets are interpolated in between
|
||||
// sweep segments.
|
||||
// sweep segments.
|
||||
std::vector<Eigen::Vector3d> profile_offsets;
|
||||
std::vector<std::optional<Eigen::Matrix3d>> profile_rotations;
|
||||
std::vector<double> longitudes;
|
||||
|
||||
@@ -28,7 +28,7 @@ using namespace ifcopenshell::geom;
|
||||
taxonomy::ptr mapping::map_impl(const IfcSchema::IfcSegmentedReferenceCurve& inst) {
|
||||
if (!inst.BaseCurve().as<IfcSchema::IfcGradientCurve>())
|
||||
logger_.warning("GEO", 291, "Expected IfcSegmentedReferenceCurve.BaseCurve to be IfcGradient", inst); // CT 4.1.7.1.1.3
|
||||
|
||||
|
||||
auto segments = inst.Segments();
|
||||
|
||||
taxonomy::piecewise_function::span_list spans;
|
||||
|
||||
@@ -97,9 +97,9 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcSweptDiskSolid& inst) {
|
||||
return taxonomy::make<taxonomy::sweep_along_curve>(taxonomy::make<taxonomy::matrix4>(), f, nullptr, loop);
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
|
||||
TopoDS_Wire wire, section1, section2;
|
||||
|
||||
bool hasInnerRadius = !!inst.InnerRadius();
|
||||
@@ -107,7 +107,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcSweptDiskSolid& inst) {
|
||||
if (!convert_wire(inst.Directrix(), wire)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if (util::count(wire, TopAbs_EDGE) == 1 && sp && ep) {
|
||||
@@ -119,7 +119,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcSweptDiskSolid& inst) {
|
||||
double a, b;
|
||||
auto crv = BRep_Tool::Curve(e, a, b);
|
||||
if ((crv->DynamicType() == STANDARD_TYPE(Geom_Circle)) ||
|
||||
(crv->DynamicType() == STANDARD_TYPE(Geom_Ellipse)))
|
||||
(crv->DynamicType() == STANDARD_TYPE(Geom_Ellipse)))
|
||||
{
|
||||
BRepBuilderAPI_MakeEdge me(crv, *sp, *ep);
|
||||
if (me.IsDone()) {
|
||||
@@ -227,7 +227,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcSweptDiskSolid& inst) {
|
||||
j += 1;
|
||||
} else {
|
||||
ifcopenshell::logger::root().error("Unexpected amount of fillet edges generated");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ifcopenshell::logger::root().error("Unable to build fillet, probably edge too short");
|
||||
}
|
||||
@@ -258,7 +258,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcSweptDiskSolid& inst) {
|
||||
// NB: Note that StartParam and EndParam param are ignored and the assumption is
|
||||
// made that the parametric range over which to be swept matches the IfcCurve in
|
||||
// its entirety.
|
||||
|
||||
|
||||
util::process_sweep(wire, inst.Radius() * length_unit_, shape);
|
||||
|
||||
if (shape.IsNull()) {
|
||||
|
||||
@@ -43,7 +43,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcTShapeProfileDef& inst) {
|
||||
logger_.message(ifcopenshell::logger::LOG_NOTICE, "GEO", 296, "Skipping zero sized profile:", inst);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
double dy1 = 0.0f;
|
||||
double dy2 = 0.0f;
|
||||
double dx1 = 0.0f;
|
||||
|
||||
@@ -29,21 +29,21 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcTrimmedCurve& inst) {
|
||||
auto basis_curve = inst.BasisCurve();
|
||||
bool isConic = basis_curve.declaration().is(IfcSchema::IfcConic::Class());
|
||||
double parameterFactor = isConic ? angle_unit_ : length_unit_;
|
||||
|
||||
|
||||
auto tc = taxonomy::make<taxonomy::edge>();
|
||||
tc->basis = map(inst.BasisCurve());
|
||||
|
||||
|
||||
bool trim_cartesian = inst.MasterRepresentation() != IfcSchema::IfcTrimmingPreference::IfcTrimmingPreference_PARAMETER;
|
||||
auto trims1 = inst.Trim1();
|
||||
auto trims2 = inst.Trim2();
|
||||
|
||||
|
||||
// reversed orientation handling happens in geometry kernel
|
||||
unsigned sense_agreement = 0;
|
||||
double flts[2];
|
||||
taxonomy::point3::ptr pnts[2];
|
||||
bool has_flts[2] = {false,false};
|
||||
bool has_pnts[2] = {false,false};
|
||||
|
||||
|
||||
tc->curve_sense = inst.SenseAgreement();
|
||||
|
||||
for (auto it = trims1.begin(); it != trims1.end(); it ++) {
|
||||
|
||||
@@ -33,7 +33,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcUShapeProfileDef& inst) {
|
||||
const double d1 = inst.WebThickness() * length_unit_;
|
||||
const double d2 = inst.FlangeThickness() * length_unit_;
|
||||
const double slope = inst.FlangeSlope().value_or(0.) * angle_unit_;
|
||||
|
||||
|
||||
double dy1 = 0.0f;
|
||||
double dy2 = 0.0f;
|
||||
double f1 = 0.0f;
|
||||
|
||||
@@ -31,7 +31,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcZShapeProfileDef& inst) {
|
||||
|
||||
bool doFillet = !!inst.FilletRadius();
|
||||
bool doEdgeFillet = !!inst.EdgeRadius();
|
||||
|
||||
|
||||
double f1 = 0.;
|
||||
double f2 = 0.;
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ std::vector<IfcSchema::IfcProduct> mapping::products_represented_by(const IfcSch
|
||||
auto invs = prodrep.file()->get_inverse(prodrep.id(), &IfcSchema::IfcProduct::Class(), -1);
|
||||
for (auto& inv : invs) {
|
||||
products.push_back(inv.as<IfcSchema::IfcProduct>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (only_direct) {
|
||||
@@ -169,7 +169,7 @@ bool mapping::reuse_ok_(const std::vector<IfcSchema::IfcProduct>& products) {
|
||||
|
||||
std::vector<express::base> mapping::find_openings(const express::base& inst) {
|
||||
std::vector<express::base> openings;
|
||||
|
||||
|
||||
if (auto rep = inst.as<IfcSchema::IfcRepresentation>()) {
|
||||
// @todo this is essentially only for hybrid kernel trying to guess
|
||||
// when not to use a simple kernel.
|
||||
@@ -246,11 +246,11 @@ void mapping::get_representations(std::vector<geometry_conversion_task>& tasks,
|
||||
int task_index = 0;
|
||||
|
||||
std::set<IfcSchema::IfcProduct> products_seen;
|
||||
|
||||
|
||||
for (auto representation : representations) {
|
||||
IfcSchema::IfcRepresentationMap rmap;
|
||||
std::vector<IfcSchema::IfcProduct> ifcproducts = filter_products(products_represented_by(representation, rmap, false), filters);
|
||||
|
||||
|
||||
if (ifcproducts.empty()) {
|
||||
continue;
|
||||
}
|
||||
@@ -838,7 +838,7 @@ express::base mapping::get_decomposing_entity(const express::base& inst, bool in
|
||||
for (auto it = parents.begin(); it != parents.end(); ++it) {
|
||||
IfcSchema::IfcRelDecomposes decompose = (*it).as<IfcSchema::IfcRelDecomposes>();
|
||||
express::base ifc_objectdef;
|
||||
|
||||
|
||||
ifc_objectdef = get_RelatingObject(decompose);
|
||||
|
||||
if (!ifc_objectdef || product == ifc_objectdef) continue;
|
||||
@@ -871,7 +871,7 @@ void mapping::initialize_units_() {
|
||||
length_unit_ = 1.;
|
||||
angle_unit_ = -1.;
|
||||
length_unit_name_ = "METER";
|
||||
|
||||
|
||||
#ifdef SCHEMA_HAS_IfcContext
|
||||
auto projects = file_->instances_by_type<IfcSchema::IfcContext>();
|
||||
#else
|
||||
@@ -1133,7 +1133,7 @@ bool mapping::get_layerset_information(const express::base& p, layerset_informat
|
||||
std::vector<IfcSchema::IfcExtrudedAreaSolid> extrusions;
|
||||
for (auto& r : resources) {
|
||||
if (auto ex = r.as<IfcSchema::IfcExtrudedAreaSolid>()) {
|
||||
extrusions.push_back(ex);
|
||||
extrusions.push_back(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1209,7 +1209,7 @@ bool mapping::get_layerset_information(const express::base& p, layerset_informat
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
namespace ifcopenshell {
|
||||
|
||||
namespace geom {
|
||||
|
||||
|
||||
class POSTFIX_SCHEMA(mapping) : public abstract_mapping {
|
||||
private:
|
||||
ifcopenshell::file* file_;
|
||||
@@ -30,7 +30,7 @@ namespace geom {
|
||||
const express::base placement_rel_to_instance_;
|
||||
|
||||
Eigen::Matrix4d offset_and_rotation_ = Eigen::Matrix4d::Identity();
|
||||
|
||||
|
||||
void initialize_units_();
|
||||
void addRepresentationsFromContextIds(std::vector<IfcSchema::IfcRepresentation>&);
|
||||
void addRepresentationsFromPriorities(std::vector<IfcSchema::IfcRepresentation>&);
|
||||
@@ -136,7 +136,7 @@ namespace geom {
|
||||
template <>
|
||||
struct element_type<taxonomy::solid> {
|
||||
typedef taxonomy::shell type;
|
||||
};
|
||||
};
|
||||
|
||||
template <typename U = taxonomy::collection, typename T>
|
||||
typename U::ptr map_to_collection(POSTFIX_SCHEMA(mapping)* m, const T& ts) {
|
||||
|
||||
@@ -182,4 +182,4 @@ BIND(IfcSurfaceStyle); // -> style
|
||||
|
||||
#ifdef SCHEMA_HAS_IfcCurveSegment
|
||||
BIND(IfcCurveSegment);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -7,8 +7,8 @@ taxonomy::loop::ptr ifcopenshell::geom::fillet_loop(taxonomy::loop::ptr loop, do
|
||||
const auto child_count = static_cast<int>(loop->children.size());
|
||||
for (int b = 0; b < child_count; ++b) {
|
||||
int c = (b + child_count - 1) % child_count;
|
||||
pps[b] = {
|
||||
std::get<taxonomy::point3::ptr>(loop->children[c]->start)->ccomponents(),
|
||||
pps[b] = {
|
||||
std::get<taxonomy::point3::ptr>(loop->children[c]->start)->ccomponents(),
|
||||
radius, loop->children[c], loop->children[b]
|
||||
};
|
||||
}
|
||||
@@ -227,7 +227,7 @@ std::pair<std::vector<taxonomy::point3::ptr>, std::vector<std::set<std::string>>
|
||||
if (equal) {
|
||||
// do not remove the first or last point to
|
||||
// maintain connectivity with other wires
|
||||
|
||||
|
||||
/*
|
||||
// Only removing direct equality so does not impact connectivity
|
||||
if ((closed && j == 0) || (!closed && j == (n - 1))) {
|
||||
|
||||
@@ -121,7 +121,7 @@ ifcopenshell::geom::triangulation::triangulation(const native& shape_model)
|
||||
, weld_offset_(0)
|
||||
{
|
||||
for (std::vector<ifcopenshell::geom::conversion_result>::const_iterator iit = shape_model.begin(); iit != shape_model.end(); ++iit) {
|
||||
|
||||
|
||||
// Don't weld vertices that belong to different items to prevent non-manifold situations.
|
||||
resetWelds();
|
||||
|
||||
|
||||
@@ -108,7 +108,7 @@ namespace ifcopenshell::geom {
|
||||
std::vector<int> faces_;
|
||||
std::vector<std::vector<int>> polyhedral_faces_without_holes_;
|
||||
std::vector<std::vector<std::vector<int>>> polyhedral_faces_with_holes_;
|
||||
|
||||
|
||||
std::vector<int> edges_;
|
||||
std::vector<double> normals_;
|
||||
std::vector<double> uvs_;
|
||||
|
||||
@@ -162,7 +162,7 @@ int convert_to_ifc(ifcopenshell::file& f, const opencascade::handle<Geom_Curve>&
|
||||
el.setSemiAxis1(ellipse->MajorRadius());
|
||||
el.setSemiAxis2(ellipse->MinorRadius());
|
||||
curve = el;
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
#ifdef SCHEMA_HAS_IfcRationalBSplineSurfaceWithKnots
|
||||
@@ -461,11 +461,11 @@ int convert_to_ifc(ifcopenshell::file& f, const TopoDS_Edge& e, IfcSchema::IfcEd
|
||||
IfcSchema::IfcEdge edge2 = f.create<IfcSchema::IfcEdge>();
|
||||
edge2.setEdgeStart(vertex1);
|
||||
edge2.setEdgeEnd(vertex2);
|
||||
|
||||
|
||||
auto ori = f.create<IfcSchema::IfcOrientedEdge>();
|
||||
ori.setEdgeElement(edge2);
|
||||
ori.setOrientation(true);
|
||||
|
||||
|
||||
edge = ori;
|
||||
return 1;
|
||||
} else {
|
||||
|
||||
@@ -620,7 +620,7 @@ typedef item const* ptr;
|
||||
|
||||
struct equal_functor {
|
||||
bool operator()(taxonomy::item::ptr const& a,
|
||||
taxonomy::item::ptr const& b) const
|
||||
taxonomy::item::ptr const& b) const
|
||||
{
|
||||
if (a == b) {
|
||||
return true;
|
||||
|
||||
@@ -106,7 +106,7 @@ std::string format_json(const double& d) {
|
||||
template <>
|
||||
std::string format_json(const gp_Dir& d) {
|
||||
std::stringstream ss;
|
||||
ss << std::setprecision(std::numeric_limits<double>::digits10)
|
||||
ss << std::setprecision(std::numeric_limits<double>::digits10)
|
||||
<< "[" << d.X() << "," << d.Y() << "," << d.Z() << "]";
|
||||
return ss.str();
|
||||
}
|
||||
@@ -311,7 +311,7 @@ protected:
|
||||
m(3,0), m(3,1), m(3,2), m(3,3)
|
||||
};
|
||||
swrite(s, std::string((char*)matrix_array, 16 * sizeof(double)));
|
||||
|
||||
|
||||
// The first bit of the string is always the instance name of the representation.
|
||||
const std::string& representation_id = geom->geometry().id();
|
||||
const int integer_representation_id = atoi(representation_id.c_str());
|
||||
@@ -326,13 +326,13 @@ protected:
|
||||
indices.reserve(faces.size());
|
||||
for (std::vector<int>::const_iterator it = faces.begin(); it != faces.end(); ++it) {
|
||||
indices.push_back(*it);
|
||||
}
|
||||
}
|
||||
swrite_array<int32_t>(s, indices);
|
||||
|
||||
if (append_line_data) {
|
||||
std::vector<int32_t> lines;
|
||||
std::set<int32_t> faces_set (indices.begin(), indices.end());
|
||||
|
||||
|
||||
const std::vector<int>& edges = geom->geometry().edges();
|
||||
for ( std::vector<int>::const_iterator it = edges.begin(); it != edges.end(); ) {
|
||||
const int32_t i1 = *(it++);
|
||||
@@ -349,7 +349,7 @@ protected:
|
||||
swrite_array<int32_t>(s, lines);
|
||||
}
|
||||
}
|
||||
{
|
||||
{
|
||||
// We remove the blanks here from the material array. I.e. materials without a diffuse color
|
||||
std::vector<boost::optional<std::array<float, 4> > > diffuse_color_array;
|
||||
for (auto it = geom->geometry().materials().begin(); it != geom->geometry().materials().end(); ++it) {
|
||||
@@ -369,7 +369,7 @@ protected:
|
||||
|
||||
std::map<int, int> orig_to_condensed_index_map;
|
||||
std::vector<float> diffuse_color_array_condensed;
|
||||
|
||||
|
||||
int new_index = 0;
|
||||
for (size_t orig = 0; orig < diffuse_color_array.size(); ++orig) {
|
||||
auto& material = diffuse_color_array[orig];
|
||||
@@ -470,13 +470,13 @@ private:
|
||||
const ifcopenshell::geom::native_element* elem_;
|
||||
public:
|
||||
QuantityWriter_v0(const ifcopenshell::geom::native_element* elem) :
|
||||
elem_(elem)
|
||||
elem_(elem)
|
||||
{
|
||||
put_json(TOTAL_SURFACE_AREA, 0.);
|
||||
put_json(TOTAL_SHAPE_VOLUME, 0.);
|
||||
if (elem_->type() == "IfcSpace") {
|
||||
put_json(WALKABLE_SURFACE_AREA, 0.);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -548,7 +548,7 @@ public:
|
||||
};
|
||||
|
||||
int main () {
|
||||
// Redirect stdout to this stream, so that involuntary
|
||||
// Redirect stdout to this stream, so that involuntary
|
||||
// writes to stdout do not interfere with our protocol.
|
||||
std::ostringstream oss;
|
||||
stdout_redir = oss.rdbuf();
|
||||
@@ -672,7 +672,7 @@ int main () {
|
||||
}
|
||||
}
|
||||
default:
|
||||
exit_code = 1;
|
||||
exit_code = 1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -276,7 +276,7 @@ int IFCImp::DoImport(const TCHAR *name, ImpInterface *impitfc, Interface *itfc,
|
||||
const int v1 = o->geometry().faces()[3*i+0];
|
||||
const int v2 = o->geometry().faces()[3*i+1];
|
||||
const int v3 = o->geometry().faces()[3*i+2];
|
||||
|
||||
|
||||
const edge_t e1((std::min)(v1, v2), (std::max)(v1, v2));
|
||||
const edge_t e2((std::min)(v2, v3), (std::max)(v2, v3));
|
||||
const edge_t e3((std::min)(v3, v1), (std::max)(v3, v1));
|
||||
@@ -294,7 +294,7 @@ int IFCImp::DoImport(const TCHAR *name, ImpInterface *impitfc, Interface *itfc,
|
||||
}
|
||||
tri->mesh.faces[i].setMatID(mtlid);
|
||||
}
|
||||
|
||||
|
||||
tri->mesh.buildNormals();
|
||||
// Either use this or undefine the FACESETS_AS_COMPOUND option in IfcGeom.h to have
|
||||
// properly oriented normals. Using only the line below will result in a consistent
|
||||
@@ -322,6 +322,6 @@ int IFCImp::DoImport(const TCHAR *name, ImpInterface *impitfc, Interface *itfc,
|
||||
} while (iterator.next());
|
||||
|
||||
itfc->ProgressEnd();
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@
|
||||
|
||||
extern ClassDesc* GetIFCImpDesc();
|
||||
|
||||
class IFCImp : public SceneImport
|
||||
class IFCImp : public SceneImport
|
||||
{
|
||||
public:
|
||||
int ExtCount(); // = 1
|
||||
|
||||
@@ -66,6 +66,12 @@ Alternatively, you can use Python:
|
||||
report.report()
|
||||
report.to_file("report.json")
|
||||
|
||||
# Or to a SQLite database. Unlike JSON, entities are stored once and
|
||||
# referenced by ID, so this stays small on large models and can be queried
|
||||
# instead of parsed. Recommended for anything but small audits. Results are
|
||||
# written directly to the file, so there is no report() step.
|
||||
reporter.Sqlite(specs).to_file("report.db")
|
||||
|
||||
# Or to ODS spreadsheet
|
||||
report = reporter.Ods(specs)
|
||||
report.report()
|
||||
|
||||
@@ -47,6 +47,7 @@ def _create_layout(file: ifcopenshell.file, alignment: entity_instance, points:
|
||||
|
||||
start_dist_along = 0.0
|
||||
gradient = None
|
||||
dir = None
|
||||
for p1, p2 in zip(points, points[1:]):
|
||||
x1, y1, z1 = p1.Coordinates
|
||||
x2, y2, z2 = p2.Coordinates
|
||||
@@ -86,6 +87,7 @@ def _create_layout(file: ifcopenshell.file, alignment: entity_instance, points:
|
||||
start_dist_along += length
|
||||
|
||||
# zero length segment
|
||||
assert dir is not None
|
||||
hsegment = file.createIfcAlignmentSegment(
|
||||
ifcopenshell.guid.new(),
|
||||
DesignParameters=file.createIfcAlignmentHorizontalSegment(
|
||||
|
||||
@@ -258,5 +258,5 @@ if __name__ == "__main__":
|
||||
for output in sys.argv[2:]:
|
||||
mdl = importlib.import_module(output)
|
||||
mdl.Generator(m).emit()
|
||||
sys.stdout.write(m.schema.name)
|
||||
print(m.schema.name)
|
||||
""" % ("\n ".join(statements)))
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
import sys, fileinput
|
||||
|
||||
if sys.platform == "win32" and not hasattr(sys.stdout, "buffer"):
|
||||
import os, msvcrt
|
||||
|
||||
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
|
||||
|
||||
files = sys.argv[1:]
|
||||
if files[0] == "-o":
|
||||
b = open(files[1], "wb")
|
||||
files = files[2:]
|
||||
else:
|
||||
b = getattr(sys.stdout, "buffer", sys.stdout)
|
||||
|
||||
for line in fileinput.input(files=files, mode="rb"):
|
||||
b.write(line)
|
||||
@@ -486,5 +486,4 @@ if __name__ == "__main__":
|
||||
for output in sys.argv[2:]:
|
||||
mdl = importlib.import_module(output)
|
||||
mdl.Generator(m).emit()
|
||||
sys.stdout.write(m.schema.name)
|
||||
|
||||
|
||||
@@ -19,9 +19,14 @@
|
||||
|
||||
from __future__ import annotations
|
||||
import sys
|
||||
import nodes
|
||||
import templates
|
||||
import schema
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from . import nodes, schema, templates
|
||||
else:
|
||||
import nodes
|
||||
import schema
|
||||
import templates
|
||||
|
||||
|
||||
class Mapping:
|
||||
@@ -36,6 +41,15 @@ class Mapping:
|
||||
"binary": "boost::dynamic_bitset<>",
|
||||
}
|
||||
|
||||
cpp_to_argument_types = {
|
||||
"boolean": "BOOL",
|
||||
"logical": "LOGICAL",
|
||||
"integer": "INT",
|
||||
"real": "DOUBLE",
|
||||
"number": "DOUBLE",
|
||||
"string": "STRING",
|
||||
}
|
||||
|
||||
supported_argument_types = set(
|
||||
[
|
||||
"INT",
|
||||
@@ -117,8 +131,8 @@ class Mapping:
|
||||
else:
|
||||
return "Type::%s" % type
|
||||
|
||||
def make_argument_type(self, attr):
|
||||
def _make_argument_type(type):
|
||||
def make_argument_type(self, attr: nodes.Node | str) -> str:
|
||||
def _make_argument_type(type: nodes.Node | str) -> str:
|
||||
if isinstance(type, nodes.SimpleType):
|
||||
type = type.type
|
||||
if self.schema.is_entity(type) or isinstance(type, nodes.SelectType):
|
||||
@@ -134,8 +148,8 @@ class Mapping:
|
||||
if ty == "UNKNOWN":
|
||||
return "UNKNOWN"
|
||||
return "AGGREGATE_OF_" + ty
|
||||
elif str(type) in self.express_to_cpp_typemapping:
|
||||
return self.express_to_cpp_typemapping.get(str(type), type).split("::")[-1].upper()
|
||||
elif (ty := self.cpp_to_argument_types.get(str(type))) is not None:
|
||||
return ty
|
||||
elif self.schema.is_type(type):
|
||||
return _make_argument_type(self.schema.types[type].type)
|
||||
else:
|
||||
@@ -253,10 +267,10 @@ class Mapping:
|
||||
derived = set(self.derived_in_supertype(t))
|
||||
attrs = enumerate(self.arguments(t))
|
||||
|
||||
def include(attr):
|
||||
def include(attr: nodes.Node) -> bool:
|
||||
not_derived = include_derived or (attr.name not in derived)
|
||||
supported = self.make_argument_type(attr) != "ifcopenshell::Argument_UNKNOWN"
|
||||
return not_derived and supported
|
||||
return bool(not_derived and supported)
|
||||
|
||||
return [
|
||||
{
|
||||
|
||||
@@ -1,199 +0,0 @@
|
||||
@ECHO OFF
|
||||
|
||||
:: python bootstrap.py express.bnf > express_parser.py
|
||||
|
||||
IF EXIST IFC2X3_TC1.exp (
|
||||
python express_parser.py IFC2X3_TC1.exp header implementation schema_class definitions
|
||||
|
||||
IF EXIST Ifc2x3-schema.cpp (
|
||||
:: v0.6.0
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc2x3.cpp txt/header_ifc2x3.txt Ifc2x3.cpp
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc2x3.h txt/header_ifc2x3.txt Ifc2x3.h
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc2x3-schema.cpp txt/header_ifc2x3.txt Ifc2x3-schema.cpp
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc2x3-definitions.h txt/header_ifc2x3.txt Ifc2x3-definitions.h
|
||||
) ELSE (
|
||||
:: v0.5.0
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc2x3.cpp txt/header_ifc2x3.txt txt/ifndef_ifc4.txt Ifc2x3.cpp txt/endif.txt
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc2x3.h txt/header_ifc2x3.txt Ifc2x3.h
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc2x3enum.h txt/header_ifc2x3.txt Ifc2x3enum.h
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc2x3-latebound.cpp txt/header_ifc2x3.txt txt/ifndef_ifc4.txt Ifc2x3-latebound.cpp txt/endif.txt
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc2x3-latebound.h txt/header_ifc2x3.txt Ifc2x3-latebound.h
|
||||
)
|
||||
|
||||
del *.cpp *.h
|
||||
)
|
||||
|
||||
IF EXIST IFC4_ADD2TC1.exp (
|
||||
python express_parser.py IFC4_ADD2TC1.exp header implementation schema_class definitions
|
||||
|
||||
IF EXIST Ifc4-schema.cpp (
|
||||
:: v0.6.0
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc4.cpp txt/header_ifc4.txt Ifc4.cpp
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc4.h txt/header_ifc4.txt Ifc4.h
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc4-schema.cpp txt/header_ifc4.txt Ifc4-schema.cpp
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc4-definitions.h txt/header_ifc4.txt Ifc4-definitions.h
|
||||
) ELSE (
|
||||
:: v0.5.0
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc4.cpp txt/header_ifc4.txt txt/ifdef_ifc4.txt Ifc4.cpp txt/endif.txt
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc4.h txt/header_ifc4.txt Ifc4.h
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc4enum.h txt/header_ifc4.txt Ifc4enum.h
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc4-latebound.cpp txt/header_ifc4.txt txt/ifdef_ifc4.txt Ifc4-latebound.cpp txt/endif.txt
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc4-latebound.h txt/header_ifc4.txt Ifc4-latebound.h
|
||||
)
|
||||
|
||||
del *.cpp *.h
|
||||
)
|
||||
|
||||
IF EXIST IFC4x1.exp (
|
||||
python express_parser.py IFC4x1.exp header implementation schema_class definitions
|
||||
|
||||
IF EXIST Ifc4x1-schema.cpp (
|
||||
:: v0.6.0
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc4x1.cpp txt/header_ifc4x1.txt Ifc4x1.cpp
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc4x1.h txt/header_ifc4x1.txt Ifc4x1.h
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc4x1-schema.cpp txt/header_ifc4x1.txt Ifc4x1-schema.cpp
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc4x1-definitions.h txt/header_ifc4x1.txt Ifc4x1-definitions.h
|
||||
)
|
||||
|
||||
del *.cpp *.h
|
||||
)
|
||||
|
||||
IF EXIST IFC4x2.exp (
|
||||
python express_parser.py IFC4x2.exp header implementation schema_class definitions
|
||||
|
||||
IF EXIST Ifc4x2-schema.cpp (
|
||||
:: v0.6.0
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc4x2.cpp txt/header_ifc4x2.txt Ifc4x2.cpp
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc4x2.h txt/header_ifc4x2.txt Ifc4x2.h
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc4x2-schema.cpp txt/header_ifc4x2.txt Ifc4x2-schema.cpp
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc4x2-definitions.h txt/header_ifc4x2.txt Ifc4x2-definitions.h
|
||||
)
|
||||
|
||||
del *.cpp *.h
|
||||
)
|
||||
|
||||
IF EXIST IFC4x3_RC1.exp (
|
||||
python express_parser.py IFC4x3_RC1.exp header implementation schema_class definitions
|
||||
|
||||
IF EXIST Ifc4x3_rc1-schema.cpp (
|
||||
:: v0.6.0
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc4x3_rc1.cpp txt/header_ifc4x3_rc1.txt Ifc4x3_rc1.cpp
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc4x3_rc1.h txt/header_ifc4x3_rc1.txt Ifc4x3_rc1.h
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc4x3_rc1-schema.cpp txt/header_ifc4x3_rc1.txt Ifc4x3_rc1-schema.cpp
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc4x3_rc1-definitions.h txt/header_ifc4x3_rc1.txt Ifc4x3_rc1-definitions.h
|
||||
)
|
||||
|
||||
del *.cpp *.h
|
||||
)
|
||||
|
||||
IF EXIST IFC4x3_RC2.exp (
|
||||
python express_parser.py IFC4x3_RC2.exp header implementation schema_class definitions
|
||||
|
||||
IF EXIST Ifc4x3_rc2-schema.cpp (
|
||||
:: v0.6.0
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc4x3_rc2.cpp txt/header_ifc4x3_rc2.txt Ifc4x3_rc2.cpp
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc4x3_rc2.h txt/header_ifc4x3_rc2.txt Ifc4x3_rc2.h
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc4x3_rc2-schema.cpp txt/header_ifc4x3_rc2.txt Ifc4x3_rc2-schema.cpp
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc4x3_rc2-definitions.h txt/header_ifc4x3_rc2.txt Ifc4x3_rc2-definitions.h
|
||||
)
|
||||
|
||||
del *.cpp *.h
|
||||
)
|
||||
|
||||
IF EXIST IFC4x3_RC3.exp (
|
||||
python express_parser.py IFC4x3_RC3.exp header implementation schema_class definitions
|
||||
|
||||
IF EXIST Ifc4x3_rc3-schema.cpp (
|
||||
:: v0.6.0
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc4x3_rc3.cpp txt/header_ifc4x3_rc2.txt Ifc4x3_rc3.cpp
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc4x3_rc3.h txt/header_ifc4x3_rc2.txt Ifc4x3_rc3.h
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc4x3_rc3-schema.cpp txt/header_ifc4x3_rc2.txt Ifc4x3_rc3-schema.cpp
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc4x3_rc3-definitions.h txt/header_ifc4x3_rc2.txt Ifc4x3_rc3-definitions.h
|
||||
)
|
||||
|
||||
del *.cpp *.h
|
||||
)
|
||||
|
||||
IF EXIST IFC4x3_RC4.exp (
|
||||
python express_parser.py IFC4x3_RC4.exp header implementation schema_class definitions
|
||||
|
||||
IF EXIST Ifc4x3_rc4-schema.cpp (
|
||||
:: v0.6.0
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc4x3_rc4.cpp txt/header_ifc4x3_rc2.txt Ifc4x3_rc4.cpp
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc4x3_rc4.h txt/header_ifc4x3_rc2.txt Ifc4x3_rc4.h
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc4x3_rc4-schema.cpp txt/header_ifc4x3_rc2.txt Ifc4x3_rc4-schema.cpp
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc4x3_rc4-definitions.h txt/header_ifc4x3_rc2.txt Ifc4x3_rc4-definitions.h
|
||||
)
|
||||
|
||||
del *.cpp *.h
|
||||
)
|
||||
|
||||
IF EXIST IFC4X3.exp (
|
||||
python express_parser.py IFC4X3.exp header implementation schema_class definitions
|
||||
|
||||
IF EXIST Ifc4x3-schema.cpp (
|
||||
:: v0.6.0
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc4x3.cpp txt/header_ifc4x3_rc2.txt Ifc4x3.cpp
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc4x3.h txt/header_ifc4x3_rc2.txt Ifc4x3.h
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc4x3-schema.cpp txt/header_ifc4x3_rc2.txt Ifc4x3-schema.cpp
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc4x3-definitions.h txt/header_ifc4x3_rc2.txt Ifc4x3-definitions.h
|
||||
)
|
||||
|
||||
del *.cpp *.h
|
||||
)
|
||||
|
||||
IF EXIST IFC4X3_TC1.exp (
|
||||
python express_parser.py IFC4X3_TC1.exp header implementation schema_class definitions
|
||||
|
||||
IF EXIST Ifc4x3_tc1-schema.cpp (
|
||||
:: v0.6.0
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc4x3_tc1.cpp txt/header_ifc4x3_tc1.txt Ifc4x3_tc1.cpp
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc4x3_tc1.h txt/header_ifc4x3_tc1.txt Ifc4x3_tc1.h
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc4x3_tc1-schema.cpp txt/header_ifc4x3_tc1.txt Ifc4x3_tc1-schema.cpp
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc4x3_tc1-definitions.h txt/header_ifc4x3_tc1.txt Ifc4x3_tc1-definitions.h
|
||||
)
|
||||
|
||||
del *.cpp *.h
|
||||
)
|
||||
|
||||
IF EXIST IFC4X3_ADD1.exp (
|
||||
python express_parser.py IFC4X3_ADD1.exp header implementation schema_class definitions
|
||||
|
||||
IF EXIST Ifc4x3_add1-schema.cpp (
|
||||
:: v0.6.0
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc4x3_add1.cpp txt/header_ifc4x3_add1.txt Ifc4x3_add1.cpp
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc4x3_add1.h txt/header_ifc4x3_add1.txt Ifc4x3_add1.h
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc4x3_add1-schema.cpp txt/header_ifc4x3_add1.txt Ifc4x3_add1-schema.cpp
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc4x3_add1-definitions.h txt/header_ifc4x3_add1.txt Ifc4x3_add1-definitions.h
|
||||
)
|
||||
|
||||
del *.cpp *.h
|
||||
)
|
||||
|
||||
IF EXIST IFC4X3_ADD2.exp (
|
||||
python express_parser.py IFC4X3_ADD2.exp header implementation schema_class definitions
|
||||
|
||||
IF EXIST Ifc4x3_add2-schema.cpp (
|
||||
:: v0.6.0
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc4x3_add2.cpp txt/header_ifc4x3_add2.txt Ifc4x3_add2.cpp
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc4x3_add2.h txt/header_ifc4x3_add2.txt Ifc4x3_add2.h
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc4x3_add2-schema.cpp txt/header_ifc4x3_add2.txt Ifc4x3_add2-schema.cpp
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Ifc4x3_add2-definitions.h txt/header_ifc4x3_add2.txt Ifc4x3_add2-definitions.h
|
||||
)
|
||||
|
||||
del *.cpp *.h
|
||||
)
|
||||
|
||||
IF EXIST header_schema.exp (
|
||||
python express_parser.py header_schema.exp header implementation schema_class definitions
|
||||
|
||||
IF EXIST Header_section_schema-schema.cpp (
|
||||
:: v0.6.0
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Header_section_schema.cpp Header_section_schema.cpp
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Header_section_schema.h Header_section_schema.h
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Header_section_schema-schema.cpp Header_section_schema-schema.cpp
|
||||
python cat.py -o ..\..\..\ifcparse\schemas\Header_section_schema-definitions.h Header_section_schema-definitions.h
|
||||
)
|
||||
|
||||
del *.cpp *.h
|
||||
)
|
||||
@@ -1,25 +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/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file has been generated from IFC2X3_TC1.exp. Do not make modifications *
|
||||
* but instead modify the python script that has been used to generate this. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user