<commit_before>/*******************************************************
 * Copyright (c) 2014, ArrayFire
 * All rights reserved.
 *
 * This file is distributed under 3-clause BSD license.
 * The complete license agreement can be obtained at:
 * http://arrayfire.com/licenses/BSD-3-Clause
 ********************************************************/

#include <af/dim4.hpp>
#include <af/defines.h>
#include <af/statistics.h>
#include <af/index.h>
#include <af/arith.h>
#include <af/data.h>
#include <handle.hpp>
#include <err_common.hpp>
#include <backend.hpp>
#include <sort.hpp>
#include <math.hpp>
#include <cast.hpp>

using namespace detail;
using af::dim4;

template<typename T>
static double median(const af_array& in)
{
    dim_t nElems = getInfo(in).elements();
    double mid      = (nElems + 1) / 2;
    af_seq mdSpan[1]= {af_make_seq(mid-1, mid, 1)};
    dim4 dims(nElems, 1, 1, 1);

    af_array temp = 0;
    AF_CHECK(af_moddims(&temp, in, 1, dims.get()));
    const Array<T> input  = getArray<T>(temp);

    Array<T> sortedArr = sort<T, true>(input, 0);

    double result;
    T resPtr[2];
    af_array res = 0;
    AF_CHECK(af_index(&res, getHandle<T>(sortedArr), 1, mdSpan));
    AF_CHECK(af_get_data_ptr((void*)&resPtr, res));

    if (nElems % 2 == 1) {
        result = resPtr[0];
    } else {
        if (input.isFloating()) {
            result = division(resPtr[0] + resPtr[1], 2);
        } else {
            result = division((float)resPtr[0] + (float)resPtr[1], 2);
        }
    }

    AF_CHECK(af_release_array(res));
    AF_CHECK(af_release_array(temp));

    return result;
}

template<typename T>
static af_array median(const af_array& in, const dim_t dim)
{
    const Array<T> input = getArray<T>(in);
    Array<T> sortedIn   = sort<T, true>(input, dim);

    int nElems    = input.dims()[0];
    double mid    = (nElems + 1) / 2;
    af_array left = 0;

    af_seq slices[4] = {af_span, af_span, af_span, af_span};
    slices[dim] = af_make_seq(mid-1.0, mid-1.0, 1.0);

    af_array sortedIn_handle = getHandle<T>(sortedIn);
    AF_CHECK(af_index(&left, sortedIn_handle, input.ndims(), slices));

    if (nElems % 2 == 1) {
        // mid-1 is our guy
        if (input.isFloating()) return left;

        // Return as floats for consistency
        af_array out;
        AF_CHECK(af_cast(&out, left, f32));
        AF_CHECK(af_release_array(left));
        AF_CHECK(af_release_array(sortedIn_handle));
        return out;
    } else {
        // ((mid-1)+mid)/2 is our guy
        dim4  dims = input.dims();
        af_array right = 0;
        slices[dim] = af_make_seq(mid, mid, 1.0);

        AF_CHECK(af_index(&right, sortedIn_handle, dims.ndims(), slices));

        af_array sumarr = 0;
        af_array carr   = 0;
        af_array result = 0;

        dim4 cdims = dim4(1, dims[1], dims[2], dims[3]);
        AF_CHECK(af_constant(&carr, 0.5, cdims.ndims(), cdims.get(), input.isDouble() ? f64 : f32));

        if (!input.isFloating()) {
            af_array lleft, rright;
            AF_CHECK(af_cast(&lleft, left, f32));
            AF_CHECK(af_cast(&rright, right, f32));
            AF_CHECK(af_release_array(left));
            AF_CHECK(af_release_array(right));
            left = lleft;
            right = rright;
        }

        AF_CHECK(af_add(&sumarr, left, right, false));
        AF_CHECK(af_mul(&result, sumarr, carr, false));

        AF_CHECK(af_release_array(left));
        AF_CHECK(af_release_array(right));
        AF_CHECK(af_release_array(sumarr));
        AF_CHECK(af_release_array(carr));
        AF_CHECK(af_release_array(sortedIn_handle));
        return result;
    }
}

af_err af_median_all(double *realVal, double *imagVal, const af_array in)
{
    try {
        ArrayInfo info = getInfo(in);
        af_dtype type = info.getType();
        switch(type) {
            case f64: *realVal = median<double>(in); break;
            case f32: *realVal = median<float >(in); break;
            case s32: *realVal = median<int   >(in); break;
            case u32: *realVal = median<uint  >(in); break;
            case s16: *realVal = median<short >(in); break;
            case u16: *realVal = median<ushort>(in); break;
            case  u8: *realVal = median<uchar >(in); break;
            default : TYPE_ERROR(1, type);
        }
    }
    CATCHALL;
    return AF_SUCCESS;
}

af_err af_median(af_array* out, const af_array in, const dim_t dim)
{
    try {
        ARG_ASSERT(2, (dim>=0 && dim<=0));

        af_array output = 0;
        ArrayInfo info = getInfo(in);
        af_dtype type = info.getType();
        switch(type) {
            case f64: output = median<double>(in, dim); break;
            case f32: output = median<float >(in, dim); break;
            case s32: output = median<int   >(in, dim); break;
            case u32: output = median<uint  >(in, dim); break;
            case s16: output = median<short >(in, dim); break;
            case u16: output = median<ushort>(in, dim); break;
            case  u8: output = median<uchar >(in, dim); break;
            default : TYPE_ERROR(1, type);
        }
        std::swap(*out, output);
    }
    CATCHALL;
    return AF_SUCCESS;
}
<commit_msg>Memory leak fix in af_median_all<commit_after>/*******************************************************
 * Copyright (c) 2014, ArrayFire
 * All rights reserved.
 *
 * This file is distributed under 3-clause BSD license.
 * The complete license agreement can be obtained at:
 * http://arrayfire.com/licenses/BSD-3-Clause
 ********************************************************/

#include <af/dim4.hpp>
#include <af/defines.h>
#include <af/statistics.h>
#include <af/index.h>
#include <af/arith.h>
#include <af/data.h>
#include <handle.hpp>
#include <err_common.hpp>
#include <backend.hpp>
#include <sort.hpp>
#include <math.hpp>
#include <cast.hpp>

using namespace detail;
using af::dim4;

template<typename T>
static double median(const af_array& in)
{
    dim_t nElems = getInfo(in).elements();
    double mid      = (nElems + 1) / 2;
    af_seq mdSpan[1]= {af_make_seq(mid-1, mid, 1)};
    dim4 dims(nElems, 1, 1, 1);

    af_array temp = 0;
    AF_CHECK(af_moddims(&temp, in, 1, dims.get()));
    const Array<T> input  = getArray<T>(temp);

    Array<T> sortedArr = sort<T, true>(input, 0);

    af_array sarrHandle = getHandle<T>(sortedArr);

    double result;
    T resPtr[2];
    af_array res = 0;
    AF_CHECK(af_index(&res, sarrHandle, 1, mdSpan));
    AF_CHECK(af_get_data_ptr((void*)&resPtr, res));

    AF_CHECK(af_release_array(res));
    AF_CHECK(af_release_array(sarrHandle));
    AF_CHECK(af_release_array(temp));

    if (nElems % 2 == 1) {
        result = resPtr[0];
    } else {
        if (input.isFloating()) {
            result = division(resPtr[0] + resPtr[1], 2);
        } else {
            result = division((float)resPtr[0] + (float)resPtr[1], 2);
        }
    }

    return result;
}

template<typename T>
static af_array median(const af_array& in, const dim_t dim)
{
    const Array<T> input = getArray<T>(in);
    Array<T> sortedIn   = sort<T, true>(input, dim);

    int nElems    = input.dims()[0];
    double mid    = (nElems + 1) / 2;
    af_array left = 0;

    af_seq slices[4] = {af_span, af_span, af_span, af_span};
    slices[dim] = af_make_seq(mid-1.0, mid-1.0, 1.0);

    af_array sortedIn_handle = getHandle<T>(sortedIn);
    AF_CHECK(af_index(&left, sortedIn_handle, input.ndims(), slices));

    if (nElems % 2 == 1) {
        // mid-1 is our guy
        if (input.isFloating()) return left;

        // Return as floats for consistency
        af_array out;
        AF_CHECK(af_cast(&out, left, f32));
        AF_CHECK(af_release_array(left));
        AF_CHECK(af_release_array(sortedIn_handle));
        return out;
    } else {
        // ((mid-1)+mid)/2 is our guy
        dim4  dims = input.dims();
        af_array right = 0;
        slices[dim] = af_make_seq(mid, mid, 1.0);

        AF_CHECK(af_index(&right, sortedIn_handle, dims.ndims(), slices));

        af_array sumarr = 0;
        af_array carr   = 0;
        af_array result = 0;

        dim4 cdims = dim4(1, dims[1], dims[2], dims[3]);
        AF_CHECK(af_constant(&carr, 0.5, cdims.ndims(), cdims.get(), input.isDouble() ? f64 : f32));

        if (!input.isFloating()) {
            af_array lleft, rright;
            AF_CHECK(af_cast(&lleft, left, f32));
            AF_CHECK(af_cast(&rright, right, f32));
            AF_CHECK(af_release_array(left));
            AF_CHECK(af_release_array(right));
            left = lleft;
            right = rright;
        }

        AF_CHECK(af_add(&sumarr, left, right, false));
        AF_CHECK(af_mul(&result, sumarr, carr, false));

        AF_CHECK(af_release_array(left));
        AF_CHECK(af_release_array(right));
        AF_CHECK(af_release_array(sumarr));
        AF_CHECK(af_release_array(carr));
        AF_CHECK(af_release_array(sortedIn_handle));
        return result;
    }
}

af_err af_median_all(double *realVal, double *imagVal, const af_array in)
{
    try {
        ArrayInfo info = getInfo(in);
        af_dtype type = info.getType();
        switch(type) {
            case f64: *realVal = median<double>(in); break;
            case f32: *realVal = median<float >(in); break;
            case s32: *realVal = median<int   >(in); break;
            case u32: *realVal = median<uint  >(in); break;
            case s16: *realVal = median<short >(in); break;
            case u16: *realVal = median<ushort>(in); break;
            case  u8: *realVal = median<uchar >(in); break;
            default : TYPE_ERROR(1, type);
        }
    }
    CATCHALL;
    return AF_SUCCESS;
}

af_err af_median(af_array* out, const af_array in, const dim_t dim)
{
    try {
        ARG_ASSERT(2, (dim>=0 && dim<=0));

        af_array output = 0;
        ArrayInfo info = getInfo(in);
        af_dtype type = info.getType();
        switch(type) {
            case f64: output = median<double>(in, dim); break;
            case f32: output = median<float >(in, dim); break;
            case s32: output = median<int   >(in, dim); break;
            case u32: output = median<uint  >(in, dim); break;
            case s16: output = median<short >(in, dim); break;
            case u16: output = median<ushort>(in, dim); break;
            case  u8: output = median<uchar >(in, dim); break;
            default : TYPE_ERROR(1, type);
        }
        std::swap(*out, output);
    }
    CATCHALL;
    return AF_SUCCESS;
}
<|endoftext|>


<commit_before>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * 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
 * OpenSceneGraph Public License for more details.
*/

#include <osgUtil/Optimizer>
#include <osgDB/ReadFile>
#include <osgProducer/Viewer>

#include <osg/Material>
#include <osg/Geode>
#include <osg/BlendFunc>
#include <osg/Depth>
#include <osg/Projection>
#include <osg/PolygonOffset>
#include <osg/MatrixTransform>

#include <osgText/Text>

osg::Node* createHUD()
{
    osg::Geode* geode = new osg::Geode();

    std::string timesFont("fonts/arial.ttf");

    // turn lighting off for the text and disable depth test to ensure its always ontop.
    osg::StateSet* stateset = geode->getOrCreateStateSet();
    stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);

#if 0
    // to ensure the hud appears on top we can either use osg::Depth to force the
    // depth fragments to be placed at the front of the screen.
    stateset->setAttribute(new osg::Depth(osg::Depth::LESS,0.0,0.0001));
#else
    // or disable depth test, and make sure that the hud is drawn after everything
    // else so that it always appears ontop.
    stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);
    stateset->setRenderBinDetails(11,"RenderBin");
