iOS CoreAnimation专题——技巧篇(四)平面向量 - 优雅的绘图指挥家

本文详细介绍了平面向量在iOS开发中的应用,特别是如何利用向量进行绘图。文章涵盖了向量的数据结构、属性、计算方法以及在坐标变换中的角色。通过向量,可以轻松实现平移、旋转等操作,甚至绘制任意正多边形。文章提供了具体的数学公式和实现代码,帮助开发者深入理解并运用向量。
摘要由CSDN通过智能技术生成

平面向量是在二维平面内既有方向(direction)又有大小(magnitude)的量,物理学中也称作矢量,与之相对的是只有大小、没有方向的数量(标量)。

大家可以忽略本章所有出现的代码,因为它们实际上就在这里

那么向量和我们的绘图又有怎样的关系呢?

向量的数据结构

首先我们要搞清楚的是,如何来表示一个向量。

我在这里不会像数学课一样去详细的讲解向量,只会把向量中我们能应用于我们绘图的那些关键的知识点进行讲解。如果大家对向量完全不了解,那么推荐先了解一下平面向量再来阅读这篇文章。

在数学中,向量有多种表示方式,而我们如果想要把向量的数据用于绘图的话,通常会使用向量的坐标表示,即用一个坐标点来表示一个向量。比如我们可以声明一个向量 a⃗  = (2,3),那么实际上向量 a⃗  就表示起点位于原点,终点位于坐标系中(2,3)的向量。

注意由于向量是由方向和大小来决定的,所以一旦两个向量的方向和大小相等,那么这两个向量就是相等的向量。比如起点位于(1,1)终点位于(3,4)的向量和我们上面的向量a就是方向相同,大小相等的向量,它们两个是相等的向量。

而由于我们在绘图中不能保证我们所需要的向量起点一定位于UIKit坐标系下的(0,0)点,所以在设计向量的数据结构的时候,我们必须至少要两个成员:起点和终点。

一旦我们确定了一个向量对象的起点和终点,那么这个向量就一定能确定下来了。

@interface DHVector2D : NSObject

@property (nonatomic) CGPoint startPoint;
@property (nonatomic) CGPoint endPoint;

@end

为了方便使用,我们可以声明一些initializer来灵活的创建向量。


/**
 *  用两个点初始化一个向量
 *
 *  @param start 起始点
 *  @param end   结束点
 *
 *  @return 生成的向量
 */
- (instancetype)initWithStartPoint:(CGPoint)start endPoint:(CGPoint)end;

/**
 *  指定一个角度生成一个单位向量
 *
 *  @param radian 该向量在逆时针方向上到X轴正方向的角度
 *
 *  @return 单位向量
 */
- (instancetype)initAsIdentityVectorWithAngleToXPositiveAxis:(CGFloat)radian;

/**
 *  用一个CGPoint作为坐标表达式初始化一个向量,该向量起点在(0,0)点
 *
 *  @param position 向量坐标表达式
 *
 *  @return 生成的向量
 */
- (instancetype)initWithCoordinateExpression:(CGPoint)position;

/**
 *  相当于复制一个向量
 *
 *  @param vector 要复制的向量
 *
 *  @return 生成的向量
 */
+ (instancetype)vectorWithVector:(DHVector2D *)vector;

那么这些方法的实现如下:

- (instancetype)initWithStartPoint:(CGPoint)start endPoint:(CGPoint)end
{
    self = [super init];
    _startPoint = start;
    _endPoint = end;
    return self;
}

- (instancetype)initWithCoordinateExpression:(CGPoint)position
{
    self = [self initWithStartPoint:CGPointZero endPoint:position];

    return self;
}

+ (instancetype)vectorWithVector:(DHVector2D *)vector
{
    DHVector2D * aVector = [[DHVector2D alloc] initWithStartPoint:vector.startPoint endPoint:vector.endPoint];

    return aVector;
}

- (NSString *)description
{
    return [NSString stringWithFormat:@"start : %@, end: %@, coordinate: %@",NSStringFromCGPoint(self.startPoint),NSStringFromCGPoint(self.endPoint),NSStringFromCGPoint([self coordinateExpression])];
}

而initAsIdentityVectorWithAngleToXPositiveAxis方法初始化的向量涉及到了旋转操作,我们将在后面来实现。

除了我们制定一些参数初始化的向量以外,我们还可以直接生成一些特殊的向量:

@interface DHVector2D (SpecialVectors)

