Hi Clement

Here is code for method like ConvexHull.

```
public static List<Point3d> CreateConvexHull(List<Point3d> points, double tolerance)
{
List<Point3d> pointsCulled = Point3d.CullDuplicates(points, tolerance).ToList();
//we sort points by defaukt comparer, see Point3d.GreaterThan Operator
pointsCulled.Sort();
if (pointsCulled.Count < 3)
{
return null;
}
if (!Point3d.ArePointsCoplanar(pointsCulled, tolerance))
{
return null;
}
//we determine most left and most right point
Point3d A = pointsCulled.First(); // most left
Point3d B = pointsCulled.Last(); // most right
if (A.X == B.X)
{
//points are laying on vertical line
return pointsCulled;
}
// Now we calclulate equation of line determined with points A and B
// Equation is Y= k*X + q, if we now two points then
// k = (y2-y1)/(x2-x1)
// q = ( x2*y1 -x1*y2 )/ (x2-x1)
double k = (B.Y - A.Y) / (B.X - A.X);
double q = (B.X * A.Y - A.X * B.Y) / (B.X - A.X);
//Create resulting list
List<Point3d> polyLinePoints = new List<Point3d>();
//add A point to result
polyLinePoints.Add(A);
//and process all points below A-B line
Vector3d previousVector = new Vector3d(0, -1, 0); ;
for (int i = 1; i < pointsCulled.Count ; i++)
{
double minAngle = Math.PI;
int foundPointIndex = -1;
Point3d lastPoint = polyLinePoints[polyLinePoints.Count - 1];
for (int j = i; j < pointsCulled.Count; j++)
{
var px = pointsCulled[j].X;
var py = pointsCulled[j].Y;
//check that point is below A-B line,
if (py <= k * px + q || j== pointsCulled.Count-1)
{
Vector3d currVector = pointsCulled[j] - lastPoint;
double angle = Vector3d.VectorAngle(previousVector, currVector, Plane.WorldXY);
if (angle < minAngle)
{
minAngle = angle;
foundPointIndex = j;
}
}
}
//process found whose vector has minimum angle
if (foundPointIndex> -1)
{
polyLinePoints.Add(pointsCulled[foundPointIndex]);
i = foundPointIndex;
previousVector = polyLinePoints[polyLinePoints.Count - 1] - polyLinePoints[polyLinePoints.Count - 2];
}
}
//and process all points above A-B line (A and B should be already in resulting list polyLinePoints)
previousVector = polyLinePoints[polyLinePoints.Count - 1] - polyLinePoints[polyLinePoints.Count - 2];
//we process from right to left
for (int i = pointsCulled.Count-2; i >=0; i--)
{
double minAngle = Math.PI;
int foundPointIndex = -1;
Point3d lastPoint = polyLinePoints[polyLinePoints.Count - 1];
for (int j = i; j >=0 ; j--)
{
var px = pointsCulled[j].X;
var py = pointsCulled[j].Y;
//check if point is above A-B line
if (py > k * px + q || j == 0)
{
Vector3d currVector = pointsCulled[j] - lastPoint;
double angle = Vector3d.VectorAngle(previousVector, currVector, Plane.WorldXY);
if (angle < minAngle)
{
minAngle = angle;
foundPointIndex = j;
}
}
}
//process found point whose vector has minimum angle
if (foundPointIndex > -1)
{
polyLinePoints.Add(pointsCulled[foundPointIndex]);
i = foundPointIndex;
previousVector = polyLinePoints[polyLinePoints.Count - 1] - polyLinePoints[polyLinePoints.Count - 2];
}
}
return polyLinePoints;
}
```

Code can be shorten and probably more optimised but for easy readibility I post it like this.

Algorithm is ismple. We find most left point, A, and most right point, B, which will be definitely part of ConvexHull polyline. First we process points below A-B line and later points above A-B line.

Point A is first point, we find next point P by creating vector A-P and checking for vector that has minimum angle between prevoius vector (in case of first point A previous vector can be {0,-1,0} which is unit vector in -Y axis direction). And so onâ€¦

Points should be in XY plane.

Radovan