一、背景:根据任务,需要在已有地形的基础之上,绘制边长为偶数结尾的(保留2位小数)直角多边形。
二、任务解析:
(1)获取选择集,实现单选+多选+多段线;
(2)获取已有的地形数据,删除每条直线上首尾节点外的其他多余点;
(3)先计算原始各边的边长;
(4)计算从起始边开始的,沿直线前进方向左侧或右侧的下一个点的方向,得到方向数值;
(5)处理第一条边,使其在方向不变的情况下,边长为偶数;
(6)批处理多段线的中间节点,要求根据方向数值和原始边长值,计算下一条边的末点边长;
(9)处理末位边长,使其与起始边保持垂直,并计算最后的节点坐标;
(10)输出到块表区域;
(11)完成图形绘制。
三、完整代码
//-----------------------------------------------------------------------------
//----- acrxEntryPoint.cpp
//-----------------------------------------------------------------------------
#include "StdAfx.h"
#include "resource.h"
#include <vector>
//-----------------------------------------------------------------------------
#define szRDS _RXST("AB")
const int MAX = 50;
//-----------------------------------------------------------------------------
//----- ObjectARX EntryPoint
class CArxProject4App : public AcRxArxApp {
public:
CArxProject4App () : AcRxArxApp () {}
virtual AcRx::AppRetCode On_kInitAppMsg (void *pkt) {
// TODO: Load dependencies here
// You *must* call On_kInitAppMsg here
AcRx::AppRetCode retCode =AcRxArxApp::On_kInitAppMsg (pkt) ;
// TODO: Add your initialization code here
return (retCode) ;
}
virtual AcRx::AppRetCode On_kUnloadAppMsg (void *pkt) {
// TODO: Add your code here
// You *must* call On_kUnloadAppMsg here
AcRx::AppRetCode retCode =AcRxArxApp::On_kUnloadAppMsg (pkt) ;
// TODO: Unload dependencies here
return (retCode) ;
}
virtual void RegisterServerComponents () {
}
//*****************命令FF函数***************************
static void ABMyGroupFF () {
// Put your command code here
AcGePoint2d pA[MAX];//存储多段线顶点坐标
int num=0;//存储多段线顶点数量
GetPolylineCoordinates(pA,num);//获取多段线顶点坐标
//ShowCoordinates(pA, MAX);//显示获取的坐标
//acutPrintf(_T("获取多段线顶点坐标正常执行"));
if (num == 0)
{
acutPrintf(_T("失败,退出功能"));
return;
}
double dis[MAX];
CalDistance(pA, MAX, dis);//计算原始两点间距离
int dir[MAX];
for (int i = 0; i < MAX; i++)
{
dir[i] = 0;
}
AcDbPolyline* pl = new AcDbPolyline();
AcDbPolyline* pd = new AcDbPolyline();
int index = 0;
//acutPrintf(_T("计算两点间距离正常执行"));
//*****************处理第一条边的坐标***************************
//第一步,计算与X轴正方向的角度(弧度)
AcGeVector2d Vab = pA[1] - pA[0];
double Angle_ab = Vab.angle();
//计算增量
double dx = dis[0] * cos(Angle_ab);
double dy = dis[0] * sin(Angle_ab);
//计算新的B点
AcGePoint2d ptB_1(pA[0].x + dx, pA[0].y + dy);
//更改数组中的B点坐标
pA[1] = ptB_1;
//调用函数绘制起始线
pl->addVertexAt(index, pA[0]);
index++;
pl->addVertexAt(index, ptB_1);
index++;
//acutPrintf(_T("A点坐标:%g,%g\n"), pA[0].y, pA[0].x);
//acutPrintf(_T("B点坐标:%g,%g\n"), pA[1].y, pA[1].x);
//acutPrintf(_T("第一条边正常执行"));
//***********************处理方向*********************************
pd->addVertexAt(0, pA[0]);
pd->addVertexAt(1, pA[1]);
for (int i = 2; i < num; i++)
{
pd->addVertexAt(i, pA[i]);
}
Direction(pd, dir);
pd->close();
//acutPrintf(_T("处理方向正常执行"));
//***********************批处理中间节点*********************************
for (int i = 0; i < num-2; i++)
{
if (dir[i] == 1)
{
pA[i + 2] = DrawPolyline_Left(pA[i], pA[i + 1], dis[i + 1], pl, index);
}
else if (dir[i] == 2)
{
pA[i + 2] = DrawPolyline_Right(pA[i], pA[i + 1], dis[i + 1], pl, index);
}
}
//acutPrintf(_T("批处理中间节点正常执行"));
//***************************处理末位节点****************************
int numvertex=pl->numVerts();
//acutPrintf(_T("numvertex:%d\n"), numvertex);
AcGePoint2d ptc;
pl->getPointAt(numvertex - 2, ptc);
AcGePoint2d ptd;
pl->getPointAt(numvertex - 1, ptd);
AcGePoint2d pta;
pl->getPointAt(0, pta);
AcGePoint2d ptb;
pl->getPointAt(1, ptb);
AcGeVector2d vecPrev = ptd - ptc;
//acutPrintf(_T("获取末位节点正常执行"));
//AcGeVector2d vecNext = vecPrev.perpVector();//取逆时针,前进方向的左侧
AcGeVector2d vecNext = vecPrev.perpVector().negate();//取顺时针
vecNext.normalize();
AcGePoint2d ptE = ptd + vecNext * dis[num-2];
AcGeLine2d l1(ptd, ptE);
AcGeLine2d l2(pta, ptb);
AcGePoint2d ii;
int sta=l1.intersectWith(l2, ii);
//acutPrintf(_T("ii:%g,%g"), ii.y,ii.x);
/* AcDbLine* pline1 = new AcDbLine(AcGePoint3d(ptd.x, ptd.y, 0), AcGePoint3d(ptE.x, ptE.y, 0));
AcDbLine* pline2 = new AcDbLine(AcGePoint3d(ptb.x, ptb.y, 0), AcGePoint3d(pta.x, pta.y, 0));
AcGePoint3dArray pt_intersect3d;
pline1->intersectWith(pline2, AcDb::kOnBothOperands, pt_intersect3d);
int ll = pt_intersect3d.length();
if (ll >= 1)
{
AcGePoint2d intersect2d(pt_intersect3d[0].x, pt_intersect3d[0].y);
pl->addVertexAt(index, intersect2d);
pl->removeVertexAt(0);
}*/
pl->addVertexAt(index, ii);
pl->removeVertexAt(0);
//****************************输入块表******************************
//结尾代码
//pl->setPointAt(0, intersect2d);
pl->setClosed(true);//闭合多段线
AcDbObjectId id;
Setblocktable(pl, id);
pl->close();
//acutPrintf(_T("结束正常执行"));
}
//------------------------------------------END--------------------------------------------------------
//****************************方向判断函数******************************
static void Direction(AcDbPolyline* pl,int dir[])
{
int index = pl->numVerts(); int k = 0;
//acutPrintf(_T("index:%d\n"), index);
for (int i = 0; i < index - 2; i++)
{
AcGePoint2d p0;
pl->getPointAt(i, p0);
AcGePoint2d p1;
pl->getPointAt(i+1, p1);
AcGePoint2d p2;
pl->getPointAt(i+2, p2);
double v1_x = p1.x - p0.x;
double v1_y = p1.y - p0.y;
double v2_x = p2.x - p0.x;
double v2_y = p2.y - p0.y;
double cross = v1_x * v2_y - v1_y * v2_x;
const double eps = 1e-8;
if (cross > eps)
{
dir[k] = 1; //左侧
}
else if(cross<-eps)
{
dir[k] = 2; //右侧
}
//acutPrintf(_T("方向%d:%d\n"), k, dir[k]);
k++;
}
}
//**************************添加至块表函数**********************************
static void Setblocktable(AcDbPolyline* pl, AcDbObjectId &lineId)
{
AcDbBlockTable* pBlockTable = NULL;
//获取这个图形数据库的块表
acdbHostApplicationServices()->workingDatabase()->getBlockTable(pBlockTable, AcDb::kForRead);
AcDbBlockTableRecord* pBlockTableRecord;
//获取块表的记录
pBlockTable->getAt(ACDB_MODEL_SPACE, pBlockTableRecord, AcDb::kForWrite);//模型空间就是一个块表记录
//创建实体,并加入到指定的块表记录中
pBlockTableRecord->appendAcDbEntity(lineId, pl);
pBlockTable->close();
pBlockTableRecord->close();
}
//**********************绘制垂直线函数(取前进方向左侧)*************************************
static AcGePoint2d DrawPolyline_Left(AcGePoint2d ptA, AcGePoint2d ptB,double dis,AcDbPolyline *pl,int &index)
{
AcGeVector2d vecPrev = ptB - ptA;
AcGeVector2d vecNext = vecPrev.perpVector();//取逆时针,前进方向的左侧
//AcGeVector2d vecNext = vecPrev.perpVector().negate();//取顺时针
vecNext.normalize();
AcGePoint2d ptC = ptB + vecNext * dis;
//acutPrintf(TEXT("dis[0]%.6f"), dis);
pl->addVertexAt(index,ptC);
index++;
return ptC;
}
//**********************绘制垂直线函数(取前进方向右侧)*************************************
static AcGePoint2d DrawPolyline_Right(AcGePoint2d ptA, AcGePoint2d ptB, double dis, AcDbPolyline* pl, int& index)
{
AcGeVector2d vecPrev = ptB - ptA;
//AcGeVector2d vecNext = vecPrev.perpVector();//取逆时针,前进方向的左侧
AcGeVector2d vecNext = vecPrev.perpVector().negate();//取顺时针,前进方向右侧
vecNext.normalize();
AcGePoint2d ptC = ptB + vecNext * dis;
//acutPrintf(TEXT("dis[0]%.6f"), dis);
pl->addVertexAt(index, ptC);
index++;
return ptC;
}
//***********************计算两点间距离函数**********************************
static void CalDistance(AcGePoint2d pA[], int num,double dis[])
{
for (int i = 0; i < num-1; i++)
{
dis[i]=pA[i].distanceTo(pA[i + 1]);
//acutPrintf(TEXT("dis[0]-a:%.6f\n"), dis[i]);
int a = static_cast<int>(dis[i] * 100);
if (a % 2)
{
a=a+1;
}
dis[i] = double(a) / 100;
}
}
//***********************显示坐标函数*********************************
static void ShowCoordinates(AcGePoint2d pA[],int num)
{
for (int i = 0; i < num; i++)
{
acutPrintf(TEXT("XY%d:%g,%g\n"), i, pA[i].x, pA[i].y);
}
}
//*************************获取坐标函数**********************************
static void GetPolylineCoordinates(AcGePoint2d *pA,int &num)
{
ads_name ss;
resbuf rb;
rb.restype = 0;
rb.resval.rstring = _T("LWPOLYLINE");
rb.rbnext = NULL;
int rt = acedSSGet(_T("-b:S"), NULL, NULL, &rb, ss);
if (rt == RTNORM)
{
acutPrintf(TEXT("选择了一条多段线\n"));
ads_name entres;
acedSSName(ss, 0, entres);
AcDbObjectId ssId;
acdbGetObjectId(ssId, entres);
AcDbEntity* pEnt;
acdbOpenObject(pEnt, ssId, AcDb::kForRead);
if (pEnt->isKindOf(AcDbPolyline::desc()))
{
AcDbPolyline* pPolyline;
pPolyline = AcDbPolyline::cast(pEnt);
num = pPolyline->numVerts();
//acutPrintf(TEXT("num:%d\n"), num);
for (int j = 0; j < num; j++)
{
AcGePoint2d pt;
if (pPolyline->getPointAt(j, pt) == eOk)
{
*pA = pt;
pA += 1;
//acutPrintf(TEXT("XY:%g,%g\n"), pt.x, pt.y);
}
}
pPolyline->close();
}
pEnt->close();
acedSSFree(entres);
}
else if(rt==RTCAN)
{
acutPrintf(TEXT("取消\n"));
}
else if (rt == RTREJ)
{
acutPrintf(TEXT("输入无效\n"));
}
else
{
acutPrintf(TEXT("输入失效2\n"));
}
acedSSFree(ss);
}
//********************************end*****************************
static void ABMyGroupMyPickFirst () {
ads_name result ;
int iRet =acedSSGet (ACRX_T("_I"), NULL, NULL, NULL, result) ;
if ( iRet == RTNORM )
{
// There are selected entities
// Put your command using pickfirst set code here
}
else
{
// There are no selected entities
// Put your command code here
}
}
static void ABMyGroupMySessionCmd () {
// Put your command code here
}
static int ads_MyLispFunction () {
return (RTNORM) ;
}
} ;
//-----------------------------------------------------------------------------
IMPLEMENT_ARX_ENTRYPOINT(CArxProject4App)
ACED_ARXCOMMAND_ENTRY_AUTO(CArxProject4App, ABMyGroup, FF, FF, ACRX_CMD_MODAL, NULL)
ACED_ARXCOMMAND_ENTRY_AUTO(CArxProject4App, ABMyGroup, MyPickFirst, MyPickFirstLocal, ACRX_CMD_MODAL | ACRX_CMD_USEPICKSET, NULL)
ACED_ARXCOMMAND_ENTRY_AUTO(CArxProject4App, ABMyGroup, MySessionCmd, MySessionCmdLocal, ACRX_CMD_MODAL | ACRX_CMD_SESSION, NULL)
ACED_ADSSYMBOL_ENTRY_AUTO(CArxProject4App, MyLispFunction, false)
在acrxEntryPoint.cpp文件中,写入上述代码,生成解决方案即可。
四、CAD中调用上述生成的.arx插件。

绘制图形,如下:

五、工具适用场景
一般用于房产测绘中房子的绘制。
37

被折叠的 条评论
为什么被折叠?



