Question

Replace Attributes by


I have 1 ESRI Shape polygon where each polygon has an ID which represents the object it belongs to. Some polygons belong to one object some belong to multiple objects. Each object is unique.

 

 

Geometry      ID                                                    NEW ID

 

1                   AAAAA                                             AAAAA-BBBBB

 

2                   BBBBB                                            AAAAA-BBBBB

 

3                   CCCCC                                           CCCCC-DDDD-EEEEE

 

4                   DDDDD                                           CCCCC-DDDD-EEEEE

 

5                   EEEEE                                            CCCCC-DDDD-EEEEE

 

6                   AAAAA-BBBBB                                AAAAA-BBBBB

 

7                   CCCCC-DDDDD                             CCCCC-DDDD-EEEEE

 

8                   CCCCC-DDDD-EEEEE                   CCCCC-DDDD-EEEEE

 

....

 

 

I want to substitue the ID of all polygons which IDs are part of the biggest multi-ID.

 

 

This should not affect the geometries, just reassign the attributes. I tried several approaches with ListBasedMerger and StringSearcher but don´t find the right way. Anyone any ideas ?

11 replies

Badge +3
Hi,

 

 

attributesplitter (delimitter "-") can split your ID attribute in a list of ID's.

 

 

With a featuremerger you could test if the  1st in a list, using listindexer index=0, is a match. (1st seems enough for the requirement you set in your example table) 

 

To do that you must enter same data to both inputports of the featuremerger.

 

You will have to set process duplicate to yes and enter a list, this list you must explode on the output.

 

 

 

 

 

 

Hi, thanks for fast feedback.

 

 

That is understood but how to get Nr. 2 BBBBB into AAAAA-BBBBB ?

 

Whta does that ListExplode in the end ?
Userlevel 2
Badge +17
Hi,

 

 

Maybe this workflow works.

 

 

 

Alternatively, the InlineQuerier can be also used.

 

SQL statement example:

 

-----

 

select s.ID as ID, s.NEW_ID as NEW_ID

 

from (select a.ID, b.ID as NEW_ID, Length(b.ID) as Len

 

    from Polygon as a cross join Polygon as b

 

    where b.ID like '%'||a.ID||'%') as s

 

inner join (select c.ID, Max(Length(d.ID)) MaxLen

 

    from Polygon as c cross join Polygon as d

 

    where d.ID like '%'||c.ID||'%' group by c.ID) as t

 

on s.ID = t.ID and s.Len = t.MaxLen

 

-----

 

 

Takashi
Userlevel 2
Badge +17
This workflow is also available, and looks smarter a little.

 

 

Gio's solution works basically but I still face some problems as the IDs are not in sequence. The unconditional merging 1 on 1 explodes with number of objects. This is a basic sample of the raw data (we are talking about 3d roof shapes):

 

 

 

 

After the routine all shapes should show ID "224201-224203-224204". Still working on that...

 

 

https://drive.google.com/file/d/0B4emmhUVx9b-WVl6bHBlc0c3bWc/edit?usp=sharing

 

 

Userlevel 2
Badge +17
In the raw data, there are GEODB_OID values which have common part but don't have inclusion relationships.

 

----------

 

GEODB_OID

 

.....

 

224203-224204

 

224201-224203

 

.....

 

----------

 

 

There wasn't such a condition in your first post. Since the condition is different from the example data, both Gio's approach and my approach don't work for the raw data.

 

I think it's difficult to achieve your purpose with existing transformers only. Probably Python scripting (PythonCaller) would be a quicker solution in this case. For example:

 

-----

 

# Python Excample (not testing enouth)

 

import fmeobjects

 

 

class FeatureProcessor(object):

 

    def __init__(self):

 

        self.ids = []

 

        self.features = []

 

       

 

    def input(self, feature):

 

        s = set(feature.getAttribute('GEODB_OID').split('-'))

 

        self.features.append((feature, s))

 

        self.ids.append(s)

 

        self.updateIDSetList()

 

       

 

    def close(self):

 

        sid = [(s, '-'.join(sorted(list(s)))) for s in self.ids]

 

        for f, t in self.features:

 

            for s, id in sid:

 

                if 0 < len (s & t):

 

                    f.setAttribute('NEW_GEODB_OID', id)

 

                    self.pyoutput(f)

 

                    break

 

                   

 

    def updateIDSetList(self):

 

        n = len(self.ids)

 

        t = []

 

        for i in range(n):

 

            if self.ids[i] == None:

 

                continue

 

            hit = None

 

            for j in range (i + 1, n):

 

                if self.ids[j] == None:

 

                    continue

 

                if 0 < len(self.ids[i] & self.ids[j]):

 

                    hit = self.ids[j]

 

                    self.ids[j] = None

 

                    break

 

            if hit != None:

 

                t.append(self.ids[i] | hit)

 

            else:

 

                t.append(self.ids[i])

 

        self.ids = t

 

        if len(self.ids) != n:

 

            self.updateIDSetList()

 

-----
Userlevel 2
Badge +17
It seems that the required new ID should consist of every ID of spatially contiguous polygons. Is it correct?

 

If so, there is a spatial approach. That is, you can use the Dissolver to collect every ID; use some transformers to create new ID; use the SpatialFilter to transfer the new ID to the original polygons.

 

Just be aware that there was a narrow gap between 224201 polygon and 224201-224203 polygon in the data you uploaded.
Yes - that was my fault in the first description of the problem - I reached a 75% solution with Gios Approach as I built the ID list and compared {0} with {1}, {0} with {2} and so on. Did that up to {9}... Workbench gets full by that. In the shown sample this does not work because 224201 becomes 224201-224203 but does not get the 224203 and 224204 relation. I wil try the python script but haven´t worked with the python caller yet.

 

 

I cannot rely on the spatial relation in the whole dataset (120.000 polygons) but the idea is worth to check as it could help to get these types of objects fixed with an additional approach. Thanks for support so far!
Badge +3
Hi,

 

 

Hi u can do this with transformers. List transformers galore!

 

 

This one assumes all buildings have unique GFK.

 

Zoom in for settings.

 

Badge +3
I forgot; u must at end unconditionally merge the result attribute to the objects (but i think u figured that one out already..;))
Badge +3
Hi,

 

 

I actually managed to build the first rule you posted using transformers.

 

The workspace is a bit big though. (maybe it can be reduced Takashi?)

 

It runs 1.7 seconds for the building u posted.

 

 

I'll post it  to you both.

 

 

Gio

Reply