038集——quadtree(CAD—C#二次开发入门)

news2024/11/25 21:40:25

效果如下:

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Application = Autodesk.AutoCAD.ApplicationServices.Application;
using System.Runtime.CompilerServices;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.GraphicsInterface;
using System.Drawing;
using Autodesk.AutoCAD.Colors;
namespace AcTools
{

        public class QuadTreeDemo
        {
        [CommandMethod("xx")]
        public static void treedemo()
            {
                 //四叉树用于存储平面物体的位置数据,并根据位置选定指定对象,随机画8000个圆,圆心在(100,100)到(800,800)之间。 
                 //用户指定一个点,选定这个点附近200范围内所有的圆并高亮显示。
                Document dm = Z.doc;
                Random rand = new Random();
                List<Circle> cirs = new List<Circle>();
                //做八千个小圆
                for (int i = 0; i < 8000; i++)
                {
                    Point3d cent = new Point3d(100+ rand.NextDouble() * 800, 100+rand.NextDouble() * 800, 0);
                    Circle cir = new Circle(cent, Vector3d.ZAxis, 1);
                    cir.Radius = 1 + (rand.NextDouble() * (10 - 1));//[1到10)的随机数
                cir.ColorIndex = rand.Next(255);
                cirs.Add(cir);
                }
                Extents3d ext = new Extents3d();
                cirs.ForEach(c => ext.AddExtents(c.GeometricExtents));
                //new 四叉树,把小圆添加到四叉树里,ext是四叉树的整个范围
                QuadTreeNode<Circle> qtree = new QuadTreeNode<Circle>(ext);
                for (int i = 0; i < cirs.Count; i++)
                {
                //添加了圆心和圆的四个象限点并延伸一定距离。所有满足条件的都会选中。
                qtree.AddNode(cirs[i].Center, cirs[i]);
                //qtree.AddNode(new Point3d(cirs[i].GetPointAtParameter(0).X + 400, cirs[i].GetPointAtParameter(0).Y + 300, 0), cirs[i]);
                //qtree.AddNode(new Point3d(cirs[i].GetPointAtParameter(Math.PI / 2).X + 400, cirs[i].GetPointAtParameter(Math.PI / 2).Y + 400, 0), cirs[i]);
                //qtree.AddNode(cirs[i].GeometricExtents.MinPoint , cirs[i]);//包围盒的两个点
                //包围盒最大的的x增大200,相当于这个圆的包围盒最大点的x右移200,如果在指定范围,那么选中,如果右移200不到范围,或超出范围,那么不选中,所以图中会有两个区域被选中
                qtree.AddNode(new Point3d(cirs[i].GeometricExtents.MaxPoint.X+200, cirs[i].GeometricExtents.MaxPoint.Y,0), cirs[i]);
               
            }

                //把圆添加到数据库
                using (Transaction tr = dm.Database.TransactionManager.StartTransaction())
                {
                    BlockTable bt = (BlockTable)tr.GetObject(dm.Database.BlockTableId, OpenMode.ForRead);
                    BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
                    for (int i = 0; i < cirs.Count; i++)
                    {
                        cirs[i].SetDatabaseDefaults();
                        btr.AppendEntity(cirs[i]);
                        tr.AddNewlyCreatedDBObject(cirs[i], true);
                    }
                    tr.Commit();
                }

                ViewTableRecord acView = new ViewTableRecord();
                acView.Height = 1000;
                acView.Width = 1000;
                acView.CenterPoint = new Point2d(500, 500);
                dm.Editor.SetCurrentView(acView);

                //任选一点
                PromptPointResult ppr = dm.Editor.GetPoint("选择一点");
                if (ppr.Status == PromptStatus.OK)
                {
                    Point3d pt = ppr.Value;
                    // 查找这个点周围50范围内的对象 
                    List<Circle> cirsref = qtree.GetNodeRecRange(pt, 50);
                //亮显这些圆
                Z.db.AddCircleModeSpace(pt, 50);
                    cirsref.ForEach(c => c.Highlight());
                }

                /*
                 * 四叉树里可以添加任何对象,比如线,文字,块参照,甚至序号,啥都行,
                 * 只要把对象和点对应上,就是用点来表示这个对象的位置,
                 * 如果一个对象不能用一个点来完全表示他的位置。那么重复添加这个对象,并设置多个点
                 * 比如一个直线的两个端点,或者一条曲线上等分的若干个点。一个文字的四个角点,等等。
                 * 请自由发挥。
                 */

            }
        }

        public class QuadTreeLeaf<T>
        {
            private Point3d pos;
            private T refObject;

            public QuadTreeLeaf(Point3d pos, T obj)
            {
                this.pos = pos;
                refObject = obj;
            }

            public T LeafObject
            {
                get
                {
                    return refObject;
                }
            }

            public Point3d Pos
            {
                get { return pos; }
                set { pos = value; }
            }
        }
        /// <summary>
        /// 四叉树节点
        /// </summary>
        /// <typeparam name="T"></typeparam>
        public class QuadTreeNode<T>
        {
            /// <summary>
            /// 节点拥有的叶子节点
            /// </summary>
            public List<QuadTreeLeaf<T>> items;
            /// <summary>
            /// 节点拥有的分支
            /// </summary>
            public QuadTreeNode<T>[] branch;
            /// <summary>
            /// 节点空间最大容量,受minSize影响
            /// </summary>
            protected int maxItems;
            /// <summary>
            /// 节点空间分割的最小大小(最小宽度,高度)
            /// </summary>
            protected double minSize;

            public const double TOLERANCE = 0.00001f;
            /// <summary>
            /// 节点的空间
            /// </summary>
            //public Rect bounds;
            public Extents3d ext;


            public QuadTreeNode(Extents3d ext, int 每级最多存储数量 = 4, double minSize = -1)
            {
                this.ext = ext;
                //bounds = new Rect(ext.MinPoint.X, ext.MinPoint.Y, ext.MaxPoint.X - ext.MinPoint.X, ext.MinPoint.Y - ext.MinPoint.Y);

                maxItems = 每级最多存储数量;
                this.minSize = minSize;
                items = new List<QuadTreeLeaf<T>>();

            }
            public bool HasChildren()
            {
                if (branch != null)
                    return true;
                else
                    return false;
            }

            /// <summary>
            /// 将节点空间分割4份
            /// </summary>
            protected void Split()
            {
                if (minSize != -1)
                {
                    if ((ext.MaxPoint.X - ext.MinPoint.X) <= minSize && (ext.MaxPoint.Y - ext.MinPoint.Y) <= minSize)
                    {
                        return;
                    }
                }
                var ext4 = ext.Split4();

                branch = new QuadTreeNode<T>[4];
                for (int i = 0; i < 4; i++)
                {
                    branch[i] = new QuadTreeNode<T>(ext4[i], maxItems, minSize);
                }

                foreach (var item in items)
                {
                    AddNode(item);
                }

                items.Clear();
            }

            /// <summary>
            /// 根据坐标获得相应的子空间
            /// </summary>
            /// <param name="pos"></param>
            /// <returns></returns>
            protected QuadTreeNode<T> GetChild(Point3d pos)
            {
                if (ext.Contains(pos))
                {
                    if (branch != null)
                    {
                        for (int i = 0; i < branch.Length; i++)
                            if (branch[i].ext.Contains(pos))
                                return branch[i].GetChild(pos);

                    }
                    else
                        return this;
                }
                return null;
            }
            /// <summary>
            /// 增加叶子节点数据
            /// </summary>
            /// <param name="leaf"></param>
            /// <returns></returns>
            private bool AddNode(QuadTreeLeaf<T> leaf)
            {
                if (branch is null)
                {
                    this.items.Add(leaf);

                    if (this.items.Count > maxItems) Split();
                    return true;
                }
                else
                {
                    QuadTreeNode<T> node = GetChild(leaf.Pos);
                    if (node != null)
                    {
                        return node.AddNode(leaf);
                    }
                }
                return false;
            }
            public bool AddNode(Point3d pos, T obj)
            {
                return AddNode(new QuadTreeLeaf<T>(pos, obj));
            }

            /// <summary>
            /// 可以是空间任意位置,只是根据这个位置找到所在的空间去删除对象
            /// </summary>
            /// <param name="pos"></param>
            /// <param name="obj"></param>
            /// <returns></returns>
            public bool RemoveNode(Point3d pt, T obj)
            {
                if (branch is null)
                {
                    for (int i = 0; i < items.Count; i++)
                    {
                        QuadTreeLeaf<T> qtl = items[i];
                        if (qtl.LeafObject.Equals(obj))
                        {
                            items.RemoveAt(i);
                            return true;
                        }
                    }
                }
                else
                {
                    QuadTreeNode<T> node = GetChild(pt);
                    if (node != null)
                    {
                        return node.RemoveNode(pt, obj);
                    }
                }
                return false;
            }
            public int GetNode(Extents3d ext, ref List<T> nodes)
            {
                Point2d p0 = new Point2d(ext.MinPoint.X, ext.MinPoint.Y);
                Vector3d vt = ext.MaxPoint - ext.MinPoint;
                //Rect rect = new Rect(p0, new Point2d(vt.X, vt.Y));
                if (branch is null)
                {
                    foreach (QuadTreeLeaf<T> item in items)
                    {
                        if (ext.Contains(item.Pos))
                        {
                            nodes.Add(item.LeafObject);
                        }
                    }
                }
                else
                {
                    for (int i = 0; i < branch.Length; i++)
                    {
                        if (branch[i].ext.Overlaps(ext))
                            branch[i].GetNode(ext, ref nodes);
                    }
                }
                return nodes.Count;
            }
            public List<T> GetNode(Extents3d ext)
            {
                List<T> nodes = new List<T>();
                GetNode(ext, ref nodes);
                return nodes;
            }
            /// <summary>
            /// 根据坐标得到坐标附近节点的数据
            /// </summary>
            /// <param name="pos"></param>
            /// <param name="ShortestDistance">离坐标最短距离</param>
            /// <param name="list"></param>
            /// <returns></returns>
            public int GetNodeRecRange(Point3d pos, double ShortestDistance, ref List<T> list)
            {
                double distance;
                if (branch is null)
                {
                    foreach (QuadTreeLeaf<T> leaf in items)
                    {
                        distance = (pos - leaf.Pos).Length;

                        if (distance < ShortestDistance)
                        {
                            list.Add(leaf.LeafObject);
                        }
                    }
                }
                else
                {
                    for (int i = 0; i < branch.Length; i++)
                    {
                        double childDistance = branch[i].ext.PointToExtentsDistance(pos);
                        if (childDistance < ShortestDistance * ShortestDistance)
                        {
                            branch[i].GetNodeRecRange(pos, ShortestDistance, ref list);
                        }
                    }
                }
                return list.Count;
            }
            public List<T> GetNodeRecRange(Point3d pos, double ShortestDistance)
            {
                List<T> list = new List<T>();
                int n = GetNodeRecRange(pos, ShortestDistance, ref list);
                return list;
            }
        }

        public static class EX
        {
            public static List<Extents3d> Split4(this Extents3d ext)
            {
                var x1 = ext.MinPoint.X;
                var x2 = ext.MaxPoint.X;
                var y1 = ext.MinPoint.Y;
                var y2 = ext.MaxPoint.Y;
                var xm = x2 / 2 + x1 / 2;
                var ym = y2 / 2 + y1 / 2;
                Extents3d ext1 = new Extents3d(new Point3d(x1, y1, 0), new Point3d(xm, ym, 0));
                Extents3d ext2 = new Extents3d(new Point3d(x1, ym, 0), new Point3d(xm, y2, 0));
                Extents3d ext3 = new Extents3d(new Point3d(xm, ym, 0), new Point3d(x2, y2, 0));
                Extents3d ext4 = new Extents3d(new Point3d(xm, y1, 0), new Point3d(x2, ym, 0));

                return [ext1, ext2, ext3, ext4];
            }
            public static bool Contains(this Extents3d ext, Point3d pt)
            {
                return pt.X >= ext.MinPoint.X && pt.X <= ext.MaxPoint.X && pt.Y >= ext.MinPoint.Y && pt.Y <= ext.MaxPoint.Y;

            }
            public static bool Overlaps(this Extents3d ext, Extents3d other)
            {
                return other.MaxPoint.X > ext.MinPoint.X && other.MinPoint.X < ext.MaxPoint.X
                    && other.MaxPoint.Y > ext.MinPoint.Y && other.MinPoint.Y < ext.MaxPoint.Y;
            }
            public static Point3d PointToNormalized(Extents3d rectangle, Point3d point)
            {
                return new Point3d(
                    InverseLerp(rectangle.MinPoint.X, rectangle.MinPoint.X, point.X),
                    InverseLerp(rectangle.MinPoint.X, rectangle.MaxPoint.Y, point.Y),
                    0);
            }
            public static double PointToExtentsDistance(this Extents3d ext, Point3d pos)
            {
                double xdisance;
                double ydisance;

                if (ext.MinPoint.X <= pos.X && pos.X <= ext.MaxPoint.X)
                {
                    xdisance = 0;
                }
                else
                {
                    xdisance = Math.Min((Math.Abs(pos.X - ext.MaxPoint.X)), Math.Abs(pos.X - ext.MinPoint.X));
                }

                if (ext.MinPoint.Y <= pos.Y && pos.Y <= ext.MaxPoint.Y)
                {
                    ydisance = 0;
                }
                else
                {
                    ydisance = Math.Min(Math.Abs(pos.Y - ext.MaxPoint.Y), Math.Abs(pos.Y - ext.MinPoint.Y));
                }

                return xdisance * xdisance + ydisance * ydisance;
            }
            public static double InverseLerp(double a, double b, double value)
            {
                if (a != b)
                {
                    return Clamp01((value - a) / (b - a));
                }

                return 0f;
            }
            public static double Lerp(double a, double b, double t)
            {
                return a + (b - a) * Clamp01(t);
            }
            public static double Clamp01(double value)
            {
                if (value < 0)
                {
                    return 0;
                }

                if (value > 1)
                {
                    return 1;
                }

                return value;
            }

        }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2247509.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深入探讨 Puppeteer 如何使用 X 和 Y 坐标实现鼠标移动

背景介绍 现代爬虫技术中&#xff0c;模拟人类行为已成为绕过反爬虫系统的关键策略之一。无论是模拟用户点击、滚动&#xff0c;还是鼠标的轨迹移动&#xff0c;都可以为爬虫脚本带来更高的“伪装性”。在众多的自动化工具中&#xff0c;Puppeteer作为一个无头浏览器控制库&am…

RabbitMQ2:介绍、安装、快速入门、数据隔离

欢迎来到“雪碧聊技术”CSDN博客&#xff01; 在这里&#xff0c;您将踏入一个专注于Java开发技术的知识殿堂。无论您是Java编程的初学者&#xff0c;还是具有一定经验的开发者&#xff0c;相信我的博客都能为您提供宝贵的学习资源和实用技巧。作为您的技术向导&#xff0c;我将…

Linux 下进程基本概念与状态

文章目录 一、进程的定义二、 描述进程-PCBtask_ struct内容分类 三、 进程状态 一、进程的定义 狭义定义&#xff1a;进程是正在运行的程序的实例&#xff08;an instance of a computer program that is being executed&#xff09;。广义定义&#xff1a;进程是一个具有一定…

数据库MYSQL——表的设计

文章目录 前言三大范式&#xff1a;几种实体间的关系&#xff1a;一对一关系&#xff1a;一对多关系&#xff1a;多对多关系&#xff1a; 前言 之前的博客中我们讲解的是关于数据库的增删改查与约束的基本操作&#xff0c; 是在已经创建数据库&#xff0c;表之上的操作。 在实…

开源动态表单form-create-designer 扩展个性化配置的最佳实践教程

在开源低代码表单设计器 form-create-designer 的右侧配置面板里&#xff0c;field 映射规则为开发者提供了强大的工具去自定义和增强组件及表单配置的显示方式。通过这些规则&#xff0c;你可以简单而高效地调整配置项的展示&#xff0c;提升用户体验。 源码地址: Github | G…

面试:请阐述MySQL配置文件my.cnf中参数log-bin和binlog-do-db的作用

大家好&#xff0c;我是袁庭新。星球里的小伙伴去面试&#xff0c;面试官问&#xff1a;MySQL配置文件my.cnf中参数log-bin和binlog-do-db的作用&#xff1f;一脸懵逼&#xff5e;不知道该如何回答。 在MySQL的配置文件my.cnf中&#xff0c;log-bin和binlog-do-db是与二进制日志…

Java语言编程,通过阿里云mongo数据库监控实现数据库的连接池优化

一、背景 线上程序连接mongos超时&#xff0c;mongo监控显示连接数已使用100%。 java程序报错信息&#xff1a; org.mongodb.driver.connection: Closed connection [connectionId{localValue:1480}] to 192.168.10.16:3717 because there was a socket exception raised by…

Hive离线数仓结构分析

Hive离线数仓结构 首先&#xff0c;在数据源部分&#xff0c;包括源业务库、用户日志、爬虫数据和系统日志&#xff0c;这些都是数据的源头。这些数据通过Sqoop、DataX或 Flume 工具进行提取和导入操作。这些工具负责将不同来源的数据传输到基于 Hive 的离线数据仓库中。 在离线…

MySQL1——基本原理和基础操作

文章目录 Mysql数据库1——基本原理和基础操作1. 基本概念2. Mysql体系结构2.1 连接层2.2 服务层2.3 存储引擎层 3. 三级范式与反范式4. 完整性约束4.1 实体完整性约束4.2 参照完整性约束 5. CRUDDDLDMLDCLDQL 6. 高级查询基础查询条件查询分页查询查询结果排序分组聚合查询联表…

【Ubuntu24.04】服务部署(虚拟机)

目录 0 背景1 安装虚拟机1.1 下载虚拟机软件1.2 安装虚拟机软件1.2 安装虚拟电脑 2 配置虚拟机2.1 配置虚拟机网络及运行初始化脚本2.2 配置服务运行环境2.2.1 安装并配置JDK172.2.2 安装并配置MySQL8.42.2.3 安装并配置Redis 3 部署服务4 总结 0 背景 你的服务部署在了你的计算…

Redis 常用数据类型插入性能对比:循环插入 vs. 批量插入

Redis 是一款高性能的键值数据库&#xff0c;其支持多种数据类型&#xff08;String、Hash、List、Set、ZSet、Geo&#xff09;。在开发中&#xff0c;经常会遇到需要插入大量数据的场景。如果逐条插入&#xff0c;性能会显得较低&#xff0c;而采用 Pipeline 批量插入 能大幅提…

uniapp页面样式和布局和nvue教程详解

uniapp页面样式和布局和nvue教程 尺寸单位 uni-app 支持的通用 css 单位包括 px、rpx px 即屏幕像素。rpx 即响应式px&#xff0c;一种根据屏幕宽度自适应的动态单位。以750宽的屏幕为基准&#xff0c;750rpx恰好为屏幕宽度。屏幕变宽&#xff0c;rpx 实际显示效果会等比放大…

Spring AI 框架使用的核心概念

一、模型&#xff08;Model&#xff09; AI 模型是旨在处理和生成信息的算法&#xff0c;通常模仿人类的认知功能。通过从大型数据集中学习模式和见解&#xff0c;这些模型可以做出预测、文本、图像或其他输出&#xff0c;从而增强各个行业的各种应用。 AI 模型有很多种&…

(Keil)MDK-ARM各种优化选项详细说明、实际应用及拓展内容

参考 MDK-ARM各种优化选项详细说明、实际应用及拓展内容 本文围绕MDK-ARM优化选项,以及相关拓展知识(微库、实际应用、调试)进行讲述,希望对你今后开发项目有所帮助。 1 总述 我们所指的优化,主要两方面: 1.代码大小(Size) 2.代码性能(运行时间) 在MDK-ARM中,优…

python成绩分级 2024年6月python二级真题 青少年编程电子学会编程等级考试python二级真题解析

目录 python成绩分级 一、题目要求 1、编程实现 2、输入输出 二、算法分析 三、程序代码 四、程序说明 五、运行结果 六、考点分析 七、 推荐资料 1、蓝桥杯比赛 2、考级资料 3、其它资料 python成绩分级 2024年6月 python编程等级考试二级编程题 一、题目要求 …

苹果Siri将搭载大型语言模型,近屿智能抢占AIGC大模型人才培养高地

据媒体报道&#xff0c;苹果公司正在研发一款全新升级、更加智能且对话能力显著提升的Siri&#xff0c;意在超越OpenAI的ChatGPT及其他语音服务。 报道指出&#xff0c;新一代Siri将搭载更为先进的大型语言模型&#xff08;LLM&#xff09;&#xff0c;苹果期望其能够进行连续…

Ubuntu,openEuler,MySql安装

文章目录 Ubuntu什么是Ubuntu概述Ubuntu版本简介桌面版服务器版 部署系统新建虚拟机安装系统部署后的设置设置root密码关闭防火墙启用允许root进行ssh安装所需软件制作快照 网络配置Netplan概述配置详解配置文件DHCP静态IP设置 软件安装方法apt安装软件作用常用命令配置apt源 d…

【C++动态规划】1411. 给 N x 3 网格图涂色的方案数|1844

本文涉及知识点 C动态规划 LeetCode1411. 给 N x 3 网格图涂色的方案数 提示 你有一个 n x 3 的网格图 grid &#xff0c;你需要用 红&#xff0c;黄&#xff0c;绿 三种颜色之一给每一个格子上色&#xff0c;且确保相邻格子颜色不同&#xff08;也就是有相同水平边或者垂直…

小鹏汽车智慧材料数据库系统项目总成数据同步

1、定时任务处理 2、提供了接口 小鹏方面提供的推送的数据表结构&#xff1a; 这几个表总数为100多万&#xff0c;经过条件筛选过滤后大概2万多条数据 小鹏的人给的示例图&#xff1a; 界面&#xff1a; SQL: -- 查询车型 select bmm.md_material_id, bmm.material_num, bm…

【解决方案】VITE 忽略指定路径的资源

前言 问题起因是因为项目需要引入服务器端的网络图片 而在编写配置时发现&#xff0c;Vite并不支持排除指定前缀的资源 唯一可以排外的只有 Rollup 的 external 选项可以排除外部依赖&#xff0c;但他只能排除外部依赖&#xff0c;不支持指定路径资源或指定前缀的资源&#…