<commit_before>#include "../stdafx.h"
#include "GraphView.h"
#include "../Document.h"
#include "../res/resource.h"
#include "ViewUtil.h"
#include "../SideView.h"
#include "../MainWindow.h"
#include "../MainView.h"
#include "../CPlotApp.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

enum
{
	ID_desc = 2000,
	ID_visible
};

IMPLEMENT_DYNAMIC(GraphView, CWnd)
BEGIN_MESSAGE_MAP(GraphView, CWnd)
	ON_WM_CREATE()
	ON_WM_SIZE()
	ON_BN_CLICKED(ID_visible, OnVisible)
	ON_BN_CLICKED(ID_desc,    OnSelect)
	//ON_LBN_DBLCLK(ID_name, OnEdit)
END_MESSAGE_MAP()

GraphView::GraphView(SideSectionGraphs &parent, Graph &g)
: parent(parent), g_id(g.oid())
{
}

BOOL GraphView::PreCreateWindow(CREATESTRUCT &cs)
{
	cs.style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
	return CWnd::PreCreateWindow(cs);
}

BOOL GraphView::Create(const RECT &rect, CWnd *parent, UINT ID)
{
	static bool init = false;
	if (!init)
	{
		WNDCLASS wndcls; memset(&wndcls, 0, sizeof(WNDCLASS));
		wndcls.style = CS_DBLCLKS;
		wndcls.lpfnWndProc = ::DefWindowProc;
		wndcls.hInstance = AfxGetInstanceHandle();
		wndcls.hCursor = theApp.LoadStandardCursor(IDC_ARROW);
		wndcls.lpszMenuName = NULL;
		wndcls.lpszClassName = _T("GraphView");
		if (!AfxRegisterClass(&wndcls)) throw std::runtime_error("AfxRegisterClass(GraphView) failed");
		init = true;
	}

	return CWnd::Create(_T("GraphView"), NULL, WS_CHILD | WS_TABSTOP, rect, parent, ID);
}

int GraphView::OnCreate(LPCREATESTRUCT cs)
{
	if (CWnd::OnCreate(cs) < 0) return -1;
	EnableScrollBarCtrl(SB_BOTH, FALSE);

	START_CREATE;

	desc.Create(_T(""), WS_CHILD | BS_PUSHBUTTON, whatever, this, ID_desc);
	desc.SetFont(&controlFont());
	desc.m_nFlatStyle = CMFCButton::BUTTONSTYLE_NOBORDERS;
	desc.m_bDrawFocus = false;
	desc.m_nAlignStyle = CMFCButton::ALIGN_LEFT;

	CHECK(visible, "");
	return 0;
}

int GraphView::height(int w) const
{
	DS0;
	return DS(10+22);
}

void GraphView::OnVisible()
{
	Graph *g = graph(); if (!g) return;
	g->options.hidden = !g->options.hidden;
	visible.SetCheck(!g->options.hidden);
	Plot &plot = parent.document().plot;
	plot.update_axis();
	parent.Recalc(g);
}

void GraphView::OnSelect()
{
	Graph *g = graph(); if (!g) return;
	Plot &plot = parent.document().plot;
	plot.set_current_graph(g);

	parent.Update(false);
	MainWindow *w = (MainWindow*)GetParentFrame();
	w->GetMainView().Update();

}

void GraphView::Update(bool full)
{
	CRect bounds; GetClientRect(bounds);
	Graph *g = graph();
	if (!g) return;
	DS0;

	visible.SetCheck(!g->options.hidden);
	desc.SetWindowText(Convert(g->description_line()));
	Plot &plot = parent.document().plot;
	bool bold = (plot.number_of_graphs() > 1 && plot.current_graph() == g);
	desc.SetFont(&controlFont(bold));

	if (!full) return;

	const int W = bounds.Width();
	const int SPC = DS(5); // amount of spacing
	const int w1 = DS(20); // checkbox width
	const int x0 = SPC;  // row x start / amount of space on the left
	const int x1 = W - SPC;
	int y = SPC; // y for next control

	const int h_label = DS(14), h_edit = DS(20), h_delta = DS(20), h_button = DS(20), h_row = DS(22);

	MOVE(visible, x0, x0 + w1, y, h_button, h_row);
	MOVE(desc, x0 + w1 + SPC, x1, y, h_label, h_row);
}

void GraphView::OnInitialUpdate()
{
	Update(true);
}

void GraphView::OnSize(UINT type, int w, int h)
{
	CWnd::OnSize(type, w, h);
	EnableScrollBarCtrl(SB_BOTH, FALSE);
	Update(true);
}
<commit_msg>update when changing current graph<commit_after>#include "../stdafx.h"
#include "GraphView.h"
#include "../Document.h"
#include "../res/resource.h"
#include "ViewUtil.h"
#include "../SideView.h"
#include "../MainWindow.h"
#include "../MainView.h"
#include "../CPlotApp.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

enum
{
	ID_desc = 2000,
	ID_visible
};

IMPLEMENT_DYNAMIC(GraphView, CWnd)
BEGIN_MESSAGE_MAP(GraphView, CWnd)
	ON_WM_CREATE()
	ON_WM_SIZE()
	ON_BN_CLICKED(ID_visible, OnVisible)
	ON_BN_CLICKED(ID_desc,    OnSelect)
	//ON_LBN_DBLCLK(ID_name, OnEdit)
END_MESSAGE_MAP()

GraphView::GraphView(SideSectionGraphs &parent, Graph &g)
: parent(parent), g_id(g.oid())
{
}

BOOL GraphView::PreCreateWindow(CREATESTRUCT &cs)
{
	cs.style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
	return CWnd::PreCreateWindow(cs);
}

BOOL GraphView::Create(const RECT &rect, CWnd *parent, UINT ID)
{
	static bool init = false;
	if (!init)
	{
		WNDCLASS wndcls; memset(&wndcls, 0, sizeof(WNDCLASS));
		wndcls.style = CS_DBLCLKS;
		wndcls.lpfnWndProc = ::DefWindowProc;
		wndcls.hInstance = AfxGetInstanceHandle();
		wndcls.hCursor = theApp.LoadStandardCursor(IDC_ARROW);
		wndcls.lpszMenuName = NULL;
		wndcls.lpszClassName = _T("GraphView");
		if (!AfxRegisterClass(&wndcls)) throw std::runtime_error("AfxRegisterClass(GraphView) failed");
		init = true;
	}

	return CWnd::Create(_T("GraphView"), NULL, WS_CHILD | WS_TABSTOP, rect, parent, ID);
}

int GraphView::OnCreate(LPCREATESTRUCT cs)
{
	if (CWnd::OnCreate(cs) < 0) return -1;
	EnableScrollBarCtrl(SB_BOTH, FALSE);

	START_CREATE;

	desc.Create(_T(""), WS_CHILD | BS_PUSHBUTTON, whatever, this, ID_desc);
	desc.SetFont(&controlFont());
	desc.m_nFlatStyle = CMFCButton::BUTTONSTYLE_NOBORDERS;
	desc.m_bDrawFocus = false;
	desc.m_nAlignStyle = CMFCButton::ALIGN_LEFT;

	CHECK(visible, "");
	return 0;
}

int GraphView::height(int w) const
{
	DS0;
	return DS(10+22);
}

void GraphView::OnVisible()
{
	Graph *g = graph(); if (!g) return;
	g->options.hidden = !g->options.hidden;
	visible.SetCheck(!g->options.hidden);
	Plot &plot = parent.document().plot;
	plot.update_axis();
	parent.Recalc(g);
}

void GraphView::OnSelect()
{
	Graph *g = graph(); if (!g) return;
	Plot &plot = parent.document().plot;
	plot.set_current_graph(g);

	parent.parent().UpdateAll();
	MainWindow *w = (MainWindow*)GetParentFrame();
	w->GetMainView().Update();
}

void GraphView::Update(bool full)
{
	CRect bounds; GetClientRect(bounds);
	Graph *g = graph();
	if (!g) return;
	DS0;

	visible.SetCheck(!g->options.hidden);
	desc.SetWindowText(Convert(g->description_line()));
	Plot &plot = parent.document().plot;
	bool bold = (plot.number_of_graphs() > 1 && plot.current_graph() == g);
	desc.SetFont(&controlFont(bold));

	if (!full) return;

	const int W = bounds.Width();
	const int SPC = DS(5); // amount of spacing
	const int w1 = DS(20); // checkbox width
	const int x0 = SPC;  // row x start / amount of space on the left
	const int x1 = W - SPC;
	int y = SPC; // y for next control

	const int h_label = DS(14), h_edit = DS(20), h_delta = DS(20), h_button = DS(20), h_row = DS(22);

	MOVE(visible, x0, x0 + w1, y, h_button, h_row);
	MOVE(desc, x0 + w1 + SPC, x1, y, h_label, h_row);
}

void GraphView::OnInitialUpdate()
{
	Update(true);
}

void GraphView::OnSize(UINT type, int w, int h)
{
	CWnd::OnSize(type, w, h);
	EnableScrollBarCtrl(SB_BOTH, FALSE);
	Update(true);
}
<|endoftext|>


<commit_before>#include "vector.h"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "LSM303.h"
#include "L3G4200D.h"
#include <sys/time.h>

/*
promising:
http://elinux.org/Interfacing_with_I2C_Devices
https://i2c.wiki.kernel.org/index.php/Main_Page
*/

// TODO: read http://www.cs.cmu.edu/~spiff/moedit99/expmap.pdf

int millis()
{
    struct timeval tv;
    gettimeofday(&tv, NULL);
    return (tv.tv_sec) * 1000 + (tv.tv_usec)/1000;
}

void streamRawValues(LSM303& compass, L3G4200D& gyro)
{
    compass.enableDefault();
    gyro.enableDefault();

    while(1)
    {
        compass.read();
        gyro.read();
        printf("%7d %7d %7d,  %7d %7d %7d,  %7d %7d %7d\n",
               compass.m(0), compass.m(1), compass.m(2),
               compass.a(0), compass.a(1), compass.a(2),
               gyro.g(0), gyro.g(1), gyro.g(2)
        );
        usleep(100*1000);
    }
}

void calibrate(LSM303& compass)
{
    compass.enableDefault();
    int_vector mag_max, mag_min;
    while(1)
    {
        compass.read();
        mag_min = mag_min.cwiseMin(compass.m);
        mag_max = mag_max.cwiseMax(compass.m);
        printf("%7d %7d %7d  %7d %7d %7d\n",
               mag_min(0), mag_min(1), mag_min(2),
               mag_max(0), mag_max(1), mag_max(2));
        usleep(10*1000);
        // TODO: have some way of writing to ~/.lsm303_mag_cal
    }
}

void loadCalibration(int_vector& mag_min, int_vector& mag_max)
{
    // TODO: recalibrate for my new IMU
    // TODO: load from ~/.lsm303_mag_cal instead of hardcoding
    mag_min = int_vector(-519, -476, -765);
    mag_max = int_vector(475, 623, 469);
}

static void enableSensors(LSM303& compass, L3G4200D& gyro)
{
    compass.writeAccReg(LSM303_CTRL_REG1_A, 0x47); // normal power mode, all axes enabled, 50 Hz
    compass.writeAccReg(LSM303_CTRL_REG4_A, 0x20); // 8 g full scale

    compass.writeMagReg(LSM303_MR_REG_M, 0x00); // continuous conversion mode
    // 15 Hz default

    gyro.writeReg(L3G4200D_CTRL_REG1, 0x0F); // normal power mode, all axes enabled, 100 Hz
    gyro.writeReg(L3G4200D_CTRL_REG4, 0x20); // 2000 dps full scale
}

// Calculate offsets, assuming the MiniMU is resting
// with is z axis pointing up.
static void calculateOffsets(LSM303& compass, L3G4200D& gyro,
                             vector& accel_offset, vector& gyro_offset)
{
    // LSM303 accelerometer: 8 g sensitivity.  3.8 mg/digit; 1 g = 256.
    // TODO: unify this with the other place in the code where we scale accelerometer readings.
    const int gravity = 256;

    gyro_offset = accel_offset = vector::Zero();
    const int sampleCount = 32;
    for(int i = 0; i < sampleCount; i++)
    {
        gyro.read();
        compass.readAcc();
        gyro_offset += gyro.g.cast<float>();
        accel_offset += compass.a.cast<float>();
        usleep(20*1000);
    }
    gyro_offset /= sampleCount;
    accel_offset /= sampleCount;
    accel_offset(2) -= gravity;

    if (accel_offset.norm() > 50)
    {
        fprintf(stderr, "Unable to calculate accelerometer offset because board was not resting in the correct orientation.\n");
        accel_offset = vector::Zero();
    }
}

// Returns the measured angular velocity vector
// in units of radians per second, in the body coordinate system.
static vector readGyro(L3G4200D& gyro, const vector& gyro_offset)
{
    // At the full-scale=2000 dps setting, the gyro datasheet says
    // we get 0.07 dps/digit.
    const float gyro_scale = 0.07 * 3.14159265 / 180;

    gyro.read();
    return ( gyro.g.cast<float>() - gyro_offset ) * gyro_scale;
}

// Returns acceleration vector in units of g, where g is 9.8 m/s^2,
// in the body coordinate system.
static vector readAcc(LSM303& compass, const vector& accel_offset)
{
    // LSM303 accelerometer: At 8 g sensitivity, the datasheet says
    // we get 3.9 mg/digit.
    // TODO: double check this figure using the correct datasheet
    const float accel_scale = 0.0039;

    compass.readAcc();
    return ( compass.a.cast<float>() - accel_offset ) * accel_scale;
}

