<commit_before>/* Bucky Frost
 * Paul Gentemann
 * CS 381
 * File Name : splinepatch.cpp
 * Last Modified : Sat 09 Nov 2013 11:46:15 PM AKST
 * Description : A pair of spline plains, patched together, that will
 * ripple upon user input.
 */

// OpenGL/GLUT includes - DO THESE FIRST
#include <cstdlib>       // Do this before GL/GLUT includes
using std::exit;
#ifndef __APPLE__
# include <GL/glew.h>
# include <GL/glut.h>    // Includes OpenGL headers as well
#else
# include <GLEW/glew.h>
# include <GLUT/glut.h>  // Apple puts glut.h in a different place
#endif
#ifdef _MSC_VER          // Tell MS-Visual Studio about GLEW lib
# pragma comment(lib, "glew32.lib")
#endif
#include "lib381/bitmapprinter.h"
#include "lib381/glslprog.h"    // For GLSL code-handling functions
#include <string>
using std::string;
#include <iostream>
using std::cout; using std::cerr; using std::endl;
#include <vector>
using std::vector;
#include <sstream>
using std::ostringstream;
#include <iomanip>
using std::setprecision;
using std::fixed;
#include <cmath>
using std::sin;
#include "mouse.h"
Mouse mousy = Mouse();

// Function prototypes
void documentation();
void waveFun(int);
void drawBezierPatch(int, double, GLdouble *);
void myDisplay();
void myIdle();
void reset(GLdouble);
void myKeyboard(unsigned char, int, int);
void myPassiveMotion(int, int);
void init();
void myReshape(int, int);
void set(GLdouble, GLdouble, GLdouble, GLdouble,
         GLdouble, GLdouble, GLdouble, GLdouble);

// Global variables
const int ESCKEY = 27;         // ASCII value of Escape
const int startwinsize = 600;  // Start window width & height (pixels)
int winw = 1, winh = 1;        // Window width, height (pixels)
bool help = false;

// Shaders
string vshader1fname;          // Filename for vertex shader source
string fshader1fname;          // Filename for fragment shader source
GLhandleARB prog1;             // GLSL Program Object
bool shaderbool1 = false;
GLfloat shaderfloat1 = .5;

// Camera
GLdouble viewmatrix[16],
         viewang = 5.;         // Degrees

// Wave/Spline Patches
int numsubdivs;           // Number of subdivisions for object
const int minsubdivs = 1;      //  Minumum of above
const int maxsubdivs = 50;     //  Maximum of above
const int PTS = 4;             // Number of control points in a patch
const int EDGES = 4;           // Sides in a patch
const int SIZE = PTS*EDGES*3;  // Size of Patch Arrays
bool wave;                     // Starts the wave propagation.
double modd;                   // Value for the waves in the Bezier patches

GLdouble b1[SIZE] = {
    1.5,-1.5, 0.0,   1.5,-0.5,-3.0,   1.5, 0.5,-2.0,   1.5, 1.5, 1.0,
    0.5,-1.5, 0.0,   0.5,-0.5, 0.0,   0.5, 0.5, 0.0,   0.5, 1.5, 0.0,
   -0.5,-1.5, 0.0,  -0.5,-0.5, 1.0,  -0.5, 0.5,-3.0,  -0.5, 1.5, 1.0,
   -1.5,-1.5, 1.0,  -1.5,-0.5,-2.0,  -1.5, 0.5, 1.0,  -1.5, 1.5, 0.0};

GLdouble b2[SIZE] = {
    1.5, 1.5, 1.0,   1.5, 0.5,-2.0,   2.5, 0.5,-2.0,   1.5, 1.5, 1.0,
    0.5, 1.5, 0.0,   0.5, 0.5, 0.0,   1.5, 0.5, 0.0,   0.5, 1.5, 0.0,
   -0.5, 1.5, 1.0,  -0.5, 0.5,-3.0,  -1.5, 0.5,-3.0,  -0.5, 1.5, 1.0,
   -1.5, 1.5, 0.0,  -1.5, 0.5, 1.0,  -2.5, 0.5, 1.0,  -1.5, 1.5, 0.0};

// waveFun
// Propogates a wave through one of the axes of a spline patch.
void waveFun(GLdouble *arr, int column, int axis)
{
    for (int i = 0; i < PTS; ++i)
    {
        arr[(column * 3 + axis) * i] *= sin(modd);
        cout << (column + axis) * 3 + i << endl;
    }
}

// drawBezierPatch
// Draws a number of control points for a bezier patch
// The z coordinates of all the points are translated
// by the sine of the mod parameter.
void drawBezierPatch(int subdivs, double mod, GLdouble *cpts)
{
    glColor3d(0.,0.,0.5);
    glMap2d(GL_MAP2_VERTEX_3, 0., 1., 3, 4, 0., 1., 3*4, 4, cpts);
    glEnable(GL_MAP2_VERTEX_3);

    glMapGrid2d(subdivs, 0., 1., subdivs, 0., 1.);
    glEnable(GL_AUTO_NORMAL);

    glFrontFace(GL_CW);  // Normals are evidently backwards here :-(
    glEvalMesh2(GL_FILL, 0, subdivs, 0, subdivs);
    glFrontFace(GL_CCW);
}

// myDisplay
// The GLUT display function
void myDisplay()
{
    glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    GLhandleARB theprog;  // CURRENTLY-used program object or 0 if none

    // Activating the shaders
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    theprog = prog1;

    glEnable(GL_DEPTH_TEST);    // Set up 3D

    // Setting up the camera view
    glLoadIdentity();
    glMultMatrixd(viewmatrix);

    // Position light source 0 & draw ball there
    glPushMatrix();
//        glRotated(lightrotang, 1.,0.,0.);
        glTranslated(-1., 1., 2.);
        GLfloat origin4[] = { 0.f, 0.f, 0.f, 1.f };
        glLightfv(GL_LIGHT0, GL_POSITION, origin4);
        GLfloat spotdir3[] = { 1.f, -1.f, -1.f };
        glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, spotdir3);
        glUseProgramObjectARB(0);
        glColor3d(1., 1., 1.);
        glutSolidSphere(0.1, 20, 15);  // obj for light source
    glPopMatrix();

    glUseProgramObjectARB(theprog);

    //Send info to shader
    if (theprog)
    {
        GLint loc;  // Location for shader vars

        loc = glGetUniformLocationARB(theprog, "myb1");
        if (loc != -1)
        {
            glUniform1i(loc, shaderbool1);
        }

        loc = glGetUniformLocationARB(theprog, "myf1");
        if (loc != -1)
        {
            glUniform1f(loc, shaderfloat1);
        }
    }

    // Draw objects
    glTranslated(0,0,-4);
    if(wave)
    {
        drawBezierPatch(numsubdivs, modd, b1);
        drawBezierPatch(numsubdivs, modd, b2);
    }
    else
    {
        drawBezierPatch(numsubdivs, 0, b1);
        drawBezierPatch(numsubdivs, 0, b2);
    }

    documentation();
    glutSwapBuffers();
}

// myIdle
// The GLUT idle function
void myIdle()
{
    modd += 0.1;
    waveFun(b1, 3, 2);
    waveFun(b2, 0, 2);
    glutPostRedisplay();
    // Print OpenGL errors, if there are any (for debugging)
    static int error_count = 0;
    if (GLenum err = glGetError())
    {
        ++error_count;
        cerr << "OpenGL ERROR " << error_count << ": "
             << gluErrorString(err) << endl;
    }
}

// set()
// Sets given matrix to given translation/rotation.
void set(GLdouble *arr, GLdouble tx, GLdouble ty, GLdouble tz,
         GLdouble rang=0., GLdouble rx=0., GLdouble ry=0., GLdouble rz=0.)
{
    glLoadIdentity();
    glTranslated(tx, ty, tz);
    glRotated(rang, rx, ry, rz);
    glMultMatrixd(arr);
    glGetDoublev(GL_MODELVIEW_MATRIX, arr);
}

// reset()
// Resets the given matrix to the identity
void reset(GLdouble *arr)
{
    glLoadIdentity();
    glGetDoublev(GL_MODELVIEW_MATRIX, arr);
}

// myKeyboard
// The GLUT keyboard function
void myKeyboard(unsigned char key, int x, int y)
{
    switch (key)
    {
    case ESCKEY:  // Esc: quit
        exit(0);
        break;
    case '+':
        set(viewmatrix, 0., 0., 1.);
        break;
    case '-':
        set(viewmatrix, 0., 0., -1.);
        break;
    case '<':
        set(viewmatrix, 0., -1., 0., 10,1,0,0);
        break;
    case '>':
        set(viewmatrix, 0., 1., 0., -10,1,0,0);
        break;
    case ',':
        set(viewmatrix, 0., -1., 0., 10,0,1,0);
        break;
    case '.':
        set(viewmatrix, 0., 1., 0., -10,0,1,0);
        break;
    case 'R':
    case 'r':
        reset(viewmatrix);
        break;
    case ' ':
        wave = !wave;
        break;
    case '(':
        if(numsubdivs > minsubdivs)
            --numsubdivs;
        break;
    case ')':
        if(numsubdivs < maxsubdivs)
            ++numsubdivs;
        break;
    case 'h':
    case 'H':
        help = !help;
        break;
    case 'f':     // Space: toggle shader bool
        shaderbool1 = !shaderbool1;
        break;
    case '[':     // [: Decrease shader float
        shaderfloat1 -= 0.02;
        if (shaderfloat1 < 0.)
            shaderfloat1 = 0.;
        break;
    case ']':     // ]: Increase shader float
        shaderfloat1 += 0.02;
        if (shaderfloat1 > 1.)
            shaderfloat1 = 1.;
        break;
    }
    glutPostRedisplay();
}

