<commit_before>#include <iostream>
#include <string>
#include <cctype>
using namespace std;

#define MARGIN "     "

string job;
string product;
string outfit;
string outfitadjective;
string name;
string drink;
string drinksize;
bool gamewon;

char ask(string question){
	string answer;
	cout << question << " ";
	getline(cin, answer);
	return toupper(answer[0]);
}

string ask(string question, bool shortanswer){
	string answer;
	cout << question << " ";
	getline(cin, answer);
	return answer;
}

void splashscreen(){
	cout << " #####  ####   ####  ######  ####  #    # #####  #### #####" << endl;
	cout << "#      #    # #      #      #    # #    # #     #       #  " << endl;
	cout << "#      ###### #  ### ####   #  # # #    # ####   ###    #  " << endl;
	cout << "#      #    # #    # #      #   ## #    # #         #   #  " << endl;
	cout << " ##### #    #  ####  ######  #####  ####  ##### ####    #  " << endl;
	cout << "..........................................................." << endl;
	cout << "CageQuest 2K17 by Alex Vermillion                          " << endl;
	cout << endl << endl;
}

int newgame(){
	char startchoice = ask("Are you ready to start a new game? [y/n]");
	cout << endl;
	if (startchoice == 'Y'){
		splashscreen();
		return 0;
	}
	if (startchoice == 'N'){
		cout << "You probably shouldn't have started up the game then moron!" << endl;
		cout << endl;
		cout << "G O O D   B Y E" << endl;
		return 1;
	}
	else {
		cout << "Hmm..." << endl;
		cout << "I don't have any idea what you are trying to type!" << endl;
		cout << "." << "." << "." << endl;
		cout << "No, really!" << endl;
		cout << "I'm not magic! I'm not an A.I.! I don't have a dictionary programmed in!" << endl;
		cout << "I just take the first character of your response and check if it is yes or no." << endl;
		cout << "You really should be more careful in the future." << endl;
	}
}

int tutorial(){
	char tutorialchoice;
	tutorialchoice = ask("Would you like to view the tutorial? [y/n]");
	if (tutorialchoice == 'N'){
		return 0;
	}
	cout << "Hi!" << endl << "I'm the tutorial guide. I'll teach you how to navigate CageQuest." << endl;
	cout << "CageQuest is a text-based RPG adventure, or a tbRPGa. Allow me to explain." << endl;
	cout << "All you are going to see here is text. You'll get some stuff to read, and then you'll type back" << endl;
	cout << "I'll give you some choices in brackets at the end, and you will type back ONE CHARACTER unless told otherwise." << endl;
	cout << "Here is what the choices look like [a/b/c]" << endl;
	cout << "If you see a [y/n], you are being asked a yes or no question." << endl;
	cout << "That's all I've got for you!" << endl;
	char tutorialexitchoice;
	tutorialexitchoice = ask("Are you ready to exit the tutorial? [y/n]");
	cout << endl;
	if (tutorialexitchoice == 'Y'){
		return 1;
	}
	else {
		return tutorial();
	}
}

int morning(){
    cout << "BEEP BEEP BEEP BEEP BEEP BEEP" << endl;
    cout << "It's your alarm clock. You look over at it and read the time. It's 7:00." << endl;
    cout << "You have to go to work. You can't quite remember your job." << endl;
    char jobchoice;
    jobchoice = ask("Do you work as a sandwich maker, a burrito crafter, or as a gyro artist? [s/b/g]");
    if (jobchoice == 'S'){
		job = "sandwich maker";
		product = "sandwich";
	}
    if (jobchoice == 'B'){
		job = "burrito crafter";
		product = "burrito";
	}
    if (jobchoice == 'G'){
		job = "gyro artist";
		product = "gyro";
	}
    if ((jobchoice != 'S') and (jobchoice != 'B') and (jobchoice != 'G')) {
		job = "person who is unable to correctly type single character responses in text adventure games";
		product = "mistake";
	}
    cout << "Now you remember! You love your job as the top " << job << " in all of New York City." << endl;
    cout << "You receive $10,000 US for every " << product << " that you make." << endl;
    cout << "Anyway, it's time to get to work. You step out of bed, fully dressed." << endl;
    outfit = ask("What are you wearing? [free response]",1);
    cout << "But this isn't just any " << outfit << ", this one is special." << endl;
    outfitadjective = ask("What adjective would describe this outfit? [free response]",1);
    name = ask("Last but not least, what is your name? [free response]",1);
    cout << "To recap: You are " << name << ", NYC's most prestigious " << job << " and today you are wearing a(n) " << outfitadjective << " " << outfit <<endl;
    char exitmorningchoice;
    exitmorningchoice = ask("Is that all correct? [y/n]");
    if (exitmorningchoice == 'Y'){
		return 0;
    }
    else {
		cout << "Here we go again..." << endl;
		return morning();
    }
}

int drinkaquisition(){
	cout << "You open your fridge and see you have some milk. On the counter is your coffee maker and some teabags." << endl;
	cout << "Mmmm. So many choices. What should you take to drink on the way to work?" << endl;
	char drinkchoice;
	drinkchoice = ask("Will you drink milk, coffee, or tea? [m/c/t]");
	if (drinkchoice == 'M'){
		drink = "milk";
		drinksize = "glass";
	}
	if (drinkchoice == 'C'){
		drink = "coffee";
		drinksize = "mug";
	}
	if (drinkchoice == 'T'){
		drink = "tea";
		drinksize = "cup";
	}
	if ((drinkchoice != 'M') and (drinkchoice != 'C') and (drinkchoice != 'T')){
		drink = "urine";
		drinksize = "keg";
	}
	cout << "Yum! Your favorite! You make up a " << drinksize << " of " << drink << " and get on your way." << endl;
}

int work(){
	cout << "You go to work and make a million dollars. When you get back to your vehicle, there is a note. The note reads:" << endl;
	cout << endl;
	cout << MARGIN << "Dear " << name << "," << endl;
	cout << MARGIN << "     I've been watching you for some time now, and I think you are a really cool person. Let's go on a date." << endl;
	cout << MARGIN << "Meet me at the restaurant in town that serves your favorite beverages at 18:00 sharp. You don't need to dress up," << endl;
	cout << MARGIN << "just come in your work clothes." << endl;
	cout << MARGIN << "Love," << endl;
	cout << MARGIN << "Your Secret Admirer, NKC" << endl;
	cout << endl;
}

int meetingtheman(){
	cout << "Glancing down at your watch you realize it is already 17:30! You only have 30 minutes to make it to the " << drink << " shop!" << endl;
	cout << "You decide to ignore the fact that this person is more of a stalker than a secret admirer, and you rush to the " << drink << " shop." << endl;
	cout << "When you get there, it is 18:04. 'Wow, good first impression " << name << "', you sarcastically think to yourself." << endl;
	cout << "You look around for a table occupied by a person who looks like they are watching for their date." << endl;
	cout << "While searching, you spot a celebrity." << endl;
	cout << MARGIN << "\"Excuse me, Mr. Nicolas Cage, may I have your autograph?\" you find yourself asking." << endl;
	cout << MARGIN << "\"Ah, " << name << "! Sit down, sit down. Oh, you seem surprised. Yes, I am the one who invited you here,\" he responds." << endl;
	cout << "You feel your heart race. Nicolas Cage, your favorite actor of all time has invited you on a date. You can't believe it." << endl;
	cout << "Nicolas turns to you. \"I ordered you two " << drinksize << "s of " << drink << ", your favorite,\" he offers. I hope you like it.\"" << endl;
	cout << "Eagerly, you take a sip. \"Mmmmm,\" you say. \"It's delicious!\"" << endl;
	cout << "\"Thank you, I ordered it myself,\" he says, erupting into laughter at his own joke. \"Ooh, that's a good one!\" he finishes." << endl;
}

int date(){
	cout << "\"Anyway,\" he begins. \"I quite like your " << outfit << ", " << name << "; it's quite " << outfitadjective << ".\"" << endl;
	cout << "He orders you both meals that cost more than your lifetime salary. You enjoy yours very much." << endl;
	cout << "When it comes time to pay, he smiles at the waitstaff and gives them more money than you thought was in circulation." << endl;
	cout << "Nic offers to drive you home. He drives your car home using his mind. Soon, you arrive at your doorstep. You look at him." << endl;
	cout << "\"Well,\" you begin. \"This is my stop,\" you say timidly." << endl;
	cout << "Nicolas Cage looks at you. \"I know.\" he says." << endl;
	if ((product == "mistake") or (drink == "urine")){
		cout << "\"I should have told you. I'm a big fan of text adventure games that star myself as the main character\" he says." << endl;
		cout << "\"And I don't think I can be with someone who is too dumb to input valid options when prompted.\"" << endl;
		cout << "Nicolas Cage punches you in the stomach." << endl;
		cout << "He throws you out of his car, and drives away over your car. Your car is crushed to pieces." << endl;
		cout << "As he leaves, he throws a match that lights your house on fire." << endl;
		cout << "As he fades into the distance, he shouts to you:" << endl;
		cout << "\"Next time you play this game, try not to do so poorly!\" he yells." << endl;
		cout << "Game over." << endl;
		cout << "You lost! Ahaha what a loser!" << endl;
		gamewon = false;
	}
	else {
		cout << "Nicolas Cage pulls out a wedding ring." << endl;
		cout << "\"Will you be my National Treasure?\" he asks." << endl;
		cout << "You say yes. Obviously. You guys get married, and the pope does the ceremony." << endl;
		cout << "Every celebrity ever is there, even the ones who are dead and also the ones from the future." << endl;
		cout << "Nicolas Cage tells you he loves you, and you guys live forever in his mansion that is heaven because he is God." << endl;
		cout << "Game over." << endl;
		cout << "You win! Woohoo what a winner!" << endl;
		gamewon = true;
	}

}

int main()
{
	if (newgame() != 0){ return 1;}
	tutorial();
	morning();
	drinkaquisition();
	work();
	meetingtheman();
	date();
	return gamewon;
}
<commit_msg>Delete old C++ source<commit_after><|endoftext|>


<commit_before>#include "imgui.h"
#include "imgui-sfml.h"
#include <iostream>
#include <SFML/Graphics.hpp>
#include <SFML/System/Clock.hpp>

#define IM_ARRAYSIZE(_ARR)  ((int)(sizeof(_ARR)/sizeof(*_ARR)))

class Grid
{
private:
    sf::RectangleShape _line;

    int _step;
    int _thickness;
    sf::Color _color;

public:
    Grid(sf::Color color=sf::Color::White, int width=1):
        _color(color), _thickness(width){}
// set
    void step(int step){_step = step;}
    void thickness(int thickness){_thickness = thickness;}
    void color(sf::Color color){_color = color;}
// get
    int step(){return _step;}
    int width(){return _thickness;}
    sf::Color color(){return _color;}

    void draw(sf::RenderWindow &window);
};

void Grid::draw(sf::RenderWindow &window)
{
    _line.setFillColor(_color);

    for (int dir=0; dir<2; ++dir){
        unsigned int limit;
        switch(dir){
            case 0:
                limit = window.getSize().y;
                _line.setSize(sf::Vector2f(limit, _thickness));
                break;
            case 1:
                limit = window.getSize().x;
                _line.setSize(sf::Vector2f(_thickness, limit));
                break;
        }
        for (int i=0; i<limit; i+= _step){
            switch(dir){
                case 0: _line.setPosition(0,i); break;
                case 1: _line.setPosition(i,0); break;
                }
            window.draw(_line);
        }
    }
}

class Background
{
private:
    Grid  _grid;
    sf::Color _color;

    int _step[3] {12,24,96};
    int _grad[3] {5,10,25};

public:
    Background(sf::Color color=sf::Color(30,80,120)) : _color(color){}
// set
    void color(sf::Color color){_color = color;}
// get
    sf::Color color(){return _color;}

    void draw(sf::RenderWindow &window);
};

void Background::draw(sf::RenderWindow &window)
{
    window.clear(_color);

    for (int i=0;i<3;++i){
        _grid.step(_step[i]);
        _grid.color(_color + sf::Color(_grad[i], _grad[i], _grad[i]));

        _grid.draw(window);
    }
}

class Outline
{
public:
    sf::Color _color;
    int _thickness;

    Outline(const int thickness=1, const sf::Color color=sf::Color::Black):
        _color(color), _thickness(thickness) {}
};

class Figure{
public:
    sf::Vector2i _center;
    sf::Vector2i _size;
    sf::Vector2i _initSize;
    float _scale;

