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 def generate_tsne_network(n_points=200, n_clusters=5, n_neighbors=3, n_dims_raw=7, perplexity=30, seed=42): rng = np.random.RandomState(seed) raw_points = rng.randn(n_points, n_dims_raw) labels = KMeans(n_clusters=n_clusters, random_state=seed, n_init=4)\ .fit_predict(raw_points) tree = KDTree(raw_points) _, indices = tree.query(raw_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))) tsne = TSNE(n_components=2, perplexity=perplexity, random_state=seed) points_2d = tsne.fit_transform(raw_points) edges = [] for i, j in edges_idx: x1, y1 = points_2d[i] x2, y2 = points_2d[j] # orthogonal routing mid = (x2, y1) edges.append(((float(x1), float(y1)), (float(mid[0]), float(mid[1])))) edges.append(((float(mid[0]), float(mid[1])), (float(x2), float(y2)))) return edges class FeatureProcessor(object): def __init__(self): pass def input(self, feature: fmeobjects.FMEFeature): lines = generate_tsne_network(n_points=133, n_clusters=5, n_neighbors=3, n_dims_raw=2, perplexity=3, seed=42) # 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)