Ping @berndhahnebach and @yorikvanhavre and @aothms
IfcOpenShell is used in a lot of utilities, which can lead to duplicate code if the same things are implemented again and again.
I propose to create a new util module, which can be imported as import ifcopenshell.util. It will contain methods that can be reused across the many implementations.
Here are four functions I propose to add first, as I suspect they can be instantly reused in FreeCAD/BlenderBIM Add-on/IFCCSV/BIMTester/any mini-script written by someone/etc.
ifcopenshell.util.get_pset_property(element, pset_name, prop_name) returns the wrappedValue if it is a simple property definition, else, for now, return is undefined.ifcopenshell.util.get_qto_property(element, qto_name, prop_name) - same, but for Qtoifcopenshell.util.dd2dms(dd) - converts from decimal degrees to degrees minutes seconds. Returns a tuple of (d, m, s). This is required for almost all georeferencing implementationsifcopenshell.util.dms2dd(dms) - the other way aroundWe can add more and tweak as we go along, but I suspect these 4 have little debate around them, so would be a good starting point.
Thanks for this initiative. Great idea.
Regarding properties and quantities: how about just enumerating all properties and quantities into a defaultdict(dict). So that users do something like
util.get_all_properties(elem)["PSet_WallCommon"].get("IsExternal").
Advantages:
Is it useful to distinguish type/instance prop associations?
Basically there is code for this defined here: https://github.com/IfcOpenShell/IfcOpenShell/blob/master/src/ifcopenshell-python/ifcopenshell/geom/app.py#L320
Indeed we have to think about the return type. Even for PSingleValue there can be a Unit. And if Unit is null we probably need to apply the IfcProject Unit (as that's the default for geometry too). So that e.g. the volume/surface measures correspond. Perhaps it can be some custom class to encapsulate all of this (it can inherit from str or float so that users can use it easily).
Sounds great to me! I'm more than happy to make a start on the module if @yorikvanhavre and @berndhahnebach are also keen, and then we can collectively tweak it. I like your suggestion about a default dict!
Unit is tricky - we need some util functions for unit conversions. I've got some code already related to that... but we need to agree on the function signature.
Should I do this in a PR, or? (I won't replace any existing functions with this util function until we're all happy with it)
Like the idea! I'd definitely try to use that in FreeCAD ;) and i like using a dict or defaultdict as well.. it's easy later on to add more specific stuff..
It would be interesting to have a function that returns the project unit too.. then the needed conversions could be done by the user for now
Should I do this in a PR, or?
For me a PR is not necessary.
Re unit functionality, there was somebody on the forums willing to contribute something https://sourceforge.net/p/ifcopenshell/discussion/1782717/thread/1a1c98e843/#c68f
@yorikvanhavre I will also invite you as a developer so that if you have additions to the util module or elsewhere you don't need depend on us.
Humbled by your trust @aothms . Thanks!!
We had a short disscussion about this on FreeCAD forum some days ago. Great to see this realised that fast. It would be excellent if we could move these methods mentioned by moult into ifcopenshell. All programms which use ifcopenshell would treat ifc files the same way than.
It would make things much simpler in FreeCAD too.
cheers bernd
I've made a start. The perfect is the enemy of the good, so here's what I've done ;)
ifcopenshell.util.geolocationifcopenshell.util.element there is get_psets(element) which takes any element and will grab its psets and qtos and return a dictionary of the results as per @aothms 's code. Slight modification to allow you to feed it a type object too. I also made it _not_ return the relating type's psets, as I believe we need to think carefully how users might 1) want psets _only_ defined at the object level, and 2) want psets with type vs element pset overriding occuring.ifcopenshell.util.unit is the unit code I already use in blenderbim add-on, and I believe has some similarities in freecad. The functions are a bit simplistic, but this will be improved.ifcopenshell.util.selector is a selector allowing you to parse an IFC shorthand query (see #748). For now, it supports the CSS-style syntax which I have been using extensively to implement CLI filtering in IFCCSV, and am about to roll out to IfcClash, IfcDiff, and BlenderBIM Add-on itself. When an XPath style selector syntax is designed, it can also be supported, or may supersede the current CSS-style. I think with this code-shared, @yorikvanhavre can very quickly implement these features in FreeCAD too :)Hello, I do not understand much of what's going on here, sorry, but as i'm becoming a real FreeCAD addict, i'm really motivated to help in this field :)
@Moult Fantastic. Maybe create a couple of issues where others (incl. me) can help. We have good first issue and help wanted labels. Edit: Tiny comment it seems in dms2dd() you don't incorporate milliseconds.
@aothms cheers and you are absolutely right about the bug in dms2dd()! @carlopav what do you reckon, is this something you'd like to fix? You can then also swap out the FreeCAD dms2dd and dd2dms code with this module?
Edit: actually, it would be cool to also use xyz2enh in FreeCAD - FreeCAD already has georeferencing entities stored, so it is fairly trivial to make a new feature which converts local to global...
... and maybe, then, we also need a enh2xyz()?
@moult sure I can try.
I'd love to see added to the utils
get_transform (Perhaps world and local)get_material (Less clear what the data structure would be for this)These two methods would make conversion utilities easier to write when they chose not to use the internal create_shape method.
I make use of ifcopenshell.util.element.get_psets(ifcfileinstance[entity]) on a regular basis. Lately even IfcComplexProperty has been added. Thanks to moult. (2a22acfdc936) One reason more to use this in FreeCAD. I may implent it in FreeCAD ...
The reason why I post is as follows. How about making get_psets working like get_info()
entityinstance.get_psets()
ping @aothms
cheers bernd
The reason why I post is as follows. How about making get_psets working like get_info():
entityinstance.get_psets()
I don't have a strong opinion. The utils thing are a bit harder to discover, on the other hand it can be made a bit clearer that not all entity instances have psets (object and typeobject, through a different mechanism). Do as you please.
Closing as the util module is well underway and evolving :)
Most helpful comment
Like the idea! I'd definitely try to use that in FreeCAD ;) and i like using a dict or defaultdict as well.. it's easy later on to add more specific stuff..
It would be interesting to have a function that returns the project unit too.. then the needed conversions could be done by the user for now