文本盒三种方式获取
本帖最后由 gzxl 于 2025-3-13 18:33 编辑文本盒(好像三种方式)获取,总结 getGeomExtents 比较其他两者范围大些,acedTextBox 和 AcGiTextStyle 差不多。
getGeomExtents 方式
ads_name eName;
ads_point pt;
if (RTNORM != acedEntSel(_T("\n选择一个单行文字画包围盒:"), eName, pt))
return;
AcDbObjectId objId;
acdbGetObjectId(objId, eName);
AcDbText* pText;
acdbOpenObject(pText, objId, AcDb::kForRead);
if (objId == NULL)
return;
AcDbExtents ext;
pText->getGeomExtents(ext);
AcGePoint2d minPt, maxPt; // 左下角 右上角
minPt = ext.minPoint().x;
minPt = ext.minPoint().y;
maxPt = ext.maxPoint().x;
maxPt = ext.maxPoint().y;
pText->close();
// 左上角 右下角
AcGePoint2d ptLeftTop(minPt.x, maxPt.y);
AcGePoint2d ptRightBottom(maxPt.x, minPt.y);
AcDbPolyline *pPoly = new AcDbPolyline(4);
pPoly->addVertexAt(0, minPt, 0, 0, 0);
pPoly->addVertexAt(1, ptRightBottom, 0, 0, 0);
pPoly->addVertexAt(2, maxPt, 0, 0, 0);
pPoly->addVertexAt(3, ptLeftTop, 0, 0, 0);
pPoly->setClosed(Adesk::kTrue);
AcDbBlockTable* pBlockTable;
acdbHostApplicationServices()->workingDatabase()->getSymbolTable(pBlockTable, AcDb::kForRead);
AcDbBlockTableRecord* pBlockTableRecord;
pBlockTable->getAt(ACDB_MODEL_SPACE, pBlockTableRecord, AcDb::kForWrite);
AcDbObjectId polyId;
pBlockTableRecord->appendAcDbEntity(polyId, pPoly);
pBlockTable->close();
pBlockTableRecord->close();
pPoly->close();acedTextBox 方式
// 结果缓冲区列表中搜索指定类型的组码
static struct resbuf* EntItem(struct resbuf *rchain, int gcode)
{
while ((rchain != NULL) && (rchain->restype != gcode))
rchain = rchain->rbnext;
return rchain;
}
ads_name tname;
struct resbuf *textent, *tent;
ads_point origin, lowleft, upright, p1, p2, p3, p4;
ads_real rotatn;
TCHAR rotatstr;
if (acedEntSel(_T("\n选择一个单行文字画包围盒: "), tname, p1) != RTNORM)
{
acdbFail(_T("没有选择文本实体\n"));
return;
}
textent = acdbEntGet(tname);
if (textent == NULL)
{
acdbFail(_T("无法检索文本实体\n"));
return;
}
tent = EntItem(textent, 10);
origin = tent->resval.rpoint; // ECS 坐标
origin = tent->resval.rpoint;
tent = EntItem(textent, 50);
rotatn = tent->resval.rreal;
// acdbAngToS() 将弧度转换为度数
if (acdbAngToS(rotatn, 0, 8, rotatstr) != RTNORM)
{
acdbFail(_T("弧度转换为度数失败!\n"));
acutRelRb(textent);
return;
}
if (acedTextBox(textent, lowleft, upright) != RTNORM)
{
acdbFail(_T("无法检索文本框坐标\n"));
acutRelRb(textent);
return;
}
acutRelRb(textent);
// 如果当前不在 WCS 中,此时添加
// 调用 acedTrans() 转换坐标
// 从 acedTextBox() 中检索
p1 = origin + lowleft; // UCS 坐标
p1 = origin + lowleft;
p2 = origin + upright;
p2 = origin + lowleft;
p3 = origin + upright;
p3 = origin + upright;
p4 = origin + lowleft;
p4 = origin + upright;
AcGePoint2d pt1, pt2, pt3, pt4;
pt1 = p1;
pt1 = p1;
pt2 = p2;
pt2 = p2;
pt3 = p3;
pt3 = p3;
pt4 = p4;
pt4 = p4;
AcDbPolyline *pPoly = new AcDbPolyline(4);
pPoly->addVertexAt(0, pt1, 0, 0, 0);
pPoly->addVertexAt(1, pt2, 0, 0, 0);
pPoly->addVertexAt(2, pt3, 0, 0, 0);
pPoly->addVertexAt(3, pt4, 0, 0, 0);
pPoly->setClosed(Adesk::kTrue);
AcDbBlockTable* pBlockTable;
acdbHostApplicationServices()->workingDatabase()->getSymbolTable(pBlockTable, AcDb::kForRead);
AcDbBlockTableRecord* pBlockTableRecord;
pBlockTable->getAt(ACDB_MODEL_SPACE, pBlockTableRecord, AcDb::kForWrite);
AcDbObjectId polyId;
pBlockTableRecord->appendAcDbEntity(polyId, pPoly);
pBlockTable->close();
pBlockTableRecord->close();
pPoly->close();
AcGePoint3d ptBase;
ptBase.x = origin;
ptBase.y = origin;
ptBase.z = 0.0;
AcGeMatrix3d xform;
AcGeVector3d vec(0, 0, 1);
xform.setToRotation(rotatn, vec, ptBase);
AcDbEntity *pEnt = NULL;
Acad::ErrorStatus es = acdbOpenObject(pEnt, polyId, AcDb::kForWrite, false);
if (es == Acad::eOk)
{
es = pEnt->transformBy(xform);
pEnt->close();
}
AcGiTextStyle 方式
Acad::ErrorStatus es = Acad::eOk;
AcGiTextStyle textStyle;
AcDbTextStyleTable* pTable = NULL;
AcDbTextStyleTableRecord* pRecord = NULL;
acdbHostApplicationServices()->workingDatabase()->getSymbolTable(pTable, AcDb::kForRead);
const ACHAR* styleName = strFontName;
es = pTable->getAt(styleName, pRecord, AcDb::kForRead);
if (es == Acad::eOk)
{
fromAcDbTextStyle(textStyle, pRecord->objectId());
pRecord->close();
pTable->close();
textStyle.loadStyleRec();
textStyle.extentsBox(str, Adesk::kFalse, _tcslen(str), Adesk::kTrue, extMin, extMax);
}
谢谢楼主分享 我还以为有解析字体文件了 AcGiTextStyle 方式没写全,补一下。
// AcGiTextStyle 方式
static void GetTextStrBox(LPCTSTR str, const CString& strFontName, AcGePoint2d& extMin, AcGePoint2d& extMax)
{
Acad::ErrorStatus es = Acad::eOk;
AcGiTextStyle textStyle;
AcDbTextStyleTable* pTable = NULL;
AcDbTextStyleTableRecord* pRecord = NULL;
acdbHostApplicationServices()->workingDatabase()->getSymbolTable(pTable, AcDb::kForRead);
const ACHAR* styleName = strFontName;
es = pTable->getAt(styleName, pRecord, AcDb::kForRead);
if (es == Acad::eOk)
{
fromAcDbTextStyle(textStyle, pRecord->objectId());
pRecord->close();
pTable->close();
textStyle.loadStyleRec();
textStyle.extentsBox(str, Adesk::kFalse, _tcslen(str), Adesk::kTrue, extMin, extMax);
}
}
ads_name eName;
ads_point pt;
if (RTNORM != acedEntSel(_T("\n选择一个单行文字画包围盒:"), eName, pt))
return;
AcDbObjectId objId;
acdbGetObjectId(objId, eName);
AcDbText* pText = NULL;
acdbOpenObject(pText, objId, AcDb::kForRead);
if (objId == AcDbObjectId::kNull)
return;
ACHAR* acText = pText->textString();
CString strText = acText;
delete[]acText;
AcDbObjectId textStyleId = pText->textStyle();
AcDbTextStyleTableRecord* pTextStyleRcd = NULL;
if (acdbOpenObject(pTextStyleRcd, textStyleId, AcDb::kForRead) == Acad::eOk)
{
ACHAR* textStyleName;
pTextStyleRcd->getName(textStyleName);
CString strFontName(textStyleName);
pTextStyleRcd->close();
delete[]textStyleName;
// 使用 AcGiTextStyle 查找文本字符串的范围
AcGePoint2d extMin, extMax;
GetTextStrBox(strText, strFontName, extMin, extMax);
// 范围点赋值给 pt1 pt2
AcGePoint3d pt1(extMin.x, extMin.y, 0.0);
AcGePoint3d pt2(extMax.x, extMax.y, 0.0);
// 3D 空间的仿射变换
AcGeMatrix3d coordSysMat;
// 返回与文本平面法线向量正交的向量(法线向量 WCS 坐标)
AcGeVector3d xAxis = pText->normal().perpVector();
// 返回文本平面法线向量的叉积
AcGeVector3d yAxis = pText->normal().crossProduct(xAxis);
// 输入角度围绕输入点旋转实体
xAxis.rotateBy(pText->rotation(), pText->normal());
yAxis.rotateBy(pText->rotation(), pText->normal());
// 设置矩阵
coordSysMat.setCoordSystem(pText->position(), xAxis, yAxis, pText->normal());
// 应用变换矩阵
pt1.transformBy(coordSysMat);
pt2.transformBy(coordSysMat);
// 提取两个角点的坐标值
double x1 = pt1.x, x2 = pt2.x;
double y1 = pt1.y, y2 = pt2.y;
// 计算矩形的角点
AcGePoint2d ptLeftBottom(min(x1, x2), min(y1, y2));
AcGePoint2d ptRightBottom(max(x1, x2), min(y1, y2));
AcGePoint2d ptRightTop(max(x1, x2), max(y1, y2));
AcGePoint2d ptLeftTop(min(x1, x2), max(y1, y2));
// 创建多段线
AcDbPolyline* pPoly = new AcDbPolyline(4);
pPoly->addVertexAt(0, ptLeftBottom, 0, 0, 0); // 添加顶点
pPoly->addVertexAt(1, ptRightBottom, 0, 0, 0);
pPoly->addVertexAt(2, ptRightTop, 0, 0, 0);
pPoly->addVertexAt(3, ptLeftTop, 0, 0, 0);
pPoly->setClosed(Adesk::kTrue); // 设置闭合
// 获得当前图形数据库的块表
AcDbBlockTable* pBlockTable = NULL;
acdbHostApplicationServices()->workingDatabase()->getSymbolTable(pBlockTable, AcDb::kForRead);
// 获得模型空间对应的块表记录
AcDbBlockTableRecord* pBlockTableRecord = NULL;
pBlockTable->getAt(ACDB_MODEL_SPACE, pBlockTableRecord, AcDb::kForWrite);
// 将多段线实体添加到模型空间的块表记录
AcDbObjectId polyId;
pBlockTableRecord->appendAcDbEntity(polyId, pPoly);
// 关闭模型空间块表记录和多段线实体
pBlockTable->close();
pBlockTableRecord->close();
pPoly->close();
}
pText->close();
谢谢楼主分享
页:
[1]