    int _depth;

    sf::Color _color;
    Outline _outline;

    sf::Vector2i _startPoint;

    Figure(const sf::Vector2i   &center,
           const sf::Vector2i   &initSize=sf::Vector2i(450,450),

           const int            depth=0,

           const sf::Color      &color=sf::Color::White,
           const Outline        &outline=Outline()):
                _center(center), _initSize(initSize), _scale(1),
                _color(color), _outline(outline),
                _depth(depth)
    {
        calcSize();
        calcStartPoint();
    }

    void draw(sf::RenderWindow &window);
    void draw(sf::RenderWindow &window, int depth,
              sf::Vector2i position, sf::Vector2i size,
              int thickness);

    void calcSize(){
        _size.x = _initSize.x*_scale;
        _size.y = _initSize.y*_scale;
    }

    void calcStartPoint(){
        _startPoint.x = _center.x - _size.x/2;
        _startPoint.y = _center.y - _size.y/2;
    }
};

// Exist some problem with rounding of <Vector2i size> variable
// For example:
// if init <size.x> value = 200, is losed 2 pixel when program
// step into next recurtion level (200/3 -> 198)
void Figure::draw(sf::RenderWindow &window)
{
    draw(window, _depth, _startPoint, _size, _outline._thickness);
}

void Figure::draw(sf::RenderWindow &window, int depth,
                  sf::Vector2i position, sf::Vector2i size,
                  int thickness)
{
    sf::RectangleShape element;

    element.setFillColor(_color);

    element.setOutlineThickness(thickness);
    element.setOutlineColor(_outline._color);

    if (depth == 0){
        element.setSize(sf::Vector2f(size.x,size.y));
        element.setPosition(sf::Vector2f(_startPoint.x,_startPoint.y));
        window.draw(element);
        return;
    }

    element.setSize(sf::Vector2f(size.x/3, size.y/3));
    sf::Vector2i point(position);

    for (int i=1; i<=9; ++i)
    {
        if (i != 5){
            element.setPosition(sf::Vector2f(point.x,point.y));

            if (depth == 1)
                window.draw(element);
            else{

                draw(window, depth-1, point, size/3, thickness/2);
            }
         }
        if (!(i%3)){
            point.y += size.x/3;
            point.x =  position.x;
            continue;
        }
        point.x += size.y/3;
    }
}

int main()
{
    // SFML and ImGui Init
    sf::RenderWindow window(sf::VideoMode(800,600),"ReIGen", sf::Style::Titlebar|
                                                             sf::Style::Close);
    ImGui::SFML::Init(window);

    sf::Clock deltaClock;

    // Set color settings
    Background bg;
    int imGui_FillColor[4]{255,255,255,255};
    int imGui_outlineColor[4]{0,0,0,255};

    // Set Figure settings
    int uiWidth = 200;
    sf::Vector2i canvasCenter((window.getSize().x - uiWidth)/2,
                               window.getSize().y/2);

    Figure  SierpinskiCarpet(canvasCenter, sf::Vector2i(450,450), 5);

    const char* type[]{"Curve","Gasket"};
    int typeIndex = 1;

    const char* gasketSubType[]{"Sierpinski sieves","Sierpinski carpet"};
    int gasketSubTypeIndex = 1;

    ImGuiStyle& style = ImGui::GetStyle();
    style.WindowPadding.x = 32;
    // style.ItemSpacing.y   = 0;

    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            ImGui::SFML::ProcessEvent(event);

            if (event.type == sf::Event::Closed)
                    window.close();
        }

        ImGui::SFML::Update(window, deltaClock.restart());

        ImGui::SetNextWindowPos(ImVec2(600,0));
        ImGui::SetNextWindowSize(ImVec2(uiWidth,600));

        ImGui::Begin("Settings", false, ImGuiWindowFlags_NoTitleBar|
                                        ImGuiWindowFlags_NoResize|
                                        ImGuiWindowFlags_NoMove|
                                        ImGuiWindowFlags_NoCollapse|
                                        ImGuiWindowFlags_ShowBorders);
        ImGui::Text("");
        ImGui::Text("Type");
        ImGui::Combo("##Type", &typeIndex, type,
                     IM_ARRAYSIZE(type));

        ImGui::Text("");
        ImGui::Text("Subtype");
        ImGui::Combo("##Subtype", &gasketSubTypeIndex, gasketSubType,
                     IM_ARRAYSIZE(gasketSubType));

        ImGui::Text("");
        ImGui::Separator();
        ImGui::Text("");

        ImGui::Text("Recursion depth");
        ImGui::SliderInt("##Recursion depth", &SierpinskiCarpet._depth, 0, 5);
        ImGui::Text("");

        ImGui::Text("Image Scale");
        if(ImGui::SliderFloat("##Image Scale", &SierpinskiCarpet._scale, 0.5, 2))
        {
           SierpinskiCarpet.calcSize();
           SierpinskiCarpet.calcStartPoint();
        }

        ImGui::Text("");
        ImGui::Separator();
        ImGui::Text("");

        ImGui::Text("Fill Color");
        if(ImGui::DragInt4("##Fill Color", imGui_FillColor, 1, 0, 255)){
           SierpinskiCarpet._color.r = imGui_FillColor[0];
           SierpinskiCarpet._color.g = imGui_FillColor[1];
           SierpinskiCarpet._color.b = imGui_FillColor[2];
           SierpinskiCarpet._color.a = imGui_FillColor[3];
        }

        ImGui::Text("Outline Color");
        if(ImGui::DragInt4("##Outline Color", imGui_outlineColor, 1, 0, 255)){
           SierpinskiCarpet._outline._color.r = imGui_outlineColor[0];
           SierpinskiCarpet._outline._color.g = imGui_outlineColor[1];
           SierpinskiCarpet._outline._color.b = imGui_outlineColor[2];
           SierpinskiCarpet._outline._color.a = imGui_outlineColor[3];
        }

        ImGui::Text("");
        ImGui::Text("Outline Thickness");
        ImGui::SliderInt("##outline Thickness",
                         &SierpinskiCarpet._outline._thickness, 0, -16);

        ImGui::End();

        window.clear();
        bg.draw(window);
        SierpinskiCarpet.draw(window);
        // ImGui::ShowTestWindow();
        ImGui::Render();
        window.display();
    }

    ImGui::SFML::Shutdown();
    return 0;
}
<commit_msg>improve UI: add ability to change background color<commit_after>#include "imgui.h"
#include "imgui-sfml.h"
#include <iostream>
#include <SFML/Graphics.hpp>
#include <SFML/System/Clock.hpp>

#define IM_ARRAYSIZE(_ARR)  ((int)(sizeof(_ARR)/sizeof(*_ARR)))

class Grid
{
private:
    sf::RectangleShape _line;

    int _step;
    int _thickness;
    sf::Color _color;

public:
    Grid(sf::Color color=sf::Color::White, int width=1):
        _color(color), _thickness(width){}
// set
    void step(int step){_step = step;}
    void thickness(int thickness){_thickness = thickness;}
    void color(sf::Color color){_color = color;}
// get
    int step(){return _step;}
    int width(){return _thickness;}
    sf::Color color(){return _color;}

    void draw(sf::RenderWindow &window);
};

void Grid::draw(sf::RenderWindow &window)
{
    _line.setFillColor(_color);

    for (int dir=0; dir<2; ++dir){
        unsigned int limit;
        switch(dir){
            case 0:
                limit = window.getSize().y;
                _line.setSize(sf::Vector2f(limit, _thickness));
                break;
            case 1:
                limit = window.getSize().x;
                _line.setSize(sf::Vector2f(_thickness, limit));
                break;
        }
        for (int i=0; i<limit; i+= _step){
            switch(dir){
                case 0: _line.setPosition(0,i); break;
                case 1: _line.setPosition(i,0); break;
                }
            window.draw(_line);
        }
    }
}

class Background
{
private:
    Grid  _grid;
    sf::Color _color;

    int _step[3] {12,24,96};
    int _grad[3] {5,10,25};

public:
    Background(sf::Color color=sf::Color(30,80,120)) : _color(color){}
// set
    void color(sf::Color color){_color = color;}
// get
    sf::Color color(){return _color;}

    void draw(sf::RenderWindow &window);
};

void Background::draw(sf::RenderWindow &window)
{
    window.clear(_color);

    for (int i=0;i<3;++i){
        _grid.step(_step[i]);
        _grid.color(_color + sf::Color(_grad[i], _grad[i], _grad[i]));

        _grid.draw(window);
    }
}

class Outline
{
public:
    sf::Color _color;
    int _thickness;

    Outline(const int thickness=1, const sf::Color color=sf::Color::Black):
        _color(color), _thickness(thickness) {}
};

class Figure{
public:
    sf::Vector2i _center;
    sf::Vector2i _size;
    sf::Vector2i _initSize;
    float _scale;

    int _depth;

    sf::Color _color;
    Outline _outline;

    sf::Vector2i _startPoint;

    Figure(const sf::Vector2i   &center,
           const sf::Vector2i   &initSize=sf::Vector2i(450,450),

           const int            depth=0,

           const sf::Color      &color=sf::Color::White,
           const Outline        &outline=Outline()):
                _center(center), _initSize(initSize), _scale(1),
                _color(color), _outline(outline),
                _depth(depth)
    {
        calcSize();
        calcStartPoint();
    }

    void draw(sf::RenderWindow &window);
    void draw(sf::RenderWindow &window, int depth,
              sf::Vector2i position, sf::Vector2i size,
              int thickness);

    void calcSize(){
        _size.x = _initSize.x*_scale;
        _size.y = _initSize.y*_scale;
    }

    void calcStartPoint(){
        _startPoint.x = _center.x - _size.x/2;
        _startPoint.y = _center.y - _size.y/2;
    }
};

// Exist some problem with rounding of <Vector2i size> variable
// For example:
// if init <size.x> value = 200, is losed 2 pixel when program
// step into next recurtion level (200/3 -> 198)
void Figure::draw(sf::RenderWindow &window)
{
    draw(window, _depth, _startPoint, _size, _outline._thickness);
}

void Figure::draw(sf::RenderWindow &window, int depth,
                  sf::Vector2i position, sf::Vector2i size,
                  int thickness)
{
    sf::RectangleShape element;

    element.setFillColor(_color);

    element.setOutlineThickness(thickness);
    element.setOutlineColor(_outline._color);

    if (depth == 0){
        element.setSize(sf::Vector2f(size.x,size.y));
        element.setPosition(sf::Vector2f(_startPoint.x,_startPoint.y));
        window.draw(element);
        return;
    }

    element.setSize(sf::Vector2f(size.x/3, size.y/3));
    sf::Vector2i point(position);

    for (int i=1; i<=9; ++i)
    {
        if (i != 5){
            element.setPosition(sf::Vector2f(point.x,point.y));

            if (depth == 1)
                window.draw(element);
            else{

                draw(window, depth-1, point, size/3, thickness/2);
            }
         }
        if (!(i%3)){
            point.y += size.x/3;
            point.x =  position.x;
            continue;
        }
        point.x += size.y/3;
    }
}

int main()
{
    // SFML and ImGui Init
    sf::RenderWindow window(sf::VideoMode(800,600),"ReIGen", sf::Style::Titlebar|
                                                             sf::Style::Close);
    ImGui::SFML::Init(window);

    sf::Clock deltaClock;

    // Set color settings
    Background bg;
    int imGui_FillColor[4]{255,255,255,255};
    int imGui_outlineColor[4]{0,0,0,255};
    int imGui_bgColor[4]{bg.color().r, bg.color().g, bg.color().b, bg.color().a};

    // Set Figure settings
    int uiWidth = 200;
    sf::Vector2i canvasCenter((window.getSize().x - uiWidth)/2,
                               window.getSize().y/2);

    Figure  SierpinskiCarpet(canvasCenter, sf::Vector2i(450,450), 5);

    const char* type[]{"Curve","Gasket"};
    int typeIndex = 1;

    const char* gasketSubType[]{"Sierpinski sieves","Sierpinski carpet"};
    int gasketSubTypeIndex = 1;

    ImGuiStyle& style = ImGui::GetStyle();
    style.WindowPadding.x = 32;
    // style.ItemSpacing.y   = 0;

    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            ImGui::SFML::ProcessEvent(event);

            if (event.type == sf::Event::Closed)
                    window.close();
        }

        ImGui::SFML::Update(window, deltaClock.restart());

        ImGui::SetNextWindowPos(ImVec2(600,0));
        ImGui::SetNextWindowSize(ImVec2(uiWidth,600));

        ImGui::Begin("Settings", false, ImGuiWindowFlags_NoTitleBar|
                                        ImGuiWindowFlags_NoResize|
                                        ImGuiWindowFlags_NoMove|
                                        ImGuiWindowFlags_NoCollapse|
                                        ImGuiWindowFlags_ShowBorders);
        ImGui::Text("");
        ImGui::Text("Type");
        ImGui::Combo("##Type", &typeIndex, type,
                     IM_ARRAYSIZE(type));

        ImGui::Text("");
        ImGui::Text("Subtype");
        ImGui::Combo("##Subtype", &gasketSubTypeIndex, gasketSubType,
                     IM_ARRAYSIZE(gasketSubType));

        ImGui::Text("");
        ImGui::Separator();
        ImGui::Text("");

        ImGui::Text("Recursion depth");
        ImGui::SliderInt("##Recursion depth", &SierpinskiCarpet._depth, 0, 5);
        ImGui::Text("");

        ImGui::Text("Image Scale");
        if(ImGui::SliderFloat("##Image Scale", &SierpinskiCarpet._scale, 0.5, 2))
        {
           SierpinskiCarpet.calcSize();
           SierpinskiCarpet.calcStartPoint();
        }

        ImGui::Text("");
        ImGui::Separator();
        ImGui::Text("");

        ImGui::Text("Fill Color");
        if(ImGui::DragInt4("##Fill Color", imGui_FillColor, 1, 0, 255)){
           SierpinskiCarpet._color.r = imGui_FillColor[0];
           SierpinskiCarpet._color.g = imGui_FillColor[1];
           SierpinskiCarpet._color.b = imGui_FillColor[2];
           SierpinskiCarpet._color.a = imGui_FillColor[3];
        }

        ImGui::Text("Outline Color");
        if(ImGui::DragInt4("##Outline Color", imGui_outlineColor, 1, 0, 255)){
           SierpinskiCarpet._outline._color.r = imGui_outlineColor[0];
           SierpinskiCarpet._outline._color.g = imGui_outlineColor[1];
           SierpinskiCarpet._outline._color.b = imGui_outlineColor[2];
           SierpinskiCarpet._outline._color.a = imGui_outlineColor[3];
        }

        ImGui::Text("");
        ImGui::Text("Outline Thickness");
        ImGui::SliderInt("##outline Thickness",
                         &SierpinskiCarpet._outline._thickness, 0, -16);

        ImGui::Text("");
        ImGui::Separator();
        ImGui::Text("");

        ImGui::Text("Background color");
        if(ImGui::DragInt4("##Background color", imGui_bgColor, 1, 0, 255)){
            bg.color(sf::Color(imGui_bgColor[0],imGui_bgColor[1],
                               imGui_bgColor[2],imGui_bgColor[3]));
        }
        ImGui::End();

        window.clear();
        bg.draw(window);
        SierpinskiCarpet.draw(window);
        // ImGui::ShowTestWindow();
        ImGui::Render();
        window.display();
    }

    ImGui::SFML::Shutdown();
    return 0;
}
<|endoftext|>


<commit_before>28950323-ad5c-11e7-a947-ac87a332f658<commit_msg>GOD DAMNED IT!<commit_after>290bc099-ad5c-11e7-ab44-ac87a332f658<|endoftext|>


<commit_before>///////////////////////////////////////////////////////////////////////////////
//
// File VortexWaveInteractionSolver.cpp
//
// For more information, please see: http://www.nektar.info
//
// The MIT License
//
// Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
// Department of Aeronautics, Imperial College London (UK), and Scientific
// Computing and Imaging Institute, University of Utah (USA).
//
// License for the specific language governing rights and limitations under
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Description: Vortex Wave Interaction solver
//
///////////////////////////////////////////////////////////////////////////////

#include <Auxiliary/Driver.h>
#include <LibUtilities/BasicUtils/SessionReader.h>

using namespace Nektar;

int main(int argc, char *argv[])
{

    if(argc != 2)
    {
        cerr << "\n \t Usage: VortexWaveInteractionSolver  input \n" << endl;
        exit(1);
    }

    LibUtilities::SessionReaderSharedPtr IncNSsession, AdvDiffsession, LinNSsession;
    string vDriverModule;
    DriverSharedPtr LinNSdrv;
    int pargc = 2;
    std::string meshfile(argv[argc-1]);
    meshfile += ".xml";

    // system call strings;
    string FldToRst("cp -f ");
    FldToRst += argv[argc-1];
    FldToRst += ".fld ";
    FldToRst += argv[argc-1];
    FldToRst += ".rst";

    string FldToBase("cp -f ");
    FldToBase += argv[argc-1];
    FldToBase += ".fld ";
    FldToBase += argv[argc-1];
    FldToBase += "-Base.fld";

    string FldToStreak("cp -f ");
    FldToStreak += argv[argc-1];
    FldToStreak += ".fld ";
    FldToStreak += argv[argc-1];
    FldToStreak += "_streak.fld";

    try
    {
        // Initialise NS solver
        std::string IncCondFile(argv[argc-1]);
        IncCondFile += "_IncNSCond.xml";
        std::vector<std::string> IncNSFilenames;
        IncNSFilenames.push_back(meshfile);
        IncNSFilenames.push_back(IncCondFile);

        // Initialise AdvDiff solver
        std::string AdvDiffCondFile(argv[argc-1]);
        AdvDiffCondFile += "_AdvDiffCond.xml";
        std::vector<std::string> AdvDiffFilenames;
        AdvDiffFilenames.push_back(meshfile);
        AdvDiffFilenames.push_back(AdvDiffCondFile);

        // Initialise LinNS solver
        std::string LinNSCondFile(argv[argc-1]);
        LinNSCondFile += "_LinNSCond.xml";
        std::vector<std::string> LinNSFilenames;
        LinNSFilenames.push_back(meshfile);
        LinNSFilenames.push_back(LinNSCondFile);

        // Create IncompressibleNavierStokesSolver session reader.
        IncNSsession = LibUtilities::SessionReader::CreateInstance(argc, argv, IncNSFilenames);
        // Setup Incompresible solver and execute
        std::string vEquation = IncNSsession->GetSolverInfo("SolverType");
        EquationSystemSharedPtr NSeqn = GetEquationSystemFactory().CreateInstance(vEquation,IncNSsession);

        NSeqn->PrintSummary(cout);
        NSeqn->DoInitialise();
        NSeqn->DoSolve();
        NSeqn->Output();

        // Copy .fld file to .rst and base.fld
        cout << "Executing " <<  FldToRst << endl;
        system(FldToRst.c_str());
        cout << "Executing " <<  FldToBase << endl;
        system(FldToBase.c_str());

        // Create AdvDiffusion session reader.
        AdvDiffsession = LibUtilities::SessionReader::CreateInstance(argc, argv, AdvDiffFilenames);
        // Setup and execute Advection Diffusion solver
        vEquation = AdvDiffsession->GetSolverInfo("EqType");
        EquationSystemSharedPtr AdvDiffeqn = GetEquationSystemFactory().CreateInstance(vEquation,AdvDiffsession);

        AdvDiffeqn->PrintSummary(cout);
        AdvDiffeqn->DoInitialise();
        AdvDiffeqn->DoSolve();
        AdvDiffeqn->Output();

        cout << "Executing " <<  FldToStreak << endl;
        system(FldToStreak.c_str());

        // Create Linearised NS stability session reader.
        LinNSsession = LibUtilities::SessionReader::CreateInstance(argc, argv, LinNSFilenames);
        // Create driver
        LinNSsession->LoadSolverInfo("Driver", vDriverModule, "ModifiedArnoldi");
        LinNSdrv = GetDriverFactory().CreateInstance(vDriverModule, LinNSsession);
        /// Do NavierStokes Session
        LinNSdrv->Execute();

        // Finalise communications
        IncNSsession->Finalise();
        AdvDiffsession->Finalise();
        LinNSsession->Finalise();

    }
    catch (const std::runtime_error& e)
    {
        return 1;
    }
    catch (const std::string& eStr)
    {
        cout << "Error: " << eStr << endl;
    }

    return 0;
}
<commit_msg>UPdate to first working vesion wtih symmetrization<commit_after>///////////////////////////////////////////////////////////////////////////////
//
// File VortexWaveInteractionSolver.cpp
//
// For more information, please see: http://www.nektar.info
//
// The MIT License
//
// Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
// Department of Aeronautics, Imperial College London (UK), and Scientific
// Computing and Imaging Institute, University of Utah (USA).
//
// License for the specific language governing rights and limitations under
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Description: Vortex Wave Interaction solver
//
///////////////////////////////////////////////////////////////////////////////

#include <Auxiliary/Driver.h>
#include <LibUtilities/BasicUtils/SessionReader.h>

using namespace Nektar;

void CalcNonLinearForce(EquationSystemSharedPtr &eqn);

int main(int argc, char *argv[])
{

    if(argc != 2)
    {
        cerr << "\n \t Usage: VortexWaveInteractionSolver  input \n" << endl;
        exit(1);
    }

    LibUtilities::SessionReaderSharedPtr IncNSsession, AdvDiffsession, LinNSsession;
    string vDriverModule;
    DriverSharedPtr LinNSdrv;
    int pargc = 2;
    std::string meshfile(argv[argc-1]);
    meshfile += ".xml";

    // system call strings;
    string FldToRst("cp -f ");
    FldToRst += argv[argc-1];
    FldToRst += ".fld ";
    FldToRst += argv[argc-1];
    FldToRst += ".rst";

    string FldToBase("cp -f ");
    FldToBase += argv[argc-1];
    FldToBase += ".fld ";
    FldToBase += argv[argc-1];
    FldToBase += "-Base.fld";

    string FldToStreak("cp -f ");
    FldToStreak += argv[argc-1];
    FldToStreak += ".fld ";
    FldToStreak += argv[argc-1];
    FldToStreak += "_streak.fld";

    try
    {
#if 1
       // Initialise NS solver
        std::string IncCondFile(argv[argc-1]);
        IncCondFile += "_IncNSCond.xml";
        std::vector<std::string> IncNSFilenames;
        IncNSFilenames.push_back(meshfile);
        IncNSFilenames.push_back(IncCondFile);

        // Initialise AdvDiff solver
        std::string AdvDiffCondFile(argv[argc-1]);
        AdvDiffCondFile += "_AdvDiffCond.xml";
        std::vector<std::string> AdvDiffFilenames;
        AdvDiffFilenames.push_back(meshfile);
        AdvDiffFilenames.push_back(AdvDiffCondFile);

        // Create IncompressibleNavierStokesSolver session reader.
        IncNSsession = LibUtilities::SessionReader::CreateInstance(argc, argv, IncNSFilenames);
        // Setup Incompresible solver and execute
        std::string vEquation = IncNSsession->GetSolverInfo("SolverType");
        EquationSystemSharedPtr NSeqn = GetEquationSystemFactory().CreateInstance(vEquation,IncNSsession);

        NSeqn->PrintSummary(cout);
        NSeqn->DoInitialise();
        NSeqn->DoSolve();
        NSeqn->Output();

        // Copy .fld file to .rst and base.fld
        cout << "Executing " <<  FldToRst << endl;
        system(FldToRst.c_str());
        cout << "Executing " <<  FldToBase << endl;
        system(FldToBase.c_str());

        // Create AdvDiffusion session reader.
        AdvDiffsession = LibUtilities::SessionReader::CreateInstance(argc, argv, AdvDiffFilenames);
        // Setup and execute Advection Diffusion solver
        vEquation = AdvDiffsession->GetSolverInfo("EqType");
        EquationSystemSharedPtr AdvDiffeqn = GetEquationSystemFactory().CreateInstance(vEquation,AdvDiffsession);

        AdvDiffeqn->PrintSummary(cout);
        AdvDiffeqn->DoInitialise();
        AdvDiffeqn->DoSolve();
        AdvDiffeqn->Output();

        cout << "Executing " <<  FldToStreak << endl;
        system(FldToStreak.c_str());
#endif

        // Initialise LinNS solver
        std::string LinNSCondFile(argv[argc-1]);
        LinNSCondFile += "_LinNSCond.xml";
        std::vector<std::string> LinNSFilenames;
        LinNSFilenames.push_back(meshfile);
        LinNSFilenames.push_back(LinNSCondFile);

        // Create Linearised NS stability session reader.
        LinNSsession = LibUtilities::SessionReader::CreateInstance(argc, argv, LinNSFilenames);
        // Create driver
        LinNSsession->LoadSolverInfo("Driver", vDriverModule, "ModifiedArnoldi");
        LinNSdrv = GetDriverFactory().CreateInstance(vDriverModule, LinNSsession);
        /// Do linearised NavierStokes Session  with Modified Arnoldi
        LinNSdrv->Execute();

        // Calculate Non-linear wave terms
        CalcNonLinearForce(LinNSdrv->GetEqu()[0]);

        // Finalise communications
        IncNSsession->Finalise();
        AdvDiffsession->Finalise();
        LinNSsession->Finalise();

    }
    catch (const std::runtime_error& e)
    {
        return 1;
    }
    catch (const std::string& eStr)
    {
        cout << "Error: " << eStr << endl;
    }
}

