#include "StdAfx.h" #include "SectionUtility.h" #include "math.h" #include "TchGlobalFunc.h" #include "TAcDbObjectPtr.h" short SectionUtility::Projection_line2plane( const TGGeSectionPlane &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 TGGeSectionPlane &plane, const TGGeLine &in_seg, TGGeLine &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 TGGeSectionPlane §ion, const TGGeSectionPlane &plane, TGGePoly2D &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 TGGeSectionPlane &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 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(TGGiExplodeDrawBase &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 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(TGGiExplodeDrawBase &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 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 &lines, const AcCmColor color) { for (size_t i = 0; i < lines.size(); ++i) { TGGeLine 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 > &lines, const int nIndex, TGGeLine &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 = GetSymbolName(objId).cs(); // 被 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 TGGeSectionPlane §ion, const TGGePoly2D &plane, TGGePoly2D &poly ) { TGGeSectionPlane pln(plane, AcGeVector3d::kZAxis); return Projection_plane2plane(section, pln, poly); } TGGeCurveSegment SectionUtility::GetSegmentOfPoly(const TGGePoly2D &poly, const int nIdx) { TADSGePoint3d pt1, pt2; if (nIdx < GetCountOfSegmentForPoly(poly)) { pt1 = poly[nIdx]; if (nIdx == poly.Length()-1) pt2 = poly[0]; else pt2 = poly[nIdx + 1]; } return TGGeCurveSegment(pt1, pt2, 0.); } int SectionUtility::GetCountOfSegmentForPoly(const TGGePoly2D &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 TGGePoly2D &poly, const double &elev, const double &height, std::vector &planes, const bool bTopFace /*= false*/) { int nCount = GetCountOfSegmentForPoly(poly); for (int i = 0; i < nCount; ++i) { TGGeCurveSegment 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(TGGeSectionPlane(pt1, pt2, pt4, pt3, AcGeVector3d::kZAxis)); } if (bTopFace) { TGGePoly2D poly1(poly); poly1.SetElevation(elev); planes.push_back(TGGeSectionPlane(poly1, AcGeVector3d::kZAxis)); poly1.SetElevation(elev + height); planes.push_back(TGGeSectionPlane(poly1, AcGeVector3d::kZAxis)); } } void GEOAPI SectionUtility::DrawPoly2D( const TGGePoly2D &poly, const int color /*= 7*/ ) { for (int i = 0; i < GetCountOfSegmentForPoly(poly); ++i) { TGGeCurveSegment seg = GetSegmentOfPoly(poly, i); AcDbLine *pL = new AcDbLine(seg.GetStartPoint(), seg.GetEndPoint()); pL->setColorIndex(color); AddToCurrentSpace(pL, 1); } } void GEOAPI SectionUtility::DrawTGGePlane( const TGGeSectionPlane &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 TGGePoly2D &poly, const TGGeSectionPlane §ion, std::vector &records, const double &elev, const double &height, const AcDbEntity &ent, TObjSectionRecord::SectionType type /*= TObjSectionRecord::eTCH_WALL*/, const bool bTopFace /*= false*/) { AcDbObjectId id = ent.objectId(); AcDbObjectId layer = ent.layerId(); TGGePoly2D result; double dDis = 0.; std::vector 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(TObjSectionRecord(id, layer, type, dDis, result)); } }