Compare commits

...

17 Commits

Author SHA1 Message Date
Dion Moult 2c1d445d5b ifcviewer-web: mint session model ids when a load is requested
A federated pick could be attributed to the wrong file. The model slot a
host sees — ElementRef::model_index, modelProgress's index — is a rank in
session_model_id order, and on web that id was minted at the END of the
sidecar read chain, after three network round trips. So the ranking was
the order the models' reads happened to finish in, not the order the host
added them. With ~40 similarly-sized models over HTTP, adjacent models
swapped and a click reported its neighbour's file; the host page then
asked for a GUID the file does not contain.

Mint the id at the top of loadSidecarMetadataWeb instead, which runs
synchronously from load_sidecar_from_source_c and therefore in the order
the host asked for its models. A load that fails partway just abandons
its id, and the ranks compact over the surviving models as before.

Positions are still positions, though: if one model fails to load, every
later index shifts down one and a host mapping index into its own list
silently drifts again. So also carry the source id — the handle the host
minted itself when it registered the file — through ElementRef into the
pick payload and getObjects rows, and document it as the way to attribute
an object to a file. ModelGpuData::web_source_id defaults to -1 now, since
0 is a real source id and cannot double as "none".

The test server grows a ?delay=<ms> knob so a test can force the losing
interleaving: georef-a is added first and served slowly, and its objects
must still come back as model 0.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-21 11:30:56 +10:00
Dion Moult d86f89090b ifcviewer-web: draw the axis indicator (corner gizmo + orbit pivot)
The desktop viewport draws an RGB triad in the bottom-left corner and a
second one at the orbit target while navigating; the web build drew
neither. Both lived in the Qt-coupled OverlayRenderer, which only
ViewportWindow drives — the web host no-ops the overlay hooks — so the
wasm build had no path to them at all.

Lift them into AxisIndicatorRenderer, a Qt-free renderer in
IfcViewerCore, and drive it from ViewportCore::render for desktop and
web alike. Same move SectionGizmoRenderer already made; the drawing code
is unchanged apart from swapping qDegreesToRadians for CameraMath's kPiF.

Pivot visibility moves to the core with it: it was a QTimer on
ViewportWindow, so the afterglow couldn't follow the gizmo across. It is
now a Stopwatch deadline next to the drawing, with render() requesting
frames until an armed afterglow expires. Hosts keep the same three
triggers (on for orbit/pan drags, off on release, 600 ms on wheel).

