gzxl 发表于 2025-2-22 15:53:20

ARX 曲线文字

官方有个例子,但版本是 2008 的、而且涉及太多。

看了 Lee Mac 的代码觉得容易理解。翻译成 ARX 的。


      Acad::ErrorStatus es = Acad::eOk;
      // 用户选择单行文字
      ads_name nameText;
      ads_point pt;
      if (RTNORM != acedEntSel(_T("\n选择一个单行文字沿曲线排列:"), nameText, pt))
            return;
      AcDbObjectId TextID;
      es = acdbGetObjectId(TextID, nameText);
      if (es != Acad::eOk)
            return;
      AcDbEntity* pEntText = NULL;
      es = acdbOpenObject(pEntText, TextID, AcDb::kForWrite);
      if (es != Acad::eOk)
            return;
      AcDbText* pText = AcDbText::cast(pEntText);
      if (pText == NULL)
      {
            pEntText->close();
            return;
      }
      ACHAR* pTextStr = pText->textString();
      CString strText = pTextStr;
      delete[] pTextStr;
      pText->close();
      pEntText->close();
      // 用户选择曲线
      ads_name nameCurve;
      if (RTNORM != acedEntSel(_T("\n选择一条曲线:"), nameCurve, pt))
            return;
      AcDbObjectId CurveID;
      es = acdbGetObjectId(CurveID, nameCurve);
      if (es != Acad::eOk)
      {
            acutPrintf(_T("\n获取曲线 ID 失败!"));
            return;
      }
      AcDbEntity* pEntCurve = NULL;
      es = acdbOpenObject(pEntCurve, CurveID, AcDb::kForRead);
      if (es != Acad::eOk)
      {
            acutPrintf(_T("\n打开曲线失败!"));
            return;
      }
      AcDbCurve* pCurve = AcDbCurve::cast(pEntCurve);
      if (pCurve == NULL)
      {
            pEntCurve->close();
            return;
      }
      pCurve->close();
      pEntCurve->close();

      int nCount = 0;

      AcGePoint3dArray mousePoints;// 鼠标移动-点集

      AcGePoint3d grrPt;
      int track = 1, type;
      struct resbuf result;
      while (track > 0)
      {
            acedGrRead(track, &type, &result);   // 追踪光标移动
            grrPt = result.resval.rpoint;// 获得用户输入点的位置
            grrPt = result.resval.rpoint;
            int nResult = result.resval.rint;

            // 点从用户坐标系坐标转换到世界坐标系
            AcGePoint3d wGrrPt = UcsToWcsPoint(grrPt);

            if (type == 5)// 鼠标移动
            {
                //mousePoints.append(wGrrPt);

                AcGePoint3d ptOnCurve;
                // 获取最接近曲线上的点
                pCurve->getClosestPointTo(wGrrPt, ptOnCurve, Adesk::kFalse);
                // 获取角度(弧度值)
                double dAngle = acutAngle(asDblArray(ptOnCurve), asDblArray(wGrrPt));
                // 获取曲线起点和点之间曲线段的长度
                double dLength;
                pCurve->getDistAtPoint(ptOnCurve, dLength);
                // 获取点处曲线的参数
                double dParam;
                pCurve->getParamAtPoint(ptOnCurve, dParam);
                // 获取 dParam 曲线的一阶导数
                AcGeVector3d firstDeriv;
                pCurve->getFirstDeriv(dParam, firstDeriv);
                // 计算两向量的夹角
                AcGePoint3d vecPt(0.0, 0.0, 0.0);
                AcGePoint3d vecDerivPt(firstDeriv.x, firstDeriv.y, firstDeriv.z);
                double dDer = acutAngle(asDblArray(vecPt), asDblArray(vecDerivPt));

                if ((PI * 0.5 < dDer) && (dDer <= (3.0 * PI * 0.5)))
                {
                  std::string str(CW2A(strText.GetString()));
                  std::reverse(str.begin(), str.end());
                  strText = str.c_str();
                }
                int textLen = strText.GetLength();
                if (textLen > 1)
                {
                  dDer = GetCorrectionAngle(dDer); // 校正角度
                }
                dDer = GetCorrectionAngle(dDer); // 校正角度
                double dDif = dAngle - dDer;
                // 当前注释比例的值
                double dTextSize;
                GetVar(_T("textsize"), dTextSize);
                // 文字长度
                int nTextLen = strText.GetLength();
                double ln = 0 - (1 + nTextLen * 0.5);
                // 获取位于 dLength 指定位置的点
                AcGePoint3d pt;
                pCurve->getPointAtDist(dLength + (ln + 1) * dSpacin * dTextSize, pt);
                ln++;

                SetTextRotation(CurveID, TextID, dDif, dLength, pt);
            }

            if (type == 2)
            {
                if (nResult == 46)
                {
                  dSpacin += 0.1;
                  //acedAlert(_T("按下>键"));
                }
                if (nResult == 44)
                {
                  dSpacin -= 0.1;
                  //acedAlert(_T("按下<键"));
                }
                if (nResult == 61)
                {
                  dOffset += 0.1;
                  //acedAlert(_T("按下+键"));
                }
                if (nResult == 45)
                {
                  dOffset -= 0.1;
                  //acedAlert(_T("按下-键"));
                }
                if (nResult == 32)
                {
                  track = 0;
                  //acedAlert(_T("按下-空格键"));
                }
                //CString sKey;
                //sKey.Format(_T("%d"), nResult);
                //acedAlert(sKey);
            }

            if (type == 3)// 用户按下了鼠标左键
            {
                track = 0;
            }
      }

    static void SetTextRotation(AcDbObjectId CurveID, AcDbObjectId TextID, double dDif, double dLength, const AcGePoint3d& pt)
    {
      Acad::ErrorStatus es = Acad::eOk;

      AcDbEntity* pEntCurve = NULL;
      es = acdbOpenObject(pEntCurve, CurveID, AcDb::kForRead);
      if (es != Acad::eOk)
            return;
      AcDbCurve* pCurve = AcDbCurve::cast(pEntCurve);
      if (pCurve == NULL)
            return;

      // 当前注释比例的值
      double dTextSize;
      GetVar(_T("textsize"), dTextSize);
      // 获取点处曲线的参数
      double dParam;
      pCurve->getParamAtPoint(pt, dParam);
      // 获取 dParam 曲线的一阶导数
      AcGeVector3d firstDeriv;
      pCurve->getFirstDeriv(dParam, firstDeriv);
      // 计算夹角
      AcGePoint3d vecPt(0.0, 0.0, 0.0);
      AcGePoint3d vecDerivPt(firstDeriv.x, firstDeriv.y, firstDeriv.z);
      double dDer = acutAngle(asDblArray(vecPt), asDblArray(vecDerivPt));
      double dCorrect = GetCorrectionAngle(dDer); // 校正角度
      double dDist = dDif + dDer;
      AcDbEntity* pEntText = NULL;
      es = acdbOpenObject(pEntText, TextID, AcDb::kForWrite);
      if (es != Acad::eOk) return;
      if (pEntText->isKindOf(AcDbText::desc()))
      {
            AcDbText* pText = AcDbText::cast(pEntText);

            pText->setHorizontalMode(TextHorzMode::kTextMid);
            pText->setVerticalMode(TextVertMode::kTextVertMid);
            AcGePoint3d AlignmentPt = PolarPoint(pt, dDist, dTextSize * dOffset);
            pText->setAlignmentPoint(AlignmentPt);
            pText->setRotation(dDer + dCorrect);
            pText->close();
      }
      pEntText->close();
      pCurve->close();
      pEntCurve->close();
    }


你有种再说一遍 发表于 2025-2-22 16:01:31

太长了不看,嘻嘻

寒潮大冬瓜 发表于 2025-2-22 16:14:16

大侠改成lisp版?

gzxl 发表于 2025-2-22 16:26:49

你有种再说一遍 发表于 2025-2-22 16:01
太长了不看,嘻嘻

还好啦,官方的例子,看到我两眼泪汪汪

gzxl 发表于 2025-2-22 16:32:05

gzxl 发表于 2025-2-22 16:26
还好啦,官方的例子,看到我两眼泪汪汪

lisp源码就是看Lee的,还改什么?

你有种再说一遍 发表于 2025-2-22 17:22:42

gzxl 发表于 2025-2-22 16:26
还好啦,官方的例子,看到我两眼泪汪汪

核心就是切线是一阶导数,也就是顺着它放文字就好了.
https://www.cnblogs.com/JJBox/p/14300098.html#_label6

yanshengjiang 发表于 2025-2-24 09:22:40

虽然看不懂
页: [1]
查看完整版本: ARX 曲线文字