Search code examples
c++qtalgebracalculusqcustomplot

Is there a method to either recalculate and equation in terms of a different variable?


I am currently a senior in AP Calculus BC and have taken the challenge of replicating a topic in C++ Qt. This topic covers integrals as area beneath a curve, and rotations of said areas to form a solid model with a definite volume.

enter image description here

I have successfully rotated a custom equation defined as:

double y = abs(qSin(qPow(graphXValue,graphXValue))/qPow(2, (qPow(graphXValue,graphXValue)-M_PI/2)/M_PI))

OR

equation

My question is how to rotate such an equation around the Y-Axis instead of the X-Axis. Are there any methods to approximate the solving of this equation in terms of y instead of x? Are there any current implementations of such a task?

Keep in mind, I am calculating each point for the transformation in a 3D coordinate system:

for (float x = 0.0f; x < t_functionMaxX - t_projectionStep; x+=t_projectionStep)
{
    currentSet = new QSurfaceDataRow;
    nextSet = new QSurfaceDataRow;

    float x_pos_mapped = x;
    float y_pos_mapped = static_cast<float>(ui->customPlot->graph(0)->data()->findBegin(static_cast<double>(x), true)->value);

    float x_pos_mapped_ahead = x + t_projectionStep;
    float y_pos_mapped_ahead = static_cast<float>(graph1->data()->findBegin(static_cast<double>(x + t_projectionStep), true)->value);

    QList<QVector3D> temp_points;
    for (float currentRotation = static_cast<float>(-2*M_PI); currentRotation < static_cast<float>(2*M_PI); currentRotation += static_cast<float>((1) * M_PI / 180))
    {
        float y_pos_calculated = static_cast<float>(qCos(static_cast<qreal>(currentRotation))) * y_pos_mapped;
        float z_pos_calculated = static_cast<float>(qSin(static_cast<qreal>(currentRotation))) * y_pos_mapped;

        float y_pos_calculated_ahead = static_cast<float>(qCos(static_cast<qreal>(currentRotation))) * y_pos_mapped_ahead;
        float z_pos_calculated_ahead = static_cast<float>(qSin(static_cast<qreal>(currentRotation))) * y_pos_mapped_ahead;

        QVector3D point(x_pos_mapped, y_pos_calculated, z_pos_calculated);
        QVector3D point_ahead(x_pos_mapped_ahead, y_pos_calculated_ahead, z_pos_calculated_ahead);

        *currentSet << point;
        *nextSet << point_ahead;

        temp_points << point;
    }
    *data << currentSet << nextSet;


    points << temp_points;
}

Solution

  • Essentially, you rotate the vector (x,f(x),0) around the Y axis, so the Y value remains the same but the X and Y parts vary according to rotation.

    I also replaced all the static_cast<float> parts by explicit invocations of the float constructor, which (I find) reads a bit better.

    // Render the upper part, grow from the inside
    for (float x = 0.0f; x < t_functionMaxX - t_projectionStep; x+=t_projectionStep)
    {
        currentSet = new QSurfaceDataRow;
        nextSet = new QSurfaceDataRow;
    
        float x_pos_mapped = x;
        float y_pos_mapped = float(ui->customPlot->graph(0)->data()->findBegin(double(x), true)->value);
    
        float x_pos_mapped_ahead = x + t_projectionStep;
        float y_pos_mapped_ahead = float(graph1->data()->findBegin(double(x + t_projectionStep), true)->value);
    
        QList<QVector3D> temp_points;
        for (float currentRotation = float(-2*M_PI); currentRotation < float(2*M_PI); currentRotation += float((1) * M_PI / 180))
        {
            float x_pos_calculated = float(qCos(qreal(currentRotation))) * x_pos_mapped;
            float z_pos_calculated = float(qSin(qreal(currentRotation))) * x_pos_mapped;
    
            float x_pos_calculated_ahead = float(qCos(qreal(currentRotation))) * x_pos_mapped_ahead;
            float z_pos_calculated_ahead = float(qSin(qreal(currentRotation))) * x_pos_mapped_ahead;
    
            QVector3D point(x_pos_calculated, y_pos_mapped, z_pos_calculated);
            QVector3D point_ahead(x_pos_calculated_ahead, y_pos_mapped_ahead, z_pos_calculated_ahead);
    
            *currentSet << point;
            *nextSet << point_ahead;
    
            temp_points << point;
        }
        *data << currentSet << nextSet;
    
    
        points << temp_points;
    }
    

    Next, you need to add the bottom "plate". This is simply a bunch of triangles that connect (0,0,0) with two adjacent points of the rotation of (1,0,0) around the Y axis, just like we did above.

    Finally, if f(t_functionmaxX) is not zero, you need to add a side that connects (t_functionmaxX, f(t_functionmaxX), 0) to (t_functionmaxX, 0, 0), again rotating in steps around the Y axis.

    Note that this will do weird things if y < 0. How you want to solve that is up to you.