翼型轮廓几何图

时间:2014-09-21 11:50:37

标签: python plot geometry curves

我在计算坐标时遇到了一些问题。给出两个列表中的翼型轮廓,具有以下示例性坐标:

示例:

x_Coordinates = [1,   0.9,   0.7,   0.5,   0.3,   0.1, 0.0, ...] 
y_Coordinates = [0, -0.02, -0.06, -0.08, -0.10, -0.05, 0.0, ...]

图1: enter image description here

关于个人资料的唯一已知事项是上面的列表和以下事实:

  • 第一个坐标始终是后缘,在上面的示例中为(x = 1,y = 0)
  • 坐标始终在底部/底部到前缘,在上面的示例中为(0,0)并从那里返回到后缘
  • 该配置文件未规范化,并且可以以旋转的形式存在

现在我想确定

  1. 前沿和
  2. 弧线。
  3. 到目前为止,我一直使用最小的x-coodinate作为前沿。但是,这不会起作用 以下示例性轮廓,因为最小的x坐标位于轮廓的上表面上。

    图2: enter image description here

    有人有想法,我如何轻松计算/确定这些数据?


    修改

    一个完整的样本数组数据

    (1.0, 0.95, 0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.25, 0.2, 0.15, 0.1, 0.075, 0.05, 0.025, 0.0125, 0.005, 0.0, 0.005, 0.0125, 0.025, 0.05, 0.075, 0.1, 0.15, 0.2, 0.25, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 0.95, 1.0)
    (0.00095, 0.00605, 0.01086, 0.01967, 0.02748, 0.03423, 0.03971, 0.04352, 0.04501, 0.04456, 0.04303, 0.04009, 0.03512, 0.0315, 0.02666, 0.01961, 0.0142, 0.0089, 0.0, -0.0089, -0.0142, -0.01961, -0.02666, -0.0315, -0.03512, -0.04009, -0.04303, -0.04456, -0.04501, -0.04352, -0.03971, -0.03423, -0.02748, -0.01967, -0.01086, -0.00605, -0.00095)
    

2 个答案:

答案 0 :(得分:3)

好吧,我用翅膀做了很多年。

我的图像上没有任何偏斜的翅膀数据,我发现最接近的是:

