예제 #1
0
        def transform_path_non_affine(self, path):
            vertices = path.vertices
            codes = path.codes
            steps = path._interpolation_steps

            x, y = np.array(list(zip(*vertices)))

            if len(vertices) > 1 and not isinstance(steps, int):
                if steps == 'inf_circle':
                    z = x + y * 1j
                    new_vertices = []
                    new_codes = []

                    for i in range(len(z) - 1):
                        az = self._axes._moebius_z(0.5 * (z[i] + z[i+1]))
                        zz = self._axes._moebius_z(z[i:i+2])
                        ax, ay = az.real, az.imag
                        bz, cz = zz
                        bx, cx = zz.real - ax
                        by, cy = zz.imag - ay

                        k = 2 * (bx * cy - by * cx)
                        xm = (cy * (bx ** 2 + by ** 2) - by * (cx ** 2 + cy ** 2)) / k + ax
                        ym = (bx * (cx ** 2 + cy ** 2) - cx * (bx ** 2 + by ** 2)) / k + ay

                        zm = xm + ym * 1j
                        d = 2 * abs(zm - az)

                        ang0 = np.angle(bz - zm, deg=True) % 360
                        ang1 = np.angle(cz - zm, deg=True) % 360

                        reverse = ang0 > ang1
                        if reverse:
                            ang0, ang1 = ang1, ang0

                        arc = Arc([xm, ym], d, d, theta1=ang0, theta2=ang1, transform=self._axes.transMoebius)
                        arc_path = arc.get_patch_transform().transform_path(arc.get_path())

                        if reverse:
                            new_vertices.append(arc_path.vertices[::-1])
                        else:
                            new_vertices.append(arc_path.vertices)

                        new_codes.append(arc_path.codes)

                    new_vertices = np.concatenate(new_vertices)
                    new_codes = np.concatenate(new_codes)
                elif steps == 'center_circle':
                    points = self._axes._get_key("path.default_interpolation")

                    z = self._axes._moebius_z(x + y * 1j)

                    ang0, ang1 = np.angle(z[0:2]) % TWO_PI
                    ccw = (ang1 - ang0) % TWO_PI < np.pi

                    ix, iy = [np.real(z[0])], [np.imag(z[0])]
                    new_codes = [Path.MOVETO]

                    for i in range(len(z) - 1):
                        zz = z[i:i + 2]

                        r0, r1 = np.abs(zz)
                        ang0, ang1 = np.angle(zz) % TWO_PI

                        if ccw:
                            if ang0 > ang1:
                                ang1 += TWO_PI
                        else:
                            if ang1 > ang0:
                                ang0 += TWO_PI

                        r = np.linspace(r0, r1, points)[1:]
                        ang = np.linspace(ang0, ang1, points)[1:]

                        ix += list(np.cos(ang) * r)
                        iy += list(np.sin(ang) * r)

                        new_codes += (points - 1) * [Path.LINETO]

                    new_vertices = list(zip(ix, iy))
                else:
                    raise ValueError("Interpolation must be either an integer, 'inf_circle' or 'center_circle'")
            else:
                if steps == 0:
                    steps = self._axes._get_key("path.default_interpolation")

                ix, iy = ([x[0:1]], [y[0:1]])
                for i in range(len(x) - 1):
                    x0, x1 = x[i:i + 2]
                    y0, y1 = y[i:i + 2]


                    tx = self._axes.real_interp1d([x0, x1], steps)[1:]
                    if abs(x0 - x1) > EPSILON:
                        ty = y0 + (tx - x0) * (y1 - y0) / (x1 - x0)
                    else:
                        ty = self._axes.imag_interp1d([y0, y1], steps)[1:]

                    ix.append(tx)
                    iy.append(ty)

                if codes is not None:
                    new_codes = Path.LINETO * np.ones((len(codes) - 1) * steps + 1)
                    new_codes[0::steps] = codes
                else:
                    new_codes = None

                new_vertices = self.transform_non_affine(list(zip(np.concatenate(ix), np.concatenate(iy))))
                new_codes = codes

            return Path(new_vertices, new_codes, 1)