1479 lines
42 KiB
C++
1479 lines
42 KiB
C++
#include "StdAfx.h"
|
|
#include "resource.h"
|
|
#include "OpeningRegul.h"
|
|
|
|
#define CHOSEAXICS 0
|
|
#define CHOSEDK 1
|
|
|
|
template <class TSwapType>
|
|
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<TDbOpening*, TDbOpening*> 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<SOpeningRegulStruct*, SOpeningRegulStruct*> 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<TDbOpening*, TDbOpening*> &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<TOpeningData> lstOpening;
|
|
// pWall->GetOpenings(lstOpening, FALSE);
|
|
|
|
const TDPtrList<AcDbSoftPointerId> &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<TDbOpening*, TDbOpening*> &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<XPoint, XPoint&> &aryDoorWinPosNew,
|
|
CArray<XPoint, XPoint&> &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<XPoint, XPoint&> &aryDoorWinPosNew,
|
|
CArray<XPoint, XPoint&> &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<XPoint, XPoint&> 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<XPoint, XPoint&> 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<XPoint, XPoint&> 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);
|
|
} |