wing

  1. 前沿对于不平凡的翅膀不正确

    找到dx的符号正在翻转并计算

    的点
    dx(i)=x(i)-x(i-1)
    

    然后标记dx为正或负的区域,找到它们之间的中间区域(通常dx==0为该区域)。将边缘点标记为ix1

  2. 弧线

    对于精确几何体,您需要从每侧铸造法线的交叉点,以便:

    • 从大纲点i
    • 开始
    • 施放正常的内翼
    • 搜索对面。
    • 找到点,它正常与相反的法线相交并将两个法线分成相同的距离

    这是可行的但具有疯狂的复杂性

  3. 近似弧线

    不太精确的方式,但速度要快得多:

    1. 从大纲点i
    2. 开始
    3. 在对面找到最接近的点
    4. 计算它们之间的中点并将其存储为不准确的axis0点。对所有点i=(0-ix1)(红线)
    5. 执行此操作
    6. 做同样的事情但从对面的商店开始axis1(深红色)
    7. 完成后,只需查找axis0,axis1
    8. 之间的平均值即可

      这可以使结果与蓝轴折线

      相同

      C ++来源:

          List<double> pnt;   // outline 2D pnts = {x0,y0,x1,y1,x2,y2,...}
          List<double> axis;  // axis line 2D pnts = {x0,y0,x1,y1,x2,y2,...}
          int ix0,ix1;        // edge points
      
      void compute()
          {
          int i,i0,i1;
          double d,dd;
          double *p0,*p1,*p2;
          double x0,x1,y0,y1;
          List<double> axis0,axis1;
      
          // find leading edge point
          ix0=0; ix1=0;
          for (p0=pnt.dat,p1=p0+2,p2=p1+2,i=2;i<pnt.num;i+=2,p0=p1,p1=p2,p2+=2)
           if ((p1[0]-p0[0])*(p2[0]-p1[0])<=0.0) { ix1=i; break; }
          // find axis0: midpoint of i0=(0-ix1) i1=find closest from (ix1,pnt.num)
          for (i0=2,i1=pnt.num-2;i0<ix1-2;i0+=2)
              {
              x0=pnt[i0+0];
              y0=pnt[i0+1];
              for (d=-1.0,i=i1;i>ix1+2;i-=2)
                  {
                  x1=pnt[i+0];
                  y1=pnt[i+1];
                  dd=((x1-x0)*(x1-x0))+((y1-y0)*(y1-y0));
                  if ((d<0.0)||(dd<=d)) { i1=i; d=dd; }
                  }
              if (d>=0.0)
                  {
                  x1=pnt[i1+0];
                  y1=pnt[i1+1];
                  axis0.add(0.5*(x0+x1));
                  axis0.add(0.5*(y0+y1));
                  }
              }
          // find axis1: midpoint of i0=(ix1,pnt.num) i1=find closest from (0,ix1)
          for (i1=2,i0=pnt.num-2;i0>ix1+2;i0-=2)
              {
              x0=pnt[i0+0];
              y0=pnt[i0+1];
              for (d=-1.0,i=i1;i<ix1-2;i+=2)
                  {
                  x1=pnt[i+0];
                  y1=pnt[i+1];
                  dd=((x1-x0)*(x1-x0))+((y1-y0)*(y1-y0));
                  if ((d<0.0)||(dd<=d)) { i1=i; d=dd; }
                  }
              if (d>=0.0)
                  {
                  x1=pnt[i1+0];
                  y1=pnt[i1+1];
                  axis1.add(0.5*(x0+x1));
                  axis1.add(0.5*(y0+y1));
                  }
              }
          // find axis: midpoint of i0=<0-axis0.num) i1=find closest from <0-axis1.num)
          axis.add(pnt[ix0+0]);
          axis.add(pnt[ix0+1]);
          for (i0=0,i1=0;i0<axis0.num;i0+=2)
              {
              x0=axis0[i0+0];
              y0=axis0[i0+1];
              for (d=-1.0,i=i1;i<axis1.num;i+=2)
                  {
                  x1=axis1[i+0];
                  y1=axis1[i+1];
                  dd=((x1-x0)*(x1-x0))+((y1-y0)*(y1-y0));
                  if ((d<0.0)||(dd<=d)) { i1=i; d=dd; }
                  }
              if (d>=0.0)
                  {
                  x1=axis1[i1+0];
                  y1=axis1[i1+1];
                  axis.add(0.5*(x0+x1));
                  axis.add(0.5*(y0+y1));
                  }
              }
          axis.add(pnt[ix1+0]);
          axis.add(pnt[ix1+1]);
          }
      
      • List<double> xxx;只是我的动态列表模板,与double xxx[];
      • 相同
      • xxx.add(5);在列表末尾添加5
      • xxx[7]访问数组元素
      • xxx.num是数组的实际使用大小
      • xxx.reset()清除数组并设置xxx.num = 0

      [edit1]正确的前沿点

      有一个疯狂的想法,在运行中找到边缘点加上一些代码调整,结果对我来说足够好:)所以首先解释一下:

      enter image description here

      轴的算法保持不变,但不是ix1绑定,只使用尚未使用的点...如果没有找到停止,则只计算有效的最近点(在另一侧)(顶部图像的情况) 。从这一点开始,找到距离最后一个轴点的最远点,这是前沿点。

      这种方法具有更准确的输出(axis0,axis1更接近)

      现在是C ++代码:

      void compute()
          {
          int i,i0,i1,ii,n=4;
          double d,dd;
          double x0,x1,y0,y1;
          List<double> axis0,axis1;
          ix0=0; ix1=0;
      
          // find axis0: midpoint of i0=(0-ix1) i1=find closest from (ix1,pnt.num)
          for (i0=0,i1=pnt.num-2;i0+n<i1;i0+=2)
              {
              x0=pnt[i0+0];
              y0=pnt[i0+1];
              i=i1+n; if (i>pnt.num-2) i=pnt.num-2; ii=i1;
              for (d=-1.0;i>i0+n;i-=2)
                  {
                  x1=pnt[i+0];
                  y1=pnt[i+1];
                  dd=((x1-x0)*(x1-x0))+((y1-y0)*(y1-y0));
                  if ((d<0.0)||((dd<=d)&&(dd>1e-10))) { i1=i; d=dd; }
                  if ((d>=0.0)&&(dd>d)) break;
                  }
              if (d>=0.0)
                  {
                  if (i1-i0<=n+2) { i1=ii; break; } // stop if non valid closest point found
                  x1=pnt[i1+0];
                  y1=pnt[i1+1];
                  axis0.add(0.5*(x0+x1));
                  axis0.add(0.5*(y0+y1));
                  }
              }
          // find leading edge point (the farest point from last found axis point)
          x0=axis0[axis0.num-2];
          y0=axis0[axis0.num-1];
          for (d=0.0,i=i0;i<=i1;i+=2)
              {
              x1=pnt[i+0];
              y1=pnt[i+1];
              dd=((x1-x0)*(x1-x0))+((y1-y0)*(y1-y0));
              if (dd>d) { ix1=i; d=dd; }
              }
          axis0.add(pnt[ix1+0]);
          axis0.add(pnt[ix1+1]);
      
          // find axis1: midpoint of i0=(ix1,pnt.num) i1=find closest from (0,ix1)
          for (i1=0,i0=pnt.num-2;i0+n>i1;i0-=2)
              {
              x0=pnt[i0+0];
              y0=pnt[i0+1];
              i=i1-n; if (i<0) i=0; ii=i1;
              for (d=-1.0;i<i0-n;i+=2)
                  {
                  x1=pnt[i+0];
                  y1=pnt[i+1];
                  dd=((x1-x0)*(x1-x0))+((y1-y0)*(y1-y0));
                  if ((d<0.0)||((dd<=d)&&(dd>1e-10))) { i1=i; d=dd; }
                  if ((d>=0.0)&&(dd>d)) break;
                  }
              if (d>=0.0)
                  {
                  if (i0-i1<=n+2) { i1=ii; break; } // stop if non valid closest point found
                  x1=pnt[i1+0];
                  y1=pnt[i1+1];
                  axis1.add(0.5*(x0+x1));
                  axis1.add(0.5*(y0+y1));
                  }
              }
          // find leading edge point (the farest point from last found axis point)
          x0=axis1[axis1.num-2];
          y0=axis1[axis1.num-1];
          for (d=0.0,i=i1;i<=i0;i+=2)
              {
              x1=pnt[i+0];
              y1=pnt[i+1];
              dd=((x1-x0)*(x1-x0))+((y1-y0)*(y1-y0));
              if (dd>d) { ix1=i; d=dd; }
              }
          axis1.add(pnt[ix1+0]);
          axis1.add(pnt[ix1+1]);
      
          // find axis: midpoint of i0=<0-axis0.num) i1=find closest from <0-axis1.num)
          for (i0=0,i1=0;i0<axis0.num;i0+=2)
              {
              x0=axis0[i0+0];
              y0=axis0[i0+1];
              for (d=-1.0,i=i1;i<axis1.num;i+=2)
                  {
                  x1=axis1[i+0];
                  y1=axis1[i+1];
                  dd=((x1-x0)*(x1-x0))+((y1-y0)*(y1-y0));
                  if ((d<0.0)||(dd<=d)) { i1=i; d=dd; }
                  }
              if (d>=0.0)
                  {
                  x1=axis1[i1+0];
                  y1=axis1[i1+1];
                  axis.add(0.5*(x0+x1));
                  axis.add(0.5*(y0+y1));
                  }
              }
          }
      

      常量n=4仅用于安全重叠搜索最近点,它应该是pnt.num的一小部分。有时最近的点是在最后找到的最近点之前,这取决于展位侧面的曲率。太大n会导致速度减慢,如果n>pnt.num/4它也会导致输出无效。

      如果太小,则对于较小的曲率半径将降低精度,该方法取决于足够的点覆盖。如果采用过低的点数对机翼进行采样,则可能导致不准确。源代码是您可以选择的3次几乎相同的事情ix1要记住(从第一次或第二次搜索)它们是相邻点

      测试资料:

      1.000000 0.000000
      0.990000 0.006719
      0.980000 0.013307
      0.970000 0.019757
      0.960000 0.026064
      0.950000 0.032223
      0.940000 0.038228
      0.930000 0.044075
      0.920000 0.049759
      0.910000 0.055276
      0.900000 0.060623
      0.890000 0.065795
      0.880000 0.070790
      0.870000 0.075604
      0.860000 0.080234
      0.850000 0.084678
      0.840000 0.088935
      0.830000 0.093001
      0.820000 0.096876
      0.810000 0.100558
      0.800000 0.104046
      0.790000 0.107339
      0.780000 0.110438
      0.770000 0.113342
      0.760000 0.116051
      0.750000 0.118566
      0.740000 0.120887
      0.730000 0.123016
      0.720000 0.124954
      0.710000 0.126702
      0.700000 0.128262
      0.690000 0.129637
      0.680000 0.130829
      0.670000 0.131839
      0.660000 0.132672
      0.650000 0.133331
      0.640000 0.133818
      0.630000 0.134137
      0.620000 0.134292
      0.610000 0.134287
      0.600000 0.134127
      0.590000 0.133815
      0.580000 0.133356
      0.570000 0.132755
      0.560000 0.132016
      0.550000 0.131146
      0.540000 0.130148
      0.530000 0.129030
      0.520000 0.127795
      0.510000 0.126450
      0.500000 0.125000
      0.490000 0.123452
      0.480000 0.121811
      0.470000 0.120083
      0.460000 0.118275
      0.450000 0.116392
      0.440000 0.114441
      0.430000 0.112429
      0.420000 0.110361
      0.410000 0.108244
      0.400000 0.106085
      0.390000 0.103889
      0.380000 0.101663
      0.370000 0.099414
      0.360000 0.097148
      0.350000 0.094870
      0.340000 0.092589
      0.330000 0.090309
      0.320000 0.088037
      0.310000 0.085779
      0.300000 0.083541
      0.290000 0.081329
      0.280000 0.079149
      0.270000 0.077006
      0.260000 0.074906
      0.250000 0.072855
      0.240000 0.070858
      0.230000 0.068920
      0.220000 0.067047
      0.210000 0.065242
      0.113262 0.047023
      0.110002 0.042718
      0.106385 0.038580
      0.102428 0.034615
      0.098146 0.030832
      0.093556 0.027239
      0.088673 0.023844
      0.083516 0.020652
      0.078101 0.017670
      0.072448 0.014904
      0.066574 0.012361
      0.060499 0.010044
      0.054241 0.007958
      0.047820 0.006108
      0.041256 0.004497
      0.034569 0.003129
      0.027779 0.002005
      0.020907 0.001129
      0.013972 0.000502
      0.006997 0.000126
      0.000000 0.000000
      0.000000 0.000000
      -0.003997 0.000126
      -0.007972 0.000502
      -0.011907 0.001129
      -0.015779 0.002005
      -0.019569 0.003129
      -0.023256 0.004497
      -0.026820 0.006108
      -0.030241 0.007958
      -0.033499 0.010044
      -0.036574 0.012361
      -0.039448 0.014904
      -0.042101 0.017670
      -0.044516 0.020652
      -0.046673 0.023844
      -0.048556 0.027239
      -0.050146 0.030832
      -0.051428 0.034615
      -0.052385 0.038580
      -0.053002 0.042718
      -0.053262 0.047023
      -0.053153 0.051484
      -0.052659 0.056093
      -0.051768 0.060841
      -0.050467 0.065717
      -0.048744 0.070711
      -0.046588 0.075813
      -0.043988 0.081012
      -0.040935 0.086297
      -0.037420 0.091658
      -0.033435 0.097082
      -0.028972 0.102558
      -0.024025 0.108074
      -0.018589 0.113618
      -0.012657 0.119178
      -0.006228 0.124741
      0.000704 0.130295
      0.008139 0.135828
      0.016079 0.141326
      0.024525 0.146777
      0.033475 0.152169
      0.042930 0.157488
      0.052885 0.162722
      0.063339 0.167858
      0.074287 0.172883
      0.085723 0.177784
      0.097643 0.182549
      0.110038 0.187166
      0.122902 0.191621
      0.136226 0.195903
      0.150000 0.200000
      0.164214 0.203899
      0.178856 0.207590
      0.193914 0.211059
      0.209376 0.214297
      0.225227 0.217291
      0.241453 0.220032
      0.258039 0.222509
      0.274968 0.224711
      0.292223 0.226629
      0.309787 0.228254
      0.327641 0.229575
      0.345766 0.230585
      0.364142 0.231274
      0.382749 0.231636
      0.401566 0.231662
      0.420570 0.231345
      0.439740 0.230679
      0.459054 0.229657
      0.478486 0.228274
      0.498015 0.226525
      0.517615 0.224404
      0.537262 0.221908
      0.556930 0.219032
      0.576595 0.215775
      0.596231 0.212132
      0.615811 0.208102
      0.635310 0.203684
      0.654700 0.198876
      0.673956 0.193679
      0.693050 0.188091
      0.711955 0.182115
      0.730644 0.175751
      0.749091 0.169002
      0.767268 0.161869
      0.785149 0.154357
      0.802706 0.146468
      0.819913 0.138207
      0.836742 0.129580
      0.853169 0.120591
      0.869166 0.111246
      0.884707 0.101553
      0.899768 0.091518
      0.914322 0.081149
      0.928345 0.070455
      0.941813 0.059445
      0.954701 0.048128
      0.966987 0.036514
      0.978646 0.024614
      0.989658 0.012439
      1.000000 0.000000
      

