<?xml encoding=”UTF-8″>
CenterLine and CenterMark are two new entities based on AcDbBlockReferenes introduced in AutoCAD 2017; they are basically unnamed blockreference catering different purpose.
For more information on these two entities – CenterLine & CenterMark
In this post we will look at how to identifying if the underlying entities is a CenterLine or CenterMark objects, unfortunately there isn’t a public API to get to know what is the type of the Entity.
However through using Non-Com property system we can figure out if the entity is whether a CenterLine or CenterMark.
C++ Sample (Non-COM Properties Method)
void testIt() {
ads_name ename;
ads_point pt;
AcDbObjectId objId = AcDbObjectId::kNull;
AcDbEntity* pEnt = nullptr;
if (RTNORM != acedEntSel(_T(""), ename, pt))
return;
if (!eOkVerify(acdbGetObjectId(objId, ename)))
return;
if (!eOkVerify(acdbOpenAcDbEntity(pEnt, objId, AcDb::kForRead)))
return;
isCenterLineOrNot(pEnt);
}
// Utils (Non-COM Property System functions)
void getAttInfo(const AcRxAttribute * att,
const AcRxObject * member,
AcString & attInfo)
{
if (att->isA() == AcRxCOMAttribute::desc())
{
AcRxCOMAttribute * a = AcRxCOMAttribute::cast(att);
attInfo.format(_T("\n%s - %s"), att->isA()->name(), a->name());
}
else if (att->isA() == AcRxUiPlacementAttribute::desc())
{
AcRxUiPlacementAttribute* a = AcRxUiPlacementAttribute::cast(att);
attInfo.format(
_T("\n%s - %s - %f"),
att->isA()->name(),
a->getCategory(member),
a->getWeight(member));
}
else
{
if (att->isA() != nullptr)
{
attInfo.format(_T("\n%s"),
att->isA()->name());
}
}
}
void printValues(AcRxObject * entity,
const AcRxMember * member,
Adesk::Boolean& isCenterLine)
{
Acad::ErrorStatus err = Acad::eOk;
AcString strValue;
AcRxProperty * prop = AcRxProperty::cast(member);
if (prop != NULL)
{
AcRxValue value;
if ((err = prop->getValue(entity, value)) == Acad::eOk)
{
ACHAR * szValue = NULL;
int buffSize = value.toString(NULL, 0);
if (buffSize > 0)
{
buffSize++;
szValue = new ACHAR[buffSize];
value.toString(szValue, buffSize);
}
strValue.format(_T("%s = %s"),
value.type().name(),
(szValue == NULL) ? _T("none") : szValue);
if (szValue)
delete szValue;
}
else
{
strValue.format(_T("Error Code = %d"), err);
}
}
AcString str;
str.format(_T("\n%s - %s [%s]"), member->isA()->name(),
member->name(), strValue.kACharPtr());
AcString memberName;
memberName.format(_T("%s"), member->name());
if (0 == memberName.collateNoCase(_T("IsCenterLine")))
{
AcString isTrue(strValue.kACharPtr());
// Check if value contains '1'
if (isTrue.find(_T("1")) > 0) {
isCenterLine = Adesk::kTrue;
}
}
acutPrintf(str);
const AcRxAttributeCollection & atts = member->attributes();
for (int i = 0; i < atts.count(); i++)
{
const AcRxAttribute * att = atts.getAt(i);
AcString attInfo;
getAttInfo(att, member, attInfo);
acutPrintf(attInfo);
}
if (member->children() != NULL)
{
for (int i = 0; i < member->children()->length(); i++)
{
const AcRxMember * subMember =
member->children()->at(i);
printValues(entity, subMember, isCenterLine);
}
}
}
Adesk::Boolean isCenterLineOrNot(AcDbEntity* pEnt)
{
AcRxMemberIterator * iter =
AcRxMemberQueryEngine::theEngine()->newMemberIterator(pEnt);
Adesk::Boolean isCenterLine = Adesk::kFalse;
for (; !iter->done(); iter->next())
{
printValues(pEnt, iter->current(), isCenterLine);
}
return isCenterLine;
}
C++ Sample (AssocAction Method – Update)
enum CenterType
{
CenterMark = 0,
CenterLine
};
AcString SmartCenters[] = { L"CenterMark", L"CenterLine" };
Acad::ErrorStatus getTypeOfSmartCenterObject(const AcDbObjectId& blockRefObjId, CenterType& type)
{
AcDbSmartObjectPointer pCenter(blockRefObjId, AcDb::kForRead, true);
if (pCenter.openStatus() != Acad::eOk)
return Acad::eNullEntityPointer;
AcDbObjectIdArray actionIds;
Acad::ErrorStatus err = AcDbAssocAction::getActionsDependentOnObject(pCenter, false, true, actionIds);
if (!eOkVerify(err))
return err;
for (int i = 0; i < actionIds.length(); i++)
{
AcDbObjectId actionBody = AcDbAssocAction::actionBody(actionIds[i]);
auto objClass = actionBody.objectClass();
AcString objClassName = objClass->name();
if (objClassName == L"AcDbCenterMarkActionBody") {
type = CenterType::CenterMark;
return Acad::eOk;
}
else if (objClassName == L"AcDbCenterLineActionBody") {
type = CenterType::CenterLine;
return Acad::eOk;
}
else;
}
return Acad::eNotApplicable;
}
// Usage snippet
// CenterType type;
// if (eOkVerify(getTypeOfSmartCenterObject(objId, type)))
// {
// acutPrintf(_T("CenterType : %s"), SmartCenters[type].kACharPtr());
// }
.NET Port (C# Sample)
public void TestCenter()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
if (doc == null) return;
Editor ed = doc.Editor;
Database db = doc.Database;
PromptEntityOptions prOpt = new PromptEntityOptions("Select block: ");
prOpt.SetRejectMessage("Not a block!");
prOpt.AddAllowedClass(typeof(BlockReference), true);
PromptEntityResult prRes = ed.GetEntity(prOpt);
if (prRes.Status != PromptStatus.OK) return;
using (Transaction tr = doc.TransactionManager.StartTransaction())
{
var br =
tr.GetObject(prRes.ObjectId, OpenMode.ForRead) as BlockReference;
try
{
var idCols = AssocAction.GetActionsDependentOnObject(br, false, true);
if (idCols.Count > 0)
{
foreach (ObjectId id in idCols)
{
ObjectId idAct = AssocAction.GetActionBody(id);
if (idAct.ObjectClass.Name == "AcDbCenterMarkActionBody")
{
ed.WriteMessage("\nIt is CenterMark");
break;
}
if (idAct.ObjectClass.Name == "AcDbCenterLineActionBody")
{
ed.WriteMessage("\nIt is CenterLine");
break;
}
}
}
}
catch { } // Empty catch block is generally bad practice, but retained from original sample
tr.Commit();
}
}

Leave a Reply