永利棋牌官方下载-www.55402.com-永利国际唯一指定官网

永利棋牌官方下载提供最新最好玩的真人游戏,www.55402.com是澳门国际娱乐平台官方网站唯一授权会员登录手机版,www.316net,www.366net,516.net,626.net,766.net,www.565.net,www.16.net,bwin62.com,bwin180.com,永利国际唯一指定官网为新老顾客提供更多的精彩娱乐项目,,所有的玩家都可以得到注册送体验金的巨大福利是设身处地为玩家量身订造的经典网站。

.NET平台下对C3D文件的读写

【题外话】

近来实验室要本身修改C3D(The 3D Biomechanics Data Standard)文件,即使从网络找到了三个叫c3d4sharp.NET平台下对C3D文件的读写。的类库,那个类库单纯读取C3D文件的话还足以,不过一旦要落到实处修改或许创建C3D文件就相比较艰难了。同不时候c3d4sharp达成得相比较轻易,很多C3D文件里一些数据都不支持。幸好C3D文件总体不是很复杂,于是笔者就从头重新写了贰个C3D文件读写的库,未来在codeplex上开创了个类别叫.NET平台下对C3D文件的读写。C3D.NET。

 

【文章索引】

  1. C3D文件格式的协会
  2. C3D文件头的构造
  3. C3D文件参数会集的结构
  4. C3D文件数量区域的结构
  5. 动用C3D.NET读写文件示例

.NET平台下对C3D文件的读写。 

【一、C3D文件格式的布局】

第一说C3D文件全体不是很复杂,也不曾过多良莠不齐的概念,C3D的文书档案格式可以从其官方网址下载或在线阅读。首先C3D文件是以Section为单位存储的,每三个Section固定为512字节。Section一定是按顺序存款和储蓄的,不过有趣的是,Section的序号是从1开首的,并非0。C3D文件分为三有些,分别是Section ID = 1的C3D文件头(固定为二个Section,512字节),Section ID平时等于2(在文件头内会提交)的C3D参数集合以至Section ID不晓得等于几(在文件头和参数会集中都会付给)的C3D数据部分。

只是C3D也许有很复杂的地点,一个是有关整型的应用,能够利用使用有号子的(Int16),也足以选用无符号的(UInt16),只可是前者能积累的数据量要多一些罢了,既然那样,不知为什么当初还要选取有号子的整型。并且最首要的是,文书档案内并未有别的标记能提出文书档案使用的是何种整型。官方给出的化解方式是,能够遵照比方帧总量、帧索引等剖断,假若读出负数,则利用无符号的,不然选择有标记的。

另一个是C3D文件能在不相同类别的CPU上扭转,那表现于分歧CPU大概应用的字节序(Endian)和浮点数字分化,比如咱们用的CPU都以行使Little-Endian乃至IEEE754的浮点数标准。从互连网查还开掘有DEC (VAX)以至IBM等CPU选拔差异的浮点数标准,详见作者前边一篇作品:。而C3D则是援救3类CPU,速龙CPU选用Little-Endian以致IEEE754标准的浮点数,DEC (VAX)采纳的Little-Endian以至故意的浮点数,MIPS (SGI)采纳的Big-Endian以至IEEE754规范的浮点数,所以在读取文书档案的时候也许必要卓殊开展拍卖,在第二节会详细表达。

 

【二、C3D文件头的结构】

率先来讲第一片段,也等于C3D的公文头,C3D的文件头一定只占1个Section,即定位的512字节,所以一旦读取前512字节就足以把一切头数据获得到了。尽管各类Section有512字节之多,不过对于C3D的文本头只占了少之又少的一局部,在文书头中有多量空白的区域。个中第一部分是文本头参数部分,内容如下:

图片 1

字节 类型 说明
00H Byte 参数集合开始的Section ID(通常为0x02,但也不一定)
01H Byte 文件标识(固定为0x50)
02H-03H Int16 每帧里3D坐标点的个数
04H-05H Int16 每帧里模拟测量的个数
06H-07H Int16 第1帧的序号(最小为1)
08H-09H Int16 最后1帧的序号
0AH-0BH Int16 最大插值差距
0CH-0FH Single 比例因子(正数表示存储的帧为整数帧,负数为浮点帧)
10H-11H Int16  数据区域开始的Section ID
12H-13H Int16 每帧模拟采样个数
14H-17H Single 帧率

