This is one of those funny scenarios... I was just thinking about what to do for my next post - whether to dive into some new features of AutoCAD 2010 (which I will do soon, I promise! :-) or whether to choose something from my ever-increasing to-do list, when I received two emails.
One was from our old friend Fernando Malard, suggesting a topic for a blog post, and the other was from Philippe Leefsma, a member of our DevTech team in Europe, in response to an ADN members question. It provided some code that could eventually form the basis for a response to Fernando's question. Coincidence? Maybe. Am I one to ignore serendipity at work (or to look a gift horse in the mouth)? No!
So, here's Fernando's question:
Just would suggest a new topic for your Blog. An article explaining how to insert a dynamic block and modifying its dynamic properties like point, rotation, dimension. This is something I’m currently working on .NET and I think it would be a very interesting topic to evolve.
Philippe's code is a little different - it shows how to retrieve and display the "dynamic" properties of a dynamic block read in from an external file - but it was a great start for my first step towards Fernando's goal, which was simply to access the dynamic properties for a block selected by the user.
Here's the C# code I based on Philippe's:
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
namespace DynamicBlocks
{
public class Commands
{
[CommandMethod("DBP")]
static public void DynamicBlockProps()
{
Document doc =
Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
PromptStringOptions pso =
new PromptStringOptions(
"\nEnter dynamic block name or enter to select: "
);
pso.AllowSpaces = true;
PromptResult pr = ed.GetString(pso);
if (pr.Status != PromptStatus.OK)
return;
Transaction tr =
db.TransactionManager.StartTransaction();
using (tr)
{
BlockReference br = null;
// If a null string was entered allow entity selection
if (pr.StringResult == "")
{
// Select a block reference
PromptEntityOptions peo =
new PromptEntityOptions(
"\nSelect 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;
// Access the selected block reference
br =
tr.GetObject(
per.ObjectId,
OpenMode.ForRead
) as BlockReference;
}
else
{
// Otherwise we look up the block by name
BlockTable bt =
tr.GetObject(
db.BlockTableId,
OpenMode.ForRead) as BlockTable;
if (!bt.Has(pr.StringResult))
{
ed.WriteMessage(
"\nBlock \"" + pr.StringResult + "\" does not exist."
);
return;
}
// Create a new block reference referring to the block
br =
new BlockReference(
new Point3d(),
bt[pr.StringResult]
);
}
BlockTableRecord btr =
(BlockTableRecord)tr.GetObject(
br.DynamicBlockTableRecord,
OpenMode.ForRead
);
// Call our function to display the block properties
DisplayDynBlockProperties(ed, br, btr.Name);
// Committing is cheaper than aborting
tr.Commit();
}
}
private static void DisplayDynBlockProperties(
Editor ed, BlockReference br, string name
)
{
// Only continue is we have a valid dynamic block
if (br != null && br.IsDynamicBlock)
{
ed.WriteMessage(
"\nDynamic properties for \"{0}\"\n",
name
);
// Get the dynamic block's property collection
DynamicBlockReferencePropertyCollection pc =
br.DynamicBlockReferencePropertyCollection;
// Loop through, getting the info for each property
foreach (DynamicBlockReferenceProperty prop in pc)
{
// Start with the property name, type and description
ed.WriteMessage(
"\nProperty: \"{0}\" : {1}",
prop.PropertyName,
prop.UnitsType
);
if (prop.Description != "")
ed.WriteMessage(
"\n Description: {0}",
prop.Description
);
// Is it read-only?
if (prop.ReadOnly)
ed.WriteMessage(" (Read Only)");
// Get the allowed values, if it's constrained
bool first = true;
foreach (object value in prop.GetAllowedValues())
{
ed.WriteMessage(
(first ? "\n Allowed values: [" : ", ")
);
ed.WriteMessage("\"{0}\"", value);
first = false;
}
if (!first)
ed.WriteMessage("]");
// And finally the current value
ed.WriteMessage(
"\n Current value: \"{0}\"\n",
prop.Value
);
}
}
}
}
}
Here's what happens when we run the DBP command, selecting the "Hex Socket Bolt (Side) - Metric" block from the "Mechanical - Metric.dwg" file in the Samples\Dynamic Blocks folder of your AutoCAD installation.
Command: DBP
Enter dynamic block name or enter to select:
Select dynamic block reference:
Dynamic properties for "Hex Socket Bolt (Side) - Metric"
Property: "d1" : Distance
Allowed values: ["3", "4", "5", "6", "8", "10", "12", "14", "16", "20", "24",
"27", "30", "36"]
Current value: "14"
Property: "Origin" : NoUnits (Read Only)
Current value: "(97.714,-5,0)"
Property: "b" : Distance
Allowed values: ["18", "20", "22", "24", "28", "32", "36", "40", "44", "52",
"57", "60", "65", "66", "72", "73", "84", "85"]
Current value: "40"
Property: "Origin" : NoUnits (Read Only)
Current value: "(100,-3.5,0)"
Property: "k" : Distance
Allowed values: ["3", "4", "5", "6", "8", "10", "12", "14", "16", "20", "24",
"27", "30", "36"]
Current value: "14"
Property: "Origin" : NoUnits (Read Only)
Current value: "(5.64204767561892E-15,-7,0)"
Property: "d2" : Distance
Allowed values: ["5.5", "7", "8.5", "10", "13", "16", "18", "21", "24", "30",
"36", "40", "45", "54"]
Current value: "21"
Property: "Origin" : NoUnits (Read Only)
Current value: "(3.5527136788005E-15,-8,0)"
Property: "Size" : NoUnits
Allowed values: ["M3", "M4", "M5", "M6", "M8", "M10", "M12", "M14"]
Current value: "M14"
Property: "Visibility" : NoUnits
Allowed values: ["M3", "M4", "M5", "M6", "M8", "M10", "M12", "M14"]
Current value: "M14"
Property: "Length (M3)" : Distance
Description: Set the bolt length
Allowed values: ["25", "30", "35", "40", "45", "50", "60"]
Current value: "100"
Property: "Origin" : NoUnits (Read Only)
Current value: "(0,0,0)"
Property: "Length (M4)" : Distance
Description: Set the bolt length
Allowed values: ["30", "35", "40", "45", "50", "60", "70", "80"]
Current value: "100"
Property: "Origin" : NoUnits (Read Only)
Current value: "(0,0,0)"
Property: "Length (M5)" : Distance
Description: Set the bolt length
Allowed values: ["30", "35", "40", "45", "50", "55", "60", "70", "80", "90",
"100"]
Current value: "100"
Property: "Origin" : NoUnits (Read Only)
Current value: "(0,0,0)"
Property: "Length (M6)" : Distance
Description: Set the bolt length
Allowed values: ["35", "40", "45", "50", "55", "60", "65", "70", "75", "80",
"90", "100", "110", "120"]
Current value: "100"
Property: "Origin" : NoUnits (Read Only)
Current value: "(2.25597318603832E-14,0,0)"
Property: "Length (M8)" : Distance
Description: Set the bolt length
Allowed values: ["40", "45", "50", "55", "60", "65", "70", "75", "80", "85",
"90", "100", "110", "120", "130", "140", "150", "160", "180", "200"]
Current value: "100"
Property: "Origin" : NoUnits (Read Only)
Current value: "(2.25597318603832E-14,0,0)"
Property: "Length (M10)" : Distance
Description: Set the bolt length
Allowed values: ["45", "50", "55", "60", "65", "70", "75", "80", "85", "90",
"100", "110", "120", "130", "140", "150", "160", "180", "200"]
Current value: "100"
Property: "Origin" : NoUnits (Read Only)
Current value: "(2.25597318603832E-14,0,0)"
Property: "Length (M12)" : Distance
Description: Set the bolt length
Allowed values: ["55", "60", "65", "70", "75", "80", "85", "90", "100",
"110", "120", "130", "140", "150", "160", "180", "200"]
Current value: "100"
Property: "Origin" : NoUnits (Read Only)
Current value: "(2.25597318603832E-14,0,0)"
Property: "Length (M14)" : Distance
Description: Set the bolt length
Allowed values: ["60", "65", "70", "75", "80", "90", "100", "110", "120",
"130", "140", "150", "160"]
Current value: "100"
Property: "Origin" : NoUnits (Read Only)
Current value: "(2.25597318603832E-14,0,0)"
Many of the properties are actually 0, but have ended up being printed as a very small number... it would be simple enough to check these against a tolerance rather than trusting them to be understood as being zero.
OK, that's a good enough start for today. In the next post we'll address the need to capture dynamic properties from an inserted dynamic block and copy them across to another, already-inserted dynamic block. A bit like a "property painter" for dynamic blocks. (If you're thinking that this doesn't sound quite like what Fernando originally asked for, then you'd be quite right. We exchanged a few emails, and I then opted for a "property painter" approach to address the problem.)
Thanks for the inspiration, Fernando and Philippe! :-)