// Returns the magnetic field vector in the body coordinate system.
// For each component, a value of 1 corresponds to the max value
// and a value of -1 corresponds to the min value.
static vector readMag(LSM303& compass, const int_vector& mag_min, const int_vector& mag_max)
{
    compass.readMag();
    vector m;
    m(0) = (float)(compass.m(0) - mag_min(0)) / (mag_max(0) - mag_min(0)) * 2 - 1;
    m(1) = (float)(compass.m(1) - mag_min(1)) / (mag_max(1) - mag_min(1)) * 2 - 1;
    m(2) = (float)(compass.m(2) - mag_min(2)) / (mag_max(2) - mag_min(2)) * 2 - 1;
    return m;
}

static matrix updateMatrix(const vector& w, float dt)
{
    matrix u = matrix::Identity();
    u(2,0) = -w(1) * dt;
    u(0,2) =  w(1) * dt;

    u(0,1) = -w(2) * dt;
    u(1,0) =  w(2) * dt;

    u(1,2) = -w(0) * dt;
    u(2,1) =  w(0) * dt;
    return u;
}

static matrix normalize(const matrix & m)
{
    //float error = m.row(0).dot(m.row(1));
    matrix norm;
    norm.row(0) = m.row(0) + m.row(1).cross(m.row(2))/10;
    norm.row(1) = m.row(1) + m.row(2).cross(m.row(0))/10;
    norm.row(2) = m.row(2) + m.row(0).cross(m.row(1))/10;
    norm.row(0).normalize();
    norm.row(1).normalize();
    norm.row(2).normalize();
    return norm;
}

void fuse_gyro_only(matrix& rotation, float dt, const vector& angular_velocity)
{
   rotation *= updateMatrix(angular_velocity, dt);

   rotation = normalize(rotation);
}

#define Kp_ROLLPITCH 1
#define Ki_ROLLPITCH 0.00002
#define Kp_YAW 1.2
#define Ki_YAW 0.00002

void fuse(matrix& rotation, float dt, const vector& angular_velocity,
  const vector& acceleration, const vector& magnetic_field)
{
    vector up = acceleration;     // usually true
    vector magnetic_east = magnetic_field.cross(up);
    vector east = magnetic_east;  // a rough approximation
    vector north = up.cross(east);

    matrix rotationFromCompass;
    rotationFromCompass.row(0) = east;
    rotationFromCompass.row(1) = north;
    rotationFromCompass.row(2) = up;
    rotationFromCompass.row(0).normalize();
    rotationFromCompass.row(1).normalize();
    rotationFromCompass.row(2).normalize();

    // We trust the accelerometer more if it is telling us 1G.
    float accel_weight = 1 - 2*abs(1 - acceleration.norm());
    if (accel_weight < 0){ accel_weight = 0; }

    vector omegaP(0,0,0);
    //static vector omegaI;

    // TMPHAX
    //rotation = matrix::Identity();
    //acceleration = vector(0,1,0);

    // Add a "torque" that makes our up vector (rotation.row(2))
    // get closer to the acceleration vector.
    vector errorRollPitch = acceleration.cross(rotation.row(2)) * accel_weight;

    fprintf(stderr, "errorRollPitch = %7.4f %7.4f %7.4f\n", errorRollPitch(0), errorRollPitch(1), errorRollPitch(2));

    omegaP += errorRollPitch * Kp_ROLLPITCH;
    //omegaI += errorRollPitch * Ki_ROLLPITCH;

    // Add a "torque" that makes our east vector (rotation.row(0))
    // get closer to east vector calculated from the compass.
    //vector errorYaw = east.cross(rotation.row(0));
    //omegaP += errorYaw * Kp_YAW;
    //omegaI += errorYaw * Ki_YAW;

    rotation *= updateMatrix(angular_velocity + omegaP, dt);
    rotation = normalize(rotation);
}

// DCM algorithm: http://diydrones.com/forum/topics/robust-estimator-of-the

void print(matrix m)
{
    printf("%7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f",
           m(0,0), m(0,1), m(0,2),
           m(1,0), m(1,1), m(1,2),
           m(2,0), m(2,1), m(2,2));
}

void ahrs(LSM303& compass, L3G4200D& gyro)
{
    int_vector mag_min, mag_max;
    loadCalibration(mag_min, mag_max);

    enableSensors(compass, gyro);

    vector accel_offset, gyro_offset;
    calculateOffsets(compass, gyro, accel_offset, gyro_offset);

    fprintf(stderr, "Gyro offset: %7f %7f %7f\nAccel offset: %7f %7f %7f (%7f)\n",
            gyro_offset(0), gyro_offset(1), gyro_offset(2),
            accel_offset(0), accel_offset(1), accel_offset(2),
            accel_offset.norm());

    // The rotation matrix that can convert a vector in body coordinates
    // to ground coordinates.
    matrix rotation = matrix::Identity();

    int start = millis(); // truncate 64-bit return value
    while(1)
    {
        int last_start = start;
        start = millis();
        float dt = (start-last_start)/1000.0;
        if (dt < 0){ throw "time went backwards"; }

        vector angular_velocity = readGyro(gyro, gyro_offset);
        vector acceleration = readAcc(compass, accel_offset);
        vector magnetic_field = readMag(compass, mag_min, mag_max); // TODO: read mag at 10Hz instead?  Why do others do that?

        fuse(rotation, dt, angular_velocity, acceleration, magnetic_field);

        //fprintf(stderr, "g: %8d %8d %8d\n", gyro.g(0), gyro.g(1), gyro.g(2));
        //fprintf(stderr, "m: %7.4f %7.4f %7.4f  m_raw: %8d %8d %8d\n", magnetic_field(0), magnetic_field(1), magnetic_field(2), compass.m(0), compass.m(1), compass.m(2));
        //fprintf(stderr, "dt: %7.4f  w: %7.4f %7.4f %7.4f\n", dt, angular_velocity(0), angular_velocity(1), angular_velocity(2));

        //rotation = rotationFromCompass;  // TMPHAX

        printf("%7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f  %7.4f %7.4f %7.4f  %7.4f %7.4f %7.4f\n",
               rotation(0,0), rotation(0,1), rotation(0,2),
               rotation(1,0), rotation(1,1), rotation(1,2),
               rotation(2,0), rotation(2,1), rotation(2,2),
               acceleration(0), acceleration(1), acceleration(2),
               magnetic_field(0), magnetic_field(1), magnetic_field(2));
        fflush(stdout);

        //std::cout << rotation;

        // Ensure that each iteration of the loop takes at least 20 ms.
        while(millis() - start < 20)
        {
            usleep(1000);
        }
    }
}

void tmphaxTest()
{
    const float turnAmount = 3.14159265/2;  // radians
    const float turnTime = 0.5; // seconds
    const int pieces = turnTime/0.02;
    const vector angular_velocity(0, 0, turnAmount/turnTime);

    const float dt = turnTime/pieces;
    matrix rotation = matrix::Identity();

    for (int i = 0; i < pieces; i++)
    {
        fuse_gyro_only(rotation, dt, angular_velocity);
    }

    print(rotation);
    putchar('\n');
    printf("tmphaxTest done\n");
    exit(3);
}

int main(int argc, char *argv[])
{
    I2CBus i2c("/dev/i2c-0");
    LSM303 compass(i2c);
    L3G4200D gyro(i2c);

    //tmphaxTest();

    uint8_t result = compass.readMagReg(LSM303_WHO_AM_I_M);
    if (result != 0x3C)
    {
        std::cerr << "Error getting \"Who Am I\" register." << std::endl;
        exit(2);
    }

    if (argc > 1)
    {
        if (0 == strcmp("cal", argv[1]))
        {
            calibrate(compass);
        }
        else if (0 == strcmp("raw", argv[1]))
        {
            streamRawValues(compass, gyro);
        }
        else
        {
            fprintf(stderr, "Unknown action '%s'.\n", argv[1]);
            exit(3);
        }
    }
    else
    {
        ahrs(compass, gyro);
    }

    return 0;
}
<commit_msg>made drift correction but it seems kind of bad<commit_after>#include "vector.h"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "LSM303.h"
#include "L3G4200D.h"
#include <sys/time.h>

/*
promising:
http://elinux.org/Interfacing_with_I2C_Devices
https://i2c.wiki.kernel.org/index.php/Main_Page
*/

// TODO: read http://www.cs.cmu.edu/~spiff/moedit99/expmap.pdf

int millis()
{
    struct timeval tv;
    gettimeofday(&tv, NULL);
    return (tv.tv_sec) * 1000 + (tv.tv_usec)/1000;
}

void streamRawValues(LSM303& compass, L3G4200D& gyro)
{
    compass.enableDefault();
    gyro.enableDefault();

    while(1)
    {
        compass.read();
        gyro.read();
        printf("%7d %7d %7d,  %7d %7d %7d,  %7d %7d %7d\n",
               compass.m(0), compass.m(1), compass.m(2),
               compass.a(0), compass.a(1), compass.a(2),
               gyro.g(0), gyro.g(1), gyro.g(2)
        );
        usleep(100*1000);
    }
}

void calibrate(LSM303& compass)
{
    compass.enableDefault();
    int_vector mag_max, mag_min;
    while(1)
    {
        compass.read();
        mag_min = mag_min.cwiseMin(compass.m);
        mag_max = mag_max.cwiseMax(compass.m);
        printf("%7d %7d %7d  %7d %7d %7d\n",
               mag_min(0), mag_min(1), mag_min(2),
               mag_max(0), mag_max(1), mag_max(2));
        usleep(10*1000);
        // TODO: have some way of writing to ~/.lsm303_mag_cal
    }
}

void loadCalibration(int_vector& mag_min, int_vector& mag_max)
{
    // TODO: recalibrate for my new IMU
    // TODO: load from ~/.lsm303_mag_cal instead of hardcoding
    mag_min = int_vector(-519, -476, -765);
    mag_max = int_vector(475, 623, 469);
}

static void enableSensors(LSM303& compass, L3G4200D& gyro)
{
    compass.writeAccReg(LSM303_CTRL_REG1_A, 0x47); // normal power mode, all axes enabled, 50 Hz
    compass.writeAccReg(LSM303_CTRL_REG4_A, 0x20); // 8 g full scale

    compass.writeMagReg(LSM303_MR_REG_M, 0x00); // continuous conversion mode
    // 15 Hz default

    gyro.writeReg(L3G4200D_CTRL_REG1, 0x0F); // normal power mode, all axes enabled, 100 Hz
    gyro.writeReg(L3G4200D_CTRL_REG4, 0x20); // 2000 dps full scale
}

// Calculate offsets, assuming the MiniMU is resting
// with is z axis pointing up.
static void calculateOffsets(LSM303& compass, L3G4200D& gyro,
                             vector& accel_offset, vector& gyro_offset)
{
    // LSM303 accelerometer: 8 g sensitivity.  3.8 mg/digit; 1 g = 256.
    // TODO: unify this with the other place in the code where we scale accelerometer readings.
    const int gravity = 256;

    gyro_offset = accel_offset = vector::Zero();
    const int sampleCount = 32;
    for(int i = 0; i < sampleCount; i++)
    {
        gyro.read();
        compass.readAcc();
        gyro_offset += gyro.g.cast<float>();
        accel_offset += compass.a.cast<float>();
        usleep(20*1000);
    }
    gyro_offset /= sampleCount;
    accel_offset /= sampleCount;
    accel_offset(2) -= gravity;

    if (accel_offset.norm() > 50)
    {
        fprintf(stderr, "Unable to calculate accelerometer offset because board was not resting in the correct orientation.\n");
        accel_offset = vector::Zero();
    }
}

// Returns the measured angular velocity vector
// in units of radians per second, in the body coordinate system.
static vector readGyro(L3G4200D& gyro, const vector& gyro_offset)
{
    // At the full-scale=2000 dps setting, the gyro datasheet says
    // we get 0.07 dps/digit.
    const float gyro_scale = 0.07 * 3.14159265 / 180;

    gyro.read();
    return ( gyro.g.cast<float>() - gyro_offset ) * gyro_scale;
}

// Returns acceleration vector in units of g, where g is 9.8 m/s^2,
// in the body coordinate system.
static vector readAcc(LSM303& compass, const vector& accel_offset)
{
    // LSM303 accelerometer: At 8 g sensitivity, the datasheet says
    // we get 3.9 mg/digit.
    // TODO: double check this figure using the correct datasheet
    const float accel_scale = 0.0039;

    compass.readAcc();
    return ( compass.a.cast<float>() - accel_offset ) * accel_scale;
}

// Returns the magnetic field vector in the body coordinate system.
// For each component, a value of 1 corresponds to the max value
// and a value of -1 corresponds to the min value.
static vector readMag(LSM303& compass, const int_vector& mag_min, const int_vector& mag_max)
{
    compass.readMag();
    vector m;
    m(0) = (float)(compass.m(0) - mag_min(0)) / (mag_max(0) - mag_min(0)) * 2 - 1;
    m(1) = (float)(compass.m(1) - mag_min(1)) / (mag_max(1) - mag_min(1)) * 2 - 1;
    m(2) = (float)(compass.m(2) - mag_min(2)) / (mag_max(2) - mag_min(2)) * 2 - 1;
    return m;
}

static matrix updateMatrix(const vector& w, float dt)
{
    matrix u = matrix::Identity();
    u(2,0) = -w(1) * dt;
    u(0,2) =  w(1) * dt;

    u(0,1) = -w(2) * dt;
    u(1,0) =  w(2) * dt;

    u(1,2) = -w(0) * dt;
    u(2,1) =  w(0) * dt;
    return u;
}

