FME Geometry, PythonCaller, GenerativeArt

#main_script import fmeobjects import numpy as np from fmeobjects import FMELine, FMEPoint, FMEPolygon import math from sklearn.cluster import KMeans from sklearn.neighbors import KDTree from sklearn.manifold import TSNE from sklearn.cluster import SpectralClustering """ Generate a network using spectral clustering Spectral clustering shines on non-convex shapes where KMeans fails """ def generate_spectral_network(n_points=200, n_clusters=5, n_neighbors=3, seed=42): # output: [((x1,y1), (x2,y2)), ...] connected coordinate pairs rng = np.random.RandomState(seed) angles = rng.uniform(0, 2 * np.pi, n_points) radii = rng.choice([3, 7, 12], size=n_points) noise = rng.randn(n_points, 2) * 0.5 points = np.column_stack([ radii * np.cos(angles), radii * np.sin(angles) ]) + noise spectral = SpectralClustering( n_clusters=n_clusters, affinity="nearest_neighbors", n_neighbors=n_neighbors * 2, random_state=seed, assign_labels="kmeans" ) labels = spectral.fit_predict(points) tree = KDTree(points) _, indices = tree.query(points, k=n_neighbors + 1) edges_idx = set() for i, neighbors in enumerate(indices): for j in neighbors[1:]: edges_idx.add((min(i, j), max(i, j))) edges = [ ( (float(points[i][0]), float(points[i][1])), (float(points[j][0]), float(points[j][1])) ) for i, j in edges_idx ] return edges class FeatureProcessor(object): def __init__(self): pass def input(self, feature: fmeobjects.FMEFeature): lines = generate_spectral_network(n_points=210, n_clusters=5, n_neighbors=7, seed=42) print(lines) # output the star boundary for i,line in enumerate(lines): tri_ring = (list(map(tuple, line))) tri_line = FMELine([tuple(p) for p in tri_ring]) out_feat = fmeobjects.FMEFeature(feature) out_feat.setGeometry(tri_line) self.pyoutput(out_feat)