#endif

    osg::Vec3 position(150.0f,800.0f,0.0f);
    osg::Vec3 delta(0.0f,-120.0f,0.0f);

    {
        osgText::Text* text = new  osgText::Text;
        geode->addDrawable( text );

        text->setFont(timesFont);
        text->setPosition(position);
        text->setText("Head Up Displays are simple :-)");

        position += delta;
    }

    {
        osgText::Text* text = new  osgText::Text;
        geode->addDrawable( text );

        text->setFont(timesFont);
        text->setPosition(position);
        text->setText("All you need to do is create your text in a subgraph.");

        position += delta;
    }

    {
        osgText::Text* text = new  osgText::Text;
        geode->addDrawable( text );

        text->setFont(timesFont);
        text->setPosition(position);
        text->setText("Disable depth test in this subgraph to ensure its always ontop.");

        position += delta;
    }

    {
        osgText::Text* text = new  osgText::Text;
        geode->addDrawable( text );

        text->setFont(timesFont);
        text->setPosition(position);
        text->setText("Then place an osg::Projection node above the subgraph\nto create an orthographic projection.");

        position += delta;
    }

    {
        osgText::Text* text = new  osgText::Text;
        geode->addDrawable( text );

        text->setFont(timesFont);
        text->setPosition(position);
        text->setText("And add an osg::ModelViewMatrix set to ABSOLUTE_RF to ensure\nit remains independent from any external model view matrices.");

        position += delta;
    }

    {
        osg::BoundingBox bb;
        for(unsigned int i=0;i<geode->getNumDrawables();++i)
        {
            bb.expandBy(geode->getDrawable(i)->getBound());
        }

        osg::Geometry* geom = new osg::Geometry;

        osg::Vec3Array* vertices = new osg::Vec3Array;
        float depth = bb.zMin()-0.1;
        vertices->push_back(osg::Vec3(bb.xMin(),bb.yMax(),depth));
        vertices->push_back(osg::Vec3(bb.xMin(),bb.yMin(),depth));
        vertices->push_back(osg::Vec3(bb.xMax(),bb.yMin(),depth));
        vertices->push_back(osg::Vec3(bb.xMax(),bb.yMax(),depth));
        geom->setVertexArray(vertices);

        osg::Vec3Array* normals = new osg::Vec3Array;
        normals->push_back(osg::Vec3(0.0f,0.0f,1.0f));
        geom->setNormalArray(normals);
        geom->setNormalBinding(osg::Geometry::BIND_OVERALL);

        osg::Vec4Array* colors = new osg::Vec4Array;
        colors->push_back(osg::Vec4(1.0f,1.0,0.8f,0.2f));
        geom->setColorArray(colors);
        geom->setColorBinding(osg::Geometry::BIND_OVERALL);

        geom->addPrimitiveSet(new osg::DrawArrays(GL_QUADS,0,4));

        osg::StateSet* stateset = geom->getOrCreateStateSet();
        stateset->setMode(GL_BLEND,osg::StateAttribute::ON);
        //stateset->setAttribute(new osg::PolygonOffset(1.0f,1.0f),osg::StateAttribute::ON);
        stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);

        geode->addDrawable(geom);
    }

    // create the hud.
    osg::MatrixTransform* modelview_abs = new osg::MatrixTransform;
    modelview_abs->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
    modelview_abs->setMatrix(osg::Matrix::identity());
    modelview_abs->addChild(geode);

    osg::Projection* projection = new osg::Projection;
    projection->setMatrix(osg::Matrix::ortho2D(0,1280,0,1024));
    projection->addChild(modelview_abs);

    return projection;

}

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

    // use an ArgumentParser object to manage the program arguments.
    osg::ArgumentParser arguments(&argc,argv);

    // set up the usage document, in case we need to print out how to use this program.
    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the example which demonstrates how to do Head Up Displays.");
    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] [filename] ...");
    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");

    // construct the viewer.
    osgProducer::Viewer viewer(arguments);

    // set up the value with sensible default event handlers.
    viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);

    // get details on keyboard and mouse bindings used by the viewer.
    viewer.getUsage(*arguments.getApplicationUsage());

    // if user request help write it out to cout.
    if (arguments.read("-h") || arguments.read("--help"))
    {
        arguments.getApplicationUsage()->write(std::cout);
        return 1;
    }

    // any option left unread are converted into errors to write out later.
    arguments.reportRemainingOptionsAsUnrecognized();

    // report any errors if they have occured when parsing the program aguments.
    if (arguments.errors())
    {
        arguments.writeErrorMessages(std::cout);
        return 1;
    }

    // read the scene from the list of file specified commandline args.
    osg::ref_ptr<osg::Node> scene = osgDB::readNodeFiles(arguments);

    osg::ref_ptr<osg::Group> group  = new osg::Group;

    // add the HUD subgraph.
    if (scene.valid()) group->addChild(scene.get());
    group->addChild(createHUD());

    // set the scene to render
    viewer.setSceneData(group.get());

    // create the windows and run the threads.
    viewer.realize();

    while( !viewer.done() )
    {
        // wait for all cull and draw threads to complete.
        viewer.sync();

        // update the scene by traversing it with the the update visitor which will
        // call all node update callbacks and animations.
        viewer.update();

        // fire off the cull and draw traversals of the scene.
        viewer.frame();

    }

    // wait for all cull and draw threads to complete before exit.
    viewer.sync();

    return 0;
}
<commit_msg>Disabled culling on the aboslute transform to fix bug culling of hud.<commit_after>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * 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
 * OpenSceneGraph Public License for more details.
*/

#include <osgUtil/Optimizer>
#include <osgDB/ReadFile>
#include <osgProducer/Viewer>

#include <osg/Material>
#include <osg/Geode>
#include <osg/BlendFunc>
#include <osg/Depth>
#include <osg/Projection>
#include <osg/PolygonOffset>
#include <osg/MatrixTransform>

#include <osgText/Text>

osg::Node* createHUD()
{
    osg::Geode* geode = new osg::Geode();

    std::string timesFont("fonts/arial.ttf");

    // turn lighting off for the text and disable depth test to ensure its always ontop.
    osg::StateSet* stateset = geode->getOrCreateStateSet();
    stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);

#if 0
    // to ensure the hud appears on top we can either use osg::Depth to force the
    // depth fragments to be placed at the front of the screen.
    stateset->setAttribute(new osg::Depth(osg::Depth::LESS,0.0,0.0001));
#else
    // or disable depth test, and make sure that the hud is drawn after everything
    // else so that it always appears ontop.
    stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);
    stateset->setRenderBinDetails(11,"RenderBin");
#endif

    osg::Vec3 position(150.0f,800.0f,0.0f);
    osg::Vec3 delta(0.0f,-120.0f,0.0f);

    {
        osgText::Text* text = new  osgText::Text;
        geode->addDrawable( text );

        text->setFont(timesFont);
        text->setPosition(position);
        text->setText("Head Up Displays are simple :-)");

        position += delta;
    }

    {
        osgText::Text* text = new  osgText::Text;
        geode->addDrawable( text );

        text->setFont(timesFont);
        text->setPosition(position);
        text->setText("All you need to do is create your text in a subgraph.");

        position += delta;
    }

    {
        osgText::Text* text = new  osgText::Text;
        geode->addDrawable( text );

        text->setFont(timesFont);
        text->setPosition(position);
        text->setText("Disable depth test in this subgraph to ensure its always ontop.");

        position += delta;
    }

    {
        osgText::Text* text = new  osgText::Text;
        geode->addDrawable( text );

        text->setFont(timesFont);
        text->setPosition(position);
        text->setText("Then place an osg::Projection node above the subgraph\nto create an orthographic projection.");

        position += delta;
    }

    {
        osgText::Text* text = new  osgText::Text;
        geode->addDrawable( text );

        text->setFont(timesFont);
        text->setPosition(position);
        text->setText("And add an osg::ModelViewMatrix set to ABSOLUTE_RF to ensure\nit remains independent from any external model view matrices.");

        position += delta;
    }

    {
        osg::BoundingBox bb;
        for(unsigned int i=0;i<geode->getNumDrawables();++i)
        {
            bb.expandBy(geode->getDrawable(i)->getBound());
        }

        osg::Geometry* geom = new osg::Geometry;

        osg::Vec3Array* vertices = new osg::Vec3Array;
        float depth = bb.zMin()-0.1;
        vertices->push_back(osg::Vec3(bb.xMin(),bb.yMax(),depth));
        vertices->push_back(osg::Vec3(bb.xMin(),bb.yMin(),depth));
        vertices->push_back(osg::Vec3(bb.xMax(),bb.yMin(),depth));
        vertices->push_back(osg::Vec3(bb.xMax(),bb.yMax(),depth));
        geom->setVertexArray(vertices);

        osg::Vec3Array* normals = new osg::Vec3Array;
        normals->push_back(osg::Vec3(0.0f,0.0f,1.0f));
        geom->setNormalArray(normals);
        geom->setNormalBinding(osg::Geometry::BIND_OVERALL);

        osg::Vec4Array* colors = new osg::Vec4Array;
        colors->push_back(osg::Vec4(1.0f,1.0,0.8f,0.2f));
        geom->setColorArray(colors);
        geom->setColorBinding(osg::Geometry::BIND_OVERALL);

        geom->addPrimitiveSet(new osg::DrawArrays(GL_QUADS,0,4));

        osg::StateSet* stateset = geom->getOrCreateStateSet();
        stateset->setMode(GL_BLEND,osg::StateAttribute::ON);
        //stateset->setAttribute(new osg::PolygonOffset(1.0f,1.0f),osg::StateAttribute::ON);
        stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);

        geode->addDrawable(geom);
    }

    // create the hud.
    osg::MatrixTransform* modelview_abs = new osg::MatrixTransform;
    modelview_abs->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
    modelview_abs->setCullingActive(false);
    modelview_abs->setMatrix(osg::Matrix::identity());
    modelview_abs->addChild(geode);

    osg::Projection* projection = new osg::Projection;
    projection->setMatrix(osg::Matrix::ortho2D(0,1280,0,1024));
    projection->addChild(modelview_abs);

    return projection;

}

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

    // use an ArgumentParser object to manage the program arguments.
    osg::ArgumentParser arguments(&argc,argv);

    // set up the usage document, in case we need to print out how to use this program.
    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the example which demonstrates how to do Head Up Displays.");
    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] [filename] ...");
    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");

    // construct the viewer.
    osgProducer::Viewer viewer(arguments);

    // set up the value with sensible default event handlers.
    viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);

    // get details on keyboard and mouse bindings used by the viewer.
    viewer.getUsage(*arguments.getApplicationUsage());

    // if user request help write it out to cout.
    if (arguments.read("-h") || arguments.read("--help"))
    {
        arguments.getApplicationUsage()->write(std::cout);
        return 1;
    }

    // any option left unread are converted into errors to write out later.
    arguments.reportRemainingOptionsAsUnrecognized();

    // report any errors if they have occured when parsing the program aguments.
    if (arguments.errors())
    {
        arguments.writeErrorMessages(std::cout);
        return 1;
    }

    // read the scene from the list of file specified commandline args.
    osg::ref_ptr<osg::Node> scene = osgDB::readNodeFiles(arguments);

    osg::ref_ptr<osg::Group> group  = new osg::Group;

    // add the HUD subgraph.
    if (scene.valid()) group->addChild(scene.get());
    group->addChild(createHUD());

    // set the scene to render
    viewer.setSceneData(group.get());

    // create the windows and run the threads.
    viewer.realize();

    while( !viewer.done() )
    {
        // wait for all cull and draw threads to complete.
        viewer.sync();

        // update the scene by traversing it with the the update visitor which will
        // call all node update callbacks and animations.
        viewer.update();

        // fire off the cull and draw traversals of the scene.
        viewer.frame();

    }

    // wait for all cull and draw threads to complete before exit.
    viewer.sync();

    return 0;
}
<|endoftext|>


<commit_before>#include <signal.h>				// for signal, SIGINT
#include <zmq.h>
#include "zmq_packet.h"
#include <uuid.h>
#include <ctime>
#include "util.h"
#include "timesync.h"
#include "h5analogwriter.h"

bool s_interrupted = false;

static void s_signal_handler(int)
{
	s_interrupted = true;
	printf("\n");
}

static void s_catch_signals(void)
{
	struct sigaction action;
	action.sa_handler = s_signal_handler;
	action.sa_flags = 0;
	sigemptyset(&action.sa_mask);
	sigaction(SIGINT, &action, NULL);
	sigaction(SIGQUIT, &action, NULL);
	sigaction(SIGTERM, &action, NULL);
}