static matrix normalize(const matrix & m)
{
    //float error = m.row(0).dot(m.row(1));
    matrix norm;
    norm.row(0) = m.row(0) + m.row(1).cross(m.row(2))/10;
    norm.row(1) = m.row(1) + m.row(2).cross(m.row(0))/10;
    norm.row(2) = m.row(2) + m.row(0).cross(m.row(1))/10;
    norm.row(0).normalize();
    norm.row(1).normalize();
    norm.row(2).normalize();
    return norm;
}

void fuse_gyro_only(matrix& rotation, float dt, const vector& angular_velocity)
{
   rotation *= updateMatrix(angular_velocity, dt);

   rotation = normalize(rotation);
}

#define Kp_ROLLPITCH 1
#define Ki_ROLLPITCH 0.00002
#define Kp_YAW 1
#define Ki_YAW 0.00002

#define PI 3.14159265

void fuse(matrix& rotation, float dt, const vector& angular_velocity,
  const vector& acceleration, const vector& magnetic_field)
{
    vector up = acceleration;     // usually true
    vector magnetic_east = magnetic_field.cross(up);
    vector east = magnetic_east;  // a rough approximation
    vector north = up.cross(east);

    matrix rotationFromCompass;
    rotationFromCompass.row(0) = east;
    rotationFromCompass.row(1) = north;
    rotationFromCompass.row(2) = up;
    rotationFromCompass.row(0).normalize();
    rotationFromCompass.row(1).normalize();
    rotationFromCompass.row(2).normalize();

    // The board's x axis in earth coordinates.
    vector x = rotationFromCompass.col(0);
    x.normalize();
    x(2) = 0;
    float heading_weight = x.norm();

    // 0 = east, pi/2 = north
    float heading = atan2(x(1), x(0));

    fprintf(stderr, "B = %7.4f %7.4f %7.4f (%7.4f)  w=%7.4f h=%7.4f\n",
            magnetic_field(0), magnetic_field(1), magnetic_field(2),
            magnetic_field.norm(), heading_weight, heading*180/PI);

    // We trust the accelerometer more if it is telling us 1G.
    float accel_weight = 1 - 2*abs(1 - acceleration.norm());
    if (accel_weight < 0){ accel_weight = 0; }

    vector omegaP(0,0,0);
    //static vector omegaI;

    // Add a "torque" that makes our up vector (rotation.row(2))
    // get closer to the acceleration vector.
    vector errorRollPitch = acceleration.cross(rotation.row(2)) * accel_weight;

    //fprintf(stderr, "errorRollPitch = %7.4f %7.4f %7.4f\n", errorRollPitch(0), errorRollPitch(1), errorRollPitch(2));

    omegaP += errorRollPitch * Kp_ROLLPITCH;
    //omegaI += errorRollPitch * Ki_ROLLPITCH;

    // Add a "torque" that makes our east vector (rotation.row(0))
    // get closer to east vector calculated from the compass.
    vector errorYaw = east.cross(rotation.row(0));
    omegaP += errorYaw * Kp_YAW;
    //omegaI += errorYaw * Ki_YAW;

    rotation *= updateMatrix(angular_velocity + omegaP, dt);
    rotation = normalize(rotation);
}

// DCM algorithm: http://diydrones.com/forum/topics/robust-estimator-of-the

void print(matrix m)
{
    printf("%7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f",
           m(0,0), m(0,1), m(0,2),
           m(1,0), m(1,1), m(1,2),
           m(2,0), m(2,1), m(2,2));
}

void ahrs(LSM303& compass, L3G4200D& gyro)
{
    int_vector mag_min, mag_max;
    loadCalibration(mag_min, mag_max);

    enableSensors(compass, gyro);

    vector accel_offset, gyro_offset;
    calculateOffsets(compass, gyro, accel_offset, gyro_offset);

    fprintf(stderr, "Gyro offset: %7f %7f %7f\nAccel offset: %7f %7f %7f (%7f)\n",
            gyro_offset(0), gyro_offset(1), gyro_offset(2),
            accel_offset(0), accel_offset(1), accel_offset(2),
            accel_offset.norm());

    // The rotation matrix that can convert a vector in body coordinates
    // to ground coordinates.
    matrix rotation = matrix::Identity();

    int start = millis(); // truncate 64-bit return value
    while(1)
    {
        int last_start = start;
        start = millis();
        float dt = (start-last_start)/1000.0;
        if (dt < 0){ throw "time went backwards"; }

        vector angular_velocity = readGyro(gyro, gyro_offset);
        vector acceleration = readAcc(compass, accel_offset);
        vector magnetic_field = readMag(compass, mag_min, mag_max); // TODO: read mag at 10Hz instead?  Why do others do that?

        fuse(rotation, dt, angular_velocity, acceleration, magnetic_field);

        //fprintf(stderr, "g: %8d %8d %8d\n", gyro.g(0), gyro.g(1), gyro.g(2));
        //fprintf(stderr, "m: %7.4f %7.4f %7.4f  m_raw: %8d %8d %8d\n", magnetic_field(0), magnetic_field(1), magnetic_field(2), compass.m(0), compass.m(1), compass.m(2));
        //fprintf(stderr, "dt: %7.4f  w: %7.4f %7.4f %7.4f\n", dt, angular_velocity(0), angular_velocity(1), angular_velocity(2));

        //rotation = rotationFromCompass;  // TMPHAX

        printf("%7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f  %7.4f %7.4f %7.4f  %7.4f %7.4f %7.4f\n",
               rotation(0,0), rotation(0,1), rotation(0,2),
               rotation(1,0), rotation(1,1), rotation(1,2),
               rotation(2,0), rotation(2,1), rotation(2,2),
               acceleration(0), acceleration(1), acceleration(2),
               magnetic_field(0), magnetic_field(1), magnetic_field(2));
        fflush(stdout);

        //std::cout << rotation;

        // Ensure that each iteration of the loop takes at least 20 ms.
        while(millis() - start < 20)
        {
            usleep(1000);
        }
    }
}

void tmphaxTest()
{
    const float turnAmount = 3.14159265/2;  // radians
    const float turnTime = 0.5; // seconds
    const int pieces = turnTime/0.02;
    const vector angular_velocity(0, 0, turnAmount/turnTime);

    const float dt = turnTime/pieces;
    matrix rotation = matrix::Identity();

    for (int i = 0; i < pieces; i++)
    {
        fuse_gyro_only(rotation, dt, angular_velocity);
    }

    print(rotation);
    putchar('\n');
    printf("tmphaxTest done\n");
    exit(3);
}

int main(int argc, char *argv[])
{
    I2CBus i2c("/dev/i2c-0");
    LSM303 compass(i2c);
    L3G4200D gyro(i2c);

    //tmphaxTest();

    uint8_t result = compass.readMagReg(LSM303_WHO_AM_I_M);
    if (result != 0x3C)
    {
        std::cerr << "Error getting \"Who Am I\" register." << std::endl;
        exit(2);
    }

    if (argc > 1)
    {
        if (0 == strcmp("cal", argv[1]))
        {
            calibrate(compass);
        }
        else if (0 == strcmp("raw", argv[1]))
        {
            streamRawValues(compass, gyro);
        }
        else
        {
            fprintf(stderr, "Unknown action '%s'.\n", argv[1]);
            exit(3);
        }
    }
    else
    {
        ahrs(compass, gyro);
    }

    return 0;
}
<|endoftext|>


<commit_before>// based on http://stackoverflow.com/questions/4636456/stack-trace-for-c-using-gcc/4732119#4732119
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include <signal.h>

extern int done;
extern int emcOperatorError(int id, const char *fmt, ...);

void backtrace(int signo)
{
    char pid_buf[30];
    char name_buf[512];
    char filename[512];

    signal(signo, SIG_IGN); // prevent multiple invocations on same signal
    sprintf(pid_buf, "%d", getpid());
    sprintf(filename,"/tmp/backtrace.%s", pid_buf);

    name_buf[readlink("/proc/self/exe", name_buf, 511)]=0;
    int child_pid = fork();
    if (!child_pid) {
	fclose(stderr);
	stderr = freopen(filename, "a", stderr);
        dup2(2,1); // child: redirect output to stderr
        fprintf(stdout,"stack trace for %s pid=%s signal=%d\n",name_buf,pid_buf, signo);
        execlp("gdb", "gdb", "--batch", "-n", "-ex", "thread", "-ex", "bt", name_buf, pid_buf, NULL);
	emcOperatorError(0, "backtrace for %s (pid %s signal %d): gdb failed to start", name_buf, pid_buf, signo);
        abort(); /* If gdb failed to start */
    } else {
	int status;
        waitpid(child_pid, &status,0);
	if (signo == SIGUSR1) {  // continue running after backtrace
	    signal(SIGUSR1, backtrace);
	    fprintf(stderr, "%s continuing status=%d\n", name_buf, status);
	} else {
	    // this takes emcmodule.cc:EMC_COMMAND_TIMEOUT seconds to display:
	    if (status == 0) // backtrace succeeded
		emcOperatorError(0, "%s (pid %d) died on signal %d, backtrace stored in %s",
				 name_buf, getpid(), signo, filename);
	    fprintf(stderr, "%s exiting\n", name_buf);
	    done = 1;  // signal task to exit main loop
	}
    }
}
<commit_msg>task/backtrace: polish a bit<commit_after>// based on http://stackoverflow.com/questions/4636456/stack-trace-for-c-using-gcc/4732119#4732119
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include <signal.h>

extern int done;
extern int emcOperatorError(int id, const char *fmt, ...);
extern int emcOperatorText(int id, const char *fmt, ...);

void backtrace(int signo)
{
    char pid_buf[30];
    char name_buf[512];
    char filename[512];

    signal(signo, SIG_IGN); // prevent multiple invocations on same signal
    sprintf(pid_buf, "%d", getpid());
    sprintf(filename,"/tmp/backtrace.%s", pid_buf);

    name_buf[readlink("/proc/self/exe", name_buf, 511)]=0;
    int child_pid = fork();
    if (!child_pid) {
	fclose(stderr);
	stderr = freopen(filename, "a", stderr);
        dup2(2,1); // child: redirect output to stderr
        fprintf(stdout,"stack trace for %s pid=%s signal=%d\n",name_buf,pid_buf, signo);
        execlp("gdb", "gdb", "--batch", "-n", "-ex", "thread", "-ex", "bt", name_buf, pid_buf, NULL);
	emcOperatorError(0, "backtrace for %s (pid %s signal %d): gdb failed to start", name_buf, pid_buf, signo);
        abort(); /* If gdb failed to start */
    } else {
	int status;
        waitpid(child_pid, &status,0);
	if (signo == SIGUSR1) {  // continue running after backtrace
	    signal(SIGUSR1, backtrace);
	    emcOperatorText(0, "backtrace for %s stored in %s, continuing", name_buf, filename);
	    fprintf(stderr, "%s: backtrace stored in %s, continuing\n", name_buf, filename);
	} else {
	    // this takes emcmodule.cc:EMC_COMMAND_TIMEOUT seconds to display:
	    if (status == 0) // backtrace succeeded
		emcOperatorError(0, "%s (pid %d) died on signal %d, backtrace stored in %s",
				 name_buf, getpid(), signo, filename);
	    fprintf(stderr, "%s exiting\n", name_buf);
	    done = 1;  // signal task to exit main loop
	}
    }
}
<|endoftext|>


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

  Program:   Insight Segmentation & Registration Toolkit
  Module:    ShapeDetectApp.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 2002 Insight Consortium. All rights reserved.
  See ITKCopyright.txt or http://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.

=========================================================================*/
#include <fstream>
#include "ShapeDetectApp.h"
#include "AppUtility.h"

#include "RawVolumeReader.h"
#include "itkImageRegionIterator.h"
#include "itkExceptionObject.h"

#include "itkFastMarchingImageFilter.h"

#include "vnl/vnl_math.h"

#include <string>

ShapeDetectApp
::ShapeDetectApp()
{
  this->Initialize();
}

void
ShapeDetectApp
::Initialize()
{

  m_InputImage = InputImageType::New();
  m_EdgePotentialImage = ImageType::New();
  m_SegmentationMask = ImageType::New();
  m_DetectionFilter = DetectionFilterType::New();

  m_Sigma = 1.0;

  m_DumpPGMFiles = true;

}

