用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 isinstance判断对象类型
Sep 06 Python
python网络编程之数据传输UDP实例分析
May 20 Python
python多进程提取处理大量文本的关键词方法
Jun 05 Python
详解Python 协程的详细用法使用和例子
Jun 15 Python
根据DataFrame某一列的值来选择具体的某一行方法
Jul 03 Python
python跳过第一行快速读取文件内容的实例
Jul 12 Python
python利用Tesseract识别验证码的方法示例
Jan 21 Python
python代理工具mitmproxy使用指南
Jul 04 Python
python标记语句块使用方法总结
Aug 05 Python
python opencv调用笔记本摄像头
Aug 28 Python
python 发送邮件的示例代码(Python2/3都可以直接使用)
Dec 03 Python
关于 Python json中load和loads区别
Nov 07 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学习之字符串比较和查找
2011/04/17 PHP
ThinkPHP简单使用memcache缓存的方法
2016/11/15 PHP
CentOS 上搭建 PHP7 开发测试环境
2017/02/26 PHP
javascript开发中因空格引发的错误
2010/11/08 Javascript
25个优雅的jQuery Tooltip插件推荐
2011/05/25 Javascript
JavaScript常用对象的方法和属性小结
2012/01/24 Javascript
jQuery源码中的chunker 正则过滤符分析
2012/07/31 Javascript
jquery获得keycode的示例代码
2013/12/30 Javascript
jquery 使用简明教程
2014/03/05 Javascript
利用jQuery实现可以编辑的表格
2014/05/26 Javascript
laytpl 精致巧妙的JavaScript模板引擎
2014/08/29 Javascript
用简洁的jQuery方法toggleClass实现隔行换色
2014/10/22 Javascript
推荐4个原生javascript常用的函数
2015/01/12 Javascript
js轮盘抽奖实例分析
2020/04/17 Javascript
基于JavaScript Array数组方法(新手必看篇)
2016/08/20 Javascript
node.js用fs.rename强制重命名或移动文件夹的方法
2017/12/27 Javascript
详解从买域名到使用pm2部署node.js项目全过程
2018/03/07 Javascript
微信小程序 弹窗输入组件的实现解析
2019/08/12 Javascript
Vue开发环境中修改端口号的实现方法
2019/08/15 Javascript
探究数组排序提升Python程序的循环的运行效率的原因
2015/04/01 Python
Windows系统下多版本pip的共存问题详解
2017/10/10 Python
python微信公众号之关注公众号自动回复
2018/10/25 Python
python 将大文件切分为多个小文件的实例
2019/01/14 Python
Django 批量插入数据的实现方法
2020/01/12 Python
对tensorflow中cifar-10文档的Read操作详解
2020/02/10 Python
Django rest framework分页接口实现原理解析
2020/08/21 Python
基于CentOS搭建Python Django环境过程解析
2020/08/24 Python
英国优质鞋类专家:Robinson’s Shoes
2017/12/08 全球购物
奥斯汀独木舟和皮划艇:Austin Canoe & Kayak
2018/05/22 全球购物
俄罗斯品牌服装和鞋子在线商店:BRIONITY
2020/03/26 全球购物
关于迟到的检讨书
2014/01/26 职场文书
尊师重教演讲稿
2014/09/04 职场文书
AJAX学习笔记
2021/05/18 Javascript
单身狗福利?Python爬取某婚恋网征婚数据
2021/06/03 Python
PHP设计模式(观察者模式)
2021/07/07 PHP
Golang获取List列表元素的四种方式
2022/04/20 Golang