在一些非IEEE754标准的微机发生的二进制文件中,同期c3d4sharp达成得比较简单

字节 类型 说明
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))

之所以可通过如下的公式来计算浮点数的值,当中,C是尾数标准化后减去的常量,B是移码的偏移量,可以预知A、B、C分别为A
= 2、B = 0x7F以致C = 1.0。

 

可怜有趣的是,VAX存款和储蓄的协会实际不是按顺序存款和储蓄的,而是选拔了风流罗曼蒂克种名为Middle-Endian的积存格局来累积(实际不是字节序卡塔尔:对于四字节来讲其顺序正是2301,八字节为23016745,十四字节为23016745AB89EFCD。可是全体来讲,VAX浮点型与IEEE754依旧很相近的,比方VAX也要进行标准化,可是其正式成为(0.1FFFFF..FF)2,所以上述的C就为0.5,其最后多少个M的约束即为五分二<= M <= 1 – 1 /
224;而同一时间其也并未明确无穷大,没有必要独自为极端大留出最大的阶码,所以上述的B为0x80。

Byte

V = (-1)^S * (F + C) * A^(E - B)

参数寄放内容的品种(-1 Char,1 Byte,2
Int16,4 Single卡塔尔,相对值即为长度

【二、VAX及IBM浮点数字的蕴藏和转移】

  • 对此每帧的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

VAX双精度浮点:

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

图片 1

参数内容维数(0-3卡塔尔

 1 Single ToSingle(Byte[] data)
 2 {
 3     Double a = 2.0;
 4     Double b = 127.0;
 5     Double c = 1.0;
 6     Double d = -126.0;
 7 
 8     Byte byte1 = data[3];
 9     Byte byte2 = data[2];
10     Byte byte3 = data[1];
11     Byte byte4 = data[0];
12 
13     Double s = (byte1 & 0x80) >> 7;
14     Double e = ((byte1 & 0x7F) << 1) + ((byte2 & 0x80) >> 7);
15     Double f = ((byte2 & 0x7F) << 16) + (byte3 << 8) + byte4;
16     Double m = f / Math.Pow(2, 23);
17 
18     if (e == 0xFF && f == 0) return (s == 0 ? Single.PositiveInfinity : Single.NegativeInfinity);
19     if (e == 0xFF && f != 0) return Single.NaN;
20     if (e == 0x00 && f == 0) return 0;
21     if (e == 0x00 && f != 0) return (Single)((s == 0 ? 1.0 : -1.0) * m * Math.Pow(a, d));
22 
23     return (Single)((s == 0 ? 1.0 : -1.0) * (c + m) * Math.Pow(a, e - b));
24 }
25 
26 Byte[] GetBytes(Single num)
27 {
28     Double a = 2.0;
29     Double b = 127.0;
30     Double c = 1.0;
31     Double d = Math.Log(2);
32 
33     Int32 s = (num >= 0 ? 0 : 1);
34 
35     Double v = Math.Abs(num);
36     Int32 e = (Int32)(Math.Log(v) / d + b);
37 
38     Double m = (v / Math.Pow(a, e - b)) - c;
39     Int32 f = (Int32)(m * Math.Pow(2, 23));
40 
41     Byte[] data = new Byte[4];
42     data[3] = (Byte)((s << 7) + ((e & 0xFE) >> 1));
43     data[2] = (Byte)(((e & 0x01) << 7) + ((f & 0x007F0000) >> 16));
44     data[1] = (Byte)((f & 0x0000FF00) >> 8);
45     data[0] = (Byte)(f & 0x000000FF);
46 
47     return data;
48 }

C3D文件存储了多量的参数,其行使了雷同目录的章程存款和储蓄了参数,然则万幸只有一流。即参数部分独有参数组和参数,何况每一种参数组里只可以有参数无法再饱含参数组,每一种参数必需在贰个参数组内。参数会集开头于文件头中的首先个字节表示的Section
ID,平时为2,可是也不自然,有的文件会在文书头后留出空白,然后参数集结开首的Section
ID就延迟了。所以判定是否为C3D文件千万不要朝气蓬勃起初读进去个Int16然后剖断是或不是0x5002,而自然要判别第1个字节是或不是0x50,明确参数集结的岗位也必要求依赖文件的率先字节来。

【相关链接】

参数组描述长度

但是表示超级小的数字,允许当E = 0时非规范化的倒数存在。即当E = 0且F
!=0时,V = (-1)^S * F * A^-126。

Byte[] 

VAX单精度浮点:

字节

 1 using System;
 2 
 3 namespace DotMaysWind.Numerics
 4 {
 5     /// <summary>
 6     /// VAX单精度浮点数字
 7     /// </summary>
 8     /// <remarks>
 9     /// SEF         S        EEEEEEEE        FFFFFFF        FFFFFFFF        FFFFFFFF
10     /// bits        1        2      9        10                                    32          
11     /// bytes       byte2           byte1                   byte4           byte3
12     /// </remarks>
13     public struct VAXSingle
14     {
15         #region 常量
16         private const Int32 LENGTH = 4;
17         private const Double BASE = 2.0;
18         private const Double EXPONENT_BIAS = 128.0;
19         private const Double MANTISSA_CONSTANT = 0.5;
20         private const Double E24 = 16777216.0;
21         #endregion
22 
23         #region 字段
24         private Byte[] _data;
25         #endregion
26 
27         #region 构造方法
28         /// <summary>
29         /// 初始化新的VAX单精度浮点数字
30         /// </summary>
31         /// <param name="data">VAX单精度浮点数字字节数组</param>
32         /// <param name="startIndex">数据起始位置</param>
33         public VAXSingle(Byte[] data, Int32 startIndex)
34         {
35             this._data = new Byte[VAXSingle.LENGTH];
36             Array.Copy(data, startIndex, this._data, 0, VAXSingle.LENGTH);
37         }
38 
39         /// <summary>
40         /// 初始化新的VAX单精度浮点数字
41         /// </summary>
42         /// <param name="num">系统标准的单精度浮点数字</param>
43         public VAXSingle(Single num)
44         {
45             Int32 s = (num >= 0 ? 0 : 1);
46 
47             Double v = Math.Abs(num);
48             Int32 e = (Int32)(Math.Log(v) / Math.Log(2.0) + 1.0 + VAXSingle.EXPONENT_BIAS);
49 
50             Double m = (v / Math.Pow(VAXSingle.BASE, e - VAXSingle.EXPONENT_BIAS)) - VAXSingle.MANTISSA_CONSTANT;
51             Int32 f = (Int32)(m * VAXSingle.E24);
52 
53             this._data = new Byte[VAXSingle.LENGTH];
54             this._data[1] = (Byte)((s << 7) + ((e & 0xFE) >> 1));
55             this._data[0] = (Byte)(((e & 0x01) << 7) + ((f & 0x007F0000) >> 16));
56             this._data[3] = (Byte)((f & 0x0000FF00) >> 8);
57             this._data[2] = (Byte)(f & 0x000000FF);
58         }
59         #endregion
60 
61         #region 方法
62         /// <summary>
63         /// 获取系统标准的单精度浮点数字
64         /// </summary>
65         /// <returns>系统标准的单精度浮点数字</returns>
66         public Single ToSingle()
67         {
68             Byte b1 = this._data[1];
69             Byte b2 = this._data[0];
70             Byte b3 = this._data[3];
71             Byte b4 = this._data[2];
72 
73             Double s = (b1 & 0x80) >> 7;
74             Double e = ((b1 & 0x7F) << 1) + ((b2 & 0x80) >> 7);
75             Double f = ((b2 & 0x7F) << 16) + (b3 << 8) + b4;
76             Double m = f / VAXSingle.E24;
77 
78             if (e == 0 && s == 0) return 0;
79             if (e == 0 && s == 1) return Single.NaN;
80 
81             return (Single)((s == 0 ? 1.0 : -1.0) * (VAXSingle.MANTISSA_CONSTANT + m) * Math.Pow(VAXSingle.BASE, e - VAXSingle.EXPONENT_BIAS));
82         }
83 
84         /// <summary>
85         /// 获取VAX单精度浮点数据字节数组
86         /// </summary>
87         /// <returns>字节数组</returns>
88         public Byte[] ToArray()
89         {
90             Byte[] data = new Byte[VAXSingle.LENGTH];
91 
92             Array.Copy(this._data, data, VAXSingle.LENGTH);
93 
94             return data;
95         }
96         #endregion
97     }
98 }
1 //首先需要添加参数集合,ID为正数
2 file.Parameters.AddGroup(1, "POINT", "");
3 //然后往指定ID的参数集合中添加参数即可
4 file.Parameters[1].Add("USED", "").SetData<Int16>(5);

若果设数符为S,阶码为E,尾数的小数部分为F,那么能够经过位运算获得那叁位:

【相关链接】

足见,浮点数就荒诞不经0的定义了,所以只能用极端小来代表,相同的时间为了表示无穷大,规定E取值范围为0
< E < 0xFF,即-0x7F < (E – B) < 0x80。

 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 }

于是,有了上述的这几个音信,大家就可以将浮点数字与字节数组相互转变了(本文假定给定的字节数组都以Litten-Endian卡塔 尔(阿拉伯语:قطر‎:

然则要求证实的是,对于Char[]以及Char[,]这两种,假诺表示的话实际应该相应的是String以致String[]。

图片 2图片 3

 

 

此处需求证实的正是,由于参数能够寄存数组,所以扩展了维数的标志,即当维数为0时,寄放的原委为Char、Byte、Int16、Single等转移出的字节数组;而当维数为1时,存放的为Char[]、Byte[]、Int16[]、Single[]等转移出的字节数组,依此类推。而对数组的蕴藏,其实就是数组每种成分依次展开仓储,而对于多维数组,则是按行优先开展仓库储存的,比如三个维度数组,先存款和储蓄Data[0,0,1]再存储Data[0,0,2],依次类推。

 

 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 }
SEF    S     EEEEEEEE     FFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF
bits   1     2      9     10                                                          64
bytes  byte2        byte3         byte0    byte1    byte6    byte7    byte4    byte5

【小说索引】

当E = 0时,指数最小,规定F = 0时为0,当中又有S = 0为正0以致S = 1时为-0。

 

 

C3D文件未有规定三个参数组前边跟另一个参数组如故跟该参数组里的保有参数,所以读取的时候要留神下。而参数的内容则与参数组基本风姿浪漫致,只是在下风流罗曼蒂克参数组/参数的撼动与参数组描述长度之间寄存着该参数的莫过于数据罢了,由于地方描述起来太艰巨了,这里就不写了。

里头,S为数符,它意味着浮点数的正负,但与其立见成效位(倒数卡塔 尔(英语:State of Qatar)是分别的。阶码用移码表示,阶码的真值都被加上二个常数(偏移量卡塔 尔(英语:State of Qatar),如短实数、长实数和一时实数的偏移量用十五进制表示分别为7FH、3FFH和3FFFH。倒数部分不感到奇都以规格化表示,即非“0”的立见成效位最高位一而再1。

字节 类型 说明
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字节)

率先依旧按字节看下VAX和IBM浮点型的存放:

  1. C3D.ORG:http://www.c3d.org/
  2. c3d4sharp – C3D File reading/writing tools written in
    C#:http://code.google.com/p/c3d4sharp/
  3. C3D.NET:https://c3d.codeplex.com/
 1 using System;
 2 
 3 namespace DotMaysWind.Numerics
 4 {
 5     /// <summary>
 6     /// IBM单精度浮点数字
 7     /// </summary>
 8     /// <remarks>
 9     /// SEF         S        EEEEEEE        FFFFFFFF        FFFFFFFF        FFFFFFFF
10     /// bits        1        2     8        9                                      32
11     /// bytes       byte1                   byte2           byte3           byte4
12     /// </remarks>
13     public struct IBMSingle
14     {
15         #region 常量
16         private const Int32 LENGTH = 4;
17         private const Double BASE = 16.0;
18         private const Double EXPONENT_BIAS = 64.0;
19         private const Double E24 = 16777216.0;
20         #endregion
21 
22         #region 字段
23         private Byte[] _data;
24         #endregion
25 
26         #region 构造方法
27         /// <summary>
28         /// 初始化新的IBM单精度浮点数字
29         /// </summary>
30         /// <param name="data">IBM单精度浮点数字字节数组</param>
31         /// <param name="startIndex">数据起始位置</param>
32         public IBMSingle(Byte[] data, Int32 startIndex)
33         {
34             this._data = new Byte[IBMSingle.LENGTH];
35             Array.Copy(data, startIndex, this._data, 0, IBMSingle.LENGTH);
36         }
37 
38         /// <summary>
39         /// 初始化新的IBM单精度浮点数字
40         /// </summary>
41         /// <param name="num">系统标准的单精度浮点数字</param>
42         public IBMSingle(Single num)
43         {
44             Int32 s = (num >= 0 ? 0 : 1);
45 
46             Double v = Math.Abs(num);
47             Int32 e = (Int32)(Math.Log(v) / Math.Log(2.0) / 4.0 + 1.0 + IBMSingle.EXPONENT_BIAS);
48 
49             Double m = (v / Math.Pow(IBMSingle.BASE, e - IBMSingle.EXPONENT_BIAS));
50             Int32 f = (Int32)(m * IBMSingle.E24);
51 
52             this._data = new Byte[IBMSingle.LENGTH];
53             this._data[3] = (Byte)(s + e);
54             this._data[2] = (Byte)((f & 0x00FF0000) >> 16);
55             this._data[1] = (Byte)((f & 0x0000FF00) >> 8);
56             this._data[0] = (Byte)(f & 0x000000FF);
57         }
58         #endregion
59 
60         #region 方法
61         /// <summary>
62         /// 获取系统标准的单精度浮点数字
63         /// </summary>
64         /// <returns>系统标准的单精度浮点数字</returns>
65         public Single ToSingle()
66         {
67             Byte b1 = this._data[3];
68             Byte b2 = this._data[2];
69             Byte b3 = this._data[1];
70             Byte b4 = this._data[0];
71 
72             Double s = (b1 & 0x80) >> 7;
73             Double e = (b1 & 0x7F);
74             Double f = (b2 << 16) + (b3 << 8) + b4;
75             Double m = f / IBMSingle.E24;
76 
77             if (e == 0 && f == 0 && s == 0) return 0;
78 
79             return (Single)((s == 0 ? 1.0 : -1.0) * m * Math.Pow(IBMSingle.BASE, e - IBMSingle.EXPONENT_BIAS));
80         }
81 
82         /// <summary>
83         /// 获取IBM单精度浮点数据字节数组
84         /// </summary>
85         /// <returns>字节数组</returns>
86         public Byte[] ToArray()
87         {
88             Byte[] data = new Byte[IBMSingle.LENGTH];
89 
90             Array.Copy(this._data, data, IBMSingle.LENGTH);
91 
92             return data;
93         }
94         #endregion
95     }
96 }

而读取模拟采集样板的话,采取的方法也周围:

View Code

 

而二进制小数转十进制小数的总计能够平素按整数的转变成做,然后除以2n就能够,n在那间实在便是尾数的尺寸,为23。

 

IBM双精度浮点:

 

  1. IEEE754规范浮点数字的囤积详细解释
  2. VAX及IBM浮点数字的存款和储蓄和转移
  3. 双精度浮点数的管理

C3D数据区域以帧为单位寄存的,其实一定于这些区域正是五个帧的汇集。而C3D帧其实分为二种,风姿浪漫种是整数帧,而另后生可畏种是浮点帧。那多头的区分在于,前面一个存款和储蓄的有着剧情都是Int16,而后人则为Single,除此而外,前面多少个的3D坐标点(X、Y、Z卡塔 尔(阿拉伯语:قطر‎还亟需倍Gaby例因子本领够,而后人存款和储蓄的剧情也就是已经乘以了百分比因子了。

看得出,其阶码增添了3位,即最大值是原本翻了3翻,为1024。而为了保障能表示无穷值,所以B为1023。除此而外只需求多读取前面扩大的尾数就能够,步骤与单精度基本相符。

前段时间实验室要本身修正C3D(The 3D Biomechanics Data
Standard卡塔 尔(阿拉伯语:قطر‎文件,即使从网络找到了五个叫c3d4sharp的类库,那么些类库单纯读取C3D文件的话还足以,可是假使要兑现改过或然创制C3D文件就相比较费心了。同期c3d4sharp达成得比较容易,超级多C3D文件里部分数据都不扶助。万幸C3D文件总体不是很复杂,于是作者就开始重新写了三个C3D文件读写的库,未来在codeplex上开创了个类型叫C3D.NET

以下是得以完毕IBM浮点字节数组与系统浮点数字互相转变的类:

在这里之后的第二部分,也正是积累的事件,听起来应该占比超多字节,不过由于约束了平地风波数量最多不可能超越二12个,同期事件名称最长为4字节,所以事件部分也只占比相当少的空中。由于C3D主借使为着记录运动的数目,可能在中间有那些相当重大的地点,事件便是用来标识出那个地点的。二个事件富含四个内容,分别是最长四字节的事件名称、一字节的事件是或不是相应显得的图景以至一个四字节的单精度浮点数表示事件现身的小时。

Double S = (byte1 & 0x80) >> 7;
Double E = ((byte1 & 0x7F) << 1) + ((byte2 & 0x80) >> 7);
Double F = ((byte2 & 0x7F) << 16) + (byte3 << 8) + byte4;

类型

  1. Transform between IEEE, IBM or VAX floating point number formats and
    bytes
    expressions:http://www.codeproject.com/Articles/12363/Transform-between-IEEE-IBM-or-VAX-floating-point-n
  2. VAX F_FLOAT and D_FLOAT to IEEE T_FLOAT and S_FLOAT
    (double):http://yaadc.blogspot.com/2013/01/vax-ffloat-and-dfloat-to-ieee-tfloat.html
  3. IEEE
    Arithmetic:http://docs.oracle.com/cd/E19957-01/806-3568/ncg_math.html
  4. Floating-Point:http://andromeda.rutgers.edu/~dupre/231/lecture13.doc
  5. IBM Floating Point
    Architecture:http://en.wikipedia.org/wiki/IBM_Floating_Point_Architecture
  6. VAX floating point to
    Decimal:http://arstechnica.com/civis/viewtopic.php?f=20&t=171682

对此每一种帧,又满含七个部分,第风度翩翩部分为3D坐标点部分,第二有个别为仿照采样部分。

【风流浪漫、IEEE754标准浮点数字的蕴藏详整】

对此英特尔和DEC生成的文书档案,都以运用Little-Endian字节序存款和储蓄的文档,所以自然要运用Little-Endian来读取Int16、Single等连串;而MIPS则采用的Big-Endian字节序存储文书档案,所以在读取的时候势供给咬定当前Computer暗许的字节序以致文档选择的字节序。

SEF         S        EEEEEEE        FFFFFFFF        FFFFFFFF        FFFFFFFF
bits        1        2     8        9                                      32
bytes       byte1                   byte2           byte3           byte4

 

SEF    S     EEEEEEE EEEE  FFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF
bits   1     2          12 13                                                       64
bytes  byte1         byte2      byte3    byte4    byte5    byte6    byte7    byte8

【生机勃勃、C3D文件格式的组织】

【文章索引】

多少区域从前于参数集结中的”POINT”参数组中的”DATA_START”参数,其代表数据区域在这从前的Section
ID,除却,在文书头中也可能有风姿罗曼蒂克份别本。然则依照法定的传教,倘使文件头和参数集合中皆有个别内容,优先读取参数集结中的数据。

这两日在做C3D文件的深入分析,好古怪的是文本中居然存款和储蓄了CPU的类型,原来不认为然,结果后来读取一个文书发掘浮点数全部读取错误。查了下发掘尽管在上世纪80时代就提议了IEEE754要合併浮点数规范,可是到现在依旧有Computer应用分化格局存款和储蓄浮点数。在好几非IEEE754标准的微型机产生的二进制文件中,假使得到别的计算机中读取,即便不实行特意的调换,只怕变成数据失实等主题材料。

而对此英特尔和MIPS生成的文书档案,对于浮点数字的囤积都以运用专门的学问的IEEE754浮点数字,对于.NET来说无需开展其余管理;而DEC生成的文书档案则动用特有浮点数,必要将4个字节全部读取现在再张开特别的转变,转变方法见本身前边的篇章:http://www.cnblogs.com/mayswind/p/3365594.html

为此,当E = 0xFF时,指数最大,规定F = 0时为无穷值,当中又有S =
0为正无穷以致S = 1为负无穷;而F != 0时为无用数字(NaN卡塔尔国。

 

以单精度浮点数为例,即便字节查六柱预测应是之类那几个样子的,数符占第1字节的第3位,阶码占第1字节的后7位及第二字节的第二位,其他都以尾数。

【二、C3D文件头的结构】

SEF      S        EEEEEEEE        FFFFFFF        FFFFFFFF        FFFFFFFF
bits     1        2      9        10                                    32
bytes    byte1           byte2                   byte3           byte4

首先说C3D文件全部不是很复杂,也并未有过多犬牙相错的概念,C3D的文书档案格式能够从其官方网站下载或在线阅读。首先C3D文件是以Section为单位存储的,每五个Section固定为512字节。Section一定是按顺序存款和储蓄的,然则风趣的是,Section的序号是从1上马的,并非0。C3D文件分为三片段,分别是Section
ID = 1的C3D文件头(固定为三个Section,512字节卡塔尔国,Section
ID日常等于2(在文书头内会付出卡塔尔国的C3D参数会集以致Section
ID不知道等于几(在文件头和参数会集中都会付给卡塔 尔(英语:State of Qatar)的C3D数据部分。

 

 

出于阶码用移码表示,所以实际的阶码则是E –
0x7F。而尾数由于是规格化的意味,就要倒数规范成为(1.FFFFF……FF)2,但只存小数点之后的有些。由于1
/ 2 + 1 / 4 + 1 / 8 + … + 1 / n = 1 – 1 /
2n,所以能够尾数M(M = 1.0 + F卡塔尔的限制为1 <= M <= 2 – 1
/ 223

Byte

以下是兑现VAX浮点字节数组与系统浮点数字相互转变的类:

Int16

【题外话】

而外三次性将C3D文件内容全方位读收取来的这种办法以外,还是能够使用C3DReader来黄金时代帧生龙活虎帧的读取。

二进制表示 十六进制表示 含义 十进制表示
0 11111111 00000000000000000000000 7F 80 00 00 正无穷 +∞ 
1 11111111 00000000000000000000000 FF 80 00 00 负无穷 -∞ 
0 00000000 00000000000000000000000 00 00 00 00 +0 0
1 00000000 00000000000000000000000 80 00 00 00 -0 0
0 00000000 00000000000000000000001 00 00 00 01  最小正数  1.401298E-45
0 11111110 11111111111111111111111 7F 7F FF FF 最大值 3.402823E+38
1 11111110 11111111111111111111111 FF 7F FF FF 最小值 -3.402823E+38
0 01111111 00000000000000000000000 3F 80 00 00 +1 1

Byte[]

IBM单精度浮点:

 

上述的浮点数转字节数组不能协助NaN和非标准化的场地,当然也得以友善看清下。当然了,上面说了如此多照旧为着介绍上面二种浮点数做铺垫。如果实现系统浮点数与字节数组调换的话,用下边这种方法转变就不比用System.BitConverter来的方便人民群众了。

Byte

【三、双精度浮点数的拍卖】

其后的内容

SEF    S     EEEEEEE  FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF
bits   1     2     8  9                                                            64
bytes  byte1          byte2    byte3    byte4    byte5    byte6    byte7    byte8

对此遍历全部的3D坐标能够使用以下的形式,首先能够从文件恐怕从流中成立C3D文件,然后从文件头中读取存款和储蓄的第1帧的序号,然后读取采集样本点的数据就足以了,当然也足以不从参数组中读取,直接接纳file.AllFrames[i].Point3Ds.Length也可以:

图片 4图片 5

说明

双精度浮点数与单精度浮点数相像,只可是会扩展阶码和倒数的约束罢了。对于IEEE754的双精度浮点来讲,不仅仅尾数的位数扩充,还有可能会增加阶码的尾数,字节存款和储蓄如下:

前方说了这么多,其实假使用C3D.NET来解析的话实际是特别轻易的。我们能够从https://c3d.codeplex.com/下载C3D.NET的二进制文件只怕源码,援引后根本的类都在C3D那个命名空间下。

而对此VAX和IBM的双精度浮点,更是未有扩展阶码的限量,而只是扩张了倒数的限制,使得只要多读取扩张的4位尾数就能够,而常数A、B、C更是没有需求校订。两个字节存款和储蓄如下:

参数实际内容

对此x86等周围的CPU,都以接收IEEE754存款和储蓄和计量浮点型的,当然在.NET平高雄浮点型也是IEEE754标准的。首先想起下本科时学过的Computer组成原理,查了下课本发掘是之类介绍IEEE754浮点数的蕴藏的(唐朔飞版课本233页卡塔 尔(英语:State of Qatar):

对此开创贰个C3D文件,只要求选用C3DFile.Create()就足以创设叁个空的C3D文件的,不带有别的的参数集合。而保存C3D文件则一贯动用file.SaveTo(“文件路线”)就足以了。

而IBM单精度浮点则与上述三种差距越来越大。首先其阶码并不是8位,而是7位,由于如故选拔移码存款和储蓄的阶码,所以其削减的不可能是127要么128,而是64,所以其与VAX同样,也尚无无穷值的意味。除却,其亦非以2为底总结阶码的,而是以16为底,何况其并未有标准化倒数的渴求(当然那也与其以16为底有关卡塔尔,所以无需对尾数进行加减运算,其范围为1/16
<= M <= 1- 1 / 224

字节 类型 说明
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 帧率

 

 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 }

View Code

参数每风流倜傥维大小(如若维数为0,就平昔不此部分卡塔尔国

SEF         S        EEEEEEEE        FFFFFFF        FFFFFFFF        FFFFFFFF
bits        1        2      9        10                                    32
bytes       byte2           byte3                   byte0           byte1

增多帧基本上能用如下的代码:

 

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

自然,也能够将C3DPoint3DData数组换来C3DAnalogSamples数组,或许两个同期加上也得以。

而对于参数集结,发轫的4字节概念如下:

【题外话】

以前的剧情

对此拉长参数集结能够选拔以下的代码:

对于参数组,要存款和储蓄以下6个内容:

其间前2个字节官方说一贯忽视就能够,然而为了合营在写入的时候如故要写进去的。第3字节其实我们按顺序读到头也无需以此数据。这里面重点的是CPU类型,由于不一样CPU类型采取的字节序以致存款和储蓄的浮点数字有所不相同,所以我们还亟需依照CPU类型进行相应的拍卖。

 

图片 6

下后生可畏参数组/参数的偏移(蕴含本内容的2字节卡塔尔

【四、C3D文件数量区域的组织】

  1. C3D文件格式的结构
  2. C3D文件头的协会
  3. C3D文件参数集合的构造
  4. C3D文件数量区域的布局
  5. 使用C3D.NET读写文件示例
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} }));

另三个是C3D文件能在不相同门类的CPU上调换,那表现于不一样CPU恐怕应用的字节序(Endian卡塔 尔(英语:State of Qatar)和浮点数字差异,比方大家用的CPU都是使用Little-Endian以至IEEE754的浮点数标准。从互连网查还发掘成DEC
(VAX)甚至IBM等CPU采纳区别的浮点数标准,详见小编后边风姿浪漫篇小说:http://www.cnblogs.com/mayswind/p/3365594.html。而C3D则是帮衬3类CPU,英特尔CPU选用Little-Endian以至IEEE754标准的浮点数,DEC
(VAX)选用的Little-Endian以至故意的浮点数,MIPS
(SGI)接纳的Big-Endian以致IEEE754标准的浮点数,所以在读取文书档案的时候或然须求优质开展拍卖,在第2节会详细表明。

 

只是C3D也会有很复杂的地点,一个是关于整型的使用,能够应用应用有灯号的(Int16卡塔 尔(阿拉伯语:قطر‎,也得以利用无符号的(UInt16卡塔 尔(阿拉伯语:قطر‎,只然则后面一个能储存的数据量要多一些而已,既然那样,不知为何当初还要采用有暗号的整型。并且最根本的是,文书档案内还没此外标记能提议文书档案使用的是何种整型。官方给出的减轻情势是,能够依靠举个例子帧总量、帧索引等判断,假使读出负数,则采纳无符号的,不然接受有标记的。

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

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

先是来讲第风度翩翩部分,也正是C3D的文件头,C3D的文书头一定只占1个Section,即一定的512字节,所以风姿罗曼蒂克旦读取前512字节就足以把全路头数据获得到了。尽管各种Section有512字节之多,但是对于C3D的文书头只占了少之又少的后生可畏都部队分,在文件头中有雅量单手的区域。个中第风流倜傥有的是文本头参数部分,内容如下:

相关文章