Skip to content

Commit

Permalink
fix: Minor bugfixes and refactoring (#119)
Browse files Browse the repository at this point in the history
  • Loading branch information
Krande authored Nov 21, 2024
1 parent 102eada commit ad22775
Show file tree
Hide file tree
Showing 74 changed files with 1,265 additions and 351 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci-FEM.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ jobs:
run: echo "DATE=$(echo $(date +'%y%m%d'))" >> $GITHUB_ENV

- uses: mamba-org/setup-micromamba@v2 # https://github.com/mamba-org/setup-micromamba
environment-name: fem-env
with:
environment-name: fem-env
condarc: |
channels:
- conda-forge
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/ci-code-profiling.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ jobs:
create-args: >-
ada-py
bcf-client
numpy<2
python=3.12
pytest
pytest-benchmark
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pr-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:

- uses: prefix-dev/[email protected] # https://github.com/prefix-dev/setup-pixi
with:
pixi-version: v0.30.0
pixi-version: v0.36.0
cache: true
environments: lint

Expand Down
30 changes: 26 additions & 4 deletions examples/scripts/geom/boxes.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,39 @@
import ada
from ada.base.ifc_types import SpatialTypes
from ada.visit.renderer_manager import RenderParams


def build_and_show():
dp = ada.Point(0.5, 0.5, 0.5)
boxes = []
for i, box_c in enumerate([(0, 0, 0), (3, 0, 0), (3, 3, 0), (0, 3, 0)], start=1):
coords = [(0, 0, 0), (3, 0, 0), (3, 3, 0), (0, 3, 0)]
for i, box_c in enumerate(coords, start=1):
p1 = ada.Point(box_c) - dp
p2 = ada.Point(box_c) + dp
box = ada.PrimBox(f"box{i}", p1, p2)
box = ada.PrimBox(f"SpaceBox{i}", p1, p2)
boxes.append(box)

p = ada.Part("MyPart") / boxes
p.show()
p = ada.Part("MySpaces", ifc_class=SpatialTypes.IfcSpace) / boxes
p.add_group("MyBoxes", boxes)

boxes = []
offset = ada.Point(0, 0, 3)
dp = ada.Point(0.5, 0.5, 0.5)
for i, box_c in enumerate(coords, start=1):
p1 = offset + ada.Point(box_c) - dp
p2 = offset + ada.Point(box_c) + dp
box = ada.PrimBox(f"StoreyBox{i}", p1, p2, color="red", opacity=0.5)
boxes.append(box)
p2 = ada.Part("MyStorey") / boxes

a = ada.Assembly("MySite") / (p, p2)
layer = a.presentation_layers.add_layer("Hidden", "Hidden Layer")
layer.members.extend(boxes)

a.show(
params_override=RenderParams(gltf_export_to_file="temp/demo.glb", gltf_asset_extras_dict={"web3dversion": "2"})
)
a.to_ifc("temp/space_boxes.ifc")


if __name__ == "__main__":
Expand Down
293 changes: 238 additions & 55 deletions pixi.lock

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ frontend = { features = ["web"], no-default-feature = true}

[tool.pixi.feature.py312.dependencies]
python="3.12"
bcf-client="*"
kaleido-core = "0.1.0"
numpy = "*"
hdf5 = "*"
Expand All @@ -88,7 +89,7 @@ trimesh = "*"
occt =">=7.7.2"
send2trash = "*"
meshio = "*"
websockets = "*"
websockets = ">=14"
plotly = "*"
python-kaleido = "*"
calculix = "*"
Expand Down
2 changes: 2 additions & 0 deletions src/ada/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
from ada.materials import Material
from ada.sections import Section
from ada.visit.config import set_jupyter_part_renderer
from ada.warnings import deprecated

if TYPE_CHECKING:
import ifcopenshell
Expand Down Expand Up @@ -122,6 +123,7 @@ def from_genie_xml(xml_path, **kwargs) -> Assembly:
"BeamSweep",
"BeamRevolve",
"Boolean",
"deprecated",
"Group",
"Plate",
"PlateCurved",
Expand Down
2 changes: 1 addition & 1 deletion src/ada/api/connections.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def __init__(self, name, members: List[Beam], centre: Any[float], parent: Connec
m._ifc_elem = None

if parent is not None:
parent.parent.add_set(f"{name}_joint", members)
parent.parent.add_group(f"{name}_joint", members)

def _init_check(self, members):
if self.__class__.__name__ == "JointBase":
Expand Down
2 changes: 1 addition & 1 deletion src/ada/api/curves.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ def origin(self) -> Point:
return self.orientation.origin

@property
def normal(self):
def normal(self) -> Direction:
return self.orientation.zdir

@property
Expand Down
2 changes: 2 additions & 0 deletions src/ada/api/groups.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from dataclasses import dataclass, field
from typing import TYPE_CHECKING

from ada.base.changes import ChangeAction
from ada.core.guid import create_guid

if TYPE_CHECKING:
Expand All @@ -16,6 +17,7 @@ class Group:
parent: Part | Assembly
description: str = ""
guid: str = field(default_factory=create_guid)
change_type: ChangeAction = ChangeAction.NOTDEFINED

def to_part(self, name: str):
p = Part(name)
Expand Down
6 changes: 2 additions & 4 deletions src/ada/api/plates/base_pl.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

from typing import TYPE_CHECKING, Iterable, Union

import numpy as np

from ada.api.bounding_box import BoundingBox
from ada.api.curves import CurvePoly2d
from ada.api.nodes import Node
Expand Down Expand Up @@ -80,7 +78,7 @@ def __init__(
self._bbox = None

@staticmethod
def from_3d_points(name, points, t, mat="S420", xdir=None, color=None, metadata=None, **kwargs):
def from_3d_points(name, points, t, mat="S420", xdir=None, color=None, metadata=None, **kwargs) -> Plate:
poly = CurvePoly2d.from_3d_points(points, xdir=xdir, **kwargs)
return Plate(name, poly, t, mat=mat, color=color, metadata=metadata, **kwargs)

Expand Down Expand Up @@ -156,7 +154,7 @@ def material(self, value: Material):
self._material = value

@property
def n(self) -> np.ndarray:
def n(self) -> Direction:
"""Normal vector"""
return self.poly.normal

Expand Down
10 changes: 0 additions & 10 deletions src/ada/api/spatial/assembly.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import pathlib
from typing import TYPE_CHECKING, Callable, Union

from ada.api.presentation_layers import PresentationLayers
from ada.api.spatial.part import Part
from ada.api.user import User
from ada.base.ifc_types import SpatialTypes
Expand Down Expand Up @@ -69,7 +68,6 @@ def __init__(
self._ifc_sections = None
self._ifc_materials = None
self._source_ifc_files = dict()
self._presentation_layers = PresentationLayers()

self._cache_store = None
if enable_cache:
Expand Down Expand Up @@ -291,14 +289,6 @@ def ifc_store(self) -> IfcStore:
def ifc_store(self, value):
self._ifc_store = value

@property
def presentation_layers(self) -> PresentationLayers:
return self._presentation_layers

@presentation_layers.setter
def presentation_layers(self, value):
self._presentation_layers = value

@property
def user(self) -> User:
return self._user
Expand Down
48 changes: 40 additions & 8 deletions src/ada/api/spatial/part.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from ada.api.containers import Beams, Connections, Materials, Nodes, Plates, Sections
from ada.api.groups import Group
from ada.api.plates import PlateCurved
from ada.api.presentation_layers import PresentationLayers
from ada.base.changes import ChangeAction
from ada.base.ifc_types import SpatialTypes
from ada.base.physical_objects import BackendGeom
Expand Down Expand Up @@ -85,6 +86,7 @@ def __init__(
if fem is not None:
fem.parent = self

self._presentation_layers = PresentationLayers()
self.fem = FEM(name + "-1", parent=self) if fem is None else fem

def add_beam(self, beam: Beam, add_to_layer: str = None) -> Beam:
Expand Down Expand Up @@ -324,14 +326,18 @@ def add_instance(self, element, placement: Placement):
self._instances[element] = Instance(element)
self._instances[element].placements.append(placement)

def add_set(self, name, set_members: list[Part | Beam | Plate | Wall | Pipe | Shape]) -> Group:
if name not in self.groups.keys():
self.groups[name] = Group(name, set_members, parent=self)
def add_group(self, name, set_members: list[Part | Beam | Plate | Wall | Pipe | Shape]) -> Group:
exist_group = self.groups.get(name)
if exist_group is None:
self.groups[name] = Group(name, set_members, parent=self, change_type=ChangeAction.ADDED)
else:
logger.info(f'Appending set "{name}"')
for mem in set_members:
if mem not in self.groups[name].members:
self.groups[name].members.append(mem)
if mem not in exist_group.members:
exist_group.members.append(mem)

if exist_group.change_type != ChangeAction.ADDED:
exist_group.change_type = ChangeAction.MODIFIED

return self.groups[name]

Expand Down Expand Up @@ -452,9 +458,17 @@ def create_objects_from_fem(self, skip_plates=False, skip_beams=False) -> None:
convert_part_objects(self, skip_plates, skip_beams)
logger.info("Conversion complete")

def get_part(self, name: str) -> Part:
def get_part(self, name: str, search_all_parts_in_assembly=False) -> Part | None:
"""Get part by name."""
if search_all_parts_in_assembly:
all_parts = self.get_all_parts_in_assembly(include_self=True)
for part in all_parts:
if part.name == name:
return part
return None

key_map = {key.lower(): key for key in self.parts.keys()}
return self.parts[key_map[name.lower()]]
return self.parts.get(key_map[name.lower()])

def _get_by_prop(self, value: str, prop: str) -> Part | Plate | Beam | Shape | Material | Pipe | None:
pmap = {getattr(p, prop): p for p in self.get_all_subparts() + [self]}
Expand Down Expand Up @@ -612,7 +626,12 @@ def get_all_subparts(self, include_self=False) -> list[Part]:
return list_of_parts

def get_all_physical_objects(
self, sub_elements_only=False, by_type=None, filter_by_guids: list[str] = None, pipe_to_segments=False
self,
sub_elements_only=False,
by_type=None,
filter_by_guids: list[str] = None,
pipe_to_segments=False,
by_metadata: dict = None,
) -> Iterable[Beam | Plate | Wall | Pipe | Shape]:
physical_objects = []
if sub_elements_only:
Expand All @@ -630,6 +649,11 @@ def get_all_physical_objects(

if by_type is not None:
res = filter(lambda x: type(x) is by_type, chain.from_iterable(physical_objects))
elif by_metadata is not None:
res = filter(
lambda x: all(x.metadata.get(key) == value for key, value in by_metadata.items()),
chain.from_iterable(physical_objects),
)
else:
res = chain.from_iterable(physical_objects)

Expand Down Expand Up @@ -917,6 +941,14 @@ def fem(self, value: FEM):
sec.material = self.add_material(sec.material)
self._fem = value

@property
def presentation_layers(self) -> PresentationLayers:
return self._presentation_layers

@presentation_layers.setter
def presentation_layers(self, value):
self._presentation_layers = value

@property
def connections(self) -> Connections:
return self._connections
Expand Down
1 change: 1 addition & 0 deletions src/ada/base/ifc_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class SpatialTypes(Enum):
# Spatial SubElements
IfcBuilding = "IfcBuilding"
IfcSpatialZone = "IfcSpatialZone"
IfcSpace = "IfcSpace"
IfcBuildingStorey = "IfcBuildingStorey"
IfcElementAssembly = "IfcElementAssembly"
IfcGrid = "IfcGrid"
Expand Down
Empty file.
3 changes: 2 additions & 1 deletion src/ada/cadit/gxml/read/read_sets.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from typing import TYPE_CHECKING, Dict

from ada import Group, Part
from ada.base.changes import ChangeAction
from ada.config import logger

if TYPE_CHECKING:
Expand All @@ -15,7 +16,7 @@ def get_sets(xml_root: ET.Element, parent: Part) -> Dict[str, Group]:
for el_set in xml_root.findall(".//set"):
name = el_set.attrib["name"]
members = list(filter(lambda x: x is not None, [get_concept(m, parent) for m in el_set.findall(".//concept")]))
el_sets[name] = Group(name, members, parent=parent)
el_sets[name] = Group(name, members, parent=parent, change_type=ChangeAction.ADDED)

return el_sets

Expand Down
13 changes: 13 additions & 0 deletions src/ada/cadit/gxml/write/write_sets.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import xml.etree.ElementTree as ET

import ada


def add_sets(structure_domain, part: ada.Part):
sets = ET.SubElement(structure_domain, "sets")
for p in part.get_all_parts_in_assembly(include_self=True):
for group in p.groups.values():
set_elem = ET.SubElement(sets, "set", name=group.name)
concepts = ET.SubElement(set_elem, "concepts")
for member in group.members:
ET.SubElement(concepts, "concept", concept_ref=member.name)
3 changes: 3 additions & 0 deletions src/ada/cadit/gxml/write/write_xml.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from .write_plates import add_plates
from .write_sat_embedded import embed_sat_geometry
from .write_sections import add_sections
from .write_sets import add_sets

if TYPE_CHECKING:
from ada import Part
Expand Down Expand Up @@ -57,6 +58,8 @@ def write_xml(part: Part, xml_file, embed_sat=False, writer_postprocessor: Calla
add_boundary_conditions(structures_elem, part)
add_masses(structures_elem, part)

add_sets(structure_domain, part)

if writer_postprocessor:
writer_postprocessor(root, part)

Expand Down
8 changes: 5 additions & 3 deletions src/ada/cadit/ifc/read/geom/geom_reader.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Iterable, Union
from typing import Union

import ifcopenshell

Expand All @@ -12,12 +12,14 @@
GEOM = Union[geo_so.SOLID_GEOM_TYPES | geo_cu.CURVE_GEOM_TYPES | geo_su.SURFACE_GEOM_TYPES]


def get_product_definitions(prod_def: ifcopenshell.entity_instance) -> Iterable[GEOM]:
def get_product_definitions(prod_def: ifcopenshell.entity_instance) -> list[GEOM]:
geometries = []
for representation in prod_def.Representation.Representations:
if representation.RepresentationIdentifier != "Body":
continue
for item in representation.Items:
yield import_geometry_from_ifc_geom(item)
geometries.append(import_geometry_from_ifc_geom(item))
return geometries


def import_geometry_from_ifc_geom(geom_repr: ifcopenshell.entity_instance) -> GEOM:
Expand Down
Loading

0 comments on commit ad22775

Please sign in to comment.