块与块参照的一些知识——CAD c#二次开发

块(Block Definition)和块参照(Block Reference)是两个重要的概念,它们既有区别又相互联系,以下是详细介绍:

区别

1. 定义和本质

  • 块(Block Definition):它是一个或多个图形对象的集合,这些对象被组合在一起并赋予一个唯一的名称,存储在图形的块表(Block Table)中。块定义是一个抽象的概念,它定义了一组图形元素的结构和属性,但本身并不直接显示在图形中。可以将其看作是一个模板或者蓝图,规定了块的组成元素和外观。
  • 块参照(Block Reference):是块定义在图形中的实际实例。它是基于块定义创建的,代表了块在特定位置、以特定比例和旋转角度插入到图形中的具体表现。块参照是可见的,并且可以在图形中进行移动、复制、删除等操作。

2. 存储方式

  • 块(Block Definition):在图形数据库中,块定义以唯一的名称存储在块表中。无论在图形中插入多少次该块,块定义只存储一次,这有助于节省存储空间。
  • 块参照(Block Reference):每个块参照都有自己独立的插入点、缩放比例、旋转角度等属性,并且在图形数据库中作为独立的对象存储。不同的块参照可以具有不同的属性设置,即使它们基于同一个块定义。

3. 属性特点

  • 块(Block Definition):定义了块的基本属性,如基点、包含的图形对象等。这些属性对于所有基于该块定义创建的块参照都是相同的。一旦块定义被修改,所有引用该块定义的块参照都会相应地更新。
  • 块参照(Block Reference):除了继承块定义的属性外,还具有自己的特定属性,如插入点、缩放比例、旋转角度等。这些属性可以根据需要进行单独设置,使得每个块参照在图形中具有不同的外观和位置。

4. 操作方式

 

  • 块(Block Definition):对块定义的操作主要涉及创建、编辑和删除。创建块定义时,需要选择要包含在块中的图形对象,并指定块的基点和名称。编辑块定义会影响所有基于该定义的块参照。
  • 块参照(Block Reference):对块参照的操作主要包括插入、移动、复制、旋转、缩放等。这些操作只会影响当前的块参照,而不会改变块定义本身。

联系

1. 依赖关系

 

块参照依赖于块定义而存在。没有块定义,就无法创建块参照。每个块参照都必须基于一个已有的块定义来创建,并且在插入到图形中时会继承块定义的基本属性。

2. 更新机制

 

当块定义被修改时,所有引用该块定义的块参照都会自动更新以反映这些变化。例如,如果修改了块定义中的某个图形对象,那么所有基于该块定义的块参照都会相应地更新显示。

3. 数据共享

 

块定义实现了数据的共享。通过将常用的图形组合定义为块,可以在不同的位置多次插入该块的参照,而不需要重复绘制相同的图形对象。这样不仅节省了绘图时间,还减少了图形文件的大小。

 

综上所述,块是一种图形元素的集合定义,而块参照是块定义在图形中的具体实例。

 

 

  • 块定义的基点:指的是在创建块定义时所指定的一个特定点,它是块定义自身的一个属性。在 CAD 中,基点起到了块的 “锚点” 作用,是块进行旋转、缩放以及插入操作的参考点。在 C# 代码里,可借助 BlockTableRecord 类的 Origin 属性来设定和获取该基点。例如:

 

csharp

using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;// 创建块定义
BlockTableRecord blockDef = new BlockTableRecord();
// 设置基点
Point3d basePoint = new Point3d(0, 0, 0);
blockDef.Origin = basePoint;

 

  • 块的位置:通常是指块参照(即块在图形中实际插入的实例)在 CAD 图形中的具体插入点。它明确了块参照在图形空间里的具体位置,会受到插入操作时所指定的插入点坐标的影响。在 C# 代码中,可通过 BlockReference 类的构造函数来指定插入点。例如:

 

 

using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;// 假设 blockId 是块定义的 ObjectId
ObjectId blockId = ...;
// 指定插入点
Point3d insertPoint = new Point3d(10, 10, 0);
BlockReference blockRef = new BlockReference(insertPoint, blockId);

 

 

 

 

2. 作用和影响

 

  • 块定义的基点:主要用于在块的内部操作中提供一个固定的参考点。当对块进行旋转、缩放等操作时,这些操作都会以基点为中心来进行。而且,在插入块时,基点会与指定的插入点对齐。
  • 块的位置:直接决定了块参照在图形中的实际摆放位置。不同的插入点会使块出现在图形的不同地方。

