主要实现了在模型空间下的得到一个包围所有图元的最小圆,该算法的思路是这样:
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. SIGCHLD waitpid, 小心子进程结束事件被偷了

    原本项目中依赖子进程执行的地方,都使用jni调用java层的ProcessManager,换了c++ACE框架后,发现这些任务都很慢,调试才发现所有子进程执行的任务都必须等待到reactor超时才返回 ...

  2. Leetcode 25/24 - Reverse Nodes in k-Group

    题目描述 Leetcode 24 题主要考察的链表的反转,而 25 题是 24 的拓展版,加上对递归的考察. 对题目做一下概述: 提供一个链表,给定一个正整数 k, 每 k 个节点一组进行翻转,最后返 ...

  3. JavaWeb04-JSP及会话跟踪技术

    JSP入门 1 JSP概述 1.1 什么是JSP JSP(Java Server Pages)是JavaWeb服务器端的动态资源.它与html页面的作用是相同的,显示数据和获取数据. 1.2 JSP的 ...

  4. 【并发编程】Java对并发编程的支持历史

    本博客系列是学习并发编程过程中的记录总结.由于文章比较多,写的时间也比较散,所以我整理了个目录贴(传送门),方便查阅. 并发编程系列博客传送门 本文转载,原文请点击链接 本章主要对Java并发(Con ...

  5. 【Luogu P3834】可持久化线段树(主席树)

    Luogu P3834 可持久化数据结构就是支持在历史版本上进行查询和修改操作的数据结构. 主席树就是对线段树的改进,使之可持久化. 前置知识:动态开点线段树 我们利用权值(值域)线段树统计区间内的数 ...

  6. MySQL8.0 新特性 Hash Join

    概述&背景 MySQL一直被人诟病没有实现HashJoin,最新发布的8.0.18已经带上了这个功能,令人欣喜.有时候在想,MySQL为什么一直不支持HashJoin呢?我想可能是因为MySQ ...

  7. Bash Shell编程简记

    Shell编程简记 经常在linux环境下开发的同学,难免要使用shell的一些命令或者编写小的脚本,我这里也总结和整理下,自己对Shell的理解和常用的一些shell脚本. 按照目录分为如下3个节: ...

  8. Prometheus Label 标签管理

    目录 前言 配置测试 删除metric值 重新加载配置文件后测试 更换 重新加载配置文件后测试 删除 Label 标签 前言 在prometheus监控体系中.标签label是一个极为重要的参数,考虑 ...

  9. 使用echarts常用问题总结

    1,echarts配合element ui的抽屉插件出现报错,上次解决方法是使用element ui 抽屉的open事件,让在打开事件重新加载,我们项目的需求是点击某个数据,要传递这条数据包含的其他值 ...

  10. 循环神经网络(RNN)的改进——长短期记忆LSTM

     一:vanilla RNN 使用机器学习技术处理输入为基于时间的序列或者可以转化为基于时间的序列的问题时,我们可以对每个时间步采用递归公式,如下,We can process a sequence ...