图形几何变换

在绘图过程中,经常需要对图形进行平移、缩小、放大和旋转等操作。Excel提供了专门的方法来实现图形的几何变换。[大谦Excel,dqexcel点com]

几何变换的基本原理

旋转变换使对象绕x,y或z轴旋转,逆时针旋转时角度为正。如果旋转角度为θ,则下面的矩阵定义绕各轴的旋转。

平移变换相对于当前位置移动对象,用距离tx,ty和tz指定平移。下面的矩阵显示了这些元素在变换矩阵中的位置。

缩放(比例)变换改变对象的大小,指定比例因子sx, sy和sz创建下面的矩阵:

默认变换矩阵是单位矩阵,可以用eye函数创建它。下面是单位矩阵:

图形平移

使用Shape对象的IncrementLeft方法,将该对象所表示的图形进行水平方向的平移。该方法有一个参数,参数的值大于0时图形向右移,值小于0时向左移。

使用Shape对象的IncrementTop方法,将该对象所表示的图形进行垂直方向的平移。该方法有一个参数,参数的值大于0时图形向下移,值小于0时向上移。

下面的例子创建一个添加水滴预设纹理的矩形区域,然后将该区域向右平移70个单位,向下平移50个单位。完整代码见:Samples->ch05 创建新图表->39 平移变换->py.py。

code.python
root=os.getcwd()    #获取当前工作路径
app=xw.App(visible=True,add_book=False)    #创建Excel应用
wb=app.books.open(root+r'/data.xlsx',read_only=False)    #打开数据文件返回工作簿对象
sht=wb.sheets('Sheet1')    #获取指定工作表对象
shp=sht.api.Shapes.AddChart2()    #创建空白图表
shp.Left=20
cht=shp.Chart    #获取图表
cht.ChartType=xw.constants.ChartType.xlXYScatter    #图表类型为散点图
ax1=cht.Axes(1)    #获取横轴
ax2=cht.Axes(2)    #获取纵轴
ax1.MinimumScale=0    #横轴最小值
ax1.MaximumScale=400
ax2.MinimumScale=0    #纵轴最小值
ax2.MaximumScale=300
set_style(cht)    #设置样式
cht.SeriesCollection().NewSeries()    #新建序列
x=shape_x(cht,50)
y=shape_y(cht,250)
w=cht.PlotArea.InsideWidth/(ax1.MaximumScale-ax1.MinimumScale)*200
h=cht.PlotArea.InsideHeight/(ax2.MaximumScale-ax2.MinimumScale)*100
shp2=cht.Shapes.AddShape(1,x,y,w,h)    #矩形区域
shp2.Fill.PresetTextured(5)    #水滴预设纹理
shp2.IncrementLeft(70)    #右移70
shp2.IncrementTop(50)    #下移50

平移前后的图形如图2-41和图2-42所示。

Document Image Document Image

图2-41 平移前的图形 图2-42 平移后的图形

图形旋转

使用Shape对象的IncrementRotation方法实现图形的旋转。该方法绕Z轴旋转指定的角度。有一个参数,表示旋转的角度,以度为单位。为正值时顺时针方向旋转图形,为负值时逆时针方向旋转图形。

下面的例子创建一个添加水滴预设纹理的矩形区域,然后将该区域绕Z轴顺时针方向旋转30度。完整代码见:Samples->ch05 创建新图表->40 旋转变换->py.py。

code.python
#... 省略部分代码
cht.SeriesCollection().NewSeries()    #新建序列
x=shape_x(cht,100)
y=shape_y(cht,200)
w=cht.PlotArea.InsideWidth/(ax1.MaximumScale-ax1.MinimumScale)*200
h=cht.PlotArea.InsideHeight/(ax2.MaximumScale-ax2.MinimumScale)*100
shp2=cht.Shapes.AddShape(1,x,y,w,h)    #矩形区域
shp2.Fill.PresetTextured(5)    #水滴预设纹理
shp2.IncrementRotation(30)   #顺时针方向旋转30度

图2-43为旋转后的矩形区域。

Document Image

图2-43 旋转后的图形

图形缩放