在 CAD 的 C# .NET API 里,BlockTransform 代表的是块参照(BlockReference)相对于其块定义的变换矩阵。变换矩阵是一个 4x4 的矩阵,其用途是描述块在插入到图形时所经历的平移、旋转、缩放等变换。

 BlockTransform 矩阵如下:

 

plaintext

((1,0,0,-11977397.9393674),(0,1,0,1929600.37706195),(0,0,1,0),(0,0,0,1))

这个矩阵可以写成标准的 4x4 矩阵形式:

plaintext

| 1  0  0  -11977397.9393674 |
| 0  1  0   1929600.37706195 |
| 0  0  1   0                |
| 0  0  0   1                |

下面对这个矩阵的各项含义进行详细分析:

1. 缩放和旋转部分

矩阵的左上角 3x3 子矩阵:

plaintext

| 1  0  0 |
| 0  1  0 |
| 0  0  1 |

这代表没有进行缩放和旋转操作。主对角线上的元素 (1, 1, 1) 表明在 X、Y、Z 轴方向上的缩放因子均为 1,也就是没有缩放;而非对角线元素 (0, 0, 0, 0, 0, 0) 表示没有旋转。

2. 平移部分

矩阵的第四列前三个元素:

plaintext

| -11977397.9393674 |
|  1929600.37706195 |
|  0                |

这三个元素分别表示在 X、Y、Z 轴方向上的平移量。在这个例子中,块在 X 轴方向上平移了 -11977397.9393674 个单位,在 Y 轴方向上平移了 1929600.37706195 个单位,在 Z 轴方向上没有平移。

3. 齐次坐标部分

 

矩阵的最后一行 (0, 0, 0, 1) 是齐次坐标的标准形式,在二维和三维变换中用于保持变换的一致性。

 

综上所述,这个 BlockTransform 矩阵表明块在插入时没有进行缩放和旋转,只是在 X 轴方向上向左平移了 11977397.9393674 个单位,在 Y 轴方向上向上平移了 1929600.37706195 个单位。

 