int main(int argc, char *argv[])
{
	// h5bbsave [zmq_sub] [filename]

	if (argc < 3) {
		printf("\nh5bbsave - save broadband data to NWB (HDF5)\n");
		printf("usage: h5bbsave [zmq_sub] [filename]\n\n");
		return 1;
	}

	std::string zin = argv[1];
	std::string fn	= argv[2];

	printf("ZMQ SUB: %s\n", zin.c_str());
	printf("Filename: %s\n", fn.c_str());
	printf("\n");

	s_catch_signals();

	TimeSyncClient *tsc = new TimeSyncClient();  // translates tk and ts

	H5AnalogWriter h5;

	zmq::context_t zcontext(1);	// single zmq thread

	zmq::socket_t po8e_query_sock(zcontext, ZMQ_REQ);
	po8e_query_sock.connect("ipc:///tmp/po8e-query.zmq");

	u64 nnc; // num neural channels
	zmq::message_t msg(3);
	memcpy(msg.data(), "NNC", 3);
	po8e_query_sock.send(msg);
	msg.rebuild();
	try {
		po8e_query_sock.recv(&msg);
	} catch (zmq::error_t &e) {
		exit(1);
	}
	memcpy(&nnc, (u64 *)msg.data(), sizeof(u64));

	std::vector <std::string> names;

	for (u64 ch=0; ch<nnc; ch++) {
		// NC : X : NAME
		msg.rebuild(2);
		memcpy(msg.data(), "NC", 2);
		po8e_query_sock.send(msg, ZMQ_SNDMORE);
		msg.rebuild(sizeof(u64));
		memcpy(msg.data(), &ch, sizeof(u64));
		po8e_query_sock.send(msg, ZMQ_SNDMORE);
		msg.rebuild(4);
		memcpy(msg.data(), "NAME", 4);
		po8e_query_sock.send(msg);
		msg.rebuild();
		po8e_query_sock.recv(&msg);
		names.push_back(std::string((const char *)msg.data(), msg.size()));
	}

	size_t max_str = 0;
	for (auto &x : names) {
		max_str = max_str > x.size() ? max_str : x.size();
	}
	auto name = new char[max_str*names.size()];
	for (size_t i=0; i<names.size(); i++) {
		strncpy(&name[i*max_str], names[i].c_str(), names[i].size());
	}

	uuid_t u;
	uuid_generate(u);
	char uu[37];
	uuid_unparse(u, uu);

	time_t t_create;
	time(&t_create);
	char create_date[sizeof("YYYY-MM-DDTHH:MM:SSZ")];
	strftime(create_date, sizeof(create_date), "%FT%TZ", gmtime(&t_create));

	h5.open(fn.c_str(), nnc);
	h5.setVersion();
	h5.setUUID(uu);
	h5.setFileCreateDate(create_date);
	h5.setSessionDescription("broadband data");
	h5.setMetaData(1.0/3276700, name, max_str);

	delete[] name;

	zmq::socket_t socket_in(zcontext, ZMQ_SUB);
	socket_in.connect(zin.c_str());
	socket_in.setsockopt(ZMQ_SUBSCRIBE, "", 0);	// subscribe to everything

	// init poll set
	zmq::pollitem_t items [] = {
		{ socket_in, 	0, ZMQ_POLLIN, 0 }
	};

	int waiter = 0;
	int counter = 0;
	std::vector<const char *> spinner;
	spinner.emplace_back(">>>    >>>");
	spinner.emplace_back(" >>>    >>");
	spinner.emplace_back("  >>>    >");
	spinner.emplace_back("   >>>    ");
	spinner.emplace_back("    >>>   ");
	spinner.emplace_back(">    >>>  ");
	spinner.emplace_back(">>    >>> ");

	size_t zin_n = zin.find_last_of("/");

	while (!s_interrupted) {

		try {
			zmq::poll(&items[0], 1, -1); //  -1 means block
		} catch (zmq::error_t &e) {}

		if (items[0].revents & ZMQ_POLLIN) {

			socket_in.recv(&msg);

			char *ptr = (char *)msg.data();

			u64 nc, ns;

			// parse message
			memcpy(&nc, ptr+0, sizeof(u64));
			memcpy(&ns, ptr+8, sizeof(u64));

			auto tk 	= new i64[ns];
			auto ts 	= new double[ns];

			memcpy(tk, ptr+16, sizeof(i64));

			ts[0] = tsc->getTime(tk[0]);
			for (size_t i=1; i < ns; i++) {
				tk[i] = tk[i-1] + 1;
				ts[i] = tsc->getTime(tk[i]);
			}

			auto f = new float[nc*ns];
			memcpy(f, ptr+24, nc*ns*sizeof(float));

			auto x = new i16[nc*ns];
			for (size_t i=0; i<nc; i++) {
				for (size_t k=0; k<ns; k++) {
					// note that we transpose on the fly here to NWB format
					x[k*nc+i] = (i16)(f[i*ns+k] * 3276700 / 1e6); // pack
				}
			}
			delete[] f;

			h5.write(nc, ns, tk, ts, x); // frees memory when done

			if (waiter % 200 == 0) {
				time_t now;
				time(&now);
				double sec = difftime(now, t_create);
				int min = sec / 60;
				int hr  = min / 60;
				printf(" [%s]%s[%s] (%02d:%02d:%02d)\r",
				       zin.substr(zin_n+1).c_str(),
				       spinner[counter % spinner.size()],
				       fn.c_str(),
				       hr,
				       min % 60,
				       int(sec) % 60);
				fflush(stdout);
				counter++;
			}
			waiter++;

		}

	}

	h5.close();

	delete tsc;

}<commit_msg>i think i have h5bbsave compiling etc again<commit_after>#include <signal.h>				// for signal, SIGINT
#include <zmq.h>
#include "zmq_packet.h"
#include <uuid.h>
#include <ctime>
#include "util.h"
#include "timesync.h"
#include "h5analogwriter.h"

bool s_interrupted = false;
std::vector <void *> g_socks;

static void s_signal_handler(int)
{
	s_interrupted = true;
}

static void s_catch_signals(void)
{
	struct sigaction action;
	action.sa_handler = s_signal_handler;
	action.sa_flags = 0;
	sigemptyset(&action.sa_mask);
	sigaction(SIGINT, &action, NULL);
	sigaction(SIGQUIT, &action, NULL);
	sigaction(SIGTERM, &action, NULL);
}

static void die(void *ctx, int status)
{
	s_interrupted = true;
	for (auto &sock : g_socks) {
		zmq_close(sock);
	}
	zmq_ctx_destroy(ctx);
	exit(status);
}

int main(int argc, char *argv[])
{
	// h5bbsave [zmq_sub] [filename]

	if (argc < 3) {
		printf("\nh5bbsave - save broadband data to NWB (HDF5)\n");
		printf("usage: h5bbsave [zmq_sub] [filename]\n\n");
		return 1;
	}

	std::string zin = argv[1];
	std::string fn	= argv[2];

	debug("ZMQ SUB: %s", zin.c_str());
	debug("Filename: %s", fn.c_str());

	s_catch_signals();

	xdgHandle xdg;
	xdgInitHandle(&xdg);
	char *confpath = xdgConfigFind("spk/spk.rc", &xdg);
	char *tmp = confpath;
	// confpath is "string1\0string2\0string3\0\0"

	luaConf conf;

	while (*tmp) {
		conf.loadConf(tmp);
		tmp += strlen(tmp) + 1;
	}
	if (confpath)
		free(confpath);
	xdgWipeHandle(&xdg);

	std::string zq = "ipc:///tmp/query.zmq";
	conf.getString("spk.query_socket", zq);

	TimeSyncClient *tsc = new TimeSyncClient();  // translates tk and ts

	H5AnalogWriter h5;

	void *zcontext = zmq_ctx_new();
	if (zcontext == NULL) {
		error("zmq: could not create context");
		return 1;
	}

	// we don't need 1024 sockets
	if (zmq_ctx_set(zcontext, ZMQ_MAX_SOCKETS, 64) != 0) {
		error("zmq: could not set max sockets");
		die(zcontext, 1);
	}

	void *query_sock = zmq_socket(zcontext, ZMQ_REQ);
	if (query_sock == NULL) {
		error("zmq: could not create socket");
		die(zcontext, 1);
	}
	g_socks.push_back(query_sock);

	if (zmq_connect(query_sock, zq.c_str()) != 0) {
		error("zmq: could not connect to socket");
		die(zcontext, 1);
	}

	u64 nnc; // num neural channels
	zmq_send(query_sock, "NNC", 3, 0);
	if (zmq_recv(query_sock, &nnc, sizeof(u64), 0) == -1) {
		error("zmq: could not recv from query sock");
		die(zcontext, 1);
	}

	std::vector <std::string> names;

	for (u64 ch=0; ch<nnc; ch++) {
		// NC : X : NAME
		zmq_send(query_sock, "NC", 2, ZMQ_SNDMORE);
		zmq_send(query_sock, &ch, sizeof(u64), ZMQ_SNDMORE);
		zmq_send(query_sock, "NAME", 4, 0);

		zmq_msg_t msg;
		zmq_msg_init(&msg);
		zmq_msg_recv(&msg, query_sock, 0);

		names.push_back(std::string((const char *)zmq_msg_data(&msg), zmq_msg_size(&msg)));
		zmq_msg_close(&msg);

	}

	size_t max_str = 0;
	for (auto &x : names) {
		max_str = max_str > x.size() ? max_str : x.size();
	}
	auto name = new char[max_str*names.size()];
	for (size_t i=0; i<names.size(); i++) {
		strncpy(&name[i*max_str], names[i].c_str(), names[i].size());
	}

	uuid_t u;
	uuid_generate(u);
	char uu[37];
	uuid_unparse(u, uu);

	time_t t_create;
	time(&t_create);
	char create_date[sizeof("YYYY-MM-DDTHH:MM:SSZ")];
	strftime(create_date, sizeof(create_date), "%FT%TZ", gmtime(&t_create));

	h5.open(fn.c_str(), nnc);
	h5.setVersion();
	h5.setUUID(uu);
	h5.setFileCreateDate(create_date);
	h5.setSessionDescription("broadband data");
	h5.setMetaData(1.0/3276700, name, max_str);

	delete[] name;

	void *socket_in = zmq_socket(zcontext, ZMQ_SUB);
	if (socket_in == NULL) {
		error("zmq: could not create socket");
		die(zcontext, 1);
	}
	g_socks.push_back(socket_in);

	if (zmq_connect(socket_in, zin.c_str()) != 0) {
		error("zmq: could not connect to socket");
		die(zcontext, 1);
	}
	// subscribe to everything
	if (zmq_setsockopt(socket_in, ZMQ_SUBSCRIBE, "", 0) != 0) {
		error("zmq: could not set socket options");
		die(zcontext, 1);
	}

	zmq_pollitem_t items [] = {
		{ socket_in, 	0, ZMQ_POLLIN, 0 }
	};

	int waiter = 0;
	int counter = 0;
	std::vector<const char *> spinner;
	spinner.emplace_back(">>>    >>>");
	spinner.emplace_back(" >>>    >>");
	spinner.emplace_back("  >>>    >");
	spinner.emplace_back("   >>>    ");
	spinner.emplace_back("    >>>   ");
	spinner.emplace_back(">    >>>  ");
	spinner.emplace_back(">>    >>> ");

	size_t zin_n = zin.find_last_of("/");

	while (!s_interrupted) {

		if (zmq_poll(items, 1, -1) == -1) {
			break;
		}

		if (items[0].revents & ZMQ_POLLIN) {

			zmq_msg_t header;
			zmq_msg_init(&header);
			zmq_msg_recv(&header, socket_in, 0);
			size_t nh = zmq_msg_size(&header);
			zmq_neural_header *p = (zmq_neural_header *)zmq_msg_data(&header);

			u64 nc = p->nc;
			u64 ns = p->ns;

			auto tk = new i64[ns];
			auto ts = new double[ns];

			tk[0] = p->tk;
			ts[0] = tsc->getTime(tk[0]);
			for (size_t i=1; i<ns; i++) {
				tk[i] = tk[i-1] + 1;
				ts[i] = tsc->getTime(tk[i]);
			}

			zmq_msg_t body;
			zmq_msg_init(&body);
			zmq_msg_recv(&body, socket_in, 0);
			size_t nb = zmq_msg_size(&body);
			float *f = (float*)zmq_msg_data(&body);

			auto x = new i16[nc*ns];
			for (size_t i=0; i<nc; i++) {
				for (size_t k=0; k<ns; k++) {
					// note that we transpose on the fly here to NWB format
					x[k*nc+i] = (i16)(f[i*ns+k] * 3276700 / 1e6); // pack
				}
			}

			h5.write(nc, ns, tk, ts, x); // frees memory when done

			zmq_msg_close(&header);
			zmq_msg_close(&body);

			if (waiter % 200 == 0) {
				time_t now;
				time(&now);
				double sec = difftime(now, t_create);
				int min = sec / 60;
				int hr  = min / 60;
				printf(" [%s]%s[%s] (%02d:%02d:%02d)\r",
				       zin.substr(zin_n+1).c_str(),
				       spinner[counter % spinner.size()],
				       fn.c_str(),
				       hr,
				       min % 60,
				       int(sec) % 60);
				fflush(stdout);
				counter++;
			}
			waiter++;

		}

	}

	h5.close();

	delete tsc;

	die(zcontext, 0);

}<|endoftext|>


<commit_before>#ifndef ___INANITY_GRAPHICS_EDITABLE_GEOMETRY_H___
#define ___INANITY_GRAPHICS_EDITABLE_GEOMETRY_H___

#include "Geometry.hpp"
#include "GeometryFormat.hpp"
#include <vector>
#include <map>
#include <set>
#include <algorithm>

BEGIN_INANITY_GRAPHICS

/// Класс типизированной редактируемой геометрии.
/**
Различные процедуры выдвигают различные требования к шаблонным параметрам.
Они написаны в комментариях.
*/
template <typename Vertex, typename Index = unsigned short>
class EditableGeometry : public Object
{
private:
	std::vector<Vertex> vertices;
	std::vector<Index> indices;

public:
	/// Создать типизированную геометрию.
	EditableGeometry(const std::vector<Vertex>& vertices, const std::vector<Index>& indices)
		: vertices(vertices), indices(indices) {}

	/// Создать типизированную геометрию из неиндексированных вершин.
	EditableGeometry(const std::vector<Vertex>& vertices) : vertices(vertices)
	{
		indices.resize(vertices.size());
		for(size_t i = 0; i < indices.size(); ++i)
			indices[i] = i;
	}

	/// Получить вершины.
	std::vector<Vertex>& GetVertices()
	{
		return vertices;
	}

