将动态块转换为静态块
你好,沼泽的巫师们!当我尝试通过C#将动态块转换为静态块时,我遇到了一个问题,问题是我转换的一些块以错误的旋转结束。
我有一个公司使用的DWG,在这里我运行一个名为“STATIFY”的自定义命令。该命令删除我公司喜欢使用的一些动态块,并从客户给我们的外部DWG中插入新的静态块。由于客户给定的规格,我们生产的DWG需要包含客户提供的静态模块。这使得内置的ConvertToStaticBlock方法无用,因为当您使用ConvertToStaticBlock方法时,您的“新”转换块的名称将是动态块的匿名名称。也就是说,转换后的块获得名称*UXX,而我希望该名称为客户_块_类型_YY。
所以我的STATIFY命令工作得很好,对于某些块,它甚至工作得很完美,但这还不够好。简而言之,我将动态块的块参考值传递给静态块的块参考值。
...
NewBlockRef.Rotation = OldBlockRef.Rotation
NewBlockRef.Scaling = OldBlockRef.Scaling
...
在这一点上,我遇到了麻烦,因为当我设置旋转值时,它并不总是正确的。起初,我认为这是因为翻转状态,但仔细检查后,我认为我必须处理的DWG中的动态块有问题。例如,我注意到90度旋转在不同的区块上以不同的方式工作,尽管它不应该这样:
我怀疑这可能是由用户错误引起的,但我认为如果我告诉人们他们必须重做所有的图纸,我将是一个非常不受欢迎的人,而且我认为我接近一个可行的解决方案:
//This line fixes the rotation
NewBlockRef.BlockTableRecord = OldBlockRef.BlockTableRecord
//This next line fixes my problem too
NewBlockRef.BlockTableRecord = OldBlockRef.AnonymousBlockTableRecord
//The following line does NOT fix the rotation
NewBlockRef.BlockTableRecord = OldBlockRef.DynamicBlockTableRecord
不幸的是,这两个修复导致我的新静态块获得匿名块的名称(*UXX,而不是Customer_Block_YY)。当我不设定时:
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中提取的转换矩阵,但这也不起作用。
我现在不在我的工作站上,所以我无法访问代码,但是如果有人想尝试一下,我可以在回去工作时发布一些代码。我必须对我发布的代码采取一些预防措施,因为这是一个工作项目,但是如果我能够在沼泽的帮助下让我的代码工作,我显然会写一个工作示例,我可以发布,这样其他人可以从我的错误中学习。
**** Hidden Message *****
嗨,会不会是你用错了函数?
public virtual void ConvertToStaticBlock();
public virtual void ConvertToStaticBlock(string new block name);
将动态块实例转换为传统(非动态)块。
成功后,动态块特性将冻结在当前值,并且参考不再是动态块。用名称newBlockName定义新块,该名称必须不存在于图形中,并且必须满足普通块参照的所有命名限制。
谢谢你的建议!
我已经尝试使用
oldBlkRef.ConvertToStaticBlock(name)
但这也会产生一个DuplicateNameError错误。我想如果我创建一个由匿名块名和我想使用的块名组成的新名称,这个方法会有点用。我仍然认为这种方法有两个局限性:
1)被转换的块不是我的客户的静态块。转换后的块最终成为我公司的动态块,没有动态特性。因此,我必须通过编程来改变转换后的块,使其看起来像静态块,但最终它不会是我想要的静态块。
2)我是AutoCAD开发的新手,我很好奇自己哪里出错了。在我的头脑中,我的方法应该是可行的,我想要理解我目前不理解的东西。
不过,我确实认为您的建议是一个可行的解决方法。所以我试着这样做:
//Turns out having a * in the string I want as a name is what made me get the InalidInputError
oldBlockRef.ConvertToStaticBlock(customerBlockName+anonymousBlockName.Subtring(1))
newBlockRef.Rotation = oldBlockRef.Rotation
...
newBlockRef.BlockTableRecord = oldBlockRef.BlockTableRecord
现在我有了正确类型的块,其名称为:
Customer _ Block _ YYUXX
。我当然更喜欢这个名字,而不是简单地成为
Customer _ Block _ YY
,但我想这比我迄今为止所做的更接近于一个解决方案,我认为我可以使用这个名字,所以我得到了一个足够好的解决方案。
但这并不完美,我真的想了解我做错了什么,只是为了学习。
BlockRecordTable
包含哪些数据使循环完美地工作?WCS和UCS(我没有这方面的经验)会参与进来吗?为什么我不能创建同名的块?我的意思是,我见过多次出现
Customer_Block_YY
的图纸,只要我不设置
[,我就能创建多次出现
Customer _ Block _ YY
的图块代码6]
乔恩,
我只是跑过去...
定义块(. 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
问候,
谢谢你的解释,你让我找到了正确的方向,我也想出了一个解决方案。解决方案非常简单,我只需分解动态块并存储分解块的值,而不是动态块的值。
我将在几天内发布解决方案代码/伪代码,以防有人感兴趣。 >乔恩,你需要经常做这个过程吗
>有多少个街区
在我们使用的DWG上,我认为我们通常有20-100个区块。这些块可以是我们从客户那里得到的任何20种静态块
>您是否能够通过动态设置轻松确定客户端块的名称
这可能不是最好的解决方案,但我有一个带有静态块的DWG和一个带有(未修改的)动态块的DWV。我创建了一个导入这两个DWG的方法,以便创建命名对:
List blockPairs
string[] blockPair
blockPair =new string {"static_block_XX","dynamic_block_XX"}
blockPairs.Add(blockPair)
当然,还有更多,但这是它的本质。
>如果图形中有多个动态块实例,我假设您会遇到问题
一开始我是这样做的,但我在基恩的博客上找到了一些帮助:
https://www.keanw.com/2012/09/creating-a-selection-filter-that-finds-dynamic-blocks-in-autocad-using-net.html
因此,我的插件在替换动态块时的逻辑基本上是:
//GetDynamicBlockNames() returns names of the format "dynamic_block_XX"
List dynamicBlockNames = GetDynamicBlockNames()
List anonymousNames
foreach(dynamicBlockName in dynamicBlockNames)
{
//GetAnonymousNames() returns the anonymous names of the format "*UXX"
anonymousNames = GetAnonymousNames(dynamicBlockName)
foreach(anonymousName in anonymousNames)
{
ReplaceBlock(blockTable)
}
}
我现在唯一的“问题”是,该插件在重复使用后有时会崩溃。例如,如果用户在动态和静态块之间来回转换5次以上,我有时会随机得到一个AccessViolationError。但我很确定这是AutoCAD的API及其DynamicBlock特性的问题,因为如果我设置动态块的旋转特性而不是链接到旋转的DynamicBlock属性,则不会出现此问题。此外,当我远离DynamicBlockProperty时,我的性能也得到了显著的提高
//The faster and safer way
blkRef.Rotation = Math.PI
//The slower and less safe way
DynamicBlockReferenceProperty rotation= dynamicBlockReferencePropertyCollection;
rotation.Value = Math.PI
最后,这是我一直在努力的方法,直到你让我理解了我的问题。
private static void AddBlock(Database db, Transaction acTrans, string nameOfBlockToInsert, BlockReference blockToReplace)
{
BlockTable acBlockTable = (BlockTable)acTrans.GetObject(db.BlockTableId, OpenMode.ForRead);
ObjectId acBlkRecId = acBlockTable;
BlockReference acBlkRef = new BlockReference(blockToReplace.Origin, acBlkRecId);
DBObjectCollection dbObjectCollection = new DBObjectCollection();
BlockTableRecord currentSpaceTableRecord = (BlockTableRecord)acTrans.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
Point3d position = new Point3d();
Vector3d normal = new Vector3d();
double rotation = 0;
double scaleX = 1;
double scaleY = 1;
//This turned out to be the trick
blockToReplace.Explode(dbObjectCollection);
foreach (DBObject dbObj in dbObjectCollection)
{
BlockReference acEnt = (BlockReference) dbObj;
//Consider this statement:
rotation = acEnt.Rotation;
//VS.
//rotation = blockToReplace.Rotation
scaleX = acEnt.ScaleFactors.X;
scaleY = acEnt.ScaleFactors.Y;
position = acEnt.Position;
normal = acEnt.Normal;
dbObj.Dispose();
}
acBlkRef.ScaleFactors = new Scale3d(scaleX,scaleY,1);
acBlkRef.Position = position;
acBlkRef.Rotation = rotation;
acBlkRef.Normal = normal;
currentSpaceTableRecord .AppendEntity(acBlkRef);
acTrans.AddNewlyCreatedDBObject(acBlkRef, true);
acBlkRef.Dispose();
}
再次感谢您的帮助
页:
[1]