void CalcNonLinearForce(EquationSystemSharedPtr &eqn)
{
    Array<OneD, MultiRegions::ExpListSharedPtr> fields = eqn->UpdateFields();
    MultiRegions::ExpListSharedPtr pres = eqn->GetPressure();

    int npts    = fields[0]->GetPlane(0)->GetNpoints();
    int ncoeffs = fields[0]->GetPlane(0)->GetNcoeffs();
    Array<OneD, NekDouble> val(npts), der1(2*npts);
    Array<OneD, NekDouble> der2 = der1 + npts;
    Array<OneD, Array<OneD, NekDouble> >  outfield(2);

    outfield[0] = Array<OneD, NekDouble> (2*ncoeffs);
    outfield[1] = outfield[0] + ncoeffs;

    // determine inverse of area normalised field.
    pres->GetPlane(0)->BwdTrans(pres->GetPlane(0)->GetCoeffs(),
                                pres->GetPlane(0)->UpdatePhys());
    pres->GetPlane(0)->BwdTrans(pres->GetPlane(1)->GetCoeffs(),
                                pres->GetPlane(1)->UpdatePhys());
    NekDouble norm = eqn->GetPressure()->L2();
    Vmath::Fill(2*npts,1.0,der1,1);
    norm = sqrt(fields[0]->PhysIntegral(der1)/(norm*norm));

    // Get hold of arrays.
    fields[0]->GetPlane(0)->BwdTrans(fields[0]->GetPlane(0)->GetCoeffs(),fields[0]->GetPlane(0)->UpdatePhys());
    Array<OneD, NekDouble> u_real = fields[0]->GetPlane(0)->UpdatePhys();
    Vmath::Smul(npts,norm,u_real,1,u_real,1);
    fields[0]->GetPlane(1)->BwdTrans(fields[0]->GetPlane(1)->GetCoeffs(),fields[0]->GetPlane(1)->UpdatePhys());
    Array<OneD, NekDouble> u_imag = fields[0]->GetPlane(1)->UpdatePhys();
    Vmath::Smul(npts,norm,u_imag,1,u_imag,1);
    fields[1]->GetPlane(0)->BwdTrans(fields[1]->GetPlane(0)->GetCoeffs(),fields[1]->GetPlane(0)->UpdatePhys());
    Array<OneD, NekDouble> v_real = fields[1]->GetPlane(0)->UpdatePhys();
    Vmath::Smul(npts,norm,v_real,1,v_real,1);
    fields[1]->GetPlane(1)->BwdTrans(fields[1]->GetPlane(1)->GetCoeffs(),fields[1]->GetPlane(1)->UpdatePhys());
    Array<OneD, NekDouble> v_imag = fields[1]->GetPlane(1)->UpdatePhys();
    Vmath::Smul(npts,norm,v_imag,1,v_imag,1);

    // Calculate non-linear terms for x and y directions
    // d/dx(u u* + u* u)
    Vmath::Vmul (npts,u_real,1,u_real,1,val,1);
    Vmath::Vvtvp(npts,u_imag,1,u_imag,1,val,1,val,1);
    Vmath::Smul (npts,2.0,val,1,val,1);
    fields[0]->GetPlane(0)->PhysDeriv(0,val,der1);

    // d/dy(v u* + v* u)
    Vmath::Vmul (npts,u_real,1,v_real,1,val,1);
    Vmath::Vvtvp(npts,u_imag,1,v_imag,1,val,1,val,1);
    Vmath::Smul (npts,2.0,val,1,val,1);
    fields[0]->GetPlane(0)->PhysDeriv(1,val,der2);

    Vmath::Vadd(npts,der1,1,der2,1,der1,1);

    fields[0]->GetPlane(0)->FwdTrans_IterPerExp(der1,outfield[0]);
    Vmath::Neg(ncoeffs,outfield[0],1);

    // d/dx(u v* + u* v)
    fields[0]->GetPlane(0)->PhysDeriv(0,val,der1);

    // d/dy(v v* + v* v)
    Vmath::Vmul(npts,v_real,1,v_real,1,val,1);
    Vmath::Vvtvp(npts,v_imag,1,v_imag,1,val,1,val,1);
    Vmath::Smul (npts,2.0,val,1,val,1);
    fields[0]->GetPlane(0)->PhysDeriv(1,val,der2);

    fields[0]->GetPlane(0)->FwdTrans_IterPerExp(der1,outfield[1]);
    Vmath::Neg(ncoeffs,outfield[1],1);

    // Symmetrise forcing
    //-> Get coordinates
    Array<OneD, NekDouble> coord(2);
    Array<OneD, NekDouble> coord_x(npts);
    Array<OneD, NekDouble> coord_y(npts);

    //-> Impose symmetry (x -> -x + Lx/2, y-> -y) on coordinates
    fields[0]->GetPlane(0)->GetCoords(coord_x,coord_y);
    NekDouble xmax = Vmath::Vmax(npts,coord_x,1);
    Vmath::Neg(npts,coord_x,1);
    Vmath::Sadd(npts,xmax,coord_x,1,coord_x,1);
    Vmath::Neg(npts,coord_y,1);

    int i, physoffset;

    //-> Obtain list of expansion element ids for each point.
    Array<OneD, int> Eid(npts);
    // This search may not be necessary every iteration
    for(i = 0; i < npts; ++i)
    {
        coord[0] = coord_x[i];
        coord[1] = coord_y[i];

        // Note this will not quite be symmetric.
        Eid[i] = fields[0]->GetPlane(0)->GetExpIndex(coord,1e-6);
    }

    // Interpolate field 0
    fields[0]->GetPlane(0)->BwdTrans_IterPerExp(outfield[0],der1);
    for(i = 0; i < npts; ++i)
    {
        physoffset = fields[0]->GetPlane(0)->GetPhys_Offset(Eid[i]);
        coord[0] = coord_x[i];
        coord[1] = coord_y[i];
        der2[i] = fields[0]->GetPlane(0)->GetExp(Eid[i])->PhysEvaluate(coord,
                                                          der1 + physoffset);
    }
    //-> Average field 0
    Vmath::Vsub(npts,der1,1,der2,1,der2,1);
    Vmath::Smul(npts,0.5,der2,1,der2,1);
    fields[0]->GetPlane(0)->FwdTrans_IterPerExp(der2, outfield[0]);

    //-> Interpoloate field 1
    fields[0]->GetPlane(0)->BwdTrans_IterPerExp(outfield[1],der1);
    for(i = 0; i < npts; ++i)
    {
        physoffset = fields[0]->GetPlane(0)->GetPhys_Offset(Eid[i]);
        coord[0] = coord_x[i];
        coord[1] = coord_y[i];
        der2[i] = fields[0]->GetPlane(0)->GetExp(Eid[i])->PhysEvaluate(coord,
                                                         der1 + physoffset);
    }

    //-> Average field 1
    Vmath::Vsub(npts,der1,1,der2,1,der2,1);
    Vmath::Smul(npts,0.5,der2,1,der2,1);
    fields[0]->GetPlane(0)->FwdTrans_IterPerExp(der2, outfield[1]);

    // dump output
    Array<OneD, std::string> variables(2);
    variables[0] = "u";   variables[1] = "v";

    std::string outname = eqn->GetSessionName().substr(0,eqn->GetSessionName().find_last_of('.')) + ".vwi";

    eqn->WriteFld(outname, fields[0]->GetPlane(0), outfield, variables);
}
<|endoftext|>


<commit_before>#include <FAST/Algorithms/HounsefieldConverter/HounsefieldConverter.hpp>
#include "FAST/Algorithms/TubeSegmentationAndCenterlineExtraction/TubeSegmentationAndCenterlineExtraction.hpp"
#include "FAST/Importers/ImageFileImporter.hpp"
#include "FAST/Visualization/SliceRenderer/SliceRenderer.hpp"
#include "FAST/Visualization/LineRenderer/LineRenderer.hpp"
#include "FAST/Algorithms/SurfaceExtraction/SurfaceExtraction.hpp"
#include "FAST/Visualization/TriangleRenderer/TriangleRenderer.hpp"
#include "FAST/Visualization/SimpleWindow.hpp"
#include <FAST/Tools/CommandLineParser.cpp>

using namespace fast;

int main(int argc, char** argv) {
    CommandLineParser parser("Liver vessel segmentation");
    parser.addPositionVariable(1, "filename", true, "Path to CT file");
    parser.parse(argc, argv);

    auto importer = ImageFileImporter::create(parser.get("filename"));

    auto converter = HounsefieldConverter::create()->connect(importer);

    auto tubeExtraction = TubeSegmentationAndCenterlineExtraction::create()->connect(converter);

    // Parameters
    tubeExtraction->extractBrightTubes();
    tubeExtraction->setMinimumRadius(1);
    tubeExtraction->setMaximumRadius(25);
    tubeExtraction->setRadiusStep(0.5);
    tubeExtraction->setSensitivity(0.95);
    tubeExtraction->setMinimumIntensity(100);
    tubeExtraction->setMaximumIntensity(200);
    tubeExtraction->setMinimumTreeSize(500);
    tubeExtraction->setKeepLargestTree(true);
    tubeExtraction->enableAutomaticCropping();

    auto renderer = SliceRenderer::create(PLANE_Z)->connect(importer);

    auto lineRenderer = LineRenderer::create(Color::Blue(), true)
        ->connect(tubeExtraction, 1);

    auto surfaceExtraction = SurfaceExtraction::create()
        ->connect(tubeExtraction);

    auto triangleRenderer = TriangleRenderer::create()->connect(surfaceExtraction);

    auto window = SimpleWindow3D::create()->connect({
        renderer,
        triangleRenderer,
        lineRenderer
	});
    window->run();
}<commit_msg>fixed typo in liver vessel segmentation example<commit_after>#include <FAST/Algorithms/HounsefieldConverter/HounsefieldConverter.hpp>
#include "FAST/Algorithms/TubeSegmentationAndCenterlineExtraction/TubeSegmentationAndCenterlineExtraction.hpp"
#include "FAST/Importers/ImageFileImporter.hpp"
#include "FAST/Visualization/SliceRenderer/SliceRenderer.hpp"
#include "FAST/Visualization/LineRenderer/LineRenderer.hpp"
#include "FAST/Algorithms/SurfaceExtraction/SurfaceExtraction.hpp"
#include "FAST/Visualization/TriangleRenderer/TriangleRenderer.hpp"
#include "FAST/Visualization/SimpleWindow.hpp"
#include <FAST/Tools/CommandLineParser.hpp>

using namespace fast;

int main(int argc, char** argv) {
    CommandLineParser parser("Liver vessel segmentation");
    parser.addPositionVariable(1, "filename", true, "Path to CT file");
    parser.parse(argc, argv);

    auto importer = ImageFileImporter::create(parser.get("filename"));

    auto converter = HounsefieldConverter::create()->connect(importer);

    auto tubeExtraction = TubeSegmentationAndCenterlineExtraction::create()->connect(converter);

    // Parameters
    tubeExtraction->extractBrightTubes();
    tubeExtraction->setMinimumRadius(1);
    tubeExtraction->setMaximumRadius(25);
    tubeExtraction->setRadiusStep(0.5);
    tubeExtraction->setSensitivity(0.95);
    tubeExtraction->setMinimumIntensity(100);
    tubeExtraction->setMaximumIntensity(200);
    tubeExtraction->setMinimumTreeSize(500);
    tubeExtraction->setKeepLargestTree(true);
    tubeExtraction->enableAutomaticCropping();

    auto renderer = SliceRenderer::create(PLANE_Z)->connect(importer);

    auto lineRenderer = LineRenderer::create(Color::Blue(), true)
        ->connect(tubeExtraction, 1);

    auto surfaceExtraction = SurfaceExtraction::create()
        ->connect(tubeExtraction);

    auto triangleRenderer = TriangleRenderer::create()->connect(surfaceExtraction);

    auto window = SimpleWindow3D::create()->connect({
        renderer,
        triangleRenderer,
        lineRenderer
	});
    window->run();
}
<|endoftext|>


<commit_before>// #include <vector>
#include <iostream>
#include <cmath>
#include <fstream>

#include <CGAL/Nef_polyhedron_3.h>
#include <CGAL/Aff_transformation_3.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Mesh_triangulation_3.h>
#include <CGAL/Mesh_complex_3_in_triangulation_3.h>
#include <CGAL/Mesh_criteria_3.h>
#include <CGAL/Mesh_polyhedron_3.h>
#include <CGAL/Polyhedral_mesh_domain_with_features_3.h>
#include <CGAL/Triangulation_vertex_base_with_info_3.h>
#include <CGAL/Triangulation_cell_base_with_info_3.h>
#include <CGAL/make_mesh_3.h>
#include <CGAL/Cartesian_converter.h>

#include <dolfin/common/MPI.h>
#include <dolfin/log/log.h>
#include <dolfin/mesh/Mesh.h>
#include <dolfin/mesh/MeshEditor.h>
#include <dolfin/mesh/MeshPartitioning.h>

#include <dolfin/plot/plot.h>

#define HAS_CGAL

#include <dolfin/generation/CGALMeshBuilder.h>

#include "cgal_triangulate_polyhedron.h"
#include "cgal_copy_polygon_to.h"
#include "cgal_csg3d.h"

#include <dolfin.h>
#include "model.h"

using namespace dolfin;

typedef CGAL::Simple_cartesian<double> IK;
typedef CGAL::Cartesian_converter<IK,csg::Exact_Kernel> IK_to_EK;

void build_mesh(const csg::C3t3& c3t3, Mesh& mesh)
{
  typedef csg::C3t3 C3T3;
  typedef C3T3::Triangulation Triangulation;
  typedef Triangulation::Vertex_handle Vertex_handle;

  // CGAL triangulation
  const Triangulation& triangulation = c3t3.triangulation();

  // Clear mesh
  mesh.clear();

  // Count cells in complex
  std::size_t num_cells = 0;
  for(csg::C3t3::Cells_in_complex_iterator cit = c3t3.cells_in_complex_begin();
      cit != c3t3.cells_in_complex_end();
      ++cit)
  {
    num_cells++;
  }

  // Create and initialize mesh editor
  dolfin::MeshEditor mesh_editor;
  mesh_editor.open(mesh, 3, 3);
  mesh_editor.init_vertices(triangulation.number_of_vertices());
  mesh_editor.init_cells(num_cells);

  // Add vertices to mesh
  std::size_t vertex_index = 0;
  std::map<Vertex_handle, std::size_t> vertex_id_map;

  for (Triangulation::Finite_vertices_iterator
         cgal_vertex = triangulation.finite_vertices_begin();
       cgal_vertex != triangulation.finite_vertices_end(); ++cgal_vertex)
  {
    vertex_id_map[cgal_vertex] = vertex_index;

      // Get vertex coordinates and add vertex to the mesh
    Point p(cgal_vertex->point()[0], cgal_vertex->point()[1], cgal_vertex->point()[2]);
    mesh_editor.add_vertex(vertex_index, p);

    ++vertex_index;
  }

  // Add cells to mesh
  std::size_t cell_index = 0;
  for(csg::C3t3::Cells_in_complex_iterator cit = c3t3.cells_in_complex_begin();
      cit != c3t3.cells_in_complex_end();
      ++cit)
  {
    mesh_editor.add_cell(cell_index,
                         vertex_id_map[cit->vertex(0)],
                         vertex_id_map[cit->vertex(1)],
                         vertex_id_map[cit->vertex(2)],
                         vertex_id_map[cit->vertex(3)]);

    ++cell_index;
  }

  // Close mesh editor
  mesh_editor.close();
}

void generate(Mesh& mesh, const csg::Polyhedron_3& p, double cell_size) {
  dolfin_assert(p.is_pure_triangle());
  csg::Mesh_domain domain(p);
  domain.detect_features();
  csg::Mesh_criteria criteria(CGAL::parameters::facet_angle = 25,
			      CGAL::parameters::facet_size = cell_size,
			      CGAL::parameters::cell_radius_edge_ratio = 3.0,
			      CGAL::parameters::edge_size = cell_size);

  std::cout << "Generating mesh" << std::endl;
  csg::C3t3 c3t3 = CGAL::make_mesh_3<csg::C3t3>(domain, criteria,
                                                CGAL::parameters::no_perturb(),
                                                CGAL::parameters::no_exude());
  // optimize mesh
  std::cout << "Optimizing mesh by odt optimization" << std::endl;
  odt_optimize_mesh_3(c3t3, domain);
  std::cout << "Optimizing mesh by lloyd optimization" << std::endl;
  lloyd_optimize_mesh_3(c3t3, domain);
  // This is too slow. Is it really needed?
  // std::cout << "Optimizing mesh by perturbation" << std::endl;
  // CGAL::perturb_mesh_3(c3t3, domain);
  std::cout << "Optimizing mesh by sliver exudation" << std::endl;
  exude_mesh_3(c3t3);

  std::fstream out;
  out.open("~/mesh.txt");
  out << c3t3;
  out.close();

  build_mesh(c3t3, mesh);
}

// The transformation first scales the object by the vector (a, b, c),
// then rotates it by the quaternion (x, y, z, w) and then shifts it
// by the vector (t, u, v).
template<class K>
CGAL::Aff_transformation_3<K> trans(double a, double b, double c,
				    double x, double y, double z, double w,
				    double t, double u, double v)
{
  double S = std::sin(w);
  double C = std::cos(w);
  // Scaling
  CGAL::Aff_transformation_3<K> scal(a, 0, 0, 0, b, 0, 0, 0, c);

  // Rotation
  CGAL::Aff_transformation_3<K>
    rot(C + x*x*(1-C), x*y*(1-C) - z*S, x*z*(1-C) + y*S,
      y*x*(1-C) + z*S, C + y*y*(1-C), y*z*(1-C) - x*S,
      z*x*(1-C) - y*S, z*y*(1-C) + x*S, C + z*z*(1-C));

  // Translation
  CGAL::Aff_transformation_3<csg::Exact_Kernel>
    trans(1, 0, 0, t, 0, 1, 0, u, 0, 0, 1, v);

  return trans * rot * scal;
}

typedef CGAL::Aff_transformation_3<csg::Exact_Kernel> Aff_trans_3;

// Test if Point p is on the boundary of the cube which is the
// standard (-1, -1, -1) -- (1, 1, 1) cube transformed by the
// transformation t, within a precision of eps
bool is_on_boundary(const csg::Exact_Point_3& p, const Aff_trans_3& t,
		    double eps = 10000)
{
  csg::Exact_Point_3 q = t.inverse()(p);
  // Test if point is inside of a cube that is a bit larger
  if(!((CGAL::abs(q.x()) <= 1 + eps) &&
       (CGAL::abs(q.y()) <= 1 + eps) &&
       (CGAL::abs(q.z()) <= 1 + eps)))
    return false;
  // Test if point is outside of a cube that is a bit smaller
  if(!((CGAL::abs(q.x()) >= 1 - eps) &&
       (CGAL::abs(q.y()) >= 1 - eps) &&
       (CGAL::abs(q.z()) >= 1 - eps)))
    return false;
  return true;
}

struct CubeDomain : public SubDomain
{
  Aff_trans_3 trans;
  CubeDomain(const Aff_trans_3& t) : trans(t) {}
  bool inside(const Array<double>& x, bool on_boundary) const
  {
    return is_on_boundary(csg::Exact_Point_3(x[0], x[1], x[2]), trans)
      && on_boundary;
  }
};

// Evaluate the transformation from the boundary of one cube to the
// boundary of a transformed cube.
struct CubeToCube : public Expression
{
  Aff_trans_3 first_cube;
  Aff_trans_3 second_cube;
  CubeToCube (const Aff_trans_3& a, const Aff_trans_3& b)
    : Expression(3), first_cube(a), second_cube(b) {}
  void eval(Array<double>& values, const Array<double>& x) const
  {
    IK_to_EK to_exact;
    csg::Exact_Point_3 p(to_exact(x[0]), to_exact(x[1]), to_exact(x[2]));
    (second_cube * first_cube.inverse())(p);
    values[0] = CGAL::to_double(p[0]);
    values[1] = CGAL::to_double(p[1]);
    values[2] = CGAL::to_double(p[2]);
  }
};

int main() {
  std::string off_file = "../cube.off";
  csg::Exact_Polyhedron_3 cube; // unit cube
  std::cout << "reading file " << off_file << std::endl;
  std::ifstream file(off_file.c_str());
  file >> cube;
  std::cout << "done reading file." << std::endl;
  double cell_size = 0.5;
  bool detect_sharp_features = true;
  Mesh m;

  csg::Exact_Polyhedron_3 outer(cube);

  // scale the outer box
  CGAL::Aff_transformation_3<csg::Exact_Kernel>
    St(4, 0, 0, 0, 0, 3, 0, 0, 0, 0, 2.5, 0);
  std::transform(outer.points_begin(), outer.points_end(),
  		 outer.points_begin(), St);

  // scale the inner box
  CGAL::Aff_transformation_3<csg::Exact_Kernel>
    Et(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0);
  csg::Nef_polyhedron_3 Omega(outer);
  csg::Exact_Polyhedron_3 first_inner(cube);
  // csg::Exact_Polyhedron_3 second_inner(cube);
  // second_inner = transformed(second_inner, 0, 0, 1, 0.1, 1.5, 0, 0);

  Omega -= first_inner;
  // Omega -= second_inner;

  csg::Exact_Polyhedron_3 p;
  Omega.convert_to_polyhedron(p);
  csg::Polyhedron_3 q;
  copy_to(p, q);

  generate(m, q, cell_size);

  plot(m, "mesh of a cube");
  interactive(true);

  std::cout << "Solving the variational problem" << std::endl;
  model::FunctionSpace V(m);

  CubeDomain first_inner_domain(Et);
  CubeToCube c2c(Et, Et);
  CubeDomain outer_domain(St);
  CubeToCube o2o(St, St);

  // Create Dirichlet boundary conditions
  DirichletBC bci(V, c2c, first_inner_domain);
  DirichletBC bco(V, o2o, outer_domain);
  std::vector<const DirichletBC*> bcs;
  bcs.push_back(&bci);
  bcs.push_back(&bco);

  // Define source and boundary traction functions
  Constant B(0.0, -0.5, 0.0);
  Constant T(0.1,  0.0, 0.0);

  // Define solution function
  Function u(V);

  // Set material parameters
  const double E  = 10.0;
  const double nu = 0.3;
  Constant mu(E/(2*(1 + nu)));
  Constant lambda(E*nu/((1 + nu)*(1 - 2*nu)));

  // Create (linear) form defining (nonlinear) variational problem
  model::ResidualForm F(V);
  F.mu = mu; F.lmbda = lambda; F.B = B; F.T = T; F.u = u;

  // Create jacobian dF = F' (for use in nonlinear solver).
  model::JacobianForm J(V, V);
  J.mu = mu; J.lmbda = lambda; J.u = u;

  // Solve nonlinear variational problem F(u; v) = 0
  solve(F == 0, u, bcs, J);

  // Plot solution
  plot(u);
  interactive();

  std::getchar();
}
<commit_msg>fixed meshing<commit_after>// #include <vector>
#include <iostream>
#include <cmath>
#include <fstream>

#include <CGAL/Nef_polyhedron_3.h>
#include <CGAL/Aff_transformation_3.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Mesh_triangulation_3.h>
#include <CGAL/Mesh_complex_3_in_triangulation_3.h>
#include <CGAL/Mesh_criteria_3.h>
#include <CGAL/Mesh_polyhedron_3.h>
#include <CGAL/Polyhedral_mesh_domain_with_features_3.h>
#include <CGAL/Triangulation_vertex_base_with_info_3.h>
#include <CGAL/Triangulation_cell_base_with_info_3.h>
#include <CGAL/make_mesh_3.h>
#include <CGAL/Cartesian_converter.h>

#include <dolfin/common/MPI.h>
#include <dolfin/log/log.h>
#include <dolfin/mesh/Mesh.h>
#include <dolfin/mesh/MeshEditor.h>
#include <dolfin/mesh/MeshPartitioning.h>