// mySpecial
// The GLUT special function
void mySpecial(int key, int x, int y)
{
    switch (key)
    {
        case GLUT_KEY_LEFT:
            set(viewmatrix, 0.,0.,0., -viewang, 0.,1.,0.);
            break;
        case GLUT_KEY_RIGHT:
            set(viewmatrix, 0.,0.,0., viewang, 0.,1.,0.);
            break;
        case GLUT_KEY_UP:
            set(viewmatrix, 0.,0.,0., -viewang,0.,.0,1.);
            break;
        case GLUT_KEY_DOWN:
            set(viewmatrix, 0.,0.,0., viewang,0.,.0,1.);
            break;
    }
    glutPostRedisplay();
}

// myReshape
// The GLUT reshape function
void myReshape(int w, int h)
{
    // Set viewport & save window dimensions in globals
    glViewport(0, 0, w, h);
    winw = w;
    winh = h;
    // Set up projection
    // Perspective projection with near quite near & far pretty far
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(60., double(w)/h, 0.01, 100.);
    glMatrixMode(GL_MODELVIEW);  // Always go back to model/view mode
}

// init
// Initialize GL states & global data
void init()
{
    reset(viewmatrix);    // Reset camera position
    glMatrixMode(GL_MODELVIEW);
    modd = 0.0;
    wave = false;
    numsubdivs = 10;

    // Shaders
    prog1 = makeProgramObjectFromFiles(vshader1fname, fshader1fname);
}

// myPassiveMotion
// The GLUT passiveMotion function
void myPassiveMotion(int x, int y)
{
    // Save mouse position in class (haha)
    mousy.saveMouse(x, y);
}

// The main
int main(int argc, char ** argv)
{
    // Initilization of OpenGL/GLUT
    glutInit(&argc, argv);
    // Set shader source filenames. Done here, as opposed to in
    getShaderFilenames(vshader1fname, fshader1fname, argc, argv);
    //  function init, so that we can use command-line arguments.
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);

    // Creating the view window
    glutInitWindowSize(startwinsize, startwinsize);
    glutInitWindowPosition(50, 50);
    glutCreateWindow("CS 381 - Shaders, Normals, Lighting, and Splines Oh My!");

    // Init GLEW & check status - exit on failure
    if (glewInit() != GLEW_OK)
    {
        cerr << "glewInit failed" << endl;
        exit(1);
    }

    init();
    glutDisplayFunc(myDisplay);
    glutIdleFunc(myIdle);
    glutReshapeFunc(myReshape);
//    glutMouseFunc(myMouse);
    glutKeyboardFunc(myKeyboard);
    glutSpecialFunc(mySpecial);
    glutPassiveMotionFunc(myPassiveMotion);

    // Start GLUT event handling loop
    glutMainLoop();

    return 0;
}

void documentation()
{
    // Draw documentation
    glDisable(GL_DEPTH_TEST);
    glLoadIdentity();
    glMatrixMode(GL_PROJECTION);  // Set up simple ortho projection
    glPushMatrix();
        glLoadIdentity();
        gluOrtho2D(0., double(winw), 0., double(winh));
        glColor3d(0., 0., 0.);        // Black text
        BitmapPrinter p(20., winh-20., 20.);
        if(help)
        {
            ostringstream os2;
            os2 << fixed << setprecision(2) << numsubdivs;
            p.print("Arrows         Rotate Scene");
            p.print("( )            Change Subdivisions (" + os2.str() + ")");
            p.print("+/-            Zoom in/out");
            p.print("r              Reset Camera");
            p.print(string("space          Start wave (" )+ (wave ? "true" : "false") + ")");
        }
        else
        {
            p.print("h              help");
        }
        p.print("Esc            Quit");
    glPopMatrix();                // Restore prev projection
    glMatrixMode(GL_MODELVIEW);
}
<commit_msg>rotate works, but zoom is screwy<commit_after>/* Bucky Frost
 * Paul Gentemann
 * CS 381
 * File Name : splinepatch.cpp
 * Last Modified : Sun 10 Nov 2013 05:16:20 AM AKST
 * Description : A pair of spline plains, patched together, that will
 * ripple upon user input.
 */

// OpenGL/GLUT includes - DO THESE FIRST
#include <cstdlib>       // Do this before GL/GLUT includes
using std::exit;
#ifndef __APPLE__
# include <GL/glew.h>
# include <GL/glut.h>    // Includes OpenGL headers as well
#else
# include <GLEW/glew.h>
# include <GLUT/glut.h>  // Apple puts glut.h in a different place
#endif
#ifdef _MSC_VER          // Tell MS-Visual Studio about GLEW lib
# pragma comment(lib, "glew32.lib")
#endif
#include "lib381/bitmapprinter.h"
#include "lib381/glslprog.h"    // For GLSL code-handling functions
#include <string>
using std::string;
#include <iostream>
using std::cout; using std::cerr; using std::endl;
#include <vector>
using std::vector;
#include <sstream>
using std::ostringstream;
#include <iomanip>
using std::setprecision;
using std::fixed;
#include <cmath>
using std::sin;
#include "mouse.h"
Mouse mousy = Mouse();

// Function prototypes
void documentation();
void waveFun(int);
void drawBezierPatch(int, GLdouble *);
void myDisplay();
void myIdle();
void reset(GLdouble);
void myKeyboard(unsigned char, int, int);
void myPassiveMotion(int, int);
void init();
void myReshape(int, int);
void set(GLdouble, GLdouble, GLdouble, GLdouble,
         GLdouble, GLdouble, GLdouble, GLdouble);

// Global variables
const int ESCKEY = 27;         // ASCII value of Escape
const int startwinsize = 600;  // Start window width & height (pixels)
int winw = 1, winh = 1;        // Window width, height (pixels)
bool help = false;
int zoom = -4;

// Shaders
bool shaderbool1 = true;
string vshader1fname;          // Filename for vertex shader source
string fshader1fname;          // Filename for fragment shader source
GLhandleARB prog1;             // GLSL Program Object
GLfloat shaderfloat1 = .5;

// Camera
GLdouble viewmatrix[16],
         viewang = 5.;         // Degrees

// Wave/Spline Patches
int numsubdivs;           // Number of subdivisions for object
const int minsubdivs = 1;      //  Minumum of above
const int maxsubdivs = 50;     //  Maximum of above
const int PTS = 4;             // Number of control points in a patch
const int EDGES = 4;           // Sides in a patch
const int SIZE = PTS*EDGES*3;  // Size of Patch Arrays
bool wave;                     // Starts the wave propagation.
double modd;                   // Value for the waves in the Bezier patches

GLdouble b1[SIZE] = {
    1.5,-1.5, 0.0,   1.5,-0.5,-0.0,   1.5, 0.5,-0.0,   1.5, 1.5, 0.0,
    0.5,-1.5, 0.0,   0.5,-0.5, 0.0,   0.5, 0.5, 0.0,   0.5, 1.5, 0.0,
   -0.5,-1.5, 0.0,  -0.5,-0.5, 0.0,  -0.5, 0.5,-0.0,  -0.5, 1.5, 0.0,
   -1.5,-1.5, 0.0,  -1.5,-0.5,-0.0,  -1.5, 0.5, 0.0,  -1.5, 1.5, 0.0};

GLdouble b2[SIZE] = {
    1.5, 0.5, 0.0,   1.5, 1.5,-0.0,   2.5, 1.8,-0.0,   3.0, 3.5,-0.0,
    0.5, 0.5, 0.0,   0.5, 1.5, 0.0,   1.5, 2.0, 0.0,   0.0, 3.5, 0.0,
   -0.5, 0.5, 0.0,  -0.5, 1.5,-0.0,  -1.5, 2.3,-0.0,  -0.0, 3.5,-0.0,
   -1.5, 0.5, 0.0,  -1.5, 1.5, 0.0,  -2.5, 2.8, 0.0,  -3.0, 3.5, 0.0};

// waveFun
// Propogates a wave through one of the axes of a spline patch.
void waveFun(GLdouble *arr, int column, int axis, int mult)
{
    for (int i = 0; i < PTS; ++i)
    {
        arr[PTS * 3 * i + (3 * column + axis)] = mult * sin(modd);
    }
}

// drawBezierPatch
// Draws a number of control points for a bezier patch. The z coordinates
// of all the points are translated by the sine of the mod parameter.
void drawBezierPatch(int subdivs, GLdouble *cpts)
{
    glColor3d(0.,0.,0.5);
    glMap2d(GL_MAP2_VERTEX_3, 0., 1., 3, 4, 0., 1., 3*4, 4, cpts);
    glEnable(GL_MAP2_VERTEX_3);

    glMapGrid2d(subdivs, 0., 1., subdivs, 0., 1.);
    glEnable(GL_AUTO_NORMAL);

    glFrontFace(GL_CW);  // Normals are evidently backwards here :-(
    glEvalMesh2(GL_FILL, 0, subdivs, 0, subdivs);
    glFrontFace(GL_CCW);
}

