Python坐标转换

86

是否有用于不同坐标系之间转换的函数?

例如,Matlab 中有 [rho,phi] = cart2pol(x,y) 可将笛卡尔坐标系转换为极坐标系。看起来应该也可以在 numpy 或 scipy 中找到。

11个回答

136

使用numpy,您可以定义以下内容:

import numpy as np

def cart2pol(x, y):
    rho = np.sqrt(x**2 + y**2)
    phi = np.arctan2(y, x)
    return(rho, phi)

def pol2cart(rho, phi):
    x = rho * np.cos(phi)
    y = rho * np.sin(phi)
    return(x, y)

如果没有单独的x和y,而是在一个numpy数组中,numpy.linalg.norm(arr)可以作为np.sqrt(arr[:, 0]**2....)的替代方案。 - K.-Michael Aye
1
交替使用 arr**2 将独立地对所有元素进行平方,接下来你需要 np.sum(arr,axis=1) 对行求和,最后再使用 **.5 进行平方根运算。 - onaclov2000
然后呢?你要怎么处理x和y? - john k

26
现有的答案可以简化:
from numpy import exp, abs, angle

def polar2z(r,theta):
    return r * exp( 1j * theta )

def z2polar(z):
    return ( abs(z), angle(z) )

甚至更多:

polar2z = lambda r,θ: r * exp( 1j * θ )
z2polar = lambda z: ( abs(z), angle(z) )

请注意,这些也适用于数组!

rS, thetaS = z2polar( [z1,z2,z3] )
zS = polar2z( rS, thetaS )

5
我喜欢这个,但由于问题以x和y(而不是z)开头,我会添加简单的一行代码 z = x + 1j * y - jpobst
1
这是如何工作的?polar2z返回单个参数! - john k
2
@johnktejik z = polar2z(r,theta) 然后 x = np.real(z)y = np.imag(z)此外,np.angle() 有一个 deg 选项,可以返回角度而不是弧度。如果你想要角度,只需将其传递给 z2polar() 即可。 - travc
1
这似乎假定 z 表示为一个复数。对于其他形式,你需要先转换成复数,然后再应用此函数。 - Acccumulation
np.angle(z) 内部提取复数 z 的实部和虚部,并对它们使用 np.arctan2(zimag, zreal)。@nzh 的答案避免了不必要的转换。 - divenex

18

你可以使用cmath模块。

如果数字被转换为复数格式,那么只需在该数字上调用极坐标方法即可变得更加容易。

import cmath
input_num = complex(1, 2) # stored as 1+2j
r, phi = cmath.polar(input_num)

15

如果在Numpy或Scipy中找不到它,这里有一些快速函数和点类:

import math

def rect(r, theta):
    """theta in degrees

    returns tuple; (float, float); (x,y)
    """
    x = r * math.cos(math.radians(theta))
    y = r * math.sin(math.radians(theta))
    return x,y

def polar(x, y):
    """returns r, theta(degrees)
    """
    r = (x ** 2 + y ** 2) ** .5
    theta = math.degrees(math.atan2(y,x))
    return r, theta

class Point(object):
    def __init__(self, x=None, y=None, r=None, theta=None):
        """x and y or r and theta(degrees)
        """
        if x and y:
            self.c_polar(x, y)
        elif r and theta:
            self.c_rect(r, theta)
        else:
            raise ValueError('Must specify x and y or r and theta')
    def c_polar(self, x, y, f = polar):
        self._x = x
        self._y = y
        self._r, self._theta = f(self._x, self._y)
        self._theta_radians = math.radians(self._theta)
    def c_rect(self, r, theta, f = rect):
        """theta in degrees
        """
        self._r = r
        self._theta = theta
        self._theta_radians = math.radians(theta)
        self._x, self._y = f(self._r, self._theta)
    def setx(self, x):
        self.c_polar(x, self._y)
    def getx(self):
        return self._x
    x = property(fget = getx, fset = setx)
    def sety(self, y):
        self.c_polar(self._x, y)
    def gety(self):
        return self._y
    y = property(fget = gety, fset = sety)
    def setxy(self, x, y):
        self.c_polar(x, y)
    def getxy(self):
        return self._x, self._y
    xy = property(fget = getxy, fset = setxy)
    def setr(self, r):
        self.c_rect(r, self._theta)
    def getr(self):
        return self._r
    r = property(fget = getr, fset = setr)
    def settheta(self, theta):
        """theta in degrees
        """
        self.c_rect(self._r, theta)
    def gettheta(self):
        return self._theta
    theta = property(fget = gettheta, fset = settheta)
    def set_r_theta(self, r, theta):
        """theta in degrees
        """
        self.c_rect(r, theta)
    def get_r_theta(self):
        return self._r, self._theta
    r_theta = property(fget = get_r_theta, fset = set_r_theta)
    def __str__(self):
        return '({},{})'.format(self._x, self._y)

