|
[code]1)计算直线几何类和 圆弧几何类的交点。
注册命令InsertsetWith,实现代码:
static void AAAMyGroupIntersectWith() {
// 计算所要计算交点的几何类对象
AcGeCircArc2d geArc(AcGePoint2d::kOrigin, 50, 0, 6);
//AcGePoint2d::kOrigin返回一个坐标为(0,0)的点
//圆弧的圆心为(0,0),半径为50,起始角0;终止角6
AcGeLine2d geLine(AcGePoint2d::kOrigin, AcGePoint2d(10, 10));
//构造一条穿过(0,0)和(10, 10)的无界线
//计算并输出交点
AcGePoint2d point1, point2;
int num;
if (geArc.intersectWith(geLine, num, point1, point2))//如果存在交点,intersectWith返回Adesk::kTrue
{
acutPrintf(TEXT("\n直线和圆弧有%d个交点."), num);
if (num > 0)
{
acutPrintf(TEXT("\n交点1坐标:(%.4f,%.4f)."), point1.x, point1.y);
}
if (num > 1)
{
acutPrintf(TEXT("\n交点2坐标:(%.4f,%.4f)."), point2.x, point2.y);
}
}
}
效果:
加载AutoCAD2018,执行命令IntersectWith:
快捷键Ctrl+F2 打开文本窗口:
直线和圆弧有2个交点.
交点1坐标:(35.3553,35.3553).
交点2坐标:(-35.3553,-35.3553).
(2)注册一个新命令LineDistance
用于提示用户在图形窗口中选择两条直线,计算两条直线之间的最短距离,并在命令窗口中选择两条直线,计算两条直线之阿的最短距离并在命令窗口中输出:
static void AAAMyGroupLineDistance() {
// 提示用户选择所要计算距离的两条直线
AcDbObjectIdArray lineIds;
if (CSelectUtil::PromptSelectEnts(TEXT("\n选择两条直线:"), AcDbLine::desc(), lineIds))
{
if (lineIds.length() != 2)
{
acutPrintf(TEXT("\n必须选择两条直线."));
return;
}
//将直线转换成对应的几何类对象
AcGeLineSeg2d geLine1 = GetGeLineObj(lineIds[0]);
AcGeLineSeg2d geLine2 = GetGeLineObj(lineIds[1]);
//计算并输出两者之间的最短距离
double distance = geLine1.distanceTo(geLine2);
acutPrintf(TEXT("\n两条直线之间的最短距离为:%.4f."), distance);
}
}
其中,
GetGeLineObj函数的实现:
//根据输入的实体ID获得相同参数的AcGeLineSeg2d对象
static AcGeLineSeg2d GetGeLineObj(AcDbObjectId lineId)
{
AcGeLineSeg2d geLine; //AcGeLineSeg2d:在二维空间中表示一个有界的线段。
AcDbLine *pLine = NULL;
if (acdbOpenObject(pLine, lineId, AcDb::kForRead) == Acad::eOk)
//指针pLine指向打开的对象lineId
{
geLine.set(ToPoint2d(pLine->startPoint()),
ToPoint2d(pLine->endPoint()));
pLine->close();
}
return geLine;
}
ToPoint2d函数的实现:
// 二维点和三维点之间的转换
static AcGePoint2d ToPoint2d(const AcGePoint3d &point3d)
{
return AcGePoint2d(point3d.x, point3d.y);
}
PromptSelectEnts函数的实现:
bool CSelectUtil::PromptSelectEnts(const TCHAR* prompt, AcRxClass* classDesc, AcDbObjectIdArray &entIds)
{
std::vector<AcRxClass*> vecClassDesc;
vecClassDesc.push_back(classDesc);
return PromptSelectEnts(prompt, vecClassDesc, entIds);
}
bool CSelectUtil::PromptSelectEnts(const TCHAR* prompt, const std::vector<AcRxClass*> &classDescs, AcDbObjectIdArray &entIds)
{
// 初始化
entIds.setLogicalLength(0);
// 提示用户选择实体
ads_name sset;
int result = 0;
acutPrintf(prompt);
result = acedSSGet(NULL, NULL, NULL, NULL, sset);
if (result != RTNORM)
{
return false;
}
// 取得选择集的长度
long length = 0;
acedSSLength(sset, (Adesk::Int32 *)&length);
// 遍历选择集
Acad::ErrorStatus es;
AcDbEntity* pEnt = NULL;
for (long i = 0; i < length; i++)
{
ads_name ename;
acedSSName(sset, i, ename);
AcDbObjectId curEntId;
es = acdbGetObjectId(curEntId, ename);
if (es != Acad::eOk)
{
continue;
}
// 打开实体
es = acdbOpenObject(pEnt, curEntId, AcDb::kForRead);
if (es != Acad::eOk)
{
continue;
}
// 判断当前实体是否是指定的实体类型
for (int j = 0; j < (int)classDescs.size(); j++)
{
if (pEnt->isKindOf(classDescs[j]))
{
entIds.append(pEnt->objectId());
break;
}
}
pEnt->close(); // 关闭实体
}
acedSSFree(sset); // 释放选择集
return (entIds.length() > 0);
}
效果:
在AutoCAD2018中创建两条直线,执行命令LineDistance,得到两直线的最短距离。
(3)注册新命令CurveBoolean
用于获得两条曲线相交之后形成的边界线:
命令CurveBoolean 函数的实现:
//获得两条曲线相交之后形成的边界线
static void AAAMyGroupCurveBoolean() {
//选择所要操作的两条多段线
AcDbObjectIdArray polyIds;
if (CSelectUtil::PromptSelectEnts(TEXT("\n选择两条多段线:"),
AcDbPolyline::desc(), polyIds))//获得polyIds,返回bool
{
if (polyIds.length() != 2)
{
acutPrintf(TEXT("\n必须选择两条多段线."));
return;
}
//获得两条多段线的交点
bool bOk = false;
AcDbPolyline *pPoly1 = NULL, *pPoly2 = NULL;
if (acdbOpenObject(pPoly1, polyIds[0], AcDb::kForWrite) == Acad::eOk)
{ //pPoly1指向打开的对象polyIds[0]
if (acdbOpenObject(pPoly2, polyIds[1], AcDb::kForWrite) ==
Acad::eOk)
{
AcGePoint3dArray intPoints;
pPoly1->intersectWith(pPoly2, AcDb::kOnBothOperands,
intPoints);//pPoly2:pPoly1实体将与之相交的实体
//kOnBothOperands:不要扩展任何一个实体。这只会计算出两个实体
//的几何相交的交点
//intPoints:表示输出的交点
if (intPoints.length() >= 2)
{
bOk = true;
}
else
{
acutPrintf(TEXT("\n多段线之间交点少于2个,无法进行计算."));
}
//根据交点和参数值获得交点之间的曲线
if (bOk)
{
GetCurveBetweenIntPoints(pPoly1, intPoints);
GetCurveBetweenIntPoints(pPoly2, intPoints);
pPoly2->erase(); //擦除对象
}
pPoly2->close(); //关闭对象,自从它被打开以来,对对象所做的所有更改
//都被提交到数据库中
}
if (bOk)
{
pPoly1->erase();
}
pPoly1->close();
}
}
}
其中:
GetCurveBetweenIntPoints函数的实现:
static void GetCurveBetweenIntPoints(AcDbPolyline *pPoly,
const AcGePoint3dArray &intPoints)
{
AcDbVoidPtrArray curves;
pPoly->getSplitCurves(intPoints, curves);
//在曲线上输入参数的数组intPoints
//返回到新创建的实体的指针curves,这些实体是原始的子曲线
for (int i = 0; i < curves.length(); i++)
{
AcDbCurve *pCurve = static_cast<AcDbCurve*>(curves[i]);
//删除首尾两条曲线,其他段的曲线添加到模型空间
if (i == 0 || i == curves.length() - 1)
{
delete pCurve;
}
else
{
AcDbObjectId curveId = CDwgDatabaseUtil::PostToModelSpace(pCurve);
}
}
}
其中:
PostToModelSpace函数的声明:
static AcDbObjectId PostToModelSpace(AcDbEntity *pEnt,
AcDbDatabase *pDb = acdbHostApplicationServices()->workingDatabase());
PostToModelSpace函数的实现:
AcDbObjectId CDwgDatabaseUtil::PostToModelSpace(AcDbEntity *pEnt, AcDbDatabase *pDb)
{
// 检查输入参数的有效性
assert(pEnt); // 等效于assert (pEnt != NULL);
// 获得当前图形数据库的块表
AcDbBlockTable *pBlkTbl = NULL;
pDb->getBlockTable(pBlkTbl, AcDb::kForRead);
// 获得模型空间对应的块表记录
AcDbBlockTableRecord *pBlkTblRcd = NULL;
pBlkTbl->getAt(ACDB_MODEL_SPACE, pBlkTblRcd, AcDb::kForWrite);
pBlkTbl->close();
// 将实体添加到模型空间的块表记录
AcDbObjectId entId;
Acad::ErrorStatus es = pBlkTblRcd->appendAcDbEntity(entId, pEnt);
if (es != Acad::eOk)
{
pBlkTblRcd->close();
delete pEnt; // 添加失败时,要delete
pEnt = NULL;
return AcDbObjectId::kNull;
}
// 关闭模型空间块表记录和实体
pBlkTblRcd->close();
pEnt->close();
return entId;
}
效果:
绘制两条多段线,执行命令CurveBoolean:[/code]
[code]原文链接:https://blog.csdn.net/qq_40416052/article/details/82961341[/code] |
|