// myDisplay
// The GLUT display function
void myDisplay()
{
    glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    GLhandleARB theprog;  // CURRENTLY-used program object or 0 if none

    // Activating the shaders
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    theprog = prog1;

    glEnable(GL_DEPTH_TEST);    // Set up 3D

    // Setting up the camera view
    glLoadIdentity();
    glMultMatrixd(viewmatrix);

    // Position light source 0 & draw ball there
    glPushMatrix();
        glTranslated(-1., 1., 2.);
        GLfloat origin4[] = { 0.f, 0.f, 0.f, 1.f };
        glLightfv(GL_LIGHT0, GL_POSITION, origin4);
        GLfloat spotdir3[] = { 1.f, -1.f, -1.f };
        glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, spotdir3);
        glUseProgramObjectARB(0);
        glColor3d(1., 1., 1.);
        glutSolidSphere(0.1, 20, 15);  // obj for light source
    glPopMatrix();

    glUseProgramObjectARB(theprog);

    //Send info to shader
    if (theprog)
    {
        GLint loc;  // Location for shader vars
        loc = glGetUniformLocationARB(theprog, "myb1");
        if (loc != -1)
        {
            glUniform1i(loc, shaderbool1);
        }
        loc = glGetUniformLocationARB(theprog, "myf1");
        if (loc != -1)
        {
            glUniform1f(loc, shaderfloat1);
        }
    }

    // Draw objects
    glTranslated(0,0,zoom);
    if(wave)
    {
        modd += 0.1;
        waveFun(b1, 2, 2, 1);
        waveFun(b2, 2, 2, -1);
        drawBezierPatch(numsubdivs, b1);
        drawBezierPatch(numsubdivs, b2);
    }
    else
    {
        drawBezierPatch(numsubdivs, b1);
        drawBezierPatch(numsubdivs, b2);
    }

    documentation();
    glutSwapBuffers();
}

// myIdle
// The GLUT idle function
void myIdle()
{
    glutPostRedisplay();
    // Print OpenGL errors, if there are any (for debugging)
    static int error_count = 0;
    if (GLenum err = glGetError())
    {
        ++error_count;
        cerr << "OpenGL ERROR " << error_count << ": "
             << gluErrorString(err) << endl;
    }
}

// set()
// Sets given matrix to given translation/rotation.
void set(GLdouble *arr, GLdouble tx, GLdouble ty, GLdouble tz,
         GLdouble rang=0., GLdouble rx=0., GLdouble ry=0., GLdouble rz=0.)
{
    glLoadIdentity();
    glTranslated(tx, ty, tz);
    glRotated(rang, rx, ry, rz);
    glMultMatrixd(arr);
    glGetDoublev(GL_MODELVIEW_MATRIX, arr);
}

// reset()
// Resets the given matrix to the identity
void reset(GLdouble *arr)
{
    glLoadIdentity();
    glGetDoublev(GL_MODELVIEW_MATRIX, arr);
}

// myKeyboard
// The GLUT keyboard function
void myKeyboard(unsigned char key, int x, int y)
{
    switch (key)
    {
    case ESCKEY:  // Esc: quit
        exit(0);
        break;
    case '+':
        ++zoom;
        set(viewmatrix, 0., 0., 1.);
        break;
    case '-':
        --zoom;
        set(viewmatrix, 0., 0.,-1.);
        break;
    case '<':
        set(viewmatrix, 0., -1., 0., 10,1,0,0);
        break;
    case '>':
        set(viewmatrix, 0., 1., 0., -10,1,0,0);
        break;
    case ',':
        set(viewmatrix, 0., -1., 0., 10,0,1,0);
        break;
    case '.':
        set(viewmatrix, 0., 1., 0., -10,0,1,0);
        break;
    case 'R':
    case 'r':
        zoom = -4;
        reset(viewmatrix);
        break;
    case ' ':
        wave = !wave;
        break;
    case '(':
        if(numsubdivs > minsubdivs)
            --numsubdivs;
        break;
    case ')':
        if(numsubdivs < maxsubdivs)
            ++numsubdivs;
        break;
    case 'h':
    case 'H':
        help = !help;
        break;
    case 'f':     // Space: toggle shader bool
        shaderbool1 = !shaderbool1;
        break;
    case '[':     // [: Decrease shader float
        shaderfloat1 -= 0.02;
        if (shaderfloat1 < 0.)
            shaderfloat1 = 0.;
        break;
    case ']':     // ]: Increase shader float
        shaderfloat1 += 0.02;
        if (shaderfloat1 > 1.)
            shaderfloat1 = 1.;
        break;
    }
    glutPostRedisplay();
}

// mySpecial
// The GLUT special function
void mySpecial(int key, int x, int y)
{
    glLoadMatrixd(viewmatrix);
    glTranslated(0., 0., zoom);
    switch (key)
    {
        case GLUT_KEY_LEFT:
            glRotated(-5, 0., 1., 0.);
            break;
        case GLUT_KEY_RIGHT:
            glRotated(5, 0., 1., 0.);
            break;
        case GLUT_KEY_UP:
            glRotated(-5, 0., 0., 1.);
            break;
        case GLUT_KEY_DOWN:
            glRotated(5, 0., 0., 1.);
            break;
    }
    glTranslated(0., 0., -zoom);
    glGetDoublev(GL_MODELVIEW_MATRIX, viewmatrix);
    glutPostRedisplay();
}

// myReshape
// The GLUT reshape function
void myReshape(int w, int h)
{
    // Set viewport & save window dimensions in globals
    glViewport(0, 0, w, h);
    winw = w;
    winh = h;
    // Set up projection
    // Perspective projection with near quite near & far pretty far
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(60., double(w)/h, 0.01, 100.);
    glMatrixMode(GL_MODELVIEW);  // Always go back to model/view mode
}

// init
// Initialize GL states & global data
void init()
{
    reset(viewmatrix);    // Reset camera position
    glMatrixMode(GL_MODELVIEW);
    modd = 0.0;
    wave = false;
    numsubdivs = 10;

    // Shaders
    prog1 = makeProgramObjectFromFiles(vshader1fname, fshader1fname);
}

// myPassiveMotion
// The GLUT passiveMotion function
void myPassiveMotion(int x, int y)
{
    // Save mouse position in class (haha)
    mousy.saveMouse(x, y);
}

// The main
int main(int argc, char ** argv)
{
    // Initilization of OpenGL/GLUT
    glutInit(&argc, argv);
    // Set shader source filenames. Done here, as opposed to in
    getShaderFilenames(vshader1fname, fshader1fname, argc, argv);
    //  function init, so that we can use command-line arguments.
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);

    // Creating the view window
    glutInitWindowSize(startwinsize, startwinsize);
    glutInitWindowPosition(50, 50);
    glutCreateWindow("CS 381 - Shaders, Normals, Lighting, and Splines Oh My!");

    // Init GLEW & check status - exit on failure
    if (glewInit() != GLEW_OK)
    {
        cerr << "glewInit failed" << endl;
        exit(1);
    }

    init();
    glutDisplayFunc(myDisplay);
    glutIdleFunc(myIdle);
    glutReshapeFunc(myReshape);
//    glutMouseFunc(myMouse);
    glutKeyboardFunc(myKeyboard);
    glutSpecialFunc(mySpecial);
    glutPassiveMotionFunc(myPassiveMotion);

    // Start GLUT event handling loop
    glutMainLoop();

    return 0;
}

void documentation()
{
    // Draw documentation
    glDisable(GL_DEPTH_TEST);
    glLoadIdentity();
    glMatrixMode(GL_PROJECTION);  // Set up simple ortho projection
    glPushMatrix();
        glLoadIdentity();
        gluOrtho2D(0., double(winw), 0., double(winh));
        glColor3d(0., 0., 0.);        // Black text
        BitmapPrinter p(20., winh-20., 20.);
        if(help)
        {
            ostringstream os2;
            os2 << fixed << setprecision(2) << numsubdivs;
            p.print("Arrows         Rotate Scene");
            p.print("( )            Change Subdivisions (" + os2.str() + ")");
            p.print("+/-            Zoom in/out");
            p.print("r              Reset Camera");
            p.print(string("space          Start wave (" )+ (wave ? "true" : "false") + ")");
        }
        else
        {
            p.print("h              help");
        }
        p.print("Esc            Quit");
    glPopMatrix();                // Restore prev projection
    glMatrixMode(GL_MODELVIEW);
}
<|endoftext|>


<commit_before>/****************************************************************************
 *
 *   Copyright (c) 2013 PX4 Development Team. All rights reserved.
 *   Author: 	@author Thomas Gubler <thomasgubler@gmail.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name PX4 nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/

/**
 * @file mTecs.cpp
 *
 * @author Thomas Gubler <thomasgubler@gmail.com>
 */

#include "mTecs.h"

#include <lib/geo/geo.h>
#include <stdio.h>

