Without 'Material.Name' layers merge. - #7700
Conversation
|
This is through hard won trial and error. Not entirely sure why |
|
from AI...
The practical problem is that this is a hidden coupling: a developer reading |
|
also from AI.... Now we can see exactly what happens. Looking at
python elif key in ("material", "mat"):
value = ifcopenshell.util.element.get_material(value, should_skip_usage=True)It hits this explicit special-case branch, which traverses python if key == "Name" and value.is_a("IfcMaterialLayerSet"):
key = "LayerSetName"
It doesn't match any special keyword. It falls through to the python attribute = getattr(value, key, None) # key = "Material"So it's looking for a direct This confirms the earlier suspicion, but more precisely: when a wall, for example, with an IfcMaterialLayerSet, when This is a subtle but elegant interaction between two parts of the code. The key is that python keys = []
for query in join_criteria:
key = ifcopenshell.util.selector.get_element_value(element, query)
keys.append(key)
if layer:
for query in join_criteria:
key = ifcopenshell.util.selector.get_element_value(layer, query)
keys.append(key)
hash_keys = hash(tuple(keys))The Now the difference becomes clear:
So with In other words, |
Backport of PR IfcOpenShell#9493 (v0.9.0). Fixes IfcOpenShell#7830. Addresses the second half of IfcOpenShell#7000. A material layer's cut linework could never merge with a non-layered element of the same material, no matter what JoinCriteria was set to. The key was built by evaluating every criterion against the element, then, if the cut was a material layer, evaluating every criterion again against the layer and appending those values. A layered cut's key tuple was therefore roughly twice the length of an unlayered one's, so the two could not hash equal even when every value agreed. The list was also doing two unrelated jobs at once: controlling which elements merge, and which layers stay apart. It only worked because "material.Name" and "Material.Name" happened to cancel at the element level while diverging at the layer level - "Material.Name" resolves to None on a wall, but to the layer's own IfcMaterial on an IfcMaterialLayer, purely because "Material" is a real attribute there. That was added in IfcOpenShell#7700 to fix IfcOpenShell#7252 and IfcOpenShell#7369, where every layer hashed alike and collapsed into one polygon. Introduce "cut_material": the material of the cut itself - that layer's material for a layered cut, or the element's own material where it has exactly one. The layer pass goes away, so the key is one tuple of fixed length either way, and the same material keys identically whether or not it arrived as a layer. This replaces both "material.Name" and "Material.Name" in the default criteria; layers still keep each other apart, so IfcOpenShell#7252 and IfcOpenShell#7369 do not regress. "cut_material" is deliberately join-local vocabulary rather than a new selector key. Which material a cut carries depends on which layer is being drawn, which is drawing state no query over the element alone can express, and the drawing join code is the only caller in the tree that ever passed a non-product entity to get_element_value. Keeping it separate leaves "material.Name" meaning the layer set name here exactly as it does in Metadata, IfcCSV and text literals. Where nothing identifies a cut's material - no material at all, or several with unlayered geometry - the IFC class is appended instead, so unidentified cuts do not all share one key and merge on contact. With EPset_Drawing.JoinClasses (IfcOpenShell#4395) naming the classes and "class" omitted from JoinCriteria, a slab's concrete layer now reads continuous into a concrete footing. Verified on SECTION - EAST of a real project: the two footings and the slab's concrete layer merge into a single closed 19 point path, while the slab's vapour barrier layer, the wall layers, and the unlayered slab outline all stay separate. Note one behaviour change under the default criteria: a layered cut is now keyed on its layer's material alone, where previously the layer set name also participated. Two different layer sets sharing a material will merge where they touch. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
No description provided.