ifctrano 0.3.0__py3-none-any.whl → 0.7.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
ifctrano/__init__.py CHANGED
@@ -1,3 +1,8 @@
1
1
  import warnings
2
2
 
3
3
  warnings.filterwarnings("ignore", category=RuntimeWarning)
4
+ warnings.filterwarnings(
5
+ "ignore",
6
+ message=".*Pydantic serializer warnings.*",
7
+ category=UserWarning,
8
+ )
ifctrano/base.py CHANGED
@@ -1,5 +1,6 @@
1
1
  import json
2
2
  import math
3
+ import sys
3
4
  from itertools import combinations
4
5
  from multiprocessing import Process
5
6
  from pathlib import Path
@@ -54,6 +55,9 @@ class BaseShow(BaseModel):
54
55
  def description(self) -> Any: ... # noqa: ANN401
55
56
 
56
57
  def show(self, interactive: bool = True) -> None:
58
+ if sys.platform == "win32":
59
+ _show(self.lines(), interactive)
60
+ return
57
61
  p = Process(target=_show, args=(self.lines(), interactive))
58
62
  p.start()
59
63
 
@@ -394,6 +398,7 @@ class CommonSurface(BaseShow):
394
398
  main_vertices: FaceVertices
395
399
  common_vertices: FaceVertices
396
400
  exterior: bool = True
401
+ polygon: str
397
402
 
398
403
  def __hash__(self) -> int:
399
404
  return hash(
ifctrano/bounding_box.py CHANGED
@@ -14,7 +14,7 @@ from pydantic import (
14
14
  Field,
15
15
  ConfigDict,
16
16
  )
17
- from scipy.spatial import ConvexHull # type: ignore
17
+ from scipy.spatial import ConvexHull, QhullError # type: ignore
18
18
  from vedo import Line # type: ignore
19
19
 
20
20
  from ifctrano.base import (
@@ -78,6 +78,7 @@ class ExtendCommonSurface(CommonSurface):
78
78
  orientation=self.orientation,
79
79
  main_vertices=self.main_vertices,
80
80
  common_vertices=self.common_vertices,
81
+ polygon=self.polygon,
81
82
  )
82
83
 
83
84
 
@@ -137,6 +138,7 @@ class OrientedBoundingBox(BaseShow):
137
138
  common_vertices=projected_face_1.common_vertices(
138
139
  intersection
139
140
  ),
141
+ polygon=intersection.wkt,
140
142
  )
141
143
  )
142
144
 
@@ -190,8 +192,14 @@ class OrientedBoundingBox(BaseShow):
190
192
  entity_shape, entity_shape.geometry # type: ignore
191
193
  )
192
194
  vertices_ = Vertices.from_arrays(np.asarray(vertices))
193
- hull = ConvexHull(vertices_.to_array())
194
- vertices_ = Vertices.from_arrays(vertices_.to_array()[hull.vertices])
195
+ try:
196
+ hull = ConvexHull(vertices_.to_array())
197
+ vertices_ = Vertices.from_arrays(vertices_.to_array()[hull.vertices])
198
+
199
+ except QhullError:
200
+ logger.error(
201
+ f"Convex hull failed for {entity.GlobalId} ({entity.is_a()}).... Continuing without it."
202
+ )
195
203
  points_ = open3d.utility.Vector3dVector(vertices_.to_array())
196
204
  aab = open3d.geometry.AxisAlignedBoundingBox.create_from_points(points_)
197
205
  return cls.from_vertices(aab.get_box_points(), entity)
ifctrano/building.py CHANGED
@@ -1,3 +1,4 @@
1
+ import logging
1
2
  import re
2
3
  from pathlib import Path
3
4
  from typing import List, Tuple, Any, Optional, Set
@@ -12,7 +13,11 @@ from trano.topology import Network # type: ignore
12
13
  from vedo import Line # type: ignore
13
14
 
14
15
  from ifctrano.base import BaseModelConfig, Libraries, Vector, BaseShow, CommonSurface
