#include "StdAfx.h" #include "resource.h" #include "OpeningRegul.h" #define CHOSEAXICS 0 #define CHOSEDK 1 template inline void LSWAP(TSwapType &data1, TSwapType &data2 ) { TSwapType dataDump = data1; data1 = data2; data2 = dataDump; } BOOL CWDRegualDlg::m_bDK1 = TRUE; BOOL CWDRegualDlg::m_bDK2 = TRUE; double CWDRegualDlg::m_dDK1 = 100; double CWDRegualDlg::m_dDK2 = 300; CString CWDRegualDlg::m_strDKTo2 = _T("120"); // 规整为xxx; BOOL CWDRegualDlg::m_bMid = TRUE; // 门窗居中 BOOL CWDRegualDlg::m_nAxis = CHOSEDK; // 单选按钮勾选轴线居中或者墙柱居中(TRUE:轴线居中) BOOL CWDRegualDlg::m_bMidDis = FALSE; BOOL CWDRegualDlg::m_bEdgeDis = FALSE; CString CWDRegualDlg::m_strMidDis = _T("1200"); CString CWDRegualDlg::m_strEdgeDis = _T("1200"); CWDRegualDlg::CWDRegualDlg(CWnd* pParent /*=NULL*/) : CModelessDialog(CWDRegualDlg::IDD, pParent) { //{{AFX_DATA_INIT(CWDRegualDlg) //}}AFX_DATA_INIT ResetChangCMD(); m_bInCmd = true; } CWDRegualDlg::~CWDRegualDlg() { m_bInCmd = false; } void CWDRegualDlg::DoDataExchange(CDataExchange* pDX) { CModelessDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CWDRegualDlg) DDX_Check(pDX, IDC_CHK_DK1, m_bDK1); DDX_Check(pDX, IDC_CHK_DK2, m_bDK2); DDX_Text(pDX, IDC_EDIT_DK1, m_dDK1); DDX_Text(pDX, IDC_EDIT_DK2, m_dDK2); DDX_CBString(pDX, IDC_CMB_DK2, m_strDKTo2); DDX_Radio(pDX, IDC_RADIO_AXIS, m_nAxis); DDX_Check(pDX, IDC_CHK_DW_MID, m_bMid); DDX_Check(pDX, IDC_CHK_EDGE_DIS, m_bEdgeDis); DDX_Check(pDX, IDC_CHK_MID_DIS, m_bMidDis); DDX_CBString(pDX, IDC_CMB_MID_DIS, m_strMidDis); DDX_CBString(pDX, IDC_CMB_EDGE_DIS, m_strEdgeDis); //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CWDRegualDlg, CModelessDialog) //{{AFX_MSG_MAP(CWDRegualDlg) ON_BN_CLICKED(IDC_CHK_DK1, OnBnClickCheckDK1) ON_BN_CLICKED(IDC_CHK_DK2, OnBnClickCheckDK2) ON_BN_CLICKED(IDC_CHK_DW_MID, OnBnClickCheckMid) ON_BN_CLICKED(IDC_CHK_MID_DIS, OnBnClickCheckMidDis) ON_BN_CLICKED(IDC_CHK_EDGE_DIS, OnBnClickCheckMidEdge) ON_BN_CLICKED(IDC_RADIO_AXIS, OnRadioClick) ON_BN_CLICKED(IDC_RADIO_WALL_EDGE, OnRadioClick) ON_WM_CLOSE() ON_WM_DESTROY() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CWDRegualDlg message handlers BOOL CWDRegualDlg::OnInitDialog() { // 根据当前的 CModelessDialog::OnInitDialog(); SetState(); static int s_nDKCmb2Ary[] = {0, 60, 100, 120, 180, 200, 240, 300, 360}; static int s_nMidDisAry[] = {1000, 1200, 1500, 2000}; static int s_nEdgeDisAry[] = {1000, 1200, 1500, 2000}; int i = 0; CComboBox *pCbo = (CComboBox*)GetDlgItem(IDC_CMB_DK2); if (pCbo != NULL) { pCbo->ResetContent(); for (i = 0; i < sizeof(s_nDKCmb2Ary)/sizeof(int); i++) { pCbo->AddString(XString(_T("%d"), s_nDKCmb2Ary[i])); } pCbo->SetWindowText(m_strDKTo2); } pCbo = (CComboBox*)GetDlgItem(IDC_CMB_MID_DIS); if (pCbo != NULL) { pCbo->ResetContent(); for (i = 0; i < sizeof(s_nMidDisAry)/sizeof(int); i++) { pCbo->AddString(XString(_T("%d"), s_nMidDisAry[i])); } pCbo->SetWindowText(m_strMidDis); } pCbo = (CComboBox*)GetDlgItem(IDC_CMB_EDGE_DIS); if (pCbo != NULL) { pCbo->ResetContent(); for (i = 0; i < sizeof(s_nEdgeDisAry)/sizeof(int); i++) { pCbo->AddString(XString(_T("%d"), s_nEdgeDisAry[i])); } pCbo->SetWindowText(m_strEdgeDis); } AddTip(IDC_CHK_MID_DIS, _T("此项参数只在同一墙段上存在多个门窗并进行居中移位时起作用")); AddTip(IDC_CHK_EDGE_DIS, _T("此项参数只在同一墙段上存在多个门窗并进行居中移位时起作用")); UpdateData(FALSE); return TRUE; } #define bMidOnly (m_bMid && !m_bDK1 && !m_bDK2) void CWDRegualDlg::SetState() { GetDlgItem(IDC_EDIT_DK1)->EnableWindow(m_bDK1); GetDlgItem(IDC_EDIT_DK2)->EnableWindow(m_bDK2); GetDlgItem(IDC_CMB_DK2)->EnableWindow(m_bDK2); GetDlgItem(IDC_RADIO_AXIS)->EnableWindow(m_bMid); GetDlgItem(IDC_RADIO_WALL_EDGE)->EnableWindow(m_bMid); GetDlgItem(IDC_CHK_MID_DIS)->EnableWindow(bMidOnly); GetDlgItem(IDC_CHK_EDGE_DIS)->EnableWindow(bMidOnly); GetDlgItem(IDC_CMB_MID_DIS)->EnableWindow(bMidOnly && m_bMidDis); GetDlgItem(IDC_CMB_EDGE_DIS)->EnableWindow(bMidOnly && m_bEdgeDis); } void CWDRegualDlg::OnClose() { CModelessDialog::OnClose(); if (m_bInCmd) { PostCommand(_T("\33")); } } void CWDRegualDlg::OnDestroy() { CModelessDialog::OnDestroy(); UpdateData(); // 把所有该记忆的数据取下来。 } void CWDRegualDlg::OnBnClickCheckDK1() { m_bDK1 = !m_bDK1; UpdateData(TRUE); // 把当前的数据取出来 SetState(); UpdateData(FALSE); } void CWDRegualDlg::OnBnClickCheckDK2() { m_bDK2 = !m_bDK2; UpdateData(TRUE); // 把当前的数据取出来 SetState(); UpdateData(FALSE); } // 选择是否居中 void CWDRegualDlg::OnBnClickCheckMid() { m_bMid = !m_bMid; UpdateData(TRUE); // 把当前的数据取出来 BOOL bOldMid = m_bMid; SetState(); UpdateData(FALSE); if (m_nAxis == CHOSEAXICS) { SetChangeCMD(); PostCommand(_T("\33")); } } void CWDRegualDlg::OnBnClickCheckMidDis() { m_bMidDis = !m_bMidDis; UpdateData(TRUE); // 把当前的数据取出来 if (m_bMidDis) m_bEdgeDis = FALSE; SetState(); UpdateData(FALSE); } void CWDRegualDlg::OnBnClickCheckMidEdge() { m_bEdgeDis = !m_bEdgeDis; UpdateData(TRUE); // 把当前的数据取出来 if (m_bEdgeDis) m_bMidDis = FALSE; SetState(); UpdateData(FALSE); } void CWDRegualDlg::OnRadioClick() { UpdateData(TRUE); SetChangeCMD(); PostCommand(_T("\33")); } bool CWDRegualDlg::IsNeedMidRegul() // 是否需要居中 { UpdateData(); return m_bMid ? true : false; } bool CWDRegualDlg::IsNeedDK1() // 是否剁宽1调整 { UpdateData(); return m_bDK1 ? true : false; } bool CWDRegualDlg::IsNeedDK2() // 是否剁宽2调整 { UpdateData(); return m_bDK2 ? true : false; } bool CWDRegualDlg::IsAxisMid() // 是否轴线居中,true:轴线居中,否则,墙柱边居中 { UpdateData(); return m_nAxis == CHOSEAXICS; } bool CWDRegualDlg::IsNeedMidDis() // 是否需要中距居中 { UpdateData(); return bMidOnly && m_bMidDis; } bool CWDRegualDlg::IsNeedEdgeDis() // 是否需要边距居中 { UpdateData(); return bMidOnly && m_bEdgeDis; } double CWDRegualDlg::GetDK1() // 剁宽1的范围 { UpdateData(); return (m_dDK1 > 0) ? m_dDK1 : 0.0; } double CWDRegualDlg::GetDK2() // 剁宽2的方位 { UpdateData(); return (m_dDK2 > 0) ? m_dDK2 : 0.0; } double CWDRegualDlg::GetDK2To() // 剁宽2调整的值 { UpdateData(); double dValue = _tstof(m_strDKTo2); return (dValue > 0) ? dValue : 0; } double CWDRegualDlg::GetMidDis() // 中距 { UpdateData(); double dValue = _tstof(m_strMidDis); return (dValue > 0) ? dValue : 0; } double CWDRegualDlg::GetEdgeDis() // 边距 { UpdateData(); double dValue = _tstof(m_strEdgeDis); return (dValue > 0) ? dValue : 0; } ////////////////////////////////////////////////////////////////////////// // 算法处理 class SOpeningRegulStruct { public: TDbWall *pWall; XPoint ptExtents[2]; // 居中的两端位置 void RemoveOpeningAt(int i); void RemoveOpeningAll(); void close(); BOOL IsEmpty() const {return (aryOpening.GetSize()== 0) || (pWall == NULL);} CArray aryOpening; public: // sg add 111018,给所有本类内部的成员设置打开方式,只读或者可写 // 主要是解决04环境下,使用SSGET时候的崩溃问题,临时改成读打开 // bUpgrade为TRUE时,表示读变成写,否则为写变成读 void SetAllOpeningAndWallOpenMode(BOOL bUpgrade); }; void SOpeningRegulStruct::close() { for (int i = 0; i < (int)aryOpening.GetSize(); i++) aryOpening[i]->close(); if (pWall != NULL) pWall->close(); } void SOpeningRegulStruct::RemoveOpeningAt(int i) { aryOpening[i]->close(); aryOpening.RemoveAt(i); } void SOpeningRegulStruct::RemoveOpeningAll() { for (int i = 0; i < aryOpening.GetSize(); i++) aryOpening[i]->close(); aryOpening.RemoveAll(); } // sg add 111018,给所有本类内部的成员设置打开方式,只读或者可写 void SOpeningRegulStruct::SetAllOpeningAndWallOpenMode(BOOL bUpgrade) { if (bUpgrade) // 读变成写 { pWall->upgradeOpen(); for (int i = 0; i < aryOpening.GetSize(); i++) { aryOpening[i]->upgradeOpen(); } } else //写变成读 { pWall->downgradeOpen(); for (int i = 0; i < aryOpening.GetSize(); i++) { aryOpening[i]->downgradeOpen(); } } } // 将该Ary做为一个类型,可以控制内存的释放和实体的关闭。省却了在各个分支中处理释放和关闭的麻烦 class AryOpeningRegualStruct { public: // 需要可以自动释放内存 ~AryOpeningRegualStruct(); // 需要自动把内存给释放了。同时还要引发对象释放 int GetSize() {return (int)aryOpeningStruct.GetSize();} SOpeningRegulStruct* operator [] (int i) {return aryOpeningStruct[i];} void Add(SOpeningRegulStruct* psr) {aryOpeningStruct.Add(psr);} void RemoveAt(int i); BOOL IsEmpty() const {return aryOpeningStruct.GetSize()== 0;} CArray aryOpeningStruct; }; void AryOpeningRegualStruct::RemoveAt(int i) { aryOpeningStruct[i]->close(); delete aryOpeningStruct[i]; aryOpeningStruct.RemoveAt((INT_PTR)i); } AryOpeningRegualStruct::~AryOpeningRegualStruct() { for (int i = 0; i < (int)aryOpeningStruct.GetSize(); i++) { aryOpeningStruct[i]->close(); delete aryOpeningStruct[i]; } aryOpeningStruct.RemoveAll(); } void GetSidePointOnCurve(TDbOpening *pOp1, const TGGeCurveSegment &curveSeg, XPoint &pt1, XPoint &pt2) { XPoint _pt1, _pt2; pOp1->GetSidePoints(_pt1, _pt2); curveSeg.ProjectToMe(_pt1, pt1); curveSeg.ProjectToMe(_pt2, pt2); } XPoint GetProjectPoint(const XPoint &ptSrc, const TGGeCurveSegment &curveSeg) { XPoint ptTemp; curveSeg.ProjectToMe(ptSrc, ptTemp); return ptTemp; } // 把ss的内容做成结构体填充到aryOpeningRegulStruct中去。 void PickSetToRegualStruct(TPickEntSet &ss, AryOpeningRegualStruct &aryOpeningRegulStruct) { AcDbObjectIdArray idAry; ss.AsIdArray(idAry); for (int i = 0; i < (int)idAry.length(); i++) { AcDbEntity *pEntTmp = NULL; if (acdbOpenAcDbEntity(pEntTmp, idAry[i], AcDb::kForWrite) == Acad::eOk) { if (pEntTmp == NULL) continue; TDbOpening *pOpening = TDbOpening::cast(pEntTmp); if (pOpening == NULL) continue; pOpening->assertWriteEnabled(); AcDbObjectId wallid = pOpening->GetWallId(); for (int j = 0; j < (int)aryOpeningRegulStruct.GetSize(); j++) { if (wallid == aryOpeningRegulStruct[j]->pWall->id()) { aryOpeningRegulStruct[j]->aryOpening.Add(pOpening); break; } } if (j == (int)aryOpeningRegulStruct.GetSize()) { if (acdbOpenAcDbEntity(pEntTmp, wallid, AcDb::kForWrite) == Acad::eOk) { TDbWall *pWall = TDbWall::cast(pEntTmp); if (pWall != NULL) { pWall->assertWriteEnabled(); SOpeningRegulStruct *pNewSOR = new SOpeningRegulStruct; pNewSOR->pWall = pWall; pNewSOR->aryOpening.Add(pOpening); aryOpeningRegulStruct.Add(pNewSOR); } } else { pOpening->close(); // 有开有关。 } } } } } // 墙起点剁宽点(投影到基线) XPoint GetWallDKStartPoint(TDbWall *pWall) { // 取长基线, TGGeCurveSegment wallBaseCurve(*pWall); TGGeCurveSegment lCurve, rCurve; pWall->GetSideCurve(lCurve, rCurve); double d1 = 0.0; double d2 = wallBaseCurve.PathDistance(lCurve.StartPoint()); double d3 = wallBaseCurve.PathDistance(rCurve.StartPoint()); TGGeCurveSegment curveRes = wallBaseCurve; if (d1 < d2) LSWAP(curveRes, lCurve),LSWAP(d1, d2); if (d1 < d3) LSWAP(curveRes, rCurve), LSWAP(d1, d3); TADSGePoint3d ptRes; wallBaseCurve.ProjectToMe(curveRes.StartPoint(), ptRes); return ptRes; } // 墙终点剁宽点,(投影到基线上) XPoint GetWallDkEndPoint(TDbWall *pWall) { // 取长基线, TGGeCurveSegment wallBaseCurve(*pWall); TGGeCurveSegment lCurve, rCurve; pWall->GetSideCurve(lCurve, rCurve); double d1 = 0.0; double d2 = wallBaseCurve.PathDistance(lCurve.EndPoint(), FALSE); double d3 = wallBaseCurve.PathDistance(rCurve.EndPoint(), FALSE); TGGeCurveSegment curveRes = wallBaseCurve; if (d1 < d2) LSWAP(curveRes, lCurve),LSWAP(d1, d2); if (d1 < d3) LSWAP(curveRes, rCurve), LSWAP(d1, d3); TADSGePoint3d ptRes; wallBaseCurve.ProjectToMe(curveRes.EndPoint(), ptRes); return ptRes; } // 支持任意类型的轴线和任意类型的门窗,搜索包围门窗的轴线,把轴线跟墙体的交点填充到ptExtents中 // 该函数的正确性需要检测 void GetFillAxisofOpenings(SOpeningRegulStruct &sors) { TGGeCurveSegment wallBaseCurve = sors.pWall->GetLongBaseLine(); // 取墙有延伸的 TGGePoly2D poly; wallBaseCurve.AsPoly2D(poly); TGGePoly poly1; poly.MapToPolygon(poly1); // 在这堆门窗中找出最近的最靠边的两个点 XPoint ptMinDis, ptMaxDis; // 门窗中提供的函数,因不明原因不好使,采用该函数做投影 GetSidePointOnCurve(sors.aryOpening[0], *sors.pWall, ptMinDis, ptMaxDis); double dMinDis = wallBaseCurve.PathDistance(ptMinDis); double dMaxDis = wallBaseCurve.PathDistance(ptMaxDis); // 这两个没关系。 if (dMinDis > dMaxDis) { LSWAP(ptMaxDis, ptMinDis); LSWAP(dMinDis, dMaxDis); } for (long i = 1; i < sors.aryOpening.GetSize(); i++) { XPoint pt1, pt2; sors.aryOpening[i]->GetSidePointsOnBase(pt1, pt2); GetSidePointOnCurve(sors.aryOpening[i], *sors.pWall, pt1, pt2); double dDis1 = wallBaseCurve.PathDistance(pt1); double dDis2 = wallBaseCurve.PathDistance(pt2); if (dDis1 < dMinDis) { ptMinDis = pt1; dMinDis = dDis1; } if (dDis2 < dMinDis) { ptMinDis = pt2; dMinDis = dDis2; } if (dDis1 > dMaxDis) { ptMaxDis = pt1; dMaxDis = dDis1; } if (dDis2 > dMaxDis) { ptMaxDis = pt2; dMaxDis = dDis2; } } // // sg add 111018,临时将所有的门窗、墙对象读打开 sors.SetAllOpeningAndWallOpenMode(FALSE); // 取到轴线 TPickEntSet ss(SS_FREE); ss.Get(_T("F"), TRBList(poly1.Fence()), NULL, TRBList(RTDXF0, _T("LINE,ARC,CIRCLE"), 8, LAY_AXIS, NULL)); // sg add 111018,临时将所有的门窗、墙对象恢复可写 sors.SetAllOpeningAndWallOpenMode(TRUE); // 计算轴线和门窗的交点,并且查找这些交点中最靠谱的 const double dWallLen = wallBaseCurve.GetLength(); XPoint ptMinAxis, ptMaxAxis; // 这个没法做初始化 double dMinAxis = -1.0, dMaxAxis = dWallLen + 1.0; bool bFindFirst = false; for (i = 0; i < ss.Length(); i++) { ads_point ptInter, pt2; int nInterNum = wallBaseCurve.Intersection(TGGeCurveSegment(ss[i], LS_FINITE), ptInter, pt2); if (nInterNum == 0 || nInterNum == 2) continue; double dDis = wallBaseCurve.PathDistance(ptInter); if ( dDis < 0 || dDis > dWallLen ) continue; if (dDis < dMinDis && dDis > dMinAxis) { dMinAxis = dDis; ptMinAxis = ptInter; } else if (dDis > dMaxDis && dDis < dMaxAxis) { dMaxAxis = dDis; ptMaxAxis = ptInter; } } // 找完之后还要比较一下,是不是真的 if (dMinAxis < 0.0) { ptMinAxis = sors.pWall->StartPoint(); } if (dMaxAxis > dWallLen) { ptMaxAxis = sors.pWall->EndPoint(); } sors.ptExtents[0] = XPoint(ptMinAxis); sors.ptExtents[1] = XPoint(ptMaxAxis); } // 门窗排序函数 static TDbWall *s_pWallForSort = NULL; int OpeningSortCMP(const void *ppOpening1, const void *ppOpening2) { TDbOpening *pOpening1 = (TDbOpening*)(*((TDbOpening**)ppOpening1)); TDbOpening *pOpening2 = (TDbOpening*)(*((TDbOpening**)ppOpening2)); double d1 = s_pWallForSort->PathDistance(pOpening1->GetLocation()); double d2 = s_pWallForSort->PathDistance(pOpening2->GetLocation()); if (fabs(d1-d2) < 1e-6) return 0; else return d1 < d2 ? -1 : 1; } // 按照pWall的走向,对aryOpening进行排序。(aryOpening需要在墙上) void SortDoorWin(TDbWall *pWall, CArray &aryOpening) { s_pWallForSort = pWall; qsort(aryOpening.GetData(), aryOpening.GetSize(), sizeof(TDbOpening*), OpeningSortCMP); s_pWallForSort = NULL; } // 判断门窗是否可以插入墙体。 // 需要保证: // 1、门窗不在墙体内, // 2、门窗插入位置不合其他门窗重合,或者二者在标高上可以错开 bool CanInsertOpening(TDbWall* pWall, TDbOpening *pOpening) { #define LessEqual(d1, d2) (fabs(d1 - d2) < 1e-6 || d1 < d2) // 取得墙的短基线: TGGeCurveSegment wallShortBasecurve(*pWall); wallShortBasecurve.SetPoints(GetWallDKStartPoint(pWall), GetWallDkEndPoint(pWall)); // 判断门窗是否在墙基线之内:(没有超出起点和终点的范围) double dWallLen = wallShortBasecurve.GetLength(); XPoint ptTemp1, ptTemp2, ptSide1, ptSide2; pOpening->GetSidePoints(ptSide1, ptSide2); wallShortBasecurve.ProjectToMe(ptSide1, ptTemp1); wallShortBasecurve.ProjectToMe(ptSide2, ptTemp2); double d1 = wallShortBasecurve.PathDistance(ptTemp1); // if (d1 < 0.0 || d1 > dWallLen) if (!LessEqual(0.0, d1) || !LessEqual(d1, dWallLen)) return false; double d2 = wallShortBasecurve.PathDistance(ptTemp2); // if (d2 < 0.0 || d2 > dWallLen) if (!LessEqual(0.0, d2) || !LessEqual(d2, dWallLen)) return false; // 判断和墙内任意门窗不相交,或者二者标高有差距: // TDPtrList lstOpening; // pWall->GetOpenings(lstOpening, FALSE); const TDPtrList &lstOpening = pWall->GetOpeningIdList(); for (int i = 0; i < (int)lstOpening.Length(); i++) { TOpeningData *pData = NULL; OPENOBJ_BEGIN(lstOpening[i], AcDb::kForRead, TDbOpening, pOp) { if (pOp != NULL) pData = pOp; else continue; } OPENOBJ_END() pData->GetSidePoints(ptSide1, ptSide2); wallShortBasecurve.ProjectToMe(ptSide1, ptTemp1); wallShortBasecurve.ProjectToMe(ptSide2, ptTemp2); double dTemp1 = wallShortBasecurve.PathDistance(ptTemp1); double dTemp2 = wallShortBasecurve.PathDistance(ptTemp2); if (LessEqual(d1, dTemp1) && LessEqual(d1, dTemp2) && LessEqual(d2, dTemp1) && LessEqual(d2, dTemp2)) continue; else if (LessEqual(dTemp1, d1) && LessEqual(dTemp2, d1) && LessEqual(dTemp1, d2) && LessEqual(dTemp2, d2)) continue; else { // 初步认定两者重合了。需要比较它们的标高,如何还有重合,它们就XX了。 double dEle = pOpening->GetElevation(); double dHeiEle = dEle + pOpening->GetHeight(); double dEleTemp = pData->GetElevation(); double dHeiEleTemp = dEle + pData->GetHeight(); if (LessEqual(dEle, dEleTemp) && LessEqual(dEle, dHeiEleTemp) && LessEqual(dHeiEle, dEleTemp) && LessEqual(dHeiEle, dHeiEleTemp)) continue; else if (LessEqual(dEleTemp, dEle) && LessEqual(dHeiEleTemp, dEle) && LessEqual(dEleTemp, dHeiEle) && LessEqual(dHeiEleTemp, dHeiEle)) continue; else return false; } } return true; } // 从墙中删除该ID void RemoveDoorWinIdFromWall(TDbWall *pWall, AcDbObjectId id) { // 这个函数不知道是否会好使。 pWall->RemoveReferenceOpening(id); } // 删除墙中aryOpening中的ID void RemoveDoorWinsFromWall(TDbWall *pWall, CArray &aryOpening) { for (int i = 0; i < (int)aryOpening.GetSize(); i++) { RemoveDoorWinIdFromWall(pWall, aryOpening[i]->id()); } } enum EHitCurvePoint{ eHitUp = 1, eHitDown = 2, eHitStartPoint = 3, eHitEndPoint = 4, eHitKO = 5, eHitLineStart = 6, eHitLineEnd = 7, eHitArcStart = 7, eHitArcEnd = 6, }; // dis可以为负,要求ptStart在curveSeg中,否则结果未知 XPoint GetPolarPoint(const TGGeCurveSegment &curveSeg, const XPoint &_ptStart, double dDis) { XPoint ptStart = GetProjectPoint(_ptStart, curveSeg); TADSGePointDir2d dir2d; if (ptStart.Distance2d(curveSeg.StartPoint()) < 1e-6) curveSeg.Polar(dDis, dir2d); else if (ptStart.Distance2d(curveSeg.EndPoint()) < 1e-6) curveSeg.Polar(-dDis, dir2d, FALSE); else { TGGeCurveSegment seg = curveSeg; seg.SetPoints(ptStart, curveSeg.EndPoint()); seg.Polar(dDis, dir2d); } return dir2d; } // 计算中距居中下,门窗的新位置,pSors中门窗有序!! // dMidDis:中距, // aryDoorWinPosNew, 返回的结果点,aryDoorWinPosOld,保存的原门窗点。 void CalcNewPos(SOpeningRegulStruct *pSors, double dMidDis, CArray &aryDoorWinPosNew, CArray &aryDoorWinPosOld) { int index = 0; // 调整之后门窗的总长度 double dAllLen = 0.0; for (index = 0; index < (int)pSors->aryOpening.GetSize(); index++) { dAllLen += pSors->aryOpening[index]->GetWidth(); // 这个函数要跟踪检查一下 } dAllLen += ((pSors->aryOpening.GetSize()-1)*dMidDis); // 在添加间距 // 3、起始门窗的位移: TGGeCurveSegment wallLongBaseCurve(pSors->pWall->GetLongBaseLine()); // 墙体的长基线 TGGeCurveSegment curveTemp = wallLongBaseCurve; curveTemp.SetPoints(pSors->ptExtents[0], pSors->ptExtents[1]); double dWallLen = curveTemp.GetLength(); double dStartOff = (dWallLen - dAllLen)*0.5; // 起始点的位移。 // 4、根据起始门窗的位置计算所有门窗的位置,暂不设置门窗的位置。因为还需要判断该位置是否合理 aryDoorWinPosNew.SetSize(pSors->aryOpening.GetSize()); aryDoorWinPosOld.SetSize(pSors->aryOpening.GetSize()); double dNextStartLen = dStartOff; curveTemp.SetPoints(pSors->ptExtents[0], pSors->ptExtents[1]); TGGeCurveSegment wallMidSeg = pSors->pWall->OffsetGeomCenter(LS_INFINITE, TRUE); for (index = 0; index < (int)aryDoorWinPosNew.GetSize(); index++) { aryDoorWinPosOld[index] = pSors->aryOpening[index]->GetLocation(); double dDoorLen = pSors->aryOpening[index]->GetWidth(); XPoint ptTemp = GetPolarPoint(curveTemp, pSors->ptExtents[0], dNextStartLen + dDoorLen*0.5); wallMidSeg.ProjectToMe(ptTemp, aryDoorWinPosNew[index]); aryDoorWinPosNew[index].z = aryDoorWinPosOld[index].z; // 设置它的标高。 dNextStartLen += (dDoorLen + dMidDis); } } // 关闭一个实体,并且返回它的ID AcDbObjectId LCloseEnt(AcDbEntity *pEnt) { AcDbObjectId id = pEnt->id(); pEnt->close(); return id; } // 重新打开一个实体,没有实体指针的返回,该指针仍旧由旧指针保存 void LReOpenEnt(AcDbObjectId id, AcDb::OpenMode mode = AcDb::kForWrite) { AcDbEntity *pEnt; acdbOpenAcDbEntity(pEnt, id, mode); // 只是打开它,不记录。外边有指针等着呢 } bool SetOpeningPosAndAdd(TDbWall *pWall, TDbOpening *pOpening, const XPoint &posNew, const XPoint &posOld) { pOpening->SetLocation(posNew); if (CanInsertOpening(pWall, pOpening)) { // AcDbObjectId idWall = LCloseEnt(pWall); // pOpening->SetWallId(idWall); pOpening->SetWallId(pWall->id()); XPoint pOldLabelPos = pOpening->GetLabelPos(); pOpening->SetLabelPos(pOldLabelPos + posNew - posOld); // LReOpenEnt(idWall); pOpening->SetThickness(pWall->GetWidth()); pWall->InsertOpening(pOpening); return true; } return false; } bool SetNewPoint(SOpeningRegulStruct *pSors, CArray &aryDoorWinPosNew, CArray &aryDoorWinPosOld) { int index = 0; // 判断新的门窗位置是否合理,并且添加 RemoveDoorWinsFromWall(pSors->pWall, pSors->aryOpening); // for (index = 0; index < (int)pSors->aryOpening.GetSize(); index++) { pSors->aryOpening[index]->SetLocation(aryDoorWinPosNew[index]); if (!CanInsertOpening(pSors->pWall, (pSors->aryOpening[index]))) break; } if (index < pSors->aryOpening.GetSize()) { // 不能添加 for (index = 0; index < (int)pSors->aryOpening.GetSize(); index++) { // 统一在添加一遍 // AcDbObjectId idWall = LCloseEnt(pSors->pWall); // pSors->aryOpening[index]->SetWallId(idWall); pSors->aryOpening[index]->SetWallId(pSors->pWall->id()); pSors->aryOpening[index]->SetLocation(aryDoorWinPosOld[index]); // LReOpenEnt(idWall); pSors->aryOpening[index]->SetThickness(pSors->pWall->GetWidth()); pSors->pWall->AddOpeningId(pSors->aryOpening[index]->id()); } return false; } else { for (index = 0; index < (int)pSors->aryOpening.GetSize(); index++) { // 统一在添加一遍 SetOpeningPosAndAdd(pSors->pWall, pSors->aryOpening[index], aryDoorWinPosNew[index], aryDoorWinPosOld[index]); } return true; } } bool WallDKAdjust(SOpeningRegulStruct *pSors, double DK, double DKTo) { // 1、取得墙体剁宽起点,和墙体剁宽终点 TADSGePoint3d ptStart = GetWallDKStartPoint(pSors->pWall); TADSGePoint3d ptEnd = GetWallDkEndPoint(pSors->pWall); TGGeCurveSegment wallMidSeg = pSors->pWall->OffsetGeomCenter(LS_INFINITE, TRUE); TADSGePointDir2d ptTemp, ptTemp2; TGGeCurveSegment curveTemp1 = wallMidSeg; ptStart = GetProjectPoint(ptStart, wallMidSeg); ptEnd = GetProjectPoint(ptEnd, wallMidSeg); ptStart.z = 0.0; ptEnd.z = 0.0; // 要规整为统一标高,去计算距离。 // 2、遍历门窗,判断门窗是否在该剁宽1范围内,如果在范围之内,则调整,调整之后从列表中删除 for (int i = 0; i < (int)pSors->aryOpening.GetSize(); i++) { TDbOpening *pOpening = pSors->aryOpening[i]; XPoint pt1, pt2; pOpening->GetSidePoints(pt1, pt2); pt1 = GetProjectPoint(pt1, wallMidSeg); pt2 = GetProjectPoint(pt2, wallMidSeg); pt1.z = 0.0; pt2.z = .0; // // 计算门窗的两端点跟墙起点和终点的距离,如果小于剁宽,则执行 curveTemp1 = wallMidSeg; curveTemp1.SetPoints(ptStart, pt1); double d1 = curveTemp1.GetLength(); curveTemp1 = wallMidSeg; curveTemp1.SetPoints(ptStart, pt2); double d2 = curveTemp1.GetLength(); TGGeCurveSegment curveTemp3; curveTemp3 = wallMidSeg; curveTemp3.SetPoints(pt1, ptEnd); double d3 = curveTemp3.GetLength(); curveTemp3 = wallMidSeg; curveTemp3.SetPoints(pt2, ptEnd); double d4 = curveTemp3.GetLength(); double dm1 = d1 < d2 ? d1 : d2; double dm3 = d3 < d4 ? d3 : d4; // if (d1 < DK || d2 < DK) if (dm1 < dm3 && dm1 < DK) { // 执行起始端的归零操作。 curveTemp1.Polar(pOpening->GetWidth() * 0.5 + DKTo, ptTemp); *((TADSGePoint3d*)(&ptTemp2)) = pOpening->GetLocation(); ptTemp.z = ptTemp2.z; pOpening->SetLocation(ptTemp); RemoveDoorWinIdFromWall(pSors->pWall, pOpening->id()); if (CanInsertOpening(pSors->pWall, pOpening)) { SetOpeningPosAndAdd(pSors->pWall, pOpening, ptTemp, ptTemp2); // pSors->RemoveOpeningAt(i--); } else { // 如果不能插入仍旧插入原先的数据 pOpening->SetWallId(pSors->pWall->id()); pOpening->SetLocation(ptTemp2); pOpening->SetThickness(pSors->pWall->GetWidth()); pSors->pWall->InsertOpening(pOpening); return false; } } else if (dm3 < DK) { // 判断跟终点是否可以处理一下 // curveTemp1 = wallMidSeg; // curveTemp1.SetPoints(pt1, ptEnd); // double d3 = curveTemp1.GetLength(); // curveTemp1 = wallMidSeg; // curveTemp1.SetPoints(pt2, ptEnd); // double d4 = curveTemp1.GetLength(); curveTemp1 = curveTemp3; // if (d3 < DK || d4 < DK) { //wlw add 14.07.22算法有问题 curveTemp1.Polar(pOpening->GetWidth() * 0.5 + DKTo, ptTemp, FALSE); *((TADSGePoint3d*)(&ptTemp2)) = pOpening->GetLocation(); ptTemp.z = ptTemp2.z; pOpening->SetLocation(ptTemp); RemoveDoorWinIdFromWall(pSors->pWall, pOpening->id()); if (CanInsertOpening(pSors->pWall, pOpening)) { SetOpeningPosAndAdd(pSors->pWall, pOpening, ptTemp, ptTemp2); pSors->RemoveOpeningAt(i--); } else { // AcDbObjectId idWall = LCloseEnt(pSors->pWall); // pOpening->SetWallId(idWall); pOpening->SetWallId(pSors->pWall->id()); pOpening->SetLocation(ptTemp2); // LReOpenEnt(idWall); pOpening->SetThickness(pSors->pWall->GetWidth()); pSors->pWall->InsertOpening(pOpening); return false; } } } } return true; } void LLRegulTest() { CString strPrompt = _T("\n第一根轴线: "); TEntitySet ssEnt1, ssEnt2; int bRet = SelectEntity(strPrompt, ssEnt1, TRBList(RTDXF0, _T("LINE,ARC"), 8, LAY_AXIS, NULL)); if (bRet != RTNORM && bRet != RTNONE) return; TGGeCurveSegment curveSegAxis(ssEnt1); // ads_point ptres; // ads_getpoint(NULL, _T("\n输入一个点吧: "), ptres); // // XPoint ptCur(ptres); ads_real dreal1 = 0.0; ads_getreal(_T("\n输入一个real值吧: "), &dreal1); BOOL bStart = false; ads_getint(_T("\n是否从起点开始: "), &bStart); TADSGePointDir2d dir2d; // TGGeLine line(ptCur, GetPolarPoint(curveSegAxis, ptCur, dreal1)); curveSegAxis.Polar(dreal1, dir2d, bStart); TGGeLine line(bStart ? curveSegAxis.StartPoint() : curveSegAxis.EndPoint() , dir2d); line.Make(); } // 门窗规整 void WDRegul() { // LLRegulTest(); // 启动这个对话框 CWDRegualDlg dlg; { CAcModuleResourceOverride vTemp; dlg.Create(CWDRegualDlg::IDD, acedGetAcadFrame()); } dlg.ShowWindow(SW_SHOW); // 运行逻辑: int nStep = 0; // 记录步骤,如果需要回退的话,则根据该数据引发回退 #define BACKCMD \ { \ if (nStep > 0) \ ads_command(RTSTR, _T("UNDO"), RTSTR, _T("BACK"), RTNONE); \ nStep--; \ } while (true) { // 该循环一直在运行 if (!IsWindow(dlg.m_hWnd)) break; // dlg.UpdateData(TRUE); // 在下边即将要调用对话框中的数据之前,需要先更新一下对话框中的数据。 AryOpeningRegualStruct *paryStructRegul = new AryOpeningRegualStruct; AryOpeningRegualStruct &aryOpeningRegul = *paryStructRegul; if (dlg.IsNeedMidRegul() && dlg.IsAxisMid()) { // TPickEntSet ss; CString strPrompt, strKey; if (nStep == 0) { strPrompt = _T("\n请选择需归整的门窗或[指定参考轴线(S)]<退出>: "); strKey = _T("S"); } else { strPrompt = _T("\n请选择需归整的门窗或[指定参考轴线(S)/回退(U)]<退出>: "); strKey = _T("S U"); } TCHAR chDumpRet; int bRet = (SelectEntitiesOnce(strPrompt, ss, TRBList(RTDXF0, _T("TCH_OPENING"), NULL), strKey, chDumpRet) ); if (bRet != RTNORM && bRet != RTKWORD && bRet != RTERROR && !dlg.IfChangCMD()) break; // 退出 if (dlg.IfChangCMD() || bRet == RTERROR) { dlg.ResetChangCMD(); continue; } if (bRet == RTNORM) { // 执行了正常的选择: // 门窗分组, PickSetToRegualStruct(ss, aryOpeningRegul); // 按墙线分组的每组门窗中找出他们的两边的轴线 for (long i = 0; i < (long)aryOpeningRegul.GetSize(); i++) { GetFillAxisofOpenings(*(aryOpeningRegul[i])); } // 获得了包围他们的点 } else if (bRet == RTKWORD) { if (chDumpRet == _T('U')) { // 这里需要执行回退 BACKCMD continue; } else if (chDumpRet == _T('S')) { // 选轴线,根据选择的轴线搜索门窗,然后门窗分组,填充轴线跟门窗的交点到结构体中 TGGePoly2D poly; CString strPrompt = _T("\n第一根轴线: "); TEntitySet ssEnt1, ssEnt2; int bRet = SelectEntity(strPrompt, ssEnt1, TRBList(RTDXF0, _T("LINE,ARC"), 8, LAY_AXIS, NULL)); if (bRet != RTNORM && bRet != RTNONE && !dlg.IfChangCMD()) break; // 退出 if (dlg.IfChangCMD() || bRet == RTNONE ) { dlg.ResetChangCMD(); continue; } if (bRet == RTNORM) { // 执行了正常的选择: TGGeCurveSegment segDump(ssEnt1); poly.AppendNode(segDump.StartPoint(), segDump.GetBulge()); poly.AppendNode(segDump.EndPoint(), 0); } strPrompt = _T("\n第二根轴线: "); bRet = SelectEntity(strPrompt, ssEnt2, TRBList(RTDXF0, _T("LINE,ARC"), 8, LAY_AXIS, NULL)); if (bRet != RTNORM && bRet != RTNONE && !dlg.IfChangCMD()) break; // 退出 if (dlg.IfChangCMD() || bRet == RTNONE ) { dlg.ResetChangCMD(); continue; } if (bRet == RTNORM) { // 执行了正常的选择: TGGeCurveSegment segTemp(ssEnt2); poly.AppendNode(segTemp.EndPoint(), -segTemp.GetBulge()); poly.AppendNode(segTemp.StartPoint(), 0); poly.SetClosed(); // poly.Make(); } if (poly.IsSelfIntersect()) continue; // 区域自交了。 TPickEntSet ssp(SS_FREE); ads_point lowPt, upPt; poly.GetExtend(lowPt, upPt); ssp.Get(_T("C"), lowPt, upPt, RBList(RTDXF0, _T("TCH_OPENING"), NULL)); // 还需要使用poly进行过滤,紧紧保留在该poly范围内的 long i = 0; for (i = 0; i < (long)ssp.Length(); i++) { OPENOBJ_BEGIN(TEntitySet(ssp[i]), AcDb::kForRead, TDbOpening, pEnt) { XPoint ptBack, ptFront; pEnt->GetSidePoints(ptBack, ptFront); //取得门窗的边界点 ptBack.z = 0.0; ptFront.z = 0.0; int nRet1 = (ptBack & poly); int nRet2 = (ptFront & poly); if ((nRet1 != PR_INSIDE) || (nRet2 != PR_INSIDE)) ssp -= ssp[i--]; } OPENOBJ_END() } // 分类。 PickSetToRegualStruct(ssp, aryOpeningRegul); // 规整,去除根当前轴线没有交点的,而有交点的则把交点填充在结构体中。 for (i = 0; i < (long)aryOpeningRegul.GetSize(); i++) { TGGeCurveSegment axisCurve1(ssEnt1), axisCurve2(ssEnt2); // 轴线, // 墙线需要跟轴线有交点 ads_point pt2; TGGeCurveSegment wallCurve(*(aryOpeningRegul[i]->pWall)); wallCurve.SetLineFlag(LS_INFINITE); // 墙可以设置延长 int nRet = wallCurve.Intersection(axisCurve1, aryOpeningRegul[i]->ptExtents[0], pt2); if (nRet == 0 || nRet == 2) { aryOpeningRegul.RemoveAt(i--); continue; } nRet = wallCurve.Intersection(axisCurve2, aryOpeningRegul[i]->ptExtents[1], pt2); if (nRet == 0 || nRet == 2) { aryOpeningRegul.RemoveAt(i--); continue; } } } } } else { // 直接选择门窗,门窗分组,如果勾选了墙体居中 TPickEntSet ss; CString strPrompt, strKey; if (nStep == 0) { strPrompt = _T("\n请选择需归整的门窗<退出>: "); strKey = _T(""); } else { strPrompt = _T("\n请选择需归整的门窗或[回退(U)]<退出>: "); strKey = _T("U"); } TCHAR chDumpRet; int bRet = (SelectEntitiesOnce(strPrompt, ss, TRBList(RTDXF0, _T("TCH_OPENING"), NULL), strKey, chDumpRet) ); if (bRet != RTNORM && bRet != RTKWORD && bRet != RTERROR && !dlg.IfChangCMD()) break; // 退出 if (dlg.IfChangCMD() || bRet == RTERROR) { dlg.ResetChangCMD(); continue; } if (bRet == RTNORM) { // 执行了正常的选择: PickSetToRegualStruct(ss, aryOpeningRegul); if (dlg.IsNeedMidRegul() && !dlg.IsAxisMid()) { // 找每段墙两端的多起点和终点,设置为居中的起点和终点 for (long i = 0; i < (long)aryOpeningRegul.GetSize(); i++) { aryOpeningRegul[i]->ptExtents[0] = GetWallDKStartPoint(aryOpeningRegul[i]->pWall); aryOpeningRegul[i]->ptExtents[1] = GetWallDkEndPoint(aryOpeningRegul[i]->pWall); } } } else if (bRet == RTKWORD) { // 只有一个回退关键字。 BACKCMD // if (nStep > 0) // { // int nRet = ads_command(RTSTR, _T("UNDO"), RTSTR, _T("BACK"), RTNONE); // ASSERT(nRet == RTNORM); // nStep--; // } continue; } } ads_command(RTSTR, _T("UNDO"), RTSTR, _T("MARK"), RTNONE); // 处理选择的结果:aryOpeningRegul, // 处理的算法: // 1、先判断是否要做剁宽1规整,2,判断是否要进行剁宽2规整,3,判断是否要进行居中调整 for (long iRegulIndex = 0; iRegulIndex < (int)aryOpeningRegul.GetSize(); iRegulIndex++) { SOpeningRegulStruct *pSors = aryOpeningRegul[iRegulIndex]; // 排序 n SortDoorWin(pSors->pWall, pSors->aryOpening); if (dlg.IsNeedDK1() && !pSors->IsEmpty()) { // 要根据剁宽1调整 if (!WallDKAdjust(pSors, dlg.GetDK1(), 0.0)) { // 要退出本墙上门窗的规整,并且打印提示信息 break; } } if (dlg.IsNeedDK2() && !pSors->IsEmpty()) { // 要根据剁宽2调整 if (!WallDKAdjust(pSors, dlg.GetDK2(), dlg.GetDK2To())) { break; } } if (dlg.IsNeedMidRegul() && !pSors->IsEmpty()) { // 要进行居中调整 if (dlg.IsNeedMidDis()) {// 勾选了中距,先把选中门窗同间隔,然后执行中距调整 CArray aryDoorWinPosNew, aryDoorWinPosOld; CalcNewPos(pSors, dlg.GetMidDis(), aryDoorWinPosNew, aryDoorWinPosOld); if (!SetNewPoint(pSors, aryDoorWinPosNew, aryDoorWinPosOld)) { ads_printf(_T("\n中距过大,无法调整门窗位置!\n")); } } else if (dlg.IsNeedEdgeDis()) { // 勾选了边距,,根据边距计算出中距,然后按照中距调整的步骤 double dMidDis = 0.0; // 计算墙中排序起始点和终止点之间的长度 TGGeCurveSegment wallLongBaseCurve = pSors->pWall->GetLongBaseLine(); TGGeCurveSegment curveTemp = wallLongBaseCurve; curveTemp.SetPoints(pSors->ptExtents[0], pSors->ptExtents[1]); double dAllLen = curveTemp.GetLength(); //计算所有门窗的长度 int index = 0; double dAllDoorWinLen = 0; for (index = 0; index <(int)pSors->aryOpening.GetSize(); index++) dAllDoorWinLen += pSors->aryOpening[index]->GetWidth(); // 墙长度减去所有门窗的长度减去两个边距, double dSubLen = dAllLen - dAllDoorWinLen - dlg.GetEdgeDis() * 2.0; if (dSubLen < 0) { // 不能添加 ads_printf(_T("\n边距过大,无法调整门窗位置!\n")); } else { // 计算平均间距。 if (pSors->aryOpening.GetSize() > 1) dMidDis = dSubLen/(pSors->aryOpening.GetSize()-1); // 执行中距算法 CArray aryDoorWinPosNew, aryDoorWinPosOld; CalcNewPos(pSors, dMidDis, aryDoorWinPosNew, aryDoorWinPosOld); if (!SetNewPoint(pSors, aryDoorWinPosNew, aryDoorWinPosOld)) ads_printf(_T("\n边距过大,无法调整门窗位置!\n")); } } else { // 未勾选中距和边距,直接把这些门窗居中 // 取得门窗范围点,并且计算该范围的中点(墙的方向上) TGGeCurveSegment wallLongBaseCurve = pSors->pWall->GetLongBaseLine(); TDbOpening *pOpeningFirst = pSors->aryOpening[0]; TDbOpening *pOpeningLast = pSors->aryOpening[pSors->aryOpening.GetSize()-1]; // 取得门窗最外部的点 XPoint pt1, pt2, ptDoorStart, ptDoorEnd; double d1 = 0.0, d2 = 0.0; pOpeningFirst->GetSidePoints(pt1, pt2); d1 = pSors->pWall->PathDistance(pt1); d2 = pSors->pWall->PathDistance(pt2); ptDoorStart = d1 < d2 ? pt1 : pt2; pOpeningLast->GetSidePoints(pt1, pt2); d1 = pSors->pWall->PathDistance(pt1); d2 = pSors->pWall->PathDistance(pt2); ptDoorEnd = d1 > d2 ? pt1 : pt2; // 取他们的中点,根据他们的中点计算偏移量 TGGeCurveSegment curveTempAxis = wallLongBaseCurve; curveTempAxis.SetPoints(pSors->ptExtents[0], pSors->ptExtents[1]); pt1 = curveTempAxis.MidPoint(); TGGeCurveSegment curveTempDoorWin = wallLongBaseCurve; curveTempDoorWin.SetPoints(ptDoorStart, ptDoorEnd); pt2 = curveTempDoorWin.MidPoint(); // 这里假设了所选居中时,所有门窗必须在轴线范围内 d1 = curveTempAxis.PathDistance(pt1); d2 = curveTempAxis.PathDistance(pt2); double dOff = d1 - d2; // 轴线中点距-门窗中点距 // 调整所有的门窗位置(新位置和老位置) CArray aryDoorWinPosNew, aryDoorWinPosOld; aryDoorWinPosNew.SetSize(pSors->aryOpening.GetSize()); aryDoorWinPosOld.SetSize(pSors->aryOpening.GetSize()); TGGeCurveSegment curveTemp; TGGeCurveSegment wallMidSeg = pSors->pWall->OffsetGeomCenter(LS_INFINITE, TRUE); for (int index = 0; index < (int)aryDoorWinPosNew.GetSize(); index++) { aryDoorWinPosOld[index] = pSors->aryOpening[index]->GetLocation(); XPoint ptTTT = GetPolarPoint(curveTempAxis, aryDoorWinPosOld[index], dOff); wallMidSeg.ProjectToMe(ptTTT, aryDoorWinPosNew[index]); aryDoorWinPosNew[index].z = aryDoorWinPosOld[index].z; } // 判断门窗为是是否合理并且添加 SetNewPoint(pSors, aryDoorWinPosNew, aryDoorWinPosOld); } } } delete paryStructRegul; paryStructRegul = NULL; // 记录前进一步 nStep++; } if (IsWindow(dlg.m_hWnd)) { dlg.m_bInCmd = false; dlg.DestroyWindow(); } } ////////////////////////////////////////////////////////////////////////// // 选择函数 class CSelectStruct { public: static BOOL KeyFilter(MSG* msg); static int SelectEnts(CString csPrompt,PickSet &ssResult, TRBList &rbBaseMask,const TCHAR* szKeyword, TCHAR &chRet); private: static CString m_sKeyWordList; static int m_rtRet; static TCHAR m_chRet; }; CString CSelectStruct::m_sKeyWordList; int CSelectStruct::m_rtRet; TCHAR CSelectStruct::m_chRet; //////////////////////////////////////////////////////////////////////////// BOOL CSelectStruct::KeyFilter(MSG* msg) { if(!acdbCurDwg()) return FALSE; BOOL bRet = FALSE; m_sKeyWordList.MakeUpper(); switch(msg->message) { case WM_KEYDOWN: //键盘输入关键字 { if (msg->wParam == VK_RETURN || msg->wParam == VK_SPACE)// 键盘输入回车和空格 add by lxb on 2011/11/29 { m_rtRet = RTNONE; msg->wParam = VK_SPACE; } else { CString sKey(TCHAR(msg->wParam)); sKey.MakeUpper(); if (m_sKeyWordList.Find(sKey) != -1) { // ads_printf(sKey); m_chRet = sKey[0]; m_rtRet = RTKWORD; msg->wParam = VK_SPACE; } } } break; case WM_RBUTTONDOWN: // 鼠标右键 { m_rtRet = RTNONE; msg->wParam = VK_SPACE; } break; default: break; } return bRet; } int CSelectStruct::SelectEnts(CString csPrompt,PickSet &ssResult, TRBList &rbBaseMask,const TCHAR* szKeyword, TCHAR &chRet) { if (szKeyword == NULL) m_sKeyWordList = _T(""); else m_sKeyWordList = szKeyword; m_rtRet = RTERROR; // 钩子函数监视键盘中输入关键字 acedRegisterFilterWinMsg(KeyFilter); // 保存返回结果 int nRet = 0; const TCHAR *szTempPrompts[2]={csPrompt, _T("") }; int iRet = ssResult.Get(_T(":S:$"), szTempPrompts, NULL, rbBaseMask); if (m_rtRet == RTKWORD) { chRet = m_chRet; nRet = RTKWORD; } else if (m_rtRet == RTNONE) { nRet = RTNONE; } else nRet = iRet; // 释放函数 acedRemoveFilterWinMsg(KeyFilter); return nRet; } int SelectEntitiesOnce(CString csPrompt,PickSet &ssResult, TRBList &rbBaseMask,const TCHAR* szKeyword, TCHAR &chRet) { return CSelectStruct::SelectEnts(csPrompt, ssResult, rbBaseMask, szKeyword, chRet); }