当前位置: 首页 > news >正文

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

相关文章:

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

效果如下&#xff1a; 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.T…...

备赛蓝桥杯--算法题目(1)

1. 链表求和 . - 力扣&#xff08;LeetCode&#xff09; class Solution { public:ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {ListNode *head nullptr, *tail nullptr;int carry 0;while (l1 || l2) {int n1 l1 ? l1->val: 0;int n2 l2 ? l2->val:…...

机器学习100道经典面试题库(二)

机器学习100道经典面试题库&#xff08;31-60&#xff09; 在大规模的语料中&#xff0c;挖掘词的相关性是一个重要的问题。以下哪一个信息不能用于确定两个词的相关性。 A、互信息 B、最大熵 C、卡方检验 D、最大似然比 答案&#xff1a;B 解析&#xff1a;最大熵代表了…...

Unet++改进37:添加KACNConvNDLayer(2024最新改进方法)

本文内容:添加KACNConvNDLayer 目录 论文简介 1.步骤一 2.步骤二 3.步骤三 4.步骤四 论文简介 1.步骤一 新建block/kacn_conv.py文件,添加如下代码: import torch import torch.nn as nn##源码地址:https://github.com/SynodicMonth/ChebyKAN class KACNConvNDLaye…...

基于 Levenberg - Marquardt 法的 BP 网络学习改进算法详解

基于 Levenberg - Marquardt 法的 BP 网络学习改进算法详解 一、引言 BP&#xff08;Back Propagation&#xff09;神经网络在众多领域有着广泛应用&#xff0c;但传统 BP 算法存在收敛速度慢、易陷入局部最优等问题。Levenberg - Marquardt&#xff08;LM&#xff09;算法作…...

MySQL 8.0与PostgreSQL 15.8的性能对比

根据搜索结果&#xff0c;以下是MySQL 8.0与PostgreSQL 15.8的性能对比&#xff1a; MySQL 8.0性能特点&#xff1a; MySQL在处理大量读操作时表现出色&#xff0c;其存储引擎InnoDB提供了行级锁定和高效的事务处理&#xff0c;适用于并发读取的场景。MySQL通过查询缓存来提高读…...

qt连接postgres数据库时 setConnectOptions函数用法

连接选项&#xff0c;而这些选项没有直接的方法对应&#xff0c;你可能需要采用以下策略之一&#xff1a; 由于Qt SQL API的限制&#xff0c;你可能需要采用一些变通方法或查阅相关文档和社区资源以获取最新的信息和最佳实践。如果你确实需要设置特定的连接选项&#xff0c;并且…...

MySQL45讲 第二十七讲 主库故障应对:从库切换策略与 GTID 详解——阅读总结

文章目录 MySQL45讲 第二十七讲 主库故障应对&#xff1a;从库切换策略与 GTID 详解一、一主多从架构与主备切换的挑战&#xff08;一&#xff09;一主多从基本结构&#xff08;二&#xff09;主备切换的复杂性 二、基于位点的主备切换&#xff08;一&#xff09;同步位点的概念…...

JavaWeb笔记整理——Spring Task、WebSocket

目录 SpringTask ​cron表达式 WebSocket SpringTask cron表达式 WebSocket...

基于SpringBoot+RabbitMQ完成应⽤通信

前言&#xff1a; 经过上面俩章学习&#xff0c;我们已经知道Rabbit的使用方式RabbitMQ 七种工作模式介绍_rabbitmq 工作模式-CSDN博客 RabbitMQ的工作队列在Spring Boot中实现&#xff08;详解常⽤的⼯作模式&#xff09;-CSDN博客作为⼀个消息队列,RabbitMQ也可以⽤作应⽤程…...

Flutter踩坑记录(一)debug运行生成的项目,不能手动点击运行

问题 IOS14设备&#xff0c;切后台划掉&#xff0c;二次启动崩溃。 原因 IOS14以上 flutter 不支持debugger模式下的二次启动 。 要二次启动需要以release方式编译工程安装至手机。 操作步骤 清理项目&#xff1a;在命令行中运行flutter clean来清理之前的构建文件。重新构…...

