用python拟合等角螺线的实现示例


Posted in Python onDecember 27, 2019

人类很早就注意到飞蛾扑火这一奇怪的现象,并且自作主张地赋予了飞蛾扑火很多含义,引申出为了理想和追求义无反顾、不畏牺牲的精神。但是,这种引申和比喻,征求过飞蛾的意见吗?

后来,生物学家又提出来昆虫趋光性这一假说来解释飞蛾扑火。不过,这个假说似乎也不成立。如果昆虫真的追逐光明,估计地球上早就没有昆虫了——它们应该齐刷刷整体移民到太阳或月亮上去了。

仔细观察飞蛾扑火,就会发现,昆虫们并不是笔直地飞向光源,而是绕着光源飞行,同时越来越接近光源,最终酿成了“惨案”。这一行为被解释成“失误”似乎更合理一点。既然火烛危险,那么飞蛾为什么要绕着火烛飞行呢?

最新的解释是,飞蛾在夜晚飞行时是依据月光和星光作为参照物进行导航的。星星和月亮离我们非常远,光到了地面上可以看成平行光,当飞蛾的飞行路径保持与光线方向成恒定夹角时,飞蛾就变成了直线飞行,如下图所示。

用python拟合等角螺线的实现示例

然而,当飞蛾遇到了火烛等危险光源时,还是按照以前的飞行方式,路径保持与光线方向成恒定夹角,以为依旧能飞成一条直线,结果悲剧了。此时它的飞行轨迹并不是一条直线,而是一条等角螺旋线,如下图所示。

用python拟合等角螺线的实现示例

可怜的飞蛾!亿万年进化出来的精准导航,在人工光源的干扰下竟如此不堪。

螺线及等角螺线

螺线家族很庞大,比如,阿基米德螺线、费马螺线、等角螺线、双曲螺线、连锁螺线、斐波那契螺线、欧拉螺线等等。等角螺线,又叫对数螺线,螺线家族的一员。

早在2000多年以前,古希腊数学家阿基米德就对螺旋线进行了研究。公元1638年,著名数学家笛卡尔首先描述了对数螺旋线(等角螺旋线),并列出了螺旋线的解析式。这种螺旋线有很多特点,其中最突出的一点就是它的形状,无论你把它放大或缩小它都不会有任何的改变。就像我们不能把角放大或缩小一样。

用python拟合等角螺线的实现示例

用极坐标分析法分析飞蛾扑火的飞行轨迹,可知,轨迹线上任意一点的切线与该点与原点的连线之间的夹角是固定的,这就是等角螺线得名的由来。因为分析过程使用了对数,所以等角螺线又叫对数螺线。我不太会用LaTeX写数学公式,所以就用 python 的方法写出螺线方程。其中,fixed 表示螺线固定角,大于 pi/2 则为顺时针螺线,小于 pi/2 则为逆时针螺线。theta 表示旋转弧度,r 表示距离中心点距离。

r = fixed*np.exp(theta/np.tan(fixed))

等角螺线在生活中也经常见到,比如,鹦鹉螺的花纹、玫瑰花瓣的排列,星系的悬臂,低气压云图等。

用python拟合等角螺线的实现示例

绘制等角螺线

给定中心点和固定角,一个等角螺线就被唯一地确定了。这个螺线可以绕很多圈,可以填满整个宇宙。但很多时候,我们往往只需要观察螺线上的一小部分,这时候就需要两个参数来约定:一个叫作 circle,表示你希望看到多少圈螺线,一个叫作 phase,表示螺线的可见部分向内(顺时针)或向外(逆时针螺线)旋转多少圈。

这是使用 matplotlib 绘制等角螺线的函数,其中固定角参数 fixed 做了一点处理:以度(°)为单位,以零为中心,大于零则为顺时针螺线,小于零则为逆时针螺线

import numpy as np
import matplotlib.pyplot as plt

from pylab import mpl
mpl.rcParams['font.sans-serif'] = ['FangSong']
mpl.rcParams['axes.unicode_minus'] = False

