437 lines
12 KiB
C++
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 §ion, 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 §ion, 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 §ion,
|
|
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));
|
|
}
|
|
}
|