乐筑天下

搜索
欢迎各位开发者和用户入驻本平台 尊重版权,从我做起,拒绝盗版,拒绝倒卖 签到、发布资源、邀请好友注册,可以获得银币 请注意保管好自己的密码,避免账户资金被盗
查看: 118|回复: 5

将动态块转换为静态块

[复制链接]
jon

2

主题

6

帖子

2

银币

初来乍到

Rank: 1

铜币
14
发表于 2019-5-12 18:38:32 | 显示全部楼层 |阅读模式
你好,沼泽的巫师们!
当我尝试通过C#将动态块转换为静态块时,我遇到了一个问题,问题是我转换的一些块以错误的旋转结束。
我有一个公司使用的DWG,在这里我运行一个名为“STATIFY”的自定义命令。该命令删除我公司喜欢使用的一些动态块,并从客户给我们的外部DWG中插入新的静态块。由于客户给定的规格,我们生产的DWG需要包含客户提供的静态模块。这使得内置的ConvertToStaticBlock方法无用,因为当您使用ConvertToStaticBlock方法时,您的“新”转换块的名称将是动态块的匿名名称。也就是说,转换后的块获得名称*UXX,而我希望该名称为客户_块_类型_YY。
所以我的STATIFY命令工作得很好,对于某些块,它甚至工作得很完美,但这还不够好。简而言之,我将动态块的块参考值传递给静态块的块参考值。
  1. ...
  2. NewBlockRef.Rotation = OldBlockRef.Rotation
  3. NewBlockRef.Scaling = OldBlockRef.Scaling
  4. ...

在这一点上,我遇到了麻烦,因为当我设置旋转值时,它并不总是正确的。起初,我认为这是因为翻转状态,但仔细检查后,我认为我必须处理的DWG中的动态块有问题。例如,我注意到90度旋转在不同的区块上以不同的方式工作,尽管它不应该这样:


我怀疑这可能是由用户错误引起的,但我认为如果我告诉人们他们必须重做所有的图纸,我将是一个非常不受欢迎的人,而且我认为我接近一个可行的解决方案:
  1. //This line fixes the rotation
  2. NewBlockRef.BlockTableRecord = OldBlockRef.BlockTableRecord
  3. //This next line fixes my problem too
  4. NewBlockRef.BlockTableRecord = OldBlockRef.AnonymousBlockTableRecord
  5. //The following line does NOT fix the rotation
  6. NewBlockRef.BlockTableRecord = OldBlockRef.DynamicBlockTableRecord

不幸的是,这两个修复导致我的新静态块获得匿名块的名称(*UXX,而不是Customer_Block_YY)。当我不设定时:
  1. NewBlockRef.BlockTableRecord = OldBlockRef.BlockTableRecord

我的所有新块都获得了它们应该获得的名称。如果我能够将名称从*UXX更改为CUSTOMER_BLOCK_TYPE_YY,我想我的解决方案将会是完整的,但这不起作用,因为我得到了一个DuplicateNameError错误。我也无法将名称更改为CUSTOMER_BLOCK_TYPE_YY*UXX,因为这会导致InvalidInputError。我怀疑这些错误是由于我对AutoCAD以及BlockReference和BlockTableRecord到底是什么缺乏了解而导致的,而且我也知道语句代码2]
有问题。尽管如此,我的大脑告诉我,我必须在这里有所作为。在
OldBlockRef中必须有一些数据。BlockTableRecord

OldBlockRef。AnonymousBlockTableRecord
这将使我的新块的旋转正确吗?这可能是什么数据,我该如何提取它?例如,我试图检查是否有一个可以从OldBlockRef中提取的转换矩阵,但这也不起作用。
我现在不在我的工作站上,所以我无法访问代码,但是如果有人想尝试一下,我可以在回去工作时发布一些代码。我必须对我发布的代码采取一些预防措施,因为这是一个工作项目,但是如果我能够在沼泽的帮助下让我的代码工作,我显然会写一个工作示例,我可以发布,这样其他人可以从我的错误中学习。

本帖以下内容被隐藏保护;需要你回复后,才能看到!

游客,如果您要查看本帖隐藏内容请回复
回复

使用道具 举报

jon

2

主题

6

帖子

2

银币

初来乍到

Rank: 1

铜币
14
发表于 2019-5-12 20:52:58 | 显示全部楼层

