mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-20 15:08:51 +00:00
See #1227. Don't touch manual booleans when regenerating wall body.
This commit is contained in:
+27
-13
@@ -16,6 +16,7 @@
|
|||||||
# You should have received a copy of the GNU Lesser General Public License
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import json
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import ifcopenshell
|
import ifcopenshell
|
||||||
import ifcopenshell.api.geometry
|
import ifcopenshell.api.geometry
|
||||||
@@ -119,6 +120,8 @@ class Regenerator:
|
|||||||
self.end_points = []
|
self.end_points = []
|
||||||
self.end_vector = np.array((0.0, 0.0, 1.0))
|
self.end_vector = np.array((0.0, 0.0, 1.0))
|
||||||
self.end_offset = 0.0
|
self.end_offset = 0.0
|
||||||
|
manual_booleans = self.get_manual_booleans(wall)
|
||||||
|
|
||||||
for rel in wall.ConnectedTo:
|
for rel in wall.ConnectedTo:
|
||||||
if rel.is_a("IfcRelConnectsPathElements"):
|
if rel.is_a("IfcRelConnectsPathElements"):
|
||||||
wall2 = rel.RelatedElement
|
wall2 = rel.RelatedElement
|
||||||
@@ -160,6 +163,9 @@ class Regenerator:
|
|||||||
|
|
||||||
builder = ifcopenshell.util.shape_builder.ShapeBuilder(self.file)
|
builder = ifcopenshell.util.shape_builder.ShapeBuilder(self.file)
|
||||||
|
|
||||||
|
# Don't offset wall if there are manual booleans, because that'll also shift operands
|
||||||
|
offset = None if manual_booleans else self.reference_p1 * -1
|
||||||
|
|
||||||
if self.is_angled:
|
if self.is_angled:
|
||||||
start_points = [p.copy() for p in self.start_points]
|
start_points = [p.copy() for p in self.start_points]
|
||||||
end_points = [p.copy() for p in self.end_points]
|
end_points = [p.copy() for p in self.end_points]
|
||||||
@@ -174,7 +180,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, position_offset=self.reference_p1 * -1),
|
builder.polyline(points, closed=True, position_offset=offset),
|
||||||
magnitude=self.wall_vectors["d"],
|
magnitude=self.wall_vectors["d"],
|
||||||
extrusion_vector=self.wall_vectors["z"],
|
extrusion_vector=self.wall_vectors["z"],
|
||||||
)
|
)
|
||||||
@@ -195,7 +201,7 @@ 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, position_offset=self.reference_p1 * -1),
|
builder.polyline(points, closed=True, position_offset=offset),
|
||||||
magnitude=magnitude,
|
magnitude=magnitude,
|
||||||
extrusion_vector=self.start_vector,
|
extrusion_vector=self.start_vector,
|
||||||
)
|
)
|
||||||
@@ -217,7 +223,7 @@ 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, position_offset=self.reference_p1 * -1),
|
builder.polyline(points, closed=True, position_offset=offset),
|
||||||
magnitude=magnitude,
|
magnitude=magnitude,
|
||||||
extrusion_vector=self.end_vector,
|
extrusion_vector=self.end_vector,
|
||||||
)
|
)
|
||||||
@@ -229,7 +235,7 @@ 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, position_offset=self.reference_p1 * -1),
|
builder.polyline(points, closed=True, position_offset=offset),
|
||||||
magnitude=magnitude,
|
magnitude=magnitude,
|
||||||
extrusion_vector=atpath_vector,
|
extrusion_vector=atpath_vector,
|
||||||
)
|
)
|
||||||
@@ -286,14 +292,10 @@ 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(
|
profiles.append(builder.profile(builder.polyline(points, closed=True, position_offset=offset)))
|
||||||
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(
|
profiles.append(builder.profile(builder.polyline(points, closed=True, position_offset=offset)))
|
||||||
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)
|
||||||
@@ -301,6 +303,10 @@ class Regenerator:
|
|||||||
profile = profiles[0]
|
profile = profiles[0]
|
||||||
|
|
||||||
item = builder.extrude(profile, magnitude=self.wall_vectors["d"], extrusion_vector=self.wall_vectors["z"])
|
item = builder.extrude(profile, magnitude=self.wall_vectors["d"], extrusion_vector=self.wall_vectors["z"])
|
||||||
|
for boolean in self.get_manual_booleans(wall):
|
||||||
|
boolean.FirstOperand = item
|
||||||
|
item = boolean
|
||||||
|
|
||||||
body_rep = builder.get_representation(self.body, items=[item])
|
body_rep = builder.get_representation(self.body, items=[item])
|
||||||
if old_rep := ifcopenshell.util.representation.get_representation(wall, self.body):
|
if old_rep := ifcopenshell.util.representation.get_representation(wall, self.body):
|
||||||
ifcopenshell.util.element.replace_element(old_rep, body_rep)
|
ifcopenshell.util.element.replace_element(old_rep, body_rep)
|
||||||
@@ -308,7 +314,7 @@ 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], position_offset=self.reference_p1 * -1)
|
item = builder.polyline([self.reference_p1, self.reference_p2], position_offset=offset)
|
||||||
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)
|
||||||
@@ -316,7 +322,7 @@ class Regenerator:
|
|||||||
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))):
|
if not np.allclose(self.reference_p1, np.array((0.0, 0.0))) and not manual_booleans:
|
||||||
children = []
|
children = []
|
||||||
for referenced_placement in wall.ObjectPlacement.ReferencedByPlacements:
|
for referenced_placement in wall.ObjectPlacement.ReferencedByPlacements:
|
||||||
matrix = ifcopenshell.util.placement.get_local_placement(referenced_placement)
|
matrix = ifcopenshell.util.placement.get_local_placement(referenced_placement)
|
||||||
@@ -599,7 +605,7 @@ class Regenerator:
|
|||||||
return result * -1
|
return result * -1
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def get_axes(self, wall, reference, layers: list[PrioritisedLayer], angle: float):
|
def get_axes(self, wall: ifcopenshell.entity_instance, reference, layers: list[PrioritisedLayer], angle: float):
|
||||||
axes = [[p.copy() for p in reference]]
|
axes = [[p.copy() for p in reference]]
|
||||||
# Apply usage to convert the Reference line into MlsBase
|
# Apply usage to convert the Reference line into MlsBase
|
||||||
sense_factor = 1
|
sense_factor = 1
|
||||||
@@ -612,3 +618,11 @@ class Regenerator:
|
|||||||
y_offset = (layer.thickness * sense_factor) / cos(angle)
|
y_offset = (layer.thickness * sense_factor) / cos(angle)
|
||||||
axes.append([p.copy() + np.array((0.0, y_offset)) for p in axes[-1]])
|
axes.append([p.copy() + np.array((0.0, y_offset)) for p in axes[-1]])
|
||||||
return axes
|
return axes
|
||||||
|
|
||||||
|
def get_manual_booleans(self, element: ifcopenshell.entity_instance):
|
||||||
|
if pset := ifcopenshell.util.element.get_pset(element, "BBIM_Boolean"):
|
||||||
|
try:
|
||||||
|
return [self.file.by_id(boolean_id) for boolean_id in json.loads(pset["Data"])]
|
||||||
|
except:
|
||||||
|
return []
|
||||||
|
return []
|
||||||
|
|||||||
Reference in New Issue
Block a user