#include "stdafx.h" #include "AecDbFlume.h" #include "GiDrawUtility.h" #include "AecDb3dRoadAxisLine.h" #include "CoreTools.h" namespace { Acad::ErrorStatus moveTo(AcDbEntity *pEnt, const AcGeVector3d &vt, const double &dist) { AcGeVector3d v(vt); v.normalize(); v *= dist; AcGeMatrix3d mat; mat.setToTranslation(v); return pEnt->transformBy(mat); } } ACRX_DXF_DEFINE_MEMBERS(AecDbFlume, AecDbEwPipeBase, AcDb::kDHL_CURRENT, AcDb::kMReleaseCurrent, AcDbProxyEntity::kNoOperation | AcDbProxyEntity::kDisableProxyWarning, AEC_DBFLUME, "AecDbFlume" "|Product Desc: shanghua earthworm app obj" "|Company: shanghua inc" "|WEB Address: www.shanghuasoft.com") Adesk::UInt32 AecDbFlume::kCurrentVersionNumber = 1; IMP_XDATA_KEY(AecDbFlume, _START_PT_); IMP_XDATA_KEY(AecDbFlume, _END_PT_); IMP_XDATA_KEY(AecDbFlume, _W_); IMP_XDATA_KEY(AecDbFlume, _H_); IMP_XDATA_KEY(AecDbFlume, _T_); IMP_XDATA_KEY(AecDbFlume, _TYPE_); IMP_XDATA_KEY(AecDbFlume, _NORMAL_); IMP_XDATA_KEY(AecDbFlume, _RADIUS_); IMP_XDATA_KEY(AecDbFlume, _ANGLE_); IMP_XDATA_KEY(AecDbFlume, _HEAD_SPACING_C_); IMP_XDATA_KEY(AecDbFlume, _TAIL_SPACING_C_); IMP_XDATA_KEY(AecDbFlume, _HEAD_SPACING_T_); IMP_XDATA_KEY(AecDbFlume, _TAIL_SPACING_T_); IMP_XDATA_KEY(AecDbFlume, _WEIR_H_1); IMP_XDATA_KEY(AecDbFlume, _SPACING_1); IMP_XDATA_KEY(AecDbFlume, _WEIR_H_2); IMP_XDATA_KEY(AecDbFlume, _SPACING_2); AecDbFlume::AecDbFlume() { SetWidth(100.); SetHeight(100.); SetThick(5.); SetType(eCircle); SetStartPt(AcGePoint3d::kOrigin); SetEndPt(AcGePoint3d(100., 0., 0.)); SetNormal(AcGeVector3d::kZAxis); SetRadius(25.); SetAngle(PI * .5); SetHeadSpaC(100); SetTailSpaC(0.); SetSpacingC(150.); SetWeirHC(25.); SetHeadSpaT(0.); SetTailSpaT(0.); SetSpacingT(150.); SetWeirHT(50.); m_mapSpecXData.SetAt(KEY_NAME, _T("集水槽")); } AecDbFlume::~AecDbFlume() { } void AecDbFlume::subList() const { assertReadEnabled(); AecDbEwPipeBase::subList(); Type tt = (Type)GetType(); CString str(_T("圆孔")); if (tt == eTriangle) str = _T("三角"); else if (tt == eCAndT) str = _T("三角&圆孔"); acutPrintf(_T("\n槽类型:%s"), str); acutPrintf(_T("\n槽宽:%.1f mm"), GetWidth()); acutPrintf(_T("\n槽高:%.1f mm"), GetHeight()); acutPrintf(_T("\n槽板厚:%.1f mm"), GetThick()); acutPrintf(_T("\n槽长:%.1f mm"), GetStartPt().distanceTo(GetEndPt())); AcGeVector3d v(GetNormal()); acutPrintf(_T("\n法向:(%.3f,%.3f,%.3f)"), v.x, v.y, v.z); AcGePoint3d pt(GetStartPt()); acutPrintf(_T("\n起点:(%.3f,%.3f,%.3f)"), pt.x, pt.y, pt.z); pt = GetEndPt(); acutPrintf(_T("\n终点:(%.3f,%.3f,%.3f)"), pt.x, pt.y, pt.z); if (tt == eCircle || tt == eCAndT) { acutPrintf(_T("圆孔径:%.1f mm"), GetRadius()); acutPrintf(_T("圆孔距:%.1f mm"), GetSpacingC()); acutPrintf(_T("圆孔距顶面高:%.1f mm"), GetWeirHC()); acutPrintf(_T("圆孔头部安装距离:%.1f mm"), GetHeadSpaC()); acutPrintf(_T("圆孔尾部安装距离:%.1f mm"), GetTailSpaC()); } else if (tt == eTriangle || tt == eCAndT) { acutPrintf(_T("三角角度:%.1f mm"), GetRadius()); acutPrintf(_T("三角距:%.1f mm"), GetSpacingT()); acutPrintf(_T("三角距顶面高:%.1f mm"), GetWeirHT()); acutPrintf(_T("三角头部安装距离:%.1f mm"), GetHeadSpaT()); acutPrintf(_T("三角尾部安装距离:%.1f mm"), GetTailSpaT()); } } Acad::ErrorStatus AecDbFlume::copyFrom(const AcRxObject * pSrc) { AecDbCurveBase::copyFrom(pSrc); AecDbFlume *p = AecDbFlume::cast(pSrc->desc()); if (!p) return Acad::eInvalidInput; m_mapSpecXData.Empty(); m_mapSpecXData.CopyFrom(&p->m_mapSpecXData); m_sGUID = CoreTools::guid(); return Acad::eOk; } Acad::ErrorStatus AecDbFlume::subTransformBy(const AcGeMatrix3d & xform) { AssertWriteEnabled(); AcGePoint3d pt(GetStartPt()); pt.transformBy(xform); SetStartPt(pt); pt = GetEndPt(); pt.transformBy(xform); SetEndPt(pt); return AecDbEwPipeBase::subTransformBy(xform); } Acad::ErrorStatus AecDbFlume::dwgInFields(AcDbDwgFiler * pFiler) { AssertWriteEnabled(); //----- Read parent class information first. Acad::ErrorStatus es = Acad::eOk; es = AecDbEwPipeBase::dwgInFields(pFiler); if (es != Acad::eOk) return (es); //----- Object version number needs to be read first Adesk::UInt32 version(0); if ((es = pFiler->readUInt32(&version)) != Acad::eOk) return (es); if (version > AecDbFlume::kCurrentVersionNumber) return Acad::eMakeMeProxy; return Acad::eOk; } Acad::ErrorStatus AecDbFlume::dwgOutFields(AcDbDwgFiler * pFiler) const { assertReadEnabled(); //----- Save parent class information first. Acad::ErrorStatus es = Acad::eOk; es = AecDbEwPipeBase::dwgOutFields(pFiler); if (es != Acad::eOk) return (es); //----- Object version number needs to be saved first if ((es = pFiler->writeUInt32(AecDbFlume::kCurrentVersionNumber)) != Acad::eOk) return (es); return Acad::eOk; } Acad::ErrorStatus AecDbFlume::dxfInFields(AcDbDxfFiler * pFiler) { return AecDbEwPipeBase::dxfInFields(pFiler); } Acad::ErrorStatus AecDbFlume::dxfOutFields(AcDbDxfFiler * pFiler) const { return AecDbEwPipeBase::dxfOutFields(pFiler); } void AecDbFlume::GetGripText(int nPos, CString & sText) { switch (nPos) { case 0: sText = _T("移动起点"); break; case 1: sText = _T("平移"); break; case 2: sText = _T("移动终点"); default: break; } } Acad::ErrorStatus AecDbFlume::Draw2d(AcGiDraw & dc) const { assertReadEnabled(); int clr(256), oldclr; m_mapSpecXData.GetAt(_T("COLOR"), clr); oldclr = dc.GetColor(); dc.SetColor(clr); if (Has2DBuffer()) { Draw2DBuffers(dc); return Acad::eOk; } Type type((Type)GetType()); if (type == eNone) { AecDbEwPipeBase::Draw2d(dc); return Acad::eOk; } AcGePoint3d ptS(GetStartPt()), ptE(GetEndPt()); double w(GetWidth()), len(ptS.distanceTo(ptE)); AcGeVector3d vtDir(ptE - ptS), vt(ptE - ptS), vtNormal(GetNormal()); vt.rotateBy(PI * .5, vtNormal); vtDir.normalize(); vtNormal.normalize(); vt.normalize(); AcDbPolyline *pl = new AcDbPolyline; AcGePoint3d pt0(ptS + vt * (w * .5)); AcGePoint3d pt1(pt0 + vtDir * len); AcGePoint3d pt2(pt1 - vt * w); AcGePoint3d pt3(pt2 - vtDir * len); pl->addVertexAt(0, pt0.convert2d(AcGePlane::kXYPlane)); pl->addVertexAt(1, pt1.convert2d(AcGePlane::kXYPlane)); pl->addVertexAt(2, pt2.convert2d(AcGePlane::kXYPlane)); pl->addVertexAt(3, pt3.convert2d(AcGePlane::kXYPlane)); pl->setClosed(true); dc.DrawPolyline(*pl); Add2DBuffer(pl); dc.SetColor(oldclr); return Acad::eOk; } Acad::ErrorStatus AecDbFlume::Draw3d(AcGiDraw & dc) const { assertReadEnabled(); int clr(256), oldclr; m_mapSpecXData.GetAt(_T("COLOR"), clr); oldclr = dc.GetColor(); dc.SetColor(clr); if (Has3DBuffer()) { Draw3DBuffers(dc); return Acad::eOk; } Type type((Type)GetType()); if (type != eNone) // 根据参数绘制 主体 + 打孔 { AcDb3dSolid *pSolid = GetBaseSolid(); if (!pSolid) { return Acad::eInvalidInput; } if (pSolid && (type == eCircle || type == eCAndT)) { BooleanOper_Circle(pSolid); } if (pSolid && (type == eTriangle || type == eCAndT)) { BooleanOper_Triangle(pSolid); } if (pSolid) { pSolid->setTransparency(transparency()); dc.DrawEntity(*pSolid); Add3DBuffer(pSolid); } return Acad::eOk; } else // 普通槽,通过外部传入的截面,和路径绘制 { return DrawByPipebase(dc); } dc.SetColor(oldclr); return Acad::eOk; } AcDb3dSolid* AecDbFlume::MakeCircleRegin() const { AcGePoint3d ptS(GetStartPt()), ptE(GetEndPt()); double h(GetHeight()), len(ptS.distanceTo(ptE)), r(GetRadius()) , spac(GetSpacingC()), weirH(GetWeirHC()) , headSpac(GetHeadSpaC()), tailSpac(GetTailSpaC()); double half(r); // 半长 len -= (headSpac + tailSpac); // 减掉头尾空隙 //if (spac < 2 * half || len < 2 * half || h < weirH) return NULL; AcGePoint3d ptC1, ptC2; GetSubSolidPath(eCircle, ptC1, ptC2); AcDbLine tmpLine(ptC1, ptC2); AcDbCircle tmpCir(AcGePoint3d::kOrigin, AcGeVector3d::kZAxis, r); AcDbEntity *pEnt = GiDrawUtility::DrawPipe(&tmpLine , &tmpCir , AcGePoint3d::kOrigin); if (!pEnt) return NULL; AcDb3dSolid *pSub = AcDb3dSolid::cast(pEnt); if (!pSub) { DELETE_PTR(pEnt); return NULL; } return pSub; } AcDb3dSolid* AecDbFlume::MakeTriangleRegin() const { AcGePoint3d ptS(GetStartPt()), ptE(GetEndPt()); double h(GetHeight()), len(ptS.distanceTo(ptE)), angle(GetAngle()) , spac(GetSpacingT()), weirH(GetWeirHT()) , headSpac(GetHeadSpaT()), tailSpac(GetTailSpaT()); double half(tan(.5 * angle) * weirH); // 半长 // 初步验证数据正确性 len -= (headSpac + tailSpac); // 减掉头尾空隙 //if (spac < 2 * half || len < 2 * half || h < weirH) return NULL; AcGePoint3d ptC1, ptC2; GetSubSolidPath(eTriangle, ptC1, ptC2); // 先在原点处画三角面 AcGeVector2d vt2d(AcGeVector2d::kXAxis); vt2d.rotateBy(.5 * (PI - angle)); vt2d *= weirH / cos(angle * .5); AcDbPolyline pl; pl.addVertexAt(0, AcGePoint2d::kOrigin); pl.addVertexAt(1, AcGePoint2d::kOrigin + vt2d); vt2d.rotateBy(angle); pl.addVertexAt(2, AcGePoint2d::kOrigin + vt2d); pl.setClosed(true); AcDbLine tmpLine(ptC1, ptC2); AcDbEntity *pEnt = GiDrawUtility::DrawPipe(&tmpLine , &pl , AcGePoint3d::kOrigin); if (!pEnt) return NULL; AcDb3dSolid *pSub = AcDb3dSolid::cast(pEnt); if (!pSub) { DELETE_PTR(pEnt); return NULL; } return pSub; } void AecDbFlume::BooleanOper_Circle(AcDb3dSolid *pSolid) const { AcDb3dSolid *pSub = MakeCircleRegin(); if (!pSub) return; AcGePoint3d ptS(GetStartPt()), ptE(GetEndPt()); double len(ptS.distanceTo(ptE)), spac(GetSpacingC()) , headSpac(GetHeadSpaC()), tailSpac(GetTailSpaC()); double half(GetRadius()); // 半长 AcGeVector3d vtDir(ptE - ptS), vt(ptE - ptS), vtNormal(GetNormal());; vtDir.normalize(); vt.rotateBy(PI * .5, vtNormal); vt.normalize(); len -= (headSpac + tailSpac); BooleanOper(pSolid, pSub, len, spac, half, vtDir, vt); DELETE_PTR(pSub); } void AecDbFlume::BooleanOper_Triangle(AcDb3dSolid *pSolid) const { AcDb3dSolid *pSub = MakeTriangleRegin(); if (!pSub) return; AcGePoint3d ptS(GetStartPt()), ptE(GetEndPt()); double len(ptS.distanceTo(ptE)), angle(GetAngle()) , spac(GetSpacingT()), weirH(GetWeirHT()) , headSpac(GetHeadSpaT()), tailSpac(GetTailSpaT()); double half(tan(.5 * angle) * weirH); // 半长 AcGeVector3d vtDir(ptE - ptS), vt(ptE - ptS), vtNormal(GetNormal()); vtDir.normalize(); vt.rotateBy(PI * .5, vtNormal); vt.normalize(); len -= (headSpac + tailSpac); BooleanOper(pSolid, pSub, len, spac, half, vtDir, vt); DELETE_PTR(pSub); } void AecDbFlume::BooleanOper(AcDb3dSolid * pSolid , AcDb3dSolid * pSub , const double &len , const double &spac , const double &half , const AcGeVector3d &vtDir // 槽方向 , const AcGeVector3d &vt // 在槽底面上,与槽方向垂直的向量 ) const { double w(GetWidth()), t(GetThick()); int num = int(len / spac); // 检查一下,还能不能画最后一个 if (len - num * spac > 2 * half) num++; for (int i = 0; i < num; ++i) { // 沿vtDir移动spacing moveTo(pSub, vtDir, i * spac); // 先在一侧打洞 CoreTools::booleanOper(pSolid, pSub, AcDb::kBoolSubtract); // 向vt方向,移动到另一侧 moveTo(pSub, vt, w - t); // 再打洞 CoreTools::booleanOper(pSolid, pSub, AcDb::kBoolSubtract); // 再移动回去 moveTo(pSub, -vt, w - t); moveTo(pSub, -vtDir, i * spac); } } void AecDbFlume::GetSubSolidPath(const Type &type, AcGePoint3d & pt1, AcGePoint3d & pt2) const { AcGePoint3d ptS(GetStartPt()), ptE(GetEndPt()); double w(GetWidth()), h(GetHeight()), t(GetThick()) , weirH(type == eCircle ? GetWeirHC() : GetWeirHT()) , headSpac(type == eCircle ? GetHeadSpaC() : GetHeadSpaT()); double half(.0); if (type == eCircle) half = GetRadius(); else { double angle(GetAngle()); half = tan(.5 * angle) * weirH; } AcGeVector3d vtDir(ptE - ptS), vtNormal(GetNormal()), vt(ptE - ptS); vtDir.normalize(); vt.rotateBy(PI * .5, vtNormal); vt.normalize(); vtNormal.normalize(); AcGePoint3d ptTopRight(ptS); ptTopRight -= vt * (.5 * w); ptTopRight += vtNormal * h; pt1 = (ptTopRight - vtNormal * weirH); // 拉伸面起点 pt2 = (pt1 + vt * t); // 拉伸面终点 // 两个点向vtDir方向移动距离headSpac + half pt1 += vtDir * (headSpac + half); pt2 += vtDir * (headSpac + half); } AcDb3dSolid * AecDbFlume::GetBaseSolid() const { /* pt7 _ pt6 pt3 _ pt2 | | | | | | | | | |pt5 pt4| | | |__________| | |______________| pt0 O pt1 O - 原点 pt0->pt1 w pt1->pt2 h pt2->pt3 t */ double w(GetWidth()), h(GetHeight()), t(GetThick()); AcGePoint3d pt0, pt1, pt2, pt3, pt4, pt5, pt6, pt7; AcGeVector3d vtX(AcGeVector3d::kXAxis); AcGeVector3d vtY(AcGeVector3d::kYAxis); pt0 = AcGePoint3d::kOrigin - vtX * (.5 * w); pt1 = pt0 + vtX * w; pt2 = pt1 + vtY * h; pt3 = pt2 - vtX * t; pt4 = pt3 - vtY * (h - t); pt5 = pt4 - vtX * (w - 2 * t); pt6 = pt5 + vtY * (h - t); pt7 = pt6 - vtX * t; AcDbPolyline pl; pl.addVertexAt(0, pt0.convert2d(AcGePlane::kXYPlane)); pl.addVertexAt(1, pt1.convert2d(AcGePlane::kXYPlane)); pl.addVertexAt(2, pt2.convert2d(AcGePlane::kXYPlane)); pl.addVertexAt(3, pt3.convert2d(AcGePlane::kXYPlane)); pl.addVertexAt(4, pt4.convert2d(AcGePlane::kXYPlane)); pl.addVertexAt(5, pt5.convert2d(AcGePlane::kXYPlane)); pl.addVertexAt(6, pt6.convert2d(AcGePlane::kXYPlane)); pl.addVertexAt(7, pt7.convert2d(AcGePlane::kXYPlane)); pl.setClosed(true); AcDbLine tmpLine(GetStartPt(), GetEndPt()); AcDbEntity *pEnt1 = GiDrawUtility::DrawPipe(&tmpLine, &pl, AcGePoint3d::kOrigin); if (!pEnt1) { #ifndef NDEBUG CoreTools::CloneAndAddToModelSpace(&pl); #endif return NULL; } AcDb3dSolid *pSolid(AcDb3dSolid::cast(pEnt1)); if (!pSolid) { DELETE_PTR(pEnt1); return NULL; } return pSolid; } Acad::ErrorStatus AecDbFlume::DrawByPipebase(AcGiDraw & dc) const { return AecDbEwPipeBase::Draw3d(dc); if (m_pBaseCurve == NULL) return Acad::eInvalidInput; //图层 AcDbObjectId idLay = dc.GetLayerId(); dc.SetLayer(layerId()); int nCrBk = dc.GetColor(); int nColor = nCrBk; if (m_mapSpecXData.GetAt(_T("COLOR"), nColor)) { dc.SetColor(nColor); } AcGePoint3d ptCen, ptGe; m_mapSpecXData.GetAt(KEY_SECCEN, ptCen); AcGePoint3dArray arPts; double dW = 0.0, dDis = 0.0; for (int i = 0; i < m_arBreaks.length(); i++) { ptGe = m_arBreaks.at(i).ptGe; dW = m_arBreaks.at(i).dW; m_pBaseCurve->getDistAtPoint(ptGe, dDis); dDis -= 0.5 * dW; m_pBaseCurve->getPointAtDist(dDis, ptGe); arPts.append(ptGe); dDis += dW; m_pBaseCurve->getPointAtDist(dDis, ptGe); arPts.append(ptGe); } AcDbRegion* pRegnCln = m_pRegion; double dAngle = 0.0; if (m_mapSpecXData.GetAt(KEY_ROTATION, dAngle)) { pRegnCln = (AcDbRegion*)m_pRegion->clone(); if (pRegnCln != NULL) { AcGeMatrix3d xformR; xformR.setToRotation(dAngle, AcGeVector3d::kZAxis); pRegnCln->transformBy(xformR); } } if (arPts.length() > 0) { AcDbVoidPtrArray arCurPtrs; m_pBaseCurve->getSplitCurves(arPts, arCurPtrs); AcDbCurve* pBaseCrv = NULL; AcDbEntity* p3dEnt = NULL; for (int j = 0; j < arCurPtrs.length(); j++) { pBaseCrv = (AcDbCurve*)arCurPtrs.at(j); p3dEnt = dc.DrawPipe(pBaseCrv, pRegnCln, ptCen); if (p3dEnt != NULL) { p3dEnt->setColorIndex(nColor); Add3DBuffer(p3dEnt); } DELETE_PTR(pBaseCrv); } } else { AecDb3dRoadAxisLine* pALn = AecDb3dRoadAxisLine::cast(m_pBaseCurve); if (pALn != NULL) { AcDbCurve* pCurve = NULL; AcDbEntity* p3dEnt = NULL; int nCount = pALn->GetCurveSegCount(); for (int ii = 0; ii < nCount; ii++) { pCurve = pALn->GetCurveSeg(ii); p3dEnt = dc.DrawPipe(pCurve, pRegnCln, ptCen); if (p3dEnt != NULL) { p3dEnt->setColorIndex(nColor); Add3DBuffer(p3dEnt); } } } else { AcDbEntity* p3dEnt = dc.DrawPipe(m_pBaseCurve, pRegnCln, ptCen); if (p3dEnt != NULL) { p3dEnt->setColorIndex(nColor); Add3DBuffer(p3dEnt); } } } //如果是旋转的REGION,则删除临时 if (pRegnCln != m_pRegion) { delete pRegnCln; } dc.SetLayer(idLay); dc.SetColor(nCrBk); return Acad::eOk; } double AecDbFlume::GetWidth() const { assertReadEnabled(); double v; m_mapSpecXData.GetAt(_W_, v); if (CoreTools::getFlume2DStyle() == 1) v += 2 * GetThick(); return v; } double AecDbFlume::GetHeight() const { assertReadEnabled(); double v; m_mapSpecXData.GetAt(_H_, v); if (CoreTools::getFlume2DStyle() == 1) v += GetThick(); return v; } bool AecDbFlume::SetWidth(const double &v) { AssertWriteEnabled(); return m_mapSpecXData.SetAt(_W_, v) == TRUE ? true : false; } bool AecDbFlume::SetHeight(const double &v) { AssertWriteEnabled(); return m_mapSpecXData.SetAt(_H_, v) == TRUE ? true : false; } bool AecDbFlume::GetSrcString(CString &src) { assertReadEnabled(); return m_mapSpecXData.GetAt(_T("_SRC_STRING_"), src) == 0 ? false : true; } void AecDbFlume::SetSrcString(LPCTSTR src) { assertWriteEnabled(); if (src && !CString(src).IsEmpty()) m_mapSpecXData.SetAt(_T("_SRC_STRING_"), src); } SHJson::WValue& AecDbFlume::ToJson(bool bExprotGeo) const { using namespace SHJson; return AecDbEwPipeBase::ToJson(); } bool AecDbFlume::ByJson(const SHJson::WValue &v) { AssertWriteEnabled(); return AecDbEwPipeBase::ByJson(v); }