//-----------------------------------------------------------------------------+ // Copyright (C), 1998-2007, SH Software Co. Ltd. // = FileName : XPoly2D 类 // = Version : ver2.0 // = Author : zjq // = CreateDate : 2002-09-09 // = Description: XPoly2D 类定义 // = Maintainers: // //-----------------------------------------------------------------------------+ #include "StdAfx.h" #include "XPoly2D.h" #include "XPointList.h" #include "dbregion.h" #include "XPushPrec.h" #include "XDbObject.h" #include "XPoly3D.h" #include "XDirectionCurve.h" #include "List.h" #include "XPolygonEx.h" #include "PointList.h" #include "XGlobalFunc.h" #include "XPrivateGlobalFunc.h" #include "XGlobalCurveFunc.h" #include "geblok3d.h" #include "geblok2d.h" #include "XCurveInline.h" XPoly2D::XPoly2D() : m_nFlag(0) { m_ardbulges.Reset(); } XPoly2D::XPoly2D(const Entity& ent) { Entity entPLine = ent; XString sEntType; XPoint pt; double dTAng = 0.0, dAng = 0.0; entPLine.GetData(0, (TCHAR *)sEntType); if (sEntType == _T("CIRCLE")) { XCurveSegment cir(ent); cir.AsPoly2D(*this); return; } else if (sEntType == _T("LINE") || sEntType == _T("ARC")) { XCurveSegment segTemp(ent); if (!segTemp) { return; } segTemp.AsPoly2D(*this); } if ((sEntType != _T("POLYLINE") && sEntType != _T("LWPOLYLINE")) || entPLine.GetData(70, &m_nFlag) != RTNORM) { return; } int nFlag = m_nFlag; if ((nFlag & 2) || (nFlag & 4) || (nFlag & 16) || (nFlag & 32) || (nFlag & 64)) { return; } if (sEntType == _T("POLYLINE")) { OPENOBJ_BEGIN(entPLine, AcDb::kForRead, AcDb3dPolyline, pLine); if (pLine != NULL) { AcDbObjectIterator* pIter = pLine->vertexIterator(); if (pIter != NULL) { for (pIter->start(); !pIter->done(); pIter->step()) { AcDb3dPolylineVertex *pVertex = NULL; acdbOpenObject(pVertex, pIter->objectId(), AcDb::kForRead); if (pVertex != NULL) { if (pVertex->vertexType() == AcDb::k3dSimpleVertex) { m_ardbulges.Append(new double(0.0)); Append(new XPoint(pVertex->position())); } pVertex->close(); } } delete pIter; } return; } OPENOBJ_END(); Entity subEnt = entPLine; while ( 1 ) { Entity sub_ent; if (ads_entnext(subEnt, sub_ent) != RTNORM) { break; } subEnt = sub_ent; subEnt.FreeGroups(); if (!subEnt.Is(_T("VERTEX"))) { break; } subEnt.GetData(10, pt); subEnt.GetData(42, &dTAng); if (fabs(dTAng) < 1E-6) { m_ardbulges.Append(new double(0.0)); } else { dAng = atan(dTAng) * 4.0; m_ardbulges.Append(new double(dAng)); } Append(new XPoint(pt)); } } else { double dElevation = 0.0; entPLine.GetData(38, &dElevation); resbuf *ebuf = (resbuf *)(entPLine.groups); if (!ebuf) { XGeLib::adsout << _T("\nResbuf error"); } while(ebuf) { resbuf *rb1 = AT_get_resbuf(ebuf, 10); resbuf *rb2 = rb1 ? AT_get_resbuf(rb1, 42) : NULL; if (rb1 && rb2) { dTAng = rb2->resval.rreal; pt = rb1->resval.rpoint; if (fabs(dTAng) < 1E-6) { m_ardbulges.Append(new double(0.0)); } else { dAng = atan(dTAng) * 4.0; m_ardbulges.Append(new double(dAng)); } pt.z = dElevation; Append(new XPoint(pt)); ebuf = rb2->rbnext; } else { break; } } } } XPoly2D::XPoly2D(int nflg) : m_nFlag(nflg) { m_ardbulges.Reset(); } XPoly2D::XPoly2D(const XPoly2D &src) { XPointList::copyFrom(src); m_ardbulges.Reset(); m_ardbulges.copyFrom( src.m_ardbulges ); m_nFlag = src.GetFlag(); } XPoly2D::~XPoly2D() { } void XPoly2D::CopyFrom(const XEntity* pSrc) { if (this != pSrc && pSrc->IsKindOf(XEntity::ePoly2D)) { m_nFlag = ((XPoly2D*)pSrc)->m_nFlag; copyFrom(*((XPoly2D*)pSrc)); m_ardbulges.copyFrom(((XPoly2D*)pSrc)->m_ardbulges); } } int XPoly2D::operator !() const { return (Length() < 2 ? 1 : 0); } XPoly2D& XPoly2D::operator = (const XPoly2D &src) { if (this != &src) { Reset(); m_nFlag = src.m_nFlag; for(int i = 0; i < src.Length(); i++) { const XPoint &pt = src[i]; double val = src.m_ardbulges[i]; Append(new XPoint(pt)); m_ardbulges.Append(new ads_real(val)); } } return *this; } int XPoly2D::IsValid(int nIndex) const { int nLen = Length(); if (nIndex < 0 || nIndex >= nLen) { return 0; } if (!(m_nFlag & 1) && nIndex == nLen - 1) { return 0; } return 1; } int XPoly2D::IsClosed() const { return ((m_nFlag & 0x01) ? 1 : 0); } bool XPoly2D::SetClosed() { if (Length() > 2) { m_nFlag = 1; return true; } return false; } int XPoly2D::TotalSegments() const { int nLen = Length(); return (m_nFlag & 1) ? nLen : nLen - 1; } double XPoly2D::Area() const { return fabs(PathArea()); } void XPoly2D::Reset() { DList::Reset(); m_ardbulges.Reset(); } resbuf* XPoly2D::Fence(int nCirDiv) { XPoly pts; if (MapToPolygon(pts, nCirDiv) == RTNORM) { return (IsClosed() ? pts.Fence() : pts.Polygon()); } return NULL; } resbuf* XPoly2D::Polygon(int nCirDiv) { XPoly pts; if (MapToPolygon(pts, nCirDiv) == RTNORM) { return pts.Polygon(); } return NULL; } void XPoly2D::AppendNode(const XPoint &pt, ads_real dBulge) { assert(Length() == m_ardbulges.Length()); Append(new XPoint(pt)); m_ardbulges.Append(new double(dBulge)); } void XPoly2D::InsertNodeAt(int nIndex, const XPoint &pt, double dBulge) { if (nIndex >= Length()) { AppendNode(pt, dBulge); } else { (*this)[nIndex]; Insert(new XPoint(pt)); m_ardbulges[nIndex]; m_ardbulges.Insert(new double(dBulge)); } } void XPoly2D::RemoveNode(long nIndex) { Remove(nIndex); m_ardbulges.Remove(nIndex); } void XPoly2D::TransformBy(const AcGeMatrix3d &mat) { //zjq 2009-08-31 修改 BOOL bIsMirror = IsMirrorMatrix(mat); for (int i = 0; i < Length(); i++) { XPoint *pt = (*this)[i]; pt->TransformBy(mat); // zjq 2009-08-31 修改,减少循环 if (bIsMirror) { *m_ardbulges[i] = -*(m_ardbulges[i]); } } /* if (IsMirrorMatrix(mat)) { for (int m = 0; m < Length(); m++) { *m_ardbulges[m] = -*(m_ardbulges[m]); } }*/ } XPoint XPoly2D::GetPoint(int nIOFlag, ads_real dDist) { XPoint ptPick; XCurveSegment curve; if (Nth(0, curve) != RTNORM) { return ptPick; } if (nIOFlag == 0) { ptPick = curve.Offset(PathArea() > 0 ? OFFSET_RIGHT : OFFSET_LEFT, dDist, LS_FINITE).MidPoint(); } else { ptPick = curve.Offset(PathArea() > 0 ? OFFSET_LEFT : OFFSET_RIGHT, dDist, LS_FINITE).MidPoint(); } return ptPick; } XPoint XPoly2D::GetInsidePoint() { assert(Length()); XPoly polyTemp; MapToPolygon(polyTemp); XPolygonEx polyEx(polyTemp); XPoint pt; if (polyEx.GetInsidePoint(pt, TRUE) == RTNORM) { return pt; } return GetPoint(0, 10 * _DIST_SNAP); } ads_real XPoly2D::Distance2d() const { int nLen = TotalSegments(); double dRes = 0.0; for (int i = 0; i < nLen; i++) { dRes += Distance2d(i); } return dRes; } ads_real XPoly2D::Distance2d(int nIndex) const { int nLen = Length(); if (nIndex < 0 || nIndex >= nLen) { return 0; } if (!(m_nFlag & 1) && nIndex == nLen - 1) { return 0; } XCurveSegment seg; Nth(nIndex, seg); seg.SetElevation(0.0); return seg.GetLength(); } ads_real XPoly2D::Distance3d() const { int nLen = TotalSegments(); double dRes = 0.0; for (int i = 0; i < nLen; i++) { dRes += Distance3d(i); } return dRes; } ads_real XPoly2D::Distance3d(int nIndex) const { int nLen = Length(); if (nIndex < 0 || nIndex >= nLen) { return 0; } if (!(m_nFlag & 1) && nIndex == nLen - 1) { return 0; } XCurveSegment seg; Nth(nIndex, seg); return seg.GetLength(); } int XPoly2D::HitTestOnCurve(const XPoint &ptTest, double dTol) const { const XPoly2D &polyPath = *this; XPoint pt2d = ptTest; for (int i = 0; i < polyPath.Length(); i++) { if (pt2d.Distance2d(polyPath[i]) < dTol) { return (i + 1); } } XPushPrec vTemp(dTol, _angSnap); int nEdgeNum = polyPath.TotalSegments(); for (int i = 0; i < nEdgeNum; i++) { XCurveSegment seg; polyPath.Nth(i, seg); seg.SetElevation(0.0); if ((pt2d & seg) == PR_INSIDE) { return (-i - 1); } } return 0; } inline int XPoly2D::Nth(int nIndex, XCurveSegment &curve) const { if (!IsValid(nIndex)) { return RTERROR; } static XLine ln; static XArc arc; int nflg = Nth(nIndex, ln, arc); int nFlag = curve.m_nFlag; int nRet = RTNORM; switch(nflg) { case LINE_SEGMENT: //curve = ln; curve.m_startPoint = ln.m_startPoint; curve.m_endPoint = ln.m_endPoint; curve.m_dBulge = 0.0; break; case ARC_SEGMENT: curve = arc; break; default: nRet = RTERROR; } curve.m_nFlag = nFlag; return nRet; } inline int XPoly2D::Nth(int nIndex, XLine &xline, XArc &xarc) const { if (!IsValid(nIndex)) { return RTERROR; } int nLen = Length(); XPoint p1 = (*this)[nIndex]; XPoint p2; if (nIndex == nLen - 1) { p2 = (*this)[0]; } else { p2 = (*this)[nIndex + 1]; } double dAng = m_ardbulges[nIndex]; if (fabs(dAng) > 1.0E-6) { xarc.Set(p1,p2,dAng); return ARC_SEGMENT; } else { //xline.SetPoints(p1, p2); xline.m_startPoint = p1; xline.m_endPoint = p2; return LINE_SEGMENT; } } inline int XPoly2D::Nth(int nIndex, XDirectionCurve &curve) const { if (!IsValid(nIndex)) { return RTERROR; } int nLen = Length(); XPoint p1 = (*this)[nIndex], p2; if (nIndex == nLen - 1) { p2 = (*this)[0]; } else { p2 = (*this)[nIndex + 1]; } double dAng = m_ardbulges[nIndex]; curve.m_startPoint = p1; curve.m_endPoint = p2; curve.m_dBulge = dAng; return RTNORM; } int XPoly2D::Make(const TCHAR *szlay) const { int nLen = Length(); if (nLen <= 1) { return RTERROR; } // LWPLINE AcDbPolyline *pLwPoly = new AcDbPolyline(nLen); for (int i = 0; i < nLen; i++) { double dBuge = tan(m_ardbulges[i] / 4.0); pLwPoly->addVertexAt(i, (*this)[i].AsAcGePoint2d(), dBuge); } if (szlay) { AssureLayer(szlay, LAYSTAT_UNLOCK); pLwPoly->setLayer(szlay); } pLwPoly->setClosed(m_nFlag ? Adesk::kTrue : Adesk::kFalse); double dThickness = 0.0; xg_getvar(_T("THICKNESS"), &dThickness); pLwPoly->setThickness(dThickness); pLwPoly->setElevation((*this)[0].z); AddToModelSpace(pLwPoly, Adesk::kTrue); return RTNORM; } int XPoly2D::MakeSegments(const TCHAR *szlay) const { int nLen = Length(); for (int i = 0; i < nLen; i++) { MakeSegment(i, szlay); } return RTNORM; } int XPoly2D::MakeSegment(int nIndex, const TCHAR *szlay) const { XLine line; XArc arc; int nrc = Nth(nIndex, line, arc); if (nrc == LINE_SEGMENT) { line.Make(szlay); } else if (nrc == ARC_SEGMENT) { arc.Make(szlay); } return RTNORM; } // dDrt--ptRes所在的切向 // 按2d距离求点和方向,注意返回的点是3d int XPoly2D::Polar2d(ads_real dis, XPoint &ptRes, ads_real *dDrt) const { //zjq 2009-08-31 修改存取方式 int nLen = TotalSegments(), iNext = 0; double dSum = 0.0, dAng = 0.0, dsita = 0.0; XPoint p1, p2, pt1, pt2; for (int i = 0; i < nLen; i++) { dSum += Distance2d(i); if (dSum > dis - _DIST_SNAP) { p1 = (*this)[i]; iNext = i + 1; if (iNext >= Length()) { iNext = 0; } p2 = (*this)[iNext]; dAng = m_ardbulges[i]; if (fabs(dAng) > 1E-6) { XArc xarc(p1, p2, dAng); dsita = (dSum - dis) / xarc.m_dRadius; if (dAng > 0) { ads_polar(xarc.m_ptCenter, xarc.m_dendAngle - dsita, xarc.m_dRadius, ptRes); if (dDrt) { *dDrt = CT_std_angle(xarc.m_dendAngle - dsita + PI / 2.0); } } else { ads_polar(xarc.m_ptCenter, xarc.m_dstartAngle + dsita, xarc.m_dRadius, ptRes); if (dDrt) { *dDrt = CT_std_angle(xarc.m_dstartAngle + dsita - PI / 2.0); } } } else { ads_polar(p2, ads_angle(p2, p1), dSum - dis, ptRes); pt1 = p1; pt2 = p2; pt2.z = pt1.z; ptRes.z += (p1.z - p2.z) / ads_distance(pt2, pt1) * (dSum - dis); if (dDrt) { *dDrt = ads_angle(pt1, pt2); } } return i; } } return RTERROR; } int XPoly2D::Polar3d(ads_real dis, XPoint &ptRes, XVector3D &vt) const { //zjq 2009-08-31 修改存取方式 int nLen = TotalSegments(), iNext = 0; double dSum = 0.0, dAng = 0.0, dsita = 0.0; XPoint p1, p2, pt1, pt2; double dDrt = 0.0; for (int i = 0; i < nLen; i++) { dSum += Distance3d(i); if (dSum > dis - _DIST_SNAP) { p1 = (*this)[i]; iNext = i + 1; if (iNext >= Length()) { iNext = 0; } p2 = (*this)[iNext]; dAng = m_ardbulges[i]; if (fabs(dAng) > 1E-6) { XArc xarc(p1, p2, dAng); dsita = (dSum - dis) / xarc.m_dRadius; if (dAng > 0) { ads_polar(xarc.m_ptCenter, xarc.m_dendAngle - dsita, xarc.m_dRadius, ptRes); dDrt = CT_std_angle(xarc.m_dendAngle - dsita + PI / 2.0); } else { ads_polar(xarc.m_ptCenter, xarc.m_dstartAngle + dsita, xarc.m_dRadius, ptRes); dDrt = CT_std_angle(xarc.m_dstartAngle + dsita - PI / 2.0); } vt.x = cos(dDrt); vt.y = sin(dDrt); vt.z = 0; } else { vt = p2 - p1; XVector3D vtNormal = vt; ((AcGeVector3d &)vtNormal).normalize(); vt = vtNormal; vtNormal *= dis - dSum; ptRes = p2 + vtNormal; } return i; } } return RTERROR; } ads_real XPoly2D::PathArea() const { int i = 0; int nflg; XArc arc; XLine line; double dresult = 0.0; while ((nflg = Nth(i, line, arc)) != RTERROR) { if (nflg == LINE_SEGMENT) { dresult += line.PathArea(); } else if (m_ardbulges[i] > 0) { dresult += arc.PathArea(); } else { dresult -= arc.PathArea(); } i++; } return dresult; } int XPoly2D::MapToPolygon(XPoly &pts, int nCirDiv) { //zjq 2009-08-31 修改存取方式 pts.Reset(); int nLen = Length(); int i = 0, n = 0, nNum = 0, nRetFlag = 0; XPoint pt; double dincrement = 0.0; for (i = 0; i < nLen; i++) { if (fabs(*m_ardbulges[i]) < 1E-6) { pts.Append(new XPoint(*(*this)[i])); } else if (i < nLen - 1 || IsClosed()) { XArc arc; XLine xl; nRetFlag = Nth(i, xl, arc); ASSERT(nRetFlag == ARC_SEGMENT); //圆用30边做成 nNum = (int)(arc.Bulge() / (2.0 * PI) * nCirDiv); nNum = max(nNum, 1); dincrement = arc.Bulge() / nNum; for (n = 0; n < nNum; n++) { if (*m_ardbulges[i] > 0) { ads_polar(arc.m_ptCenter, arc.m_dstartAngle + dincrement * n, arc.m_dRadius, pt); } else { ads_polar(arc.m_ptCenter, arc.m_dendAngle - dincrement * n, arc.m_dRadius, pt); } pts.Append(new XPoint(pt)); } } } return RTNORM; } void XPoly2D::Disperse(XPoly2D &polyBase1, int nCirDivSeg) const { XPoly polyBase; AsOpenPoly(polyBase, nCirDivSeg); int nCount = polyBase.Length(); if (IsClosed()) { nCount--; } for (int n = 0; n < nCount; n++) { polyBase1.AppendNode(*polyBase[n]); } polyBase1.SetFlag(m_nFlag); } int XPoly2D::AsOpenPoly(XPoly &pts, int nCirDiv) const { //zjq 2009-08-31 修改存取方式 pts.Reset(); int nLen = Length(); const XPoly2D &poly = *this; int i = 0, n = 0, nNum = 0, nRetFlag = 0; XPoint pt; double dincrement = 0.0; XArc arc; for ( i = 0; i < nLen; i++) { if (fabs(m_ardbulges[i]) < 1E-6) { pts.Append(new XPoint(poly[i])); if (i == nLen - 1 && IsClosed()) { //最后一点为起点 pts.Append(new XPoint(poly[0])); } } else { //Arc if (!IsClosed() && i == nLen - 1) { //不封闭的最后一点 pts.Append(new XPoint(poly[i])); return RTNORM; } XLine xl; nRetFlag = Nth(i, xl, arc); ASSERT(nRetFlag == ARC_SEGMENT); nNum = (int)(arc.Bulge() / (2.0 * PI) * nCirDiv); nNum = max(nNum, 1); dincrement = arc.Bulge() / nNum; if (i == nLen-1 && IsClosed()) { //最后一封闭弧段 nNum += 1; } for (n = 0; n < nNum; n++) { if (m_ardbulges[i] > 0) { ads_polar(arc.m_ptCenter, arc.m_dstartAngle + dincrement * n, arc.m_dRadius, pt); } else { ads_polar(arc.m_ptCenter, arc.m_dendAngle - dincrement * n, arc.m_dRadius, pt); } pts.Append(new XPoint(pt)); } } } return RTNORM; } int XPoly2D::MapToPolygon1(XPoly &pts, double dDeviation) { //zjq 2009-08-31 修改存取方式 pts.Reset(); int nLen = Length(); int i = 0, n = 0, nNum = 0, nRetFlag = 0, nCirDiv = 0; XPoint pt; double dincrement = 0.0; XArc arc; XPoint* pPtScr = NULL; for (i = 0; i < nLen; i++) { if (fabs(*m_ardbulges[i]) < 1E-6) { pPtScr = new XPoint(*(*this)[i]); pts.Append(pPtScr); } else if (i < nLen - 1 || IsClosed()) { //不到最后一点或闭合的最后一段 XLine xl; nRetFlag = Nth(i, xl, arc); ASSERT(nRetFlag == ARC_SEGMENT); if (arc.GetLength() < _DIST_SNAP) { continue; } nCirDiv = GetCirDivNum(arc.m_dRadius, dDeviation); nNum = (int)(arc.Bulge() / (2.0 * PI) * nCirDiv); nNum = max(nNum, 1); dincrement = arc.Bulge() / nNum; for (n = 0; n < nNum; n++) { if (*m_ardbulges[i] > 0) { ads_polar(arc.m_ptCenter, arc.m_dstartAngle + dincrement * n, arc.m_dRadius, pt); } else { ads_polar(arc.m_ptCenter, arc.m_dendAngle - dincrement * n, arc.m_dRadius, pt); } pts.Append(new XPoint(pt)); } } } return RTNORM; } void XPoly2D::Disperse1(XPoly2D &polyBase1, double dDeviation) const { XPoly polyBase; AsOpenPoly1(polyBase, dDeviation); int nCount = polyBase.Length(); if (IsClosed()) { nCount--; } for (int n = 0; n 0) { ads_polar(arc.m_ptCenter, arc.m_dstartAngle + dincrement * n, arc.m_dRadius, pt); } else { ads_polar(arc.m_ptCenter, arc.m_dendAngle - dincrement * n, arc.m_dRadius, pt); } pts.Append(new XPoint(pt)); } } } return RTNORM; } double XPoly2D::PathDistance2d(XPoint ptHit) const { double nRet = 0.0; int nHitLeft = HitTestOnCurve(ptHit); if (nHitLeft < 0) { int iLeft = abs(nHitLeft) - 1; XDirectionCurve leftHitCurve; Nth(iLeft, leftHitCurve); nRet = leftHitCurve.PathDistance(ptHit); for (int k = 0; k < iLeft; k++) { Nth(k, leftHitCurve); nRet += leftHitCurve.GetLength(); } } return nRet; } int XPoly2D::CreatePface(int nCirDiv, const TCHAR *pszLay) { XPoly pts; MapToPolygon(pts, nCirDiv); return pts.CreatePface(pszLay); } int XPoly2D::GetExtend(ads_point lowPt, ads_point upPt) const { int nNum = TotalSegments(); if (!nNum) { return RTERROR; } XCurveSegment seg; XPoint ptlow, ptup; ptlow = ptup = ((*this)[0]); for (int n = 0; n < nNum; n++) { if (Nth(n, seg) != RTNORM) { continue; } XPoint pt1, pt2; seg.GetExtend(pt1, pt2); ptlow = Min(ptlow, pt1); ptup = Max(ptup, pt2); } ptlow > lowPt; ptup > upPt; return RTNORM; } // 没有判断边重合的情况 BOOL XPoly2D::IsSelfIntersect() const { const XPoly2D &polyOutline = *this; int nLen = polyOutline.Length(); XArc xa; for (int i = 0; i < nLen - 2; i++) { XLine ln0(LS_FINITE); polyOutline.Nth(i, ln0, xa); if (ln0.GetLength() < _DIST_SNAP) { continue; } for (int j = i + 2; j < ((i == 0 && m_nFlag == 1) ? (nLen - 1) : nLen); j++) { XLine ln1(LS_FINITE); polyOutline.Nth(j, ln1, xa); if (ln1.GetLength() < _DIST_SNAP) { continue; } XPoint ptInt; if (ln0.Intersection(&ln1, ptInt)) { return TRUE; } } } return FALSE; } int XPoly2D::AppendSegment(const XCurveSegment &curve, int bMinus, int bFinal) { if (bMinus) { Append(new XPoint(curve.GetEndPoint())); m_ardbulges.Append(new double(-curve.GetBulge())); if (bFinal && !(m_nFlag & 0x01)) { Append(new XPoint(curve.GetStartPoint())); m_ardbulges.Append(new double(0.0)); } } else { Append(new XPoint(curve.GetStartPoint())); m_ardbulges.Append(new double(curve.GetBulge())); if (bFinal && !(m_nFlag & 0x01)) { Append(new XPoint(curve.GetEndPoint())); m_ardbulges.Append(new double(0.0)); } } return RTNORM; } int XPoly2D::Compress(bool bUnionCurve) { if (Length() < 1) { return RTERROR; } const XPoly2D &poly = *this; List ptList; List anList; ptList.AddTail(poly[0]); long i(1); for (i = 1; i < Length(); i++) { if (ptList.GetCurData() != poly[i]) { ptList.AddTail(poly[i]); anList.AddTail(*(m_ardbulges[i - 1])); } } anList.AddTail(*(m_ardbulges[i - 1])); if (IsClosed()) { if (ptList.GetLength() > 1 && poly[0] == ptList.GetCurData()) { ptList.DelCur(); anList.DelCur(); } } if (ptList.GetLength() < Length()) { Reset(); m_ardbulges.Reset(); for (ptList.MoveToFirst(), anList.MoveToFirst(); !ptList.IsOut(); ptList.MoveToNext(), anList.MoveToNext()) { AppendNode(ptList.GetCurData(), anList.GetCurData()); } } if (!bUnionCurve) { return RTNORM; } XPoly2D destPoly(m_nFlag); int nTotalSeg = TotalSegments(); XCurveSegment curve; int bMinusCurve = 0, bMinusSeg = 0, bMerged = 0; for (int n = 0; n < nTotalSeg; n++) { XCurveSegment seg; Nth(n, seg); if (!seg) { continue; } bMinusSeg = (*m_ardbulges[n] < -1.0E-8); bMerged = 0; if (!curve) { curve = seg; bMinusCurve = bMinusSeg; continue; } else { bMerged = MergeCurve(curve, seg, bMinusCurve, bMinusSeg); } if (!bMerged) { destPoly.AppendSegment(curve, bMinusCurve); curve = seg; bMinusCurve = bMinusSeg; } } if (!curve) { return RTERROR; } else { destPoly.AppendSegment(curve, bMinusCurve, 1); } if ((destPoly.GetFlag() & 0x01) && destPoly.TotalSegments() >= 2) { int nTotalDest = destPoly.TotalSegments(); int bMinusFirst = (destPoly.GetBulge(0) < -1.0E-8); int bMinusFinal = (destPoly.GetBulge(nTotalDest - 1) < -1.0E-8); XCurveSegment curveFirst, curveFinal; destPoly.Nth(0, curveFirst); destPoly.Nth(nTotalDest - 1, curveFinal); if (MergeCurve(curveFinal, curveFirst, bMinusFinal, bMinusFirst)) { if (bMinusFinal) { destPoly.SetBulge(0,-curveFinal.GetBulge()); destPoly.SetPointListAt(0, curveFinal.EndPoint()); } else { destPoly.SetBulge(0, curveFinal.GetBulge()); destPoly.SetPointListAt(0, curveFinal.StartPoint()); } destPoly.RemoveBugle(nTotalDest - 1); destPoly.RemovePointListAt(nTotalDest - 1); } } *this = destPoly; return RTNORM; } int XPoly2D::Reverse() { if (Length() < 2) { return RTERROR; } XPoly2D destPoly; int nTotalSeg = TotalSegments(); XDirectionCurve cv; for (int i = nTotalSeg - 1; i >= 0; i--) { Nth(i, cv); destPoly.AppendNode(cv.EndPoint(), -cv.GetBulge()); } if (!(m_nFlag & 0x01)) { destPoly.AppendNode(*((*this)[0]), -(*m_ardbulges[nTotalSeg])); } destPoly.SetFlag(m_nFlag); *this = destPoly; return RTNORM; } int XPoly2D::Offset(ads_real dDist, XPoly2D &destPoly) const { int nTotalSeg = TotalSegments(); if (!nTotalSeg) { return RTERROR; } if (fabs(dDist) < _DIST_SNAP) { destPoly = *this; return RTNORM; } destPoly.Reset(); destPoly.SetFlag(m_nFlag); XDirectionCurve finalMidSeg, lastSeg; if (m_nFlag & 0x01) { Nth(nTotalSeg - 1, finalMidSeg); lastSeg = finalMidSeg.Offset(dDist, LS_INFINITE); if (!lastSeg) { return RTERROR; } } XPoint nextPt,pt1, pt2, curPt; XDirectionCurve curMidSeg, curSeg, nextMidSeg, nextSeg; int nNum = 0, nextIndex = 0; XArc arc; for (int i = 0; i < nTotalSeg; i++) { Nth(i, curMidSeg); curSeg = curMidSeg.Offset(dDist, LS_INFINITE); if (!curSeg) { return RTERROR; } if (!i) { // 求当前点 if (!lastSeg) { curPt = curSeg.GetStartPoint(); } else { nNum = curSeg.Intersection(lastSeg, pt1, pt2); if (nNum == 2) { curPt = XLine(pt1, pt2).NearPoint(curSeg.GetStartPoint()); } else if (nNum == 1) { curPt = pt1; } else { if (CT_IsSameDrt(curSeg.IDirection(0), lastSeg.IDirection(1), _angSnap)) { //同方向, 两段连接. curPt = curSeg.GetStartPoint(); } else { return RTERROR; } } } } else { curPt = nextPt; } // 求下一个端点 if (i == nTotalSeg - 1 && !(m_nFlag & 0x01)) { //不封闭的最后一段 nextPt = curSeg.GetEndPoint(); } else { //为最后时下一段为起始 nextIndex = i >= nTotalSeg - 1 ? 0 : i + 1; Nth(nextIndex, nextMidSeg); nextSeg = nextMidSeg.Offset(dDist, LS_INFINITE); if (!nextSeg) { return RTERROR; } nNum = curSeg.Intersection(nextSeg, pt1, pt2); if (nNum == 2) { nextPt = XLine(pt1, pt2).NearPoint(curSeg.GetEndPoint()); } else if (nNum == 1) { nextPt = pt1; } else { if (CT_IsSameDrt(curSeg.IDirection(1), nextSeg.IDirection(0), _angSnap)) { nextPt = curSeg.GetEndPoint(); } else { return RTERROR; } } } lastSeg = curSeg; if (curSeg.Is(CURVE_ARC)) { arc = curSeg.GetArc(); if (!curSeg.IsMinusArc()) { //逆时针 arc.SetStarAngle(ads_angle(arc.GetCenterPt(), curPt)); arc.SetEndAngle(ads_angle(arc.GetCenterPt(), nextPt)); curSeg.SetBulge(arc.Bulge()); } else { arc.SetStarAngle(ads_angle(arc.GetCenterPt(), nextPt)); arc.SetEndAngle(ads_angle(arc.GetCenterPt(), curPt)); curSeg.SetBulge(-arc.Bulge()); } curSeg.SetStartPoint(curPt); curSeg.SetEndPoint(nextPt); } assert(!curSeg.Is(CURVE_CIRCLE)); //加一段 destPoly.Append(new XPoint(curPt)); destPoly.m_ardbulges.Append(new double(curSeg.GetBulge())); if (i == nTotalSeg - 1 && !(m_nFlag & 0x01)) { destPoly.Append(new XPoint(nextPt)); destPoly.m_ardbulges.Append(new double(0.0)); } } return RTNORM; } int XPoly2D::HasArcSegment() const { for (int i = 0; i < TotalSegments(); i++) { if (fabs(m_ardbulges[i]) > 1.0E-6) { return 1; } } return 0; } int XPoly2D::QuickOffset(ads_real dDist, XPoly2D &destPoly) const { const XPoly2D &basePoly = *this; destPoly.Reset(); destPoly.m_nFlag = m_nFlag; int nVertexNum = basePoly.Length(); XDirectionCurve prevEdge; int bIsClosed = ((basePoly.m_nFlag & 0x01) != 0); if (bIsClosed) { basePoly.Nth(nVertexNum - 1, prevEdge); } XPoint newVertex; for (int j = 0; j < nVertexNum; j++) { XDirectionCurve curEdge; double dFromDirection, dToDirection; if (j == nVertexNum - 1) { dToDirection = CT_std_angle(prevEdge.IDirection(1) - PI); dFromDirection = prevEdge.IDirection(1); if (bIsClosed) { basePoly.Nth(nVertexNum - 1, curEdge); dFromDirection = CT_std_angle(curEdge.IDirection(0) - PI); } } else { basePoly.Nth(j, curEdge); dFromDirection = CT_std_angle(curEdge.IDirection(0) - PI); dToDirection = curEdge.IDirection(0); if (j > 0 || bIsClosed) { dToDirection = CT_std_angle(prevEdge.IDirection(1) - PI); } } double dDirection = XSector(dFromDirection, dToDirection).MidAngle(); const XPoint &thisVertex = basePoly[j]; double dSinAng = fabs(sin(CT_std_angle(dDirection - dFromDirection))); if (fabs(dSinAng) < 1E-6) { return RTERROR; } else { ads_polar(thisVertex, dDirection, dDist / dSinAng, newVertex); } destPoly.AppendNode(newVertex, m_ardbulges[j]); prevEdge = curEdge; } XPoint ptMid; double dAbsBulge; assert(TotalSegments() == destPoly.TotalSegments()); for (int i = 0; i < TotalSegments(); i++) { XDirectionCurve cvSrc, cvDest, dv; Nth(i, cvSrc); destPoly.Nth(i, cvDest); if (fabs(cvSrc.GetBulge()) > 1.0E-5) { XDirectionCurve dv = cvSrc.Offset(dDist, LS_FINITE); if (!dv) { return RTERROR; } dv.GetArc().MidPoint(ptMid); XArc ar(cvDest.GetStartPoint(), ptMid, cvDest.GetEndPoint()); dAbsBulge = ar.Bulge(); if (dAbsBulge < 1.0E-5) { return RTERROR; } *destPoly.m_ardbulges[i] = (cvSrc.GetBulge() > 0) ? dAbsBulge : -dAbsBulge; } } return RTNORM; } AcDbRegion* XPoly2D::AsRegion() const { const XPoly2D &poly = *this; if (!poly.IsClosed()) { return NULL; } AcDbPolyline pline; PolyConvert(poly, pline); AcDbVoidPtrArray curveSegments; curveSegments.append(&pline); AcDbVoidPtrArray regions; if (AcDbRegion::createFromCurves(curveSegments, regions) == Acad::eOk && regions.length() > 0) { AcDbRegion *regioni = (AcDbRegion *)regions[0]; regions.removeAt(0); ReleaseEntSet(regions); return regioni; } //如果整个pline创建region,不成功的时候,再炸开 AcDbVoidPtrArray explodeSegments; pline.explode(explodeSegments); AcDbVoidPtrArray regions2; if (AcDbRegion::createFromCurves(curveSegments, regions2) == Acad::eOk && regions2.length() > 0) { AcDbRegion *regioni = (AcDbRegion *)regions2[0]; regions2.removeAt(0); ReleaseEntSet(regions2); return regioni; } ReleaseEntSet(explodeSegments); return NULL; } bool XPoly2D::IsRegionInclude(const XPoly2D& poly) const { XPoly2D poly1, poly2; poly1 = *this; poly2 = poly; poly1.SetElevation(0.0); poly2.SetElevation(0.0); AcDbRegion *pRegion1 = poly1.AsRegion(); AcDbRegion *pRegion2 = poly2.AsRegion(); double area0; double area1; if (pRegion1 != NULL && pRegion2 != NULL) { pRegion1->getArea(area0); if (pRegion1->booleanOper(AcDb::kBoolUnite,pRegion2) == Acad::eOk) { pRegion1->getArea(area1); if (fabs(area1 - area0) < 1E-6) { delete pRegion1; delete pRegion2; return true; } } } if (pRegion1 != NULL) { delete pRegion1; } if (pRegion2 != NULL) { delete pRegion2; } return false; } bool XPoly2D::IsRegionOverlap(const XPoly2D& poly) const { XPoly2D poly1, poly2; poly1 = *this; poly2 = poly; poly1.SetElevation(0.0); poly2.SetElevation(0.0); AcDbRegion *pRegion1 = poly1.AsRegion(); AcDbRegion *pRegion2 = poly2.AsRegion(); double area; if (pRegion1 != NULL && pRegion2 != NULL) { if (pRegion1->booleanOper(AcDb::kBoolIntersect, pRegion2) == Acad::eOk) { pRegion1->getArea(area); if (area > 1E-6) { delete pRegion1; delete pRegion2; return true; } } } if (pRegion1 != NULL) { delete pRegion1; } if (pRegion2 != NULL) { delete pRegion2; } return false; } AcDbCurve* XPoly2D::AsAcDbCurve() const { AcDbPolyline* pLwPoly = new AcDbPolyline(Length()); double dBuge = 0.0; for (int i = 0; i < Length(); i++) { dBuge = tan(m_ardbulges[i] / 4.0); pLwPoly->addVertexAt(i, ((*this)[i]).AsAcGePoint2d(), dBuge); } if (Length() >0) { pLwPoly->setElevation((*this)[0].z); } pLwPoly->setClosed(IsClosed() ? Adesk::kTrue : Adesk::kFalse); return pLwPoly; } bool XPoly2D::SetAcDbCurve(AcDbCurve*pCurve) { AcDbPolyline* pLwPoly = AcDbPolyline::cast(pCurve); if (pLwPoly == NULL) { return false; } Reset(); double dElev = pLwPoly->elevation(); AcGePoint2d pt; double dBulge = 0.0; for (long i = 0; i < (long)pLwPoly->numVerts(); i++) { pLwPoly->getPointAt(i, pt); pLwPoly->getBulgeAt(i, dBulge); dBulge = atan(dBulge) * 4; AppendNode(XPoint(pt.x, pt.y, dElev), dBulge); } if (pLwPoly->isClosed()) { m_nFlag = 1; } else { m_nFlag = 0; } return true; } void XPoly2D::SetFlag(int nFlag) { m_nFlag = nFlag; } int XPoly2D::GetFlag() const { return m_nFlag; } void XPoly2D::RemoveBugle(int nIndex) { m_ardbulges.Remove(nIndex); } void XPoly2D::AppendBugle(ads_real dBugle) { m_ardbulges.Append( new double(dBugle)); } double XPoly2D::GetBulge(int nIndex) const { return m_ardbulges[nIndex]; } void XPoly2D::SetBulge(int nIndex, double dBugle) { *m_ardbulges[nIndex] = dBugle; } void XPoly2D::SetPointListAt(int nIndex, const XPoint& pt) { if (Length() > nIndex) { *((*this)[nIndex]) = pt; } } void XPoly2D::RemovePointListAt(int nIndex) { if (Length() > nIndex) { Remove(nIndex); } } void XPoly2D::AppendPointListAt(XPoint* pPt) { Append(pPt); } XPoint* XPoly2D::GetPointListAt(int nIndex) { return (*this)[nIndex]; } const XPoint& XPoly2D::GetPointListAt(int nIndex) const { return (*this)[nIndex]; } XPoly3D XPoly2D::PlaneToWcs(const AcGeVector3d& normal)const { XPoly3D poly3d = *this; AcGeMatrix3d mat; mat.setToPlaneToWorld(normal); poly3d.TransformBy(mat); return poly3d; } int XPoly2D::SetBulges(DList& ardbulges) { if (ardbulges.Length() > 0) { m_ardbulges.Reset(); m_ardbulges.copyFrom(ardbulges); return m_ardbulges.Length(); } return -1; } int XPoly2D::GetBulges(DList& ardbulges) { if (m_ardbulges.Length() > 0) { ardbulges.copyFrom(m_ardbulges); return ardbulges.Length(); } return -1; } DList& XPoly2D::GetBulges() { return m_ardbulges; } bool XPoly2D::IsKindOf(XEntity::TEntityId entType) const { switch(entType) { case XEntity::eEntity: case XEntity::eCurve: case XEntity::ePoly2D: return true; } return false; } XEntity::TEntityId XPoly2D::Type() const { return XEntity::ePoly2D; }