@@ -81,6 +81,40 @@ def strrepr(x): return repr(x) if isinstance(x, str) else str(x)
81
81
+ ")" )
82
82
83
83
84
+ def matrix_transform (vertices ,mtx ):
85
+ """
86
+ Transforms a vertex or set of vertices with a matrix mtx of
87
+ one dimension higher.
88
+
89
+ Parameters
90
+ ----------
91
+ vertices : n-element array or (m, n) array, with m vertices
92
+ mtx : (n+1, n+1) matrix
93
+ """
94
+ values = np .asanyarray (vertices )
95
+ _ ,input_dims = mtx .shape
96
+ input_dims = input_dims - 1
97
+
98
+ if (len (values .shape )== 1 ):
99
+ # single point
100
+ if (values .shape == (input_dims ,)):
101
+ point = mtx .dot (np .append (values , [1 ]))
102
+ point = point / point [- 1 ]
103
+ return point [:input_dims ]
104
+ raise RuntimeError ("Invalid vertices provided to transform" )
105
+
106
+ # multiple points
107
+ if (len (values .shape )== 2 and values .shape [1 ]== input_dims ):
108
+ points = np .hstack ((values ,np .ones ((values .shape [0 ],1 ))))
109
+ points = np .dot (mtx ,points .T ).T
110
+ last_coords = points [:,- 1 ]
111
+ points = points / last_coords [:,np .newaxis ]
112
+ return points [:, :- 1 ]
113
+
114
+ raise ValueError ("Dimensions of input must match the input dimensions of "
115
+ "the transform" )
116
+
117
+
84
118
class TransformNode :
85
119
"""
86
120
The base class for anything that participates in the transform tree
@@ -1873,34 +1907,12 @@ def to_values(self):
1873
1907
mtx = self .get_matrix ()
1874
1908
return tuple (mtx [:self .input_dims ].swapaxes (0 ,1 ).flat )
1875
1909
1876
- def _affine_transform (self ,vertices ,mtx ):
1877
- """
1878
- Default implementation of affine_transform if a C implementation isn't
1879
- available
1880
- """
1881
- values = np .asanyarray (vertices )
1882
-
1883
- if (len (values .shape )== 1 ):
1884
- # single point
1885
- if (values .shape == (self .input_dims ,)):
1886
- return mtx .dot (np .append (values , [1 ]))[:self .input_dims ]
1887
- raise RuntimeError ("Invalid vertices provided to transform" )
1888
-
1889
- # multiple points
1890
- if (len (values .shape )== 2 and values .shape [1 ]== self .input_dims ):
1891
- homogeneous = np .hstack ((values ,np .ones ((values .shape [0 ],1 ))))
1892
- return np .dot (mtx ,homogeneous .T ).T [:, :- 1 ]
1893
-
1894
- raise ValueError ("Dimensions of input must match the input dimensions of "
1895
- "the transform" )
1896
-
1897
1910
@_api .rename_parameter ("3.8" ,"points" ,"values" )
1898
1911
def transform_affine (self ,values ):
1899
1912
mtx = self .get_matrix ()
1900
1913
1901
1914
# Default to python implementation if C implementation isn't available
1902
- transform_fn = (affine_transform if self .input_dims <= 2
1903
- else self ._affine_transform )
1915
+ transform_fn = (affine_transform if self .input_dims <= 2 else matrix_transform )
1904
1916
1905
1917
if isinstance (values ,np .ma .MaskedArray ):
1906
1918
tpoints = transform_fn (values .data ,mtx )