当前位置: 首页 > article >正文

objectARX自用总结

实体发布到模型空间

AcDbObjectId CDwgDataBaseUtil::PostToModelSpace(AcDbEntity *pEnt, AcDbDatabase *pDb) {if (pEnt == NULL) {return AcDbObjectId::kNull;//空指针}AcDbBlockTable *pTable;//块表AcDbBlockTableRecord *blkTblRec;//模型空间记录AcDbObjectId objId;//对象IDpDb->getBlockTable(pTable, AcDb::OpenMode::kForRead);//从数据库pDb中获取块表(block table),并将其存储在变量pTable中。这个操作使用只读模式。pTable->getAt(ACDB_MODEL_SPACE, blkTblRec,AcDb::OpenMode::kForWrite);//在块表(block table)中获取模型空间的记录,并将其存储在变量blkTblRec中。这个操作使用写入模式。pTable->close();//关闭块表(block table)Acad::ErrorStatus status=blkTblRec->appendAcDbEntity(objId,pEnt);//在模型空间记录(block table record)中追加实体。如果操作成功,则返回状态码Acad::eOk;否则,返回其他状态码。if (status != Acad::eOk) {blkTblRec->close();delete pEnt;pEnt = NULL;return AcDbObjectId::kNull;}blkTblRec->close();pEnt->close();return objId;
}

 获取AutoCAD数据库中所有满足指定图层条件的实体对象ID

//获取AutoCAD数据库中所有满足指定图层条件的实体对象ID
AcDbObjectIdArray CDwgDataBaseUtil::GetAllEntityIds(const TCHAR* layerName, AcDbDatabase *pDb)
{AcDbObjectIdArray entIds;	// 满足条件的实体ID集合bool bFilterLayer = false;	// 是否需要过滤图层AcDbObjectId layerId; if (layerName != NULL)//如果layerName不为NULL,则需要进行图层过滤{   // 获取层表->判断是否有该图层->获得层表id->设置过滤控制符AcDbLayerTable *pLayerTbl = NULL;//访问AutoCAD的图层表acdbHostApplicationServices()->workingDatabase()//调用ObjectARX函数获取工作数据库的符号表,并将其赋值给pLayerTbl。->getSymbolTable(pLayerTbl, AcDb::kForRead);if (!pLayerTbl->has(layerName))//检查指定的图层是否存在,如果存在,则获取该图层的ID,并将bFilterLayer设置为true{pLayerTbl->close();return entIds;}pLayerTbl->getAt(layerName, layerId);pLayerTbl->close();bFilterLayer = true;}// 获得块表AcDbBlockTable *pBlkTbl = NULL;pDb->getBlockTable(pBlkTbl, AcDb::kForRead);// 获得模型空间的块表记录AcDbBlockTableRecord *pBlkTblRcd = NULL;pBlkTbl->getAt(ACDB_MODEL_SPACE, pBlkTblRcd, AcDb::kForRead);pBlkTbl->close();// 创建遍历器,依次访问模型空间的每一个实体AcDbBlockTableRecordIterator *it = NULL;pBlkTblRcd->newIterator(it);for (it->start(); !it->done(); it->step()){   // 如果过滤控制符为真,获得该层上所有实体的idAcDbEntity *pEnt = NULL;Acad::ErrorStatus es = it->getEntity(pEnt, AcDb::kForRead);//使用迭代器获取当前实体的指针,并检查获取操作是否成功。if (es == Acad::eOk){if (bFilterLayer)	// 过滤图层{if (pEnt->layerId() == layerId)//检查当前实体是否属于指定的图层{entIds.append(pEnt->objectId());//将该实体的ID添加到entIds数组中}}else{entIds.append(pEnt->objectId());}pEnt->close();}else{acutPrintf(TEXT("\nCDwgDatabaseUtil::GetAllEntityIds中打开实体失败(错误代码:%d)."), (int)es);}}delete it;pBlkTblRcd->close();//释放资源,关闭打开的对象和迭代器return entIds; //返回满足条件的实体对象ID数组。
}

图层操作 

//从CAD的图层表中获取指定图层的ID(图层名称)
AcDbObjectId CLayerUtil::GetLayerId(const TCHAR * layerName)
{assert(layerName != NULL);AcDbLayerTable *lTable = NULL;//AcDbLayerTable是AutoCAD中存储图层信息的数据结构if (acdbHostApplicationServices()->workingDatabase()->getSymbolTable(lTable, AcDb::OpenMode::kForRead) != ErrorStatus::eOk)return AcDbObjectId::kNull;//打开工作数据库并将lTable指向它,以读取模式打开AcDbObjectId lId;//存储图层的ID//检查指定的图层名是否存在于图层表中if (lTable->has(layerName)) {lTable->getAt(layerName, lId);//如果指定的图层名存在于图层表中,这行代码将从图层表中获取该图层的ID,并将其存储在变量lId中}lTable->close();//关闭图层表,释放相关资源return lId;//返回存储在变量lId中的图层ID
}
//处理AutoCAD的图层(图层名称,颜色索引)
AcDbObjectId CLayerUtil::Add(const ACHAR* layerName, const int colorIndex)
{assert(layerName != NULL);//图层名称是否为空bool colorRight = (colorIndex >= 1 && colorIndex <= 255);assert(colorRight);//颜色索引是否在1到255的范围内if (!colorRight){acutPrintf(_T("\n颜色索引值无效!"));}AcDbLayerTable* lTable = NULL;//AcDbLayerTable是AutoCAD中存储图层信息的数据结构。if (acdbHostApplicationServices()->workingDatabase()->getSymbolTable(lTable, AcDb::OpenMode::kForWrite) != ErrorStatus::eOk)return AcDbObjectId::kNull;if (lTable->has(layerName)) {//检查指定的图层名是否已经存在于图层表中lTable->close();acutPrintf(TEXT("已存在该层名\n"));return AcDbObjectId::kNull;}else {//新建图层AcDbLayerTableRecord* lRec = new AcDbLayerTableRecord();lRec->setName(layerName);//创建一个新的AcCmColor对象,并将其指针赋值给c。AcCmColor* c = new AcCmColor();//然后设置这个颜色的颜色索引为输入的colorIndexc->setColorIndex(colorIndex);lRec->setColor(*c);//将新图层的颜色设置为上一步创建的颜色的副本。AcDbObjectId  lId;//存储新图层的ID。lTable->add(lId, lRec);//将新图层添加到图层表中,并将新图层的ID存储在lId中lRec->close(); //关闭新创建的图层记录,释放其内存delete c;//删除创建的AcCmColor对象,释放其内存lTable->close();acutPrintf(TEXT("添加成功\n"));return lId;}
}
//设置指定图层的颜色(图层的名称,颜色索引)
bool CLayerUtil::SetColor(const TCHAR * layerName, const int colorIndex)
{   //将图层名称转换为图层ID,并将其赋值给lIdAcDbObjectId lId = GetLayerId(layerName);assert(colorIndex >= 1 && colorIndex <= 255);if (lId.isNull()) {return false;}else{AcDbLayerTableRecord *lRec = NULL; // AutoCAD的图层表记录。if (acdbOpenObject(lRec, lId, AcDb::OpenMode::kForWrite) != ErrorStatus::eOk)return false;AcCmColor *color = new AcCmColor();color->setColorIndex(colorIndex);//设置新创建的颜色的颜色索引为输入的颜色索引lRec->setColor(*color);//将新创建的颜色应用到打开的图层记录delete color;lRec->close();return true;}
}
//获取AutoCAD图层表中所有图层的ID
void CLayerUtil::GetLayerList(AcDbObjectIdArray & lIds)
{AcDbLayerTable *lTable = NULL; //存储图层信息的数据acdbHostApplicationServices()->workingDatabase()->getSymbolTable(lTable, AcDb::OpenMode::kForRead);AcDbLayerTableIterator * lIter = NULL;//这个迭代器用于遍历图层表lTable->newIterator(lIter);//创建一个新的图层表迭代器,并将其赋值给lIterfor (lIter->start(); !lIter->done();lIter->step())/*这是一个循环,开始于图层表的起始位置,当迭代器没有完成时(即还有更多的图层),循环会继续。每次迭代后,都会调用lIter->step()来前进到下一个图层。*/{   //使用迭代器的getRecordId方法获取当前图层的ID,并将其赋值给lIdAcDbObjectId lId;lIter->getRecordId(lId);lIds.append(lId);//将当前图层的ID添加到输入参数lIds}delete lIter;//删除图层表迭代器,释放其占用的内存
}

 几何类(中心点,偏移,删除重复点等)

AcGePoint2d FymGeometry::GetMiddlePt(const AcGePoint2d& startPt, const AcGePoint2d& endPt)
{double x = (startPt.x + endPt.x) * 0.5;double y = (startPt.y + endPt.y) * 0.5;return AcGePoint2d(x, y);
}AcGePoint3d FymGeometry::GetMiddlePt(const AcGePoint3d& startPt, const AcGePoint3d& endPt)
{double x = (startPt.x + endPt.x) * 0.5;double y = (startPt.y + endPt.y) * 0.5;double z = (startPt.z + endPt.z) * 0.5;return AcGePoint3d(x, y, z);
}AcGePoint3d FymGeometry::Polar(const AcGePoint3d& basePoint, double angle, double length)
{double x = basePoint.x + length * cos(angle);double y = basePoint.y + length * sin(angle);return AcGePoint3d(x,y,basePoint.z);
}AcGePoint3d FymGeometry::RelativePoint(const AcGePoint3d& Pt, double x, double y)
{AcGePoint3d ptReturn(Pt.x + x, Pt.y + y, Pt.z);return ptReturn;
}
//比较两个AcGePoint2d类型的点(即二维坐标点)是否相等,tol为公差
bool CGePointUtil::IsEqual(const AcGePoint2d & firstPoint, const AcGePoint2d & secondPoint, double tol)
{return (fabs(firstPoint.x - secondPoint.x) < tol&&fabs(firstPoint.y - secondPoint.y) < tol);
}
//比较两个AcGePoint3d类型的点(即三维坐标点)是否相等。
bool CGePointUtil::IsEqual(const AcGePoint3d & firstPoint, const AcGePoint3d & secondPoint, double tol)
{return (fabs(firstPoint.x - secondPoint.x) < tol&&fabs(firstPoint.y - secondPoint.y) < tol&&fabs(firstPoint.z - firstPoint.z) < tol);
}
//在给定的三维点数组points中查找一个特定的三维点point。如果找到了这个点,函数会返回这个点的索引值;如果没有找到,函数会返回-1。
int CGePointUtil::FindPoint(const AcGePoint3dArray & points, const AcGePoint3d & point, double tol)
{for (int i = 0; i < points.length(); i++){if (IsEqual(points[i], point, tol)) {return i;}}return -1;
}
//在给定的二维点数组points中查找一个特定的二维点point。如果找到了这个点,函数会返回这个点的索引值;如果没有找到,函数会返回-1。
int CGePointUtil::FindPoint(const AcGePoint2dArray & points, const AcGePoint2d & point, double tol)
{for (int i = 0; i < points.length(); i++){if (IsEqual(points[i], point, tol)) {return i;}}return -1;
}
//  过滤掉那些在给定的公差范围内的重复点。
void CGePointUtil::FilterEqualPoints(AcGePoint3dArray & points, double tol)
{for (int i = points.length() - 1; i > 0; i--) {
//  遍历数组中的每个点,从最后一个开始for (int j = 0; j < i; j++) {if (MathUtil::IsEqual(points[i].x, points[j].x, tol) &&MathUtil::IsEqual(points[i].y, points[j].y, tol)) {//检查当前点(i)和另一个点(j)的x和y坐标是否在给定的公差范围内是否相等。points.removeAt(i); //移除当前点(i),删除重复的点break;}}}}
//遍历一个包含三维点的数组,并删除所有与给定的二维点距离在给定的公差范围内的三维点
void CGePointUtil::FilterEqualPoints(AcGePoint3dArray & points, const AcGePoint2d & pt, double tol)
{AcGePoint3dArray tempPoints; //存储过滤后的非重复三维点for (int i = 0; i < points.length(); i++){//距离大于给定的公差tol,那么它将这个三维点添加到临时数组tempPoints中if (CConvertUtil::ToPoint2d(points[i]).distanceTo(pt)>tol) {tempPoints.append(points[i]);}}points = tempPoints;//这样输入数组points现在就只包含那些距离给定的二维点pt大于给定公差的非重复三维点
}

 点,角度等转换,整型,浮点型,字符型转换,坐标系转换

AcGePoint3d FymConverUtil::ToPoint3d(const AcGePoint2d& pt, double z)
{return AcGePoint3d(pt.x, pt.y, z);
}AcGePoint2d FymConverUtil::ToPoint2d(const AcGePoint3d& pt)
{return AcGePoint2d(pt.x, pt.y);
}double FymConverUtil::AngleToRadion(double angle)
{return angle * FymMathUtil::PI() / 180;
}double FymConverUtil::RadionToAngle(double radius)
{return radius * 180 / FymMathUtil::PI();
}CString FymConverUtil::ToString(int val)// 整型转字符串(需要支持MFC)
{CString str;str.Format(_T("%d"), val);//使用'Format'函数将整数'val'格式化为字符串,并存储在'str'中。'_T("%d")'是一个宏,用于生成一个包含'%d'的宽字符字符串,其中'%d'会被替换为'val'的值return str;
}//将一个双精度浮点数转换为字符串。precision 参数指定了小数点后的位数,默认2
CString CConvertUtil::ToString(double value, int precision /*= 2*/)
{CString strFormat, str;strFormat.Format(TEXT("%%.%df"), precision);//使用 strFormat.Format() 函数将格式字符串 "%%.%df" 中的 %df 替换为 precision 参数的值str.Format(strFormat, value);//使用 str.Format() 函数将格式化的字符串和输入的浮点数 value 结合在一起,生成最终的字符串return str;
}
//将一个TCHAR类型的字符串转换为双精度浮点数。
double CConvertUtil::ToDouble(const TCHAR* str)
{TCHAR* pszStop = NULL;return _tcstod(str, &pszStop);
}/*_tcstod 函数将字符串转换为浮点数。_tcstod 是C++中用来将TCHAR类型的字符串转换为双精度浮点数的函数。它需要两个参数:要转换的字符串和用于存储转换结束位置的指针。在这里,我们没有用到 pszStop,所以它的值被设为 NULL。返回值就是转换后的浮点数。*/AcGePoint3d FymConverUtil::WcsPointToDcsPoint(const AcGePoint3d& point)
{AcGePoint3d pt;struct resbuf rbFrom, rbTo;rbFrom.restype = RTSHORT;rbFrom.resval.rint = 0;rbTo.restype = RTSHORT;rbTo.resval.rint = 2;//对浮点数进行四舍五入// 坐标系转换函数:wcs坐标、wcs标识符(0)、dcs标识符(2)、类型为点(0)、dcs坐标acedTrans(asDblArray(point), &rbFrom, &rbTo, 0, asDblArray(pt));return pt;}AcGePoint3d FymConverUtil::UcsPointToWcsPoint(const AcGePoint3d& point)
{AcGePoint3d pt;struct resbuf rbFrom, rbTo;rbFrom.restype = RTSHORT;rbFrom.resval.rint = 1;rbTo.restype = RTSHORT;rbTo.resval.rint = 0;// 坐标系转换函数:ucs坐标、ucs标识符(1)、wcs标识符(0)、类型为点(0)、wcs坐标acedTrans(asDblArray(point), &rbFrom, &rbTo, 0, asDblArray(pt));return pt;
}AcGePoint3d FymConverUtil::WcsPointToUcsPoint(const AcGePoint3d& point)
{AcGePoint3d pt;struct resbuf rbFrom, rbTo;rbFrom.restype = RTSHORT;rbFrom.resval.rint = 0;rbTo.restype = RTSHORT;rbTo.resval.rint = 1;// 坐标系转换函数:wcs坐标、ucs标识符(1)、wcs标识符(0)、类型为点(0)、ucs坐标acedTrans(asDblArray(point), &rbFrom, &rbTo, 0, asDblArray(pt));return pt;
}

通过用户交互界面获取输入

int CGetInputUtil::GetPointReturnCode(const AcGePoint3d & basePoint, const TCHAR * prompt, AcGePoint3d & point)
{AcGePoint3d ucsBasePoint = CConvertUtil::WcsToUcsPoint(basePoint);//basePoint从WCS(世界坐标系)转换为UCS(用户坐标系)int nReturn = acedGetPoint(asDblArray(ucsBasePoint), prompt, asDblArray(point));//asDblArray将pnt返回为三个双精度数组/*这一行代码调用AutoCAD的API函数acedGetPoint,获取用户输入的点。这个函数需要三个参数:一个点的数组(我们前面已经将basePoint转换为UCS,所以这里传入ucsBasePoint),一个提示字符串(prompt),和一个点的数组(用于存储用户输入的点,我们传入的是point)*/if (nReturn == RTNORM) {point = CConvertUtil::UcsToWcsPoint(point);}//如果返回值是RTNORM(这通常表示正常的结束状态),那么就将用户输入的点从UCS转换为WCS。return nReturn;}int CGetInputUtil::GetPointReturnCode(const TCHAR * prompt, AcGePoint3d & point)
{int nReturn = acedGetPoint(NULL, prompt, asDblArray(point));if (nReturn == RTNORM) {point = CConvertUtil::UcsToWcsPoint(point);}return nReturn;}bool CGetInputUtil::GetPoint(const AcGePoint3d & basePoint, const TCHAR * prompt, AcGePoint3d & point)
{if (GetPointReturnCode(basePoint, prompt, point) == RTNORM){acutPrintf(_T("\n用户成功输入了一个点"))return true;}else{return false;}
}bool CGetInputUtil::GetPoint(const TCHAR * prompt, AcGePoint3d & point)
{if (GetPointReturnCode(prompt, point) == RTNORM){acutPrintf(_T("\n用户成功输入了一个点"))return true;}else{return false;}
}
//获取关键词的函数(提示字符串,关键词字符串,默认关键词字符串,默认关键词索引,指向整数的引用)
bool CGetInputUtil::GetKeyword(const TCHAR * prompt, const TCHAR * keywords, const TCHAR * firstDefault, int defaultKeyIndex, int & nRet)
{int rc;//整数变量rc,用于存储函数acedGetKword的返回值TCHAR kword[20];//字符数组kword,用于存储用户输入的关键词//firstDefault参数输入NULL表示不予许直接按ENTER键acedInitGet(firstDefault == NULL ? 1 : 0, keywords);//调用acedInitGet函数初始化获取关键词的环境。如果firstDefault为NULL,则第一个参数为1,否则为0。第二个参数是关键词字符串。CString strPrompt = prompt;if (firstDefault != NULL) {//在提示字符串后添加"<"、firstDefault和">:"strPrompt += L"<";strPrompt += firstDefault;strPrompt += ">:";}else {strPrompt += L":";}rc = acedGetKword(strPrompt, kword);// 调用acedGetKword函数获取用户输入的关键词,并存储在kword中switch (rc) {case RTCAN:return false;//按下esccase RTNONE://按enternRet = defaultKeyIndex;return true;case RTNORM:{std::vector<CString>items;CStringUtil::Split(keywords, TEXT(" "), items);for (int i = 0; i < (int)items.size(); i++){if (items[i].CompareNoCase(kword) == 0) {nRet = i;break;}}return true;}default:return false;}
}
//提示用户输入一个实数。如果用户输入了一个有效的实数,或者没有输入而直接按回车(即默认值),则函数返回true。否则,返回false
bool CGetInputUtil::GetReal(const TCHAR * prompt, double defaultVal, int precision, double & ret)
{//参数(提示用户输入的字符串,默认的实数值d,表示精度的整数,用于保存用户输入的实数的引用)CString strPrompt = prompt;strPrompt.TrimRight();//去掉字符串末尾的空格。strPrompt.TrimRight(TEXT(":"));// 去掉字符串末尾的冒号。CString strDefaultValue;// 创建一个新的CString对象strDefaultValuestrDefaultValue.Format(TEXT("<%%.%df>:"), precision);/* 使用Format方法格式化字符串,其中<%%.%df>:是一个占位符,%d表示整数部分,%f表示小数部分,precision表示小数点后的位数。例如,如果精度为3,那么占位符将被替换为<%%.3f>。*/strPrompt.Format(strPrompt + strDefaultValue, defaultVal);//将格式化的默认值添加到提示字符串中。ret = defaultVal;//将默认值赋给函数的引用参数retint rc = acedGetReal(strPrompt, &ret);//获取用户的实数输入,并将结果存储在变量rc中if (rc == RTNORM || rc == RTNONE) {return true;}else {return false;}}

 获取模块(即当前正在运行的程序dll)的文件路径

//获取模块(即当前正在运行的程序dll)的文件路径
CString CAppDirectoryUtil::GetCurrentDirectory(HMODULE hInstance)
{TCHAR szPath[255];//存储模块的文件路径//获取当前模块的文件路径。这个函数将模块的完整路径存储在 szPath 数组中GetModuleFileName(hInstance, szPath, sizeof(szPath));//获取 szPath 中最后一个反斜杠(\\)的位置,并将该位置处的字符设置为 null 字符(\0)// ,从而截断字符串,得到应用程序的目录*(_tcsrchr(szPath, '\\')) = 0;CString strResult = szPath;//将截断后的路径存储在 strResult 中。return strResult;//返回应用程序的目录
}
//获取模块的父目录的绝对路径
CString CAppDirectoryUtil::GetParentDirectory(HMODULE hInstance)
{TCHAR szPath[256];GetModuleFileName(hInstance, szPath, sizeof(szPath));*(_tcsrchr(szPath, '\\')) = 0;*(_tcsrchr(szPath, '\\')) = 0;CString strResult = szPath;return strResult;
}

 数值计算

double MathUtil::PI()
{return atan(1.0) * 4;//常识,求π的高精度表示//tan π/4=1 所以 atan( 1 ) = π/4,PI = atan(1) * 4
}
// 判断两个双精度浮点数是否相等,因为浮点数都是近似存储
bool MathUtil::IsEqual(double a, double b, double tol)
{   // 当两个浮点数的差小于10E-7,则判定两个浮点数相等return (fabs(a - b) < tol);
}
//一位小数四舍五入
int MathUtil::Round(double a)
{return(int)(a + 0.5);
}
//圆整,四舍五入
double MathUtil::Round(double a, int precision)
{return (floor(a*pow(10.0, precision) + 0.5) / pow(10.0, precision));//a乘10 的 precision 次方加0.5,用floor向下取整,最后除以10的p次方,从而将小数点移回到原来的位置
}
//生成一个在指定范围minValue和maxValue之间的随机整数
int MathUtil::GetRand(int minValue, int maxValue)
{assert(maxValue - minValue);//使用assert宏来检查maxValue和minValue之间的差异。如果maxValue小于或等于minValue,那么assert宏将抛出一个断言错误int value = rand();//调用标准库中的rand()函数来生成一个随机整数,并将其赋值给变量valueint rc=minValue+((int)CMathUtil::Round(((double)value)/RAND_MAX*(maxValue - minValue)));/*这行代码首先将value强制转换为double类型,然后除以RAND_MAX(在标准库中,这是一个表示随机数生成器可以生成的最大值的常量)。这样做的目的是将生成的随机数缩放到[0, maxValue - minValue]的范围内。然后使用CMathUtil::Round函数对这个浮点数进行四舍五入,并转换回整数。最后,将结果加上minValue,以将生成的随机数转换回原始的范围[minValue, maxValue]。*/return rc;//最后,这行代码返回计算出的随机整数。
}

文件操作

//文件操作函数,将一系列字符串保存到一个文本文件中(字符串,保存的文件名;字符串的向量,写入文件的内容)
void TextFileUtil::Save(const TCHAR* fileName, const std::vector<CString> &lines)
{   // 以下是支持MFC才有的,相当于open函数功能CStdioFile file(fileName, CFile::modeCreate | CFile::modeWrite | CFile::typeText);for (int i = 0; i < (int)lines.size(); i++){file.WriteString(lines[i]);//写入每个字符串并换行file.WriteString(_RXST("\n"));}file.Close();
}
//从指定的文本文件中读取所有行,并将它们存储在lines这个向量中(读取的文本文件的名称,保存读取到的文本文件的每一行)
bool TextFileUtil::Load(const TCHAR* fileName, std::vector<CString> &lines)
{// 纠错函数:如果文件不存在打印if (PathFileExists(fileName) != TRUE){acutPrintf(_T("\n读取的文件不存在!"));return false;}else{lines.clear();CStdioFile file(fileName, CFile::modeRead | CFile::typeText);CString strLine;//用于保存从文件中读取的每一行while (file.ReadString(strLine))//尝试从打开的文件中读取一行文本,并将其保存在strLine变量中{lines.push_back(strLine);//将每一行(保存在strLine中)添加到lines向量中}return true;}
}
// 通过对话框选择获取文件绝对路径(多选):一些MFC语句,了解即可,重点看注释语句
bool TextFileUtil::SelectFilePath(CStringArray& fileNameArray)
{// 构建文件过滤器CNavFilter* filter;// 过滤的注释LPCTSTR filterDesc[] = { _T("可选文件格式"), NULL };// 过滤的后缀名:可以在null前增加后缀LPCTSTR filterDWG[] = { _T("*.dwg"),_T("*.dxf"), NULL };LPCTSTR* filterSpec[] = { filterDWG, NULL };CNavFilterArray gFilterArray;gFilterArray.RemoveAllData();int i = 0, j;while (filterSpec[i] != NULL){filter = gFilterArray.AddData();if (filter != NULL){filter->SetDescription(filterDesc[i]);j = 0;while (filterSpec[i][j] != NULL){filter->Add(filterSpec[i][j]);j++;}}i++;}fileNameArray.RemoveAll();CNavDataArray gDataArray;while (true){	// 获取autoCAD的窗口句柄HWND acadhandle = adsw_acadMainWnd();// 使句柄成为当前窗口::EnableWindow(acadhandle, true);// 设置焦点::SetFocus(acadhandle);// 获取MFC的主窗口CWnd* pWnd = CWnd::FromHandle(acadhandle);CAcUiNavDialog dlg(gDataArray, gFilterArray, 0, pWnd);// 开启多选模式dlg.SetMultiSelectAllowed(true);// 对话框标题dlg.SetDialogCaption(_T("多选对话框"));// 设置当前点选的文件可见缩略图dlg.SetPreviewPresent(true);dlg.SetPreviewVisible(true);// 如果点选了确认按钮if (dlg.DoModal() == IDOK){for (int i = 0; i < gDataArray.GetCount(); i++){LPITEMIDLIST id = gDataArray.GetAt(i)->GetID();// 获取并打印:每个选择到的 文件绝对路径 的 字符串fileNameArray.Add(gDataArray.GetAt(i)->GetText());}}// 跳出循环break;}if (fileNameArray.GetCount() > 0)return true;elsereturn false;
}

字体,文本样式 

// 创建字体样式:字体样式名、字体文件名、大字体文件名(亚洲国家用)
AcDbObjectId FymTextStyle::Add(const ACHAR *name, const ACHAR *fontFileName, const ACHAR *bigfontFile)
{   // 获得字体样式表Acad::ErrorStatus es;AcDbTextStyleTable *pTextStyle = NULL;es = acdbHostApplicationServices()->workingDatabase()->getTextStyleTable(pTextStyle, AcDb::kForWrite);if (es != ErrorStatus::eOk){acutPrintf(L"\n打开文字样式表失败");return AcDbObjectId::kNull;}// 创建字体样式表记录AcDbTextStyleTableRecord* pTextStyleRcd = new AcDbTextStyleTableRecord();// 字体样式表记录添加:名称、字体文件名、比例、pTextStyleRcd->setName(name);pTextStyleRcd->setBigFontFileName(bigfontFile);pTextStyleRcd->setFileName(fontFileName);pTextStyleRcd->setXScale(1.0);// 字体样式记录添加进字体样式表中pTextStyle->add(pTextStyleRcd);// 返回字体样式表记录idAcDbObjectId styleId = pTextStyleRcd->objectId();pTextStyleRcd->close();pTextStyle->close();return styleId;
}
// 从AutoCAD的文本样式表中获取指定名称的文本样式的ID:字体样式名称
AcDbObjectId FymTextStyle::GetStyleId(const ACHAR* styleName)
{AcDbObjectId textStyleId = AcDbObjectId::kNull;// 如果字体样式名非空if (_tcslen(styleName)>0){AcDbTextStyleTable* pTextStyle = NULL;// 获得字体样式表指针Acad::ErrorStatus es;es = acdbHostApplicationServices()->workingDatabase()->getTextStyleTable(pTextStyle, AcDb::kForRead);// 获得字体样式记录id 并赋值textStyleIdif (es != ErrorStatus::eOk) {acutPrintf(L"未能打开文本样式表");return AcDbObjectId::kNull;}AcDbObjectId styleId;if (pTextStyle->has(styleName)) {pTextStyle->getAt(styleName, textStyleId);pTextStyle->close();return textStyleId;// 若字体样式名为空,返回kNull}else {pTextStyle->close();return AcDbObjectId::kNull;}}else {acutPrintf(L"请输入文本样式的名称");return AcDbObjectId::kNull;}
}
//获取AutoCAD中所有文本样式的名称,并存储命名为styleNames,返回对象数组
AcDbObjectIdArray FymTextStyle::GetAll(std::vector<CString>& styleNames)
{AcDbObjectIdArray styleIds;styleNames.clear();AcDbTextStyleTable* pStyleTable = NULL;Acad::ErrorStatus es;es = acdbHostApplicationServices()->workingDatabase()->getTextStyleTable(pStyleTable, AcDb::kForRead);//获取当前工作数据库,调用getTextStyleTable方法来以只读方式获取文本样式表,并将其赋值给pStyleTable指针if (es != ErrorStatus::eOk) {acutPrintf(L"未能打开文本样式表");return styleIds;}AcDbTextStyleTableIterator* pItr = NULL;pStyleTable->newIterator(pItr);//创建一个新的文本样式表迭代器,并将其赋值给pItr指针for (pItr->start();!pItr->done();pItr->step()){// 从文本样式表的起始位置开始迭代,直到完成遍历AcDbTextStyleTableRecord* pRcd;pItr->getRecord(pRcd, AcDb::kForRead);// 获取当前迭代的文本样式表记录,并将其赋值给pRcd指针ACHAR* textStyleName;//存储文本样式的名称pRcd->getName(textStyleName);//获取文本样式的名称,并将其赋值给textStyleName指针if (_tcslen(textStyleName)>0)//检查textStyleName的长度是否大于0{styleNames.push_back(textStyleName);//将textStyleName添加到传递给方法的styleNames向量中styleIds.append(pRcd->objectId());//获取并添加文本样式记录的对象ID}acutDelString(textStyleName);//释放textStyleName的内存pRcd->close();//关闭当前迭代的文本样式表记录}delete pItr;//删除创建的文本样式表迭代器pStyleTable->close();//关闭文本样式表
}

 文字输入

//在AutoCAD的模型空间中创建一个新的文本对象(单行),并返回这个新对象的ID(三维插入点、文本字符串、文本样式、文本高度和旋转角度)
AcDbObjectId FymText::AddText(const AcGePoint3d& ptInsert, const ACHAR* text, AcDbObjectId style, double height, double rotation)
{   //创建一个新的AcDbText对象,即CAD中创建的文本AcDbText* pTxt = new AcDbText(ptInsert, text, style, height, rotation);return FymDatabase::PostToModelSpace(pTxt);
}
//CAD模型空间创建多行文本
AcDbObjectId FymText::AddMText(const AcGePoint3d& ptInsert, const ACHAR* text, AcDbObjectId style, double height, double width)
{AcDbMText* pMtext = new AcDbMText();pMtext->setTextStyle(style);//样式pMtext->setContents(text);//文本内容pMtext->setLocation(ptInsert);//插入点pMtext->setHeight(height);//文字高度pMtext->setWidth(width);//宽度pMtext->setAttachment(AcDbMText::kBottomLeft);//位置:左下角return FymDatabase::PostToModelSpace(pMtext);//返回ID并添加到模型空间
}

 字符串操作

void StringUtil::Split(const CString& text, const ACHAR* separator, std::vector<CString>& result, bool bAddEmptyStr)
{int prev = 0, current = 0;// 初始化两个指针,prev(前一个索引号)和current(当前索引号),都设置为0  CString strCopyTxT = text;// 创建一个text的副本,并去除其右边的空格  strCopyTxT.TrimRight(_T(" "));if (strCopyTxT.Find(separator,0)<0)//如果在副本中找不到分隔符,未找到返回-1,那么整个副本就是一个单独的字符串{if (strCopyTxT.GetLength()>0){result.push_back(strCopyTxT);// 如果副本的长度大于0,则将其添加到字符串容器中  }// 如果传入的字符串长度为0,啥也不添加return;}// 以下为至少发现一个分隔符,获得字符串总长度int length = strCopyTxT.GetLength();// 初始化一个标志位,表示是否已经找到了所有的分隔符bool bExit = false;while (true)// 开启无限循环:注意循环中的break语句{current = strCopyTxT.Find(separator, prev); // 在副本中查找分隔符,从prev指针的位置开始查找 if (current == -1)// 到最后一组了{current = length;bExit = true;// 如果找不到分隔符,将整个字符串长度赋值current,标识退出变量为真}// 取最后一个分隔符到结尾的字符串,Mid见下注释CString item = strCopyTxT.Mid(prev, current - prev);if (bAddEmptyStr || item.GetLength()>0){   // 添加进容器的条件:每个提取的子字符串是否过滤0长度result.push_back(item);// 如果bAddEmptyStr为true,或者子字符串的长度大于0,则将子字符串添加到结果列表中}if (bExit){break;// 如果已经找到了所有的分隔符,那么跳出循环 }prev = current + int(_tcslen(separator)); // 将prev指针移动到当前分隔符的后面,以便在下一次循环中查找下一个分隔符  }
}
// 合并字符串:传入字符串容器、分隔符,返回合并的字符串
CString StringUtil::Join(const std::vector<CString>& items, const ACHAR *spearator)
{CString strResult;// 逐个拼接容器中的字符串for (int i = 0; i < items.size();i++){strResult += items.at(i) + spearator;}// 删除右侧的空字符strResult.TrimRight(spearator);//调用'TrimRight'函数,从'strResult'的右侧删除所有的分隔符。这样做是为了避免在最后一个元素后面出现不必要的分隔符return strResult;// 返回拼接好的字符串
}

 实体的选中

//提示用户选择AutoCAD中的实体,并将所选择的实体的ID添加到一个AcDbObjectIdArray数组中。
bool CSelectUtil::PromptSelectEnts(const TCHAR * prompt, resbuf * rb,AcDbObjectIdArray & entIds)//(提示字符串,指向resbuf的指针,id数组引用entIds。返回类型为布尔值)
{ads_name selName;acutPrintf(prompt);//打印出传入的提示字符串int rc = acedSSGet(NULL, NULL, NULL, rb, selName);//提示用户选择实体。选择的结果存储在selName中,并返回一个整数rc作为结果代码if (rc == RTNORM) {//用户正常选择了实体int length;acedSSLength(selName, &length);// 获取用户选择实体的数量for (int i = 0; i < length; i++)//循环遍历每一个选择的实体{ads_name name;acedSSName(selName, i, name);//获取第i个选择实体的名称AcDbObjectId oId;if (acdbGetObjectId(oId, name) == ErrorStatus::eOk) {entIds.append(oId);//尝试获取实体的ID。如果成功将该ID添加到entIds数组中}}acedSSFree(selName);//释放与selName相关的内存return true;//如果用户正常选择了实体,则返回true}else {acedSSFree(selName);//释放与selName相关的内存acutPrintf(_T("\n用户没有选择任何实体或者发生了错误"));return false;}
}
//提示用户选择实体并获取选定实体ID(提示用户进行选择的消息,保存选择集,保存类描述,保存选定的实体ID)
bool CSelectUtil::PromptSelectEnts(const TCHAR * prompt, resbuf * rb, std::vector<AcRxClass*>& classDescs, AcDbObjectIdArray & entIds)
{ads_name selName;acutPrintf(prompt);//打印提示消息(prompt)int rc = acedSSGet(NULL, NULL, NULL, rb, selName);if (rc == RTNORM) {int length;acedSSLength(selName, &length);for (int i = 0; i < length; i++){ads_name name;acedSSName(selName, i, name);AcDbObjectId oId;if (acdbGetObjectId(oId, name) == ErrorStatus::eOk) {AcDbEntity *ent = NULL;if (acdbOpenObject(ent, oId) != ErrorStatus::eOk) {continue;}for (int j = 0; j < (int)classDescs.size(); j++){if (ent->isKindOf(classDescs[j])) {entIds.append(ent->objectId());break;}}ent->close();}}}acedSSFree(selName);return (entIds.length() > 0);
}bool CSelectUtil::PromptSelectEnts(const TCHAR * prompt, resbuf * rb, AcRxClass *& classDescs, AcDbObjectIdArray & entIds)
{std::vector<AcRxClass*> vec;vec.push_back(classDescs);//将classDescs添加到了vec的尾部return CSelectUtil::PromptSelectEnts(prompt, rb, vec, entIds);
}
//提示用户选择一个实体,并检查所选实体是否符合一系列指定的类描述(...,包含类描述的向量,用于返回所选实体的引用,用于存储选择点的pickPoint,布尔值(决定打开实体的模式是只读还是可写)。
bool CSelectUtil::PromptSelectEntity(const TCHAR * prompt, std::vector<AcRxClass*>& classDescs, AcDbEntity *& pEnt, AcGePoint3d & pickPoint, bool bOpenForWrite)
{ads_name entName;
// 如果用户没有选择有效的实体(例如,取消了选择),代码会跳转到标签RETRY,重新提示用户进行选择。
RETRY:if (acedEntSel(prompt, entName, asDblArray(pickPoint)) == RTNORM) 
{AcDbObjectId oId;//尝试从AutoCAD的内部名称空间获取所选实体的对象ID。如果成功,它将返回ErrorStatus::eOk。if (acdbGetObjectId(oId, entName) == ErrorStatus::eOk) //提示用户选择一个实体,并将所选实体的名称存储在entName中,同时将选择点存储在pickPoint中。{ErrorStatus es;if (bOpenForWrite) //决定是以写入模式还是读取模式打开所选实体{es = acdbOpenObject(pEnt, oId, AcDb::OpenMode::kForWrite);}else {es = acdbOpenObject(pEnt, oId, AcDb::OpenMode::kForRead);}//如果打开实体失败(例如,因为权限问题或实体不存在),函数会返回false。if (es != ErrorStatus::eOk) {pEnt = NULL;return false;}//否则,它会检查所选实体是否属于classDescs中的任何一个类else {bool ret = false;for (int i = 0; i < (int)classDescs.size(); i++){   //检查所选实体是否属于指定的类if (pEnt->isKindOf(classDescs[i])) {ret = true;break;}else{pEnt = NULL;return false;}}if (ret)return true;else {pEnt->close();acutPrintf(L"\n选择的实体类型不符合要求,请再次选择...");goto RETRY;}}}else {   //如果用户没有选择有效的实体(例如,取消了选择),这个调用会失败pEnt = NULL;return false;}
}bool CSelectUtil::PromptSelectEntity(const TCHAR * prompt, AcRxClass *& classDescs, AcDbEntity *& pEnt, AcGePoint3d & pickPoint, bool bOpenForWrite)
{std::vector<AcRxClass*>vec;vec.push_back(classDescs);//将参数classDescs添加到向量vec中return CSelectUtil::PromptSelectEntity(prompt, vec, pEnt, pickPoint, bOpenForWrite);
}

 面域

#include "brbrep.h"
#include "brvtx.h"
#include "brface.h"
#include "bredge.h"
#include "brletrav.h"
#include "brbftrav.h"
#include "brfltrav.h"AcDbObjectIdArray FymRegion::AddRegion(const AcDbObjectIdArray& objIds)//传入面域边界数据库对象id列表
{AcDbObjectIdArray regionArrs;//用于生成面域对象的数组AcDbVoidPtrArray curves;//指向面域曲线边界的指针列表AcDbVoidPtrArray regions;//指向新创建面域对象的指针列表AcDbEntity* pEnt = NULL;//关闭边界曲线实体对象的临时指针AcDbRegion* pRegion = NULL;//面域对象指针,用于将其添加到模型空间for (int i = 0; i < objIds.length(); i++)// 遍历边界对象{   // 提取每个边界对象的指针acdbOpenObject(pEnt, objIds.at(i), AcDb::kForRead);// 判断指针是否为曲线类的派生类(面域边界的必要条件)if (pEnt->isKindOf(AcDbCurve::desc())){   // 将指针类型强制转换为曲线类对象AcDbCurve* pCurve = AcDbCurve::cast(pEnt);curves.append(pCurve);// 添加到指针列表中}}// 用AcDbRegion的方法创建面域:用指针列表curves创建面域Acad::ErrorStatus es = AcDbRegion::createFromCurves(curves, regions);if (es == Acad::eOk){for (int i = 0; i < regions.length(); i++){// pRegion = AcDbRegion::cast((AcDbRegion*)regions.at(i));pRegion = (AcDbRegion*)regions.at(i);pRegion->setDatabaseDefaults(); //重置pRegion对象的所有设置为默认值AcDbObjectId regId;regId = FymDatabase::PostToModelSpace(pRegion);regionArrs.append(regId);}}else{   // 如果创建失败,释放指针指向的内存空间for (int i = 0; i < regions.length(); i++){delete(AcRxObject*)regions.at(i);}}// 关闭对象for (int i = 0; i < curves.length(); i++){pEnt = (AcDbEntity*)curves.at(i);pEnt->close();}return regionArrs;
}//通过遍历给定的面域的所有面和边,来获取面域中所有的点
void FymRegion::GetRegionPoints(AcDbRegion* pRegion, AcGePoint3dArray& points)
{AcBrBrep* pBrep = new AcBrBrep;pBrep->set(*pRegion);//数据复制AcBrBrepFaceTraverser brFaTrav;for (brFaTrav.setBrep(*pBrep); !brFaTrav.done(); brFaTrav.next())//使用brFaTrav遍历AcBrBrep的所有面{//在面遍历循环内部,创建AcBrFaceLoopTraverser对象并获取当前面的信息AcBrFaceLoopTraverser faLoTrav;AcBrFace face;brFaTrav.getFace(face);//使用faLoTrav遍历当前面的所有环。for (faLoTrav.setFace(face); !faLoTrav.done(); faLoTrav.next()){AcBrLoopEdgeTraverser loEdTrav;//在环遍历循环内部,创建AcBrLoopEdgeTraverser对象并尝试设置当前环// 。如果设置成功,进入下一轮循环。if (loEdTrav.setLoop(faLoTrav) == AcBr::eOk){for (; !loEdTrav.done(); loEdTrav.next())//使用loEdTrav遍历环的所有边{AcBrEdge edge;loEdTrav.getEdge(edge);//获取当前边的信息AcBrVertex start;edge.getVertex1(start);//获取边的起始顶点AcGePoint3d pt;start.getPoint(pt);//获取起始顶点的坐标points.append(pt);//将该点的坐标添加到输出数组中}} // 否则就是一个孤立的循环    }}delete pBrep;
}

鼠标拖动 

DrawRecJig::DrawRecJig()
{pl = NULL;
}DrawRecJig::~DrawRecJig()
{
}
//在拖动操作期间获取用户输入的点,并基于这个点以及拖动操作的状态来决定下一步的操作
AcEdJig::DragStatus DrawRecJig::sampler()
{setUserInputControls((AcEdJig::UserInputControls)(//这行代码设置了这个插件接受的用户输入控制。它接受三维坐标、不接受负响应以及接受空响应。AcEdJig::kAccept3dCoordinates |//接受z坐标AcEdJig::kNoNegativeResponseAccepted |//不接受负值AcEdJig::kNullResponseAccepted//空输入可接受));AcGePoint3d ptTemp;//临时存储拖动操作中的点//获取用户输入的点并存储在ptTemp中AcEdJig::DragStatus status = acquirePoint(ptTemp);if (ptTemp != ptCurrent) {//判断当前拖动的点是否与之前的点不同。如果不同,则更新ptCurrent为新的拖动点。ptCurrent= ptTemp;}else if (status == DragStatus::kNormal) {//如果拖动点的状态为正常(即没有特殊情况,例如无效输入或用户取消操作),// 则返回AcEdJig::kNoChange,表示没有发生改变return AcEdJig::kNoChange;}return status;}
//绘图辅助,x型
bool DrawRecJig::update()
{double dist = CConvertUtil::ToPoint2d(ptCenter).distanceTo(CConvertUtil::ToPoint2d(ptCurrent));for (int i = 0; i < 4; i++){double angle = i*MathUtil::PI()*0.5 + MathUtil::PI()*0.25;AcGePoint2d pt = FymGeometry::Polar(CConvertUtil::ToPoint2d(ptCenter), angle, dist);pl->setPointAt(i, pt);//将pt(在折线OCS坐标中)设置为索引顶点的位置,并储存在pl中}return true;
}AcDbEntity * DrawRecJig::entity() const
{return pl;
}
//创建一个四边形多段线,并提示用户拖动它。如果用户按照提示操作,
// 该方法将把多段线发布到模型空间并返回成功;否则,它将删除多段线并返回失败
bool DrawRecJig::DoIt(AcGePoint3d & ptCenter, AcDbObjectId &plId)
{this->ptCenter = ptCenter;pl = new AcDbPolyline();for (int i = 0; i < 4; i++){pl->addVertexAt(i, CConvertUtil::ToPoint2d(ptCenter));}pl->setClosed(true);setDispPrompt(L"请拖动鼠标:");if (drag()==kNormal) {plId=CDwgDataBaseUtil::PostToModelSpace(pl);return true;}else {delete pl;return false;}}

 图形的复制,移动,旋转,对称,缩放

//根据给定的字符数组获取该实体的ID
//tips为acedEntSel()在暂停之前显示的可选字符串; 如果是空指针, AutoCAD将显示"选择对象"默认提示 
AcDbObjectId CTransUtil::GetId(const ACHAR *tips)
{ads_name entName; //存储AutoLISP实体名称ads_point pt; //存储点的坐标if (acedEntSel(tips, entName, pt) == RTNORM) {//选择AutoCAD中的实体AcDbObjectId oId;acdbGetObjectId(oId, entName);return oId;//根据给定的实体名称获取该实体的ID,并将该ID存储在变量oId中}else {return AcDbObjectId::kNull;}
}
//通过克隆给定的对象并返回新对象的ID
AcDbObjectId CTransUtil::MyClone(AcDbObjectId objId)
{if (objId == AcDbObjectId::kNull) {return objId; }else {AcDbEntity *pEnt = NULL;//只读方式打开实体if (acdbOpenAcDbEntity(pEnt, objId, AcDb::OpenMode::kForRead) != ErrorStatus::eOk)return AcDbObjectId::kNull;AcDbEntity *copyEnt = AcDbEntity::cast(pEnt->clone());//克隆通过指针pEnt打开的实体,并将其转换为AcDbEntity类型的指针copyEntAcDbObjectId copyId=CDwgDataBaseUtil::PostToModelSpace(copyEnt);//将克隆的实体发布到模型空间,并将返回的ID存储在变量copyId中。acutPrintf(TEXT("克隆成功!"));pEnt->close();return copyId;//关闭实体并返回新克隆实体的ID。}
}
//将指定的AutoCAD对象按照指定的移动点进行移动
void CTransUtil::Move(const AcGePoint3d & basePoint, const AcGePoint3d & movePoint, AcDbObjectId objId)
{AcDbEntity *pEnt = NULL;if (acdbOpenAcDbEntity(pEnt, objId, AcDb::OpenMode::kForWrite) != ErrorStatus::eOk)return;AcGeMatrix3d matrxMove;//3D变换矩阵,用于进行空间变换AcGeVector3d v = movePoint - basePoint;//从基础点到移动点的向量matrxMove.setTranslation(v);//使用向量v设置矩阵matrxMove的平移部分。这会使实体沿着这个向量移动。pEnt->transformBy(matrxMove);//使用矩阵matrxMove对实体进行变换。这会使实体沿着移动向量移动到新的位置。acutPrintf(TEXT("移动成功!"));pEnt->close();
}
//将指定的AutoCAD实体围绕指定的基点旋转指定的角度。
void CTransUtil::Rotate(const AcGePoint3d & basePoint, const double rotation, AcDbObjectId objId)
{AcDbEntity *pEnt = NULL;if (acdbOpenAcDbEntity(pEnt, objId, AcDb::OpenMode::kForWrite) != ErrorStatus::eOk)return;AcGeVector3d normal = AcGeVector3d(0, 0, 1);//旋转轴pEnt->transformBy(AcGeMatrix3d::rotation(rotation, normal, basePoint));/*使用基点、旋转角度和旋转轴对实体进行变换。这是通过调用transformBy方法实现的,该方法接受一个变换矩阵作为参数。在这个例子中,旋转矩阵是由AcGeMatrix3d::rotation函数生成的。*/acutPrintf(TEXT("旋转成功!"));pEnt->close();
}
//将指定的AutoCAD实体以指定的轴进行对称。
void CTransUtil::Mirrore(AcDbObjectId entId, const AcGeLine3d& line, double rotate)
{AcGeMatrix3d xform;//定义一个三维变换矩阵AcDbEntity *pEnt = NULL;if (acdbOpenAcDbEntity(pEnt, entId, AcDb::OpenMode::kForWrite) != ErrorStatus::eOk)return;pEnt->transformBy(AcGeMatrix3d::mirroring(line));acutPrintf(TEXT("对称成功!"));pEnt->close();
}//将指定的AutoCAD实体以指定的基点缩放。
void CTransUtil::Scale(AcDbObjectId objId, double scale,AcGePoint3d &ptBase)
{AcDbEntity *pEnt = NULL;if (acdbOpenAcDbEntity(pEnt, objId, AcDb::OpenMode::kForWrite) != ErrorStatus::eOk)return;pEnt->transformBy(AcGeMatrix3d::scaling(scale, ptBase));//先调用AcGeMatrix3d::scaling函数创建一个表示缩放操作的矩阵,// 然后调用实体指针pEnt的transformBy方法,将这个矩阵应用于该实体。pEnt->close();acutPrintf(TEXT("缩放成功!"));
}

 图块的创建范例

void CreateBlock()
{AcDbBlockTable* pBlkTbl = NULL;//CAD中图块的表格acdbHostApplicationServices()->workingDatabase()->getBlockTable(pBlkTbl, AcDb::kForWrite);//从当前工作数据库中获取图块表,并将其设置为可写入的AcDbBlockTableRecord* pBlkRcd = new AcDbBlockTableRecord();//创建一个新的图块定义ACHAR blkName[40];//存储图块的名称if (acedGetString(Adesk::kFalse, _RXST("\n请输入图块名称:"), blkName) != RTNORM){   //获取失败(例如用户取消输入),则关闭图块表和删除图块定义,并返回pBlkTbl->close();delete pBlkRcd;return;}pBlkRcd->setName(blkName);//设置图块的名称AcDbObjectId blkDefId;//存储图块定义的IDpBlkTbl->add(blkDefId, pBlkRcd);//将新的图块定义添加到图块表中pBlkTbl->close();//关闭图块表//以下定义了三个实体对象:一条线(pLine)、另一条线(pLine2)和一个圆(pCir)。这些对象代表了图块的实体AcGePoint3d ptStart(-10, 0, 0), ptEnd(10, 0, 0);AcDbLine* pLine = new AcDbLine(ptStart, ptEnd);ptStart.set(0, -10, 0);ptEnd.set(0, 10, 0);AcDbLine* pLine2 = new AcDbLine(ptStart, ptEnd);AcDbCircle* pCir = new AcDbCircle(AcGePoint3d::kOrigin, AcGeVector3d(0, 0, 1), 6);//使用appendAcDbEntity函数将这三个实体添加到图块定义中。注意,这里使用了entId,它应该是相同的ID,表示这些实体都属于同一个图块定义。AcDbObjectId entId;pBlkRcd->appendAcDbEntity(entId, pLine);pBlkRcd->appendAcDbEntity(entId, pLine2);pBlkRcd->appendAcDbEntity(entId, pCir);//关闭这些实体对象和图块定义。pLine->close();pLine2->close();pCir->close();pBlkRcd->close();
}

椭圆 

cDbObjectId FymEllipse::Add(const AcGePoint3d& ptCenter, const AcGeVector3d& vecNormal, const AcGeVector3d& majorAxis, double ratio)
{//缺省的两个参数为椭圆起始弧度与终止弧度,ratio为大半径与小半径比AcDbEllipse* pEllipse = new AcDbEllipse(ptCenter, vecNormal, majorAxis, ratio);return FymDatabase::PostToModelSpace(pEllipse);
}AcDbObjectId FymEllipse::Add(const AcGePoint2d& pt1, const AcGePoint2d& pt2) {AcGePoint3d ptCenter;ptCenter = FymGeometry::GetMiddlePt(FymConverUtil::ToPoint3d(pt1), FymConverUtil::ToPoint3d(pt2));AcGeVector3d vecNormal(0, 0, 1);AcGeVector3d majorAxis(fabs(pt1.x - pt2.x) / 2, 0, 0);double ratio = fabs((pt1.y - pt2.y) / (pt1.x - pt2.x));return Add(ptCenter, vecNormal, majorAxis, ratio);
}AcDbObjectId FymEllipse::Add(const AcGePoint2d& pt1, const AcGePoint2d& pt2, const AcGePoint2d& pt3)
{AcGePoint3d ptCenter;ptCenter = FymGeometry::GetMiddlePt(FymConverUtil::ToPoint3d(pt1), FymConverUtil::ToPoint3d(pt2));AcGeVector3d vecNormal(0, 0, 1);double ellipseAsq = pow(pt1.x - ptCenter.x, 2) + pow(pt1.y - ptCenter.y, 2);double ellipseBsq = pow(pt3.x - ptCenter.x, 2) + pow(pt3.y - ptCenter.y, 2);AcGeVector3d majorAxis;double ratio;if (ellipseAsq > ellipseBsq){majorAxis = AcGeVector3d((ptCenter.x - pt1.x), (ptCenter.y - pt1.y), 0.0);ratio = sqrt(ellipseBsq/ellipseAsq);}else{majorAxis = AcGeVector3d((ptCenter.x - pt3.x), (ptCenter.y - pt3.y), 0.0);ratio = sqrt(ellipseAsq/ellipseBsq);}return Add(ptCenter, vecNormal, majorAxis, ratio);
}

 圆

AcDbObjectId FymCircle::Add(const AcGePoint3d& centerPt, const AcGeVector3d& normal, double radius)
{AcDbCircle* pcir = new AcDbCircle(centerPt, normal, radius);return FymDatabase::PostToModelSpace(pcir);
}AcDbObjectId FymCircle::Add(const AcGePoint3d& centerPt, double radius)
{AcGeVector3d vec(0, 0, 1);//默认normalreturn Add(centerPt, vec, radius);
}AcDbObjectId FymCircle::Add(const AcGePoint2d& point1, const AcGePoint2d& point2)//点在圆上
{AcGePoint2d center = FymGeometry::GetMiddlePt(point1, point2);AcGePoint3d center3d(center.x, center.y, 0.0);double radius = center.distanceTo(point1);//中点和点1距离return Add(center3d, radius);
}AcDbObjectId FymCircle::AddByMath(const AcGePoint2d& point1, const AcGePoint2d& point2, const AcGePoint2d& point3)
{double xysm = 0, xyse = 0, xy = 0;AcGePoint3d ptCenter;double radius = 0;//sqrt为求平方根函数xy = pow(point1.x, 2) + pow(point2.y, 2);xyse = xy - pow(point3.x, 2) - pow(point3.y, 2);xysm = xy - pow(point2.x, 2) - pow(point2.y, 2);xy = (point1.x - point2.x) * (point1.y - point3.y) - (point1.x - point3.x) * (point1.y - point2.y);//fabs为绝对值函数if (fabs(xy) < 0.000001){AfxMessageBox(_T("输入参数无效,不能创建图形!"));return AcDbObjectId::kNull;}ptCenter.x = (xysm * (point1.y - point3.y) - xyse * (point1.y - point2.y)) / (2 * xy);ptCenter.y = (xysm * (point1.x - point2.x) - xysm * (point1.x - point3.x)) / (2 * xy);ptCenter.z = 0.0;//sqrt为求平方根函数radius = sqrt((point1.x - ptCenter.x) * (point1.x - ptCenter.x) + (point1.y - ptCenter.y) * (point1.y - ptCenter.y));if (radius < 0.0000001){AfxMessageBox(_T("半径过小!"));//在CAD界面弹出消息框return AcDbObjectId::kNull;}return Add(ptCenter, radius);
}AcDbObjectId FymCircle::Add(const AcGePoint2d& point1, const AcGePoint2d& point2, const AcGePoint2d& point3)
{AcGeCircArc2d geArc(point1, point2, point3);AcGePoint3d center(geArc.center().x, geArc.center().y, 0.0);return Add(center, geArc.radius());
}

 多段线

AcDbObjectId FymPolyline::Add(const AcGePoint2dArray& points, double width, Adesk::Boolean isClosed)
{int numVerts = points.length();//计算输入点数组的长度AcDbPolyline* pPline = new AcDbPolyline(numVerts);for (int i = 0; i < points.length(); i++){pPline->addVertexAt(i, points.at(i), 0, width, width, 0); //将每个点添加到多段线中}pPline->setClosed(isClosed);//为真,则多线段将被设置为闭合return FymDatabase::PostToModelSpace(pPline);
}AcDbObjectId FymPolyline::Add(const AcGePoint2d& ptStart, const AcGePoint2d& ptEnd, double width)
{AcGePoint2dArray points;points.append(ptStart);points.append(ptEnd);return Add(points, width);
}
//2d多段线
AcDbObjectId FymPolyline::Add2dPolyline(const AcGePoint3dArray& points, double startWidth, double endWidth, Adesk::Boolean isClosed)
{AcGePoint3dArray verPoints = points;AcDb2dPolyline* pPline = new AcDb2dPolyline(AcDb::k2dSimplePoly, verPoints, 0, isClosed, startWidth, endWidth);return FymDatabase::PostToModelSpace(pPline);
}
//3d多段线
AcDbObjectId FymPolyline::Add3dPolyline(const AcGePoint3dArray& points)
{AcGePoint3dArray verPts = points;AcDb3dPolyline* pPline = new AcDb3dPolyline(AcDb::k3dSimplePoly, verPts);return FymDatabase::PostToModelSpace(pPline);
}
//正多边形,(rotation)为旋转角度
AcDbObjectId FymPolyline::Add3dPolyGon(const AcGePoint2d& ptCenter, int number, double radius, double rotation, double width)
{double angle = 2 * FymMathUtil::PI() / (double)number;//计算每个顶点与中心的夹角AcGePoint2dArray points;//存储多段线的所有顶点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);}AcDbObjectId polyId = Add(points, width, Adesk::kTrue);FymEditor::Rotate(polyId, ptCenter, rotation);return polyId;
}
//对角线矩形
AcDbObjectId FymPolyline::AddRectang(const AcGePoint2d& pt1, const AcGePoint2d& pt2, double width)
{double x1 = pt1.x, x2 = pt2.x;double y1 = pt1.y, y2 = pt2.y;AcGePoint2d ptLeftBottom(min(x1, x2), min(y1, y2));AcGePoint2d ptRightBottom(max(x1, x2), min(y1, y2));AcGePoint2d ptRightTop(max(x1, x2), max(y1, y2));AcGePoint2d ptLeftTop(min(x1, x2), max(y1, y2));AcGePoint2dArray points;points.append(ptLeftBottom);points.append(ptRightBottom);points.append(ptRightTop);points.append(ptLeftTop);return Add(points, width, Adesk::kTrue);
}
//测试:小爱心,bulge0.5为四分之一圆
AcDbObjectId FymPolyline::AddPolyCircle(const AcGePoint2d& ptCenter, double radius, double width)
{AcGePoint2d pt1, pt2, pt3, pt4;pt1.x = ptCenter.x + radius;pt1.y = ptCenter.y;pt2.x = ptCenter.x - radius;pt2.y = ptCenter.y;pt3.x = ptCenter.x ;pt3.y = ptCenter.y + radius;pt4.x = ptCenter.x;pt4.y = ptCenter.y - radius;AcDbPolyline* pPloy = new AcDbPolyline(4);pPloy->addVertexAt(0, pt1, 1, width, width);pPloy->addVertexAt(1, pt3, 1, width, width);pPloy->addVertexAt(2, pt2, 0.1, width, width);pPloy->addVertexAt(3, pt4, 0.1, width, width);pPloy->setClosed(Adesk::kTrue);return FymDatabase::PostToModelSpace(pPloy);
}AcDbObjectId FymPolyline::SetWidth(const AcDbObjectId& polyId, ads_real width)
{AcDbPolyline* pPline = NULL;if (acdbOpenObject(pPline,polyId,AcDb::kForWrite)==Acad::eOk){pPline->setConstantWidth(width);pPline->close();} return FymDatabase::PostToModelSpace(pPline);}

图案填充

//图案填充(ID,图案名称,图案缩放因子)
AcDbObjectId FymHatch::Add(const AcDbObjectIdArray& objIds, const ACHAR* patName, double patternScale)
{Acad::ErrorStatus es;//1创建空的填充对象AcDbHatch* pHatch = new AcDbHatch();//2设置填充平面AcGeVector3d normal(0, 0, 1);//法线pHatch->setNormal(normal);//设置图案的标高。首先设置为0,然后设置为true使图案在实体表面上方pHatch->setElevation(0);pHatch->setElevation(true);	//3设置关联性//设置填充图案类型为预定义,并指定图案名称为输入的 patName。pHatch->setPattern(AcDbHatch::kPreDefined, patName);//5添加填充边界es = pHatch->appendLoop(AcDbHatch::kExternal, objIds);//6显示填充对象es = pHatch->evaluateHatch();//7添加到模型空间AcDbObjectId hatchId = FymDatabase::PostToModelSpace(pHatch);//关联性填充,填充对象与边界进行绑定,使其能获得边界对象修改的通知if (acdbOpenObject(pHatch, hatchId, AcDb::kForRead) == Acad::eOk){AcDbObjectIdArray assocEntids;pHatch->getAssocObjIds(assocEntids);//将与填充图案关联的所有对象的ID存储在assocEntids数组for (int i = 0; i < assocEntids.length(); i++){AcDbEntity* pEnt = NULL;//以只写模式打开与当前关联对象ID对应的实体对象if (acdbOpenObject(pEnt, assocEntids.at(i), AcDb::kForWrite) == Acad::eOk){pEnt->addPersistentReactor(hatchId);pEnt->close();/*如果成功打开了实体对象,这行代码将为该实体添加一个持久反应器(Reactor),该反应器的ID是当前的填充图案的ID(hatchId)。这意味着,每当该实体发生更改时,与其关联的填充图案也将被更新。*/}}pHatch->close();}return hatchId;
}

http://www.lryc.cn/news/2417219.html

相关文章:

  • HTK学习笔记(一)
  • CLSID应用
  • MPC模型预测控制及在Matlab中实现函数定义
  • U盘全新安装windows2003系统
  • 10款用于查询IP地址的工具网站
  • DirectSound 与Waveout的区别
  • 实验误差分析大全,实验员必备!
  • Wireshark过滤总结
  • 【读码JDK】-java.lang包介绍
  • java启动参数xmm_更快的方法来测试xmm / ymm寄存器是否为零?
  • 敏捷软件开发
  • .mp4视频测试地址
  • Java IO流操作汇总: inputStream 和 outputStream
  • DRM-widevine 总结
  • 电脑提示msvcp110.dll丢失修复方法,总结四个有效的方法
  • Linux入门基础完整版【详解】
  • 微机原理与接口技术实验二:8255A控制4按键二进制输入数码管显示
  • 发现了一个好网站.绝不是打广告,独乐乐不如众乐乐.
  • 变量及四种变量类型
  • 汉字编码问题
  • 史上最全网址导航大全,让世上没有找不到的好东西
  • 新手写CSDN的教程
  • [转]DTV(数字电视)扫盲-DVB介绍
  • 微软官方精简Windows7系统——Windows Thin PC的安装过程
  • 【渗透测试笔记】之【钓鱼姿势——exe伪装word文档(exe图标修改方法)】_restorator如何添加exe资源(2)
  • google protocol buffer全解析------田纪原,2024年安卓开发进阶课程
  • js中的offsetLeft和style.left
  • 计算机丢失msvcrtdll怎么修复,雨林木风修复msvcrtdll 【操作方案】 的详细_
  • 人工智能与物流:智能化的物流管理
  • rearm 命令_运行输入slmgr.vbs -rearm 命令什么意思