本文迁移自本人网易博客,写于2011年1月12日,ARX测试_绘制道路横断面 - lysygyy的日志 - 网易博客 (163.com)
1、已提供道路的图形,获取用户输入的两点,并在两点间画一条虚线。
计算这条直线与多少条直线相交,若数量不等于7,提示用户,非二板块道路并返回。
//获取用户输入点
ads_point pt1, pt2;
if (acedGetPoint(NULL, "请选择一个点:", pt1) != RTNORM)
{
return;
}
//以第一点为基点,从用户处获得第二点
if (acedGetPoint(pt1, "请选择一个点:", pt2) != RTNORM)
{
return;
}
//创建直线
AcDbLine *pLine = new AcDbLine(asPnt3d(pt1), asPnt3d(pt2));
//设置线性为虚线
char linetype[30];
strcpy(linetype, "DASHED");
AcDbLinetypeTable *pLinetypeTbl;
AcDbObjectId ltId;
acdbCurDwg()->getLinetypeTable(pLinetypeTbl, AcDb::kForRead);
if ((pLinetypeTbl->getAtlinetype, ltId)) != Acad::eOk)
{
pLinetypeTbl-> close();
acdbCurDwg()-> loadLineTypeFile(linetype, "acadiso.lin");
acdbCurDwg()-> getLinetypeTable(pLinetypeTbl, AcDb::kForRead);
pLinetypeTbl-> getAt(linetype, ltId);
}
pLinetypeTbl-> close();
pLine-> setLinetype(ltId);
//将虚线添加到当前数据库中
AcDbObjectId objId;
postToDatabase(pLine, objId);
//计算这条直线与多少条直线相交,并且这些直线都互相平行
//将图形中凡是与虚线相交的直线添加到组中
//创建新组
AcDbGroup *pGroup = new AcDbGroup();
//将新组添加到组字典中
AcDbDictionary *pGroupDict;
acdbHostApplicationServices()->workingDatabase()->getGroupDictionary(pGroupDict, AcDb::kForWrite);
AcDbObjectId goupId;
pGroupDict->setAt("grouptest", pGroup, groupId);
pGroupDict->close();
pGroup->close();
AcDbBlockTable pBlockTbl;
acDbHostApplicationServices()->workingDatabase()->getSymbolTable(pBlockTbl, AcDb::kForRead);
AcDbBlockTableRecord *pBlockRecord;
if (pBlockTbl->getAt(ACDB_MODEL_SPACE,
pBlockTableRecord, AcDb::kForRead) == Acad::eOk)
{
pBlockTbl->close();
AcDbObject *pObj;
AcDbBlockTableRecordIterator *pIter = pBlockRecord->newIterator();
AcGePoint3dArray pointArray;
AcDbLine *pTempLine;
int i = 0;
while (!pIter->done())
{
pIter->getObject(pObj, AcDbForRead);
if (pObj->isKindOf(AcDbLine::desc())
{
//判断当前直线是否与虚线相交
AcGePoint3dArray tempArray;
pLine->intersectWith(pObj, AcDb::kOnBothOperands, tempArray) ;
if (!tempArray->isEmpty())
{
//判断当前直线是否与上一直线平行,即当前直线与上一条直线是否没有交点
if (i == 0)
{
pTempLine = pObj->copy();
}
else if (i > 0)
{
AcGePoint3dArray tempArray1;
pTempLine->intersectWith(pObj, AcDb::kOnBothOperands, tempArray1) ;
if (!tempArray1->isEmpty())
{
return;
}
pointArray->append(tempArray[i]);
pGroup->append(pObj->objectId());
pointArray[i]
pObj->close();
pTempLine =
i++;
}
}
}
else
{
pObj->close();
return;
}
pTempLine->close();
pBlockRecord->close();
pGroup->close();
//若组中实体数量不等于7,返回
if (pGroup->count() != 7)
{
return;
}
2、获取虚线与道路的交点(x坐标最小的,排序坐标点,若虚线是Y轴方向的,判断Y的大小),从该坐标点画一条粗直线,与道路线垂直。
double x;
AcGePoint3d firstPoint;
AcGePoint3dArray sortArray;
for (int i = 0; i < pointArray->length(); i ++)
{
int x1 = pointArray[i][X];
for (int j = i; j < pointArray->length(); j++)
{
if (i = j)
{
x = x1;
firstPoint = pointArray[j];
}
else
{
if (x > x1)
{
x = x1;
firstPoint = pointArray[j];
}
}
}
sortArray[i] = firstPoint;
}
//若交点数量不等于7,返回
int length = pointArray->length();
if(length != 7)
{
return;
}
//交点坐标排序后,删除最中间的点
pointArray->removeAt(length / 2);
//画一个圆,求得另外一个交点(垂足)
firstPoint = pointArray[0];
AcGePoint3d lastPoint = pointArray[length - 1];
double pX = lastPoint[X] - firstPoint[X];
double pY = lastPoint[Y] - firstPoint[Y];
AcGePoint3d centerPoint = {pX, pY, 0.0);
AcDbCircle *pCircle = new AcDbCircle();
pCircle->setCenter(centerPoint);
double r = sqrt(pX * pX / 4 + pY *pY / 4);
pCircle->setRadius(r);
AcDbObjectId ocircleId;
//将实体圆添加到块表记录中
postToDatabase(pCircle, ocircleId);
//新建一个组,将各平行线排序
//新建组的代码略,只写关键代码
//找到经过最后一个点的直线,并求圆与该直线的交点(不包含在交点数组中的点)
AcDbGroupIterator *pIter = pGroup->newIterator();
AcDbObject *pObj;
AcDbLine *pLastline;
for (; !pIter->done(); pIter->next())
{
pIter->getObject(pObj, AcDb::kForRead);
//判断lastPoint是否在该直线上
AcGePoint3dArray tempArray2;
lastPoint->intersectWith(pObj, AcDb::kOnBothOperands, tempArray2);
if (!tempArray2->isEmpty())
{
pLastLine = pObj->copy();
pObj->close();
}
}
//求圆与最后一条直线的交点
AcGePoint3d endPoint;
AcGePoint3dArray tempArray3;
pLastLine->intersectWith(pCircle, AcDb::kOnBothOperands, tempArray3);
if (tempArray3->length() < 2)
{
return;
}
if (tempArray3[0][X] == lastPoint[X] && tempArray3[0][Y] == lastPoint[Y])
{
endPoint = tempArray3[1];
}
else
{
endPoint = tempArray3[0];
}
//延伸法线(延伸长度为5),并获取到起点和终点,画粗直线
double d = 5.0;
double x1 = firstPoint[X];
double y1 = firstPoint[Y];
double x2 = endPoint[X];
double y2 = endPoint[Y];
double k = (y1 - y2) / (x1 - x2);
double b1 = y1 - k * x1;
double a = (k*k + 1);
double b = -2 * (x1 + k * y1 - k * b1);
double c = x1 * x1 + (y1 - b1) * (y1 - b1) - d * d;
double m = b * b - 4 * a * c;
if ( m < 0)
{
return;
}
double x3 = ( - b + sqrt(m)) / 2 / a;
double x4 = ( - b - sqrt(m)) / 2 / a;
double firstx;
if ( x3 > x1 && x3 > x2 || x3 < x1 && x3 < x2)
{
firstx = x3;
}
else
{
firstx = x4;
}
double firsty = k * firstx + b1;
AcGePoint3d Point1 = {firstx, firsty, 0.0);
//同样方法求得Point2,略
AcGePoint3d Point2;
//画粗直线
AcDbLine *pNewLine = new AcDbLine(Point1, Point2);
AcDbObjectId objId;
//将实体添加到块表记录中
postToDatabase(pNewLine, objId);
//将粗直线与组中各直线的交点写入一个数组中,并排序,略
AcGePoint3dArray ptArray;
//将各段距离写入一个double型数组中
double dArray[5];
for (int i = 0; i < 5; i++)
{
dArray[i] = acutDistance(ptArray[i], ptArray[i + 1]);
}
//获取用户输入的横断面名称,横断面名称必须不多于2个字符
string str;
bool flag = false;
while (!flag)
{
if (acedGetString(2, "请输入横断面名称(不多于2个字符):", &str) != RTNORM)
{
if (str == "")
{
AfxMessageBox("输入字符不能为空!");
}
else if ( str.length() > 2)
{
AfxMessageBox("名称不能多于2个字符!");
}
else if (FALSE == 遍历图形实体,判断是否有扩展数据与输入名称相同的)//没有相同名称
{
flag = TRUE;
}
}
}
}
//遍历图形中实体,判断扩展数据是否与输入的横断面名称相同
LPCTSTR szAppName = "RNAME";
TCHAR* pszRetDat;
AcDbBlockTableRecordIterator *pIterator = new AcDbBlockTableRecordIterator;
pBlockRec->newIterator(pIterator);
for (; !pIterator->done(); pIterator->step)
{
pIterator->getObject(pObj, AcDb::kForRead);
//得到指定对象、指定应用名下的扩展数据(DXF1000处)
GetXData1000(pObj, szAppName, &pszRetDat);
if (pszRetDat == str)
{
return TRUE;//名称相同
}
}
return FALSE;
//获取第一个文本的位置坐标,距离粗直线3
AcGePoint3d textPoint1;
int x1 = textPoint1[X];
int y1 = textPoint[Y];
int a = - 1 / k;
int b = y1 - a * x1;
//根据求延伸点的方法求出点坐标,略
//获取第二个文本的位置坐标,与上同,略;
AcGePoint3d textPoint2;
//将粗直线的第一个端点坐标转换为WCS
struct resbuf to, from;
from.restype = RTSHORT;
from.resval.rint = 1;//UCS
to.restype = RTSHORT;
to.resval.rint = 0; //WCS
acedTrans(asDblArray(textPoint1), &from, &to, Adesk::kFalse, asDblArray(textPoint1));
//将粗直线的第二个端点坐标转换为WCS
acedTrans(asDblArray(textPoint2), &from, &to, Adesk::kFalse, asDblArray(textPoint2));
//绘制粗直线上的第一个端点处的文字
AcDbText *PText = new AcDbText;
pText->setTextString(str);
pText->setPosition(textPoint1);
pText->setRotation(acutAngle(Point1, textPoint1));
pText->setHeight(8);
//绘制粗直线上第二个端点处的文字,略
//擦除辅助圆,虚线与其相同,略
ads_name objName;
circleName = acdbGetAdsName(&objName, objId);
acdbEntDel(objName);
4、绘制多段线,并描绘出距离。
//用户输入多段线起点
ads_point basePoint;
if (acedGetPoint(NULL, "请选择横断面的基点:", basePoint) != RTNORM)
{
return;
}
//新建一个数组,将各端点坐标值放入其中
AcGePoint2dArray *newArray = new AcGePoint2dArray;
newArray->append(basePoint);
//找到第二个端点
AcGePoint2d (newPoint);
acutPolar(basePoint, -2, 5, newPoint);
newArray->append(newPoint);
//第3个点
acutPolar(newPoint, -1, 10, newPoint);
newArray->append(newPoint);
//第4个点,距离数组
acutPolar(newPoint, 0, distArray[0], newPoint);
newArray->append(newPoint);
//第5个点
acutPolar(newPoint, -1, 1, newPoint);
newArray->append(newPoint);
//第6个点
acutPolar(newPoint, 0, distArray[1], newPoint);
newArray->append(newPoint);
//第7个点
acutPolar(newPoint, 1, 1, newPoint);
newArray->append(newPoint);
//第8个点
acutPolar(newPoint, 0, distArray[2], newPoint);
newArray->append(newPoint);
//第9个点
acutPolar(newPoint, -1, 1, newPoint);
newArray->append(newPoint);
//第10个点
acutPolar(newPoint, 0, distArray[3], newPoint);
newArray->append(newPoint);
//第11个点
acutPolar(newPoint, 1, 1, newPoint);
newArray->append(newPoint);
//第12个点
acutPolar(newPoint, 0, distArray[4], newPoint);
newArray->append(newPoint);
//第13个点
acutPolar(newPoint, 1, 10, newPoint);
newArray->append(newPoint);
//第14个点
acutPolar(newPoint, 0.5, 5, newPoint);
newArray->append(newPoint);
//绘制多段线
AcDbPolyline *pPolyline = new AcDbPolyline;
//将数组中的点添加到多段线中
for (int i = 0; i < newArray->length(); i++)
{
pPolyline->addVertexAt(i, *newArray[i], 0);
}
//新建一个组,将多段线及后面创建的直线和文本全都添加到组中
pGroup->append(pPolyline);
//获取多段线下第一条横线的起点和终点
AcGePoint3d *startPoint, *endPoint;
acutPolar(newArray[0], -1, 20, startPoint);
acutPolar(newArray[newArray->length() - 1], -1, 20, endPoint);
//创建起点到终点的直线,并将其加入组中,略
//获取多段线下第二条横线的起点和终点,距离为30,并将其加入组中,略
//获取左边第一条垂直线的起点和终点
AcGePoint3d *topPoint = (basePoint[X], newArray[1][Y], 0);
startPoint = (topPoint[X], newArray[2][Y, 0);
acutPolar(topPoint, -1, 30, endPoint);
//获取左边第二条垂直线的起点和终点
topPoint = (basePoint[X], newArray[3][Y], 0);
startPoint = (topPoint[X], startPoint[Y], 0);
acutPolar(topPoint, -1, 20, endPoint);
//获取左边第三条垂直线的起点和终点
topPoint = (basePoint[X], newArray[5][Y], 0);
startPoint = (topPoint[X], startPoint[Y], 0);
acutPolar(topPoint, -1, 20, endPoint);
//获取左边第4条垂直线的起点和终点
topPoint = (basePoint[X], newArray[7][Y], 0);
startPoint = (topPoint[X], startPoint[Y], 0);
acutPolar(topPoint, -1, 20, endPoint);
//获取左边第5条垂直线的起点和终点
topPoint = (basePoint[X], newArray[9][Y], 0);
startPoint = (topPoint[X], starPoint[Y], 0);
acutPolar(topPoint, -1, 20, endPoint);
//获取最后一条垂直线的起点和终点
topPoint = (basePoint[X], newArray[11][Y], 0);
startPoint = (topPoint[X], startPoint[Y], 0);
acutPolar(topPoint, -1, 30, endPoint);
//设置第一段距离的文本,并将其添加到组中
//获取文本位置的基点
topPoint = ((newArray[1][X] + newArray[3][X]) / 2, newArray[0][Y], 0);
acutPolar(topPoint, -1, 17, basePoint);
//文本内容为textArray[0],创建文本实体的函数略
//设置第二段距离的文本
topPoint = ((newArray[3][X] + newArray[5][X]) / 2, newArray[0][Y], 0);
acutPolar(topPoint, -1, 17, basePoint);
//设置第3、4、5段距离的文本,与上同,略
//设置总长度的文本
topPoint = ((newArray[0][X] + newArray[newArray->length() - 1]) / 2, newArray[0][Y], 0);
acutPolar(topPoint, -1, 27, basePoint);
//设置横断面的名称,A1-A1,设置其文本为粗体,高度
acutPolar(topPoint, -1,50, basePoint);
//遍历组中所有实体添加扩展数据A1
addXdata(pObj, appName, str);