How do I draw a circle?

Moho allows users to write new tools and plugins. Discuss scripting ideas and problems here.

Moderators: Víctor Paredes, Belgarath, slowtiger

ggoblin
Posts: 266
Joined: Wed Jan 19, 2022 2:09 pm

How do I draw a circle?

Post by ggoblin »

Sorry this is probably a very silly question, but how do I draw a circle from a script.

I tried the following, but am finding the last point seems to insist on being a peak even though its curvature is correctly set:

Code: Select all

	local mesh = moho:Mesh()
	local v = LM.Vector2:new_local()
	
	v.x = -0.02
	v.y = -0.02
	mesh:AddLonePoint(v, 0)
	
	v.x = -0.02
	v.y = 0.02
	mesh:AppendPoint(v, 0)

	v.x = 0.02
	v.y = 0.02
	mesh:AppendPoint(v, 0)

	v.x = 0.02
	v.y = -0.02
	mesh:AppendPoint(v, 0)

	v.x = -0.02
	v.y = -0.02
	mesh:AppendPoint(v, 0)
	mesh:WeldPoints(0, mesh:CountPoints() - 1, 0)
	
	local curv = 0.391379  -- 0.391379 is the magic number for a circle

	mesh:Point(0):SetCurvature(curv,0)
	mesh:Point(1):SetCurvature(curv,0)
	mesh:Point(2):SetCurvature(curv,0)
	mesh:Point(3):SetCurvature(curv,0)
	mesh:SelectAll()

	local shapeid = moho:CreateShape(true,false,0)	
	local shape = mesh:Shape(shapeid)
I used curve:GetCurvature to check each point in the curve,all their curvatures are correctly set to 0.391379, which I gather is what is required for a circle.

When I looked at the curve in Moho, one of the bezier handles of the last point, where it joins the first point, is not extended unlike all the other curves.

Image

Thank you.
User avatar
SimplSam
Posts: 1066
Joined: Thu Mar 13, 2014 5:09 pm
Location: London, UK
Contact:

Re: How do I draw a circle?

Post by SimplSam »

It appears that you are welding the points the wrong way around, which caused the circle to start at what was point #2 (-.02, .02), as point #1 was 'moved' to what was point #5 and deleted during the weld/merge - resulting in new point #4 which does not have its outgoing bezier handle set correctly.

Should be as follows - which will weld/merge/move point #5 into point #1.

Code: Select all

mesh:WeldPoints(mesh:CountPoints() - 1, 0, 0)
-- updated for clarity
Last edited by SimplSam on Thu Jun 23, 2022 8:22 am, edited 1 time in total.
Moho 14.1 » Win 11 Pro 64GB » NVIDIA GTX 1080ti 11GB
Moho 14.1 » Mac mini 2012 8GB » macOS 10.15 Catalina
Tube: SimplSam


Sam
User avatar
hayasidist
Posts: 3565
Joined: Wed Feb 16, 2011 8:12 pm
Location: Kent, England

Re: How do I draw a circle?

Post by hayasidist »

ggoblin wrote: Wed Jun 22, 2022 4:24 pm I used curve:GetCurvature to check each point in the curve, all their curvatures are correctly set to 0.391379, which I gather is what is required for a circle.
FWIW: the curvature of 0.391379 is for a 4-point circle. It's derived from the bezier handle coordinates which are "optimally" (4/3)*tan(pi/2n) away from the drawing point on a tangent through the point (n is the number of drawing points in the circle) -- there's a load of background on circles and bezier handles here. Broadly - that magic number will decrease as the number of points increases.

There is a way to convert between "Curvature" and bezier handles here should you be interested.

There's a load of history wrapped up in Moho's curvature and spatial interpolation between mesh points -- I'll skip over that -- but if you stumble across "Legacy Curves" that's there to support the drawing algorithm used in AS7 and earlier.
ggoblin
Posts: 266
Joined: Wed Jan 19, 2022 2:09 pm

Re: How do I draw a circle?

Post by ggoblin »

SimplSam wrote: Wed Jun 22, 2022 7:04 pm It appears that you are welding the points the wrong way around, which caused the circle to start at what was point #2 (-.02, .02), as point #1 was 'moved' to what was point #5 and deleted during the merge - resulting in new point #4 which does not have its outgoing bezier handle set correctly.

Should be as follows, with point #5 moving to point #1.

Code: Select all

mesh:WeldPoints(mesh:CountPoints() - 1, 0, 0)
Thank you SimplSam, it works!

But I'm still not 100% clear why it works. I had assumed AddLonePoint was to add the first point and then to create a closed curve I had to ensure that the last AppendPoint matched this first point before calling WeldPoints. I gather that this is not the case? The first AppendPoint after AddLonePoint has to have the same location, and the last point doesnt need to match.. it will close it anyway when you call WeldPoints?

Also I tried the WeldPoints change you suggested, for some reason it resulted in a 3 point shape. Its not a problem as the existing WeldPoints statement worked fine with your point movement suggestion. But I would like to understand what the parameters of WeldPoints mean. I had assumed the first two parameters just indicated the range of points to weld, but this is what mohoscripting.com says:
M_Mesh:WeldPoints(movingID, solidID, frame)
Version added: before 9.5

Welds two points together
Argument Type Description Default Ver
movingID int32 Point identifier < 9.5
solidID int32 Point identifier < 9.5
frame int32 Frame number < 9.5

Return type (bool): true if successful, otherwise false
Welds two points together. The point identified by movingID will move if necessary to line up with solidID. Not all welding operations are allowed, so this function will return the status of the weld.
Any clarification would be most helpful.

Thank you.
ggoblin
Posts: 266
Joined: Wed Jan 19, 2022 2:09 pm

Re: How do I draw a circle?

Post by ggoblin »

hayasidist wrote: Wed Jun 22, 2022 9:07 pm
ggoblin wrote: Wed Jun 22, 2022 4:24 pm I used curve:GetCurvature to check each point in the curve, all their curvatures are correctly set to 0.391379, which I gather is what is required for a circle.
FWIW: the curvature of 0.391379 is for a 4-point circle. It's derived from the bezier handle coordinates which are "optimally" (4/3)*tan(pi/2n) away from the drawing point on a tangent through the point (n is the number of drawing points in the circle) -- there's a load of background on circles and bezier handles here. Broadly - that magic number will decrease as the number of points increases.

There is a way to convert between "Curvature" and bezier handles here should you be interested.

There's a load of history wrapped up in Moho's curvature and spatial interpolation between mesh points -- I'll skip over that -- but if you stumble across "Legacy Curves" that's there to support the drawing algorithm used in AS7 and earlier.
Thank you Hayasidist,

I don't like magic numbers, like to understand where things come from. I noticed the number is close to pi/8, but only to 2 decimal places, next I did a web search for "0.391379 circle" but I think it took me to some Etherium to dollar exchange :roll:

Thank you for the references, I will check them out.

Converting from bezier to curvature might come in useful when I play with generating more comples shapes from script, like a heart shape?
ggoblin
Posts: 266
Joined: Wed Jan 19, 2022 2:09 pm

Re: How do I draw a circle?

Post by ggoblin »

ggoblin wrote: Thu Jun 23, 2022 12:11 am Also I tried the WeldPoints change you suggested, for some reason it resulted in a 3 point shape.
Just checked,its actually 4 points - the last two are at same location.
ggoblin
Posts: 266
Joined: Wed Jan 19, 2022 2:09 pm

Re: How do I draw a circle?

Post by ggoblin »

Just had a coffee and looked at it again with a fresh pair of eyes.. feel even more of an idiot now :D Reread mohoscripting description of WeldPoints and reread SimplSam's anwer, makes perfect sense now.

I had thought SimplSam meant move point #5 in the script to point #1, so after I did that of course the existing WeldPoints worked, but when I also changed the weld statement as he suggested it stopped working as both were equivalent. I hadn't understood how WeldPoints worked - the first parameter determines which point gets moved so either I duplicate points at start and have one of them moved for welding or otherwise I duplicate end point and have that move for welding - not both. lol :lol:

Thank you SimplSam!
ggoblin
Posts: 266
Joined: Wed Jan 19, 2022 2:09 pm

Re: How do I draw a circle?

Post by ggoblin »

ggoblin wrote: Thu Jun 23, 2022 12:30 am Converting from bezier to curvature might come in useful when I play with generating more comples shapes from script, like a heart shape?
Actually creating a heart shape is rather simple. Combining curvature with point placement makes Moho a very effective drawing tool without having to resort to beziers.

Code: Select all

	local mesh = moho:Mesh()
	local v = LM.Vector2:new_local()
	
	v.x = 0.0 + x
	v.y = 0.075 + y
	mesh:AddLonePoint(v, 0)

	v.x = 0.0 + x
	v.y = 0.075	+ y
	mesh:AppendPoint(v, 0)

	v.x = 0.15 + x
	v.y = 0.1 + y
	mesh:AppendPoint(v, 0)
	
	v.x = 0.0 + x
	v.y = -0.15	+ y
	mesh:AppendPoint(v, 0)

	v.x = -0.15 + x
	v.y = 0.1 + y
	mesh:AppendPoint(v, 0)

	mesh:WeldPoints(0, mesh:CountPoints() - 1, 0)

	mesh:Point(0):SetCurvature(0,0)
	mesh:Point(1):SetCurvature(0.55,0)
	mesh:Point(2):SetCurvature(0,0)
	mesh:Point(3):SetCurvature(0.55,0)
	mesh:SelectAll()
	
	local shapeid = moho:CreateShape(true,false,0)	
	local shape = mesh:Shape(shapeid)