	/// Получить индексы.
	std::vector<Index>& GetIndices()
	{
		return indices;
	}

	/// Преобразовать тип индексов.
	template <typename ToIndex>
	ptr<EditableGeometry<Vertex, ToIndex> > CastIndices() const
	{
		return NEW(EditableGeometry<Vertex, ToIndex>(vertices, std::vector<ToIndex>(indices.begin(), indices.end())));
	}

	/// Сериализовать геометрию.
	void Serialize(ptr<OutputStream> outputStream, const String& formatFileName)
	{
		// проверить, являются ли индексы последовательными числами
		// тогда геометрию можно будет сериализовать без индексов
		bool needIndices = false;
		for(size_t i = 0; i < indices.size(); ++i)
			if(indices[i] != i)
			{
				needIndices = true;
				break;
			}

		ptr<StreamWriter> writer = NEW(StreamWriter(outputStream));

		writer->WriteShortly(vertices.size());
		writer->WriteShortly(sizeof(Vertex));
		writer->WriteShortly(needIndices ? indices.size() : 0);
		if(needIndices)
			writer->WriteShortly(sizeof(Index));
		writer->WriteString(formatFileName);
		writer->Write(&*vertices.begin(), vertices.size() * sizeof(Vertex));
		if(needIndices)
			writer->Write(&*indices.begin(), indices.size() * sizeof(Index));
	}

	ptr<File> SerializeVertices() const
	{
		ptr<File> file = NEW(MemoryFile(vertices.size() * sizeof(Vertex)));
		memcpy(file->GetData(), &*vertices.begin(), vertices.size() * sizeof(Vertex));
		return file;
	}

	ptr<File> SerializeIndices() const
	{
		ptr<File> file = NEW(MemoryFile(indices.size() * sizeof(Index)));
		memcpy(file->GetData(), &*indices.begin(), indices.size() * sizeof(Index));
		return file;
	}

	/// Оптимизировать геометрию
	/** Выполняется объединение одинаковых вершин, с заданием соответствующих индексов.
	Для типа Vertex требуется наличие operator< и operator==.
	*/
	ptr<EditableGeometry> Optimize() const
	{
		//скопировать вершины в новый массив с их индексами
		std::vector<std::pair<Vertex, size_t> > newVertices(vertices.size());
		for(size_t i = 0; i < vertices.size(); ++i)
			newVertices[i] = std::make_pair(vertices[i], i);
		//отсортировать их
		std::sort(newVertices.begin(), newVertices.end());
		//выполнить объединение одинаковых вершин
		//заодно построить массив преобразования индексов
		std::vector<Vertex> resultVertices;
		std::vector<size_t> indexMap(vertices.size());
		resultVertices.reserve(vertices.size());
		for(size_t i = 0; i < newVertices.size(); )
		{
			size_t j;
			for(j = i + 1; j < newVertices.size() && newVertices[i].first == newVertices[j].first; ++j);
			size_t newIndex = resultVertices.size();
			resultVertices.push_back(newVertices[i].first);
			for(; i < j; ++i)
				indexMap[newVertices[i].second] = newIndex;
		}
		//скопировать индексы в новый массив
		std::vector<Index> resultIndices(indices.size());
		//и преобразовать их
		for(size_t i = 0; i < resultIndices.size(); ++i)
			resultIndices[i] = indexMap[indices[i]];
		return NEW(EditableGeometry(resultVertices, resultIndices));
	}

	/// Добавить в геометрию тангенту и бинормаль.
	template <typename OutputVertex>
	ptr<EditableGeometry<OutputVertex, Index> > CreateTangentAndBinormal() const
	{
		//ликвидировать индексы
		std::vector<OutputVertex> outputVertices(indices.size());
		for(size_t i = 0; i < outputVertices.size(); ++i)
		{
			const Vertex& vertex = vertices[indices[i]];
			OutputVertex& outputVertex = outputVertices[i];
			outputVertex.position = vertex.position;
			outputVertex.texcoord = vertex.texcoord;
		}

		//обработать треугольники и вычислить для каждого нормали
		for(size_t i = 0; i < outputVertices.size(); i += 3)
		{
			//получить указатель на три вершины
			OutputVertex* v = &*(outputVertices.begin() + i);

			//вычислить нормаль
			float3 temp;
			float3 normal;
			D3DXVec3Cross(&temp, &(v[2].position - v[0].position), &(v[1].position - v[0].position));
			D3DXVec3Normalize(&normal, &temp);

			//вычислить касательную и бинормаль
			float3 tangent, binormal;
			{
				//для этого делаем матрицу
				float4x4 m, m1;
				m._11 = v[1].position.x - v[0].position.x;
				m._12 = v[1].position.y - v[0].position.y;
				m._13 = v[1].position.z - v[0].position.z;
				m._14 = 0;
				m._21 = v[2].position.x - v[0].position.x;
				m._22 = v[2].position.y - v[0].position.y;
				m._23 = v[2].position.z - v[0].position.z;
				m._24 = 0;
				m._31 = normal.x;
				m._32 = normal.y;
				m._33 = normal.z;
				m._34 = 0;
				m._41 = 0;
				m._42 = 0;
				m._43 = 0;
				m._44 = 1;
				//обращаем её
				D3DXMatrixInverse(&m1, NULL, &m);
				//и умножаем её сначала на один вектор (для касательной)
				D3DXVec3TransformCoord(&tangent, &float3(v[1].texcoord.x - v[0].texcoord.x, v[2].texcoord.x - v[0].texcoord.x, 0), &m1);
				//а затем на другой (для бинормали)
				D3DXVec3TransformCoord(&binormal, &float3(v[1].texcoord.y - v[0].texcoord.y, v[2].texcoord.y - v[0].texcoord.y, 0), &m1);
			}

			//записать вектора в вершины
			for(size_t j = 0; j < 3; ++j)
			{
				v[j].normal = normal;
				v[j].tangent = tangent;
				v[j].binormal = binormal;
			}
		}

		//вернуть геометрию
		return NEW((EditableGeometry<OutputVertex, Index>(outputVertices)));
	}

	/// Добавить в геометрию трансформации для прямого bump'а.
	template <typename OutputVertex>
	ptr<EditableGeometry<OutputVertex, Index> > CreateBumpTransformations() const
	{
		//ликвидировать индексы
		std::vector<OutputVertex> outputVertices(indices.size());
		for(size_t i = 0; i < outputVertices.size(); ++i)
		{
			const Vertex& vertex = vertices[indices[i]];
			OutputVertex& outputVertex = outputVertices[i];
			outputVertex.position = vertex.position;
			outputVertex.texcoord = vertex.texcoord;
		}

		//обработать треугольники
		for(size_t i = 0; i < outputVertices.size(); i += 3)
		{
			//получить указатель на три вершины
			OutputVertex* v = &*(outputVertices.begin() + i);

			//вычислить нормаль
			float3 temp;
			float3 normal;
			D3DXVec3Cross(&temp, &(v[2].position - v[0].position), &(v[1].position - v[0].position));
			D3DXVec3Normalize(&normal, &temp);

			//вычислить два базовых мировых вектора
			float3 Ba, Ca;
			temp = v[1].position - v[0].position;
			D3DXVec3Normalize(&Ba, &temp);
			temp = v[2].position - v[0].position;
			D3DXVec3Normalize(&Ca, &temp);
			//и два базовых нормальных вектора
			float2 ba, ca;
			float2 temp2;
			temp2 = v[1].texcoord - v[0].texcoord;
			D3DXVec2Normalize(&ba, &temp2);
			temp2 = v[2].texcoord - v[0].texcoord;
			D3DXVec2Normalize(&ca, &temp2);
			float3 transform1, transform2, transform3;
			{
				//для этого делаем матрицу
				float4x4 m, m1;
				m._11 = ba.x;
				m._12 = ba.y;
				m._13 = 0;
				m._14 = 0;
				m._21 = ca.x;
				m._22 = ca.y;
				m._23 = 0;
				m._24 = 0;
				m._31 = 0;
				m._32 = 0;
				m._33 = 1;
				m._34 = 0;
				m._41 = 0;
				m._42 = 0;
				m._43 = 0;
				m._44 = 1;
				//обращаем её
				D3DXMatrixInverse(&m1, NULL, &m);
				//делаем другую матрицу
				float4x4 m2;
				m2._11 = Ba.x;
				m2._12 = Ba.y;
				m2._13 = Ba.z;
				m2._14 = 0;
				m2._21 = Ca.x;
				m2._22 = Ca.y;
				m2._23 = Ca.z;
				m2._24 = 0;
				m2._31 = normal.x;
				m2._32 = normal.y;
				m2._33 = normal.z;
				m2._34 = 0;
				m2._41 = 0;
				m2._42 = 0;
				m2._43 = 0;
				m2._44 = 1;
				//умножаем матрицы
				m = m1 * m2;

				//получаем трансформации
				transform1 = float3(m._11, m._21, m._31);
				transform2 = float3(m._12, m._22, m._32);
				transform3 = float3(m._13, m._23, m._33);
			}

			//записать вектора в вершины
			for(size_t j = 0; j < 3; ++j)
			{
				v[j].transform1 = transform1;
				v[j].transform2 = transform2;
				v[j].transform3 = transform3;
			}
		}

		//вернуть геометрию (макрос NEW никак не хочет компилироваться)
		return new EditableGeometry<OutputVertex, Index>(outputVertices);
	}

	//структура из трех векторов
	struct ThreeVectors
	{
		float3 a;
		float3 b;
		float3 c;

		ThreeVectors(const float3& a = float3(0, 0, 0), const float3& b = float3(0, 0, 0), const float3& c = float3(0, 0, 0))
			: a(a), b(b), c(c)
		{
		}

		void operator+=(const ThreeVectors& v)
		{
			a += v.a;
			b += v.b;
			c += v.c;
		}

		void operator/=(const float v)
		{
			a /= v;
			b /= v;
			c /= v;
		}
	};
	//сравниватель векторов
	struct Float3Comparer
	{
		bool operator()(const float3& a, const float3& b) const
		{
			if(a.x < b.x - GraphicsMath::eps) return true;
			if(b.x < a.x - GraphicsMath::eps) return false;
			if(a.y < b.y - GraphicsMath::eps) return true;
			if(b.y < a.y - GraphicsMath::eps) return false;
			return a.z < b.z - GraphicsMath::eps;
		}
	};
	//сравниватель троек векторов; используется только для разделения различных
	struct ThreeVectorsComparer
	{
		Float3Comparer comparer;
		bool operator()(const ThreeVectors& a, const ThreeVectors& b) const
		{
			if(comparer(a.a, b.a)) return true;
			if(comparer(b.a, a.a)) return false;
			if(comparer(a.b, b.b)) return true;
			if(comparer(b.b, a.b)) return false;
			return comparer(a.c, b.c);
		}
	};

	/// Сгладить геометрию с bump'ом.
	/** Выполняется усреднение нормалей, тангент и бинормалей. */
	template <
		float3 Vertex::*transform1,
		float3 Vertex::*transform2,
		float3 Vertex::*transform3
	>
	ptr<EditableGeometry> SmoothBump() const
	{
		/* Алгоритм заключается в том, чтобы объединить вершины,
		находящиеся в одной точке, и усреднить в этих вершинах
		компоненты. При этом при усреднении несколько одинаковых векторов
		считаются за один, чтобы не допускать искажение.
		*/
		//карта по векторам, содержащая на каждый вектор сумму векторов - трансформаций
		std::map<float3, std::set<ThreeVectors, ThreeVectorsComparer>, Float3Comparer> vectors;

		//собрать информацию
		for(size_t i = 0; i < indices.size(); ++i)
		{
			size_t j = indices[i];
			vectors[vertices[j].position].insert(ThreeVectors(vertices[j].*transform1, vertices[j].*transform2, vertices[j].*transform3));
		}

		//вычислить результирующие вектора
		std::map<float3, ThreeVectors, Float3Comparer> results;
		for(auto i = vectors.begin(); i != vectors.end(); ++i)
		{
			const std::set<ThreeVectors, ThreeVectorsComparer>& vectorSet = i->second;
			ThreeVectors r;
			for(std::set<ThreeVectors, ThreeVectorsComparer>::const_iterator j = vectorSet.begin(); j != vectorSet.end(); ++j)
				r += *j;
			r /= (float)vectorSet.size();
			results[i->first] = r;
		}

		//сформировать новые вершины
		std::vector<Vertex> outputVertices(indices.size());
		for(size_t i = 0; i < outputVertices.size(); ++i)
		{
			outputVertices[i] = vertices[indices[i]];
			const ThreeVectors& t = results[outputVertices[i].position];
			outputVertices[i].*transform1 = t.a;
			outputVertices[i].*transform2 = t.b;
			outputVertices[i].*transform3 = t.c;
		}

		//создать геометрию
		return NEW(EditableGeometry(outputVertices));
	}
};

END_INANITY_GRAPHICS

#endif
<commit_msg>removed unused code from EditableGeometry<commit_after>#ifndef ___INANITY_GRAPHICS_EDITABLE_GEOMETRY_H___
#define ___INANITY_GRAPHICS_EDITABLE_GEOMETRY_H___