def plotSpiral(core, fixed, phase=0, circle=4):
  """绘制等角螺线
  core		- 等角螺线的中心坐标,tuple类型
  fixed    - 等角螺线的固定角度,单位:度(°)。fixed大于零则为顺时针螺线,小于零则为逆时针螺线
  phase    - 初始相位,单位:圈(360°)。对顺时针螺线,该数值越大,螺线越大,对逆时针螺线则相反
  circle   - 螺线可见部分的圈数,单位:圈(360°)
  """
  
  plt.axis("equal")
  plt.plot([core[0]], [core[1]], c='red', marker='+', markersize=10)
  
  fixed_rad = np.radians(90 + fixed)
  theta = np.linspace(0, circle*2*np.pi, 361) + phase*2*np.pi
  r = fixed_rad*np.exp(theta/np.tan(fixed_rad))
  x = r*np.cos(theta) + core[0]
  y = r*np.sin(theta) - core[1]
  plt.plot(x, y, c='blue')
  
  plt.show()

下图展示了逆时针等角螺线各个参数的意义:

用python拟合等角螺线的实现示例

下图展示了顺时针等角螺线各个参数的意义:

用python拟合等角螺线的实现示例

拟合等角螺线

在台风定位时,需要手动确定台风中心位置,并标识出台风螺线轨迹上的部分点,然后逆合出螺线方程。如下图所示,蓝色十字为台风中心点,5个黄色圆点是手工标注的台风螺线轨迹上的点。

用python拟合等角螺线的实现示例

以下为拟合函数

import numpy as np
from scipy import optimize

def fit_spiral(core, dots):
  """拟合等角螺线,返回定角fixed,初始相位phase"""
  
  fixed_ccw = 0.445*np.pi
  fixed_cw = 0.555*np.pi
  
  # 将dots拆分成x_list和y_list
  x_list, y_list = list(), list()
  for x, y in dots:
    x_list.append(x-core[0])
    y_list.append(y-core[1])
  
  # 计算距离
  x = np.array(x_list)
  y = np.array(y_list)
  r = np.hypot(x,y)
  
  # 按照距离排序
  sort_mask = np.argsort(r)
  x = x[sort_mask]
  y = y[sort_mask]
  r = r[sort_mask]
  
  # 计算角度
  theta = np.arctan(y/x)
  theta[x<0] += np.pi
  
  # 确定顺序(CW-顺时针,CCW-逆时针)
  d = np.diff(theta)
  print(d)
  ccw = d[d>0].size > d[d<0].size
  print('ccw=',ccw)
  
  # 调整角度为升序(CCW)或降序(CW)
  if ccw:
    for i in range(1, theta.size):
      while theta[i] < theta[i-1]:
        theta[i] += 2*np.pi
      
      dtheta = theta[i] - theta[i-1]
      while r[i]/r[i-1] > 1.8*np.exp(dtheta/np.tan(fixed_ccw)):
        theta[i] += 2*np.pi
        dtheta = theta[i] - theta[i-1]
  else:
    for i in range(theta.size-1)[::-1]:
      while theta[i] < theta[i+1]:
        theta[i] += 2*np.pi
      
      dtheta = theta[i+1] - theta[i]
      while r[i+1]/r[i] > 1.8*np.exp(dtheta/np.tan(fixed_cw)):
        theta[i] += 2*np.pi
        dtheta = theta[i+1] - theta[i]
  
  # 定义拟合函数
  def fmax(theta, fixed, phase):
    fixed = np.radians(90 + fixed)
    return fixed*np.exp((theta+phase*2*np.pi)/np.tan(fixed))
  
  try: 
    fita, fitb = optimize.curve_fit(fmax, theta, r, [2-int(ccw), 0], maxfev=10000)
    return fita
  except:
    return None

core = (530, 496)
dots = [(467,538), (448,675), (522,484), (513,451), (811,519)]
result = fit_spiral(core, dots)
if isinstance(result, np.ndarray):
  plotSpiral(core, result[0], phase=result[1], circle=4)
else:
  print(u'拟合失败')

拟合效果如下图:

