【问题标题】:Python conversion between coordinates坐标之间的Python转换
【发布时间】:2014-01-22 07:54:01
【问题描述】:

不同坐标系之间有转换函数吗?

例如,Matlab 有[rho,phi] = cart2pol(x,y) 用于从笛卡尔坐标转换为极坐标。似乎它应该是 numpy 或 scipy。

【问题讨论】:

    标签: python coordinate-systems


    【解决方案1】:

    使用 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....)
    • 或者 arr**2 将独立地对所有元素进行平方,接下来是 np.sum(arr,axis=1) 行,最后是 **.5 以将其平方。
    • 然后呢?你用 x,y 做什么?
    【解决方案2】:

    现有答案可以简化:

    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 )
    

    【讨论】:

    • 我喜欢这个,但由于问题以 x 和 y(不是 z)开头,我将添加简单的行 z = x + 1j * y
    • 这是如何工作的? polar2z 返回一个参数!
    • @johnktejik z = polar2z(r,theta) 然后 x = np.real(z)y = np.imag(z) 另外,np.angle() 有一个 deg 选项,它返回度数而不是弧度。如果你想要学位,你可以通过z2polar() 传递它。
    • 这似乎假设z 表示为一个复数。对于其他形式,您必须先转换为复数,然后再应用此函数。
    • np.angle(z) 在内部提取复数 z 的实部和虚部,并在它们上使用 np.arctan2(zimag, zreal)。 @nzh 的回答避免了不必要的转换
    【解决方案3】:

    您可以使用cmath 模块。

    如果将数字转换为复杂格式,那么只需对数字调用 polar 方法就变得更容易了。

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

    【讨论】:

      【解决方案4】:

      如果你在 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)
      

      【讨论】:

        【解决方案5】:

        有一个更好的方法可以编写一个从笛卡尔坐标转换为极坐标的方法;在这里:

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

        【讨论】:

        • 为什么要更好?它不是矢量化的。
        • 好的,然后使用 np.hypot。关键是你永远不应该写 sqrt(x2+y2)。假设存在是有原因的。
        • 来自 KeithB 的评论,return np.hypot(x, y), np.arctan2(y, x)
        • 什么是x,什么是y?我得到了一个弧度和距离的角度。
        • @mLstudent33:显然polar 将笛卡尔(x,y)转换为极坐标(rho theta),如果将(rho,theta)转换为(x,y)的函数,您需要什么,请参阅复杂方法的其他答案或仅使用简单的 cos/sin,如 this answer
        【解决方案6】:

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

        【讨论】:

          【解决方案7】:

          如果您像我一样尝试控制一个接受基于操纵杆值的速度和航向值的机器人,请改用它(它将弧度转换为度数:

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

          【讨论】:

            【解决方案8】:

            以上所有适合我的答案的混合:

            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
            

            【讨论】:

              【解决方案9】:

              总的来说,我会强烈考虑将坐标系隐藏在精心设计的抽象背后。引用鲍勃叔叔和他的书:

              class Point(object)
                  def setCartesian(self, x, y)
                  def setPolar(self, rho, theta)
                  def getX(self)
                  def getY(self)
                  def getRho(self)
                  def setTheta(self)
              

              有了这样的接口,Point 类的任何用户都可以选择方便的表示,不会执行显式转换。所有这些丑陋的正弦、余弦等都将隐藏在一个地方。点类。仅在您应该关心计算机内存中使用哪种表示的地方。

              【讨论】:

              • Python 中不需要 getter 和 setter。只需使用属性。
              • @K.-MichaelAye,我认为他在谈论重载初始化程序并使用方法在后台转换类属性。我没有意识到问题是关于转换引擎盖下的属性。
              猜你喜欢
              • 2019-10-08
              • 1970-01-01
              • 2015-07-07
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2014-08-29
              相关资源
              最近更新 更多