12

有一种更好的方法来编写从笛卡尔坐标系转换为极坐标系的方法;以下是它:

import numpy as np
def polar(x, y) -> tuple:
  """returns rho, theta (degrees)"""
  return np.hypot(x, y), np.degrees(np.arctan2(y, x))

为什么应该更好?它没有矢量化。 - enedil
2
好的,那就使用np.hypot。关键是你不应该写sqrt(x2+y2),因为hypot是有原因存在的。 - KeithB
3
根据KeithB的评论,return np.hypot(x, y), np.arctan2(y, x) 可翻译为:返回 np.hypot(x, y)np.arctan2(y, x) - mrtpk
什么是x和y?我被给定了一个以弧度为单位的角度和距离。 - mLstudent33
2
@mLstudent33:显然,polar将笛卡尔坐标系(x,y)转换为极坐标系(rho theta),如果你需要将(rho,theta)转换为(x,y)的函数,请参考其他答案中的复杂方法或者只需使用简单的cos/sin,就像这个答案中所示。 - mins
1
抱歉打扰了。为什么“永远不要写 sqrt(x**2+y**2)”?在我的测试中,sqrt(x**2+y**2)np.hypot(x,y) 快了50%以上。 - Mitchell van Zuylen

5

如果您的坐标以复数形式存储,则可以使用cmath


3
综合以上所有回答,以下翻译适合我:
import numpy as np

def pol2cart(r,theta):
    '''
    Parameters:
    - r: float, vector amplitude
    - theta: float, vector angle
    Returns:
    - x: float, x coord. of vector end
    - y: float, y coord. of vector end
    '''

    z = r * np.exp(1j * theta)
    x, y = z.real, z.imag

    return x, y

def cart2pol(x, y):
    '''
    Parameters:
    - x: float, x coord. of vector end
    - y: float, y coord. of vector end
    Returns:
    - r: float, vector amplitude
    - theta: float, vector angle
    '''

    z = x + y * 1j
    r,theta = np.abs(z), np.angle(z)

    return r,theta

3
如果像我一样,你正在尝试控制一个机器人,它接受一个速度和航向值,基于摇杆的值,请使用以下代码(它会将弧度转换为角度):
def cart2pol(x, y):
    rho = np.sqrt(x**2 + y**2)
    phi = np.arctan2(y, x)
    return(rho, math.degrees(phi))

0
如果您有一个包含 (x,y) 坐标或者 (rho, phi) 坐标的数组,您可以使用 numpy 一次性地对它们进行转换。
这些函数会返回一个已转换坐标的数组。
import numpy as np

def combine2Coord(c1, c2):
    return np.concatenate((c1.reshape(-1, 1), c2.reshape(-1, 1)), axis=1)

def cart2pol(xyArr):
    rho = np.sqrt((xyArr**2).sum(1))
    phi = np.arctan2(xyArr[:,1], xyArr[:,0])
    return combine2Coord(rho, phi)

def pol2cart(rhoPhiArr):
    x = rhoPhiArr[:,0] * np.cos(rhoPhiArr[:,1])
    y = rhoPhiArr[:,0] * np.sin(rhoPhiArr[:,1])
    return combine2Coord(x, y)

0

你关心速度吗?使用cmath,它比numpy快一个数量级。而且它已经包含在任何python 2以上的版本中了!

使用ipython

import cmath, numpy as np

def polar2z(polar):
    rho, phi = polar
    return rho * np.exp( 1j * phi )

def z2polar(z):
    return ( np.abs(z), np.angle(z) )


def cart2polC(xy):
    x, y = xy
    return(cmath.polar(complex(x, y))) # rho, phi

def pol2cartC(polar):
    rho, phi = polar
    z = rho * cmath.exp(1j * phi)
    return z.real, z.imag

def cart2polNP(xy):
    x, y = xy
    rho = np.sqrt(x**2 + y**2)
    phi = np.arctan2(y, x)
    return(rho, phi)

def pol2cartNP(polar):
    rho, phi = polar
    x = rho * np.cos(phi)
    y = rho * np.sin(phi)
    return(x, y)

xy = (100,100)
polar = (100,0)

%timeit cart2polC(xy)
%timeit pol2cartC(polar)

%timeit cart2polNP(xy)
%timeit pol2cartNP(polar)

%timeit z2polar(complex(*xy))
%timeit polar2z(polar)

373 ns ± 4.76 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
337 ns ± 0.976 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
4.3 µs ± 34.2 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
3.41 µs ± 5.78 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
3.4 µs ± 5.4 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
1.39 µs ± 3.86 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接