#include <dolfin/plot/plot.h>

#define HAS_CGAL

#include <dolfin/generation/CGALMeshBuilder.h>

#include "cgal_triangulate_polyhedron.h"
#include "cgal_copy_polygon_to.h"
#include "cgal_csg3d.h"

#include <dolfin.h>
#include "model.h"

using namespace dolfin;

typedef CGAL::Simple_cartesian<double> IK;
typedef CGAL::Cartesian_converter<IK,csg::Exact_Kernel> IK_to_EK;

void build_mesh(const csg::C3t3& c3t3, Mesh& mesh)
{
  typedef csg::C3t3 C3T3;
  typedef C3T3::Triangulation Triangulation;
  typedef Triangulation::Vertex_handle Vertex_handle;

  // CGAL triangulation
  const Triangulation& triangulation = c3t3.triangulation();

  // Clear mesh
  mesh.clear();

  // Count cells in complex
  std::size_t num_cells = 0;
  for(csg::C3t3::Cells_in_complex_iterator cit = c3t3.cells_in_complex_begin();
      cit != c3t3.cells_in_complex_end();
      ++cit)
  {
    num_cells++;
  }

  // Create and initialize mesh editor
  dolfin::MeshEditor mesh_editor;
  mesh_editor.open(mesh, 3, 3);
  mesh_editor.init_vertices(triangulation.number_of_vertices());
  mesh_editor.init_cells(num_cells);

  // Add vertices to mesh
  std::size_t vertex_index = 0;
  std::map<Vertex_handle, std::size_t> vertex_id_map;

  for (Triangulation::Finite_vertices_iterator
         cgal_vertex = triangulation.finite_vertices_begin();
       cgal_vertex != triangulation.finite_vertices_end(); ++cgal_vertex)
  {
    vertex_id_map[cgal_vertex] = vertex_index;

      // Get vertex coordinates and add vertex to the mesh
    Point p(cgal_vertex->point()[0], cgal_vertex->point()[1], cgal_vertex->point()[2]);
    mesh_editor.add_vertex(vertex_index, p);

    ++vertex_index;
  }

  // Add cells to mesh
  std::size_t cell_index = 0;
  for(csg::C3t3::Cells_in_complex_iterator cit = c3t3.cells_in_complex_begin();
      cit != c3t3.cells_in_complex_end();
      ++cit)
  {
    mesh_editor.add_cell(cell_index,
                         vertex_id_map[cit->vertex(0)],
                         vertex_id_map[cit->vertex(1)],
                         vertex_id_map[cit->vertex(2)],
                         vertex_id_map[cit->vertex(3)]);

    ++cell_index;
  }

  // Close mesh editor
  mesh_editor.close();
}

void generate(Mesh& mesh, const csg::Polyhedron_3& p, double cell_size) {
  dolfin_assert(p.is_pure_triangle());
  csg::Mesh_domain domain(p);
  domain.detect_features();
  csg::Mesh_criteria criteria(CGAL::parameters::facet_angle = 25,
			      CGAL::parameters::facet_size = cell_size,
			      CGAL::parameters::cell_radius_edge_ratio = 3.0,
			      CGAL::parameters::edge_size = cell_size);

  std::cout << "Generating mesh" << std::endl;
  csg::C3t3 c3t3 = CGAL::make_mesh_3<csg::C3t3>(domain, criteria,
                                                CGAL::parameters::no_perturb(),
                                                CGAL::parameters::no_exude());
  // optimize mesh
  // std::cout << "Optimizing mesh by odt optimization" << std::endl;
  // odt_optimize_mesh_3(c3t3, domain);
  // std::cout << "Optimizing mesh by lloyd optimization" << std::endl;
  // lloyd_optimize_mesh_3(c3t3, domain);
  // This is too slow. Is it really needed?
  // std::cout << "Optimizing mesh by perturbation" << std::endl;
  // CGAL::perturb_mesh_3(c3t3, domain);
  // std::cout << "Optimizing mesh by sliver exudation" << std::endl;
  // exude_mesh_3(c3t3);

  std::fstream out;
  out.open("~/mesh.txt", std::ios::out);
  out << c3t3;
  out.close();

  build_mesh(c3t3, mesh);
}

// The transformation first scales the object by the vector (a, b, c),
// then rotates it by the quaternion (x, y, z, w) and then shifts it
// by the vector (t, u, v).
template<class K>
CGAL::Aff_transformation_3<K> trans(double a, double b, double c,
				    double x, double y, double z, double w,
				    double t, double u, double v)
{
  double S = std::sin(w);
  double C = std::cos(w);
  // Scaling
  CGAL::Aff_transformation_3<K> scal(a, 0, 0, 0, b, 0, 0, 0, c);

  // Rotation
  CGAL::Aff_transformation_3<K>
    rot(C + x*x*(1-C), x*y*(1-C) - z*S, x*z*(1-C) + y*S,
      y*x*(1-C) + z*S, C + y*y*(1-C), y*z*(1-C) - x*S,
      z*x*(1-C) - y*S, z*y*(1-C) + x*S, C + z*z*(1-C));

  // Translation
  CGAL::Aff_transformation_3<csg::Exact_Kernel>
    trans(1, 0, 0, t, 0, 1, 0, u, 0, 0, 1, v);

  return trans * rot * scal;
}

typedef CGAL::Aff_transformation_3<csg::Exact_Kernel> Aff_trans_3;

// Test if Point p is on the boundary of the cube which is the
// standard (-1, -1, -1) -- (1, 1, 1) cube transformed by the
// transformation t, within a precision of eps
bool is_on_boundary(const csg::Exact_Point_3& p, const Aff_trans_3& t,
		    double eps = 1e-7)
{
  csg::Exact_Point_3 q = t.inverse()(p);
  // Test if point is inside of a cube that is a bit larger
  if(!((CGAL::abs(q.x()) <= 1 + eps) &&
       (CGAL::abs(q.y()) <= 1 + eps) &&
       (CGAL::abs(q.z()) <= 1 + eps)))
    return false;
  // Test if point is not inside of a cube that is a bit smaller
  if((CGAL::abs(q.x()) <= 1 - eps) &&
     (CGAL::abs(q.y()) <= 1 - eps) &&
     (CGAL::abs(q.z()) <= 1 - eps))
    return false;
  return true;
}

struct CubeDomain : public SubDomain
{
  Aff_trans_3 trans;
  std::string debug;
  CubeDomain(const Aff_trans_3& t, std::string d)
    : trans(t), debug(d) {}
  bool inside(const Array<double>& x, bool on_boundary) const
  {
    std::cout << x[0] << " " << x[1] << " " << x[2];
    bool b = is_on_boundary(csg::Exact_Point_3(x[0], x[1], x[2]), trans);
    std::cout << debug << " " << b << on_boundary << std::endl;
    return b && on_boundary;
  }
};

// Evaluate the transformation from the boundary of one cube to the
// boundary of a transformed cube.
struct CubeToCube : public Expression
{
  Aff_trans_3 first_cube;
  Aff_trans_3 second_cube;
  CubeToCube (const Aff_trans_3& a, const Aff_trans_3& b)
    : Expression(3), first_cube(a), second_cube(b) {}
  void eval(Array<double>& values, const Array<double>& x) const
  {
    IK_to_EK to_exact;
    csg::Exact_Point_3 p(to_exact(x[0]), to_exact(x[1]), to_exact(x[2]));
    (second_cube * first_cube.inverse())(p);
    values[0] = CGAL::to_double(p[0]);
    values[1] = CGAL::to_double(p[1]);
    values[2] = CGAL::to_double(p[2]);
  }
};

int main() {
  std::string off_file = "../cube.off";
  csg::Exact_Polyhedron_3 cube; // unit cube
  std::cout << "reading file " << off_file << std::endl;
  std::ifstream file(off_file.c_str());
  file >> cube;
  std::cout << "done reading file." << std::endl;
  double cell_size = 1.0;
  bool detect_sharp_features = true;
  Mesh m;

  csg::Exact_Polyhedron_3 outer(cube);

  // scale the outer box
  CGAL::Aff_transformation_3<csg::Exact_Kernel>
    St(4, 0, 0, 0, 0, 3, 0, 0, 0, 0, 2.5, 0);
  std::transform(outer.points_begin(), outer.points_end(),
  		 outer.points_begin(), St);

  // scale the inner box
  CGAL::Aff_transformation_3<csg::Exact_Kernel>
    Et(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0);
  csg::Nef_polyhedron_3 Omega(outer);
  csg::Exact_Polyhedron_3 first_inner(cube);
  // csg::Exact_Polyhedron_3 second_inner(cube);
  // second_inner = transformed(second_inner, 0, 0, 1, 0.1, 1.5, 0, 0);

  csg::Exact_Point_3 Q(1, 1, 1);
  std::cout << "test: " << is_on_boundary(Q, Et) << std::endl;

  Omega -= first_inner;
  // Omega -= second_inner;

  csg::Exact_Polyhedron_3 p;
  Omega.convert_to_polyhedron(p);
  csg::Polyhedron_3 q;
  copy_to(p, q);

  generate(m, q, cell_size);

  plot(m, "mesh of a cube");
  interactive(true);

  std::cout << "Solving the variational problem" << std::endl;
  model::FunctionSpace V(m);

  CubeDomain first_inner_domain(Et, "inner");
  CubeToCube c2c(Et, Et);
  CubeDomain outer_domain(St, "outer");
  CubeToCube o2o(St, St);

  // Create Dirichlet boundary conditions
  DirichletBC bci(V, c2c, first_inner_domain);
  DirichletBC bco(V, o2o, outer_domain);
  std::vector<const DirichletBC*> bcs;
  bcs.push_back(&bci);
  bcs.push_back(&bco);

  // Define source and boundary traction functions
  Constant B(0.0, -0.5, 0.0);
  Constant T(0.1,  0.0, 0.0);

  // Define solution function
  Function u(V);

  // Set material parameters
  const double E  = 10.0;
  const double nu = 0.3;
  Constant mu(E/(2*(1 + nu)));
  Constant lambda(E*nu/((1 + nu)*(1 - 2*nu)));

  // Create (linear) form defining (nonlinear) variational problem
  model::ResidualForm F(V);
  F.mu = mu; F.lmbda = lambda; F.B = B; F.T = T; F.u = u;

  // Create jacobian dF = F' (for use in nonlinear solver).
  model::JacobianForm J(V, V);
  J.mu = mu; J.lmbda = lambda; J.u = u;

  // Solve nonlinear variational problem F(u; v) = 0
  solve(F == 0, u, bcs, J);

  // Plot solution
  plot(u);
  interactive();

  std::getchar();
}
<|endoftext|>


<commit_before>// =============================================================================
// PROJECT CHRONO - http://projectchrono.org
//
// Copyright (c) 2014 projectchrono.org
// All right reserved.
//
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file at the top level of the distribution and at
// http://projectchrono.org/license-chrono.txt.
//
// =============================================================================
// Authors: Justin Madsen
// =============================================================================
//
// Suspension testing mechanism, using force or motion inputs to the locked wheels
//  to simulate the effect of a post-testing mechanism
//
// The Irrlicht interface used to observe the suspension test, and also to provide
// any steering inputs.
//
// The vehicle reference frame has Z up, X towards the front of the vehicle, and
// Y pointing to the left.
//
// =============================================================================

#include <vector>

#include "core/ChFileutils.h"
#include "core/ChStream.h"
#include "core/ChRealtimeStep.h"
#include "physics/ChSystem.h"
#include "physics/ChLinkDistance.h"

#include "chrono_vehicle/ChVehicleModelData.h"

#include "chrono_utils/ChUtilsInputOutput.h"

// subsystems, all read in fron JSON files
#include "ModelDefs.h"

#include "chrono_vehicle/suspensionTest/SuspensionTest.h"
#include "chrono_vehicle/tire/RigidTire.h"
#include "chrono_vehicle/terrain/FlatTerrain.h"
#include "chrono_vehicle/driver/ChDataDriver.h"

// Irrlicht includes
#if IRRLICHT_ENABLED
# include "unit_IRRLICHT/ChIrrApp.h"
# include "chrono_vehicle/driver/ChIrrGuiST.h"
# define USE_IRRLICHT
#endif

// DEBUGGING:  Uncomment the following line to print shock data
//#define DEBUG_LOG
#define DEBUG_ACTUATOR    // debug actuator in SuspensionTest
using namespace chrono;

// =============================================================================
// USER SETTINGS
// =============================================================================
double steer_limit = 0.6;
double post_limit = 0.2;

// Simulation step size
double step_size = 0.001;
double render_step_size = 1.0 / 50;   // Time interval between two render frames
double output_step_size = 1.0 / 1;    // Time interval between two output frames

#ifdef USE_IRRLICHT
  // Point on chassis tracked by the camera
  ChVector<> trackPoint(1.65, 0.0, 0);
  double camera_chase = 0;
  double camera_height = 2.0;
#else
  double tend = 20.0;
  const std::string out_dir = "../HMMWV";
  const std::string pov_dir = out_dir + "/POVRAY";
#endif

// =============================================================================
// JSON file for suspension
// std::string suspensionTest_file = vehicle::GetDataFile("hmmwv/suspensionTest/HMMWV_ST_front.json");
std::string suspensionTest_file = vehicle::GetDataFile("hmmwv/suspensionTest/HMMWV_ST_rear.json");

// JSON files for tire models (rigid) and powertrain (simple)
std::string rigidtire_file = vehicle::GetDataFile("hmmwv/tire/HMMWV_RigidTire.json");

// Driver input file (if not using Irrlicht)
std::string driver_file = vehicle::GetDataFile("generic/driver/Sample_Maneuver.txt");

// radius of wheel + vertical distance between spindle and chassis center marker
ChVector<> initLoc(0, 0, 0.496);
ChQuaternion<> initRot(1, 0, 0, 0);

// =============================================================================
int main(int argc, char* argv[])
{
  // Create the testing mechanism, initilize ity
  SuspensionTest tester(suspensionTest_file);
  tester.Initialize(ChCoordsys<>(initLoc, initRot));
  // tester.Save_DebugLog(DBG_SPRINGS | DBG_SHOCKS | DBG_CONSTRAINTS | DBG_SUSPENSIONTEST,"log_test_SuspensionTester.csv");
  tester.Save_DebugLog(DBG_SUSPENSIONTEST,"log_test_SuspensionTester.csv");

  // Create and initialize two rigid wheels
  ChSharedPtr<ChTire> tire_front_right;
  ChSharedPtr<ChTire> tire_front_left;

  // flat rigid terrain, height = 0
  FlatTerrain flat_terrain(0);

  // use rigid wheels to actuate suspension
  ChSharedPtr<RigidTire> tire_FL(new RigidTire(rigidtire_file, flat_terrain));
  ChSharedPtr<RigidTire> tire_FR(new RigidTire(rigidtire_file, flat_terrain));

  tire_FL->Initialize(tester.GetWheelBody(FRONT_LEFT));
  tire_FR->Initialize(tester.GetWheelBody(FRONT_RIGHT));

  tire_front_left = tire_FL;
  tire_front_right = tire_FR;

#ifdef USE_IRRLICHT
  irr::ChIrrApp application(&tester,
                            L"HMMWV Suspension test",
                            irr::core::dimension2d<irr::u32>(1000, 800),
                            false,
                            true);

  // make a skybox that has Z pointing up (default .AddTypicalSky()  Y up)
  std::string mtexturedir = GetChronoDataFile("skybox/");
  std::string str_lf = mtexturedir + "sky_lf.jpg";
  std::string str_up = mtexturedir + "sky_up.jpg";
  std::string str_dn = mtexturedir + "sky_dn.jpg";
  irr::video::ITexture* map_skybox_side =
      application.GetVideoDriver()->getTexture(str_lf.c_str());
  irr::scene::ISceneNode* mbox = application.GetSceneManager()->addSkyBoxSceneNode(
      application.GetVideoDriver()->getTexture(str_up.c_str()),
      application.GetVideoDriver()->getTexture(str_dn.c_str()),
      map_skybox_side,
      map_skybox_side,
      map_skybox_side,
      map_skybox_side);
  mbox->setRotation( irr::core::vector3df(90,0,0));

  bool do_shadows = false; // shadow map is experimental
  irr::scene::ILightSceneNode* mlight = 0;

  if (do_shadows) {
    mlight = application.AddLightWithShadow(
      irr::core::vector3df(-5.f, 1.f, 6.f),
      irr::core::vector3df(5.f, -1.f, -2.f),
      250, 60, 80, 15, 512, irr::video::SColorf(1, 1, 1), false, false);
  } else {
    application.AddTypicalLights(
      irr::core::vector3df(30.f, -30.f, 100.f),
      irr::core::vector3df(30.f, 50.f, 100.f),
      250, 130);
  }

  application.SetTimestep(step_size);

  ChIrrGuiST driver(application, tester, trackPoint, camera_chase, camera_height, steer_limit, post_limit);

  // Set the time response for steering keyboard inputs, when they are used
  // NOTE: this is not exact, since not rendered quite at the specified FPS.
  double steering_time = 2.0;  // time to go from 0 to max
  double post_time = 3.0; // time to go from 0 to max applied post motion
  driver.SetSteeringDelta(render_step_size / steering_time * steer_limit);
  driver.SetPostDelta(render_step_size / post_time * post_limit);

  // Set up the assets for rendering
  application.AssetBindAll();
  application.AssetUpdateAll();
  if (do_shadows)
  {
    application.AddShadowAll();
  }
#else
  ChDataDriver driver;
#endif

  // ---------------
  // Simulation loop
#ifdef DEBUG_LOG
  GetLog() << "\n\n============ System Configuration ============\n";
  vehicle.LogHardpointLocations();
#endif

  // Inter-module communication data
  ChTireForces tire_forces(2);
  ChWheelState wheel_states[2];
  double       steering_input;
  double       post_z_L, post_z_R;

  // Number of simulation steps between two 3D view render frames
  int render_steps = (int)std::ceil(render_step_size / step_size);

  // Number of simulation steps between two output frames
  int output_steps = (int)std::ceil(output_step_size / step_size);

  // Initialize simulation frame counter and simulation time
  int step_number = 0;
  double time = 0;

#ifdef USE_IRRLICHT

  ChRealtimeStepTimer realtime_timer;

  while (application.GetDevice()->run())
  {
    // update the position of the shadow mapping so that it follows the car
    if (do_shadows)
    {
      ChVector<> lightaim = tester.GetChassisPos();
      ChVector<> lightpos = tester.GetChassisPos() + ChVector<>(10, 30, 60);
      irr::core::vector3df mlightpos((irr::f32)lightpos.x, (irr::f32)lightpos.y, (irr::f32)lightpos.z);
      irr::core::vector3df mlightaim((irr::f32)lightaim.x, (irr::f32)lightaim.y, (irr::f32)lightaim.z);
      application.GetEffects()->getShadowLight(0).setPosition(mlightpos);
      application.GetEffects()->getShadowLight(0).setTarget(mlightaim);
      mlight->setPosition(mlightpos);
    }

    // Render scene
    if (step_number % render_steps == 0) {
      application.GetVideoDriver()->beginScene(true, true, irr::video::SColor(255, 140, 161, 192));
      driver.DrawAll();
      application.GetVideoDriver()->endScene();
    }

#ifdef DEBUG_LOG
    if (step_number % output_steps == 0) {
      GetLog() << "\n\n============ System Information ============\n";
      GetLog() << "Time = " << time << "\n\n";
      tester.DebugLog(DBG_SPRINGS | DBG_SHOCKS | DBG_CONSTRAINTS);
    }
#endif

#ifdef DEBUG_ACTUATOR
    if (step_number % output_steps == 0) {
      GetLog() << "\n\n============ System Information ============\n";
      GetLog() << "Time = " << time << "\n\n";
      tester.DebugLog(DBG_SPRINGS | DBG_SUSPENSIONTEST);
    }
    if (step_number % render_steps == 0) {
      // write output data
      tester.SaveLog();
    }
#endif

    // Collect output data from modules, here it's the steering and post displacements
    steering_input = driver.GetSteering();
    post_z_L = driver.Get_post_z_L();
    post_z_R = driver.Get_post_z_R();

    tire_forces[FRONT_LEFT.id()] = tire_front_left->GetTireForce();
    tire_forces[FRONT_RIGHT.id()] = tire_front_right->GetTireForce();
    wheel_states[FRONT_LEFT.id()] = tester.GetWheelState(FRONT_LEFT);
    wheel_states[FRONT_RIGHT.id()] = tester.GetWheelState(FRONT_RIGHT);

    // Update modules (process inputs from other modules)
    time = tester.GetChTime();

    driver.Update(time);

    flat_terrain.Update(time);

    tire_front_left->Update(time, wheel_states[FRONT_LEFT.id()]);
    tire_front_right->Update(time, wheel_states[FRONT_RIGHT.id()]);

    tester.Update(time, steering_input, post_z_L, post_z_R, tire_forces);

    // Advance simulation for one timestep for all modules
    double step = realtime_timer.SuggestSimulationStep(step_size);

    driver.Advance(step);

    flat_terrain.Advance(step);

    tire_front_left->Advance(step);
    tire_front_right->Advance(step);

    tester.Advance(step);

    // Increment frame number
    step_number++;
  }

  application.GetDevice()->drop();

#else

  int render_frame = 0;

  if(ChFileutils::MakeDirectory(out_dir.c_str()) < 0) {
    std::cout << "Error creating directory " << out_dir << std::endl;
    return 1;
  }
  if(ChFileutils::MakeDirectory(pov_dir.c_str()) < 0) {
    std::cout << "Error creating directory " << pov_dir << std::endl;
    return 1;
  }

  vehicle.ExportMeshPovray(out_dir);

  char filename[100];

  while (time < tend)
  {
    if (step_number % render_steps == 0) {
      // Output render data
      sprintf(filename, "%s/data_%03d.dat", pov_dir.c_str(), render_frame + 1);
      utils::WriteShapesPovray(&vehicle, filename);
      std::cout << "Output frame:   " << render_frame << std::endl;
      std::cout << "Sim frame:      " << step_number << std::endl;
      std::cout << "Time:           " << time << std::endl;
      std::cout << "             throttle: " << driver.GetThrottle() << " steering: " << driver.GetSteering() << std::endl;
      std::cout << std::endl;
      render_frame++;
    }

#ifdef DEBUG_LOG
    if (step_number % output_steps == 0) {
      GetLog() << "\n\n============ System Information ============\n";
      GetLog() << "Time = " << time << "\n\n";
      vehicle.DebugLog(DBG_SHOCKS);
    }
#endif

    // Collect output data from modules (for inter-module communication)
    steering_input = driver.GetSteering();

    tire_forces[FRONT_LEFT.id()] = tire_front_left->GetTireForce();
    tire_forces[FRONT_RIGHT.id()] = tire_front_right->GetTireForce();

    wheel_states[FRONT_LEFT.id()] = vehicle.GetWheelState(FRONT_LEFT);
    wheel_states[FRONT_RIGHT.id()] = vehicle.GetWheelState(FRONT_RIGHT);

    // Update modules (process inputs from other modules)
    time = vehicle.GetChTime();

    driver.Update(time);

    flat_terrain.Update(time);

    tire_front_left->Update(time, wheel_states[FRONT_LEFT.id()]);
    tire_front_right->Update(time, wheel_states[FRONT_RIGHT.id()]);

    tester.Update(time, steering_input);

    // Advance simulation for one timestep for all modules
    driver.Advance(step_size);

    flat_terrain.Advance(step_size);

    tire_front_right->Advance(step_size);
    tire_front_left->Advance(step_size);

    tester.Advance(step_size);

    // Increment frame number
    step_number++;
  }

#endif

  return 0;
}
<commit_msg>Fixes to demo_SuspensionTest.<commit_after>// =============================================================================
// PROJECT CHRONO - http://projectchrono.org
//
// Copyright (c) 2014 projectchrono.org
// All right reserved.
//
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file at the top level of the distribution and at
// http://projectchrono.org/license-chrono.txt.
//
// =============================================================================
// Authors: Justin Madsen, Radu Serban
// =============================================================================
//
// Suspension testing mechanism, using force or motion inputs to the locked wheels
//  to simulate the effect of a post-testing mechanism
//
// The Irrlicht interface used to observe the suspension test, and also to provide
// any steering inputs.
//
// The vehicle reference frame has Z up, X towards the front of the vehicle, and
// Y pointing to the left.
//
// =============================================================================

#include <vector>

#include "core/ChFileutils.h"
#include "core/ChStream.h"
#include "core/ChRealtimeStep.h"
#include "physics/ChSystem.h"
#include "physics/ChLinkDistance.h"

#include "chrono_vehicle/ChVehicleModelData.h"

