Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Changing the name variable in a loop for  (Read 2004 times)

0 Members and 2 Guests are viewing this topic.

etudiantengalere

  • Newbie
  • *
  • Posts: 5
    • View Profile
Changing the name variable in a loop for
« on: February 11, 2023, 11:26:13 pm »
Hello, I'm tryng to draw multiple graph with SFML on a single window and for that I need to change the name of a vertexarray variable inside my loop for, unfortunately I don't know how to do it, anyone can help me ?
Thanks ! ;D

#include <SFML/Graphics.hpp>
#include <iostream>
#include <sstream>
#include <cmath>
#include<fstream>

using namespace std;

double dt=1;//sec
double dx=0.1;//m
int tmax = 30 ;
int xmax = 40 ;


int main()
{
    fstream fich; //file with stuff to plot
    fich.open("results.txt", ios::in);
    const unsigned int s = 800;
    const unsigned int N = 1500;

    sf::RenderWindow window(sf::VideoMode(N, s),"Graph", sf::Style::Default);
    window.setVerticalSyncEnabled(true);
    window.setFramerateLimit(60);

       
        sf::VertexArray chart1(sf::LinesStrip, N);
        for (unsigned int i=0; i<400; i++){
            double x1, U1, x2, U2, Utot, t;
            fich>>x1>> U1>> x2>> U2>> Utot>> t;
            double abscisse = x1*N/xmax;
            double ordonne = s-Utot*s/2;
            chart1.append(sf::Vertex(sf::Vector2f(abscisse, ordonne), sf::Color::Black));
        }
        sf::VertexArray chart2(sf::LinesStrip, N);
        for (unsigned int i=0; i<400; i++){
            double x1, U1, x2, U2, Utot, t;
            fich>>x1>> U1>> x2>> U2>> Utot>> t;
            double abscisse = x1*N/xmax;
            double ordonne = s-Utot*s/2;
            chart2.append(sf::Vertex(sf::Vector2f(abscisse, ordonne), sf::Color::Black));
        }
        sf::VertexArray chart3(sf::LinesStrip, N);
        for (unsigned int i=0; i<400; i++){
            double x1, U1, x2, U2, Utot, t;
            fich>>x1>> U1>> x2>> U2>> Utot>> t;
            double abscisse = x1*N/xmax;
            double ordonne = s-Utot*s/2;
            chart3.append(sf::Vertex(sf::Vector2f(abscisse, ordonne), sf::Color::Black));
        }
        sf::VertexArray chart4(sf::LinesStrip, N);
        for (unsigned int i=0; i<400; i++){
            double x1, U1, x2, U2, Utot, t;
            fich>>x1>> U1>> x2>> U2>> Utot>> t;
            double abscisse = x1*N/xmax;
            double ordonne = s-Utot*s/2;
            chart4.append(sf::Vertex(sf::Vector2f(abscisse, ordonne), sf::Color::Black));
        }
        sf::VertexArray chart5(sf::LinesStrip, N);
        for (unsigned int i=0; i<400; i++){
            double x1, U1, x2, U2, Utot, t;
            fich>>x1>> U1>> x2>> U2>> Utot>> t;
            double abscisse = x1*N/xmax;
            double ordonne = s-Utot*s/2;
            chart5.append(sf::Vertex(sf::Vector2f(abscisse, ordonne), sf::Color::Black));
        }
        sf::VertexArray chart6(sf::LinesStrip, N);
        for (unsigned int i=0; i<400; i++){
            double x1, U1, x2, U2, Utot, t;
            fich>>x1>> U1>> x2>> U2>> Utot>> t;
            double abscisse = x1*N/xmax;
            double ordonne = s-Utot*s/2;
            chart6.append(sf::Vertex(sf::Vector2f(abscisse, ordonne), sf::Color::Black));
        }
        sf::VertexArray chart7(sf::LinesStrip, N);
        for (unsigned int i=0; i<400; i++){
            double x1, U1, x2, U2, Utot, t;
            fich>>x1>> U1>> x2>> U2>> Utot>> t;
            double abscisse = x1*N/xmax;
            double ordonne = s-Utot*s/2;
            chart7.append(sf::Vertex(sf::Vector2f(abscisse, ordonne), sf::Color::Black));
        }
        sf::VertexArray chart8(sf::LinesStrip, N);
        for (unsigned int i=0; i<400; i++){
            double x1, U1, x2, U2, Utot, t;
            fich>>x1>> U1>> x2>> U2>> Utot>> t;
            double abscisse = x1*N/xmax;
            double ordonne = s-Utot*s/2;
            chart8.append(sf::Vertex(sf::Vector2f(abscisse, ordonne), sf::Color::Black));
        }
        sf::VertexArray chart9(sf::LinesStrip, N);
        for (unsigned int i=0; i<400; i++){
            double x1, U1, x2, U2, Utot, t;
            fich>>x1>> U1>> x2>> U2>> Utot>> t;
            double abscisse = x1*N/xmax;
            double ordonne = s-Utot*s/2;
            chart9.append(sf::Vertex(sf::Vector2f(abscisse, ordonne), sf::Color::Black));
        }
        sf::VertexArray chart10(sf::LinesStrip, N);
        for (unsigned int i=0; i<400; i++){
            double x1, U1, x2, U2, Utot, t;
            fich>>x1>> U1>> x2>> U2>> Utot>> t;
            double abscisse = x1*N/xmax;
            double ordonne = s-Utot*s/2;
            chart10.append(sf::Vertex(sf::Vector2f(abscisse, ordonne), sf::Color::Black));
        }
        sf::VertexArray chart11(sf::LinesStrip, N);
        for (unsigned int i=0; i<400; i++){
            double x1, U1, x2, U2, Utot, t;
            fich>>x1>> U1>> x2>> U2>> Utot>> t;
            double abscisse = x1*N/xmax;
            double ordonne = s-Utot*s/2;
            chart11.append(sf::Vertex(sf::Vector2f(abscisse, ordonne), sf::Color::Black));
        }
        sf::VertexArray chart12(sf::LinesStrip, N);
        for (unsigned int i=0; i<400; i++){
            double x1, U1, x2, U2, Utot, t;
            fich>>x1>> U1>> x2>> U2>> Utot>> t;
            double abscisse = x1*N/xmax;
            double ordonne = s-Utot*s/2;
            chart12.append(sf::Vertex(sf::Vector2f(abscisse, ordonne), sf::Color::Black));
        }
        sf::VertexArray chart13(sf::LinesStrip, N);
        for (unsigned int i=0; i<400; i++){
            double x1, U1, x2, U2, Utot, t;
            fich>>x1>> U1>> x2>> U2>> Utot>> t;
            double abscisse = x1*N/xmax;
            double ordonne = s-Utot*s/2;
            chart13.append(sf::Vertex(sf::Vector2f(abscisse, ordonne), sf::Color::Black));
        }
        sf::VertexArray chart14(sf::LinesStrip, N);
        for (unsigned int i=0; i<400; i++){
            double x1, U1, x2, U2, Utot, t;
            fich>>x1>> U1>> x2>> U2>> Utot>> t;
            double abscisse = x1*N/xmax;
            double ordonne = s-Utot*s/2;
            chart14.append(sf::Vertex(sf::Vector2f(abscisse, ordonne), sf::Color::Black));
        }
        sf::VertexArray chart15(sf::LinesStrip, N);
        for (unsigned int i=0; i<400; i++){
            double x1, U1, x2, U2, Utot, t;
            fich>>x1>> U1>> x2>> U2>> Utot>> t;
            double abscisse = x1*N/xmax;
            double ordonne = s-Utot*s/2;
            chart15.append(sf::Vertex(sf::Vector2f(abscisse, ordonne), sf::Color::Black));
        }


   
    fich.close();
    while (window.isOpen()){
        sf::Event event;
        while (window.pollEvent(event))
            if (event.type == sf::Event::Closed) window.close();

        window.clear(sf::Color::White);
        window.draw(chart1);
        window.draw(chart2);
        window.draw(chart3);
        window.draw(chart4);
        window.draw(chart5);
        window.draw(chart6);
        window.draw(chart7);
        window.draw(chart8);
        window.draw(chart9);
        window.draw(chart10);
        window.draw(chart11);
        window.draw(chart12);
        window.draw(chart13);
        window.draw(chart14);
        window.draw(chart15);

        window.display();
    }
    return 0;
}
« Last Edit: February 12, 2023, 08:53:27 pm by eXpl0it3r »

