CAD中的四个关系,HardOwner,SoftOwner,HardPointer,SoftPointer

news/2025/1/7 16:36:53/文章来源:https://www.cnblogs.com/yyy2023/p/18649655

起因:

  在学习在CAD中附加自定义的数据的时候,发现的一个知识点。在组码表中,330,340,350,360四个键分别对应四种关系。

  如下图:

  在DataCell里也有类似的操作:

  总结起来,就是在CAD中,我们可以人为地给两个DBObject建立某种关系,即:软指针,硬指针,软所有者,硬所有者。

   后来,在CAD官方的帮助页面找了一下,找到了官方的解释。

官方解释翻译过来是:

  将对象写入DXF或DWG文件时,该对象拥有的所有对象也会被写出。深度克隆操作还递归地复制克隆对象所拥有的每个对象。(参见深度克隆。)硬所有权关系保护所拥有的对象免受清除。
  所有者可以是其对象的硬所有者或软所有者。
  以下是硬所有权的三个例子: 
    数据库对象是其扩展字典的硬所有者。
    块表是模型空间和图纸空间块表记录(但不是其他块表记录)的硬所有者。
    扩展字典是其元素的硬所有者。
  软所有权ID(类型为AcDbSoftOwnershipId)不会保护所拥有的对象免受清除。以下是软所有权的示例:
    在大多数情况下,符号表是其元素的软所有者(例外情况包括块*MODEL_SPACE、*PAPER_SPACE、*PAPER_SPACE0和层0;对于这些元素,符号表维护一个硬引用)。
    词典是其条目的软所有者(但您可以将词典标记为其条目的硬所有者)。
  您的自定义类还可能包含对数据库中其他对象的硬指针或软指针引用。指针是单向链接(也就是说,引用的对象中没有指示指针来源的信息)。一个对象可以指向或被任意数量的其他对象指向。
  硬指针引用保护对象免受清除。例如,实体包含对层的硬指针引用。因此,您无法清除由一个或多个实体指向的图层。当从现有数据库中写出新数据库时(例如,在WBLOCK操作中),所有硬指针都会复制到新数据库中。
   硬指针引用的其他示例
     引线图元包含指向标注样式的硬指针引用。
    文本实体包含对文本样式的硬指针引用。
    标注图元包含指向标注样式的硬指针引用。
    mline实体具有指向mline样式的硬指针引用。
  软指针只是指向对象的指针。它不会保护引用的对象免受清除。
   软指针引用示例
     Xdata引用是软指针。
    持久性反应堆是软指针。
  如果使用软指针引用对象,则应在打开对象之前检查该对象是否仍然存在。

