//-------------------------------------------------------------------------------------------------------+ // 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 &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;iat(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 &ss, TDPtrList &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 &lstCurves) { TDPtrList 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 *lstDistArray = new TDPtrList [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 &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 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 &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 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 & ss1, TDPtrList & 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 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 &ssIn, TDPtrList &ssOut) { TGGeRdupCurveOper rm; rm.SpecialRemoveDupCurve(ssIn, ssOut); } GEOAPI void TdRemoveDupCurves(TDPtrList &lstCurves, BOOL bExactDup,BOOL bIntsect) { TGGeRdupCurveOper rm; rm.removeDupCurve(lstCurves, bExactDup, bIntsect); } GEOAPI void TdRemoveDupLines(TPickEntSet &ss) { TGGeRdupCurveOper rm; rm.RemoveDupLine(ss); }