C#读取Adams的Shell文件(*.shl)

Shell文件(*.shl)是Adams的一种几何形状文件,外形全是由多边形(直线连接的节点组成)表示的。本文介绍一下Shell文件的读取方法,以及在OpenGL中的显示方法。

1. Shell文件格式

Shell文件现在有两个版本。

1.1 版本1的范例:

8 6 1.0
-1.0 -1.0 1.0
-1.0 1.0 1.0
1.0 1.0 1.0
1.0 -1.0 1.0
-1.0 -1.0 -1.0
-1.0 1.0 -1.0
1.0 1.0 -1.0
1.0 -1.0 -1.0
4 1 2 3 4
4 5 6 2 1
3 2 6 7
4 3 7 8 4
4 1 4 8 5
4 8 7 6 5

蓝色行中的第一个数字表示节点的个数,第二个是多边形的数量,第三个是缩放系数(一般情况下为1)。

红色行为每个节点的坐标。绿色行第一个数字为多边形节点的数目,剩下的为每个节点的编号,与红色部分节点的顺序相对应,节点编号是从1开始。

1.2 版本2的范例:

Version: 2
3559 1362 3559 1.000000
-0.020500 0.005692 -0.001418
-0.020500 0.006541 -0.002266
-0.020500 0.005692 -0.000797
-0.020500 0.005692 -0.000797
-0.020500 0.005692 -0.001418
13 14 18 22 27 28 24 20 15 10 6 4 8 12
3 236 71 1
3 33 1 71
5 121 118 110 112 116
15 70 74 76 83 101 104 106 98 95 91 93 88 86 81 79
-0.022787 -0.041839 0.998864
1.000000 -0.000000 0.000000
0.018219 0.496961 0.867581
0.000000 0.923962 0.382485
1.000000 -0.000000 0.000000

蓝色行中的第一个数字表示节点的个数,第二个是多边形的数量,第三个对应紫色行的数目,第四个是缩放系数(一般情况下为1)。

红色和绿色行与版本1的含义一致。紫色行的用处不清楚,Adams帮助文档中只介绍了版本1的格式。

2. 读取Shell文件

C#读取shell文件代码如下,输入变量path是shell文件的路径。

public static void DrawShell(string path)
{
    List<Vector3> points = new List<Vector3>(); //points
    List<List<int>> seqs = new List<List<int>>(); //sequency
    List<Vector3> normals = new List<Vector3>(); 
    int lineNumber = 0;

    //read shl file
    if (!File.Exists(path))
    {
        MessageBox.Show("Cannot find the shell file");
    }
    string content = File.ReadAllText(path);
    string[] lines = content.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries);
    bool version2 = false;

    while (lines[lineNumber].Contains(":"))
    {
        lineNumber++;
        version2 = true;
    }

    string[] numbers = lines[lineNumber].Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
    int ptNum = Convert.ToInt32(numbers[0]);
    int seqNum = Convert.ToInt32(numbers[1]);
    int normalNum;
    float scale;

    if (version2)
    {
        normalNum = Convert.ToInt32(numbers[2]);
        scale = Convert.ToSingle(numbers[3]);
    }
    else
    {
        normalNum = 0;
        scale = Convert.ToSingle(numbers[2]);
    }
    
    
    
    for (int i = 0; i < ptNum; i++)
    {
        string[] pt = lines[lineNumber + 1 + i].Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
        if (pt.Count() == 3)
        {
            points.Add(new Vector3(
                Convert.ToSingle(pt[0].Trim()) * scale,
                Convert.ToSingle(pt[1].Trim()) * scale,
                Convert.ToSingle(pt[2].Trim()) * scale)
                );

        }
        else
        {
            points.Add(new Vector3(0f, 0f, 0f));
        }
    }
    
    for (int i = 0; i < seqNum; i++)
    {
        string[] seq = lines[lineNumber + 1 + ptNum + i].Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
        if (seq.Count() > 1)
        {
            seqs.Add(seq.ToList().ConvertAll<int>(x => Convert.ToInt32(x)));
        }
    }

    /*
    if (normalNum > 0)
    {
        for (int i = 0; i < normalNum; i++)
        {
            string[] pt = lines[lineNumber + 1 + i].Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
            if (pt.Count() == 3)
            {
                normals.Add(new Vector3(
                    Convert.ToDouble(pt[0].Trim()),
                    Convert.ToDouble(pt[1].Trim()),
                    Convert.ToDouble(pt[2].Trim()))
                    );

            }
            else
            {
                normals.Add(new Vector3d(0d, 0d, 0d));
            }
        }
    }
    */

    foreach(List<int> seq in seqs)
    {
        if (seq[0] > 2)
        {
            List<Vector3> vertices = new List<Vector3>();
            
            seq.RemoveAt(0);
            foreach (int index in seq)
            {
                vertices.Add(points[index - 1]);
            }

            //使用OpenGL显示每个多边形
            Tessellation.Triangulate(vertices);
        }
    }
   
}

上面代码中的Tessellation.Triangulate(vertices),是使用Glu的网格化(Tessellation)显示形状。该Tessellation类的具体内容,见我的另一篇文章:OPENGL: 多边形网格化(tessellation) 。

下面是读取某个齿轮shell文件的显示结果:

原文地址:https://www.cnblogs.com/xpvincent/p/2940484.html