Files
gjm 164968b62e chore
把非utf8-bom编码的cpp/h文件改为 utf8 bom 编码, msvc识别utf8编码时,如果不是bom格式的,会使用当前cp_oem来解码.
2026-10-04 00:04:20 +08:00

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;
}