autocad 二次开发 最小包围圆算法
主要实现了在模型空间下的得到一个包围所有图元的最小圆,该算法的思路是这样:
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 二次开发 最小包围圆算法的更多相关文章
- AutoCAD二次开发——AutoCAD.NET API开发环境搭建
AutoCAD二次开发工具:1986年AutoLisp,1989年ADS,1990年DCL,1993年ADS-RX,1995年ObjectARX,1996年Active X Automation(CO ...
- matlab练习程序(Ritter‘s最小包围圆)
原始算法是sphere,我这里简化为circle了. Ritter's求最小包围圆为线性算法,因为非常简单,所以应用非常广泛. 该算法求出的圆比最优圆大概会大个5%到20%左右,求最优圆应该可以用Bo ...
- 1,下载和部署开发环境--AutoCAD二次开发
环境需求为: AutoCAD 2020版 ObjectARX SDK 下载地址:https://www.autodesk.com/developer-network/platform-technolo ...
- AutoCad 二次开发 .net 之层表的增加 删除 修改图层颜色 遍历 设置当前层
AutoCad 二次开发 .net 之层表的增加 删除 修改图层颜色 遍历 设置当前层 AutoCad 二次开发 .net 之层表的增加 删除 修改图层颜色 遍历 设置当前层我理解的图层的作用大概是把 ...
- AutoCad 二次开发 文字镜像
AutoCad 二次开发 文字镜像 参考:https://adndevblog.typepad.com/autocad/2013/10/mirroring-a-dbtext-entity.html 在 ...
- AutoCad 二次开发 jig操作之标注跟随线移动
AutoCad 二次开发 jig操作之标注跟随线移动 在autocad当中,我认为的jig操作的意思就是即时绘图的意思,它能够实时的显示出当前的操作,以便我们直观的感受到当前的绘图操作是什么样子会有什 ...
- AutoCAD二次开发-使用ObjectARX向导创建应用程序(HelloWorld例子)
AutoCAD2007+vs2005 首先自己去网上搜索下载AutoCAD2007的ARX开发包. 解压后如下 打开后如下 classmap文件夹为C++类和.net类的框架图,是一个DWG文件. d ...
- 我的AutoCAD二次开发之路 (一)
原帖地址 http://379910987.blog.163.com/blog/static/33523797201011184552167/ 今天在改代码的时候,遇到了AddVertexAt方法的用 ...
- Autocad中使用命令来调用python对Autocad二次开发打包后的exe程序
在Autocad中直接调用Python二次开发程序是有必要的,下面介绍一种方法来实现这个功能: 其基本思路是:先将二次开发的程序打包为可执行程序exe,然后编写lsp文件,该文件写入调用exe程序的语 ...
随机推荐
- shodan 文档学习笔记
Table of Contents 1. Introduction 1.1. All About the Data 1.2. Data Collection 1.3. SSL in Depth 1.3 ...
- 更改input标签的placeholder的样式
主要是要区别不同浏览器的不同css类 在input框中有时想将输入的字和placeholder设为不同的颜色或其它效果,这时就可以用以下代码来对placeholder进行样式设置了. input::- ...
- Entity Framework Core For MySql查询中使用DateTime.Now的问题
背景 最近一直忙于手上澳洲线上项目的整体迁移和升级的准备工作,导致博客和公众号停更.本周终于艰难的完成了任务,借此机会,总结一下项目中遇到的一些问题. EF Core一直是我们团队中中小型项目常用的O ...
- 【Linux系列】Centos7安装Samba并将工作区挂载到win(八)
目的 本文主要介绍以下两点: 一. 安装Samba 二. 挂载到window 演示 一. 安装Samba Samba是基于smb协议的,主要作用是实现跨平台文件传输. 安装 yum install - ...
- Python练习100题
Python练习100题 题目:有1.2.3.4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少? #Filename:001.py cnt = 0#count the sum of res ...
- PyQt5的安装及测试(pycharm)
参考链接:https://www.cnblogs.com/pywjh/articles/9835931.html https://blog.csdn.net/SeekAndFindYou/ar ...
- 防范XSS攻击
原文链接:http://www.cnblogs.com/chenty/p/5136834.html 最近,有个项目突然接到总部的安全漏洞报告,查看后知道是XSS攻击. 问题描述: 在页面上有个隐藏域: ...
- HT Vue 集成
(本文中 dataModel = dm = 数据容器, gv = graphView = g2d = 2D 视图) 初始化项目 使用 vue-cli 生成项目.生成注意以下几个问题 1. 建议手动配置 ...
- yum运行报错:File "/usr/libexec/urlgrabber-ext-down", line 28
[root@sdw1 bin]# vim /usr/libexec/urlgrabber-ext-down 再次执行yum命令,正常下载
- 本地存储常用方式 localStorage, sessionStorage,cookie 的区别 和 服务器存储session
本地存储:把一些信息存储到客户端本地(主要目的有很多,其中有一个就是实现多页面之间的信息共享) 1. 离线缓存(xxx.manifest) H5处理离线缓存还是存在一些硬伤的,所以真实项 ...