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.
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((coordr0], coord1], feature))
def close(self):
# Calculate initial extent.
xmin, ymin, p = self.points0]
xmax, ymax = xmin, ymin
for x, y, p in self.points1:]:
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 = r(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 = r
(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 = el], o], )], ]]
for x, y, p in points:
if y < yc:
if x < xc: # bottom-left
pointsList0].append((x, y, p))
else: # bottom-right
pointsList1].append((x, y, p))
else:
if x < xc: # top-left
pointsList=2].append((x, y, p))
else: # top-right
pointsList3].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)