mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 17:58:20 +00:00
See #1227. Implement updating of object position.
This commit is contained in:
@@ -34,6 +34,27 @@ def edit_object_placement(
|
||||
is_si: bool = True,
|
||||
should_transform_children: bool = False,
|
||||
) -> ifcopenshell.entity_instance:
|
||||
"""Changes the object placement matrix of an element
|
||||
|
||||
The placement matrix is a 4x4 matrix describing the location and
|
||||
orientation of an element in 3D. See
|
||||
https://docs.ifcopenshell.org/ifcopenshell-python/geometry_creation.html#object-placements
|
||||
for more details.
|
||||
|
||||
This only supports local placements. Grid and linear placements are not
|
||||
supported.
|
||||
|
||||
:param matrix: A 4x4 matrix in numpy. If left blank, it is the identity
|
||||
matrix (equivalent to ``np.eye(4)``).
|
||||
:param is_si: If True, the matrix is given in SI units. If false, in
|
||||
project units.
|
||||
:param should_transform_children: A child element is a nested element,
|
||||
opening, filling, etc. If true, child elements will move along with the
|
||||
parent. If false, child elements will stay where they are. Because most
|
||||
placements in IFC are relative, this means that if a child moves, we
|
||||
actually don't change their placement.
|
||||
:return: The new or updated IfcLocalPlacement entity
|
||||
"""
|
||||
usecase = Usecase()
|
||||
usecase.file = file
|
||||
usecase.settings = {
|
||||
|
||||
+36
-9
@@ -19,9 +19,10 @@
|
||||
import numpy as np
|
||||
import ifcopenshell
|
||||
import ifcopenshell.api.geometry
|
||||
import ifcopenshell.util.shape_builder
|
||||
import ifcopenshell.util.element
|
||||
import ifcopenshell.util.unit
|
||||
import ifcopenshell.util.element
|
||||
import ifcopenshell.util.placement
|
||||
import ifcopenshell.util.shape_builder
|
||||
from collections import namedtuple
|
||||
from math import sin, cos
|
||||
from typing import Optional
|
||||
@@ -63,6 +64,14 @@ def regenerate_wall_representation(
|
||||
additional extrusions are generated for each connection that boolean
|
||||
difference the base extrusion.
|
||||
|
||||
This will also update the axis line representation (e.g. trim the axis line
|
||||
to any connections).
|
||||
|
||||
The wall's object placement will also be updated such that the placement is
|
||||
equivalent to the axis line's start point (which therefore becomes (0.0,
|
||||
0.0)). This is a logical, consistent, and useful placement coordinate
|
||||
(especially for apps that can pivot using this point).
|
||||
|
||||
:param wall: The IfcWall for the representation,
|
||||
only Model/Body/MODEL_VIEW type of representations are currently supported.
|
||||
:param length: If the wall doesn't have an axis length, this is the default
|
||||
@@ -165,7 +174,7 @@ class Regenerator:
|
||||
end_points.reverse()
|
||||
points.extend(end_points)
|
||||
item = builder.extrude(
|
||||
builder.polyline(points, closed=True),
|
||||
builder.polyline(points, closed=True, position_offset=self.reference_p1 * -1),
|
||||
magnitude=self.wall_vectors["d"],
|
||||
extrusion_vector=self.wall_vectors["z"],
|
||||
)
|
||||
@@ -186,7 +195,9 @@ class Regenerator:
|
||||
magnitude = np.linalg.norm(self.start_vector * (self.wall_vectors["h"] / self.start_vector[2]))
|
||||
operands.append(
|
||||
builder.extrude(
|
||||
builder.polyline(points, closed=True), magnitude=magnitude, extrusion_vector=self.start_vector
|
||||
builder.polyline(points, closed=True, position_offset=self.reference_p1 * -1),
|
||||
magnitude=magnitude,
|
||||
extrusion_vector=self.start_vector,
|
||||
)
|
||||
)
|
||||
|
||||
@@ -206,7 +217,9 @@ class Regenerator:
|
||||
magnitude = np.linalg.norm(self.end_vector * (self.wall_vectors["h"] / self.end_vector[2]))
|
||||
operands.append(
|
||||
builder.extrude(
|
||||
builder.polyline(points, closed=True), magnitude=magnitude, extrusion_vector=self.end_vector
|
||||
builder.polyline(points, closed=True, position_offset=self.reference_p1 * -1),
|
||||
magnitude=magnitude,
|
||||
extrusion_vector=self.end_vector,
|
||||
)
|
||||
)
|
||||
|
||||
@@ -216,7 +229,9 @@ class Regenerator:
|
||||
magnitude = np.linalg.norm(atpath_vector * (self.wall_vectors["h"] / atpath_vector[2]))
|
||||
operands.append(
|
||||
builder.extrude(
|
||||
builder.polyline(points, closed=True), magnitude=magnitude, extrusion_vector=atpath_vector
|
||||
builder.polyline(points, closed=True, position_offset=self.reference_p1 * -1),
|
||||
magnitude=magnitude,
|
||||
extrusion_vector=atpath_vector,
|
||||
)
|
||||
)
|
||||
|
||||
@@ -265,10 +280,14 @@ class Regenerator:
|
||||
remaining_path_points.append(minpath_points)
|
||||
self.minpath_points = remaining_path_points
|
||||
|
||||
profiles.append(builder.profile(builder.polyline(points, closed=True)))
|
||||
profiles.append(
|
||||
builder.profile(builder.polyline(points, closed=True, position_offset=self.reference_p1 * -1))
|
||||
)
|
||||
|
||||
for points in self.maxpath_points + self.minpath_points:
|
||||
profiles.append(builder.profile(builder.polyline(points, closed=True)))
|
||||
profiles.append(
|
||||
builder.profile(builder.polyline(points, closed=True, position_offset=self.reference_p1 * -1))
|
||||
)
|
||||
|
||||
if len(profiles) > 1:
|
||||
profile = self.file.createIfcCompositeProfileDef("AREA", Profiles=profiles)
|
||||
@@ -283,13 +302,21 @@ class Regenerator:
|
||||
else:
|
||||
ifcopenshell.api.geometry.assign_representation(self.file, product=wall, representation=body_rep)
|
||||
|
||||
item = builder.polyline([self.reference_p1, self.reference_p2])
|
||||
item = builder.polyline([self.reference_p1, self.reference_p2], position_offset=self.reference_p1 * -1)
|
||||
axis_rep = builder.get_representation(self.axis, items=[item])
|
||||
if old_rep := ifcopenshell.util.representation.get_representation(wall, self.axis):
|
||||
ifcopenshell.util.element.replace_element(old_rep, axis_rep)
|
||||
ifcopenshell.util.element.remove_deep2(self.file, old_rep)
|
||||
else:
|
||||
ifcopenshell.api.geometry.assign_representation(self.file, product=wall, representation=axis_rep)
|
||||
|
||||
if not np.allclose(self.reference_p1, np.array((0.0, 0.0))):
|
||||
matrix = ifcopenshell.util.placement.get_local_placement(wall.ObjectPlacement)
|
||||
matrix[:, 3] = matrix @ np.concatenate((self.reference_p1, (0, 1)))
|
||||
ifcopenshell.api.geometry.edit_object_placement(
|
||||
self.file, product=wall, matrix=matrix, is_si=False, should_transform_children=False
|
||||
)
|
||||
|
||||
return body_rep
|
||||
|
||||
def join(self, wall1, wall2, layers1, layers2, connection1, connection2):
|
||||
|
||||
Reference in New Issue
Block a user