Hello. A query, any of you know any method or function that tells me the orientation of a polyline, if it is clockwise or counter-clockwise
Thanks
Solved! Go to Solution.
Solved by _gile. Go to Solution.
Solved by ccalvo12. Go to Solution.
public static Boolean IsCCW(Transaction acTrans, ObjectId plineId, double precision) { Polyline acPoly = (Polyline)acTrans.GetObject(plineId, OpenMode.ForRead); VladUtils.qacBB.BoundingBox bbtempoPline = VladUtils.qacBB.GetBoundingBox(plineId, acTrans); qNGeom.qContour points = qacPoints.GetEntPoints(plineId); //no bulges if (!acPoly.HasBulges) { return points.IsCCW(precision); } else //bulges { int LowestRightestPointInd = vldplUniversalPolylines.IntersectionAnalytics.GetLowestRightestPointInd(points, precision); //arc arenot lower points if (qNMath.IsSameNumbers(points.Contour[LowestRightestPointInd].y, bbtempoPline.minPoint.y, precision)) { return points.IsCCW(precision); } else { if (acPoly.NumberOfVertices == 2 && !qNMath.IsZero(acPoly.GetBulgeAt(0), precision) && !qNMath.IsZero(acPoly.GetBulgeAt(1), precision)) { if(acPoly.GetArcSegment2dAt(0).Radius> acPoly.GetArcSegment2dAt(1).Radius) { return !acPoly.GetArcSegment2dAt(0).IsClockWise; } else { return !acPoly.GetArcSegment2dAt(1).IsClockWise; } } else { for (int i = 0; i < acPoly.NumberOfVertices; i++) { double curbulge = acPoly.GetBulgeAt(i); if (!qNMath.IsZero(curbulge, precision)) { CircularArc2d ccc = acPoly.GetArcSegment2dAt(i); if (qNMath.IsSameNumbers(ccc.OrthoBoundBlock.BasePoint.Y, bbtempoPline.minPoint.y, precision)) { return !ccc.IsClockWise; } } } } } } return false; }
I would love to publish the ready-to-go code , but to extract and adapt the code will take really long time.
Honestly I can't afford it.
CAD programmers who are interesting in CW/CCW direction are not beginners.
I assume that name of functions and variables are pretty obvious and will not take too long time to recreate functions.
To use the area or angle method to determine the direction necessary to find index of obvious convex point, for example lowest rightest point (GetLowestRightestPointInd)
@VladPaly wrote:I would love to publish the ready-to-go code , but to extract and adapt the code will take really long time.
Honestly I can't afford it.
CAD programmers who are interesting in CW/CCW direction are not beginners.
I assume that name of functions and variables are pretty obvious and will not take too long time to recreate functions.
To use the area or angle method to determine the direction necessary to find index of obvious convex point, for example lowest rightest point (GetLowestRightestPointInd)
I don't think there's anything obvious about the types and their methods that you didn't include.
IMO, what you posted is more of a puzzle than a helpful contribution..
@VladPaly wrote:public static Boolean IsCCW(Transaction acTrans, ObjectId plineId, double precision) { Polyline acPoly = (Polyline)acTrans.GetObject(plineId, OpenMode.ForRead); VladUtils.qacBB.BoundingBox bbtempoPline = VladUtils.qacBB.GetBoundingBox(plineId, acTrans); qNGeom.qContour points = qacPoints.GetEntPoints(plineId); //no bulges if (!acPoly.HasBulges) { return points.IsCCW(precision); } else //bulges { int LowestRightestPointInd = vldplUniversalPolylines.IntersectionAnalytics.GetLowestRightestPointInd(points, precision); //arc arenot lower points if (qNMath.IsSameNumbers(points.Contour[LowestRightestPointInd].y, bbtempoPline.minPoint.y, precision)) { return points.IsCCW(precision); } else { if (acPoly.NumberOfVertices == 2 && !qNMath.IsZero(acPoly.GetBulgeAt(0), precision) && !qNMath.IsZero(acPoly.GetBulgeAt(1), precision)) { if(acPoly.GetArcSegment2dAt(0).Radius> acPoly.GetArcSegment2dAt(1).Radius) { return !acPoly.GetArcSegment2dAt(0).IsClockWise; } else { return !acPoly.GetArcSegment2dAt(1).IsClockWise; } } else { for (int i = 0; i < acPoly.NumberOfVertices; i++) { double curbulge = acPoly.GetBulgeAt(i); if (!qNMath.IsZero(curbulge, precision)) { CircularArc2d ccc = acPoly.GetArcSegment2dAt(i); if (qNMath.IsSameNumbers(ccc.OrthoBoundBlock.BasePoint.Y, bbtempoPline.minPoint.y, precision)) { return !ccc.IsClockWise; } } } } } } return false; }
There is nothing all that obvious about the highlighted members and types.
For example, given a set of points that include the right-most point (10, 10, 0) and the lowest point (5, 5, 0), which of the two is the 'LowestRightestPoint' ?
I also strongly disagree with the suggestion that anyone that needs to know the handed-ness of a polyline is not a beginner.
I prepared the code. Ready to go. Works correctly .Any feedback is welcome.
using System; using System.Collections.Generic; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.Geometry; namespace CCWHub { public class plineCCW { public static Boolean IsEqualacPoints(Point2d firstPoint, Point2d secondPoint, double precision) { return (IsEqual(firstPoint.X, secondPoint.X, precision) && IsEqual(firstPoint.Y, secondPoint.Y, precision)); } public static Boolean IsEqual(double firstNumber, double secondNumber, double precision) { return (Math.Abs(firstNumber - secondNumber)) <= precision ? true : false; } public static Boolean IsInRange(double firstNumber, double secondNumber, double checkedNumber, double precision) { if (IsEqual(firstNumber, checkedNumber, precision)) return true; if (IsEqual(secondNumber, checkedNumber, precision)) return true; if (firstNumber < checkedNumber && checkedNumber < secondNumber) return true; if (secondNumber < checkedNumber && checkedNumber < firstNumber) return true; return false; } public static int GetLowestRightestPointInd(Point2dCollection points, double precision) { double ymin = points[0].Y, xmax = points[0].X; int indexToReturn = 0; for (int i = 1; i < points.Count; i++) { if (ymin > points[i].Y || (IsEqual(ymin, points[i].Y, precision) && xmax < points[i].X)) { indexToReturn = i; ymin = points[i].Y; xmax = points[i].X; } } return indexToReturn; } public static void Reverse(Transaction acTrans, ObjectId plineId) { #region init collectors Polyline acPoly = (Polyline)acTrans.GetObject(plineId, OpenMode.ForWrite); Point2dCollection revercedPoints = new Point2dCollection(); List<double> buldgeList = new List<double>(); List<double> width1 = new List<double>(); List<double> width2 = new List<double>(); #endregion init collectors #region collecting for (int i = acPoly.NumberOfVertices - 1; i >= 0; i--) { revercedPoints.Add(acPoly.GetPoint2dAt(i)); int k = (i == 0) ? acPoly.NumberOfVertices - 1 : i - 1; buldgeList.Add(acPoly.GetBulgeAt(k) * -1); width1.Add(acPoly.GetEndWidthAt(k)); width2.Add(acPoly.GetStartWidthAt(k)); } #endregion collecting #region changing settings for (int i = 0; i < acPoly.NumberOfVertices; i++) { acPoly.SetPointAt(i, revercedPoints[i]); acPoly.SetStartWidthAt(i, width1[i]); acPoly.SetEndWidthAt(i, width2[i]); acPoly.SetBulgeAt(i, buldgeList[i]); } #endregion changing settings } public static Point2dCollection GetPoints2D(Polyline acPoly) { Point2dCollection points = new Point2dCollection(); for (int i = 0; i < acPoly.NumberOfVertices; i++) { points.Add(acPoly.GetPoint2dAt(i)); } return points; } public static Boolean IsPointBelongToLWPlineArcSegment(Polyline acPoly, int indStart, int indEnd, Point2d pointToCheck, double precision) { CircularArc2d circularArc2d = acPoly.GetArcSegment2dAt(indStart); double radius = circularArc2d.Radius; if (pointToCheck.GetDistanceTo(circularArc2d.Center) > radius) { return false; } //bulge double bulge = acPoly.GetBulgeAt(indStart); //translate points by arc center to 0,0 Vector2d centerV = circularArc2d.Center.GetAsVector(); Vector2d startV = acPoly.GetPoint2dAt(indStart).GetAsVector() - centerV; Vector2d endV = acPoly.GetPoint2dAt(indEnd).GetAsVector() - centerV; Vector2d pointToCheckV = pointToCheck.GetAsVector() - centerV; //angle of rotation double angleToRotate = (endV - startV).Angle * -1; //make hord horizontal Vector2d startV1 = startV.RotateBy(angleToRotate); Vector2d endV1 = endV.RotateBy(angleToRotate); Vector2d pointToCheckV1 = pointToCheckV.RotateBy(angleToRotate); double firstLimit = startV1.Y, secondlimit = 0; double radiusCorrection = (Math.Round(startV1.Y / Math.Abs(endV1.Y), 0) > 0) ? 1 : -1; #region finding second limit if (IsEqual(Math.Abs(bulge), 1, precision)) { if (bulge >= 0) { secondlimit = radius * -1; } else { secondlimit = radius; } } else if (Math.Abs(bulge) < 1) { secondlimit = radius * radiusCorrection; } else { secondlimit = radius * radiusCorrection * -1; } #endregion finding second limit //Is in belong to segment Boolean isIn = IsInRange(firstLimit, secondlimit, pointToCheckV1.Y, precision); return isIn; } public static Boolean IsCCWnoarcs(Polyline acPoly, double precision) { Point2dCollection points =GetPoints2D(acPoly); //lrpInd - Lowest Rightest Point Index //plrpInd - previous to lrpInd //nlrpInd - next of lrpInd int lrpInd = GetLowestRightestPointInd(points, precision), plrpInd = (lrpInd == 0) ? points.Count - 1 : lrpInd - 1, nlrpInd = (lrpInd == points.Count - 1) ? 0 : lrpInd + 1; Point2d curPoint = acPoly.GetPoint2dAt(lrpInd), prevPoint = acPoly.GetPoint2dAt(plrpInd), nextPoint = acPoly.GetPoint2dAt(nlrpInd); double curAngle = (nextPoint.GetAsVector() - curPoint.GetAsVector()).Angle, prevAngle = (prevPoint.GetAsVector() - curPoint.GetAsVector()).Angle; return (prevAngle > curAngle) ? true : false; } public static Boolean IsCCWstraigtorarc(Transaction acTrans, ObjectId plineId, double precision) { Boolean isCCW = false; Polyline acPoly = (Polyline)acTrans.GetObject(plineId, OpenMode.ForRead); //Polyline doesn't have any arcs if (!acPoly.HasBulges) { isCCW = IsCCWnoarcs(acPoly, precision); return isCCW; } else //at least one arc { Extents3d acPolyBB = acPoly.GeometricExtents; double bbMinX = acPolyBB.MinPoint.X, bbMinY = acPolyBB.MinPoint.Y, bbMaxX = acPolyBB.MaxPoint.X, bbMaxY = acPolyBB.MaxPoint.Y; #region check for convex arcs touching bounding box for (int i = 0; i < acPoly.NumberOfVertices; i++) { if (acPoly.GetSegmentType(i) == SegmentType.Arc) { double curBulge = acPoly.GetBulgeAt(i); CircularArc2d circularArc2d = acPoly.GetArcSegment2dAt(i); Point2d StartPoint = circularArc2d.StartPoint, EndPoint = circularArc2d.EndPoint, Center = circularArc2d.Center; double StartAngle = (StartPoint.GetAsVector() - Center.GetAsVector()).Angle, EndAngle = (EndPoint.GetAsVector() - Center.GetAsVector()).Angle, Radius = circularArc2d.Radius, totalAngle = circularArc2d.EndAngle; #region angle correction if (curBulge > 0) { if (IsEqual(StartAngle, Math.PI * 2, precision)) StartAngle = 0; if (IsEqual(EndAngle, 0, precision)) EndAngle = Math.PI * 2; } else { if (IsEqual(StartAngle, 0, precision)) StartAngle = Math.PI * 2; if (IsEqual(EndAngle, Math.PI * 2, precision)) EndAngle = 0; } #endregion angle correction #region quadrants double eastQuadrant = Center.X + Radius, northQuadrant = Center.Y + Radius, westQuadrant = Center.X - Radius, southQuadrant = Center.Y - Radius; #endregion quadrants #region check for quadrants //0 if (!IsEqual(eastQuadrant, StartPoint.X, precision) && !IsEqual(eastQuadrant, EndPoint.X, precision) && ((StartAngle > EndAngle && curBulge > 0) || (StartAngle < EndAngle && curBulge < 0)) && IsEqual(eastQuadrant, bbMaxX, precision)) { isCCW = !circularArc2d.IsClockWise; return isCCW; } //90 else if (!IsEqual(northQuadrant, StartPoint.Y, precision) && !IsEqual(northQuadrant, EndPoint.Y, precision) && ((StartAngle < Math.PI * 0.5 && Math.PI * 0.5 < EndAngle && curBulge > 0) || (EndAngle < Math.PI * 0.5 && Math.PI * 0.5 < StartAngle && curBulge < 0)) && IsEqual(northQuadrant, bbMaxY, precision)) { isCCW = !circularArc2d.IsClockWise; return isCCW; } //180 else if (!IsEqual(westQuadrant, StartPoint.X, precision) && !IsEqual(westQuadrant, EndPoint.X, precision) && ((StartAngle < Math.PI && Math.PI < EndAngle && curBulge > 0) || (EndAngle < Math.PI && Math.PI < StartAngle && curBulge < 0)) && IsEqual(westQuadrant, bbMinX, precision)) { isCCW = !circularArc2d.IsClockWise; return isCCW; } //270 else if (!IsEqual(southQuadrant, StartPoint.Y, precision) && !IsEqual(southQuadrant, EndPoint.Y, precision) && ((StartAngle < Math.PI * 1.5 && Math.PI * 1.5 < EndAngle && curBulge > 0) || (EndAngle < Math.PI * 1.5 && Math.PI * 1.5 < StartAngle && curBulge < 0)) && IsEqual(southQuadrant, bbMinY, precision)) { isCCW = !circularArc2d.IsClockWise; return isCCW; } #endregion check for quadrants } } #endregion check for convex arcs touching bounding box Point2dCollection points =GetPoints2D(acPoly); //lrpInd - Lowest Rightest Point Index //plrpInd - previous to lrpInd //nlrpInd - next of lrpInd int lrpInd = GetLowestRightestPointInd(points, precision), plrpInd = (lrpInd == 0) ? points.Count - 1 : lrpInd - 1, nlrpInd = (lrpInd == points.Count - 1) ? 0 : lrpInd + 1; Point2d curPoint = acPoly.GetPoint2dAt(lrpInd), prevPoint = acPoly.GetPoint2dAt(plrpInd), nextPoint = acPoly.GetPoint2dAt(nlrpInd); if (acPoly.GetSegmentType(lrpInd) == SegmentType.Line && acPoly.GetSegmentType(plrpInd) == SegmentType.Line) { double curAngle = (nextPoint.GetAsVector() - curPoint.GetAsVector()).Angle, prevAngle = (prevPoint.GetAsVector() - curPoint.GetAsVector()).Angle; isCCW = (prevAngle > curAngle) ? true : false; return isCCW; } else if (acPoly.GetSegmentType(lrpInd) == SegmentType.Line && acPoly.GetSegmentType(plrpInd) == SegmentType.Arc) { int indStart = plrpInd; int indEnd = lrpInd; int indToCheck = nlrpInd; Boolean IsIn = IsPointBelongToLWPlineArcSegment(acPoly, indStart, indEnd, acPoly.GetPoint2dAt(indToCheck), precision); //ed.WriteMessage("\n Is in =" + IsIn.ToString()); if (IsIn) { CircularArc2d circularArc2d = acPoly.GetArcSegment2dAt(indStart); isCCW = !circularArc2d.IsClockWise; return isCCW; } else { double curAngle = (nextPoint.GetAsVector() - curPoint.GetAsVector()).Angle, prevAngle = (prevPoint.GetAsVector() - curPoint.GetAsVector()).Angle; isCCW = (prevAngle > curAngle) ? true : false; return isCCW; } //ed.WriteMessage("\n isCCW =" + isCCW.ToString()); } else if (acPoly.GetSegmentType(lrpInd) == SegmentType.Arc && acPoly.GetSegmentType(plrpInd) == SegmentType.Line) { int indStart = lrpInd; int indEnd = nlrpInd; int indToCheck = plrpInd; Boolean IsIn = IsPointBelongToLWPlineArcSegment(acPoly, indStart, indEnd, acPoly.GetPoint2dAt(indToCheck), precision); if (IsIn) { CircularArc2d circularArc2d = acPoly.GetArcSegment2dAt(indStart); isCCW = !circularArc2d.IsClockWise; return isCCW; } else { double curAngle = (nextPoint.GetAsVector() - curPoint.GetAsVector()).Angle, prevAngle = (prevPoint.GetAsVector() - curPoint.GetAsVector()).Angle; isCCW = (prevAngle > curAngle) ? true : false; return isCCW; } //ed.WriteMessage("\n isCCW =" + isCCW.ToString()); } else if (acPoly.GetSegmentType(lrpInd) == SegmentType.Arc && acPoly.GetSegmentType(plrpInd) == SegmentType.Arc) { CircularArc2d curArc = acPoly.GetArcSegment2dAt(lrpInd); Point2d curCenter = curArc.Center; double curTangentAngle = (curCenter.GetAsVector() - curPoint.GetAsVector()).Angle - Math.PI * 0.5; CircularArc2d prevArc = acPoly.GetArcSegment2dAt(plrpInd); Point2d preCenter = prevArc.Center; double preTangentAngle = (preCenter.GetAsVector() - curPoint.GetAsVector()).Angle - Math.PI * 0.5; isCCW = (curTangentAngle < preTangentAngle) ? !curArc.IsClockWise : !prevArc.IsClockWise; return isCCW; } } return isCCW; } } }
Call is :
[CommandMethod("MyGroup", "MyCommand", "MyCommandLocal", CommandFlags.Modal)] public void MyCommand() // This method can have any name { double precision = 0.0001; Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument; Editor ed = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor; if (doc != null) { PromptEntityOptions peo = new PromptEntityOptions("\nselect polyline"); peo.SetRejectMessage("\nYou're missing, try again >>"); peo.AddAllowedClass(typeof(Polyline), true); PromptEntityResult res = ed.GetEntity(peo); if (res.Status != PromptStatus.OK) return; ObjectId plineId = res.ObjectId; if (!plineId.IsValid && plineId.IsErased && plineId.IsNull && plineId.IsEffectivelyErased) return; using (Transaction acTrans = doc.TransactionManager.StartTransaction()) { if (!CCWHub.plineCCW.IsCCWstraigtorarc(acTrans, plineId, precision)) { //plinesToReverse.Add(plineId); ed.WriteMessage("\nNo"); } else { ed.WriteMessage("\nYes"); } } } }
Are you sure your code better than the code @_gile ?
Відповідь корисна? Клікніть на "ВПОДОБАЙКУ" цім повідомленням! | Do you find the posts helpful? "LIKE" these posts!
Находите сообщения полезными? Поставьте "НРАВИТСЯ" этим сообщениям!
На ваше запитання відповіли? Натисніть кнопку "ПРИЙНЯТИ РІШЕННЯ" | Have your question been answered successfully? Click "ACCEPT SOLUTION" button.
На ваш вопрос успешно ответили? Нажмите кнопку "УТВЕРДИТЬ РЕШЕНИЕ"
Alexander Rivilis / Александр Ривилис / Олександр Рівіліс
Programmer & Teacher & Helper / Программист - Учитель - Помощник / Програміст - вчитель - помічник
Facebook | Twitter | LinkedIn
I have same function IsCCWnoarcs.
The angle or area method don't make practically any difference.
May method can pass all test cases in the attached drawing.
correction for function
public static Boolean IsCCWstraigtorarc(Transaction acTrans, ObjectId plineId, double precision) { Boolean isCCW = false; Polyline acPoly = (Polyline)acTrans.GetObject(plineId, OpenMode.ForRead); //Polyline doesn't have any arcs if (!acPoly.HasBulges) { isCCW = IsCCWnoarcs(acPoly, precision); return isCCW; } else //at least one arc { Extents3d acPolyBB = acPoly.GeometricExtents; double bbMinX = acPolyBB.MinPoint.X, bbMinY = acPolyBB.MinPoint.Y, bbMaxX = acPolyBB.MaxPoint.X, bbMaxY = acPolyBB.MaxPoint.Y; #region check for convex arcs touching bounding box for (int i = 0; i < acPoly.NumberOfVertices; i++) { if (acPoly.GetSegmentType(i) == SegmentType.Arc) { double curBulge = acPoly.GetBulgeAt(i); CircularArc2d circularArc2d = acPoly.GetArcSegment2dAt(i); Point2d StartPoint = circularArc2d.StartPoint, EndPoint = circularArc2d.EndPoint, Center = circularArc2d.Center; double StartAngle = (StartPoint.GetAsVector() - Center.GetAsVector()).Angle, EndAngle = (EndPoint.GetAsVector() - Center.GetAsVector()).Angle, Radius = circularArc2d.Radius, totalAngle = circularArc2d.EndAngle; #region angle correction if (curBulge > 0) { if (IsEqual(StartAngle, Math.PI * 2, precision)) StartAngle = 0; if (IsEqual(EndAngle, 0, precision)) EndAngle = Math.PI * 2; } else { if (IsEqual(StartAngle, 0, precision)) StartAngle = Math.PI * 2; if (IsEqual(EndAngle, Math.PI * 2, precision)) EndAngle = 0; } #endregion angle correction #region quadrants double eastQuadrant = Center.X + Radius, northQuadrant = Center.Y + Radius, westQuadrant = Center.X - Radius, southQuadrant = Center.Y - Radius; #endregion quadrants #region check for quadrants //0 if (!IsEqual(eastQuadrant, StartPoint.X, precision) && !IsEqual(eastQuadrant, EndPoint.X, precision) && ((StartAngle > EndAngle && curBulge > 0) || (StartAngle < EndAngle && curBulge < 0)) && IsEqual(eastQuadrant, bbMaxX, precision)) { isCCW = !circularArc2d.IsClockWise; return isCCW; } //90 else if (!IsEqual(northQuadrant, StartPoint.Y, precision) && !IsEqual(northQuadrant, EndPoint.Y, precision) && ((StartAngle < Math.PI * 0.5 && Math.PI * 0.5 < EndAngle && curBulge > 0) || (EndAngle < Math.PI * 0.5 && Math.PI * 0.5 < StartAngle && curBulge < 0)) && IsEqual(northQuadrant, bbMaxY, precision)) { isCCW = !circularArc2d.IsClockWise; return isCCW; } //180 else if (!IsEqual(westQuadrant, StartPoint.X, precision) && !IsEqual(westQuadrant, EndPoint.X, precision) && ((StartAngle < Math.PI && Math.PI < EndAngle && curBulge > 0) || (EndAngle < Math.PI && Math.PI < StartAngle && curBulge < 0)) && IsEqual(westQuadrant, bbMinX, precision)) { isCCW = !circularArc2d.IsClockWise; return isCCW; } //270 else if (!IsEqual(southQuadrant, StartPoint.Y, precision) && !IsEqual(southQuadrant, EndPoint.Y, precision) && ((StartAngle < Math.PI * 1.5 && Math.PI * 1.5 < EndAngle && curBulge > 0) || (EndAngle < Math.PI * 1.5 && Math.PI * 1.5 < StartAngle && curBulge < 0)) && IsEqual(southQuadrant, bbMinY, precision)) { isCCW = !circularArc2d.IsClockWise; return isCCW; } #endregion check for quadrants } } #endregion check for convex arcs touching bounding box Point2dCollection points =GetPoints2D(acPoly); //lrpInd - Lowest Rightest Point Index //plrpInd - previous to lrpInd //nlrpInd - next of lrpInd int lrpInd = GetLowestRightestPointInd(points, precision), plrpInd = (lrpInd == 0) ? points.Count - 1 : lrpInd - 1, nlrpInd = (lrpInd == points.Count - 1) ? 0 : lrpInd + 1; Point2d curPoint = acPoly.GetPoint2dAt(lrpInd), prevPoint = acPoly.GetPoint2dAt(plrpInd), nextPoint = acPoly.GetPoint2dAt(nlrpInd); if (acPoly.GetSegmentType(lrpInd) == SegmentType.Line && acPoly.GetSegmentType(plrpInd) == SegmentType.Line) { double curAngle = (nextPoint.GetAsVector() - curPoint.GetAsVector()).Angle, prevAngle = (prevPoint.GetAsVector() - curPoint.GetAsVector()).Angle; isCCW = (prevAngle > curAngle) ? true : false; return isCCW; } else if (acPoly.GetSegmentType(lrpInd) == SegmentType.Line && acPoly.GetSegmentType(plrpInd) == SegmentType.Arc) { int indStart = plrpInd; int indEnd = lrpInd; int indToCheck = nlrpInd; Boolean IsIn = IsPointBelongToLWPlineArcSegment(acPoly, indStart, indEnd, acPoly.GetPoint2dAt(indToCheck), precision); //ed.WriteMessage("\n Is in =" + IsIn.ToString()); if (IsIn) { CircularArc2d circularArc2d = acPoly.GetArcSegment2dAt(indStart); isCCW = !circularArc2d.IsClockWise; return isCCW; } else { double curAngle = (nextPoint.GetAsVector() - curPoint.GetAsVector()).Angle, prevAngle = (prevPoint.GetAsVector() - curPoint.GetAsVector()).Angle; isCCW = (prevAngle > curAngle) ? true : false; return isCCW; } //ed.WriteMessage("\n isCCW =" + isCCW.ToString()); } else if (acPoly.GetSegmentType(lrpInd) == SegmentType.Arc && acPoly.GetSegmentType(plrpInd) == SegmentType.Line) { int indStart = lrpInd; int indEnd = nlrpInd; int indToCheck = plrpInd; Boolean IsIn = IsPointBelongToLWPlineArcSegment(acPoly, indStart, indEnd, acPoly.GetPoint2dAt(indToCheck), precision); if (IsIn) { CircularArc2d circularArc2d = acPoly.GetArcSegment2dAt(indStart); isCCW = !circularArc2d.IsClockWise; return isCCW; } else { double curAngle = (nextPoint.GetAsVector() - curPoint.GetAsVector()).Angle, prevAngle = (prevPoint.GetAsVector() - curPoint.GetAsVector()).Angle; isCCW = (prevAngle > curAngle) ? true : false; return isCCW; } //ed.WriteMessage("\n isCCW =" + isCCW.ToString()); } else if (acPoly.GetSegmentType(lrpInd) == SegmentType.Arc && acPoly.GetSegmentType(plrpInd) == SegmentType.Arc) { CircularArc2d curArc = acPoly.GetArcSegment2dAt(lrpInd); Point2d curCenter = curArc.Center; double curTangentAngle = (curCenter.GetAsVector() - curPoint.GetAsVector()).Angle - Math.PI * 0.5; CircularArc2d prevArc = acPoly.GetArcSegment2dAt(plrpInd); Point2d preCenter = prevArc.Center; double preTangentAngle = (preCenter.GetAsVector() - curPoint.GetAsVector()).Angle - Math.PI * 0.5; #region moon condition if (IsEqualacPoints(nextPoint, prevPoint, precision)) { return (curArc.Radius < prevArc.Radius) ? !curArc.IsClockWise : !prevArc.IsClockWise; } #endregion moon condition #region previous point in curent segmentc int indStart = lrpInd; int indEnd = nlrpInd; int indToCheck = plrpInd; Boolean IsIn = IsPointBelongToLWPlineArcSegment(acPoly, indStart, indEnd, acPoly.GetPoint2dAt(indToCheck), precision); if (IsIn) return !curArc.IsClockWise; #endregion previous point in curent segmentc #region next point in previous segmentc indStart = plrpInd; indEnd = lrpInd; indToCheck = nlrpInd; IsIn = IsPointBelongToLWPlineArcSegment(acPoly, indStart, indEnd, acPoly.GetPoint2dAt(indToCheck), precision); if (IsIn) return !prevArc.IsClockWise; #endregion next point in previous segment #region triangle method double curAngle = (nextPoint.GetAsVector() - curPoint.GetAsVector()).Angle, prevAngle = (prevPoint.GetAsVector() - curPoint.GetAsVector()).Angle; isCCW = (prevAngle > curAngle) ? true : false; return isCCW; #endregion triangle method } } return isCCW; }