嗨,会不会是你用错了函数?
public virtual void ConvertToStaticBlock();
public virtual void ConvertToStaticBlock(string new block name);
将动态块实例转换为传统(非动态)块。
成功后,动态块特性将冻结在当前值,并且参考不再是动态块。用名称newBlockName定义新块,该名称必须不存在于图形中,并且必须满足普通块参照的所有命名限制。
回复

使用道具 举报

57

主题

559

帖子

13

银币

中流砥柱

Rank: 25

铜币
786
发表于 2019-5-13 03:24:12 | 显示全部楼层
谢谢你的建议!
我已经尝试使用
  1. oldBlkRef.ConvertToStaticBlock(name)

但这也会产生一个DuplicateNameError错误。我想如果我创建一个由匿名块名和我想使用的块名组成的新名称,这个方法会有点用。我仍然认为这种方法有两个局限性:
1)被转换的块不是我的客户的静态块。转换后的块最终成为我公司的动态块,没有动态特性。因此,我必须通过编程来改变转换后的块,使其看起来像静态块,但最终它不会是我想要的静态块。
2)我是AutoCAD开发的新手,我很好奇自己哪里出错了。在我的头脑中,我的方法应该是可行的,我想要理解我目前不理解的东西。
不过,我确实认为您的建议是一个可行的解决方法。所以我试着这样做:
  1. //Turns out having a * in the string I want as a name is what made me get the InalidInputError
  2. oldBlockRef.ConvertToStaticBlock(customerBlockName+anonymousBlockName.Subtring(1))
  3. newBlockRef.Rotation = oldBlockRef.Rotation
  4. ...
  5. newBlockRef.BlockTableRecord = oldBlockRef.BlockTableRecord

现在我有了正确类型的块,其名称为:
Customer _ Block _ YYUXX
。我当然更喜欢这个名字,而不是简单地成为
Customer _ Block _ YY
,但我想这比我迄今为止所做的更接近于一个解决方案,我认为我可以使用这个名字,所以我得到了一个足够好的解决方案。
但这并不完美,我真的想了解我做错了什么,只是为了学习。
BlockRecordTable
包含哪些数据使循环完美地工作?WCS和UCS(我没有这方面的经验)会参与进来吗?为什么我不能创建同名的块?我的意思是,我见过多次出现
Customer_Block_YY
的图纸,只要我不设置
[,我就能创建多次出现
Customer _ Block _ YY
的图块代码6]
回复

使用道具 举报

jon

2

主题

6

帖子

2

银币

初来乍到

Rank: 1

铜币
14
发表于 2019-5-13 05:29:54 | 显示全部楼层
乔恩,
我只是跑过去...
定义块(. NET)
http://help.autodesk.com/view/ACD/2017/ENU/?guid=GUID-DF67671C-101D-4917-808B-DD2C5BE3C7E9
插入块(. NET)
http://help.autodesk.com/view/ACD/2017/ENU/?guid=GUID-2656E245-6EAA-41A3-ABE9-742868182821
尝试吸收这些。
可能有更好的例子,但本质上,在概念上
定义在概念上类似于类定义。
插入实例在概念上类似于类实例,从定义中添加元素并应用缩放、旋转、位置、层等。
一旦你摸索到,它就变得更容易了。
属性是下一步...
欢迎来到TheSwamp
问候,
回复

使用道具 举报

57

主题

559

帖子

13

银币

中流砥柱

Rank: 25

铜币
786
发表于 2019-5-13 12:48:02 | 显示全部楼层
谢谢你的解释,你让我找到了正确的方向,我也想出了一个解决方案。解决方案非常简单,我只需分解动态块并存储分解块的值,而不是动态块的值。
我将在几天内发布解决方案代码/伪代码,以防有人感兴趣。
回复

使用道具 举报

jon

2

主题

6

帖子

2

银币

初来乍到

Rank: 1

铜币
14
发表于 2019-5-13 22:34:51 | 显示全部楼层
>乔恩,你需要经常做这个过程吗
>有多少个街区
在我们使用的DWG上,我认为我们通常有20-100个区块。这些块可以是我们从客户那里得到的任何20种静态块
>您是否能够通过动态设置轻松确定客户端块的名称
这可能不是最好的解决方案,但我有一个带有静态块的DWG和一个带有(未修改的)动态块的DWV。我创建了一个导入这两个DWG的方法,以便创建命名对:
  1. List blockPairs
  2. string[] blockPair
  3. blockPair =  new string[2] {"static_block_XX","dynamic_block_XX"}
  4. blockPairs.Add(blockPair)

