[Cuis-dev] Understanding Arc

Juan Vuletich juan at jvuletich.org
Tue May 4 14:38:04 PDT 2021


Hi Hilaire,

On 5/4/2021 4:18 PM, Hilaire Fernandes via Cuis-dev wrote:
>
> Hi Juan,
>
> In DrGeo, the user can define an arc passing though three points 
> (there is other way). With Vector Graphics primitive, there is this 
> largeFlag attribute, depending on its value and the position of the 
> three user defined points, the arc will do or not as expected.
>
> Bellow the arc does not do as expected, when largeFlag is false. if I 
> toggle largeFlag to true, then the arc goes through the three points.
>
> The arc does not pass by the third point
>
> However it will not work the other way, when the second point is moved 
> close to the other points. I don't understand how should the largeFlag 
> attribute be set.
>
> The DrGeo's arc model knows about its center, radius, starting angle, 
> and its oriented angle. Its polymoprhic pointAt: method gives the 
> coordinates of any point on its line, with curvilinear abscissa 
> between 0 and 1.
>
> drawOn: canvas
>      | start end r orientation |
>      start _ self drawable worldToMorph: (mathItem pointAt: 0).
>      end  _ self drawable worldToMorph: (mathItem pointAt: 1).
>      r _ self drawable worldToPixel: mathItem radius.
>      orientation _ mathItem length negative.
>      canvas strokeWidth: borderWidth color: borderColor do: [
>          canvas moveToX: start x y: start y;
>          arcToX: end x y: end y rx: r  ry: r angleOfXAxis: 0 largeFlag: false sweepFlag: orientation]
>
>
> -- 
> GNU Dr. Geo
> http://drgeo.eu
> http://blog.drgeo.eu

The arc implementation follows https://www.w3.org/TR/SVG/implnote.html . 
With the start and end points and a radius, and without knowing the 
center, or the third point, in general there are two possible whole 
circles, and four possible arcs. Of each of the two whole circles we 
could chose to draw the smaller or the larger arc. That's what the large 
flag is for.

I know. This is not clear at all. But it is what the SVG stadard does, 
which I chose to follow it. Maybe a code example will help. Note that 
negating the flags will draw the other alternative arcs honoring start, 
end and radius, but not middle point.
The whole example, to play in a workspace, is:

x1 _ 400. y1 _ 300.
x3 _ 600. y3 _ 700.
"various examples of mid point"
x2 _ 900. y2 _ 450.
x2 _ 900. y2 _ 1450.
x2 _ 300. y2 _ 1450.
x2 _ 300. y2 _ 450.
x2 _ 300. y2 _ 650.
x2 _ 300. y2 _ 950.
x2 _ 1300. y2 _ 950.
x2 _ 1300. y2 _ 350.
x2 _ 600. y2 _ 350.
x2 _ 600. y2 _ 150.
"Shamesly copied from 
https://www.geeksforgeeks.org/equation-of-circle-when-three-points-on-the-circle-are-given/"
x12 _ x1 - x2.
x13 _ x1 - x3.
y12 _ y1 - y2.
y13 _ y1 - y3.
y31 _ y3 - y1.
y21 _ y2 - y1.
x31 _ x3 - x1.
x21 _ x2 - x1.
sx13 _ x1 squared - x3 squared.
sy13 _ y1 squared - y3 squared.
sx21 _ x2 squared - x1 squared.
sy21 _ y2 squared - y1 squared.
f _  ((sx13 * x12)
             + (sy13 * x12)
             + (sx21 * x13)
             + (sy21 * x13))
             / (2 * ((y31 * x12) - (y21 * x13))).
g _  ((sx13 * y12)
             + (sy13 * y12)
             + (sx21 * y13)
             + (sy21 * y13))
             / (2 * ((x31 * y12) - (x21 * y13))).
c _ 0 - x1 squared - y1 squared - (2 * g *x1) - (2 * f * y1).
  "    // eqn of circle be
     // x^2 + y^2 + 2*g*x + 2*f*y + c = 0
     // where centre is (h = -g, k = -f) and radius r
     // as r^2 = h^2 + k^2 - c"
h _ g negated.
k _ f negated.
center _ h at k.
rSquared _ h squared + k squared - c.
  "    // r is the radius"
r _ rSquared sqrt.
"Ok. Found center and r. That's all we wanted."
start _ x1 @ y1.
end _ x3 @ y3.
mid _ x2 at y2.
alpha1 _ ((mid - center) theta radiansToDegrees - (start - center) theta 
radiansToDegrees) \\ 360.
alpha2 _ ((end - center) theta radiansToDegrees - (start - center) theta 
radiansToDegrees) \\ 360.
alpha1 > alpha2
     ifTrue: [
         alpha1 _ alpha1 - 360.
         alpha2 _ alpha2 - 360.
         orientation _ false ]
     ifFalse: [
         orientation _ true ].
largeFlag _ alpha2 abs > 180.
canvas _ VectorCanvas onForm: Display.
canvas ellipseCenterX: x1 y: y1 rx: 15 ry: 15 borderWidth: 5 
borderColor: Color red fillColor: Color yellow.
canvas ellipseCenterX: x2 y: y2 rx: 15 ry: 15 borderWidth: 5 
borderColor: Color red fillColor: Color orange.
canvas ellipseCenterX: x3 y: y3 rx: 15 ry: 15 borderWidth: 5 
borderColor: Color red fillColor: Color red.
canvas strokeWidth: 5 color: Color red do: [
         canvas moveToX: start x y: start y;
         arcToX: end x y: end y rx: r ry: r angleOfXAxis: 0 largeFlag: 
largeFlag sweepFlag: orientation ].
Display forceToScreen

Hope this helps.

Cheers,

-- 
Juan Vuletich
www.cuis-smalltalk.org
https://github.com/Cuis-Smalltalk/Cuis-Smalltalk-Dev
https://github.com/jvuletich
https://www.linkedin.com/in/juan-vuletich-75611b3
@JuanVuletich


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.cuis.st/mailman/archives/cuis-dev/attachments/20210504/4208d0f7/attachment.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: image/png
Size: 2871 bytes
Desc: not available
URL: <http://lists.cuis.st/mailman/archives/cuis-dev/attachments/20210504/4208d0f7/attachment.png>


More information about the Cuis-dev mailing list