插入块与插入属性块的代码

  public static ObjectId InsertBlock(this Database db, ObjectId blockRecordId, Point3d point, double rotation, double scalefactorX, double scalefactorY, double scalefactorZ){//Scale3d scale = new Scale3d(scalefactorX * 0.03937, scalefactorY * 0.03937, scalefactorZ * 0.03937);Scale3d scale = new Scale3d(scalefactorX , scalefactorY , scalefactorZ );ObjectId btrId = ObjectId.Null;using (Transaction trans = db.TransactionManager.StartTransaction()){BlockTable bt = (BlockTable)trans.GetObject(db.BlockTableId, OpenMode.ForRead);//foreach (var item in bt)//获取模型空间、图纸空间、块名等快表记录名称//{//    BlockTableRecord btr = (BlockTableRecord)item.GetObject(OpenMode.ForRead);//    string na = btr.Name;//}if (bt.Has(blockRecordId)){BlockReference brefe = new BlockReference(point, blockRecordId);brefe.Rotation = rotation;brefe.ScaleFactors = scale;BlockTableRecord btr = (BlockTableRecord)trans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);btrId = btr.AppendEntity(brefe);trans.AddNewlyCreatedDBObject(brefe, true);}trans.Commit();}return btrId;}public static ObjectId InsertAttrBlock(this Database db, ObjectId blockRecordId, Point3d point, double rotation, double scalefactorX, double scalefactorY, double scalefactorZ){Scale3d scale = new Scale3d(scalefactorX * 0.03937, scalefactorY * 0.03937, scalefactorZ * 0.03937);ObjectId btrId = ObjectId.Null;using (Transaction trans = db.TransactionManager.StartTransaction()){BlockTable bt = (BlockTable)trans.GetObject(db.BlockTableId, OpenMode.ForRead);if (bt.Has(blockRecordId)){BlockReference br = new BlockReference(point, blockRecordId);br.Rotation = rotation;br.ScaleFactors = scale;//模型空间的快表记录BlockTableRecord btr = (BlockTableRecord)trans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);btrId = btr.AppendEntity(br);//添加属性定义 属性块的快表记录BlockTableRecord btr2 = (BlockTableRecord)blockRecordId.GetObject(OpenMode.ForRead);if (btr2.HasAttributeDefinitions){foreach (var item in btr2){DBObject obj = item.GetObject(OpenMode.ForRead);if (obj is AttributeDefinition){//声明属性参照AttributeReference attrefe = new AttributeReference();attrefe.SetAttributeFromBlock((AttributeDefinition)obj, br.BlockTransform);br.AttributeCollection.AppendAttribute(attrefe);trans.AddNewlyCreatedDBObject(attrefe, true);}}}trans.AddNewlyCreatedDBObject(br, true);}trans.Commit();}return btrId;}

在AutoCAD中,块参照的**包围盒(Extents3d)仅由其内部几何图元的实际位置决定,与块定义的基点(Origin)无关。以下是关键分析:

 **1. 包围盒的本质**

- **定义**:包围盒是包含所有可见几何图元的最小三维长方体,计算时仅基于图元的顶点坐标。

- **基点作用**:基点是块插入时的定位参考点,不参与包围盒计算(除非基点处存在几何图元)。

 **2. 嵌套块场景分析**

假设块`B`的基点为`(0,0,0)`,但其内部图元(如一个圆)位于`(100,100,0)`:

- **块B的包围盒**:仅包含圆的范围(圆心`(100,100,0)`,半径相关),**不包含基点`(0,0,0)`**。

- **块A中的块B参照**:当块B被插入到块A中时,假设插入点为`(50,50,0)`:

  - 圆的实际位置变为`(50+100,50+100,0) = (150,150,0)`。

  - 包围盒将覆盖该圆的范围(以`(150,150,0)`为中心的区域)。

 

---

 

### **3. 验证方法**

通过以下代码直接获取块参照的包围盒:

```csharp

BlockReference blkRef = ...; // 获取块参照

Extents3d extents = blkRef.Bounds.Value; // 直接获取包围盒

```

无论块定义的基点位置如何,`extents`始终反映**图元在模型空间中的实际位置范围**。

using Autodesk.AutoCAD.ApplicationServices;

using Autodesk.AutoCAD.DatabaseServices;

using Autodesk.AutoCAD.EditorInput;

using Autodesk.AutoCAD.Geometry;

using System.IO;

using System;

 

public class BlockRefInfoExporter

{

    public static void GetBlockReferenceInfo()

    {

        Document doc = Application.DocumentManager.MdiActiveDocument;

        Database db = doc.Database;

        Editor ed = doc.Editor;

 

        // 提示用户输入块参照名称

        PromptStringOptions pso = new PromptStringOptions("\n请输入块参照名称: ");

        PromptResult pr = ed.GetString(pso);

        if (pr.Status != PromptStatus.OK) return;

        string blockName = pr.StringResult;

 

        // 准备输出文件路径

        string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);

        string outputPath = Path.Combine(desktopPath, "BlockRefInfo.txt");

 

        using (Transaction tr = db.TransactionManager.StartTransaction())

        {

            try

            {

                // 打开模型空间块表记录

                BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;

                BlockTableRecord modelSpace = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead) as BlockTableRecord;

 

                using (StreamWriter writer = new StreamWriter(outputPath))

                {

                    writer.WriteLine($"块参照名称: {blockName}");

                    writer.WriteLine("==================================");

 

                    int count = 0;

                    // 遍历模型空间中的实体

                    foreach (ObjectId objId in modelSpace)

                    {

                        Entity ent = tr.GetObject(objId, OpenMode.ForRead) as Entity;

                        if (ent is BlockReference blkRef && blkRef.Name.Equals(blockName, StringComparison.OrdinalIgnoreCase))

                        {

                            count++;

                            // 获取插入点(位置)

                            Point3d position = blkRef.Position;

 

                            // 获取块定义的基点

                            BlockTableRecord btr = tr.GetObject(blkRef.BlockTableRecord, OpenMode.ForRead) as BlockTableRecord;

                            Point3d basePoint = btr.Origin;

 

                            // 获取包围盒范围

                            Extents3d extents = new Extents3d();

                            try

                            {

                                extents = blkRef.Bounds.Value;

                            }

                            catch

                            {

                                extents = new Extents3d(position, position); // 处理空包围盒

                            }

 

                            // 写入信息

                            writer.WriteLine($"实例 {count}:");

                            writer.WriteLine($"插入点位置: X={position.X}, Y={position.Y}, Z={position.Z}");

                            writer.WriteLine($"块定义基点: X={basePoint.X}, Y={basePoint.Y}, Z={basePoint.Z}");

                            writer.WriteLine($"包围盒范围:");

                            writer.WriteLine($" 最小点: X={extents.MinPoint.X}, Y={extents.MinPoint.Y}, Z={extents.MinPoint.Z}");

                            writer.WriteLine($" 最大点: X={extents.MaxPoint.X}, Y={extents.MaxPoint.Y}, Z={extents.MaxPoint.Z}");

                            writer.WriteLine("----------------------------------");

                        }

                    }

 

                    if (count == 0)

                    {

                        writer.WriteLine("未找到匹配的块参照!");

                    }

                }

 

                ed.WriteMessage($"\n成功导出{count}个块参照信息到: {outputPath}");

            }

            catch (Exception ex)

            {

                ed.WriteMessage($"\n错误: {ex.Message}");

            }

            finally

            {

                tr.Commit();

            }

        }

    }

}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Second Me:在 AI 中保留自我的火种丨社区来稿

