主要实现了在模型空间下的得到一个包围所有图元的最小圆,该算法的思路是这样:
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)平方数之和 个人题解

    给定一个非负整数 c ,你要判断是否存在两个整数 a 和 b,使得 a2 + b2 = c. 示例1: 输入: 5 输出: True 解释: 1 * 1 + 2 * 2 = 5 示例2: 输入: 3 ...

  2. ZeroC Ice发送大数据

    继上文,我们使用ZeroC Ice传递大块数据时,通常有两种做法,一种是一次请求,另一种就是分多次请求(,这种做法在官方文档有例子).选哪一种根据需要而定. 当分多次请求来完成一大块数据,到底选择每次 ...

  3. spring、mybatis、事务项目整合,附完整代码和数据库文件

    配置依赖项 pom.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http:/ ...

  4. 攻克数通,斩获云计算!誉天Double HCIE学员考证秘笈揭晓

    不知不觉,已经过了四个月的时间了,我是六月多报名云计算的,本来是奔着邹Sir去的,但是当时邹sir已经上到HCIE的课程了,只能蹭学弟之前的录屏看.等到七月八号,又正式跟了曾曦老师上了一次完整的课程. ...

  5. Android DecorView 与 Activity 绑定原理分析

    一年多以前,曾经以为自己对 View 的绘制已经有了解了,事后发现也只是懂了些皮毛而已.经过一年多的实战,Android 和 Java 基础都有了提升,时机成熟了,是时候该去总结 View 的绘制流程 ...

  6. 🙈羞,Spring Bean 初始化/销毁竟然有这么多姿势

    文章来源:http://1t.click/bfHN 一.前言 日常开发过程有时需要在应用启动之后加载某些资源,或者在应用关闭之前释放资源.Spring 框架提供相关功能,围绕 Spring Bean ...

  7. java运算符详解

    java运算符: 定义:用来指明对于操作数的运算方式 按照操作数数目分类: 单目运算    数目运算    三目运算 a++              a+b           (a>b) ? ...

  8. 给公司写的composer包开发的规范

    版本格式 主版本号.次版本号.修订号 版本号递增规则 主版本号:当你做了不兼容的 API 修改 次版本号:当你做了向下兼容的功能性新增 修订号:当你做了向下兼容的问题修正 先行版本号及版本编译元数据可 ...

  9. Vue 指令总结大全

    1.v-text v-text主要用来更新textContent. <p>{{msg}}</p>与<p v-text="msg2"></p ...

  10. &#128293;《手把手教你》系列练习篇之1-python+ selenium自动化测试(详细教程)

    1.简介 相信各位小伙伴或者同学们通过前面已经介绍了的Python+Selenium基础篇,通过前面几篇文章的介绍和练习,Selenium+Python的webUI自动化测试算是 一只脚已经迈入这个门 ...