def get_rotation_matrix(self, x0, y0): theta = pi / 180.0 * self.get_rotation() # translate x0,y0 to origin Torigin = Matrix([[1, 0, -x0], [0, 1, -y0], [0, 0, 1]]) # rotate by theta R = Matrix([[cos(theta), -sin(theta), 0], [sin(theta), cos(theta), 0], [0, 0, 1]]) # translate origin back to x0,y0 Tback = Matrix([[1, 0, x0], [0, 1, y0], [0, 0, 1]]) return Tback * R * Torigin
def polyfit(x, y, N): """ Do a best fit polynomial of order N of y to x. Return value is a vector of polynomial coefficients [pk ... p1 p0]. Eg, for N=2 p2*x0^2 + p1*x0 + p0 = y1 p2*x1^2 + p1*x1 + p0 = y1 p2*x2^2 + p1*x2 + p0 = y2 ..... p2*xk^2 + p1*xk + p0 = yk Method: if X is a the Vandermonde Matrix computed from x (see http://mathworld.wolfram.com/VandermondeMatrix.html), then the polynomial least squares solution is given by the 'p' in X*p = y where X is a len(x) x N+1 matrix, p is a N+1 length vector, and y is a len(x) x 1 vector This equation can be solved as p = (XT*X)^-1 * XT * y where XT is the transpose of X and -1 denotes the inverse. For more info, see http://mathworld.wolfram.com/LeastSquaresFittingPolynomial.html, but note that the k's and n's in the superscripts and subscripts on that page. The linear algebra is correct, however. See also polyval """ x = asarray(x) + 0. y = asarray(y) + 0. y = reshape(y, (len(y), 1)) X = Matrix(vander(x, N + 1)) Xt = Matrix(transpose(X)) c = array(linear_algebra.inverse(Xt * X) * Xt * y) # convert back to array c.shape = (N + 1, ) return c
def _get_layout(self, renderer): # layout the xylocs in display coords as if angle = zero and # then rotate them around self._x, self._y key = self.get_prop_tup() if self.cached.has_key(key): return self.cached[key] horizLayout = [] pad = 2 thisx, thisy = self._transform.xy_tup((self._x, self._y)) width = 0 height = 0 xmin, ymin = thisx, thisy if self.is_math_text(): lines = [self._text] else: lines = self._text.split('\n') whs = [] for line in lines: w, h = renderer.get_text_width_height(line, self._fontproperties, ismath=self.is_math_text()) if not len(line) and not self.is_math_text(): # approx the height of empty line with tall char tmp, h = renderer.get_text_width_height('T', self._fontproperties, ismath=False) whs.append((w, h)) offsety = h + pad horizLayout.append((line, thisx, thisy, w, h)) thisy -= offsety # now translate down by text height, window coords width = max(width, w) ymin = horizLayout[-1][2] ymax = horizLayout[0][2] + horizLayout[0][-1] height = ymax - ymin xmax = xmin + width # get the rotation matrix M = self.get_rotation_matrix(xmin, ymin) # the corners of the unrotated bounding box cornersHoriz = ((xmin, ymin), (xmin, ymax), (xmax, ymax), (xmax, ymin)) offsetLayout = [] # now offset the individual text lines within the box if len(lines) > 1: # do the multiline aligment malign = self._get_multialignment() for line, thisx, thisy, w, h in horizLayout: if malign == 'center': offsetx = width / 2.0 - w / 2.0 elif malign == 'right': offsetx = width - w else: offsetx = 0 thisx += offsetx offsetLayout.append((thisx, thisy)) else: # no additional layout needed offsetLayout = [(thisx, thisy) for line, thisx, thisy, w, h in horizLayout] # now rotate the bbox cornersRotated = [ M * Matrix([[thisx], [thisy], [1]]) for thisx, thisy in cornersHoriz ] txs = [float(v[0][0]) for v in cornersRotated] tys = [float(v[1][0]) for v in cornersRotated] # compute the bounds of the rotated box xmin, xmax = min(txs), max(txs) ymin, ymax = min(tys), max(tys) width = xmax - xmin height = ymax - ymin # Now move the box to the targe position offset the display bbox by alignment halign = self._horizontalalignment valign = self._verticalalignment # compute the text location in display coords and the offsets # necessary to align the bbox with that location tx, ty = self._transform.xy_tup((self._x, self._y)) if halign == 'center': offsetx = tx - (xmin + width / 2.0) elif halign == 'right': offsetx = tx - (xmin + width) else: offsetx = tx - xmin if valign == 'center': offsety = ty - (ymin + height / 2.0) elif valign == 'top': offsety = ty - (ymin + height) else: offsety = ty - ymin xmin += offsetx xmax += offsetx ymin += offsety ymax += offsety bbox = lbwh_to_bbox(xmin, ymin, width, height) # now rotate the positions around the first x,y position xys = [ M * Matrix([[thisx], [thisy], [1]]) for thisx, thisy in offsetLayout ] tx = [float(v[0][0]) + offsetx for v in xys] ty = [float(v[1][0]) + offsety for v in xys] # now inverse transform back to data coords xys = [self._transform.inverse_xy_tup(xy) for xy in zip(tx, ty)] xs, ys = zip(*xys) ret = bbox, zip(lines, whs, xs, ys) self.cached[key] = ret return ret