15
- from ifctrano.exceptions import IfcFileNotFoundError, NoIfcSpaceFoundError
16
+ from ifctrano.exceptions import (
17
+ IfcFileNotFoundError,
18
+ NoIfcSpaceFoundError,
19
+ NoSpaceBoundariesError,
20
+ )
16
21
  from ifctrano.space_boundary import (
17
22
  SpaceBoundaries,
18
23
  initialize_tree,
@@ -20,6 +25,8 @@ from ifctrano.space_boundary import (
20
25
  )
21
26
  from ifctrano.construction import Constructions, default_construction
22
27
 
28
+ logger = logging.getLogger(__name__)
29
+
23
30
 
24
31
  def get_spaces(ifcopenshell_file: file) -> List[entity_instance]:
25
32
  return ifcopenshell_file.by_type("IfcSpace")
@@ -180,9 +187,18 @@ class Building(BaseShow):
180
187
  ]
181
188
  if not spaces:
182
189
  raise NoIfcSpaceFoundError("No IfcSpace found in the file.")
183
- space_boundaries = [
184
- SpaceBoundaries.from_space_entity(ifc_file, tree, space) for space in spaces
185
- ]
190
+ space_boundaries = []
191
+ for space in spaces:
192
+ try:
193
+ space_boundaries.append(
194
+ SpaceBoundaries.from_space_entity(ifc_file, tree, space)
195
+ )
196
+ except Exception as e: # noqa: PERF203
197
+ logger.error(f"Cannot process space {space.id()}. Reason {e}")
198
+ continue
199
+ if not space_boundaries:
200
+ raise NoSpaceBoundariesError("No valid space boundaries found.")
201
+
186
202
  return cls(
187
203
  space_boundaries=space_boundaries,
188
204
  ifc_file=ifc_file,
ifctrano/construction.py CHANGED
@@ -189,9 +189,9 @@ class Constructions(BaseModel):
189
189
  def get_construction(self, entity: entity_instance) -> Construction:
190
190
  construction_id = self._get_construction_id(entity)
191
191
  if construction_id is None:
192
- logger.error(
193
- f"Construction ID not found for {entity.GlobalId} ({entity.is_a()}) "
194
- f"({entity.Name}). Using default construction."
192
+ logger.warning(
193
+ f"Construction ID not found for {entity.GlobalId} ({entity.is_a()}). "
194
+ f"Using default construction."
195
195
  )
196
196
  return default_construction
197
197
  constructions = [
@@ -210,11 +210,11 @@ class Constructions(BaseModel):
210
210
  if association.is_a() == "IfcRelAssociatesMaterial"
211
211
  ]
212
212
  if not associates_materials:
213
- logger.error(f"Associate materials not found for {entity.GlobalId}.")
213
+ logger.warning(f"Associate materials not found for {entity.GlobalId}.")
214
214
  return None
215
215
  relating_material = associates_materials[0].RelatingMaterial
216
216
  if relating_material.is_a() == "IfcMaterialList":
217
- logger.error(
217
+ logger.warning(
218
218
  f"Material list found for {entity.GlobalId}, but no construction ID available."
219
219
  )
220
220
  return None
ifctrano/exceptions.py CHANGED
@@ -18,6 +18,10 @@ class NoIfcSpaceFoundError(Exception):
18
18
  pass
19
19
 
20
20
 
21
+ class NoSpaceBoundariesError(Exception):
22
+ pass
23
+
24
+
21
25
  class InvalidLibraryError(Exception):
22
26
  pass
23
27
 
ifctrano/main.py CHANGED
@@ -15,6 +15,7 @@ from trano.utils.utils import is_success # type: ignore
15
15
  from ifctrano.base import Libraries
16
16
  from ifctrano.building import Building
17
17
  from ifctrano.exceptions import InvalidLibraryError
18
+ from rich import print
18
19
 
19
20
  app = typer.Typer()
20
21
  CHECKMARK = "[green]✔[/green]"
@@ -34,11 +35,11 @@ def create(
34
35
  show_space_boundaries: Annotated[
35
36
  bool,
36
37
  typer.Option(help="Show computed space boundaries."),
37
- ] = True,
38
+ ] = False,
38
39
  simulate_model: Annotated[
39
40
  bool,
40
41
  typer.Option(help="Simulate the generated model."),
41
- ] = True,
42
+ ] = False,
42
43
  ) -> None:
43
44
  with Progress(
44
45
  SpinnerColumn(),
@@ -66,12 +67,16 @@ def create(
66
67
  print(f"{CHECKMARK} Model generated at {modelica_model_path}")
67
68
  if simulate_model:
68
69
  print("Simulating...")
69
- results = simulate(
70
- modelica_model_path.parent,
71
- building.create_network(
72
- library=library # type: ignore
73
- ), # TODO: cannot use the network after cretingt he model
74
- )
70
+ try:
71
+ results = simulate(
72
+ modelica_model_path.parent,
73
+ building.create_network(
74
+ library=library # type: ignore
75
+ ), # TODO: cannot use the network after creating he model
76
+ )
77
+ except Exception as e:
78
+ print(f"{CROSS_MARK} Simulation failed: {e}")
79
+ return
75
80
  if not is_success(results):
76
81
  print(f"{CROSS_MARK} Simulation failed. See logs for more information.")
77
82
  return
@@ -5,7 +5,8 @@ import ifcopenshell
5
5
  import ifcopenshell.geom
6
6
  import ifcopenshell.util.shape
7
7
  from ifcopenshell import entity_instance, file
8
- from pydantic import Field, BeforeValidator, BaseModel
8
+ from pydantic import Field, BeforeValidator, BaseModel, ConfigDict
9
+ from shapely import wkt # type: ignore
9
10
  from trano.data_models.conversion import SpaceParameter # type: ignore
10
11
  from trano.elements import Space as TranoSpace, ExternalWall, Window, BaseWall, ExternalDoor # type: ignore
11
12
  from trano.elements.system import Occupancy # type: ignore
@@ -24,7 +25,12 @@ from ifctrano.base import (
24
25
  from ifctrano.bounding_box import OrientedBoundingBox
25
26
  from ifctrano.construction import glass, Constructions
26
27
  from ifctrano.exceptions import HasWindowsWithoutWallsError
27
- from ifctrano.utils import remove_non_alphanumeric, _round, get_building_elements
28
+ from ifctrano.utils import (
29
+ remove_non_alphanumeric,
30
+ _round,
31
+ get_building_elements,
32
+ short_uuid,
33
+ )
28
34
 
29
35
  ROOF_VECTOR = Vector(x=0, y=0, z=1)
30
36
 
@@ -175,7 +181,10 @@ class SpaceBoundary(BaseModelConfig):
175
181
  return hash(self.common_surface)
176
182
 
177
183
  def boundary_name(self) -> str:
178
- return f"{self.entity.is_a()}_{remove_non_alphanumeric(self.entity.GlobalId)}"
184
+ return (
185
+ f"{remove_non_alphanumeric(self.entity.Name) or self.entity.is_a().lower()}_"
186
+ f"__{remove_non_alphanumeric(self.entity.GlobalId)}{short_uuid()}"
187
+ )
179
188
 
180
189
  def model_element( # noqa: PLR0911
181
190
  self,
@@ -332,4 +341,109 @@ class SpaceBoundaries(BaseShow):
332
341
  )
333
342
  if space_boundary:
334
343
  space_boundaries.append(space_boundary)
335
- return cls(space=space_, boundaries=space_boundaries)
344
+ merged_boundaries = MergedSpaceBoundaries.from_boundaries(space_boundaries)
345
+ space_boundaries_ = merged_boundaries.merge_boundaries_from_part()
346
+ space_boundaries__ = remove_duplicate_boundaries(space_boundaries_)
347
+ return cls(space=space_, boundaries=space_boundaries__)
348
+
349
+
350
+ def remove_duplicate_boundaries(
351
+ boundaries: List[SpaceBoundary],
352
+ ) -> List[SpaceBoundary]:
353
+ types = ["IfcRoof", "IfcSlab"]
354
+ boundaries = sorted(boundaries, key=lambda b: b.entity.GlobalId)
355
+ boundaries_without_types = [
356
+ sp for sp in boundaries if sp.entity.is_a() not in types
357
+ ]
358
+ new_boundaries = []
359
+ for type_ in types:
360
+ references = [sp for sp in boundaries if sp.entity.is_a() == type_]
361
+ while True:
362
+ reference = next(iter(references), None)
363
+ if not reference:
364
+ break
365
+ others = [p_ for p_ in references if p_ != reference]
366
+ intersecting = [
367
+ o
368
+ for o in others
369
+ if (
370
+ wkt.loads(o.common_surface.polygon).intersects(
371
+ wkt.loads(reference.common_surface.polygon)
372
+ )
373
+ and o.common_surface.orientation
374
+ == reference.common_surface.orientation
375
+ )
376
+ and (
377
+ wkt.loads(o.common_surface.polygon).intersection(
378
+ wkt.loads(reference.common_surface.polygon)
379
+ )
380
+ ).area
381
+ > 0
382
+ ]
383
+ current_group = sorted(
384
+ [*intersecting, reference], key=lambda p: p.entity.GlobalId
385
+ )
386
+ new_boundaries.append(next(iter(current_group)))
387
+ references = [p_ for p_ in references if p_ not in current_group]
388
+ return [*boundaries_without_types, *new_boundaries]
389
+
390
+
391
+ class MergedSpaceBoundary(BaseModel):
392
+ model_config = ConfigDict(arbitrary_types_allowed=True)
393
+ parent: entity_instance
394
+ related_boundaries: List[SpaceBoundary]
395
+
396
+ def get_new_boundary(self) -> Optional[SpaceBoundary]:
397
+ related_boundaries = sorted(
398
+ self.related_boundaries, key=lambda b: b.entity.GlobalId
399
+ )
400
+ boundary = next(iter(related_boundaries), None)
401
+ if boundary:
402
+ return SpaceBoundary.model_validate(
403
+ boundary.model_dump() | {"entity": self.parent}
404
+ )
405
+ return None
406
+
407
+
408
+ class MergedSpaceBoundaries(BaseModel):
409
+ part_boundaries: List[MergedSpaceBoundary]
410
+ original_boundaries: List[SpaceBoundary]
411
+
412
+ @classmethod
413
+ def from_boundaries(
414
+ cls, space_boundaries: List[SpaceBoundary]
415
+ ) -> "MergedSpaceBoundaries":
416
+ building_element_part_boundaries = [
417
+ boundary
418
+ for boundary in space_boundaries
419
+ if boundary.entity.is_a() in ["IfcBuildingElementPart"]
420
+ ]
421
+ existing_parent_entities = {
422
+ decompose.RelatingObject
423
+ for b in building_element_part_boundaries
424
+ for decompose in b.entity.Decomposes
425
+ }
426
+ part_boundaries = [
427
+ MergedSpaceBoundary(
428
+ parent=parent,
429
+ related_boundaries=[
430
+ b
431
+ for b in building_element_part_boundaries
432
+ for decompose in b.entity.Decomposes
433
+ if decompose.RelatingObject == parent
434
+ ],
435
+ )
436
+ for parent in existing_parent_entities
437
+ ]
438
+ return cls(
439
+ part_boundaries=part_boundaries, original_boundaries=space_boundaries
440
+ )
441
+
442
+ def merge_boundaries_from_part(self) -> List[SpaceBoundary]:
443
+ new_boundaries = [b.get_new_boundary() for b in self.part_boundaries]
444
+ new_boundaries_ = [nb for nb in new_boundaries if nb is not None]
445
+ return [
446
+ b
447
+ for b in self.original_boundaries
448
+ if b.entity.is_a() not in ["IfcBuildingElementPart"]
449
+ ] + new_boundaries_
ifctrano/types.py CHANGED
@@ -1,5 +1,11 @@
1
1
  from typing import Literal
2
2
 
3
3
  BuildingElements = Literal[
4
- "IfcWall", "IfcSlab", "IfcRoof", "IfcDoor", "IfcWindow", "IfcPlate"
4
+ "IfcWall",
5
+ "IfcSlab",
6
+ "IfcRoof",
7
+ "IfcDoor",
8
+ "IfcWindow",
9
+ "IfcPlate",
10
+ "IfcBuildingElementPart",
5
11
  ]
ifctrano/utils.py CHANGED
@@ -1,4 +1,6 @@
1
+ import random
1
2
  import re
3
+ import string
2
4
  import uuid
3
5
  from typing import get_args
4
6
 
@@ -13,6 +15,12 @@ def remove_non_alphanumeric(text: str) -> str:
13
15
  return re.sub(r"[^a-zA-Z0-9_]", "", text).lower()
14
16
 
15
17
 
18
+ def short_uuid() -> str:
19
+ return "".join(
20
+ random.choices(string.ascii_letters + string.digits, k=3) # noqa: S311
21
+ )
22
+
23
+
16
24
  def generate_alphanumeric_uuid() -> str:
17
25
  return str(uuid.uuid4().hex).lower()
18
26
 
@@ -1,8 +1,9 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.4
2
2
  Name: ifctrano
3
- Version: 0.3.0
3
+ Version: 0.7.0
4
4
  Summary: Package for generating building energy simulation model from IFC
5
5
  License: GPL V3
6
+ License-File: LICENSE
6
7
  Keywords: BIM,IFC,energy simulation,modelica,building energy simulation,buildings,ideas
7
8
  Author: Ando Andriamamonjy
8
9
  Author-email: andoludovic.andriamamonjy@gmail.com
@@ -15,7 +16,7 @@ Classifier: Programming Language :: Python :: 3.12
15
16
  Requires-Dist: ifcopenshell (>=0.8.1.post1,<0.9.0)
16
17
  Requires-Dist: open3d (>=0.19.0,<0.20.0)
17
18
  Requires-Dist: shapely (>=2.0.7,<3.0.0)
18
- Requires-Dist: trano (>=0.5.0,<0.6.0)
19
+ Requires-Dist: trano (>=0.10.0,<0.11.0)
19
20
  Requires-Dist: typer (>=0.12.5,<0.13.0)
20
21
  Requires-Dist: vedo (>=2025.5.3,<2026.0.0)
21
22
  Project-URL: Repository, https://github.com/andoludo/ifctrano
@@ -23,33 +24,11 @@ Description-Content-Type: text/markdown
23
24
 
24
25
  # ifctrano - IFC to Energy Simulation Tool
25
26
 
27
+ ---
26
28
  📖 **Full Documentation:** 👉 [ifctrano Docs](https://andoludo.github.io/ifctrano/)
29
+ ---
27
30
 
28
- ```bash
29
- pip install ifctrano
30
- ```
31
-
32
- To check the installation, run the following commands:
33
-
34
- ```bash
35
- ifctrano --help
36
-
37
- ifctrano verify
38
- ```
39
-
40
- # ⚠️ WARNING ⚠️
41
-
42
- **This package is still under construction and is largely a work in progress.**
43
- There are still several aspects that need further development, including:
44
-
45
- - Material and construction extraction
46
- - Slab and roof boundaries
47
- - Systems integration
48
- - Additional validation
49
- - Bug fixes
50
- - ...
51
- -
52
- Help and contribution are more than appreciated! 🚧
31
+ Generate Modelica building models directly from IFC files — with support for simulation, visualization, and multiple libraries.
53
32
 
54
33
  ## Overview
55
34
  ifctrano is yet another **IFC to energy simulation** tool designed to translate **Industry Foundation Classes (IFC)** models into energy simulation models in **Modelica**.
@@ -79,10 +58,104 @@ ifctrano has been tested using open-source IFC files from various repositories:
79
58
  - 🕸️ [Ifc2Graph Test Files](https://github.com/JBjoernskov/Ifc2Graph/tree/main/test_ifc_files)
80
59
  - 🔓 [Open Source BIM](https://github.com/opensourceBIM)
81
60
 
82
- ## Installation & Usage
83
- (Installation and usage instructions will be provided here, depending on the package distribution method.)
61
+ ## 🚀 Installation
62
+
63
+ ### 📦 Install `ifctrano`
64
+
65
+ !!! warning
66
+ Trano requires python 3.9 or higher and docker to be installed on the system.
67
+
68
+
69
+ ifctrano is a Python package that can be installed via pip.
70
+
71
+ ```bash
72
+ pip install ifctrano
73
+ ```
74
+
75
+ ### ✅ Verify Installation
76
+
77
+ Run the following commands to ensure everything is working:
78
+
79
+ ```bash
80
+ ifctrano --help
81
+ ifctrano verify
82
+ ```
83
+
84
+ ---
85
+
86
+ ## 🔧 Optional Dependencies
87
+
88
+ ### 🐳 Docker (for simulation)
89
+
90
+ To enable model simulation using the official OpenModelica Docker image, install Docker Desktop:
91
+
92
+ 👉 [https://docs.docker.com/desktop/](https://docs.docker.com/desktop/)
93
+
94
+ Required for using the `--simulate-model` flag.
95
+
96
+ ---
84
97
 
98
+ ### 🧠 Graphviz (for layout visualization)
99
+
100
+ `ifctrano` leverages Graphviz to optimize component layout in generated Modelica models. It is optional, but **recommended**.
101
+
102
+ #### 📥 Install on Windows
103
+
104
+ - Download and install from: [https://graphviz.org/download/](https://graphviz.org/download/)
105
+ - Add the Graphviz `bin` folder to your **system `PATH`**.
106
+
107
+ #### 🐧 Install on Linux
108
+
109
+ ```bash
110
+ sudo apt update
111
+ sudo apt install graphviz
112
+ ```
113
+
114
+ ---
115
+
116
+ ## ⚙️ Usage
117
+
118
+ ### 📁 Generate Modelica models from IFC
119
+
120
+ #### 🏢 Using the **Buildings** library
121
+
122
+ ```bash
123
+ ifctrano create /path/to/your.ifc
124
+ ```
125
+
126
+ #### 🏫 Using the **IDEAS** library
127
+
128
+ ```bash
129
+ ifctrano create /path/to/your.ifc IDEAS
130
+ ```
131
+
132
+ #### 🧮 Using the **Reduced Order** library
133
+
134
+ ```bash
135
+ ifctrano create /path/to/your.ifc reduced_order
136
+ ```
137
+
138
+ ---
139
+
140
+ ### 🧱 Show Space Boundaries
141
+
142
+ To visualize the computed space boundaries:
143
+
144
+ ```bash
145
+ ifctrano create /path/to/your.ifc --show-space-boundaries
146
+ ```
147
+
148
+ ---
149
+
150
+ ### 🔁 Simulate the Model
151
+
152
+ Run a full simulation after model generation:
153
+
154
+ ```bash
155
+ ifctrano create /path/to/your.ifc --simulate-model
156
+ ```
85
157
 
158
+ Make sure Docker is installed and running before simulating.
86
159
 
87
160
  ---
88
161
  💡 **ifctrano** aims to make energy simulation model generation from IFC files **simpler, more accessible, and less reliant on incomplete IFC attributes**. 🚀
@@ -0,0 +1,16 @@
1
+ ifctrano/__init__.py,sha256=6wK0Qa_5Xe0KSk5Spn98AjTNCTIXtenZ3C0k8ZaVcn8,191
2
+ ifctrano/base.py,sha256=s8BSnQqd6v_NFvkQFRriHCine6iylUBQai2FduC4IFk,14352
3
+ ifctrano/bounding_box.py,sha256=64jlzY60ZDUX4ipR34WkOICpPhxLP-5w-FP42yBONRs,7729
4
+ ifctrano/building.py,sha256=tBctMyrsvwRiDk5bDhAdfgRlbyvnbCCeA8rcdUjMbU8,9355
5
+ ifctrano/construction.py,sha256=Lyh_o37znrDyxtKgw7dOqVsQk1S3btCPDh2YTJ8h6T0,7234
6
+ ifctrano/example/verification.ifc,sha256=tQ9QcubT_wrbb-sc1WRRwYpb2cbkWm3dnRfXdP5GTTg,131
7
+ ifctrano/exceptions.py,sha256=JDy_0HV7_FLfr92DkrN8F59zUHl9KdMa_lfIcfBJG6I,540
8
+ ifctrano/main.py,sha256=YTp7RaWRMKt_UC2DRt_oXXLGTLCAc9FPg6Tsqg1zgpk,4979
9
+ ifctrano/space_boundary.py,sha256=PmiKhcJo6iyxXKNab5NCphQgBQwatoNsqsi-BYHOONs,16055
10
+ ifctrano/types.py,sha256=FBSWrD66EL7uHvv0GveCXmYyLtCr8gGRlT7-5j7aZD8,181
11
+ ifctrano/utils.py,sha256=zLQUGVo15RSQQ-vfOuHsJBkHy4QhpxKSAH7Au72s0s0,873
12
+ ifctrano-0.7.0.dist-info/METADATA,sha256=VAynLl3eaecRmVSgvU3XVSmO-_weipMqdfbw-pq3Blw,4884
13
+ ifctrano-0.7.0.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
14
+ ifctrano-0.7.0.dist-info/entry_points.txt,sha256=_2daDejazkphufyEu0m3lOeTio53WYmjol3KmSN0JM4,46
15
+ ifctrano-0.7.0.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
16
+ ifctrano-0.7.0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 2.1.2
2
+ Generator: poetry-core 2.2.1
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1,16 +0,0 @@
1
- ifctrano/__init__.py,sha256=UT1-izHuXPq06nSeKzgs6qoVRfc6RqIhabf-ZKgAXf4,76
2
- ifctrano/base.py,sha256=BQpMZwSq0tiUN0g56CfzF11lIlijwi7VuLjC2XY4mx0,14224
3
- ifctrano/bounding_box.py,sha256=k74UIutxaNxfdfAjSqvr6Jj3gu6OP4sbQB_kTnZlltw,7431
4
- ifctrano/building.py,sha256=MUaSqWQP_4kZbH6-yrjRahm8poxLBHiBlMjOFNUV88o,8910
5
- ifctrano/construction.py,sha256=KGiJJ6L0D7mK254GYl6CO7TKoTNoUSJeZCSHzbkhslo,7244
6
- ifctrano/example/verification.ifc,sha256=tQ9QcubT_wrbb-sc1WRRwYpb2cbkWm3dnRfXdP5GTTg,131
7
- ifctrano/exceptions.py,sha256=SKFiFEhn0bW2Dm4fVHeMGIQ1C84nlLhapxy8y46SkfM,488
8
- ifctrano/main.py,sha256=cXev3w-uC_wgi4lxtvn4zrAogX-6pUSR0GNav3s0Z5g,4793
9
- ifctrano/space_boundary.py,sha256=lDhq05FC8BMZ07vGhU9smXj-gnOy-zoqIpkoW0QFCeI,11922
10
- ifctrano/types.py,sha256=wxKVb2R4Dz58YzN4PzgXhuuVw-UYobSh9fnYWQrYlqQ,130
11
- ifctrano/utils.py,sha256=AjQrIqbKAk4CWCcfeRHSZtWT6AAxQLyj-uDWPdUU6UU,712
12
- ifctrano-0.3.0.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
13
- ifctrano-0.3.0.dist-info/METADATA,sha256=5hdAUTbC0kirbMFK_uvxKk76HGHHf-f8sHKJxkhkaWs,3533
14
- ifctrano-0.3.0.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
15
- ifctrano-0.3.0.dist-info/entry_points.txt,sha256=_2daDejazkphufyEu0m3lOeTio53WYmjol3KmSN0JM4,46
16
- ifctrano-0.3.0.dist-info/RECORD,,