

dotnet OpenXML SDK 形状几何 Geometry 的计算公式含义
source link: https://lindexi.gitee.io/post/dotnet-OpenXML-SDK-%E5%BD%A2%E7%8A%B6%E5%87%A0%E4%BD%95-Geometry-%E7%9A%84%E8%AE%A1%E7%AE%97%E5%85%AC%E5%BC%8F%E5%90%AB%E4%B9%89.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

本文来告诉大家,在 OpenXML 里面的 Geometry 的如 gdLst 和 ahLst 和 pathLst 等里面参数的公式的参数含义
这部分内容放在 ECMA-376 的 20.1.10.55 章文档里面,本文只是将文档里面的内容翻译一下
在使用 OpenXML 读取形状时,会看到有些形状的定义内容如下
<avLst xmlns="http://schemas.openxmlformats.org/drawingml/2006/main">
<gd name="adj1" fmla="val 50000" />
</avLst>
<gdLst xmlns="http://schemas.openxmlformats.org/drawingml/2006/main">
<gd name="x2" fmla="*/ w adj1 100000" />
<gd name="x1" fmla="+/ l x2 2" />
<gd name="x3" fmla="+/ r x2 2" />
<gd name="y3" fmla="*/ h 3 4" />
</gdLst>
<ahLst xmlns="http://schemas.openxmlformats.org/drawingml/2006/main">
<ahXY gdRefX="adj1" minX="-2147483647" maxX="2147483647">
<pos x="x2" y="vc" />
</ahXY>
</ahLst>
<pathLst xmlns="http://schemas.openxmlformats.org/drawingml/2006/main">
<path fill="none">
<moveTo>
<pt x="l" y="t" />
</moveTo>
<cubicBezTo>
<pt x="x1" y="t" />
<pt x="x2" y="hd4" />
<pt x="x2" y="vc" />
</cubicBezTo>
<cubicBezTo>
<pt x="x2" y="y3" />
<pt x="x3" y="b" />
<pt x="r" y="b" />
</cubicBezTo>
</path>
</pathLst>
如果想要绘制形状的 Path 几何图形,就需要了解此形状里面的 Path 的各个值。如上图,可以看到都采用的是公式的方式进行计算,如 gd 的内容如下
<gd name="adj1" fmla="val 50000" />
以上表示了在 avLst 也就是 AdjustValueList 调整点的参数,以上的 gd 也就是 OpenXML SDK 的 ShapeGuide 类型,这里面的 name 就是 adj1 换句话说就是变量名为 adj1 的值。此 adj1 变量将会在接下来的公式里面使用。而 fmla 就是 ShapeGuide 的 Formula 公式内容,通过如下代码可以获取到公式
private void Foo(ShapeGuide shapeGuide)
{
var formula = shapeGuide.Formula;
}
可以看到以上的 val 50000
字符串就是公式的内容,以上的 val 表示常量,也就是相当于 adj1 = val 50000
也就是 adj1 变量的值就是 50000 的常量
而后续在 gdLst 也就是 ShapeGuideList 类型里面,将会在如下代码使用到 adj1 变量
<gdLst xmlns="http://schemas.openxmlformats.org/drawingml/2006/main">
<gd name="x2" fmla="*/ w adj1 100000" />
<gd name="x1" fmla="+/ l x2 2" />
<gd name="x3" fmla="+/ r x2 2" />
<gd name="y3" fmla="*/ h 3 4" />
</gdLst>
此时在 gd name="x2" fmla="*/ w adj1 100000"
里面通过计算,拿到 x2 变量的值,以上使用了 */
这个符号,其实在 OpenXML 里面的公式用的是逆波兰表达的公式,大概的意思就是 */
运算符要求后续传入三个参数,假定这三个参数是 a b c 三个,那么计算的方法是 (a * b) / c
拿到值
通过不断代入公式可以拿到对应的变量,从而计算出 Path 里面的内容。但以上有一部分公式使用了常量,如下面代码
<moveTo>
<pt x="l" y="t" />
</moveTo>
上面代码的 pt x="l" y="t"
的 l 和 t 都是常量,在文档里面都有定义
下面将告诉大家计算的符号的含义,以及常量的值
表示三分之四的圆,以上的 c 就是 Circle 圆的意思,而 d 就是除法的意思, 相当于 3 * 圆 / 4
的值
以上的圆使用的是 180° 的表示,也就是以上常量的值等于 3cd4 = 3 x 360° / 4 = 270°
通过 Office Open XML 的测量单位 可以拿到角度对应的值是 16200000.0 的常量值。在 OpenXML 里面使用 60000 表示 360° 的圆
以此可以了解到以下的对圆的计算值
3cd4 = 3 x 360° / 4 = 270° = 16200000 Degree
3cd8 = 3 x 360° / 8 = 135° = 8100000 Degree
5cd8 = 5 x 360° / 8 = 225° = 13500000 Degree
7cd8 = 7 x 360° / 8 = 315° = 18900000 Degree
cd2 = 360° / 2 = 180° = 10800000 Degree
cd4 = 360° / 4 = 90° = 5400000 Degree
cd8 = 360° / 8 = 45° = 2700000 Degree
也就是 Shape Top Edge 的含义,表示上边缘,等价于常量 0 的值。原因是 OpenXML 的形状采用的坐标系和 DirectX 的坐标系相同,左上角是 0,0 点,从上到下 y 的值不断加大。从左到右 x 的值加大
也就是 Shape Bottom Edge 的含义,等价于常量 h 的值
这是形状的下边缘,因为形状的上边缘被认为是 0 点,因此下边缘就是形状的高度
关于常量 h 的值,请看下文
也就是 Shape Height 的含义,表示形状的高度,需要通过形状的属性拿到形状的高度才能了解此值
表示的是高度除以 2 的值,以上的 h 是 高度 而 d 表示的是除以,相当于如下公式
*/ h 1.0 2.0
以此可以了解如下的几个常量的计算
hd2 = */ h 1.0 2.0 = height / 2
hd4 = */ h 1.0 4.0 = height / 4
hd5 = */ h 1.0 5.0 = height / 5
hd6 = */ h 1.0 6.0 = height / 6
hd8 = */ h 1.0 8.0 = height / 8
也就是 Vertical Center of Shape 的含义,表示垂直的中心,相当于高度的一半,使用如下公式
*/ h 1.0 2.0
以上代码的 */
公式内容请参阅下文,而 h 表示的是宽度
也就是 Shape Left Edge 的含义,表示左边缘的值,等价于常量 0 的值。原因是 OpenXML 的形状采用的坐标系和 DirectX 的坐标系相同,左上角是 0,0 点,从上到下 y 的值不断加大。从左到右 x 的值加大
也就是 Shape Right Edge 的含义,表示右边缘的值,等价于常量 w 的值。也就是右边缘的值和形状的宽度相同,因为形状的左边缘是 0 的值,因此形状的右边的值就和形状的宽度相同
关于 w 请看下文
也就是 Shape Width 形状宽度的含义,需要通过形状的属性拿到形状的高度才能了解此值
表示形状宽度的一半,以上的 w 是 宽度 而 d 表示的是除以,相当于如下公式
*/ w 1.0 2.0
以此可以了解如下的几个常量的计算
wd2 = */ w 1.0 2.0 = width / 2
wd4 = */ w 1.0 4.0 = width / 4
wd5 = */ w 1.0 5.0 = width / 5
wd6 = */ w 1.0 6.0 = width / 6
wd8 = */ w 1.0 8.0 = width / 8
wd10 = */ w 1.0 10.0 = width / 10
也就是 Horizontal Center 的含义,表示水平的中心点,相当于宽度的一半,计算的公式如下
*/ w 1.0 2.0
以上代码的 */
公式内容请参阅下文,而 w 表示的是宽度
也就是 Longest Side of Shape 的含义,表示宽度或高度里面最长的一边,等价以下公式
max w h
也就是返回宽度或高度的最大值
也就是 Shortest Side of Shape 的含义,表示宽度或高度里面最短的一边,等价以下公式
min w h
也就是返回宽度或高度的最小值
表示的是 ss 除以 2 的值,也就是获取宽度或高度的最小值除以 2 的值,以上 d 表示的是除以,使用如下公式
*/ ss 1.0 2.0
以此可以了解如下的几个常量的计算
ssd2 = */ ss 1.0 2.0 = Shortest Side / 2
ssd4 = */ ss 1.0 4.0 = Shortest Side / 4
ssd6 = */ ss 1.0 6.0 = Shortest Side / 6
ssd8 = */ ss 1.0 8.0 = Shortest Side / 8
而形状的计算符号定义在 ECMA 376 的 20.1.9.11 章文档
含义如下,以下的 x 和 y 和 z 表示传入的三个参数的值,如 fmla="*/ x y z"
的实际文档的值是 fmla="*/ 1 2 3"
也就是表示 x = 1 ,y = 2 ,z = 3 的值
Multiply Divide Formula
乘除公式使用 */
表示,要求传入三个参数
"*/ x y z" = ((x * y) / z)
Add Subtract Formula
加减公式使用 +-
表示,要求传入三个参数
"+- x y z" = ((x + y) - z)
Add Divide Formula
加除公式使用 +/
表示,要求传入三个参数
"+/ x y z" = ((x + y) / z)
If Else Formula
条件判断使用 ?:
符号表示,和 C# 里面的 ?:
逻辑相同,需要传入三个参数,假定参数是 x y z 三个参数,判断是如果传入的 x 大于 0 那么则是 true 代码如下
"?: x y z" = x > 0 ? y : z
if (x > 0)
{
return y;
}
else
{
return z;
}
Absolute Value Formula
绝对值公式使用 abs
表示,需要传入一个参数,计算方法如下
abs x = Math.Abs(x)
ArcTan Formula
表示三角函数的 arctan2
公式,计算方法如下
at2 x y = arctan(y / x) = Atan2(y, x)
而 Atan2 等的定义如下
/// <summary>
/// OpenXml 三角函数的Sin函数:sin x y = (x * sin( y )) = (x * Math.Sin(y))
/// </summary>
/// <param name="x">ppt的数值</param>
/// <param name="y">ppt表示角度的值</param>
/// <returns></returns>
public static double Sin(double x, int y)
{
var angle = GetAngle(y);
return x * Math.Sin(angle);
}
public static double ATan2(double x, double y)
{
var radians = Math.Atan2(y, x);
var angle = GetAngle(radians);
return angle * 60000;
}
/// <summary>
/// OpenXml 三角函数的Cos函数:cos x y = (x * cos( y )) = (x * Math.Cos(y))
/// </summary>
/// <param name="x">ppt的数值</param>
/// <param name="y">ppt表示角度的值</param>
/// <returns></returns>
public static double Cos(double x, int y)
{
var angle = GetAngle(y);
return x * Math.Cos(angle);
}
/// <summary>
/// OpenXml 三角函数的Tan函数:tan x y = (x * tan( y )) = (x * Math.Tan(y))
/// </summary>
/// <param name="x">ppt的数值</param>
/// <param name="y">ppt表示角度的值</param>
/// <returns></returns>
public static double Tan(double x, int y)
{
var angle = GetAngle(y);
return x * Math.Tan(angle);
}
/// <summary>
/// ppt的值转为角度
/// </summary>
/// <param name="value">ppt表示角度的值</param>
/// <returns></returns>
private static double GetAngle(int value)
{
var degree = value / 60000.0; // [Office Open XML 的测量单位](https://blog.lindexi.com/post/Office-Open-XML-%E7%9A%84%E6%B5%8B%E9%87%8F%E5%8D%95%E4%BD%8D.html )
var angle = degree * Math.PI / 180;
return angle;
}
Cosine ArcTan Formula
表示三角函数的两次计算 cat2
公式,计算方法如下
cat2 x y z = (x*(cos(arctan(z / y))) = (x * Cos(Math.Atan2(z, y)))
Cosine Formula
表示三角函数的 cos
公式,计算方法如下
cos x y = (x * cos( y )) = (x * Cos(y))
Sine ArcTan Formula
表示三角函数的 sat2
公式,计算方法如下
sat2 x y z = (x*sin(arctan(z / y))) = (x * Sin(Atan2(z, y)))
Sine Formula
表示三角函数的 sin
公式,计算方法如下
sin x y = (x * sin( y )) = (x * Sin(y))
Tangent Formula
表示三角函数的 tan
公式,计算方法如下
tan x y = (x * tan( y )) = (x * Tan(y))
Maximum Value Formula
表示两个数里面最大的一个值,使用 max
公式,计算方法如下
max x y = Math.Max(x, y)
Minimum Value Formula
表示两个数里面最小的一个值,使用 min
公式,计算方法如下
min x y = Math.Min(x, y)
Modulo Formula
表示 mod
公式,计算方法如下
mod x y z = sqrt(x^2 + b^2 + c^2) = Math.Sqrt(x * x + y * y + z * z)
Pin To Formula
表示 pin
公式,计算方法如下
pin x y z =
if (y < x)
{
return x;
}
else if (y > z)
{
return z;
}
else
{
return y;
}
Square Root Formula
表示 sqrt
公式,计算方法如下
sqrt x = Math.Sqrt(x)
Literal Value Formula
表示一个常量的值,相当于 var
的定义,表示的是 val
公式,将会返回对应的值
如 val x
就是返回 x 的值
如需要转换为 SVG 的字符串,请看 dotnet OpenXML 让 PathLst 自定义形状转 SVG 路径格式的 Geometry 内容
更多请看 Office 使用 OpenXML SDK 解析文档博客目录
感谢 Ryzen 提供的公式和代码
本文会经常更新,请阅读原文: https://blog.lindexi.com/post/dotnet-OpenXML-SDK-%E5%BD%A2%E7%8A%B6%E5%87%A0%E4%BD%95-Geometry-%E7%9A%84%E8%AE%A1%E7%AE%97%E5%85%AC%E5%BC%8F%E5%90%AB%E4%B9%89.html ,以避免陈旧错误知识的误导,同时有更好的阅读体验。
如果你想持续阅读我的最新博客,请点击 RSS 订阅,推荐使用RSS Stalker订阅博客,或者前往 CSDN 关注我的主页
本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名林德熙(包含链接: https://blog.lindexi.com ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请 与我联系 。
无盈利,不卖课,做纯粹的技术博客
以下是广告时间
推荐关注 Edi.Wang 的公众号
欢迎进入 Eleven 老师组建的 .NET 社区
以上广告全是友情推广,无盈利
Recommend
-
10
dotnet OpenXML 从文档生成创建文档的代码的库本文和大家介绍 Serialize.OpenXml.CodeGen 这个支持从某个文档生成用于创建出这个文档的 C# 或 VB 代码的库。作用就是可以让小伙伴在拿到一份模版文件之后,可以通过 Serialize.OpenXml.CodeGen 生成能创建出...
-
12
dotnet OpenXML 解析 WPS 不规范的 PPT 文件的 cNvPr 重复 id 问题在收到了反馈说有一份课件,打开解析就发现替换的元素不对,原因是这个课件里面的 Slide Master 里面存在一个元素的 id 和某个页面的元素 id 是相同的,这不符合 ECMA 376 的规范。通过读...
-
12
dotnet OpenXML 修复 Office 文档里面包含格式不正确的 Uri 而无法解析在使用 OpenXML 解析 Office 文档,无论是 PPT 还是 Word 还是 Excel 文档,都会使用标准方式解析。而此时的文档如果包含了错误的 Url 格式,例如不正确的邮件名的时候,将会在解析的...
-
14
dotnet OpenXML 解析 WPS 不符合压缩文档规范的文档我遇到了有老师给我反馈说用我的小工具去辅助编辑课件的时候,遇到了他使用 WPS 制作的文档打开失败,原因是 WPS 制作的一些文档不符合压缩文档规范。而 Office 的基于 ECMA 376 的文档,都是使用标准的...
-
12
dotnet OpenXML 图片特效的 BiLevel 黑白特效修改图片颜色在 Office 中,如 PPT 和 Word 可以不对原图修改的前提下,通过叠加特效的方式,提供对图片的视觉输出进行修改的方法,本文将介绍 ECMA 376 里面的 第 20.1.8.11 章的 Bi-Level (Black White Effec...
-
13
dotnet OpenXML 读取形状轮廓线条样式序号超过主题样式列表数在 OpenXML 中,默认的形状可以通过指定 LineReference 让形状使用文档主题里面的样式。文档主题里面包含多个样式,在形状里面指定样式通过的是序号的方法,如果在形状里面指定的序号超过了主题...
-
9
dotnet OpenXML 形状的 Outline 的 LineWidth 线条轮廓粗细宽度的行为本文来和大家聊聊 OpenXML 里面的给 PPT 用的形状里面的线条宽度的定义,以及在 PowerPoint 上的行为 本文属于 OpenXML 系列博客,前后文请参阅
-
9
dotnet OpenXML 读取 PPT 形状边框定义在 Style 的颜色画刷本文来和大家聊聊在 PPT 形状使用了 Style 样式的颜色画刷读取方法 在开始之前,期望大家已了解如何在 dotnet 应用里面读取 PPT 文件,如果还不了解读取方法,请参阅
-
7
dotnet OpenXML 聊聊 PPT 文本行距行高计算公式 在 Office 的 PPT 里面,将根据储存文档的行距以及字号,计算出渲染出来的每一行的文本行高。本文将根据 Office 2016 和 M365 两个版本,加上 QQ 截图测量,通过魔法的计算方式加上逗比的算法,从而...
-
16
在用户界面技术中,绘图是一个绕不开的话题。WPF提供了多种可根据应用程序要求进行优化的2D图形和图像的处理功能,包括画刷(Brush)、形状(Shape)、几何图形(Geometry)、图画(Drawing)和变换(Transform)等。其中形状(Shape)、几何图形(Geometry)和图画(Drawing)承担了...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK