<commit_before>//
// This file is part of the Marble Desktop Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2007      Inge Wallin  <ingwa@kde.org>
// Copyright 2008      Jens-Michael Hoffmann <jensmh@gmx.de>
//

#include "ViewParams.h"

#include <QtCore/QDebug>
#include <QtGui/QImage>

#include "AbstractProjection.h"
#include "GeoSceneDocument.h"
#include "GeoSceneSettings.h"
#include "MapThemeManager.h"
#include "ViewportParams.h"

namespace Marble
{

class ViewParamsPrivate
{
public:
    ViewParamsPrivate();
    ~ViewParamsPrivate();

    GeoSceneDocument *m_mapTheme;

    ViewportParams  m_viewport;

    // The quality that we are painting right now.
    MapQuality           m_mapQuality;

    // FIXME: We should try to get rid of these two:
    Quaternion  m_planetAxisUpdated;
    int         m_radiusUpdated;

    // Parameters that determine the painting
    // Show/don't show options

    // FIXME: All of these parameters should get stored as a GeoSceneSettings
    //        property object in the future instead ...
    bool        m_showAtmosphere;
    bool        m_showCrosshairs;

    bool        m_showElevationModel;

    bool        m_showGps; //for gps layer

    // Cached data that will make painting faster.
    QImage  *m_canvasImage;     // Base image with space and atmosphere
    QImage  *m_coastImage;      // A slightly higher level image.
};

ViewParamsPrivate::ViewParamsPrivate()
    : m_mapTheme( 0 ),
      m_viewport(),
      m_mapQuality( NormalQuality ),
      m_planetAxisUpdated(),
      m_radiusUpdated( 0 ),
      // Show / don't show parameters
      m_showAtmosphere( true ),
      m_showElevationModel( false ),
      // Other layers
      m_showGps( false ),
      // Just to have something.  These will be resized anyway.
      m_canvasImage( new QImage( 10, 10, QImage::Format_RGB32 )),
      m_coastImage( new QImage( 10, 10, QImage::Format_RGB32 ))
{
}

ViewParamsPrivate::~ViewParamsPrivate()
{
    delete m_canvasImage;
    delete m_coastImage;
}

ViewParams::ViewParams()
    : d( new ViewParamsPrivate )
{
}

ViewParams::~ViewParams()
{
    delete d;
}

ViewportParams *ViewParams::viewport()
{
    return &d->m_viewport;
}

Projection ViewParams::projection() const
{
    return d->m_viewport.projection();
}

MapQuality ViewParams::mapQuality()
{
    return d->m_mapQuality;
}

void ViewParams::setMapQuality( MapQuality mapQuality )
{
    d->m_mapQuality = mapQuality;
}

AbstractProjection *ViewParams::currentProjection() const
{
    return d->m_viewport.currentProjection();
}

void ViewParams::setProjection(Projection newProjection)
{
    d->m_viewport.setProjection( newProjection );

    // Repaint the background if necessary
    if ( !currentProjection()->mapCoversViewport( viewport() ) ) {
        canvasImage()->fill(0); // Using Qt::transparent is wrong here (equals "18")!
    }
}

void ViewParams::setMapThemeId( const QString& mapThemeId )
{
    GeoSceneDocument* mapTheme = MapThemeManager::loadMapTheme( mapThemeId );

    // Check whether the selected theme got parsed well
    if ( !mapTheme ) {

        // Check whether the previous theme works
        if ( !d->m_mapTheme ){
            // Fall back to default theme
            qDebug() << "Falling back to default theme";
            mapTheme = MapThemeManager::loadMapTheme("earth/srtm/srtm.dgml");

            // If this last resort doesn't work either shed a tear and exit
            if ( !mapTheme ) {
                qDebug() << "Couldn't find a valid DGML map.";
                exit(-1);
            }
        }
        else {
            qDebug() << "Selected theme doesn't work, so we stick to the previous one";
            return;
        }
    }

    d->m_mapTheme = mapTheme;
}

GeoSceneDocument *ViewParams::mapTheme()
{
    return d->m_mapTheme;
}

void ViewParams::setPropertyValue( const QString &name, bool value )
{
    if ( d->m_mapTheme ) {
        d->m_mapTheme->settings()->setPropertyValue( name, value );
    }
    else {
        qDebug() << "WARNING: Failed to access a map theme! Property: " << name;
    }
}

void ViewParams::propertyValue( const QString &name, bool &value )
{
    if ( d->m_mapTheme ) {
        d->m_mapTheme->settings()->propertyValue( name, value );
    }
    else {
        value = false;
        qDebug() << "WARNING: Failed to access a map theme! Property: " << name;
    }
}

void ViewParams::propertyAvailable( const QString &name, bool &value )
{
    if ( d->m_mapTheme ) {
        d->m_mapTheme->settings()->propertyAvailable( name, value );
    }
    else {
        value = false;
        qDebug() << "WARNING: Failed to access a map theme! Property: " << name;
    }
}

int ViewParams::radius() const
{
    return d->m_viewport.radius();
}

void ViewParams::setRadius(int newRadius)
{
    d->m_viewport.setRadius( newRadius );

    // Repaint the background if necessary
    if ( !currentProjection()->mapCoversViewport( viewport() ) ) {
        canvasImage()->fill(0); // Using Qt::transparent is wrong here (equals "18")!
    }

}

Quaternion ViewParams::planetAxis() const
{
    return d->m_viewport.planetAxis();
}

void ViewParams::setPlanetAxis(const Quaternion &newAxis)
{
    d->m_viewport.setPlanetAxis( newAxis );
/*
    // Repaint the background if necessary
    if ( projection() != Spherical && !currentProjection()->mapCoversViewport( viewport() ) ) {
        canvasImage()->fill(0); // Using Qt::transparent is wrong here (equals "18")!
    }
*/
}

void ViewParams::centerCoordinates( qreal &centerLon, qreal &centerLat )
{
    d->m_viewport.centerCoordinates( centerLon, centerLat );
}

QImage * ViewParams::canvasImage() const
{
    return d->m_canvasImage;
}

void ViewParams::setCanvasImage( QImage * const image )
{
    delete d->m_canvasImage;
    d->m_canvasImage = image;

    // Repaint the background if necessary
    if ( !currentProjection()->mapCoversViewport( viewport() ) ) {
        d->m_canvasImage->fill(0); // Using Qt::transparent is wrong here (equals "18")!
    }

}

QImage * ViewParams::coastImage() const
{
    return d->m_coastImage;
}

void ViewParams::setCoastImage( QImage * const image )
{
    delete d->m_coastImage;
    d->m_coastImage = image;
}

int ViewParams::radiusUpdated() const
{
    return d->m_radiusUpdated;
}

void ViewParams::setRadiusUpdated( int radiusUpdated )
{
    d->m_radiusUpdated = radiusUpdated;
}

bool ViewParams::showGps() const
{
    return d->m_showGps;
}

void ViewParams::setShowGps( bool showGps )
{
    d->m_showGps = showGps;
}

bool ViewParams::showElevationModel() const
{
    return d->m_showElevationModel;
}

void ViewParams::setShowElevationModel( bool showElevationModel )
{
    d->m_showElevationModel = showElevationModel;
}

bool ViewParams::showAtmosphere() const
{
    return d->m_showAtmosphere;
}

void ViewParams::setShowAtmosphere( bool showAtmosphere )
{
    d->m_showAtmosphere = showAtmosphere;
}

Quaternion ViewParams::planetAxisUpdated() const
{
    return d->m_planetAxisUpdated;
}

void ViewParams::setPlanetAxisUpdated( const Quaternion & planetAxisUpdated )
{
    d->m_planetAxisUpdated = planetAxisUpdated;
}

}
<commit_msg>Adjust setRadiusUpdated signature. Bug: 213528<commit_after>//
// This file is part of the Marble Desktop Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2007      Inge Wallin  <ingwa@kde.org>
// Copyright 2008      Jens-Michael Hoffmann <jensmh@gmx.de>
//

#include "ViewParams.h"

#include <QtCore/QDebug>
#include <QtGui/QImage>

#include "AbstractProjection.h"
#include "GeoSceneDocument.h"
#include "GeoSceneSettings.h"
#include "MapThemeManager.h"
#include "ViewportParams.h"

namespace Marble
{

class ViewParamsPrivate
{
public:
    ViewParamsPrivate();
    ~ViewParamsPrivate();

    GeoSceneDocument *m_mapTheme;

    ViewportParams  m_viewport;

    // The quality that we are painting right now.
    MapQuality           m_mapQuality;

    // FIXME: We should try to get rid of these two:
    Quaternion  m_planetAxisUpdated;
    int         m_radiusUpdated;

    // Parameters that determine the painting
    // Show/don't show options

    // FIXME: All of these parameters should get stored as a GeoSceneSettings
    //        property object in the future instead ...
    bool        m_showAtmosphere;
    bool        m_showCrosshairs;

    bool        m_showElevationModel;

    bool        m_showGps; //for gps layer

    // Cached data that will make painting faster.
    QImage  *m_canvasImage;     // Base image with space and atmosphere
    QImage  *m_coastImage;      // A slightly higher level image.
};

ViewParamsPrivate::ViewParamsPrivate()
    : m_mapTheme( 0 ),
      m_viewport(),
      m_mapQuality( NormalQuality ),
      m_planetAxisUpdated(),
      m_radiusUpdated( 0 ),
      // Show / don't show parameters
      m_showAtmosphere( true ),
      m_showElevationModel( false ),
      // Other layers
      m_showGps( false ),
      // Just to have something.  These will be resized anyway.
      m_canvasImage( new QImage( 10, 10, QImage::Format_RGB32 )),
      m_coastImage( new QImage( 10, 10, QImage::Format_RGB32 ))
{
}

ViewParamsPrivate::~ViewParamsPrivate()
{
    delete m_canvasImage;
    delete m_coastImage;
}

ViewParams::ViewParams()
    : d( new ViewParamsPrivate )
{
}

ViewParams::~ViewParams()
{
    delete d;
}

ViewportParams *ViewParams::viewport()
{
    return &d->m_viewport;
}

Projection ViewParams::projection() const
{
    return d->m_viewport.projection();
}

MapQuality ViewParams::mapQuality()
{
    return d->m_mapQuality;
}

void ViewParams::setMapQuality( MapQuality mapQuality )
{
    d->m_mapQuality = mapQuality;
}

AbstractProjection *ViewParams::currentProjection() const
{
    return d->m_viewport.currentProjection();
}

void ViewParams::setProjection(Projection newProjection)
{
    d->m_viewport.setProjection( newProjection );

    // Repaint the background if necessary
    if ( !currentProjection()->mapCoversViewport( viewport() ) ) {
        canvasImage()->fill(0); // Using Qt::transparent is wrong here (equals "18")!
    }
}

void ViewParams::setMapThemeId( const QString& mapThemeId )
{
    GeoSceneDocument* mapTheme = MapThemeManager::loadMapTheme( mapThemeId );

    // Check whether the selected theme got parsed well
    if ( !mapTheme ) {

        // Check whether the previous theme works
        if ( !d->m_mapTheme ){
            // Fall back to default theme
            qDebug() << "Falling back to default theme";
            mapTheme = MapThemeManager::loadMapTheme("earth/srtm/srtm.dgml");

            // If this last resort doesn't work either shed a tear and exit
            if ( !mapTheme ) {
                qDebug() << "Couldn't find a valid DGML map.";
                exit(-1);
            }
        }
        else {
            qDebug() << "Selected theme doesn't work, so we stick to the previous one";
            return;
        }
    }

    d->m_mapTheme = mapTheme;
}

GeoSceneDocument *ViewParams::mapTheme()
{
    return d->m_mapTheme;
}

void ViewParams::setPropertyValue( const QString &name, bool value )
{
    if ( d->m_mapTheme ) {
        d->m_mapTheme->settings()->setPropertyValue( name, value );
    }
    else {
        qDebug() << "WARNING: Failed to access a map theme! Property: " << name;
    }
}

void ViewParams::propertyValue( const QString &name, bool &value )
{
    if ( d->m_mapTheme ) {
        d->m_mapTheme->settings()->propertyValue( name, value );
    }
    else {
        value = false;
        qDebug() << "WARNING: Failed to access a map theme! Property: " << name;
    }
}

void ViewParams::propertyAvailable( const QString &name, bool &value )
{
    if ( d->m_mapTheme ) {
        d->m_mapTheme->settings()->propertyAvailable( name, value );
    }
    else {
        value = false;
        qDebug() << "WARNING: Failed to access a map theme! Property: " << name;
    }
}

int ViewParams::radius() const
{
    return d->m_viewport.radius();
}

void ViewParams::setRadius(int newRadius)
{
    d->m_viewport.setRadius( newRadius );

    // Repaint the background if necessary
    if ( !currentProjection()->mapCoversViewport( viewport() ) ) {
        canvasImage()->fill(0); // Using Qt::transparent is wrong here (equals "18")!
    }

}

Quaternion ViewParams::planetAxis() const
{
    return d->m_viewport.planetAxis();
}

void ViewParams::setPlanetAxis(const Quaternion &newAxis)
{
    d->m_viewport.setPlanetAxis( newAxis );
/*
    // Repaint the background if necessary
    if ( projection() != Spherical && !currentProjection()->mapCoversViewport( viewport() ) ) {
        canvasImage()->fill(0); // Using Qt::transparent is wrong here (equals "18")!
    }
*/
}

void ViewParams::centerCoordinates( qreal &centerLon, qreal &centerLat )
{
    d->m_viewport.centerCoordinates( centerLon, centerLat );
}

QImage * ViewParams::canvasImage() const
{
    return d->m_canvasImage;
}

void ViewParams::setCanvasImage( QImage * const image )
{
    delete d->m_canvasImage;
    d->m_canvasImage = image;

    // Repaint the background if necessary
    if ( !currentProjection()->mapCoversViewport( viewport() ) ) {
        d->m_canvasImage->fill(0); // Using Qt::transparent is wrong here (equals "18")!
    }

}

QImage * ViewParams::coastImage() const
{
    return d->m_coastImage;
}

void ViewParams::setCoastImage( QImage * const image )
{
    delete d->m_coastImage;
    d->m_coastImage = image;
}

int ViewParams::radiusUpdated() const
{
    return d->m_radiusUpdated;
}

void ViewParams::setRadiusUpdated( const int radiusUpdated )
{
    d->m_radiusUpdated = radiusUpdated;
}

bool ViewParams::showGps() const
{
    return d->m_showGps;
}

void ViewParams::setShowGps( bool showGps )
{
    d->m_showGps = showGps;
}

bool ViewParams::showElevationModel() const
{
    return d->m_showElevationModel;
}

void ViewParams::setShowElevationModel( bool showElevationModel )
{
    d->m_showElevationModel = showElevationModel;
}

bool ViewParams::showAtmosphere() const
{
    return d->m_showAtmosphere;
}

void ViewParams::setShowAtmosphere( bool showAtmosphere )
{
    d->m_showAtmosphere = showAtmosphere;
}

Quaternion ViewParams::planetAxisUpdated() const
{
    return d->m_planetAxisUpdated;
}

void ViewParams::setPlanetAxisUpdated( const Quaternion & planetAxisUpdated )
{
    d->m_planetAxisUpdated = planetAxisUpdated;
}

}
<|endoftext|>


<commit_before>#include "stdafx.h"
#include "json.h"

#include "Simulation.h"

void debug_terminate()
{
	std::cerr << "Uncaught exception." << std::endl;
	assert(false);
}

int main(int argc, char* argv[])
{
	// options can either be passed as a filename in the command line or as input to stdin
	std::string inputFilename = "";
	for (int i = 1; i < argc; ++i)
	{
		std::string option = argv[i];

		if (option == "-f" && (i < argc - 1))
		{
			inputFilename = argv[i + 1];
		}
	}

	json_spirit::Value jsonData;
	bool jsonResult = false;

	if (!inputFilename.empty())
	{
		jsonResult = json_spirit::read(std::ifstream(inputFilename, std::ifstream::in), jsonData);
	}
	else
	{
		jsonResult = json_spirit::read(std::cin, jsonData);
	}

	if (!jsonResult)
	{
		exit(1);
	}

	std::set_terminate(debug_terminate);

//#define EXCEPTIONDEBUG
#ifdef EXCEPTIONDEBUG
	try
#endif
	{

		sim::Simulation simulation(jsonData);
		simulation.execute();

		json_spirit::Object results = simulation.getJSONResults();
		std::string json = json_spirit::write(results, json_spirit::remove_trailing_zeros);
		std::cout << json << std::endl;
	}
#ifdef EXCEPTIONDEBUG
	catch(const std::runtime_error& re)
	{
		std::cerr << "Runtime error: " << re.what() << std::endl;
		assert (false);
		exit(1);
	}
	catch(const std::exception& ex)
	{
		std::cerr << "Error occurred: " << ex.what() << std::endl;
		assert (false);
		exit(1);
	}
	catch(...)
	{
		std::cerr << "An unexpected error occurred." << std::endl;
		assert (false);
		exit(1);
	}
#endif

	return 0;
}

<commit_msg>buildfix g++: add explicit conversion to ifstream->istream<commit_after>#include "stdafx.h"
#include "json.h"

#include "Simulation.h"

void debug_terminate()
{
	std::cerr << "Uncaught exception." << std::endl;
	assert(false);
}

int main(int argc, char* argv[])
{
	// options can either be passed as a filename in the command line or as input to stdin
	std::string inputFilename = "";
	for (int i = 1; i < argc; ++i)
	{
		std::string option = argv[i];

		if (option == "-f" && (i < argc - 1))
		{
			inputFilename = argv[i + 1];
		}
	}

	json_spirit::Value jsonData;
	bool jsonResult = false;

	if (!inputFilename.empty())
	{
		jsonResult = json_spirit::read((std::istream&)std::ifstream(inputFilename, std::ifstream::in), jsonData);
	}
	else
	{
		jsonResult = json_spirit::read((std::istream&)std::cin, jsonData);
	}

	if (!jsonResult)
	{
		exit(1);
	}

	std::set_terminate(debug_terminate);

//#define EXCEPTIONDEBUG
#ifdef EXCEPTIONDEBUG
	try
#endif
	{

		sim::Simulation simulation(jsonData);
		simulation.execute();

		json_spirit::Object results = simulation.getJSONResults();
		std::string json = json_spirit::write(results, json_spirit::remove_trailing_zeros);
		std::cout << json << std::endl;
	}
#ifdef EXCEPTIONDEBUG
	catch(const std::runtime_error& re)
	{
		std::cerr << "Runtime error: " << re.what() << std::endl;
		assert (false);
		exit(1);
	}
	catch(const std::exception& ex)
	{
		std::cerr << "Error occurred: " << ex.what() << std::endl;
		assert (false);
		exit(1);
	}
	catch(...)
	{
		std::cerr << "An unexpected error occurred." << std::endl;
		assert (false);
		exit(1);
	}
#endif

	return 0;
}

<|endoftext|>


<commit_before>//
// Created by louis on 06/10/16.
//

#include <iostream>
#include <sstream>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <zconf.h>
#include <memory>

#include "FileBuffer.h"
#include "rendering/Context.h"
#include "rendering/Scene.h"
#include "rendering/Renderable.h"
#include "rendering/RenderableSphere.h"
#include "physics/World.h"
#include "physics/Body.h"
#include "rendering/RenderableTrajectory.h"

//DECLARATIONS

//#define SIMULATION_TO_COUT

//TODO rajouter des constantes

struct Planet {
    Planet(std::string name, std::shared_ptr<Body> body, std::shared_ptr<RenderableSphere> render);
    std::string name;
    std::shared_ptr<Body> body;
    std::shared_ptr<RenderableSphere> render;
    std::shared_ptr<RenderableTrajectory> trajectory;
    FileBuffer buffer;
};

std::string DATE;
int currentPlanet = 0;
std::unique_ptr<Scene> scene = nullptr;
std::unique_ptr<World> world = nullptr;
std::vector<Planet> planets;

//TODO struct parameters
bool enableGraphicalSimulation = true;

void addPlanet(std::string name, double mass, double x, double y, double z, double size);

/** Ajoute un objet 3D à la scene et au monde physique. */
void addPlanet(Planet planet);

/** Initialise la scène ainsi que le monde physique. */
void createScene();

/** J'ajoute le système solaire à la scène ! */
void addSolarSystem();

/** Cette méthode est le coeur du thread graphique,
 * Elle crée la fenetre, charge les ressources, effectue
 * la boucle principale de l'application, gère les
 * entrées sorties, puis détruit les ressources lorsque
 * l'utilisateur ferme la fenetre. */
void graphicThread();

/** Cette méthode est appelée à chaque tour de boucle pour
 * analyser les entrées sorties, mettre à jour le monde physique
 * et dessiner la scene à l'écran. */
void mainLoop(GLFWwindow * window, Context *context);

void glfwErrorCallback(int error, const char* description);
void glfwKeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods);
void glfwScrollCallback(GLFWwindow* window, double xoffset, double yoffset);

//MAIN

int main(int argc, char** argv) {
    //printf("nombre : %.80Lf\n", M_PIl); //;)

    //TODO déterminer la date
    //TODO pouvoir reprendre les résultats de la simulation précédente

    createScene();

    graphicThread();

    for (Planet &object : planets) {
        object.buffer.writeData();
    }

    return 0;
}

//IMPLEMENTATIONS

Planet::Planet(std::string name, std::shared_ptr<Body> body, std::shared_ptr<RenderableSphere> render)
    : name(name), body(body), render(render), buffer(name + "_" + DATE),
      trajectory(std::make_shared<RenderableTrajectory>()) {

}

void createScene() {
    scene = std::make_unique<Scene>();

    Light light(LIGHT_POINT, 0, 0, 0);
    scene->setLight(light);

    //dist 1e10 m, mass 1e21 kg, tps 1e6 s, vit 1e4 m.s-1 -> G *= 1e3 (- 10*3 + 21 + 6*2)
    world = std::make_unique<World>();
    world->setGravityConstant(6.7e-11 * 1e3);

    addSolarSystem();
}

void addSolarSystem() {
    //Rendus
    auto moonRender = std::make_shared<RenderableSphere>(0.8, 64, 64);
    moonRender->addTexturePath("assets/moon.png");

    auto earthRender = std::make_shared<RenderableSphere>(0.8, 64, 64);
    earthRender->addTexturePath("assets/earth.png");

    auto jupiterRender = std::make_shared<RenderableSphere>(1.5, 64, 64);
    jupiterRender->addTexturePath("assets/jupiter.png");

    auto marsRender = std::make_shared<RenderableSphere>(0.7, 64, 64);
    marsRender->addTexturePath("assets/mars.png");

    auto sunRender = std::make_shared<RenderableSphere>(3, 64, 64);
    sunRender->getMaterial().setAmbient(0.85f, 0.25f, 0.1f);
    sunRender->addTexturePath("assets/sun.png");
    sunRender->getMaterial().setEmit(true);

    //Physique
    auto moonBody = std::make_shared<Body>(73.0);
    moonBody->setPosition(-20.0, 0, 0);
    moonBody->setSpeed(0, 5e-6, 0);

    auto earthBody = std::make_shared<Body>(6000.0);
    earthBody->setPosition(-15, 0, 0);
    earthBody->setSpeed(0, 2.9, 0);

    auto marsBody = std::make_shared<Body>(6000.0);
    marsBody->setPosition(0, -24.9, 0);
    marsBody->setSpeed(2.19, 0, 0);

    auto jupiterBody = std::make_shared<Body>(1.9e6);
    jupiterBody->setPosition(0, 77.8, 0);
    jupiterBody->setSpeed(-1.3, 0, 0);

    auto sunBody = std::make_shared<Body>(1e9);

    //Ajout des objets
    addPlanet({"sun", sunBody, sunRender});
    addPlanet({"earth", earthBody, earthRender});
    //addPlanet({"moon", moonBody, moonRender});
    addPlanet({"mars", marsBody, marsRender});
    addPlanet({"jupiter", jupiterBody, jupiterRender});
}

void addPlanet(std::string name, double mass, double x, double y, double z, double size) {
    auto sphereRender = std::make_shared<RenderableSphere>(size, 64, 64);
    sphereRender->getMaterial().setDiffuse(0.85f, 0.75f, 0.1f);
    auto sphereBody = std::make_shared<Body>(mass);
    sphereBody->setPosition(x, y, z);
    addPlanet({name, sphereBody, sphereRender});
}

void addPlanet(Planet planet) {
    planets.push_back(planet);
    if (planet.body != nullptr) world->addObject(planet.body);
    if (planet.render != nullptr) {
        scene->addObject(planet.render);
        planet.render->getMaterial().setSpecular(0, 0, 0);
    }
}

void graphicThread() {
    int width, height;

    if (!glfwInit()) {
        std::cerr << "Erreur au lancement de glfw." << std::endl;
        return;
    }

    glfwSetErrorCallback(glfwErrorCallback);

    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
    glfwWindowHint(GLFW_SAMPLES, 16);
    GLFWwindow* window = glfwCreateWindow(800, 600, "Simulation", NULL, NULL);

    if (!window) {
        std::cerr << "Erreur au lancement de glfw." << std::endl;
        return;
    }

    glfwMakeContextCurrent(window);
    gladLoadGLLoader((GLADloadproc) glfwGetProcAddress);
    glfwSwapInterval(1);

    glfwSetKeyCallback(window, glfwKeyCallback);
    glfwSetScrollCallback(window, glfwScrollCallback);

    //Création du contexte
    Context context(window);

    glEnable(GL_MULTISAMPLE);
    glClearColor(3 / 255.0f, 0 / 255.0f, 32 / 255.0f, 1);

    while (!glfwWindowShouldClose(window)) {

        glfwGetFramebufferSize(window, &width, &height);
        glViewport(0, 0, width, height);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

        mainLoop(window, &context);

        glfwSwapBuffers(window);
        glfwPollEvents();

        if (enableGraphicalSimulation) usleep(20000);
    }

    glfwDestroyWindow(window);

    glfwTerminate();
}

void mainLoop(GLFWwindow *window, Context *context) {

    /*
     | -> LEFT et RIGHT pour tourner autour de l'axe UP (quasi toujours vers le haut)
     | -> UP et DOWN pour faire pivoter la position de la cam vers le haut ou le bas (limite aux extremes)
     | -> 0 pour la vue de dessus centrée sur 0, 0
     + -> En vue de dessus, LEFT et RIGHT font tourner l'axe UP selon l'axe Z.
     | -> vue de côté pour chacun des astres sur les touches 1, 2, 3, 4 ...
     | -> Rotation molette pour le zoom.
      */
    //Controles
    int rightKey = glfwGetKey(window, GLFW_KEY_RIGHT);
    int leftKey = glfwGetKey(window, GLFW_KEY_LEFT);
    int upKey = glfwGetKey(window, GLFW_KEY_UP);
    int downKey = glfwGetKey(window, GLFW_KEY_DOWN);

    if (!scene->camera().isTraveling()) {
        //Mise à jour en fonction de la planete actuelle
        if (currentPlanet != -1) {
            //TODO check not out of bounds
            glm::vec3 planetGraphicalPos = planets[currentPlanet].render->getPosition();
            scene->camera().moveCameraByCenterPoint(planetGraphicalPos.x, planetGraphicalPos.y, planetGraphicalPos.z);
        }

        glm::vec3 cameraUp = scene->camera().getUp();

        if (cameraUp.x == 0 && cameraUp.y == 0) {
            if (rightKey == GLFW_PRESS && leftKey != GLFW_PRESS) {
                scene->camera().rotateZ(180.0f / 70.0f);
            }
            else if (leftKey == GLFW_PRESS && rightKey != GLFW_PRESS) {
                scene->camera().rotateZ(- 180.0f / 70.0f);
            }

            if (upKey == GLFW_PRESS && downKey != GLFW_PRESS) {
                scene->camera().rotateUpDown(180.0f / 70.0f);
            }
            else if (downKey == GLFW_PRESS && upKey != GLFW_PRESS) {
                scene->camera().rotateUpDown(- 180.0f / 70.0f);
            }
        }
        else if (cameraUp.z == 0){
            //TODO contrôle de la caméra en vue de dessus
        }

    }

    //Mise à jour du monde (précision ~ 1h) t*10e6
    const double timeScale = 2;
    const double baseStep = 0.004;
    world->step(timeScale, (int) (timeScale / baseStep)); //TODO step tient compte du temps de calcul -> pour plus de précision
    // -> Sachant que les mesures effectuées sont enregistrées avec le bon temps dans le fichier.

    for (Planet &planet : planets) {
        auto &body = planet.body;

        if (body != nullptr) {
            //TODO check la présence de la planète 0
            double x = body->getX() - planets[0].body->getX();
            double y = body->getY() - planets[0].body->getY();
            double z = body->getZ() - planets[0].body->getZ();

            //Mise à jour des coordonnées de l'objet
            planet.render->setPosition((float) x, (float) y, (float) z);

            //Envoi des coordonnées dans le buffer
            std::string separator = ";";
            std::ostringstream stringstream;
            stringstream << world->getTime() << separator << x << separator << y << separator << z;
            planet.buffer.addLine(stringstream.str());

#ifdef SIMULATION_TO_COUT //TODO to parameter
            std::cout << planet.name << ":" << stringstream.str() << std::endl;
#endif
        }
    }

    if (enableGraphicalSimulation) scene->render(context);
}

//Declaration des callbacks
void glfwErrorCallback(int error, const char* description) {
    std::cerr << "There was a glfw error : " << description << std::endl;
}

void glfwKeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods) {

    if (action == GLFW_PRESS) {
        if (key == GLFW_KEY_KP_0) {
            currentPlanet = -1;

            auto traveling = std::make_unique<Traveling>(
                    scene->camera(), 0, 0, 30, 0, 0, 0, 0, 1, 0
            );
            traveling->setDuration(0.5f);
            scene->camera().traveling(traveling);
        }
        else if (key >= GLFW_KEY_KP_1 && key <= GLFW_KEY_KP_9){
            int targetPlanet = key - GLFW_KEY_KP_1;

            if (targetPlanet < planets.size()) {
                currentPlanet = targetPlanet;

                std::shared_ptr<Body> planetBody = planets[currentPlanet].body;

                //TODO le 15 en fonction du radius de la planète.

                auto traveling = std::make_unique<Traveling>(
                        scene->camera(),
                        planetBody->getX() + 15, planetBody->getY() + 15, planetBody->getZ() + 15,
                        planetBody->getX(), planetBody->getY(), planetBody->getZ(), 0, 0, 1
                );
                traveling->setDuration(0.5f);
                scene->camera().traveling(traveling);
            }
        }
    }
}

void glfwScrollCallback(GLFWwindow* window, double xoffset, double yoffset) {
    scene->camera().zoom((float) pow(1.2, - yoffset));
}
<commit_msg>Brainstorming avec les autres membres de l'équipe<commit_after>//
// Created by louis on 06/10/16.
//

#include <iostream>
#include <sstream>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <zconf.h>
#include <memory>

#include "FileBuffer.h"
#include "rendering/Context.h"
#include "rendering/Scene.h"
#include "rendering/Renderable.h"
#include "rendering/RenderableSphere.h"
#include "physics/World.h"
#include "physics/Body.h"
#include "rendering/RenderableTrajectory.h"

//DECLARATIONS

//#define SIMULATION_TO_COUT

//TODO rajouter des constantes

struct Planet {
    Planet(std::string name, std::shared_ptr<Body> body, std::shared_ptr<RenderableSphere> render);
    std::string name;
    std::shared_ptr<Body> body;
    std::shared_ptr<RenderableSphere> render;
    std::shared_ptr<RenderableTrajectory> trajectory;
    FileBuffer buffer;
};

std::string DATE;
int currentPlanet = 0;
std::unique_ptr<Scene> scene = nullptr;
std::unique_ptr<World> world = nullptr;
std::vector<Planet> planets;

//TODO struct parameters
bool enableGraphicalSimulation = true;

void addPlanet(std::string name, double mass, double x, double y, double z, double size);

/** Ajoute un objet 3D à la scene et au monde physique. */
void addPlanet(Planet planet);

/** Initialise la scène ainsi que le monde physique. */
void createScene();

/** J'ajoute le système solaire à la scène ! */
void addSolarSystem();

/** Cette méthode est le coeur du thread graphique,
 * Elle crée la fenetre, charge les ressources, effectue
 * la boucle principale de l'application, gère les
 * entrées sorties, puis détruit les ressources lorsque
 * l'utilisateur ferme la fenetre. */
void graphicThread();

/** Cette méthode est appelée à chaque tour de boucle pour
 * analyser les entrées sorties, mettre à jour le monde physique
 * et dessiner la scene à l'écran. */
void mainLoop(GLFWwindow * window, Context *context);

void glfwErrorCallback(int error, const char* description);
void glfwKeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods);
void glfwScrollCallback(GLFWwindow* window, double xoffset, double yoffset);

//MAIN

/** Arguments de la ligne de commande :
 * --method [méthode]
 * -m [methode] : choisir la méthode de calcul. Méthodes disponibles :
 * Euler, Runge-Kotta.
 * --input [dossier]
 * -i [dossier] : continuer une simulation précédente. Le dossier
 * indique l'emplacement de la sauvegarde.
 * --system [système]
 * -S [système] : choisir le système de départ (système solaire, ...)
 * --tick [secondes]
 * -t [secondes] choisir la durée d'un tick, qui détermine la vitesse de la simulation
 * -s [secondes] choisir le pas physique de la simulation */

int main(int argc, char** argv) {
    //printf("nombre : %.80Lf\n", M_PIl); //;)

    //TODO déterminer la date
    //TODO pouvoir reprendre les résultats de la simulation précédente

    createScene();

    graphicThread();

    for (Planet &object : planets) {
        object.buffer.writeData();
    }

    return 0;
}

//IMPLEMENTATIONS

Planet::Planet(std::string name, std::shared_ptr<Body> body, std::shared_ptr<RenderableSphere> render)
    : name(name), body(body), render(render), buffer(name + "_" + DATE),
      trajectory(std::make_shared<RenderableTrajectory>()) {

}

void createScene() {
    scene = std::make_unique<Scene>();

    Light light(LIGHT_POINT, 0, 0, 0);
    scene->setLight(light);

    //dist 1e10 m, mass 1e21 kg, tps 1e6 s, vit 1e4 m.s-1 -> G *= 1e3 (- 10*3 + 21 + 6*2)
    world = std::make_unique<World>();
    world->setGravityConstant(6.7e-11 * 1e3);

    addSolarSystem();
}

void addSolarSystem() {
    //Rendus
    auto moonRender = std::make_shared<RenderableSphere>(0.8, 64, 64);
    moonRender->addTexturePath("assets/moon.png");

    auto earthRender = std::make_shared<RenderableSphere>(0.8, 64, 64);
    earthRender->addTexturePath("assets/earth.png");

    auto jupiterRender = std::make_shared<RenderableSphere>(1.5, 64, 64);
    jupiterRender->addTexturePath("assets/jupiter.png");

    auto marsRender = std::make_shared<RenderableSphere>(0.7, 64, 64);
    marsRender->addTexturePath("assets/mars.png");

    auto sunRender = std::make_shared<RenderableSphere>(3, 64, 64);
    sunRender->getMaterial().setAmbient(0.85f, 0.25f, 0.1f);
    sunRender->addTexturePath("assets/sun.png");
    sunRender->getMaterial().setEmit(true);

    //Physique
    auto moonBody = std::make_shared<Body>(73.0);
    moonBody->setPosition(-20.0, 0, 0);
    moonBody->setSpeed(0, 5e-6, 0);

    auto earthBody = std::make_shared<Body>(6000.0);
    earthBody->setPosition(-15, 0, 0);
    earthBody->setSpeed(0, 2.9, 0);

    auto marsBody = std::make_shared<Body>(600.0);
    marsBody->setPosition(0, -24.9, 0);
    marsBody->setSpeed(2.19, 0, 0);

    auto jupiterBody = std::make_shared<Body>(1.9e6);
    jupiterBody->setPosition(0, 77.8, 0);
    jupiterBody->setSpeed(-1.3, 0, 0);

    auto sunBody = std::make_shared<Body>(1e9);

    //Ajout des objets
    addPlanet({"sun", sunBody, sunRender});
    addPlanet({"earth", earthBody, earthRender});
    //addPlanet({"moon", moonBody, moonRender});
    addPlanet({"mars", marsBody, marsRender});
    addPlanet({"jupiter", jupiterBody, jupiterRender});
}

void addPlanet(std::string name, double mass, double x, double y, double z, double size) {
    auto sphereRender = std::make_shared<RenderableSphere>(size, 64, 64);
    sphereRender->getMaterial().setDiffuse(0.85f, 0.75f, 0.1f);
    auto sphereBody = std::make_shared<Body>(mass);
    sphereBody->setPosition(x, y, z);
    addPlanet({name, sphereBody, sphereRender});
}

void addPlanet(Planet planet) {
    planets.push_back(planet);
    if (planet.body != nullptr) world->addObject(planet.body);
    if (planet.render != nullptr) {
        scene->addObject(planet.render);
        planet.render->getMaterial().setSpecular(0, 0, 0);
    }
}

void graphicThread() {
    int width, height;

    if (!glfwInit()) {
        std::cerr << "Erreur au lancement de glfw." << std::endl;
        return;
    }

    glfwSetErrorCallback(glfwErrorCallback);

    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
    glfwWindowHint(GLFW_SAMPLES, 16);
    GLFWwindow* window = glfwCreateWindow(800, 600, "Simulation", NULL, NULL);

    if (!window) {
        std::cerr << "Erreur au lancement de glfw." << std::endl;
        return;
    }

    glfwMakeContextCurrent(window);
    gladLoadGLLoader((GLADloadproc) glfwGetProcAddress);
    glfwSwapInterval(1);

    glfwSetKeyCallback(window, glfwKeyCallback);
    glfwSetScrollCallback(window, glfwScrollCallback);

    //Création du contexte
    Context context(window);

    glEnable(GL_MULTISAMPLE);
    glClearColor(3 / 255.0f, 0 / 255.0f, 32 / 255.0f, 1);

    while (!glfwWindowShouldClose(window)) {

        glfwGetFramebufferSize(window, &width, &height);
        glViewport(0, 0, width, height);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

        mainLoop(window, &context);

        glfwSwapBuffers(window);
        glfwPollEvents();

        if (enableGraphicalSimulation) usleep(20000);
    }

    glfwDestroyWindow(window);

    glfwTerminate();
}

void mainLoop(GLFWwindow *window, Context *context) {

    /*
     | -> LEFT et RIGHT pour tourner autour de l'axe UP (quasi toujours vers le haut)
     | -> UP et DOWN pour faire pivoter la position de la cam vers le haut ou le bas (limite aux extremes)
     | -> 0 pour la vue de dessus centrée sur 0, 0
     + -> En vue de dessus, LEFT et RIGHT font tourner l'axe UP selon l'axe Z.
     | -> vue de côté pour chacun des astres sur les touches 1, 2, 3, 4 ...
     | -> Rotation molette pour le zoom.
      */
    //Controles
    int rightKey = glfwGetKey(window, GLFW_KEY_RIGHT);
    int leftKey = glfwGetKey(window, GLFW_KEY_LEFT);
    int upKey = glfwGetKey(window, GLFW_KEY_UP);
    int downKey = glfwGetKey(window, GLFW_KEY_DOWN);

    if (!scene->camera().isTraveling()) {
        //Mise à jour en fonction de la planete actuelle
        if (currentPlanet != -1) {
            //TODO check not out of bounds
            glm::vec3 planetGraphicalPos = planets[currentPlanet].render->getPosition();
            scene->camera().moveCameraByCenterPoint(planetGraphicalPos.x, planetGraphicalPos.y, planetGraphicalPos.z);
        }

        glm::vec3 cameraUp = scene->camera().getUp();

        if (cameraUp.x == 0 && cameraUp.y == 0) {
            if (rightKey == GLFW_PRESS && leftKey != GLFW_PRESS) {
                scene->camera().rotateZ(180.0f / 70.0f);
            }
            else if (leftKey == GLFW_PRESS && rightKey != GLFW_PRESS) {
                scene->camera().rotateZ(- 180.0f / 70.0f);
            }

            if (upKey == GLFW_PRESS && downKey != GLFW_PRESS) {
                scene->camera().rotateUpDown(180.0f / 70.0f);
            }
            else if (downKey == GLFW_PRESS && upKey != GLFW_PRESS) {
                scene->camera().rotateUpDown(- 180.0f / 70.0f);
            }
        }
        else if (cameraUp.z == 0){
            //TODO contrôle de la caméra en vue de dessus
        }

    }

    //Mise à jour du monde (précision ~ 1h) t*10e6
    const double timeScale = 2;
    const double baseStep = 0.004;
    world->step(timeScale, (int) (timeScale / baseStep)); //TODO step tient compte du temps de calcul -> pour plus de précision
    // -> Sachant que les mesures effectuées sont enregistrées avec le bon temps dans le fichier.

    for (Planet &planet : planets) {
        auto &body = planet.body;

        if (body != nullptr) {
            //TODO check la présence de la planète 0
            double x = body->getX() - planets[0].body->getX();
            double y = body->getY() - planets[0].body->getY();
            double z = body->getZ() - planets[0].body->getZ();

            //Mise à jour des coordonnées de l'objet
            planet.render->setPosition((float) x, (float) y, (float) z);

            //Envoi des coordonnées dans le buffer
            std::string separator = ";";
            std::ostringstream stringstream;
            stringstream << world->getTime() << separator << x << separator << y << separator << z;
            planet.buffer.addLine(stringstream.str());

#ifdef SIMULATION_TO_COUT //TODO to parameter
            std::cout << planet.name << ":" << stringstream.str() << std::endl;
#endif
        }
    }

    if (enableGraphicalSimulation) scene->render(context);
}

//Declaration des callbacks
void glfwErrorCallback(int error, const char* description) {
    std::cerr << "There was a glfw error : " << description << std::endl;
}

void glfwKeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods) {

    if (action == GLFW_PRESS) {
        if (key == GLFW_KEY_KP_0) {
            currentPlanet = -1;

            auto traveling = std::make_unique<Traveling>(
                    scene->camera(), 0, 0, 30, 0, 0, 0, 0, 1, 0
            );
            traveling->setDuration(0.5f);
            scene->camera().traveling(traveling);
        }
        else if (key >= GLFW_KEY_KP_1 && key <= GLFW_KEY_KP_9){
            int targetPlanet = key - GLFW_KEY_KP_1;

            if (targetPlanet < planets.size()) {
                currentPlanet = targetPlanet;

                std::shared_ptr<Body> planetBody = planets[currentPlanet].body;

                //TODO le 15 en fonction du radius de la planète.

                auto traveling = std::make_unique<Traveling>(
                        scene->camera(),
                        planetBody->getX() + 15, planetBody->getY() + 15, planetBody->getZ() + 15,
                        planetBody->getX(), planetBody->getY(), planetBody->getZ(), 0, 0, 1
                );
                traveling->setDuration(0.5f);
                scene->camera().traveling(traveling);
            }
        }
    }
}

void glfwScrollCallback(GLFWwindow* window, double xoffset, double yoffset) {
    scene->camera().zoom((float) pow(1.2, - yoffset));
}
<|endoftext|>


<commit_before>/*
    This file is part of Kotel.

    Copyright © 2013 Vladimír Vondruš <mosra@centrum.cz>

    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.
*/

#include <numeric>
#include <DefaultFramebuffer.h>
#include <Renderer.h>
#ifndef CORRADE_TARGET_NACL
#include <Platform/Sdl2Application.h>
#else
#include <Platform/NaClApplication.h>
#endif
#include <Primitives/Cylinder.h>
#include <Shaders/MeshVisualizer.h>
#include <MeshTools/CompressIndices.h>
#include <MeshTools/Duplicate.h>
#include <MeshTools/FlipNormals.h>
#include <MeshTools/Interleave.h>
#include <MeshTools/Transform.h>
#include <SceneGraph/Camera3D.h>
#include <SceneGraph/Drawable.h>
#include <SceneGraph/DualQuaternionTransformation.h>
#include <SceneGraph/Scene.h>
#include <Trade/MeshData3D.h>

#ifdef MAGNUM_BUILD_STATIC
#include <Shaders/magnumShadersResourceImport.hpp>
#endif

#include "Kotel.h"

namespace Kotel { namespace Prototype {

typedef SceneGraph::Object<SceneGraph::DualQuaternionTransformation> Object3D;
typedef SceneGraph::Scene<SceneGraph::DualQuaternionTransformation> Scene3D;

class Forces3D: public Platform::Application {
    public:
        explicit Forces3D(const Arguments& arguments);

        void viewportEvent(const Vector2i& size) override;
        void drawEvent() override;

    private:
        Scene3D scene;
        Object3D* cameraObject;
        SceneGraph::Camera3D* camera;
        SceneGraph::DrawableGroup3D drawables;
};

Forces3D::Forces3D(const Arguments& arguments): Platform::Application(arguments, Configuration()
        #ifndef CORRADE_TARGET_NACL
        .setTitle("Kotel::Prototype::Forces3D")
        #endif
    )
{
    Renderer::setFeature(Renderer::Feature::DepthTest, true);
    Renderer::setFeature(Renderer::Feature::FaceCulling, true);
    Renderer::setClearColor(Color3(0.125f));

    (cameraObject = new Object3D(&scene))
        ->translate({1.0f, 1.2f, 10.0f});
    (camera = new SceneGraph::Camera3D(*cameraObject))
        ->setAspectRatioPolicy(SceneGraph::AspectRatioPolicy::Extend)
        .setPerspective(Deg(35.0f), 4.0f/3, 0.001f, 100.0f);

    class Tube: public Object3D, SceneGraph::Drawable3D {
        public:
            Tube(Object3D* parent, SceneGraph::DrawableGroup3D* drawables): Object3D(parent), SceneGraph::Drawable3D(*this, drawables), shader(Shaders::MeshVisualizer::Flag::Wireframe|Shaders::MeshVisualizer::Flag::NoGeometryShader) {
                Trade::MeshData3D cube = Primitives::Cylinder::solid(10, 16, 10.0f);
                std::vector<Float> vertexIndices(cube.indices().size(), 0.0f);
                std::iota(vertexIndices.begin(), vertexIndices.end(), 0.0f);
                MeshTools::flipFaceWinding(cube.indices());
                MeshTools::transformVectorsInPlace(Quaternion::rotation(Deg(90.0f), Vector3::xAxis()), cube.positions(0));
                MeshTools::interleave(mesh, vertexBuffer, Buffer::Usage::StaticDraw,
                    MeshTools::duplicate(cube.indices(), cube.positions(0)),
                    vertexIndices);

                mesh.setPrimitive(cube.primitive())
                    .addInterleavedVertexBuffer(vertexBuffer, 0,
                        Shaders::MeshVisualizer::Position(), Shaders::MeshVisualizer::VertexIndex());
            }

        private:
            void draw(const Matrix4& transformationMatrix, SceneGraph::AbstractCamera3D& camera) override {
                shader.setTransformationProjectionMatrix(camera.projectionMatrix()*transformationMatrix)
                    .setViewportSize(Vector2(camera.viewport()))
                    .setColor(Color3(0.15f))
                    .setWireframeColor(Color4::fromHSV(Deg(25.0f), 0.75f, 0.9f, 0.75f))
                    .use();

                mesh.draw();
            }

            Buffer indexBuffer, vertexBuffer;
            Mesh mesh;
            Shaders::MeshVisualizer shader;
    };

    new Tube(&scene, &drawables);
}

void Forces3D::viewportEvent(const Vector2i& size) {
    defaultFramebuffer.setViewport({{}, size});

    camera->setViewport(size);
}

void Forces3D::drawEvent() {
    defaultFramebuffer.clear(FramebufferClear::Color|FramebufferClear::Depth);

    camera->draw(drawables);

    swapBuffers();
}

}}

