Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Passing changes to/from EdgeDB and Unordered lists in IFC/Diffing technique #9

Open
Krande opened this issue Sep 13, 2022 · 3 comments

Comments

@Krande
Copy link
Owner

Krande commented Sep 13, 2022

Hey @aothms,

I am quite close to having a working PoC of EdgeDB as a backend IFC DB for Blender.

Right now I am focusing on how specific changes are passed to/from the EdgeDB database.

Therefore, I have 2 questions about the IFC schema that I find challenging when roundtripping changes to/from the EdgeDB database that I wanted to get your thoughts on.

Q1 -> IfcRepresentation.Items is a SET (unordered list).

Any suggestions on how I can ensure that I am updating the correct item in the scenario I would have multiple IfcRepresentationItem objects and the IfcRepresentationItem does not have any unique markers? Currently I am thinking I would have to replace the entire set :(

FYI see this for a more detailed description of the issue I am facing and a specific example.

Q2 -> My Diffing technique

Inspired by the IfcDiff module, I made my own class that also uses deepdiff but compares all rooted elements (each rooted element is compared recursively) and it returns a dictionary with precise property changes and their path per rooted element.

My question is then whether you think this strategy would miss any changes to non-rooted elements (inverse attribute-objects etc.) and if so any tips on how I could catch those?

@aothms
Copy link

aothms commented Sep 13, 2022

Like all problems in life, I think this is mostly caused by IfcOpenShell.

We know IfcRepresentation.Items is a SET but still we return a Python list. What does EdgeDB give you?

I think when reading an IFC model we should be able to tweak the data types. If we map an Express SET to a python (frozen)set then equality comparison would work. Making this change now in ifopsh is a bit drastic, but we should be able to work out some sort of mapping function to help.

import pprint
import ifcopenshell
from functools import partial
# pip install frozendict
from frozendict import frozendict

f = ifcopenshell.open("d.ifc")
inst = [i for i in f.by_type('IfcShapeRepresentation') if len(i.Items) > 1][0]

def transform_aggregates(f, val, attr=None, ent=None):
    if isinstance(val, dict):
        ent = ifcopenshell.ifcopenshell_wrapper.schema_by_name(f.schema).declaration_by_name(val['type'])
        def inner(kv):
            return kv[0], transform_aggregates(f, kv[1], attr=kv[0], ent=ent)
        return frozendict(map(inner, val.items()))
    elif isinstance(val, (list, tuple)):
        adef = [a for a in ent.all_attributes() if a.name() == attr][0]
        if adef.type_of_attribute().type_of_aggregation_string():
            return frozenset(map(partial(transform_aggregates, f), val))
    else:
        return val

tree1 = inst.get_info(include_identifier=False, recursive=True)
pprint.pprint(tree1)
tree2 = transform_aggregates(f, tree1)
pprint.pprint(tree2)

See above for a rough sketch (doesn't work for list of list yet). The difficulty is in the nesting. If we want attributes to be sets, they need to be hashable. But neither entity_instance nor dict is hashable because they both can be changed.

So we need to use both frozendict and frozenset so that they can be contained in higher level sets. It's a bit obscure, and I don't know how deepdiff would treat these kind of things. But the good news is that you can readily compare them for equality in python.


There is one non-rooted entity instance that in many times conceptually is a root, it's IfcStyledItem, reachable from the IfcRepresentationItem.StyledByItem.

@Krande
Copy link
Owner Author

Krande commented Sep 13, 2022

Like all problems in life, I think this is mostly caused by IfcOpenShell.

Haha :)

Thanks for getting back to me so quickly!

Before delving into the matter in your response, I can at least say that EdgeDB gives me an ordered list for Items (defined as a multi link in edgedb).

@Krande
Copy link
Owner Author

Krande commented Sep 13, 2022

Oops, I misspoke. EdgeDB's multi link apparently does NOT return an ordered list as a default. But there are options to order items in multi link sets in EdgeDB. I'll try to find a way to order the items in EdgeDB using an identifier that makes sense!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants