0

I am preparing to create a program to detect arcs and line segments from the collection of points (x,y) which follow each other and generally, they create a closed polygon. I just dont know where to start. Maybe someone knows "ready to go" library (can be paid) which do such a think for me? Or maybe some propositions of algorithms that are relatively easy to implement? I am looking for any advices.

Jacek Majer
  • 345
  • 1
  • 3
  • 14
  • https://stackoverflow.com/questions/42995738/approximate-a-curve-with-a-limited-number-of-line-segments-and-arcs-of-circles – Hans Passant Jun 06 '19 at 22:37

1 Answers1

1

If your points don't precisely fall on the arcs and segments, but you're trying to find the closest fit, see: 'https://en.wikipedia.org/wiki/Curve_fitting'.

If your points follow exactly arcs or line segments, maybe this closed solution might work for you. It assumes arcs are made out of at least 4 points. You can create an arc with any 3 points, so there is no way to tell if they are supposed to be an arc or line segment (unless you use an angle threshold). With 4 points you can compare if points (0,1,2) and (0,1,3) are part of the same arc.

When creating arc objects from 3 points, internally it calculates the radius and center to be able to compare them. To find a circle from 3 points: https://math.stackexchange.com/questions/213658/get-the-equation-of-a-circle-when-given-3-points

     PolyCurve ArcsAndLines(List<Point3d> points)
    {
        var curve = new PolyCurve();
        Arc current = Arc.Unset;

        for (int i = 0; i < points.Count - 1; i++)
        {
            var areEqual = false;

            if (i + 3 < points.Count)
            {
                var arcA = new Arc(points[i], points[i + 1], points[i + 2]);
                var arcB = new Arc(points[i], points[i + 1], points[i + 3]);
                areEqual = AreEqual(arcA, arcB);
            }

            if (areEqual)
            {
                var start = current == Arc.Unset ? points[i] : current.StartPoint;
                current = new Arc(start, points[i + 1], points[i + 3]);
            }
            else
            {
                if (current != Arc.Unset)
                {
                    curve.Append(current);
                    current = Arc.Unset;
                    i++;
                }
                else
                {
                    curve.Append(new Line(points[i], points[i + 1]));
                }
            }
        }

        return curve;
    }

    bool AreEqual(Arc a, Arc b)
    {
        const double tol = 0.001;

        bool sameRadius = Math.Abs(a.Radius - b.Radius) < tol;
        if (!sameRadius) return false;

        bool sameCenter = a.Center.DistanceTo(b.Center) < tol;
        return sameCenter;
    }

'curve' is a list containing line and arc segments.

It should work with open polylines and polygons (with end point being the same as start). If the start of a polygon lies in the middle of an arc, it will be split into two arcs. A regular polygon (resulting in a circle) will not work properly since you'll be defining an arc with the same start and end points.

visose
  • 26
  • 3