MAGNUM_APPLICATION_MAIN(Kotel::Prototype::Forces3D)
<commit_msg>prototypes: try to use MSAA also for the 3D prototype.<commit_after>/*
    This file is part of Kotel.

    Copyright © 2013 Vladimír Vondruš <mosra@centrum.cz>

    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.
*/

#include <numeric>
#include <DefaultFramebuffer.h>
#include <Renderer.h>
#ifndef CORRADE_TARGET_NACL
#include <Platform/Sdl2Application.h>
#else
#include <Platform/NaClApplication.h>
#endif
#include <Primitives/Cylinder.h>
#include <Shaders/MeshVisualizer.h>
#include <MeshTools/CompressIndices.h>
#include <MeshTools/Duplicate.h>
#include <MeshTools/FlipNormals.h>
#include <MeshTools/Interleave.h>
#include <MeshTools/Transform.h>
#include <SceneGraph/Camera3D.h>
#include <SceneGraph/Drawable.h>
#include <SceneGraph/DualQuaternionTransformation.h>
#include <SceneGraph/Scene.h>
#include <Trade/MeshData3D.h>

#ifdef MAGNUM_BUILD_STATIC
#include <Shaders/magnumShadersResourceImport.hpp>
#endif

#include "Kotel.h"

namespace Kotel { namespace Prototype {

typedef SceneGraph::Object<SceneGraph::DualQuaternionTransformation> Object3D;
typedef SceneGraph::Scene<SceneGraph::DualQuaternionTransformation> Scene3D;

class Forces3D: public Platform::Application {
    public:
        explicit Forces3D(const Arguments& arguments);

        void viewportEvent(const Vector2i& size) override;
        void drawEvent() override;

    private:
        Scene3D scene;
        Object3D* cameraObject;
        SceneGraph::Camera3D* camera;
        SceneGraph::DrawableGroup3D drawables;
};

Forces3D::Forces3D(const Arguments& arguments): Platform::Application(arguments, nullptr) {
    /* Try to create MSAA context */
    Configuration conf;
    #ifndef CORRADE_TARGET_NACL
    conf.setTitle("Kotel::Prototype::Forces3D");
    #endif
    conf.setSampleCount(16);
    if(!tryCreateContext(conf)) {
        Warning() << "Cannot enable 16x MSAA, fallback to no-AA rendering";
        createContext(conf.setSampleCount(0));
    }

    Renderer::setFeature(Renderer::Feature::DepthTest, true);
    Renderer::setFeature(Renderer::Feature::FaceCulling, true);
    Renderer::setClearColor(Color3(0.125f));

    (cameraObject = new Object3D(&scene))
        ->translate({1.0f, 1.2f, 10.0f});
    (camera = new SceneGraph::Camera3D(*cameraObject))
        ->setAspectRatioPolicy(SceneGraph::AspectRatioPolicy::Extend)
        .setPerspective(Deg(35.0f), 4.0f/3, 0.001f, 100.0f);

    class Tube: public Object3D, SceneGraph::Drawable3D {
        public:
            Tube(Object3D* parent, SceneGraph::DrawableGroup3D* drawables): Object3D(parent), SceneGraph::Drawable3D(*this, drawables), shader(Shaders::MeshVisualizer::Flag::Wireframe|Shaders::MeshVisualizer::Flag::NoGeometryShader) {
                Trade::MeshData3D cube = Primitives::Cylinder::solid(10, 16, 10.0f);
                std::vector<Float> vertexIndices(cube.indices().size(), 0.0f);
                std::iota(vertexIndices.begin(), vertexIndices.end(), 0.0f);
                MeshTools::flipFaceWinding(cube.indices());
                MeshTools::transformVectorsInPlace(Quaternion::rotation(Deg(90.0f), Vector3::xAxis()), cube.positions(0));
                MeshTools::interleave(mesh, vertexBuffer, Buffer::Usage::StaticDraw,
                    MeshTools::duplicate(cube.indices(), cube.positions(0)),
                    vertexIndices);

                mesh.setPrimitive(cube.primitive())
                    .addInterleavedVertexBuffer(vertexBuffer, 0,
                        Shaders::MeshVisualizer::Position(), Shaders::MeshVisualizer::VertexIndex());
            }

        private:
            void draw(const Matrix4& transformationMatrix, SceneGraph::AbstractCamera3D& camera) override {
                shader.setTransformationProjectionMatrix(camera.projectionMatrix()*transformationMatrix)
                    .setViewportSize(Vector2(camera.viewport()))
                    .setColor(Color3(0.15f))
                    .setWireframeColor(Color4::fromHSV(Deg(25.0f), 0.75f, 0.9f, 0.75f))
                    .use();

                mesh.draw();
            }

            Buffer indexBuffer, vertexBuffer;
            Mesh mesh;
            Shaders::MeshVisualizer shader;
    };

    new Tube(&scene, &drawables);
}

void Forces3D::viewportEvent(const Vector2i& size) {
    defaultFramebuffer.setViewport({{}, size});

    camera->setViewport(size);
}

void Forces3D::drawEvent() {
    defaultFramebuffer.clear(FramebufferClear::Color|FramebufferClear::Depth);

    camera->draw(drawables);

    swapBuffers();
}

}}

MAGNUM_APPLICATION_MAIN(Kotel::Prototype::Forces3D)
<|endoftext|>


<commit_before>/*ckwg +5
 * Copyright 2011 by Kitware, Inc. All Rights Reserved. Please refer to
 * KITWARE_LICENSE.TXT for licensing information, or contact General Counsel,
 * Kitware, Inc., 28 Corporate Drive, Clifton Park, NY 12065.
 */

#include "python_convert_any.h"

#include <boost/python/converter/registry.hpp>
#include <boost/python/extract.hpp>
#include <boost/cstdint.hpp>

/**
 * \file python_convert_any.cxx
 *
 * \brief Helpers for working with boost::any in Python.
 */

using namespace boost::python;

boost_any_to_object
::boost_any_to_object()
{
  converter::registry::push_back(
    &convertible,
    &construct,
    type_id<boost::any>());
}

boost_any_to_object
::~boost_any_to_object()
{
}

void*
boost_any_to_object
::convertible(PyObject* obj)
{
  return obj;
}

#define REGISTER_TYPES(call) \
  call(std::string);         \
  call(int32_t);             \
  call(char);                \
  call(bool);                \
  call(double)

PyObject*
boost_any_to_object
::convert(boost::any const& a)
{
  if (a.empty())
  {
    return detail::none();
  }

  type_info const info(a.type());

  converter::registration const* const reg = converter::registry::query(info);

#define TRY_CONVERT_TO(T)                  \
  do                                       \
  {                                        \
    try                                    \
    {                                      \
      T const t = boost::any_cast<T>(a);   \
      object const o(t);                   \
      return incref(o.ptr());              \
    }                                      \
    catch (boost::bad_any_cast&)           \
    {                                      \
    }                                      \
    catch (error_already_set&)             \
    {                                      \
      /** \todo Log that there is not a */ \
      /** known converter for the type. */ \
      return detail::none();               \
    }                                      \
  } while (false)

  if (reg)
  {
    REGISTER_TYPES(TRY_CONVERT_TO);
  }

#undef TRY_CONVERT_TO

  /// \todo Log that the any has a type which is not supported yet.

  return detail::none();
}

void
boost_any_to_object
::construct(PyObject* obj, converter::rvalue_from_python_stage1_data* data)
{
  void* storage = reinterpret_cast<converter::rvalue_from_python_storage<boost::any>*>(data)->storage.bytes;

#define CONSTRUCT(args)            \
  do                               \
  {                                \
    new (storage) boost::any args; \
    data->convertible = storage;   \
    return;                        \
  } while (false)

  if (obj == Py_None)
  {
    CONSTRUCT(());
  }

#define TRY_CONVERT_FROM_RAW(T)        \
  do                                   \
  {                                    \
    extract<T> ex(obj);                \
    if (ex.check())                    \
    {                                  \
      CONSTRUCT((ex()));               \
    }                                  \
  } while (false)
#define TRY_CONVERT_FROM(T)      \
  TRY_CONVERT_FROM_RAW(T);       \
  TRY_CONVERT_FROM_RAW(T const); \
  TRY_CONVERT_FROM_RAW(T const&)

  REGISTER_TYPES(TRY_CONVERT_FROM);

#undef TRY_CONVERT_FROM
#undef TRY_CONVERT_FROM_RAW

  CONSTRUCT(());

#undef CONSTRUCT
}

#undef REGISTER_TYPES
<commit_msg>Add a const specifier<commit_after>/*ckwg +5
 * Copyright 2011 by Kitware, Inc. All Rights Reserved. Please refer to
 * KITWARE_LICENSE.TXT for licensing information, or contact General Counsel,
 * Kitware, Inc., 28 Corporate Drive, Clifton Park, NY 12065.
 */

#include "python_convert_any.h"

#include <boost/python/converter/registry.hpp>
#include <boost/python/extract.hpp>
#include <boost/cstdint.hpp>

/**
 * \file python_convert_any.cxx
 *
 * \brief Helpers for working with boost::any in Python.
 */

using namespace boost::python;

boost_any_to_object
::boost_any_to_object()
{
  converter::registry::push_back(
    &convertible,
    &construct,
    type_id<boost::any>());
}

boost_any_to_object
::~boost_any_to_object()
{
}

void*
boost_any_to_object
::convertible(PyObject* obj)
{
  return obj;
}

#define REGISTER_TYPES(call) \
  call(std::string);         \
  call(int32_t);             \
  call(char);                \
  call(bool);                \
  call(double)

PyObject*
boost_any_to_object
::convert(boost::any const& a)
{
  if (a.empty())
  {
    return detail::none();
  }

  type_info const info(a.type());

  converter::registration const* const reg = converter::registry::query(info);

#define TRY_CONVERT_TO(T)                  \
  do                                       \
  {                                        \
    try                                    \
    {                                      \
      T const t = boost::any_cast<T>(a);   \
      object const o(t);                   \
      return incref(o.ptr());              \
    }                                      \
    catch (boost::bad_any_cast&)           \
    {                                      \
    }                                      \
    catch (error_already_set&)             \
    {                                      \
      /** \todo Log that there is not a */ \
      /** known converter for the type. */ \
      return detail::none();               \
    }                                      \
  } while (false)

  if (reg)
  {
    REGISTER_TYPES(TRY_CONVERT_TO);
  }

#undef TRY_CONVERT_TO

  /// \todo Log that the any has a type which is not supported yet.

  return detail::none();
}

void
boost_any_to_object
::construct(PyObject* obj, converter::rvalue_from_python_stage1_data* data)
{
  void* storage = reinterpret_cast<converter::rvalue_from_python_storage<boost::any>*>(data)->storage.bytes;

#define CONSTRUCT(args)            \
  do                               \
  {                                \
    new (storage) boost::any args; \
    data->convertible = storage;   \
    return;                        \
  } while (false)

  if (obj == Py_None)
  {
    CONSTRUCT(());
  }

#define TRY_CONVERT_FROM_RAW(T)        \
  do                                   \
  {                                    \
    extract<T> const ex(obj);          \
    if (ex.check())                    \
    {                                  \
      CONSTRUCT((ex()));               \
    }                                  \
  } while (false)
#define TRY_CONVERT_FROM(T)      \
  TRY_CONVERT_FROM_RAW(T);       \
  TRY_CONVERT_FROM_RAW(T const); \
  TRY_CONVERT_FROM_RAW(T const&)

  REGISTER_TYPES(TRY_CONVERT_FROM);

#undef TRY_CONVERT_FROM
#undef TRY_CONVERT_FROM_RAW

  CONSTRUCT(());

#undef CONSTRUCT
}

#undef REGISTER_TYPES
<|endoftext|>


<commit_before>/* The MIT License

   Copyright (c) 2008 Genome Research Ltd (GRL).

   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.
*/

/* Contact: Heng Li <lh3@sanger.ac.uk> */

/* Last Modified: 12APR2009 */

/* De-macro'd by the ACE-team 18MAY2012 wattup! */

/*Converted into template classes by CTS 11DEC2014*/

#ifndef AC_KSEQ_H
  #define AC_KSEQ_H

#define HAVE_ZLIB  1
#define HAVE_BZIP2 1

#include <ctype.h>
#include <string>
#include <cstdlib>
#include <unistd.h>

#if HAVE_ZLIB
#include <zlib.h>
class FunctorZlib
{
public:
    int operator()(gzFile file, void * buffer, int len)
    {
        return gzread(file, buffer, len);
    }
};
#endif

#if HAVE_BZIP2
#include <bzlib.h>
class FunctorBZlib2
{
public:
    int operator()(BZFILE* file, void * buffer, int len)
    {
        return BZ2_bzread(file, buffer, len );
    }
};
#endif

class FunctorRead
{
public:
    size_t operator()(int fd, void *buf, size_t count)
    {
        return read(fd, buf, count);
    }
};

class kseq
{
public:
    kseq();
    ~kseq();
    std::string name;
    std::string comment;
    std::string seq;
    std::string qual;
    int last_char;
};

template<class ret_t, class ReadFunction>
class kstream
{
public:
    kstream(ret_t f, ReadFunction rf)
    {
        this->f = f;
        this->buf = (char*)malloc(4096);
        this->is_eof = 0;
        this->begin = 0;
        this->end = 0;
        this->readfunc = rf;
    }

    ~kstream()
    {
        free(buf);
    }

    int read(kseq& seq)
    {
        int c;
        if (seq.last_char == 0)
        {
            while ((c = this->getc()) != -1 && c != '>' && c != '@');
            if (c == -1)
                return -1;
            seq.last_char = c;
        }
        seq.comment.clear();
        seq.seq.clear();
        seq.qual.clear();

        if (this->getuntil(0, seq.name, &c) < 0)
            return -1;
        if (c != '\n')
            this->getuntil( '\n', seq.comment, 0);
        while ((c = this->getc()) != -1 && c != '>' && c != '+' && c != '@')
        {
            if (isgraph(c))
            {
                seq.seq += (char)c;
            }
        }
        if (c == '>' || c == '@')
            seq.last_char = c;

        if (c != '+')
            return (int)seq.seq.length();

        while ((c = this->getc()) != -1 && c != '\n');

        if (c == -1)
            return -2;
        while ((c = this->getc()) != -1 && seq.qual.length() < seq.seq.length()) {
            if (c >= 33 && c <= 127)
                seq.qual += (char)c;
        }
        seq.last_char = 0;
        if (seq.seq.length() != seq.qual.length())
            return -2;
        return (int)seq.seq.length();
    }

private:
    int getc()
    {
        if (this->is_eof && this->begin >= this->end)
            return -1;
        if (this->begin >= this->end)
        {
            this->begin = 0;
            this->end = this->readfunc(this->f, this->buf, 4096);
            if (this->end < 4096)
                this->is_eof = 1;
            if (this->end == 0)
                return -1;
        }
        return (int)this->buf[this->begin++];
    }

    int getuntil(int delimiter, std::string &str, int *dret)
    {
        if (dret)
            *dret = 0;
        if (!str.empty()) {
            str.clear();
        }

        if (this->begin >= this->end && this->is_eof)
            return -1;
        for (;;)
        {
            int i;
            if (this->begin >= this->end)
            {
                if (!this->is_eof)
                {
                    this->begin = 0;
                    this->end = this->readfunc(this->f, this->buf, 4096);
                    if (this->end < 4096)
                        this->is_eof = 1;
                    if (this->end == 0)
                        break;
                }
                else
                    break;
            }
            if (delimiter > 1)
            {
                for (i = this->begin; i < this->end; ++i)
                {
                    if (this->buf[i] == delimiter)
                        break;
                }
            }
            else if (delimiter == 0)
            {
                for (i = this->begin; i < this->end; ++i)
                {
                    if (isspace(this->buf[i]))
                        break;
                }
            }
            else if (delimiter == 1)
            {
                for (i = this->begin; i < this->end; ++i){
                    if (isspace(this->buf[i]) && this->buf[i] != ' ')
                        break;
                }
            }
            else i = 0;

            str.append(this->buf + this->begin, i - this->begin);
            this->begin = i + 1;
            if (i < this->end)
            {
                if (dret)
                    *dret = this->buf[i];
                break;
            }
        }
        return (int)str.length();
    }

    char *buf;
    int begin;
    int end;
    int is_eof;
    ret_t f;
    ReadFunction readfunc;
};

kseq::kseq()
{
    this->last_char = 0;
}

kseq::~kseq()
{}

#endif
<commit_msg>Update kseq.hpp<commit_after>/* The MIT License

   Copyright (c) 2008 Genome Research Ltd (GRL).

   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.
*/

/* Contact: Heng Li <lh3@sanger.ac.uk> */

/* Last Modified: 12APR2009 */

/* De-macro'd by the ACE-team 18MAY2012 wattup! */

/*Converted into template classes by CTS 11DEC2014*/

#ifndef AC_KSEQ_H
  #define AC_KSEQ_H

#define HAVE_ZLIB  1
#define HAVE_BZIP2 1

#include <ctype.h>
#include <string>
#include <cstdlib>
#include <unistd.h>

#if HAVE_ZLIB
#include <zlib.h>
class FunctorZlib
{
public:
    int operator()(gzFile file, void * buffer, int len)
    {
        return gzread(file, buffer, len);
    }
};
#endif

#if HAVE_BZIP2
#include <bzlib.h>
class FunctorBZlib2
{
public:
    int operator()(BZFILE* file, void * buffer, int len)
    {
        return BZ2_bzread(file, buffer, len );
    }
};
#endif

class FunctorRead
{
public:
    size_t operator()(int fd, void *buf, size_t count)
    {
        return read(fd, buf, count);
    }
};

class kseq
{
public:
    kseq();
    ~kseq();
    std::string name;
    std::string comment;
    std::string seq;
    std::string qual;
    int last_char;
};

template<class ret_t, class ReadFunction>
class kstream
{
public:
    kstream(ret_t f, ReadFunction rf)
    {
        this->f = f;
        this->buf = (char*)malloc(4096);
        this->is_eof = 0;
        this->begin = 0;
        this->end = 0;
        this->readfunc = rf;
    }

    ~kstream()
    {
        free(buf);
    }

    int read(kseq& seq)
    {
        int c;
        if (seq.last_char == 0)
        {
            while ((c = this->getc()) != -1 && c != '>' && c != '@');
            if (c == -1)
                return -1;
            seq.last_char = c;
        }
        seq.comment.clear();
        seq.seq.clear();
        seq.qual.clear();

        if (this->getuntil(0, seq.name, &c) < 0)
            return -1;
        if (c != '\n')
            this->getuntil( '\n', seq.comment, 0);
        while ((c = this->getc()) != -1 && c != '>' && c != '+' && c != '@')
        {
            if (isgraph(c))
            {
                seq.seq += (char)c;
            }
        }
        if (c == '>' || c == '@')
            seq.last_char = c;

        if (c != '+')
            return (int)seq.seq.length();

        while ((c = this->getc()) != -1 && c != '\n');

        if (c == -1)
            return -2;
        while ((c = this->getc()) != -1 && seq.qual.length() < seq.seq.length()) {
            if (c >= 33 && c <= 127)
                seq.qual += (char)c;
        }
        seq.last_char = 0;
        if (seq.seq.length() != seq.qual.length())
            return -2;
        return (int)seq.seq.length();
    }

private:
    int getc()
    {
        if (this->is_eof && this->begin >= this->end)
            return -1;
        if (this->begin >= this->end)
        {
            this->begin = 0;
            this->end = this->readfunc(this->f, this->buf, 4096);
            if (this->end < 4096)
                this->is_eof = 1;
            if (this->end == 0)
                return -1;
        }
        return (int)this->buf[this->begin++];
    }

    int getuntil(int delimiter, std::string &str, int *dret)
    {
        if (dret)
            *dret = 0;
        if (!str.empty()) {
            str.clear();
        }

        if (this->begin >= this->end && this->is_eof)
            return -1;
        for (;;)
        {
            int i;
            if (this->begin >= this->end)
            {
                if (!this->is_eof)
                {
                    this->begin = 0;
                    this->end = this->readfunc(this->f, this->buf, 4096);
                    if (this->end < 4096)
                        this->is_eof = 1;
                    if (this->end == 0)
                        break;
                }
                else
                    break;
            }
            if (delimiter > 1)
            {
                for (i = this->begin; i < this->end; ++i)
                {
                    if (this->buf[i] == delimiter)
                        break;
                }
            }
            else if (delimiter == 0)
            {
                for (i = this->begin; i < this->end; ++i)
                {
                    if (isspace(this->buf[i]))
                        break;
                }
            }
            else if (delimiter == 1)
            {
                for (i = this->begin; i < this->end; ++i){
                    if (isspace(this->buf[i]) && this->buf[i] != ' ')
                        break;
                }
            }
            else i = 0;

            str.append(this->buf + this->begin, i - this->begin);
            this->begin = i + 1;
            if (i < this->end)
            {
                if (dret)
                    *dret = this->buf[i];
                break;
            }
        }
        return (int)str.length();
    }

    char *buf;
    int begin;
    int end;
    int is_eof;
    ret_t f;
    ReadFunction readfunc;
};

inline kseq::kseq()
{
    this->last_char = 0;
}

inline kseq::~kseq()
{}

#endif
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    $RCSfile: itkVTKTetrahedralMeshReader.hxx,v $
  Language:  C++
  Date:      $Date: 2011-10-05 18:01:00 $
  Version:   $Revision: 1.19 $

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or https://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#ifndef itkVTKTetrahedralMeshReader_hxx
#define itkVTKTetrahedralMeshReader_hxx

#include "itkVTKTetrahedralMeshReader.h"
#include <fstream>
#include <cstdio>
#include <cstring>

