用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 自动安装 Rising 杀毒软件
Apr 24 Python
python基础教程项目三之万能的XML
Apr 02 Python
django缓存配置的几种方法详解
Jul 16 Python
python 函数内部修改外部变量的方法
Dec 18 Python
Python分析彩票记录并预测中奖号码过程详解
Jul 09 Python
python经典趣味24点游戏程序设计
Jul 26 Python
python函数声明和调用定义及原理详解
Dec 02 Python
python实现将json多行数据传入到mysql中使用
Dec 31 Python
Python实现多线程下载脚本的示例代码
Apr 03 Python
更新升级python和pip版本后不生效的问题解决
Apr 17 Python
pandas中read_csv、rolling、expanding用法详解
Apr 21 Python
Python趣味挑战之用pygame实现简单的金币旋转效果
May 31 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
自己动手做一个SQL解释器
2006/10/09 PHP
以文本方式上传二进制文件的PHP程序
2006/10/09 PHP
通过文字传递创建的图形按钮
2006/10/09 PHP
ThinkPHP基于PHPExcel导入Excel文件的方法
2014/10/15 PHP
php获得网站访问统计信息类Compete API用法实例
2015/04/02 PHP
PHP实现git部署的方法教程
2017/12/19 PHP
php/JS实现的生成随机密码(验证码)功能示例
2019/06/06 PHP
用javascript控制iframe滚动的代码
2007/04/10 Javascript
js操作iframe的一些方法介绍
2013/06/25 Javascript
js中document.write使用过程中的一点疑问解答
2014/03/20 Javascript
jquery实现下拉菜单的二级联动利用json对象从DB取值显示联动
2014/03/27 Javascript
javascript实现对表格元素进行排序操作
2015/11/18 Javascript
Javascript中apply、call、bind的巧妙使用
2016/08/18 Javascript
运用js教你轻松制作html音乐播放器
2020/04/17 Javascript
jquery表单验证实例仿Toast提示效果
2017/03/03 Javascript
在node中如何使用 ES6
2017/04/22 Javascript
JQuery判断radio单选框是否选中并获取值的方法
2019/01/17 jQuery
vue 获取视频时长的实例代码
2019/08/20 Javascript
通过高德地图API获得某条道路上的所有坐标用于描绘道路的方法
2020/08/24 Javascript
vue video和vue-video-player实现视频铺满教程
2020/10/30 Javascript
原生js实现自定义消息提示框
2020/11/19 Javascript
[55:26]DOTA2-DPC中国联赛 正赛 Aster vs LBZS BO3 第一场 2月23日
2021/03/11 DOTA
Python callable()函数用法实例分析
2018/03/17 Python
python pandas库中DataFrame对行和列的操作实例讲解
2018/06/09 Python
详解Django中CBV(Class Base Views)模型源码分析
2019/02/25 Python
深入浅析python3中的unicode和bytes问题
2019/07/03 Python
使用python写一个自动浏览文章的脚本实例
2019/12/05 Python
屏蔽Django admin界面添加按钮的操作
2020/03/11 Python
美国学校校服,儿童和婴儿服装:Cookie’s Kids
2016/10/14 全球购物
德国家具在线:Fashion For Home
2017/03/11 全球购物
家长给老师的道歉信
2014/01/13 职场文书
供货协议书
2014/04/22 职场文书
人事聘任通知
2015/04/21 职场文书
2015年扶贫帮困工作总结
2015/05/20 职场文书
解决pytorch读取自制数据集出现过的问题
2021/05/31 Python
Python之基础函数案例详解
2021/08/30 Python