The web demo shell's log overlay sat exactly on top of the corner gizmo,
so it shifts right of the 110 px box.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-21 11:16:41 +10:00
Andrej730 973f61c6dc express.h: remove non-snake case aliases (schemas are regenerated now) 2026-08-19 20:17:51 +05:00
Andrej730 f47aa4d81a Manually update other schemas 2026-08-19 20:17:51 +05:00
Andrej730 fa9a3383aa Use snake case in cpp consistently 2026-08-19 20:17:51 +05:00
Andrej730 104591a80b Normalize whitespaces in the codebase 2026-08-19 20:17:50 +05:00
Andrej730 030e6e5bb4 Regen cpp schemas 2026-08-19 20:17:50 +05:00
Andrej730 a031310a66 express/run.bat: rewrite in Python 2026-08-19 20:17:50 +05:00
Andrej730 436e3f7b2a Header_section_schema-definitions.h: use IFC_SCHEMA_API 2026-08-19 20:17:50 +05:00
Andrej730 335d571854 gltf_serializer: refactor proj code into a separate call 2026-08-19 20:17:49 +05:00
Andrej730 f78b380b71 express/mapping: fix breaking generation after f23db9440f
It was failing to map `int64_t` to `Argument_INT` enum.
2026-08-19 19:38:30 +05:00
Andrej730 2cebc3f60b typing 2026-08-19 19:38:30 +05:00
Andrej730 0a8159505d pyproject: black to format all files by default 2026-08-19 19:38:30 +05:00
Andrej730 301fba5a8b Bump ty to 0.0.72 2026-08-19 19:38:30 +05:00
Andrej730 ba90cf220d black, ruff 2026-08-19 19:38:29 +05:00
Andrej730 6318892a97 Script to check whitespace issues in the codebase 2026-08-19 19:33:08 +05:00
Dion Moult 1a6336bd20 Output test audits to sqlite 2026-08-18 13:50:14 +10:00
193 changed files with 45525 additions and 44679 deletions
+377
View File
@@ -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())
+1
View 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
View File
@@ -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 -1
View File
@@ -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
+6 -6
View File
@@ -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);
+6 -6
View File
@@ -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
+20 -20
View File
@@ -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);
+2 -2
View File
@@ -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();
+28 -28
View File
@@ -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));
+2 -2
View File
@@ -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)
+2 -2
View File
@@ -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();
}
}
}
+6 -6
View File
@@ -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 {
+1 -1
View File
@@ -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 {
+3 -3
View File
@@ -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();
+1 -1
View File
@@ -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_; }
+2 -2
View File
@@ -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
View File
@@ -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.
+1 -1
View 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);
+2 -2
View File
@@ -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);
}
+4 -4
View File
@@ -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)) {
+1 -1
View File
@@ -9,7 +9,7 @@
namespace ifcopenshell {
namespace geom {
struct IFC_GEOM_API cross_section {
double dist_along;
taxonomy::geom_item::ptr section_geometry;
+4 -4
View File
@@ -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");
}
+2 -2
View File
@@ -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) {
+9 -9
View File
@@ -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);
+1 -1
View File
@@ -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)) {
+10 -10
View File
@@ -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);
+1 -1
View File
@@ -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() };
}
};
};
}
}
+5 -5
View File
@@ -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]);
+1 -1
View File
@@ -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);
+2 -2
View File
@@ -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);
+18 -18
View File
@@ -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;
+1 -1
View File
@@ -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())));
+1 -1
View File
@@ -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;
}
+1 -1
View File
@@ -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);
+1 -1
View File
@@ -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) {
+10 -10
View File
@@ -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;
+2 -2
View File
@@ -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;
}
+1 -1
View File
@@ -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;
+1 -1
View File
@@ -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;
}
+1 -1
View File
@@ -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);
}
+1 -1
View File
@@ -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 };
+2 -2
View File
@@ -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}},
+1 -1
View File
@@ -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;
+2 -2
View File
@@ -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;
+6 -6
View File
@@ -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()) {
+1 -1
View File
@@ -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;
+4 -4
View File
@@ -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 ++) {
+1 -1
View File
@@ -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;
+1 -1
View File
@@ -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.;
+8 -8
View File
@@ -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;
}
+3 -3
View File
@@ -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) {
+1 -1
View File
@@ -182,4 +182,4 @@ BIND(IfcSurfaceStyle); // -> style
#ifdef SCHEMA_HAS_IfcCurveSegment
BIND(IfcCurveSegment);
#endif
#endif
+3 -3
View File
@@ -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))) {
+1 -1
View File
@@ -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();
+1 -1
View File
@@ -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 {
+1 -1
View File
@@ -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;
+10 -10
View File
@@ -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;
+3 -3
View File
@@ -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
View File
@@ -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. *
* *
********************************************************************************/
@@ -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 IFC4.exp. Do not make modifications *
* but instead modify the python script that has been used to generate this. *
* *
********************************************************************************/
@@ -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 IFC4x1.exp. Do not make modifications *
* but instead modify the python script that has been used to generate this. *
* *
********************************************************************************/
@@ -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 IFC4x2.exp. Do not make modifications *
* but instead modify the python script that has been used to generate this. *
* *
********************************************************************************/
@@ -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 IFC4X3_ADD1.exp. Do not make modifications *
* but instead modify the python script that has been used to generate this. *
* *
********************************************************************************/
@@ -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 IFC4X3_ADD2.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