news 2026/3/5 2:37:02

基于.Net 8创建 CAD勘测定界图(四)——填充及拉线标注

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于.Net 8创建 CAD勘测定界图(四)——填充及拉线标注

好的,之前的两篇文章大概介绍了一下关于做这个功能的背景和关于Aspose.CAD For .Net填充无效,转用ACadSharp创建红线、界址点符号、界址点标注以及边长标注的方法,具体看:
基于.Net 8创建 CAD勘测定界图(一)
基于.Net 8创建 CAD勘测定界图(二)
基于.Net 8创建 CAD勘测定界图(三)
那么接下来,我们一步一步开始添加对应的图斑填充和拉线标注

图斑填充

图斑填充的效果要求是实现下图的效果

那么基于这个需求直接开搞就得了,首先先确认填充样式,是下图的这个

这里要注意啊,是ANSI31而不是ANS131,反正当时第一时间被这个编码折腾了挺久的。
那么知道了这个的样式,步骤和之前创建界址点的填充模式一样,甚至比之前的界址点创建还要简单。

绘制轮廓
创建路径
获取样式
填充保存

OK,那么先来第一步,上传的矢量文件中已经有现成的Polygon或者MultiPolygon了,拿到这个要素,转成CAD的LwPolyline(我个人比较习惯这个而不是Ployline,没记错的话,应该是从AutoCAD大概12以后官方都比较推荐这个做2D,如果需要有Z值的,还是乖乖PolyLine比较靠谱)。

  • Step1.创建边界多段线
    varcoords=sonItem.SonGeometry.Coordinates;// 坐标(NTS)varpltList=coords.Select(c=>newXY(c.X,c.Y)).ToList();// 点集ListvarlwPolyline=BuildRedPolyline(pltList);// 创建LwPolyLinelwPolyline.Color=newColor(255,255,255);// 设置颜色lwPolyline.ConstantWidth=0.03;// 线宽lwPolyline.Layer=xzLayer;// 图层doc.ModelSpace.Entities.Add(lwPolyline);
    这里面有个自己的 FunctionBuildRedPolyline主要就是读取坐标点转CAD的过程,之前代码应该也贴过了就不重复水了;
  • Step2.绑定路径
    路径和之前一样
    varboundaryPolyline=newHatch.BoundaryPath.Polyline(lwPolyline.Vertices.Select(v=>newXYZ(v.Location.X,v.Location.Y,v.Bulge)),isClosed:lwPolyline.IsClosed);varpath=newHatch.BoundaryPath();path.Edges.Add(boundaryPolyline);
  • Step3.填充
    varpattern=newHatchPattern("ANSI31");pattern.Lines.Add(newHatchPattern.Line{Angle=MathHelper.DegToRad(45.0),BasePoint=newXY(0,0),// PAT 格式中 offset 是沿线法向的重复偏移,这里直接给出等效的重复向量Offset=newXY(0,10),// 行距为 1,PatternScale 会整体缩放// ANSI31 通常为实线,不需要 dash 断续;如果需要虚线可设置 DashLengths// DashLengths = { 4.0, -2.0 }});varhatch=newHatch{IsSolid=false,Color=newColor(255,255,255),Pattern=pattern,PatternType=HatchPatternType.PatternFill,PatternScale=1.0,PatternAngle=0.0,Layer=xzLayer};hatch.Paths.Add(path);// 添加至少一个位于边界内部的种子点(例如多边形质心或任意内部点)varcentroid=lwPolyline.Vertices.Select(v=>v.Location).Aggregate(newXY(0,0),(acc,p)=>newXY(acc.X+p.X,acc.Y+p.Y));centroid=newXY(centroid.X/lwPolyline.Vertices.Count,centroid.Y/lwPolyline.Vertices.Count);hatch.SeedPoints.Add(centroid);
    这里强调:种子点添加很重要种子点添加很重要种子点添加很重要!重要的事情讲3遍,如果不添加内部种子点,你的填充很有可能失效(几率不明)我测了60几次遇到过10多次,概率不低。

到这里,所有关于图斑填充的问题结束。创建出来的图斑填充效果如下:

至于为什么是白色的,因为每个填充按照不同类型进行填充,我只是用了new Color(255,255,255) // White示例,具体各位需要什么颜色,请使用各位自定义的颜色配置。

拉线标注&中心标注

我得到的需求是:

  • A .小的填充图斑在红线内
  • B. 红线图斑需要中心标注
  • C. 小的填充图斑需要拉线标注

基于这三个需求,开始分别实现拉线标注及中心标注,需要标注的状态示意如下:

分析一下,下面地类名称,上面地块编号 + 面积
可以有2种做法:

  • A .上面的创建下划线文本 + 文本拼接 + 按位置需求创建下方文本
  • B. 创建LwPolyLine + 创建上方文本+创建下方文本

这里说明,我使用的是方法B

拉线标注

按照上面的B方法先拉线:

  • 首先获取需要拉线标注的元素中心点

    varentList=newList<Entity>();varsonGeom=sonItem.SonGeometry;varcenterPoint=sonGeom.Centroid;
  • 计算终点

    varrightPoint=newNetTopologySuite.Geometries.Point(centerPoint.X+98,centerPoint.Y);varrightLine=newNetTopologySuite.Geometries.LineString([newCoordinate(rightPoint.X-40,rightPoint.Y),newCoordinate(rightPoint.X,rightPoint.Y),newCoordinate(rightPoint.X+40,rightPoint.Y)]);varleftPoint=newNetTopologySuite.Geometries.Point(centerPoint.X-98,centerPoint.Y);varleftLine=newNetTopologySuite.Geometries.LineString([newCoordinate(leftPoint.X-40,leftPoint.Y),newCoordinate(leftPoint.X,leftPoint.Y),newCoordinate(leftPoint.X+40,leftPoint.Y)]);varupPoint=newNetTopologySuite.Geometries.Point(centerPoint.X,centerPoint.Y+98);varupLine=newNetTopologySuite.Geometries.LineString([newCoordinate(upPoint.X-40,upPoint.Y),newCoordinate(upPoint.X,upPoint.Y),newCoordinate(upPoint.X+40,upPoint.Y)]);vardownPoint=newNetTopologySuite.Geometries.Point(centerPoint.X,centerPoint.Y-98);vardownLine=newNetTopologySuite.Geometries.LineString([newCoordinate(downPoint.X-40,downPoint.Y),newCoordinate(downPoint.X,downPoint.Y),newCoordinate(downPoint.X+40,downPoint.Y)]);

    我个人比较懒,正常应该是一个动态计算斜率k的终点线,我直接上下左右了。反正原理是这样,需要计算的朋友可以自己设置斜率哈。

  • 方向判断
    按照刚刚创建的4条线,判断哪个方向是最合适的,标注应在红线外。

    varcandidates=newDictionary<string,(NetTopologySuite.Geometries.Point pt,boolinside,XY target)>{["right"]=(rightPoint,fStruct.Geometry.Intersects(rightLine),newXY(rightPoint.X,rightPoint.Y)),["left"]=(leftPoint,fStruct.Geometry.Intersects(leftLine),newXY(leftPoint.X,leftPoint.Y)),["up"]=(upPoint,fStruct.Geometry.Intersects(upLine),newXY(upPoint.X,upPoint.Y)),["down"]=(downPoint,fStruct.Geometry.Intersects(downLine),newXY(downPoint.X,downPoint.Y)),["center"]=(centerPoint,true,newXY(centerPoint.X,centerPoint.Y))};// 找到未包含的方向(若恰有一个为 false,则选该方向)varnotInside=candidates.Where(kv=>!kv.Value.inside).Select(kv=>kv.Key).ToList();varlineCenterPt=newXY();vardir=notInside.Count!=0?notInside[0]:"center";lineCenterPt=candidates[dir].target;

    仍旧日常偷懒,选哪个方向最好应该是可以计算的,反正我还是一个字,懒。

  • 创建文字间的横线
    知道了刚刚创建的多段线的终点,把终点作为横线的终点,创建横线,线长按需

    varconnectLine=newLwPolyline(){Color=newColor(255,255,255),ConstantWidth=0.3,IsClosed=false,Layer=layer};connectLine.Vertices.Add(newLwPolyline.Vertex(newXY(centerPoint.X,centerPoint.Y)));connectLine.Vertices.Add(newLwPolyline.Vertex(newXY(lineCenterPt.X+7.5,lineCenterPt.Y)));entList.Add(connectLine);
  • 创建文字
    创建文字的时候注意中心对齐哈

    varupArea=Math.Round(sonGeom.Area/10000.0,4);vartextUp=newTextEntity{Value=$"{fStruct.DkId}{upArea:F4}hm²",InsertPoint=newXYZ(lineCenterPt.X-30,lineCenterPt.Y+3,0),AlignmentPoint=newXYZ(lineCenterPt.X-30,lineCenterPt.Y+3,0),Color=newColor(255,255,255),Height=6.5,HorizontalAlignment=TextHorizontalAlignment.Center,VerticalAlignment=TextVerticalAlignmentType.Middle,Layer=layer};

    下方文字创建道理同上,Y坐标减去对应值就可以。

到这里,拉线标注创建完成。

中心标注

道理和拉线标注一样,只不过这次不用创建拉线了,直接用NTS或者ACadSharp的元素Center或Centriod都可以,这个点作为文字中间横线的中点。创建方法和之前一样

最终效果

结合之前的3篇文章,创建出来的效果如下:

好了,到这里打印基本大差不差了,下一篇估计就是最后且最麻烦的一篇,打印图廓了,有时间再写吧……就这样,债见。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/27 18:58:16

Kotaemon在华为云上的部署实践:全流程记录

Kotaemon在华为云上的部署实践&#xff1a;全流程记录 在企业智能客服、知识库问答系统日益普及的今天&#xff0c;一个真正“可用”的AI代理不仅要能回答问题&#xff0c;更要答得准、有依据、可维护。然而现实是&#xff0c;许多基于大模型的聊天机器人仍困于“幻觉频发”“…

作者头像 李华
网站建设 2026/3/3 0:16:48

校园便利平台|基于springboot + vue校园便利平台系统(源码+数据库+文档)

校园便利平台 目录 基于springboot vue校园便利平台系统 一、前言 二、系统功能演示 三、技术选型 四、其他项目参考 五、代码参考 六、测试参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 基于springboot vue校园便利平台系统 一、前言 博主介绍&…

作者头像 李华
网站建设 2026/3/1 13:34:36

38、Linux 脚本编程:bc 计算器、数组与特殊技巧

Linux 脚本编程:bc 计算器、数组与特殊技巧 1. bc - 任意精度计算器语言 在处理整数运算时,shell 能满足很多需求,但当需要进行高级数学运算或使用浮点数时,shell 就显得力不从心了。这时可以借助外部程序,比如 bc 。 bc 是许多 Linux 系统上都有的计算器程序,它能…

作者头像 李华
网站建设 2026/3/2 15:42:00

揭秘高亮车灯升级2025年值得推荐的TOP8车灯产品

在2025年&#xff0c;车灯升级已成为车主关注的热点之一&#xff0c;尤其是高亮车灯的选择。作为提升行车安全与舒适性的关键装备&#xff0c;市场上涌现出多款值得推荐的车灯产品。从LED日行灯到高效的激光透镜&#xff0c;这些产品通过先进的技术改善了照明效果和能效。为满足…

作者头像 李华
网站建设 2026/3/4 19:40:10

WSL2 / Ubuntu 下用 SDKMAN 管理多版本 Java(项目级切换,真香)

WSL2 / Ubuntu 下用 SDKMAN 管理多版本 Java&#xff08;项目级切换&#xff0c;真香&#xff09; 在 WSL2 Ubuntu 做 Java 后端开发时&#xff0c;经常会遇到这种组合&#xff1a; 老项目还在 Java 8新项目已经是 Java 17 / 21同一台机器、同一个终端&#xff0c;需要随时切换…

作者头像 李华
网站建设 2026/3/3 23:31:19

从“幻觉”到“诚实”:OpenAI 如何重新定义大模型的不靠谱问题

如果你对 Agent 可信性、模型行为、安全边界、长期对齐问题 感兴趣&#xff0c;欢迎关注 LuhuiDev。 我会在全平台持续更新这个系列&#xff0c;把论文、实验、工程直觉&#xff0c;慢慢拆给你看。OpenAI 如何重新定义大模型的不靠谱问题&#xff1f; 过去两年&#xff0c;几乎…

作者头像 李华