Skip to main content
Solved

Python caller issue/ Grouping points into tiles


!

Hi

I am trying to use this python script which would be very helpful for me. I have a huge amount of data from a WFS which needs to be tiled in a good way. @takashi had a very good code, but I can’t get it to work in 2017.10.154 edition (the version I have).

I have a test file with more than 2000 points and I want tiles with 230 points each.

I have python installed on my computer and I am using the python caller.

I get error messages:

” FME Configuration: No destination coordinate system set

PythonFactory failed to load python symbol `FeatureProcessor'

Factory proxy not initialized f_4(PythonFactory): PythonFactory failed to process feature”

Why is that?

Any suggestions?

/Regards, Tobias

Best answer by daveatsafe

Hi @trydlinge,

In your PythonCaller, please change the Class or Function to Process Features to 'NonUniformBoxGenerator'. It is presently set to the default 'FeatureProcessor', but there is no class or function with that name in your script.

View original
Did this help you find an answer to your question?

2 replies

daveatsafe
Safer
Forum|alt.badge.img+19
  • Safer
  • Best Answer
  • February 19, 2018

Hi @trydlinge,

In your PythonCaller, please change the Class or Function to Process Features to 'NonUniformBoxGenerator'. It is presently set to the default 'FeatureProcessor', but there is no class or function with that name in your script.


takashi
Influencer
  • February 20, 2018

The script was created for the old pyfme module (maybe in FME 2013 and earlier), so it may not work in the current FME even if you have modified the parameter setting. This is updated version.

Note: Your sample data contains many duplicate points. In my observation, the maximum number of duplicates was 1330, so this script cannot finish iteration for dividing bounding box if you set  230 (less than 1330) to stopping condition. If you need to separate the duplicate points into groups having 230 or less points, the script would not be useful.

import fmeobjects

class NonUniformBoxGenerator(object):
    def __init__(self):
        self.points = [] # List of (x, y, point feature)
        self.boxId = 0 # Bounding Box ID
        
    def input(self, feature):
        # Extract coordinate and store the point feature.
        coord = feature.getCoordinate(0)
        self.points.append((coord[0], coord[1], feature))
        
    def close(self):
        # Calculate initial extent.
        xmin, ymin, p = self.points[0]
        xmax, ymax = xmin, ymin
        for x, y, p in self.points[1:]:
            if x < xmin:
                xmin = x
            elif xmax < x:
                xmax = x
            if y < ymin:
                ymin = y
            elif ymax < y:
                ymax = y
                
        # Start creating boxes.
        self.createBoundingBox((xmin, ymin, xmax, ymax), self.points)    
    
    # This method will be called recursively to divide box by four,
    # until the number of inside points becomes less than 230.
    def createBoundingBox(self, extent, points):
        xmin, ymin, xmax, ymax = extent
        
        if len(points) < 230:
            # Create a box polygon; output the polygon and inside points.
            # Output features can be classified by the GeometryFilter.
            coords = [(xmin,ymin),(xmax,ymin),(xmax,ymax),(xmin,ymax),(xmin,ymin)]
            boundary = fmeobjects.FMELine(coords)
            box = fmeobjects.FMEFeature()
            box.setGeometry(fmeobjects.FMEPolygon(boundary))
            box.setAttribute('_box_id', self.boxId)
            self.pyoutput(box)
            
            for x, y, p in points:
                p.setAttribute('_box_id', self.boxId)
                self.pyoutput(p)
            self.boxId += 1
            
        else:
            # Calculate extent of divided boxes.
            xc = (xmin + xmax) * 0.5 # Center X
            yc = (ymin + ymax) * 0.5 # Center Y
            extentList = [
                (xmin, ymin, xc, yc), # bottom-left
                (xc, ymin, xmax, yc), # bottom-right
                (xmin, yc, xc, ymax), # top-left
                (xc, yc, xmax, ymax) # top-right
            ]
            
            # Collect inside points for each box.
            pointsList = [[], [], [], []]
            for x, y, p in points:
                if y < yc:
                    if x < xc: # bottom-left
                        pointsList[0].append((x, y, p))
                    else# bottom-right
                        pointsList[1].append((x, y, p))
                else:
                    if x < xc: # top-left
                        pointsList[2].append((x, y, p))
                    else# top-right
                        pointsList[3].append((x, y, p))
            del points # save memory
            
            # Call the method for each box.
            for extent, points in zip(extentList, pointsList):
                self.createBoundingBox(extent, points)

 


Reply


Cookie policy

We use cookies to enhance and personalize your experience. If you accept you agree to our full cookie policy. Learn more about our cookies.

 
Cookie settings