描述:该功能可保持多段线各条边方向不动的情况下,调整多段线的某一条边或某多条边为指定长度,用于修正图形。
根据提示,点选边,输入边指定长度,空格,即可得到修正后的图形。
注意:由于方向不变,某一条边的长度变化,这必然导致图形发生变化,故此,该功能只设计为垂直多边形可用,其末位点和首点之间的线段也属于垂直关系闭合。故此,其他用途图形不适应。
1、完整代码
//-----------------------------------------------------------------------------
//----- acrxEntryPoint.cpp
//-----------------------------------------------------------------------------
#include "StdAfx.h"
#include "resource.h"
#include "acedCmdNF.h"
//-----------------------------------------------------------------------------
#define szRDS _RXST("AA")
const double EPS = 0.1;
//-----------------------------------------------------------------------------
//----- ObjectARX EntryPoint
class CArxProject3_App : public AcRxArxApp {
public:
CArxProject3_App() : 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() {
}
static void AAMyGroupZZ() {
// Put your command code here
std::vector<AcGePoint2d> pt;//存储多段线顶点坐标
std::vector<AcGePoint2d> pick;//存储鼠标点击的位置
AcDbPolyline* pL = new AcDbPolyline();
int juget = 1;//用于判断循环是否结束
double ds = 1.0;
std::vector<double> dsInp;
int num;//存储顶点坐标
while (juget == 1)
{
ads_name ss;
ads_point pickPt;
int st = acedEntSel(_T("\n请选择线段:"), ss, pickPt);
//acutPrintf(_T("st:%d\n"),st);
if (st == RTNORM)
{
AcGePoint2d p = asPnt2d(pickPt);
pick.push_back(p);
AcDbObjectId obid;//临时值
int len;
acedSSLength(ss, &len);
if (len == 0)
{
juget = 2;
return;
}
if (acdbGetObjectId(obid, ss) == Acad::eOk)
{
AcDbEntity* pEnt;
acdbOpenObject(pEnt, obid, AcDb::kForRead);
AcDbPolyline* pl;
pl = AcDbPolyline::cast(pEnt);
pL = pl;
//注记起始点
AcGePoint2d pT;
pL->getPointAt(0, pT);
zhuJi(pT);
num = pL->numVerts();
pl->close();
pEnt->close();
}
else
{
juget = 2;
return;
}
int st2 = acedGetReal(_T("\n请输入边长:(10.0)"), &ds);
//acutPrintf(_T("st2:%d\n"), st2);
if (st2 == -5001)//无内容按下空格键时返回该值
{
//acutPrintf(_T("ds:%.5f\n"), ds);
ds = 10.0;
dsInp.push_back(ds);
}
else if (st2 == RTCAN)
{
juget = 2;
return;
}
else if (st2 == RTNORM)
{
dsInp.push_back(ds);
}
else if (st2 == 5000)
{
ds = 10.0;
dsInp.push_back(ds);
}
}
else if (st == RTCAN)
{
juget = 2;
return;
}
else if (st == -5001)//无内容按下空格键时返回该值
{
juget = 2;
}
else if (st == RTERROR)
{
juget = 2;
return;
}
else
{
juget = 2;
return;
}
acedSSFree(ss);
}
if (juget == 2 && num == 0)
{
acutPrintf(_T("退出,选择为空\n"));
return;
}
num = pL->numVerts();
std::vector<double> dis;//存储线段的长度
std::vector<AcGeVector2d> v2d;//存储线段的向量
for (int i = 0; i < num; i++)
{
AcGePoint2d p1;
pL->getPointAt(i, p1);
pt.push_back(p1);
}
pt.push_back(pt[0]);
for (int i = 0; i < num; i++)
{
AcGePoint2d p1 = pt[i];
AcGePoint2d p2 = pt[i + 1];
double s = p1.distanceTo(p2);
dis.push_back(s);
AcGeVector2d v(p2 - p1);
v2d.push_back(v);
}
std::vector<int> indexD;
size_t num2 = pick.size();
double S = 0; int countS = 0;
for (double i : dis)
{
S += i; countS++;
}
S /= countS;
double dk = S/100.0;
if (dk < 0.5)
{
dk = 0.5;
}
acutPrintf(_T("dk:%g\n"), dk);
for (int i = 0; i < num2; i++)
{
AcGePoint2d pk1(pick[i].x - dk, pick[i].y - dk);
AcGePoint2d pk2(pick[i].x + dk, pick[i].y - dk);
AcGePoint2d pk3(pick[i].x + dk, pick[i].y + dk);
AcGePoint2d pk4(pick[i].x - dk, pick[i].y + dk);
int index1 = 0; double d = 0;
for (int j = 0; j < num; j++)
{
AcGePoint2d p1 = pt[j];
AcGePoint2d p2 = pt[j + 1];
int kk1 = KuaLi(pk1, pk2, p1, p2);
int kk2 = KuaLi(pk1, pk4, p1, p2);
int kk3 = KuaLi(pk3, pk2, p1, p2);
int kk4 = KuaLi(pk3, pk4, p1, p2);
if (kk1 == 1 || kk2 == 1 || kk3 == 1 || kk4 == 1)
{
//acutPrintf(_T("跨立%d\n"),j);
index1 = j;
}
int b = isOnLine(p1, p2, pick[i]);
if (b == 1)
{
//acutPrintf(_T("线上%d\n"), j);
index1 = j;
}
}
indexD.push_back(index1);
//acutPrintf(_T("indexD[%d]-:%d\n"),i,index1);
}
size_t num3 = dsInp.size();
size_t num4 = indexD.size();
if (num4 == num3)
{
//acutPrintf(_T("进入循环,num3=num4=%d\n"), num3);
for (int i = 0; i < num3; i++)
{
int k = indexD[i];
//acutPrintf(_T("dis[k]-:%.5f\n"), dis[k]);
dis[k] = dsInp[i];
//acutPrintf(_T("dis[k]:%.5f\n"), dis[k]);
}
}
else
{
//acutPrintf(_T("num3:%d\n"), num3);
//acutPrintf(_T("num4:%d\n"), num4);
acutPrintf(_T("退出,未检测到边\n"));
return;
}
for (int i = 0; i < num - 1; i++)
{
AcGeVector2d v = v2d[i].normalize();
pt[i + 1] = pt[i] + v * dis[i];
}
//-----------------------------------------------------------
AcGePoint2d p1 = pt[num - 2];
AcGePoint2d p2 = pt[num - 1];
AcGePoint2d p3 = pt[0];
AcGeLine2d l12(p1, p2);
AcGePointOnCurve2d p_2d;
l12.getClosestPointTo(p3, p_2d);
AcGePoint2d ppt = p_2d.point2d();
pt[num - 1] = ppt;
//-------------------------------------------
ads_point getP;
AcGePoint2d pmove;//目标点
int zhuangtai = acedGetPoint(NULL, _T("\n请选择绘制点:"), getP);
if (zhuangtai == RTNORM)
{
pmove = asPnt2d(getP);//ads_point转AcGePoint2d
}
else
{
acutPrintf(_T("已取消\n"));
return;
}
//----------------------------------------------------
AcDbPolyline* pline = new AcDbPolyline();
int indexPline = 0;
for (int i = 0; i < num; i++)
{
pline->addVertexAt(indexPline, pt[i]);
indexPline++;
}
AcDbObjectId lineId;
Setblocktable(pline, lineId);
pline->setClosed(true);
pL->close();
pline->close();
//--------------------------------------------
ads_name ss;
acedSSAdd(NULL, NULL, ss);
ads_name entres;
acdbGetAdsName(entres, lineId);
acedSSAdd(entres, ss, ss);
AcGePoint2d pstart=pt[0];
acedCommandS(RTSTR, _T("MOVE"), RTPICKS, ss, RTSTR, _T(""), RTPOINT ,pstart, RTPOINT, pmove, RTNONE);
acedSSFree(entres);
acedSSFree(ss);
//----------------------------------------------
std::vector<AcGePoint2d> pt1;
for (int i = 0; i < num; i++)
{
AcGePoint2d p1;
pline->getPointAt(i, p1);
pt1.push_back(p1);
}
pt1.push_back(pt1[0]);
std::vector<CString> cs;
std::vector<AcGePoint2d> pc;
std::vector<double> angle;
BiaoJi(cs, pc, angle, pt1, num);
setWenzi(cs, pc, angle);
pline->close();
//end
}
static void zhuJi(AcGePoint2d pT)
{
AcDbText* pText = new AcDbText();
AcGePoint3d p3d(pT.x, pT.y, 0);
CString cst;
cst.Format(_T("%d"), 1);
pText->setTextString(cst);
pText->setPosition(p3d);
pText->setHeight(0.5);
pText->setColorIndex(1);
pText->setLayer(_T("0"));
AcDbBlockTable* pBT;
acdbHostApplicationServices()->workingDatabase()->getBlockTable(pBT, AcDb::kForRead);
AcDbBlockTableRecord* pBTR;
pBT->getAt(ACDB_MODEL_SPACE, pBTR, AcDb::kForWrite);
pBTR->appendAcDbEntity(pText);
pBT->close();
pBTR->close();
pText->close();
}
static void BiaoJi(std::vector<CString>& dis,
std::vector<AcGePoint2d>& positionC, std::vector<double>& angle,
std::vector<AcGePoint2d> pt, int num)
{
//有向面积法,正-逆时针,负-顺时针
double A = 0;
for (int i = 0; i < num - 1; i++)
{
A += pt[i].x * pt[i + 1].y - pt[i + 1].x * pt[i].y;
}
for (int i = 0; i < num - 1; i++)
{
//获取每条边的极角值(弧度值)
double angle1;
double pi = 4 * atan(1);
angle1 = atan2(pt[i + 1].y - pt[i].y, pt[i + 1].x - pt[i].x);
if (angle1 < 0)
{
angle1 += 2 * pi;
}
int bb = 0, cc = 0, dd = 0;
if (angle1 > pi / 2 && angle1 <= 1.5 * pi)
{
bb = 1;
}
if (angle1 > 2 * pi)
{
cc = 1;
}
if (cc == 1 || bb == 1)
{
dd = 1;
}
//处理文字方向
while (dd == 1)
{
if (angle1 > pi / 2 && angle1 <= 1.5 * pi)
{
angle1 += pi;
bb = 1;
}
else
{
bb = 0;
}
if (angle1 > 2 * pi)
{
angle1 -= 2 * pi;
cc = 1;
}
else
{
cc = 0;
}
if (bb == 1 || cc == 1)
{
dd = 1;
}
else
{
dd = 0;
}
}
angle.push_back(angle1);
//计算距离值
double d = pt[i].distanceTo(pt[i + 1]);
CString a;
a.Format(_T("%.4f"), d);
dis.push_back(a);
//计算插入点位置
double x1, y1;
x1 = pt[i].x + pt[i + 1].x;
y1 = pt[i].y + pt[i + 1].y;
AcGeVector2d v = pt[i + 1] - pt[i];
AcGeVector2d v2 = v.normalize();
x1 /= 2;
y1 /= 2;
AcGePoint2d pc(x1, y1);//线段中点坐标
AcGePoint2d pz = pc + v2 * 0.2;//距离中点0.5米沿线段方向的坐标
AcGePoint2d pE;
if (A > 0)
{
//逆时针旋转90度
AcGeVector2d vc1 = pz - pc;
AcGeVector2d vc12(-vc1.y, vc1.x);
pE = pc + vc12;
}
if (A < 0)
{
//顺时针旋转90度
AcGeVector2d vc1 = pz - pc;
AcGeVector2d vc12(vc1.y, -vc1.x);
pE = pc + vc12;
}
positionC.push_back(pE);
}
}
static void setWenzi(std::vector<CString> s, std::vector<AcGePoint2d> position, std::vector<double> rotation)
{
//获取文字样式表
AcDbTextStyleTable* pTextStyleTab;
acdbHostApplicationServices()->workingDatabase()
->getTextStyleTable(pTextStyleTab, AcDb::kForWrite);
//simsun.ttc(宋体的字体文件名称)
AcDbTextStyleTableRecord* pTextStyleTabRcd;
pTextStyleTabRcd = new AcDbTextStyleTableRecord();
//获取宋体字样
pTextStyleTab->getAt(_T("宋体"), pTextStyleTabRcd, AcDb::kForRead);
//设置新的字体名称并关联字体文件(需放在CAD字体文件夹目录下)
//pTextStyleTabRcd->setName(_T("宋体 常规"));//字体显示名称
//pTextStyleTabRcd->setFileName(_T("simsun.ttc"));//字体文件名称,打开控制面板,打开字体文件夹,右键字体属性查看
//添加到样式表
pTextStyleTab->add(pTextStyleTabRcd);
//获取对象ID
AcDbObjectId styleId = pTextStyleTabRcd->objectId();
//释放指针,不然实体无法删除等操作
pTextStyleTabRcd->close();
pTextStyleTab->close();
//添加到块表中
AcDbBlockTable* pBT;
acdbHostApplicationServices()->workingDatabase()->getBlockTable(pBT, AcDb::kForRead);
AcDbBlockTableRecord* pBTR;
pBT->getAt(ACDB_MODEL_SPACE, pBTR, AcDb::kForWrite);
size_t cc = s.size();
for (int i = 0; i < cc; i++)
{
AcDbText* ptr = new AcDbText();
CString str = s[i];
double height = 0.3;
AcGePoint3d position1(position[i].x, position[i].y, 0);
double rotation1 = rotation[i];
ptr->setTextString(str);
ptr->setHeight(height);
ptr->setRotation(rotation1);
//关联宋体样式
ptr->setTextStyle(styleId);
//对正模式设置--正中
ptr->setHorizontalMode(AcDb::kTextMid);
ptr->setVerticalMode(AcDb::kTextVertMid);
ptr->setAlignmentPoint(position1);//设置对正模式时,需使用此函数插入点,setpositin()函数无效
pBTR->appendAcDbEntity(ptr);
ptr->close();
}
pBT->close();
pBTR->close();
}
static int KuaLi(AcGePoint2d pa, AcGePoint2d pb, AcGePoint2d pc, AcGePoint2d pd)
{
AcGeVector2d vab = pb - pa;
AcGeVector2d vcd = pd - pc;
AcGeVector2d v1 = pc - pa;
AcGeVector2d v2 = pd - pa;
AcGeVector2d v3 = pa - pc;
AcGeVector2d v4 = pb - pc;
double cross1 = Cross(v1, vab);
double cross2 = Cross(v2, vab);
double cross3 = Cross(v3, vcd);
double cross4 = Cross(v4, vcd);
//说明两线段存在线中相交,交点不在端点上,在线段两端点间
if (((cross1 * cross2) < 0) && ((cross3 * cross4) < 0))
{
return 1;//跨立相交
}
else
{
return 0;//不存在跨立相交
}
}
//向量叉积的结果
static double Cross(AcGeVector2d v1, AcGeVector2d v2)
{
return v1.x * v2.y - v1.y * v2.x;
}
//判断点是否在线上(含端点)
static int isOnLine(AcGePoint2d pa, AcGePoint2d pb, AcGePoint2d pt1)
{
int a = 0, b = 0, c = 0;
AcGeVector2d v1 = pb - pa;
AcGeVector2d v2 = pt1 - pa;
double cross = Cross(v1, v2);
double Xmin_ab = 0, Xmax_ab = 0, Ymin_ab = 0, Ymax_ab = 0;
Xmin_ab = min(pa.x, pb.x);
Xmax_ab = max(pa.x, pb.x);
Ymin_ab = min(pa.y, pb.y);
Ymax_ab = max(pa.y, pb.y);
if (fabs(cross) < 1e-5)//叉乘结果为0,则表示3点共线
{
if (pt1.x >= Xmin_ab && pt1.x <= Xmax_ab)//判断是否在线段上,而不是线段的延长线上
{
if (pt1.y >= Ymin_ab && pt1.y <= Ymax_ab)
{
a = 1;//点在线上(含端点)
}
}
}
//考虑到计算容差问题,补充线段上两个端点与目标点重合的判断逻辑
if (fabs(pt1.x - pa.x) < EPS && fabs(pt1.y - pa.y) < EPS)
{
//目标点与端点a重合
b = 1;
}
if (fabs(pt1.x - pb.x) < EPS && fabs(pt1.y - pb.y) < EPS)
{
//目标点与端点b重合
c = 1;
}
if (a == 1 || b == 1 || c == 1)
{
return 1;//该点位于线段上
}
else
{
return 2;//该点不在线段上
}
}
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);//模型空间就是一个块表记录
//创建实体,并加入到指定的块表记录中
//AcDbObjectId lineId;
pBlockTableRecord->appendAcDbEntity(lineId, pl);
pBlockTable->close();
pBlockTableRecord->close();
}
// Modal Command with pickfirst selection
// ACED_ARXCOMMAND_ENTRY_AUTO(CArxProject3_App, AAMyGroup, MyPickFirst, MyPickFirstLocal, ACRX_CMD_MODAL | ACRX_CMD_USEPICKSET)
static void AAMyGroupMyPickFirst() {
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
}
}
// Application Session Command with localized name
// ACED_ARXCOMMAND_ENTRY_AUTO(CArxProject3_App, AAMyGroup, MySessionCmd, MySessionCmdLocal, ACRX_CMD_MODAL | ACRX_CMD_SESSION)
static void AAMyGroupMySessionCmd() {
// Put your command code here
}
static int ads_MyLispFunction() {
//struct resbuf *args =acedGetArgs () ;
// Put your command code here
//acutRelRb (args) ;
// Return a value to the AutoCAD Lisp Interpreter
// acedRetNil, acedRetT, acedRetVoid, acedRetInt, acedRetReal, acedRetStr, acedRetPoint, acedRetName, acedRetList, acedRetVal
return (RTNORM);
}
};
//-----------------------------------------------------------------------------
IMPLEMENT_ARX_ENTRYPOINT(CArxProject3_App)
ACED_ARXCOMMAND_ENTRY_AUTO(CArxProject3_App, AAMyGroup, ZZ, ZZ, ACRX_CMD_MODAL, NULL)
ACED_ARXCOMMAND_ENTRY_AUTO(CArxProject3_App, AAMyGroup, MyPickFirst, MyPickFirstLocal, ACRX_CMD_MODAL | ACRX_CMD_USEPICKSET, NULL)
ACED_ARXCOMMAND_ENTRY_AUTO(CArxProject3_App, AAMyGroup, MySessionCmd, MySessionCmdLocal, ACRX_CMD_MODAL | ACRX_CMD_SESSION, NULL)
ACED_ADSSYMBOL_ENTRY_AUTO(CArxProject3_App, MyLispFunction, false)
4338

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



