I looked through the managed API and couldn't find anything that returns the insertion points for a dynamic block. I also didn't find any native APIs that did that. That doesn't mean one doesn't exist, but I don't have time to do an exhaustive search through dozens of libraries.
So it looks like the only solution is the brute-force one that involves the use of the EvalGraph and P/Invoking acdbEntGet(), which I've had to resort to before for similar purposes. The code below was very quickly adapted from code I wrote long ago for accessing visibility parameter info, and should give you what you're after.
public static partial class BlockReferenceExtensions
{
/// <summary>
/// Returns the alternate block insertion points for
/// the given BlockReference, transformed to its ECS.
/// </summary>
/// <param name="blkref"></param>
/// <param name="trans"></param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
public static IEnumerable<Point3d> GetInsertionPoints(this BlockReference blkref, Transaction trans)
{
if(blkref is null)
throw new ArgumentNullException(nameof(blkref));
if(trans is null)
throw new ArgumentNullException(nameof(trans));
EvalGraph evalGraph = GetEvalGraph(blkref, trans);
if(evalGraph != null)
{
var nodes = evalGraph.GetAllNodes();
if(nodes != null & nodes.Length > 0)
{
var matrix = blkref.BlockTransform;
foreach(uint id in nodes)
{
var node = evalGraph.GetNode(id, OpenMode.ForRead, trans);
if(node.ObjectId.ObjectClass == BlockXYGripClass)
{
foreach(TypedValue tv in node.EntGet())
{
if(tv.TypeCode == 1010)
{
yield return ((Point3d)tv.Value).TransformBy(matrix);
break;
}
}
}
}
}
}
}
public static EvalGraph GetEvalGraph(this BlockReference blkref, Transaction trans)
{
if(blkref is null)
throw new ArgumentNullException(nameof(blkref));
if(trans is null)
throw new ArgumentNullException(nameof(trans));
if(!blkref.IsDynamicBlock)
return null;
ObjectId btrId = blkref.DynamicBlockTableRecord;
var btr = (BlockTableRecord)trans.GetObject(btrId, OpenMode.ForRead);
var xdictId = btr.ExtensionDictionary;
if(xdictId.IsNull)
return null;
var xdict = (DBDictionary)trans.GetObject(xdictId, OpenMode.ForRead);
var result = xdict.GetAt("ACAD_ENHANCEDBLOCK");
if(result.IsNull)
return null;
return (EvalGraph)trans.GetObject(result, OpenMode.ForRead);
}
/// <summary>
/// TODO: You must change the filename "acdb26.dll" to
/// the name of the file for the targeted AutoCAD release
/// (e.g., "acdb24.dll", "acdb25.dll", etc.)
/// </summary>
const string ACDB_DLL = "acdb26.dll";
const string ACCORE_DLL = "accore.dll";
[DllImport(ACCORE_DLL, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "acdbEntGet")]
static extern IntPtr acdbEntGet(AdsName ename);
[DllImport(ACDB_DLL, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "?acdbGetAdsName@@YA?AW4ErrorStatus@Acad@@AEAY01_JVAcDbObjectId@@@Z")]
static extern ErrorStatus acdbGetAdsName(out AdsName ename, ObjectId id);
public static AdsName GetAdsName(this ObjectId id)
{
if(id.IsNull)
throw new ArgumentException(nameof(id));
AdsName result;
var es = acdbGetAdsName(out result, id);
if(es != ErrorStatus.OK)
throw new Autodesk.AutoCAD.Runtime.Exception(es);
return result;
}
static ResultBuffer EntGet(this ObjectId id)
{
if(id.IsNull)
throw new Autodesk.AutoCAD.Runtime.Exception(ErrorStatus.NullObjectId);
var result = acdbEntGet(GetAdsName(id));
if(result != IntPtr.Zero)
return ResultBuffer.Create(result, true);
return null;
}
static RXClass BlockXYGripClass =
(RXClass)SystemObjects.ClassDictionary["AcDbBlockXYGrip"];
}