namespace itk
{

//
// Constructor
//
template <typename TOutputMesh>
VTKTetrahedralMeshReader<TOutputMesh>::VTKTetrahedralMeshReader()
{
  //
  // Create the output
  //
  typename TOutputMesh::Pointer output = TOutputMesh::New();
  this->ProcessObject::SetNumberOfRequiredOutputs(1);
  this->ProcessObject::SetNthOutput(0, output.GetPointer());
}

//
// Destructor
//
template <typename TOutputMesh>
VTKTetrahedralMeshReader<TOutputMesh>::~VTKTetrahedralMeshReader()
{}

template <typename TOutputMesh>
void
VTKTetrahedralMeshReader<TOutputMesh>::GenerateData()
{
  OutputMeshType * outputMesh = this->GetOutput();

  outputMesh->SetCellsAllocationMethod(OutputMeshType::CellsAllocatedDynamicallyCellByCell);

  if (m_FileName == "")
  {
    itkExceptionMacro(<< "No input FileName");
  }

  //
  // Read input file
  //
  std::ifstream inputFile(m_FileName.c_str());

  if (!inputFile.is_open())
  {
    itkExceptionMacro(<< "Unable to open file\n"
                      << "inputFilename= " << m_FileName);
  }

  inputFile.imbue(std::locale::classic());
  std::string line;

  // The first line must be "# vtk DataFile Version x.x" where x.x can
  // vary
  std::getline(inputFile, m_Version, '\n');
  if (inputFile.fail())
  {
    itkExceptionMacro(<< "Error reading file: " << m_FileName << "\nUnexpected end-of-file trying to read first line.");
  }

  if (m_Version.find("# vtk DataFile Version ") == std::string::npos)
  {
    itkExceptionMacro(
      << "Error reading file: " << m_FileName << "\nOnly vtk legacy format files can be read."
      << "\nThis file does not start with the line: # vtk DataFile Version x.x where x.x is the version.");
  }

  // Next is a one line description
  std::getline(inputFile, m_Header, '\n');
  if (inputFile.eof())
  {
    itkExceptionMacro(<< "Error reading file: " << m_FileName << "\nUnexpected end-of-file trying to read header.");
  }

  // Next is the file format
  std::getline(inputFile, line, '\n');
  if (inputFile.eof())
  {
    itkExceptionMacro(<< "Error reading file: " << m_FileName << "\nUnexpected end-of-file trying to file format.");
  }

  if (line.find("ASCII") == std::string::npos)
  {
    itkExceptionMacro(<< "Error reading file: " << m_FileName << "\nFile format is " << line
                      << " but only ASCII files can be read.");
  }

  bool foundPoints = false;
  while (!inputFile.eof())
  {
    std::getline(inputFile, line, '\n');

    if (line.find("POINTS") != std::string::npos)
    {
      foundPoints = true;
      break;
    }
  }

  if (!foundPoints)
  {
    itkExceptionMacro(<< "Error reading file: " << m_FileName << "\nUnexpected end-of-file before finding POINTS.");
  }
  itkDebugMacro("POINTS line" << line);

  std::string pointLine(line, strlen("POINTS "), line.length());
  itkDebugMacro("pointLine " << pointLine);

  unsigned long numberOfPoints = NumericTraits<unsigned long>::ZeroValue();

  if (sscanf(pointLine.c_str(), "%lu", &numberOfPoints) != 1)
  {
    itkExceptionMacro(<< "Error reading file: " << m_FileName << "\nFailed to read numberOfPoints.\n"
                      << "       pointLine= " << pointLine);
  }

  itkDebugMacro("numberOfPoints= " << numberOfPoints);

  if (numberOfPoints < 1)
  {
    itkExceptionMacro(<< "Error reading file: " << m_FileName << "numberOfPoints < 1"
                      << "       numberOfPoints line= " << numberOfPoints);
  }

  PointsContainer * points = outputMesh->GetPoints();
  points->Reserve(numberOfPoints);

  //
  // Load the point coordinates into the itk::Mesh
  //

  PointType point;

  for (PointIdentifier pointId = 0; pointId < numberOfPoints; pointId++)
  {
    inputFile >> point;
    if (inputFile.eof())
    {
      itkExceptionMacro(<< "Error while reading file: " << m_FileName
                        << "\nUnexpected end-of-file trying to read points.");
    }

    if (inputFile.fail())
    {
      itkExceptionMacro(<< "Error reading file: " << m_FileName << "\nInput could not be interpreted as a point.");
    }

    outputMesh->SetPoint(pointId, point);
  }

  // Continue searching for the CELLS line
  bool foundCells = false;
  while (!inputFile.eof())
  {
    std::getline(inputFile, line, '\n');
    if (line.find("CELLS") != std::string::npos)
    {
      foundCells = true;
      break;
    }
  }

  if (!foundCells)
  {
    itkExceptionMacro(<< "Error reading file: " << m_FileName << "\nUnexpected end-of-file before finding CELLS.");
  }

  itkDebugMacro("CELLS line" << line);

  std::string cellsLine(line, strlen("CELLS "), line.length());
  itkDebugMacro("cellsLine " << cellsLine);

  //
  // Read the number of cells
  //

  unsigned long numberOfCells = NumericTraits<unsigned long>::ZeroValue();
  unsigned long numberOfIndices = NumericTraits<unsigned long>::ZeroValue();

  if (sscanf(cellsLine.c_str(), "%lu %lu", &numberOfCells, &numberOfIndices) != 2)
  {
    itkExceptionMacro(<< "Error reading file: " << m_FileName << "\nFailed to read numberOfCells from subline2"
                      << "\ncellsLine = " << cellsLine);
  }

  itkDebugMacro("numberOfCells " << numberOfCells);
  itkDebugMacro("numberOfIndices " << numberOfIndices);

  if (numberOfCells < 1)
  {
    itkExceptionMacro(<< "Error reading file: " << m_FileName
                      << "\nnumberOfCells < 1\nnumberOfCells= " << numberOfCells);
  }

  if (numberOfIndices < numberOfCells)
  {
    itkExceptionMacro(<< "Error reading file: " << m_FileName << "\nnumberOfIndices < numberOfCells\n"
                      << "numberOfIndices= " << numberOfIndices << "\n"
                      << "numberOfCells= " << numberOfCells);
  }

  //
  // Load the cells into the itk::Mesh
  //

  unsigned long numberOfCellPoints;
  long          ids[4];

  for (CellIdentifier cellId = 0; cellId < numberOfCells; cellId++)
  {
    std::getline(inputFile, line, '\n');
    if (inputFile.eof())
    {
      itkExceptionMacro(<< "Error reading file: " << m_FileName << "\nFailed to read " << numberOfCells
                        << " cells before the end of file."
                        << " Only read " << cellId + 1);
    }

    if (line.find("DATA") != std::string::npos)
    {
      itkExceptionMacro(<< "Error reading file: " << m_FileName << "\nRead keyword DATA");
    }

    unsigned long numberOfPointsFound;
    if ((numberOfPointsFound =
           sscanf(line.c_str(), "%lu %ld %ld %ld %ld", &numberOfCellPoints, &ids[0], &ids[1], &ids[2], &ids[3])) != 5)
    {
      itkExceptionMacro(<< "Error reading file: " << m_FileName
                        << "\nError parsing Tetrahedron CELLS . Expected 5 items but got " << numberOfPointsFound
                        << std::endl
                        << "Line is: " << line);
    }

    if (numberOfCellPoints != 4)
    {
      itkExceptionMacro(<< "Error reading file: " << m_FileName << "\nnumberOfCellPoints != 4\n"
                        << "numberOfCellPoints= " << numberOfCellPoints << "\ncellId = " << cellId
                        << ". VTKTetrahedralMeshReader can only read tetrahedra");
    }

    if (ids[0] < 0 || ids[1] < 0 || ids[2] < 0 || ids[3] < 0)
    {
      itkExceptionMacro(<< "Error reading file: " << m_FileName
                        << "point ids must be >= 0.\n"
                           "ids="
                        << ids[0] << " " << ids[1] << " " << ids[2] << " " << ids[3]);
    }

    if (static_cast<PointIdentifier>(ids[0]) >= numberOfPoints ||
        static_cast<PointIdentifier>(ids[1]) >= numberOfPoints ||
        static_cast<PointIdentifier>(ids[2]) >= numberOfPoints ||
        static_cast<PointIdentifier>(ids[3]) >= numberOfPoints)
    {
      itkExceptionMacro(<< "Error reading file: " << m_FileName << "Point ids must be < number of points: "
                        << numberOfPoints << "\nids= " << ids[0] << " " << ids[1] << " " << ids[2] << " " << ids[3]);
    }

    CellAutoPointer cell;

    auto * tetrahedronCell = new TetrahedronCellType;
    for (PointIdentifier pointId = 0; pointId < 4; pointId++)
    {
      tetrahedronCell->SetPointId(pointId, ids[pointId]);
    }

    cell.TakeOwnership(tetrahedronCell);
    outputMesh->SetCell(cellId, cell);
  }

  // Continue searching for the CELL_TYPES line
  bool bfoundCellTypes = false;
  while (!inputFile.eof())
  {
    std::getline(inputFile, line, '\n');
    if (line.find("CELL_TYPES") != std::string::npos)
    {
      bfoundCellTypes = true;
      break;
    }
  }

  if (!bfoundCellTypes)
  {
    itkExceptionMacro(<< "Error reading file: " << m_FileName << "\nUnexpected end-of-file before finding CELL_TYPES.");
  }

  itkDebugMacro("CELL_TYPES line" << line);

  std::string cellsTypesLine(line, strlen("CELL_TYPES "), line.length());

  itkDebugMacro("cellsTypesLine " << cellsTypesLine);

  unsigned int numberOfCellTypes = 0;
  if (sscanf(cellsTypesLine.c_str(), "%u", &numberOfCellTypes) != 1)
  {
    itkExceptionMacro(<< "Error reading file: " << m_FileName << "\nFailed to read numberOfCellTypes from subline2"
                      << "\ncellsTypesLine = " << cellsTypesLine);
  }

  if (static_cast<CellIdentifier>(numberOfCellTypes) != numberOfCells)
  {
    itkExceptionMacro(<< "Error reading file: " << m_FileName << "\nnumberOfCellTypes < numberOfCells ");
  }

  for (CellIdentifier cellId = 0; cellId < numberOfCellTypes; cellId++)
  {
    std::getline(inputFile, line, '\n');
    if (inputFile.eof())
    {
      itkExceptionMacro(<< "Error reading file: " << m_FileName << "\nFailed to read " << numberOfCellTypes
                        << " cells before the end of file."
                        << " Only read " << cellId + 1);
    }

    int cellTypeID = 0;
    int cellTypeFound;
    if ((cellTypeFound = sscanf(line.c_str(), "%d ", &cellTypeID)) != 1)
    {
      itkExceptionMacro(<< "Error reading file: " << m_FileName
                        << "\nError parsing Cells types. Expected 1 item but got " << cellTypeFound << std::endl
                        << "Line is: " << line);
    }

    constexpr int tetrahedralCellTypeID = 10;

    if (cellTypeID != tetrahedralCellTypeID)
    {
      itkExceptionMacro(<< "Error reading file: " << m_FileName << "\nCell type != 10\n"
                        << "Cell type = " << cellTypeID << ". VTKTetrahedralMeshReader can only read tetrahedra");
    }
  }

  bool foundPointData = false;

  while (!inputFile.eof())
  {
    std::getline(inputFile, line, '\n');

    if (line.find("POINT_DATA") != std::string::npos)
    {
      foundPointData = true;
      break;
    }
  }

  if (foundPointData)
  {
    using PointDataContainer = typename OutputMeshType::PointDataContainer;
    using PointDataContainerPointer = typename PointDataContainer::Pointer;

    PointDataContainerPointer pointDataContainer = PointDataContainer::New();
    pointDataContainer->Reserve(numberOfPoints);

    outputMesh->SetPointData(pointDataContainer);

    itkDebugMacro("POINT_DATA line" << line);

    // Skip two lines
    for (int j = 0; j < 2; j++)
    {
      if (!inputFile.eof())
      {
        std::getline(inputFile, line, '\n');
      }
      else
      {
        inputFile.close();
        return;
      }
    }

    double pointData;

    for (PointIdentifier pid = 0; pid < numberOfPoints; pid++)
    {
      if (inputFile.eof())
      {
        itkExceptionMacro(<< "Error reading file: " << m_FileName
                          << "\nUnexpected end-of-file while trying to read POINT_DATA."
                          << "Failed while trying to reading point data for id: " << pid);
      }
      inputFile >> pointData;
      outputMesh->SetPointData(pid, pointData);
    }
  }
  inputFile.close();
}

template <typename TOutputMesh>
void
VTKTetrahedralMeshReader<TOutputMesh>::PrintSelf(std::ostream & os, Indent indent) const
{
  Superclass::PrintSelf(os, indent);

  os << indent << "FileName: " << m_FileName << std::endl;
  os << indent << "Version: " << m_Version << std::endl;
  os << indent << "Header: " << m_Header << std::endl;
}

} // end of namespace itk

#endif
<commit_msg>COMP: update VTKTetrahedralMeshReader to enum class<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    $RCSfile: itkVTKTetrahedralMeshReader.hxx,v $
  Language:  C++
  Date:      $Date: 2011-10-05 18:01:00 $
  Version:   $Revision: 1.19 $

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or https://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#ifndef itkVTKTetrahedralMeshReader_hxx
#define itkVTKTetrahedralMeshReader_hxx

#include "itkVTKTetrahedralMeshReader.h"
#include <fstream>
#include <cstdio>
#include <cstring>