答案 1 :(得分:0)

有些过时了,但我仍然看到了这篇文章。

我对前缘圆的解决方案是首先通过机翼坐标插值样条曲线。这给出了机翼的平滑参数表示。然后计算参数曲线的曲率和曲率圆,并取最小的圆。这将定义前缘位置,并在那里返回半径。

下面有两个Python函数(依赖于numpy和scipy包):

def spline(self, x, y, points=200, degree=2, evaluate=False):
    """Interpolate spline through given points

    Args:
        spline (int, optional): Number of points on the spline
        degree (int, optional): Degree of the spline
        evaluate (bool, optional): If True, evaluate spline just at
                                   the coordinates of the knots
    """

    # interpolate B-spline through data points
    # returns knots of control polygon
    # tck ... tuple (t,c,k) containing the vector of knots,
    # the B-spline coefficients, and the degree of the spline.
    # u ... array of the parameters for each knot
    # NOTE: s=0.0 is important as no smoothing should be done on the spline
    # after interpolating it
    tck, u = interpolate.splprep([x, y], s=0.0, k=degree)

    # number of points on interpolated B-spline (parameter t)
    t = np.linspace(0.0, 1.0, points)

    # if True, evaluate spline just at the coordinates of the knots
    if evaluate:
        t = u

    # evaluate B-spline at given parameters
    # der=0: returns point coordinates
    coo = interpolate.splev(t, tck, der=0)

    # evaluate 1st derivative at given parameters
    der1 = interpolate.splev(t, tck, der=1)

    # evaluate 2nd derivative at given parameters
    der2 = interpolate.splev(t, tck, der=2)

    spline_data = [coo, u, t, der1, der2, tck]

    return spline_data

用于计算参数曲线的曲率特性的函数:

    def getCurvature(spline_data):
    """Curvature and radius of curvature of a parametric curve

    der1 is dx/dt and dy/dt at each point
    der2 is d2x/dt2 and d2y/dt2 at each point

    Returns:
        float: Tuple of numpy arrays carrying gradient of the curve,
               the curvature, radiusses of curvature circles and
               curvature circle centers for each point of the curve
    """

    coo = spline_data[0]
    der1 = spline_data[3]
    der2 = spline_data[4]

    xd = der1[0]
    yd = der1[1]
    x2d = der2[0]
    y2d = der2[1]
    n = xd**2 + yd**2
    d = xd*y2d - yd*x2d

    # gradient dy/dx = dy/du / dx/du
    gradient = der1[1] / der1[0]

    # radius of curvature
    R = n**(3./2.) / abs(d)

    # curvature
    C = d / n**(3./2.)

    # coordinates of curvature-circle center points
    xc = coo[0] - R * yd / np.sqrt(n)
    yc = coo[1] + R * xd / np.sqrt(n)

    return [gradient, C, R, xc, yc]

示例: enter image description here

详细信息: enter image description here

请注意,我还在前端使用了样条曲线的细化。相应的算法不在此处(不在主题范围内)。