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

Author Topic: Crash visualization of Diffusion-limited aggregation  (Read 3022 times)

0 Members and 1 Guest are viewing this topic.

Sevas

  • Newbie
  • *
  • Posts: 2
    • View Profile
Crash visualization of Diffusion-limited aggregation
« on: January 22, 2017, 05:45:45 pm »
I have made visualization of DLA process
I used two vectors, for moving particles and second for stucked.
My programm basically works, but sometimes I have error - exception for sfml-graphics-2.dll
I can`t find where I made mistakes.

Here is my source

#include <SFML/Graphics.hpp>
#include <stdio.h>
#include <stdlib.h>             /* srand, rand */
#include <time.h>       /* time */
#include <vector>

int main()
{       // create the window
        int W = 800;
        int H = 600;
        int r = 5;
        std::size_t count = 1000;
        sf::RenderWindow window(sf::VideoMode(W, H), "Particles");
        window.setFramerateLimit(30);
        window.setVerticalSyncEnabled(true);

        std::vector<sf::CircleShape> circle_free;
        std::vector<sf::CircleShape> circle_stucked;

        //create moving particles
        for (std::size_t i = 0; i < count; i++)
        {
                sf::CircleShape circle;
                int x = std::rand() % W;
                int y = std::rand() % H;
                //printf("%i %i\n", x , y);
                circle.setPointCount(8);
                circle.setRadius(r);
                circle.setPosition(x, y);
                sf::Color color = sf::Color(255, 0, 0, 100);
                circle.setFillColor(color);

                circle_free.push_back(circle);
        }
        //Stucked point
        std::srand(time(NULL));
        for (std::size_t i = 0; i < 30; i++){
                sf::CircleShape circle2;
               
                int x = std::rand() % W;
                int y = std::rand() % H;
                circle2.setPosition(x, y);
                circle2.setPointCount(6);
                circle2.setRadius(5);
                sf::Color color = sf::Color(0, 255, 0, 255);
                circle2.setFillColor(color);
                circle_stucked.push_back(circle2);
        }
               


    // run the main loop
    while (window.isOpen())
    {
        // handle events
        sf::Event event;
        while (window.pollEvent(event))
        {
            if(event.type == sf::Event::Closed)
                window.close();
        }


                window.clear();
               

               

                //moving random particles
                for (std::size_t i = 0; i < circle_free.size(); i++) {
                        sf::Vector2f offset;
                        float speed = 10;
                        offset.x = ( speed / 2.0 - static_cast <float> (rand()) / (static_cast <float> (RAND_MAX / speed)) );
                        offset.y = ( speed / 2.0 - static_cast <float> (rand()) / (static_cast <float> (RAND_MAX / speed)) );

                        circle_free[i].move(offset);

                        //printf("%i\n", sz);
                        //back particles to window
                        if (circle_free[i].getPosition().x > W) circle_free[i].setPosition(W-10, circle_free[i].getPosition().y);
                        if (circle_free[i].getPosition().y > H) circle_free[i].setPosition(circle_free[i].getPosition().x, H-10);
                        if (circle_free[i].getPosition().x < 0) circle_free[i].setPosition(10, circle_free[i].getPosition().y);
                        if (circle_free[i].getPosition().y < 0) circle_free[i].setPosition(circle_free[i].getPosition().x, 10);
                }

                for (std::size_t i = 0; i < circle_free.size(); i++) {
                        for (std::size_t j = 0; j < circle_stucked.size(); j++) {
                                //printf("OK");
                                float dist = pow(circle_free[i].getPosition().x - circle_stucked[j].getPosition().x, 2) +
                                        pow(circle_free[i].getPosition().y - circle_stucked[j].getPosition().y, 2);
                                dist = sqrt(dist);

                                if (dist <= (r * 2) ) {//here we stuck moving particles
                                        sf::Color color = sf::Color(0, 255, 0, 200);
                                        circle_free[i].setFillColor(color);

                                        //add moving particle to stucked vector
                                        circle_stucked.push_back(circle_free[i]);
                                        //delete moving particles from vector

                                        circle_free.erase(circle_free.begin() + i);
                                }
                        }
                }

                //draw moving particles
                for (std::size_t i = 0; i < circle_free.size(); i++) {
                        window.draw(circle_free[i]);
                }
                //draw stucked particles
                for (std::size_t i = 0; i < circle_stucked.size(); i++) {
                        window.draw(circle_stucked[i]);
                }

        window.display();
    }

    return 0;
}
 

Chaia*

  • Newbie
  • *
  • Posts: 21
    • View Profile
Re: Crash visualization of Diffusion-limited aggregation
« Reply #1 on: January 23, 2017, 12:57:46 pm »
I think your problem is located in this loop:
for (std::size_t i = 0; i < circle_free.size(); i++) {
            for (std::size_t j = 0; j < circle_stucked.size(); j++) {
                //printf("OK");
                float dist = pow(circle_free[i].getPosition().x - circle_stucked[j].getPosition().x, 2) +
                    pow(circle_free[i].getPosition().y - circle_stucked[j].getPosition().y, 2);
                dist = sqrt(dist);

                if (dist <= (r * 2) ) {//here we stuck moving particles
                    sf::Color color = sf::Color(0, 255, 0, 200);
                    circle_free[i].setFillColor(color);

                    //add moving particle to stucked vector
                    circle_stucked.push_back(circle_free[i]);
                    //delete moving particles from vector

                    circle_free.erase(circle_free.begin() + i);
                }
            }
        }

Try adding a
break;
after
circle_free.erase(circle_free.begin() + i);
 
. The problem is, if you erase the element i, and then further iterate through the circle_stucked, your're trying to access circle_free[ i ], which you already deleted an iteration ago.

Therefore, since your moving_particle[ i ] got deleted, you do not need and you should not further check interation with circle_stucked.

Another possibility to solve your problem would be you do not erase/push_back the circles in this multidimensional loop at all, but instead you only process and calculate and then you save all your erase/push_back jobs somehow in a list/vector etc.
After completing this step, you apply your erase/push_back job list.
« Last Edit: January 23, 2017, 12:59:43 pm by Chaia* »

Sevas

  • Newbie
  • *
  • Posts: 2
    • View Profile
Re: Crash visualization of Diffusion-limited aggregation
« Reply #2 on: January 23, 2017, 05:38:17 pm »
Yes, probably I fixed problem by changing indexes of loops

this
Quote
for (std::size_t i = 0; i < circle_free.size(); i++) {
            for (std::size_t j = 0; j < circle_stucked.size(); j++) {

to this
Quote
for (std::size_t j = 0;j< circle_free.size();j++) {
            for (std::size_t i = 0; i < circle_stucked.size(); i++) {

Now I don`t have crash, and all works.
But not sure I have effective code.
Will try as you adviced.

Thank you very much!
« Last Edit: January 23, 2017, 05:46:48 pm by Sevas »

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11030
    • View Profile
    • development blog
    • Email
Re: Crash visualization of Diffusion-limited aggregation
« Reply #3 on: January 25, 2017, 01:25:20 pm »
You renamed the indices and now it should suddenly work?

Say circle_free and circle_stucked have each 5 elements. Now when the outer loop hits the last element (i = 4), while the inner loop is only at the first element (j = 0), then you remove the last element of circle_free, but i still remains at 4, thus you'll access a none-existing element when the inner loop starts again, because i = 4 doesn't exist anymore.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

JayhawkZombie

  • Jr. Member
  • **
  • Posts: 76
    • View Profile
Re: Crash visualization of Diffusion-limited aggregation
« Reply #4 on: January 26, 2017, 04:35:44 am »
You could try use range-based for-loops. They would be safer than using explicit indices.

for (auto & cfree : circle_free) {
  for (auto & cstuck : circle_stucked) {
  ...
  }
}

Plus, under the right circumstances, they can be faster than the regular way of doing loops.