#include "chrono_utils/ChUtilsInputOutput.h"

// subsystems, all read in fron JSON files
#include "ModelDefs.h"

#include "chrono_vehicle/suspensionTest/SuspensionTest.h"
#include "chrono_vehicle/tire/RigidTire.h"
#include "chrono_vehicle/terrain/FlatTerrain.h"
#include "chrono_vehicle/driver/ChDataDriver.h"

// Irrlicht includes
#if IRRLICHT_ENABLED
# include "unit_IRRLICHT/ChIrrApp.h"
# include "chrono_vehicle/driver/ChIrrGuiST.h"
# define USE_IRRLICHT
#endif

// DEBUGGING:  Uncomment the following line to print shock data
//#define DEBUG_LOG
#define DEBUG_ACTUATOR    // debug actuator in SuspensionTest
using namespace chrono;

// =============================================================================
// USER SETTINGS
// =============================================================================
double steer_limit = 0.6;
double post_limit = 0.2;

// Simulation step size
double step_size = 0.001;
double render_step_size = 1.0 / 50;   // Time interval between two render frames
double output_step_size = 1.0 / 1;    // Time interval between two output frames

#ifdef USE_IRRLICHT
  // Point on chassis tracked by the camera
  ChVector<> trackPoint(1.65, 0.0, 0);
  double camera_chase = 0;
  double camera_height = 2.0;
#else
  double tend = 20.0;
  const std::string out_dir = "../HMMWV";
  const std::string pov_dir = out_dir + "/POVRAY";
#endif

// =============================================================================
// JSON file for suspension
// std::string suspensionTest_file("hmmwv/suspensionTest/HMMWV_ST_front.json");
std::string suspensionTest_file("hmmwv/suspensionTest/HMMWV_ST_rear.json");

// JSON files for tire models (rigid) and powertrain (simple)
std::string rigidtire_file("hmmwv/tire/HMMWV_RigidTire.json");

// Driver input file (if not using Irrlicht)
std::string driver_file("generic/driver/Sample_Maneuver.txt");

// radius of wheel + vertical distance between spindle and chassis center marker
ChVector<> initLoc(0, 0, 0.496);
ChQuaternion<> initRot(1, 0, 0, 0);

// =============================================================================
int main(int argc, char* argv[])
{
  // Create the testing mechanism, initilize ity
  SuspensionTest tester(vehicle::GetDataFile(suspensionTest_file));
  tester.Initialize(ChCoordsys<>(initLoc, initRot));
  // tester.Save_DebugLog(DBG_SPRINGS | DBG_SHOCKS | DBG_CONSTRAINTS | DBG_SUSPENSIONTEST,"log_test_SuspensionTester.csv");
  tester.Save_DebugLog(DBG_SUSPENSIONTEST,"log_test_SuspensionTester.csv");

  // Create and initialize two rigid wheels
  ChSharedPtr<ChTire> tire_front_right;
  ChSharedPtr<ChTire> tire_front_left;

  // flat rigid terrain, height = 0
  FlatTerrain flat_terrain(0);

  // use rigid wheels to actuate suspension
  ChSharedPtr<RigidTire> tire_FL(new RigidTire(vehicle::GetDataFile(rigidtire_file), flat_terrain));
  ChSharedPtr<RigidTire> tire_FR(new RigidTire(vehicle::GetDataFile(rigidtire_file), flat_terrain));

  tire_FL->Initialize(tester.GetWheelBody(FRONT_LEFT));
  tire_FR->Initialize(tester.GetWheelBody(FRONT_RIGHT));

  tire_front_left = tire_FL;
  tire_front_right = tire_FR;

#ifdef USE_IRRLICHT
  irr::ChIrrApp application(&tester,
                            L"HMMWV Suspension test",
                            irr::core::dimension2d<irr::u32>(1000, 800),
                            false,
                            true);

  // make a skybox that has Z pointing up (default .AddTypicalSky()  Y up)
  std::string mtexturedir = GetChronoDataFile("skybox/");
  std::string str_lf = mtexturedir + "sky_lf.jpg";
  std::string str_up = mtexturedir + "sky_up.jpg";
  std::string str_dn = mtexturedir + "sky_dn.jpg";
  irr::video::ITexture* map_skybox_side =
      application.GetVideoDriver()->getTexture(str_lf.c_str());
  irr::scene::ISceneNode* mbox = application.GetSceneManager()->addSkyBoxSceneNode(
      application.GetVideoDriver()->getTexture(str_up.c_str()),
      application.GetVideoDriver()->getTexture(str_dn.c_str()),
      map_skybox_side,
      map_skybox_side,
      map_skybox_side,
      map_skybox_side);
  mbox->setRotation( irr::core::vector3df(90,0,0));

  bool do_shadows = false; // shadow map is experimental
  irr::scene::ILightSceneNode* mlight = 0;

  if (do_shadows) {
    mlight = application.AddLightWithShadow(
      irr::core::vector3df(-5.f, 1.f, 6.f),
      irr::core::vector3df(5.f, -1.f, -2.f),
      250, 60, 80, 15, 512, irr::video::SColorf(1, 1, 1), false, false);
  } else {
    application.AddTypicalLights(
      irr::core::vector3df(30.f, -30.f, 100.f),
      irr::core::vector3df(30.f, 50.f, 100.f),
      250, 130);
  }

  application.SetTimestep(step_size);

  ChIrrGuiST driver(application, tester, trackPoint, camera_chase, camera_height, steer_limit, post_limit);

  // Set the time response for steering keyboard inputs, when they are used
  // NOTE: this is not exact, since not rendered quite at the specified FPS.
  double steering_time = 2.0;  // time to go from 0 to max
  double post_time = 3.0; // time to go from 0 to max applied post motion
  driver.SetSteeringDelta(render_step_size / steering_time * steer_limit);
  driver.SetPostDelta(render_step_size / post_time * post_limit);

  // Set up the assets for rendering
  application.AssetBindAll();
  application.AssetUpdateAll();
  if (do_shadows)
  {
    application.AddShadowAll();
  }
#else
  ChDataDriver driver(vehicle::GetDataFile(driver_file));
#endif

  // ---------------
  // Simulation loop
#ifdef DEBUG_LOG
  GetLog() << "\n\n============ System Configuration ============\n";
  vehicle.LogHardpointLocations();
#endif

  // Inter-module communication data
  ChTireForces tire_forces(2);
  ChWheelState wheel_states[2];
  double       steering_input;
  double       post_z_L = 0;
  double       post_z_R = 0;

  // Number of simulation steps between two 3D view render frames
  int render_steps = (int)std::ceil(render_step_size / step_size);

  // Number of simulation steps between two output frames
  int output_steps = (int)std::ceil(output_step_size / step_size);

  // Initialize simulation frame counter and simulation time
  int step_number = 0;
  double time = 0;

#ifdef USE_IRRLICHT

  ChRealtimeStepTimer realtime_timer;

  while (application.GetDevice()->run())
  {
    // update the position of the shadow mapping so that it follows the car
    if (do_shadows)
    {
      ChVector<> lightaim = tester.GetChassisPos();
      ChVector<> lightpos = tester.GetChassisPos() + ChVector<>(10, 30, 60);
      irr::core::vector3df mlightpos((irr::f32)lightpos.x, (irr::f32)lightpos.y, (irr::f32)lightpos.z);
      irr::core::vector3df mlightaim((irr::f32)lightaim.x, (irr::f32)lightaim.y, (irr::f32)lightaim.z);
      application.GetEffects()->getShadowLight(0).setPosition(mlightpos);
      application.GetEffects()->getShadowLight(0).setTarget(mlightaim);
      mlight->setPosition(mlightpos);
    }

    // Render scene
    if (step_number % render_steps == 0) {
      application.GetVideoDriver()->beginScene(true, true, irr::video::SColor(255, 140, 161, 192));
      driver.DrawAll();
      application.GetVideoDriver()->endScene();
    }

#ifdef DEBUG_LOG
    if (step_number % output_steps == 0) {
      GetLog() << "\n\n============ System Information ============\n";
      GetLog() << "Time = " << time << "\n\n";
      tester.DebugLog(DBG_SPRINGS | DBG_SHOCKS | DBG_CONSTRAINTS);
    }
#endif

#ifdef DEBUG_ACTUATOR
    if (step_number % output_steps == 0) {
      GetLog() << "\n\n============ System Information ============\n";
      GetLog() << "Time = " << time << "\n\n";
      tester.DebugLog(DBG_SPRINGS | DBG_SUSPENSIONTEST);
    }
    if (step_number % render_steps == 0) {
      // write output data
      tester.SaveLog();
    }
#endif

    // Collect output data from modules, here it's the steering and post displacements
    steering_input = driver.GetSteering();
    post_z_L = driver.Get_post_z_L();
    post_z_R = driver.Get_post_z_R();

    tire_forces[FRONT_LEFT.id()] = tire_front_left->GetTireForce();
    tire_forces[FRONT_RIGHT.id()] = tire_front_right->GetTireForce();
    wheel_states[FRONT_LEFT.id()] = tester.GetWheelState(FRONT_LEFT);
    wheel_states[FRONT_RIGHT.id()] = tester.GetWheelState(FRONT_RIGHT);

    // Update modules (process inputs from other modules)
    time = tester.GetChTime();

    driver.Update(time);

    flat_terrain.Update(time);

    tire_front_left->Update(time, wheel_states[FRONT_LEFT.id()]);
    tire_front_right->Update(time, wheel_states[FRONT_RIGHT.id()]);

    tester.Update(time, steering_input, post_z_L, post_z_R, tire_forces);

    // Advance simulation for one timestep for all modules
    double step = realtime_timer.SuggestSimulationStep(step_size);

    driver.Advance(step);

    flat_terrain.Advance(step);

    tire_front_left->Advance(step);
    tire_front_right->Advance(step);

    tester.Advance(step);

    // Increment frame number
    step_number++;
  }

  application.GetDevice()->drop();

#else

  int render_frame = 0;

  if(ChFileutils::MakeDirectory(out_dir.c_str()) < 0) {
    std::cout << "Error creating directory " << out_dir << std::endl;
    return 1;
  }
  if(ChFileutils::MakeDirectory(pov_dir.c_str()) < 0) {
    std::cout << "Error creating directory " << pov_dir << std::endl;
    return 1;
  }

  char filename[100];

  while (time < tend)
  {
    if (step_number % render_steps == 0) {
      // Output render data
      sprintf(filename, "%s/data_%03d.dat", pov_dir.c_str(), render_frame + 1);
      //// TODO:  Fix this!  Must modify ChSuspensionTest to conform to ChVehicle
      ////utils::WriteShapesPovray(&vehicle, filename);
      std::cout << "Output frame:   " << render_frame << std::endl;
      std::cout << "Sim frame:      " << step_number << std::endl;
      std::cout << "Time:           " << time << std::endl;
      std::cout << "             throttle: " << driver.GetThrottle() << " steering: " << driver.GetSteering() << std::endl;
      std::cout << std::endl;
      render_frame++;
    }

#ifdef DEBUG_LOG
    if (step_number % output_steps == 0) {
      GetLog() << "\n\n============ System Information ============\n";
      GetLog() << "Time = " << time << "\n\n";
      vehicle.DebugLog(DBG_SHOCKS);
    }
#endif

    // Collect output data from modules (for inter-module communication)
    steering_input = driver.GetSteering();

    tire_forces[FRONT_LEFT.id()] = tire_front_left->GetTireForce();
    tire_forces[FRONT_RIGHT.id()] = tire_front_right->GetTireForce();

    wheel_states[FRONT_LEFT.id()] = tester.GetWheelState(FRONT_LEFT);
    wheel_states[FRONT_RIGHT.id()] = tester.GetWheelState(FRONT_RIGHT);

    // Update modules (process inputs from other modules)
    time = tester.GetChTime();

    driver.Update(time);

    flat_terrain.Update(time);

    tire_front_left->Update(time, wheel_states[FRONT_LEFT.id()]);
    tire_front_right->Update(time, wheel_states[FRONT_RIGHT.id()]);

    tester.Update(time, steering_input, post_z_L, post_z_R, tire_forces);

    // Advance simulation for one timestep for all modules
    driver.Advance(step_size);

    flat_terrain.Advance(step_size);

    tire_front_right->Advance(step_size);
    tire_front_left->Advance(step_size);

    tester.Advance(step_size);

    // Increment frame number
    step_number++;
  }

#endif

  return 0;
}
<|endoftext|>