<p><a href="https://i.sstatic.net/gzxt0.gif" rel="nofollow noreferrer"><img src="https://i.sstatic.net/gzxt0.gif" alt="enter image description here" /></a></p>
<p>After rewriting the application to only render in the display function I have found what the bug was. The line was continuously rewriting on top of the vector in each frame as opposed to each mouse click release. Here is the fully working code. I have also implemented the suggestion above using floating-point variables. A more thorough explanation can be found <a href="https://stackoverflow.com/questions/72312477/how-to-clear-my-beziercurve-vector-to-stop-writing-coordinates-on-top-of-each-ot">here</a>:</p>
<p>header.h</p>
<pre><code>#pragma once

int SCREEN_HEIGHT = 500;

//Point class for taking the points
class Point {
public:
    float x, y;

    void setxy(float x2, float y2)
    {
        x = x2; y = y2;
    }

    //operator overloading for '=' sign
    const Point&amp; operator=(const Point&amp; rPoint)
    {
        x = rPoint.x;
        y = rPoint.y;
        return *this;
    }

};

void drawDot(Point p1)
{
    glBegin(GL_POINTS);
    glVertex2i(p1.x, p1.y);
    glEnd();
}

void drawLine(Point p1, Point p2)
{
    glBegin(GL_LINE_STRIP);
    glVertex2f(p1.x, p1.y);
    glVertex2f(p2.x, p2.y);
    glEnd();
}

float interpolate(float n1, float n2, float perc)
{
    float diff = n2 - n1;

    return n1 + (diff * perc);
}
</code></pre>
<p>main.cpp</p>
<pre><code>#include &lt;iostream&gt;
#include &lt;stdlib.h&gt;
#include &lt;GL/glut.h&gt;
#include &lt;vector&gt;
#include &lt;math.h&gt;
#include &quot;header.h&quot;

using namespace std;

vector&lt;Point&gt; Points;
Point Tangent;
Point inverseTangent;
Point cursorLocationLive;
int TangentsSize = 0;
vector&lt;Point&gt; Tangents(TangentsSize);
vector&lt;Point&gt; inverseTangents(TangentsSize);
vector&lt;Point&gt; BezierCurve;
bool MouseReleased = false;
bool PrevMouse = false;

void myMouse(int button, int state, int x, int y)
{
    if (button == GLUT_LEFT_BUTTON)
    {
        if (state == GLUT_DOWN)
        {
            MouseReleased = false;
            // Store points into Points vector on click
            Point point;
            point.setxy(x, SCREEN_HEIGHT - y);
            Points.push_back(point);

            // Tangents are set to the cursor position
            Tangent.setxy(x, SCREEN_HEIGHT - y);
            inverseTangent.x = (2 * Points[Points.size() - 1].x) - Tangent.x;
            inverseTangent.y = (2 * Points[Points.size() - 1].y) - Tangent.y;

            /*Add new element to Tangent &amp; inverseTangent so when we draw the curve
            the tangents are accessed at the right index*/
            TangentsSize++;
        }
        else if (state == GLUT_UP)
        {
            MouseReleased = true;
            // Upon mouse release store tangent and inverse tangent into separate vectors
            Tangents.push_back(Tangent);
            inverseTangents.push_back(inverseTangent);
        }
    }
}

void passiveMotion(int x, int y)
{
    // Sets the location of cursor while moving with no buttons pressed
    cursorLocationLive.setxy(x, SCREEN_HEIGHT - y);
}

void motion(int x, int y)
{
    // Sets the coordinates of the tangents when mouse moves with a button held down
    Tangent.setxy(x, SCREEN_HEIGHT - y);
    inverseTangent.x = (2 * Points[Points.size() - 1].x) - Tangent.x;
    inverseTangent.y = (2 * Points[Points.size() - 1].y) - Tangent.y;
}