namespace itk
{

//
// Constructor
//
template <typename TOutputMesh>
VTKTetrahedralMeshReader<TOutputMesh>::VTKTetrahedralMeshReader()
{
  //
  // Create the output
  //
  typename TOutputMesh::Pointer output = TOutputMesh::New();
  this->ProcessObject::SetNumberOfRequiredOutputs(1);
  this->ProcessObject::SetNthOutput(0, output.GetPointer());
}

//
// Destructor
//
template <typename TOutputMesh>
VTKTetrahedralMeshReader<TOutputMesh>::~VTKTetrahedralMeshReader()
{}

template <typename TOutputMesh>
void
VTKTetrahedralMeshReader<TOutputMesh>::GenerateData()
{
  OutputMeshType * outputMesh = this->GetOutput();

  outputMesh->SetCellsAllocationMethod(MeshClassCellsAllocationMethodType::CellsAllocatedDynamicallyCellByCell);

  if (m_FileName == "")
  {
    itkExceptionMacro(<< "No input FileName");
  }

  //
  // Read input file
  //
  std::ifstream inputFile(m_FileName.c_str());

  if (!inputFile.is_open())
  {
    itkExceptionMacro(<< "Unable to open file\n"
                      << "inputFilename= " << m_FileName);
  }

  inputFile.imbue(std::locale::classic());
  std::string line;

  // The first line must be "# vtk DataFile Version x.x" where x.x can
  // vary
  std::getline(inputFile, m_Version, '\n');
  if (inputFile.fail())
  {
    itkExceptionMacro(<< "Error reading file: " << m_FileName << "\nUnexpected end-of-file trying to read first line.");
  }

  if (m_Version.find("# vtk DataFile Version ") == std::string::npos)
  {
    itkExceptionMacro(
      << "Error reading file: " << m_FileName << "\nOnly vtk legacy format files can be read."
      << "\nThis file does not start with the line: # vtk DataFile Version x.x where x.x is the version.");
  }

  // Next is a one line description
  std::getline(inputFile, m_Header, '\n');
  if (inputFile.eof())
  {
    itkExceptionMacro(<< "Error reading file: " << m_FileName << "\nUnexpected end-of-file trying to read header.");
  }

  // Next is the file format
  std::getline(inputFile, line, '\n');
  if (inputFile.eof())
  {
    itkExceptionMacro(<< "Error reading file: " << m_FileName << "\nUnexpected end-of-file trying to file format.");
  }

  if (line.find("ASCII") == std::string::npos)
  {
    itkExceptionMacro(<< "Error reading file: " << m_FileName << "\nFile format is " << line
                      << " but only ASCII files can be read.");
  }

  bool foundPoints = false;
  while (!inputFile.eof())
  {
    std::getline(inputFile, line, '\n');

    if (line.find("POINTS") != std::string::npos)
    {
      foundPoints = true;
      break;
    }
  }

  if (!foundPoints)
  {
    itkExceptionMacro(<< "Error reading file: " << m_FileName << "\nUnexpected end-of-file before finding POINTS.");
  }
  itkDebugMacro("POINTS line" << line);

  std::string pointLine(line, strlen("POINTS "), line.length());
  itkDebugMacro("pointLine " << pointLine);

  unsigned long numberOfPoints = NumericTraits<unsigned long>::ZeroValue();

  if (sscanf(pointLine.c_str(), "%lu", &numberOfPoints) != 1)
  {
    itkExceptionMacro(<< "Error reading file: " << m_FileName << "\nFailed to read numberOfPoints.\n"
                      << "       pointLine= " << pointLine);
  }

  itkDebugMacro("numberOfPoints= " << numberOfPoints);

  if (numberOfPoints < 1)
  {
    itkExceptionMacro(<< "Error reading file: " << m_FileName << "numberOfPoints < 1"
                      << "       numberOfPoints line= " << numberOfPoints);
  }

  PointsContainer * points = outputMesh->GetPoints();
  points->Reserve(numberOfPoints);

  //
  // Load the point coordinates into the itk::Mesh
  //

  PointType point;

  for (PointIdentifier pointId = 0; pointId < numberOfPoints; pointId++)
  {
    inputFile >> point;
    if (inputFile.eof())
    {
      itkExceptionMacro(<< "Error while reading file: " << m_FileName
                        << "\nUnexpected end-of-file trying to read points.");
    }

    if (inputFile.fail())
    {
      itkExceptionMacro(<< "Error reading file: " << m_FileName << "\nInput could not be interpreted as a point.");
    }

    outputMesh->SetPoint(pointId, point);
  }

  // Continue searching for the CELLS line
  bool foundCells = false;
  while (!inputFile.eof())
  {
    std::getline(inputFile, line, '\n');
    if (line.find("CELLS") != std::string::npos)
    {
      foundCells = true;
      break;
    }
  }

  if (!foundCells)
  {
    itkExceptionMacro(<< "Error reading file: " << m_FileName << "\nUnexpected end-of-file before finding CELLS.");
  }

  itkDebugMacro("CELLS line" << line);

  std::string cellsLine(line, strlen("CELLS "), line.length());
  itkDebugMacro("cellsLine " << cellsLine);

  //
  // Read the number of cells
  //

  unsigned long numberOfCells = NumericTraits<unsigned long>::ZeroValue();
  unsigned long numberOfIndices = NumericTraits<unsigned long>::ZeroValue();

  if (sscanf(cellsLine.c_str(), "%lu %lu", &numberOfCells, &numberOfIndices) != 2)
  {
    itkExceptionMacro(<< "Error reading file: " << m_FileName << "\nFailed to read numberOfCells from subline2"
                      << "\ncellsLine = " << cellsLine);
  }

  itkDebugMacro("numberOfCells " << numberOfCells);
  itkDebugMacro("numberOfIndices " << numberOfIndices);

  if (numberOfCells < 1)
  {
    itkExceptionMacro(<< "Error reading file: " << m_FileName
                      << "\nnumberOfCells < 1\nnumberOfCells= " << numberOfCells);
  }

  if (numberOfIndices < numberOfCells)
  {
    itkExceptionMacro(<< "Error reading file: " << m_FileName << "\nnumberOfIndices < numberOfCells\n"
                      << "numberOfIndices= " << numberOfIndices << "\n"
                      << "numberOfCells= " << numberOfCells);
  }

  //
  // Load the cells into the itk::Mesh
  //

  unsigned long numberOfCellPoints;
  long          ids[4];

  for (CellIdentifier cellId = 0; cellId < numberOfCells; cellId++)
  {
    std::getline(inputFile, line, '\n');
    if (inputFile.eof())
    {
      itkExceptionMacro(<< "Error reading file: " << m_FileName << "\nFailed to read " << numberOfCells
                        << " cells before the end of file."
                        << " Only read " << cellId + 1);
    }

    if (line.find("DATA") != std::string::npos)
    {
      itkExceptionMacro(<< "Error reading file: " << m_FileName << "\nRead keyword DATA");
    }

    unsigned long numberOfPointsFound;
    if ((numberOfPointsFound =
           sscanf(line.c_str(), "%lu %ld %ld %ld %ld", &numberOfCellPoints, &ids[0], &ids[1], &ids[2], &ids[3])) != 5)
    {
      itkExceptionMacro(<< "Error reading file: " << m_FileName
                        << "\nError parsing Tetrahedron CELLS . Expected 5 items but got " << numberOfPointsFound
                        << std::endl
                        << "Line is: " << line);
    }

    if (numberOfCellPoints != 4)
    {
      itkExceptionMacro(<< "Error reading file: " << m_FileName << "\nnumberOfCellPoints != 4\n"
                        << "numberOfCellPoints= " << numberOfCellPoints << "\ncellId = " << cellId
                        << ". VTKTetrahedralMeshReader can only read tetrahedra");
    }

    if (ids[0] < 0 || ids[1] < 0 || ids[2] < 0 || ids[3] < 0)
    {
      itkExceptionMacro(<< "Error reading file: " << m_FileName
                        << "point ids must be >= 0.\n"
                           "ids="
                        << ids[0] << " " << ids[1] << " " << ids[2] << " " << ids[3]);
    }

    if (static_cast<PointIdentifier>(ids[0]) >= numberOfPoints ||
        static_cast<PointIdentifier>(ids[1]) >= numberOfPoints ||
        static_cast<PointIdentifier>(ids[2]) >= numberOfPoints ||
        static_cast<PointIdentifier>(ids[3]) >= numberOfPoints)
    {
      itkExceptionMacro(<< "Error reading file: " << m_FileName << "Point ids must be < number of points: "
                        << numberOfPoints << "\nids= " << ids[0] << " " << ids[1] << " " << ids[2] << " " << ids[3]);
    }

    CellAutoPointer cell;

    auto * tetrahedronCell = new TetrahedronCellType;
    for (PointIdentifier pointId = 0; pointId < 4; pointId++)
    {
      tetrahedronCell->SetPointId(pointId, ids[pointId]);
    }

    cell.TakeOwnership(tetrahedronCell);
    outputMesh->SetCell(cellId, cell);
  }

  // Continue searching for the CELL_TYPES line
  bool bfoundCellTypes = false;
  while (!inputFile.eof())
  {
    std::getline(inputFile, line, '\n');
    if (line.find("CELL_TYPES") != std::string::npos)
    {
      bfoundCellTypes = true;
      break;
    }
  }

  if (!bfoundCellTypes)
  {
    itkExceptionMacro(<< "Error reading file: " << m_FileName << "\nUnexpected end-of-file before finding CELL_TYPES.");
  }

  itkDebugMacro("CELL_TYPES line" << line);

  std::string cellsTypesLine(line, strlen("CELL_TYPES "), line.length());

  itkDebugMacro("cellsTypesLine " << cellsTypesLine);

  unsigned int numberOfCellTypes = 0;
  if (sscanf(cellsTypesLine.c_str(), "%u", &numberOfCellTypes) != 1)
  {
    itkExceptionMacro(<< "Error reading file: " << m_FileName << "\nFailed to read numberOfCellTypes from subline2"
                      << "\ncellsTypesLine = " << cellsTypesLine);
  }

  if (static_cast<CellIdentifier>(numberOfCellTypes) != numberOfCells)
  {
    itkExceptionMacro(<< "Error reading file: " << m_FileName << "\nnumberOfCellTypes < numberOfCells ");
  }

  for (CellIdentifier cellId = 0; cellId < numberOfCellTypes; cellId++)
  {
    std::getline(inputFile, line, '\n');
    if (inputFile.eof())
    {
      itkExceptionMacro(<< "Error reading file: " << m_FileName << "\nFailed to read " << numberOfCellTypes
                        << " cells before the end of file."
                        << " Only read " << cellId + 1);
    }

    int cellTypeID = 0;
    int cellTypeFound;
    if ((cellTypeFound = sscanf(line.c_str(), "%d ", &cellTypeID)) != 1)
    {
      itkExceptionMacro(<< "Error reading file: " << m_FileName
                        << "\nError parsing Cells types. Expected 1 item but got " << cellTypeFound << std::endl
                        << "Line is: " << line);
    }

    constexpr int tetrahedralCellTypeID = 10;

    if (cellTypeID != tetrahedralCellTypeID)
    {
      itkExceptionMacro(<< "Error reading file: " << m_FileName << "\nCell type != 10\n"
                        << "Cell type = " << cellTypeID << ". VTKTetrahedralMeshReader can only read tetrahedra");
    }
  }

  bool foundPointData = false;

  while (!inputFile.eof())
  {
    std::getline(inputFile, line, '\n');

    if (line.find("POINT_DATA") != std::string::npos)
    {
      foundPointData = true;
      break;
    }
  }

  if (foundPointData)
  {
    using PointDataContainer = typename OutputMeshType::PointDataContainer;
    using PointDataContainerPointer = typename PointDataContainer::Pointer;

    PointDataContainerPointer pointDataContainer = PointDataContainer::New();
    pointDataContainer->Reserve(numberOfPoints);

    outputMesh->SetPointData(pointDataContainer);

    itkDebugMacro("POINT_DATA line" << line);

    // Skip two lines
    for (int j = 0; j < 2; j++)
    {
      if (!inputFile.eof())
      {
        std::getline(inputFile, line, '\n');
      }
      else
      {
        inputFile.close();
        return;
      }
    }

    double pointData;

    for (PointIdentifier pid = 0; pid < numberOfPoints; pid++)
    {
      if (inputFile.eof())
      {
        itkExceptionMacro(<< "Error reading file: " << m_FileName
                          << "\nUnexpected end-of-file while trying to read POINT_DATA."
                          << "Failed while trying to reading point data for id: " << pid);
      }
      inputFile >> pointData;
      outputMesh->SetPointData(pid, pointData);
    }
  }
  inputFile.close();
}

template <typename TOutputMesh>
void
VTKTetrahedralMeshReader<TOutputMesh>::PrintSelf(std::ostream & os, Indent indent) const
{
  Superclass::PrintSelf(os, indent);

  os << indent << "FileName: " << m_FileName << std::endl;
  os << indent << "Version: " << m_Version << std::endl;
  os << indent << "Header: " << m_Header << std::endl;
}

} // end of namespace itk

#endif
<|endoftext|>