当然,还有更多,但这是它的本质。
>如果图形中有多个动态块实例,我假设您会遇到问题
一开始我是这样做的,但我在基恩的博客上找到了一些帮助:
https://www.keanw.com/2012/09/creating-a-selection-filter-that-finds-dynamic-blocks-in-autocad-using-net.html
因此,我的插件在替换动态块时的逻辑基本上是:
  1. //GetDynamicBlockNames() returns names of the format "dynamic_block_XX"
  2. List dynamicBlockNames = GetDynamicBlockNames()
  3. List anonymousNames
  4. foreach(dynamicBlockName in dynamicBlockNames)
  5. {
  6.     //GetAnonymousNames() returns the anonymous names of the format "*UXX"
  7.     anonymousNames = GetAnonymousNames(dynamicBlockName)
  8.     foreach(anonymousName in anonymousNames)
  9.     {
  10.             ReplaceBlock(blockTable[anonymousName])
  11.     }
  12. }

我现在唯一的“问题”是,该插件在重复使用后有时会崩溃。例如,如果用户在动态和静态块之间来回转换5次以上,我有时会随机得到一个AccessViolationError。但我很确定这是AutoCAD的API及其DynamicBlock特性的问题,因为如果我设置动态块的旋转特性而不是链接到旋转的DynamicBlock属性,则不会出现此问题。此外,当我远离DynamicBlockProperty时,我的性能也得到了显著的提高
  1. //The faster and safer way
  2. blkRef.Rotation = Math.PI
  3. //The slower and less safe way
  4. DynamicBlockReferenceProperty rotation= dynamicBlockReferencePropertyCollection[2];
  5. rotation.Value = Math.PI

最后,这是我一直在努力的方法,直到你让我理解了我的问题。
  1. private static void AddBlock(Database db, Transaction acTrans, string nameOfBlockToInsert, BlockReference blockToReplace)
  2. {
  3.             BlockTable acBlockTable = (BlockTable)acTrans.GetObject(db.BlockTableId, OpenMode.ForRead);
  4.             ObjectId acBlkRecId = acBlockTable[nameOfBlockToInsert];
  5.             BlockReference acBlkRef = new BlockReference(blockToReplace.Origin, acBlkRecId);
  6.             DBObjectCollection dbObjectCollection = new DBObjectCollection();
  7.             BlockTableRecord currentSpaceTableRecord = (BlockTableRecord)acTrans.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
  8.         
  9.             Point3d position = new Point3d();
  10.             Vector3d normal = new Vector3d();
  11.             double rotation = 0;
  12.             double scaleX = 1;
  13.             double scaleY = 1;
  14.             //This turned out to be the trick
  15.             blockToReplace.Explode(dbObjectCollection);
  16.             foreach (DBObject dbObj in dbObjectCollection)
  17.             {
  18.                 BlockReference acEnt = (BlockReference) dbObj;
  19.                 //Consider this statement:
  20.                 rotation = acEnt.Rotation;
  21.                 //VS.
  22.                 //rotation = blockToReplace.Rotation
  23.                
  24.                 scaleX = acEnt.ScaleFactors.X;
  25.                 scaleY = acEnt.ScaleFactors.Y;
  26.                 position = acEnt.Position;
  27.                 normal = acEnt.Normal;
  28.                 dbObj.Dispose();
  29.             }
  30.             acBlkRef.ScaleFactors = new Scale3d(scaleX,scaleY,1);
  31.             acBlkRef.Position = position;
  32.             acBlkRef.Rotation = rotation;
  33.             acBlkRef.Normal = normal;
  34.             currentSpaceTableRecord .AppendEntity(acBlkRef);
  35.             acTrans.AddNewlyCreatedDBObject(acBlkRef, true);
  36.             acBlkRef.Dispose();
  37. }

再次感谢您的帮助
回复

使用道具 举报

发表回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

  • 微信公众平台

  • 扫描访问手机版

  • 点击图片下载手机App

QQ|关于我们|小黑屋|乐筑天下 繁体中文

GMT+8, 2025-2-4 08:42 , Processed in 0.168061 second(s), 64 queries .

© 2020-2025 乐筑天下

联系客服 关注微信 帮助中心 下载APP 返回顶部 返回列表