|
[code]1. 说明
本节介绍若干个函数,分别用于创建轻量多段线、三维多段线、正多边形、矩形、圆(圆环)和圆弧。这里所说的圆形和博客(6)中创建的圆不一样,因为本节创建的圆实际上是一条闭合的多段线,可以设置线宽。
(1) 创建轻量多段线(二维点, 连接点线宽)
(2) 创建仅包含一条直线的多段线(二维起点, 二维结束点, 连接点线宽)
(3) 创建三维多段线(三维点集)
(4) ---实体操作:旋转/移动/放缩
(5) 创建正多边形(中心、边数、外接圆半径、旋转角度(弧度值)和线宽)
(6) 多线段矩形(两个角点、线宽)
(7) 多线段圆(圆心、半径和线宽)
(8) 多线段圆弧(圆心、半径、起始角度、终止角度和线宽)
2. 思路
ObjectARX 中提供了三种多段线的相关类: AcDbPolyline 、 AcDb2dPolyline 和
AcDb3dPolyline 。其中,利用 AutoCAD 的内部命令可以创建 AcDbPolyline 和 AcDb3dPolyline
类的对象,用 PLINE 命令创建的对象是轻量多段线( AcDbPolyline ),用 3DPOLY 命令创建
的对象是三维多段线( AcDb3dPolyline )。鉴于 AcDb2dPolyline 目前并不常用,本节不准备详
细讨论它。
创建轻量多段线和三维多段线的函数,直接封装 AcDbPolyline 和 AcDb3dPolyline 类的构
造函数即可;创建正多边形、矩形、圆形和圆环,实际上都是创建了特殊形状的轻量多段线,
创建这些对象的关键都在于顶点和凸度的确定。
3. 步骤
(1) 在CCreateEnt类中:添加一个函数 CreatePolyline,用于向模型空间添加轻量多段线.
创建 AcDbPolyline 对象可以分成两个步骤:创建类的实例和添加顶点。
创建类的实例, 以多段线的顶点个数作为参数调用 AcDbPolyline::AcDbPolyline 函数;
添加顶点时,则使用了 AcDbPolyline::addVertexAt 函数,将每一个顶点添加到多段线中。
//创建轻量多段线
static AcDbObjectId CreatePolyline(AcGePoint2dArray points, double width = 0);
//创建轻量多段线
//创建 AcDbPolyline 对象可以分成两个步骤:创建类的实例和添加顶点
AcDbObjectId CCreateEnt::CreatePolyline(AcGePoint2dArray points, double width)
{
//创建类的实例, 以多段线的顶点个数作为参数调用 AcDbPolyline::AcDbPolyline 函数;
int numVertices = points.length();
AcDbPolyline *pPoly = new AcDbPolyline(numVertices);
for (int i = 0; i < numVertices; i++)
{
//添加顶点时,则使用了 AcDbPolyline::addVertexAt 函数,将每一个顶点添加到多段线中。
pPoly->addVertexAt(i, points.at(i), 0, width, width);
}
/*
//addVertexAt 函数定义为:
Acad::ErrorStatus addVertexAt(
unsigned int index, //index 用来指定插入顶点的索引号(从 0 开始);
const AcGePoint2d& pt, //pt 指定顶点的位置;
double bulge = 0., //bulge 指出要创建的顶点的凸度;
double startWidth = -1., //startWidth 和 endWidth 指定了从该顶点到下一顶点之间连线的起始和终止线宽,
double endWidth = -1); //利用该特性可以使用多段线创建一个实心箭头。
*/
AcDbObjectId polyId;
polyId = CCreateEnt::PostToModelSpace(pPoly);
return polyId;
}
凸度是多段线中一个比较难理解的概念,用于指定当前顶点的平滑性,其被定义为:在
多段线顶点显示中,选取顶点与下一个顶点形成的弧之间角度的四分之一的正切值。凸度可
以用来设置多段线某一段的凸出参数,0 表示直线,1 表示半圆,介于 0~1 之间为劣弧,大
于 1 为优弧。在创建圆的函数中,你会进一步学习。
(2) 创建仅包含一条直线的多段线
//创建仅包含一条直线的多段线
static AcDbObjectId CreatePolyline(AcGePoint2d ptStart, AcGePoint2d ptEnd, double width);
//创建仅包含一条直线的多段线
AcDbObjectId CCreateEnt::CreatePolyline(AcGePoint2d ptStart, AcGePoint2d ptEnd, double width)
{
AcGePoint2dArray points;
points.append(ptStart);
points.append(ptEnd);
return CreatePolyline(points, width);
}
(3) 添加一个创建三维多段线的函数
//添加一个创建三维多段线的函数
static AcDbObjectId Create3dPolyline(AcGePoint3dArray points);
//添加一个创建三维多段线的函数
AcDbObjectId CCreateEnt::Create3dPolyline(AcGePoint3dArray points)
{
AcDb3dPolyline *pPoly3d = new AcDb3dPolyline(AcDb::k3dSimplePoly, points);
return CCreateEnt::PostToModelSpace(pPoly3d);
/*
AcDb3dPolyline 类的构造函数接受了三个参数:
第一个参数值 AcDb::k3dSimplePoly 表示创建的多段线是一个未经拟合的标准多段线;
第二个参数值指定了创建三维多段线的顶点数组;
第三个参数指定是否闭合多段线,这里使用了默认参数值,不在创建多段线时将其闭合。
*/
}
(4) 在 CModifyEnt 类中,添加一个函数 Rotate,按照指定的角度(用弧度值表示)旋转指定的实体.
AcDbEntity::transformBy 函数对实体进行旋转,该函数能对实体进行比例变换、移动和旋转操作,其输入参数是一个几何变换矩阵(AcGeMatrix3d 类)
AcGeMatrix3d 类用于实体的几何变换非常简单,只要使用 setToScaling 、 setToRotation 和 setToTranslation
三个函数设置所要进行的变换,然后对所要变换的实体执行 transformBy 函数即可。
move和scale同理.
Acad::ErrorStatus Rotate(AcDbObjectId entId, AcGePoint2d ptBase, double rotation); //旋转实体
Acad::ErrorStatus Move(AcDbObjectId entId, AcGePoint3d ptBase, AcGePoint3d ptDest); //移动实体
Acad::ErrorStatus Scale(AcDbObjectId entId, AcGePoint3d ptBase, double scaleFactor); //缩放实体
//旋转实体
Acad::ErrorStatus CModifyEnt::Rotate(AcDbObjectId entId, AcGePoint2d ptBase, double rotation)
{
CGeometryOper m_geometryOper;
AcGeMatrix3d xform;
AcGeVector3d vec(0, 0, 1);
xform.setToRotation(rotation, vec, m_geometryOper.Pt2dTo3d(ptBase));
AcDbEntity *pEnt;
Acad::ErrorStatus es = acdbOpenObject(pEnt, entId, AcDb::kForWrite, false);
pEnt->transformBy(xform);
pEnt->close();
return es;
}
//移动实体
Acad::ErrorStatus CModifyEnt::Move(AcDbObjectId entId, AcGePoint3d ptBase, AcGePoint3d ptDest)
{
// 设置变换矩阵的参数
AcGeMatrix3d xform;
AcGeVector3d vec(ptDest.x - ptBase.x, ptDest.y - ptBase.y, ptDest.z - ptBase.z);
xform.setToTranslation(vec);
AcDbEntity *pEnt;
Acad::ErrorStatus es = acdbOpenObject(pEnt, entId, AcDb::kForWrite, false);
pEnt->transformBy(xform);
pEnt->close();
return es;
}
//缩放实体
Acad::ErrorStatus CModifyEnt::Scale(AcDbObjectId entId, AcGePoint3d ptBase, double scaleFactor)
{
// 设置变换矩阵的参数
AcGeMatrix3d xform;
xform.setToScaling(scaleFactor, ptBase);
AcDbEntity *pEnt;
Acad::ErrorStatus es = acdbOpenObject(pEnt, entId, AcDb::kForWrite, false);
pEnt->transformBy(xform);
pEnt->close();
return es;
}
(5) 添加创建正多边形的函数。创建正多边形的输入参数为中心、边数、外接圆半径、 旋转角度(弧度值)和线宽
步骤 (a)计算顶点位置;
(b)根据顶点位置创建多段线;
(c)闭合多段线;
(d)旋转多段线。
步骤(c) 是新接触到的内容。前面已经介绍过,使用 acdbOpenAcDbEntity 函数能够得到一个指向 AcDbEntity 对象的指针,但是如何将其转化为指向 AcDbPolyline 的指针,从而利用AcDbPolylien 类的函数修改其特性呢?注意下面的语句:
AcDbPolyline *pPoly = AcDbPolyline::cast(pEnt);
cast 是 ObjectARX 所有类的基类 — AcRxObject 中实现的一个函数,该函数提供了一种
安全的类型转换机制,这里的作用就是从基类指针 pEnt 获得派生类的指针 pPoly 。
如果你想为这条语句加上一个错误处理,还可以写成这样的形式:
if (pEnt->isKindOf(AcDbPolyline::desc()) == Adesk::kTrue)
{
AcDbPolyline *pPoly = AcDbPolyline::cast(pEnt);
if (pPoly != NULL)
{
pPoly->setClosed(Adesk::kTrue);
}
}
isKindOf 和 desc 函数提供了 ObjectARX 中一种常用的动态类型检查机制,这种方法在
ObjectARX 编程中极为常见。
代码如下:
//添加创建正多边形的函数(中心、边数、外接圆半径、旋转角度(弧度值)和线宽)
static AcDbObjectId CreatePolygon(AcGePoint2d ptCenter, int number, double radius, double rotation, double width);
//添加创建正多边形的函数(中心、边数、外接圆半径、旋转角度(弧度值)和线宽)
//步骤(a)计算顶点位置;(b)根据顶点位置创建多段线;(c)闭合多段线;(d)旋转多段线。
AcDbObjectId CCreateEnt::CreatePolygon(AcGePoint2d ptCenter, int number, double radius, double rotation, double width)
{
CGeometryOper m_geometryOper;
AcGePoint2dArray points;
double angle = 2 * m_geometryOper.PI() / (double)number;
//1.计算顶点位置;
for (int i = 0; i < number; i++)
{
AcGePoint2d pt;
pt.x = ptCenter.x + radius * cos(i * angle);
pt.y = ptCenter.y + radius * sin(i * angle);
points.append(pt);
}
//2.根据顶点位置创建多段线;
AcDbObjectId polyId= CCreateEnt::CreatePolyline(points, width);
//3.闭合多段线;
AcDbEntity *pEnt;
acdbOpenAcDbEntity(pEnt, polyId, AcDb::kForWrite);
AcDbPolyline *pPoly = AcDbPolyline::cast(pEnt);
if (pPoly != NULL)
{
pPoly->setClosed(Adesk::kTrue);
}
pEnt->close();
//4.旋转多段线。
CModifyEnt m_modifyEnt;
m_modifyEnt.Rotate(polyId, ptCenter, rotation);
return polyId;
}
(6) 多线段矩形(两个角点、线宽)
先在CGeometryOper类中添加取最大最小值得函数
double Max(double a, double b);
double Min(double a, double b);
//求最大值
double CGeometryOper::Max(double a, double b)
{
if (a > b)
{
return a;
}
else
{
return b;
}
}
//求最小值
double CGeometryOper::Min(double a, double b)
{
if (a < b)
{
return a;
}
else
{
return b;
}
}
再在CCreateEnt类中添加创建矩形函数
//矩形(两个角点、线宽)
static AcDbObjectId CreateRectangle(AcGePoint2d pt1, AcGePoint2d pt2, double width);
//矩形(两个角点、线宽)
AcDbObjectId CCreateEnt::CreateRectangle(AcGePoint2d pt1, AcGePoint2d pt2, double width)
{
// 提取两个角点的坐标值
double x1 = pt1.x, x2 = pt2.x;
double y1 = pt1.y, y2 = pt2.y;
// 计算矩形的角点
CGeometryOper m_geometryOper;
AcGePoint2d ptLeftBottom(m_geometryOper.Min(x1, x2),
m_geometryOper.Min(y1, y2));
AcGePoint2d ptRightBottom(m_geometryOper.Max(x1, x2),
m_geometryOper.Min(y1, y2));
AcGePoint2d ptRightTop(m_geometryOper.Max(x1, x2),
m_geometryOper.Max(y1, y2));
AcGePoint2d ptLeftTop(m_geometryOper.Min(x1, x2),
m_geometryOper.Max(y1, y2));
// 创建对应的多段线
AcDbPolyline *pPoly = new AcDbPolyline(4);
pPoly->addVertexAt(0, ptLeftBottom, 0, width, width);
pPoly->addVertexAt(1, ptRightBottom, 0, width, width);
pPoly->addVertexAt(2, ptRightTop, 0, width, width);
pPoly->addVertexAt(3, ptLeftTop, 0, width, width);
pPoly->setClosed(Adesk::kTrue);
// 将多段线添加到模型空间
AcDbObjectId polyId;
polyId = CCreateEnt::PostToModelSpace(pPoly);
return polyId;
}
(7) 多线段圆(圆心、半径和线宽)
//多线段圆(圆心、半径和线宽)
static AcDbObjectId CreatePolyCircle(AcGePoint2d ptCenter, double radius, double width);
//多线段圆(圆心、半径和线宽)
AcDbObjectId CCreateEnt::CreatePolyCircle(AcGePoint2d ptCenter, double radius, double width)
{
// 计算顶点的位置
AcGePoint2d pt1, pt2, pt3;
pt1.x = ptCenter.x + radius;
pt1.y = ptCenter.y;
pt2.x = ptCenter.x - radius;
pt2.y = ptCenter.y;
pt3.x = ptCenter.x + radius;
pt3.y = ptCenter.y;
// 创建多段线
AcDbPolyline *pPoly = new AcDbPolyline(3);
pPoly->addVertexAt(0, pt1, 1, width, width);
pPoly->addVertexAt(1, pt2, 1, width, width);
pPoly->addVertexAt(2, pt3, 1, width, width);
pPoly->setClosed(Adesk::kTrue);
// 将多段线添加到模型空间
AcDbObjectId polyId;
polyId = CCreateEnt::PostToModelSpace(pPoly);
return polyId;
}
(8) 多线段圆弧(圆心、半径、起始角度、终止角度和线宽)
//多线段圆弧(圆心、半径、起始角度、终止角度和线宽)
static AcDbObjectId CreatePolyArc(AcGePoint2d ptCenter, double radius, double angleStart, double angleEnd, double width);
//多线段圆弧(圆心、半径、起始角度、终止角度和线宽)
AcDbObjectId CCreateEnt::CreatePolyArc(AcGePoint2d ptCenter, double radius,
double angleStart, double angleEnd, double width)
{
// 计算顶点的位置
AcGePoint2d pt1, pt2;
pt1.x = ptCenter.x + radius * cos(angleStart);
pt1.y = ptCenter.y + radius * sin(angleStart);
pt2.x = ptCenter.x + radius * cos(angleEnd);
pt2.y = ptCenter.y + radius * sin(angleEnd);
// 创建多段线
AcDbPolyline *pPoly = new AcDbPolyline(3);
pPoly->addVertexAt(0, pt1, tan((angleEnd - angleStart) / 4), width, width);
pPoly->addVertexAt(1, pt2, 0, width, width);
// 将多段线添加到模型空间
AcDbObjectId polyId;
polyId = CCreateEnt::PostToModelSpace(pPoly);
return polyId;
}
(9) 在acrxEntryPoint.cpp中添加
ACED_ARXCOMMAND_ENTRY_AUTO(CArxConfigApp, MidasMyGroup, MyDrawPolyline, MyDrawPolyline, ACRX_CMD_MODAL, NULL) //画多段线
//当前项目中注册一个命令 AddPolyline
static void MidasMyGroupMyDrawPolyline()
{
CGeometryOper m_geometryOper;
// 创建三维多段线
AcGePoint3d pt1(0, 0, 0), pt2(10, 0, 0), pt3(10, 10, 0), pt4(10, 10, 10);
AcGePoint3dArray points;
points.append(pt1);
points.append(pt2);
points.append(pt3);
points.append(pt4);
AcDbObjectId polyline3dId;
polyline3dId = CCreateEnt::Create3dPolyline(points);
//创建正多边形(中心、边数、外接圆半径、旋转角度(弧度值)和线宽)
AcDbObjectId polygonId;
polygonId = CCreateEnt::CreatePolygon(AcGePoint2d::kOrigin, 6, 15, 0, 1);
// 创建圆
AcGePoint2d pt5(20, 20);
AcDbObjectId polyCircleId;
polyCircleId = CCreateEnt::CreatePolyCircle(pt5, 10, 1);
// 创建圆弧
AcGePoint2d pt6(10, 15);
AcDbObjectId polyArcId;
polyArcId = CCreateEnt::CreatePolyArc(pt6, 15, m_geometryOper.GtoR(45), m_geometryOper.GtoR(225), 1);
CModifyEnt m_modifyEnt;
m_modifyEnt.ChangeColor(polyline3dId, 1);
m_modifyEnt.ChangeColor(polygonId, 1);
m_modifyEnt.ChangeColor(polyCircleId, 1);
m_modifyEnt.ChangeColor(polyArcId, 1);
}
————————————————
原文链接:https://blog.csdn.net/qq_42981953/article/details/121806893[/code] |
|