mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-26 10:11:46 +00:00
See #1227. Implement updating of object position.
This commit is contained in:
@@ -1008,7 +1008,6 @@ class DumbWallJoiner:
|
|||||||
ifcopenshell.api.geometry.edit_object_placement(
|
ifcopenshell.api.geometry.edit_object_placement(
|
||||||
tool.Ifc.get(), product=element1, matrix=matrix, is_si=False, should_transform_children=False
|
tool.Ifc.get(), product=element1, matrix=matrix, is_si=False, should_transform_children=False
|
||||||
)
|
)
|
||||||
self.import_position(element1, wall1)
|
|
||||||
self.recreate_wall(element1, wall1)
|
self.recreate_wall(element1, wall1)
|
||||||
|
|
||||||
def merge(self, wall1, wall2):
|
def merge(self, wall1, wall2):
|
||||||
@@ -1111,13 +1110,6 @@ class DumbWallJoiner:
|
|||||||
else:
|
else:
|
||||||
ifcopenshell.api.geometry.assign_representation(self.file, product=wall, representation=rep)
|
ifcopenshell.api.geometry.assign_representation(self.file, product=wall, representation=rep)
|
||||||
|
|
||||||
def import_position(self, element, obj):
|
|
||||||
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
|
|
||||||
matrix = ifcopenshell.util.placement.get_local_placement(element.ObjectPlacement)
|
|
||||||
matrix[:, 3] *= unit_scale
|
|
||||||
obj.matrix_world = tool.Loader.apply_blender_offset_to_matrix_world(obj, matrix)
|
|
||||||
tool.Geometry.record_object_position(obj)
|
|
||||||
|
|
||||||
def join_E(self, wall1, target):
|
def join_E(self, wall1, target):
|
||||||
if tool.Ifc.is_moved(wall1):
|
if tool.Ifc.is_moved(wall1):
|
||||||
bonsai.core.geometry.edit_object_placement(tool.Ifc, tool.Geometry, tool.Surveyor, obj=wall1)
|
bonsai.core.geometry.edit_object_placement(tool.Ifc, tool.Geometry, tool.Surveyor, obj=wall1)
|
||||||
@@ -1198,6 +1190,12 @@ class DumbWallJoiner:
|
|||||||
should_sync_changes_first=False,
|
should_sync_changes_first=False,
|
||||||
)
|
)
|
||||||
tool.Geometry.record_object_materials(obj)
|
tool.Geometry.record_object_materials(obj)
|
||||||
|
|
||||||
|
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
|
||||||
|
matrix = ifcopenshell.util.placement.get_local_placement(element.ObjectPlacement)
|
||||||
|
matrix[:, 3] *= unit_scale
|
||||||
|
obj.matrix_world = tool.Loader.apply_blender_offset_to_matrix_world(obj, matrix)
|
||||||
|
tool.Geometry.record_object_position(obj)
|
||||||
return
|
return
|
||||||
|
|
||||||
wall_moved = tool.Ifc.is_moved(obj)
|
wall_moved = tool.Ifc.is_moved(obj)
|
||||||
|
|||||||
@@ -34,6 +34,27 @@ def edit_object_placement(
|
|||||||
is_si: bool = True,
|
is_si: bool = True,
|
||||||
should_transform_children: bool = False,
|
should_transform_children: bool = False,
|
||||||
) -> ifcopenshell.entity_instance:
|
) -> 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 = Usecase()
|
||||||
usecase.file = file
|
usecase.file = file
|
||||||
usecase.settings = {
|
usecase.settings = {
|
||||||
|
|||||||
+36
-9
@@ -19,9 +19,10 @@
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
import ifcopenshell
|
import ifcopenshell
|
||||||
import ifcopenshell.api.geometry
|
import ifcopenshell.api.geometry
|
||||||
import ifcopenshell.util.shape_builder
|
|
||||||
import ifcopenshell.util.element
|
|
||||||
import ifcopenshell.util.unit
|
import ifcopenshell.util.unit
|
||||||
|
import ifcopenshell.util.element
|
||||||
|
import ifcopenshell.util.placement
|
||||||
|
import ifcopenshell.util.shape_builder
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
from math import sin, cos
|
from math import sin, cos
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
@@ -63,6 +64,14 @@ def regenerate_wall_representation(
|
|||||||
additional extrusions are generated for each connection that boolean
|
additional extrusions are generated for each connection that boolean
|
||||||
difference the base extrusion.
|
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,
|
:param wall: The IfcWall for the representation,
|
||||||
only Model/Body/MODEL_VIEW type of representations are currently supported.
|
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
|
:param length: If the wall doesn't have an axis length, this is the default
|
||||||
@@ -165,7 +174,7 @@ class Regenerator:
|
|||||||
end_points.reverse()
|
end_points.reverse()
|
||||||
points.extend(end_points)
|
points.extend(end_points)
|
||||||
item = builder.extrude(
|
item = builder.extrude(
|
||||||
builder.polyline(points, closed=True),
|
builder.polyline(points, closed=True, position_offset=self.reference_p1 * -1),
|
||||||
magnitude=self.wall_vectors["d"],
|
magnitude=self.wall_vectors["d"],
|
||||||
extrusion_vector=self.wall_vectors["z"],
|
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]))
|
magnitude = np.linalg.norm(self.start_vector * (self.wall_vectors["h"] / self.start_vector[2]))
|
||||||
operands.append(
|
operands.append(
|
||||||
builder.extrude(
|
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]))
|
magnitude = np.linalg.norm(self.end_vector * (self.wall_vectors["h"] / self.end_vector[2]))
|
||||||
operands.append(
|
operands.append(
|
||||||
builder.extrude(
|
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]))
|
magnitude = np.linalg.norm(atpath_vector * (self.wall_vectors["h"] / atpath_vector[2]))
|
||||||
operands.append(
|
operands.append(
|
||||||
builder.extrude(
|
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)
|
remaining_path_points.append(minpath_points)
|
||||||
self.minpath_points = remaining_path_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:
|
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:
|
if len(profiles) > 1:
|
||||||
profile = self.file.createIfcCompositeProfileDef("AREA", Profiles=profiles)
|
profile = self.file.createIfcCompositeProfileDef("AREA", Profiles=profiles)
|
||||||
@@ -283,13 +302,21 @@ class Regenerator:
|
|||||||
else:
|
else:
|
||||||
ifcopenshell.api.geometry.assign_representation(self.file, product=wall, representation=body_rep)
|
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])
|
axis_rep = builder.get_representation(self.axis, items=[item])
|
||||||
if old_rep := ifcopenshell.util.representation.get_representation(wall, self.axis):
|
if old_rep := ifcopenshell.util.representation.get_representation(wall, self.axis):
|
||||||
ifcopenshell.util.element.replace_element(old_rep, axis_rep)
|
ifcopenshell.util.element.replace_element(old_rep, axis_rep)
|
||||||
ifcopenshell.util.element.remove_deep2(self.file, old_rep)
|
ifcopenshell.util.element.remove_deep2(self.file, old_rep)
|
||||||
else:
|
else:
|
||||||
ifcopenshell.api.geometry.assign_representation(self.file, product=wall, representation=axis_rep)
|
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
|
return body_rep
|
||||||
|
|
||||||
def join(self, wall1, wall2, layers1, layers2, connection1, connection2):
|
def join(self, wall1, wall2, layers1, layers2, connection1, connection2):
|
||||||
|
|||||||
Reference in New Issue
Block a user