Solved

How to efficiently filter features with an IFMECompositeSurface geometry from those with an IFMEFace geometry?

  • 28 February 2022
  • 3 replies
  • 6 views

Badge +3

A while back I developed a workspace in which I wanted to calculate the 'outsideWallArea' of buildings. That is, whenever buildings are directly next to each other, the touching wall that they both share, shouldn't be counted as an outsideWall. So for example, consider these 3 buildings (cubes with sidelength of 1);

imageNow both building 1 and 2 would have an outsideWallArea of 3, and building 3 would have an outsideWallArea of 4 (note, the floor and roof do not count as wallArea).

 

For this purpose, I used a SurfaceOnSurfaceOverlayer on the buildings. In this way neighbouring buildings fall apart in individual IFMEFaces, and by using the _overlaps attribute neighbouring walls can be excluded from the (outside)WallArea.

 

The 'problem' now is that disjoint buildings are not overlayed to other buildings, and these keep having an IFMECompositeSurface geometry, where neighbouring buildings fall apart in IFMEFace geometry features.

So after this step I need to distinguish between buildings that fell apart in IFMEFaces, and buildings that remained an IFMECompositeSurface geometry

imageNow I was wondering if there would be efficient ways to do this.

 

A simple GeometryFilter doesn't cut it, because both the IFMEFace and the IFMECompositeSurface are Surfaces. Then I used a GeometryPartExtractor with the Test Clause:

This part Hierarchy Position Is Root Node AND

This part Geometry Type = IFMECompositeSurface

 

This did work, but this turned out to be quite slow, probably because on the one hand this transformer is not really intended to be used to filter by Geometry Type. Also it seems to me that FME can be quite slow when executing many individual (geometry) XQuery statements.

 

I also found the PlanarityFilter transformer, which was really fast, but in my case I had to use a tolerance in the SurfaceOnSurfaceOverlayer, and because of this the IFMEFaces wouldn't always be exactly planar. Therefore there I chose a quick and dirty solution to first with also a slight tolerance, and then for all NonPlanar features (slightly 'bent' IFMEFaces and/or IFMECompositeSurfaces), I used a GeometryPartExtractor to extract all IFMEFace portions of the features.

 

I was wondering if others have some ideas on how to efficiently filter features with an IFMECompositeSurface geometry from those with an IFMEFace geometry?

Besides the discussed two methods, I also thought about extracting the geometry an attribute in FME XML encoding, and then use an XMLXQueryExtractor to extract the name of the top root geometry element. But also here executing this XMLXQueryExtractor turned out to be pretty slow when compared to executing it once on an XML list attribute.

 

See the below screenshot for an overview (I also attached this workspace to the case)

imageNote, for the indicated speed comparison, I ran with feature caching, but collapsed the bookmarks of the 4 methods first, and then run the entire bookmark, to exclude the speed/impact of feature caching at intermediate steps of the bookmark.

 

As you can see these options are quite elaborate, and I hope that there are other more simple and more efficient ways to achieve the simple sounding goal of filtering features with an IFMECompositeSurface geometry from those with an IFMEFace geometry

 

Curious to hear other peoples thoughts on this.

 

Kind regards,

 

Thijs

icon

Best answer by ebygomm 28 February 2022, 16:39

View original

3 replies

Userlevel 1
Badge +10

Python? 

This should give you number of parts (1 for face, 6 for composite surface in your example) which you could use to set an attribute which you could then filter by

feature.getGeometry().numParts()

 

 

Badge +3

Python? 

This should give you number of parts (1 for face, 6 for composite surface in your example) which you could use to set an attribute which you could then filter by

feature.getGeometry().numParts()

 

 

Hi @ebygomm​ ,

 

That's a great suggestion! That option can also be done without Python, with the PartCounter transformer. That's definitely a very efficient solution for this specific use case.

 

In my head I'm thinking if there could be more general cases to this question. So if there could be similar cases where the general geometry type (those distinguised by the GeometryFilter) would be the same, and also the number of parts the same, but the ~'IFME geometry type' is different. But maybe I should fist see if that actually happens, and also I can of course always use the first or second from my own sample workspace in those cases (even though they are not 'very clean' solutions)

Userlevel 1
Badge +10

Hi @ebygomm​ ,

 

That's a great suggestion! That option can also be done without Python, with the PartCounter transformer. That's definitely a very efficient solution for this specific use case.

 

In my head I'm thinking if there could be more general cases to this question. So if there could be similar cases where the general geometry type (those distinguised by the GeometryFilter) would be the same, and also the number of parts the same, but the ~'IFME geometry type' is different. But maybe I should fist see if that actually happens, and also I can of course always use the first or second from my own sample workspace in those cases (even though they are not 'very clean' solutions)

I'm not sure if there is a more direct way, a get geometry type statement in python returns the same value for both face and composite surface.

But this will give you a description

feature.setAttribute("geometrytype",str(feature.getGeometry()))

image 

Reply