程序员文章、书籍推荐和程序员创业信息与资源分享平台

网站首页 > 技术文章 正文

3.Python趣味数学笔记:二维向量_python设计一个二维向量类

hfteth 2025-02-17 12:20:02 技术文章 10 ℃

我们在上一章了解了线性代数的发展历程,解析几何学中的“数形结合”,提供了一个很好的思维工具。本章我们将使用“数形结合”的思想,更加直观地认识二维向量。

我们生活中经常会使用到“维度”这个词,不同场景下所表达的具体含义有所不同:

1)“对这个问题从三个维度作出解释”,这里的“维度”侧重于描述思维角度;

2)“FC射击类游戏《魂斗罗》是2D游戏,射击类手游《和平精英》是3D游戏”,这里的“维度”侧重于描述物体所处空间位置;

3)“某气象台为了监测天气变化,需要记录温度、湿度等多维度的天气数据。”,这里的“维度”侧重于描述天气相关属性。

透过不同场景下“维度”的具体含义,其所表达的抽象含义为:事物“有联系”的抽象概念数量。我们之所以选择从不同“维度”关注同一个事物,目的在于期望了解事物本身和跟其他事物所存在的联系。

一页纸或者手机、平板和电脑屏幕上的图像,这些是二维(2D)对象,具有长和宽;我们生活在三维世界,加上时间这一维度,可以描述某一事件发生的时间和地点。三维(3D)对象不仅有长度和宽度,还有高度。物理世界的仿真模拟、游戏和动画会把三维数据映射到二维屏幕上。

我们天生对于处理二维或者三维空间中的数据感到自然,但现实场景下的数据往往具有更多维度。

比如:某购物网站为了分析用户的消费习惯,需要跟踪记录性别、年龄、出生年月、喜欢的商品种类等上百个用户相关属性。

这就需要一个能够处理高维数据的数学工具,即向量数学。二维空间中的点,使用有序数对来表示,而三维空间中点,使用三元数对来表示。以此类推,可以推广到多维空间。我们把向量(vector)看作多维空间中的一个点。

向量不仅可以描述二维或者三维空间,还可以扩展到多维空间。我们先从最简单的二维向量开始,了解二维向量的基本概念。

二维向量

二维向量(two-dimensional vector)可以看作平面上从A点指向B点的有向线段。有向线段的长度表示向量的大小,有向线段的方向表示向量的方向。


可以使用黑体字母a,w,v,F表示向量,也可以使用如下方式表示向量:


为了方便处理和观察,我们会把作为原点,建立坐标系。二维向量可以使用有序对表示:

多个二维向量可以组成有意思的形状。比如:我们使用Python绘制一个正方形。

1.绘制散点图

#定义一组二维向量
two_dim_vectors=[(-2,2),(0,2),(2,2),(2,0),(2,-2),(0,-2),(-2,-2),(-2,0)]
#绘制散点图
draw_objects(Points(two_dim_vectors))

绘制效果图:

2.绘制线段

#定义一组二维向量
two_dim_vectors=[(-2,2),(0,2),(2,2),(2,0),(2,-2),(0,-2),(-2,-2),(-2,0)]
#绘制(-2,2)到(0,2)的线段
start_point=(-2,2)
end_point=(0,2)
draw_objects(Points(two_dim_vectors),Line(start_point,end_point))

绘制效果图:

3.绘制正方形

我们将散点图中的所有点,通过直线连接,可以得到二维平面下的正方形:

#定义一组二维向量
two_dim_vectors=[(-2,2),(0,2),(2,2),(2,0),(2,-2),(0,-2),(-2,-2),(-2,0)]
#绘制正方形
draw_objects(Points(two_dim_vectors),Lines(two_dim_vectors))

绘制效果图:

绘制函数定义

#draw_objects.py
#绘制一个或者多个对象
from math import  ceil, floor
import numpy as np
import matplotlib.pyplot as plt

#颜色定义
blue = 'b'
black = 'k'
red = 'r'
green = 'g'

#定义一组点:二维向量列表和默认颜色
class Points:
      def __init__(self,vectors,color=black):
          self.vectors=vectors
          self.color=color
#定义一条线段:起点 终点和默认颜色
class Line:
      def __init__(self,start_point,end_point,color=black):
          self.start_point=start_point
          self.end_point=end_point
          self.color=color
#绘制多条线段
class Lines:
    def __init__(self, vectors, color=blue):
        self.vectors = vectors
        self.color = color

