Reputation: 14125
I want to draw a rectangle/square and I want that if I drag any side of that rectangle then that side of rectangle should change to circle as shown in first image.
I managed to draw a rectangle/square with stretchable sides using Quadratic Curves but the issue is that when I stretch side of rectangle it does not stretch as circle but as elipse or something as shown in second image.
I know you might recommend using Bezier Curve but I want single control point like Quadratic Curve but bezier have two(correct me if I am wrong).
Please suggest me what should be the best approach towards this issue.
Image - what I wanted
Image - what I have achieved
What I have done
This fiddle
shows result of my work.
To draw rectangle just click and drag your maouse on canvas.
Upvotes: 0
Views: 606
Reputation: 40160
The higher the order of a bezier curve, the more control points it needs. Quadratic curves are second order bezier curves, and they need a single control point. Bezier curves with two control points are third order. A bezier curve of order one is effectively a straight line. No finite order of bezier curves can make a perfect circle arc.
By the way, the quadratic curve is not a "elipse or something" it is a parabolic segment.
If you want to have circle arcs, you should use... well circle arcs! To control it you will need to change the radius, in fact you could do it by moving the center of the circle.
You will need additional logic to handle the straight line, as the circle arc is never a straight line. So if the drag point is over the straight line you will draw a line, if not you will draw the arc with an appropriate radius.
So, let's say you have the following situation:
Where the segment ab
is the straight line of your rectangle and acb
is the desired arc. y
is the height of the segment and x
is the horizontal offset of the drag. We are looking for r
the radius of the circle defined by the three points a
, c
and b
.
Now the angle sda
is a turn/4, sd
is r - x
and ad
is y / 2
. If we use Pythagoras' we get:
r^2 = (r-x)^2 + (y/2)^2
=>
r^2 = (r-x)(r-x) + (y/2)^2
=>
r^2 = r^2 - 2rx + x^2 + (y/2)^2
=>
r^2 = r^2 - 2rx + x^2 + (y^2/4)
=>
0 = - 2rx + x^2 + (y^2/4)
=>
2rx = x^2 + (y^2/4)
=>
r = (x^2 + (y^2/4)) / 2x
=>
r = ((x^2) / 2x) + ((y^2/4) / 2x)
=>
r = (x/2) + ((y^2/4) / 2x)
=>
r = (x/2) + (y^2/8x)
As you can see, when x
is 0 we have division by 0. That's why you will have to switch to drawing straight lines when that happens.
We the found formula ( r = (x/2) + (y^2/8x)
) you will be able to determinate the radius of the circle to draw the arc. Finding the center point is trivial...
To find the angles you can use either the Law of Sines or the Law of cosines, at your preference, both work well. You have the choice of using the triangle asb
, the triangle asd
or the triangle adc
(in green) to find the angles.
For a simple approach let's continue with the triangle asd
, and let's use the Law of Sines:
r / sin(turn/4) = (y/2) / sin(θ/2)
Since the sine of a quarter turn is 1, we can replace it:
=>
r / 1 = (y/2) / sin(θ/2)
=>
1 = (y/2) / sin(θ/2)
Now, solve it for the angle:
=>
sin(θ/2) = (y/2)
=>
θ/2 = asin(y/2)
When calling the function to draw the arc, the starting angle will be -θ/2 and the ending angle will be θ/2.
Note: all this was made for the right side of the rectangle adjustments will be needed for the other sides.
Upvotes: 1