Files
envi-code/SourceCode/Code2026/EarthWormCmd/terrainAnalysis.cpp
T
gjm 164968b62e chore
把非utf8-bom编码的cpp/h文件改为 utf8 bom 编码, msvc识别utf8编码时,如果不是bom格式的,会使用当前cp_oem来解码.
2026-10-04 00:04:20 +08:00

1614 lines
41 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#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);
}