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

437 lines
12 KiB
C++

#include "StdAfx.h"
#include "SectionUtility.h"
#include "math.h"
#include "XGlobalFunc.h"
#include "XDbObject.h"
short SectionUtility::Projection_line2plane( const XSectionPlane &plane, const AcGeLineSeg3d &in_seg, AcGeLineSeg3d &out_seg, AcGePoint3d &out_pt )
{
short iRet = 0;
AcGePlane ge_pln = plane.AsAcGePlane();
AcGePoint3d ptS = in_seg.startPoint().orthoProject(ge_pln); // 起点在面上的投影
AcGePoint3d ptE = in_seg.endPoint().orthoProject(ge_pln); // 终点在面上的投影
AcGeVector3d vtS = in_seg.startPoint() - ptS; // 线段起点的投影点到线段起点的向量
AcGeVector3d vtE = in_seg.endPoint() - ptE; // 线段终点的投影点到线段终点的向量
bool bDirS = vtS.dotProduct(plane.normal()) > 0 ? true : false; // vtS是否与法向量同向
bool bDirE = vtE.dotProduct(plane.normal()) > 0 ? true : false; // vtE是否与法向量同向
if (ptE == ptS) // 垂直
{
if (!bDirS && !bDirE)
iRet = -1;
else
{
if (plane.IsOn(ptE, true))
{
out_pt = ptE;
iRet = 1;
}
else
iRet = -1;
}
}
else if (bDirE && bDirS) // 两端点在面同侧
{
iRet = Projection_line2Plane_sub(plane, in_seg, out_seg, out_pt);
}
else if (bDirE || bDirS) // 两端点在面异侧
{
AcGePoint3d intersect_pt;
in_seg.intersectWith(ge_pln, intersect_pt);// 两端点在面异侧,线与面一定有交点
if (bDirS)
ptE = intersect_pt;
else
ptS = intersect_pt;
AcGeLineSeg3d seg(ptS, ptE); // 截去与面法向方向相反的那段线段
iRet = Projection_line2Plane_sub(plane, seg, out_seg, out_pt);
}
else
iRet = -1;
return iRet;
}
short GEOAPI SectionUtility::Projection_line2plane( const XSectionPlane &plane, const XLine &in_seg, XLine &out_seg, AcGePoint3d &out_pt )
{
AcGeLineSeg3d In(in_seg.GetStartPoint().AsAcGePoint3d(), in_seg.GetEndPoint().AsAcGePoint3d());
AcGeLineSeg3d Out;
short ret = Projection_line2plane(plane, In, Out, out_pt);
out_seg.SetStartPoint(Out.startPoint());
out_seg.SetEndPoint(Out.endPoint());
return ret;
}
double SectionUtility::Projection_plane2plane( const XSectionPlane &section, const XSectionPlane &plane, XPoly2D &poly )
{
AcGePoint3d pt1(0., 0., 0.), pt2(0., 0., 0.), ptTmp(0., 0., 0.);
AcGeLineSeg3d out_seg(pt1, pt2);
int nCount = plane.GetSegmentCount();
for (int i = 0; i < nCount; ++i)
{
AcGeLineSeg3d pln_seg = plane.get_seg(i);
short iRet = Projection_line2plane(section, pln_seg, out_seg, pt1);
if (iRet == 1) // pt 点有效, out_seg无效
{
if (poly.Tail())
{
if (*poly.Tail() != pt1)
poly.AppendNode(pt1);
}
else
poly.AppendNode(pt1);
}
else if (iRet == 0)
{
pt1 = out_seg.startPoint();
if (poly.Tail())
{
if (*poly.Tail() != pt1)
poly.AppendNode(pt1);
}
else
poly.AppendNode(pt1);
pt2 = out_seg.endPoint();
poly.AppendNode(pt2);
}
}
// 由曲线所构成的不规则面,如果曲线是闭合的,则投影面也闭合
if (plane.IsPoly() && plane.GetPoly().IsClosed())
poly.SetClosed();
if (!plane.IsPoly()) // 标准面本身为闭合曲线
poly.SetClosed();
return section.Distance(plane);
}
short SectionUtility::Projection_line2Plane_sub( const XSectionPlane &plane, const AcGeLineSeg3d &in_seg, AcGeLineSeg3d &out_seg, AcGePoint3d &out_pt )
{
short iRet = 0;
AcGePlane ge_pln = plane.AsAcGePlane();
AcGePoint3d ptS = in_seg.startPoint().orthoProject(ge_pln); // 起点在面上的投影
AcGePoint3d ptE = in_seg.endPoint().orthoProject(ge_pln); // 终点在面上的投影
bool bInS = plane.IsOn(ptS, true);
bool bInE = plane.IsOn(ptE, true);
if (bInS && bInE) // 两投影点都在面边界内
out_seg.set(ptS, ptE);
else
{
AcGeLineSeg3d seg(ptS, ptE);
std::vector<AcGePoint3d> arPts;
plane.intersect_with_segment(seg, arPts);
if (bInE || bInS) // 一个投影点在面边界内,另一个不在
{
if (bInS)
ptE = arPts[0];
else
ptS = arPts[0];
out_seg.set(ptS, ptE);
}
else if (!bInS && !bInE) // 两个投影点都不在面边界内
{
if (2 == arPts.size())
{
double d0 = seg.paramOf(arPts[0]),
d1 = seg.paramOf(arPts[1]);
if (d0 < d1)
out_seg.set(arPts[0], arPts[1]);
else
out_seg.set(arPts[1], arPts[0]);
}
else if (1 == arPts.size()) // 过投影点的线,正好是面的四个边界点其中之一
{
out_pt = arPts[0];
iRet = 1;
}
else if (arPts.empty()) // 过投影点的线段不在面边界内
iRet = -1;
}
}
return iRet;
}
/*
画出一个箭头,放入 AcDbPolyline内
arrowHead 箭头点, arrowTail 箭尾点
箭边长度是底边的3倍
*/
void SectionUtility::MakeArrow(AcDbPolyline &poly, const AcGePoint3d &arrowHead, const AcGePoint3d &arrowTail)
{
double arrowSide = 250;
// resbuf rb;
// if (acedGetVar(_T("DIMASZ"), &rb) == RTNORM) // 取得CAD注释箭头大小
// arrowSide = rb.resval.rreal * 100;
double angle = asin(1./6);//箭头夹角的半角
AcGeVector3d vec = arrowTail - arrowHead;
vec.normalize();
vec *= /*arrowSide*/arrowHead.distanceTo(arrowTail) * .1;
AcGePoint3d pt1, pt2;
vec.rotateBy(angle, AcGeVector3d::kZAxis);
pt1 = arrowHead + vec;
vec.rotateBy(2 * (PI - angle), AcGeVector3d::kZAxis);
pt2 = arrowHead + vec;
poly.addVertexAt(0, AcGePoint2d(pt1.x, pt1.y));
poly.addVertexAt(1, AcGePoint2d(arrowHead.x, arrowHead.y));
poly.addVertexAt(2, AcGePoint2d(pt2.x, pt2.y));
poly.addVertexAt(3, AcGePoint2d(pt1.x, pt1.y));
}
void SectionUtility::DrawColumn3D(XExplodeDraw &dc, const AcGePoint3d& TopCenter, const AcGePoint3d &BottomCenter, const double &scale)
{
AcGeVector3d vtHori= TopCenter - BottomCenter;
vtHori.normalize();
vtHori.rotateBy(PI*0.5, AcGeVector3d::kZAxis);
AcGeVector3d vtVert= vtHori.perpVector(); // 底圆心向量
vtVert.normalize();
double radius = (TopCenter.distanceTo(BottomCenter) / 9.) * tan(asin(1./6)) / 3.;
// resbuf rb;
// if (acedGetVar(_T("DIMASZ"), &rb) == RTNORM) // 取得CAD注释箭头大小
// radius = rb.resval.rreal * scale;
radius *= .1/6; // 半径
vtHori *= radius;
AcGeVector3d vec = vtHori;
int nPart = 21;
std::vector<AcGePoint3d> arPt(2*nPart, AcGePoint3d(0., 0., 0.));
for (int i = 0; i < nPart; ++i)
{
arPt[i] = TopCenter + vtHori.rotateBy(2*PI/(nPart-1), vtVert);
arPt[nPart+i] = BottomCenter + vec.rotateBy(2*PI/(nPart-1), vtVert);
}
dc.DrawMesh(2, nPart, &arPt[0]);
}
void SectionUtility::DrawTaper3D(XExplodeDraw &dc, const AcGePoint3d &BottomCenter, const AcGeVector3d &Dir, const double &scale)
{
// resbuf rb;
// if (acedGetVar(_T("DIMASZ"), &rb) == RTNORM) // 取得CAD注释箭头大小
// c = rb.resval.rreal * scale;
double b = Dir.length() / 9.;
double a = b * tan(asin(1./6)); // 半径(直角边a)
/*Dir.length() / 9 为另一直角边*/
AcGeVector3d vtHori = Dir;
vtHori.normalize();
AcGePoint3d TopCenter = BottomCenter + vtHori*b;
vtHori.rotateBy(PI*0.5, AcGeVector3d::kZAxis);
AcGeVector3d vtVert = vtHori.perpVector();
vtHori *= a;
int nPart = 21;
std::vector<AcGePoint3d> arPt(2*nPart, AcGePoint3d(0., 0., 0.));
for (int i = 0; i < nPart; ++i)
{
arPt[i] = TopCenter;
arPt[nPart+i] = BottomCenter+ vtHori.rotateBy(2*PI/(nPart-1), vtVert);
}
dc.DrawMesh(2, nPart, &arPt[0]);
return;
}
void SectionUtility::DrawLines( const std::vector<XLine> &lines, const AcCmColor color)
{
for (size_t i = 0; i < lines.size(); ++i)
{
XLine line = lines[i];
AcDbLine *pLine = new AcDbLine(line.GetStartPoint().AsAcGePoint3d(),
line.GetEndPoint().AsAcGePoint3d());
pLine->setColor(color);
AddToCurrentSpace(pLine, TRUE);
}
}
bool SectionUtility::GetLine( const std::vector<std::pair<int, XLine> > &lines, const int nIndex, XLine &line)
{
for (size_t i = 0; i < lines.size(); ++i)
{
if (lines[i].first == nIndex)
{
line = lines[i].second;
return true;
}
}
return false;
}
AcDbObjectId SectionUtility::CloneAndResetLineTypeForBlockTableRecord(AcDbObjectId &objId, const CString &sLine)
{
AcDbObjectId idBlock = AcDbObjectId::kNull;
CString sName = (LPCTSTR)GetSymbolName(objId); // 被 clone 块的 名称
if (sName.IsEmpty())
return idBlock;
sName += _T("_DASH_"); // 新块的名称
// 搜索新块是否已经存在
AcDbBlockTable *pBlockTable = NULL;
AcDbObjectId modelSpaceId;
acdbHostApplicationServices()->workingDatabase()->getSymbolTable(pBlockTable, AcDb::kForWrite);
if (pBlockTable)
{
if (pBlockTable->has(sName))
{
pBlockTable->getAt(sName, idBlock);
pBlockTable->close();
return idBlock;
}
pBlockTable->getAt(ACDB_MODEL_SPACE, modelSpaceId);
AcDbBlockTableRecord *pNewRec = new AcDbBlockTableRecord();
pNewRec->setName(sName);
pBlockTable->add(idBlock, pNewRec);
AcDbBlockReference *pRef = new AcDbBlockReference(AcGePoint3d::kOrigin, objId);
AcDbVoidPtrArray ptrArr;
pRef->explode(ptrArr);
for (int i = 0; i < ptrArr.length(); i++)
{
AcDbEntity *pEnt = (AcDbEntity*)ptrArr[i];
AcDbEntity *pNewEnt = (AcDbEntity*)pEnt->clone();
if(pNewEnt != NULL)
{
pNewEnt->setLinetype(sLine);
pNewRec->appendAcDbEntity(pNewEnt);
pNewEnt->close();
}
}
delete pRef;
pNewRec->close();
pBlockTable->close();
}
return idBlock;
}
double GEOAPI SectionUtility::Projection_poly2plane( const XSectionPlane &section, const XPoly2D &plane, XPoly2D &poly )
{
XSectionPlane pln(plane, AcGeVector3d::kZAxis);
return Projection_plane2plane(section, pln, poly);
}
XCurveSegment SectionUtility::GetSegmentOfPoly(const XPoly2D &poly, const int nIdx)
{
XPoint pt1, pt2;
if (nIdx < GetCountOfSegmentForPoly(poly))
{
pt1 = poly[nIdx];
if (nIdx == poly.Length()-1)
pt2 = poly[0];
else
pt2 = poly[nIdx + 1];
}
return XCurveSegment(pt1, pt2, 0.);
}
int SectionUtility::GetCountOfSegmentForPoly(const XPoly2D &poly)
{
if (poly.IsClosed())
return poly.Length();
else
return poly.Length() - 1;
}
AcGeMatrix3d SectionUtility::GetCoordSystem(const AcGeVector3d &vt)
{
AcGeMatrix3d mat;
AcGePoint3d ptOrigin;
AcGeVector3d vtNormal(0,0,1);
AcGeVector3d vtToX(1,0,0);
AcGeVector3d vtToY(0,1,0);
AcGeVector3d vecView = vt;
vecView.normalize();
//顺着剖切的方向是Y轴,根据右手定则,与z轴差乘是X轴
AcGeVector3d vtFromX = vecView.crossProduct(vtNormal);
mat.setToAlignCoordSys(ptOrigin, vtFromX, vecView, vtNormal, ptOrigin, vtToX, vtToY, vtNormal);
AcGeMatrix3d matWcs;
matWcs.setToRotation(-PI*.5, vtToX);
return matWcs * mat;
}
void GEOAPI SectionUtility::MakeFacesByPoly( const XPoly2D &poly, const double &elev, const double &height,
std::vector<XSectionPlane> &planes, const bool bTopFace /*= false*/)
{
int nCount = GetCountOfSegmentForPoly(poly);
for (int i = 0; i < nCount; ++i)
{
XCurveSegment seg = GetSegmentOfPoly(poly, i);
AcGePoint3d pt1(seg.GetStartPoint().AsAcGePoint3d()), pt2(seg.GetEndPoint().AsAcGePoint3d());
pt1.z = pt2.z = elev;
AcGePoint3d pt3(pt1), pt4(pt2);
pt3.z = pt4.z = elev + height;
planes.push_back(XSectionPlane(pt1, pt2, pt4, pt3, AcGeVector3d::kZAxis));
}
if (bTopFace)
{
XPoly2D poly1(poly);
poly1.SetElevation(elev);
planes.push_back(XSectionPlane(poly1, AcGeVector3d::kZAxis));
poly1.SetElevation(elev + height);
planes.push_back(XSectionPlane(poly1, AcGeVector3d::kZAxis));
}
}
void GEOAPI SectionUtility::DrawPoly2D( const XPoly2D &poly, const int color /*= 7*/ )
{
for (int i = 0; i < GetCountOfSegmentForPoly(poly); ++i)
{
XCurveSegment seg = GetSegmentOfPoly(poly, i);
AcDbLine *pL = new AcDbLine(seg.GetStartPoint(), seg.GetEndPoint());
pL->setColorIndex(color);
AddToCurrentSpace(pL, 1);
}
}
void GEOAPI SectionUtility::DrawXPlane( const XSectionPlane &plane, const int color)
{
AcDbFace face;
plane.AsAcDbFace(face);
AcDbFace *pF = (AcDbFace*)face.clone();
pF->setColorIndex(color);
AddToCurrentSpace(pF, 1);
}
void GEOAPI SectionUtility::FillRecordsByPoly( const XPoly2D &poly, const XSectionPlane &section,
std::vector<ObjSectionRecord> &records,
const double &elev, const double &height,
const AcDbEntity &ent,
ObjSectionRecord::SectionType type /*= ObjSectionRecord::eAEC_WALL*/,
const bool bTopFace /*= false*/)
{
AcDbObjectId id = ent.objectId();
AcDbObjectId layer = ent.layerId();
XPoly2D result;
double dDis = 0.;
std::vector<XSectionPlane> planes;
SectionUtility::MakeFacesByPoly(poly, elev, height, planes, bTopFace);
for (size_t i = 0; i < planes.size(); ++i)
{
result.Reset();
dDis = SectionUtility::Projection_plane2plane(section, planes[i], result);
if (result.Length())
records.push_back(ObjSectionRecord(id, layer, type, dDis, result));
}
}