Here a script to make dotted image with tangent circles following a curve.

CirclesOnCurveOnMesh_LEGACY.gh (28.9 KB)

SCARLETT JOHANSSON BY LEETA HARDING

Joconde from Leonard da Vinci

With Hilbert Curve

Andy Warhol’s Marilyn Monroe

AUBRY GASPARD Mappemonde en métal laqué

The idea uses the script from this disucssion

The idea there is not to provide the radius for each dot but to provide the minimum and maximum radius for dots. The radius depends on the brightness with the following formula. Power is use to change the contrast.

Radius = (radius2 - radius1)*Math.Pow(brightness, power)+ radius1

For script you have to choose

- The type of curve (spiral on center off the image, spiral on the side, Hilbert curve)
- The coefficient between maximum radius and minimum radius (here 4)
- The contrast (between 0.5 and 3 here)
- The parameters for your curve
- The path of your image

I choose to use a colored sphere instead of dots because I had many problems with dots. I don’t know if it is better now but I stay with that.

I use one of my spiral plugin

Some others discussions on dotted images or thickened curves images

And for the C# guys

```
private void RunScript(Curve curve, Mesh mesh, double radius1, double radius2, double power, ref object points, ref object radiuses, ref object colors)
{
//Calculate the center of circles with specified radius on a curve
// Radiuses are calculated depending on the brightness of the image
// 14/12/2021
// Laurent Delrieu
List<Point3d> lst_points = new List<Point3d>();
List<double> lst_radiuses = new List<double>();
List<Color> lst_colors = new List<Color>();
Point3d pointOnCurve = curve.PointAtStart;
lst_points.Add(pointOnCurve);
System.Drawing.Color color = System.Drawing.Color.White;
double radiusPrec = GetRadius(mesh, pointOnCurve, radius1, radius2, power, out color);
double radius = radiusPrec;
lst_radiuses.Add(radius);
lst_colors.Add(color);
int count = 2000000;
for (int i = 1; i < count; i++)
{
Point3d pointOnCurveNew = CurveCircleIntersection(curve, pointOnCurve, radiusPrec + radius);
if (pointOnCurveNew != Point3d.Unset)
{
pointOnCurve = pointOnCurveNew;
lst_points.Add(pointOnCurve);
lst_radiuses.Add(radius);
double radiusNew = GetRadius(mesh, pointOnCurve, radius1, radius2, power, out color);
lst_colors.Add(color);
radiusPrec = radius;
radius = radiusNew;
}
else
{
break;
}
}
points = lst_points;
radiuses = lst_radiuses;
colors = lst_colors;
}
// <Custom additional code>
/// <summary>
/// Return a radius depending on the brighness
/// </summary>
/// <param name="mesh">Colored mesh</param>
/// <param name="point">Point near the mesh</param>
/// <param name="radius1">First radius</param>
/// <param name="radius2">Second radius</param>
/// <param name="power">Power used for contrast, 1 if you don't know what to use, test with 0.5 or 1.5 to see the effect</param>
/// <param name="color">Color near the point</param>
/// <returns></returns>
double GetRadius(Mesh mesh, Point3d point, double radius1, double radius2, double power, out System.Drawing.Color color)
{
double radius = Math.Max(radius1, radius2);
MeshPoint mp = mesh.ClosestMeshPoint(point, radius * 500);
color = Color.White;
if (mp != null)
{
//System.Drawing.Color color = mesh.ColorAt(mp);
color = mesh.ColorAt(mp);
double brightness = (double) color.GetBrightness();
radius = (radius2 - radius1) * Math.Pow(brightness, power) + radius1;
}
return radius;
}
/// <summary>
/// Calculate the point on a curve that is at a certain radius from a point
/// this point must be after the previous point
/// </summary>
/// <param name="curve">The curve</param>
/// <param name="point">The point on the curve</param>
/// <param name="radius">The radius at which the new pointt must be from previous point</param>
/// <returns>Next point, Point3d.Unset if no point found</returns>
Point3d CurveCircleIntersection(Curve curve, Point3d point, double radius)
{
double tolerance = 0.0001;
double overlapTolerance = 0.0001;
Point3d output = Point3d.Unset;
double t = double.NaN;
curve.ClosestPoint(point, out t);
if (t != double.NaN)
{
Circle circle = new Circle(Plane.WorldXY, point, radius);
CurveIntersections ci = Rhino.Geometry.Intersect.Intersection.CurveCurve(curve, new ArcCurve(circle), tolerance, overlapTolerance);
double tMinOK = double.NaN;
foreach (IntersectionEvent ie in ci)
{
if (ie.ParameterA > t)
{
//First parameter that is OK
if (Double.IsNaN(tMinOK))
{
tMinOK = ie.ParameterA;
output = ie.PointA;
}
else
{
//If a parameter is nearer
if (ie.ParameterA < tMinOK)
{
tMinOK = ie.ParameterA;
output = ie.PointA;
}
}
}
}
}
return output;
}
```