/**
 *  x轴正方向的单位向量
 *
 *  @return x轴正方向的单位向量
 */
+ (DHVector2D *)xPositiveIdentityVector;

/**
 *  x轴负方向的单位向量
 *
 *  @return x轴负方向的单位向量
 */
+ (DHVector2D *)xNegativeIdentityVector;

/**
 *  y轴正方向的单位向量
 *
 *  @return y轴正方向的单位向量
 */
+ (DHVector2D *)yPositiveIdentityVector;

/**
 *  y轴负方向的单位向量
 *
 *  @return y轴负方向的单位向量
 */
+ (DHVector2D *)yNegativeIdentityVector;

/**
 *  零向量
 *
 *  @return 零向量
 */
+ (DHVector2D *)zeroVector;

@end

实现如下:

@implementation DHVector2D (SpecialVectors)

#define IDENTITY_LENGTH 1

#pragma mark - 特殊向量

+ (DHVector2D *)xPositiveIdentityVector
{
    DHVector2D * vector = [[DHVector2D alloc] initWithCoordinateExpression:CGPointMake(IDENTITY_LENGTH, 0)];
    return vector;
}

+ (DHVector2D *)xNegativeIdentityVector
{
    DHVector2D * vector = [[DHVector2D alloc] initWithCoordinateExpression:CGPointMake(-IDENTITY_LENGTH, 0)];
    return vector;
}

+ (DHVector2D *)yPositiveIdentityVector
{
    DHVector2D * vector = [[DHVector2D alloc] initWithCoordinateExpression:CGPointMake(0, IDENTITY_LENGTH)];
    return vector;
}

+ (DHVector2D *)yNegativeIdentityVector
{
    DHVector2D * vector = [[DHVector2D alloc] initWithCoordinateExpression:CGPointMake(0, -IDENTITY_LENGTH)];
    return vector;
}

+ (DHVector2D *)zeroVector
{
    DHVector2D * vector = [[DHVector2D alloc] initWithCoordinateExpression:CGPointZero];

    return vector;
}

@end

向量的属性

向量拥有许多直接计算的属性,比如向量的长度,与另一个向量的夹角等,我们将这些属性定义为实例方法供外部直接调用。

向量的坐标表达式

即向量的标准表达式,也就是我们在上一部分讲到的使用一个坐标点来表示一个向量,该表达式是以起点为原点,取终点的值来表示一个向量。那么任意向量的坐标表达式应该如何来实现呢?实际上非常简单,就是找一个起始点在原点的向量 a⃗  ,使它等于原向量(方向和大小与原向量相同),那么向量 a⃗  的终点就是原向量的坐标表达式。这一段描述是用来方便大家理解坐标表达式的,而我们通常在计算的时候直接可以套用公式:

对于一个向量 a⃗  ,起始点为 (x1,y1) ,终止点为 (x2,y2) ,那么它的坐标表达式就是:

a⃗ =(x2x1,y2y1)

向量相等

若两个向量的坐标表达式一样,那么它们就是相等的向量。

向量的长度

向量的长度又叫做向量的模,有时候我们需要直接计算一个向量的长度,而我们所知的信息只有向量的起始点和终止点的坐标,实际上在高中数学的解析几何中大量使用这个公式,向量长度的计算就是一个勾股定理的计算。

对于一个向量 a⃗  ,起始点为 (x1,y1) ,终止点为 (x2,y2) ,把向量的长度看做一个直角三角形的斜边,那么两条直角边的长度就分别是 |x2x1| |y2y1| (绝对值符号应该认识吧),然后使用勾股定理计算出斜边长度也就是向量的模:

|a⃗ |=(x2x1)2+(y2y1)2

由于取了平方,所以能保证值为正数,可以去掉绝对值。

若该向量使用坐标表达式表示,即:

a⃗ =(x,y)

那么它的起始点为(0,0),则该向量的模为:

|a⃗ |=(x0)2+(y0)2=x2+y2

这就明显是一个勾股定理了。

向量的夹角

向量的夹角表示的是两个向量的起始点相同时所形成的弧度小于π的角的大小,通常我们会使用它们的坐标表达式来计算夹角(因为使用坐标表达式的时候这两个向量的起始点都是原点,满足计算夹角的条件)。

在这里我们直接套用向量的公式,实际上向量夹角的计算公式来源于向量点积(内积)的几何意义,关于点积,我们在下面会作讲解。

若有两个向量 a⃗ =(x1,y1)

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值