ifctrano 0.1.12__py3-none-any.whl → 0.3.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/exceptions.py CHANGED
@@ -24,3 +24,7 @@ class InvalidLibraryError(Exception):
24
24
 
25
25
  class VectorWithNansError(Exception):
26
26
  pass
27
+
28
+
29
+ class HasWindowsWithoutWallsError(Exception):
30
+ pass
ifctrano/main.py CHANGED
@@ -1,10 +1,16 @@
1
1
  import shutil
2
+ import webbrowser
2
3
  from pathlib import Path
3
4
  from tempfile import TemporaryDirectory
4
5
  from typing import Annotated, get_args
5
6
 
6
7
  import typer
7
8
  from rich.progress import Progress, SpinnerColumn, TextColumn
9
+ from trano.reporting.html import to_html_reporting # type: ignore
10
+ from trano.reporting.reporting import ModelDocumentation # type: ignore
11
+ from trano.reporting.types import ResultFile # type: ignore
12
+ from trano.simulate.simulate import simulate # type: ignore
13
+ from trano.utils.utils import is_success # type: ignore
8
14
 
9
15
  from ifctrano.base import Libraries
10
16
  from ifctrano.building import Building
@@ -25,6 +31,14 @@ def create(
25
31
  str,
26
32
  typer.Argument(help="Modelica library to be used for simulation."),
27
33
  ] = "Buildings",
34
+ show_space_boundaries: Annotated[
35
+ bool,
36
+ typer.Option(help="Show computed space boundaries."),
37
+ ] = True,
38
+ simulate_model: Annotated[
39
+ bool,
40
+ typer.Option(help="Simulate the generated model."),
41
+ ] = True,
28
42
  ) -> None:
29
43
  with Progress(
30
44
  SpinnerColumn(),
@@ -41,12 +55,47 @@ def create(
41
55
  total=None,
42
56
  )
43
57
  building = Building.from_ifc(Path(model))
44
- modelica_model = building.create_model(library=library) # type: ignore
58
+ if show_space_boundaries:
59
+ print(f"{CHECKMARK} Showing space boundaries.")
60
+ building.show()
61
+ modelica_network = building.create_network(library=library) # type: ignore
45
62
  progress.update(task, completed=True)
46
63
  task = progress.add_task(description="Writing model to file...", total=None)
47
- modelica_model_path.write_text(modelica_model)
64
+ modelica_model_path.write_text(modelica_network.model())
48
65
  progress.remove_task(task)
49
66
  print(f"{CHECKMARK} Model generated at {modelica_model_path}")
67
+ if simulate_model:
68
+ 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
+ )
75
+ if not is_success(results):
76
+ print(f"{CROSS_MARK} Simulation failed. See logs for more information.")
77
+ return
78
+
79
+ result_path = (
80
+ Path(modelica_model_path.parent)
81
+ / "results"
82
+ / f"{modelica_model_path.stem.lower()}.building_res.mat"
83
+ )
84
+ if not result_path.exists():
85
+ print(
86
+ f"{CROSS_MARK} Simulation failed. Result file not found in {result_path}."
87
+ )
88
+ return
89
+ reporting = ModelDocumentation.from_network(
90
+ building.create_network(library=library), # type: ignore
91
+ result=ResultFile(path=result_path),
92
+ )
93
+ html = to_html_reporting(reporting)
94
+ report_path = Path(
95
+ modelica_model_path.parent / f"{modelica_model_path.stem}.html"
96
+ )
97
+ report_path.write_text(html)
98
+ webbrowser.open(f"file://{report_path}")
50
99
 
51
100
 
52
101
  @app.command()
@@ -73,3 +122,7 @@ def verify() -> None:
73
122
  print(
74
123
  f"{CROSS_MARK} Model could not be created... please check your system."
75
124
  )
125
+
126
+
127
+ if __name__ == "__main__":
128
+ app()
@@ -1,37 +1,32 @@
1
1
  import multiprocessing
2
- import re
3
- from typing import Optional, List, Tuple, Any
2
+ from typing import Optional, List, Tuple, Any, Annotated
4
3
 
