@@ -1978,3 +1978,30 @@ def bbox(**kw):
19781978 return xs .min (), xs .max (), ys .min (), ys .max ()
19791979
19801980 assert bbox () == bbox (outline_width = 1.0 , outline_alpha = 1.0 , outline_color = "black" )
1981+
1982+
1983+ def test_scale_geometries_matches_affinity_scale ():
1984+ # The vectorised datashader polygon scale must equal shapely.affinity.scale's default
1985+ # (bounding-box-centre) origin, including for asymmetric shapes, multipolygons and holes.
1986+ import shapely
1987+ from shapely import affinity
1988+
1989+ from spatialdata_plot .pl ._geometry import _scale_geometries
1990+
1991+ rng = np .random .default_rng (0 )
1992+ geoms = []
1993+ for cx , cy in rng .random ((50 , 2 )) * 100 :
1994+ # asymmetric exterior (bbox-centre != centroid) with a hole
1995+ geoms .append (
1996+ Polygon (
1997+ [(cx , cy ), (cx + 6 , cy + 1 ), (cx + 5 , cy + 4 ), (cx + 1 , cy + 3 )],
1998+ [[(cx + 2 , cy + 2 ), (cx + 3 , cy + 2 ), (cx + 3 , cy + 3 ), (cx + 2 , cy + 3 )][::- 1 ]],
1999+ )
2000+ )
2001+ geoms .append (MultiPolygon ([geoms [0 ], affinity .translate (geoms [1 ], 10 , 10 )])) # multi-part
2002+ arr = np .array (geoms , dtype = object )
2003+
2004+ for scale in (0.6 , 2.0 ):
2005+ expected = np .array ([affinity .scale (g , xfact = scale , yfact = scale ) for g in geoms ], dtype = object )
2006+ result = _scale_geometries (arr , scale )
2007+ assert all (shapely .equals_exact (a , b , tolerance = 1e-9 ) for a , b in zip (expected , result , strict = True ))
0 commit comments