536 lines
13 KiB
C++
536 lines
13 KiB
C++
// XWall.cpp: implementation of the XWall class.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
#include "stdafx.h"
|
|
|
|
//#include <arxtools.h>
|
|
|
|
#include "tapi.h"
|
|
#include "XWall.h"
|
|
#include "XBlock.h"
|
|
#include "TelDef.h"
|
|
|
|
#define XD_WIN _T("wpline") // sr add app reg
|
|
#define XD_WINTHICK _T("wthick") // sr add app reg
|
|
|
|
#ifdef _DEBUG
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[]=__FILE__;
|
|
#define new DEBUG_NEW
|
|
#endif
|
|
|
|
#define MAXWALLTHICK 720
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Construction/Destruction
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
XWall::XWall()
|
|
{
|
|
m_bFirst = TRUE;
|
|
}
|
|
|
|
XWall::~XWall()
|
|
{
|
|
|
|
}
|
|
|
|
XWall::XWall(Entity ent)
|
|
{
|
|
m_bFirst = TRUE;
|
|
m_ent = ent;
|
|
IsArcWall();
|
|
}
|
|
|
|
BOOL XWall::IsArcWall()
|
|
{
|
|
if(m_ent.Is(_T("ARC"))){
|
|
XArc arc(m_ent);
|
|
arc.GetStartPoint(m_ptStart);
|
|
arc.GetEndPoint(m_ptEnd);
|
|
// arc.GetPoints(m_ptStart, m_ptEnd);
|
|
m_ent.GetData(10, m_ptCen);
|
|
m_ent.GetData(40, &m_nRadius);
|
|
return TRUE;
|
|
}
|
|
else{
|
|
XLine line(m_ent, 1);
|
|
m_ptStart = line.StartPoint();
|
|
m_ptEnd = line.EndPoint();
|
|
m_nAngle = ads_angle(m_ptStart, m_ptEnd);
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
Entity XWall::GetNextWallLine(XPoint ptPick)
|
|
{
|
|
XPoint ptUcs = Wcs2Ucs(ptPick);
|
|
PickSet ssSel(SS_FREE);
|
|
if(IsArcWall())
|
|
GetPointPickSet(ptUcs, ssSel, RBList(RTDXF0, _T("ARC"), 8, LAY_WALL, NULL), MAXWALLTHICK/2);
|
|
else
|
|
GetPointPickSet(ptUcs, ssSel, RBList(RTDXF0, _T("LINE"), 8, LAY_WALL, NULL), MAXWALLTHICK/2);
|
|
if(ssSel.Length() < 2){
|
|
return Entity();
|
|
}
|
|
|
|
ssSel -= m_ent;
|
|
long len = ssSel.Length();
|
|
for(long i=0;i<len;i++){
|
|
Entity entWall = ssSel[i];
|
|
if(m_ent.Is(_T("ARC")) && entWall.Is(_T("ARC"))){
|
|
XPoint ptCen;
|
|
double Radius;
|
|
entWall.GetData(10, ptCen);
|
|
entWall.GetData(40, &Radius);
|
|
if(ptCen == m_ptCen){
|
|
return entWall;
|
|
}
|
|
}
|
|
else if(m_ent.Is(_T("LINE")) && entWall.Is(_T("LINE"))){
|
|
XLine l1(m_ent, 1);
|
|
XLine l2(entWall, 1);
|
|
if(l2.GetLength() < MAXWALLTHICK/2) //接门窗墙
|
|
continue;
|
|
double ang1 = ads_angle(l1.StartPoint(), l1.EndPoint());
|
|
double ang2 = ads_angle(l2.StartPoint(), l2.EndPoint());
|
|
if((l1.StartPoint() & l2 ) == PR_EXTEND)
|
|
continue;
|
|
if(fabs(ang1 - ang2) < 0.01 || fabs(fabs(ang1 - ang2) - PI) < 0.01 || fabs(fabs(ang1 - ang2) - PI*2) < 0.01)
|
|
return entWall;
|
|
}
|
|
}
|
|
return Entity();
|
|
}
|
|
|
|
Entity XWall::GetWinFromWall(Entity ent, XPoint pt)
|
|
{
|
|
RBList rbMask = ads_buildlist( -4, _T("<or"),
|
|
-4, _T("<and"), RTDXF0, _T("INSERT"), 8, LAY_WIN, -4, _T("and>"),
|
|
-4, _T("<and"), RTDXF0, _T("INSERT"), 8, LAY_COLU, -4, _T("and>"),
|
|
-4, _T("or>"), NULL);
|
|
|
|
PickSet ss(SS_FREE);
|
|
GetPointPickSet(pt, ss, rbMask, MAXWALLTHICK / 2);
|
|
long len = ss.Length();
|
|
if(ss.Length() < 1 )
|
|
return Entity();
|
|
else if(ss.Length() == 1 )
|
|
return ss[0L];
|
|
double nMinDist = -1.0;
|
|
long Index = -1;
|
|
for (long i=0;i<len;i++){
|
|
Entity entBlk = ss[i];
|
|
XPoint ptIns;
|
|
entBlk.GetData(10, &ptIns);
|
|
double nDist = ads_distance(pt, ptIns);
|
|
if(nMinDist > nDist || nMinDist < 0) {
|
|
nMinDist = nDist;
|
|
Index = i;
|
|
}
|
|
|
|
}
|
|
return ss[Index];
|
|
|
|
}
|
|
|
|
BOOL XWall::GetWinData(Entity entWin, double &nWallThick, XPointList &lstPt)
|
|
{
|
|
AcDbObjectId eId;
|
|
AcDbEntity *pEnt;
|
|
acdbGetObjectId(eId, entWin);
|
|
if(!eId)
|
|
return FALSE;
|
|
acdbOpenObject(pEnt, eId, AcDb::kForRead);
|
|
|
|
resbuf *pxData = pEnt->xData(XD_WIN);
|
|
if(!pxData){
|
|
pEnt->close(); //根本没有扩展数据!
|
|
return FALSE;
|
|
}
|
|
resbuf *pNext = pxData->rbnext;
|
|
XBlock myBlock(entWin);
|
|
while(pNext) {
|
|
AcGePoint3d ptBlk;
|
|
XPoint xpoint;
|
|
if(pNext->restype == 1010) {
|
|
xpoint = pNext->resval.rpoint;
|
|
ptBlk = xpoint;
|
|
ptBlk = ptBlk.transformBy(myBlock.GetMatrix3d());
|
|
lstPt.NewAppend(ptBlk);
|
|
}
|
|
pNext = pNext->rbnext;
|
|
}
|
|
ads_relrb(pxData);
|
|
resbuf *pxData2 = pEnt->xData(XD_WINTHICK);
|
|
if(!pxData2){
|
|
pEnt->close(); //根本没有扩展数据!
|
|
return FALSE;
|
|
}
|
|
resbuf *pNext2 = pxData2->rbnext;
|
|
if(pNext2 && pNext2->restype == 1040)
|
|
nWallThick = pNext2->resval.rreal;
|
|
ads_relrb(pxData2);
|
|
|
|
pEnt->close();
|
|
return TRUE;
|
|
}
|
|
|
|
extern BOOL Is2LineOnLine(XLine line1, XLine line2);
|
|
extern BOOL Is2ArcOnArc(XArc arc1, XArc arc2);
|
|
|
|
Entity XWall::GetWinNextWall(Entity entWin, Entity FirstWall, XPoint &ptStart, XPoly2D &xpoly1)
|
|
{
|
|
PickSet ssSel(SS_FREE);
|
|
ads_point lowPt, upPt, lowPt2, upPt2;
|
|
lowPt[2] = upPt[2] = lowPt2[2] = upPt2[2] = 0;
|
|
entWin.GetExtend(lowPt, upPt);
|
|
lowPt[0] -= 100;
|
|
lowPt[1] -= 100;
|
|
upPt[0] += 100;
|
|
upPt[1] += 100;
|
|
|
|
lowPt2[0] = upPt[0];
|
|
lowPt2[1] = lowPt[1];
|
|
upPt2[0] = lowPt[0];
|
|
upPt2[1] = upPt[1];
|
|
|
|
RBList rbMask = ads_buildlist( -4, _T("<or"),
|
|
-4, _T("<and"), RTDXF0, _T("LINE"), 8, LAY_WALL, -4, _T("and>"),
|
|
-4, _T("<and"), RTDXF0, _T("ARC"), 8, LAY_WALL, -4, _T("and>"),
|
|
-4, _T("or>"), NULL);
|
|
ssSel.Get(_T("C"), upPt, lowPt, rbMask);
|
|
if(ssSel.Length() < 2)
|
|
return Entity();
|
|
|
|
ssSel -= FirstWall;
|
|
long len = ssSel.Length();
|
|
for(long i=0;i<len;i++){
|
|
Entity entTmp = ssSel[i];
|
|
if(FirstWall.Is(_T("LINE")) && entTmp.Is(_T("LINE"))){
|
|
XLine fLine(FirstWall);
|
|
XLine nLine(entTmp);
|
|
if(Is2LineOnLine(fLine, nLine)){
|
|
if(ads_distance(ptStart, nLine.StartPoint()) > ads_distance(ptStart, nLine.EndPoint()))
|
|
ptStart = nLine.EndPoint();
|
|
else
|
|
ptStart = nLine.StartPoint();
|
|
return entTmp;
|
|
}
|
|
}
|
|
else if(FirstWall.Is(_T("ARC")) && entTmp.Is(_T("ARC"))){
|
|
XPoint ptS, ptE;
|
|
XArc fArc(FirstWall);
|
|
XArc nArc(entTmp);
|
|
if(Is2ArcOnArc(fArc, nArc)){
|
|
nArc.GetStartPoint(ptS);
|
|
nArc.GetEndPoint(ptE);
|
|
// nArc.GetPoints(ptS, ptE);
|
|
if(ads_distance(ptStart, ptS) > ads_distance(ptStart, ptE))
|
|
ptStart = ptE;
|
|
else
|
|
ptStart = ptS;
|
|
return entTmp;
|
|
}
|
|
}
|
|
}
|
|
XPointList lstPt;
|
|
double nWallThick = 0.0;
|
|
if(!GetWinData(entWin, nWallThick, lstPt))
|
|
return Entity();
|
|
|
|
XPoly2D xpoly;
|
|
for(int j=0;j<lstPt.Length();j++)
|
|
xpoly.AppendNode(*lstPt[j]);
|
|
|
|
XPoint ptTEMP;
|
|
for(j=0;j<2;j++){
|
|
xpoly.Offset(nWallThick / 2, xpoly1);
|
|
XPoint ptTmp1, ptTmp2;
|
|
ptTmp1 = *xpoly1[0];
|
|
ptTmp2 = *xpoly1[xpoly1.Length() - 1];
|
|
if(ptTmp1 == ptStart || ptTmp2 == ptStart){
|
|
if(ptTmp1 == ptStart) ptTEMP = ptTmp2;
|
|
if(ptTmp2 == ptStart) ptTEMP = ptTmp1;
|
|
break;
|
|
}
|
|
nWallThick = -nWallThick;
|
|
}
|
|
PickSet sspt(SS_FREE);
|
|
GetPointPickSet(ptTEMP, sspt, rbMask, 2);
|
|
len = sspt.Length();
|
|
for(i=0;i<len;i++){
|
|
Entity entCul = sspt[i];
|
|
if(entCul.Is(_T("ARC")))
|
|
return Entity();
|
|
XLine line(entCul);
|
|
if(line.GetLength() == nWallThick)
|
|
break;
|
|
if(line.StartPoint() == ptTEMP || line.EndPoint() == ptTEMP){
|
|
if(line.StartPoint() == ptTEMP) ptStart = line.StartPoint();
|
|
if(line.EndPoint() == ptTEMP) ptStart = line.EndPoint();
|
|
return entCul;
|
|
}
|
|
}
|
|
|
|
return Entity();
|
|
}
|
|
|
|
Entity XWall::GetWallFromPt(Entity ent, XPoint pt)
|
|
{
|
|
RBList rbMask = ads_buildlist( -4, _T("<or"),
|
|
-4, _T("<and"), RTDXF0, _T("LINE"), 8, LAY_WALL, -4, _T("and>"),
|
|
-4, _T("<and"), RTDXF0, _T("ARC"), 8, LAY_WALL, -4, _T("and>"),
|
|
-4, _T("or>"), NULL);
|
|
PickSet ssTemp(SS_FREE);
|
|
GetPointPickSet(pt, ssTemp, rbMask, 2);
|
|
int len = ssTemp.Length();
|
|
if(ssTemp.Length() < 2){
|
|
return Entity();
|
|
}
|
|
ssTemp -= ent;
|
|
if(len == 2)
|
|
return ssTemp[0L];
|
|
for(long i=0;i<len - 1;i++){
|
|
Entity entCul = ssTemp[i];
|
|
XPoint ptStart, ptEnd;
|
|
GetWire2Point(entCul, ptStart, ptEnd);
|
|
if(ptStart == pt || ptEnd == pt)
|
|
return entCul;
|
|
}
|
|
return ssTemp[0L];
|
|
|
|
}
|
|
|
|
BOOL XWall::IsEndWall(Entity ent)
|
|
{
|
|
XPoint ptStart, ptEnd;
|
|
GetWire2Point(ent, ptStart, ptEnd);
|
|
Entity ent1 = GetWallFromPt(ent, ptStart);
|
|
Entity ent2 = GetWallFromPt(ent, ptEnd);
|
|
if(!ent1 || !ent2)
|
|
return FALSE;
|
|
if(ent1.Is(_T("LINE")) && ent2.Is(_T("LINE"))){
|
|
XLine line1(ent1, 1);
|
|
XLine line2(ent2, 1);
|
|
double ang1 = ads_angle(line1.StartPoint(), line1.EndPoint());
|
|
double ang2 = ads_angle(line2.StartPoint(), line2.EndPoint());
|
|
if(fabs(ang1 - ang2) < 0.1 || fabs(fabs(ang1 - ang2) - PI) < 0.1)
|
|
return TRUE;
|
|
}
|
|
else if(ent1.Is(_T("ARC")) && ent2.Is(_T("ARC"))){
|
|
XArc arc1(ent1);
|
|
XArc arc2(ent2);
|
|
if(arc1.GetCenterPt() == arc2.GetCenterPt())
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
//返回TRUE: 搜索到断墙, FALSE: 封闭墙
|
|
BOOL XWall::DoSearch(XPoint pt, PickSet &ss)
|
|
{
|
|
Entity ent = m_ent;
|
|
RBList rbMask = ads_buildlist( -4, _T("<or"),
|
|
-4, _T("<and"), RTDXF0, _T("LINE"), 8, LAY_WALL, -4, _T("and>"),
|
|
-4, _T("<and"), RTDXF0, _T("ARC"), 8, LAY_WALL, -4, _T("and>"),
|
|
-4, _T("or>"), NULL);
|
|
|
|
while(1){
|
|
PickSet ssTemp(SS_FREE);
|
|
Entity entTemp = ent;
|
|
XPoint ptStart, ptEnd;
|
|
XPoly2D xpoly;
|
|
GetPointPickSet(pt, ssTemp, rbMask, 10);
|
|
int iLen = ssTemp.Length();
|
|
|
|
if(ssTemp.Length() < 1)
|
|
break;
|
|
|
|
if(ssTemp.Length() == 1){ //1:墙到头 2:连柱子
|
|
Entity entWin = GetWinFromWall(ent, pt);
|
|
if(!!entWin){
|
|
ent = GetWinNextWall(entWin, ent, pt, xpoly);
|
|
if(!ent){
|
|
AppendTail(pt);
|
|
return TRUE;
|
|
}
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
else if(ssTemp.Length() >= 2){
|
|
if(ssTemp.Length() == 2){ //1:墙到头 2:墙转弯
|
|
ssTemp -= ent;
|
|
ent = ssTemp[0L];
|
|
}
|
|
else { //遇到超短墙
|
|
ssTemp -= ent;
|
|
for(long j=0;j<ssTemp.Length();j++){
|
|
Entity entCul = ssTemp[j];
|
|
XPoint ptStart, ptEnd;
|
|
GetWire2Point(entCul, ptStart, ptEnd);
|
|
if(ptStart == pt || ptEnd == pt){
|
|
ent = entCul;
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
XCurveSegment seg(ent);
|
|
if(seg.GetLength() < MAXWALLTHICK && IsEndWall(ent)){//到墙末端
|
|
XCurveSegment seg(ent);
|
|
XPoint ptMid = seg.MidPoint();
|
|
Entity entWin = GetWinFromWall(ent, ptMid);
|
|
if(!!entWin){
|
|
ent = GetWinNextWall(entWin, entTemp, pt, xpoly);
|
|
if(!ent){
|
|
AppendTail(pt);
|
|
return TRUE;
|
|
}
|
|
else{
|
|
if(!!xpoly){ //转角窗
|
|
|
|
int lenPoly = xpoly.Length();
|
|
for(int ii=1;ii<lenPoly;ii++){
|
|
if(*xpoly[0] == pt)
|
|
m_ptPolyEnd = *xpoly[lenPoly - ii];
|
|
else if(*xpoly[lenPoly - 1] == pt)
|
|
m_ptPolyEnd = *xpoly[ii];
|
|
XCurveSegment seg;
|
|
XLine line(m_ptPolyStart, m_ptPolyEnd, LS_FINITE);
|
|
seg = line;
|
|
XPoint ptStartm, ptEndm;
|
|
GetWire2Point(m_ent, ptStartm, ptEndm);
|
|
if(ptEndm == m_ptPolyStart)
|
|
ptFirstTemp = m_ptPolyEnd;
|
|
else{
|
|
m_lstSeg.Append(new XCurveSegment(seg));
|
|
}
|
|
m_ptPolyStart = m_ptPolyEnd;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else{
|
|
AppendTail(pt);
|
|
return TRUE;
|
|
}
|
|
}
|
|
else{
|
|
|
|
m_ptPolyEnd = pt;
|
|
XCurveSegment seg;
|
|
if(entTemp.Is(_T("LINE"))){
|
|
XLine line(m_ptPolyStart, m_ptPolyEnd, LS_FINITE);
|
|
seg = line;
|
|
}
|
|
else if(entTemp.Is(_T("ARC"))){
|
|
XArc aTemp(entTemp);
|
|
XPoint ptMidTemp;
|
|
aTemp.MidPoint(ptMidTemp);
|
|
XArc arc(m_ptPolyStart, ptMidTemp, m_ptPolyEnd);
|
|
seg = arc;
|
|
}
|
|
XPoint ptStartm, ptEndm;
|
|
GetWire2Point(m_ent, ptStartm, ptEndm);
|
|
if(ptEndm == m_ptPolyStart)
|
|
ptFirstTemp = m_ptPolyEnd;
|
|
else{
|
|
m_lstSeg.Append(new XCurveSegment(seg));
|
|
}
|
|
|
|
m_ptPolyStart = m_ptPolyEnd;
|
|
}
|
|
}
|
|
|
|
if(m_ent == ent){
|
|
AppendTail(pt);
|
|
return FALSE;
|
|
}
|
|
ss += ent;
|
|
GetWire2Point(ent, ptStart, ptEnd);
|
|
if(ptStart == pt)
|
|
pt = ptEnd;
|
|
else
|
|
pt = ptStart;
|
|
|
|
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
void XWall::AppendTail(XPoint pt)
|
|
{
|
|
m_ptPolyEnd = pt;
|
|
XCurveSegment seg;
|
|
if(m_ent.Is(_T("LINE"))){
|
|
XLine line(m_ptPolyStart, ptFirstTemp, LS_FINITE);
|
|
seg = line;
|
|
}
|
|
else if(m_ent.Is(_T("ARC"))){
|
|
XArc aTemp(m_ent);
|
|
XPoint ptMidTemp;
|
|
aTemp.MidPoint(ptMidTemp);
|
|
XArc arc(m_ptPolyStart, ptMidTemp, ptFirstTemp);
|
|
seg = arc;
|
|
}
|
|
m_lstSeg.Append(new XCurveSegment(seg));
|
|
}
|
|
|
|
void XWall::SearchAllWallLine(PickSet &ss)
|
|
{
|
|
XPoint ptStart, ptEnd;
|
|
GetWire2Point(m_ent, ptStart, ptEnd);
|
|
m_ptPolyStart = ptEnd;
|
|
ss += m_ent;
|
|
if(DoSearch(ptStart, ss)){
|
|
m_bFirst = FALSE;
|
|
DoSearch(ptEnd, ss);
|
|
}
|
|
|
|
GetExternalBoundaryFromCurves(m_lstSeg, m_poly);
|
|
if(!m_poly)
|
|
Callme(_T("外墙不封闭, 搜索失败!"));
|
|
}
|
|
|
|
|
|
BOOL XWall::GetInsEquipPt(XPoint &ptPick, double &nRotate, double nDist)
|
|
{
|
|
Entity ent = GetNextWallLine(ptPick);
|
|
if(!ent)
|
|
return FALSE;
|
|
XCurveSegment seg(ent);
|
|
if(seg.Is(CURVE_LINE)){
|
|
double angleWall = m_nAngle;
|
|
double angleWall1 = m_nAngle;
|
|
double angleWall2 = ads_angle(seg.StartPoint(), seg.EndPoint());
|
|
double dn = fabs(angleWall2 - angleWall1);
|
|
if(fabs(dn - PI) < 0.001){
|
|
XLine line(seg.EndPoint(), seg.StartPoint(), 1);
|
|
if(line.OnWhichSide(ptPick) == OFFSET_RIGHT)
|
|
angleWall = angleWall + PI;
|
|
}
|
|
else if(seg.OnWhichSide(ptPick) == OFFSET_RIGHT)
|
|
angleWall = angleWall + PI;
|
|
ads_polar(ptPick, angleWall+(PI/2), nDist, ptPick);
|
|
nRotate = angleWall * 180 / PI;
|
|
}
|
|
else if(seg.Is(CURVE_ARC)){
|
|
double angle = ads_angle(ptPick, m_ptCen);
|
|
nRotate = angle * 180 / PI;
|
|
if(seg.OnWhichSide(ptPick) == OFFSET_LEFT){
|
|
ads_polar(ptPick, angle, nDist, ptPick);
|
|
nRotate -= 90;
|
|
}
|
|
else{
|
|
ads_polar(ptPick, angle, -nDist, ptPick);
|
|
nRotate += 90;
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|