<p>Check out the section on <a href="https://pages.mtu.edu/%7Eshene/COURSES/cs3621/NOTES/spline/NURBS/RB-circles.html" rel="nofollow noreferrer">Circular Arcs and Circles</a>, from <a href="https://pages.mtu.edu/%7Eshene/COURSES/cs3621/NOTES/notes.html" rel="nofollow noreferrer">Ching-Kuang Shene's excellent computational geometry course notes</a>:</p>
<blockquote>
<p>[G]iven three control points P0, P1 and P2 such that P0P1 = P1P2 holds, if we choose w, the weight for P1, to be sin(a), where a is the half angle at control point P1, the resulting rational Bézier curve is a circle.</p>
</blockquote>
<p>The second diagram on that page is particularly useful. If P0 is at (0,0), P1 is at (1,0), and P2 is at (1,1), then the angle at P1 is 90 degrees; half that is 45, so assigning weights w0 = w2 = 1 and w1 = sin(45) = 1/sqrt(2) will produce a circle.</p>
<p><strong>EDIT</strong>: To actually implement this from your code: The three points are <code>[a,b,c]</code>. If you know that the distance from <code>a</code> to <code>b</code> is the same as the distance from <code>b</code> to <code>c</code>, then you can set <code>w1</code> and <code>w3</code> to 1, and <code>w2</code> to the sine of half the angle between them. Look up the <a href="https://mathworld.wolfram.com/Half-AngleFormulas.html" rel="nofollow noreferrer">half-angle formula</a> for sine to see that <code>sin(x/2) = sqrt((1 - cos x) / 2)</code>. The cosine of the angle between two vectors is the normalized dot product, i.e. <code>cos x = dot(a-b,c-b) / (a-b)^2</code>. Thus, you can do something like</p>
<pre><code>ba = a - b
bc = c - b
cosx = ba.Dot(bc) / ba.Dot(ba);
w2 = math.sqrt(0.5 * (1 - cosx));
</code></pre>
<p>Again, this will only work if the distances <code>ba</code> and <code>bc</code> are the same. (You can still make a circle otherwise, but the weights will be more compilcated.)</p>

CC BY-SA 4.0
2020-10-21T01:28:54.477Z
Thank you! Please excuse my ignorance, but what do I use in my code from this equation: `w1 = sin(45) = 1/sqrt(2)`? Having the two equal signs confuses me: is it saying that the `sin(45) == 1/sqrt(2)`?
Dr. Pontchartrain
CC BY-SA 4.0
2020-10-21T07:17:13.797Z
Yes, I was just pointing out that the sine of 45 degrees is one over the square root of two. You'd probably just write `w1 = 1 / sqrt(2)`.
gilgamec
CC BY-SA 4.0
2020-10-21T18:23:26.540Z
Thanks for the reply. Where is the angle variable in that equation? Wouldn't `w1 = sin(x)` be better for a program? Maybe I'm not understanding correctly.
Dr. Pontchartrain
CC BY-SA 4.0
2021-04-17T11:03:08.370Z
You can still make a circle if the distances ba and bc are different?? I don’t think so.
bubba
CC BY-SA 4.0
2022-01-25T12:21:13.473Z
In the document the computation of w comes from the equation w/(1+w) = mx/mp1. Where does it come from?
Luca Carlon
CC BY-SA 4.0
2020-10-20T07:27:08.530Z
2020-10-23T07:40:48.993Z
2020-10-23T07:40:48.993Z
gilgamec
<p>I am trying to create a spherical interpolation with 3 points. I'm currently using Quadratic Bezier Interpolation but <a href="https://computergraphics.stackexchange.com/a/10317/14079">have been told</a> I should use Rational Quadratic Bezier Curve in order to get a perfectly circular curve. I have tried implementing this based on the formula I found <a href="http://demofox.org/bezquadrational.html" rel="nofollow noreferrer">here</a> (3 control points A,B and C, 3 weights W1, W2, W3 and a time t):</p>
<p><code>CurvePoint = (A*W1*(1-t)^2 + B*W2*2t(1-t) + C*W3*t^2) / (W1*(1-t)^2 + W2*2t(1-t) + W3*t^2).</code></p>
<p>How do I determine the correct weight values for this to work as a circle? Is that even possible without moving the middle point? Thank you.</p>
<p>Here is the code I am using (with all weights set to 1.0) and the curve it produces:</p>
<pre class="lang-python prettyprint-override"><code>
def ArcPoints(node):
    points = node.GetAllPoints()

    # The three points of the point object
    a, b, c = points[:3]

    samples = 6
    arcPoints = list()
    for i in range(samples):
        t = float(i)/(samples - 1)
        w1 = 1
        w2 = 1
        w3 = 1
        p2 = (a * w1 * (1-t) ** 2 + b * w2 * 2*t * (1-t) + c * w3 * t ** 2 ) / (w1 * (1-t) ** 2 + w2 * 2*t * (1-t) + w3 * t**2)
        arcPoints.append(p)

    return arcPoints

</code></pre>
<p><a href="https://i.sstatic.net/yQEbu.jpg" rel="nofollow noreferrer"><img src="https://i.sstatic.net/yQEbu.jpg" alt="Rational Quadratic Bezier Curve" /></a></p>