namespace fwPosctrl {

mTecs::mTecs() :
	SuperBlock(NULL, "MT"),
	/* Parameters */
	_mTecsEnabled(this, "ENABLED"),
	_airspeedMin(this, "FW_AIRSPD_MIN", false),
	/* Publications */
	_status(&getPublications(), ORB_ID(tecs_status)),
	/* control blocks */
	_controlTotalEnergy(this, "THR"),
	_controlEnergyDistribution(this, "PIT", true),
	_controlAltitude(this, "FPA", true),
	_controlAirSpeed(this, "ACC"),
	_airspeedDerivative(this, "AD"),
	_throttleSp(0.0f),
	_pitchSp(0.0f),
	_BlockOutputLimiterTakeoffThrottle(this, "TKF_THR"),
	_BlockOutputLimiterTakeoffPitch(this, "TKF_PIT", true),
	_BlockOutputLimiterUnderspeedThrottle(this, "USP_THR"),
	_BlockOutputLimiterUnderspeedPitch(this, "USP_PIT", true),
	_BlockOutputLimiterLandThrottle(this, "LND_THR"),
	_BlockOutputLimiterLandPitch(this, "LND_PIT", true),
	timestampLastIteration(hrt_absolute_time()),
	_firstIterationAfterReset(true),
	_dtCalculated(false),
	_counter(0),
	_debug(false)
{
}

mTecs::~mTecs()
{
}

int mTecs::updateAltitudeSpeed(float flightPathAngle, float altitude, float altitudeSp, float airspeed,
		float airspeedSp, tecs_mode mode, LimitOverride limitOverride)
{
	/* check if all input arguments are numbers and abort if not so */
	if (!isfinite(flightPathAngle) || !isfinite(altitude) ||
			!isfinite(altitudeSp) || !isfinite(airspeed) || !isfinite(airspeedSp) || !isfinite(mode)) {
		return -1;
	}

	/* time measurement */
	updateTimeMeasurement();

	/* calculate flight path angle setpoint from altitude setpoint */
	float flightPathAngleSp = _controlAltitude.update(altitudeSp - altitude);

	/* Debug output */
	if (_counter % 10 == 0) {
		debug("***");
		debug("updateAltitudeSpeed: altitudeSp %.4f, altitude %.4f, flightPathAngleSp %.4f", (double)altitudeSp, (double)altitude, (double)flightPathAngleSp);
	}

	/* Write part of the status message */
	_status.altitudeSp = altitudeSp;
	_status.altitude = altitude;

	/* use flightpath angle setpoint for total energy control */
	return updateFlightPathAngleSpeed(flightPathAngle, flightPathAngleSp, airspeed,
			airspeedSp, mode, limitOverride);
}

int mTecs::updateFlightPathAngleSpeed(float flightPathAngle, float flightPathAngleSp, float airspeed,
		float airspeedSp, tecs_mode mode, LimitOverride limitOverride)
{
	/* check if all input arguments are numbers and abort if not so */
	if (!isfinite(flightPathAngle) || !isfinite(flightPathAngleSp) ||
			!isfinite(airspeed) || !isfinite(airspeedSp) || !isfinite(mode)) {
		return -1;
	}

	/* time measurement */
	updateTimeMeasurement();

	/* calculate longitudinal acceleration setpoint from airspeed setpoint*/
	float accelerationLongitudinalSp = _controlAirSpeed.update(airspeedSp - airspeed);

	/* Debug output */
	if (_counter % 10 == 0) {
		debug("updateFlightPathAngleSpeed airspeedSp %.4f, airspeed %.4f, accelerationLongitudinalSp%.4f", (double)airspeedSp, (double)airspeed, (double)accelerationLongitudinalSp);
	}

	/* Write part of the status message */
	_status.flightPathAngleSp = flightPathAngleSp;
	_status.flightPathAngle = flightPathAngle;
	_status.airspeedSp = airspeedSp;
	_status.airspeed = airspeed;

	/* use longitudinal acceleration setpoint for total energy control */
	return updateFlightPathAngleAcceleration(flightPathAngle, flightPathAngleSp, airspeed,
			accelerationLongitudinalSp, mode, limitOverride);
}

int mTecs::updateFlightPathAngleAcceleration(float flightPathAngle, float flightPathAngleSp, float airspeed,
		float accelerationLongitudinalSp, tecs_mode mode, LimitOverride limitOverride)
{
	/* check if all input arguments are numbers and abort if not so */
	if (!isfinite(flightPathAngle) || !isfinite(flightPathAngleSp) ||
			!isfinite(airspeed) || !isfinite(accelerationLongitudinalSp) || !isfinite(mode)) {
		return -1;
	}
	/* time measurement */
	updateTimeMeasurement();

	/* update parameters first */
	updateParams();

	/* calculate values (energies) */
	float flightPathAngleError = flightPathAngleSp - flightPathAngle;
	float airspeedDerivative = 0.0f;
	if(_airspeedDerivative.getDt() > 0.0f) {
		airspeedDerivative = _airspeedDerivative.update(airspeed);
	}
	float airspeedDerivativeNorm = airspeedDerivative / CONSTANTS_ONE_G;
	float airspeedDerivativeSp = accelerationLongitudinalSp;
	float airspeedDerivativeNormSp = airspeedDerivativeSp / CONSTANTS_ONE_G;
	float airspeedDerivativeNormError = airspeedDerivativeNormSp - airspeedDerivativeNorm;

	float totalEnergyRate = flightPathAngle + airspeedDerivativeNorm;
	float totalEnergyRateError = flightPathAngleError + airspeedDerivativeNormError;
	float totalEnergyRateSp = flightPathAngleSp + airspeedDerivativeNormSp;
	float totalEnergyRateError2 = totalEnergyRateSp - totalEnergyRate;

	float energyDistributionRate = flightPathAngle - airspeedDerivativeNorm;
	float energyDistributionRateError = flightPathAngleError - airspeedDerivativeNormError;
	float energyDistributionRateSp = flightPathAngleSp - airspeedDerivativeNormSp;
	float energyDistributionRateError2 = energyDistributionRateSp - energyDistributionRate;

	/* Debug output */
	if (_counter % 10 == 0) {
		debug("totalEnergyRateSp %.2f, totalEnergyRate %.2f, totalEnergyRateError %.2f totalEnergyRateError2 %.2f airspeedDerivativeNorm %.4f",
				(double)totalEnergyRateSp, (double)totalEnergyRate, (double)totalEnergyRateError, (double)totalEnergyRateError2, (double)airspeedDerivativeNorm);
		debug("energyDistributionRateSp %.2f, energyDistributionRate %.2f, energyDistributionRateError %.2f energyDistributionRateError2 %.2f",
				(double)energyDistributionRateSp, (double)energyDistributionRate, (double)energyDistributionRateError, (double)energyDistributionRateError2);
	}

	/* Check airspeed: if below safe value switch to underspeed mode (if not in takeoff mode) */
	if (!TECS_MODE_LAND && airspeed < _airspeedMin.get()) {
		mode = TECS_MODE_UNDERSPEED;
	}

	/* Set special ouput limiters if we are not in TECS_MODE_NORMAL */
	BlockOutputLimiter *outputLimiterThrottle = NULL; // NULL --> use standard inflight limits
	BlockOutputLimiter *outputLimiterPitch = NULL; // NULL --> use standard inflight limits
	if (mode == TECS_MODE_TAKEOFF) {
		outputLimiterThrottle = &_BlockOutputLimiterTakeoffThrottle; //XXX: accept prelaunch values from launchdetector
		outputLimiterPitch = &_BlockOutputLimiterTakeoffPitch;
	} else if (mode == TECS_MODE_LAND) {
		// only limit pitch but do not limit throttle
		outputLimiterPitch = &_BlockOutputLimiterLandPitch;
	} else if (mode == TECS_MODE_LAND_THROTTLELIM) {
		outputLimiterThrottle = &_BlockOutputLimiterLandThrottle;
		outputLimiterPitch = &_BlockOutputLimiterLandPitch;
	} else if (mode == TECS_MODE_UNDERSPEED) {
		outputLimiterThrottle = &_BlockOutputLimiterUnderspeedThrottle;
		outputLimiterPitch = &_BlockOutputLimiterUnderspeedPitch;
	}

	/* Apply overrride given by the limitOverride argument (this is used for limits which are not given by
	 * parameters such as pitch limits with takeoff waypoints or throttle limits when the launchdetector
	 * is running) */
	bool limitApplied = limitOverride.applyOverride(outputLimiterThrottle == NULL ?
			_controlTotalEnergy.getOutputLimiter() :
			*outputLimiterThrottle,
			outputLimiterPitch == NULL ?
			_controlEnergyDistribution.getOutputLimiter() :
			*outputLimiterPitch);

	/* Write part of the status message */
	_status.airspeedDerivativeSp = airspeedDerivativeSp;
	_status.airspeedDerivative = airspeedDerivative;
	_status.totalEnergyRateSp = totalEnergyRateSp;
	_status.totalEnergyRate = totalEnergyRate;
	_status.energyDistributionRateSp = energyDistributionRateSp;
	_status.energyDistributionRate = energyDistributionRate;
	_status.mode = mode;

	/** update control blocks **/
	/* update total energy rate control block */
	_throttleSp = _controlTotalEnergy.update(totalEnergyRateSp, totalEnergyRateError, outputLimiterThrottle);

	/* update energy distribution rate control block */
	_pitchSp = _controlEnergyDistribution.update(energyDistributionRateSp, energyDistributionRateError, outputLimiterPitch);

	if (_counter % 10 == 0) {
		debug("_throttleSp %.1f, _pitchSp %.1f, flightPathAngleSp %.1f, flightPathAngle %.1f accelerationLongitudinalSp %.1f, airspeedDerivative %.1f",
				(double)_throttleSp, (double)_pitchSp,
				(double)flightPathAngleSp, (double)flightPathAngle,
				(double)accelerationLongitudinalSp, (double)airspeedDerivative);
	}

	/* publish status messge */
	_status.update();

	/* clean up */
	_firstIterationAfterReset = false;
	_dtCalculated = false;

	_counter++;

	return 0;
}

void mTecs::resetIntegrators()
{
	_controlTotalEnergy.getIntegral().setY(0.0f);
	_controlEnergyDistribution.getIntegral().setY(0.0f);
	timestampLastIteration = hrt_absolute_time();
	_firstIterationAfterReset = true;
}

void mTecs::resetDerivatives(float airspeed)
{
	_airspeedDerivative.setU(airspeed);
}

void mTecs::updateTimeMeasurement()
{
	if (!_dtCalculated) {
		float deltaTSeconds = 0.0f;
		if (!_firstIterationAfterReset) {
			hrt_abstime timestampNow = hrt_absolute_time();
			deltaTSeconds = (float)(timestampNow - timestampLastIteration) * 1e-6f;
			timestampLastIteration = timestampNow;
		}
		setDt(deltaTSeconds);

		_dtCalculated = true;
	}
}

void mTecs::debug_print(const char *fmt, va_list args)
{
	fprintf(stderr, "%s: ", "[mtecs]");
	vfprintf(stderr, fmt, args);

	fprintf(stderr, "\n");
}

void mTecs::debug(const char *fmt, ...) {

	if (!_debug) {
		return;
	}

	va_list args;

	va_start(args, fmt);
	debug_print(fmt, args);
}

bool mTecs::LimitOverride::applyOverride(BlockOutputLimiter &outputLimiterThrottle,
		BlockOutputLimiter &outputLimiterPitch)
{
	bool ret = false;

	if (overrideThrottleMinEnabled)	{
		outputLimiterThrottle.setMin(overrideThrottleMin);
		ret = true;
	}
	if (overrideThrottleMaxEnabled)	{
		outputLimiterThrottle.setMax(overrideThrottleMax);
		ret = true;
	}
	if (overridePitchMinEnabled)	{
		outputLimiterPitch.setMin(overridePitchMin);
		ret = true;
	}
	if (overridePitchMaxEnabled)	{
		outputLimiterPitch.setMax(overridePitchMax);
		ret = true;
	}

	return ret;
}

} /* namespace fwPosctrl */
<commit_msg>fix stupid error in underspeed detection<commit_after>/****************************************************************************
 *
 *   Copyright (c) 2013 PX4 Development Team. All rights reserved.
 *   Author: 	@author Thomas Gubler <thomasgubler@gmail.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name PX4 nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/

/**
 * @file mTecs.cpp
 *
 * @author Thomas Gubler <thomasgubler@gmail.com>
 */

