主要实现了在模型空间下的得到一个包围所有图元的最小圆,该算法的思路是这样:
1.从点集中随机选出两个点作为直径对圆进行初始化。
2.判断下一个点p是否在圆中,如果在则继续本步骤,如果不在则进行步骤3。
3.使用p作为新圆的一个边界点,另一个边界点为距离p最远的圆上的点,使用这两个点作为直径构造新圆。
4.继续步骤2,直到遍历完所有点。
参考:https://blog.csdn.net/u010559586/article/details/90903896
实现出来的效果如图所示:

首先是获得所有的点,包括参照的点和普通实体的点,获取点之后得到的点集去重。如果是块参照要看它的Bounds属性是否有值,有值就取边界值,如果是普通实体就取Entity的Extends属性的边界点。还有如果是标注,就不计入点,因为标注的边界属性得出来的点不准确。我先得到BlockRecord的Bounds边界,然后继续把这个blockRecord遍历了一遍,得到实体。这样做,我是想把块参照也遍历进去,但是我不知道如何区分普通的实体所在的块和有名块,还有可能有匿名的块参照,我区分不了,,就重复遍历了,最后得到的点集去个重就行了。
代码:

 public void GetAllPts()
{ using (var trans = Db.TransactionManager.StartTransaction())
{ BlockTable blkTbl = (BlockTable)trans.GetObject(Db.BlockTableId, OpenMode.ForRead); foreach (ObjectId oId in blkTbl)
{ var rec = trans.GetObject(oId, OpenMode.ForRead) as BlockTableRecord; if (rec != null)
{
//块参照
if (rec.Bounds.HasValue)
{
var ptMin = rec.Bounds.Value.MinPoint;
var ptMax = rec.Bounds.Value.MaxPoint;
var radius = (ptMax - ptMin).Length / 2.0;
listPts.Add(new Point3d((ptMin.X + ptMax.X) / , (ptMin.Y + ptMax.Y) / , ));
listRadius.Add(radius);
}
//实体
foreach (ObjectId entId in rec)
{
var ent = trans.GetObject(entId, OpenMode.ForRead) as Entity; //在计算边界属性时,dimension的不准确,我就跳过了
if ((ent as Dimension) != null)
{
continue;
} if (ent != null)
{
var ptMin = ent.GeometricExtents.MinPoint;
var ptMax = ent.GeometricExtents.MaxPoint; var radius = (ptMax - ptMin).Length / 2.0; listPts.Add(new Point3d((ptMin.X + ptMax.X) / , (ptMin.Y + ptMax.Y) / , ));
listRadius.Add(radius);
}
}
}
}
listPts = listPts.Distinct<Point3d>().ToList();
trans.Commit();
}
}

得到点集之后,就可以写算法了,这里,我先得到第一个圆,如果模型空间上只有一个图元,我就已这个图元的中心做圆心,边界对角线的一半作为半径 构成一个圆返回;如果是只有两个图元,我就以这两个图元的中心点做直径,直径的中点做圆心构成一个圆返回;如果是3个或者3个以上,我就以点集的第一个点,和点集的中间点构成一个圆返回。代码如下:

 public Circle GetFirstCircle()
{
//如果只有一个图,就直接返回这个图元的边界圆
if (listPts.Count == )
{
Circle c = new Circle(listPts[], Vector3d.ZAxis, listRadius[]);
return c;
}
else if (listPts.Count == )
{
var ptMin = listPts[];
var ptMax = listPts[];
var radius = (ptMax - ptMin).Length / 2.0;
var ptCenter = new Point3d((ptMin.X + ptMax.X) / , (ptMin.Y + ptMax.Y) / , ); Circle c = new Circle(ptCenter, Vector3d.ZAxis, radius); return c; }
else
{
var ptMin = listPts[];
var ptMax = listPts[listPts.Count / ];
var radius = (ptMax - ptMin).Length / 2.0;
var ptCenter = new Point3d((ptMin.X + ptMax.X) / , (ptMin.Y + ptMax.Y) / , ); Circle c = new Circle(ptCenter, Vector3d.ZAxis, radius); listPts.Remove(ptMin);
listPts.Remove(ptMax); return c;
}
}

最后是第二步和第三步的算法:

  Database Db = Application.DocumentManager.MdiActiveDocument.Database;
//所有的点集
List<Point3d> listPts = new List<Point3d>();
List<double> listRadius = new List<double>(); [CommandMethod("GetMinC")]
public void GetCircle()
{
listPts.Clear();
listRadius.Clear(); GetAllPts(); Circle minCircle = null;
if (listPts.Count >= )
{
Circle c= GetFirstCircle(); for (int i = ; i < listPts.Count; i++)
{
var pt = listPts[i]; var len = c.Radius; var cCen = c.Center; var len2 = (pt - cCen).Length; //如果pt在圆内,继续下一个点
if (len > len2)
{
continue;
}
else
{
//求圆心和pt点构成的直线和圆的交点,
//并求出pt点离圆最远的那个点pt1或者是Pt2,最后用这两个点构成一个新的圆,继续循环,直到所有的点遍历完
var line = new Line(pt, cCen); Point3dCollection pt3Coll = new Point3dCollection(); c.IntersectWith(line, Intersect.ExtendBoth, pt3Coll, IntPtr.Zero, IntPtr.Zero); var pt1 = pt3Coll[];
var pt2 = pt3Coll[]; var l1 = (pt1 - pt).Length;
var l2 = (pt2 - pt).Length; if (l1 > l2)
{
var center = new Point3d((pt1.X + pt.X) / , (pt1.Y + pt.Y) / , ); c = new Circle(center, Vector3d.ZAxis, l1/);
}
else
{
var center = new Point3d((pt2.X + pt.X) / , (pt2.Y + pt.Y) / , ); c = new Circle(center, Vector3d.ZAxis, l2 / );
}
}
}
minCircle = c;
}
else
{
minCircle = GetFirstCircle();
}
if (minCircle != null)
//加入模型空间
minCircle.ToSpace();
minCircle.Dispose();
}

