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/__init__.py +3 -0
- ifctrano/base.py +266 -13
- ifctrano/bounding_box.py +99 -169
- ifctrano/building.py +109 -54
- ifctrano/construction.py +227 -0
- ifctrano/example/verification.ifc +3 -3043
- ifctrano/exceptions.py +4 -0
- ifctrano/main.py +55 -2
- ifctrano/space_boundary.py +168 -98
- ifctrano/types.py +5 -0
- ifctrano/utils.py +29 -0
- {ifctrano-0.1.12.dist-info → ifctrano-0.3.0.dist-info}/METADATA +6 -5
- ifctrano-0.3.0.dist-info/RECORD +16 -0
- {ifctrano-0.1.12.dist-info → ifctrano-0.3.0.dist-info}/WHEEL +1 -1
- ifctrano-0.1.12.dist-info/RECORD +0 -13
- {ifctrano-0.1.12.dist-info → ifctrano-0.3.0.dist-info}/LICENSE +0 -0
- {ifctrano-0.1.12.dist-info → ifctrano-0.3.0.dist-info}/entry_points.txt +0 -0
ifctrano/exceptions.py
CHANGED
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
|
-
|
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(
|
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()
|
ifctrano/space_boundary.py
CHANGED
@@ -1,37 +1,32 @@
|
|
1
1
|
import multiprocessing
|
2
|
-
import
|
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
|
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
|
88
|
-
self.floor_area * self.average_room_height
|
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
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
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
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
)
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
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,
|
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=
|
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=
|
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=
|
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(
|
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,
|
273
|
+
self,
|
274
|
+
exclude_entities: List[str],
|
275
|
+
north_axis: Vector,
|
276
|
+
constructions: Constructions,
|
215
277
|
) -> Optional[TranoSpace]:
|
216
|
-
external_boundaries = [
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
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
|
-
|
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
|
-
|
253
|
-
|
254
|
-
|
255
|
-
ifcopenshell_file.by_guid(
|
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
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
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
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
|
+
Metadata-Version: 2.3
|
2
2
|
Name: ifctrano
|
3
|
-
Version: 0.
|
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:
|
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.
|
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,,
|
ifctrano-0.1.12.dist-info/RECORD
DELETED
@@ -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,,
|
File without changes
|
File without changes
|