python-materialsdb 0.0.2__py3-none-any.whl → 0.2.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.
- materialsdb/__init__.py +3 -1
- materialsdb/cache.py +5 -6
- materialsdb/classes.py +14 -6
- materialsdb/config.py +3 -6
- materialsdb/construction.py +441 -0
- materialsdb/gui/__init__.py +0 -0
- materialsdb/gui/__main__.py +32 -0
- materialsdb/gui/discovery.py +28 -0
- materialsdb/gui/listener.py +151 -0
- materialsdb/gui/server.py +730 -0
- materialsdb/gui/static/app-constructions.js +639 -0
- materialsdb/gui/static/app.js +451 -0
- materialsdb/gui/static/constructions.html +107 -0
- materialsdb/gui/static/index.html +56 -0
- materialsdb/gui/static/picker-core.js +111 -0
- materialsdb/ifc/material_builder.py +295 -0
- materialsdb/ifc/material_psets.json +594 -580
- materialsdb/ifc/project_library.py +77 -212
- materialsdb/query.py +24 -0
- materialsdb/schema/MaterialsDBIndex100.xsd +60 -0
- materialsdb/schema/materialsdb102.xsd +820 -0
- materialsdb/schema/materialsdb103.xsd +938 -0
- materialsdb/serialiser.py +45 -18
- materialsdb/store.py +293 -0
- materialsdb/summary.py +83 -0
- materialsdb/utils.py +15 -21
- python_materialsdb-0.2.0.dist-info/METADATA +170 -0
- python_materialsdb-0.2.0.dist-info/RECORD +33 -0
- {python_materialsdb-0.0.2.dist-info → python_materialsdb-0.2.0.dist-info}/WHEEL +1 -1
- python_materialsdb-0.2.0.dist-info/entry_points.txt +2 -0
- python_materialsdb-0.0.2.dist-info/METADATA +0 -68
- python_materialsdb-0.0.2.dist-info/RECORD +0 -14
- {python_materialsdb-0.0.2.dist-info → python_materialsdb-0.2.0.dist-info/licenses}/LICENSE.md +0 -0
- {python_materialsdb-0.0.2.dist-info → python_materialsdb-0.2.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
"""Resolved push payloads for the listener channel (slice 1: add_materials).
|
|
2
|
+
|
|
3
|
+
The server resolves picker selections into exactly the entity list
|
|
4
|
+
MaterialBuilder would create (one entry per IfcMaterial); the Bonsai add-on
|
|
5
|
+
maps the payload onto its open file without importing this library."""
|
|
6
|
+
|
|
7
|
+
from materialsdb import config, utils
|
|
8
|
+
from materialsdb.ifc.material_builder import PSETS, get_value
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def _resolved_psets(layer, country) -> dict:
|
|
12
|
+
resolved = {}
|
|
13
|
+
for pset_name, props in PSETS.items():
|
|
14
|
+
values = {}
|
|
15
|
+
for prop_name, definition in props.items():
|
|
16
|
+
if not definition["primary_measure_type"]:
|
|
17
|
+
continue
|
|
18
|
+
value = get_value(layer, definition, country)
|
|
19
|
+
if value:
|
|
20
|
+
values[prop_name] = value * (definition.get("unit_factor") or 1)
|
|
21
|
+
if values:
|
|
22
|
+
resolved[pset_name] = values
|
|
23
|
+
return resolved
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def build_add_materials_payload(store_, items, country=None, lang=None):
|
|
27
|
+
"""Resolve picker items [{id, layer_ids?}] into
|
|
28
|
+
({"action": "add_materials", "materials": [...]}, missing_ids).
|
|
29
|
+
|
|
30
|
+
One materials[] entry per IfcMaterial, mirroring MaterialBuilder.build():
|
|
31
|
+
a 2-layer material yields 2 same-named entries, each carrying its own
|
|
32
|
+
layer's resolved psets. Ids that fail to resolve (unknown, or no
|
|
33
|
+
resolvable layers) land in missing_ids."""
|
|
34
|
+
country = country or config.get_country()
|
|
35
|
+
lang = lang or config.get_lang()
|
|
36
|
+
materials = []
|
|
37
|
+
missing = []
|
|
38
|
+
for item in items:
|
|
39
|
+
if not isinstance(item, dict):
|
|
40
|
+
missing.append(str(item))
|
|
41
|
+
continue
|
|
42
|
+
material_id = str(item.get("id") or "")
|
|
43
|
+
summary = store_.get_summary(material_id)
|
|
44
|
+
material = store_.get(material_id)
|
|
45
|
+
if summary is None or material is None:
|
|
46
|
+
missing.append(material_id)
|
|
47
|
+
continue
|
|
48
|
+
wanted = {str(g) for g in item.get("layer_ids") or []} or None
|
|
49
|
+
name = str(utils.get_material_name(material, lang))
|
|
50
|
+
description = str(utils.get_material_description(material, lang))
|
|
51
|
+
category = str(getattr(material.information, "group", "") or "")
|
|
52
|
+
color = getattr(material.information, "color", None)
|
|
53
|
+
entries = []
|
|
54
|
+
for layer in utils.get_material_layers(material):
|
|
55
|
+
if wanted is not None and str(layer.id) not in wanted:
|
|
56
|
+
continue
|
|
57
|
+
geometry = utils.get_by_country(layer.geometry or (), country)
|
|
58
|
+
thick = getattr(geometry, "thick", None)
|
|
59
|
+
entries.append(
|
|
60
|
+
{
|
|
61
|
+
"source_id": material_id,
|
|
62
|
+
"layer_id": str(layer.id),
|
|
63
|
+
"name": name,
|
|
64
|
+
"description": description,
|
|
65
|
+
"category": category,
|
|
66
|
+
"color": int(color) if color else None,
|
|
67
|
+
"identity": {
|
|
68
|
+
"material_id": material_id,
|
|
69
|
+
"company_id": str(summary.company_id or ""),
|
|
70
|
+
"company": str(summary.company or ""),
|
|
71
|
+
},
|
|
72
|
+
"psets": _resolved_psets(layer, country),
|
|
73
|
+
"layer": {"layer_id": str(layer.id), "thick_m": thick / 1000} if thick else None,
|
|
74
|
+
}
|
|
75
|
+
)
|
|
76
|
+
if not entries:
|
|
77
|
+
missing.append(material_id)
|
|
78
|
+
continue
|
|
79
|
+
materials.extend(entries)
|
|
80
|
+
return {"action": "add_materials", "materials": materials}, missing
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
_DESIGN_USAGE_TO_TYPES = {
|
|
84
|
+
"consDesignForWall": ["IfcWallType"],
|
|
85
|
+
"consDesignForFloor": ["IfcSlabType"],
|
|
86
|
+
"consDesignForRoof": ["IfcRoofType"],
|
|
87
|
+
}
|
|
88
|
+
GENERIC_TYPES = ["IfcWallType", "IfcSlabType", "IfcRoofType"]
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def build_add_construction_payload(store_, body, country=None, lang=None):
|
|
92
|
+
"""Resolve a construction body into a self-sufficient add_construction
|
|
93
|
+
payload (or (None, problems) when validation fails). Materials travel
|
|
94
|
+
minimal — identity/name/category/color, to_ifc_layer_set-style — and
|
|
95
|
+
find-or-create on the add-on side keys on the identity pset."""
|
|
96
|
+
from materialsdb import construction as cm
|
|
97
|
+
|
|
98
|
+
body = dict(body or {})
|
|
99
|
+
if body.get("design_usage") not in (None, *_DESIGN_USAGE_TO_TYPES):
|
|
100
|
+
body["design_usage"] = None # unknown usage -> generic types (validate_construction would reject it)
|
|
101
|
+
construction, problems = cm.validate_construction(body, store_)
|
|
102
|
+
if problems:
|
|
103
|
+
return None, problems
|
|
104
|
+
country = country or config.get_country()
|
|
105
|
+
lang = lang or config.get_lang()
|
|
106
|
+
layers = []
|
|
107
|
+
for layer in construction.layers:
|
|
108
|
+
if layer.placeholder is not None:
|
|
109
|
+
layers.append(
|
|
110
|
+
{
|
|
111
|
+
"material_id": None,
|
|
112
|
+
"thickness_m": layer.thickness_m,
|
|
113
|
+
"placeholder": dict(layer.placeholder),
|
|
114
|
+
}
|
|
115
|
+
)
|
|
116
|
+
continue
|
|
117
|
+
summary = store_.get_summary(layer.material_id)
|
|
118
|
+
material = store_.get(layer.material_id)
|
|
119
|
+
if summary is None or material is None:
|
|
120
|
+
problems.append(f"unknown material id: {layer.material_id}")
|
|
121
|
+
continue
|
|
122
|
+
color = getattr(material.information, "color", None)
|
|
123
|
+
layers.append(
|
|
124
|
+
{
|
|
125
|
+
"material_id": layer.material_id,
|
|
126
|
+
"thickness_m": layer.thickness_m,
|
|
127
|
+
"material": {
|
|
128
|
+
"source_id": layer.material_id,
|
|
129
|
+
"name": str(utils.get_material_name(material, lang)),
|
|
130
|
+
"description": str(utils.get_material_description(material, lang)),
|
|
131
|
+
"category": str(getattr(material.information, "group", "") or ""),
|
|
132
|
+
"color": int(color) if color else None,
|
|
133
|
+
"identity": {
|
|
134
|
+
"material_id": layer.material_id,
|
|
135
|
+
"company_id": str(summary.company_id or ""),
|
|
136
|
+
"company": str(summary.company or ""),
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
}
|
|
140
|
+
)
|
|
141
|
+
if problems:
|
|
142
|
+
return None, problems
|
|
143
|
+
return {
|
|
144
|
+
"action": "add_construction",
|
|
145
|
+
"construction": {
|
|
146
|
+
"name": construction.name,
|
|
147
|
+
"design_usage": construction.design_usage,
|
|
148
|
+
"types": _DESIGN_USAGE_TO_TYPES.get(construction.design_usage or "", GENERIC_TYPES),
|
|
149
|
+
"layers": layers,
|
|
150
|
+
},
|
|
151
|
+
}, []
|