#include "Geometry.hpp"
#include "GeometryFormat.hpp"
#include <vector>
#include <map>
#include <set>
#include <algorithm>

BEGIN_INANITY_GRAPHICS

/// Класс типизированной редактируемой геометрии.
/**
Различные процедуры выдвигают различные требования к шаблонным параметрам.
Они написаны в комментариях.
*/
template <typename Vertex, typename Index = unsigned short>
class EditableGeometry : public Object
{
private:
	std::vector<Vertex> vertices;
	std::vector<Index> indices;

public:
	/// Создать типизированную геометрию.
	EditableGeometry(const std::vector<Vertex>& vertices, const std::vector<Index>& indices)
		: vertices(vertices), indices(indices) {}

	/// Создать типизированную геометрию из неиндексированных вершин.
	EditableGeometry(const std::vector<Vertex>& vertices) : vertices(vertices)
	{
		indices.resize(vertices.size());
		for(size_t i = 0; i < indices.size(); ++i)
			indices[i] = i;
	}

	/// Получить вершины.
	std::vector<Vertex>& GetVertices()
	{
		return vertices;
	}

	/// Получить индексы.
	std::vector<Index>& GetIndices()
	{
		return indices;
	}

	/// Преобразовать тип индексов.
	template <typename ToIndex>
	ptr<EditableGeometry<Vertex, ToIndex> > CastIndices() const
	{
		return NEW(EditableGeometry<Vertex, ToIndex>(vertices, std::vector<ToIndex>(indices.begin(), indices.end())));
	}

	/// Сериализовать геометрию.
	void Serialize(ptr<OutputStream> outputStream, const String& formatFileName)
	{
		// проверить, являются ли индексы последовательными числами
		// тогда геометрию можно будет сериализовать без индексов
		bool needIndices = false;
		for(size_t i = 0; i < indices.size(); ++i)
			if(indices[i] != i)
			{
				needIndices = true;
				break;
			}

		ptr<StreamWriter> writer = NEW(StreamWriter(outputStream));

		writer->WriteShortly(vertices.size());
		writer->WriteShortly(sizeof(Vertex));
		writer->WriteShortly(needIndices ? indices.size() : 0);
		if(needIndices)
			writer->WriteShortly(sizeof(Index));
		writer->WriteString(formatFileName);
		writer->Write(&*vertices.begin(), vertices.size() * sizeof(Vertex));
		if(needIndices)
			writer->Write(&*indices.begin(), indices.size() * sizeof(Index));
	}

	ptr<File> SerializeVertices() const
	{
		ptr<File> file = NEW(MemoryFile(vertices.size() * sizeof(Vertex)));
		memcpy(file->GetData(), &*vertices.begin(), vertices.size() * sizeof(Vertex));
		return file;
	}

	ptr<File> SerializeIndices() const
	{
		ptr<File> file = NEW(MemoryFile(indices.size() * sizeof(Index)));
		memcpy(file->GetData(), &*indices.begin(), indices.size() * sizeof(Index));
		return file;
	}

	/// Оптимизировать геометрию
	/** Выполняется объединение одинаковых вершин, с заданием соответствующих индексов.
	Для типа Vertex требуется наличие operator< и operator==.
	*/
	ptr<EditableGeometry> Optimize() const
	{
		//скопировать вершины в новый массив с их индексами
		std::vector<std::pair<Vertex, size_t> > newVertices(vertices.size());
		for(size_t i = 0; i < vertices.size(); ++i)
			newVertices[i] = std::make_pair(vertices[i], i);
		//отсортировать их
		std::sort(newVertices.begin(), newVertices.end());
		//выполнить объединение одинаковых вершин
		//заодно построить массив преобразования индексов
		std::vector<Vertex> resultVertices;
		std::vector<size_t> indexMap(vertices.size());
		resultVertices.reserve(vertices.size());
		for(size_t i = 0; i < newVertices.size(); )
		{
			size_t j;
			for(j = i + 1; j < newVertices.size() && newVertices[i].first == newVertices[j].first; ++j);
			size_t newIndex = resultVertices.size();
			resultVertices.push_back(newVertices[i].first);
			for(; i < j; ++i)
				indexMap[newVertices[i].second] = newIndex;
		}
		//скопировать индексы в новый массив
		std::vector<Index> resultIndices(indices.size());
		//и преобразовать их
		for(size_t i = 0; i < resultIndices.size(); ++i)
			resultIndices[i] = indexMap[indices[i]];
		return NEW(EditableGeometry(resultVertices, resultIndices));
	}
};

END_INANITY_GRAPHICS

#endif
<|endoftext|>


<commit_before>#include "TF1.h"
#include "TFile.h"
#include "TH1.h"
#include "TH2.h"
#include "TH1F.h"
#include "TProfile.h"
#include "TRandom3.h"
#include "TTree.h"
#include <iostream>
#include <fstream>
#include <stdlib.h>
using namespace std;
#define PI2 2.0*3.141592653589793

const Int_t maxnh = 20000;
Int_t b_npg, b_n, n;
Float_t b_phirg;
Float_t b_ptg[maxnh], b_etag[maxnh], b_phig[maxnh];

void proSTEGvn()
{

  int tot_num=1000;  // number of events
  double MeanMult=2000;
  double RMSMult=0;

  //simple toy event generator
  TFile f("/store/user/tuos/healpy/toyModel/steg10_m2000_flow08/steg10kevts_m2000_jb0_prod.root", "RECREATE","ROOT file with histograms & tree");
  TTree *tree = new TTree("tree","Event tree with a few branches");
  //tree->Branch("npg", &b_npg, "npg/I");   // # of particles;
  tree->Branch("n", &b_n, "n/I");          // same as npg, # of particles;
  tree->Branch("phirg", &b_phirg, "phirg/F");  // RP angle;
  tree->Branch("ptg", &b_ptg, "ptg[n]/F");  // ;
  tree->Branch("etag", &b_etag, "etag[n]/F");
  tree->Branch("phig", &b_phig, "phig[n]/F");

  TF1 *EtaDistr = new TF1("EtaDistr","exp(-(x-2.1)^2/6.3)+exp(-(x+2.1)^2/6.3)",-2.4,2.4);
  TF1 *PhiDistr = new TF1("PhiDistr","1+2*[0]*cos([1]*x)",0,PI2);

   TF1 *PtDistr  = new TF1("PtDistr","exp (-(x/0.90))+0.15*exp (-(x/15))", 0.2,10);
  // fixed v2=0.1 by restricting the x-axis range in the TF1
  TF1 *V2Dist = new TF1("V2Dist", "ROOT::Math::cyl_bessel_i(0,x*0.1/0.04/0.04)*x/0.04/0.04*exp(-1*(x*x+0.1*0.1)/2/0.04/0.04)", 0.08, 0.080001);

//  TF1 *V3vsPt = new TF1("V3vsPt","((x/3.2)^2.3/(1+(x/3.4)^2.1))*(.00005+(1/x)^1.4)",0.2,10);
//  TF1 *V4vsPt = new TF1("V4vsPt","((x/4.8)^2.1/(1+(x/3.4)^2.1))*(.00005+(1/x)^1.4)",0.2,10);
//  TF1 *V5vsPt = new TF1("V5vsPt","((x/6.0)^3.2/(1+(x/11.4)^2.1))*(.00005+(1/x)^1.4)",0.2,10);
//  TF1 *V6vsPt = new TF1("V6vsPt","((x/5.6)^2.4/(1+(x/4.7)^2.1))*(.00005+(1/x)^1.4)",0.2,10);

  TRandom3 *rnd;
  rnd = new TRandom3(0);
  rnd->SetSeed(0);

  double v1, v2, v3, v4, v5, v6, ph, myphi, mypt, myeta, phi0, Psi;
  int nnf,k;
  double neta, nphi, npt;
  int slicept;

  for(int i=0; i<tot_num; i++){

    //Psi = rnd->Uniform(0.0,PI2);
    Psi = 0;
    b_phirg = Psi;
    rnd->SetSeed(0);
    b_npg = rnd->Gaus(MeanMult,RMSMult);
    n = 0;

    rnd->SetSeed(0);
    v2=V2Dist->GetRandom();

    for(int j=0; j<b_npg;j++ ){

      rnd->SetSeed(0);
      mypt = PtDistr->GetRandom();
      rnd->SetSeed(0);
      myeta =  EtaDistr->GetRandom();
      //v1=V1vsEta->Eval(myeta);

//      v2=V2vsPt->Eval(mypt);
//      v2=V2Dist->GetRandom();

      //v3=V3vsPt->Eval(mypt);
      //v4=V4vsPt->Eval(mypt);
      //v5=V5vsPt->Eval(mypt);
      //v6=V6vsPt->Eval(mypt);

      b_etag[n] = myeta;
      b_ptg[n]  = mypt;
      //PhiDistr->SetParameters(v1,v2,v3,v4,v5,v6);
      //PhiDistr->SetParameters(v2,v3,v4,v5,v6);
      PhiDistr->SetParameters(v2,2.0);
      rnd->SetSeed(0);
      myphi = PhiDistr->GetRandom(); // randon selection dn/dphi
      myphi = myphi+Psi; // angle in lab frame -- needed for correct cumulant v2
      if (myphi>PI2) myphi=myphi-PI2; // 0 - 2*Pi

      b_phig[n] = myphi; // save angle in lab frame

      n++;

    } // End of loop over particles

    if (i%1 == 0) cout << i << " " << "events processed" << endl;

    b_n = n;
    tree->Fill();
  } // End of loop over events

  cout << "writing tree" << endl;
  tree->Write();
  cout << "writing to file" << endl;
  f.Write();
  cout << "closing file" << endl;
  f.Close();
  cout << "THE END" << endl;
}

<commit_msg>up for random number seeds<commit_after>#include "TF1.h"
#include "TFile.h"
#include "TH1.h"
#include "TH2.h"
#include "TH1F.h"
#include "TProfile.h"
#include "TRandom3.h"
#include "TTree.h"
#include <iostream>
#include <fstream>
#include <stdlib.h>
using namespace std;
#define PI2 2.0*3.141592653589793

const Int_t maxnh = 20000;
Int_t b_npg, b_n, n;
Float_t b_phirg;
Float_t b_ptg[maxnh], b_etag[maxnh], b_phig[maxnh];

void proSTEGvn()
{

  int tot_num=1000;  // number of events
  double MeanMult=2000;
  double RMSMult=0;

  //simple toy event generator
  TFile f("/store/user/tuos/healpy/toyModel/steg10_m2000_flow08/steg10kevts_m2000_jb0_prod.root", "RECREATE","ROOT file with histograms & tree");
  TTree *tree = new TTree("tree","Event tree with a few branches");
  //tree->Branch("npg", &b_npg, "npg/I");   // # of particles;
  tree->Branch("n", &b_n, "n/I");          // same as npg, # of particles;
  tree->Branch("phirg", &b_phirg, "phirg/F");  // RP angle;
  tree->Branch("ptg", &b_ptg, "ptg[n]/F");  // ;
  tree->Branch("etag", &b_etag, "etag[n]/F");
  tree->Branch("phig", &b_phig, "phig[n]/F");

  TF1 *EtaDistr = new TF1("EtaDistr","exp(-(x-2.1)^2/6.3)+exp(-(x+2.1)^2/6.3)",-2.4,2.4);
  TF1 *PhiDistr = new TF1("PhiDistr","1+2*[0]*cos([1]*x)",0,PI2);

   TF1 *PtDistr  = new TF1("PtDistr","exp (-(x/0.90))+0.15*exp (-(x/15))", 0.2,10);
  // fixed v2=0.1 by restricting the x-axis range in the TF1
  TF1 *V2Dist = new TF1("V2Dist", "ROOT::Math::cyl_bessel_i(0,x*0.1/0.04/0.04)*x/0.04/0.04*exp(-1*(x*x+0.1*0.1)/2/0.04/0.04)", 0.08, 0.080001);

//  TF1 *V3vsPt = new TF1("V3vsPt","((x/3.2)^2.3/(1+(x/3.4)^2.1))*(.00005+(1/x)^1.4)",0.2,10);
//  TF1 *V4vsPt = new TF1("V4vsPt","((x/4.8)^2.1/(1+(x/3.4)^2.1))*(.00005+(1/x)^1.4)",0.2,10);
//  TF1 *V5vsPt = new TF1("V5vsPt","((x/6.0)^3.2/(1+(x/11.4)^2.1))*(.00005+(1/x)^1.4)",0.2,10);
//  TF1 *V6vsPt = new TF1("V6vsPt","((x/5.6)^2.4/(1+(x/4.7)^2.1))*(.00005+(1/x)^1.4)",0.2,10);

  TRandom3 *rnd;
  rnd = new TRandom3(0);
  rnd->SetSeed(0);
  gRandom->SetSeed(0);

  double v1, v2, v3, v4, v5, v6, ph, myphi, mypt, myeta, phi0, Psi;
  int nnf,k;
  double neta, nphi, npt;
  int slicept;

  for(int i=0; i<tot_num; i++){

    //Psi = rnd->Uniform(0.0,PI2);
    Psi = 0;
    b_phirg = Psi;
    b_npg = rnd->Gaus(MeanMult,RMSMult);
    n = 0;

    v2=V2Dist->GetRandom();

    for(int j=0; j<b_npg;j++ ){

      mypt = PtDistr->GetRandom();
      myeta =  EtaDistr->GetRandom();
      //v1=V1vsEta->Eval(myeta);

//      v2=V2vsPt->Eval(mypt);
//      v2=V2Dist->GetRandom();

      //v3=V3vsPt->Eval(mypt);
      //v4=V4vsPt->Eval(mypt);
      //v5=V5vsPt->Eval(mypt);
      //v6=V6vsPt->Eval(mypt);

      b_etag[n] = myeta;
      b_ptg[n]  = mypt;
      //PhiDistr->SetParameters(v1,v2,v3,v4,v5,v6);
      //PhiDistr->SetParameters(v2,v3,v4,v5,v6);
      PhiDistr->SetParameters(v2,2.0);
      myphi = PhiDistr->GetRandom(); // randon selection dn/dphi
      //cout<<"myphi = "<<myphi<<endl;
      myphi = myphi+Psi; // angle in lab frame -- needed for correct cumulant v2
      if (myphi>PI2) myphi=myphi-PI2; // 0 - 2*Pi

      b_phig[n] = myphi; // save angle in lab frame

      n++;

    } // End of loop over particles

    if (i%1 == 0) cout << i << " " << "events processed" << endl;

    b_n = n;
    tree->Fill();
  } // End of loop over events

  cout << "writing tree" << endl;
  tree->Write();
  cout << "writing to file" << endl;
  f.Write();
  cout << "closing file" << endl;
  f.Close();
  cout << "THE END" << endl;
}