用python拟合等角螺线的实现示例

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python将多个文本文件合并为一个文本的代码(便于搜索)
Mar 13 Python
python3音乐播放器简单实现代码
Apr 20 Python
基于Python 的进程管理工具supervisor使用指南
Sep 18 Python
tensorflow实现对图片的读取的示例代码
Feb 12 Python
Python实现的生产者、消费者问题完整实例
May 30 Python
python中plot实现即时数据动态显示方法
Jun 22 Python
OpenCV图像颜色反转算法详解
May 13 Python
Pyqt5实现英文学习词典
Jun 24 Python
Pandas之Dropna滤除缺失数据的实现方法
Jun 25 Python
一行Python代码制作动态二维码的实现
Sep 09 Python
python分别打包出32位和64位应用程序
Feb 18 Python
Python实现EM算法实例代码
Oct 04 Python
PyTorch 对应点相乘、矩阵相乘实例
Dec 27 #Python
pytorch中tensor.expand()和tensor.expand_as()函数详解
Dec 27 #Python
python装饰器相当于函数的调用方式
Dec 27 #Python
Python 实现数组相减示例
Dec 27 #Python
Pandas 解决dataframe的一列进行向下顺移问题
Dec 27 #Python
Pandas实现DataFrame按行求百分数(比例数)
Dec 27 #Python
pandas的相关系数与协方差实例
Dec 27 #Python
You might like
探讨:如何使用PHP实现计算两个日期间隔的年、月、周、日数
2013/06/13 PHP
php之Memcache学习笔记
2013/06/17 PHP
分享下PHP register_globals 值为on与off的理解
2013/09/26 PHP
PHP、Java des加密解密实例
2015/04/27 PHP
PHP使用xpath解析XML的方法详解
2017/05/20 PHP
TP5框架安全机制实例分析
2020/04/05 PHP
input 输入框内的输入事件详细分析
2010/03/17 Javascript
Extjs实现进度条的两种便捷方式
2013/09/26 Javascript
用js通过url传参把数据从一个页面传到另一个页面
2014/09/01 Javascript
jQuery实现TAB风格的全国省份城市滑动切换效果代码
2015/08/24 Javascript
js下载文件并修改文件名
2017/05/08 Javascript
jQuery实现滚动效果
2017/11/17 jQuery
简单了解JavaScript arguement原理及作用
2020/05/28 Javascript
在vue项目中 实现定义全局变量 全局函数操作
2020/10/26 Javascript
Python轻量级ORM框架Peewee访问sqlite数据库的方法详解
2017/07/20 Python
Python建立Map写Excel表实例解析
2018/01/17 Python
python筛选出两个文件中重复行的方法
2018/05/31 Python
对python中数据集划分函数StratifiedShuffleSplit的使用详解
2018/12/11 Python
python pandas库的安装和创建
2019/01/10 Python
Django如何简单快速实现PUT、DELETE方法
2019/07/24 Python
解决python中的幂函数、指数函数问题
2019/11/25 Python
python小项目之五子棋游戏
2019/12/26 Python
容易被忽略的Python内置类型
2020/09/03 Python
详解css3自定义滚动条样式写法
2017/12/25 HTML / CSS
HTML 5 标签、属性、事件及浏览器兼容性速查表 附打包下载
2012/10/20 HTML / CSS
linux面试题参考答案(7)
2012/10/29 面试题
运动会入场词60字
2014/02/15 职场文书
创建市级文明单位实施方案
2014/03/01 职场文书
代理协议书
2014/04/22 职场文书
行风评议整改报告
2014/11/06 职场文书
2014年党小组工作总结
2014/12/20 职场文书
思想政治表现评语
2015/01/04 职场文书
Nginx反向代理及负载均衡如何实现(基于linux)
2021/03/31 Servers
如何将JavaScript将数组转为树形结构
2021/06/02 Javascript
Spring Bean的实例化之属性注入源码剖析过程
2021/06/13 Java/Android
草系十大最强宝可梦,纸片人上榜,榜首大家最熟悉
2022/03/18 日漫