and i got some logic and modified in it i putted epsilon(tolerance) but i don't know for how much put tolerance so from your logic last else block is good thing but its not work with my logic
AcDbVoidPtrArray PolylineFromRegion(AcDbRegion *reg)
{
// We will return a collection of entities
// (should include closed Polylines and other
// closed curves, such as Circles)
AcDbVoidPtrArray res;
// Explode Region -> collection of Curves / Regions
Acad::ErrorStatus es = Acad::eOk;
AcDbVoidPtrArray cvs;
if (reg == NULL)
return res;
es = reg->explode(cvs);
// Create a plane to convert 3D coords
// into Region coord system
AcGeVector3d vec;
es = reg->getNormal(vec);
AcGePlane *pl = new AcGePlane(AcGePoint3d(0,0,0),vec);
//es = reg->getPlane(pl);
if(pl != NULL)
{
bool finished = false;
while (!finished && cvs.length() > 0)
{
// Count the Curves and the non-Curves, and find
// the index of the first Curve in the collection
int cvCnt = 0, nonCvCnt = 0, fstCvIdx = -1;
for (int i = 0; i < cvs.length(); i++)
{
AcDbCurve *tmpCv = (AcDbCurve *)cvs.at(i);
//AcGePoint3d stPnt;
//tmpCv->getStartPoint(stPnt);
//pl = new AcGePlane(stPnt,vec);
//if (tmpCv == NULL || tmpCv->isKindOf(AcDbRegion::desc()) == true)
if(tmpCv == NULL || tmpCv->isA() == AcDbRegion::desc())
nonCvCnt++;
else
{
// Closed curves can go straight into the
// results collection, and aren't added
// to the Curve count
if (tmpCv->isClosed())
{
res.append(tmpCv);
cvs.remove(tmpCv);
// Decrement, so we don't miss an item
i--;
}
else
{
cvCnt++;
if (fstCvIdx == -1)
fstCvIdx = i;
}
}
}
if (fstCvIdx >= 0)
{
// For the initial segment take the first
// Curve in the collection
AcDbCurve *fstCv = (AcDbCurve *)cvs.at(fstCvIdx);
// The resulting Polyline
AcDbPolyline *p = new AcDbPolyline();
// Set common entity properties from the Region
es = p->setPropertiesFrom(reg);
// Add the first two vertices, but only set the
// bulge on the first (the second will be set
// retroactively from the second segment)
// We also assume the first segment is counter-
// clockwise (the default for arcs), as we're
// not swapping the order of the vertices to
// make them fit the Polyline's order
AcGePoint3d pntStartPoint;
fstCv->getStartPoint(pntStartPoint);
AcGePoint2d pntStart, pntEnd;
pntStart.set(pntStartPoint.x, pntStartPoint.y);
p->addVertexAt(p->numVerts(),pntStart,BulgeFromCurve(fstCv, false), 0, 0);
AcGePoint3d pntEndPoint;
fstCv->getEndPoint(pntEndPoint);
pntEnd.set(pntEndPoint.x, pntEndPoint.y);
p->addVertexAt(p->numVerts(),pntEnd,0, 0, 0);
cvs.remove(fstCv);
// The next point to look for
AcGePoint3d nextPt;
fstCv->getEndPoint(nextPt);
// We no longer need the curve
DeleteEntity(fstCv);
// Find the line that is connected to
// the next point
// If for some reason the lines returned were not
// connected, we could loop endlessly.
// So we store the previous curve count and assume
// that if this count has not been decreased by
// looping completely through the segments once,
// then we should not continue to loop.
// Hopefully this will never happen, as the curves
// should form a closed loop, but anyway...
// Set the previous count as artificially high,
// so that we loop once, at least.
int prevCnt = cvs.length() + 1;
while (cvs.length() > nonCvCnt && cvs.length() < prevCnt)
{
prevCnt = cvs.length();
//for(INT_PTR i(0);i<prevCnt;++i) //commented on 26-05-2023: as we remove points from cvs so don't take variable(prevCnt) for loop
for (INT_PTR i(0); i<cvs.length(); ++i)
{
AcDbCurve *cv = (AcDbCurve *)cvs.at(i);
if (cv != NULL)
{
// If one end of the curve connects with the
// point we're looking for...
AcGePoint3d StartPt, EndPt;
cv->getStartPoint(StartPt);
cv->getEndPoint(EndPt);
//if (StartPt == nextPt ||EndPt == nextPt)
double epsilon = 0.00001;
double dist1 = StartPt.distanceTo(nextPt);
double dist2 = EndPt.distanceTo(nextPt);
if (dist1 <= epsilon || dist2 <= epsilon)
{
// Calculate the bulge for the curve and
// set it on the previous vertex
double bulge = BulgeFromCurve(cv, EndPt == nextPt);
if (bulge != 0.0)
p->setBulgeAt(p->numVerts()-1, bulge);
// Reverse the points, if needed
//if (StartPt == nextPt)
if(dist1 <= epsilon)
nextPt = EndPt;
else
// cv.EndPoint == nextPt
nextPt = StartPt;
// Add out new vertex (bulge will be set next
// time through, as needed)
AcGePoint2d nextTempPt;
nextTempPt.set(nextPt.x,nextPt.y);
p->addVertexAt(p->numVerts(),nextTempPt,0, 0, 0);
// Remove our curve from the list, which
// decrements the count, of course
cvs.remove(cv);
DeleteEntity(cv);
//break;
i--;
}
}
}
}
// Once we have added all the Polyline's vertices,
// transform it to the original region's plane
AcGeMatrix3d mat = AcGeMatrix3d::planeToWorld(pl->normal());
p->transformBy(mat);
//RemoveSameVertex(p);
res.append(p);
if (cvs.length() == nonCvCnt)
finished = true;
}
// If there are any Regions in the collection,
// recurse to explode and add their geometry
if (nonCvCnt > 0 && cvs.length() > 0)
{
INT_PTR iLen = cvs.length();
for(INT_PTR j(0);j<cvs.length();++j)
{
AcDbRegion *subReg = (AcDbRegion *)cvs.at(j);
AcDbVoidPtrArray cvs1;
//es = subReg->explode(cvs1);
if (subReg != NULL)
{
AcDbVoidPtrArray subRes = PolylineFromRegion(subReg);
for(INT_PTR k(0);k<subRes.length();++k)
res.append(subRes.at(k));
cvs.remove(subReg);
DeleteEntity(subReg);
}
}
}
if (cvs.length() == 0)
finished = true;
}
}
return res;
}
double BulgeFromCurve(AcDbCurve *cv,bool clockwise)
{
double bulge = 0.0;
AcDbArc *a = (AcDbArc *)cv;
if (a != NULL)
{
double newStart;
// The start angle is usually greater than the end,
// as arcs are all counter-clockwise.
// (If it isn't it's because the arc crosses the
// 0-degree line, and we can subtract 2PI from the
// start angle.)
if (a->startAngle() > a->endAngle())
newStart = a->startAngle() - 8 * atan(double(1));// * Math::Atan(1);
else
newStart = a->startAngle();
// Bulge is defined as the tan of
// one fourth of the included angle
bulge = tan((a->endAngle() - newStart) / 4);
// If the curve is clockwise, we negate the bulge
if (clockwise)
bulge = -bulge;
}
return bulge;
}