etudiantengalere

  • Newbie
  • *
  • Posts: 5
    • View Profile
Re: Changing the name variable in a loop for
« Reply #1 on: February 11, 2023, 11:28:33 pm »
I would like to know if there's a way to avoid the 15 repetitions of sf::vertexarray

Thez3rt3r

  • Newbie
  • *
  • Posts: 3
    • View Profile
Re: Changing the name variable in a loop for
« Reply #2 on: February 11, 2023, 11:47:30 pm »
I'd suggest to use std::vector<sf::VertexArray> or std::Array<sf::VertexArray, [count of vertex arrays]>.
You can then use another for loop to fill all the arrays as well as to draw them.
Quote
#include <vector>

(...)

//this will create a vector with 15 VertexArrays as they're default constructible
std::vector<sf::VertexArray> charts(15)

//here we fill charts with data from the file
//we're using range based loop
for (auto ch : charts){
//basically this is your original code
  for (unsigned int i=0; i<400; i++){
            double x1, U1, x2, U2, Utot, t;
            fich>>x1>> U1>> x2>> U2>> Utot>> t;
            double abscisse = x1*N/xmax;
            double ordonne = s-Utot*s/2;
            ch.append(sf::Vertex(sf::Vector2f(abscisse, ordonne), sf::Color::Black));
        }
}