<|endoftext|>


<commit_before> /*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: NResultSetMetaData.cxx,v $
 * $Revision: 1.7 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_connectivity.hxx"
#include "NResultSetMetaData.hxx"
#include "NDatabaseMetaData.hxx"
#include "connectivity/dbexception.hxx"
#include <com/sun/star/sdbc/DataType.hpp>
#include "NDebug.hxx"

using namespace connectivity::evoab;
using namespace com::sun::star::uno;
using namespace com::sun::star::lang;
using namespace com::sun::star::sdbc;

OEvoabResultSetMetaData::OEvoabResultSetMetaData(const ::rtl::OUString& _aTableName)
    : m_aTableName(_aTableName),
      m_aEvoabFields()
{

}
// -------------------------------------------------------------------------
OEvoabResultSetMetaData::~OEvoabResultSetMetaData()
{
}
// -------------------------------------------------------------------------
void OEvoabResultSetMetaData::setEvoabFields(const ::vos::ORef<connectivity::OSQLColumns> &xColumns) throw(SQLException)
{
        OSQLColumns::const_iterator aIter;
        static const ::rtl::OUString aName(::rtl::OUString::createFromAscii("Name"));

        for (aIter = xColumns->begin(); aIter != xColumns->end(); ++aIter)
        {
                ::rtl::OUString aFieldName;

                (*aIter)->getPropertyValue(aName) >>= aFieldName;
                guint nFieldNumber = findEvoabField(aFieldName);
                if (nFieldNumber == (guint)-1)
                    ::dbtools::throwGenericSQLException(
                        ::rtl::OUString::createFromAscii("Invalid column name: ") + aFieldName,
                        NULL);
                m_aEvoabFields.push_back(nFieldNumber);
        }
}

// -------------------------------------------------------------------------
void OEvoabResultSetMetaData::checkColumnIndex(sal_Int32 nColumnNum)  throw(SQLException, RuntimeException)
{
    if( nColumnNum <= 0 || nColumnNum > getColumnCount() )
        dbtools::throwInvalidIndexException( *this );
}
// -------------------------------------------------------------------------
sal_Int32 SAL_CALL OEvoabResultSetMetaData::getColumnDisplaySize( sal_Int32 /*nColumnNum*/ ) throw(SQLException, RuntimeException)
{
    return 50;
}
// -------------------------------------------------------------------------
sal_Int32 SAL_CALL OEvoabResultSetMetaData::getColumnType( sal_Int32 nColumnNum ) throw(SQLException, RuntimeException)
{
        sal_uInt32 nField = m_aEvoabFields[nColumnNum - 1];
    return evoab::getFieldType (nField);
}
// -------------------------------------------------------------------------
sal_Int32 SAL_CALL OEvoabResultSetMetaData::getColumnCount(  ) throw(SQLException, RuntimeException)
{
    return m_aEvoabFields.size();
}
// -------------------------------------------------------------------------
sal_Bool SAL_CALL OEvoabResultSetMetaData::isCaseSensitive( sal_Int32 /*nColumnNum*/ ) throw(SQLException, RuntimeException)
{
    return sal_True;
}
// -------------------------------------------------------------------------
::rtl::OUString SAL_CALL OEvoabResultSetMetaData::getSchemaName( sal_Int32 /*nColumnNum*/ ) throw(SQLException, RuntimeException)
{
    return ::rtl::OUString();
}
// -------------------------------------------------------------------------
::rtl::OUString SAL_CALL OEvoabResultSetMetaData::getColumnName( sal_Int32 nColumnNum ) throw(SQLException, RuntimeException)
{
    sal_uInt32 nField = m_aEvoabFields[nColumnNum - 1];
    return evoab::getFieldName( nField );
}
// -------------------------------------------------------------------------
::rtl::OUString SAL_CALL OEvoabResultSetMetaData::getColumnTypeName( sal_Int32 nColumnNum ) throw(SQLException, RuntimeException)
{
    sal_uInt32 nField = m_aEvoabFields[nColumnNum - 1];
    return evoab::getFieldTypeName( nField );
}
// -------------------------------------------------------------------------
::rtl::OUString SAL_CALL OEvoabResultSetMetaData::getColumnLabel( sal_Int32 nColumnNum ) throw(SQLException, RuntimeException)
{
    sal_uInt32 nField = m_aEvoabFields[nColumnNum - 1];
    const ColumnProperty *pSpecs = getField(nField);
    GParamSpec *pSpec = pSpecs->pField;
    rtl::OUString aLabel;

    if( pSpec )
            aLabel = rtl::OStringToOUString( g_param_spec_get_nick( (GParamSpec *) pSpec ),
                                             RTL_TEXTENCODING_UTF8 );
    return aLabel;
}
// -------------------------------------------------------------------------
::rtl::OUString SAL_CALL OEvoabResultSetMetaData::getColumnServiceName( sal_Int32 /*nColumnNum*/ ) throw(SQLException, RuntimeException)
{
    return ::rtl::OUString();
}
// -------------------------------------------------------------------------
::rtl::OUString SAL_CALL OEvoabResultSetMetaData::getTableName( sal_Int32 /*nColumnNum*/ ) throw(SQLException, RuntimeException)
{
    return m_aTableName;//::rtl::OUString::createFromAscii("TABLE");
}
// -------------------------------------------------------------------------
::rtl::OUString SAL_CALL OEvoabResultSetMetaData::getCatalogName( sal_Int32 /*nColumnNum*/ ) throw(SQLException, RuntimeException)
{
    return ::rtl::OUString();
}
// -------------------------------------------------------------------------