void
ShapeDetectApp
::Execute()
{

  char         currentLine[150];
  char         buffer[150];
  unsigned int uNumbers[3];
  float       fValue;
  char         symbol;

  std::cout << std::endl;

  // Get input file name
  while(1)
    {
    std::cout << "Input file name: ";
    std::cin.getline( currentLine, 150);
    if( sscanf( currentLine, "%s", buffer ) >= 1 ) break;
    std::cout << "Error: filename expected." << std::endl;
    }
  m_InputFileName = buffer;

  // Get big endian flag
  while(1)
    {
    std::cout << "Input image big endian? [y|n]: ";
    std::cin.getline( currentLine, 150 );
    if( sscanf( currentLine, "%c", &symbol ) >= 1  &&
        ( symbol == 'y' || symbol == 'n' ) ) break;
    std::cout << "Error: 'y' or 'n' expected." << std::endl;
    }
  if( symbol == 'y' )
    {
    m_InputBigEndian = true;
    }
  else
    {
    m_InputBigEndian = false;
    }

  // Get input file size
  while(1)
    {
    std::cout << "Input image size: ";
    std::cin.getline( currentLine, 150 );
    if( sscanf( currentLine, "%d%d%d", uNumbers, uNumbers+1, uNumbers+2 ) >= 3 ) break;
    std::cout << "Error: three unsigned integers expected." << std::endl;
    }
  for( int j = 0; j < ImageDimension; j++ )
    {
    m_InputSize[j] = uNumbers[j];
    }

  // Read in input image
  if( !this->ReadImage( m_InputFileName.c_str(), m_InputSize,
    m_InputBigEndian, m_InputImage ) )
   {
    std::cout << "Error while reading in input volume: ";
    std::cout << m_InputFileName.c_str() << std::endl;
    return;
   }

  // Get input file name
  while(1)
    {
    std::cout << "PGM output directory: ";
    std::cin.getline( currentLine, 150);
    if( sscanf( currentLine, "%s", buffer ) >= 1 ) break;
    std::cout << "Error: directory name expected." << std::endl;
    }
  m_PGMDirectory = buffer;

  if( m_DumpPGMFiles )
    {
    //dump out the input image
    std::cout << "Writing PGM files of the input volume." << std::endl;
    if( !WritePGMFiles<InputImageType>(
        m_InputImage, m_PGMDirectory.c_str(), "input" ))
      {
      std::cout << "Error while writing PGM files.";
      std::cout << "Please make sure the path is valid." << std::endl;
      return;
      }
    }

  this->ComputeEdgePotentialMap();

  std::cout << std::endl << std::endl;
  // Set the initial seed
  while(1)
    {
    std::cout << "Set initial seed index: ";
    std::cin.getline( currentLine, 150 );
    if( sscanf( currentLine, "%d%d%d", uNumbers, uNumbers+1, uNumbers+2 ) >= 3 ) break;
    std::cout << "Error: three unsigned integers expected." << std::endl;
    }
  for( int j = 0; j < ImageDimension; j++ )
    {
    m_Seed[j] = uNumbers[j];
    }

  // run the filter
  std::cout << "Generating time crossing map." << std::endl;
  this->ComputeTimeCrossingMap();

  while(1)
   {
   std::cout << std::endl << "Command [s|t|d|x]: ";
   std::cin.getline( currentLine, 150 );
   if( sscanf( currentLine, "%s", buffer ) >= 1 )
     {
     // parse the command
     switch ( buffer[0] )
      {
      case 's' :
        if( sscanf( currentLine, "%c%d%d%d", &symbol, uNumbers, uNumbers+1, uNumbers+2 ) != 4 )
          {
          std::cout << "Error: three unsigned integers expected" << std::endl;
          continue;
          }
         for( int j = 0; j < ImageDimension; j++ )
          {
          m_Seed[j] = uNumbers[j];
          }
         std::cout << "Re-generating time crossing map." << std::endl;
         this->ComputeTimeCrossingMap();
         this->ThresholdTimeCrossingMap();
         this->WriteSegmentationImage();
         break;
      case 't' :
        if( sscanf( currentLine, "%c%f", &symbol, &fValue ) != 2 )
          {
          std::cout << "Error: one floating point value expected" << std::endl;
          continue;
          }
         m_Threshold = fValue;;
         std::cout << "Re-thresholding time crossing map." << std::endl;
         this->ThresholdTimeCrossingMap();
         this->WriteSegmentationImage();
         break;
        break;
      case 'd':
        std::cout << "Seed: " << m_Seed << "Threshold: " << m_Threshold << std::endl;
        break;
      case 'x' :
        std::cout << "Goodbye. " << std::endl;
        return;
        break;
      default :
        std::cout << "Not a valid command." << std::endl;
      } //end switch

    }

   } //end while

}

void
ShapeDetectApp
::ComputeTimeCrossingMap()
{

  // connect edge potential map
  m_DetectionFilter->SetSpeedImage( m_EdgePotentialImage );

  // setup trial points
  typedef DetectionFilterType::NodeType NodeType;
  typedef DetectionFilterType::NodeContainer NodeContainer;

  NodeContainer::Pointer trialPoints = NodeContainer::New();

  NodeType node;

  node.SetValue( 0.0 );
  node.SetIndex( m_Seed );
  trialPoints->InsertElement(0, node);

  m_DetectionFilter->SetTrialPoints( trialPoints );

  // specify the size of the output image
  m_DetectionFilter->SetOutputSize( m_InputImage->GetBufferedRegion().GetSize() );

  // update the marcher
  m_DetectionFilter->Update();

}

void
ShapeDetectApp
::ThresholdTimeCrossingMap()
{

  // threshold the time crossing map
  m_SegmentationMask->SetLargestPossibleRegion(
    m_InputImage->GetLargestPossibleRegion() );
  m_SegmentationMask->SetBufferedRegion(
    m_InputImage->GetBufferedRegion() );
  m_SegmentationMask->Allocate();

  typedef itk::ImageRegionIterator<ImageType>
   Iterator;
  Iterator inIter( m_DetectionFilter->GetOutput(),
    m_DetectionFilter->GetOutput()->GetBufferedRegion() );

  Iterator outIter( m_SegmentationMask,
    m_SegmentationMask->GetBufferedRegion() );

  while( !inIter.IsAtEnd() )
    {
    if( inIter.Get() <= m_Threshold )
      {
      outIter.Set( 1 );
      }
    else
      {
      outIter.Set( 0 );
      }
    ++inIter;
    ++outIter;
    }

}

void
ShapeDetectApp
::WriteSegmentationImage()
{

   if( m_DumpPGMFiles )
    {
    //dump out the segmented image
    if( !WritePGMFiles<ImageType>( m_SegmentationMask, m_PGMDirectory.c_str(), "seg" ) )
      {
      std::cout << "Error while writing PGM files.";
      std::cout << "Please make sure the path is valid." << std::endl;
      return;
      }
    }

}

void
ShapeDetectApp
::ComputeEdgePotentialMap()
{

  // compute derivative of the input image
  DerivativeFilterPointer deriv = DerivativeFilterType::New();
  deriv->SetInput( m_InputImage );
  deriv->SetSigma( m_Sigma );
  deriv->Update();

  // allocate memory for the map
  m_EdgePotentialImage->SetLargestPossibleRegion(
    m_InputImage->GetLargestPossibleRegion() );
  m_EdgePotentialImage->SetBufferedRegion(
    m_InputImage->GetBufferedRegion() );
  m_EdgePotentialImage->Allocate();

  //****
  //FIXME - use an itk filter once API are consistent
  //****
  // compute the magnitude
  typedef itk::ImageRegionIterator<DerivativeImageType>
    DerivativeIterator;
  typedef itk::ImageRegionIterator<ImageType>
    ImageIterator;

  DerivativeIterator derivIter( deriv->GetOutput(),
    deriv->GetOutput()->GetBufferedRegion() );
  ImageIterator mapIter( m_EdgePotentialImage,
    m_EdgePotentialImage->GetBufferedRegion() );

  while( !derivIter.IsAtEnd() )
    {

    float accum = 0;
    VectorType grad = derivIter.Get();

    for( int j = 0; j < ImageDimension; j++ )
      {
      accum += vnl_math_sqr( grad[j] );
      }

    accum = vnl_math_sqrt( accum );
//    mapIter.Set( 1.0 / ( 1.0 + accum ) );
    mapIter.Set( exp( -1.0 * accum ) );

    ++derivIter;
    ++mapIter;

    }

  if( m_DumpPGMFiles )
    {
    //dump out the input image
    std::cout << "Writing PGM files of the edge potential map." << std::endl;
    if( !WritePGMFiles<ImageType>(
        m_EdgePotentialImage, m_PGMDirectory.c_str(), "map" ))
      {
      std::cout << "Error while writing PGM files.";
      std::cout << "Please make sure the path is valid." << std::endl;
      return;
      }
    }

}

bool
ShapeDetectApp
::ReadImage(
const char * filename,
const SizeType& size,
bool  bigEndian,
InputImageType::Pointer & imgPtr
)
{

  // Read in a raw volume
  typedef itk::RawVolumeReader<InputPixelType,InputImageType> ReaderType;
  ReaderType::Pointer reader = ReaderType::New();

  reader->SetFileName( filename );
  reader->SetBigEndian( bigEndian );
  reader->SetSize( size );
  reader->Execute();

  imgPtr = reader->GetImage();

  return true;
}

<commit_msg>ENH: RawVolumeReader removed. It was replaced by explicit use of the      ImageFileReader and RawImageIO classes.<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    ShapeDetectApp.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 2002 Insight Consortium. All rights reserved.
  See ITKCopyright.txt or http://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.

=========================================================================*/
#include <fstream>
#include "ShapeDetectApp.h"
#include "AppUtility.h"

#include "itkImageRegionIterator.h"
#include "itkExceptionObject.h"

#include "itkFastMarchingImageFilter.h"

#include "itkImageFileReader.h"
#include "itkRawImageIO.h"

#include "vnl/vnl_math.h"

#include <string>

ShapeDetectApp
::ShapeDetectApp()
{
  this->Initialize();
}

void
ShapeDetectApp
::Initialize()
{

  m_InputImage = InputImageType::New();
  m_EdgePotentialImage = ImageType::New();
  m_SegmentationMask = ImageType::New();
  m_DetectionFilter = DetectionFilterType::New();

  m_Sigma = 1.0;

  m_DumpPGMFiles = true;

}

void
ShapeDetectApp
::Execute()
{

  char         currentLine[150];
  char         buffer[150];
  unsigned int uNumbers[3];
  float       fValue;
  char         symbol;

  std::cout << std::endl;

  // Get input file name
  while(1)
    {
    std::cout << "Input file name: ";
    std::cin.getline( currentLine, 150);
    if( sscanf( currentLine, "%s", buffer ) >= 1 ) break;
    std::cout << "Error: filename expected." << std::endl;
    }
  m_InputFileName = buffer;

  // Get big endian flag
  while(1)
    {
    std::cout << "Input image big endian? [y|n]: ";
    std::cin.getline( currentLine, 150 );
    if( sscanf( currentLine, "%c", &symbol ) >= 1  &&
        ( symbol == 'y' || symbol == 'n' ) ) break;
    std::cout << "Error: 'y' or 'n' expected." << std::endl;
    }
  if( symbol == 'y' )
    {
    m_InputBigEndian = true;
    }
  else
    {
    m_InputBigEndian = false;
    }

  // Get input file size
  while(1)
    {
    std::cout << "Input image size: ";
    std::cin.getline( currentLine, 150 );
    if( sscanf( currentLine, "%d%d%d", uNumbers, uNumbers+1, uNumbers+2 ) >= 3 ) break;
    std::cout << "Error: three unsigned integers expected." << std::endl;
    }
  for( int j = 0; j < ImageDimension; j++ )
    {
    m_InputSize[j] = uNumbers[j];
    }

  // Read in input image
  if( !this->ReadImage( m_InputFileName.c_str(), m_InputSize,
    m_InputBigEndian, m_InputImage ) )
   {
    std::cout << "Error while reading in input volume: ";
    std::cout << m_InputFileName.c_str() << std::endl;
    return;
   }

  // Get input file name
  while(1)
    {
    std::cout << "PGM output directory: ";
    std::cin.getline( currentLine, 150);
    if( sscanf( currentLine, "%s", buffer ) >= 1 ) break;
    std::cout << "Error: directory name expected." << std::endl;
    }
  m_PGMDirectory = buffer;

  if( m_DumpPGMFiles )
    {
    //dump out the input image
    std::cout << "Writing PGM files of the input volume." << std::endl;
    if( !WritePGMFiles<InputImageType>(
        m_InputImage, m_PGMDirectory.c_str(), "input" ))
      {
      std::cout << "Error while writing PGM files.";
      std::cout << "Please make sure the path is valid." << std::endl;
      return;
      }
    }

  this->ComputeEdgePotentialMap();

  std::cout << std::endl << std::endl;
  // Set the initial seed
  while(1)
    {
    std::cout << "Set initial seed index: ";
    std::cin.getline( currentLine, 150 );
    if( sscanf( currentLine, "%d%d%d", uNumbers, uNumbers+1, uNumbers+2 ) >= 3 ) break;
    std::cout << "Error: three unsigned integers expected." << std::endl;
    }
  for( int j = 0; j < ImageDimension; j++ )
    {
    m_Seed[j] = uNumbers[j];
    }

  // run the filter
  std::cout << "Generating time crossing map." << std::endl;
  this->ComputeTimeCrossingMap();

  while(1)
   {
   std::cout << std::endl << "Command [s|t|d|x]: ";
   std::cin.getline( currentLine, 150 );
   if( sscanf( currentLine, "%s", buffer ) >= 1 )
     {
     // parse the command
     switch ( buffer[0] )
      {
      case 's' :
        if( sscanf( currentLine, "%c%d%d%d", &symbol, uNumbers, uNumbers+1, uNumbers+2 ) != 4 )
          {
          std::cout << "Error: three unsigned integers expected" << std::endl;
          continue;
          }
         for( int j = 0; j < ImageDimension; j++ )
          {
          m_Seed[j] = uNumbers[j];
          }
         std::cout << "Re-generating time crossing map." << std::endl;
         this->ComputeTimeCrossingMap();
         this->ThresholdTimeCrossingMap();
         this->WriteSegmentationImage();
         break;
      case 't' :
        if( sscanf( currentLine, "%c%f", &symbol, &fValue ) != 2 )
          {
          std::cout << "Error: one floating point value expected" << std::endl;
          continue;
          }
         m_Threshold = fValue;;
         std::cout << "Re-thresholding time crossing map." << std::endl;
         this->ThresholdTimeCrossingMap();
         this->WriteSegmentationImage();
         break;
        break;
      case 'd':
        std::cout << "Seed: " << m_Seed << "Threshold: " << m_Threshold << std::endl;
        break;
      case 'x' :
        std::cout << "Goodbye. " << std::endl;
        return;
        break;
      default :
        std::cout << "Not a valid command." << std::endl;
      } //end switch

    }

   } //end while

}