5
4
  import ifcopenshell
6
5
  import ifcopenshell.geom
7
6
  import ifcopenshell.util.shape
8
7
  from ifcopenshell import entity_instance, file
9
- from pydantic import BaseModel, Field
8
+ from pydantic import Field, BeforeValidator, BaseModel
10
9
  from trano.data_models.conversion import SpaceParameter # type: ignore
11
10
  from trano.elements import Space as TranoSpace, ExternalWall, Window, BaseWall, ExternalDoor # type: ignore
12
- from trano.elements.construction import ( # type: ignore
13
- Construction,
14
- Layer,
15
- Material,
16
- Glass,
17
- GlassLayer,
18
- GasLayer,
19
- GlassMaterial,
20
- Gas,
21
- )
22
11
  from trano.elements.system import Occupancy # type: ignore
23
12
  from trano.elements.types import Tilt # type: ignore
13
+ from vedo import Line # type: ignore
24
14
 
25
15
  from ifctrano.base import (
26
16
  GlobalId,
27
17
  settings,
28
18
  BaseModelConfig,
29
19
  CommonSurface,
30
- ROUNDING_FACTOR,
31
20
  CLASH_CLEARANCE,
32
21
  Vector,
22
+ BaseShow,
33
23
  )
34
24
  from ifctrano.bounding_box import OrientedBoundingBox
25
+ from ifctrano.construction import glass, Constructions
26
+ from ifctrano.exceptions import HasWindowsWithoutWallsError
27
+ from ifctrano.utils import remove_non_alphanumeric, _round, get_building_elements
28
+
29
+ ROOF_VECTOR = Vector(x=0, y=0, z=1)
35
30
 
36
31
 
37
32
  def initialize_tree(ifc_file: file) -> ifcopenshell.geom.tree:
@@ -48,18 +43,14 @@ def initialize_tree(ifc_file: file) -> ifcopenshell.geom.tree:
48
43
  return tree
49
44
 
50
45
 
51
- def remove_non_alphanumeric(text: str) -> str:
52
- return re.sub(r"[^a-zA-Z0-9]", "", text).lower()
53
-
54
-
55
46
  class Space(GlobalId):
56
47
  name: Optional[str] = None
57
48
  bounding_box: OrientedBoundingBox
58
49
  entity: entity_instance
59
- average_room_height: float
60
- floor_area: float
61
- bounding_box_height: float
62
- bounding_box_volume: float
50
+ average_room_height: Annotated[float, BeforeValidator(_round)]
51
+ floor_area: Annotated[float, BeforeValidator(_round)]
52
+ bounding_box_height: Annotated[float, BeforeValidator(_round)]
53
+ bounding_box_volume: Annotated[float, BeforeValidator(_round)]
63
54
 
64
55
  @classmethod
65
56
  def from_entity(cls, entity: entity_instance) -> "Space":
@@ -84,8 +75,8 @@ class Space(GlobalId):
84
75
  )
85
76
 
86
77
  def check_volume(self) -> bool:
