#include "StdAfx.h" #include "terrainAnalysis.h" #include "UITools.h" #include #include "ktcadutility.h" #include #include "dbobjptr.h" #include "aecdbterrain.h" #include "KTSetting.h" #include "coretools.h" #if ARX > 17 #include "dbsubd.h" namespace { static void AcDbSubDMeshfromAcDb3dSolid(void) { Acad::ErrorStatus err; ads_name name; ads_point pt; if (acedEntSel(L"Select a solid", name, pt) != RTNORM) return; AcDbObjectId id; acdbGetObjectId(id, name); AcDbObjectPointer ptrSolid(id, AcDb::kForRead); AcDbFaceterSettings settings; AcGePoint3dArray pts; AcArray faces; AcGiFaceData* faceData; err = acdbGetObjectMesh(ptrSolid, &settings, pts, faces, faceData); if (faceData) { delete[] faceData->trueColors(); delete[] faceData->materials(); DELETE_PTR(faceData); } AcDbObjectPointer ptrMesh; ptrMesh.create(); ptrMesh->setSubDMesh(pts, faces, 0); AcDbDatabase* pDb = acdbHostApplicationServices()->workingDatabase(); AcDbBlockTableRecordPointer ptrMS(ACDB_MODEL_SPACE, pDb, AcDb::kForWrite); ptrMS->appendAcDbEntity(ptrMesh); } struct Face { Face(): num(0), vertices(0){} int num; std::vector vertices; }; struct FacePoint { AcGePoint3d pt; Face face; void setFace(const Face &f) { face = f; AcGePlane pln(f.vertices[0], f.vertices[1], f.vertices[2]); AcGePoint3d ptClosed = pln.closestPointTo(pt); pt.z = ptClosed.z; } }; struct com_pt_z{ bool operator () (AcGePoint3d &pt1, AcGePoint3d &pt2) { return pt1.z < pt2.z; } }; double crossProduct(const AcGeVector2d v1, const AcGeVector2d &v2) { return v1.x*v2.y - v1.y*v2.x; } bool isInTriangle(const AcGePoint2d &pt0 , const AcGePoint2d &pt1 , const AcGePoint2d &pt2 , const AcGePoint2d &pt ) { AcGeVector2d v0(pt0 - pt), v1(pt1 - pt), v2(pt2 - pt); double d01 = crossProduct(v0, v1); double d12 = crossProduct(v1, v2); double d20 = crossProduct(v2, v0); return (d01 * d12 >= 0) && (d01 * d20 >= 0); } bool isInFace(const AcGePoint3d &pt, const Face &f) { if (f.num < 3) return false; AcGePoint2d pt0(f.vertices[0].x, f.vertices[0].y) , pt1(f.vertices[1].x, f.vertices[1].y) , pt2(f.vertices[2].x, f.vertices[2].y) , pt2d(pt.x, pt.y); return isInTriangle(pt0, pt1, pt2, pt2d); } bool isDouble(LPCTSTR psz, double &d) { std::wstringstream ss(psz); TCHAR c; if (!(ss >> d)) return false; if (ss >> c) return false; return true; } void polyline2PointArray(const AcDbPolyline &poly, std::vector &ar, const double &dElev) { AcGePoint3d pt; double dParam(.0); std::set params; AcGeLineSeg3d seg3d; AcGeCircArc3d arc3d; AcDbPolyline::SegType st(AcDbPolyline::kEmpty); for (int i(0); i < poly.numVerts(); ++i) { st = poly.segType(i); if (st == AcDbPolyline::kLine) { poly.getLineSegAt(i, seg3d); poly.getParamAtPoint(seg3d.startPoint(), dParam); params.insert(dParam); poly.getParamAtPoint(seg3d.endPoint(), dParam); params.insert(dParam); } else if (st == AcDbPolyline::kArc) { double dS(.0), dE(.0); poly.getArcSegAt(i, arc3d); poly.getParamAtPoint(arc3d.startPoint(), dS); poly.getParamAtPoint(arc3d.endPoint(), dE); double dStep(abs((dS - dE) * .01)); for (int i(0); i < 100; ++i) { params.insert(dS + i * dStep); } params.insert(dE); } } std::set::const_iterator it(params.begin()); for (; it != params.end(); ++it) { if (poly.getPointAtParam(*it, pt) == Acad::eOk) ar.push_back(AcGePoint3d(pt.x, pt.y, dElev)); } } void circle2PointArray(const AcDbCircle &circle, std::vector &ar, const double &dElev) { std::set params; double dS(.0), dE(.0); circle.getStartParam(dS); circle.getEndParam(dE); double dStep(abs((dS - dE) * .01)); for (int i(0); i < 100; ++i) { params.insert(dS + i * dStep); } params.insert(dE); AcGePoint3d pt; std::set::const_iterator it(params.begin()); for (; it != params.end(); ++it) { if (circle.getPointAtParam(*it, pt) == Acad::eOk) ar.push_back(AcGePoint3d(pt.x, pt.y, dElev)); } } void setBlockAttri(AcDbBlockReference *pRef, LPCTSTR str) { if (!pRef) return; AcDbObjectIterator *pIt = pRef->attributeIterator(); if (!pIt) return; AcDbAttribute *pAttr(NULL); for (pIt->start(); !pIt->done(); pIt->step()) { AcDbObjectId id = pIt->objectId(); pRef->openAttribute(pAttr, id, AcDb::kForWrite); if (pAttr) { pAttr->setTextString(str); pAttr->close(); break; } } DELETE_PTR(pIt); return; } void getBlockAttri(AcDbBlockReference *pRef, std::set &tags, std::set &texts) { if (!pRef) return; AcDbObjectIterator *pIt = pRef->attributeIterator(); if (!pIt) return; CString str(_T("")); AcDbAttribute *pAttr(NULL); for (pIt->start(); !pIt->done(); pIt->step()) { AcDbObjectId id = pIt->objectId(); pRef->openAttribute(pAttr, id, AcDb::kForRead); if (pAttr) { str = pAttr->tag(); tags.insert(pAttr->tag()); texts.insert(pAttr->textString()); pAttr->close(); } } DELETE_PTR(pIt); return; } // 判断 idDest 所代表的标高是否再 dMax 与 dMin 之间 bool modifyElevObj(AcDbObjectId idDest, const double &dMax, const double &dMin) { OPENOBJ_BEGIN(idDest, AcDb::kForWrite, AcDbEntity, pDest) { if (!pDest) return false; AcDbBlockReference *pRef2 = AcDbBlockReference::cast(pDest); AcDbPoint *pPnt2 = AcDbPoint::cast(pDest); AcDbText *pTxt2 = AcDbText::cast(pDest); AcDbMText *pMTxt2 = AcDbMText::cast(pDest); AcGePoint3d pt(AcGePoint3d::kOrigin); int prec(2); // 图块 if (pRef2) { // 比较属性 std::set attr2, text2; getBlockAttri(pRef2, attr2, text2); pt = pRef2->position(); if (isDouble(*text2.begin(), pt.z)) { if (pt.z > dMax) { pt.z = dMax; pRef2->setPosition(pt); setBlockAttri(pRef2, TypeConvert::d2s(pt.z, &prec)); } else if (pt.z < dMin) { pt.z = dMin; pRef2->setPosition(pt); setBlockAttri(pRef2, TypeConvert::d2s(pt.z, &prec)); } return true; } return true; } else if (pPnt2) // 点 { pt = pPnt2->position(); if (pt.z > dMax) { pt.z = dMax; pPnt2->setPosition(pt); } else if ( pt.z < dMin) { pt.z = dMin; pPnt2->setPosition(pt); } return true; } else if (pTxt2) // 单行文字 { pt = pTxt2->position(); if (isDouble(pTxt2->textString(), pt.z)) { if (pt.z > dMax) { pt.z = dMax; pTxt2->setPosition(pt); pTxt2->setTextString(TypeConvert::d2s(pt.z, &prec)); } else if (pt.z < dMin) { pt.z = dMin; pTxt2->setPosition(pt); pTxt2->setTextString(TypeConvert::d2s(pt.z, &prec)); } return true; } return false; } else if (pMTxt2) // 多行文字 { pt = pMTxt2->location(); if (isDouble(pMTxt2->contents(), pt.z)) { if (pt.z > dMax) { pt.z = dMax; pMTxt2->setLocation(pt); pMTxt2->setContents(TypeConvert::d2s(pt.z, &prec)); } else if (pt.z < dMin) { pt.z = dMin; pMTxt2->setLocation(pt); pMTxt2->setContents(TypeConvert::d2s(pt.z, &prec)); } return true; } return false; } return false; } OPENOBJ_END() } // 分析高程对象 // idOrig是示例对象,判断idDest是否和idOrig一样 // 如果返回false,说明不是高程点 bool analyElevObj(AcDbObjectId idOrig, AcDbObjectId idDest, AcGePoint3d &pt) { //if (idOrig == idDest) return false; AcDbObjectId idLay1, idLay2, idLt1, idLt2; AcDb::LineWeight lw1, lw2; AcCmColor cm1, cm2; AcCmTransparency ct1, ct2; // 目前只支持3种,块参照 文字对象 点对象 OPENOBJ_BEGIN(idOrig, AcDb::kForRead, AcDbEntity, pOrig) { if (!pOrig) return false; idLay1 = pOrig->layerId(); idLt1 = pOrig->linetypeId(); lw1 = pOrig->lineWeight(); cm1 = pOrig->color(); ct1 = pOrig->transparency(); if (!pOrig) return false; AcDbBlockReference *pRef1 = AcDbBlockReference::cast(pOrig); AcDbPoint *pPnt1 = AcDbPoint::cast(pOrig); AcDbText *pTxt1 = AcDbText::cast(pOrig); AcDbMText *pMTxt1 = AcDbMText::cast(pOrig); OPENOBJ_BEGIN(idDest, AcDb::kForRead, AcDbEntity, pDest) { if (!pDest) return false; idLay2 = pDest->layerId(); idLt2 = pDest->linetypeId(); lw2 = pDest->lineWeight(); cm2 = pDest->color(); ct2 = pDest->transparency(); if (idLay1 != idLay2) return false; if (idLt1 != idLt2) return false; if (lw1 != lw2) return false; if (cm1 != cm2) return false; if (ct1 != ct2) return false; // 下面分别对图块,点,文字对象进行比较 AcDbBlockReference *pRef2 = AcDbBlockReference::cast(pDest); AcDbPoint *pPnt2 = AcDbPoint::cast(pDest); AcDbText *pTxt2 = AcDbText::cast(pDest); AcDbMText *pMTxt2 = AcDbMText::cast(pDest); // 图块 if (pRef1 && pRef2) { if (pRef1->scaleFactors() != pRef2->scaleFactors()) return false; if (pRef1->rotation() != pRef2->rotation()) return false; if (pRef1->blockTableRecord() != pRef2->blockTableRecord()) return false; // 比较属性 std::set attr1, attr2, text1, text2; getBlockAttri(pRef1, attr1, text1); getBlockAttri(pRef2, attr2, text2); if (attr1 != attr2) return false; // 能走到这里,说明都有属性,或都没有属性 AcGePoint3d _pt; // 如果 ref1 有属性,并且有数字属性值(就判断第一个) if (!attr1.empty()) // 说明都有属性 { // 如果ref1 的属性值是数字,那么,ref2 属性值必须是数字(就判断第一个) if (isDouble(*text1.begin(), _pt.z)) { pt = pRef2->position(); if (!text2.empty() && isDouble(*text2.begin(), pt.z)) { return true; } else return false; } else // 如果ref1属性值不是数字,那么直接返回ref2的插入点算逑 { pt = pRef2->position(); return true; } return false; } // 都没有属性,直接取插入点 else { pt = pRef2->position(); return true; } } else if (pPnt1 && pPnt2) // 点 { pt = pPnt2->position(); return true; } else if (pTxt1 && pTxt2) // 单行文字 { if (pTxt1->textStyle() != pTxt2->textStyle()) return false; if (pTxt1->horizontalMode() != pTxt2->horizontalMode()) return false; if (pTxt1->verticalMode() != pTxt2->verticalMode()) return false; if (pTxt1->rotation() != pTxt2->rotation()) return false; if (pTxt1->thickness() != pTxt2->thickness()) return false; if (pTxt1->widthFactor() != pTxt2->widthFactor()) return false; if (pTxt1->height() != pTxt2->height()) return false; if (pTxt1->oblique() != pTxt2->oblique()) return false; if (pTxt1->isMirroredInX() != pTxt2->isMirroredInX()) return false; if (pTxt1->isMirroredInY() != pTxt2->isMirroredInY()) return false; pt = pTxt2->position(); return isDouble(pTxt2->textString(), pt.z); } else if (pMTxt1 && pMTxt2) // 多行文字 { if (pMTxt1->actualHeight() != pMTxt2->actualHeight()) return false; if (pMTxt1->actualWidth() != pMTxt2->actualWidth()) return false; if (pMTxt1->ascent() != pMTxt2->ascent()) return false; if (pMTxt1->attachment() != pMTxt2->attachment()) return false; if (pMTxt1->descent() != pMTxt2->descent()) return false; if (pMTxt1->direction() != pMTxt2->direction()) return false; if (pMTxt1->flowDirection() != pMTxt2->flowDirection()) return false; AcCmColor cm11, cm22; if (pMTxt1->getBackgroundFillColor(cm11) == Acad::eOk && pMTxt2->getBackgroundFillColor(cm22) == Acad::eOk) { if (cm11 != cm22) return false; } AcCmTransparency ct11, ct22; if (pMTxt1->getBackgroundTransparency(ct11) == Acad::eOk && pMTxt2->getBackgroundTransparency(ct22) == Acad::eOk) { if (ct11 != ct22) return false; } double d1, d2; if (pMTxt1->getBackgroundScaleFactor(d1) == Acad::eOk && pMTxt2->getBackgroundScaleFactor(d2) == Acad::eOk) { if (!EQUAL(d1, d2)) return false; } // AcGePoint3dArray ar1, ar2; // pMTxt1->getBoundingPoints(ar1); // pMTxt2->getBoundingPoints(ar2); // if (ar1 != ar2) return false; if (pMTxt1->lineSpacingFactor() != pMTxt2->lineSpacingFactor()) return false; if (pMTxt1->lineSpacingStyle() != pMTxt2->lineSpacingStyle()) return false; if (pMTxt1->width() != pMTxt2->width()) return false; if (pMTxt1->rotation() != pMTxt2->rotation()) return false; if (pMTxt1->textStyle() != pMTxt2->textStyle()) return false; if (pMTxt1->textHeight() != pMTxt2->textHeight()) return false; pt = pMTxt2->location(); return isDouble(pMTxt2->contents(), pt.z); } return false; } OPENOBJ_END() } OPENOBJ_END() return false; } // 交互:用户选取离散点 bool getElevPoints(Geometry::GePoint3dArray &arPts, AcDbObjectIdArray &ids) { ads_name adsNames, adsName; AcDbObjectId id(AcDbObjectId::kNull), idOrig(AcDbObjectId::kNull); Adesk::Int32 count(0); struct resbuf* pRb = acutBuildList(RTDXF0, _T("INSERT,POINT,TEXT,MTEXT"), 0); int nRes = CKTCadUtility::SelectEntity(_T("\n请选择一个“图块”、“点”、“文字”对象,做为参考对象:"), adsName, pRb); acutRelRb(pRb); if (nRes != RTNORM) return false; acdbGetObjectId(id, adsName); CString sFilter(_T("INSERT")); OPENOBJ_BEGIN(id, AcDb::kForRead, AcDbEntity, pEnt) { if (!pEnt) return false; AcDbBlockReference *pRef = AcDbBlockReference::cast(pEnt); AcDbPoint *pPnt = AcDbPoint::cast(pEnt); AcDbText *pTxt = AcDbText::cast(pEnt); AcDbMText *pMTxt = AcDbMText::cast(pEnt); if (pRef) sFilter = _T("INSERT"); else if (pPnt) sFilter = _T("POINT"); else if (pTxt) sFilter = _T("TEXT"); else if (pMTxt) sFilter = _T("MTEXT"); else return false; } OPENOBJ_END() // 在这里判断是用户选择,还是选一个样例,然后选中dwg中的所有与样例相同的实体 TCHAR szKey[131] = {_T('S'),}; acedInitGet(RSG_OTHER, _T("S A")); nRes = acedGetKword(_T("\n请选择[手动选择高程数据(S)/选择图中全部高程数据(A)]<手动选择高程数据(S)>:"), szKey); if (nRes == RTCAN) return false; if (nRes == RTNONE) _tcscpy(szKey, _T("S")); if (_tcscmp(szKey, _T("S")) == 0) { struct resbuf* pRb = acutBuildList(RTDXF0, sFilter, 0); nRes = CKTCadUtility::SelectEntities(_T("\n请选择“图块”、“点”、“文字”对象:"), adsNames, pRb); acutRelRb(pRb); if (nRes != RTNORM) return false; acedSSLength(adsNames, &count); if (!count) return false; } else { pRb = acutBuildList(RTDXF0, sFilter, 0); acedSSGet(_T("X"), NULL, NULL, pRb, adsNames); acutRelRb(pRb); acedSSLength(adsNames, &count); if (!count) return false; } AcGePoint3d pt(AcGePoint3d::kOrigin); for (size_t i = 0; i < count; i++) { acedSSName(adsNames, i, adsName); if (Acad::eOk != acdbGetObjectId(idOrig, adsName)) continue; if (analyElevObj(id, idOrig, pt)) { arPts.push_back(pt); ids.append(idOrig); } } acedSSFree(adsNames); return !arPts.empty(); } CString getUserSelectType(AcDbObjectId &id) { ads_name adsName; Adesk::Int32 count(0); struct resbuf *pRb = acutBuildList(RTDXF0, _T("INSERT,POINT,TEXT,MTEXT"), 0); int nRes = CKTCadUtility::SelectEntity(_T("\n请选择一个“图块”、“点”、“文字”对象,做为参考对象:"), adsName, pRb); acutRelRb(pRb); if (nRes != RTNORM) return _T(""); acdbGetObjectId(id, adsName); CString sFilter(_T("INSERT")); OPENOBJ_BEGIN(id, AcDb::kForRead, AcDbEntity, pEnt) { if (!pEnt) return _T(""); AcDbBlockReference *pRef = AcDbBlockReference::cast(pEnt); AcDbPoint *pPnt = AcDbPoint::cast(pEnt); AcDbText *pTxt = AcDbText::cast(pEnt); AcDbMText *pMTxt = AcDbMText::cast(pEnt); if (pRef) sFilter = _T("INSERT"); else if (pPnt) sFilter = _T("POINT"); else if (pTxt) sFilter = _T("TEXT"); else if (pMTxt) sFilter = _T("MTEXT"); else return _T(""); } OPENOBJ_END() return sFilter; } bool getPointsInArea(LPCTSTR pszFilter , AcDbObjectId idOrig , Geometry::GePoint3dArray &arPts , AcDbObjectIdArray &ids , Geometry::GePoint3dArray &area) { if (!pszFilter) return false; ads_name ss, ent; struct resbuf *pRb = acutBuildList(RTDXF0, pszFilter, 0); // 转成UCS Geometry::GePoint3dArray _area(area); for (int i(0); i < _area.size(); ++i) CoreTools::WCS2UCS(_area[i], _area[i]); struct resbuf *pRbFence = CoreTools::MakeFence(_area); int nRes = acedSSGet(_T("CP"), pRbFence, NULL, pRb, ss); acutRelRb(pRb); acutRelRb(pRbFence); if (nRes != RTNORM) { acutPrintf(_T("\n区域内没有需要选择的标高对象!")); return false; } AcDbObjectId id; Adesk::Int32 count(0); acedSSLength(ss, &count); AcGePoint3d pt(AcGePoint3d::kOrigin); for (size_t i = 0; i < count; i++) { acedSSName(ss, i, ent); if (Acad::eOk != acdbGetObjectId(id, ent)) continue; if (analyElevObj(idOrig, id, pt)) { arPts.push_back(pt); ids.append(id); } } acedSSFree(ss); return true; } void getPolyPoints(AcDbPolyline *pPoly , const AcGePoint3d &ptS , const AcGePoint3d &ptE , const double &step , std::vector &pts) { if (!pPoly) return; AcGePoint3d pt(AcGePoint3d::kOrigin), _ptS(ptS), _ptE(ptE); double distS(0.), distE(.0), len(.0); pPoly->getEndPoint(pt); pPoly->getDistAtPoint(pt, len); if (Acad::eOk != pPoly->getDistAtPoint(ptS, distS)) { distS = 0.; pPoly->getStartPoint(_ptS); } if (Acad::eOk != pPoly->getDistAtPoint(ptE, distE)) { distE = len; pPoly->getEndPoint(_ptE); } while (distE > distS) { pPoly->getPointAtDist(distS, pt); pts.push_back(pt); distS += step; } pts.push_back(_ptE); } // 从ptS开始以1米为间隔,逼近到ptE AcDbSubDMesh* polyline2SubDMesh(AcDbObjectId idPoly, const double &dH, const AcGePoint3d &ptS, const AcGePoint3d &ptE) { AcGePoint3dArray arBottoms(0), arTops(0); OPENOBJ_BEGIN(idPoly, AcDb::kForRead, AcDbPolyline, pPoly) { if (!pPoly) return NULL; AcGePoint3d pt(AcGePoint3d::kOrigin), _ptS(ptS), _ptE(ptE); double distS(0.), distE(.0), len(.0); pPoly->getEndPoint(pt); pPoly->getDistAtPoint(pt, len); if (Acad::eOk != pPoly->getDistAtPoint(ptS, distS)) { distS = 0.; pPoly->getStartPoint(_ptS); } if (Acad::eOk != pPoly->getDistAtPoint(ptE, distE)) { distE = len; pPoly->getEndPoint(_ptE); } while (distE > distS) { pPoly->getPointAtDist(distS, pt); arBottoms.append(pt); arTops.append(AcGePoint3d(pt.x, pt.y, pt.z + dH)); distS += 1; } arBottoms.append(_ptE); arTops.append(AcGePoint3d(_ptE.x, _ptE.y, _ptE.z + dH)); } OPENOBJ_END() arBottoms.append(arTops); int count_of_vertex = arBottoms.length(); int count_of_vertex_half = (int)( count_of_vertex* .5); int count_of_face = count_of_vertex_half - 1; AcArray faces; for (int i = 0; i < count_of_face; ++i) { faces.append(4); faces.append(i); faces.append(faces.last() + 1); faces.append(faces.last() + count_of_vertex_half); faces.append(faces.last() - 1); } AcDbSubDMesh *pMesh = new AcDbSubDMesh; pMesh->setSubDMesh(arBottoms, faces, 0); return pMesh; } void getSubDMeshFaces(AcDbSubDMesh *pFaceMesh, std::vector &fs) { AcGePoint3dArray arV; AcArray arF; Adesk::Int32 countF; pFaceMesh->getFaceArray(arF); pFaceMesh->getVertices(arV); pFaceMesh->numOfFaces(countF); int count_of_v(arV.length()); int count_of_f(arF.length()); /* arF结构如下 第1个数字n为构成一个面的顶点数量,其后n个数字为顶点在arV中的索引 */ Face f; for (int i = 0; i < count_of_f;) { f.num = abs(arF[i]); f.vertices.clear(); // 加1,跳到顶点索引开始 ++i; // 将索引取出 for (int j = 0; j < f.num; ++j) { if (i + j < count_of_f) { Adesk::Int32 &vIdx(arF[i + j]); if (vIdx < count_of_v) f.vertices.push_back(arV[vIdx]); } } fs.push_back(f); // 跳到下一个面 i += f.num; } } double calcAverageZ(const Geometry::GePoint3dArray &pts) { double dElev(.0); for (size_t i(0); i < pts.size(); ++i) dElev += pts[i].z; dElev /= pts.size(); return dElev; } void setZ(Geometry::GePoint3dArray &pts, const double &z) { for (size_t i(0); i < pts.size(); ++i) pts[i].z = z; } AecDbTerrain* makeTerrain( const Geometry::GePoint3dArray &arPts , const Geometry::GePoint3dArray &arOuter ) { if (arPts.empty()) return NULL; AecDbTerrain *pTer = new AecDbTerrain(); pTer->setPoints(arPts); if (!arOuter.empty()) pTer->setOuter(arOuter); return pTer; } void getAllOfPoints(LPCTSTR pszFilter , AcDbObjectId idOrig , Geometry::GePoint3dArray &arPoints , AcDbObjectIdArray &arIds) { Adesk::Int32 count(0); ads_name adsNames, adsName; AcDbObjectId id(AcDbObjectId::kNull); struct resbuf *pRb = acutBuildList(RTDXF0, pszFilter, 0); acedSSGet(_T("X"), NULL, NULL, pRb, adsNames); acutRelRb(pRb); acedSSLength(adsNames, &count); if (!count) return; AcGePoint3d pt(AcGePoint3d::kOrigin); for (size_t i = 0; i < count; i++) { acedSSName(adsNames, i, adsName); if (Acad::eOk != acdbGetObjectId(id, adsName)) continue; if (analyElevObj(idOrig, id, pt)) { arIds.append(id); arPoints.push_back(pt); } } acedSSFree(adsNames); } int getPointsInAreaByUser(LPCTSTR pszFilter , AcDbObjectId idOrig , std::vector &arArraysOfPoint , std::vector &arOuters , std::vector &arArraysOfId ) { Adesk::Int32 count(0); ads_name adsNames, adsName; struct resbuf *pRb = acutBuildList(RTDXF0, _T("LWPOLYLINE,CIRCLE"), 0); int nRes = CKTCadUtility::SelectEntities(_T("\n请选择由“多段线”或“圆”构成的闭合区域:"), adsNames, pRb); acutRelRb(pRb); if (nRes != RTNORM) return nRes; acedSSLength(adsNames, &count); if (!count) return RTNONE; AcDbObjectIdArray ids; Geometry::GePoint3dArray arOuter, arPts; for (int i(0); i < count; ++i) { arOuter.clear(); arPts.clear(); ids.removeAll(); acedSSName(adsNames, i, adsName); OPENOBJ_BEGIN(adsName, AcDb::kForRead, AcDbEntity, pEnt) { if (!pEnt) continue; AcDbPolyline *pPL = AcDbPolyline::cast(pEnt); AcDbCircle *pC = AcDbCircle::cast(pEnt); if (pPL) { polyline2PointArray(*pPL, arOuter, .0); } else if (pC) { circle2PointArray(*pC, arOuter, .0); } getPointsInArea(pszFilter, idOrig, arPts, ids, arOuter); if (!ids.isEmpty()) { arArraysOfId.push_back(ids); arArraysOfPoint.push_back(arPts); arOuters.push_back(arOuter); } } OPENOBJ_END() } acedSSFree(adsNames); if (arArraysOfId.empty()) { acutPrintf(_T("\n选中的区域没有符合特征的实体!")); return RTNONE; } return RTNORM; } // 0 取消 1 区域 2 全部 int IsSelectAllPoint() { // 在这里判断是用户选择,还是选一个样例,然后选中dwg中的所有与样例相同的实体 TCHAR szKey[131] = { _T('S'), }; acedInitGet(RSG_OTHER, _T("S A")); int nRes = acedGetKword(_T("\n请选择[手动选择高程区域(S)/选择图中全部高程数据(A)]<手动选择高程区域(S)>:"), szKey); if (nRes == RTCAN) return 0; if (nRes == RTNONE) return 1; return _tcscmp(szKey, _T("S")) == 0 ? 1 : 2; } } void TERRAIN::generateTerrainMesh() { AcDbObjectId idOrig(AcDbObjectId::kNull); CString sFilter(getUserSelectType(idOrig)); if (sFilter.IsEmpty()) return; int nSelType(IsSelectAllPoint()); if (nSelType == 0) return; AcDbObjectId layerId = KTSetting::InitLayer(_T("LAY_FACTORY_LAND"), false); if (nSelType == 1) { std::vector arArraysOfPoint; std::vector arOuters; std::vector arArraysOfId; int nRes = getPointsInAreaByUser(sFilter, idOrig, arArraysOfPoint, arOuters, arArraysOfId); if (nRes != RTNORM) return; if (!arArraysOfId.empty() && !arArraysOfPoint.empty() && !arOuters.empty() && arArraysOfId.size() == arArraysOfPoint.size() && arArraysOfId.size() == arOuters.size()) { for (size_t i = 0; i < arArraysOfId.size(); ++i) { //AcDbObjectIdArray &ids(arArraysOfId[i]); Geometry::GePoint3dArray &arPts(arArraysOfPoint[i]); Geometry::GePoint3dArray &arOuter(arOuters[i]); setZ(arOuter, calcAverageZ(arPts)); AecDbTerrain *pTer(makeTerrain(arPts, arOuter)); if (pTer) { if (layerId.isValid()) pTer->setLayer(layerId); CoreTools::AddToModelSpace(pTer); } } return; } } else { Geometry::GePoint3dArray arPts(0); AcDbObjectIdArray ids; getAllOfPoints(sFilter, idOrig, arPts, ids); AecDbTerrain *pTer(makeTerrain(arPts, Geometry::GePoint3dArray())); if (pTer) { if (layerId.isValid()) pTer->setLayer(layerId); CoreTools::AddToModelSpace(pTer); return; } } return; } void TERRAIN::setSmoothLevelForTerrainMesh() { ads_name entTerrain; struct resbuf *pRb = acutBuildList(RTDXF0, _T("AEC_DBTERRAIN"), 0); int nRes = CKTCadUtility::SelectEntity(_T("\n选择一个上华地形实体:"), entTerrain, pRb); if (RTNORM != nRes) return; acutRelRb(pRb); OPENOBJ_BEGIN(entTerrain, AcDb::kForWrite, AecDbTerrain, pTer) { if (!pTer) return; int iSm(pTer->getSmoothLevel()); CString str(_T("")); str.Format(_T("\n请输入平滑度(1-4)<%d>:"), iSm); acedGetInt(str, &iSm); pTer->setSmoothLevel(iSm); } OPENOBJ_END() } void TERRAIN::delHoldForTerrainMesh() { ads_name entTerrain; struct resbuf *pRb = acutBuildList(RTDXF0, _T("AEC_DBTERRAIN"), 0); int nRes = CKTCadUtility::SelectEntity(_T("\n选择一个上华地形实体:"), entTerrain, pRb); if (RTNORM != nRes) return; acutRelRb(pRb); TCHAR szKey[131] = { _T('S'), }; acedInitGet(RSG_OTHER, _T("S A")); nRes = acedGetKword(_T("\n请选择[删除单独的洞口(S)/删除全部洞口(A)]<删除单独的洞口(S)>:"), szKey); if (nRes == RTCAN) return; if (nRes == RTNONE) _tcscpy(szKey, _T("S")); if (_tcscmp(szKey, _T("S")) == 0) { ads_point adsPt; if (acedGetPoint(NULL, _T("\n请在要删除的洞口内部选择一点:"), adsPt) != RTNORM) return; AcGePoint3d ptInput(asPnt3d(adsPt)); CoreTools::UCS2WCS(ptInput, ptInput); OPENOBJ_BEGIN(entTerrain, AcDb::kForWrite, AecDbTerrain, pTer) { if (!pTer) return; if (pTer->deleteHold(ptInput)) acutPrintf(_T("\n删除地形上的洞口成功!")); else acutPrintf(_T("\n删除地形上的洞口失败!")); } OPENOBJ_END() } else { OPENOBJ_BEGIN(entTerrain, AcDb::kForWrite, AecDbTerrain, pTer) { if (!pTer) return; if (pTer->clearHolds()) acutPrintf(_T("\n地形上的洞口全部删除完毕!")); else acutPrintf(_T("\n全部删除地形上的洞口失败!")); } OPENOBJ_END() } } void TERRAIN::addHoldToTerrainMesh() { ads_name entTerrain, ssHolds, ent; struct resbuf *pRb = acutBuildList(RTDXF0, _T("AEC_DBTERRAIN"), 0); int nRes = CKTCadUtility::SelectEntity(_T("\n选择一个上华地形实体:"), entTerrain, pRb); if (RTNORM != nRes) return; acutRelRb(pRb); AcDbObjectIdArray ids; CString psz(_T("LWPOLYLINE,CIRCLE")); resbuf *pRb2 = acutBuildList(RTDXF0, psz, 0); if (CKTCadUtility::SelectEntities(_T("\n请选择洞口闭合曲线(多段线或圆):"), ssHolds, pRb2) != RTNORM) return; acutRelRb(pRb2); AcDbObjectId id; Adesk::Int32 lLen(0L); acedSSLength(ssHolds, &lLen); ids.removeAll(); for (long i = 0; i < lLen; ++i) { if (acedSSName(ssHolds, i, ent) != RTNORM) continue; if (acdbGetObjectId(id, ent) != Acad::eOk) continue; ids.append(id); } acedSSFree(ssHolds); std::vector pts; OPENOBJ_BEGIN(entTerrain, AcDb::kForWrite, AecDbTerrain, pTer) { if (!pTer) return; double dElev(pTer->getElev()); CString str(_T("")); str.Format(_T("\n请输入洞口标高(单位与高程数据一致),默认为地形平均标高< % .2f>:"), dElev); acedGetReal(str, &dElev); for (int i(0); i < ids.length(); ++i) { OPENOBJ_BEGIN(ids[i], AcDb::kForRead, AcDbEntity, pHold) { if (!pHold) continue; pts.clear(); AcDbPolyline *pPoly = AcDbPolyline::cast(pHold); AcDbCircle *pCir = AcDbCircle::cast(pHold); if (pPoly) polyline2PointArray(*pPoly, pts, dElev); else if (pCir) circle2PointArray(*pCir, pts, dElev); if (!pts.empty()) pTer->addHold(pts); } OPENOBJ_END() } } OPENOBJ_END() } void TERRAIN::addHoldForSubDMesh(const AcGePoint3dArray &arPt , const Geometry::GePolyArray3d &arHold) { Geometry::GePoint3dArray pts; for (int i(0); i < arPt.length(); ++i) pts.push_back(arPt[i]); AcGePoint3dArray vertexArray; AcArray faceArray; Geometry::delaunayTriangulationMeshWithHolds(pts, arHold, vertexArray, faceArray); AcDbSubDMesh *pSubDMesh = new AcDbSubDMesh; AcDbObjectId layerID(AcDbObjectId::kNull); g_LayerMgr::instance().getLayer(GLTools::gLayer_DS, layerID); if (layerID.isValid()) pSubDMesh->setLayer(layerID); pSubDMesh->setSubDMesh(vertexArray, faceArray, 0); CoreTools::AddToModelSpace(pSubDMesh); return; } void TERRAIN::getHull() { Geometry::GePoint3dArray arPt3Ds(0); AcDbObjectIdArray ids; if (!getElevPoints(arPt3Ds, ids)) return; Geometry::GePoint2dArray ar2d, arOuter; for (size_t i(0); i < arPt3Ds.size(); ++i) { ar2d.push_back(AcGePoint2d(arPt3Ds[i].x, arPt3Ds[i].y)); } Geometry::calcConvexHull2D(ar2d, arOuter); AcDbPolyline *pPolyline = new AcDbPolyline(); for (size_t i(0); i < arOuter.size(); ++i) { pPolyline->addVertexAt(i, arOuter[i]); } pPolyline->setClosed(1); CoreTools::AddToModelSpace(pPolyline); } void TERRAIN::levelTerrainMesh() { Geometry::GePoint3dArray arPt3Ds(0); AcDbObjectId idOrig(AcDbObjectId::kNull); CString sFilter(getUserSelectType(idOrig)); if (sFilter.IsEmpty()) return; double dMax(.0), dMin(.0); if (acedGetReal(_T("\n请输入需要平整的地形的最大标高(单位:米):"), &dMax) != RTNORM) return; if (acedGetReal(_T("\n请输入需要平整的地形的最小标高(单位:米):"), &dMin) != RTNORM) return; if (dMin > dMax) { double d(dMin); dMin = dMax; dMax = d; } bool bGenerateTerrain = true; TCHAR szKey2[131] = { _T('Y'), }; acedInitGet(RSG_OTHER, _T("Y N")); int nRes = acedGetKword(_T("\n平整成功后,是否立即生成地形?[是(Y)/否(N)]<是(Y)>:"), szKey2); if (nRes == RTNONE) _tcscpy(szKey2, _T("Y")); if (_tcscmp(szKey2, _T("Y")) != 0) bGenerateTerrain = false; AcDbObjectId layerId = KTSetting::InitLayer(_T("LAY_FACTORY_LAND"), false); int nSelType(IsSelectAllPoint()); if (nSelType == 0) return; if (nSelType == 1) { std::vector arArraysOfPoint; std::vector arOuters; std::vector arArraysOfId; nRes = getPointsInAreaByUser(sFilter, idOrig, arArraysOfPoint, arOuters, arArraysOfId); if (nRes != RTNORM) return; if (!arArraysOfId.empty() && !arArraysOfPoint.empty() && !arOuters.empty() && arArraysOfId.size() == arArraysOfPoint.size() && arArraysOfId.size() == arOuters.size()) { for (size_t i = 0; i < arArraysOfId.size(); ++i) { AcDbObjectIdArray &ids(arArraysOfId[i]); Geometry::GePoint3dArray &arOuter(arOuters[i]); // 修改标高 for (int j(0); j < ids.length(); ++j) modifyElevObj(ids[j], dMax, dMin); if (bGenerateTerrain) { arPt3Ds.clear(); // 修改后重新分析标高 AcGePoint3d pt(AcGePoint3d::kOrigin); for (int i(0); i < ids.length(); ++i) { if (analyElevObj(ids.first(), ids[i], pt)) arPt3Ds.push_back(pt); } // 重新为外轮廓设置标高 setZ(arOuter, calcAverageZ(arPt3Ds)); // 生成 AecDbTerrain *pTer(makeTerrain(arPt3Ds, arOuter)); if (pTer) { if (layerId.isValid()) pTer->setLayer(layerId); CoreTools::AddToModelSpace(pTer); } } } return; } } else { Geometry::GePoint3dArray arPts(0); AcDbObjectIdArray ids; getAllOfPoints(sFilter, idOrig, arPts, ids); // 修改标高 for (int i(0); i < ids.length(); ++i) modifyElevObj(ids[i], dMax, dMin); if (bGenerateTerrain) { arPt3Ds.clear(); // 修改后重新分析标高 AcGePoint3d pt(AcGePoint3d::kOrigin); for (int i(0); i < ids.length(); ++i) { if (analyElevObj(ids.first(), ids[i], pt)) arPt3Ds.push_back(pt); } AecDbTerrain *pTer(makeTerrain(arPts, Geometry::GePoint3dArray())); if (pTer) { if (layerId.isValid()) pTer->setLayer(layerId); CoreTools::AddToModelSpace(pTer); return; } } return; } } void TERRAIN::extractElevtionData() { ads_name adsName; ads_point adsPt; int nRes = acedEntSel(_T("\n请选择一个多面网格对象:"), adsName, adsPt); if (nRes != RTNORM) return; AcDbObjectId idMesh(AcDbObjectId::kNull); acdbGetObjectId(idMesh, adsName); if (!GLTools::isThisClass(idMesh)) { acutPrintf(_T("\n请选择一个多面网格对象!")); return; } nRes = acedEntSel(_T("\n请选择一个多段线对象:"), adsName, adsPt); if (nRes != RTNORM) return; AcDbObjectId idPoly(AcDbObjectId::kNull); acdbGetObjectId(idPoly, adsName); if (!GLTools::isThisClass(idPoly)) { acutPrintf(_T("\n请选择一个多段线对象!")); return; } nRes = acedEntSel(_T("\n请选择起始桩号:"), adsName, adsPt); if (nRes != RTNORM) return; AcDbObjectId StartTxtID(AcDbObjectId::kNull); acdbGetObjectId(StartTxtID, adsName); if (!GLTools::isThisClass(StartTxtID) || !StakeTools::isSHSStake(StartTxtID)) { acutPrintf(_T("\n请选择一个上华桩号对象。")); return; } nRes = acedEntSel(_T("\n请选择结束桩号:"), adsName, adsPt); if (nRes != RTNORM) return; AcDbObjectId EndTxtID(AcDbObjectId::kNull); acdbGetObjectId(EndTxtID, adsName); if (!GLTools::isThisClass(EndTxtID) || !StakeTools::isSHSStake(EndTxtID)) { acutPrintf(_T("\n请选择一个上华桩号对象。")); return; } // 取出网格和路线的拷贝 AcDbSubDMesh *pCloneMesh(NULL); OPENOBJ_BEGIN(idMesh, AcDb::kForRead, AcDbSubDMesh, pFaceMesh) { if (!pFaceMesh) return; pCloneMesh = (AcDbSubDMesh*)pFaceMesh->clone(); } OPENOBJ_END() AcDbPolyline *pClonePoly(NULL); OPENOBJ_BEGIN(idPoly, AcDb::kForRead, AcDbPolyline, pPoly) { if (!pPoly) { DELETE_PTR(pCloneMesh); return; } pClonePoly = (AcDbPolyline*)pPoly->clone(); } OPENOBJ_END() bool bS2E; CString strTemp; double dTemp; AcGePoint3d ptStart(AcGePoint3d::kOrigin), ptEnd(AcGePoint3d::kOrigin); StakeTools::readSHSStake(StartTxtID, ptStart, bS2E, strTemp, dTemp, dTemp); StakeTools::readSHSStake(EndTxtID, ptEnd, bS2E, strTemp, dTemp, dTemp); CString strPrefix(_T("")); StakeTools::analyStakeString(strTemp, dTemp, &strPrefix); if (!bS2E) { AcGePoint3d ptT(ptStart); ptStart = ptEnd; ptEnd = ptT; } AcDbExtents ext; pCloneMesh->getGeomExtents(ext); if ( ptStart.x > ext.maxPoint().x || ptStart.y > ext.maxPoint().y || ptStart.x < ext.minPoint().x || ptStart.y < ext.minPoint().y || ptEnd.x > ext.maxPoint().x || ptEnd.y > ext.maxPoint().y || ptEnd.x < ext.minPoint().x || ptEnd.y < ext.minPoint().y ) { acutPrintf(_T("\n起起桩号与结束桩号之间的范围大于地形网格的范围。")); return; } if (!EQUAL_ZERO(pClonePoly->elevation())) pClonePoly->setElevation(.0); std::vector pts(0); getPolyPoints(pClonePoly, ptStart, ptEnd, 1., pts); std::vector fs(0); getSubDMeshFaces(pCloneMesh, fs); std::vector fps; FacePoint fp; for (size_t i = 0; i < pts.size(); ++i) { fp.pt = pts[i]; for (size_t f = 0; f < fs.size(); ++f) { Face &face(fs[f]); if (isInFace(fp.pt, face)) { fp.setFace(face); fps.push_back(fp); break; } } } std::map mapResult; int prec(3); AcGePoint3d ptClosed(AcGePoint3d::kOrigin); double dist(.0); for (size_t i = 0; i < fps.size(); ++i) { AcGePoint3d &pt(fps[i].pt); if (Acad::eOk != pClonePoly->getClosestPointTo(pt, ptClosed)) continue; if (Acad::eOk != pClonePoly->getDistAtPoint(ptClosed, dist)) continue; mapResult.insert(std::make_pair(dist, TypeConvert::f2s(pt.z, &prec))); } if (mapResult.empty()) { DELETE_PTR(pClonePoly); DELETE_PTR(pCloneMesh); return; } CString szFilter = _T("纵断数据文件 (*.txt)|*.txt;*.txt||"); CFileDialog fileDlg(FALSE, _T("txt"), _T("纵断数据文件"), OFN_HIDEREADONLY, szFilter, acedGetAcadFrame()); if (fileDlg.DoModal() != IDOK) { DELETE_PTR(pClonePoly); DELETE_PTR(pCloneMesh); return; } CStdioFile file(fileDlg.GetPathName(), CFile::modeCreate|CFile::modeWrite); if (!file.m_hFile) { DELETE_PTR(pClonePoly); DELETE_PTR(pCloneMesh); return; } std::map::iterator it = mapResult.begin(); CString str(_T("")); for (; it != mapResult.end(); ++it) { str.Format(_T("%s %s\n"), StakeTools::generateStakeString(it->first, strPrefix), it->second); file.WriteString(str); } file.Close(); DELETE_PTR(pClonePoly); DELETE_PTR(pCloneMesh); return; } #endif namespace { class DBRule: public AcDbEntity { public: DBRule() : entitys(0) { } ~DBRule() { clear(); } void clear() { for (size_t i = 0; i < entitys.size(); ++i) { AcDbEntity *p(entitys[i]); DELETE_PTR(p); } entitys.clear(); } virtual Adesk::Boolean subWorldDraw(AcGiWorldDraw* pWd) { for (size_t i = 0; i < entitys.size(); i++) { AcDbEntity *p(entitys[i]); if (p) p->worldDraw(pWd); } return Adesk::kTrue; } void setEntitys(const std::vector &ents) { clear(); entitys.assign(ents.begin(), ents.end()); } public: std::vector entitys; }; void drawRule(const AcGePoint3d &ptS , const AcGePoint3d &ptE , const double &dElev , std::vector &lines) { // 刻度1分米 double delta = .1; AcGeVector3d vtX(ucsXDir()), vtY(ucsYDir()); vtX.normalize(); vtY.normalize(); // 沿ucsX方向画刻度, ucsY方向画数轴 AcGeVector3d vt = ptE - ptS; int iNegative(1); if (vt.dotProduct(vtY) < 0) iNegative = -1; //delta *= iNegative; vtY *= iNegative; double length(vt.length()); lines.push_back(new AcDbLine(ptS, ptS + (vtY * length))); int step(0), prec(3); double dist(.0), angle(.0); AcGePoint3d pt(AcGePoint3d::kOrigin); while (dist < length) { pt = ptS + (vtY * dist); if (!(step % 10)) { lines.push_back(new AcDbLine(pt, pt + (vtX * .05))); AcDbText *pTxt = new AcDbText(); pTxt->setHorizontalMode(AcDb::kTextRight); pTxt->setVerticalMode(AcDb::kTextVertMid); pTxt->setAlignmentPoint(pt); pTxt->setHeight(.04); pTxt->setTextString(TypeConvert::f2s(dElev + step * .1 * iNegative, &prec)); angle = AcGeVector3d::kXAxis.angleTo(vtX, AcGeVector3d::kZAxis); pTxt->setRotation(angle); lines.push_back(pTxt); } else if (!(step % 5)) { lines.push_back(new AcDbLine(pt, pt + (vtX * .03))); } else lines.push_back(new AcDbLine(pt, pt + (vtX * .01))); dist += delta; ++step; } return; } class RuleJig :public AcEdJig { public: RuleJig(const AcGePoint3d &ptS, const double &dElev) : m_pRule(NULL) , m_ptS(ptS) , m_dElev(dElev) { m_pRule = new DBRule(); } ~RuleJig() { DELETE_PTR(m_pRule); } AcEdJig::DragStatus doIt() { setDispPrompt(_T("请选择一点做为标尺终点,来确定标尺方向与长度:")); AcEdJig::DragStatus st = drag(); return st; } void getEntitys(std::vector &ents) { for (size_t i = 0; i < m_pRule->entitys.size(); ++i) ents.push_back((AcDbEntity*)m_pRule->entitys[i]->clone()); } protected: virtual AcEdJig::DragStatus sampler() { AcEdJig::DragStatus st = acquirePoint(m_ptPos); return st; } virtual Adesk::Boolean update() { if (!m_pRule) return Adesk::kFalse; std::vector ents(0); drawRule(m_ptS, m_ptPos, m_dElev, ents); // 在setEntitys()回收内存 m_pRule->setEntitys(ents); return Adesk::kTrue; } virtual AcDbEntity* entity() const { return m_pRule; } private: DBRule *m_pRule; AcGePoint3d m_ptPos; // 选中点 AcGePoint3d m_ptS; // 开始点 double m_dElev; // 起始标高 }; } void TERRAIN::GenerateScaleplate() { ads_point adsPt; int nRes = acedGetPoint(NULL, _T("\n请选择一点做为标尺起点:"), adsPt); if (nRes != RTNORM) return; acdbUcs2Wcs(adsPt, adsPt, false); AcGePoint3d ptOrig(asPnt3d(adsPt)); double dElev(.0); nRes = acedGetReal(_T("\n请输入起点标高<0>:"), &dElev); if (nRes == RTCAN) return; RuleJig *pJig = new RuleJig(ptOrig, dElev); if (pJig->doIt() != AcEdJig::kNormal) { DELETE_PTR(pJig); return; } std::vector lines; pJig->getEntitys(lines); AcDbObjectIdArray ids(0); AcDbObjectId id(AcDbObjectId::kNull); for (size_t i = 0; i < lines.size(); ++i) { if (CoreTools::AddToModelSpace(lines[i], 0, true, &id) == Acad::eOk) ids.append(id); } CoreTools::generateGroup(NULL, ids); DELETE_PTR(pJig); }