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

718 lines
18 KiB
C++

//-------------------------------------------------------------------------------------------------------+
// Copyright (C), 1998-2007, Beijing Tangent Software Co. Ltd.
// = FileName : TGGeRdupCurveOper 类
// = Version : ver2.0
// = Author : wlw
// = CreateDate : 2002-09-09
// = Description: TGGeRdupCurveOper 定义
// = Maintainers:
//
//-------------------------------------------------------------------------------------------------------+
#include "StdAfx.h"
#include "TGGeRdupCurveOper.h"
#include "TchGlobalCurveFunc.h"
#include "TGGeCurveInline.h"
static int CompareDouble(const double *p1, const double *p2)
{
if (*p1 > *p2)
{
return 1;
}
return -1;
}
TGGeRdupCurveOper::TGGeRdupCurveOper()
{
m_slength = _DIST_SNAP;
m_shortLineNum = 0;
m_delLineNum = 0;
}
TGGeRdupCurveOper::~TGGeRdupCurveOper()
{
}
int TGGeRdupCurveOper::FindNode(double dKey, TDPtrList<TDRdupLineNode> &lstNewCurves)
{
int nLen = lstNewCurves.Length();
if (!nLen)
{
return -1;
}
for (int i = 0; i < nLen; i++)
{
double nPrec = _angSnap;
if (IsSameDrt(lstNewCurves[i]->key, dKey, nPrec))
{
return i;
}
}
return -1;
}
/*wlw注掉,由于没有使用的地方
int compareDList(const TDRdupLineNode *p1, const TDRdupLineNode *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 TGGeRdupCurveOper::distanceOfPtToLine(TADSGePoint3d pt,TADSGePoint3d ptStart,TADSGePoint3d 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 TGGeRdupCurveOper::getMinPoint(AcDbIntArray *ids,TADSGePoint3d &ptMin)
{
TADSGePoint3d ptTmp(1e100,1e100,0);
int nLen = ids->length();
for (int i = 0;i<nLen;i++)
{
TGGeCurveSegSeg *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 TGGeRdupCurveOper::makeArrayByAngle(TDPtrList<TGGeCurveSegSeg> &ss, TDPtrList<TDRdupLineNode> &lstNewCurves)
{
TADSGePoint3d ptStart,ptEnd;
double dAngle = 0;
int nLen = ss.Length();
if (!nLen)
{
return FALSE;
}
int nBar = 0;
for (long i = 0; i < nLen; i++)
{
TGGeCurveSegSeg &ent = *ss[i];
if (ent.m_bDeleted)
{
continue;
}
ASSERT(ent.Is(CURVE_LINE));
ptStart = ent.GetStartPoint();
ptEnd = ent.GetEndPoint();
dAngle = ads_angle(ptStart,ptEnd);
TDRdupLineNode * node = new TDRdupLineNode;
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 TGGeRdupCurveOper::setShortLineLength(double dShortLine)
{
m_slength = fabs(dShortLine);
return;
}
// 在断点处断开单线
// Status: ss is both as input and output
// 加速算法
void TGGeRdupCurveOper::IntersectCurves(TDPtrList<TGGeCurveSegment> &lstCurves)
{
TDPtrList<TGGeCurveSegment> ss1;
int nCount = m_ssCurves.Length();
for (int i = 0; i < nCount; i++)
{
TGGeCurveSegSeg *pSeg = m_ssCurves[i];
if (!pSeg->IsDeleted() && !pSeg->Is(CURVE_CIRCLE))
{
TGGeCurveSegment *pNewSeg = new TGGeCurveSegment(*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;
}
TDPtrList<double> *lstDistArray = new TDPtrList<double> [nLen1];
for (i = 0; i < nLen1 - 1; i++)
{
if (g_bEchoSearch && !(i % nStep))
{
acedSetStatusBarProgressMeterPos(i);
}
TGGeCurveSegment &line1 = *ss1[i];
TADSGePoint3d &ptStart = line1.StartPoint();
for (int j = i + 1; j < nLen1; j++)
{
TGGeCurveSegment &line2 = *ss1[j];
TADSGePoint3d ptInt1;
if (!g_bFastCalMode)
{
if (line1.TGGeLine::Intersection(&(const TGGeLine &)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 (i = 0; i < nLen1; i++)
{
TDPtrList<double> &lstDistSeg = lstDistArray[i];
TGGeCurveSegment &line1 = *ss1[i];
double nDist0 = line1.GetStartPoint().Distance2d(line1.EndPoint());
lstDistSeg.QuickSort(CompareDouble);
lstDistSeg.Append(new double(nDist0));
double nDirection = line1.TGGeLine::Direction();
TADSGePoint3d &ptStart = line1.StartPoint();
TADSGePoint3d ptS = ptStart;
for (int j = 0; j < lstDistSeg.Length(); j++)
{
TADSGePoint3d ptE;
ads_polar(ptStart, nDirection, *lstDistSeg[j], ptE);
if (ptS.Distance2d(ptE) > _DIST_SNAP)
{
lstCurves.Append(new TGGeCurveSegment(ptS, ptE, 0.0));
}
ptS = ptE;
}
}
delete [] lstDistArray;
if (g_bEchoSearch)
{
acedRestoreStatusBar();
}
}
// 对直线消除重线
void TGGeRdupCurveOper::RemoveDupLine(TPickEntSet &ss)
{
TPickEntSet ssLine(SS_FREE), ssLine1(SS_FREE);
ssLine += ss;
ssLine.BaseFilter(TRBList(RTDXF0, _T("LINE"), NULL));
TPickEntSet ssDel(SS_FREE);
m_shortLineNum = m_delLineNum = 0;
m_ssCurves.Reset();
long nLen1 = ssLine.Length();
for (long idx = 0L; idx<nLen1; idx++)
{
TEntitySet ent = ssLine[idx];
TGGeCurveSegment seg(ent);
seg.SetElevation(0.0);
if (seg.GetLength() <= m_slength) //超短线,删除
{
m_shortLineNum++;
ssDel += ent;
}
else
{
m_ssCurves.Append(new TGGeCurveSegSeg(seg));
ssLine1 += ent;
}
}
TDPtrList<TDRdupLineNode> lstNewCurves;
makeArrayByAngle(m_ssCurves, lstNewCurves);
int nLen = lstNewCurves.Length();
if (g_bEchoSearch)
{
TCString 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);
}
TDRdupLineNode *pNode = lstNewCurves[nn];
int nCount = pNode->entArray.length();
for (int i = 0; i < nCount; i++)
{
TGGeCurveSegSeg &line1 = *m_ssCurves[pNode->entArray[i]];
if (line1.IsDeleted())
{
continue;
}
for (int j = 0; j < nCount; j++)
{
TGGeCurveSegSeg &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内
TADSGePoint3d 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;
TADSGePoint3d 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 (nn = 0; nn < nCount; nn++)
{
TEntitySet 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 TGGeRdupCurveOper::removeDupCurve(TDPtrList<TGGeCurveSegment> &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++)
{
TGGeCurveSegment &ent = *ss1[k];
if (ent.GetLength() <= m_slength) //超短线,删除
{
m_shortLineNum++;
}
else
{
m_ssCurves.Append(new TGGeCurveSegSeg(*ss1[k]));
}
}
TDPtrList<TDRdupLineNode> lstNewCurves;
makeArrayByAngle(m_ssCurves, lstNewCurves);
int nLen = lstNewCurves.Length();
if (g_bEchoSearch)
{
TCString 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);
}
TDRdupLineNode *pNode = lstNewCurves[nn];
int nCount = pNode->entArray.length();
for (int i = 0; i < nCount; i++)
{
TGGeCurveSegSeg &line1 = *m_ssCurves[pNode->entArray[i]];
if (line1.IsDeleted())
{
continue;
}
for (int j = 0; j < nCount; j++)
{
TGGeCurveSegSeg &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内
TADSGePoint3d 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;
TADSGePoint3d 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++)
{
TDRdupLineNode *pNode = lstNewCurves[nn];
int nCount = pNode->entArray.length();
for (int i = 0; i < nCount; i++)
{
TGGeCurveSegSeg &line1 = *m_ssCurves[pNode->entArray[i]];
if (line1.IsDeleted())
{
pNode->entArray.removeAt(i);
i--;
nCount--;
}
}
}
IntersectCurves(ss1);
}
else
{
int nCount = m_ssCurves.Length();
for (nn = 0; nn < nCount; nn++)
{
if (!m_ssCurves[nn]->IsDeleted())
{
ss1.Append(new TGGeCurveSegment(*m_ssCurves[nn]));
}
}
}
return;
}
void TGGeRdupCurveOper::SpecialRemoveDupCurve(const TDPtrList<TGGeCurveSegment> & ss1,
TDPtrList<TGGeCurveSegment> & 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 TGGeCurveSegSeg(ss1[i]));
}
TDPtrList<TDRdupLineNode> lstNewCurves;
makeArrayByAngle(m_ssCurves, lstNewCurves);
int nLen = lstNewCurves.Length();
for (int nn = 0; nn < nLen; nn++)
{
TDRdupLineNode *pNode = lstNewCurves[nn];
int nCount = pNode->entArray.length();
for (int i = 0; i < nCount - 1; i++)
{
TGGeCurveSegSeg &line1 = *m_ssCurves[pNode->entArray[i]];
if (line1.IsDeleted())
{
continue;
}
for (int j = i + 1; j < nCount; j++)
{
TGGeCurveSegSeg &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 (nn = 0; nn < nCount; nn++)
{
if (!m_ssCurves[nn]->IsDeleted())
{
ssOut.Append(new TGGeCurveSegment(*m_ssCurves[nn]));
}
}
}
GEOAPI void TdSpecialRemoveDupCurve(const TDPtrList<TGGeCurveSegment> &ssIn, TDPtrList<TGGeCurveSegment> &ssOut)
{
TGGeRdupCurveOper rm;
rm.SpecialRemoveDupCurve(ssIn, ssOut);
}
GEOAPI void TdRemoveDupCurves(TDPtrList<TGGeCurveSegment> &lstCurves, BOOL bExactDup,BOOL bIntsect)
{
TGGeRdupCurveOper rm;
rm.removeDupCurve(lstCurves, bExactDup, bIntsect);
}
GEOAPI void TdRemoveDupLines(TPickEntSet &ss)
{
TGGeRdupCurveOper rm;
rm.RemoveDupLine(ss);
}