87
- return round(self.bounding_box_volume, ROUNDING_FACTOR) == round(
88
- self.floor_area * self.average_room_height, ROUNDING_FACTOR
78
+ return round(self.bounding_box_volume) == round(
79
+ self.floor_area * self.average_room_height
89
80
  )
90
81
 
91
82
  def space_name(self) -> str:
@@ -93,46 +84,85 @@ class Space(GlobalId):
93
84
  return f"space_{main_name}{remove_non_alphanumeric(self.entity.GlobalId)}"
94
85
 
95
86
 
96
- material_1 = Material(
97
- name="material_1",
98
- thermal_conductivity=0.046,
99
- specific_heat_capacity=940,
100
- density=80,
101
- )
102
- construction = Construction(
103
- name="construction_4",
104
- layers=[
105
- Layer(material=material_1, thickness=0.18),
106
- ],
107
- )
108
- id_100 = GlassMaterial(
109
- name="id_100",
110
- thermal_conductivity=1,
111
- density=2500,
112
- specific_heat_capacity=840,
113
- solar_transmittance=[0.646],
114
- solar_reflectance_outside_facing=[0.062],
115
- solar_reflectance_room_facing=[0.063],
116
- infrared_transmissivity=0,
117
- infrared_absorptivity_outside_facing=0.84,
118
- infrared_absorptivity_room_facing=0.84,
119
- )
87
+ class ExternalSpaceBoundaryGroup(BaseModelConfig):
88
+ constructions: List[BaseWall]
89
+ azimuth: float
90
+ tilt: Tilt
120
91
 
121
- air = Gas(
122
- name="Air",
123
- thermal_conductivity=0.025,
124
- density=1.2,
125
- specific_heat_capacity=1005,
126
- )
127
- glass = Glass(
128
- name="double_glazing",
129
- u_value_frame=1.4,
130
- layers=[
131
- GlassLayer(thickness=0.003, material=id_100),
132
- GasLayer(thickness=0.0127, material=air),
133
- GlassLayer(thickness=0.003, material=id_100),
134
- ],
135
- )
92
+ def __hash__(self) -> int:
93
+ return hash((self.azimuth, self.tilt.value))
94
+
95
+ def has_window(self) -> bool:
96
+ return any(
97
+ isinstance(construction, Window) for construction in self.constructions
98
+ )
99
+
100
+ def has_external_wall(self) -> bool:
101
+ return any(
102
+ isinstance(construction, ExternalWall)
103
+ for construction in self.constructions
104
+ )
105
+
106
+
107
+ class ExternalSpaceBoundaryGroups(BaseModelConfig):
108
+ space_boundary_groups: List[ExternalSpaceBoundaryGroup] = Field(
109
+ default_factory=list
110
+ )
111
+
112
+ @classmethod
113
+ def from_external_boundaries(
114
+ cls, external_boundaries: List[BaseWall]
115
+ ) -> "ExternalSpaceBoundaryGroups":
116
+ boundary_walls = [
117
+ ex
118
+ for ex in external_boundaries
119
+ if isinstance(ex, (ExternalWall, Window)) and ex.tilt == Tilt.wall
120
+ ]
121
+ space_boundary_groups = list(
122
+ {
123
+ ExternalSpaceBoundaryGroup(
124
+ constructions=[
125
+ ex_
126
+ for ex_ in boundary_walls
127
+ if ex_.azimuth == ex.azimuth and ex_.tilt == ex.tilt
128
+ ],
129
+ azimuth=ex.azimuth,
130
+ tilt=ex.tilt,
131
+ )
132
+ for ex in boundary_walls
133
+ }
134
+ )
135
+ return cls(space_boundary_groups=space_boundary_groups)
136
+
137
+ def has_windows_without_wall(self) -> bool:
138
+ return all(
139
+ not (group.has_window() and not group.has_external_wall())
140
+ for group in self.space_boundary_groups
141
+ )
142
+
143
+
144
+ class Azimuths(BaseModel):
145
+ north: List[float] = [0.0, 360]
146
+ east: List[float] = [90.0]
147
+ south: List[float] = [180.0]
148
+ west: List[float] = [270.0]
149
+ northeast: List[float] = [45.0]
150
+ southeast: List[float] = [135.0]
151
+ southwest: List[float] = [225.0]
152
+ northwest: List[float] = [315.0]
153
+ tolerance: float = 22.5
154
+
155
+ def get_azimuth(self, value: float) -> float:
156
+ fields = [field for field in self.model_fields if field not in ["tolerance"]]
157
+ for field in fields:
158
+ possibilities = getattr(self, field)
159
+ for possibility in possibilities:
160
+ if (
161
+ value >= possibility - self.tolerance
162
+ and value <= possibility + self.tolerance
163
+ ):
164
+ return float(possibilities[0])
165
+ raise ValueError(f"Value {value} is not within tolerance of any azimuths.")
136
166
 
137
167
 
138
168
  class SpaceBoundary(BaseModelConfig):
@@ -141,11 +171,17 @@ class SpaceBoundary(BaseModelConfig):
141
171
  common_surface: CommonSurface
142
172
  adjacent_spaces: List[Space] = Field(default_factory=list)
143
173
 
174
+ def __hash__(self) -> int:
175
+ return hash(self.common_surface)
176
+
144
177
  def boundary_name(self) -> str:
145
178
  return f"{self.entity.is_a()}_{remove_non_alphanumeric(self.entity.GlobalId)}"
146
179
 
147
- def model_element(
148
- self, exclude_entities: List[str], north_axis: Vector
180
+ def model_element( # noqa: PLR0911
181
+ self,
182
+ exclude_entities: List[str],
183
+ north_axis: Vector,
184
+ constructions: Constructions,
149
185
  ) -> Optional[BaseWall]:
150
186
  if self.entity.GlobalId in exclude_entities:
151
187
  return None
@@ -154,23 +190,23 @@ class SpaceBoundary(BaseModelConfig):
154
190
  return ExternalWall(
155
191
  name=self.boundary_name(),
156
192
  surface=self.common_surface.area,
157
- azimuth=azimuth,
193
+ azimuth=Azimuths().get_azimuth(azimuth),
158
194
  tilt=Tilt.wall,
159
- construction=construction,
195
+ construction=constructions.get_construction(self.entity),
160
196
  )
161
197
  if "door" in self.entity.is_a().lower():
162
198
  return ExternalDoor(
163
199
  name=self.boundary_name(),
164
200
  surface=self.common_surface.area,
165
- azimuth=azimuth,
201
+ azimuth=Azimuths().get_azimuth(azimuth),
166
202
  tilt=Tilt.wall,
167
- construction=construction,
203
+ construction=constructions.get_construction(self.entity),
168
204
  )
169
205
  if "window" in self.entity.is_a().lower():
170
206
  return Window(
171
207
  name=self.boundary_name(),
172
208
  surface=self.common_surface.area,
173
- azimuth=azimuth,
209
+ azimuth=Azimuths().get_azimuth(azimuth),
174
210
  tilt=Tilt.wall,
175
211
  construction=glass,
176
212
  )
@@ -180,7 +216,16 @@ class SpaceBoundary(BaseModelConfig):
180
216
  surface=self.common_surface.area,
181
217
  azimuth=azimuth,
182
218
  tilt=Tilt.ceiling,
183
- construction=construction,
219
+ construction=constructions.get_construction(self.entity),
220
+ )
221
+ if "slab" in self.entity.is_a().lower():
222
+ orientation = self.common_surface.orientation.dot(ROOF_VECTOR)
223
+ return ExternalWall(
224
+ name=self.boundary_name(),
225
+ surface=self.common_surface.area,
226
+ azimuth=azimuth,
227
+ tilt=Tilt.ceiling if orientation > 0 else Tilt.floor,
228
+ construction=constructions.get_construction(self.entity),
184
229
  )
185
230
 
186
231
  return None
@@ -206,20 +251,45 @@ class SpaceBoundary(BaseModelConfig):
206
251
  )