#include "mTecs.h"

#include <lib/geo/geo.h>
#include <stdio.h>

namespace fwPosctrl {

mTecs::mTecs() :
	SuperBlock(NULL, "MT"),
	/* Parameters */
	_mTecsEnabled(this, "ENABLED"),
	_airspeedMin(this, "FW_AIRSPD_MIN", false),
	/* Publications */
	_status(&getPublications(), ORB_ID(tecs_status)),
	/* control blocks */
	_controlTotalEnergy(this, "THR"),
	_controlEnergyDistribution(this, "PIT", true),
	_controlAltitude(this, "FPA", true),
	_controlAirSpeed(this, "ACC"),
	_airspeedDerivative(this, "AD"),
	_throttleSp(0.0f),
	_pitchSp(0.0f),
	_BlockOutputLimiterTakeoffThrottle(this, "TKF_THR"),
	_BlockOutputLimiterTakeoffPitch(this, "TKF_PIT", true),
	_BlockOutputLimiterUnderspeedThrottle(this, "USP_THR"),
	_BlockOutputLimiterUnderspeedPitch(this, "USP_PIT", true),
	_BlockOutputLimiterLandThrottle(this, "LND_THR"),
	_BlockOutputLimiterLandPitch(this, "LND_PIT", true),
	timestampLastIteration(hrt_absolute_time()),
	_firstIterationAfterReset(true),
	_dtCalculated(false),
	_counter(0),
	_debug(false)
{
}

mTecs::~mTecs()
{
}

int mTecs::updateAltitudeSpeed(float flightPathAngle, float altitude, float altitudeSp, float airspeed,
		float airspeedSp, tecs_mode mode, LimitOverride limitOverride)
{
	/* check if all input arguments are numbers and abort if not so */
	if (!isfinite(flightPathAngle) || !isfinite(altitude) ||
			!isfinite(altitudeSp) || !isfinite(airspeed) || !isfinite(airspeedSp) || !isfinite(mode)) {
		return -1;
	}

	/* time measurement */
	updateTimeMeasurement();

	/* calculate flight path angle setpoint from altitude setpoint */
	float flightPathAngleSp = _controlAltitude.update(altitudeSp - altitude);

	/* Debug output */
	if (_counter % 10 == 0) {
		debug("***");
		debug("updateAltitudeSpeed: altitudeSp %.4f, altitude %.4f, flightPathAngleSp %.4f", (double)altitudeSp, (double)altitude, (double)flightPathAngleSp);
	}

	/* Write part of the status message */
	_status.altitudeSp = altitudeSp;
	_status.altitude = altitude;

	/* use flightpath angle setpoint for total energy control */
	return updateFlightPathAngleSpeed(flightPathAngle, flightPathAngleSp, airspeed,
			airspeedSp, mode, limitOverride);
}

int mTecs::updateFlightPathAngleSpeed(float flightPathAngle, float flightPathAngleSp, float airspeed,
		float airspeedSp, tecs_mode mode, LimitOverride limitOverride)
{
	/* check if all input arguments are numbers and abort if not so */
	if (!isfinite(flightPathAngle) || !isfinite(flightPathAngleSp) ||
			!isfinite(airspeed) || !isfinite(airspeedSp) || !isfinite(mode)) {
		return -1;
	}

	/* time measurement */
	updateTimeMeasurement();

	/* calculate longitudinal acceleration setpoint from airspeed setpoint*/
	float accelerationLongitudinalSp = _controlAirSpeed.update(airspeedSp - airspeed);

	/* Debug output */
	if (_counter % 10 == 0) {
		debug("updateFlightPathAngleSpeed airspeedSp %.4f, airspeed %.4f, accelerationLongitudinalSp%.4f", (double)airspeedSp, (double)airspeed, (double)accelerationLongitudinalSp);
	}

	/* Write part of the status message */
	_status.flightPathAngleSp = flightPathAngleSp;
	_status.flightPathAngle = flightPathAngle;
	_status.airspeedSp = airspeedSp;
	_status.airspeed = airspeed;

	/* use longitudinal acceleration setpoint for total energy control */
	return updateFlightPathAngleAcceleration(flightPathAngle, flightPathAngleSp, airspeed,
			accelerationLongitudinalSp, mode, limitOverride);
}

int mTecs::updateFlightPathAngleAcceleration(float flightPathAngle, float flightPathAngleSp, float airspeed,
		float accelerationLongitudinalSp, tecs_mode mode, LimitOverride limitOverride)
{
	/* check if all input arguments are numbers and abort if not so */
	if (!isfinite(flightPathAngle) || !isfinite(flightPathAngleSp) ||
			!isfinite(airspeed) || !isfinite(accelerationLongitudinalSp) || !isfinite(mode)) {
		return -1;
	}
	/* time measurement */
	updateTimeMeasurement();

	/* update parameters first */
	updateParams();

	/* calculate values (energies) */
	float flightPathAngleError = flightPathAngleSp - flightPathAngle;
	float airspeedDerivative = 0.0f;
	if(_airspeedDerivative.getDt() > 0.0f) {
		airspeedDerivative = _airspeedDerivative.update(airspeed);
	}
	float airspeedDerivativeNorm = airspeedDerivative / CONSTANTS_ONE_G;
	float airspeedDerivativeSp = accelerationLongitudinalSp;
	float airspeedDerivativeNormSp = airspeedDerivativeSp / CONSTANTS_ONE_G;
	float airspeedDerivativeNormError = airspeedDerivativeNormSp - airspeedDerivativeNorm;

	float totalEnergyRate = flightPathAngle + airspeedDerivativeNorm;
	float totalEnergyRateError = flightPathAngleError + airspeedDerivativeNormError;
	float totalEnergyRateSp = flightPathAngleSp + airspeedDerivativeNormSp;
	float totalEnergyRateError2 = totalEnergyRateSp - totalEnergyRate;

	float energyDistributionRate = flightPathAngle - airspeedDerivativeNorm;
	float energyDistributionRateError = flightPathAngleError - airspeedDerivativeNormError;
	float energyDistributionRateSp = flightPathAngleSp - airspeedDerivativeNormSp;
	float energyDistributionRateError2 = energyDistributionRateSp - energyDistributionRate;

	/* Debug output */
	if (_counter % 10 == 0) {
		debug("totalEnergyRateSp %.2f, totalEnergyRate %.2f, totalEnergyRateError %.2f totalEnergyRateError2 %.2f airspeedDerivativeNorm %.4f",
				(double)totalEnergyRateSp, (double)totalEnergyRate, (double)totalEnergyRateError, (double)totalEnergyRateError2, (double)airspeedDerivativeNorm);
		debug("energyDistributionRateSp %.2f, energyDistributionRate %.2f, energyDistributionRateError %.2f energyDistributionRateError2 %.2f",
				(double)energyDistributionRateSp, (double)energyDistributionRate, (double)energyDistributionRateError, (double)energyDistributionRateError2);
	}

	/* Check airspeed: if below safe value switch to underspeed mode (if not in takeoff mode) */
	if (mode != TECS_MODE_LAND && airspeed < _airspeedMin.get()) {
		mode = TECS_MODE_UNDERSPEED;
	}

	/* Set special ouput limiters if we are not in TECS_MODE_NORMAL */
	BlockOutputLimiter *outputLimiterThrottle = NULL; // NULL --> use standard inflight limits
	BlockOutputLimiter *outputLimiterPitch = NULL; // NULL --> use standard inflight limits
	if (mode == TECS_MODE_TAKEOFF) {
		outputLimiterThrottle = &_BlockOutputLimiterTakeoffThrottle; //XXX: accept prelaunch values from launchdetector
		outputLimiterPitch = &_BlockOutputLimiterTakeoffPitch;
	} else if (mode == TECS_MODE_LAND) {
		// only limit pitch but do not limit throttle
		outputLimiterPitch = &_BlockOutputLimiterLandPitch;
	} else if (mode == TECS_MODE_LAND_THROTTLELIM) {
		outputLimiterThrottle = &_BlockOutputLimiterLandThrottle;
		outputLimiterPitch = &_BlockOutputLimiterLandPitch;
	} else if (mode == TECS_MODE_UNDERSPEED) {
		outputLimiterThrottle = &_BlockOutputLimiterUnderspeedThrottle;
		outputLimiterPitch = &_BlockOutputLimiterUnderspeedPitch;
	}

	/* Apply overrride given by the limitOverride argument (this is used for limits which are not given by
	 * parameters such as pitch limits with takeoff waypoints or throttle limits when the launchdetector
	 * is running) */
	bool limitApplied = limitOverride.applyOverride(outputLimiterThrottle == NULL ?
			_controlTotalEnergy.getOutputLimiter() :
			*outputLimiterThrottle,
			outputLimiterPitch == NULL ?
			_controlEnergyDistribution.getOutputLimiter() :
			*outputLimiterPitch);

	/* Write part of the status message */
	_status.airspeedDerivativeSp = airspeedDerivativeSp;
	_status.airspeedDerivative = airspeedDerivative;
	_status.totalEnergyRateSp = totalEnergyRateSp;
	_status.totalEnergyRate = totalEnergyRate;
	_status.energyDistributionRateSp = energyDistributionRateSp;
	_status.energyDistributionRate = energyDistributionRate;
	_status.mode = mode;

	/** update control blocks **/
	/* update total energy rate control block */
	_throttleSp = _controlTotalEnergy.update(totalEnergyRateSp, totalEnergyRateError, outputLimiterThrottle);

	/* update energy distribution rate control block */
	_pitchSp = _controlEnergyDistribution.update(energyDistributionRateSp, energyDistributionRateError, outputLimiterPitch);

	if (_counter % 10 == 0) {
		debug("_throttleSp %.1f, _pitchSp %.1f, flightPathAngleSp %.1f, flightPathAngle %.1f accelerationLongitudinalSp %.1f, airspeedDerivative %.1f",
				(double)_throttleSp, (double)_pitchSp,
				(double)flightPathAngleSp, (double)flightPathAngle,
				(double)accelerationLongitudinalSp, (double)airspeedDerivative);
	}

	/* publish status messge */
	_status.update();

	/* clean up */
	_firstIterationAfterReset = false;
	_dtCalculated = false;

	_counter++;

	return 0;
}

void mTecs::resetIntegrators()
{
	_controlTotalEnergy.getIntegral().setY(0.0f);
	_controlEnergyDistribution.getIntegral().setY(0.0f);
	timestampLastIteration = hrt_absolute_time();
	_firstIterationAfterReset = true;
}

void mTecs::resetDerivatives(float airspeed)
{
	_airspeedDerivative.setU(airspeed);
}

void mTecs::updateTimeMeasurement()
{
	if (!_dtCalculated) {
		float deltaTSeconds = 0.0f;
		if (!_firstIterationAfterReset) {
			hrt_abstime timestampNow = hrt_absolute_time();
			deltaTSeconds = (float)(timestampNow - timestampLastIteration) * 1e-6f;
			timestampLastIteration = timestampNow;
		}
		setDt(deltaTSeconds);

		_dtCalculated = true;
	}
}

void mTecs::debug_print(const char *fmt, va_list args)
{
	fprintf(stderr, "%s: ", "[mtecs]");
	vfprintf(stderr, fmt, args);

	fprintf(stderr, "\n");
}

void mTecs::debug(const char *fmt, ...) {

	if (!_debug) {
		return;
	}

	va_list args;

	va_start(args, fmt);
	debug_print(fmt, args);
}

bool mTecs::LimitOverride::applyOverride(BlockOutputLimiter &outputLimiterThrottle,
		BlockOutputLimiter &outputLimiterPitch)
{
	bool ret = false;

	if (overrideThrottleMinEnabled)	{
		outputLimiterThrottle.setMin(overrideThrottleMin);
		ret = true;
	}
	if (overrideThrottleMaxEnabled)	{
		outputLimiterThrottle.setMax(overrideThrottleMax);
		ret = true;
	}
	if (overridePitchMinEnabled)	{
		outputLimiterPitch.setMin(overridePitchMin);
		ret = true;
	}
	if (overridePitchMaxEnabled)	{
		outputLimiterPitch.setMax(overridePitchMax);
		ret = true;
	}

	return ret;
}

} /* namespace fwPosctrl */
<|endoftext|>


