gzxl 发表于 2025-3-13 18:31:24

文本盒三种方式获取

本帖最后由 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);
}







革天明 发表于 2025-3-13 19:46:01

谢谢楼主分享

你有种再说一遍 发表于 2025-3-13 20:16:28

我还以为有解析字体文件了

gzxl 发表于 2025-3-15 12:06:49

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();

czb203 发表于 2025-3-15 16:53:48


谢谢楼主分享
页: [1]
查看完整版本: 文本盒三种方式获取