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

效果如下:

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;
            }

        }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ISUP协议视频平台EasyCVR私有化视频平台新能源汽车充电停车管理方案的创新与实践

在环保意识提升和能源转型的大背景下&#xff0c;新能源汽车作为低碳出行的选择&#xff0c;正在全球迅速推广。但这种快速增长也引发了充电基础设施短缺和停车秩序混乱等挑战&#xff0c;特别是在城市中心和人口密集的居住区&#xff0c;这些问题更加明显。因此&#xff0c;开…

Spring Boot中使用AOP和反射机制设计一个的幂等注解(两种持久化模式),简单易懂教程

该帖子介绍如何设计利用AOP设计幂等注解&#xff0c;且可设置两种持久化模式 1、普通模式&#xff1a;基于redis的幂等注解&#xff0c;持久化程度较低 2、增强模式&#xff1a;基于数据库&#xff08;MySQL&#xff09;的幂等注解&#xff0c;持久化程度高 如果只需要具有re…

算法编程题-网格中的最短路径

算法编程题-网格中的最短路径 原题描述思路简述代码实现[^1]复杂度分析 原题描述 LeetCode 1293 网格中的最短路径&#xff1a;给定一个m * n的网格&#xff0c;网格中的每一个点的值为0&#xff08;无障碍&#xff09;&#xff0c;为1&#xff08;有障碍&#xff09;&#xf…

Xcode 项目内 OC 混编 Python,调用 Python 函数,并获取返回值(基于 python 的 c函数库)

1:新建 Xcode 工程 2:工程添加 Python.framework 1597052861430.jpg 3:在当前工程下新建一个名字为 googleT 的 python 文件(googleT.py) 1597052584962.jpg 在 googleT.py 文件内写入一个测试 python 函数 def lgf_translate( str ):var1 Hello World!print (str var1)retu…

蓝桥杯每日真题 - 第16天

题目&#xff1a;&#xff08;卡牌&#xff09; 题目描述&#xff08;13届 C&C B组C题&#xff09; 解题思路&#xff1a; 题目分析&#xff1a; 有 n 种卡牌&#xff0c;每种卡牌的现有数量为 a[i]&#xff0c;所需的最大数量为 b[i]&#xff0c;还有 m 张空白卡牌。 每…

计算机网络——路由选择算法

路由算法 路由的计算都是以子网为单位计算的——找到从原子网到目标子网的路径 链路状态算法 序号——&#xff08;源路由器&#xff0c;序号&#xff09;——如果发现这个序号重复或者老了——就不扩散 先测量——再泛洪获得路由 路由转发情况 若S——>W是21则不更改——…

Android - Pixel 6a 手机OS 由 Android 15 降级到 Android 14 操作记录

Pixel 6a 手机由 Android 14 升级到 Android 15了&#xff0c;但是由于一些原因又想降级回 Android 14&#xff0c; 能降吗&#xff1f;该怎么降级呢&#xff1f;本篇文章来记述实际操作过程&#xff0c;希望能给想做相同操作的人一些帮助。 答案当然是能降&#xff0c;而且我…

SpringBoot+React养老院管理系统 附带详细运行指导视频

文章目录 一、项目演示二、项目介绍三、运行截图四、主要代码1.入住合同文件上传2.添加和修改套餐的代码3.查看入住记录代码 一、项目演示 项目演示地址&#xff1a; 视频地址 二、项目介绍 项目描述&#xff1a;这是一个基于SpringBootReact框架开发的养老院管理系统。首先…

Ubuntu安装ollama,并运行ollama和通义千问,使用gradio做界面

Ubuntu安装ollama&#xff0c;并运行ollama和通义千问 安装ollama方式一&#xff1a;方式二 下载安装模型运行大模型运行ollama服务前端的实现python环境安装修改pip国内源前端页面搭建测试前后端联通设计完整的ui 安装ollama 方式一&#xff1a; 访问网站连接&#xff0c;选…

【微软:多模态基础模型】(3)视觉生成