Image
User avatar
hayasidist
Posts: 3565
Joined: Wed Feb 16, 2011 8:12 pm
Location: Kent, England

Re: How do I draw a circle?

Post by hayasidist »

ggoblin wrote: Thu Jun 23, 2022 1:11 pm Actually creating a heart shape is rather simple. Combining curvature with point placement makes Moho a very effective drawing tool without having to resort to beziers.
:D yeah -- Moho actually uses cubic bezier "under the hood" to define the path between points! For another shape drawing tool take a look at viewtopic.php?p=203853#p203853
ggoblin
Posts: 266
Joined: Wed Jan 19, 2022 2:09 pm

Re: How do I draw a circle?

Post by ggoblin »

Brilliant tool Hayasidist!

Did you use different algorithms for the oval compared to the default shape tool? I lined up 4-point ovals from both and there is a slight difference between them, yours is a little rounder.
User avatar
hayasidist
Posts: 3565
Joined: Wed Feb 16, 2011 8:12 pm
Location: Kent, England

Re: How do I draw a circle?

Post by hayasidist »

ggoblin wrote: Thu Jun 23, 2022 6:53 pm Brilliant tool Hayasidist!

Did you use different algorithms for the oval compared to the default shape tool? I lined up 4-point ovals from both and there is a slight difference between them, yours is a little rounder.
mine has a sharper "corner" - more "eye shaped" than oval (it's the LM one that is rounder?) -- and yes - it's a quite different algorithm to accommodate the ability to have more than 4 points
ggoblin
Posts: 266
Joined: Wed Jan 19, 2022 2:09 pm

Re: How do I draw a circle?

Post by ggoblin »

I meant when pressing the control key, otherwise its not really an oval - like you said sharper corners.

Image
User avatar
hayasidist
Posts: 3565
Joined: Wed Feb 16, 2011 8:12 pm
Location: Kent, England

Re: How do I draw a circle?

Post by hayasidist »

ggoblin wrote: Fri Jun 24, 2022 11:49 am I meant when pressing the control key, otherwise its not really an oval - like you said sharper corners.
yeah - (see the "readme"): (in the sub-tool description) the control key forces the curvatures to be Moho's "circle" magic number; and (in "notes and know issues") the "bone shape" is one of the “interesting” behaviours .... :D
User avatar
hayasidist
Posts: 3565
Joined: Wed Feb 16, 2011 8:12 pm
Location: Kent, England

Re: How do I draw a circle?

Post by hayasidist »

hayasidist wrote: Wed Jun 22, 2022 9:07 pm
ggoblin wrote: Wed Jun 22, 2022 4:24 pm I used curve:GetCurvature to check each point in the curve, all their curvatures are correctly set to 0.391379, which I gather is what is required for a circle.
FWIW: the curvature of 0.391379 is for a 4-point circle. It's derived from the bezier handle coordinates which are "optimally" (4/3)*tan(pi/2n) away from the drawing point on a tangent through the point (n is the number of drawing points in the circle)
Since you "asked the question" about that magic number, I did some more digging ... The base curvature for a circle is the bezier handle coordinate divided by the straight line length between point and neighbour (assuming I've figured it out correctly!). So, for a 4-point circle, that's ((4/3)*tan(pi/8)) / sqrt(2)) or, pedantically, ((4/3)*tan(pi/8)) / 2*sin(pi/4)) [which can be generalised and simplified to ((2/3)*tan(pi/(n*2)))/sin(pi/n)]

BUT ... the precise evaluation for a 4-point circle gives 0.3905 to 4dp which is close to, but not exactly, the .3914 (to 4dp) value as quoted. The discrepancy can just about be explained by rounding at each calculation sub-step. Visually there's very little discernible difference.

as n increases, the curvature tends to 1/3; and for a 2 point circle, the answer is 2/3.

a 3-point circle needs a curvature of 0.44444 ... 12-points: .3391 ... :D

I think I'll put these "calculated" curvatures into my shape tool next update for "round-corners on polygons".
ggoblin
Posts: 266
Joined: Wed Jan 19, 2022 2:09 pm

Re: How do I draw a circle?

Post by ggoblin »

Well I can confirm that your magic numbers work :D

I didn't try 12 points, was more interested in seeing if I could draw a circle in Moho with just 2 point.. with your magic numbers it works!

Image

BTW When you really zoom in, in moho, you can see the difference between 0.3905 and 0.3914 4-point circles, but at that zoom level the lines look straight anyway.

BTW Apologies for all gif videos I'm posting recently.. just trying out a new freeby screen capture software. :D
Post Reply