【无标题】二进制STL文件解析 计算面积和体积与根据高度计算部分体积

场景:容器中存放液体,需要根据雷达测量出的液位计算出容器内的液体体积。
数据:扫描仪扫描容器生成STL文件。
效果图
在这里插入图片描述

处理关键代码:
数据结构

/// <summary>
/// 顶点数据结构
/// </summary>
public class Point3
{
    public Point3()
    {
    }

    public Point3(float x = 0, float y = 0, float z = 0)
    {
        X = x;
        Y = y;
        Z = z;
    }
    public float X { get; set; }
    public float Y { get; set; }
    public float Z { get; set; }
}
/// <summary>
/// 三角面数据结构
/// </summary>
public class Face
{
    /// <summary>
    /// 法矢量
    /// </summary>
    public Point3 Vector { get; set; }
   public Point3 P1 { get; set; }
   public Point3 P2 { get; set; }
   public Point3 P3 { get; set; }
    /// <summary>
    /// 三角面片的属性信息
    /// </summary>
    public short Attribute { get; set; }

}

全局变量

 /// <summary>
 /// 三角面集合
 /// </summary>
private List<Face> Faces { get; set; }

读取二进制STL文件

byte[] b = null;
try
{
    DtStart = DateTime.Now;
    using (var fs = new FileStream(FilePath, FileMode.Open, FileAccess.Read))
    {

        var length = (int)fs.Length;
        b = new byte[length];
        fs.Read(b, 0, length);
        fs.Close();
    }

}
catch (Exception e)
{
    b = null;
    AddLog(e.Message);
    MessageBox.Show(e.Message);
}

解析三角面数据

if (b == null) return;
var count = BitConverter.ToInt32(b, 80);
for (int i = 0; i < count; i++)
{
    var vx = BitConverter.ToSingle(b, i * 50 + 84);
    var vy = BitConverter.ToSingle(b, i * 50 + 88);
    var vz = BitConverter.ToSingle(b, i * 50 + 92);
    var x1 = BitConverter.ToSingle(b, i * 50 + 96);
    var y1 = BitConverter.ToSingle(b, i * 50 + 100);
    var z1 = BitConverter.ToSingle(b, i * 50 + 104);
    var x2 = BitConverter.ToSingle(b, i * 50 + 108);
    var y2 = BitConverter.ToSingle(b, i * 50 + 112);
    var z2 = BitConverter.ToSingle(b, i * 50 + 116);
    var x3 = BitConverter.ToSingle(b, i * 50 + 120);
    var y3 = BitConverter.ToSingle(b, i * 50 + 124);
    var z3 = BitConverter.ToSingle(b, i * 50 + 128);
    var at = BitConverter.ToInt16(b, i * 50 + 132);

    var face = new Face
    {
        Vector = new Point3(vx, vy, vz),
        P1 = new Point3(x1, y1, z1),
        P2 = new Point3(x2, y2, z2),
        P3 = new Point3(x3, y3, z3),
        Attribute = at
    };
    Faces.Add(face);
}

计算体积和面积

private void Calc()
{
       var v = 0d;
       var s = 0d;
       foreach (var f in Faces)
       {
           v += TriangularVolume(
               f.P1.X, f.P1.Y, f.P1.Z,
               f.P2.X, f.P2.Y, f.P2.Z,
               f.P3.X, f.P3.Y, f.P3.Z);
           s += TriangularArea(
               f.P1.X, f.P1.Y, f.P1.Z,
               f.P2.X, f.P2.Y, f.P2.Z,
               f.P3.X, f.P3.Y, f.P3.Z);
       }

       labelControl1.Text = $@"面积:{(s / 100):F3} cm2{Environment.NewLine}体积:{(v / 1000):F3} cm3";
   }
    /// <summary>
        /// 计算体积
        /// </summary>
        private double TriangularVolume(float p1X, float p1Y, float p1Z,
            float p2X, float p2Y, float p2Z,
            float p3X, float p3Y, float p3Z)
        {
            double v321 = p3X * p2Y * p1Z;
            double v231 = p2X * p3Y * p1Z;
            double v312 = p3X * p1Y * p2Z;
            double v132 = p1X * p3Y * p2Z;
            double v213 = p2X * p1Y * p3Z;
            double v123 = p1X * p2Y * p3Z;
            return (double)(1.0 / 6.0) * (-v321 + v231 + v312 - v132 - v213 + v123);
        }
        /// <summary>
        /// 计算面积
        /// </summary>
        private double TriangularArea(float p1X, float p1Y, float p1Z,
            float p2X, float p2Y, float p2Z,
            float p3X, float p3Y, float p3Z)
        {
            double ax = p2X - p1X;
            double ay = p2Y - p1Y;
            double az = p2Z - p1Z;
            double bx = p3X - p1X;
            double by = p3Y - p1Y;
            double bz = p3Z - p1Z;
            double cx = ay * bz - az * by;
            double cy = az * bx - ax * bz;
            double cz = ax * by - ay * bx;
            return (double)(0.5 * Math.Sqrt(cx * cx + cy * cy + cz * cz));
        }

对面数据排序

Faces.Sort(((a, b) => b.P1.Z.CompareTo(a.P1.Z)));

UpDown控制步进计算不同高度体积

try
{
     if (Faces == null || Faces.Count == 0) return;
     var t1 = DateTime.Now;
     var spinValue = (float)spinEdit1.Value;
     var v = 0d;
     foreach (var f in Faces)
     {
         if (f.P1.Z <= spinValue)
         {
             v += TriangularVolume(
                 f.P1.X, f.P1.Y, f.P1.Z,
                 f.P2.X, f.P2.Y, f.P2.Z,
                 f.P3.X, f.P3.Y, f.P3.Z);
         }
     }

     var t2 = (DateTime.Now - t1).TotalMilliseconds;
     labelControl2.Text = $@"体积:{(v / 1000):F3} cm3 {Environment.NewLine}用时:{t2} ms";

 }
 catch (Exception exception)
 {
     Console.WriteLine(exception);
     MessageBox.Show(exception.Message);
 }

源码:

https://download.youkuaiyun.com/download/songlinok/70112610

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值