void myDisplay()
{
    glClear(GL_COLOR_BUFFER_BIT);

    // Draw main points in red
    glColor3f(255, 0, 0);
    for (int i = 0; i &lt; Points.size(); i++)
    {
        drawDot(Points[i]);
    }

    // If there is a starting point draw a line to cursor from last drawn point in passive motion
    if (Points.size() &gt; 0)
    {
        glColor3f(0, 0, 0);
        drawLine(Points[Points.size() - 1], cursorLocationLive);
    }

    // Draw live tangent dots in green
    glColor3f(0, 255, 0);
    drawDot(Tangent);
    drawDot(inverseTangent);
    // Draw live tangent lines in blue
    glColor3f(0, 0, 255);
    drawLine(Tangent, inverseTangent);

    for (int i = 0; i &lt; Tangents.size(); i++)
    {
        // Draw stored tangent dots in green
        glColor3f(0, 255, 0);
        drawDot(Tangents[i]);
        drawDot(inverseTangents[i]);
        // Draw stored tangent lines in blue
        glColor3f(0, 0, 255);
        drawLine(Tangents[i], inverseTangents[i]);
    }

    // Loop through all points
    if (Points.size() &gt;= 2)
    {
        // p1 is the start of the curve set to second last point
        Point p1;
        p1 = Points[Points.size() - 2];

        float i;
        // Calculate curve coordinates
        for (float j = 0; j &lt;= 100; j++)
        {
            i = j / 100;
            // The Green Lines
            float xa = interpolate(Points[Points.size() - 2].x, Tangents[TangentsSize - 2].x, i);
            float ya = interpolate(Points[Points.size() - 2].y, Tangents[TangentsSize - 2].y, i);
            float xb = interpolate(Tangents[TangentsSize - 2].x, inverseTangent.x, i);
            float yb = interpolate(Tangents[TangentsSize - 2].y, inverseTangent.y, i);
            float xc = interpolate(inverseTangent.x, Points[Points.size() - 1].x, i);
            float yc = interpolate(inverseTangent.y, Points[Points.size() - 1].y, i);

            // The Blue Line
            float xm = interpolate(xa, xb, i);
            float ym = interpolate(ya, yb, i);
            float xn = interpolate(xb, xc, i);
            float yn = interpolate(yb, yc, i);

            // The Black Dot
            float x2 = interpolate(xm, xn, i);
            float y2 = interpolate(ym, yn, i);

            Point p2;
            p2.setxy(x2, y2);

            glColor3f(0, 0, 0);
            drawLine(p1, p2);

            p1 = p2;

            // Prevents curves generated during mouse motion from being stored
            if (PrevMouse == false &amp;&amp; MouseReleased == true)
            {
                // Store curvature into Bezier Points
                BezierCurve.push_back(p2);
            }
        }
    }

    // When the mouse is down PrevMouse = false so when the mouse is released
    // the if statement evaluates to true and stores the new curvature once
    // and then sets PrevMouse to true to prevent writing on top of the vector
    PrevMouse = MouseReleased;

    // Draw all bezier curvature
    for (int i = 1; i &lt; BezierCurve.size(); i++)
    {
        drawLine(BezierCurve[i - 1], BezierCurve[i]);
    }

    glutSwapBuffers();
}

void timer(int)
{
    glutTimerFunc(1000 / 60, timer, 0);
    glutPostRedisplay();
}

int main(int argc, char* argv[]) {
    glutInit(&amp;argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
    glutInitWindowSize(640, 500);
    glutInitWindowPosition(100, 150);
    glutCreateWindow(&quot;Bezier Curve&quot;);
    glutDisplayFunc(myDisplay);
    glutIdleFunc(myDisplay);
    glutTimerFunc(0, timer, 0);
    glutMouseFunc(myMouse);
    glutPassiveMotionFunc(passiveMotion);
    glutMotionFunc(motion);
    glClearColor(255, 255, 255, 0.0);
    glPointSize(3);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0.0, 640.0, 0.0, 500.0);
    glutMainLoop();

    return 0;
}
</code></pre>