在那之后的第二某个,也正是储存的风云,听起来应该占很多字节,但是由于限制了事件数量最多不可能赶过十柒个,同不经常间事件名称最长为4字节,所以事件部分也只占非常少的长空。由于C3D首假使为了记录运动的数码,大概在里头有成都百货上千比较首要的地方,事件就是用来标识出这个地点的。一个事变包罗四个内容,分别是最长四字节的平地风波名称、一字节的平地风波是或不是应该展现的情事乃至五个四字节的单精度浮点数表示事件出现的大运。

字节 类型 说明
12AH-12BH Int16 事件名是否支持4字节(支持为0x3039,不支持为0)
12CH-12DH Int16 事件数量(最大为18)
130H-176H Single[] 按事件顺序存储的每个事件发生的时间(第1个帧为0.0s)
178H-188H Byte[] 按事件顺序存储的每个事件是否应该显示(1为显示,0为不显示)
18CH-1D2H Char[] 按事件顺序存储的每个事件的名称(每个事件占4字节)

 

【三、C3D文件参数集结的结构】 

C3D文件存款和储蓄了大气的参数,其利用了临近目录的方式存储了参数,但是幸而独有一流。即参数部分独有参数组和参数,何况每一个参数组里只可以有参数不能够再包罗参数组,每种参数必需在四个参数组内。参数集结伊始于文件头中的首先个字节表示的Section ID,日常为2,可是也不鲜明,有的文件会在文件头后留出空白,然后参数集结早先的Section ID就滞缓了。所以判定是不是为C3D文件千万不要一发轫读进去个Int16然后判断是还是不是0x5002,而迟早要咬定第三个字节是还是不是0x50,分明参数集合的职位也必要求基于文件的首先字节来。

而对于参数集合,起先的4字节概念如下:

字节 类型 说明
00H Byte 第一个参数所在的Section在整个参数集合中的位置(通常为0x01,说明开头4字节之后就是第一个参数)
01H Byte 参数集合部分标识(固定为0x50)
02H Byte 参数集合所占Section数量
03H Byte 生成文件的CPU类型(0x54为Intel,0x55为DEC (VAX, PDP-11),0x56为MIPS (SGI/MIPS))

里头前2个字节官方说平昔忽视就行,不过为了合作在写入的时候依然要写进去的。第3字节其实我们按顺序读到头也不须要以此数目。这里面首要的是CPU类型,由于不相同CPU类型选择的字节序以至存款和储蓄的浮点数字有所分歧,所以大家还须要依赖CPU类型实行对应的管理。

对此AMD和DEC生成的文书档案,都是利用Little-Endian字节序存款和储蓄的文书档案,所以自然要利用Little-Endian来读取Int16、Single等品种;而MIPS则动用的Big-Endian字节序存储文书档案,所以在读取的时候自然要推断当前计算机暗中同意的字节序乃至文档选用的字节序。

而对此英特尔和MIPS生成的文书档案,对于浮点数字的仓库储存都是行使标准的IEEE754浮点数字,对于.NET而言不要求开展别的处理;而DEC生成的文书档案则应用特有浮点数,必要将4个字节整体读取今后再张开超过常规规的调换,转变方法见笔者前面包车型大巴稿子:。

在那之下就存款和储蓄着独具的参数了,参数分为两类,分别是参数组和参数。

对此参数组,要存储以下6个内容:

字节 类型 说明
00H SByte 参数组名称长度(如果为负数则表示该参数组锁定请不要修改,而长度为绝对值)
01H SByte 参数组ID的负数
02H - ... Char[] 参数组名称(仅包含大写字母、0-9以及下划线_)
... + 1 - ... + 2 Int16 下一参数组/参数的偏移(包含本内容的2字节)
... + 3
Byte 参数组描述长度
... + 4 -  Char[] 参数组描述内容(ASCII码)

.NET平台下对C3D文件的读写。C3D文件未有分明二个参数组前边跟另一个参数组照旧跟该参数组里的保有参数,所以读取的时候要注意下。而参数的源委则与参数组基本一致,只是在下一参数组/参数的撼动与参数组描述长度之间存放着该参数的其实数目罢了,由于地点描述起来太难为了,这里就不写了。

字节

类型

说明

事先的从头到尾的经过

 

Int16

下一参数组/参数的舞狮(蕴涵本内容的2字节)

 

Byte

参数贮存内容的品种(-1 Char,1 Byte,2 Int16,4 Single),绝对值即为长度

 

Byte

参数内容维数(0-3)

 

Byte[]