图形缩放又称为比例变换,是将给定的图形按照一定的比例放大或缩小。使用Shape对象的ScaleWidth方法和ScaleHeight方法可以指定水平方向和垂直方向的缩放比例,实现图形的缩放操作。

ScaleWidth方法和ScaleHeight方法都有3个参数,如表2-12所示。

表2-12 ScaleWidth方法和ScaleHeight方法的参数

名 称 必需/可选 数据类型 说 明
Factor 必需 Single 指定图形调整后的宽度与当前或原始宽度的比例
RelativeToOriginalSize 必需 MsoTriState 值为False时,相对于其当前大小进行缩放。 仅当指定的图形是图片或 OLE 对象时,才能将此参数指定为True
Scale 可选 Variant MsoScaleFrom类型的常量之一, 指定缩放图形时, 该图形的哪一部分保持在原有的位置

Scale参数的值为MsoScaleFrom枚举类型常量,表示缩放以后,图形那部分保持原来的位置。该参数的取值如表2-13中所示。

表2-13 Scale参数的取值

名 称 说 明
msoScaleFromBottomRight 2 图形的右下角保持在原有的位置
msoScaleFromMiddle 1 图形的中点保持在原有的位置
msoScaleFromTopLeft 0 图形的左上角保持在原有的位置

下面创建一个添加水滴预设纹理的矩形区域,然后对该区域水平方向缩小为原来宽度的0.75倍,垂直方向放大为原来高度的1.75倍。完整代码见:Samples->ch05 创建新图表->41 缩放变换->py.py。

code.python
#... 省略部分代码
cht.SeriesCollection().NewSeries()    #新建序列
x=shape_x(cht,50)
y=shape_y(cht,250)
w=cht.PlotArea.InsideWidth/(ax1.MaximumScale-ax1.MinimumScale)*200
h=cht.PlotArea.InsideHeight/(ax2.MaximumScale-ax2.MinimumScale)*100
shp2=cht.Shapes.AddShape(1,x,y,w,h)    #矩形区域
shp2.Fill.PresetTextured(5)    #水滴预设纹理
shp2.ScaleWidth(0.75, False)   #宽度*0.75
shp2.ScaleHeight(1.75, False)   #高度*1.75

缩放后的图形如图2-44所示。

Document Image

图2-44 缩放以后的图形

图形翻转

图形的翻转也叫做图形的镜像变换,或对称变换。使用Shape对象的Flip方法实现图形的翻转。该方法是相对于水平对称轴或垂直对称轴作翻转的,它有一个参数,指定是水平翻转还是垂直翻转。水平翻转和垂直翻转对应的取值分别为0和1。

下面的例子创建一个矩形区域,为了便于对比,添加了木质纹理。然后对该区域进行水平翻转和垂直翻转操作。完整代码见:Samples->ch05 创建新图表->42 翻转变换->py.py。

code.python
#... 省略部分代码
cht.SeriesCollection().NewSeries()    #新建序列
x=shape_x(cht,100)
y=shape_y(cht,200)
w=cht.PlotArea.InsideWidth/(ax1.MaximumScale-ax1.MinimumScale)*200
h=cht.PlotArea.InsideHeight/(ax2.MaximumScale-ax2.MinimumScale)*100
shp2=cht.Shapes.AddShape(1,x,y,w,h)    #矩形区域
shp2.Fill.PresetTextured(22)    #木纹预设纹理
shp2.Flip(0)    #水平翻转

翻转前的图形如图2-45所示。图2-46为原图形水平翻转后的图形。

Document Image Document Image

图2-45 原图形 图2-46 水平翻转

图2-47为垂直翻转后的结果,实现代码如下所示。完整代码见:Samples->ch05 创建新图表->43 翻转变换2->py.py。

Document Image

图2-47 垂直翻转

code.python
x=shape_x(cht,100)
y=shape_y(cht,200)
w=cht.PlotArea.InsideWidth/(ax1.MaximumScale-ax1.MinimumScale)*200
h=cht.PlotArea.InsideHeight/(ax2.MaximumScale-ax2.MinimumScale)*100
shp2=cht.Shapes.AddShape(1,x,y,w,h)    #矩形区域
shp2.Fill.PresetTextured(22)    #木纹预设纹理
shp2.Flip(1)    #竖直翻转