React的hook✅

为什么hook必须在组件内的顶层声明&#xff1f; 这是为了确保每次组件渲染时&#xff0c;Hooks 的调用顺序保持一致。React利用 hook 的调用顺序来跟踪各个 hook 的状态。每当一个函数组件被渲染时&#xff0c;所有的 hook 调用都是按照从上到下的顺序依次执行的。React 内部会…...

2024.5 AAAiGLaM:通过邻域分区和生成子图编码对领域知识图谱对齐的大型语言模型进行微调

GLaM: Fine-Tuning Large Language Models for Domain Knowledge Graph Alignment via Neighborhood Partitioning and Generative Subgraph Encoding 问题 如何将特定领域知识图谱直接整合进大语言模型&#xff08;LLM&#xff09;的表示中&#xff0c;以提高其在图数据上自…...

从熟练Python到入门学习C++(record 6)

基础之基础之最后一节-结构体 1.结构体的定义 结构体相对于自定义的一种新的变量类型。 四种定义方式&#xff0c;推荐第一种&#xff1b;第四种适合大量定义&#xff0c;也适合查找&#xff1b; #include <iostream> using namespace std; #include <string.h>…...

jenkins的安装(War包安装)

‌Jenkins是一个开源的持续集成工具&#xff0c;基于Java开发&#xff0c;主要用于监控持续的软件版本发布和测试项目。‌ 它提供了一个开放易用的平台&#xff0c;使软件项目能够实现持续集成。Jenkins的功能包括持续的软件版本发布和测试项目&#xff0c;以及监控外部调用执行…...

WPS 加载项开发说明wpsjs

wpsjs几个常用的CMD命令&#xff1a; 1.打开cmd输入命令测试版本号 npm -v 2.首次安装nodejs&#xff0c;npm默认国外镜像&#xff0c;包下载较慢时&#xff0c;可切换到国内镜像 //下载速度较慢时可切换国内镜像 npm config set registry https://registry.npmmirror.com …...

【Anomaly Detection论文阅读记录】PaDiM与PatchCore模型的区别与联系

