2

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;
}
Nicholas Johnson
  • 1,012
  • 2
  • 12
  • 35
  • 1
    It looks like you're already reading the values off the chart. It looks easy enough to adapt this to a rotation aroung Y, except you will produce the 3D model from the "inside out" (like a tree grows) instead of extruding a shape along the X axis. – Botje Apr 08 '20 at 12:14
  • @Botje That's exactly how I thought of it, at the start. However, I take these "height" values and that acts as my "radius." In the case of a different axis's rotation, the height value would produce a severely incorrect model. Since each "y-value" can have multiple x-values. If this doesn't make sense, I would be happy to elaborate. – Nicholas Johnson Apr 08 '20 at 12:28
  • For every X value there is one Y value, so use the X axis as your radius and use (x,0) and (x,y) as basis to compute the vertices for each layer. Connect all vertices of the same layer together and cap off the top and bottom (by connecting to the previous layer). In the end you will have the desired result. – Botje Apr 08 '20 at 12:39
  • @Botje I'm sorry to ask this, but could you elaborate? – Nicholas Johnson Apr 08 '20 at 13:04
  • Did I understand correctly that it is possible to obtain a curve from the equation, and then rotate this curve without thinking about the equation? – Vladimir Bershov Apr 08 '20 at 14:47

1 Answers1

1

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.

Botje
  • 26,269
  • 3
  • 31
  • 41