How to order grip objects based on their counterclockwise connection

Hi @dale currently I have only the following script where I would like to use this for, to make holes circular, but have also other ideas in mind where it could be used. It kind of works if the points are enough in the ballpark. The attached model right hole works, the left will fail.

sample_subd-holes.3dm (126.1 KB)


import Rhino
import rhinoscriptsyntax as rs
import scriptcontext as sc
"""
This script planarizes a group of points and organizes them equally spaced in a circle
script by Gijs de Zwart
www.studiogijs.nl
"""
def circularize():
    
    go = Rhino.Input.Custom.GetObject()
    go.SetCommandPrompt("Select controlpoints to make circular")
    go.GeometryFilter = Rhino.DocObjects.ObjectType.Grip
    go.GetMultiple(1, 0)
    object_list = Rhino.Collections.TransformObjectList()
    object_list.AddObjects(go, True)

    #convert grips to list of 3d points
    gripPts=[grip.OriginalLocation for grip in object_list.GripArray()] 
    #fit circle through these points
    result, circle = Rhino.Geometry.Circle.TryFitCircleToPoints(gripPts)
    if not result:
        return
    circle = sc.doc.Objects.AddCircle(circle)
    #get first grip and match circle seam to this first point
    pt_0 = object_list.GripArray()[0].OriginalLocation
    param = rs.CurveClosestPoint(circle, pt_0)
    rs.CurveSeam(circle,param)
    #divide circle 
    segs= len(go.Objects())
    ptlist = rs.DivideCurve(circle, segs)
    #return
    for i in range(len(ptlist)):
        #find index of closest grip point to circle point i 
        j=Rhino.Collections.Point3dList.ClosestIndexInList(gripPts, ptlist[i])
        #select corresponding grip
        grip = object_list.GripArray()[j]
        
        #calculate translation vector to circle point
        vector_from = grip.OriginalLocation
        vector_to = ptlist[i]
        dir = rs.VectorSubtract(vector_to, vector_from)
        #move grip
        xform = Rhino.Geometry.Transform.Translation(dir)
        grip.Move(xform)

    for owner in object_list.GripOwnerArray():
        sc.doc.Objects.GripUpdate(owner, True)
    
    sc.doc.Views.Redraw()
circularize()