sal_Bool SAL_CALL OEvoabResultSetMetaData::isCurrency( sal_Int32 /*nColumnNum*/ ) throw(SQLException, RuntimeException)
{
    return sal_False;
}
// -------------------------------------------------------------------------
sal_Bool SAL_CALL OEvoabResultSetMetaData::isAutoIncrement( sal_Int32 /*nColumnNum*/ ) throw(SQLException, RuntimeException)
{
    return sal_False;
}
// -------------------------------------------------------------------------
sal_Bool SAL_CALL OEvoabResultSetMetaData::isSigned( sal_Int32 /*nColumnNum*/ ) throw(SQLException, RuntimeException)
{
    return sal_False;
}
// -------------------------------------------------------------------------
sal_Int32 SAL_CALL OEvoabResultSetMetaData::getPrecision( sal_Int32 /*nColumnNum*/ ) throw(SQLException, RuntimeException)
{
    return 0;
}
// -----------------------------------------------------------------------------
sal_Int32 SAL_CALL OEvoabResultSetMetaData::getScale( sal_Int32 /*nColumnNum*/ ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
{
    return 0;
}
// -------------------------------------------------------------------------
sal_Int32 SAL_CALL OEvoabResultSetMetaData::isNullable( sal_Int32 /*nColumnNum*/ ) throw(SQLException, RuntimeException)
{
    return 0;
}
// -------------------------------------------------------------------------
sal_Bool SAL_CALL OEvoabResultSetMetaData::isSearchable( sal_Int32 /*nColumnNum*/ ) throw(SQLException, RuntimeException)
{
    return sal_False;
}
// -------------------------------------------------------------------------
sal_Bool SAL_CALL OEvoabResultSetMetaData::isReadOnly( sal_Int32 /*nColumnNum*/ ) throw(SQLException, RuntimeException)
{
    return sal_True;
}
// -------------------------------------------------------------------------
sal_Bool SAL_CALL OEvoabResultSetMetaData::isDefinitelyWritable( sal_Int32 /*nColumnNum*/ ) throw(SQLException, RuntimeException)
{
    return sal_False;
}
// -------------------------------------------------------------------------
sal_Bool SAL_CALL OEvoabResultSetMetaData::isWritable( sal_Int32 /*nColumnNum*/ ) throw(SQLException, RuntimeException)
{
    return sal_False;
}
// -------------------------------------------------------------------------
<commit_msg>INTEGRATION: CWS dba31a (1.7.32); FILE MERGED 2008/07/04 15:21:25 oj 1.7.32.1: #i89558# remove unused code<commit_after> /*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: NResultSetMetaData.cxx,v $
 * $Revision: 1.8 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_connectivity.hxx"
#include "NResultSetMetaData.hxx"
#include "NDatabaseMetaData.hxx"
#include "connectivity/dbexception.hxx"
#include <com/sun/star/sdbc/DataType.hpp>
#include "NDebug.hxx"

using namespace connectivity::evoab;
using namespace com::sun::star::uno;
using namespace com::sun::star::lang;
using namespace com::sun::star::sdbc;

OEvoabResultSetMetaData::OEvoabResultSetMetaData(const ::rtl::OUString& _aTableName)
    : m_aTableName(_aTableName),
      m_aEvoabFields()
{

}
// -------------------------------------------------------------------------
OEvoabResultSetMetaData::~OEvoabResultSetMetaData()
{
}
// -------------------------------------------------------------------------
void OEvoabResultSetMetaData::setEvoabFields(const ::vos::ORef<connectivity::OSQLColumns> &xColumns) throw(SQLException)
{
        OSQLColumns::const_iterator aIter;
        static const ::rtl::OUString aName(::rtl::OUString::createFromAscii("Name"));

        for (aIter = xColumns->begin(); aIter != xColumns->end(); ++aIter)
        {
                ::rtl::OUString aFieldName;

                (*aIter)->getPropertyValue(aName) >>= aFieldName;
                guint nFieldNumber = findEvoabField(aFieldName);
                if (nFieldNumber == (guint)-1)
                    ::dbtools::throwGenericSQLException(
                        ::rtl::OUString::createFromAscii("Invalid column name: ") + aFieldName,
                        NULL);
                m_aEvoabFields.push_back(nFieldNumber);
        }
}

// -------------------------------------------------------------------------
sal_Int32 SAL_CALL OEvoabResultSetMetaData::getColumnDisplaySize( sal_Int32 /*nColumnNum*/ ) throw(SQLException, RuntimeException)
{
    return 50;
}
// -------------------------------------------------------------------------
sal_Int32 SAL_CALL OEvoabResultSetMetaData::getColumnType( sal_Int32 nColumnNum ) throw(SQLException, RuntimeException)
{
        sal_uInt32 nField = m_aEvoabFields[nColumnNum - 1];
    return evoab::getFieldType (nField);
}
// -------------------------------------------------------------------------
sal_Int32 SAL_CALL OEvoabResultSetMetaData::getColumnCount(  ) throw(SQLException, RuntimeException)
{
    return m_aEvoabFields.size();
}
// -------------------------------------------------------------------------
sal_Bool SAL_CALL OEvoabResultSetMetaData::isCaseSensitive( sal_Int32 /*nColumnNum*/ ) throw(SQLException, RuntimeException)
{
    return sal_True;
}
// -------------------------------------------------------------------------
::rtl::OUString SAL_CALL OEvoabResultSetMetaData::getSchemaName( sal_Int32 /*nColumnNum*/ ) throw(SQLException, RuntimeException)
{
    return ::rtl::OUString();
}
// -------------------------------------------------------------------------
::rtl::OUString SAL_CALL OEvoabResultSetMetaData::getColumnName( sal_Int32 nColumnNum ) throw(SQLException, RuntimeException)
{
    sal_uInt32 nField = m_aEvoabFields[nColumnNum - 1];
    return evoab::getFieldName( nField );
}
// -------------------------------------------------------------------------
::rtl::OUString SAL_CALL OEvoabResultSetMetaData::getColumnTypeName( sal_Int32 nColumnNum ) throw(SQLException, RuntimeException)
{
    sal_uInt32 nField = m_aEvoabFields[nColumnNum - 1];
    return evoab::getFieldTypeName( nField );
}
// -------------------------------------------------------------------------
::rtl::OUString SAL_CALL OEvoabResultSetMetaData::getColumnLabel( sal_Int32 nColumnNum ) throw(SQLException, RuntimeException)
{
    sal_uInt32 nField = m_aEvoabFields[nColumnNum - 1];
    const ColumnProperty *pSpecs = getField(nField);
    GParamSpec *pSpec = pSpecs->pField;
    rtl::OUString aLabel;

    if( pSpec )
            aLabel = rtl::OStringToOUString( g_param_spec_get_nick( (GParamSpec *) pSpec ),
                                             RTL_TEXTENCODING_UTF8 );
    return aLabel;
}
// -------------------------------------------------------------------------
::rtl::OUString SAL_CALL OEvoabResultSetMetaData::getColumnServiceName( sal_Int32 /*nColumnNum*/ ) throw(SQLException, RuntimeException)
{
    return ::rtl::OUString();
}
// -------------------------------------------------------------------------
::rtl::OUString SAL_CALL OEvoabResultSetMetaData::getTableName( sal_Int32 /*nColumnNum*/ ) throw(SQLException, RuntimeException)
{
    return m_aTableName;//::rtl::OUString::createFromAscii("TABLE");
}
// -------------------------------------------------------------------------
::rtl::OUString SAL_CALL OEvoabResultSetMetaData::getCatalogName( sal_Int32 /*nColumnNum*/ ) throw(SQLException, RuntimeException)
{
    return ::rtl::OUString();
}
// -------------------------------------------------------------------------

sal_Bool SAL_CALL OEvoabResultSetMetaData::isCurrency( sal_Int32 /*nColumnNum*/ ) throw(SQLException, RuntimeException)
{
    return sal_False;
}
// -------------------------------------------------------------------------
sal_Bool SAL_CALL OEvoabResultSetMetaData::isAutoIncrement( sal_Int32 /*nColumnNum*/ ) throw(SQLException, RuntimeException)
{
    return sal_False;
}
// -------------------------------------------------------------------------
sal_Bool SAL_CALL OEvoabResultSetMetaData::isSigned( sal_Int32 /*nColumnNum*/ ) throw(SQLException, RuntimeException)
{
    return sal_False;
}
// -------------------------------------------------------------------------
sal_Int32 SAL_CALL OEvoabResultSetMetaData::getPrecision( sal_Int32 /*nColumnNum*/ ) throw(SQLException, RuntimeException)
{
    return 0;
}
// -----------------------------------------------------------------------------
sal_Int32 SAL_CALL OEvoabResultSetMetaData::getScale( sal_Int32 /*nColumnNum*/ ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
{
    return 0;
}
// -------------------------------------------------------------------------
sal_Int32 SAL_CALL OEvoabResultSetMetaData::isNullable( sal_Int32 /*nColumnNum*/ ) throw(SQLException, RuntimeException)
{
    return 0;
}
// -------------------------------------------------------------------------
sal_Bool SAL_CALL OEvoabResultSetMetaData::isSearchable( sal_Int32 /*nColumnNum*/ ) throw(SQLException, RuntimeException)
{
    return sal_False;
}
// -------------------------------------------------------------------------
sal_Bool SAL_CALL OEvoabResultSetMetaData::isReadOnly( sal_Int32 /*nColumnNum*/ ) throw(SQLException, RuntimeException)
{
    return sal_True;
}
// -------------------------------------------------------------------------
sal_Bool SAL_CALL OEvoabResultSetMetaData::isDefinitelyWritable( sal_Int32 /*nColumnNum*/ ) throw(SQLException, RuntimeException)
{
    return sal_False;
}
// -------------------------------------------------------------------------
sal_Bool SAL_CALL OEvoabResultSetMetaData::isWritable( sal_Int32 /*nColumnNum*/ ) throw(SQLException, RuntimeException)
{
    return sal_False;
}
// -------------------------------------------------------------------------
<|endoftext|>


<commit_before>/****************************************************************************
 *
 *   Copyright (c) 2013, 2014 PX4 Development Team. All rights reserved.
 *
 * 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 ets_airspeed.cpp
 * @author Simon Wilks
 *
 * Driver for the Eagle Tree Airspeed V3 connected via I2C.
 */

#include <nuttx/config.h>

#include <drivers/device/i2c.h>

#include <sys/types.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#include <semaphore.h>
#include <string.h>
#include <fcntl.h>
#include <poll.h>
#include <errno.h>
#include <stdio.h>
#include <math.h>
#include <unistd.h>

#include <nuttx/arch.h>
#include <nuttx/wqueue.h>
#include <nuttx/clock.h>

#include <board_config.h>

#include <systemlib/airspeed.h>
#include <systemlib/err.h>
#include <systemlib/param/param.h>
#include <systemlib/perf_counter.h>

#include <drivers/drv_airspeed.h>
#include <drivers/drv_hrt.h>
#include <drivers/device/ringbuffer.h>

#include <uORB/uORB.h>
#include <uORB/topics/differential_pressure.h>
#include <uORB/topics/subsystem_info.h>
#include <drivers/airspeed/airspeed.h>

/* I2C bus address */
#define I2C_ADDRESS	0x75	/* 7-bit address. 8-bit address is 0xEA */
#define ETS_PATH	"/dev/ets_airspeed"

/* Register address */
#define READ_CMD	0x07	/* Read the data */

/**
 * The Eagle Tree Airspeed V3 cannot provide accurate reading below speeds of 15km/h.
 * You can set this value to 12 if you want a zero reading below 15km/h.
 */
#define MIN_ACCURATE_DIFF_PRES_PA 0

/* Measurement rate is 100Hz */
#define CONVERSION_INTERVAL	(1000000 / 100)	/* microseconds */

class ETSAirspeed : public Airspeed
{
public:
	ETSAirspeed(int bus, int address = I2C_ADDRESS, const char* path = ETS_PATH);

protected:

	/**
	* Perform a poll cycle; collect from the previous measurement
	* and start a new one.
	*/
	virtual void	cycle();
	virtual int	measure();
	virtual int	collect();

};

/*
 * Driver 'main' command.
 */
extern "C" __EXPORT int ets_airspeed_main(int argc, char *argv[]);

ETSAirspeed::ETSAirspeed(int bus, int address, const char* path) : Airspeed(bus, address,
	CONVERSION_INTERVAL, path)
{

}

int
ETSAirspeed::measure()
{
	int ret;

	/*
	 * Send the command to begin a measurement.
	 */
	uint8_t cmd = READ_CMD;
	ret = transfer(&cmd, 1, nullptr, 0);

	if (OK != ret) {
		perf_count(_comms_errors);
	}

	return ret;
}

int
ETSAirspeed::collect()
{
	int	ret = -EIO;

	/* read from the sensor */
	uint8_t val[2] = {0, 0};

	perf_begin(_sample_perf);

	ret = transfer(nullptr, 0, &val[0], 2);

	if (ret < 0) {
		perf_count(_comms_errors);
		return ret;
	}

	uint16_t diff_pres_pa_raw = val[1] << 8 | val[0];
	uint16_t diff_pres_pa;
        if (diff_pres_pa_raw == 0) {
		// a zero value means the pressure sensor cannot give us a
		// value. We need to return, and not report a value or the
		// caller could end up using this value as part of an
		// average
		perf_count(_comms_errors);
		log("zero value from sensor");
		return -1;
        }

	if (diff_pres_pa_raw < _diff_pres_offset + MIN_ACCURATE_DIFF_PRES_PA) {
		diff_pres_pa = 0;
	} else {
		diff_pres_pa = diff_pres_pa_raw - _diff_pres_offset;
	}

	// Track maximum differential pressure measured (so we can work out top speed).
	if (diff_pres_pa > _max_differential_pressure_pa) {
		_max_differential_pressure_pa = diff_pres_pa;
	}

	differential_pressure_s report;
	report.timestamp = hrt_absolute_time();
        report.error_count = perf_event_count(_comms_errors);
	report.differential_pressure_pa = (float)diff_pres_pa;

	// XXX we may want to smooth out the readings to remove noise.
	report.differential_pressure_filtered_pa = (float)diff_pres_pa;
	report.differential_pressure_raw_pa = (float)diff_pres_pa_raw;
	report.temperature = -1000.0f;
	report.voltage = 0;
	report.max_differential_pressure_pa = _max_differential_pressure_pa;

	if (_airspeed_pub > 0 && !(_pub_blocked)) {
		/* publish it */
		orb_publish(ORB_ID(differential_pressure), _airspeed_pub, &report);
	}

	new_report(report);

	/* notify anyone waiting for data */
	poll_notify(POLLIN);

	ret = OK;

	perf_end(_sample_perf);

	return ret;
}

void
ETSAirspeed::cycle()
{
	int ret;

	/* collection phase? */
	if (_collect_phase) {

		/* perform collection */
		ret = collect();
		if (OK != ret) {
			perf_count(_comms_errors);
			/* restart the measurement state machine */
			start();
			_sensor_ok = false;
			return;
		}

		/* next phase is measurement */
		_collect_phase = false;

		/*
		 * Is there a collect->measure gap?
		 */
		if (_measure_ticks > USEC2TICK(CONVERSION_INTERVAL)) {

			/* schedule a fresh cycle call when we are ready to measure again */
			work_queue(HPWORK,
				   &_work,
				   (worker_t)&Airspeed::cycle_trampoline,
				   this,
				   _measure_ticks - USEC2TICK(CONVERSION_INTERVAL));

			return;
		}
	}

	/* measurement phase */
	ret = measure();
	if (OK != ret) {
		debug("measure error");
	}

	_sensor_ok = (ret == OK);

	/* next phase is collection */
	_collect_phase = true;

	/* schedule a fresh cycle call when the measurement is done */
	work_queue(HPWORK,
		   &_work,
		   (worker_t)&Airspeed::cycle_trampoline,
		   this,
		   USEC2TICK(CONVERSION_INTERVAL));
}

/**
 * Local functions in support of the shell command.
 */
namespace ets_airspeed
{

/* oddly, ERROR is not defined for c++ */
#ifdef ERROR
# undef ERROR
#endif
const int ERROR = -1;

ETSAirspeed	*g_dev;

void	start(int i2c_bus);
void	stop();
void	test();
void	reset();
void	info();

/**
 * Start the driver.
 */
void
start(int i2c_bus)
{
	int fd;

	if (g_dev != nullptr)
		errx(1, "already started");

	/* create the driver */
	g_dev = new ETSAirspeed(i2c_bus);

	if (g_dev == nullptr)
		goto fail;

	if (OK != g_dev->Airspeed::init())
		goto fail;

	/* set the poll rate to default, starts automatic data collection */
	fd = open(AIRSPEED_DEVICE_PATH, O_RDONLY);

	if (fd < 0)
		goto fail;

	if (ioctl(fd, SENSORIOCSPOLLRATE, SENSOR_POLLRATE_DEFAULT) < 0)
		goto fail;

	exit(0);

fail:

	if (g_dev != nullptr) {
		delete g_dev;
		g_dev = nullptr;
	}

	errx(1, "no ETS airspeed sensor connected");
}

/**
 * Stop the driver
 */
void
stop()
{
	if (g_dev != nullptr) {
		delete g_dev;
		g_dev = nullptr;

	} else {
		errx(1, "driver not running");
	}

	exit(0);
}

/**
 * Perform some basic functional tests on the driver;
 * make sure we can collect data from the sensor in polled
 * and automatic modes.
 */
void
test()
{
	struct differential_pressure_s report;
	ssize_t sz;
	int ret;

	int fd = open(AIRSPEED_DEVICE_PATH, O_RDONLY);

	if (fd < 0)
		err(1, "%s open failed (try 'ets_airspeed start' if the driver is not running", AIRSPEED_DEVICE_PATH);

	/* do a simple demand read */
	sz = read(fd, &report, sizeof(report));

	if (sz != sizeof(report))
		err(1, "immediate read failed");

	warnx("single read");
	warnx("diff pressure: %f pa", (double)report.differential_pressure_pa);

	/* start the sensor polling at 2Hz */
	if (OK != ioctl(fd, SENSORIOCSPOLLRATE, 2))
		errx(1, "failed to set 2Hz poll rate");

	/* read the sensor 5x and report each value */
	for (unsigned i = 0; i < 5; i++) {
		struct pollfd fds;

		/* wait for data to be ready */
		fds.fd = fd;
		fds.events = POLLIN;
		ret = poll(&fds, 1, 2000);

		if (ret != 1)
			errx(1, "timed out waiting for sensor data");

		/* now go get it */
		sz = read(fd, &report, sizeof(report));

		if (sz != sizeof(report))
			err(1, "periodic read failed");

		warnx("periodic read %u", i);
		warnx("diff pressure: %f pa", (double)report.differential_pressure_pa);
	}

	/* reset the sensor polling to its default rate */
	if (OK != ioctl(fd, SENSORIOCSPOLLRATE, SENSOR_POLLRATE_DEFAULT))
		errx(1, "failed to set default rate");

	errx(0, "PASS");
}

/**
 * Reset the driver.
 */
void
reset()
{
	int fd = open(AIRSPEED_DEVICE_PATH, O_RDONLY);

	if (fd < 0)
		err(1, "failed ");

	if (ioctl(fd, SENSORIOCRESET, 0) < 0)
		err(1, "driver reset failed");

	if (ioctl(fd, SENSORIOCSPOLLRATE, SENSOR_POLLRATE_DEFAULT) < 0)
		err(1, "driver poll restart failed");

	exit(0);
}

/**
 * Print a little info about the driver.
 */
void
info()
{
	if (g_dev == nullptr)
		errx(1, "driver not running");

	printf("state @ %p\n", g_dev);
	g_dev->print_info();

	exit(0);
}

} // namespace

static void
ets_airspeed_usage()
{
	warnx("usage: ets_airspeed command [options]");
	warnx("options:");
	warnx("\t-b --bus i2cbus (%d)", PX4_I2C_BUS_DEFAULT);
	warnx("command:");
	warnx("\tstart|stop|reset|test|info");
}

int
ets_airspeed_main(int argc, char *argv[])
{
	int i2c_bus = PX4_I2C_BUS_DEFAULT;

	int i;

	for (i = 1; i < argc; i++) {
		if (strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "--bus") == 0) {
			if (argc > i + 1) {
				i2c_bus = atoi(argv[i + 1]);
			}
		}
	}

	/*
	 * Start/load the driver.
	 */
	if (!strcmp(argv[1], "start"))
		ets_airspeed::start(i2c_bus);

	/*
	 * Stop the driver
	 */
	if (!strcmp(argv[1], "stop"))
		ets_airspeed::stop();

	/*
	 * Test the driver/device.
	 */
	if (!strcmp(argv[1], "test"))
		ets_airspeed::test();

	/*
	 * Reset the driver.
	 */
	if (!strcmp(argv[1], "reset"))
		ets_airspeed::reset();

	/*
	 * Print driver information.
	 */
	if (!strcmp(argv[1], "info") || !strcmp(argv[1], "status"))
		ets_airspeed::info();

	ets_airspeed_usage();
	exit(0);
}
<commit_msg>Remove voltage field for digital sensors<commit_after>/****************************************************************************
 *
 *   Copyright (c) 2013, 2014 PX4 Development Team. All rights reserved.
 *
 * 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 ets_airspeed.cpp
 * @author Simon Wilks
 *
 * Driver for the Eagle Tree Airspeed V3 connected via I2C.
 */

#include <nuttx/config.h>

#include <drivers/device/i2c.h>

#include <sys/types.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#include <semaphore.h>
#include <string.h>
#include <fcntl.h>
#include <poll.h>
#include <errno.h>
#include <stdio.h>
#include <math.h>
#include <unistd.h>

#include <nuttx/arch.h>
#include <nuttx/wqueue.h>
#include <nuttx/clock.h>

#include <board_config.h>

#include <systemlib/airspeed.h>
#include <systemlib/err.h>
#include <systemlib/param/param.h>
#include <systemlib/perf_counter.h>

#include <drivers/drv_airspeed.h>
#include <drivers/drv_hrt.h>
#include <drivers/device/ringbuffer.h>

#include <uORB/uORB.h>
#include <uORB/topics/differential_pressure.h>
#include <uORB/topics/subsystem_info.h>
#include <drivers/airspeed/airspeed.h>

/* I2C bus address */
#define I2C_ADDRESS	0x75	/* 7-bit address. 8-bit address is 0xEA */
#define ETS_PATH	"/dev/ets_airspeed"

/* Register address */
#define READ_CMD	0x07	/* Read the data */

/**
 * The Eagle Tree Airspeed V3 cannot provide accurate reading below speeds of 15km/h.
 * You can set this value to 12 if you want a zero reading below 15km/h.
 */
#define MIN_ACCURATE_DIFF_PRES_PA 0

/* Measurement rate is 100Hz */
#define CONVERSION_INTERVAL	(1000000 / 100)	/* microseconds */

class ETSAirspeed : public Airspeed
{
public:
	ETSAirspeed(int bus, int address = I2C_ADDRESS, const char* path = ETS_PATH);

protected:

	/**
	* Perform a poll cycle; collect from the previous measurement
	* and start a new one.
	*/
	virtual void	cycle();
	virtual int	measure();
	virtual int	collect();

};

/*
 * Driver 'main' command.
 */
extern "C" __EXPORT int ets_airspeed_main(int argc, char *argv[]);

ETSAirspeed::ETSAirspeed(int bus, int address, const char* path) : Airspeed(bus, address,
	CONVERSION_INTERVAL, path)
{

}

int
ETSAirspeed::measure()
{
	int ret;

	/*
	 * Send the command to begin a measurement.
	 */
	uint8_t cmd = READ_CMD;
	ret = transfer(&cmd, 1, nullptr, 0);

	if (OK != ret) {
		perf_count(_comms_errors);
	}

	return ret;
}

int
ETSAirspeed::collect()
{
	int	ret = -EIO;

	/* read from the sensor */
	uint8_t val[2] = {0, 0};

	perf_begin(_sample_perf);

	ret = transfer(nullptr, 0, &val[0], 2);

	if (ret < 0) {
		perf_count(_comms_errors);
		return ret;
	}

	uint16_t diff_pres_pa_raw = val[1] << 8 | val[0];
	uint16_t diff_pres_pa;
        if (diff_pres_pa_raw == 0) {
		// a zero value means the pressure sensor cannot give us a
		// value. We need to return, and not report a value or the
		// caller could end up using this value as part of an
		// average
		perf_count(_comms_errors);
		log("zero value from sensor");
		return -1;
        }

	if (diff_pres_pa_raw < _diff_pres_offset + MIN_ACCURATE_DIFF_PRES_PA) {
		diff_pres_pa = 0;
	} else {
		diff_pres_pa = diff_pres_pa_raw - _diff_pres_offset;
	}

	// Track maximum differential pressure measured (so we can work out top speed).
	if (diff_pres_pa > _max_differential_pressure_pa) {
		_max_differential_pressure_pa = diff_pres_pa;
	}

	differential_pressure_s report;
	report.timestamp = hrt_absolute_time();
        report.error_count = perf_event_count(_comms_errors);
	report.differential_pressure_pa = (float)diff_pres_pa;

	// XXX we may want to smooth out the readings to remove noise.
	report.differential_pressure_filtered_pa = (float)diff_pres_pa;
	report.differential_pressure_raw_pa = (float)diff_pres_pa_raw;
	report.temperature = -1000.0f;
	report.max_differential_pressure_pa = _max_differential_pressure_pa;

	if (_airspeed_pub > 0 && !(_pub_blocked)) {
		/* publish it */
		orb_publish(ORB_ID(differential_pressure), _airspeed_pub, &report);
	}

	new_report(report);

	/* notify anyone waiting for data */
	poll_notify(POLLIN);

	ret = OK;

	perf_end(_sample_perf);

	return ret;
}

void
ETSAirspeed::cycle()
{
	int ret;

	/* collection phase? */
	if (_collect_phase) {

		/* perform collection */
		ret = collect();
		if (OK != ret) {
			perf_count(_comms_errors);
			/* restart the measurement state machine */
			start();
			_sensor_ok = false;
			return;
		}

		/* next phase is measurement */
		_collect_phase = false;

		/*
		 * Is there a collect->measure gap?
		 */
		if (_measure_ticks > USEC2TICK(CONVERSION_INTERVAL)) {

			/* schedule a fresh cycle call when we are ready to measure again */
			work_queue(HPWORK,
				   &_work,
				   (worker_t)&Airspeed::cycle_trampoline,
				   this,
				   _measure_ticks - USEC2TICK(CONVERSION_INTERVAL));

			return;
		}
	}

	/* measurement phase */
	ret = measure();
	if (OK != ret) {
		debug("measure error");
	}

	_sensor_ok = (ret == OK);

	/* next phase is collection */
	_collect_phase = true;

	/* schedule a fresh cycle call when the measurement is done */
	work_queue(HPWORK,
		   &_work,
		   (worker_t)&Airspeed::cycle_trampoline,
		   this,
		   USEC2TICK(CONVERSION_INTERVAL));
}

/**
 * Local functions in support of the shell command.
 */
namespace ets_airspeed
{

/* oddly, ERROR is not defined for c++ */
#ifdef ERROR
# undef ERROR
#endif
const int ERROR = -1;

ETSAirspeed	*g_dev;

void	start(int i2c_bus);
void	stop();
void	test();
void	reset();
void	info();

/**
 * Start the driver.
 */
void
start(int i2c_bus)
{
	int fd;

	if (g_dev != nullptr)
		errx(1, "already started");

	/* create the driver */
	g_dev = new ETSAirspeed(i2c_bus);

	if (g_dev == nullptr)
		goto fail;

	if (OK != g_dev->Airspeed::init())
		goto fail;

	/* set the poll rate to default, starts automatic data collection */
	fd = open(AIRSPEED_DEVICE_PATH, O_RDONLY);

	if (fd < 0)
		goto fail;

	if (ioctl(fd, SENSORIOCSPOLLRATE, SENSOR_POLLRATE_DEFAULT) < 0)
		goto fail;

	exit(0);

fail:

	if (g_dev != nullptr) {
		delete g_dev;
		g_dev = nullptr;
	}

	errx(1, "no ETS airspeed sensor connected");
}

/**
 * Stop the driver
 */
void
stop()
{
	if (g_dev != nullptr) {
		delete g_dev;
		g_dev = nullptr;

	} else {
		errx(1, "driver not running");
	}

	exit(0);
}

/**
 * Perform some basic functional tests on the driver;
 * make sure we can collect data from the sensor in polled
 * and automatic modes.
 */
void
test()
{
	struct differential_pressure_s report;
	ssize_t sz;
	int ret;

	int fd = open(AIRSPEED_DEVICE_PATH, O_RDONLY);

	if (fd < 0)
		err(1, "%s open failed (try 'ets_airspeed start' if the driver is not running", AIRSPEED_DEVICE_PATH);

	/* do a simple demand read */
	sz = read(fd, &report, sizeof(report));

	if (sz != sizeof(report))
		err(1, "immediate read failed");

	warnx("single read");
	warnx("diff pressure: %f pa", (double)report.differential_pressure_pa);

	/* start the sensor polling at 2Hz */
	if (OK != ioctl(fd, SENSORIOCSPOLLRATE, 2))
		errx(1, "failed to set 2Hz poll rate");

	/* read the sensor 5x and report each value */
	for (unsigned i = 0; i < 5; i++) {
		struct pollfd fds;

		/* wait for data to be ready */
		fds.fd = fd;
		fds.events = POLLIN;
		ret = poll(&fds, 1, 2000);

		if (ret != 1)
			errx(1, "timed out waiting for sensor data");

		/* now go get it */
		sz = read(fd, &report, sizeof(report));

		if (sz != sizeof(report))
			err(1, "periodic read failed");

		warnx("periodic read %u", i);
		warnx("diff pressure: %f pa", (double)report.differential_pressure_pa);
	}

	/* reset the sensor polling to its default rate */
	if (OK != ioctl(fd, SENSORIOCSPOLLRATE, SENSOR_POLLRATE_DEFAULT))
		errx(1, "failed to set default rate");

	errx(0, "PASS");
}

/**
 * Reset the driver.
 */
void
reset()
{
	int fd = open(AIRSPEED_DEVICE_PATH, O_RDONLY);

	if (fd < 0)
		err(1, "failed ");

	if (ioctl(fd, SENSORIOCRESET, 0) < 0)
		err(1, "driver reset failed");

	if (ioctl(fd, SENSORIOCSPOLLRATE, SENSOR_POLLRATE_DEFAULT) < 0)
		err(1, "driver poll restart failed");

	exit(0);
}

/**
 * Print a little info about the driver.
 */
void
info()
{
	if (g_dev == nullptr)
		errx(1, "driver not running");

	printf("state @ %p\n", g_dev);
	g_dev->print_info();

	exit(0);
}

} // namespace

static void
ets_airspeed_usage()
{
	warnx("usage: ets_airspeed command [options]");
	warnx("options:");
	warnx("\t-b --bus i2cbus (%d)", PX4_I2C_BUS_DEFAULT);
	warnx("command:");
	warnx("\tstart|stop|reset|test|info");
}

int
ets_airspeed_main(int argc, char *argv[])
{
	int i2c_bus = PX4_I2C_BUS_DEFAULT;

	int i;

	for (i = 1; i < argc; i++) {
		if (strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "--bus") == 0) {
			if (argc > i + 1) {
				i2c_bus = atoi(argv[i + 1]);
			}
		}
	}

	/*
	 * Start/load the driver.
	 */
	if (!strcmp(argv[1], "start"))
		ets_airspeed::start(i2c_bus);

	/*
	 * Stop the driver
	 */
	if (!strcmp(argv[1], "stop"))
		ets_airspeed::stop();

	/*
	 * Test the driver/device.
	 */
	if (!strcmp(argv[1], "test"))
		ets_airspeed::test();

	/*
	 * Reset the driver.
	 */
	if (!strcmp(argv[1], "reset"))
		ets_airspeed::reset();

	/*
	 * Print driver information.
	 */
	if (!strcmp(argv[1], "info") || !strcmp(argv[1], "status"))
		ets_airspeed::info();

	ets_airspeed_usage();
	exit(0);
}
<|endoftext|>