CC BY-SA 4.0
2020-10-19T12:22:11.357Z
Have you read [this](https://pomax.github.io/bezierinfo/)
joojaa
CC BY-SA 4.0
2020-10-20T00:07:26.260Z
Thanks for the comment. I haven't read the document, but I saw it in my research. I'm in a bit of a time crunch so more specificity to my issue would be greatly appreciated (in code would be even better). I don't understand mathematic symbols very well. Have you read it? If so, where does it answer how to set 3-point circular Bezier weights?
Dr. Pontchartrain
<mathematics><interpolation><curve><bezier-curve><nurbs>
Determining Rational Quadratic Bezier Curve Weights for Circle
Dr. Pontchartrain
# Determining Rational Quadratic Bezier Curve Weights for Circle

(Asked by: username_0 on 2020-10-17)

I am trying to create a spherical interpolation with 3 points. I'm currently using Quadratic Bezier Interpolation but [have been told](https://computergraphics.stackexchange.com/a/10317/14079) I should use Rational Quadratic Bezier Curve in order to get a perfectly circular curve. I have tried implementing this based on the formula I found [here](http://demofox.org/bezquadrational.html) (3 control points A,B and C, 3 weights W1, W2, W3 and a time t):

`CurvePoint = (A*W1*(1-t)^2 + B*W2*2t(1-t) + C*W3*t^2) / (W1*(1-t)^2 + W2*2t(1-t) + W3*t^2).`

How do I determine the correct weight values for this to work as a circle? Is that even possible without moving the middle point? Thank you.

Here is the code I am using (with all weights set to 1.0) and the curve it produces:

```python

def ArcPoints(node):
    points = node.GetAllPoints()

    # The three points of the point object
    a, b, c = points[:3]

    samples = 6
    arcPoints = list()
    for i in range(samples):
        t = float(i)/(samples - 1)
        w1 = 1
        w2 = 1
        w3 = 1
        p2 = (a * w1 * (1-t) ** 2 + b * w2 * 2*t * (1-t) + c * w3 * t ** 2 ) / (w1 * (1-t) ** 2 + w2 * 2*t * (1-t) + w3 * t**2)
        arcPoints.append(p)

    return arcPoints

```

[![Rational Quadratic Bezier Curve](https://i.sstatic.net/yQEbu.jpg)](https://i.sstatic.net/yQEbu.jpg)

**Tags:** mathematics, interpolation, curve, bezier-curve, nurbs

> **Comments:**
> **username_1**: Have you read [this](https://pomax.github.io/bezierinfo/)  
> **username_0**: Thanks for the comment. I haven't read the document, but I saw it in my research. I'm in a bit of a time crunch so more specificity to my issue would be greatly appreciated (in code would be even better). I don't understand mathematic symbols very well. Have you read it? If so, where does it answer how to set 3-point circular Bezier weights?  

---

## 1 answers

### Answer by username_2 on 2020-10-20. Score: 6 | Accepted answer

Check out the section on [Circular Arcs and Circles](https://pages.mtu.edu/%7Eshene/COURSES/cs3621/NOTES/spline/NURBS/RB-circles.html), from [Ching-Kuang Shene's excellent computational geometry course notes](https://pages.mtu.edu/%7Eshene/COURSES/cs3621/NOTES/notes.html):

> [G]iven three control points P0, P1 and P2 such that P0P1 = P1P2 holds, if we choose w, the weight for P1, to be sin(a), where a is the half angle at control point P1, the resulting rational Bézier curve is a circle.

The second diagram on that page is particularly useful. If P0 is at (0,0), P1 is at (1,0), and P2 is at (1,1), then the angle at P1 is 90 degrees; half that is 45, so assigning weights w0 = w2 = 1 and w1 = sin(45) = 1/sqrt(2) will produce a circle.

**EDIT**: To actually implement this from your code: The three points are `[a,b,c]`. If you know that the distance from `a` to `b` is the same as the distance from `b` to `c`, then you can set `w1` and `w3` to 1, and `w2` to the sine of half the angle between them. Look up the [half-angle formula](https://mathworld.wolfram.com/Half-AngleFormulas.html) for sine to see that `sin(x/2) = sqrt((1 - cos x) / 2)`. The cosine of the angle between two vectors is the normalized dot product, i.e. `cos x = dot(a-b,c-b) / (a-b)^2`. Thus, you can do something like

```
ba = a - b
bc = c - b
cosx = ba.Dot(bc) / ba.Dot(ba);
w2 = math.sqrt(0.5 * (1 - cosx));

```

Again, this will only work if the distances `ba` and `bc` are the same. (You can still make a circle otherwise, but the weights will be more compilcated.)

> **Comments:**
> **username_0**: Thank you! Please excuse my ignorance, but what do I use in my code from this equation: `w1 = sin(45) = 1/sqrt(2)`? Having the two equal signs confuses me: is it saying that the `sin(45) == 1/sqrt(2)`?  
> **username_2**: Yes, I was just pointing out that the sine of 45 degrees is one over the square root of two. You'd probably just write `w1 = 1 / sqrt(2)`.  
> **username_0**: Thanks for the reply. Where is the angle variable in that equation? Wouldn't `w1 = sin(x)` be better for a program? Maybe I'm not understanding correctly.  
> **username_3**: You can still make a circle if the distances ba and bc are different?? I don’t think so.  
> **username_4**: In the document the computation of w comes from the equation w/(1+w) = mx/mp1. Where does it come from?  

---