<commit_before>/*
    Copyright 2012 Frederik Gladhorn <gladhorn@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) version 3, or any
    later version accepted by the membership of KDE e.V. (or its
    successor approved by the membership of KDE e.V.), which shall
    act as a proxy defined in Section 6 of version 3 of the license.

    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
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "accessibleobject.h"

#include <qstring.h>
#include <qdebug.h>

#include "accessibleobject_p.h"
#include "registry_p.h"

#include <atspi/atspi-constants.h>

using namespace QAccessibleClient;

AccessibleObject::AccessibleObject()
    :d(0)
{
}

AccessibleObject::AccessibleObject(RegistryPrivate *registryPrivate, const QString &service, const QString &path)
    :d(0)
{
    Q_ASSERT(registryPrivate);
    Q_ASSERT(!service.isEmpty());
    Q_ASSERT(!path.isEmpty());
    if (registryPrivate->m_cacheStrategy) {
        const QString id = path + service;
        d = registryPrivate->m_cacheStrategy->get(id);
        if (!d) {
            d = QSharedPointer<AccessibleObjectPrivate>(new AccessibleObjectPrivate(registryPrivate, service, path));
            registryPrivate->m_cacheStrategy->add(id, d);
        }
    } else {
        d = QSharedPointer<AccessibleObjectPrivate>(new AccessibleObjectPrivate(registryPrivate, service, path));
    }
}

AccessibleObject::AccessibleObject(const QSharedPointer<AccessibleObjectPrivate> &dd)
    :d(dd)
{
}

AccessibleObject::AccessibleObject(const AccessibleObject &other)
    : d(other.d)
{
}

AccessibleObject::~AccessibleObject()
{
}

QString AccessibleObject::id() const
{
    if (!d || !d->registryPrivate)
        return QString();
    return d->path + d->service;
}

QUrl AccessibleObject::url() const
{
    return d && d->registryPrivate ? d->registryPrivate->url(*this) : QUrl();
}

bool AccessibleObject::isValid() const
{
    return d && d->registryPrivate
             && (!d->service.isEmpty())
             && (!d->path.isEmpty())
             && (d->path != QLatin1String("/org/a11y/atspi/null"));
}

AccessibleObject &AccessibleObject::operator=(const AccessibleObject &other)
{
    d = other.d;
    return *this;
}

bool AccessibleObject::operator==(const AccessibleObject &other) const
{
    return (d == other.d) || (d && other.d && *d == *other.d);
}

RegistryPrivate* AccessibleObject::registryPrivate() const
{
    return d ? d->registryPrivate : 0;
}

QSharedPointer<AccessibleObjectPrivate> AccessibleObject::objectPrivate() const
{
    return d;
}

AccessibleObject AccessibleObject::parent() const
{
    return d->registryPrivate->parentAccessible(*this);
}

QList<AccessibleObject> AccessibleObject::children() const
{
    return d->registryPrivate->children(*this);
}

int AccessibleObject::childCount() const
{
    return d->registryPrivate->childCount(*this);
}

AccessibleObject AccessibleObject::child(int index) const
{
    return d->registryPrivate->child(*this, index);
}

int AccessibleObject::indexInParent() const
{
    return d->registryPrivate->indexInParent(*this);
}

QString AccessibleObject::name() const
{
    return d->registryPrivate->name(*this);
}

QString AccessibleObject::description() const
{
    return d->registryPrivate->description(*this);
}

AccessibleObject::Role AccessibleObject::role() const
{
    return d->registryPrivate->role(*this);
}

QString AccessibleObject::roleName() const
{
    return d->registryPrivate->roleName(*this);
}

QString AccessibleObject::localizedRoleName() const
{
    return d->registryPrivate->localizedRoleName(*this);
}

int AccessibleObject::layer() const
{
    return d->registryPrivate->layer(*this);
}

int AccessibleObject::mdiZOrder() const
{
    return d->registryPrivate->mdiZOrder(*this);
}

double AccessibleObject::alpha() const
{
    return d->registryPrivate->alpha(*this);
}

QRect AccessibleObject::boundingRect() const
{
    if( supportedInterfaces() & AccessibleObject::ComponentInterface ){
        return d->registryPrivate->boundingRect(*this);
    } else {
        qWarning() << "boundingRect called on accessible that does not implement component";
        return QRect();
    }
}

QRect AccessibleObject::characterRect(int offset) const
{
    if( supportedInterfaces() & AccessibleObject::TextInterface ){
        return d->registryPrivate->characterRect(*this, offset);
    } else {
        qWarning() << "characterRect called on accessible that does not implement text";
        return QRect();
    }
}

AccessibleObject::Interfaces AccessibleObject::supportedInterfaces() const
{
    return d->registryPrivate->supportedInterfaces(*this);
}

int AccessibleObject::caretOffset() const
{
    if( supportedInterfaces() & AccessibleObject::TextInterface ){
        return d->registryPrivate->caretOffset(*this);
    } else {
        qWarning() << "caretOffset called on accessible that does not implement text";
        return 0;
    }
}

QPoint AccessibleObject::focusPoint() const
{
    Interfaces ifaces = supportedInterfaces();
    if (ifaces & TextInterface) {
        int offset = caretOffset();
        QRect r = characterRect(offset);
        if (!r.isNull())
            return r.center();
    }
    if (ifaces & ComponentInterface) {
        QRect r = boundingRect();
        if (!r.isNull())
            return r.center();
    }
    AccessibleObject p = parent();
    if (p.isValid())
        return p.focusPoint(); // recursive
    return QPoint();
}

AccessibleObject AccessibleObject::application() const
{
    return d->registryPrivate->application(*this);
}

QString AccessibleObject::appToolkitName() const
{
    return d->registryPrivate->appToolkitName(*this);
}

QString AccessibleObject::appVersion() const
{
    return d->registryPrivate->appVersion(*this);
}

int AccessibleObject::appId() const
{
    return d->registryPrivate->appId(*this);
}

QString AccessibleObject::appLocale(LocaleType lctype) const
{
    return d->registryPrivate->appLocale(*this, lctype);
}

QString AccessibleObject::appBusAddress() const
{
    return d->registryPrivate->appBusAddress(*this);
}

double AccessibleObject::minimumValue() const
{
    return d->registryPrivate->minimumValue(*this);
}

double AccessibleObject::maximumValue() const
{
    return d->registryPrivate->maximumValue(*this);
}

double AccessibleObject::minimumValueIncrement() const
{
    return d->registryPrivate->minimumValueIncrement(*this);
}

double AccessibleObject::currentValue() const
{
    return d->registryPrivate->currentValue(*this);
}

QList<AccessibleObject> AccessibleObject::selection() const
{
    return d->registryPrivate->selection(*this);
}

QString AccessibleObject::imageDescription() const
{
    return d->registryPrivate->imageDescription(*this);
}

QString AccessibleObject::imageLocale() const
{
    return d->registryPrivate->imageLocale(*this);
}

QRect AccessibleObject::imageRect() const
{
    return d->registryPrivate->imageRect(*this);
}

QVector< QSharedPointer<QAction> > AccessibleObject::actions() const
{
    // Actions in atspi are supposed to be static what means they cannot change in
    // between (e.g. actions removed or added or edited) so we can safely just
    // fetch them only once and store the result for the life-time of the object,
    if (!d->actionsFetched) {
        d->actionsFetched = true;
        d->actions = d->registryPrivate->actions(*this);
    }
    return d->actions;
}

bool AccessibleObject::hasSelectableText() const
{
    return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_SELECTABLE_TEXT);
}

bool AccessibleObject::hasToolTip() const
{
    return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_HAS_TOOLTIP);
}

bool AccessibleObject::isActive() const
{
    return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_ACTIVE);
}

bool AccessibleObject::isCheckable() const
{
    //FIXME: Find better AccessibleObject::isCheckable
    //return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_);

    Role role = d->registryPrivate->role(*this);
    if (role == AccessibleObject::CheckBox ||
        role == AccessibleObject::CheckableMenuItem ||
        role == AccessibleObject::RadioButton ||
        role == AccessibleObject::RadioMenuItem ||
        role == AccessibleObject::ToggleButton)
            return true;
    return false;
}

bool AccessibleObject::isChecked() const
{
    return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_CHECKED);
}

bool AccessibleObject::isDefunct() const
{
    return d->defunct;
}

bool AccessibleObject::isDefault() const
{
    return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_IS_DEFAULT);
}

bool AccessibleObject::isEditable() const
{
    return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_EDITABLE);
}

bool AccessibleObject::isEnabled() const
{
    return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_ENABLED);
}

bool AccessibleObject::isExpandable() const
{
    return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_EXPANDABLE);
}

bool AccessibleObject::isExpanded() const
{
    return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_EXPANDED);
}

bool AccessibleObject::isFocusable() const
{
    return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_FOCUSABLE);
}

bool AccessibleObject::isFocused() const
{
    return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_FOCUSED);
}

bool AccessibleObject::isMultiLine() const
{
    return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_MULTI_LINE);
}

bool AccessibleObject::isSelectable() const
{
    return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_SELECTABLE);
}

bool AccessibleObject::isSelected() const
{
    return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_SELECTED);
}

bool AccessibleObject::isSensitive() const
{
    return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_SENSITIVE);
}

bool AccessibleObject::isSingleLine() const
{
    return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_SINGLE_LINE);
}

bool AccessibleObject::isVisible() const
{
    return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_VISIBLE);
}

bool AccessibleObject::supportsAutocompletion() const
{
    return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_SUPPORTS_AUTOCOMPLETION);
}

#ifndef QT_NO_DEBUG_STREAM
QACCESSIBILITYCLIENT_EXPORT QDebug QAccessibleClient::operator<<(QDebug d, const AccessibleObject &object)
{
    d.nospace();
    d << "AccessibleObject("; //d:" << hex << (void *) object.d << dec;
    d << "service=" << object.d->service;
    d << " path=" << object.d->path;
    d << ")";
    return d.space();
}
#endif

uint qHash(const QAccessibleClient::AccessibleObject& object) {
    return qHash(object.d);
}
<commit_msg>For the focus it's ok if width is zero.<commit_after>/*
    Copyright 2012 Frederik Gladhorn <gladhorn@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) version 3, or any
    later version accepted by the membership of KDE e.V. (or its
    successor approved by the membership of KDE e.V.), which shall
    act as a proxy defined in Section 6 of version 3 of the license.

    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
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "accessibleobject.h"

#include <qstring.h>
#include <qdebug.h>

#include "accessibleobject_p.h"
#include "registry_p.h"

#include <atspi/atspi-constants.h>

using namespace QAccessibleClient;

AccessibleObject::AccessibleObject()
    :d(0)
{
}

AccessibleObject::AccessibleObject(RegistryPrivate *registryPrivate, const QString &service, const QString &path)
    :d(0)
{
    Q_ASSERT(registryPrivate);
    Q_ASSERT(!service.isEmpty());
    Q_ASSERT(!path.isEmpty());
    if (registryPrivate->m_cacheStrategy) {
        const QString id = path + service;
        d = registryPrivate->m_cacheStrategy->get(id);
        if (!d) {
            d = QSharedPointer<AccessibleObjectPrivate>(new AccessibleObjectPrivate(registryPrivate, service, path));
            registryPrivate->m_cacheStrategy->add(id, d);
        }
    } else {
        d = QSharedPointer<AccessibleObjectPrivate>(new AccessibleObjectPrivate(registryPrivate, service, path));
    }
}

AccessibleObject::AccessibleObject(const QSharedPointer<AccessibleObjectPrivate> &dd)
    :d(dd)
{
}

AccessibleObject::AccessibleObject(const AccessibleObject &other)
    : d(other.d)
{
}

AccessibleObject::~AccessibleObject()
{
}

QString AccessibleObject::id() const
{
    if (!d || !d->registryPrivate)
        return QString();
    return d->path + d->service;
}

QUrl AccessibleObject::url() const
{
    return d && d->registryPrivate ? d->registryPrivate->url(*this) : QUrl();
}

bool AccessibleObject::isValid() const
{
    return d && d->registryPrivate
             && (!d->service.isEmpty())
             && (!d->path.isEmpty())
             && (d->path != QLatin1String("/org/a11y/atspi/null"));
}

AccessibleObject &AccessibleObject::operator=(const AccessibleObject &other)
{
    d = other.d;
    return *this;
}

bool AccessibleObject::operator==(const AccessibleObject &other) const
{
    return (d == other.d) || (d && other.d && *d == *other.d);
}

RegistryPrivate* AccessibleObject::registryPrivate() const
{
    return d ? d->registryPrivate : 0;
}

QSharedPointer<AccessibleObjectPrivate> AccessibleObject::objectPrivate() const
{
    return d;
}

AccessibleObject AccessibleObject::parent() const
{
    return d->registryPrivate->parentAccessible(*this);
}

QList<AccessibleObject> AccessibleObject::children() const
{
    return d->registryPrivate->children(*this);
}

int AccessibleObject::childCount() const
{
    return d->registryPrivate->childCount(*this);
}

AccessibleObject AccessibleObject::child(int index) const
{
    return d->registryPrivate->child(*this, index);
}

int AccessibleObject::indexInParent() const
{
    return d->registryPrivate->indexInParent(*this);
}

QString AccessibleObject::name() const
{
    return d->registryPrivate->name(*this);
}

QString AccessibleObject::description() const
{
    return d->registryPrivate->description(*this);
}

AccessibleObject::Role AccessibleObject::role() const
{
    return d->registryPrivate->role(*this);
}

QString AccessibleObject::roleName() const
{
    return d->registryPrivate->roleName(*this);
}

QString AccessibleObject::localizedRoleName() const
{
    return d->registryPrivate->localizedRoleName(*this);
}

int AccessibleObject::layer() const
{
    return d->registryPrivate->layer(*this);
}

int AccessibleObject::mdiZOrder() const
{
    return d->registryPrivate->mdiZOrder(*this);
}

double AccessibleObject::alpha() const
{
    return d->registryPrivate->alpha(*this);
}

QRect AccessibleObject::boundingRect() const
{
    if( supportedInterfaces() & AccessibleObject::ComponentInterface ){
        return d->registryPrivate->boundingRect(*this);
    } else {
        qWarning() << "boundingRect called on accessible that does not implement component";
        return QRect();
    }
}

QRect AccessibleObject::characterRect(int offset) const
{
    if( supportedInterfaces() & AccessibleObject::TextInterface ){
        return d->registryPrivate->characterRect(*this, offset);
    } else {
        qWarning() << "characterRect called on accessible that does not implement text";
        return QRect();
    }
}

AccessibleObject::Interfaces AccessibleObject::supportedInterfaces() const
{
    return d->registryPrivate->supportedInterfaces(*this);
}

int AccessibleObject::caretOffset() const
{
    if( supportedInterfaces() & AccessibleObject::TextInterface ){
        return d->registryPrivate->caretOffset(*this);
    } else {
        qWarning() << "caretOffset called on accessible that does not implement text";
        return 0;
    }
}

QPoint AccessibleObject::focusPoint() const
{
    Interfaces ifaces = supportedInterfaces();
    if (ifaces & TextInterface) {
        int offset = caretOffset();
        QRect r = characterRect(offset);
        if (r.x() != 0 || r.y() != 0)
            return r.center();
    }
    if (ifaces & ComponentInterface) {
        QRect r = boundingRect();
        if (!r.isNull())
            return r.center();
    }
    AccessibleObject p = parent();
    if (p.isValid())
        return p.focusPoint(); // recursive
    return QPoint();
}

AccessibleObject AccessibleObject::application() const
{
    return d->registryPrivate->application(*this);
}

QString AccessibleObject::appToolkitName() const
{
    return d->registryPrivate->appToolkitName(*this);
}

QString AccessibleObject::appVersion() const
{
    return d->registryPrivate->appVersion(*this);
}

int AccessibleObject::appId() const
{
    return d->registryPrivate->appId(*this);
}

QString AccessibleObject::appLocale(LocaleType lctype) const
{
    return d->registryPrivate->appLocale(*this, lctype);
}

QString AccessibleObject::appBusAddress() const
{
    return d->registryPrivate->appBusAddress(*this);
}

double AccessibleObject::minimumValue() const
{
    return d->registryPrivate->minimumValue(*this);
}

double AccessibleObject::maximumValue() const
{
    return d->registryPrivate->maximumValue(*this);
}

double AccessibleObject::minimumValueIncrement() const
{
    return d->registryPrivate->minimumValueIncrement(*this);
}

double AccessibleObject::currentValue() const
{
    return d->registryPrivate->currentValue(*this);
}

QList<AccessibleObject> AccessibleObject::selection() const
{
    return d->registryPrivate->selection(*this);
}

QString AccessibleObject::imageDescription() const
{
    return d->registryPrivate->imageDescription(*this);
}

QString AccessibleObject::imageLocale() const
{
    return d->registryPrivate->imageLocale(*this);
}

QRect AccessibleObject::imageRect() const
{
    return d->registryPrivate->imageRect(*this);
}

QVector< QSharedPointer<QAction> > AccessibleObject::actions() const
{
    // Actions in atspi are supposed to be static what means they cannot change in
    // between (e.g. actions removed or added or edited) so we can safely just
    // fetch them only once and store the result for the life-time of the object,
    if (!d->actionsFetched) {
        d->actionsFetched = true;
        d->actions = d->registryPrivate->actions(*this);
    }
    return d->actions;
}

bool AccessibleObject::hasSelectableText() const
{
    return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_SELECTABLE_TEXT);
}

bool AccessibleObject::hasToolTip() const
{
    return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_HAS_TOOLTIP);
}

bool AccessibleObject::isActive() const
{
    return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_ACTIVE);
}

bool AccessibleObject::isCheckable() const
{
    //FIXME: Find better AccessibleObject::isCheckable
    //return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_);

    Role role = d->registryPrivate->role(*this);
    if (role == AccessibleObject::CheckBox ||
        role == AccessibleObject::CheckableMenuItem ||
        role == AccessibleObject::RadioButton ||
        role == AccessibleObject::RadioMenuItem ||
        role == AccessibleObject::ToggleButton)
            return true;
    return false;
}

bool AccessibleObject::isChecked() const
{
    return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_CHECKED);
}

bool AccessibleObject::isDefunct() const
{
    return d->defunct;
}

bool AccessibleObject::isDefault() const
{
    return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_IS_DEFAULT);
}

bool AccessibleObject::isEditable() const
{
    return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_EDITABLE);
}

bool AccessibleObject::isEnabled() const
{
    return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_ENABLED);
}

bool AccessibleObject::isExpandable() const
{
    return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_EXPANDABLE);
}

bool AccessibleObject::isExpanded() const
{
    return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_EXPANDED);
}

bool AccessibleObject::isFocusable() const
{
    return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_FOCUSABLE);
}

bool AccessibleObject::isFocused() const
{
    return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_FOCUSED);
}

bool AccessibleObject::isMultiLine() const
{
    return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_MULTI_LINE);
}

bool AccessibleObject::isSelectable() const
{
    return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_SELECTABLE);
}

bool AccessibleObject::isSelected() const
{
    return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_SELECTED);
}

bool AccessibleObject::isSensitive() const
{
    return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_SENSITIVE);
}

bool AccessibleObject::isSingleLine() const
{
    return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_SINGLE_LINE);
}

bool AccessibleObject::isVisible() const
{
    return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_VISIBLE);
}

bool AccessibleObject::supportsAutocompletion() const
{
    return d->registryPrivate->state(*this) & (quint64(1) << ATSPI_STATE_SUPPORTS_AUTOCOMPLETION);
}

#ifndef QT_NO_DEBUG_STREAM
QACCESSIBILITYCLIENT_EXPORT QDebug QAccessibleClient::operator<<(QDebug d, const AccessibleObject &object)
{
    d.nospace();
    d << "AccessibleObject("; //d:" << hex << (void *) object.d << dec;
    d << "service=" << object.d->service;
    d << " path=" << object.d->path;
    d << ")";
    return d.space();
}
#endif

uint qHash(const QAccessibleClient::AccessibleObject& object) {
    return qHash(object.d);
}
<|endoftext|>


<commit_before>//=======================================================================
// Copyright 2014-2015 David Simmons-Duffin.
// Distributed under the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

// See the manual for a description of the correct XML input format.

#include "parse_append_many.hxx"

#include "../Polynomial.hxx"
#include "../SDP.hxx"

#include <boost/filesystem.hpp>
#include <boost/property_tree/xml_parser.hpp>

std::vector<Real> parse_vector(const boost::property_tree::ptree &tree);

Polynomial_Vector_Matrix
parse_polynomial_vector_matrix(const boost::property_tree::ptree &tree);

SDP read_bootstrap_sdp(const std::vector<boost::filesystem::path> sdp_files)
{
  Vector objective;
  std::vector<Polynomial_Vector_Matrix> polynomialVectorMatrices;
  for(auto &sdp_file : sdp_files)
    {
      {
        boost::property_tree::ptree tree;
        boost::property_tree::read_xml(sdp_file.string(), tree);

        const auto sdp = tree.get_child("sdp");
        auto objective_iterator(sdp.find("objective"));
        /// boost::property_tree uses not_found() instead of end() :(
        if(objective_iterator != sdp.not_found())
          { objective = parse_vector(objective_iterator->second); }

          auto polynomialVectorMatrices_iterator(
          sdp.find("polynomialVectorMatrices"));
        if(polynomialVectorMatrices_iterator != sdp.not_found())
          {
            parse_append_many("polynomialVectorMatrix",
                              parse_polynomial_vector_matrix,
                              polynomialVectorMatrices_iterator->second,
                              polynomialVectorMatrices);
          }
      }
    }
  return bootstrapSDP(objective, polynomialVectorMatrices);
}
<commit_msg>Reindent<commit_after>//=======================================================================
// Copyright 2014-2015 David Simmons-Duffin.
// Distributed under the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

// See the manual for a description of the correct XML input format.

#include "parse_append_many.hxx"

#include "../Polynomial.hxx"
#include "../SDP.hxx"

#include <boost/filesystem.hpp>
#include <boost/property_tree/xml_parser.hpp>

std::vector<Real> parse_vector(const boost::property_tree::ptree &tree);

Polynomial_Vector_Matrix
parse_polynomial_vector_matrix(const boost::property_tree::ptree &tree);

SDP read_bootstrap_sdp(const std::vector<boost::filesystem::path> sdp_files)
{
  Vector objective;
  std::vector<Polynomial_Vector_Matrix> polynomialVectorMatrices;
  for(auto &sdp_file : sdp_files)
    {
      boost::property_tree::ptree tree;
      boost::property_tree::read_xml(sdp_file.string(), tree);

      const auto sdp = tree.get_child("sdp");
      auto objective_iterator(sdp.find("objective"));
      /// boost::property_tree uses not_found() instead of end() :(
      if(objective_iterator != sdp.not_found())
        {
          objective = parse_vector(objective_iterator->second);
        }

      auto polynomialVectorMatrices_iterator(
      sdp.find("polynomialVectorMatrices"));
      if(polynomialVectorMatrices_iterator != sdp.not_found())
        {
          parse_append_many(
          "polynomialVectorMatrix", parse_polynomial_vector_matrix,
          polynomialVectorMatrices_iterator->second, polynomialVectorMatrices);
        }
    }
  return bootstrapSDP(objective, polynomialVectorMatrices);
}
<|endoftext|>


<commit_before>// time_t_decoder.cpp --- pretty print time_t values
// Author: Dan Harms <enniomore@icloud.com>
// Created: Thursday, July  2, 2015
// Modified Time-stamp: <2022-07-21 14:33:39 dharms>
// Modified by: Dan Harms

#include <iostream>
#include <iomanip>
#include <ctime>

int main(int argc, char* argv[])
{
   if (argc < 1)
   {
      return EXIT_FAILURE;
   }
   time_t when;
   if (argc == 1)
   {
      when = std::time(nullptr);
   }
   else
   {
      long long val = std::atoll(argv[1]);
      static const long long secs = 10000000000;
      static const long long nanos = 1000000000;
      if (val > secs)
      {
         val /= nanos;
      }
      when = val;
   }

   std::cout << std::put_time(std::gmtime(&when), "%c %Z")
             << " / "
             << std::put_time(std::localtime(&when), "%c %Z")
             << std::endl;

   return EXIT_SUCCESS;;
}

// code ends here
<commit_msg>fix small typo in src file<commit_after>// time_t_decoder.cpp --- pretty print time_t values
// Author: Dan Harms <enniomore@icloud.com>
// Created: Thursday, July  2, 2015
// Modified Time-stamp: <2022-10-12 21:56:53 dharms>
// Modified by: Dan Harms

#include <iostream>
#include <iomanip>
#include <ctime>

int main(int argc, char* argv[])
{
   if (argc < 1)
   {
      return EXIT_FAILURE;
   }
   time_t when;
   if (argc == 1)
   {
      when = std::time(nullptr);
   }
   else
   {
      long long val = std::atoll(argv[1]);
      static const long long secs = 10000000000;
      static const long long nanos = 1000000000;
      if (val > secs)
      {
         val /= nanos;
      }
      when = val;
   }

   std::cout << std::put_time(std::gmtime(&when), "%c %Z")
             << " / "
             << std::put_time(std::localtime(&when), "%c %Z")
             << std::endl;

   return EXIT_SUCCESS;
}

// code ends here
<|endoftext|>