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

719 lines
18 KiB
C++

//-------------------------------------------------------------------------------------------------------+
// Copyright (C), 1998-2007, SH Software Co. Ltd.
// = FileName : XRdupCurve 类
// = Version : ver2.0
// = Author : zjq
// = CreateDate : 2002-09-09
// = Description: XRdupCurve 定义
// = Maintainers:
//
//-------------------------------------------------------------------------------------------------------+
#include "StdAfx.h"
#include "XRdupCurve.h"
#include "XGlobalCurveFunc.h"
#include "XCurveInline.h"
static int CompareDouble(const double *p1, const double *p2)
{
if (*p1 > *p2)
{
return 1;
}
return -1;
}
XRdupCurve::XRdupCurve()
{
m_slength = _DIST_SNAP;
m_shortLineNum = 0;
m_delLineNum = 0;
}
XRdupCurve::~XRdupCurve()
{
}
int XRdupCurve::FindNode(double dKey, DList<XDRdupLineNode> &lstNewCurves)
{
int nLen = lstNewCurves.Length();
if (!nLen)
{
return -1;
}
for (int i = 0; i < nLen; i++)
{
double nPrec = _angSnap;
if (CT_IsSameDrt(lstNewCurves[i]->key, dKey, nPrec))
{
return i;
}
}
return -1;
}
/*zjq注掉,由于没有使用的地方
int compareDList(const XDRdupLineNode *p1, const XDRdupLineNode *p2)
{
ads_real dVal1, dVal2;
int nRes = 0;
dVal1 = p1->key;
dVal2 = p2->key;
if (fabs(dVal1 - dVal2) < 1e-5)
{
nRes = 0;
}
else if (dVal1 > dVal2)
{
nRes = 1;
}
else
{
nRes = -1;
}
return(nRes);
}
*/
double XRdupCurve::distanceOfPtToLine(XPoint pt,XPoint ptStart,XPoint ptEnd)
{
double c1,c2,c3;
c1 = ptEnd.y - ptStart.y;
c2 = ptStart.x - ptEnd.x;
c3 = sqrt(c1 * c1 + c2 * c2);
c1 = c1 / c3;
c2 = c2 / c3;
c3 = (ptEnd.x * ptStart.y - ptStart.x * ptEnd.y) / c3;
return ((c1 * pt[X]) + (c2 * pt[Y]) + c3);
}
void XRdupCurve::getMinPoint(AcDbIntArray *ids,XPoint &ptMin)
{
XPoint ptTmp(1e100,1e100,0);
int nLen = ids->length();
for (int i = 0;i<nLen;i++)
{
XCurveObject *pEnt = m_ssCurves[ids->at(i)];
ptTmp = pEnt->GetStartPoint();
if (ptTmp.x < ptMin.x)
{
ptMin = ptTmp;
}
ptTmp = pEnt->GetEndPoint();
if (ptTmp.x < ptMin.x)
{
ptMin = ptTmp;
}
}
return;
}
BOOL XRdupCurve::makeArrayByAngle(DList<XCurveObject> &ss, DList<XDRdupLineNode> &lstNewCurves)
{
XPoint ptStart,ptEnd;
double dAngle = 0;
int nLen = ss.Length();
if (!nLen)
{
return FALSE;
}
int nBar = 0;
for (long i = 0; i < nLen; i++)
{
XCurveObject &ent = *ss[i];
if (ent.m_bDeleted)
{
continue;
}
ASSERT(ent.Is(CURVE_LINE));
ptStart = ent.GetStartPoint();
ptEnd = ent.GetEndPoint();
dAngle = ads_angle(ptStart,ptEnd);
XDRdupLineNode * node = new XDRdupLineNode;
long iPos = FindNode(dAngle,lstNewCurves);
if (iPos >= 0)
{
(*lstNewCurves[iPos]).entArray.append(i);
delete node;
}
else
{
node->key = dAngle;
node->entArray.append(i);
lstNewCurves.Append(node);
}
}//循环后,将角度相同的实体放入同一个表中
return (lstNewCurves.Length()) ? TRUE : FALSE;
}
void XRdupCurve::setShortLineLength(double dShortLine)
{
m_slength = fabs(dShortLine);
return;
}
// 在断点处断开单线
// Status: ss is both as input and output
// 加速算法
void XRdupCurve::IntersectCurves(DList<XCurveSegment> &lstCurves)
{
DList<XCurveSegment> ss1;
int nCount = m_ssCurves.Length();
for (int i = 0; i < nCount; i++)
{
XCurveObject *pSeg = m_ssCurves[i];
if (!pSeg->IsDeleted() && !pSeg->Is(CURVE_CIRCLE))
{
XCurveSegment *pNewSeg = new XCurveSegment(*pSeg);
pNewSeg->SetLineFlag(LS_FINITE);
ss1.Append(pNewSeg);
}
}
int nLen1 = ss1.Length();
if (g_bEchoSearch)
{
acedSetStatusBarProgressMeter(_T("求交线"), 0, nLen1);
}
int nStep = nLen1 / 100;
if (nStep < 1)
{
nStep = 1;
}
DList<double> *lstDistArray = new DList<double> [nLen1];
for (int i = 0; i < nLen1 - 1; i++)
{
if (g_bEchoSearch && !(i % nStep))
{
acedSetStatusBarProgressMeterPos(i);
}
XCurveSegment &line1 = *ss1[i];
XPoint &ptStart = line1.StartPoint();
for (int j = i + 1; j < nLen1; j++)
{
XCurveSegment &line2 = *ss1[j];
XPoint ptInt1;
if (!g_bFastCalMode)
{
if (line1.XLine::Intersection(&(const XLine &)line2, ptInt1))
{
lstDistArray[i].Append(new double(ptStart.Distance2d(ptInt1)));
lstDistArray[j].Append(new double(line2.GetStartPoint().Distance2d(ptInt1)));
}
}
else
{
if (ads_inters(line1.GetStartPoint(), line1.GetEndPoint(), line2.GetStartPoint(), line2.GetEndPoint(), 1, ptInt1) == RTNORM)
{
lstDistArray[i].Append(new double(ptStart.Distance2d(ptInt1)));
lstDistArray[j].Append(new double(line2.GetStartPoint().Distance2d(ptInt1)));
}
}
}
}
for (int i = 0; i < nLen1; i++)
{
DList<double> &lstDistSeg = lstDistArray[i];
XCurveSegment &line1 = *ss1[i];
double nDist0 = line1.GetStartPoint().Distance2d(line1.EndPoint());
lstDistSeg.QuickSort(CompareDouble);
lstDistSeg.Append(new double(nDist0));
double nDirection = line1.XLine::Direction();
XPoint &ptStart = line1.StartPoint();
XPoint ptS = ptStart;
for (int j = 0; j < lstDistSeg.Length(); j++)
{
XPoint ptE;
ads_polar(ptStart, nDirection, *lstDistSeg[j], ptE);
if (ptS.Distance2d(ptE) > _DIST_SNAP)
{
lstCurves.Append(new XCurveSegment(ptS, ptE, 0.0));
}
ptS = ptE;
}
}
delete [] lstDistArray;
if (g_bEchoSearch)
{
acedRestoreStatusBar();
}
}
// 对直线消除重线
void XRdupCurve::RemoveDupLine(PickSet &ss)
{
PickSet ssLine(SS_FREE), ssLine1(SS_FREE);
ssLine += ss;
RBList tmp(RTDXF0, _T("LINE"), NULL);
ssLine.BaseFilter(tmp);
PickSet ssDel(SS_FREE);
m_shortLineNum = m_delLineNum = 0;
m_ssCurves.Reset();
long nLen1 = ssLine.Length();
for (long idx = 0L; idx<nLen1; idx++)
{
Entity ent = ssLine[idx];
XCurveSegment seg(ent);
seg.SetElevation(0.0);
if (seg.GetLength() <= m_slength) //超短线,删除
{
m_shortLineNum++;
ssDel += ent;
}
else
{
m_ssCurves.Append(new XCurveObject(seg));
ssLine1 += ent;
}
}
DList<XDRdupLineNode> lstNewCurves;
makeArrayByAngle(m_ssCurves, lstNewCurves);
int nLen = lstNewCurves.Length();
if (g_bEchoSearch)
{
XString sMsg(256);
sMsg << _T("对") << nLen << _T("组共") << nLen1 << _T("条线进行消除重线");
acedSetStatusBarProgressMeter(sMsg, 0, nLen);
}
int nStep = nLen / 100;
if (nStep < 1)
{
nStep = 1;
}
for (int nn = 0; nn < nLen; nn++)
{
if (g_bEchoSearch && !(nn % nStep))
{
acedSetStatusBarProgressMeterPos(nn);
}
XDRdupLineNode *pNode = lstNewCurves[nn];
int nCount = pNode->entArray.length();
for (int i = 0; i < nCount; i++)
{
XCurveObject &line1 = *m_ssCurves[pNode->entArray[i]];
if (line1.IsDeleted())
{
continue;
}
for (int j = 0; j < nCount; j++)
{
XCurveObject &line2 = *m_ssCurves[pNode->entArray[j]];
if (j == i)
{
continue;
}
if (line2.IsDeleted())
{
continue; // 线2已经被删除或者两线类型不匹配
}
int nFlg = (line2.GetStartPoint() & line1) ;
int nFlg1 = (line2.GetEndPoint() & line1);
if (nFlg == PR_ONPT1 || nFlg == PR_ONPT2 || nFlg == PR_INSIDE)
{
//按角度判断重合
// 线2起点在线1内(包括端点)
line2.m_bDeleted = TRUE; //线2要合并到线1内
XPoint ptOnLine1;
line2.GetEndPoint().Project(&line1, ptOnLine1); //那么需要投影后,才能判断在线上还是在外面
nFlg1 = (ptOnLine1 & line1);
if (nFlg1 == PR_EXTEND)
{
// 线2的终点在线1的延长线上, 判断在起始延长还是终止延长
if (ads_distance(line1.GetStartPoint(), line2.GetEndPoint())
< ads_distance(line1.GetEndPoint(), line2.GetEndPoint()))
{
line1.SetStartPoint(line2.GetEndPoint()); //因此改变线1的起点
}
else
{
line1.SetEndPoint(line2.GetEndPoint()); //否则线1的终点在线2内,因此改变线1的终点
}
}
else
{
ASSERT(nFlg1 != PR_OUTSIDE);
}
}
else if (nFlg1 == PR_ONPT1 || nFlg1 == PR_ONPT2 || nFlg1 == PR_INSIDE)
{
// 线2终点线1内(包括端点)
line2.m_bDeleted = TRUE;
XPoint ptOnLine1;
line2.GetStartPoint().Project(&line1, ptOnLine1);
nFlg = (ptOnLine1 & line1);
if (nFlg == PR_EXTEND)
{
// 线2的起点在线1的延长线上, 判断在起始延长还是终止延长
if (ads_distance(line1.GetStartPoint(),line2.GetStartPoint())<
ads_distance(line1.GetEndPoint(),line2.GetStartPoint()))
{
line1.SetStartPoint(line2.GetStartPoint());
}
else
{
line1.SetEndPoint(line2.GetStartPoint());
}
}
else
{
ASSERT(nFlg != PR_OUTSIDE);
}
}
else if ((nFlg == PR_EXTEND && nFlg1 == PR_EXTEND)) //线2的两端都在线一的外边
{
int nFlg2 = (line1.GetStartPoint()&line2);
if (nFlg2 == PR_INSIDE) //line1在line2内部, 替换line1
{
line1.SetStartPoint(line2.GetStartPoint());
line1.SetEndPoint(line2.GetEndPoint());
line2.m_bDeleted = TRUE;
}
}
} /* end for j */
} /* end for i */
}
if (g_bEchoSearch)
{
acedRestoreStatusBar();
}
int nCount = m_ssCurves.Length();
ASSERT(nCount == ssLine1.Length());
for (int nn = 0; nn < nCount; nn++)
{
Entity ent = ssLine1[long(nn)];
if (m_ssCurves[nn]->IsDeleted())
{
ssDel += ent;
}
else
{
m_ssCurves[nn]->Modify(&ent);
}
}
ss -= ssDel;
ssDel.Erase();
}
/*
消除重线
1:对于一条直线包含很多重线,则删除这些重线,保留最长的线
2:若连接两条线,修改前一线的终点,任何时候本程序都不新生成LINE
3:没有重线,不修改LINE的属性,保留原来的LINE
*/
// 应当改进Project的算法
void XRdupCurve::removeDupCurve(DList<XCurveSegment> &ss1, BOOL bExactDup, BOOL bIntsect)
{
int nLen1 = ss1.Length();
if (!nLen1)
{
return ;
}
m_shortLineNum = m_delLineNum = 0;
m_ssCurves.Reset();
for (int k = 0; k < nLen1; k++)
{
XCurveSegment &ent = *ss1[k];
if (ent.GetLength() <= m_slength) //超短线,删除
{
m_shortLineNum++;
}
else
{
m_ssCurves.Append(new XCurveObject(*ss1[k]));
}
}
DList<XDRdupLineNode> lstNewCurves;
makeArrayByAngle(m_ssCurves, lstNewCurves);
int nLen = lstNewCurves.Length();
if (g_bEchoSearch)
{
XString sMsg(256);
sMsg << _T("对") << nLen << _T("组共") << nLen1 << _T("条线进行消除重线");
acedSetStatusBarProgressMeter(sMsg, 0, nLen);
}
int nStep = nLen / 100;
if (nStep < 1)
{
nStep = 1;
}
for (int nn = 0; nn < nLen; nn++)
{
if (g_bEchoSearch && !(nn % nStep))
{
acedSetStatusBarProgressMeterPos(nn);
}
XDRdupLineNode *pNode = lstNewCurves[nn];
int nCount = pNode->entArray.length();
for (int i = 0; i < nCount; i++)
{
XCurveObject &line1 = *m_ssCurves[pNode->entArray[i]];
if (line1.IsDeleted())
{
continue;
}
for (int j = 0; j < nCount; j++)
{
XCurveObject &line2 = *m_ssCurves[pNode->entArray[j]];
if (j == i)
{
continue;
}
if (line2.IsDeleted())
{
continue; // 线2已经被删除或者两线类型不匹配
}
if (bExactDup)
{
if ((line1.GetStartPoint().Distance2d(line2.StartPoint()) < _DIST_SNAP
&& line1.GetEndPoint().Distance2d(line2.EndPoint()) < _DIST_SNAP)
|| (line1.GetStartPoint().Distance(line2.EndPoint()) < _DIST_SNAP
&& line1.GetEndPoint().Distance2d(line2.StartPoint()) < _DIST_SNAP)
)
{
line2.m_bDeleted = TRUE; //线2要合并到线1内
}
}
else
{
int nFlg = (line2.GetStartPoint() & line1) ;
int nFlg1 = (line2.GetEndPoint() & line1);
if (nFlg == PR_ONPT1 || nFlg == PR_ONPT2 || nFlg == PR_INSIDE)
{
// 线2起点在线1内(包括端点)
line2.m_bDeleted = TRUE; //线2要合并到线1内
XPoint ptOnLine1;
line2.GetEndPoint().Project(&line1, ptOnLine1); //那么需要投影后,才能判断在线上还是在外面
nFlg1 = (ptOnLine1 & line1);
if (nFlg1 == PR_EXTEND)
{
// 线2的终点在线1的延长线上, 判断在起始延长还是终止延长
double *pNearPoint = line1.NearPoint(line2.GetEndPoint());
BOOL bIncludeLine1Start = (pNearPoint == &(line1.StartPoint().x));
if (bIncludeLine1Start) //线1的起点在线2内
{
line1.SetStartPoint(line2.GetEndPoint()); //因此改变线1的起点
}
else
{
line1.SetEndPoint(line2.GetEndPoint()); //否则线1的终点在线2内,因此改变线1的终点
}
}
else
{
// 否则线2整个位于线1内部, 仅仅删除就可以了
ASSERT(nFlg1!=PR_OUTSIDE);
}
}
else if (nFlg1 == PR_ONPT1 || nFlg1 == PR_ONPT2 || nFlg1 == PR_INSIDE)
{
// 线2终点线1内(包括端点)
line2.m_bDeleted = TRUE;
XPoint ptOnLine1;
line2.GetStartPoint().Project(&line1, ptOnLine1);
nFlg = (ptOnLine1 & line1);
if (nFlg == PR_EXTEND)
{
// 线2的起点在线1的延长线上, 判断在起始延长还是终止延长
double *pNearPoint = line1.NearPoint(line2.GetStartPoint());
if (pNearPoint == &(line1.StartPoint().x))
{
line1.SetStartPoint(line2.GetStartPoint());
}
else
{
line1.SetEndPoint(line2.GetStartPoint());
}
}
else
{
ASSERT(nFlg!=PR_OUTSIDE); // 否则线2整个位于线1内部, 仅仅删除就可以了
}
}
else if ((nFlg == PR_EXTEND && nFlg1 == PR_EXTEND)) //线2的两端都在线一的外边
{
int nFlg2 = (line1.GetStartPoint() & line2);
if (nFlg2 == PR_INSIDE)
{
line1.SetStartPoint(line2.GetStartPoint());
line1.SetEndPoint(line2.GetEndPoint());
line2.m_bDeleted = TRUE;
}
}
}
}
}
}
if (g_bEchoSearch)
{
acedRestoreStatusBar();
}
ss1.Reset();
if (bIntsect)
{
for (int nn = 0; nn < nLen; nn++)
{
XDRdupLineNode *pNode = lstNewCurves[nn];
int nCount = pNode->entArray.length();
for (int i = 0; i < nCount; i++)
{
XCurveObject &line1 = *m_ssCurves[pNode->entArray[i]];
if (line1.IsDeleted())
{
pNode->entArray.removeAt(i);
i--;
nCount--;
}
}
}
IntersectCurves(ss1);
}
else
{
int nCount = m_ssCurves.Length();
for (int nn = 0; nn < nCount; nn++)
{
if (!m_ssCurves[nn]->IsDeleted())
{
ss1.Append(new XCurveSegment(*m_ssCurves[nn]));
}
}
}
return;
}
void XRdupCurve::SpecialRemoveDupCurve(const DList<XCurveSegment> & ss1,
DList<XCurveSegment> & ssOut)
{
int nLen1 = ss1.Length();
if (!nLen1)
{
return ;
}
m_shortLineNum = m_delLineNum = 0;
m_ssCurves.Reset();
for (int i = 0; i < nLen1; i++)
{
m_ssCurves.Append(new XCurveObject(ss1[i]));
}
DList<XDRdupLineNode> lstNewCurves;
makeArrayByAngle(m_ssCurves, lstNewCurves);
int nLen = lstNewCurves.Length();
for (int nn = 0; nn < nLen; nn++)
{
XDRdupLineNode *pNode = lstNewCurves[nn];
int nCount = pNode->entArray.length();
for (int i = 0; i < nCount - 1; i++)
{
XCurveObject &line1 = *m_ssCurves[pNode->entArray[i]];
if (line1.IsDeleted())
{
continue;
}
for (int j = i + 1; j < nCount; j++)
{
XCurveObject &line2 = *m_ssCurves[pNode->entArray[j]];
if (line2.IsDeleted())
{
continue; // 线2已经被删除或者两线类型不匹配
}
if ((line1.GetStartPoint().Distance2d(line2.StartPoint()) < _DIST_SNAP
&& line1.GetEndPoint().Distance2d(line2.EndPoint()) < _DIST_SNAP)
|| (line1.GetStartPoint().Distance(line2.EndPoint()) < _DIST_SNAP
&& line1.GetEndPoint().Distance2d(line2.StartPoint()) < _DIST_SNAP))
{
line1.m_bDeleted = TRUE;
line2.m_bDeleted = TRUE;
break;
}
}
}
}
int nCount = m_ssCurves.Length();
for (int nn = 0; nn < nCount; nn++)
{
if (!m_ssCurves[nn]->IsDeleted())
{
ssOut.Append(new XCurveSegment(*m_ssCurves[nn]));
}
}
}
GEOAPI void xdSpecialRemoveDupCurve(const DList<XCurveSegment> &ssIn, DList<XCurveSegment> &ssOut)
{
XRdupCurve rm;
rm.SpecialRemoveDupCurve(ssIn, ssOut);
}
GEOAPI void xdRemoveDupCurves(DList<XCurveSegment> &lstCurves, BOOL bExactDup,BOOL bIntsect)
{
XRdupCurve rm;
rm.removeDupCurve(lstCurves, bExactDup, bIntsect);
}
GEOAPI void xdRemoveDupLines(PickSet &ss)
{
XRdupCurve rm;
rm.RemoveDupLine(ss);
}