#收集所有二维向量(a,b)到all_vectors列表[(a,b)]中
def collect_data(*objects):
    all_vectors = []
    for draw_object in objects:
        if type(draw_object) == Points:
            for v in draw_object.vectors:
                 all_vectors.append(v)
        elif  type(draw_object) == Line:
               all_vectors.append(draw_object.start_point)
               all_vectors.append(draw_object.end_point)
        elif type(draw_object) == Lines:
            for v in draw_object.vectors:
                all_vectors.append(v)
        else:
            raise TypeError("type is not defined: {}".format(draw_object))
    return  all_vectors

#绘制数据前的准备
def draw_data_prepare(max_x, max_y, min_x, min_y,origin, axes, grid):
    # 设置坐标范围
    if grid:
        # ceil() 向上取整 ceil(2.3)=3
        # 网格间距
        x_padding = max(ceil(0.05 * (max_x - min_x)), grid[0])
        y_padding = max(ceil(0.05 * (max_y - min_y)), grid[1])
        # floor() 向下取整 floor(2.3)=2
        # 计算x轴范围(left,right)
        x_limit = floor((min_x - x_padding) / grid[0]) * grid[0], ceil((max_x + x_padding) / grid[0]) * grid[0]
        # 计算y轴范围(bottom, top)
        y_limit = floor((min_y - y_padding) / grid[1]) * grid[1], ceil((max_y + y_padding) / grid[1]) * grid[1]
        plt.xlim(x_limit)
        plt.ylim(y_limit)
    # 画出原点
    if origin:
        plt.scatter([0], [0], color='k', marker='x')
    # 展示网格
    if grid:
        # 设置网格刻度
        plt.gca().set_xticks(np.arange(plt.xlim()[0], plt.xlim()[1], grid[0]))
        plt.gca().set_yticks(np.arange(plt.ylim()[0], plt.ylim()[1], grid[1]))
        plt.grid(True)
        plt.gca().set_axisbelow(True)
    # 绘制坐标轴
    if axes:
        plt.gca().axhline(linewidth=2, color='k')
        plt.gca().axvline(linewidth=2, color='k')

"""
绘制一个或者多个对象
objects:绘制对象
origin:是否显示原点
axes:是否显示坐标轴
grid:坐标轴单元刻度
"""
def draw_objects(*objects, origin=True, axes=True, grid=(1,1)):
    #收集数据
    all_vectors=collect_data(*objects)
    #print(all_vectors)
    #使用zip将包含多个元组(a,b)的列表,拆分为(a...)和(b....)两个元组
    #*表示对传入的列表拆包,函数参数带*,会将每个元素重新组装成一个元组
    xs, ys = zip(*all_vectors)
    #print(xs)
    #print(ys)
    #寻找x和y的最小值和最大值
    max_x, max_y, min_x, min_y = max(0, *xs), max(0, *ys), min(0, *xs), min(0, *ys)

    #绘制数据前的准备
    draw_data_prepare(max_x, max_y, min_x, min_y, origin, axes, grid)
    #开始绘制
    for draw_object in objects:
        if type(draw_object)==Points:
            points_x = [vector[0] for vector in draw_object.vectors]
            points_y = [vector[1] for vector in draw_object.vectors]
            #绘制散点图
            plt.scatter(points_x,points_y,color=draw_object.color)
        elif type(draw_object) == Line:
            x1,y1=draw_object.start_point
            x2,y2=draw_object.end_point
            # 绘制单条折线
            plt.plot([x1,x2], [y1,y2], color=object.color)
        elif type(draw_object) == Lines:
            for i in range(0,len(draw_object.vectors)):
                #当前点
                x1, y1 = draw_object.vectors[i]
                #相邻点
                #注意最后一个点(下标):len(list)-1,相邻点:len(list),
                #需要取模len,得到第一个点(下标):0
                x2, y2 = draw_object.vectors[(i+1)%len(draw_object.vectors)]
                # 绘制单条折线
                plt.plot([x1, x2], [y1, y2], color=draw_object.color)
    #展示
    plt.show()

#定义一组二维向量
two_dim_vectors=[(-2,2),(0,2),(2,2),(2,0),(2,-2),(0,-2),(-2,-2),(-2,0)]
#绘制正方形
draw_objects(Points(two_dim_vectors),Lines(two_dim_vectors))

Tags:

最近发表
标签列表