autocad 二次开发 最小包围圆算法的更多相关文章

  1. AutoCAD二次开发——AutoCAD.NET API开发环境搭建

    AutoCAD二次开发工具:1986年AutoLisp,1989年ADS,1990年DCL,1993年ADS-RX,1995年ObjectARX,1996年Active X Automation(CO ...

  2. matlab练习程序(Ritter‘s最小包围圆)

    原始算法是sphere,我这里简化为circle了. Ritter's求最小包围圆为线性算法,因为非常简单,所以应用非常广泛. 该算法求出的圆比最优圆大概会大个5%到20%左右,求最优圆应该可以用Bo ...

  3. 1,下载和部署开发环境--AutoCAD二次开发

    环境需求为: AutoCAD 2020版 ObjectARX SDK 下载地址:https://www.autodesk.com/developer-network/platform-technolo ...

  4. AutoCad 二次开发 .net 之层表的增加 删除 修改图层颜色 遍历 设置当前层

    AutoCad 二次开发 .net 之层表的增加 删除 修改图层颜色 遍历 设置当前层 AutoCad 二次开发 .net 之层表的增加 删除 修改图层颜色 遍历 设置当前层我理解的图层的作用大概是把 ...

  5. AutoCad 二次开发 文字镜像

    AutoCad 二次开发 文字镜像 参考:https://adndevblog.typepad.com/autocad/2013/10/mirroring-a-dbtext-entity.html 在 ...

  6. AutoCad 二次开发 jig操作之标注跟随线移动

    AutoCad 二次开发 jig操作之标注跟随线移动 在autocad当中,我认为的jig操作的意思就是即时绘图的意思,它能够实时的显示出当前的操作,以便我们直观的感受到当前的绘图操作是什么样子会有什 ...

  7. AutoCAD二次开发-使用ObjectARX向导创建应用程序(HelloWorld例子)

    AutoCAD2007+vs2005 首先自己去网上搜索下载AutoCAD2007的ARX开发包. 解压后如下 打开后如下 classmap文件夹为C++类和.net类的框架图,是一个DWG文件. d ...

  8. 我的AutoCAD二次开发之路 (一)

    原帖地址 http://379910987.blog.163.com/blog/static/33523797201011184552167/ 今天在改代码的时候,遇到了AddVertexAt方法的用 ...

  9. Autocad中使用命令来调用python对Autocad二次开发打包后的exe程序

    在Autocad中直接调用Python二次开发程序是有必要的,下面介绍一种方法来实现这个功能: 其基本思路是:先将二次开发的程序打包为可执行程序exe,然后编写lsp文件,该文件写入调用exe程序的语 ...

随机推荐

  1. 领扣(LeetCode)错误的集合 个人题解

    集合 S 包含从1到 n 的整数.不幸的是,因为数据错误,导致集合里面某一个元素复制了成了集合里面的另外一个元素的值,导致集合丢失了一个整数并且有一个元素重复. 给定一个数组 nums 代表了集合 S ...

  2. hostnamectl命令 主机名 host相关命令

    hostnamectl set-hostname CentOS7设置主机名为CentOS7 hostnamectl status查看主机系统信息 注:host+TAB查阅host相关的所有命令 hos ...

  3. SpringBoot系列教程Web篇之开启GZIP数据压缩

    本篇可以归纳在性能调优篇,虽然内容非常简单,但效果可能出乎预料的好: 分享一个真实案例,我们的服务部署在海外,国内访问时访问服务时,响应有点夸张:某些返回数据比较大的接口,耗时在 600ms+上,然而 ...

  4. HashMap的源码学习以及性能分析

    HashMap的源码学习以及性能分析 一).Map接口的实现类 HashTable.HashMap.LinkedHashMap.TreeMap 二).HashMap和HashTable的区别 1).H ...

  5. [ML机器学习 - Stanford University] - Week1 - 01 Introduction

    What is Machine Learning? Two definitions of Machine Learning are offered. Arthur Samuel described i ...

  6. JavaScript笔记十一

    1.DOM查询 - 通过具体的元素节点来查询 - 元素.getElementsByTagName() - 通过标签名查询当前元素的指定后代元素 - 元素.childNodes - 获取当前元素的所有子 ...

  7. 【Android - 控件】之V - ViewPager的使用

    ViewPager是Android V4包中的一个控件,常常用来作为首页的滚动广告,也常常结合Fragment来实现页面的切换效果. ViewPager和ListView有很多相似的地方,都是适配器控 ...

  8. su命令、sudo命令、限制root远程登录 使用介绍

    第3周第3次课(4月4日) 课程内容:3.7 su命令3.8 sudo命令3.9 限制root远程登录 3.7 su命令 [root@jimmylinux-002 ~]# su - jimmy     ...

  9. IIS+PHP上传文件大小限制和上传时间限制,iis7和iis8上传文件大小限制和上传时间限制

    先说IIS这边的配置                                                                  一:点击站点“管理”下的“配置编辑器”. 二:设 ...

  10. zabbix配置

    一:安装zabbix服务端 1.部署准备 命令:iptables -F     #关闭防火墙命令:systemctl stop firewalld    #关闭防火墙 设置解析,自建yum源 命令:c ...