今天想和所有朋友们分享一种全新的 AI 可能性,Second Me! 2025年了,很多人和我一样,都越来越确信,AGI 的到来只是一个时间问题。 然而我也经常想,当我们所有人,都心甘情愿地为自己“造神” –…

仿新浪微博typecho主题源码

源码介绍 仿新浪微博typecho主题源码,简约美观,适合做个人博客,该源码为主题模板,需要先搭建typecho,然后吧源码放到对应的模板目录下,后台启用即可 源码特点 支持自适应 个性化程度高 可设置背景图、顶…

Ubuntu24搭建k8s高可用集群

Ubuntu24搭建k8s高可用集群 环境信息 主机名IPk8s版本备注vm-master192.168.103.2501.28.2master1vm-master2192.168.103.2491.28.2master2vm-master3192.168.103.2541.28.2master3vm-node1192.168.103.2511.28.2node1vm-node2192.168.103.2521.28.2node2 容器进行时&#xf…

洛谷P1216 [IOI 1994] 数字三角形 Number Triangles(动态规划)

P1216 [IOI 1994] 数字三角形 Number Triangles - 洛谷 代码区&#xff1a; #include<algorithm> #include<iostream>using namespace std; const int R 1005; int dp[R][R]; int arr[R][R]; int main() {int n;cin >> n;for (int i 1; i < n; i) {for…

Spring Boot Actuator 自定义健康检查(附Demo)

目录 前言1. Demo2. 拓展 前言 &#x1f91f; 找工作&#xff0c;来万码优才&#xff1a;&#x1f449; #小程序://万码优才/r6rqmzDaXpYkJZF Spring Boot 的 actuator 提供了应用监控的功能&#xff0c;其中健康检查&#xff08;Health Check&#xff09;是一个重要的部分&…

2025年优化算法:人工旅鼠算法(Artificial lemming algorithm,ALA)