个人理解:

  实际上,上面这段官方解释是分类在ObjectArx-Custom Objects里的,意味着这个知识点主要是在自定义实体中会使用到。而.NET语言不具备自定义实体开发能力,因此使用.NET开发的插件中的运行情况和上述描述不是完全对得上的。
  官方资料显示,一个DBObject只能有一个Owner,除了直属于Database的九大符号表和有名词典外,所有DBObject都应该有个Owner,Owner是这个对象能存在于数据库中的必要条件;因此,要把一个DBObject加入到Database中,一定是指定了一个Owner的。通常情况下,一个DBObject对象的Owner是它的容器对象。比如,模型空间内的一个Entity,它的Owner是模型空间BlockTableRecord;一个LayerTableRecord对象,它的Owner是LayerTable对象;一个附加在Entity上的DBDictionary对象(Entity.ExtensionDictionary),Entity是DBDictionary的Owner,DBDictionary使用SetAt()方法加入的对象,其Owner就是这个DBDictionary。删除一个对象的Owner,这个对象被一并删除,比如:删除一个块表记录,那么该记录下的所有Entity都会被删除;删除一个DBObject,存在它的ExtensionDictionary的所有信息也会被一并删除。
  Own关系是一个双向关系,给一个对象指定了所有者的时候,这个所有者的列表中也应加入这个被所有对象;删除所有者对象会同时删除被所有对象正是通过读取被所有对象列表的方式实现的;删除被所有对象的时候,需要检查它和所有者的关系是硬所有还是软所有,如果是硬所有,则不能删除它。
  在CAD二次开发中,给一个DBObject指定一个Owner的情况应该只会在自定义实体中会用到才对,令人困惑的是这些功能被公开给了.NET语言,实际试用了一下,好像也没报错。
  相比Own关系,Pointer关系就简单灵活多了,就是指定了一个引用,通过这个引用,我们可以迅速地找到另一个DBObject。
  Pointer关系是一个单向关系,引用对象将这个指针存在自己的列表里,被引用的对象不能反向找到引用它的对象。
  硬指针和软指针的区别在于,如果一个对象被一个或多个硬指针指向,那么它将被保护,不被清除;软指针不保护它指向的对象,因此软指针指向的对象在打开之前应该验证它是否仍然存在。
  值得注意的是,在CAD.NET中,“硬指针保护它指向的对象不被清除”这件事和事实有点出入。
  一个Entity对一个图层的引用是一个硬指针,存在某个Entity引用某个图层时,这个图层是无法被Purge命令或者删除命令删除的;我用一个DataTable对一个图层进行硬指针引用得到了同样的结果。但如果我将一个硬指针指向一个Line,这个Line可以被正常地删除,如果把这个Line长度改为0,也可以被Purge命令清除。因此,我判断,CAD内部只针对特定的DBObject对象进行了硬指针引用检查,实际应用中应注意这一点。
  在二次开发的程序中,我们可以把两个DBObject的关系存起来,这个关系可以随CAD环境保存到DWG文件里;下次打开时,可以读取这些关系从而迅速建立自己的数据模型,当然,最好先检查一下这个对象是否存在。

 测试代码:

 1      public static void WriteHardOwnerDataTableDemo()
 2      {
 3          var doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.CurrentDocument;
 4          if (doc == null) return;
 5          var db = doc.Database;
 6          var ed = doc.Editor;
 7          var pResult = ed.GetEntity("选择一个Entity"+"\n");
 8          if (pResult.Status!= Autodesk.AutoCAD.EditorInput.PromptStatus.OK) { ed.WriteMessage("选择Entity失败,退出"+"\n"); return; }
 9          ObjectId ownerId = ObjectId.Null;
10          switch (1)
11          {
12              case 1:
13                  string layerName = "HardOwnerTestLayer";
14                  using (var trans = db.TransactionManager.StartTransaction())
15                  {
16                      var layerTable = trans.GetObject(db.LayerTableId, OpenMode.ForWrite) as LayerTable;
17                      if (!layerTable.Has(layerName))
18                      {
19                          var layer = new LayerTableRecord();
20                          layer.Name = layerName;
21                          layerTable.Add(layer);
22                          trans.AddNewlyCreatedDBObject(layer, true);
23                      }
24                      ownerId = layerTable[layerName];
25                      trans.Commit();
26                  }
27                  break;
28              case 2:
29                  var pResult2 = ed.GetEntity("选择一个要参照的Entity"+"\n");
30                  if (pResult2.Status!= Autodesk.AutoCAD.EditorInput.PromptStatus.OK) { ed.WriteMessage("选择Entity失败,退出"+"\n"); return; }
31                  ownerId = pResult2.ObjectId;
32                  break;
33              case 3:
34 
35                  break;
36              default:
37 
38          }
39 
40 
41          var dataTable = CreatNewDataTable2(ownerId);
42          using (var trans = db.TransactionManager.StartTransaction())
43          {
44              var ent = trans.GetObject(pResult.ObjectId, Autodesk.AutoCAD.DatabaseServices.OpenMode.ForWrite) as Entity;
45              {
46                  //如果ent.ExtensionDictionary没有创建,则创建
47                  if (ent.ExtensionDictionary == ObjectId.Null) ent.CreateExtensionDictionary();
48                  var dicID = ent.ExtensionDictionary;
49                  var dic = trans.GetObject(dicID, OpenMode.ForWrite) as DBDictionary;
50                  dic.SetAt("DataTableDemo2", dataTable);
51                  trans.AddNewlyCreatedDBObject(dataTable, true);
52                  ed.WriteMessage("写入DataTable2成功"+"\n");
53              }
54              trans.Commit();
55          }
56      }
57      private static DataTable CreatNewDataTable2(ObjectId HardShipId)
58      {
59          var dataTable = new DataTable();
60          dataTable.AppendColumn(CellType.CharPtr, "Name");
61          dataTable.AppendColumn(CellType.HardPtrId, "OwnerID");
62          //dataTable.AppendColumn(CellType.HardOwnerId, "OwnerID");
63          var row = new DataCellCollection();
64          var cell1 = new DataCell();
65          cell1.SetString("NameABC");
66          var cell2 = new DataCell();
67          cell2.SetHardPointerId(HardShipId);
68          //cell2.SetHardOwnershipId(HardShipId);
69          row.Add(cell1);
70          row.Add(cell2);
71          //AppendRow()方法的第二个参数是是否对加入的这一行进行检查
72          //具体指数量检查和类型检查
73          dataTable.AppendRow(row, true);
74          return dataTable;
75 
76      }
View Code 

 

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

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