void
ShapeDetectApp
::ComputeTimeCrossingMap()
{

  // connect edge potential map
  m_DetectionFilter->SetSpeedImage( m_EdgePotentialImage );

  // setup trial points
  typedef DetectionFilterType::NodeType NodeType;
  typedef DetectionFilterType::NodeContainer NodeContainer;

  NodeContainer::Pointer trialPoints = NodeContainer::New();

  NodeType node;

  node.SetValue( 0.0 );
  node.SetIndex( m_Seed );
  trialPoints->InsertElement(0, node);

  m_DetectionFilter->SetTrialPoints( trialPoints );

  // specify the size of the output image
  m_DetectionFilter->SetOutputSize( m_InputImage->GetBufferedRegion().GetSize() );

  // update the marcher
  m_DetectionFilter->Update();

}

void
ShapeDetectApp
::ThresholdTimeCrossingMap()
{

  // threshold the time crossing map
  m_SegmentationMask->SetLargestPossibleRegion(
    m_InputImage->GetLargestPossibleRegion() );
  m_SegmentationMask->SetBufferedRegion(
    m_InputImage->GetBufferedRegion() );
  m_SegmentationMask->Allocate();

  typedef itk::ImageRegionIterator<ImageType>
   Iterator;
  Iterator inIter( m_DetectionFilter->GetOutput(),
    m_DetectionFilter->GetOutput()->GetBufferedRegion() );

  Iterator outIter( m_SegmentationMask,
    m_SegmentationMask->GetBufferedRegion() );

  while( !inIter.IsAtEnd() )
    {
    if( inIter.Get() <= m_Threshold )
      {
      outIter.Set( 1 );
      }
    else
      {
      outIter.Set( 0 );
      }
    ++inIter;
    ++outIter;
    }

}

void
ShapeDetectApp
::WriteSegmentationImage()
{

   if( m_DumpPGMFiles )
    {
    //dump out the segmented image
    if( !WritePGMFiles<ImageType>( m_SegmentationMask, m_PGMDirectory.c_str(), "seg" ) )
      {
      std::cout << "Error while writing PGM files.";
      std::cout << "Please make sure the path is valid." << std::endl;
      return;
      }
    }

}

void
ShapeDetectApp
::ComputeEdgePotentialMap()
{

  // compute derivative of the input image
  DerivativeFilterPointer deriv = DerivativeFilterType::New();
  deriv->SetInput( m_InputImage );
  deriv->SetSigma( m_Sigma );
  deriv->Update();

  // allocate memory for the map
  m_EdgePotentialImage->SetLargestPossibleRegion(
    m_InputImage->GetLargestPossibleRegion() );
  m_EdgePotentialImage->SetBufferedRegion(
    m_InputImage->GetBufferedRegion() );
  m_EdgePotentialImage->Allocate();

  //****
  //FIXME - use an itk filter once API are consistent
  //****
  // compute the magnitude
  typedef itk::ImageRegionIterator<DerivativeImageType>
    DerivativeIterator;
  typedef itk::ImageRegionIterator<ImageType>
    ImageIterator;

  DerivativeIterator derivIter( deriv->GetOutput(),
    deriv->GetOutput()->GetBufferedRegion() );
  ImageIterator mapIter( m_EdgePotentialImage,
    m_EdgePotentialImage->GetBufferedRegion() );

  while( !derivIter.IsAtEnd() )
    {

    float accum = 0;
    VectorType grad = derivIter.Get();

    for( int j = 0; j < ImageDimension; j++ )
      {
      accum += vnl_math_sqr( grad[j] );
      }

    accum = vnl_math_sqrt( accum );
//    mapIter.Set( 1.0 / ( 1.0 + accum ) );
    mapIter.Set( exp( -1.0 * accum ) );

    ++derivIter;
    ++mapIter;

    }

  if( m_DumpPGMFiles )
    {
    //dump out the input image
    std::cout << "Writing PGM files of the edge potential map." << std::endl;
    if( !WritePGMFiles<ImageType>(
        m_EdgePotentialImage, m_PGMDirectory.c_str(), "map" ))
      {
      std::cout << "Error while writing PGM files.";
      std::cout << "Please make sure the path is valid." << std::endl;
      return;
      }
    }

}

bool
ShapeDetectApp
::ReadImage(
const char * filename,
const SizeType& size,
bool  bigEndian,
InputImageType::Pointer & imgPtr
)
{

  // Read in a raw volume
  typedef itk::RawImageIO< InputPixelType, ImageDimension > RawReaderType;
  RawReaderType::Pointer rawIO = RawReaderType::New();

  rawIO->SetFileDimensionality( ImageDimension );
  rawIO->SetDimensions( 0, size[0] );
  rawIO->SetDimensions( 1, size[1] );
  rawIO->SetDimensions( 2, size[2] );

  typedef itk::ImageFileReader<InputImageType> ReaderType;
  ReaderType::Pointer reader = ReaderType::New();

  reader->SetImageIO( rawIO );
  reader->SetFileName( filename );

  reader->Update();

  imgPtr = reader->GetOutput();

  return true;
}

<|endoftext|>


<commit_before>#include "include/logging.h"

//Start the logger from a properties file
void Logger::start_log_from_file(std::string initFileName)
{
  //Read the properties file
  try {
    log4cpp::PropertyConfigurator::configure(initFileName);
  }
  catch ( log4cpp::ConfigureFailure &e ) {
    std::cout << "[log4cpp::ConfigureFailure] caught while reading" << initFileName << std::endl;
    std::cout << e.what();
    exit(1);
  }

  //Find the categories defined in the file
  // std::vector<log4cpp::Category*> categories = log4cpp::Category::getCurrentCategories();

  //Expose the logging handles
  log4cpp::Category& root = log4cpp::Category::getRoot();
  // log4cpp::Category& sub1 = log4cpp::Category::getInstance(std::string("sub1"));

  root_log = &root;
}

//Bring down the logging module
void Logger::end_log()
{
  if (!root_log) {
    std::cout << "Shutdown called with no logging module present" << std::endl;
  }
  else {
    log4cpp::Category::shutdown();
  }
}

//Constructor from a file
Logger::Logger(std::string initFileName)
{
start_log_from_file(initFileName);
}

//Destructor
Logger::~Logger()
{
  end_log();
}

//Exposures that log to the root category
void Logger::debug(std::string msg)
{
  if (!root_log)
  {
    std::cout << msg << std::endl;
  }
  else
  {
    root_log->debug(msg);
  }
}

void Logger::error(std::string msg)
{
  if (!root_log)
  {
    std::cout << msg << std::endl;
  }
  else
  {
    root_log->error(msg);
  }
}

void Logger::info(std::string msg)
{
  if (!root_log)
  {
    std::cout << msg << std::endl;
  }
  else
  {
    root_log->info(msg);
  }
}

void Logger::debug(const char * msg)
{
  if (!root_log)
  {
    std::cout << msg << std::endl;
  }
  else
  {
    root_log->debug(msg);
  }
}

void Logger::error(const char * msg)
{
  if (!root_log)
  {
    std::cout << msg << std::endl;
  }
  else
  {
    root_log->error(msg);
  }
}

void Logger::info(const char * msg)
{
  if (!root_log)
  {
    std::cout << msg << std::endl;
  }
  else
  {
    root_log->info(msg);
  }
}

void Logger::debug(int msg)
{
  if (!root_log)
  {
    std::cout << msg << std::endl;
  }
  else
  {
    root_log->debug(std::to_string(msg));
  }
}

void Logger::error(int msg)
{
  if (!root_log)
  {
    std::cout << msg << std::endl;
  }
  else
  {
    root_log->error(std::to_string(msg));
  }
}

void Logger::info(int msg)
{
  if (!root_log)
  {
    std::cout << msg << std::endl;
  }
  else
  {
    root_log->info(std::to_string(msg));
  }
}

void Logger::debug(float msg)
{
  if (!root_log)
  {
    std::cout << msg << std::endl;
  }
  else
  {
    root_log->debug(std::to_string(msg));
  }
}

void Logger::error(float msg)
{
  if (!root_log)
  {
    std::cout << msg << std::endl;
  }
  else
  {
    root_log->error(std::to_string(msg));
  }
}

void Logger::info(float msg)
{
  if (!root_log)
  {
    std::cout << msg << std::endl;
  }
  else
  {
    root_log->info(std::to_string(msg));
  }
}

void Logger::debug(double msg)
{
  if (!root_log)
  {
    std::cout << msg << std::endl;
  }
  else
  {
    root_log->debug(std::to_string(msg));
  }
}

void Logger::error(double msg)
{
  if (!root_log)
  {
    std::cout << msg << std::endl;
  }
  else
  {
    root_log->error(std::to_string(msg));
  }
}

void Logger::info(double msg)
{
  if (!root_log)
  {
    std::cout << msg << std::endl;
  }
  else
  {
    root_log->info(std::to_string(msg));
  }
}

//Pull down different categories by name
LoggingCategory* Logger::get_category(std::string name)
{
  return log4cpp::Category::getInstance(name);
}

//--------------------------Logging Category Methods---------------------------//

//Exposures that log to the root category
void LoggingCategory::debug(std::string msg)
{
  if (!int_category)
  {
    std::cout << name << ": " << msg << std::endl;
  }
  else
  {
    int_category->debug(msg);
  }
}

void LoggingCategory::error(std::string msg)
{
  if (!int_category)
  {
    std::cout << name << ": " << msg << std::endl;
  }
  else
  {
    int_category->error(msg);
  }
}

void LoggingCategory::info(std::string msg)
{
  if (!int_category)
  {
    std::cout << name << ": " << msg << std::endl;
  }
  else
  {
    int_category->info(msg);
  }
}

void LoggingCategory::debug(const char * msg)
{
  if (!int_category)
  {
    std::cout << name << ": " << msg << std::endl;
  }
  else
  {
    int_category->debug(msg);
  }
}

void LoggingCategory::error(const char * msg)
{
  if (!int_category)
  {
    std::cout << name << ": " << msg << std::endl;
  }
  else
  {
    int_category->error(msg);
  }
}

void LoggingCategory::info(const char * msg)
{
  if (!int_category)
  {
    std::cout << name << ": " << msg << std::endl;
  }
  else
  {
    int_category->info(msg);
  }
}

void LoggingCategory::debug(int msg)
{
  if (!int_category)
  {
    std::cout << name << ": " << msg << std::endl;
  }
  else
  {
    int_category->debug(std::to_string(msg));
  }
}

void LoggingCategory::error(int msg)
{
  if (!int_category)
  {
    std::cout << name << ": " << msg << std::endl;
  }
  else
  {
    int_category->error(std::to_string(msg));
  }
}

void LoggingCategory::info(int msg)
{
  if (!int_category)
  {
    std::cout << name << ": " << msg << std::endl;
  }
  else
  {
    int_category->info(std::to_string(msg));
  }
}

void LoggingCategory::debug(float msg)
{
  if (!int_category)
  {
    std::cout << name << ": " << msg << std::endl;
  }
  else
  {
    int_category->debug(std::to_string(msg));
  }
}

void LoggingCategory::error(float msg)
{
  if (!int_category)
  {
    std::cout << name << ": " << msg << std::endl;
  }
  else
  {
    int_category->error(std::to_string(msg));
  }
}

void LoggingCategory::info(float msg)
{
  if (!int_category)
  {
    std::cout << name << ": " << msg << std::endl;
  }
  else
  {
    int_category->info(std::to_string(msg));
  }
}

void LoggingCategory::debug(double msg)
{
  if (!int_category)
  {
    std::cout << name << ": " << msg << std::endl;
  }
  else
  {
    int_category->debug(std::to_string(msg));
  }
}

void LoggingCategory::error(double msg)
{
  if (!int_category)
  {
    std::cout << name << ": " << msg << std::endl;
  }
  else
  {
    int_category->error(std::to_string(msg));
  }
}

void LoggingCategory::info(double msg)
{
  if (!int_category)
  {
    std::cout << name << ": " << msg << std::endl;
  }
  else
  {
    int_category->info(std::to_string(msg));
  }
}
<commit_msg>Logging Refactor to completely encapsulate implementation and allow for logging categories<commit_after>#include "include/logging.h"

//Start the logger from a properties file
void Logger::start_log_from_file(std::string initFileName)
{
  //Read the properties file
  try {
    log4cpp::PropertyConfigurator::configure(initFileName);
  }
  catch ( log4cpp::ConfigureFailure &e ) {
    std::cout << "[log4cpp::ConfigureFailure] caught while reading" << initFileName << std::endl;
    std::cout << e.what();
    exit(1);
  }

  //Find the categories defined in the file
  // std::vector<log4cpp::Category*> categories = log4cpp::Category::getCurrentCategories();

  //Expose the logging handles
  log4cpp::Category& root = log4cpp::Category::getRoot();
  // log4cpp::Category& sub1 = log4cpp::Category::getInstance(std::string("sub1"));

  root_log = &root;
}

//Bring down the logging module
void Logger::end_log()
{
  if (!root_log) {
    std::cout << "Shutdown called with no logging module present" << std::endl;
  }
  else {
    log4cpp::Category::shutdown();
  }
}

//Constructor from a file
Logger::Logger(std::string initFileName)
{
start_log_from_file(initFileName);
}

//Destructor
Logger::~Logger()
{
  end_log();
}

//Exposures that log to the root category
void Logger::debug(std::string msg)
{
  if (!root_log)
  {
    std::cout << msg << std::endl;
  }
  else
  {
    root_log->debug(msg);
  }
}

void Logger::error(std::string msg)
{
  if (!root_log)
  {
    std::cout << msg << std::endl;
  }
  else
  {
    root_log->error(msg);
  }
}

