src/Curve.cpp: In static member function \u2018static CurvePoints Curve::evalBspline(const std::vector<Vector3f>&, unsigned int)\u2019:
src/Curve.cpp:219:30: error: qualified-id in declaration before \u2018(\u2019 token
  219 | CurvePoints Curve::evalCircle(float radius, unsigned steps) {
      |                              ^
src/Curve.cpp:267:17: error: qualified-id in declaration before \u2018(\u2019 token
  267 | void Curve::draw() {
      |                 ^
src/Curve.cpp:270:2: error: expected \u2018}\u2019 at end of input
  270 | }
      |  ^#include "Curve.h"
#include "Extra.h"
#include <GL/glut.h>
#include <iostream>

#ifndef PI
#define PI 3.14159265358979323846
#endif

Curve::Curve(const std::string& name, unsigned steps, const std::string& curveType)
    : name(name), steps(steps), curveType(curveType) {}


// Get curve name
const std::string& Curve::getName() const {
    return name;
}

// Set control points

void Curve::setControlPoints(const std::vector<Vector3f>& cps) {
    controlPoints = cps;
}

// Get control points

const std::vector<Vector3f>& Curve::getControlPoints() const {
    return controlPoints;
}

// Getter for curvePoints
const CurvePoints& Curve::getCurvePoints() const {
    return curvePoints;
}

// Setter for curvePoints
void Curve::setCurvePoints(const CurvePoints& points) {
    curvePoints = points;
}


// Set steps

void Curve::setSteps(unsigned steps) {
    this->steps = steps;
}

// Get steps

unsigned Curve::getSteps() const {
    return steps;
}

// Set curve type

void Curve::setCurveType(const std::string& type) {
    curveType = type;
}

// Get curve type

const std::string& Curve::getCurveType() const {
    return curveType;
}



CurvePoints Curve::evalBezier(const std::vector< Vector3f >& P, unsigned steps){


    // Check

    if( P.size() < 4 || P.size() % 3 != 1 )
    {
        std::cerr << "evalBezier must be called with 3n+1 control points." << std::endl;
        exit( 0 );
    }

	// 2.3.1 - Create the functionality to process Bezier control points


    // You should implement this function so that it returns a Curve
    // (e.g., a vector< CurvePoint >).  The variable "steps" tells you
    // the number of points to generate on each piece of the spline.
    // At least, that's how the sample solution is implemented and how
    // the SWP files are written.  But you are free to interpret this
    // variable however you want, so long as you can control the
    // "resolution" of the discretized spline curve with it.

    // Make sure that this function computes all the appropriate
    // Vector3fs for each CurvePoint: V,T,N,B.
    // [NBT] should be unit and orthogonal.

    // Also note that you may assume that all Bezier curves that you
    // receive have G1 continuity.  Otherwise, the TNB will not be
    // be defined at points where this does not hold.

    std::cerr << "\t>>> evalBezier has been called with the following input:" << std::endl;

    std::cerr << "\t>>> Control points (type vector< Vector3f >): "<< std::endl;
    for( unsigned i = 0; i < P.size(); ++i )
    {
        std::cerr << "\t>>> " << P[i] << std::endl;
    }

    std::cerr << "\t>>> Steps (type steps): " << steps << std::endl;
    std::cerr << "\t>>> Returning empty curve." << std::endl;

    // Right now this will just return this empty curve.
    CurvePoints res;
    Matrix4f M_B ( 1, -3,  3, -1,
                   0,  3, -6,  3,
                   0,  0,  3, -3,
                   0,  0,  0,  1);
                   
    Vector3f B0 = Vector3f(0, 0, 1);
                   
    for (unsigned i = 0; i < P.size() - 3; i += 3) {
        Matrix4f G(
            P[i][0], P[i + 1][0], P[i + 2][0], P[i + 3][0],
            P[i][1], P[i + 1][1], P[i + 2][1], P[i + 3][1],
            P[i][2], P[i + 1][2], P[i + 2][2], P[i + 3][2],
            1      , 1          , 1          , 1
        );
        
        Vector3f B_prev = B0;
        for (unsigned j = 0; j <= steps; j++) {
            float t = float(j)/ steps; // t in [0, 1]
            Vector4f M(1, t, t*t, t*t*t); // Monomial basis
            // position
            Vector3f V = (G * M_B * M).xyz();
            
            // tangent
            Vector4f dM(0, 1, 2*t, 3*t*t);
            Vector3f T = (G * M_B * dM).xyz();
            T.normalize();
            
            // Normal
            Vector3f N = Vector3f::cross(B_prev, T);
            N.normalize();
            
            // Update binormal
            Vector3f B = Vector3f::cross(T, N);
            B.normalize();
            res.push_back(CurvePoint{V, T, N, B});
            
            B_prev = B;
        }
    }
      
    return res;

}

CurvePoints Curve::evalBspline(const std::vector< Vector3f >& P, unsigned steps){

    // Check
    if( P.size() < 4 )
    {
        std::cerr << "evalBspline must be called with 4 or more control points." << std::endl;
        exit( 0 );
    }

	// 2.3.2 - Create the functionality to process BSpline control points

    // It is suggested that you implement this function by changing
    // basis from B-spline to Bezier.  That way, you can just call
    // your evalBezier function.

    std::cerr << "\t>>> evalBSpline has been called with the following input:" << std::endl;

    std::cerr << "\t>>> Control points (type vector< Vector3f >): "<< std::endl;
    for( unsigned i = 0; i < P.size(); ++i )
    {
        std::cerr << "\t>>> " << P[i] << std::endl;
    }

    std::cerr << "\t>>> Steps (type steps): " << steps << std::endl;
    std::cerr << "\t>>> Returning empty curve." << std::endl;

    // Return an empty curve right now.
    Matrix4f M_B1 (1, -3,  3, -1,
                   0,  3, -6,  3,
                   0,  0,  3, -3,
                   0,  0,  0,  1);
    Matrix4f M_B2 (1, -3,  3, -1,
                   4,  0, -6,  3,
                   1,  3,  3, -3,
                   0,  0,  0,  1);
    M_B2 /= 6.0f;
    Matrix4f M_B1_inv = M_B1.inverse();
    
    // Transform control points and pass to Bezier
    Matrix4f M_B = M_B2 * M_B1_inv;
    std::vector<Vector3f> bezierControlPoints;
    
    for (unsigned i = 0; i < P.size() - 3; i++) {
        Matrix4f G(
            P[i][0], P[i + 1][0], P[i + 2][0], P[i + 3][0],
            P[i][1], P[i + 1][1], P[i + 2][1], P[i + 3][1],
            P[i][2], P[i + 1][2], P[i + 2][2], P[i + 3][2],
            1      , 1          , 1          , 1
        );
        
        Matrix4f BezierG = G * M_B;
        for (unsigned j = 0; j < 4; j++) {
            bezierControlPoints.push_back(Vector3f(BezierG(0, j), 
                                                   BezierG(1, j),
                                                   BezierG(2, j))
                                         );
    }
    
    return evalBezier(bezierControlPoints, steps);

}


// Function to evaluate circle points based on radius and steps
CurvePoints Curve::evalCircle(float radius, unsigned steps) {
	


	// 2.3.3 - Create the functionality to process Circles based on radius and steps

    // Based on how you evaluated Bezier and B-spline curves, you will calculate and return a curve
	// that will create a circle. The curve will contain the same CurvePoint structure: V,T,N,B.


    std::cerr << "\t>>> evalCircle has been called with the following input:" << std::endl;

    std::cerr << "\t>>> Radius: "<< radius << std::endl;
    std::cerr << "\t>>> Steps (type steps): " << steps << std::endl;
    std::cerr << "\t>>> Returning empty curve." << std::endl;


    CurvePoints res;
    // Control points for one quarter-circle
    const float c = 4.0f / 3.0f * (sqrt(2.0f) - 1.0f);
    std::vector<Vector3f> cirleControlPoints = {
        Vector3f(1.0f, 0.0f, 0.0f),
        Vector3f(1.0f, c, 0.0f),
        Vector3f(c, 1.0f, 0.0f),
        Vector3f(0.0f, 1.0f, 0.0f)
    };
    
    //scale by radius
    for (auto& pt: cirleControlPoints) pt *= radius;
    
    for (int seg = 0; seg < 4; seg++) {
        Matrix3f rotation = Matrix3f::rotateZ(seg * PI / 2.0f);
        std::vector<Vector3f> controlPoints(4);
        for (int i = 0; i < 4; i++) {
            controlPoints[i] = rotation * circleControlPoints[i];
        }
        
        // eval each quarter using bezier
        CurvePoints segment = evalBezier(controlPoints, step / 4);
        res.insert(res.end(), segment.begin(), segment.end());
        
    }
    
    return res;

}


void Curve::draw() {


}