207
252
 
208
253
 
209
- class SpaceBoundaries(BaseModel):
254
+ class SpaceBoundaries(BaseShow):
210
255
  space: Space
211
256
  boundaries: List[SpaceBoundary] = Field(default_factory=list)
212
257
 
258
+ def description(self) -> set[tuple[float, tuple[float, ...], Any, str]]:
259
+ return {b.description() for b in self.boundaries}
260
+
261
+ def lines(self) -> List[Line]:
262
+ lines = []
263
+ for boundary in self.boundaries:
264
+ lines += boundary.common_surface.lines()
265
+ return lines
266
+
267
+ def remove(self, space_boundaries: List[SpaceBoundary]) -> None:
268
+ for space_boundary in space_boundaries:
269
+ if space_boundary in self.boundaries:
270
+ self.boundaries.remove(space_boundary)
271
+
213
272
  def model(
214
- self, exclude_entities: List[str], north_axis: Vector
273
+ self,
274
+ exclude_entities: List[str],
275
+ north_axis: Vector,
276
+ constructions: Constructions,
215
277
  ) -> Optional[TranoSpace]:
216
- external_boundaries = [
217
- boundary.model_element(exclude_entities, north_axis)
218
- for boundary in self.boundaries
219
- if boundary.model_element(exclude_entities, north_axis)
220
- ]
221
- if not external_boundaries:
222
- return None
278
+ external_boundaries = []
279
+ for boundary in self.boundaries:
280
+ boundary_model = boundary.model_element(
281
+ exclude_entities, north_axis, constructions
282
+ )
283
+ if boundary_model:
284
+ external_boundaries.append(boundary_model)
285
+
286
+ external_space_boundaries_group = (
287
+ ExternalSpaceBoundaryGroups.from_external_boundaries(external_boundaries)
288
+ )
289
+ if not external_space_boundaries_group.has_windows_without_wall():
290
+ raise HasWindowsWithoutWallsError(
291
+ f"Space {self.space.global_id} has a boundary that has a windows but without walls."
292
+ )
223
293
  return TranoSpace(
224
294
  name=self.space.space_name(),
225
295
  occupancy=Occupancy(),
@@ -238,28 +308,28 @@ class SpaceBoundaries(BaseModel):
238
308
  space: entity_instance,
239
309
  ) -> "SpaceBoundaries":
