SuperMap iObjects .NET 电力模型与实例化图层的碰撞

3 篇文章 0 订阅
1 篇文章 0 订阅

作者:翔翔



背景

在电力行业中,由设计院或者数据生产商提供成果数据。成果数据有的是GIM、有的是模型+姿态矩阵、有的是模型+模型对应的绕轴旋转值、轴缩放值和平移值。但是并不是所有的成果数据就绝对正确或一层不变。当杆塔所在位置地形变了,此时杆塔模型便会根据实际的地形来微调,比如旋转、缩放、平移等。微调杆塔时也需要将绝缘子串的状态实时改变。微调后还能将当前模型的矩阵导出以便做成新的成果数据提交。如何在SuperMap iObjects .Net产品中实现该流程?这就是本文要讲的主题。


主题

首先可能大家会问什么是实例化?如果大家对实例化不熟悉的话可以参考博客中的简单说明:
模型数据处理之实例化处理


数据准备

  1. 杆塔点位数据集
  2. 杆塔和绝缘子串S3MB模型文件
  3. 绝缘子串相对杆塔的矩阵信息

联动更新模型位置信息

通过编辑二维地图中的点位信息,将更改后的点位信息传入到对应的模型上,实现杆塔及其绝缘子串的位置更新。

关键代码如下::

	/// <summary>
    /// 更新模型位置信息,
    /// </summary>
    /// <param name="smid">杆塔smid</param>
    /// <param name="position">更新位置</param>
    public void UpdatePosition(int smid, Point3D position)
    {
        ///获取smid的对象
        List<LinkSource> queryLink = m_linkSource.FindAll(o => o.SmID == smid);
        m_towerInstance.States.ForEach(item =>
        {
            if (queryLink.Find(o => o.Guid == item.ID) != null)
            {
                item.Longitude = position.X;
                item.Latitude = position.Y;
                item.Altitude = position.Z;
            }
        });
    }

示意gif如下

位置更新


更新模型旋转

通过设置模型绕XYZ任意轴旋转角度,计算出杆塔和绝缘子串的旋转矩阵。绝缘子串旋转矩阵更新主要流程:

  1. 获取串的偏移值
  2. 根据旋转值计算串的新偏移
  3. 将串原始矩阵的偏移值归零,得到新的原始矩阵
  4. 通过新的旋转值构建矩阵,然后乘新的原始矩阵
  5. 将步骤2中的偏移值设置给步骤4得到的矩阵。最后将矩阵赋给对象

关键代码如下:

/// <summary>
    /// 更新模型旋转
    /// </summary>
    /// <param name="smid">杆塔smid</param>
    /// <param name="rx">X轴旋转角度</param>
    /// <param name="ry">Y轴旋转角度</param>
    /// <param name="rz">Z轴旋转角度</param>
    public void UpdateRotation(int smid, double rx, double ry, double rz)
    {
        ///获取smid的对象
        List<LinkSource> queryLink = m_linkSource.FindAll(o => o.SmID == smid);
        ///计算杆塔矩阵
        m_towerInstance.States.ForEach(item =>
        {
            if (queryLink.Find(o => o.Guid == item.ID) != null)
            {
                item.LocalMatrix = item.LocalMatrix.Multipy(Matrix.RotateXYZ(rx, ry, rz));
            }
        });
        ///计算绝缘子串矩阵信息
        m_stringInstanceS35.States.ForEach(item =>
        {
            if (queryLink.Find(o => o.Guid == item.ID) != null)
            {
                Matrix matrix = item.LocalMatrix;
                ///获取矩阵偏移值
                Point3D p1 = new Point3D(matrix.ArrayValue[12], matrix.ArrayValue[13], matrix.ArrayValue[14]);
                ///串旋转后的挂点
                Point3D p2 = CDUtil.Matrix.Matrix.removeP(p1, new Dictionary<int, double>() { { 1, rx }, { 2, ry }, { 3, rz } }, new Point3D(), new Point3D(1, 1, 1));
                ///先将原始矩阵偏移归零
                double[] temp = matrix.ArrayValue;
                temp[12] = 0;
                temp[13] = 0;
                temp[14] = 0;
                matrix.ArrayValue = temp;
                ///旋转矩阵乘归零矩阵
                matrix = Matrix.RotateXYZ(rx, ry, rz).Multipy(matrix);
                ///重新设置矩阵的偏移值,值为串旋转后的挂点
                double[] ma = matrix.ArrayValue;
                ma[12] = p2.X;
                ma[13] = p2.Y;
                ma[14] = p2.Z;
                matrix.ArrayValue = ma;
                //item.Altitude += 0.0001;
                item.LocalMatrix = matrix;
            }
        });
	}