(...)

//drawing is also simple
for (auto ch : charts){
window.draw(ch);
}

I skipped some obvious parts.
If your compiler, for any reason, doesn't know range based loops, you will need to type
Quote
for (auto ch = 0; ch < charts.size(); ++ch){
(...)
charts[ch].append(...);
}
And again I skipped obvious things.

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: Changing the name variable in a loop for
« Reply #3 on: February 11, 2023, 11:51:21 pm »
First thing you could consider is just
chart2 = chart1;
chart3 = chart1;
// etc. ...
 

An overall clean-looking way would be to create them all in a vector and the just iterate through the vector and do the same code in that loop. It does look like the code is identical each time so I'll use identical code.
For example, something like:
    std::vector<sf::VertexArray> charts(15u, sf::VertexArray(sf::LinesStrip, N));
    for (auto& chart : charts)
    {
        for (unsigned int i=0; i<400; i++){
            double x1, U1, x2, U2, Utot, t;
            fich>>x1>> U1>> x2>> U2>> Utot>> t;
            double abscisse = x1*N/xmax;
            double ordonne = s-Utot*s/2;
            chart[i] = sf::Vertex(sf::Vector2f(abscisse, ordonne), sf::Color::Black);
        }
    }

    // ...

    for (auto& chart : charts)
        window.draw(chart);
 

If you still want the vertex arrays to be separate and not with a container, you could create a vector of pointers to them and iterate through those instead.
Something like:
sf::VertexArray chart1(sf::LinesStrip, N);
// ...
sf::VertexArray chart15(sf::LinesStrip, N);

std::vector<sf::VertexArray*> pCharts(15u);
pCharts[0u] = &chart1;
// ...
pCharts[14u] = &chart15;

// ...

for (sf::VertexArray* pChart : pCharts)
    window.draw(*pChart);

 


EDIT: looks like Thez3rt3r just beat me to it!! : )
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

etudiantengalere

  • Newbie
  • *
  • Posts: 5
    • View Profile
Re: Changing the name variable in a loop for
« Reply #4 on: February 12, 2023, 12:10:36 am »
Thanks both of you for your fast responses ! It work but unfortunately there is a little probleme at the end of the plot, as you can see. Do you have any idea how to fix it ?

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: Changing the name variable in a loop for
« Reply #5 on: February 12, 2023, 12:18:19 am »
Well, you're only setting the first 400 vertices but there are 1500 (N) vertices in each vertex array. The ones not set default to position of (0, 0) and a colour of white.
Either change N to 400, or tell the draw method to only draw the first 400 vertices.
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

etudiantengalere

  • Newbie
  • *
  • Posts: 5
    • View Profile
Re: Changing the name variable in a loop for
« Reply #6 on: February 12, 2023, 12:00:37 pm »
Thank you very much it works ! <3 And since you seem to know a lot about sfml would you happen to know how to save the window in a jpg file ?

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: Changing the name variable in a loop for
« Reply #7 on: February 12, 2023, 05:36:01 pm »
You're welcome. Glad you got it going :)



https://www.sfml-dev.org/documentation/2.5.1/classsf_1_1Texture.php#ad3cceef238f7d5d2108a98dd38c17fc5
  • create an sf::Texture,
  • capture the window using the above method (texture.update(window)) to copy the window's contents to the texture,
  • create an sf::Image,
  • copy the texture to the image using the texture's copyToImage method (image = texture.copyToImage()),
  • use the image to save to file (image.saveToFile("")).
You can shortcut the last three steps (3-5) as just texture.copyToImage().saveToFile("");
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

etudiantengalere

  • Newbie
  • *
  • Posts: 5
    • View Profile
Re: Changing the name variable in a loop for
« Reply #8 on: February 13, 2023, 10:24:48 am »
Thank you but unfortunately this doesn't work, I have an error "Failed to save image " " " and I don't know how to fix it.. I saw on internet that this can come from a special letter in the file acces but this is not my case

Here is my code :

...

while (window.isOpen()){
        sf::Event event;
        while (window.pollEvent(event))
            if (event.type == sf::Event::Closed) window.close();

       
        int i=0;
        for (auto& chart : charts){
            window.clear(sf::Color::White);
            sf::Texture text;
            window.draw(chart);
            text.update(window);
            sf::Image Screen;
            Screen = text.copyToImage();
            Screen.saveToFile("screen_" + to_string(i) + ".jpg");
            i++;
        }
        window.display();
    }
...

G.

  • Hero Member
  • *****
  • Posts: 1593
    • View Profile
Re: Changing the name variable in a loop for
« Reply #9 on: February 13, 2023, 11:20:59 am »
From the link above
passing a window bigger than the texture will lead to an undefined behavior
This function does nothing if either the texture or the window was not previously created
Use create to create a texture of the correct size.

 

anything