PaDiM与PatchCore模型的区别与联系 背景介绍 PADIM(Pretrained Anomaly Detection via Image Matching)和 PatchCore 都是基于深度学习的异常检测方法,主要用于图像异常检测,尤其是在无监督学习设置下。 PADIM 是一种通过利用预训练的视觉模型(例如,ImageNet预训练的卷…...

uni-app Vue3语法实现微信小程序样式穿透uview-plus框架

1 问题描述 我在用 uni-app vue3 语法开发微信小程序时&#xff0c;在项目中使用了 uview-plus 这一开源 UI 框架。在使用 up-text 组件时&#xff0c;想要给它添加一些样式&#xff0c;之前了解到微信小程序存在样式隔离的问题&#xff0c;也在uview-plus官网-注意事项中找到…...

K8S基础概念和环境搭建

K8S的基础概念 1. 什么是K8S K8S的全称是Kubernetes K8S是一个开源的容器编排平台&#xff0c;用于自动化部署、扩缩、管理容器化应用程序。 2. 集群和节点 集群&#xff1a;K8S将多个机器统筹和管理起来&#xff0c;彼此保持通讯&#xff0c;这样的关系称之为集群。 节点…...

[服务器] 腾讯云服务器免费体验,成功部署网站

文章目录 概要整体架构流程概要 腾讯云服务器免费体验一个月。 整体架构流程 腾讯云服务器体验一个月, 选择预装 CentOS 7.5 首要最重要的是: 添加阿里云镜像。 不然国外源速度慢, 且容易失败。 yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/li…...

无机布防火卷帘门价格怎么算?按尺寸定制,按需报价

无机布防火卷帘门作为建筑防火分区的核心设备&#xff0c;价格一直是工程采购的关注重点。很多用户在询价时&#xff0c;会发现不同厂家的报价差异较大&#xff0c;这是因为无机布防火卷帘门的价格并非按统一单价计算&#xff0c;而是完全根据项目的实际需求定制化核算。 &…...

告别命令行!用Python脚本批量管理Docker容器,效率提升不止一点点

告别命令行&#xff01;用Python脚本批量管理Docker容器&#xff0c;效率提升不止一点点每次在终端敲入docker ps、docker stop、docker rm时&#xff0c;你是否想过——当容器数量超过两位数&#xff0c;这种重复劳动是否在消耗你的生命&#xff1f;去年我们团队在迁移微服务架…...

Unity安卓构建72小时实战指南:从零到真机运行

1. 这不是“又一本Unity教程”&#xff0c;而是我带三个新人从零上线第一款安卓游戏的真实路径你点开这个标题&#xff0c;大概率正站在两个路口之间&#xff1a;一边是满屏“30天速成Unity”“零基础做爆款”的短视频封面&#xff0c;一边是你刚下载完Unity Hub、卡在Android …...

Yokogawa AAI835-H50/K4A00模拟输入/输出模块

Yokogawa AAI835-H50/K4A00 模拟输入/输出模块产品特点&#xff1a;通道配置&#xff1a;共8个通道&#xff0c;含4路模拟输入和4路模拟输出。信号类型&#xff1a;所有通道均支持4-20mA标准电流信号。HART通信&#xff1a;支持HART协议&#xff0c;可与智能现场设备双向数字通…...

Arduino PWM转4-20mA工业电流信号:二阶滤波与V/I转换电路设计

1. 项目概述&#xff1a;从PWM到工业标准电流信号在工业自动化、过程控制和传感器领域&#xff0c;4-20 mA电流环是一个几乎无处不在的标准。它用4 mA代表测量值的下限&#xff08;如0C&#xff09;&#xff0c;20 mA代表上限&#xff08;如100C&#xff09;&#xff0c;这种设…...

适合地产人用的中介房源管理系统

在房产经纪行业&#xff0c;房源管理与客源管理是经纪人日常工作的核心&#xff0c;直接影响业务效率与成交转化。选择一套适配行业需求的中介房源管理系统&#xff0c;能帮助中介团队规范流程、降低运营成本、大幅提升业绩。今天我们以客观视角&#xff0c;详细解析全房源系统…...

内存占用3KB!极致瘦身释放MCU无限可能

极致小体积&#xff0c;给工业领域带来了无限的可能&#xff1a;更低硬件成本&#xff0c;更小芯片体积&#xff0c;更低功耗&#xff0c;更高可靠性&#xff0c;让每一颗小MCU都拥有大系统的完整能力。 https://www.bilibili.com/video/BV1eZLi6PEjc/?spm_id_from333.1387.ho…...

巧用对称性与平均值原理:低成本实现高精度电阻分压器校准

1. 项目概述&#xff1a;用数学思维突破测量设备的精度极限在电子实验室里捣鼓精密电路&#xff0c;尤其是涉及到电压基准、信号调理或者高精度ADC前端时&#xff0c;一个绕不开的坎就是精密分压器。你可能在设计一个需要0.1%甚至更高精度的分压网络&#xff0c;但手头的万用表…...

Raspberry Pi Debug Probe:RP2040嵌入式开发的调试利器与实战指南

1. 项目概述&#xff1a;为什么你需要一个Raspberry Pi Debug Probe&#xff1f;如果你玩过树莓派Pico或者任何基于RP2040芯片的开发板&#xff0c;肯定遇到过这样的场景&#xff1a;写好的代码&#xff0c;点一下“上传”&#xff0c;然后……就没有然后了。板子上的LED没按你…...

淘宝淘金币自动化脚本终极指南:如何每天节省25分钟实现智能任务管理

淘宝淘金币自动化脚本终极指南&#xff1a;如何每天节省25分钟实现智能任务管理 【免费下载链接】taojinbi 淘宝淘金币自动执行脚本&#xff0c;包含蚂蚁森林收取能量&#xff0c;芭芭农场全任务&#xff0c;解放你的双手 项目地址: https://gitcode.com/gh_mirrors/ta/taoji…...