人工旅鼠算法(Artificial lemming algorithm&#xff0c;ALA)是发表在中科院二区期刊“ARTIFICIAL INTELLIGENCE REVIEW”&#xff08;IF&#xff1a;11.7&#xff09;的2025年智能优化算法 01.引言 随着信息技术与工程科学的快速发展&#xff0c;现代优化问题呈现出高维、非线…

「实战指南 」Swift 并发中的任务取消机制

网罗开发 &#xff08;小红书、快手、视频号同名&#xff09; 大家好&#xff0c;我是 展菲&#xff0c;目前在上市企业从事人工智能项目研发管理工作&#xff0c;平时热衷于分享各种编程领域的软硬技能知识以及前沿技术&#xff0c;包括iOS、前端、Harmony OS、Java、Python等…

实验12深度学习

实验12深度学习 一、实验目的 &#xff08;1&#xff09;理解并熟悉深度神经网络的工作原理&#xff1b; &#xff08;2&#xff09;熟悉常用的深度神经网络模型及其应用环境&#xff1b; &#xff08;3&#xff09;掌握Anaconda的安装和设置方法&#xff0c;进一步熟悉Jupyte…

【问题解决】Postman 测试报错 406

现象 Tomcat 日志 org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver.logException Resolved org.springframework.web.HttpMediaTypeNotAcceptableException: No acceptable representation HTTP状态 406 - 不可接收 的报错&#xff0c;核心原因 客…

微信小程序:用户拒绝小程序获取当前位置后的处理办法

【1】问题描述&#xff1a; 小程序在调用 wx.getLocation() 获取用地理位置时&#xff0c;如果用户选择拒绝授权&#xff0c;代码会直接抛出错误。如果再次调用 wx.getLocation() 时&#xff0c;就不会在弹窗询问用户是否允许授权。导致用户想要重新允许获取地理位置时&#x…

【MySQL】内置函数

目录 一、日期时间函数1.1 简单使用1.2 案例实操 二、字符串函数2.1 简单使用2.2 案例实践2.2.1 获取emp表的ename列的字符集2.2.2 要求显示exam_result表中的信息&#xff0c;显示格式&#xff1a;“XXX的语文是XXX分&#xff0c;数学XXX分&#xff0c;英语XXX分”2.2.3 求exa…

模块二 单元4 安装AD+DC

模块二 单元4 安装ADDC 两个任务&#xff1a; 1.安装AD活动目录 2.升级当前服务器为DC域控制器 安装前的准备工作&#xff1a; 确定你要操作的服务器系统&#xff08;Windows server 2022&#xff09;&#xff1b; 之前的服务器系统默认是工作组的模式workgroup模式&#xff08…

卫星互联网智慧杆:开启智能城市新时代​

哇哦&#xff01;在当下这个数字化浪潮正以雷霆万钧之势席卷全球的超酷时代&#xff0c;智慧城市建设已然成为世界各国你追我赶、竞相发力的核心重点领域啦&#xff01;而咱们的卫星互联网智慧杆&#xff0c;作为一项完美融合了卫星通信与物联网顶尖技术的创新结晶&#xff0c;…

ThreadLocal 的详细使用指南

一、ThreadLocal 核心原理 ThreadLocal 是 Java 提供的线程绑定机制&#xff0c;为每个线程维护变量的独立副本。其内部通过 ThreadLocalMap 实现&#xff0c;每个线程的 Thread 对象都有一个独立的 ThreadLocalMap&#xff0c;存储以 ThreadLocal 对象为键、线程局部变量为值…

免费开源的NAS解决方案:TrueNAS

TrueNAS是业内知名的FreeNAS系统的升级版&#xff0c;是一款开源的网络存储系统&#xff0c;具有高性能、稳定性和易用性等优点。 TrueNAS目前有三个版本&#xff0c;分别是TrueNAS CORE、TrueNAS ENTERPRISE、TrueNAS SCALE。其中&#xff0c;TrueNAS CORE基于FreeBSD开发&…

Fisher 信息矩阵公式原理:使用似然估计,二阶导数等知识点

Fisher 信息矩阵公式原理:使用似然估计,二阶导数等知识点 目录 Fisher 信息矩阵公式原理:使用似然估计,二阶导数等知识点Fisher 通过似然估计求解真实数据和权重参数之间的差异**1. Fisher 信息矩阵的定义****2. 计算对数似然函数的二阶导数****3. 代入 Fisher 信息矩阵定义…

自定义myshell(精讲)

我们都知道&#xff0c;我们给Linux下发的指令都是shell帮我们处理并完成的&#xff0c;那么他是怎么完成的呢&#xff1f;不难想到他都是通过环境变量以及程序替换来完成的。我们这一篇文章就手把手来教你怎么自己实现一个简单的shell。 目标&#xff1a; 1.要能处理普通命令 …

HTML图像标签的详细介绍

1. 常用图像格式 格式特点适用场景JPEG有损压缩&#xff0c;文件小&#xff0c;不支持透明适合照片、复杂图像PNG无损压缩&#xff0c;支持透明&#xff08;Alpha通道&#xff09;适合图标、需要透明背景的图片GIF支持动画&#xff0c;最多256色简单动画、低色彩图标WebP谷歌开…

信号的捕捉(操作部分)

目录 信号集和信号屏蔽字 信号集 信号屏蔽字 信号位操作函数 sigemptyset sigaddset sigismember sigprocmask sigpending 手动操作让2号信号屏蔽打印pending 信号处理函数sigaction 我们继续来学习信号的捕捉 信号集和信号屏蔽字 信号集 信号集是存储一组信号的…

CIR-Net:用于 RGB-D 显著性目标检测的跨模态交互与优化(问题)

摘要 问题一&#xff1a;自模态注意力优化单元和跨模态加权优化单元什么意思&#xff1f; 1 优化中间件结构的作用 位置&#xff1a;位于编码器和解码器之间 输入&#xff1a;编码器提取的RGB特征&#xff0c;深度特征以及RGB-D特征。 输出&#xff1a;经过优化的RGB&…