相关文章

如何调整网站的搜索关键词,以提高搜索引擎排名和用户体验?

在优化网站关键词时,需要考虑以下几个方面:关键词研究:使用工具如Google Keyword Planner、Ahrefs或SEMrush进行关键词研究。 分析竞争对手的关键词策略,找出潜在的机会词。 确保关键词与网站内容高度相关,并且符合用户搜索习惯。页面优化:在页面标题(Title Tag)、元描…

kubeadm 快速搭建 Kubernetes 集群

快速搭建 K8s 集群角色 ipk8s-master-01 192.168.111.170k8s-node-01 192.168.111.171k8s-node-02 192.168.111.172服务器需要连接互联网下载镜像软件 版本Docker 24.0.0(CE)Kubernetes 1.28初始化配置 关闭防火墙 systemctl stop firewalld && systemctl disable fi…

特征时序化建模:基于特征缓慢变化维度历史追踪的机器学习模型性能优化方法

我们在工作中经常会遇到一个问题,数据基础设施的设计往往没有充分考虑数据科学的需求。数据仓库或数据湖仓中的大量表格(主要是事实表和维度表)缺乏构建高性能机器学习模型所需的关键字段或结构。其中最显著的局限性在于,大多数表格仅记录观测值的当前状态,而未保留历史记…

Docker安装mysql5.7.240109

docker pull mysql:5.7 docker run Note: 报错:docker: Error response from daemon: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: error mounting "/home/mysql/co…

docker-compose固定网段设置.240109

docker-compose在使用的时候,经常是多个docker组了个内网。而如果不指定内网地址的话,很容易和线下的网段冲突,会造成虽说外部IP和端口都映射好了,但是就是公网无法访问的情况。 解决方案: docker-compose.yml里面,指定network网段。 networks:seafile-net:ipam:config:-…

openEuler欧拉设置git pull免密.240112

使用git config命令在本地全局设置用户名和邮箱git config --global user.name "username":全局添加用户名 git config --global user.email “someone@mail.com”:全局添加邮箱 git config --global credential.helper store: 该命令用于为credential.helper设置…

k8s强制删除pod节点.240123

场景 突然get pod的时候,发现一堆的错误,得把它干掉,否则很不爽。解决方案正常过期的状态,比如Evicted ,用正常指令 kubectl -n jingu get pods | grep Evicted |awk {print$1}|xargs kubectl -n jingu delete pods干不掉的pods,比如Terminating,只能用强制指令 kubectl…

FTP客户端无法正常显示服务器内容的原因分析与解决方法

自从重装系统之后,用户发现通过FTP客户端连接到服务器时,远程目录显示为空。尽管FTP设置中的路径指向正确的位置(如d:\\www\\myweb),但在客户端却看不到任何文件或文件夹。 解决方案:问题 解决方案FTP客户端不显示内容 首先确认FTP服务器是否正常运行,尝试从其他设备或网…

记一次cannot access its superinterface问题的的排查 → 强如Spring也一样写Bug

开心一刻 昨天在幼儿园,领着儿子在办公室跟他班主任聊他的情况 班主任:皓瑟,你跟我聊天是不是紧张呀 儿子:是的,老师 班主任:不用紧张,我虽然是你的班主任,但我也才22岁,你就把我当成班上的女同学 班主任继续补充道:你平时跟她们怎么聊,就跟我怎么聊,男孩子要果然,…

如何在织梦CMS中修改网站地图模板

织梦CMS是一款广泛使用的开源内容管理系统,适用于各种类型的网站。修改网站地图模板可以帮助您更好地控制网站的搜索引擎优化(SEO)。以下是详细的修改步骤和注意事项:登录织梦CMS后台:使用管理员账户登录织梦CMS后台。通常,后台地址为域名/dede或域名/admin。 输入用户名…

如何轻松修改织梦网站的宽度?

修改织梦CMS(DedeCMS)网站的宽度可以通过调整CSS样式来实现。以下是详细步骤:登录后台: 使用管理员账号登录织梦CMS后台。进入模板管理: 在左侧菜单中找到“模板管理”,点击进入。选择模板文件: 在模板管理页面中,找到包含网站布局的模板文件(如index.htm、header.htm…

如何轻松修改公司网站?

修改公司网站是一个重要的维护任务,可以提升网站的吸引力和用户体验。以下是详细步骤:确定修改需求:分析现状: 评估当前网站的优缺点,确定需要修改的部分。 收集反馈: 收集用户反馈和建议,了解用户的需求和期望。 制定计划: 制定详细的修改计划,包括修改的内容、时间表…