OBJECT ARX 绘制道路横切面

来源:互联网 发布:淘宝刚开店没单怎么办 编辑:程序博客网 时间:2024/04/29 13:18
//-----------------------------------------------------------------------------//----- acrxEntryPoint.cpp//-----------------------------------------------------------------------------#include "StdAfx.h"#include "resource.h"//-----------------------------------------------------------------------------#define szRDS _RXST("HY")const double BORDEROFFSET = 5 ;////边线距离端点2mmconst double BANDER1PTCOUNT = 4;//1块板交点数量const double BANDER2PTCOUNT = 6;//2块板交点数量const double BANDER3PTCOUNT = 8;//3块板交点数量const double BANDER4PTCOUNT = 10;//4块板交点数量const double PI = 3.1415926536;//-----------------------------------------------------------------------------//----- ObjectARX EntryPointclass CArxProject3App : public AcRxArxApp{public:CArxProject3App () : AcRxArxApp () {}virtual AcRx::AppRetCode On_kInitAppMsg (void *pkt){// TODO: Load dependencies here.// You *must* call On_kInitAppMsg hereAcRx::AppRetCode retCode =AcRxArxApp::On_kInitAppMsg (pkt) ;// TODO: Add your initialization code herereturn (retCode) ;}virtual AcRx::AppRetCode On_kUnloadAppMsg (void *pkt){// TODO: Add your code here// You *must* call On_kUnloadAppMsg hereAcRx::AppRetCode retCode =AcRxArxApp::On_kUnloadAppMsg (pkt) ;// TODO: Unload dependencies herereturn (retCode) ;}virtual void RegisterServerComponents (){}//加载一个实体到数据库,返回实体ID,是否关闭实体static AcDbObjectId LoadEntity(AcDbEntity* entity,bool autoClose){AcDbBlockTable* pBlockTable;acdbHostApplicationServices()->workingDatabase()->getBlockTable(pBlockTable,AcDb::kForRead);AcDbBlockTableRecord* pBlockTableRecord;pBlockTable->getAt(ACDB_MODEL_SPACE,pBlockTableRecord,AcDb::kForWrite);AcDbObjectId Id;pBlockTableRecord->appendAcDbEntity(Id,entity);pBlockTable->close();pBlockTableRecord->close();if(autoClose){entity->close();}return Id;}////插入文字////参数依次为:X,Y,Z坐标////要插入的文字////文字大小static void InsertText(double x,double y,double z,CString strTxt,double weight){////默认不做旋转不加粗InsertText(x,y,z,strTxt,weight,0,0,AcDb::TextHorzMode::kTextMid,AcDb::TextVertMode::kTextBottom);}////插入文字////参数依次为:X,Y,Z坐标////要插入的文字////文字高度////文字旋转角度////文字加粗大小////横向显示的模式////纵向显示模式static void InsertText(double x,double y,double z,CString strTxt,double height,double rotation,double size,AcDb::TextHorzMode hm,AcDb::TextVertMode vm){AcGePoint3d ptInsert(x,y,z);AcDbText* pText = new AcDbText(ptInsert,strTxt,AcDbObjectId::kNull,height,rotation);////注意这里的先后顺序,要先设置停靠的模式后设置停靠坐标,否则赋值不上去pText->setHorizontalMode(hm);pText->setVerticalMode(vm);pText->setAlignmentPoint(ptInsert);////设置加粗比例pText->setWidthFactor(size);LoadEntity(pText,true);}//显示道路的详细信息////参数依次:道路宽度数组,道路名称,显示比例static void ShowRoadDetail(AcGeDoubleArray& roadArr,const CString& strName,double ratio){////选择显示的位置ads_point ptInput;if(acedGetPoint(NULL,_T("\n选择显示断面符号的位置"),ptInput) != RTNORM){return;}AcGePoint2d ptDetail;ptDetail = asPnt2d(ptInput);AcDbPolyline* pl = new AcDbPolyline();////绘制表格上部分AcDbPolyline* pl2 = new AcDbPolyline();////表格中间部分AcDbPolyline* plMid = new AcDbPolyline();////表格中间线AcDbPolyline* pl3 = new AcDbPolyline();////表格底部直线double totalRoad = 0.0;int len = roadArr.length();for (int i = 0;i < len; i++){roadArr.setAt(i,roadArr.at(i) * ratio);}pl->addVertexAt(0,ptDetail);////左边斜线ptDetail.set(ptDetail[X] + BORDEROFFSET,ptDetail[Y] - BORDEROFFSET);pl->addVertexAt(1,ptDetail);////左边竖线ptDetail.set(ptDetail[X] ,ptDetail[Y] - 2 * BORDEROFFSET);pl->addVertexAt(2,ptDetail);int index = 2;bool isUp = true;////先高后低for(int i = 0;i < len;i ++){double road = roadArr.at(i);totalRoad += road;index ++;ptDetail.set(ptDetail[X] + road,ptDetail[Y]);pl->addVertexAt(index,ptDetail);if(i != len - 1){index ++;if(isUp)////凹进去{ptDetail.set(ptDetail[X],ptDetail[Y] - BORDEROFFSET / 4);pl->addVertexAt(index,ptDetail);isUp = false;}else////凸起来{ptDetail.set(ptDetail[X],ptDetail[Y] + BORDEROFFSET / 4);pl->addVertexAt(index,ptDetail);isUp = true;}}}index++;////右边竖线ptDetail.set(ptDetail[X],ptDetail[Y] + 2* BORDEROFFSET);pl->addVertexAt(index,ptDetail);index ++;////右边斜线ptDetail.set(ptDetail[X] + BORDEROFFSET,ptDetail[Y] + BORDEROFFSET);pl->addVertexAt(index,ptDetail);//绘制表格中部---------------ptDetail.set(ptDetail[X] - BORDEROFFSET,ptDetail[Y] - 3.5 * BORDEROFFSET);pl2->addVertexAt(0,ptDetail);index = 1;for(int i = 0;i < len; i++){double road = roadArr.at(len - i - 1);////右边线ptDetail.set(ptDetail[X],ptDetail[Y] - 3 * BORDEROFFSET);pl2->addVertexAt(index,ptDetail);index ++;////车道ptDetail.set(ptDetail[X]-road,ptDetail[Y]);pl2->addVertexAt(index,ptDetail);index++;////左边线ptDetail.set(ptDetail[X],ptDetail[Y] + 3 * BORDEROFFSET);pl2->addVertexAt(index,ptDetail);index ++;}//绘制中间线---------两边各多出1BORDEROFFSET----------ptDetail.set(ptDetail[X]- BORDEROFFSET,ptDetail[Y] - 3 * BORDEROFFSET);plMid->addVertexAt(0,ptDetail);ptDetail.set(ptDetail[X]+ 2 * BORDEROFFSET + totalRoad,ptDetail[Y]);plMid->addVertexAt(1,ptDetail);//绘制文字-------距离底部.25border文字宽度0.5BORDER---------------------double fontSize = BORDEROFFSET * 0.3;ptDetail.set(ptDetail[X] - BORDEROFFSET,ptDetail[Y] + 0.5 * BORDEROFFSET);double curRoad = 0.0;double latRoad = 0.0;double offset = 0.0;for(int i = 0;i < len;i ++){latRoad = curRoad;curRoad = roadArr.at(len - i - 1);double offset = (curRoad + latRoad) / 2;CString strSize;double r = curRoad/ratio;strSize.Format(_T("%.1f"),r);ptDetail.set(ptDetail[X] - offset,ptDetail[Y]);InsertText(ptDetail[X],ptDetail[Y],0,strSize,fontSize);}//绘制底线-------高度2border----------------double fstRoad = roadArr.at(0);ptDetail.set(ptDetail[X] - fstRoad/ 2 - BORDEROFFSET ,ptDetail[Y] - 2.25 * BORDEROFFSET);pl3->addVertexAt(0,ptDetail);ptDetail.set(ptDetail[X] + BORDEROFFSET,ptDetail[Y]);pl3->addVertexAt(1,ptDetail);ptDetail.set(ptDetail[X],ptDetail[Y] + 2 * BORDEROFFSET);pl3->addVertexAt(2,ptDetail);ptDetail.set(ptDetail[X],ptDetail[Y] - 2 * BORDEROFFSET);pl3->addVertexAt(3,ptDetail);ptDetail.set(ptDetail[X] + totalRoad,ptDetail[Y]);pl3->addVertexAt(4,ptDetail);ptDetail.set(ptDetail[X],ptDetail[Y] + 2 * BORDEROFFSET);pl3->addVertexAt(5,ptDetail);ptDetail.set(ptDetail[X],ptDetail[Y] - 2 * BORDEROFFSET);pl3->addVertexAt(6,ptDetail);ptDetail.set(ptDetail[X] + BORDEROFFSET,ptDetail[Y]);pl3->addVertexAt(7,ptDetail);////绘制底部文字ptDetail.set(ptDetail[X]- BORDEROFFSET - (totalRoad) / 2 ,ptDetail[Y] + 0.5 * BORDEROFFSET);CString strTotal;strTotal.Format(_T("%.1f"),totalRoad/ratio);InsertText(ptDetail[X],ptDetail[Y],0,strTotal,fontSize);////最下面,显示出截面的名称CString str;str.Format(_T("%s-%s"),strName,strName);ptDetail.set(ptDetail[X] ,ptDetail[Y] - 2.25 * BORDEROFFSET);InsertText(ptDetail[X],ptDetail[Y],0,str, 4 * fontSize,0,1,AcDb::TextHorzMode::kTextMid,AcDb::TextVertMode::kTextBottom);LoadEntity(pl,true);LoadEntity(pl2,true);LoadEntity(plMid,true);LoadEntity(pl3,true);}////遍历曲线实体,取出XDATA,判断strName是否已存在其他曲线的XDATA中static bool XDataIsExist(const CString& strName){ads_name ssName;////选择集名称////添加过滤条件resbuf* filter = acutBuildList(-3, 1001, _T("RNAME"), 0);acedSSGet(_T("X"),NULL,NULL,filter,ssName);long len = 0;acedSSLength(ssName,&len);ads_name entName;AcDbObjectId id;AcDbEntity* pEnt = NULL;AcDbCurve* pCur = NULL;CString outS;for (int i=0;i<len;i++){if (acedSSName(ssName, i, entName) != RTNORM){continue;}acdbGetObjectId(id,entName);////以读模式打开,根据ID索引到对象,并打开ENTITYacdbOpenObject(pEnt,id,AcDb::OpenMode::kForRead);if (!pEnt->isKindOf(AcDbCurve::desc())){continue;}pCur = (AcDbCurve*)pEnt;struct resbuf* rb;rb = pCur->xData(_T("RNAME"));if(rb == NULL){continue;}struct resbuf* pTemp;pTemp = rb;////首先要跳过应用程序名称pTemp = pTemp->rbnext;if(pTemp!= NULL && pTemp->restype ==  AcDb::kDxfXdAsciiString && pTemp->resval.rstring !=NULL){CString str1(pTemp->resval.rstring);if(str1.Compare(strName) == 0){return true;}}acutRelRb(rb);pCur->close();}acedSSFree(ssName);return false;}//把横截面名称保存到扩展数据中////参数:多段线实体,名称static void SavePlineXData(AcDbCurve* pLine,const CString strName){//扩展数据的内容struct resbuf* pRb;////注册应用程序名称acdbRegApp(_T("RNAME"));CString strAppName(_T("RNAME"));////创建结果缓冲区链表pRb = acutBuildList(AcDb::kDxfRegAppName,strAppName,kDxfXdAsciiString,strName,RTNONE);////添加扩展数据struct resbuf* pTemp ;pTemp = pLine->xData(_T("RNAME"));//////如果已经包含扩展数据,不再重复添加if (pTemp != NULL){acutRelRb(pTemp);acutPrintf(_T("它已经包含了扩展数据"));}else{pLine->setXData(pRb);acutPrintf(_T("\n扩展数据已赋值"));}acutRelRb(pRb);}////显示扩展数据////参数:多段线实体static void ViewPlineXData(AcDbCurve* pLine){struct resbuf* pRb;pRb = pLine->xData(_T("RNAME"));if (pRb != NULL){////在命令行显示所有的扩展数据struct resbuf* pTemp;pTemp = pRb;////首先要跳过应用程序名称pTemp = pTemp->rbnext;acutPrintf(_T("\n横截面的名称是:%s\n"),pTemp->resval.rstring);acutRelRb(pRb);}else{acutPrintf(_T("\n此实体没有任何扩展数据.\n"));}}////给图形实体,返回与选择的点之间的,与这个直线实体相交的交点数组、直线方向向量////参数:曲线实体,指定选择的点集,放到resbuf里面,2dpoint数组,三维向量static void GetLineNum(AcDbCurve* pLine,resbuf* ptLst,AcGePoint3dArray& ptArr,AcGeVector3d& v,double& roadWidth,bool& success){////遍历所有实体ads_name ssName;////选择集名称acedSSGet(_T("F"),ptLst,NULL,NULL,ssName);long len = 0;acedSSLength(ssName,&len);if(len == 0){success = false;return;}ads_name entName;AcDbObjectId id;AcDbEntity* pEnt = NULL;AcDbCurve* pCur = NULL;AcGePoint3dArray ptSecArr;////交点集合AcGePoint3d ptMin(0,0,0);AcGePoint3d ptMax(0,0,0);AcDbCurve* pMaxCur = NULL;for (int i=0;i<len;i++){if (acedSSName(ssName, i, entName) != RTNORM){continue;}////根据名称得到IDacdbGetObjectId(id,entName);////以读模式打开,根据ID索引到对象,并打开ENTITYacdbOpenObject(pEnt,id,AcDb::OpenMode::kForRead);if (pEnt == NULL || !pEnt->isKindOf(AcDbCurve::desc())){continue;}pCur = (AcDbCurve*)pEnt;pCur->intersectWith(pLine,AcDb::Intersect::kOnBothOperands,ptSecArr);if (ptSecArr.length() <= 0){continue;}////拿出第一个交点(两直线相交只可能有这一个交点)AcGePoint3d pt3d (ptSecArr.at(0));////添加交点ptArr.append(pt3d);ptSecArr.removeAll();pCur->getFirstDeriv(pt3d,v);if(i == 0){ptMin = ptArr.at(0);ptMax = ptArr.at(0);pMaxCur = pCur;}else{if(ptMin[X] > pt3d[X]){ptMin = pt3d;}else if(ptMin[X] == pt3d[X]){if(ptMin[Y] > pt3d[Y]){ptMin = pt3d;}}if(ptMax[X] < pt3d[X]){ptMax = pt3d;pMaxCur = pCur;}else if(ptMax[X] == pt3d[X]){if(ptMax[Y] < pt3d[Y]){ptMax = pt3d;pMaxCur = pCur;}}}}pMaxCur->getClosestPointTo(ptMin,ptMax);roadWidth = ptMax.distanceTo(ptMin);acutPrintf(_T("road width is %.2f"),roadWidth);pMaxCur->close();success = true;////要及时释放选择集,一共只能同时打开128个选择集acedSSFree(ssName);}////对2dpoint数组排序,默认为X坐标从左到右,如果竖直,Y坐标从下到上static void Sort2dArr(AcGePoint3dArray& arr,bool isHorizon){double len = arr.length();////对于竖直情况,对Y坐标进行排序if(!isHorizon){for (int i = len - 1;i > 0; i --){for(int j = 0;j < i; j++){double preY = arr.at(j)[Y];double latY = arr.at(j + 1)[Y];if(preY > latY){arr.swap(j,j+1);}}}}else{for (int i = len - 1;i > 0; i --){for(int j = 0;j < i; j++){double preX = arr.at(j)[X];double latX = arr.at(j + 1)[X];if(preX > latX){arr.swap(j,j+1);}}}}}////画道路测试命令static void TESTroadcmd(){////输入坐标部分==============================ads_point inputStart;ads_point inputEnd;AcGePoint2d ptStart;AcGePoint2d ptEnd;////用户输入要画的坐标if (acedGetPoint(NULL,_T("\n起始点:"),inputStart) != RTNORM){acutPrintf(_T("\n未指定起始点"));return;}ptStart = asPnt2d(inputStart);if (acedGetPoint(NULL,_T("\n终点:"),inputEnd) != RTNORM){acutPrintf(_T("\n未指定终点"));return;}ptEnd = asPnt2d(inputEnd);resbuf* ptList = NULL;ptList = acutBuildList(RTPOINT,ptStart,RTPOINT,ptEnd,NULL);////这条线求交点,不用画出来AcDbPolyline* pLine = new AcDbPolyline();pLine->addVertexAt(0,ptStart);pLine->addVertexAt(1,ptEnd);AcGePoint3dArray pntArr;////交点的数组AcGeVector3d v1;////道路方向////道路宽度double roadWidth;bool isSuc = false;////是否成功取到了交点GetLineNum(pLine,ptList,pntArr,v1,roadWidth,isSuc);if(!isSuc){acutPrintf(_T("\n交点数量不合法"));acutRelRb(ptList);delete pLine;return;}delete pLine;int ptCount = pntArr.length();////交点数量////如果交点数量不合法,退出if(ptCount != BANDER1PTCOUNT  && ptCount != BANDER2PTCOUNT && ptCount != BANDER3PTCOUNT && ptCount != BANDER4PTCOUNT ){acutPrintf(_T("\n两点之间的直线数须为{4,6,8,10}."));return;}acutPrintf(_T("\n交点个数:%d"),ptCount);//////输入名称部分,改用xData判断========================CString strName;AcDbObjectId pVerLineId = NULL;ads_name name;while (true){if(acedGetString(0,_T("\n输入横断面名称:\n"),strName.GetBuffer(20))!= RTNORM){return;}////用完buffer记得release!!strName.ReleaseBuffer();if(strName.GetLength() > 2){acutPrintf(_T("\n输入的字符数太多,请重新输入"));continue;}if(!XDataIsExist(strName)){break;}else{acutPrintf(_T("\n已存在名称,请重新输入"));}}///=========画垂线部分=============================AcGeVector3d v2;////横截面直线的方向向量if(v1[X] == 0)////竖直{Sort2dArr(pntArr,true);v2.set(1,0,0);}else{if(v1[Y] == 0){Sort2dArr(pntArr,false);v2.set(0,1,0);}else{Sort2dArr(pntArr,true);v2.set(1,-v1[X] / v1[Y],0);}}AcGePoint3d ptSecFst = pntArr.at(0);////第一个交点////计算单位向量AcGeVector3d vNorm = v2.normalize();vNorm[X] = abs(vNorm[X]);vNorm[Y] = vNorm[Y];double len = 3 * BORDEROFFSET;AcGePoint3d ptEnd1;AcGePoint3d ptEnd2;ptEnd1 = ptSecFst - 3*BORDEROFFSET * vNorm;ptEnd2 = ptSecFst + (3 * BORDEROFFSET + roadWidth) * vNorm ;AcGePoint3dArray arr;arr.append(ptEnd1);arr.append(ptEnd2);AcDb3dPolyline* plVer = new AcDb3dPolyline(AcDb::Poly3dType::k3dSimplePoly,arr);plVer->setLineWeight(AcDb::LineWeight::kLnWt030);AcDbObjectId lineId = LoadEntity(plVer,true);////================绘制详细信息部分============================acdbOpenObject(plVer,lineId,AcDb::OpenMode::kForWrite);////因为要添加扩展数据  所以要以写模式再次打开//获得垂线与道路的交点集合AcGePoint3dArray pntVerArr;bool isOk = false;GetLineNum(plVer,ptList,pntVerArr,v1,roadWidth,isOk);////释放链表空间acutRelRb(ptList);if(!isOk){acutPrintf(_T("\n垂线交点数量不合法"));plVer->close();return;}acutPrintf(_T("\n垂线交点个数%d"),pntVerArr.length());if(v2[X] == 0){Sort2dArr(pntVerArr,false);}else{Sort2dArr(pntVerArr,true);}int ptVerCount = pntVerArr.length();AcGeDoubleArray roadArr;double roadLen;AcGePoint3d prePt;AcGePoint3d latPt;for(int i = 0;i < ptVerCount - 1;i ++){prePt = pntVerArr.at(i);latPt = pntVerArr.at(i + 1);roadLen = prePt.distanceTo(latPt);roadArr.append(roadLen);}////显示详细信息表格,宽度比例1:2,1:1时会导致字符超出边ShowRoadDetail(roadArr,strName,2);// //绘制横断面名称===============double fontSize = 2 * BORDEROFFSET;LocateWords(plVer,strName,fontSize,1);////保存扩展数据SavePlineXData(plVer,strName);////查看一下保存的扩展数据ViewPlineXData(plVer);////最后记得关闭polyline3dplVer->close();}////放置截面名称的文字////参数:多段线实体,文字,文字高度,文字加粗大小static void LocateWords(AcDbCurve* plVer,const CString& strName,double height,double fontSize){AcGePoint3d plPtS;plVer->getStartPoint(plPtS);AcGePoint3d plPtE;plVer->getEndPoint(plPtE);AcGeVector3d v;plVer->getFirstDeriv(plPtS,v);AcGeVector3d vX(1,0,0);AcGeVector3d vZ(0,0,1);double angle = v.angleTo(vX,vZ);acutPrintf(_T("\nangle is %.2f"),angle);InsertText(plPtS[X],plPtS[Y],0,strName,height,-angle,fontSize,AcDb::TextHorzMode::kTextLeft,AcDb::TextVertMode::kTextBottom);InsertText(plPtE[X],plPtE[Y],0,strName,height, -angle,fontSize,AcDb::TextHorzMode::kTextRight,AcDb::TextVertMode::kTextBottom);}static void TESTnormcmd(){}static void TESTtestcmd(){ads_real num;if(RTNORM != acedGetReal(_T("放大倍数"),&num)){return;}ads_real angle;if(RTNORM != acedGetReal(_T("旋转角度"),&angle)){return;}ads_point pt;if(RTNORM!= acedGetPoint(NULL,_T("选择一点"),pt)){acutPrintf(_T("\nerror select"));return;}InsertText(pt[X],pt[Y],0,_T("aaa"),num * BORDEROFFSET,angle,3,AcDb::TextHorzMode::kTextRight,AcDb::TextVertMode::kTextBottom);}} ;//-----------------------------------------------------------------------------IMPLEMENT_ARX_ENTRYPOINT(CArxProject3App)ACED_ARXCOMMAND_ENTRY_AUTO(CArxProject3App, TEST, roadcmd, roadcmd, ACRX_CMD_MODAL, NULL)ACED_ARXCOMMAND_ENTRY_AUTO(CArxProject3App, TEST, testcmd, testcmd, ACRX_CMD_MODAL, NULL)ACED_ARXCOMMAND_ENTRY_AUTO(CArxProject3App, TEST, normcmd, normcmd, ACRX_CMD_MODAL, NULL)

原创粉丝点击