void Logger::info(std::string msg)
{
  if (!root_log)
  {
    std::cout << msg << std::endl;
  }
  else
  {
    root_log->info(msg);
  }
}

void Logger::debug(const char * msg)
{
  if (!root_log)
  {
    std::cout << msg << std::endl;
  }
  else
  {
    root_log->debug(msg);
  }
}

void Logger::error(const char * msg)
{
  if (!root_log)
  {
    std::cout << msg << std::endl;
  }
  else
  {
    root_log->error(msg);
  }
}

void Logger::info(const char * msg)
{
  if (!root_log)
  {
    std::cout << msg << std::endl;
  }
  else
  {
    root_log->info(msg);
  }
}

void Logger::debug(int msg)
{
  if (!root_log)
  {
    std::cout << msg << std::endl;
  }
  else
  {
    root_log->debug(std::to_string(msg));
  }
}

void Logger::error(int msg)
{
  if (!root_log)
  {
    std::cout << msg << std::endl;
  }
  else
  {
    root_log->error(std::to_string(msg));
  }
}

void Logger::info(int msg)
{
  if (!root_log)
  {
    std::cout << msg << std::endl;
  }
  else
  {
    root_log->info(std::to_string(msg));
  }
}

void Logger::debug(float msg)
{
  if (!root_log)
  {
    std::cout << msg << std::endl;
  }
  else
  {
    root_log->debug(std::to_string(msg));
  }
}

void Logger::error(float msg)
{
  if (!root_log)
  {
    std::cout << msg << std::endl;
  }
  else
  {
    root_log->error(std::to_string(msg));
  }
}

void Logger::info(float msg)
{
  if (!root_log)
  {
    std::cout << msg << std::endl;
  }
  else
  {
    root_log->info(std::to_string(msg));
  }
}

void Logger::debug(double msg)
{
  if (!root_log)
  {
    std::cout << msg << std::endl;
  }
  else
  {
    root_log->debug(std::to_string(msg));
  }
}

void Logger::error(double msg)
{
  if (!root_log)
  {
    std::cout << msg << std::endl;
  }
  else
  {
    root_log->error(std::to_string(msg));
  }
}

void Logger::info(double msg)
{
  if (!root_log)
  {
    std::cout << msg << std::endl;
  }
  else
  {
    root_log->info(std::to_string(msg));
  }
}

//Pull down different categories by name
LoggingCategoryInterface* Logger::get_category(std::string name)
{
  return new LoggingCategory(name);
}

//--------------------------Logging Category Methods---------------------------//

//Exposures that log to the root category
void LoggingCategory::debug(std::string msg)
{
  if (!int_category)
  {
    std::cout << name << ": " << msg << std::endl;
  }
  else
  {
    int_category->debug(msg);
  }
}

void LoggingCategory::error(std::string msg)
{
  if (!int_category)
  {
    std::cout << name << ": " << msg << std::endl;
  }
  else
  {
    int_category->error(msg);
  }
}

void LoggingCategory::info(std::string msg)
{
  if (!int_category)
  {
    std::cout << name << ": " << msg << std::endl;
  }
  else
  {
    int_category->info(msg);
  }
}

void LoggingCategory::debug(const char * msg)
{
  if (!int_category)
  {
    std::cout << name << ": " << msg << std::endl;
  }
  else
  {
    int_category->debug(msg);
  }
}

void LoggingCategory::error(const char * msg)
{
  if (!int_category)
  {
    std::cout << name << ": " << msg << std::endl;
  }
  else
  {
    int_category->error(msg);
  }
}

void LoggingCategory::info(const char * msg)
{
  if (!int_category)
  {
    std::cout << name << ": " << msg << std::endl;
  }
  else
  {
    int_category->info(msg);
  }
}

void LoggingCategory::debug(int msg)
{
  if (!int_category)
  {
    std::cout << name << ": " << msg << std::endl;
  }
  else
  {
    int_category->debug(std::to_string(msg));
  }
}

void LoggingCategory::error(int msg)
{
  if (!int_category)
  {
    std::cout << name << ": " << msg << std::endl;
  }
  else
  {
    int_category->error(std::to_string(msg));
  }
}

void LoggingCategory::info(int msg)
{
  if (!int_category)
  {
    std::cout << name << ": " << msg << std::endl;
  }
  else
  {
    int_category->info(std::to_string(msg));
  }
}

void LoggingCategory::debug(float msg)
{
  if (!int_category)
  {
    std::cout << name << ": " << msg << std::endl;
  }
  else
  {
    int_category->debug(std::to_string(msg));
  }
}

void LoggingCategory::error(float msg)
{
  if (!int_category)
  {
    std::cout << name << ": " << msg << std::endl;
  }
  else
  {
    int_category->error(std::to_string(msg));
  }
}

void LoggingCategory::info(float msg)
{
  if (!int_category)
  {
    std::cout << name << ": " << msg << std::endl;
  }
  else
  {
    int_category->info(std::to_string(msg));
  }
}

void LoggingCategory::debug(double msg)
{
  if (!int_category)
  {
    std::cout << name << ": " << msg << std::endl;
  }
  else
  {
    int_category->debug(std::to_string(msg));
  }
}

void LoggingCategory::error(double msg)
{
  if (!int_category)
  {
    std::cout << name << ": " << msg << std::endl;
  }
  else
  {
    int_category->error(std::to_string(msg));
  }
}

void LoggingCategory::info(double msg)
{
  if (!int_category)
  {
    std::cout << name << ": " << msg << std::endl;
  }
  else
  {
    int_category->info(std::to_string(msg));
  }
}
<|endoftext|>


<commit_before>// file: xSP3EphemerisStore.cpp

#include "xSP3EphemerisStore.hpp"
#include "SatID.hpp"
#include "Exception.hpp"
#include "SP3Data.hpp"
#include "SP3Header.hpp"
#include "SP3Stream.hpp"

CPPUNIT_TEST_SUITE_REGISTRATION (xSP3EphemerisStore);

void xSP3EphemerisStore :: setUp (void)
{
}

/*
**** General test for the SP3EphemerisStore class
**** Test to assure the that RES throws its exceptions in the right place and
**** that it loads the SP3 file correctly

**** To further check this data, please view DumpData.txt for the dumped information
*/

void xSP3EphemerisStore :: RESTest (void)
{
      using namespace std;
      cout << "Reading " << "NGA15081Test.SP3" << endl;
      Rinex3::SP3Stream roffs("NGA15081Test.SP3");
      cout << "Writing " << "Output1.txt" << endl;
      Rinex3::SP3Stream out("Output1.txt",ios::out);
      //out.exceptions(fstream::failbit);
      Rinex3::SP3Header roh;
      Rinex3::SP3Data roe;

      roffs >> roh;
      out << roh;
      //roh.dump(cout);

      while (roffs >> roe)
      {
         out << roe;
	 //roe.dump(cout);
      }
}

/*
**** Test to assure the quality of SP3EphemerisStore class member getXvt()

**** This test makes sure that exceptions are thrown if there is no ephemeris data
**** for the given PRN and also that an exception is thrown if there is no data for
**** the PRN at the given time. Furthermore, this test finds an Xvt for a given
**** DayTime Time and PRN.

**** To see the Xvt information for the selected Time and PRN please see
**** getXvt.txt
*/
void xSP3EphemerisStore :: getXvtTest (void)
{
      using namespace std;
      cout << "Reading " << "Output1.txt" << endl;
      Rinex3::SP3Stream roffs("Output1.txt");
      cout << "Writing " << "Output2.txt" << endl;
      Rinex3::SP3Stream out("Output2.txt",ios::out);
      out.exceptions(fstream::failbit);
      Rinex3::SP3Header roh;
      Rinex3::SP3Data roe;

      roffs >> roh;
      out << roh;
      //roh.dump(cout);

      while (roffs >> roe)
      {
         out << roe;
	 //roe.dump(cout);
      }
}
/*
**** Test to assure the quality of SP3EphemerisStore class member dump()

**** This test makes sure that dump() behaves as expected.  With paramters from
**** 0-2 with each giving more and more respective information, this information is
**** then put into txt files.

**** To see the dump with paramter 0, please view DumpData0.txt
**** To see the dump with paramter 1, pleave view DumpData1.txt
**** To see the dump with paramter 2, please uncomment the test and view the command
**** line output (cout).
*/

void xSP3EphemerisStore :: dumpTest (void)
{

}

/*
**** Test to assure the quality of SP3EphemerisStore class member addEphemeris()

**** This test assures that no exceptions are thrown when a an ephemeris, taken from Store
**** is added to a blank  Object.  Then the test makes sure that only that Ephemeris
**** is in the object by checking the start and end times of the Object

**** Question:  Why does this eph data begin two hours earlier than it does on the output?
*/

void xSP3EphemerisStore :: addEphemerisTest (void)
{

}

/*
**** Test to assure the quality of SP3EphemerisStore class member edit()

**** This test assures that no exceptions are thrown when we edit a RES object
**** then after we edit the RES Object, we test to make sure that our edit time
**** parameters are now the time endpoints of the object.

**** For further inspection of the edit, please view editTest.txt
*/

void xSP3EphemerisStore :: editTest (void)
{

}

/*
**** Test to assure the quality of SP3EphemerisStore class member clear()

**** This test assures that no exceptions are thrown when we clear a SP3 object
**** then after we clear the SP3 Object, we test to make sure that END_OF_TIME is our
**** initial time and BEGINNING_OF_TIME is our final time

**** For further inspection of the edit, please view clearTest.txt
*/

void xSP3EphemerisStore :: clearTest (void)
{

}

void xSP3EphemerisStore :: dumpBadPositionsTest (void)
{
}

void xSP3EphemerisStore :: dumpBadClocksTest (void)
{
}
void xSP3EphemerisStore :: maxIntervalTest (void)
{
}
void xSP3EphemerisStore :: getTimeTest (void)
{
}

bool xSP3EphemerisStore :: fileEqualTest (char* handle1, char* handle2)
{
	bool isEqual = false;

	ifstream File1;
	ifstream File2;

	std::string File1Line;
	std::string File2Line;

	File1.open(handle1);
	File2.open(handle2);

	while (!File1.eof())
	{
		if (File2.eof())
			return isEqual;
		getline (File1, File1Line);
		getline (File2, File2Line);

		if (File1Line != File2Line)
			return isEqual;
	}
	if (!File2.eof())
		return isEqual;
	else
		return isEqual = true;
}
<commit_msg>Removed incorrect comments to the SP3Eph functional test<commit_after>// file: xSP3EphemerisStore.cpp

#include "xSP3EphemerisStore.hpp"
#include "SatID.hpp"
#include "Exception.hpp"
#include "SP3Data.hpp"
#include "SP3Header.hpp"
#include "SP3Stream.hpp"

CPPUNIT_TEST_SUITE_REGISTRATION (xSP3EphemerisStore);

void xSP3EphemerisStore :: setUp (void)
{
}

void xSP3EphemerisStore :: RESTest (void)
{
      using namespace std;
      cout << "Reading " << "NGA15081Test.SP3" << endl;
      Rinex3::SP3Stream roffs("NGA15081Test.SP3");
      cout << "Writing " << "Output1.txt" << endl;
      Rinex3::SP3Stream out("Output1.txt",ios::out);
      //out.exceptions(fstream::failbit);
      Rinex3::SP3Header roh;
      Rinex3::SP3Data roe;

      roffs >> roh;
      out << roh;
      //roh.dump(cout);

      while (roffs >> roe)
      {
         out << roe;
	 //roe.dump(cout);
      }
}

void xSP3EphemerisStore :: getXvtTest (void)
{
      using namespace std;
      cout << "Reading " << "Output1.txt" << endl;
      Rinex3::SP3Stream roffs("Output1.txt");
      cout << "Writing " << "Output2.txt" << endl;
      Rinex3::SP3Stream out("Output2.txt",ios::out);
      out.exceptions(fstream::failbit);
      Rinex3::SP3Header roh;
      Rinex3::SP3Data roe;

      roffs >> roh;
      out << roh;
      //roh.dump(cout);

      while (roffs >> roe)
      {
         out << roe;
	 //roe.dump(cout);
      }
}

void xSP3EphemerisStore :: dumpTest (void)
{

}

void xSP3EphemerisStore :: addEphemerisTest (void)
{

}

void xSP3EphemerisStore :: editTest (void)
{

}

void xSP3EphemerisStore :: clearTest (void)
{

}

void xSP3EphemerisStore :: dumpBadPositionsTest (void)
{
}

void xSP3EphemerisStore :: dumpBadClocksTest (void)
{
}
void xSP3EphemerisStore :: maxIntervalTest (void)
{
}
void xSP3EphemerisStore :: getTimeTest (void)
{
}

bool xSP3EphemerisStore :: fileEqualTest (char* handle1, char* handle2)
{
	bool isEqual = false;

	ifstream File1;
	ifstream File2;

	std::string File1Line;
	std::string File2Line;

	File1.open(handle1);
	File2.open(handle2);

	while (!File1.eof())
	{
		if (File2.eof())
			return isEqual;
		getline (File1, File1Line);
		getline (File2, File2Line);

		if (File1Line != File2Line)
			return isEqual;
	}
	if (!File2.eof())
		return isEqual;
	else
		return isEqual = true;
}
<|endoftext|>


<commit_before>/*
   This file is part of the clazy static checker.

  Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
  Author: Sérgio Martins <sergio.martins@kdab.com>

  Copyright (C) 2015 Sergio Martins <smartins@kde.org>

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Library General Public
  License as published by the Free Software Foundation; either
  version 2 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Library General Public License for more details.

  You should have received a copy of the GNU Library General Public License
  along with this library; see the file COPYING.LIB.  If not, write to
  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  Boston, MA 02110-1301, USA.
*/

