找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 3703|回复: 0

[分享] Painting properties between dynamic AutoCAD blocks using .NET

[复制链接]

已领礼包: 6个

财富等级: 恭喜发财

发表于 2013-6-12 20:27:31 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×

In the last post we looked at some code that essentially dumped out the dynamic properties of dynamic blocks to the command-line. In this post we take it a step further and capture the properties from one dynamic block reference and attempt to apply them to another.
We're going to apply slightly different logic, depending on the situation...
If the block references refer to the same dynamic block definition (i.e. their DynamicBlockTableRecord property contains the same ObjectId) then we'll assume they have the same dynamic properties in the same order. So we'll go through and attempt to copy the property value from the first to the second. This may be a flawed approach, I don't know enough to say whether there are situations where dynamic blocks might have different sets of properties or properties in a different order... if it proves to be a problem, it'd be a simple matter to remove this clause and rely on the second approach for all dynamic block references.
If the block references refer to different dynamic block definitions (i.e. their DynamicBlockTableRecord property contains different ObjectIds) then we use a slightly more elaborate approach: we go through the dynamic properties of the "source" dynamic block reference and store them in a dictionary. We then go through the dynamic properties of the "target" dynamic block reference, and if we find a value in the list we then attempt to apply it to this reference. In this way we should be able to paint properties across blocks - as long as they have the same name - even if they don't have the same overall make-up.
Here's the C# code:
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using System.Collections.Generic;

namespace DynamicBlocks2
{
  public class Commands
  {
    [CommandMethod("ADBP")]
    static public void ApplyDynamicBlockProps()
    {
      Document doc =
        Application.DocumentManager.MdiActiveDocument;
      Database db = doc.Database;
      Editor ed = doc.Editor;

      // Select the source and target block references

      PromptEntityOptions peo =
        new PromptEntityOptions(
          "\nSelect source dynamic block reference: "
        );

      peo.SetRejectMessage("\nEntity is not a block.");
      peo.AddAllowedClass(typeof(BlockReference), false);

      PromptEntityResult per =
        ed.GetEntity(peo);

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

      ObjectId sourceId = per.ObjectId;

      peo.Message =
        "\nSelect target dynamic block reference: ";
      per = ed.GetEntity(peo);

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

      ObjectId targetId = per.ObjectId;

      Transaction tr =
        db.TransactionManager.StartTransaction();
      using (tr)
      {
        // Open our block references: the source (br1)
        // for read and the target (br2) for write

        BlockReference br1 =
          (BlockReference)tr.GetObject(
            sourceId,
            OpenMode.ForRead
          );

        BlockReference br2 =
          (BlockReference)tr.GetObject(
            targetId,
            OpenMode.ForWrite
          );

        // They must both be dynamic block references

        if (br1 != null && br1.IsDynamicBlock &&
            br2 != null && br2.IsDynamicBlock)
        {
          if (br1.DynamicBlockTableRecord ==
              br2.DynamicBlockTableRecord)
          {
            // They use the same block definition - let's assume
            // the properties are in the same order

            DynamicBlockReferencePropertyCollection pc1 =
              br1.DynamicBlockReferencePropertyCollection;

            DynamicBlockReferencePropertyCollection pc2 =
              br2.DynamicBlockReferencePropertyCollection;

            if (pc1.Count == pc2.Count)
            {
              for (int i = 0; i < pc1.Count; i++)
              {
                // Get each property. If they have the same
                // name and are not read-only, attempt to
                // copy the value from the source (prop1)
                // to the target (prop2)

                DynamicBlockReferenceProperty prop1 = pc1,
                                              prop2 = pc2;
                if (prop1.PropertyName == prop2.PropertyName &&
                    !prop1.ReadOnly && !prop2.ReadOnly)
                {
                  prop2.Value = prop1.Value;
                }
              }
            }
          }
          else
          {
            // If the block references refer to different
            // dynamic block definitions, let's collect the
            // properties for the first in a dictionary and
            // attempt to apply them to the second

            DynamicBlockReferencePropertyCollection pc1 =
              br1.DynamicBlockReferencePropertyCollection;

            // Create and populate our dictionary

            Dictionary<string, DynamicBlockReferenceProperty> dict =
              new
              Dictionary<string, DynamicBlockReferenceProperty>();

            foreach (DynamicBlockReferenceProperty prop in pc1)
            {
              if (!prop.ReadOnly &&
                  !dict.ContainsKey(prop.PropertyName))
                dict.Add(prop.PropertyName, prop);
            }

            // Try to copy them to the target block reference's
            // dynamic properties

            DynamicBlockReferencePropertyCollection pc2 =
              br2.DynamicBlockReferencePropertyCollection;

            foreach (DynamicBlockReferenceProperty prop2 in pc2)
            {
              if (!prop2.ReadOnly &&
                  dict.ContainsKey(prop2.PropertyName))
              {
                try
                {
                  DynamicBlockReferenceProperty prop1;
                  if (dict.TryGetValue(
                        prop2.PropertyName, out prop1
                    )
                  )
                  {
                    if (prop2.PropertyTypeCode ==
                        prop1.PropertyTypeCode)
                    {
                      prop2.Value = prop1.Value;
                    }
                  }
                }
                // Expand if you want to diagnose specific issues
                catch { }
              }
            }
          }
        }
        else
        {
          ed.WriteMessage(
            "\nYou need to select two dynamic bock references."
          );
        }
        tr.Commit();
      }
    }
  }
}

Let's see what happens when we put our ADBP command through its paces. Here's our initial state - we have two differently-sized instances of the same dynamic block, plus one instance of a different dynamic block (which shares parameters - the left-hand block is a "Hex Socket Bolt (Side)" while the right-hand block is a "Hex Nut" - both these blocks are available in the "Mechanical - Metric.dwg" sample file in the Samples\Dynamic Blocks folder of your AutoCAD installation).
Here's where we are when we run our ADBP command and select the block reference at the top followed by the block reference at the bottom-left:
So we see it works on references of the same dynamic block definition. Now let's try it, selecting one of the left-hand elevation views on the bolt, followed by the plan view of the nut on the right:
Because they share a dynamic property ("Size", which went from "M10" to "M14"), we were able to "paint" from one to the other.
With AutoCAD 2010 you'll be able to create constraints between geometry - which is a much simpler and more powerful approach - but what we've seen in this post should be of use to people working with dynamic blocks today.
By the way - for those of you with ADN website access - I used this DevNote as inspiration for how to modify properties in a dynamic block reference: How to programmatically insert a dynamic block with attributes containing dynamic parameters? (requires login.) Thanks to Fernando for pointing me to it (at that point in my research I had not quite gotten as far as checking the ADN website... ahem), as well as for suggesting this topic in the first place.





论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|申请友链|Archiver|手机版|小黑屋|辽公网安备|晓东CAD家园 ( 辽ICP备15016793号 )

GMT+8, 2024-5-1 18:28 , Processed in 0.369784 second(s), 30 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表