240
310
  space_ = Space.from_entity(space)
311
+
312
+ elements = get_building_elements(ifcopenshell_file)
241
313
  clashes = tree.clash_clearance_many(
242
314
  [space],
243
- ifcopenshell_file.by_type("IfcWall")
244
- + ifcopenshell_file.by_type("IfcSlab")
245
- + ifcopenshell_file.by_type("IfcRoof")
246
- + ifcopenshell_file.by_type("IfcDoor")
247
- + ifcopenshell_file.by_type("IfcWindow"),
315
+ elements,
248
316
  clearance=CLASH_CLEARANCE,
249
317
  )
250
318
  space_boundaries = []
251
-
252
- for clash in clashes:
253
- elements = [
254
- ifcopenshell_file.by_guid(clash.a.get_argument(0)),
255
- ifcopenshell_file.by_guid(clash.b.get_argument(0)),
319
+ elements_ = {
320
+ entity
321
+ for c in clashes
322
+ for entity in [
323
+ ifcopenshell_file.by_guid(c.a.get_argument(0)),
324
+ ifcopenshell_file.by_guid(c.b.get_argument(0)),
256
325
  ]
257
- for element in elements:
258
- if element.GlobalId == space.GlobalId:
259
- continue
260
- space_boundary = SpaceBoundary.from_space_and_element(
261
- space_.bounding_box, element
262
- )
263
- if space_boundary:
264
- space_boundaries.append(space_boundary)
326
+ if entity.is_a() not in ["IfcSpace"]
327
+ }
328
+
329
+ for element in list(elements_):
330
+ space_boundary = SpaceBoundary.from_space_and_element(
331
+ space_.bounding_box, element
332
+ )
333
+ if space_boundary:
334
+ space_boundaries.append(space_boundary)
265
335
  return cls(space=space_, boundaries=space_boundaries)
ifctrano/types.py ADDED
@@ -0,0 +1,5 @@
1
+ from typing import Literal
2
+
3
+ BuildingElements = Literal[
4
+ "IfcWall", "IfcSlab", "IfcRoof", "IfcDoor", "IfcWindow", "IfcPlate"
5
+ ]
ifctrano/utils.py ADDED
@@ -0,0 +1,29 @@
1
+ import re
2
+ import uuid
3
+ from typing import get_args
4
+
5
+ from ifcopenshell import file, entity_instance
6
+
7
+ from ifctrano.base import ROUNDING_FACTOR
8
+ from ifctrano.types import BuildingElements
9
+
10
+
11
+ def remove_non_alphanumeric(text: str) -> str:
12
+ text = text.replace(" ", "_")
13
+ return re.sub(r"[^a-zA-Z0-9_]", "", text).lower()
14
+
15
+
16
+ def generate_alphanumeric_uuid() -> str:
17
+ return str(uuid.uuid4().hex).lower()
18
+
19
+
20
+ def _round(value: float) -> float:
21
+ return round(value, ROUNDING_FACTOR)
22
+
23
+
24
+ def get_building_elements(ifcopenshell_file: file) -> list[entity_instance]:
25
+ return [
26
+ e
27
+ for building_element in get_args(BuildingElements)
28
+ for e in ifcopenshell_file.by_type(building_element)
29
+ ]
@@ -1,8 +1,7 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.3
2
2
  Name: ifctrano
3
- Version: 0.1.12
3
+ Version: 0.3.0
4
4
  Summary: Package for generating building energy simulation model from IFC
5
- Home-page: https://github.com/andoludo/ifctrano
6
5
  License: GPL V3
7
6
  Keywords: BIM,IFC,energy simulation,modelica,building energy simulation,buildings,ideas
8
7
  Author: Ando Andriamamonjy
@@ -12,11 +11,13 @@ Classifier: License :: Other/Proprietary License
12
11
  Classifier: Programming Language :: Python :: 3
13
12
  Classifier: Programming Language :: Python :: 3.10
14
13
  Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
15
  Requires-Dist: ifcopenshell (>=0.8.1.post1,<0.9.0)
16
- Requires-Dist: pydantic (>=2.10.6,<3.0.0)
16
+ Requires-Dist: open3d (>=0.19.0,<0.20.0)
17
17
  Requires-Dist: shapely (>=2.0.7,<3.0.0)
18
- Requires-Dist: trano (>=0.1.50,<0.2.0)
18
+ Requires-Dist: trano (>=0.5.0,<0.6.0)
19
19
  Requires-Dist: typer (>=0.12.5,<0.13.0)
20
+ Requires-Dist: vedo (>=2025.5.3,<2026.0.0)
20
21
  Project-URL: Repository, https://github.com/andoludo/ifctrano
21
22
  Description-Content-Type: text/markdown
22
23
 
@@ -0,0 +1,16 @@
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,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 1.5.2
2
+ Generator: poetry-core 2.1.2
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1,13 +0,0 @@
1
- ifctrano/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- ifctrano/base.py,sha256=xpfZ27dZ5SZ5z2fz3N4GonkGWvXRYhMfOjoy94R4Yt8,5748
3
- ifctrano/bounding_box.py,sha256=OnkOR3NOyVRFSdo0d9BeFm93ZU40TV_gQSxYHOEPCYE,9382
4
- ifctrano/building.py,sha256=NoF0V5H_jDoyl0zkWPrSQa4xX0HIA23Kqu_TbH4Q56M,7134
5
- ifctrano/example/verification.ifc,sha256=L6YRD_rny7IEB4myA7uCLO6eI-xXOn2jp_67lw3lUrE,128600
6
- ifctrano/exceptions.py,sha256=1FQeuuq_lVZ4CawwewQvkE8OlDQwhBTbKfmc2FiZodo,431
7
- ifctrano/main.py,sha256=QH5KI8wFM4KsIRXNz_CVNtr3DWP3GdETtAAZGL84VEI,2703
8
- ifctrano/space_boundary.py,sha256=SxVXkBi8TNZfmPDFT-6epuewk8E9V1astVgcD3FT8ew,8617
9
- ifctrano-0.1.12.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
10
- ifctrano-0.1.12.dist-info/METADATA,sha256=aSroySKHppxHxEyq0v-RvwAEPhy70AqTL4gTRsP5oig,3490
11
- ifctrano-0.1.12.dist-info/WHEEL,sha256=7Z8_27uaHI_UZAc4Uox4PpBhQ9Y5_modZXWMxtUi4NU,88
12
- ifctrano-0.1.12.dist-info/entry_points.txt,sha256=_2daDejazkphufyEu0m3lOeTio53WYmjol3KmSN0JM4,46
13
- ifctrano-0.1.12.dist-info/RECORD,,