Grasshopper脚本电池处理全站仪数据,生成建筑、线状地物和地形

引入

在使用全站仪时,每次的测量的坐标均可保存在储存中,便于后期内业导入Cass中成图。导出的.dat数据的格式如下(随手编造的数据)
在这里插入图片描述
其中每一行为一个点的数据,用英文逗号隔开,分别表示代号,(空值),X坐标,Y坐标,Z坐标,代号根据自己设定。在这个数据中,我使用FW1表示房屋1;FW2表示房屋2;前加下划线的数据表示线状数据,这里DL表示道路;空代号表示仅仅是测的一个高程点

Cass

将数据导入Cass,展点和点号,看到如下结果
在这里插入图片描述
根据相同代码连接起来,得到测量的两个房子和一条道路
在这里插入图片描述
再生成个DTM搞个等高线,等高距0.5m,看看地形如何
在这里插入图片描述
最后就是各种修图之类的杂七杂八工作了。和这里没啥关系了

Grasshopper

在最近自己看Rhino、Grasshopper的时候,想到能不能配合上脚本电池从原始全站仪数据快速的得到地形、建筑等多种信息呢。答案肯定是可以,就是自己水平还没那么高,先简单记录下今天的成果

  1. 为脚本电池设计了三个输入参数和三个输出结果,如下
    在这里插入图片描述
  • CassData:用于接收.dat文件的路径
  • BuildMax:随机建筑高度的最大值
  • BuildMin:随机建筑高度的最小值
  • LinearFeatures:线状地物
  • SidesOfBuilding:建筑物的侧面(加盖的代码还没参悟怎么写,后期用Grasshopper来加)
  • GCPs:高程点(3D Delaunay Mesh和嵌面的代码也没搞出来,先搞出点,后面再拟合面)
  1. 接下来写了写了脚本后,连好电池,额外使用一个加盖和生成地形,如下(脚本在最后)
    在这里插入图片描述
    就能得到结果了,先看生成的地物,绿色表示选择电池输出的结果。这是线状地物
    在这里插入图片描述
    这是建筑物
    在这里插入图片描述
    这是地形(旋了一下不然看不出来起伏)
    在这里插入图片描述
    大概测的结果已经能看到了,接下来水平有限只能统统烘焙到Rhino处理一波,打开渲染模式(设置是不会设置的,切换就完事)
    在这里插入图片描述
    就这样,比起Cass的平面建筑和等高线还是直观的多,手工操作的地方也并不多。不过麻烦点的就是外业测量的时候建筑闭合的顺序要注意,还有编代号的要有统一

  2. 由于没有都写在脚本,也可以用Cluster打个包。加入Cluster Input和Cluster Output,替换确定的输入输出
    在这里插入图片描述
    然后直接全部选起来,Cluster。还可以改个参数名,设置个图标啥的。右键菜单Properties可以设置。通过File菜单的Create User Object可以变为自己的工具,以后用起来方便,美滋滋
    在这里插入图片描述
    在这里插入图片描述

  3. 脚本思路就是根据下换线和空值区分建筑、线状地物和普通高程点。对建筑的点按顺序进行封闭,拉出随机高度;对线状地物的点按顺序连接(不封闭);导出所有点的Point3d格式的List,用于生产地形。所有的脚本代码如下

  private void RunScript(string CassData, int BuildMax, int BuildMin, ref object LinearFeatures, ref object SidesOfBuilding, ref object GCPs)
  {
    List<Point3d> gcds = new List<Point3d>();
    List<Curve> budbs = new List<Curve>();
    List<Curve> builds = new List<Curve>();
    ReadCassData(CassData, ref gcds, ref budbs, ref builds);
    GCPs = gcds;
    LinearFeatures = budbs;
    SidesOfBuilding = ExBuilds(builds, BuildMax, BuildMin);
  }

  // <Custom additional code> 
  public int ReadCassData(string path, ref List<Point3d> gcds, ref List<Curve> budbs, ref List<Curve> builds)
  {
    int cNum = 0;
    string[] qPoints = File.ReadAllLines(path);  // 读取文件
    List<string> budtp = new List<string>();  // 存储标志
    Dictionary<string,List<Point3d>> budtp2 = new Dictionary<string,List<Point3d>>();  // 分组创建曲线点
    // 每行遍历查找标志的数目
    foreach (var pi in qPoints)
    {
      string[] p = pi.Split(',');  // 分割数据
      if (!budtp.Contains(p[0]) && p[0] != string.Empty)  // 判断标志是否存在,若不存在存储标志
      {
        budtp.Add(p[0]);
      }
    }
    // 标志键对应
    foreach (var item in budtp)
    {
      budtp2.Add(item, new List<Point3d>());
    }
    // 搜索高程和分组存点
    foreach (var pi in qPoints)
    {
      // 保存高程点
      string[] p = pi.Split(',');
      double px = Convert.ToDouble(p[2]);
      double py = Convert.ToDouble(p[3]);
      double pz = Convert.ToDouble(p[4]);
      Point3d gcd = new Point3d(px, py, pz);
      Point3d pmd = new Point3d(px, py, 0);
      gcds.Add(gcd);
      // 分点
      if (budtp2.ContainsKey(p[0]))
      {
        budtp2[p[0]].Add(pmd);
      }
    }
    // 创建曲线
    foreach (var item in budtp2.Keys)
    {
      if (item[0] != '_')
      {
        budtp2[item].Add(budtp2[item][0]);  // 用于封闭
        var c = new PolylineCurve(budtp2[item]);
        builds.Add(c);
      }
      else
      {
        var c = new PolylineCurve(budtp2[item]);
        budbs.Add(c);
      }
    }
    return cNum;
  }

  public List<Surface> ExBuilds(List<Curve> builds, int Rmax, int Rmin)
  {
    List<Surface> result = new List<Surface>();
    Random r = new Random();
    foreach (var item in builds)
    {
      Vector3d dir = new Vector3d(0, 0, 1) * r.Next(Rmin, Rmax);  // 随机Z方向
      var nSrf = Surface.CreateExtrusion(item, dir);  // 拉伸
      result.Add(nSrf);
    }
    return result;
  }
  // </Custom additional code> 

说真的资料真的好少,不知道多久才能写出一节更比六节强的电池。。。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值