1614 lines
41 KiB
C++
1614 lines
41 KiB
C++
#include "StdAfx.h"
|
||
#include "terrainAnalysis.h"
|
||
#include "UITools.h"
|
||
#include <sstream>
|
||
#include "ktcadutility.h"
|
||
#include <set>
|
||
#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<AcDb3dSolid> ptrSolid(id, AcDb::kForRead);
|
||
|
||
AcDbFaceterSettings settings;
|
||
AcGePoint3dArray pts;
|
||
AcArray<Adesk::Int32> faces;
|
||
AcGiFaceData* faceData;
|
||
err = acdbGetObjectMesh(ptrSolid, &settings, pts, faces, faceData);
|
||
if (faceData)
|
||
{
|
||
delete[] faceData->trueColors();
|
||
delete[] faceData->materials();
|
||
DELETE_PTR(faceData);
|
||
}
|
||
|
||
AcDbObjectPointer<AcDbSubDMesh> 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<AcGePoint3d> 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<AcGePoint3d> &ar, const double &dElev)
|
||
{
|
||
AcGePoint3d pt;
|
||
double dParam(.0);
|
||
std::set<double> 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<double>::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<AcGePoint3d> &ar, const double &dElev)
|
||
{
|
||
std::set<double> 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<double>::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<CString> &tags, std::set<CString> &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<CString> 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<CString> 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<AcGePoint3d> &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<Adesk::Int32> 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<Face> &fs)
|
||
{
|
||
AcGePoint3dArray arV;
|
||
AcArray<Adesk::Int32> 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<Geometry::GePoint3dArray> &arArraysOfPoint
|
||
, std::vector<Geometry::GePoint3dArray> &arOuters
|
||
, std::vector<AcDbObjectIdArray> &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<Geometry::GePoint3dArray> arArraysOfPoint;
|
||
std::vector<Geometry::GePoint3dArray> arOuters;
|
||
std::vector<AcDbObjectIdArray> 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<AcGePoint3d> 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<Adesk::Int32> 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<Geometry::GePoint3dArray> arArraysOfPoint;
|
||
std::vector<Geometry::GePoint3dArray> arOuters;
|
||
std::vector<AcDbObjectIdArray> 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<AcDbSubDMesh>(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<AcDbPolyline>(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<AcDbText>(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<AcDbText>(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<AcGePoint3d> pts(0);
|
||
getPolyPoints(pClonePoly, ptStart, ptEnd, 1., pts);
|
||
|
||
std::vector<Face> fs(0);
|
||
getSubDMeshFaces(pCloneMesh, fs);
|
||
|
||
std::vector<FacePoint> 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<double, CString> 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<double, CString>::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<AcDbEntity*> &ents)
|
||
{
|
||
clear();
|
||
entitys.assign(ents.begin(), ents.end());
|
||
}
|
||
|
||
public:
|
||
std::vector<AcDbEntity*> entitys;
|
||
};
|
||
|
||
void drawRule(const AcGePoint3d &ptS
|
||
, const AcGePoint3d &ptE
|
||
, const double &dElev
|
||
, std::vector<AcDbEntity*> &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<AcDbEntity*> &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<AcDbEntity*> 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<AcDbEntity*> 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);
|
||
}
|
||
|