主要实现了在模型空间下的得到一个包围所有图元的最小圆,该算法的思路是这样:
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. linux命令--文件目录操作命令

    一.命令的基本格式 1.命令提示符 [root@love2 ~]# []:这是提示符的分隔符号,没有特殊含义. root:显示的是当前的登录用户. @:分隔符号,没有特殊含义.love2:当前系统的主 ...

  2. gRPC asp.net core自定义策略认证

    在GitHub上有个项目,本来是作为自己研究学习.net core的Demo,没想到很多同学在看,还给了很多星,所以觉得应该升成3.0,整理一下,写成博分享给学习.net core的同学们. 项目名称 ...

  3. js数组合并以及对象的遍历

    这是很基础的知识,but,对于一只未系统学习过js,只略懂搬砖的跨界狗,还是经常犯错: 场景:移动端上拉加载更多. 初始数组合并后来请求的数组. 使用concat方法,不过要主要: 使用concat, ...

  4. ubantu删除源码安装文件

    1.在安装目录下执行 make uninstall (如安装目录为/opt/software/opencv3.1.0/release) 2.删除系统相关文件 cd /usr sudo find . - ...

  5. vim常用命令集合(精心整理)

    vim编辑器身为一个强大的linux平台编辑器,我就不多说他强大之处了,直接来简述下常用命令,提高自己使用编辑器的效率. 然后就先说下vim编辑器的模式,有的地方说三种,有的地方说两种,教程是按照两种 ...

  6. Kibana创建索引成功,但一直不显示出来(Fielddata is disabled on text fields by default. Set fielddata=true........)

    现象 把EFK整个集群搭建完成后,通过Kibana操作界面创建索引(如图1),我创建了lile-zabbix*的索引,显示是创建成功了,但是只要我在重新刷新一次,已经创建的索引就“消失了”.后通过查看 ...

  7. 使用boost实现线程池thread pool | boost thread pool example

    本文首发于个人博客https://kezunlin.me/post/f241bd30/,欢迎阅读! boost thread pool example Guide boost thread pool ...

  8. 使用MongoDB的Spring Boot和MongoTemplate教程

    在本教程中,我们将构建一个Spring Boot应用程序,该应用程序演示如何使用MongoTemplate API访问MongoDB数据库中的数据. 对于MongoDB,我们将使用mLab,它提供了M ...

  9. Spring 框架基础(05):事务管理机制,和实现方式

    本文源码:GitHub·点这里 || GitEE·点这里 一.Spring事务管理 1.基础描述 Spring事务管理的本质就是封装了数据库对事务支持的操作,使用JDBC的事务管理机制,就是利用jav ...

  10. 机器学习回顾篇(11):支持向量机(SVM)

    .caret, .dropup > .btn > .caret { border-top-color: #000 !important; } .label { border: 1px so ...