参数每一维大小(要是维数为0,就一直不此部分)

 

Byte[] 

参数实际内容

 

Byte

参数组描述长度

而后的从头到尾的经过

此间需求验证的正是,由于参数能够寄存数组,所以扩大了维数的标记,即当维数为0时,寄放的内容为Char、Byte、Int16、Single等转移出的字节数组;而当维数为1时,寄放的为Char[]、Byte[]、Int16[]、Single[]等转移出的字节数组,就那样类推。而对数组的囤积,其实就是数组每一种成分依次举办仓储,而对此多维数组,则是按行优先开展仓库储存的,比方三个维度数组,先存款和储蓄Data[0,0,1]再存储Data[0,0,2],依次类推。

可是需求证实的是,对于Char[]以及Char[,]这两种,要是表示的话实际应该相应的是String乃至String[]。

 

【四、C3D文件数量区域的布局】

C3D数据区域以帧为单位存放的,其实一定于那些区域便是叁个帧的集聚。而C3D帧其实分为三种,一种是整数帧,而另一种是浮点帧。那二者的分别在于,前面一个存款和储蓄的持有剧情都以Int16,而后人则为Single,除外,后面一个的3D坐标点(X、Y、Z)还索要倍加比例因子才方可,而前面一个存款和储蓄的内容也正是已经乘以了百分比因子了。

数量区域开首于参数集合中的"POINT"参数组中的"DATA_START"参数,其代表数据区域初叶的Section ID,除了这些之外,在文件头中也可能有一份别本。但是依据官方的传道,要是文件头和参数群集中都有的内容,优先读取参数集结中的数据。

对此每种帧,又带有八个部分,第一有的为3D坐标点部分,第1盘部为仿照采样部分。

  • 对于每帧的3D坐标点部分,存款和储蓄着该帧全部3D坐标点的数据,每种3D坐标点满含4个Int16或Single数据,分别是X坐标、Y坐标、Z坐标乃至Residual和Camera Mask,当中Residual和Camera Mask共占一个Int16。相比风趣的是,对于浮点帧,Residual和Camera Mask依旧也照旧多少个Int16,只可是存款和储蓄的时候要将相应的数值调换为Single再进行仓库储存。
    • 对于浮点帧,存储的X、Y、Z坐标就是其实的坐标;而对于整数帧,存款和储蓄的X、Y、Z的坐标还供给倍Gaby例因子才方可,比例因子存款和储蓄于参数集合中的"POINT"参数组中的"SCALE"参数。
    • Residual和Camera Mask共占一个Int16,将其改变为字节数组之后,高位字节(第二个字节)的最高位表示Residual的暗记,即意味着该坐标点是不是有效,尽管为0则象征有效,假使为1则代表无效,而剩余的7个字节则为Camera Mask,每一人代表一个摄像机,从未有到高位分别表示7个录像机是还是不是采纳(为1为运用,为0为未选拔)。而Residual的实际数据则为字节数组的第0字节乘以比例因子(浮点帧则为比例因子的相对值)。
  • 而模仿采样部分,则存款和储蓄着该帧全数的效仿采集样品的数目,可是各类帧恐怕含有多个模拟采集样品,同不平日间各样模仿采样或者又满含八个channel,存款和储蓄的多寡即为该channel下记录的数据。可是存款和储蓄的数量与事实上的数量还亟需基于下述公式进行折算,个中data value为存款和储蓄的数码,real world value为实际的数额。

    • zero offset能够从"ANALOG"参数组中的"OFFSET"中拿走,该数量为Int16的数组,第i位指的正是第i个channel的zero offset。
    • channel scale能够从"ANALOG"参数组中的"SCALE"中获得,该多少为Single的数组,第i位指的正是dii个channel的scale。
    • general scale是全部模拟采集样品都急需倍加的百分比,该数据足以从"ANALOG"参数组中的"GEN_SCALE"中获取,为Single。

    real world value = (data value - zero offset) channel scale general scale

 

【五、使用C3D.NET读写文件示例】

前方说了如此多,其实只要用C3D.NET来解析的话实际是很轻易的。大家能够从下载C3D.NET的二进制文件或许源码,引用后根本的类都在C3D那个命名空间下。