#include "writingtotemporary.h"
#include "Utils.h"
#include "checkmanager.h"
#include "StringUtils.h"

#include <clang/AST/AST.h>
#include <clang/Lex/Lexer.h>

using namespace clang;
using namespace std;

WritingToTemporary::WritingToTemporary(const std::string &name, const clang::CompilerInstance &ci)
    : CheckBase(name, ci)
    , m_widenCriteria(isOptionSet("widen-criteria"))
{
}

std::vector<string> WritingToTemporary::filesToIgnore() const
{
    static const vector<string> files = { "qstring.h" };
    return files;
}

vector<string> WritingToTemporary::supportedOptions() const
{
    static const vector<string> options = { "widen-criteria" };
    return options;
}

static bool isDisallowedClass(const string &className)
{
    static const vector<string> disallowed = { "QTextCursor", "QDomElement", "KConfigGroup", "QWebElement",
                                               "QScriptValue", "QTextLine", "QTextBlock", "QDomNode", "QJSValue" };
    return clazy_std::contains(disallowed, className);
}

static bool isDisallowedMethod(const string &name)
{
    static const vector<string> disallowed = { "QColor::getCmyk", "QColor::getCmykF" };
    return clazy_std::contains(disallowed, name);
}

static bool isKnownType(const string &className)
{
    static const vector<string> types = { "QList", "QVector", "QMap", "QHash", "QString", "QSet",
                                          "QByteArray", "QUrl", "QVarLengthArray", "QLinkedList",
                                          "QRect", "QRectF", "QBitmap", "QVector2D", "QVector3D",
                                          "QVector4D", "QSize", "QSizeF", "QSizePolicy", "QPoint",
                                          "QPointF", "QColor" };

    return clazy_std::contains(types, className);
}

void WritingToTemporary::VisitStmt(clang::Stmt *stmt)
{
    CallExpr *callExpr = dyn_cast<CallExpr>(stmt);
    if (!callExpr)
        return;

    // For a chain like getFoo().setBar(), returns {setBar(), getFoo()}
    vector<CallExpr *> callExprs = Utils::callListForChain(callExpr);
    if (callExprs.size() < 2)
        return;

    CallExpr *firstCallToBeEvaluated = callExprs.at(callExprs.size() - 1); // This is the call to getFoo()
    FunctionDecl *firstFunc = firstCallToBeEvaluated->getDirectCallee();
    if (!firstFunc)
        return;

    CallExpr *secondCallToBeEvaluated = callExprs.at(callExprs.size() - 2); // This is the call to setBar()
    FunctionDecl *secondFunc = secondCallToBeEvaluated->getDirectCallee();
    if (!secondFunc)
        return;

    CXXMethodDecl *secondMethod = dyn_cast<CXXMethodDecl>(secondFunc);
    if (!secondMethod || secondMethod->isConst() || secondMethod->isStatic())
        return;

    CXXRecordDecl *record = secondMethod->getParent();
    if (!record || isDisallowedClass(record->getNameAsString()))
        return;

    QualType qt = firstFunc->getReturnType();
    const Type *firstFuncReturnType = qt.getTypePtrOrNull();
    if (!firstFuncReturnType || firstFuncReturnType->isPointerType() || firstFuncReturnType->isReferenceType())
        return;

    qt = secondFunc->getReturnType();
    const Type *secondFuncReturnType = qt.getTypePtrOrNull();
    if (!secondFuncReturnType || !secondFuncReturnType->isVoidType())
        return;

    if (!m_widenCriteria && !isKnownType(record->getNameAsString()) && !clazy_std::startsWith(secondFunc->getNameAsString(), "set"))
        return;

    const string &methodName = secondMethod->getQualifiedNameAsString();
    if (isDisallowedMethod(methodName))
        return;

    emitWarning(stmt->getLocStart(), "Call to temporary is a no-op: " + methodName);
}

REGISTER_CHECK_WITH_FLAGS("writing-to-temporary", WritingToTemporary, CheckLevel0)
<commit_msg>writing-to-temporary: Whitelist QTextTableCell<commit_after>/*
   This file is part of the clazy static checker.

  Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
  Author: Sérgio Martins <sergio.martins@kdab.com>

  Copyright (C) 2015 Sergio Martins <smartins@kde.org>

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Library General Public
  License as published by the Free Software Foundation; either
  version 2 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Library General Public License for more details.

  You should have received a copy of the GNU Library General Public License
  along with this library; see the file COPYING.LIB.  If not, write to
  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  Boston, MA 02110-1301, USA.
*/

#include "writingtotemporary.h"
#include "Utils.h"
#include "checkmanager.h"
#include "StringUtils.h"

#include <clang/AST/AST.h>
#include <clang/Lex/Lexer.h>

using namespace clang;
using namespace std;

WritingToTemporary::WritingToTemporary(const std::string &name, const clang::CompilerInstance &ci)
    : CheckBase(name, ci)
    , m_widenCriteria(isOptionSet("widen-criteria"))
{
}

std::vector<string> WritingToTemporary::filesToIgnore() const
{
    static const vector<string> files = { "qstring.h" };
    return files;
}

vector<string> WritingToTemporary::supportedOptions() const
{
    static const vector<string> options = { "widen-criteria" };
    return options;
}

static bool isDisallowedClass(const string &className)
{
    static const vector<string> disallowed = { "QTextCursor", "QDomElement", "KConfigGroup", "QWebElement",
                                               "QScriptValue", "QTextLine", "QTextBlock", "QDomNode", "QJSValue" };
    return clazy_std::contains(disallowed, className);
}

static bool isDisallowedMethod(const string &name)
{
    static const vector<string> disallowed = { "QColor::getCmyk", "QColor::getCmykF" };
    return clazy_std::contains(disallowed, name);
}

static bool isKnownType(const string &className)
{
    static const vector<string> types = { "QList", "QVector", "QMap", "QHash", "QString", "QSet",
                                          "QByteArray", "QUrl", "QVarLengthArray", "QLinkedList",
                                          "QRect", "QRectF", "QBitmap", "QVector2D", "QVector3D",
                                          "QVector4D", "QSize", "QSizeF", "QSizePolicy", "QPoint",
                                          "QPointF", "QColor", "QTextTableCell" };

    return clazy_std::contains(types, className);
}

void WritingToTemporary::VisitStmt(clang::Stmt *stmt)
{
    CallExpr *callExpr = dyn_cast<CallExpr>(stmt);
    if (!callExpr)
        return;

    // For a chain like getFoo().setBar(), returns {setBar(), getFoo()}
    vector<CallExpr *> callExprs = Utils::callListForChain(callExpr);
    if (callExprs.size() < 2)
        return;

    CallExpr *firstCallToBeEvaluated = callExprs.at(callExprs.size() - 1); // This is the call to getFoo()
    FunctionDecl *firstFunc = firstCallToBeEvaluated->getDirectCallee();
    if (!firstFunc)
        return;

    CallExpr *secondCallToBeEvaluated = callExprs.at(callExprs.size() - 2); // This is the call to setBar()
    FunctionDecl *secondFunc = secondCallToBeEvaluated->getDirectCallee();
    if (!secondFunc)
        return;

    CXXMethodDecl *secondMethod = dyn_cast<CXXMethodDecl>(secondFunc);
    if (!secondMethod || secondMethod->isConst() || secondMethod->isStatic())
        return;

    CXXRecordDecl *record = secondMethod->getParent();
    if (!record || isDisallowedClass(record->getNameAsString()))
        return;

    QualType qt = firstFunc->getReturnType();
    const Type *firstFuncReturnType = qt.getTypePtrOrNull();
    if (!firstFuncReturnType || firstFuncReturnType->isPointerType() || firstFuncReturnType->isReferenceType())
        return;

    qt = secondFunc->getReturnType();
    const Type *secondFuncReturnType = qt.getTypePtrOrNull();
    if (!secondFuncReturnType || !secondFuncReturnType->isVoidType())
        return;

    if (!m_widenCriteria && !isKnownType(record->getNameAsString()) && !clazy_std::startsWith(secondFunc->getNameAsString(), "set"))
        return;

    const string &methodName = secondMethod->getQualifiedNameAsString();
    if (isDisallowedMethod(methodName))
        return;

    emitWarning(stmt->getLocStart(), "Call to temporary is a no-op: " + methodName);
}

REGISTER_CHECK_WITH_FLAGS("writing-to-temporary", WritingToTemporary, CheckLevel0)
<|endoftext|>


<commit_before>#include "WaterRenderer.h"

#include "../World/Chunk/ChunkMesh.h"
#include "../World/Block/BlockDatabase.h"
#include "../Application.h"
#include "../Camera.h"

#include <iostream>

void WaterRenderer::add(const ChunkMesh& mesh)
{
    m_chunks.push_back(&mesh);
}

void WaterRenderer::render(const Camera& camera, Config* conf)
{
    if (m_chunks.empty())
    {
        return;
    }

    glEnable(GL_BLEND);
    glDisable(GL_CULL_FACE);
    m_shader.useProgram();

    m_shader.loadProjectionViewMatrix(camera.getProjectionViewMatrix());
    m_shader.loadProjectionViewMatrix(camera.getProjectionViewMatrix());
    m_shader.loadTime(g_timeElapsed);

    for (const auto& mesh : m_chunks)
    {
        const ChunkMesh& m = *mesh;

        m.getModel().bindVAO();
        GL::drawElements(m.getModel().getIndicesCount());

    }

    m_chunks.clear();
}
<commit_msg>Fixed bugs.<commit_after>#include "WaterRenderer.h"

#include "../World/Chunk/ChunkMesh.h"
#include "../World/Block/BlockDatabase.h"
#include "../Application.h"
#include "../Camera.h"

#include <iostream>

void WaterRenderer::add(const ChunkMesh& mesh)
{
    m_chunks.push_back(&mesh);
}

void WaterRenderer::render(const Camera& camera, Config* conf)
{
    if (m_chunks.empty())
    {
        return;
    }

    glEnable(GL_BLEND);
    glDisable(GL_CULL_FACE);
    m_shader.useProgram();

    m_shader.loadProjectionViewMatrix(camera.getProjectionViewMatrix());
    m_shader.loadTime(g_timeElapsed);

    for (const auto& mesh : m_chunks)
    {
        const ChunkMesh& m = *mesh;

        m.getModel().bindVAO();
        GL::drawElements(m.getModel().getIndicesCount());

    }

    m_chunks.clear();
}
<|endoftext|>


<commit_before>#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include "files.h"
#include "misc.h"
#include "runpasses.h"
#include "stringutil.h"
#include "symtab.h"
#include "../passes/pass.h"

bool printPasses = false;

struct PassInfo {
  char* name;
  Pass* pass;
  char* args;
};

#define START_PASSLIST_REGISTRATION \
  static Pass* stringToPass(char* passname) {

#define STOP_PASSLIST_REGISTRATION \
  INT_FATAL("Couldn't find a pass named %s", passname); \
  return NULL; \
}

