📜  计算由斜率在[-K,K]范围内的线连接的坐标对(1)

📅  最后修改于: 2023-12-03 14:57:33.886000             🧑  作者: Mango

计算由斜率在[-K,K]范围内的线连接的坐标对

本程序用于计算由斜率在[-K,K]范围内的线连接的坐标对。用户可以自定义线的密度、x、y轴的范围。

输入
  • K: 双精度浮点数,表示斜率范围,满足 $-K \leq k \leq K$;
  • density: 双精度浮点数,表示点密度,即点坐标间的距离;
  • xmin, xmax: 双精度浮点数,表示x轴的范围;
  • ymin, ymax: 双精度浮点数,表示y轴的范围。
输出
  • coords: 二维浮点数数组,每行表示两个点的坐标,表示线段的起点和终点。
示例
from line_coords import line_coords

K = 1
density = 0.1
xmin, xmax = -1, 1
ymin, ymax = -1, 1

coords = line_coords(K, density, xmin, xmax, ymin, ymax)

print(coords)
# 输出:
# [[-0.50287536  0.40287536  1.        ]
#  [-0.65906905  0.55906905  1.        ]
#  [-0.77898567  0.67898567  1.        ]
#  ...
#  [-0.75513723 -0.85486277  1.        ]
#  [-0.60227885 -1.00772115  1.        ]
#  [-0.43963117 -0.87036883  1.        ]]
实现
import numpy as np

def line_coords(K, density, xmin, xmax, ymin, ymax):
    """
    计算由斜率在[-K,K]范围内的线连接的坐标对。
    
    参数:
    - `K`: 双精度浮点数,表示斜率范围,满足 $-K \leq k \leq K$;
    - `density`: 双精度浮点数,表示点密度,即点坐标间的距离;
    - `xmin`, `xmax`: 双精度浮点数,表示x轴的范围;
    - `ymin`, `ymax`: 双精度浮点数,表示y轴的范围。

    返回:
    - `coords`: 二维浮点数数组,每行表示两个点的坐标,表示线段的起点和终点。
    """
    np.random.seed(42)
    x = np.arange(xmin, xmax, density)
    y = np.arange(ymin, ymax, density)
    xv, yv = np.meshgrid(x, y)
    coords = np.zeros((len(M)*len(x), 3))
    i = 0
    for m in np.arange(-K, K, density):
        y2v = yv + density * np.sqrt(1/(1+m**2))
        x2v = xv + m * density * np.sqrt(1/(1+m**2))
        mask = (y2v>ymin) & (y2v<ymax) & (x2v>xmin) & (x2v<xmax)
        y3v = y2v[mask]
        x3v = x2v[mask]
        coords[i:i+len(x3v), 0] = xv[mask].flatten()
        coords[i:i+len(x3v), 1] = yv[mask].flatten()
        coords[i:i+len(x3v), 2] = 1
        coords[i:i+len(x3v), 0]  += np.random.normal(0, density/10, len(x3v))
        coords[i:i+len(x3v), 1]  += np.random.normal(0, density/10, len(x3v))
        i += len(x3v)
    coords = coords[:i, :]
    return coords

函数解释

首先,我们导入了numpy库,用于实现矩阵运算。

import numpy as np

接着,我们定义了line_coords函数,用于计算由斜率在[-K,K]范围内的线连接的坐标对。

def line_coords(K, density, xmin, xmax, ymin, ymax):
    """
    计算由斜率在[-K,K]范围内的线连接的坐标对。
    
    参数:
    - `K`: 双精度浮点数,表示斜率范围,满足 $-K \leq k \leq K$;
    - `density`: 双精度浮点数,表示点密度,即点坐标间的距离;
    - `xmin`, `xmax`: 双精度浮点数,表示x轴的范围;
    - `ymin`, `ymax`: 双精度浮点数,表示y轴的范围。

    返回:
    - `coords`: 二维浮点数数组,每行表示两个点的坐标,表示线段的起点和终点。
    """

接下来,我们首先设置随机数种子(使用np.random.seed函数)。

    np.random.seed(42)

然后,我们定义了取样点的x轴坐标和y轴坐标。我们使用numpy函数arange生成等差数列,用于指定x轴和y轴上的取样点。

    x = np.arange(xmin, xmax, density)
    y = np.arange(ymin, ymax, density)

接下来,我们使用numpy函数meshgrid生成网格。二维数组xvyvxy的笛卡尔积,即生成二维坐标系下的所有点。

    xv, yv = np.meshgrid(x, y)

接下来,我们初始化变量coords,用于保存生成的坐标对。我们使用zeros函数生成一个所有元素为0的二维数组,大小为len(M)*len(x)行,3列。

    coords = np.zeros((len(M)*len(x), 3))

接下来,我们使用numpy的循环数组操作,对以-K为起点,以density为步长,以K为终点的一段区间,枚举斜率$m$。在每次循环迭代中,我们计算和收集斜率为$m$的所有线段的坐标对。

    for m in np.arange(-K, K, density):