对此遍历全部的3D坐标能够应用以下的主意,首先能够从文件也许从流中创造C3D文件,然后从文件头中读取存款和储蓄的第1帧的序号,然后读取采集样品点的数额就足以了,当然也足以不从参数组中读取,直接运用file.AllFrames[i].Point3Ds.Length也可以:

 1 C3DFile file = C3DFile.LoadFromFile("文件路径");
 2 Int16 firstFrameIndex = file.Header.FirstFrameIndex;
 3 Int16 pointCount = file.Parameters["POINT:USED"].GetData<Int16>();
 4 
 5 for (Int16 i = 0; i < file.AllFrames.Count; i++)
 6 {
 7     for (Int16 j = 0; j < pointCount; j++)
 8     {
 9         Console.WriteLine("Frame {0} : X = {1}, Y = {2}, Z = {3}",
10             firstFrameIndex + i,
11             file.AllFrames[i].Point3Ds[j].X,
12             file.AllFrames[i].Point3Ds[j].Y ,
13             file.AllFrames[i].Point3Ds[j].Z);
14     }
15 }

而读取模拟采集样品的话,采取的章程也接近:

 1 Single frameRate = file.Parameters["POINT", "RATE"].GetData<Single>();
 2 Int16 analogChannelCount = file.Parameters["ANALOG", "USED"].GetData<Int16>();
 3 Int16 analogSamplesPerFrame = (Int16)(file.Parameters["ANALOG", "RATE"].GetData<Int16>() / frameRate);
 4 
 5 for (Int16 i = 0; i < file.AllFrames.Count; i++)
 6 {
 7     for (Int16 j = 0; j < analogChannelCount; j++)
 8     {
 9         for (Int16 k = 0; k < analogSamplesPerFrame; k++)
10         {
11             Console.WriteLine("Frame {0}, Sample {1} : {2}",
12                 firstFrameIndex + i, j + 1,
13                 file.AllFrames[i].AnalogSamples[j][k]);
14         }
15     }
16 }

除了那些之外壹次性将C3D文件内容总体读抽出来的这种艺术以外,还可以够动用C3DReader来一帧一帧的读取。

 1 using (FileStream fs = new FileStream("文件路径", FileMode.Open, FileAccess.Read))
 2 {
 3     C3DReader reader = new C3DReader(fs);
 4     C3DHeader header = reader.ReadHeader();
 5     C3DParameterDictionary dictionary = reader.ReadParameters();
 6     Int32 index = header.FirstFrameIndex;
 7 
 8     while (true)
 9     {
10         C3DFrame frame = reader.ReadNextFrame(dictionary);
11 
12         if (frame == null)
13         {
14             break;
15         }
16 
17         for (Int16 j = 0; j < frame.Point3Ds.Length; j++)
18         {
19             Console.WriteLine("Frame {0} : X = {1}, Y = {2}, Z = {3}",
20                 index++,
21                 frame.Point3Ds[j].X,
22                 frame.Point3Ds[j].Y,
23                 frame.Point3Ds[j].Z);
24         }
25     }
26 }

对于开创八个C3D文件,只需求运用C3DFile.Create()就能够成立贰个空的C3D文件的,不含有其余的参数集结。而保存C3D文件则向来选取file.SaveTo("文件路线")就足以了。

对于增加参数集合能够接纳以下的代码:

1 //首先需要添加参数集合,ID为正数
2 file.Parameters.AddGroup(1, "POINT", "");
3 //然后往指定ID的参数集合中添加参数即可
4 file.Parameters[1].Add("USED", "").SetData<Int16>(5);

加多帧能够使用如下的代码:

1 file.AllFrames.Add(new C3DFrame(new C3DPoint3DData[] {
2     new C3DPoint3DData() { X = x, Y = y, Z = z, Residual = residual, CameraMask = cameraMask},
3     new C3DPoint3DData() { X = x, Y = y, Z = z, Residual = residual, CameraMask = cameraMask},
4     new C3DPoint3DData() { X = x, Y = y, Z = z, Residual = residual, CameraMask = cameraMask},
5     new C3DPoint3DData() { X = x, Y = y, Z = z, Residual = residual, CameraMask = cameraMask},
6     new C3DPoint3DData() { X = x, Y = y, Z = z, Residual = residual, CameraMask = cameraMask} }));

当然,也得以将C3DPoint3DData数组换来C3DAnalog萨姆ples数组,大概双方同时丰裕也可以。

 

【相关链接】

  1. C3D.ORG:
  2. c3d4sharp - C3D File reading/writing tools written in C#:
  3. C3D.NET:

本文由永利棋牌官方下载发布于www.55402.com,转载请注明出处:.NET平台下对C3D文件的读写

您可能还会对下面的文章感兴趣: