Controversial proposal to drastically simpify mapped representations

Before I get into what is undoubtedly going to be a very controversial proposal (buckle in for a wall of text!)…

… when I first read the IFC specification about how geometries are shared, and read about the concept of mapped representations, and learned about mapped items, reuse of items within representations, possibly nested mapped representations, and cartesian transformation operator 3d (and its non-uniform variant) …

… I was really confused.

Fast forward to now, after a non-negligible amount of time poking at the spec: I get it, it’s an almost crazily flexible and nuanced shape reuse structure and as a result even after I think I understand it I still treat the potential nesting and detection of reused representations as a heavily complex part of any real coded implementation. In short:

  1. It was confusing when I first read it. It was scary to me, it probably scared other people too.
  2. I still treat it with caution now.
  3. Any further in-spec operations then multiply in complexity when you have to take into account this geometry and potential (non-uniform scaling) transformations (e.g. quantity take off, project libraries, type mapped representation reuse, colour fallbacks on material when the representation item isn’t styled, but still reused across objects…) - I can almost guarantee bugs in implementations once we really start poking at these scenarios …
  4. Out-of-spec operations, such as when Bob The Coder wants to build a script to extract and analyse BIM geometry explodes in complexity. Especially when you deal with native IFC authoring and you have to make decisions on how representations are shared and reused and modified. Usually, the only way to make sure I’m doing things right is to then test the result with a bunch of viewers - again, I can almost guarantee bugs in a lot of user-written scripts …
  5. Regardless of spec scope, it makes it less practical for humans to debug and understand, as multiple ways can be used to achieve similar things. (Esp. the hacks used as a workaround to incomplete or incorrect geolocation support - where the object placements are offset, the absolute coords are offset, the mapped items are offset, or a combination of the three…)
  6. I’m probably not the only one who feels this way. Raise your hand if this stuff makes you feel uneasy too!

In the spirit of proposing daring and possibly breaking changes for IFC5, I’d like to test the waters on how the community feels about a drastic simplification of representation reuse and representation transformations. I’d like to propose a few high level bullet points.

The purpose of all the following bullet points is to heavily simplify mapped representations. This will come at the cost of reduced flexibility and reduced efficiency. In exchange, I expect to gain a schema that is much less complex, easily scripted, easily learned by newcomers, less buggy implementations, easier to optimise coded implementations, and please please please let’s make geometry just easier overall so we can move on to more interesting data relationships.

  1. If geometry is reused, that means that they share the same construction type. End of story. See related discussion.
  2. A product definition shape must map either all of its representations, or none at all. Let’s get rid of “oh, body is mapped, box isn’t, footprint isn’t either but annotation is…” confusion.
  3. Just … delete MappedItem. Crazy, I know. But this is what leads to the majority of complexities in other operations. See related discussion. The IfcMappedItem.MappingSource.MappingOrigin will simply be part of the ObjectPlacement of the product / type product instead.
  4. No scaling allowed. Scaling, which used to be in IfcMappedItem.MappingTarget, will be deleted, and instead buildingSMART should come up with a new strategy to represent scaling, alongside other complex geometry operations which have cascading effects downstream on other relationships (qto, costing, typing, structural analysis, energy modeling, normals for geometric analysis and handling materials and textures, backface culling for viewers…). Other complex geometry operations include mirroring and arraying. The sooner that scaling is ripped out of the shape representation tree, the less likely it is for arraying to enter there and make it even messier.
  5. Remove MappingOrigin. Just use ObjectPlacement.
  6. No nested mapped representations.

To demonstrate how aggressive this proposal is, here is the current situation, with everything I have removed:

Here is the aggressively cleaned up proposal:

Also, a ton of diagrams can be simplified in the IFC spec too:

image

In words, here is how you’d explain the concept to a newcomer to IFC:

IFC products can have a local origin known as the object placement, which determines the insertion point of its geometry. Its geometry can have multiple visual representations belonging to different viewing contexts, such as 3D views, or 2D views. If a product is assigned to a typical construction type, it is possible to instead define the representations once only to that construction type. The product then inherits all of the construction type’s representations. The inherited representations from the construction type are inserted at the object placement of each product.

In the past, it would be:

So IFC products has an object placement and a product definition, which then has multiple representations. These representations may be unique to the product, or mapped. If it is mapped, it is likely but not guaranteed to be part of the construction type so don’t assume inheritance. Some representations may be mapped, but others may not, so you need to check each individually, and also don’t assume changing one representation from one context affects another, since it may or may not be equally mapped. Also, if it is mapped, you don’t know what type of geometry (e.g. brep vs solid) it is until you navigate through the nested mapped item. So the representation can have one or more items. Some of those might map to representations, some might not, I haven’t checked if there is a WR constraining this but mostly you’ll find they either all map or all don’t map, but I’m not 100% sure. So, assuming they map, the insertion point may first be transformed by a non-scaling matrix called the mapping origin. Then, the geometry itself may be transformed again by another matrix which may or may not be uniformly scaled. Also, this process may nest a few times. The final representation is the accumulated result of resolving the matrixes of all of these potentially mapped and unmapped items. Then finally you use the object placement. Also, don’t ask me how it affects quantity take off. Here’s some battle tested libraries to make sure you get it right.