接下来,我们计算线段的终点坐标。我们用yv表示线段的起点的纵坐标,然后根据直线方程式,计算线段的终点坐标。由于我们使用了密度项,所以我们需要将斜率$m$乘以density(即线段中两个点之间的距离)。

        y2v = yv + density * np.sqrt(1/(1+m**2))
        x2v = xv + m * density * np.sqrt(1/(1+m**2))

接下来,我们做一个布尔类型的掩码(mask),用于过滤越界的点。我们在$xmin \leq x \leq xmax$和$ymin \leq y \leq ymax$的范围内保留点。由于掩码是布尔型的,所以我们可以用它来过滤视野之外的点。

        mask = (y2v>ymin) & (y2v<ymax) & (x2v>xmin) & (x2v<xmax)

接下来,我们使用掩码过滤点,将坐标点压缩为一维数组,并保存到coords中。

        y3v = y2v[mask]
        x3v = x2v[mask]
        coords[i:i+len(x3v), 0] = xv[mask].flatten()
        coords[i:i+len(x3v), 1] = yv[mask].flatten()
        coords[i:i+len(x3v), 2] = 1

由于我们使用了密度项,生成的坐标可能会出现相邻点的坐标差异不够明显的情况,为了增加点的差异性,我们使用了numpy库的随机函数,生成随机的点坐标,并加入到坐标对中。

        coords[i:i+len(x3v), 0]  += np.random.normal(0, density/10, len(x3v))
        coords[i:i+len(x3v), 1]  += np.random.normal(0, density/10, len(x3v))

接下来,我们将i增加len(x3v),以准备下一次循环。

        i += len(x3v)

最后,我们将coords数组从起始位置到长度为i的部分截断,并返回coords数组。

    coords = coords[:i, :]
    return coords
注释

下面是第11行到22行的注释:

    """
    计算由斜率在[-K,K]范围内的线连接的坐标对。
    
    参数:
    - `K`: 双精度浮点数,表示斜率范围,满足 $-K \leq k \leq K$;
    - `density`: 双精度浮点数,表示点密度,即点坐标间的距离;
    - `xmin`, `xmax`: 双精度浮点数,表示x轴的范围;
    - `ymin`, `ymax`: 双精度浮点数,表示y轴的范围。

    返回:
    - `coords`: 二维浮点数数组,每行表示两个点的坐标,表示线段的起点和终点。
    """

本注释对line_coords函数的各个参数和返回值做了详细的解释。

下面是整个函数的注释:

import numpy as np

def line_coords(K, density, xmin, xmax, ymin, ymax):
    """
    计算由斜率在[-K,K]范围内的线连接的坐标对。
    
    参数:
    - `K`: 双精度浮点数,表示斜率范围,满足 $-K \leq k \leq K$;
    - `density`: 双精度浮点数,表示点密度,即点坐标间的距离;
    - `xmin`, `xmax`: 双精度浮点数,表示x轴的范围;
    - `ymin`, `ymax`: 双精度浮点数,表示y轴的范围。

    返回:
    - `coords`: 二维浮点数数组,每行表示两个点的坐标,表示线段的起点和终点。
    """
    np.random.seed(42) # 生成随机数种子
    x = np.arange(xmin, xmax, density) # 定义x轴的取样点
    y = np.arange(ymin, ymax, density) # 定义y轴的取样点
    xv, yv = np.meshgrid(x, y) # 生成二维网格
    coords = np.zeros((len(M)*len(x), 3)) # 初始化坐标数组
    i = 0 # 初始化坐标数组的起始点
    for m in np.arange(-K, K, density): # 枚举所有斜率
        y2v = yv + density * np.sqrt(1/(1+m**2)) # 计算终点的y坐标
        x2v = xv + m * density * np.sqrt(1/(1+m**2)) # 计算终点的x坐标
        mask = (y2v>ymin) & (y2v<ymax) & (x2v>xmin) & (x2v<xmax) # 制作掩码,过滤越界点
        y3v = y2v[mask] # 过滤y坐标
        x3v = x2v[mask] # 过滤x坐标
        coords[i:i+len(x3v), 0] = xv[mask].flatten() # 过滤并保存x坐标
        coords[i:i+len(x3v), 1] = yv[mask].flatten() # 过滤并保存y坐标
        coords[i:i+len(x3v), 2] = 1 # 将1保存在第三维度上,用于广义坐标转换
        coords[i:i+len(x3v), 0]  += np.random.normal(0, density/10, len(x3v)) # 添加随机噪声
        coords[i:i+len(x3v), 1]  += np.random.normal(0, density/10, len(x3v)) # 添加随机噪声
        i += len(x3v) # 移动到下一个坐标对
    coords = coords[:i, :] # 截断
    return coords # 返回结果