CC BY-SA 4.0
2022-06-16T16:26:37.527Z
2022-06-16T16:45:02.370Z
2022-06-16T16:45:02.370Z
Arjan Singh
<p>IIRC in another question, your said your Point class actually uses <code>float x,y;</code> for the coordinates. So one thing that can help is to shift the centers (the &quot;zeros&quot;) over to the edge of the pixel, like:</p>
<pre><code>int xi = pt.x + 0.5;
int yi = pt.y + 0.5;
</code></pre>
<p>And use those integers in calls the GLUT line drawing api.</p>
<p>I think this change would go inside your <code>drawLine()</code> function.</p>
<p>A more robust, but much more complicated solution would be to do the above <em>and</em> also implement anti-aliased line drawing.</p>

CC BY-SA 4.0
2022-05-17T21:20:42.130Z
My point class does use `float` I added 0.5 to `p1` and `p2` in the `drawLine()` function but nothing new happened. I have since changed all integers in the program to float and that has made the curve a lot smoother but I'm still getting the darn line.
Arjan Singh
CC BY-SA 4.0
2022-05-17T23:10:08.700Z
Curious but how would anti aliased line drawing solve this? I might look into that.
Arjan Singh
CC BY-SA 4.0
2022-05-18T00:47:52.863Z
The "jaggedness" of the lines is called aliasing, because the single pixel *aliases* many possible fractional values nearby. Drawing a line with anti-aliasing means that you treat each pixel as a box and choose the color based on how much of the box is covered by the line. Eg. for a very small 3x3 grid, instead of just black and white, [ (0, 0, 255), (0, 255, 0), (255, 0, 0) ], you blur over the corners a little, making [ (0, 100, 255), (100, 255, 100), (255, 100, 0) ]. So, it helps make the lines look smoother.
luser droog
CC BY-SA 4.0
2022-05-19T12:46:55.397Z
@luserdroog  I apologise for being an utter pedant, but _"The "jaggedness" of the lines is called aliasing, because the single pixel aliases many possible fractional values"_ is probably not really correct. It's hard to express "in the margin" but I would say the "aliasing" really refers to the high frequency content of the line (_imagine the line being represented as the sum of an infinite sequence of sine functions of increasing frequency_) not being low pass filtered before sampling and those then re-appearing (alias/false names) incorrectly as low frequency content.
Simon F
CC BY-SA 4.0
2022-05-19T16:51:21.797Z
@SimonF Do not apologize. "pedant"-away! :) (Also, it's not correct to call it a *blur*.)
luser droog
CC BY-SA 4.0
2022-05-17T12:50:39.723Z
2022-05-17T12:56:55.283Z
2022-05-17T12:56:55.283Z
luser droog
<p>I have created a bezier curve tool and each time I draw a bezier curve segment I get a straight line between each mouse click. I don't understand why this is happening and was wondering if someone could take a look at my render function and see the error. I have been working on this program with some other users on this stack exchange.</p>
<p><a href="https://i.sstatic.net/w3CdT.gif" rel="nofollow noreferrer"><img src="https://i.sstatic.net/w3CdT.gif" alt="enter image description here" /></a></p>
<pre><code>void myDisplay()
{
    glClear(GL_COLOR_BUFFER_BIT);

    if ((pointsVector[0].x != NULL) &amp;&amp; (pointsVector[0].y != NULL))
    {
        drawLine(pointsVector[points], Cursor);
    }

    for (int i = 1; i &lt; points; i++)
    {
        // draw main line &amp; dot
        glColor3f(255, 0, 0);
        drawDot(pointsVector[i - 1]);

        // draw tangent lines and tangent dots
        glColor3f(0, 255, 0);
        drawLine(controlPoints[i + 1], reverseControlPoints[i + 1]);
        glColor3f(0, 0, 255);
        drawDot(controlPoints[i + 1]);
        drawDot(reverseControlPoints[i + 1]);

        vector&lt;Point&gt; finalPoints = final4Points();
        vector&lt;Point&gt; finalPointsReverseP1 = final4PointsReverseP1();

        Point p1;
        if (firstSegmentDrawn == false)
        {
            p1.setxy(pointsVector[0].x, pointsVector[0].y);
        }
        else
        {
            p1.setxy(pointsVector[points - 1].x, pointsVector[points - 1].y);
        }

        if ((finalPoints[2].x != NULL) &amp;&amp; (finalPoints[2].y != NULL))
        {
            if (firstSegmentDrawn == true)
            {
                float i;
                // draw bezier curve
                for (float j = 0; j &lt;= 100; j++)
                {
                    i = j / 100;
                    // The Green Lines
                    int xa = getPt(finalPointsReverseP1[0].x, finalPointsReverseP1[1].x, i);
                    int ya = getPt(finalPointsReverseP1[0].y, finalPointsReverseP1[1].y, i);
                    int xb = getPt(finalPointsReverseP1[1].x, finalPointsReverseP1[2].x, i);
                    int yb = getPt(finalPointsReverseP1[1].y, finalPointsReverseP1[2].y, i);
                    int xc = getPt(finalPointsReverseP1[2].x, finalPointsReverseP1[3].x, i);
                    int yc = getPt(finalPointsReverseP1[2].y, finalPointsReverseP1[3].y, i);

                    // The Blue Line
                    int xm = getPt(xa, xb, i);
                    int ym = getPt(ya, yb, i);
                    int xn = getPt(xb, xc, i);
                    int yn = getPt(yb, yc, i);

                    // The Black Dot
                    int x2 = getPt(xm, xn, i);
                    int y2 = getPt(ym, yn, i);

                    Point p2;
                    p2.setxy(x2, y2);

                    drawLine(p1, p2);
                    //drawDot(p1);

                    p1 = p2;
                    bezierPointsMyDisplay.push_back(p2);
                }
            }
            else
            {
                float i;
                // draw bezier curve
                for (float j = 0; j &lt;= 100; j++)
                {
                    i = j / 100;
                    // The Green Lines
                    int xa = getPt(finalPoints[0].x, finalPoints[1].x, i);
                    int ya = getPt(finalPoints[0].y, finalPoints[1].y, i);
                    int xb = getPt(finalPoints[1].x, finalPoints[2].x, i);
                    int yb = getPt(finalPoints[1].y, finalPoints[2].y, i);
                    int xc = getPt(finalPoints[2].x, finalPoints[3].x, i);
                    int yc = getPt(finalPoints[2].y, finalPoints[3].y, i);

                    // The Blue Line
                    int xm = getPt(xa, xb, i);
                    int ym = getPt(ya, yb, i);
                    int xn = getPt(xb, xc, i);
                    int yn = getPt(yb, yc, i);

                    // The Black Dot
                    int x2 = getPt(xm, xn, i);
                    int y2 = getPt(ym, yn, i);

                    Point p2;
                    p2.setxy(x2, y2);

                    drawLine(p1, p2);
                    //drawDot(p1);

                    p1 = p2;
                    bezierPointsMyDisplay.push_back(p2);
                }
            }
        }
    }

    for (int i = 1; i &lt; bezierPointsMyDisplay.size(); i++)
    {
        drawLine(bezierPointsMyDisplay[i - 1], bezierPointsMyDisplay[i]);
    }

    glutSwapBuffers();
}
</code></pre>
<p>My <code>drawLine()</code> function:</p>
<pre><code>void drawLine(Point p1, Point p2) 
{
    glBegin(GL_LINE_STRIP);
    glVertex2f(p1.x, p1.y);
    glVertex2f(p2.x, p2.y);
    glEnd();
}
</code></pre>

CC BY-SA 4.0
2022-05-17T08:06:31.910Z
It looks like integer truncation. The point vectors are being loaded into integers, but for the line segments to match up correctly you need that fraction as well so your drawing API draws them at the correct subpixel and they should line up better. When drawing lines or polygons you cannot really use integer coordinates.
PaulHK
CC BY-SA 4.0
2022-05-17T20:59:48.650Z
@PaulHK I updated all the coordinates relating to drawing and storing the curve to floating point. The curve looks a lot smoother and matches up better but I'm still getting that line between the points. Any other ideas?
Arjan Singh
CC BY-SA 4.0
2022-05-17T21:13:35.120Z
@PaulHK do I need to make any changes to my `drawLine()` function? (I've shown it above in the question now) I tried doing what Luser said but that didn't really do anything. Maybe I didn't implement it right...?
Arjan Singh
CC BY-SA 4.0
2022-05-19T11:06:35.953Z
Did you change  int x2 = getPt(xm, xn, i);  int y2 = ....   to be   float x2 ...  ? Replace all the coordinate ints inside that loop to floats. Once any coordinate is converted to an int, it will forever lose its fractional part, so even if you cast back from int->float you've still got a truncated float..
PaulHK
<opengl><c++><bezier-curve><glut><line>
Why is there a straight line between my bezier paths?
Arjan Singh
# Why is there a straight line between my bezier paths?

(Asked by: username_0 on 2022-05-17)

I have created a bezier curve tool and each time I draw a bezier curve segment I get a straight line between each mouse click. I don't understand why this is happening and was wondering if someone could take a look at my render function and see the error. I have been working on this program with some other users on this stack exchange.

[![enter image description here](https://i.sstatic.net/w3CdT.gif)](https://i.sstatic.net/w3CdT.gif)

```
void myDisplay()
{
    glClear(GL_COLOR_BUFFER_BIT);

    if ((pointsVector[0].x != NULL) && (pointsVector[0].y != NULL))
    {
        drawLine(pointsVector[points], Cursor);
    }

    for (int i = 1; i < points; i++)
    {
        // draw main line & dot
        glColor3f(255, 0, 0);
        drawDot(pointsVector[i - 1]);

        // draw tangent lines and tangent dots
        glColor3f(0, 255, 0);
        drawLine(controlPoints[i + 1], reverseControlPoints[i + 1]);
        glColor3f(0, 0, 255);
        drawDot(controlPoints[i + 1]);
        drawDot(reverseControlPoints[i + 1]);

        vector<Point> finalPoints = final4Points();
        vector<Point> finalPointsReverseP1 = final4PointsReverseP1();

        Point p1;
        if (firstSegmentDrawn == false)
        {
            p1.setxy(pointsVector[0].x, pointsVector[0].y);
        }
        else
        {
            p1.setxy(pointsVector[points - 1].x, pointsVector[points - 1].y);
        }

        if ((finalPoints[2].x != NULL) && (finalPoints[2].y != NULL))
        {
            if (firstSegmentDrawn == true)
            {
                float i;
                // draw bezier curve
                for (float j = 0; j <= 100; j++)
                {
                    i = j / 100;
                    // The Green Lines
                    int xa = getPt(finalPointsReverseP1[0].x, finalPointsReverseP1[1].x, i);
                    int ya = getPt(finalPointsReverseP1[0].y, finalPointsReverseP1[1].y, i);
                    int xb = getPt(finalPointsReverseP1[1].x, finalPointsReverseP1[2].x, i);
                    int yb = getPt(finalPointsReverseP1[1].y, finalPointsReverseP1[2].y, i);
                    int xc = getPt(finalPointsReverseP1[2].x, finalPointsReverseP1[3].x, i);
                    int yc = getPt(finalPointsReverseP1[2].y, finalPointsReverseP1[3].y, i);

                    // The Blue Line
                    int xm = getPt(xa, xb, i);
                    int ym = getPt(ya, yb, i);
                    int xn = getPt(xb, xc, i);
                    int yn = getPt(yb, yc, i);

                    // The Black Dot
                    int x2 = getPt(xm, xn, i);
                    int y2 = getPt(ym, yn, i);

                    Point p2;
                    p2.setxy(x2, y2);

                    drawLine(p1, p2);
                    //drawDot(p1);

                    p1 = p2;
                    bezierPointsMyDisplay.push_back(p2);
                }
            }
            else
            {
                float i;
                // draw bezier curve
                for (float j = 0; j <= 100; j++)
                {
                    i = j / 100;
                    // The Green Lines
                    int xa = getPt(finalPoints[0].x, finalPoints[1].x, i);
                    int ya = getPt(finalPoints[0].y, finalPoints[1].y, i);
                    int xb = getPt(finalPoints[1].x, finalPoints[2].x, i);
                    int yb = getPt(finalPoints[1].y, finalPoints[2].y, i);
                    int xc = getPt(finalPoints[2].x, finalPoints[3].x, i);
                    int yc = getPt(finalPoints[2].y, finalPoints[3].y, i);

                    // The Blue Line
                    int xm = getPt(xa, xb, i);
                    int ym = getPt(ya, yb, i);
                    int xn = getPt(xb, xc, i);
                    int yn = getPt(yb, yc, i);

                    // The Black Dot
                    int x2 = getPt(xm, xn, i);
                    int y2 = getPt(ym, yn, i);

                    Point p2;
                    p2.setxy(x2, y2);

                    drawLine(p1, p2);
                    //drawDot(p1);

                    p1 = p2;
                    bezierPointsMyDisplay.push_back(p2);
                }
            }
        }
    }

    for (int i = 1; i < bezierPointsMyDisplay.size(); i++)
    {
        drawLine(bezierPointsMyDisplay[i - 1], bezierPointsMyDisplay[i]);
    }

    glutSwapBuffers();
}

```

My `drawLine()` function:

```
void drawLine(Point p1, Point p2) 
{
    glBegin(GL_LINE_STRIP);
    glVertex2f(p1.x, p1.y);
    glVertex2f(p2.x, p2.y);
    glEnd();
}

```

**Tags:** opengl, c++, bezier-curve, glut, line

> **Comments:**
> **username_1**: It looks like integer truncation. The point vectors are being loaded into integers, but for the line segments to match up correctly you need that fraction as well so your drawing API draws them at the correct subpixel and they should line up better. When drawing lines or polygons you cannot really use integer coordinates.  
> **username_0**: @username_1 I updated all the coordinates relating to drawing and storing the curve to floating point. The curve looks a lot smoother and matches up better but I'm still getting that line between the points. Any other ideas?  
> **username_0**: @username_1 do I need to make any changes to my `drawLine()` function? (I've shown it above in the question now) I tried doing what username_2 said but that didn't really do anything. Maybe I didn't implement it right...?  
> **username_1**: Did you change  int x2 = getPt(xm, xn, i);  int y2 = ....   to be   float x2 ...  ? Replace all the coordinate ints inside that loop to floats. Once any coordinate is converted to an int, it will forever lose its fractional part, so even if you cast back from int->float you've still got a truncated float..  

---

## 2 answers

### Answer by username_0 on 2022-06-16. Score: 0 | Accepted answer

[![enter image description here](https://i.sstatic.net/gzxt0.gif)](https://i.sstatic.net/gzxt0.gif)

After rewriting the application to only render in the display function I have found what the bug was. The line was continuously rewriting on top of the vector in each frame as opposed to each mouse click release. Here is the fully working code. I have also implemented the suggestion above using floating-point variables. A more thorough explanation can be found [here](https://stackoverflow.com/questions/72312477/how-to-clear-my-beziercurve-vector-to-stop-writing-coordinates-on-top-of-each-ot):

header.h

```
#pragma once

int SCREEN_HEIGHT = 500;

//Point class for taking the points
class Point {
public:
    float x, y;

    void setxy(float x2, float y2)
    {
        x = x2; y = y2;
    }

    //operator overloading for '=' sign
    const Point& operator=(const Point& rPoint)
    {
        x = rPoint.x;
        y = rPoint.y;
        return *this;
    }

};

void drawDot(Point p1)
{
    glBegin(GL_POINTS);
    glVertex2i(p1.x, p1.y);
    glEnd();
}

void drawLine(Point p1, Point p2)
{
    glBegin(GL_LINE_STRIP);
    glVertex2f(p1.x, p1.y);
    glVertex2f(p2.x, p2.y);
    glEnd();
}

float interpolate(float n1, float n2, float perc)
{
    float diff = n2 - n1;

    return n1 + (diff * perc);
}

```

main.cpp

```
#include <iostream>
#include <stdlib.h>
#include <GL/glut.h>
#include <vector>
#include <math.h>
#include "header.h"

using namespace std;

vector<Point> Points;
Point Tangent;
Point inverseTangent;
Point cursorLocationLive;
int TangentsSize = 0;
vector<Point> Tangents(TangentsSize);
vector<Point> inverseTangents(TangentsSize);
vector<Point> BezierCurve;
bool MouseReleased = false;
bool PrevMouse = false;

void myMouse(int button, int state, int x, int y)
{
    if (button == GLUT_LEFT_BUTTON)
    {
        if (state == GLUT_DOWN)
        {
            MouseReleased = false;
            // Store points into Points vector on click
            Point point;
            point.setxy(x, SCREEN_HEIGHT - y);
            Points.push_back(point);

            // Tangents are set to the cursor position
            Tangent.setxy(x, SCREEN_HEIGHT - y);
            inverseTangent.x = (2 * Points[Points.size() - 1].x) - Tangent.x;
            inverseTangent.y = (2 * Points[Points.size() - 1].y) - Tangent.y;

            /*Add new element to Tangent & inverseTangent so when we draw the curve
            the tangents are accessed at the right index*/
            TangentsSize++;
        }
        else if (state == GLUT_UP)
        {
            MouseReleased = true;
            // Upon mouse release store tangent and inverse tangent into separate vectors
            Tangents.push_back(Tangent);
            inverseTangents.push_back(inverseTangent);
        }
    }
}

void passiveMotion(int x, int y)
{
    // Sets the location of cursor while moving with no buttons pressed
    cursorLocationLive.setxy(x, SCREEN_HEIGHT - y);
}

void motion(int x, int y)
{
    // Sets the coordinates of the tangents when mouse moves with a button held down
    Tangent.setxy(x, SCREEN_HEIGHT - y);
    inverseTangent.x = (2 * Points[Points.size() - 1].x) - Tangent.x;
    inverseTangent.y = (2 * Points[Points.size() - 1].y) - Tangent.y;
}

void myDisplay()
{
    glClear(GL_COLOR_BUFFER_BIT);

    // Draw main points in red
    glColor3f(255, 0, 0);
    for (int i = 0; i < Points.size(); i++)
    {
        drawDot(Points[i]);
    }

    // If there is a starting point draw a line to cursor from last drawn point in passive motion
    if (Points.size() > 0)
    {
        glColor3f(0, 0, 0);
        drawLine(Points[Points.size() - 1], cursorLocationLive);
    }

    // Draw live tangent dots in green
    glColor3f(0, 255, 0);
    drawDot(Tangent);
    drawDot(inverseTangent);
    // Draw live tangent lines in blue
    glColor3f(0, 0, 255);
    drawLine(Tangent, inverseTangent);

    for (int i = 0; i < Tangents.size(); i++)
    {
        // Draw stored tangent dots in green
        glColor3f(0, 255, 0);
        drawDot(Tangents[i]);
        drawDot(inverseTangents[i]);
        // Draw stored tangent lines in blue
        glColor3f(0, 0, 255);
        drawLine(Tangents[i], inverseTangents[i]);
    }

    // Loop through all points
    if (Points.size() >= 2)
    {
        // p1 is the start of the curve set to second last point
        Point p1;
        p1 = Points[Points.size() - 2];

        float i;
        // Calculate curve coordinates
        for (float j = 0; j <= 100; j++)
        {
            i = j / 100;
            // The Green Lines
            float xa = interpolate(Points[Points.size() - 2].x, Tangents[TangentsSize - 2].x, i);
            float ya = interpolate(Points[Points.size() - 2].y, Tangents[TangentsSize - 2].y, i);
            float xb = interpolate(Tangents[TangentsSize - 2].x, inverseTangent.x, i);
            float yb = interpolate(Tangents[TangentsSize - 2].y, inverseTangent.y, i);
            float xc = interpolate(inverseTangent.x, Points[Points.size() - 1].x, i);
            float yc = interpolate(inverseTangent.y, Points[Points.size() - 1].y, i);

            // The Blue Line
            float xm = interpolate(xa, xb, i);
            float ym = interpolate(ya, yb, i);
            float xn = interpolate(xb, xc, i);
            float yn = interpolate(yb, yc, i);

            // The Black Dot
            float x2 = interpolate(xm, xn, i);
            float y2 = interpolate(ym, yn, i);

            Point p2;
            p2.setxy(x2, y2);

            glColor3f(0, 0, 0);
            drawLine(p1, p2);

            p1 = p2;

            // Prevents curves generated during mouse motion from being stored
            if (PrevMouse == false && MouseReleased == true)
            {
                // Store curvature into Bezier Points
                BezierCurve.push_back(p2);
            }
        }
    }

    // When the mouse is down PrevMouse = false so when the mouse is released
    // the if statement evaluates to true and stores the new curvature once
    // and then sets PrevMouse to true to prevent writing on top of the vector
    PrevMouse = MouseReleased;

    // Draw all bezier curvature
    for (int i = 1; i < BezierCurve.size(); i++)
    {
        drawLine(BezierCurve[i - 1], BezierCurve[i]);
    }

    glutSwapBuffers();
}

void timer(int)
{
    glutTimerFunc(1000 / 60, timer, 0);
    glutPostRedisplay();
}

int main(int argc, char* argv[]) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
    glutInitWindowSize(640, 500);
    glutInitWindowPosition(100, 150);
    glutCreateWindow("Bezier Curve");
    glutDisplayFunc(myDisplay);
    glutIdleFunc(myDisplay);
    glutTimerFunc(0, timer, 0);
    glutMouseFunc(myMouse);
    glutPassiveMotionFunc(passiveMotion);
    glutMotionFunc(motion);
    glClearColor(255, 255, 255, 0.0);
    glPointSize(3);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0.0, 640.0, 0.0, 500.0);
    glutMainLoop();

    return 0;
}

```


---

### Answer by username_2 on 2022-05-17. Score: 1

IIRC in another question, your said your Point class actually uses `float x,y;` for the coordinates. So one thing that can help is to shift the centers (the "zeros") over to the edge of the pixel, like:

```
int xi = pt.x + 0.5;
int yi = pt.y + 0.5;

```

And use those integers in calls the GLUT line drawing api.

I think this change would go inside your `drawLine()` function.

A more robust, but much more complicated solution would be to do the above *and* also implement anti-aliased line drawing.

> **Comments:**
> **username_0**: My point class does use `float` I added 0.5 to `p1` and `p2` in the `drawLine()` function but nothing new happened. I have since changed all integers in the program to float and that has made the curve a lot smoother but I'm still getting the darn line.  
> **username_0**: Curious but how would anti aliased line drawing solve this? I might look into that.  
> **username_2**: The "jaggedness" of the lines is called aliasing, because the single pixel *aliases* many possible fractional values nearby. Drawing a line with anti-aliasing means that you treat each pixel as a box and choose the color based on how much of the box is covered by the line. Eg. for a very small 3x3 grid, instead of just black and white, [ (0, 0, 255), (0, 255, 0), (255, 0, 0) ], you blur over the corners a little, making [ (0, 100, 255), (100, 255, 100), (255, 100, 0) ]. So, it helps make the lines look smoother.  
> **username_3**: @username_2  I apologise for being an utter pedant, but _"The "jaggedness" of the lines is called aliasing, because the single pixel aliases many possible fractional values"_ is probably not really correct. It's hard to express "in the margin" but I would say the "aliasing" really refers to the high frequency content of the line (_imagine the line being represented as the sum of an infinite sequence of sine functions of increasing frequency_) not being low pass filtered before sampling and those then re-appearing (alias/false names) incorrectly as low frequency content.  
> **username_2**: @username_3 Do not apologize. "pedant"-away! :) (Also, it's not correct to call it a *blur*.)  

---