So, thoughts and tomatoes? Maybe I’m totally off the mark here and everybody reckons the shape representation tree is fine as-is and maybe it’s just me … :slight_smile:

P.S. a clarification that this proposal is an obvious trade off where we lose efficiency / flexibility, and gain schema simplicity. Also, note that I have mentioned some valid usecases such as mirroring, scaling, and (poor man’s non-parametric) arraying which in my proposal I do not mention how to handle these usecases. I think these usecases are still valid, and should not be removed… but just, should perhaps be handled a different way (which I don’t know how yet) that prevents ambiguity to downstream applications (qto, costing, typing). On the other hand, usecases such as reusing a door knob as a mapped item across many different IfcDoor types … well, we lose that. Tough luck.

I remember when I used to teach AutoCAD to students of architecture. Everything became so much more complicated when you introduce scaling in a scenegraph… what’s the volume of a 1x1x1 cube nested in two or three levels of possibly non-uniformly nested parent coordinate systems? And what is the impact of having a few out of center rotations inserted into that three?

I support making things simple and there are many valuable suggestions here.

2 Likes

Simplifying the mapped items structure would be a huge step in simplifying the whole thing indeed… Funny that we have more or less the same concept that you propose in FreeCAD already: Any BIM object can take its shape from another BIM object, no further operation needed. It must be of the same type, and only position/rotation of the host object is applied.

1 Like

Them’s fightin’ words @Moult … I guess I would look at the solution to this a bit differently and enable an “aggregate” mode across more object concepts (like currently exist for IfcRoof, IfcStair, IfcCurtainWall, etc.). In each case, the “object/object type” could be a singular or aggregate composition and have nested/attached elements. So, for the door case, you could declare an IfcDoor to be just the door leaf OR you could declare it to be an aggregation/composite, with additional objects/object types like “hardware” or “hardware set”, “frame” or “frame set”. Then you wouldn’t lose the all important ability to map and track important components like door handles and associated locks across multiple doors… and could still apply a unique identification to each location/instance for scheduling purposes.

I dunno… just thinking off the top of my head…

@jwouellette in theory, you could already use aggregates as you’ve suggested to share door knobs, with no modification in the spec. However, the tradeoff is that you need to specify your semantics at that particular level of resolution - which I reckon is actually a good thing. So you’d reuse the representation at the IfcProduct level, not the shape representation tree level. Big win to legibility in my book.

I think we need to acknowledge that there is always a balance between schema complexity, schema efficiency, schema flexibility, and schema correctness.

Pinging some of the other implementers: @jonm @angel.velez

What I have proposed is also largely how BIM apps work and already present themselves to users (e.g. Revit has types and instances).

I think the most common case is exactly what you describe - an instance has a non-scaled transformation (position, rotation) of a shared type geometry. Simplifying that case would be great. Non-uniform and mirrored transforms are a general pain.
Counter-examples I can think of:

  1. Columns and beams that share a profile but not a length.
  2. Objects modified at the instance level (e.g., attached to a sloped object, cut by a void).
  3. Objects that share a type definition that doesn’t define geometry at all (e.g. walls)

So I think we may want to have a “simplest” case and then a “simpler” case, perhaps.

@angel.velez Cheers:

  1. Sharing a profile def is fine. The proposal has no impact on that.
  2. Objects modified at the instance level, i.e. voids / openings is not affected by this proposal. Behaviour is exactly the same as before. So no impact.
  3. The rule is that if the type has geometry, the instance must inherit it. Therefore, if the type has no geometry, the instance can either choose to specify its own instance-based geometry, or not specify anything at all. So your scenario is still valid (and should be, as it is a very valid scenario).

Can you have nested types? What if your instance is of a door with a window in the door?

@angel.velez sure - I am not proposing anything different to the existing capabilities of product aggregation. You’d just use aggregations as usual.

The only proposal I am making is to simplify the whole mapped item system, and formalise the existing intention in the spec to ensure that if a type has geometry, all instances of that type inherit the geometry.

Edit: when I am at a computer, I will draw some diagrams of before vs after for a variety or situations, including those you’ve mentioned, @angel.velez . From what I’ve seen of Revit exports, the output is already as I’ve proposed, so there are minimal changes (undoubtedly you know all of the details of the codebase)

From a user/scripter perspective, I can agree that simple is better, with one exception: mirroring. Mirrored instances of type definitions are very common in building projects. This particular transform can also originate at different levels of organization. Models can be mirrored, aggregates can be mirrored and instances can be mirrored. These transformations can compound as well. Not tracking them back to the type definition could cause some ugly QTO mistakes, and the occasional cold or scalding shower.

@Ekkonap yes, in my proposal, I am not suggesting to remove the ability to mirror, I am recommending to simply redesign the “mirror” function elsewhere to where it currently is, perhaps in a new location where something like an array makes sense too.

Moving mirroring outside can also therefore support mirroring aggregates and even groups, which are super important (typical rooms, for example). I see this as a positive.

BTW further reading why pulling the “mirror” transform outside (as I have proposed) might also be a good idea, is because it can make it easier to support scenarios like this:

Also here is a nice quote by @angel.velez which I agree with: Is IfcProductDefinitionShape a 1:1 relationship? - #4 by angel.velez

1 Like