#define REGISTER(pass) \
  if (strcmp(passname, #pass) == 0) { \
    return new pass(); \
  }

#include "passlist.cpp"

#define FIRST {NULL, NULL, NULL}
#define LAST {NULL, NULL, NULL}
#define RUN(x, a) {#x, new x(), a}
#include "passlist.h"

static void runPass(char* passName, Pass* pass, char* args) {
  struct timeval startTime;
  struct timeval stopTime;
  struct timezone timezone;

  pass->setArgs(args);
  if (printPasses) {
    fprintf(stderr, "%32s :", passName);
    fflush(stderr);
    gettimeofday(&startTime, &timezone);
  }
  pass->run(Symboltable::getModuleList(pass->whichModules));
  if (printPasses) {
    gettimeofday(&stopTime, &timezone);
    fprintf(stderr, "%8.3f seconds\n",
	    ((double)((stopTime.tv_sec*1e6+stopTime.tv_usec) -
		      (startTime.tv_sec*1e6+startTime.tv_usec))) / 1e6);
  }
}

static void parsePassFile(char* passfilename) {
  FILE* passfile = openInputFile(passfilename);
  char passname[80] = "";
  char args[80] = "";
  int readPass;
  bool readLastPass;
  do {
    readPass = fscanf(passfile, "%s", passname);
  } while (readPass == 1 && strcmp(passname, "FIRST,") != 0);
  do {
    readPass = fscanf(passfile, "%s", passname);
    readLastPass = strcmp(passname, "LAST") == 0;
    if (!readLastPass) {
      if (strncmp(passname, "//", 2) == 0) {
	char nextChar;
	do {
	  fscanf(passfile, "%c", &nextChar);
	} while (nextChar != '\n');
      } else if (strncmp(passname, "RUN(", 4) != 0) {
	fail("ill-formed passname: %s", passname);
      } else {
	char* passnameStart = passname + 4; // 4 == strlen("RUN(")
	int passnameLen = strlen(passnameStart);
	passnameStart[passnameLen-1] = '\0'; // overwrite comma

	bool readChar;
	char nextChar;
	do {
	  readChar = fscanf(passfile, "%c", &nextChar);
	} while (readChar == 1 && nextChar != '\"');
	int argLength = 0;
	do {
	  readChar = fscanf(passfile, "%c", &nextChar);
	  if (readChar) {
	    args[argLength++] = nextChar;
	  }
	} while (readChar == 1 && nextChar != '\"');
	args[--argLength] = '\0';
	char extraStuff[80];
	fscanf(passfile, "%s", extraStuff);
	if (strcmp(extraStuff, "),") != 0) {
	  fail("pass name ended poorly: %s", extraStuff);
	}

	Pass* pass = stringToPass(passnameStart);
	runPass(passnameStart, pass, args);
      }
    }
  } while (readPass == 1 && !readLastPass);
  closeInputFile(passfile);
}

void runPasses(char* passfilename) {
  if (strcmp(passfilename, "") == 0) {
    PassInfo* pass = passlist+1;  // skip over FIRST

    while (pass->name != NULL) {
      runPass(pass->name, pass->pass, pass->args);

      pass++;
    }
  } else {
    parsePassFile(passfilename);
  }
}
<commit_msg><commit_after>#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include "files.h"
#include "misc.h"
#include "runpasses.h"
#include "stringutil.h"
#include "symtab.h"
#include "../passes/pass.h"

bool printPasses = false;

struct PassInfo {
  char* name;
  char* args;
};

#define START_PASSLIST_REGISTRATION \
  static Pass* stringToPass(char* passname) {

#define STOP_PASSLIST_REGISTRATION \
  INT_FATAL("Couldn't find a pass named %s", passname); \
  return NULL; \
}

#define REGISTER(pass) \
  if (strcmp(passname, #pass) == 0) { \
    return new pass(); \
  }

#include "passlist.cpp"

#define FIRST {NULL, NULL}
#define LAST {NULL, NULL}
#define RUN(x, a) {#x, a}
#include "passlist.h"

static void runPass(char* passName, Pass* pass, char* args) {
  struct timeval startTime;
  struct timeval stopTime;
  struct timezone timezone;

  pass->setArgs(args);
  if (printPasses) {
    fprintf(stderr, "%32s :", passName);
    fflush(stderr);
    gettimeofday(&startTime, &timezone);
  }
  pass->run(Symboltable::getModuleList(pass->whichModules));
  if (printPasses) {
    gettimeofday(&stopTime, &timezone);
    fprintf(stderr, "%8.3f seconds\n",
	    ((double)((stopTime.tv_sec*1e6+stopTime.tv_usec) -
		      (startTime.tv_sec*1e6+startTime.tv_usec))) / 1e6);
  }
}

static void parsePassFile(char* passfilename) {
  FILE* passfile = openInputFile(passfilename);
  char passname[80] = "";
  char args[80] = "";
  int readPass;
  bool readLastPass;
  do {
    readPass = fscanf(passfile, "%s", passname);
  } while (readPass == 1 && strcmp(passname, "FIRST,") != 0);
  do {
    readPass = fscanf(passfile, "%s", passname);
    readLastPass = strcmp(passname, "LAST") == 0;
    if (!readLastPass) {
      if (strncmp(passname, "//", 2) == 0) {
	char nextChar;
	do {
	  fscanf(passfile, "%c", &nextChar);
	} while (nextChar != '\n');
      } else if (strncmp(passname, "RUN(", 4) != 0) {
	fail("ill-formed passname: %s", passname);
      } else {
	char* passnameStart = passname + 4; // 4 == strlen("RUN(")
	int passnameLen = strlen(passnameStart);
	passnameStart[passnameLen-1] = '\0'; // overwrite comma

	bool readChar;
	char nextChar;
	do {
	  readChar = fscanf(passfile, "%c", &nextChar);
	} while (readChar == 1 && nextChar != '\"');
	int argLength = 0;
	do {
	  readChar = fscanf(passfile, "%c", &nextChar);
	  if (readChar) {
	    args[argLength++] = nextChar;
	  }
	} while (readChar == 1 && nextChar != '\"');
	args[--argLength] = '\0';
	char extraStuff[80];
	fscanf(passfile, "%s", extraStuff);
	if (strcmp(extraStuff, "),") != 0) {
	  fail("pass name ended poorly: %s", extraStuff);
	}

	Pass* pass = stringToPass(passnameStart);
	runPass(passnameStart, pass, args);
      }
    }
  } while (readPass == 1 && !readLastPass);
  closeInputFile(passfile);
}

void runPasses(char* passfilename) {
  if (strcmp(passfilename, "") == 0) {
    PassInfo* pass = passlist+1;  // skip over FIRST

    while (pass->name != NULL) {
      runPass(pass->name, stringToPass(pass->name), pass->args);

      pass++;
    }
  } else {
    parsePassFile(passfilename);
  }
}
<|endoftext|>


<commit_before>// Copyright (c) 2019 Chris Ohk, Youngjoong Kim, SeungHyun Jeon

// We are making my contributions/submissions to this project solely in our
// personal capacity and are not conveying any rights to any intellectual
// property of any third parties.

#include <Rosetta/Games/Game.hpp>
#include <Rosetta/Models/Entity.hpp>
#include <Rosetta/Models/Player.hpp>
#include <Rosetta/Models/Spell.hpp>

namespace RosettaStone
{
Entity::Entity(Player& _owner, Card& _card) : owner(&_owner), card(_card)
{
    auraEffects = new AuraEffects(this);

    for (auto& gameTag : _card.gameTags)
    {
        Entity::SetGameTag(gameTag.first, gameTag.second);
    }
}

Entity::Entity(const Entity& ent)
{
    FreeMemory();

    owner = ent.owner;
    card = ent.card;

    auraEffects = ent.auraEffects;
    onGoingEffect = ent.onGoingEffect;
    m_gameTags = ent.m_gameTags;
}

Entity::Entity(Entity&& ent) noexcept
{
    FreeMemory();

    owner = ent.owner;
    card = ent.card;

    auraEffects = ent.auraEffects;
    onGoingEffect = ent.onGoingEffect;
    m_gameTags = ent.m_gameTags;
}

Entity::~Entity()
{
    FreeMemory();
}

Entity& Entity::operator=(const Entity& ent)
{
    if (this == &ent)
    {
        return *this;
    }

    FreeMemory();

    owner = ent.owner;
    card = ent.card;

    auraEffects = ent.auraEffects;
    onGoingEffect = ent.onGoingEffect;
    m_gameTags = ent.m_gameTags;

    return *this;
}

Entity& Entity::operator=(Entity&& ent) noexcept
{
    if (this == &ent)
    {
        return *this;
    }

    FreeMemory();

    owner = ent.owner;
    card = ent.card;

    auraEffects = ent.auraEffects;
    onGoingEffect = ent.onGoingEffect;
    m_gameTags = ent.m_gameTags;

    return *this;
}

void Entity::Reset()
{
    SetGameTag(GameTag::DAMAGE, 0);
    SetGameTag(GameTag::EXHAUSTED, 0);
    SetGameTag(GameTag::ATK, 0);
    SetGameTag(GameTag::HEALTH, 0);
    SetGameTag(GameTag::COST, 0);
    SetGameTag(GameTag::TAUNT, 0);
    SetGameTag(GameTag::FROZEN, 0);
    SetGameTag(GameTag::CHARGE, 0);
    SetGameTag(GameTag::WINDFURY, 0);
    SetGameTag(GameTag::DIVINE_SHIELD, 0);
    SetGameTag(GameTag::STEALTH, 0);
    SetGameTag(GameTag::NUM_ATTACKS_THIS_TURN, 0);
}

int Entity::GetGameTag(GameTag tag) const
{
    if (m_gameTags.find(tag) == m_gameTags.end())
    {
        if (auraEffects != nullptr)
        {
            return auraEffects->GetGameTag(tag);
        }

        return 0;
    }

    if (auraEffects != nullptr)
    {
        return m_gameTags.at(tag) + auraEffects->GetGameTag(tag);
    }

    return m_gameTags.at(tag);
}

void Entity::SetGameTag(GameTag tag, int value)
{
    m_gameTags.insert_or_assign(tag, value);
}

int Entity::GetCost() const
{
    return GetGameTag(GameTag::COST);
}

void Entity::SetCost(int cost)
{
    SetGameTag(GameTag::COST, cost);
}

bool Entity::GetExhausted() const
{
    return static_cast<bool>(GetGameTag(GameTag::EXHAUSTED));
}

void Entity::SetExhausted(bool exhausted)
{
    SetGameTag(GameTag::EXHAUSTED, static_cast<int>(exhausted));
}

void Entity::Destroy()
{
    isDestroyed = true;
}

Entity* Entity::GetFromCard(Player& player, Card&& card)
{
    Entity* result;

    switch (card.GetCardType())
    {
        case CardType::HERO:
            result = new Hero(player, card);
            break;
        case CardType::HERO_POWER:
            result = new HeroPower(player, card);
            break;
        case CardType::MINION:
            result = new Minion(player, card);
            break;
        case CardType::SPELL:
            result = new Spell(player, card);
            break;
        case CardType::WEAPON:
            result = new Weapon(player, card);
            break;
        default:
            throw std::invalid_argument(
                "Generic::DrawCard() - Invalid card type!");
    }

    // Set entity ID
    result->id = player.GetGame()->GetNextID();

    return result;
}

void Entity::FreeMemory()
{
    delete auraEffects;
    delete onGoingEffect;

    m_gameTags.clear();
}
}  // namespace RosettaStone
<commit_msg>fix: Correct code to consider case that the value of GameTag is negative<commit_after>// Copyright (c) 2019 Chris Ohk, Youngjoong Kim, SeungHyun Jeon

// We are making my contributions/submissions to this project solely in our
// personal capacity and are not conveying any rights to any intellectual
// property of any third parties.

#include <Rosetta/Games/Game.hpp>
#include <Rosetta/Models/Entity.hpp>
#include <Rosetta/Models/Player.hpp>
#include <Rosetta/Models/Spell.hpp>

namespace RosettaStone
{
Entity::Entity(Player& _owner, Card& _card) : owner(&_owner), card(_card)
{
    auraEffects = new AuraEffects(this);

    for (auto& gameTag : _card.gameTags)
    {
        Entity::SetGameTag(gameTag.first, gameTag.second);
    }
}

Entity::Entity(const Entity& ent)
{
    FreeMemory();

    owner = ent.owner;
    card = ent.card;

    auraEffects = ent.auraEffects;
    onGoingEffect = ent.onGoingEffect;
    m_gameTags = ent.m_gameTags;
}

Entity::Entity(Entity&& ent) noexcept
{
    FreeMemory();

    owner = ent.owner;
    card = ent.card;

    auraEffects = ent.auraEffects;
    onGoingEffect = ent.onGoingEffect;
    m_gameTags = ent.m_gameTags;
}

Entity::~Entity()
{
    FreeMemory();
}

Entity& Entity::operator=(const Entity& ent)
{
    if (this == &ent)
    {
        return *this;
    }

    FreeMemory();

    owner = ent.owner;
    card = ent.card;

    auraEffects = ent.auraEffects;
    onGoingEffect = ent.onGoingEffect;
    m_gameTags = ent.m_gameTags;

    return *this;
}

Entity& Entity::operator=(Entity&& ent) noexcept
{
    if (this == &ent)
    {
        return *this;
    }

    FreeMemory();

    owner = ent.owner;
    card = ent.card;

    auraEffects = ent.auraEffects;
    onGoingEffect = ent.onGoingEffect;
    m_gameTags = ent.m_gameTags;

    return *this;
}

void Entity::Reset()
{
    SetGameTag(GameTag::DAMAGE, 0);
    SetGameTag(GameTag::EXHAUSTED, 0);
    SetGameTag(GameTag::ATK, 0);
    SetGameTag(GameTag::HEALTH, 0);
    SetGameTag(GameTag::COST, 0);
    SetGameTag(GameTag::TAUNT, 0);
    SetGameTag(GameTag::FROZEN, 0);
    SetGameTag(GameTag::CHARGE, 0);
    SetGameTag(GameTag::WINDFURY, 0);
    SetGameTag(GameTag::DIVINE_SHIELD, 0);
    SetGameTag(GameTag::STEALTH, 0);
    SetGameTag(GameTag::NUM_ATTACKS_THIS_TURN, 0);
}

int Entity::GetGameTag(GameTag tag) const
{
    int value = 0;

    if (m_gameTags.find(tag) == m_gameTags.end())
    {
        if (auraEffects != nullptr)
        {
            value += auraEffects->GetGameTag(tag);
        }
    }
    else
    {
        value += m_gameTags.at(tag);

        if (auraEffects != nullptr)
        {
            value += auraEffects->GetGameTag(tag);
        }
    }

    return value > 0 ? value : 0;
}

void Entity::SetGameTag(GameTag tag, int value)
{
    m_gameTags.insert_or_assign(tag, value);
}

int Entity::GetCost() const
{
    return GetGameTag(GameTag::COST);
}

void Entity::SetCost(int cost)
{
    SetGameTag(GameTag::COST, cost);
}

bool Entity::GetExhausted() const
{
    return static_cast<bool>(GetGameTag(GameTag::EXHAUSTED));
}

void Entity::SetExhausted(bool exhausted)
{
    SetGameTag(GameTag::EXHAUSTED, static_cast<int>(exhausted));
}

void Entity::Destroy()
{
    isDestroyed = true;
}

Entity* Entity::GetFromCard(Player& player, Card&& card)
{
    Entity* result;

    switch (card.GetCardType())
    {
        case CardType::HERO:
            result = new Hero(player, card);
            break;
        case CardType::HERO_POWER:
            result = new HeroPower(player, card);
            break;
        case CardType::MINION:
            result = new Minion(player, card);
            break;
        case CardType::SPELL:
            result = new Spell(player, card);
            break;
        case CardType::WEAPON:
            result = new Weapon(player, card);
            break;
        default:
            throw std::invalid_argument(
                "Generic::DrawCard() - Invalid card type!");
    }

    // Set entity ID
    result->id = player.GetGame()->GetNextID();

    return result;
}

void Entity::FreeMemory()
{
    delete auraEffects;
    delete onGoingEffect;

    m_gameTags.clear();
}
}  // namespace RosettaStone
<|endoftext|>