I've done some research and there are many methods to doing this if the vertices and points are predetermined as seen here. However in my case, everything is specified by the user. The code I have put together (with the help of others), allows the user to create the polygon, and place points. I wrote functions to try and create vectors from the point to the vertices and then compute the angle. If it comes to 360 it should be inside and it should be colored green. Else it should be outside and red.
This is what I've been working on, but I cant seem to figure it out:
(Edit: Included my entire code)
GLint vert[100][2];
int width = 400, height = 600, n = 0, m = 0, type = GL_LINE_STRIP, v;
bool rubberbanding = false;
bool closed = false;
double testx, testy;
bool isitin;
double dotp(double x1, double y1, double x2, double y2) {
double a;
a = (x1 * x2) + (y1 * y2);
return a;
}
double mag(double x1, double y1, double x2, double y2) {
double a;
double x = (x2 - x1);
double y = (y2 - y1);
a = sqrt((x*x) + (y*y));
return a;
}
bool inpoly(int numv, GLint vx[][2], GLint vy[][2], double tx, double ty) {
double angle = 0.0;
int n = 0;
while (n != numv) {
//vector from point to vertex
double newv1x = vx[n][0] - tx;
double newv1y = vy[n][1] - ty;
double magv1 = mag(tx, ty, vx[n][0], vy[n][1]); //magnitude of vector
//vector from point to next vertex
double newv2x = vx[n + 1][0] - tx;
double newv2y = vy[n + 1][1] - ty;
double magv2 = mag(tx, ty, vx[n+1][0], vy[n+1][1]);//magnitude of vector
//dot product between the two vectors
double dp = dotp(newv1x, newv1y, newv2x, newv2y);
//angle between two vectors
double vang = acos(dp / (magv1*magv2));
angle += vang;
n++;
}
//vector from point to last vertex
double newv1x = vx[numv][0] - tx;
double newv1y = vy[numv][1] - ty;
double magv1 = mag(tx, ty, vx[numv][0], vy[numv][1]); //magnitude of vector
//vector from point to first vertex
double newv2x = vx[0][0] - tx;
double newv2y = vy[0][1] - ty;
double magv2 = mag(tx, ty, vx[0][0], vy[0][1]);//magnitude of vector
//dot product between the two vectors
double dp = dotp(newv1x, newv1y, newv2x, newv2y);
//angle between two vectors
double vang = acos(dp / (magv1*magv2));
angle += vang;
if (angle == 360.0) return true;
return false;
}
void display(){
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1, 1, 0);
glBegin(closed ? GL_LINE_LOOP : GL_LINE_STRIP);
for(int i = 0; i < m; i++){
glVertex2iv(vert[i]);
}
glEnd();
/*
glColor3f(0, 0, 1);
glBegin(GL_POINTS);
for (int i = m; i < n; i++) {
glVertex2iv(vert[i]);
}
*/
isitin = inpoly(m, vert, vert, testx, testy);
if (isitin == true) {
glColor3f(0, 1, 0);
glBegin(GL_POINTS);
for (int i = m; i < n; i++) {
glVertex2iv(vert[i]);
}
}
else {
glColor3f(1, 0, 0);
glBegin(GL_POINTS);
for (int i = m; i < n; i++) {
glVertex2iv(vert[i]);
}
}
glEnd();
glutSwapBuffers();
glutPostRedisplay();
}
void keyboard(unsigned char key, int x, int y){
switch(key){
case 'r': n = 0; m = 0; closed = false; break;
case 'c': closed = true; break;
}
glutPostRedisplay();
}
int findVertex(int x, int y){
int dx, dy;
for(int i = 0; i < n; i++){
dx = vert[i][0] - x;
dy = vert[i][1] - y;
if(dx*dx + dy*dy < 16) return i;
}
return - 1;
}
void mousemove(int x, int y)
{
testx = x;
testy = height - 1 - y;
}
void mouse(int button, int state, int x, int y){
switch(button){
case GLUT_LEFT_BUTTON:
if(state == GLUT_DOWN){
if (n < 100) {
v = n++;
vert[v][0] = x;
vert[v][1] = height - 1 - y;
// n++;
rubberbanding = true;
glutPostRedisplay();
if (!closed) m = n;
}
}
else{
rubberbanding = false;
}
break;
}
}
void motion(int x, int y){
if(rubberbanding){
vert[v][0] = x;
vert[v][1] = height - 1 - y;
glutPostRedisplay();
}
}
void main(int argc, char** argv){
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB|GLUT_DOUBLE);
glutInitWindowSize(width,height);
glutInitWindowPosition(50,100);
glutCreateWindow("Project 3");
glClearColor(0.0,0.0,0.0,0.0);
glColor3f( 1, 1, 0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, width, 0, height);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glutDisplayFunc(display);
glutKeyboardFunc(keyboard);
glutMouseFunc(mouse);
glutPassiveMotionFunc(mousemove);
glutMotionFunc(motion);
glutMainLoop();
}
When I run the program in Visual Studio, I can draw the polygon, and I can specify
points, but for some reason all the points appear red. If anyone has any ideas on how to fix this, it would be greatly appreciated.
Probably your error is that acos returns in radians, and you're testing if the sum equals 360 degrees.
Also, you shouldn't compare doubles that way, since that calculation is probably adding rounding error in each sum. See here for more information.
Related
I have built a Bezier Curve tool and each time the coordinates for each curve segment are calculated they are stored in a vector. Every single frame I am adding the entire curve's points on it over and over again. That is, frame 1, might have { p1, p2, p3 } then frame 2, it would have { p1, p2, p3, p1, p2, p3 } and so on. This would cause the line to loop back on itself when the loop at the end of the render function draws lines between the points p3 and p1. I am struggling to find where and how I should clear my BezierCurve vector between frames. Clearing after glClear() or before glSwapBuffers() only shows the previously drawn curve segment and has a straight line between points.
I basically want the straight line in between points to go away and I know why it is happening. My code is below:
#include <iostream>
#include <stdlib.h>
#include <GL/glut.h>
#include <vector>
#include <math.h>
using namespace std;
//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;
}
};
int SCREEN_HEIGHT = 500;
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;
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);
}
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
for (int i = 0; i < Points.size(); i++)
{
// If there are two points draw the first segment
if (Points.size() == 2)
{
// p1 is the start of the curve set at first point
Point p1;
p1 = Points[0];
float i;
// Calculate curve coordinates
for (float j = 0; j <= 100; j++)
{
i = j / 100;
// The Green Lines
float xa = interpolate(Points[0].x, inverseTangents[0].x, i);
float ya = interpolate(Points[0].y, inverseTangents[0].y, i);
float xb = interpolate(inverseTangents[0].x, inverseTangent.x, i);
float yb = interpolate(inverseTangents[0].y, inverseTangent.y, i);
float xc = interpolate(inverseTangent.x, Points[1].x, i);
float yc = interpolate(inverseTangent.y, Points[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);
drawLine(p1, p2);
p1 = p2;
// Prevents curves generated during mouse motion from being stored
if (MouseReleased)
{
// Store curvature into Bezier Points
BezierCurve.push_back(p2);
}
}
}
// Second segment onwards
else 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);
drawLine(p1, p2);
p1 = p2;
// Prevents curves generated during mouse motion from being stored
if (MouseReleased)
{
// Store curvature into Bezier Points
BezierCurve.push_back(p2);
}
}
}
}
// 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;
}
You will want to detect when mouse click changes from down to up:
bool prevMouse;
...
// at the end of Display()
prevMouse = MouseReleased;
Then we check when mouse click changes from pressed to released and add lines to BezierCurve:
if (PrevMouse == 0 && MouseReleased)
{
// Store curvature into Bezier Points
BezierCurve.push_back(p2);
}
The two code paths, if (Points.size() == 2), and else if (Points.size() > 2) inside the for loop can be simplified to if (Points.size() >= 2) and for that matter the for loop is extraneous, we don't need to update the bezier curve for any of the previous points, just the curve between the two newest points, Points[Points.size() - 2] and Points[Points.size() - 1].
The final code:
#include <iostream>
#include <stdlib.h>
#include <GL/glut.h>
#include <vector>
#include <math.h>
using namespace std;
//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;
}
};
int SCREEN_HEIGHT = 500;
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 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);
}
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);
drawLine(p1, p2);
p1 = p2;
// Prevents curves generated during mouse motion from being stored
if (PrevMouse == 0 && MouseReleased)
{
// Store curvature into Bezier Points
BezierCurve.push_back(p2);
}
}
}
std::cout << BezierCurve.size() << std::endl;
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;
}
This is my fist time studying Computer Graphics and i was given the code below from my professor. I think i have understood how the algorithm is implemented in general, but what i fail to understand is in what way the incx,incy,inc1,inc2 lines work. I obviously know they are there to increase something but since i haven't fully understood the algorithm i'm kinda baffled. This is the full code:
#include <gl/glut.h>
#include <stdio.h>
int xstart, ystart, xend, yend;
void myInit() {
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(0.0, 0.0, 0.0, 1.0);
glMatrixMode(GL_PROJECTION);
gluOrtho2D(0, 500, 0, 500);
}
void draw_pixel(int x, int y) {
glBegin(GL_POINTS);
glVertex2i(x, y);
glEnd();
}
void draw_line(int xstart, int xend, int ystart, int yend) {
int dx, dy, i, e;
int incx, incy, inc1, inc2;
int x,y;
dx = xend-xstart;
dy = yend-ystart;
if (dx < 0) dx = -dx;
if (dy < 0) dy = -dy;
incx = 1;
if (xend < xstart) incx = -1;
incy = 1;
if (yend < ystart) incy = -1;
x = xstart;
y = ystart;
if (dx > dy) {
draw_pixel(x, y);
e = 2 * dy-dx;
inc1 = 2*(dy-dx);
inc2 = 2*dy;
for (i=0; i<dx; i++) {
if (e >= 0) {
y += incy;
e += inc1;
}
else
e += inc2;
x += incx;
draw_pixel(x, y);
}
} else {
draw_pixel(x, y);
e = 2*dx-dy;
inc1 = 2*(dx-dy);
inc2 = 2*dx;
for (i=0; i<dy; i++) {
if (e >= 0) {
x += incx;
e += inc1;
}
else
e += inc2;
y += incy;
draw_pixel(x, y);
}
}
}
void myDisplay() {
draw_line(xstart, xend, ystart, yend);
glFlush();
}
void main(int argc, char **argv) {
printf( "Enter (xstart, ystart, xend, yend)\n");
scanf("%d %d %d %d", &xstart, &ystart, &xend, ¥d);
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutInitWindowSize(500, 500);
glutInitWindowPosition(0, 0);
glutCreateWindow("Bresenham's Line Algorithm Visualization");
myInit();
glutDisplayFunc(myDisplay);
glutMainLoop();
}
I'm trying to make Bezier curve by control point.
I have some examples and followed it. But it did not work.
It shows the line is going to (0, 0) points during working.
I still don't get it why.
Here's the code in the C++ language, using OpenGL.
#define _CRT_SECURE_NO_WARNINGS
#include <Windows.h>
#include <gl/glut.h>
#include <gl/GLU.h>
#include <gl/GL.h>
#include <math.h>
#define CTRL_COUNT 100
void display();
void init();
float getNextBezierPointX(float t);
float getNextBezierPointY(float t);
void drawline();
int ctrlPointsCount;
int ctrlPointsX[CTRL_COUNT], ctrlPointsY[CTRL_COUNT];
int X1[20] = { 10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90,95,100,105 };
int Y1[20] = { 50,60,40,70,40,60,35,80,45,55,30,60,40,60,40,55,35,70,40,50 };
void main(int argc, char *argv[]) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(500, 500);
glutInitWindowPosition(500, 300);
glutCreateWindow("Bezier");
glutDisplayFunc(display);
init();
glutMainLoop();
}
void display() {
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0, 0.0, 0.0);
ctrlPointsCount = 20;
for (int i = 0; i < 20; i++) {
ctrlPointsX[i] = X1[i];
ctrlPointsY[i] = Y1[i];
}
drawline();
glFlush();
}
void init() {
glClearColor(0.0, 0.0, 0.0, 0.0);
glColor3f(1.0, 0.0, 0.0);
glPointSize(8.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, 128.0, 0.0, 96.0);
}
float getNextBezierPointX(float t) {
float x = 0.0;
int c;
for (int i = 0; i < ctrlPointsCount; i ++) {
if (i == 0 || i == ctrlPointsCount - 1)
c = 1;
else
c = ctrlPointsCount - 1;
x = x + c * pow(t, i) * pow(1 - t, ctrlPointsCount - 1 - i) * ctrlPointsX[i];
}
return x;
}
float getNextBezierPointY(float t) {
float y = 0.0;
int c;
for (int i = 0; i < ctrlPointsCount; i ++) {
if (i == 0 || i == ctrlPointsCount - 1)
c = 1;
else
c = ctrlPointsCount - 1;
y = y + c * pow(t, i) * pow(1 - t, ctrlPointsCount - 1 - i) * ctrlPointsY[i];
}
return y;
}
void drawline() {
float x, y;
for (int i = 0; i < 20; i++) {
glBegin(GL_POINTS);
glVertex2i(ctrlPointsX[i], ctrlPointsY[i]);
glEnd();
glFlush();
}
float oldX = ctrlPointsX[0], oldY = ctrlPointsY[0];
for (double t = 0.0; t <= 1.0; t += 0.01) {
x = getNextBezierPointX(t);
y = getNextBezierPointY(t);
glColor3f(1.0, 1.0, 1.0);
glBegin(GL_LINES);
glVertex2f(oldX, oldY);
glVertex2f(x, y);
glEnd();
glFlush();
oldX = x;
oldY = y;
}
}
For a bezier curve like this you have to calculate Bernstein polynomials:
double factorial(int n)
{
double x = 1.0;
for (int i = 1; i <= n; i++)
x *= (double)i;
return x;
}
double Ni(int n, int i)
{
double a1 = factorial(n);
double a2 = factorial(i);
double a3 = factorial(n - i);
double ni = a1/ (a2 * a3);
return ni;
}
double Bernstein(int n, int i, double t)
{
double ti = (t == 0.0 && i == 0) ? 1.0 : pow(t, i); /* t^i */
double tni = (n == i && t == 1.0) ? 1.0 : pow((1 - t), (n - i)); /* (1 - t)^i */
double basis = Ni(n, i) * ti * tni; //Bernstein basis
return basis;
}
The code to create the curve may look like this:
struct vec2
{
double x, y;
};
vec2 getBezierPoint(float t, int n, int x[], int y[] )
{
vec2 pt{ 0.0, 0.0 };
for (int i = 0; i < n; i ++) {
double b = Bernstein( n - 1, i, t );
pt.x += b * x[i];
pt.y += b * y[i];
}
return pt;
}
float oldX = ctrlPointsX[0], oldY = ctrlPointsY[0];
for (double t = 0.0; t <= 1.0; t += 0.01)
{
vec2 pt = getBezierPoint( t, ctrlPointsCount, ctrlPointsX, ctrlPointsY );
glColor3f(1.0, 1.0, 1.0);
glBegin(GL_LINES);
glVertex2f(oldX, oldY);
glVertex2f((float)pt.x, (float)pt.y);
glEnd();
glFlush();
oldX = (float)pt.x; oldY = (float)pt.y;
}
An other solution is provided in the answer to the Stack Overflow question How do I implement a Bézier curve in C++?:
#include <vector>
vec2 getBezierPoint2( float t, int n, int x[], int y[] )
{
std::vector<double> tmpx( n ), tmpy( n );
for ( int i=0; i<n; ++ i )
{
tmpx[i] = x[i];
tmpy[i] = y[i];
}
int i = n - 1;
while (i > 0)
{
for (int k = 0; k < i; k++)
{
tmpx[k] = tmpx[k] + t * ( tmpx[k+1] - tmpx[k] );
tmpy[k] = tmpy[k] + t * ( tmpy[k+1] - tmpy[k] );
}
i--;
}
return { tmpx[0], tmpy[0] };
}
But may be the result is not what you expect it to be, because you create a Higher-order Bézier curve which results in a very flat curve:
Maybe you want to connect any number of points with square bezier curves: Quadratic Bézier Curve: Calculate Points
I have to write a function, which detects intersection and returns true or false.
I have Shape.cpp file, and rectangle.cpp, circle.cpp files inherits of it. I tried to calculate it, but i failed. There is no error, but when my program starts, it crashes. MY Question is why it crashes? is my way wrongs? Here is circle.cpp file.
bool Circ::intersects(Shape* pshape)
{
Rect *p1 = dynamic_cast<Rect*>(pshape);
Circ *p2 = dynamic_cast<Circ*>(pshape);
if(p1)
{
float circleDistance_x = abs(p2->getPos().x - p1->getPos().x);
float circleDistance_y = abs(p2->getPos().y - p1->getPos().y);
if(circleDistance_x > (p1->getSize().x/2 + p2->getRad()))
return false;
if(circleDistance_y > (p1->getSize().y/2 + p2->getRad()))
return false;
if(circleDistance_x <= (p1->getSize().x/2))
return true;
if(circleDistance_y <= (p1->getSize().y/2))
return true;
float cornerDistance_sq = (circleDistance_x - (p1->getSize().x/2)) + (circleDistance_y - (p1->getSize().y/2))*(circleDistance_y - (p1->getSize().y/2));
return (cornerDistance_sq <= p2->getRad()^2);
}
return false;
}
This is not the code all i want to write. But when it fails, i stopped to write.
and my Shapes.h file
#ifndef _SHAPES_H
#define _SHAPES_H
struct Point2d
{
float x, y;
};
struct Point3d
{
float r, g, b;
};
class Shape
{
protected:
bool m_bMarked;
Point3d m_col;
Point2d m_veldir;
Point2d m_pos;
float m_vel;
public:
Shape(Point2d& pos, Point2d& veldir, float vel, Point3d& col)
:m_pos(pos),m_veldir(veldir),m_vel(vel),m_col(col)
{
m_bMarked = false;
}
virtual ~Shape() {}
virtual void draw() = 0;
virtual bool intersects(Shape*) = 0;
inline void move() { m_pos.x += m_veldir.x*m_vel; m_pos.y += m_veldir.y*m_vel; }
inline void invert_xdir() { m_veldir.x *= -1; }
inline void invert_ydir() { m_veldir.y *= -1; }
inline void MarkShape() { m_bMarked = true; }
inline void UnMarkShape() { m_bMarked = false; }
inline bool isMarked() { return m_bMarked; }
inline void increase_vel() { m_vel += 0.01f; }
inline void decrease_vel() { m_vel -= 0.01f; }
};
#endif
And finally my ShapesMain.cpp file
#include <time.h>
#include <GL/glut.h>
#include <cmath>
#include "Rectangle.h"
#include "Circle.h"
// YOU CAN CHANGE THE NUMBER OF SHAPES
#define SHAPE_COUNT 20
// YOU CAN MODIFY WINDOW SIZE BY CHANGING THESE
// YOU MAY ALSO VIEW WINDOW IN FULL SCREEN
#define WINDOWX 500
#define WINDOWY 500
// UNCOMMENT THE LINE BELOW TO STOP MOVING SHAPES
//#define NO_MOTION
// CHANGE THESE DIMENSIONS HOWEVER YOU LIKE
#define MAX_SHAPE_DIM 70
#define MIN_SHAPE_DIM 10
float g_windowWidth = WINDOWX;
float g_windowHeight = WINDOWY;
Shape* g_shapeList[SHAPE_COUNT];
int g_numShapes = 0;
bool g_bShowIntersection = true;
//------------------------------------
void Initialize()
{
srand ( time(NULL) );
// delete previous shapes, if there is any
if (g_numShapes > 0)
{
for (int i = 0; i < g_numShapes; i++)
delete g_shapeList[i];
}
// create a new shape repository
do {
g_numShapes = rand() % SHAPE_COUNT; // number of shapes are randomly determined
} while (g_numShapes < 5); // we dont want to have less than 5 shapes
int rect_count = g_numShapes * (rand() % 10 / 10.0f);
int circle_count = g_numShapes - rect_count;
int half_wind_x = 3* g_windowWidth / 4;
int half_wind_y = 3* g_windowHeight / 4;
int max_dim = MAX_SHAPE_DIM; // max dim. of any shape
int min_dim = MIN_SHAPE_DIM; // min dim. of any shape
int quad_wind = g_windowWidth / 4;
for (int i= 0; i<g_numShapes; i++)
{
float x, y;
float v1, v2;
// set positions
do {
x = rand() % half_wind_x;
} while (x <= quad_wind);
do {
y = rand() % half_wind_y;
} while (y <= quad_wind);
Point2d pos = { x,y };
// set velocity directions
do{
v1 = rand() % 10 / 10.0f;
v2 = rand() % 10 / 10.0f;
} while (v1 == 0 || v2 == 0);
v1 *= (rand() % 2) ? -1 : 1;
v2 *= (rand() % 2) ? -1 : 1;
float vnorm = sqrt(v1*v1 + v2*v2);
Point2d veldir = { v1 / vnorm, v2 / vnorm };
// set velocity
float vel;
do {
vel = rand() % 2 / 10.0f;
} while (vel == 0);
#ifdef NO_MOTION
vel = 0.0f;
#endif
//set color
float R = rand()%100/100.0f;
float G = rand()%100/100.0f;
float B = rand()%100/100.0f;
Point3d color = { R,G,B };
// construct objects
if (i < rect_count)
{
float wx;
float wy;
do {
wx = rand() % quad_wind;
} while (wx < min_dim || wx>max_dim);
do {
wy = rand() % quad_wind;
} while (wy < min_dim || wy>max_dim);
Point2d size = { wx, wy };
Rect* pRect = new Rect(pos, size, veldir, vel, color);
g_shapeList[i] = pRect;
}
else
{
float rad;
do {
rad = rand() % quad_wind;
} while (rad < min_dim || rad>max_dim);
Circ* pCirc = new Circ(pos, rad, veldir, vel, color);
g_shapeList[i] = pCirc;
}
}
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
}
//-------------------------------------
// This function handles the intersections of shapes.
// if the user is not interested in marking intersections
// s/he can set bMarkIntersections to false..in this case
// no intersection test is performed
void MarkObjects(bool bMarkIntersections)
{
if (bMarkIntersections == false)
{
for (int i = 0; i < g_numShapes; i++)
g_shapeList[i]->UnMarkShape();
}
else
{
// reset the states of all shapes as unmarked
for (int i = 0; i < g_numShapes; i++)
g_shapeList[i]->UnMarkShape();
for (int i = 0; i < g_numShapes; i++)
{
for (int j = i+1; j < g_numShapes; j++)
{
if (g_shapeList[i]->intersects(g_shapeList[j]))
{
g_shapeList[i]->MarkShape();
g_shapeList[j]->MarkShape();
}
}
}
}
}
//------------------------------------
void UpdateData()
{
// create viewport bounding rectangles to keep the shapes within the viewport
Point2d Winpos = { -1.0,0.0 };
Point2d Winsize = { 1.0 , g_windowHeight };
Point2d Winveldir = { 0,0 }; // dummy veldir
float Winvel = 0.0f; //not moving
Point3d Wincol = { 0,0,0 }; // dummy color
Rect WindowRectLeft(Winpos, Winsize, Winveldir, Winvel, Wincol);
Winpos.x = 0.0; Winpos.y = -1.0;
Winsize.x = g_windowWidth; Winsize.y = 1.0;
Rect WindowRectBottom(Winpos, Winsize, Winveldir, Winvel, Wincol);
Winpos.x = g_windowWidth; Winpos.y = 0.0;
Winsize.x = 1; Winsize.y = g_windowHeight;
Rect WindowRectRight(Winpos, Winsize, Winveldir, Winvel, Wincol);
Winpos.x = 0.0; Winpos.y = g_windowHeight;
Winsize.x = g_windowWidth; Winsize.y = 1.0f;
Rect WindowRectUp(Winpos, Winsize, Winveldir, Winvel, Wincol);
for (int i = 0; i < g_numShapes; i++)
{
// move the shape
g_shapeList[i]->move();
// if it bounces to the window walls, invert its veldir
if (g_shapeList[i]->intersects(&WindowRectLeft) ||
g_shapeList[i]->intersects(&WindowRectRight))
g_shapeList[i]->invert_xdir();
if (g_shapeList[i]->intersects(&WindowRectBottom) ||
g_shapeList[i]->intersects(&WindowRectUp))
g_shapeList[i]->invert_ydir();
}
}
//------------------------------------
void ChangeSize(GLsizei w, GLsizei h)
{
if(h == 0)
h = 1;
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
g_windowHeight = h;
g_windowWidth = w;
glOrtho(0, g_windowWidth, 0, g_windowHeight , 1.0f, -1.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
//------------------------------------
void processNormalKeys(unsigned char key, int x, int y)
{
if (key == 'q') // PRESS 'q' to terminate the application
exit(0);
if(key=='r') // PRESS 'r' ket to reset the shapes
Initialize();
if (key == 's') // toggle between showing the intersections or not
g_bShowIntersection = g_bShowIntersection ? false: true;
}
//------------------------------------
void processSpecialKeys(int key, int x, int y)
{
switch(key) {
case GLUT_KEY_LEFT :
break;
case GLUT_KEY_RIGHT :
break;
case GLUT_KEY_UP:
// PRESSING UP ARROW KEY INCREASES THE SHAPE VELOCITIES
for (int i = 0; i < g_numShapes; i++)
g_shapeList[i]->increase_vel();
break;
case GLUT_KEY_DOWN:
// PRESSING DOWN ARROW KEY DECREASES THE SHAPE VELOCITIES
for (int i = 0; i < g_numShapes; i++)
g_shapeList[i]->decrease_vel();
break;
}
}
//-------------------------------------
void display() {
glClear(GL_COLOR_BUFFER_BIT); // Clear the color buffer
glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
UpdateData();
MarkObjects(g_bShowIntersection);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
for (int i= 0; i<g_numShapes; i++)
g_shapeList[i]->draw();
glutSwapBuffers();
}
//------------------------------------
int main(int argc, char* argv[])
{
glutInit(&argc, argv); // Initialize GLUT
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB );
glutInitWindowPosition(100,100);
glutInitWindowSize(WINDOWX, WINDOWY);
glutCreateWindow("COM102B - PA4");
// Register callback handler for window re-paint
glutDisplayFunc(display);
glutReshapeFunc(ChangeSize);
glutIdleFunc(display);
glutKeyboardFunc(processNormalKeys);
glutSpecialFunc(processSpecialKeys);
Initialize();
glutMainLoop(); // Enter infinitely event-processing loop
return 0;
}
Your problem is in these lines:
Rect *p1 = dynamic_cast<Rect*>(pshape);
Circ *p2 = dynamic_cast<Circ*>(pshape);
Unless you had inherited Rect from Circ or vice versa this is what makes your program crash, you can't cast your pShape to Circ if it is a Rect, so when you pass a Rect object to your function it will correctly cast to Rect* but it will fail with Circ* returning nullptr, so then when you try to access methods from p2 it will crash becouse you are accessing to invalid memory (0x00000000) :
if(p1)
{
float circleDistance_x = abs(p2->getPos().x - p1->getPos().x);
float circleDistance_y = abs(p2->getPos().y - p1->getPos().y);
if(circleDistance_x > (p1->getSize().x/2 + p2->getRad()))
return false;
if(circleDistance_y > (p1->getSize().y/2 + p2->getRad()))
return false;
if(circleDistance_x <= (p1->getSize().x/2))
return true;
if(circleDistance_y <= (p1->getSize().y/2))
return true;
float cornerDistance_sq = (circleDistance_x - (p1->getSize().x/2)) + (circleDistance_y - (p1->getSize().y/2))*(circleDistance_y - (p1->getSize().y/2));
return (cornerDistance_sq <= p2->getRad()^2);
}
So, you could simply just cast the first p1 pointer since the method is from circle, it's obvious that it was called from a Circ Object so there's no need for p2 pointer.
Rect *p1 = dynamic_cast<Rect*>(pshape);
if(p1)
{
float circleDistance_x = abs(getPos().x - p1->getPos().x);
float circleDistance_y = abs(getPos().y - p1->getPos().y);
if(circleDistance_x > (p1->getSize().x/2 + getRad()))
return false;
if(circleDistance_y > (p1->getSize().y/2 + getRad()))
return false;
if(circleDistance_x <= (p1->getSize().x/2))
return true;
if(circleDistance_y <= (p1->getSize().y/2))
return true;
float cornerDistance_sq = (circleDistance_x - (p1->getSize().x/2)) + (circleDistance_y - (p1->getSize().y/2))*(circleDistance_y - (p1->getSize().y/2));
return (cornerDistance_sq <= getRad()^2);
}
Also on the line:
return (cornerDistance_sq <= getRad()^2)
i think you are trying to get the radius square but this wont do it, what it is actually doing is
(cornerDistance_sq <= getRad()) ^ 2
becouse <= has greater precedence to ^, plus ^ is not a square operator it is a bitwise operator. So what you actually want is :
return cornerDistance_sq <= getRad() * getRad();
I am trying to draw a Bezier curve in OpenGL using floating point values. I have tried using many different code examples. My current code below, runs ,but does not show the curve on screen. The usual way to draw Bezier curves are with integer values, which means using the GLUORTHO2D() function for drawing the curve. But I want to draw a curve using floating point values. Such as x range(-1,1) and y range(-1,1).
like if x=(500) then consider it (-1 to 1) and if y=(800) then consider it (-1,1).
I have already tried using integer values and it worked for me. my code using integer values is below:
#include <GL/glut.h>
#include <math.h>
#include <stdio.h>
#define CTRL_COUNT 100
int ctrlPointsCount;
int ctrlPointsX[CTRL_COUNT], ctrlPointsY[CTRL_COUNT];
int X1[3]={20,25,20}, Y1[3]={5,24,38}; //first point(x1[0],y1[0]) second(x1[1],y1[1]) third(x1[2],y1[2])
void myInit()
{
glClearColor(0.0,0.0,0.0,0.0);
glColor3f(1.0,0.0,0.0);
glPointSize(8.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0,128.0,0.0,96.0);
}
//p(t)=(1-t)^3*p0+3t(1-t)^2*p1+3t^2(1-t)p2+t^3p3
float getNextBezierPointX(float t)
{
float x=0.0;
for(int i=0; i<ctrlPointsCount; i++)
{
int c;
if(i==0 || i==ctrlPointsCount-1)
c = 1;
else
{
c = ctrlPointsCount-1;
}
x += c * pow(t, i) * pow(1-t, ctrlPointsCount-1-i) * ctrlPointsX[i];
}
return x;
}
float getNextBezierPointY(float t)
{
float y=0.0;
for(int i=0; i<ctrlPointsCount; i++)
{
int c;
if(i==0 || i==ctrlPointsCount-1)
c = 1;
else
{
c = ctrlPointsCount-1;
}
y += c * pow(t, i) * pow(1-t, ctrlPointsCount-1-i) * ctrlPointsY[i];
}
return y;
}
void drawline()
{
// draw control points using red color
for(int i=0; i < 3; i++)
{
glBegin(GL_POINTS);
glVertex2i(ctrlPointsX[i], ctrlPointsY[i]);
glEnd();
glFlush();
}
// draw bezier curve using control poitns by calculating next points using cubic bezier curve formula
float oldX=ctrlPointsX[0], oldY=ctrlPointsY[0];
for(double t = 0.0;t <= 1.0; t += 0.01) {
float x = getNextBezierPointX(t);
float y = getNextBezierPointY(t);
//glColor3f(1.0,t,1.0);
glColor3f(1.0,1.0,1.0);
glBegin(GL_LINES);
glVertex2f(oldX, oldY);
glVertex2f(x, y);
glEnd();
glFlush();
oldX = x;
oldY = y;
}
}
void myDisplay()
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0,0.0,0.0);
ctrlPointsCount=3;
for(int i=0;i<3;i++)
{
ctrlPointsX[i] = X1[i];
ctrlPointsY[i] = Y1[i];
}
drawline();
glFlush();
}
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutInitWindowSize(640,480);
glutInitWindowPosition(100,150);
glutCreateWindow("Bezier Curve");
glutDisplayFunc(myDisplay);
myInit();
glutMainLoop();
return 0;
}
But when i tried using floating point values , it does not work for me. It does not show the curved line on screen. My code using floating point values is below:
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <GL/glut.h>
using namespace std;
#define CTRL_COUNT 100
int ctrlPointsCount;
int ctrlPointsX[CTRL_COUNT], ctrlPointsY[CTRL_COUNT];
double X1[3] = { 0.26015037593985, 0.43609022556391, 0.6 }, Y1[3] = { 0.946875, 0.884375, 0.946875 };
//Initializes 3D rendering
void initRendering() {
glEnable(GL_DEPTH_TEST);
}
float getNextBezierPointX(float t)
{
float x = 0.0;
for (int i = 0; i<ctrlPointsCount; i++)
{
int c;
if (i == 0 || i == ctrlPointsCount - 1)
c = 1;
else
{
c = ctrlPointsCount - 1;
}
x += c * pow(t, i) * pow(1 - t, ctrlPointsCount - 1 - i) * ctrlPointsX[i];
}
return x;
}
float getNextBezierPointY(float t)
{
float y = 0.0;
for (int i = 0; i<ctrlPointsCount; i++)
{
int c;
if (i == 0 || i == ctrlPointsCount - 1)
c = 1;
else
{
c = ctrlPointsCount - 1;
}
y += c * pow(t, i) * pow(1 - t, ctrlPointsCount - 1 - i) * ctrlPointsY[i];
}
return y;
}
void drawline()
{
// draw control points using red color
for (int i = 0; i < 3; i++)
{
glBegin(GL_POINTS);
glVertex2i(ctrlPointsX[i], ctrlPointsY[i]);
glEnd();
glFlush();
}
// draw bezier curve using control poitns by calculating next points using cubic bezier curve formula
float oldX = ctrlPointsX[0], oldY = ctrlPointsY[0];
for (double t = 0.0; t <= 1.0; t += 0.01)
{
float x = getNextBezierPointX(t);
float y = getNextBezierPointY(t);
//glColor3f(1.0,t,1.0);
glColor3f(1.0, 1.0, 1.0);
glBegin(GL_LINES);
glVertex2f(oldX, oldY);
glVertex2f(x, y);
glEnd();
glFlush();
oldX = x;
oldY = y;
}
}
//Called when the window is resized
void handleResize(int w, int h) {
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0, (double)w / (double)h, 1.0, 200.0);
}
float _angle = 0.0;
float _cameraAngle = 0.0;
float _ang_tri = 0.0;
//Draws the 3D scene
void drawScene() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity(); //Reset the drawing perspective
ctrlPointsCount = 3;
for (int i = 0; i<3; i++)
{
ctrlPointsX[i] = X1[i];
ctrlPointsY[i] = Y1[i];
}
drawline();
glutSwapBuffers();
}
void update(int value) {
_angle += 2.0f;
if (_angle > 360) {
_angle -= 360;
}
_ang_tri += 2.0f;
if (_ang_tri > 360) {
_ang_tri -= 360;
}
glutPostRedisplay(); //Tell GLUT that the display has changed
//Tell GLUT to call update again in 25 milliseconds
glutTimerFunc(25, update, 0);
}
int main(int argc, char** argv) {
//Initialize GLUT
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(1331, 641);
glutInitWindowPosition(0, 0);
//Create the window
glutCreateWindow("Our cg project");
initRendering();
//Set handler functions
glutDisplayFunc(drawScene);
glutReshapeFunc(handleResize);
glutTimerFunc(25, update, 0); //Add a timer
glClearColor(0.0, 0.7, 1.5,0.0);
glutMainLoop();
return 0;
}
The problem is this here:
int ctrlPointsX[CTRL_COUNT], ctrlPointsY[CTRL_COUNT];
double X1[3] = { 0.26015037593985, 0.43609022556391, 0.6 }, Y1[3] = {0.946875, 0.884375, 0.946875 };
for (int i = 0; i<3; i++)
{
ctrlPointsX[i] = X1[i];
ctrlPointsY[i] = Y1[i];
}
ctrlPointsX and ctrlPointsYcan only hold integer values. So when you do ctrlPointsX[i] = X1[i] and ctrlPointsY[i] = Y1[i] you are converting the floats to integers, which will round them down. So all your controlPoints will be 0.
You have to declare the controlPoints arrays as type double too:
double ctrlPointsX[CTRL_COUNT], ctrlPointsY[CTRL_COUNT];
double X1[3] = { 0.26015037593985, 0.43609022556391, 0.6 }, Y1[3] = {0.946875, 0.884375, 0.946875 };
This should fix your problem.