示意gif

模型旋转

更新模型缩放

通过设置模型绕XYZ任意轴缩放比例,计算出杆塔和绝缘子串的旋转矩阵。绝缘子串缩放矩阵更新主要流程:

  1. 先将缩放矩阵乘原始矩阵得到新矩阵
  2. 获取步骤1中的偏移值
  3. 计算偏移值缩放后的新偏移值
  4. 将步骤3中获取的值设置给步骤1中的偏移值

关键代码如下:

	/// <summary>
    /// 更新模型缩放
    /// </summary>
    /// <param name="smid">杆塔smid</param>
    /// <param name="sx">X缩方比例</param>
    /// <param name="sy">Y缩方比例</param>
    /// <param name="sz">Z缩方比例</param>
    public void UpdateScale(int smid, double sx, double sy, double sz)
    {
        ///获取smid的对象
        List<LinkSource> queryLink = m_linkSource.FindAll(o => o.SmID == smid);
        ///计算杆塔矩阵
        m_towerInstance.States.ForEach(item =>
        {
            if (queryLink.Find(o => o.Guid == item.ID) != null)
            {
                item.LocalMatrix = Matrix.Scale(sx, sy, sz).Multipy(item.LocalMatrix);
            }
        });
        ///计算绝缘子串矩阵信息
        m_stringInstanceS35.States.ForEach(item =>
        {
            if (queryLink.Find(o => o.Guid == item.ID) != null)
            {
                ///用缩放矩阵乘原始矩阵
                Matrix matrix = Matrix.Scale(sx, sy, sz).Multipy(item.LocalMatrix);
                ///获取矩阵偏移值
                Point3D p1 = new Point3D(matrix.ArrayValue[12], matrix.ArrayValue[13], matrix.ArrayValue[14]);
                Point3D Spoint = new Point3D(sx, sy, sz);
                ///计算偏移值缩放后的新偏移值
                Point3D p2 = CDUtil.Matrix.Matrix.removeP(p1, new Dictionary<int, double>(), new Point3D(), Spoint);
                ///设置矩阵偏移值
                double[] ma = matrix.ArrayValue;
                ma[12] = p2.X;
                ma[13] = p2.Y;
                ma[14] = p2.Z;
                matrix.ArrayValue = ma;
                item.LocalMatrix = matrix;
            }
        });
	}

示意gif

模型缩放

模型查询

将模型的唯一ID和对应的数据集SMID对应起来,同时也可存储其他的一些信息。当点击杆塔时,可以获取到该对象的唯一ID。在存储的属性中查询到唯一ID即可获取到该对象的信息。如果还有外挂了一些信息,可通过SMID去查询对应的信息并展示出来。

关键代码如下:

	/// <summary>
    /// 添加对象到实例化图层
    /// </summary>
    /// <param name="smid"></param>
    /// <param name="position"></param>
    /// <param name="description"></param>
    public void AddGeometry(int smid, Point3D position, string description)
    {
        InstanceObjectState tower = new InstanceObjectState();
        ///设置唯一guid,值的范围1-2^24之间
        int guid = GetGuid();
        LinkSource linkSource = m_linkSource.Find(o => o.Guid == guid);
        while (linkSource != null)
        {
            guid = GetGuid();
            linkSource = m_linkSource.Find(o => o.Guid == guid);
        }
        tower.ID = guid;
        tower.Longitude = position.X;
        tower.Latitude = position.Y;
        tower.Altitude = position.Z;
        m_towerInstance.States.Add(tower);
        m_linkSource.Add(new LinkSource()
        {
            Guid = guid,
            SmID = smid,
            Description = description,
            IsTower = true
        });
    }

示意gif

在这里插入图片描述

注意事项

  1. 上文主要讲的是绝缘字串的矩阵是相对于杆塔的,如果绝缘子串是独立的矩阵,那么新矩阵的算法可能会有改变。
  2. 需要demo和超图组件包的请给一个邮箱
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值