欢迎关注[【youcans的AGI学习笔记】](https://blog.csdn.net/youcans/category_12244543.html&#xff09;原创作品 【微软&#xff1a;多模态基础模型】&#xff08;1&#xff09;从专家到通用助手 【微软&#xff1a;多模态基础模型】&#xff08;2&#xff09;视觉理解 【微…

前端研发高德地图,如何根据经纬度获取地点名称和两点之间的距离?

地理编码与逆地理编码 引入插件&#xff0c;此示例采用异步引入&#xff0c;更多引入方式 https://lbs.amap.com/api/javascript-api-v2/guide/abc/plugins AMap.plugin("AMap.Geocoder", function () {var geocoder new AMap.Geocoder({city: "010", /…

Linux上使用SELinux保护网络服务

前言 SELinux&#xff08;Security-Enhanced Linux&#xff09;是一种安全模块&#xff0c;用于增强基于 Linux 的操作系统的安全性。 它通过强制访问控制&#xff08;MAC&#xff09;机制来限制进程和用户对系统资源的访问权限&#xff0c;从而防止未经授权的操作。 在 SELin…

【Linux】僵尸进程、进程状态简介

本文内容均来自个人笔记并重新梳理&#xff0c;如有错误欢迎指正&#xff01; 如果对您有帮助&#xff0c;烦请点赞、关注、转发、订阅专栏&#xff01; 专栏订阅入口 | 精选文章 | Kubernetes | Docker | Linux | 羊毛资源 | 工具推荐 | 往期精彩文章 【Docker】&#xff08;全…

uniapp 选择 省市区 省市 以及 回显

从gitee仓库可以拿到demo 以及 json省市区 文件 // 这是组件部分 <template><uni-popup ref"popup" type"bottom"><view class"popup"><view class"picker-btn"><view class"left" click"…

Unity Dots下的动画合批工具:GPU ECS Animation Baker

书接上文&#xff0c;为了实现大批量物体的生成&#xff0c;我们准备使用Unity最新的dots系统&#xff0c;在该系统下找到了动画解决方案&#xff1a;GPU ECS Animation Baker。 导入的同时&#xff0c;也需要导入以下两个插件&#xff0c;否则会提示报错&#xff1a; PS&…

windows上部署flask程序

文章目录 前言一、准备工作二、配置 Gunicorn 或 uWSGI1.安装 Waitress2.修改启动文件来使用 Waitress 启动 Flask 应用3.配置反向代理&#xff08;可选&#xff09;4.启动程序访问 三.Flask 程序在 Windows 启动时自动启动1.使用 nssm&#xff08;Non-Sucking Service Manager…

共享单车管理系统项目学习实战

前言 Spring Boot Vue前后端分离 前端&#xff1a;Vue&#xff08;CDN&#xff09; Element axios(前后端交互) BaiDuMap ECharts(图表展示) 后端&#xff1a;Spring Boot Spring MVC(Web) MyBatis Plus(数据库) 数据库:MySQL 验证码请求

python中Pandas操作excel补全内容

补全ID、InStore、Date import random from datetime import datetime, timedeltaimport pandas as pdfile_path r"C:\Users\xb\Desktop\Books_1.xlsx" books pd.read_excel(iofile_path, skiprows3, usecols"C:F", dtype{"ID": str, "I…

40分钟学 Go 语言高并发:Goroutine基础与原理

Day 03 - goroutine基础与原理 1. goroutine创建和调度 1.1 goroutine基本特性 特性说明轻量级初始栈大小仅2KB&#xff0c;可动态增长调度方式协作式调度&#xff0c;由Go运行时管理创建成本创建成本很低&#xff0c;可同时运行数十万个通信方式通过channel进行通信&#x…

Python学习------第十天

数据容器-----元组 定义格式&#xff0c;特点&#xff0c;相关操作 元组一旦定义&#xff0c;就无法修改 元组内只有一个数据&#xff0c;后面必须加逗号 """ #元组 (1,"hello",True) #定义元组 t1 (1,"hello") t2 () t3 tuple() prin…