This commit is contained in:
Andrej730
2025-02-18 15:18:23 +05:00
parent 83a351b1c7
commit 17642ca4e9
117 changed files with 683 additions and 1005 deletions
@@ -16,12 +16,14 @@
# You should have received a copy of the GNU Lesser General Public License
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
import numpy.typing as npt
import ifcopenshell.util.unit
from typing import Optional
from ifcopenshell.util.shape_builder import V, SequenceOfVectors, ifc_safe_vector_type
from typing import Optional, Union
def add_arbitrary_profile(
file: ifcopenshell.file, profile: list[tuple[float, float]], name: Optional[str] = None
file: ifcopenshell.file, profile: SequenceOfVectors, name: Optional[str] = None
) -> ifcopenshell.entity_instance:
"""Adds a new arbitrary polyline-based profile
@@ -33,13 +35,10 @@ def add_arbitrary_profile(
identical.
:param profile: A list of coordinates
:type profile: list[tuple[float, float]]
:param name: If the profile is semantically significant (i.e. to be
managed and reused by the user) then it must be named. Otherwise,
this may be left as none.
:type name: str, optional
:return: The newly created IfcArbitraryClosedProfileDef
:rtype: ifcopenshell.entity_instance
Example:
@@ -53,26 +52,30 @@ def add_arbitrary_profile(
"""
usecase = Usecase()
usecase.file = file
usecase.settings = {"profile": profile, "name": name}
return usecase.execute()
return usecase.execute(V(profile), name)
class Usecase:
def execute(self):
self.settings["unit_scale"] = ifcopenshell.util.unit.calculate_unit_scale(self.file)
points = [self.convert_si_to_unit(p) for p in self.settings["profile"]]
if self.file.schema == "IFC2X3":
curve = self.file.createIfcPolyline([self.file.createIfcCartesianPoint(p) for p in points])
else:
dimensions = len(points[0])
if dimensions == 2:
ifc_points = self.file.createIfcCartesianPointList2D(points)
elif dimensions == 3:
ifc_points = self.file.createIfcCartesianPointList3D(points)
curve = self.file.createIfcIndexedPolyCurve(ifc_points)
return self.file.createIfcArbitraryClosedProfileDef("AREA", self.settings["name"], curve)
file: ifcopenshell.file
def convert_si_to_unit(self, co):
if isinstance(co, (tuple, list)):
return [self.convert_si_to_unit(o) for o in co]
return co / self.settings["unit_scale"]
def execute(self, profile: npt.NDArray, name: Union[str, None]):
self.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(self.file)
points = self.convert_si_to_unit(profile)
if self.file.schema == "IFC2X3":
curve = self.file.create_entity(
"IfcPolyline",
[self.file.create_entity("IfcCartesianPoint", ifc_safe_vector_type(p)) for p in points],
)
else:
dimensions = points.shape[1]
if dimensions == 2:
ifc_points = self.file.create_entity("IfcCartesianPointList2D", ifc_safe_vector_type(points))
elif dimensions == 3:
ifc_points = self.file.create_entity("IfcCartesianPointList3D", ifc_safe_vector_type(points))
else:
assert False, f"Invalid dimensions: {dimensions}."
curve = self.file.create_entity("IfcIndexedPolyCurve", ifc_points)
return self.file.create_entity("IfcArbitraryClosedProfileDef", "AREA", name, curve)
def convert_si_to_unit(self, co: npt.NDArray) -> npt.NDArray:
return co / self.unit_scale
@@ -17,13 +17,15 @@
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
import ifcopenshell.util.unit
from typing import Optional
import numpy.typing as npt
from ifcopenshell.util.shape_builder import SequenceOfVectors, ifc_safe_vector_type, V
from typing import Optional, Union
def add_arbitrary_profile_with_voids(
file: ifcopenshell.file,
outer_profile: list[tuple[float, float]],
inner_profiles: list[list[tuple[float, float]]],
outer_profile: SequenceOfVectors,
inner_profiles: list[SequenceOfVectors],
name: Optional[str] = None,
) -> ifcopenshell.entity_instance:
"""Adds a new arbitrary polyline-based profile with voids
@@ -41,15 +43,11 @@ def add_arbitrary_profile_with_voids(
provided in SI meters.
:param outer_profile: A list of coordinates
:type profile: list[tuple[float, float]]
:param inner_profiles: A list of polylines
:type profile: list[list[tuple[float, float]]]
:param name: If the profile is semantically significant (i.e. to be
managed and reused by the user) then it must be named. Otherwise,
this may be left as none.
:type name: str, optional
:return: The newly created IfcArbitraryProfileDefWithVoids
:rtype: ifcopenshell.entity_instance
Example:
@@ -63,37 +61,52 @@ def add_arbitrary_profile_with_voids(
"""
usecase = Usecase()
usecase.file = file
usecase.settings = {"outer_profile": outer_profile, "inner_profiles": inner_profiles, "name": name}
return usecase.execute()
return usecase.execute(V(outer_profile), [V(p) for p in inner_profiles], name)
class Usecase:
def execute(self):
self.settings["unit_scale"] = ifcopenshell.util.unit.calculate_unit_scale(self.file)
outer_points = [self.convert_si_to_unit(p) for p in self.settings["outer_profile"]]
inner_points = []
for inner_profile in self.settings["inner_profiles"]:
inner_points.append([self.convert_si_to_unit(p) for p in inner_profile])
file: ifcopenshell.file
def execute(
self,
outer_profile: npt.NDArray,
inner_profiles: list[npt.NDArray],
name: Union[str, None],
):
self.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(self.file)
outer_points = self.convert_si_to_unit(outer_profile)
inner_points: list[npt.NDArray] = []
for inner_profile in inner_profiles:
inner_points.append(self.convert_si_to_unit(inner_profile))
inner_curves: list[ifcopenshell.entity_instance] = []
if self.file.schema == "IFC2X3":
outer_curve = self.file.createIfcPolyline([self.file.createIfcCartesianPoint(p) for p in outer_points])
inner_curves = []
outer_curve = self.file.create_entity(
"IfcPolyline",
[self.file.create_entity("IfcCartesianPoint", ifc_safe_vector_type(p)) for p in outer_points],
)
for inner_point in inner_points:
inner_curves.append(
self.file.createIfcPolyline([self.file.createIfcCartesianPoint(p) for p in inner_point])
self.file.create_entity(
"IfcPolyline",
[self.file.create_entity("IfcCartesianPoint", ifc_safe_vector_type(p)) for p in inner_point],
)
)
else:
outer_curve = self.file.createIfcIndexedPolyCurve(self.file.createIfcCartesianPointList3D(outer_points))
inner_curves = []
outer_curve = self.file.create_entity(
"IfcIndexedPolyCurve",
(self.file.create_entity("IfcCartesianPointList3D", ifc_safe_vector_type(outer_points))),
)
for inner_point in inner_points:
dimensions = len(inner_point[0])
dimensions = inner_point.shape[1]
if dimensions == 2:
ifc_points = self.file.createIfcCartesianPointList2D(inner_point)
ifc_points = self.file.create_entity("IfcCartesianPointList2D", ifc_safe_vector_type(inner_point))
elif dimensions == 3:
ifc_points = self.file.createIfcCartesianPointList3D(inner_point)
inner_curves.append(self.file.createIfcIndexedPolyCurve(ifc_points))
return self.file.createIfcArbitraryProfileDefWithVoids("AREA", self.settings["name"], outer_curve, inner_curves)
ifc_points = self.file.create_entity("IfcCartesianPointList3D", ifc_safe_vector_type(inner_point))
else:
assert False, f"Invalid dimensions: {dimensions}."
inner_curves.append(self.file.create_entity("IfcIndexedPolyCurve", ifc_points))
return self.file.create_entity("IfcArbitraryProfileDefWithVoids", "AREA", name, outer_curve, inner_curves)
def convert_si_to_unit(self, co):
if isinstance(co, (tuple, list)):
return [self.convert_si_to_unit(o) for o in co]
return co / self.settings["unit_scale"]
def convert_si_to_unit(self, co: npt.NDArray) -> npt.NDArray:
return co / self.unit_scale
@@ -26,11 +26,8 @@ def edit_profile(file: ifcopenshell.file, profile: ifcopenshell.entity_instance,
IfcProfileDef, consult the IFC documentation.
:param profile: The IfcProfileDef entity you want to edit
:type profile: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
:type attributes: dict
:return: None
:rtype: None
Example:
@@ -43,7 +40,5 @@ def edit_profile(file: ifcopenshell.file, profile: ifcopenshell.entity_instance,
ifcopenshell.api.profile.edit_profile(model,
profile=circle, attributes={"ProfileName": "1000mm Dia"})
"""
settings = {"profile": profile, "attributes": attributes}
for name, value in settings["attributes"].items():
setattr(settings["profile"], name, value)
for name, value in attributes.items():
setattr(profile, name, value)