Python.如何从x,y点和偏移距离列表中获取偏移样条曲线的x,y坐标 [英] Python. How to get the x,y coordinates of a offset spline from a x,y list of points and offset distance

查看:109
本文介绍了Python.如何从x,y点和偏移距离列表中获取偏移样条曲线的x,y坐标的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要对机翼轮廓曲线进行偏移的平行包围,但是我无法弄清楚如何使所有点与主轮廓曲线上的点在所需距离处等距.

I need to make an offset parallel enclosure of an airfoil profile curve, but I cant figure out how to make all the points be equidistant to the points on the primary profile curve at desired distance.

这是我的机翼轮廓示例

这是我最好的方法,不是很好的方法

编辑 @Patrick距离为0.2的解决方案

EDIT @Patrick Solution for distance 0.2

推荐答案

您必须对无穷大/零的斜率进行特殊处理,但是基本方法是使用插值法计算一个点的斜率,然后找到垂直斜率,然后计算该距离处的点.

You'll have to special-case slopes of infinity/zero, but the basic approach is to use interpolation to calculate the slope at a point, and then find the perpendicular slope, and then calculate the point at that distance.

我从此处修改了示例,以添加第二张图.它与您提供的数据文件一起使用,但您可能需要更改其他信封的符号计算.

I have modified the example from here to add a second graph. It works with the data file you provided, but you might need to change the sign calculation for a different envelope.

编辑根据您关于希望信封连续的评论,我在末尾添加了一个俗气的半圆,可以让您真正关闭.本质上,在创建信封时,可以使信封更圆,更凸,效果会更好.另外,您需要重叠开头和结尾,否则就会有空白.

EDIT As per your comments about wanting the envelope to be continuous, I have added a cheesy semicircle at the end that gets really close to doing this for you. Essentially, when creating the envelope, the rounder and more convex you can make it, the better it will work. Also, you need to overlap the beginning and the end, or you'll have a gap.

而且,几乎可以肯定它会变得更高效-无论如何我都不是一个麻木的专家,所以这只是纯Python.

Also, it could almost certainly be made more efficient -- I am not a numpy expert by any means, so this is just pure Python.

def offset(coordinates, distance):
    coordinates = iter(coordinates)
    x1, y1 = coordinates.next()
    z = distance
    points = []
    for x2, y2 in coordinates:
        # tangential slope approximation
        try:
            slope = (y2 - y1) / (x2 - x1)
            # perpendicular slope
            pslope = -1/slope  # (might be 1/slope depending on direction of travel)
        except ZeroDivisionError:
            continue
        mid_x = (x1 + x2) / 2
        mid_y = (y1 + y2) / 2

        sign = ((pslope > 0) == (x1 > x2)) * 2 - 1

        # if z is the distance to your parallel curve,
        # then your delta-x and delta-y calculations are:
        #   z**2 = x**2 + y**2
        #   y = pslope * x
        #   z**2 = x**2 + (pslope * x)**2
        #   z**2 = x**2 + pslope**2 * x**2
        #   z**2 = (1 + pslope**2) * x**2
        #   z**2 / (1 + pslope**2) = x**2
        #   z / (1 + pslope**2)**0.5 = x

        delta_x = sign * z / ((1 + pslope**2)**0.5)
        delta_y = pslope * delta_x

        points.append((mid_x + delta_x, mid_y + delta_y))
        x1, y1 = x2, y2
    return points

def add_semicircle(x_origin, y_origin, radius, num_x = 50):
    points = []
    for index in range(num_x):
        x = radius * index / num_x
        y = (radius ** 2 - x ** 2) ** 0.5
        points.append((x, -y))
    points += [(x, -y) for x, y in reversed(points)]
    return [(x + x_origin, y + y_origin) for x, y in points]

def round_data(data):
    # Add infinitesimal rounding of the envelope
    assert data[-1] == data[0]
    x0, y0 = data[0]
    x1, y1 = data[1]
    xe, ye = data[-2]

    x = x0 - (x0 - x1) * .01
    y = y0 - (y0 - y1) * .01
    yn = (x - xe) / (x0 - xe) * (y0 - ye) + ye
    data[0] = x, y
    data[-1] = x, yn
    data.extend(add_semicircle(x, (y + yn) / 2, abs((y - yn) / 2)))
    del data[-18:]

from pylab import *

with open('ah79100c.dat', 'rb') as f:
    f.next()
    data = [[float(x) for x in line.split()] for line in f if line.strip()]

t = [x[0] for x in data]
s = [x[1] for x in data]


round_data(data)

parallel = offset(data, 0.1)
t2 = [x[0] for x in parallel]
s2 = [x[1] for x in parallel]

plot(t, s, 'g', t2, s2, 'b', lw=1)

title('Wing with envelope')
grid(True)

axes().set_aspect('equal', 'datalim')

savefig("test.png")
show()

这篇关于Python.如何从x,y点和偏移距离列表中获取偏移样条曲线的x,y坐标的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