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();
}
太长了不看,嘻嘻 大侠改成lisp版? 你有种再说一遍 发表于 2025-2-22 16:01
太长了不看,嘻嘻
还好啦,官方的例子,看到我两眼泪汪汪 gzxl 发表于 2025-2-22 16:26
还好啦,官方的例子,看到我两眼泪汪汪
lisp源码就是看Lee的,还改什么? gzxl 发表于 2025-2-22 16:26
还好啦,官方的例子,看到我两眼泪汪汪
核心就是切线是一阶导数,也就是顺着它放文字就好了.
https://www.cnblogs.com/JJBox/p/14300098.html#_label6 虽然看不懂
页:
[1]