<commit_before>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 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 <osg/CollectOccludersVisitor>
#include <osg/Transform>
#include <osg/Switch>
#include <osg/LOD>
#include <osg/OccluderNode>
#include <osg/Projection>

#include <algorithm>

using namespace osg;

CollectOccludersVisitor::CollectOccludersVisitor():
    NodeVisitor(COLLECT_OCCLUDER_VISITOR,TRAVERSE_ACTIVE_CHILDREN)
{

    setCullingMode(VIEW_FRUSTUM_CULLING|
                   NEAR_PLANE_CULLING|
                   FAR_PLANE_CULLING|
                   SMALL_FEATURE_CULLING);

    _minimumShadowOccluderVolume = 0.005f;
    _maximumNumberOfActiveOccluders = 10;
    _createDrawables = false;

}

CollectOccludersVisitor::~CollectOccludersVisitor()
{
}

void CollectOccludersVisitor::reset()
{
    CullStack::reset();
    _occluderSet.clear();
}

float CollectOccludersVisitor::getDistanceToEyePoint(const Vec3& pos, bool withLODScale) const
{
    if (withLODScale) return (pos-getEyeLocal()).length()*getLODScale();
    else return (pos-getEyeLocal()).length();
}

float CollectOccludersVisitor::getDistanceToViewPoint(const Vec3& pos, bool withLODScale) const
{
    if (withLODScale) return (pos-getViewPointLocal()).length()*getLODScale();
    else return (pos-getViewPointLocal()).length();
}

float CollectOccludersVisitor::getDistanceFromEyePoint(const Vec3& pos, bool withLODScale) const
{
    const Matrix& matrix = *_modelviewStack.back();
    float dist = -(pos[0]*matrix(0,2)+pos[1]*matrix(1,2)+pos[2]*matrix(2,2)+matrix(3,2));

    if (withLODScale) return dist*getLODScale();
    else return dist*getLODScale();
}

void CollectOccludersVisitor::apply(osg::Node& node)
{
    if (isCulled(node)) return;

    // push the culling mode.
    pushCurrentMask();

    handle_cull_callbacks_and_traverse(node);

    // pop the culling mode.
    popCurrentMask();
}

void CollectOccludersVisitor::apply(osg::Transform& node)
{
    if (isCulled(node)) return;

    // push the culling mode.
    pushCurrentMask();

    ref_ptr<osg::RefMatrix> matrix = createOrReuseMatrix(*getModelViewMatrix());
    node.computeLocalToWorldMatrix(*matrix,this);
    pushModelViewMatrix(matrix.get(), node.getReferenceFrame());

    handle_cull_callbacks_and_traverse(node);

    popModelViewMatrix();

    // pop the culling mode.
    popCurrentMask();
}

void CollectOccludersVisitor::apply(osg::Projection& node)
{
    if (isCulled(node)) return;

    // push the culling mode.
    pushCurrentMask();

    ref_ptr<osg::RefMatrix> matrix = createOrReuseMatrix(node.getMatrix());
    pushProjectionMatrix(matrix.get());

    handle_cull_callbacks_and_traverse(node);

    popProjectionMatrix();

    // pop the culling mode.
    popCurrentMask();
}

void CollectOccludersVisitor::apply(osg::Switch& node)
{
    apply((Group&)node);
}

void CollectOccludersVisitor::apply(osg::LOD& node)
{
    if (isCulled(node)) return;

    // push the culling mode.
    pushCurrentMask();

    handle_cull_callbacks_and_traverse(node);

    // pop the culling mode.
    popCurrentMask();
}

void CollectOccludersVisitor::apply(osg::OccluderNode& node)
{
    // need to check if occlusion node is in the occluder
    // list, if so disable the appropriate ShadowOccluderVolume
    disableAndPushOccludersCurrentMask(_nodePath);

    if (isCulled(node))
    {
        popOccludersCurrentMask(_nodePath);
        return;
    }

//    std::cout<<"CollectOccludersVisitor:: We have found an Occlusion node in frustum"<<&node<<std::endl;

    // push the culling mode.
    pushCurrentMask();

    if (node.getOccluder())
    {
        // computeOccluder will check if the occluder is the view frustum,
        // if it ins't then the it will return false, when in it will
        // clip the occluder's polygons in clip space, then create occluder
        // planes, all with their normals facing inward towards the volume,
        // and then transform them back into projection space.
        ShadowVolumeOccluder svo;
        if (svo.computeOccluder(_nodePath, *node.getOccluder(), *this,_createDrawables))
        {

            if (svo.getVolume()>_minimumShadowOccluderVolume)
            {
                // need to test occluder against view frustum.
                //std::cout << "    adding in Occluder"<<std::endl;
                _occluderSet.insert(svo);
            }
            else
            {
                //std::cout << "    rejecting Occluder as its volume is too small "<<svo.getVolume()<<std::endl;
            }
        }
    }

    handle_cull_callbacks_and_traverse(node);

    // pop the culling mode.
    popCurrentMask();

    // pop the current mask for the disabled occluder
    popOccludersCurrentMask(_nodePath);
}

void CollectOccludersVisitor::removeOccludedOccluders()
{
    if (_occluderSet.empty()) return;

    ShadowVolumeOccluderSet::iterator occludeeItr=_occluderSet.begin();

    // skip the first element as this can't be occluded by anything else.
    occludeeItr++;

    // step through the rest of the occluders, remove occluders which are themselves occluded.
    for(;
        occludeeItr!=_occluderSet.end();
        ++occludeeItr)
    {

        // search for any occluders that occlude the current occluder,
        // we only need to test any occluder near the front of the set since
        // you can't be occluder by something smaller than you.
        ShadowVolumeOccluder& occludee = const_cast<ShadowVolumeOccluder&>(*occludeeItr);
        ShadowVolumeOccluder::HoleList& holeList = occludee.getHoleList();

        for(ShadowVolumeOccluderSet::iterator occluderItr=_occluderSet.begin();
            occluderItr!=occludeeItr;
            ++occluderItr)
        {
            // cast away constness of the std::set element since ShadowVolumeOccluder::contains() is non const,
            // and the std::set is a const, just for the invariance of the operator <!! Ahhhhh. oh well the below
            // should be robust since contains won't change the getVolume which is used by the operator <.  Honest,  :-)
            ShadowVolumeOccluder* occluder = const_cast<ShadowVolumeOccluder*>(&(*occluderItr));
            if (occluder->contains(occludee.getOccluder().getReferenceVertexList()))
            {
                // erase occluder from set.
                // take a copy of the iterator then rewind it one element so to prevent invalidating the occludeeItr.
                ShadowVolumeOccluderSet::iterator eraseItr = occludeeItr--;
                _occluderSet.erase(eraseItr);
                break;
            }

            // now check all the holes in the occludee against the occluder,
            // do so in reverse order so that the iterators remain valid.
            for(ShadowVolumeOccluder::HoleList::reverse_iterator holeItr=holeList.rbegin();
                holeItr!=holeList.rend();
                )
            {
                if (occluder->contains((*holeItr).getReferenceVertexList()))
                {
                    holeList.erase((++holeItr).base());
                }
                else
                {
                    ++holeItr;
                }

            }

        }
    }

    if (_occluderSet.size()<=_maximumNumberOfActiveOccluders) return;

    // move the iterator to the _maximumNumberOfActiveOccluders th occluder.
    occludeeItr = _occluderSet.begin();
    for(unsigned int i=0;i<_maximumNumberOfActiveOccluders;++i)
        ++occludeeItr;

    // discard last occluders.
    _occluderSet.erase(occludeeItr,_occluderSet.end());

}
<commit_msg>Refactored the way that hole are pruned from the occluder hole list.<commit_after>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 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 <osg/CollectOccludersVisitor>
#include <osg/Transform>
#include <osg/Switch>
#include <osg/LOD>
#include <osg/OccluderNode>
#include <osg/Projection>

#include <algorithm>

using namespace osg;

CollectOccludersVisitor::CollectOccludersVisitor():
    NodeVisitor(COLLECT_OCCLUDER_VISITOR,TRAVERSE_ACTIVE_CHILDREN)
{

    setCullingMode(VIEW_FRUSTUM_CULLING|
                   NEAR_PLANE_CULLING|
                   FAR_PLANE_CULLING|
                   SMALL_FEATURE_CULLING);

    _minimumShadowOccluderVolume = 0.005f;
    _maximumNumberOfActiveOccluders = 10;
    _createDrawables = false;

}

CollectOccludersVisitor::~CollectOccludersVisitor()
{
}

void CollectOccludersVisitor::reset()
{
    CullStack::reset();
    _occluderSet.clear();
}

float CollectOccludersVisitor::getDistanceToEyePoint(const Vec3& pos, bool withLODScale) const
{
    if (withLODScale) return (pos-getEyeLocal()).length()*getLODScale();
    else return (pos-getEyeLocal()).length();
}

float CollectOccludersVisitor::getDistanceToViewPoint(const Vec3& pos, bool withLODScale) const
{
    if (withLODScale) return (pos-getViewPointLocal()).length()*getLODScale();
    else return (pos-getViewPointLocal()).length();
}

float CollectOccludersVisitor::getDistanceFromEyePoint(const Vec3& pos, bool withLODScale) const
{
    const Matrix& matrix = *_modelviewStack.back();
    float dist = -(pos[0]*matrix(0,2)+pos[1]*matrix(1,2)+pos[2]*matrix(2,2)+matrix(3,2));

    if (withLODScale) return dist*getLODScale();
    else return dist*getLODScale();
}

void CollectOccludersVisitor::apply(osg::Node& node)
{
    if (isCulled(node)) return;

    // push the culling mode.
    pushCurrentMask();

    handle_cull_callbacks_and_traverse(node);

    // pop the culling mode.
    popCurrentMask();
}

void CollectOccludersVisitor::apply(osg::Transform& node)
{
    if (isCulled(node)) return;

    // push the culling mode.
    pushCurrentMask();

    ref_ptr<osg::RefMatrix> matrix = createOrReuseMatrix(*getModelViewMatrix());
    node.computeLocalToWorldMatrix(*matrix,this);
    pushModelViewMatrix(matrix.get(), node.getReferenceFrame());

    handle_cull_callbacks_and_traverse(node);

    popModelViewMatrix();

    // pop the culling mode.
    popCurrentMask();
}

void CollectOccludersVisitor::apply(osg::Projection& node)
{
    if (isCulled(node)) return;

    // push the culling mode.
    pushCurrentMask();

    ref_ptr<osg::RefMatrix> matrix = createOrReuseMatrix(node.getMatrix());
    pushProjectionMatrix(matrix.get());

    handle_cull_callbacks_and_traverse(node);

    popProjectionMatrix();

    // pop the culling mode.
    popCurrentMask();
}

void CollectOccludersVisitor::apply(osg::Switch& node)
{
    apply((Group&)node);
}

void CollectOccludersVisitor::apply(osg::LOD& node)
{
    if (isCulled(node)) return;

    // push the culling mode.
    pushCurrentMask();

    handle_cull_callbacks_and_traverse(node);

    // pop the culling mode.
    popCurrentMask();
}

void CollectOccludersVisitor::apply(osg::OccluderNode& node)
{
    // need to check if occlusion node is in the occluder
    // list, if so disable the appropriate ShadowOccluderVolume
    disableAndPushOccludersCurrentMask(_nodePath);

    if (isCulled(node))
    {
        popOccludersCurrentMask(_nodePath);
        return;
    }

//    std::cout<<"CollectOccludersVisitor:: We have found an Occlusion node in frustum"<<&node<<std::endl;

    // push the culling mode.
    pushCurrentMask();

    if (node.getOccluder())
    {
        // computeOccluder will check if the occluder is the view frustum,
        // if it ins't then the it will return false, when in it will
        // clip the occluder's polygons in clip space, then create occluder
        // planes, all with their normals facing inward towards the volume,
        // and then transform them back into projection space.
        ShadowVolumeOccluder svo;
        if (svo.computeOccluder(_nodePath, *node.getOccluder(), *this,_createDrawables))
        {

            if (svo.getVolume()>_minimumShadowOccluderVolume)
            {
                // need to test occluder against view frustum.
                //std::cout << "    adding in Occluder"<<std::endl;
                _occluderSet.insert(svo);
            }
            else
            {
                //std::cout << "    rejecting Occluder as its volume is too small "<<svo.getVolume()<<std::endl;
            }
        }
    }

    handle_cull_callbacks_and_traverse(node);

    // pop the culling mode.
    popCurrentMask();

    // pop the current mask for the disabled occluder
    popOccludersCurrentMask(_nodePath);
}

void CollectOccludersVisitor::removeOccludedOccluders()
{
    if (_occluderSet.empty()) return;

    ShadowVolumeOccluderSet::iterator occludeeItr=_occluderSet.begin();

    // skip the first element as this can't be occluded by anything else.
    occludeeItr++;

    // step through the rest of the occluders, remove occluders which are themselves occluded.
    for(;
        occludeeItr!=_occluderSet.end();
        ++occludeeItr)
    {

        // search for any occluders that occlude the current occluder,
        // we only need to test any occluder near the front of the set since
        // you can't be occluder by something smaller than you.
        ShadowVolumeOccluder& occludee = const_cast<ShadowVolumeOccluder&>(*occludeeItr);
        ShadowVolumeOccluder::HoleList& holeList = occludee.getHoleList();

        for(ShadowVolumeOccluderSet::iterator occluderItr=_occluderSet.begin();
            occluderItr!=occludeeItr;
            ++occluderItr)
        {
            // cast away constness of the std::set element since ShadowVolumeOccluder::contains() is non const,
            // and the std::set is a const, just for the invariance of the operator <!! Ahhhhh. oh well the below
            // should be robust since contains won't change the getVolume which is used by the operator <.  Honest,  :-)
            ShadowVolumeOccluder* occluder = const_cast<ShadowVolumeOccluder*>(&(*occluderItr));
            if (occluder->contains(occludee.getOccluder().getReferenceVertexList()))
            {
                // erase occluder from set.
                // take a copy of the iterator then rewind it one element so to prevent invalidating the occludeeItr.
                ShadowVolumeOccluderSet::iterator eraseItr = occludeeItr--;
                _occluderSet.erase(eraseItr);
                break;
            }

            // now check all the holes in the occludee against the occluder, and remove the ones that won't be valid
            unsigned int previous_valid_hole_i = 0;
            for(unsigned int i=0; i<holeList.size(); ++i)
            {
                if (!occluder->contains(holeList[i].getReferenceVertexList()))
                {
                    if (previous_valid_hole_i<i)
                    {
                        // copy valid holes into gaps left by invalid ones
                        holeList[previous_valid_hole_i] = holeList[i];
                    }

                    previous_valid_hole_i++;
                }
            }

            // remove the tail of the holeList if holes have been removed.
            if (previous_valid_hole_i<holeList.size())
            {
                holeList.erase(holeList.begin()+previous_valid_hole_i,holeList.end());
            }

        }
    }

    if (_occluderSet.size()<=_maximumNumberOfActiveOccluders) return;

    // move the iterator to the _maximumNumberOfActiveOccluders th occluder.
    occludeeItr = _occluderSet.begin();
    for(unsigned int i=0;i<_maximumNumberOfActiveOccluders;++i)
        ++occludeeItr;

    // discard last occluders.
    _occluderSet.erase(occludeeItr,_occluderSet.end());

}
<|endoftext|>


<commit_before>#include <osgSim/Sector>

#include <iostream>
#include <string>

#include <osgDB/Registry>
#include <osgDB/Input>
#include <osgDB/Output>
#include <osgDB/ParameterOutput>

bool AzimSector_readLocalData(osg::Object &obj, osgDB::Input &fr);
bool AzimSector_writeLocalData(const osg::Object &obj, osgDB::Output &fw);

osgDB::RegisterDotOsgWrapperProxy AzimSector_Proxy
(
    new osgSim::AzimSector,
    "AzimSector",
    "Object AzimSector",
    &AzimSector_readLocalData,
    &AzimSector_writeLocalData,
    osgDB::DotOsgWrapper::READ_AND_WRITE
);

bool AzimSector_readLocalData(osg::Object &obj, osgDB::Input &fr)
{
    bool iteratorAdvanced = false;
    osgSim::AzimSector &sector = static_cast<osgSim::AzimSector &>(obj);

    if (fr.matchSequence("azimuthRange %f %f %f"))
    {
        float minAzimuth;
        float maxAzimuth;
        float fadeRange;
        fr[1].getFloat(minAzimuth);
        fr[2].getFloat(maxAzimuth);
        fr[3].getFloat(fadeRange);
        fr += 4;
        sector.setAzimuthRange(minAzimuth, maxAzimuth, fadeRange);
        iteratorAdvanced = true;
    }
    return iteratorAdvanced;
}

bool AzimSector_writeLocalData(const osg::Object &obj, osgDB::Output &fw)
{
    float minAzimuth, maxAzimuth, fadeAngle;

    const osgSim::AzimSector &sector = static_cast<const osgSim::AzimSector &>(obj);
    sector.getAzimuthRange(minAzimuth, maxAzimuth, fadeAngle);
    fw.indent()<<"azimuthRange "<<minAzimuth<< " "<<maxAzimuth<< " "<<fadeAngle<<std::endl;
    return true;
}

/******************************************************************/

bool ElevationSector_readLocalData(osg::Object &obj, osgDB::Input &fr);
bool ElevationSector_writeLocalData(const osg::Object &obj, osgDB::Output &fw);

osgDB::RegisterDotOsgWrapperProxy ElevationSector_Proxy
(
    new osgSim::ElevationSector,
    "ElevationSector",
    "Object ElevationSector",
    &ElevationSector_readLocalData,
    &ElevationSector_writeLocalData,
    osgDB::DotOsgWrapper::READ_AND_WRITE
);

bool ElevationSector_readLocalData(osg::Object &obj, osgDB::Input &fr)
{
    bool iteratorAdvanced = false;
    osgSim::ElevationSector &sector = static_cast<osgSim::ElevationSector &>(obj);

    if (fr.matchSequence("elevationRange %f %f %f"))
    {
        float minElevation;
        float maxElevation;
        float fadeAngle;

        fr[1].getFloat(minElevation);
        fr[2].getFloat(maxElevation);
        fr[3].getFloat(fadeAngle);
        fr += 4;
        sector.setElevationRange(minElevation, maxElevation, fadeAngle);
        iteratorAdvanced = true;
    }
    return iteratorAdvanced;
}

bool ElevationSector_writeLocalData(const osg::Object &obj, osgDB::Output &fw)
{

    const osgSim::ElevationSector &sector = static_cast<const osgSim::ElevationSector &>(obj);

    float minElevation = sector.getMinElevation();
    float maxElevation = sector.getMaxElevation();
    float fadeAngle = sector.getFadeAngle();
    fw.indent()<<"elevationRange "<<minElevation<< " "<<maxElevation<< " "<<fadeAngle<<std::endl;

    return true;
}

/******************************************************************/

bool AzimElevationSector_readLocalData(osg::Object &obj, osgDB::Input &fr);
bool AzimElevationSector_writeLocalData(const osg::Object &obj, osgDB::Output &fw);

osgDB::RegisterDotOsgWrapperProxy AzimElevationSector_Proxy
(
    new osgSim::AzimElevationSector,
    "AzimElevationSector",
    "Object AzimElevationSector",
    &AzimElevationSector_readLocalData,
    &AzimElevationSector_writeLocalData,
    osgDB::DotOsgWrapper::READ_AND_WRITE
);

bool AzimElevationSector_readLocalData(osg::Object &obj, osgDB::Input &fr)
{
    bool iteratorAdvanced = false;
    osgSim::AzimElevationSector &sector = static_cast<osgSim::AzimElevationSector &>(obj);

    if (fr.matchSequence("azimuthRange %f %f %f"))
    {
        float minAzimuth;
        float maxAzimuth;
        float fadeAngle;
        fr[1].getFloat(minAzimuth);
        fr[2].getFloat(maxAzimuth);
        fr[3].getFloat(fadeAngle);
        fr += 4;
        sector.setAzimuthRange(minAzimuth, maxAzimuth, fadeAngle);
        iteratorAdvanced = true;
    }
    if (fr.matchSequence("elevationRange %f %f %f"))
    {
        float minElevation;
        float maxElevation;
        float fadeAngle;

        fr[1].getFloat(minElevation);
        fr[2].getFloat(maxElevation);
        fr[3].getFloat(fadeAngle);
        fr += 4;
        sector.setElevationRange(minElevation, maxElevation, fadeAngle);
        iteratorAdvanced = true;
    }
    return iteratorAdvanced;
}

bool AzimElevationSector_writeLocalData(const osg::Object &obj, osgDB::Output &fw)
{

    const osgSim::AzimElevationSector &sector = static_cast<const osgSim::AzimElevationSector &>(obj);

    float minElevation = sector.getMinElevation();
    float maxElevation = sector.getMaxElevation();
    float fadeAngle = sector.getFadeAngle();
    fw.indent()<<"elevationRange "<<minElevation<< " "<<maxElevation<< " "<<fadeAngle<<std::endl;

    float minAzimuth, maxAzimuth;
    sector.getAzimuthRange(minAzimuth, maxAzimuth, fadeAngle);
    fw.indent()<<"azimuthRange "<<minAzimuth<< " "<<maxAzimuth<< " "<<fadeAngle<<std::endl;
    return true;
}

/******************************************************************/

bool ConeSector_readLocalData(osg::Object &obj, osgDB::Input &fr);
bool ConeSector_writeLocalData(const osg::Object &obj, osgDB::Output &fw);

osgDB::RegisterDotOsgWrapperProxy ConeSector_Proxy
(
    new osgSim::ConeSector,
    "ConeSector",
    "Object ConeSector",
    &ConeSector_readLocalData,
    &ConeSector_writeLocalData,
    osgDB::DotOsgWrapper::READ_AND_WRITE
);

bool ConeSector_readLocalData(osg::Object &obj, osgDB::Input &fr)
{
    bool iteratorAdvanced = false;
    osgSim::ConeSector &sector = static_cast<osgSim::ConeSector &>(obj);

    if (fr.matchSequence("axis %f %f %f"))
    {
        float x, y, z;

        fr[1].getFloat(x);
        fr[2].getFloat(y);
        fr[3].getFloat(z);
        fr += 4;
        sector.setAxis(osg::Vec3(x, y, z));
        iteratorAdvanced = true;
    }
    if (fr.matchSequence("angle %f %f"))
    {
        float angle;
        float fadeangle;
        fr[1].getFloat(angle);
        fr[2].getFloat(fadeangle);
        fr += 3;
        sector.setAngle(angle, fadeangle);
        iteratorAdvanced;
    }
    return iteratorAdvanced;
}

bool ConeSector_writeLocalData(const osg::Object &obj, osgDB::Output &fw)
{
    const osgSim::ConeSector &sector = static_cast<const osgSim::ConeSector &>(obj);

    const osg::Vec3& axis = sector.getAxis();
    fw.indent()<<"axis "<<axis<<std::endl;

    float angle = sector.getAngle();
    float fadeangle = sector.getFadeAngle();
    fw.indent()<<"angle "<<angle<<" "<<fadeangle<<std::endl;
    return true;
}

<commit_msg>Fixed warning, which was actually a bug, sometimes you've just gotta love pedantic warnings.<commit_after>#include <osgSim/Sector>

#include <iostream>
#include <string>

#include <osgDB/Registry>
#include <osgDB/Input>
#include <osgDB/Output>
#include <osgDB/ParameterOutput>

bool AzimSector_readLocalData(osg::Object &obj, osgDB::Input &fr);
bool AzimSector_writeLocalData(const osg::Object &obj, osgDB::Output &fw);

osgDB::RegisterDotOsgWrapperProxy AzimSector_Proxy
(
    new osgSim::AzimSector,
    "AzimSector",
    "Object AzimSector",
    &AzimSector_readLocalData,
    &AzimSector_writeLocalData,
    osgDB::DotOsgWrapper::READ_AND_WRITE
);

bool AzimSector_readLocalData(osg::Object &obj, osgDB::Input &fr)
{
    bool iteratorAdvanced = false;
    osgSim::AzimSector &sector = static_cast<osgSim::AzimSector &>(obj);

    if (fr.matchSequence("azimuthRange %f %f %f"))
    {
        float minAzimuth;
        float maxAzimuth;
        float fadeRange;
        fr[1].getFloat(minAzimuth);
        fr[2].getFloat(maxAzimuth);
        fr[3].getFloat(fadeRange);
        fr += 4;
        sector.setAzimuthRange(minAzimuth, maxAzimuth, fadeRange);
        iteratorAdvanced = true;
    }
    return iteratorAdvanced;
}

bool AzimSector_writeLocalData(const osg::Object &obj, osgDB::Output &fw)
{
    float minAzimuth, maxAzimuth, fadeAngle;

    const osgSim::AzimSector &sector = static_cast<const osgSim::AzimSector &>(obj);
    sector.getAzimuthRange(minAzimuth, maxAzimuth, fadeAngle);
    fw.indent()<<"azimuthRange "<<minAzimuth<< " "<<maxAzimuth<< " "<<fadeAngle<<std::endl;
    return true;
}

/******************************************************************/

bool ElevationSector_readLocalData(osg::Object &obj, osgDB::Input &fr);
bool ElevationSector_writeLocalData(const osg::Object &obj, osgDB::Output &fw);

osgDB::RegisterDotOsgWrapperProxy ElevationSector_Proxy
(
    new osgSim::ElevationSector,
    "ElevationSector",
    "Object ElevationSector",
    &ElevationSector_readLocalData,
    &ElevationSector_writeLocalData,
    osgDB::DotOsgWrapper::READ_AND_WRITE
);

bool ElevationSector_readLocalData(osg::Object &obj, osgDB::Input &fr)
{
    bool iteratorAdvanced = false;
    osgSim::ElevationSector &sector = static_cast<osgSim::ElevationSector &>(obj);

    if (fr.matchSequence("elevationRange %f %f %f"))
    {
        float minElevation;
        float maxElevation;
        float fadeAngle;

        fr[1].getFloat(minElevation);
        fr[2].getFloat(maxElevation);
        fr[3].getFloat(fadeAngle);
        fr += 4;
        sector.setElevationRange(minElevation, maxElevation, fadeAngle);
        iteratorAdvanced = true;
    }
    return iteratorAdvanced;
}

bool ElevationSector_writeLocalData(const osg::Object &obj, osgDB::Output &fw)
{

    const osgSim::ElevationSector &sector = static_cast<const osgSim::ElevationSector &>(obj);

    float minElevation = sector.getMinElevation();
    float maxElevation = sector.getMaxElevation();
    float fadeAngle = sector.getFadeAngle();
    fw.indent()<<"elevationRange "<<minElevation<< " "<<maxElevation<< " "<<fadeAngle<<std::endl;

    return true;
}

/******************************************************************/

bool AzimElevationSector_readLocalData(osg::Object &obj, osgDB::Input &fr);
bool AzimElevationSector_writeLocalData(const osg::Object &obj, osgDB::Output &fw);

osgDB::RegisterDotOsgWrapperProxy AzimElevationSector_Proxy
(
    new osgSim::AzimElevationSector,
    "AzimElevationSector",
    "Object AzimElevationSector",
    &AzimElevationSector_readLocalData,
    &AzimElevationSector_writeLocalData,
    osgDB::DotOsgWrapper::READ_AND_WRITE
);

bool AzimElevationSector_readLocalData(osg::Object &obj, osgDB::Input &fr)
{
    bool iteratorAdvanced = false;
    osgSim::AzimElevationSector &sector = static_cast<osgSim::AzimElevationSector &>(obj);

    if (fr.matchSequence("azimuthRange %f %f %f"))
    {
        float minAzimuth;
        float maxAzimuth;
        float fadeAngle;
        fr[1].getFloat(minAzimuth);
        fr[2].getFloat(maxAzimuth);
        fr[3].getFloat(fadeAngle);
        fr += 4;
        sector.setAzimuthRange(minAzimuth, maxAzimuth, fadeAngle);
        iteratorAdvanced = true;
    }
    if (fr.matchSequence("elevationRange %f %f %f"))
    {
        float minElevation;
        float maxElevation;
        float fadeAngle;

        fr[1].getFloat(minElevation);
        fr[2].getFloat(maxElevation);
        fr[3].getFloat(fadeAngle);
        fr += 4;
        sector.setElevationRange(minElevation, maxElevation, fadeAngle);
        iteratorAdvanced = true;
    }
    return iteratorAdvanced;
}

bool AzimElevationSector_writeLocalData(const osg::Object &obj, osgDB::Output &fw)
{

    const osgSim::AzimElevationSector &sector = static_cast<const osgSim::AzimElevationSector &>(obj);

    float minElevation = sector.getMinElevation();
    float maxElevation = sector.getMaxElevation();
    float fadeAngle = sector.getFadeAngle();
    fw.indent()<<"elevationRange "<<minElevation<< " "<<maxElevation<< " "<<fadeAngle<<std::endl;

    float minAzimuth, maxAzimuth;
    sector.getAzimuthRange(minAzimuth, maxAzimuth, fadeAngle);
    fw.indent()<<"azimuthRange "<<minAzimuth<< " "<<maxAzimuth<< " "<<fadeAngle<<std::endl;
    return true;
}

/******************************************************************/

bool ConeSector_readLocalData(osg::Object &obj, osgDB::Input &fr);
bool ConeSector_writeLocalData(const osg::Object &obj, osgDB::Output &fw);

osgDB::RegisterDotOsgWrapperProxy ConeSector_Proxy
(
    new osgSim::ConeSector,
    "ConeSector",
    "Object ConeSector",
    &ConeSector_readLocalData,
    &ConeSector_writeLocalData,
    osgDB::DotOsgWrapper::READ_AND_WRITE
);

bool ConeSector_readLocalData(osg::Object &obj, osgDB::Input &fr)
{
    bool iteratorAdvanced = false;
    osgSim::ConeSector &sector = static_cast<osgSim::ConeSector &>(obj);

    if (fr.matchSequence("axis %f %f %f"))
    {
        float x, y, z;

        fr[1].getFloat(x);
        fr[2].getFloat(y);
        fr[3].getFloat(z);
        fr += 4;
        sector.setAxis(osg::Vec3(x, y, z));
        iteratorAdvanced = true;
    }
    if (fr.matchSequence("angle %f %f"))
    {
        float angle;
        float fadeangle;
        fr[1].getFloat(angle);
        fr[2].getFloat(fadeangle);
        fr += 3;
        sector.setAngle(angle, fadeangle);
        iteratorAdvanced = true;
    }
    return iteratorAdvanced;
}

bool ConeSector_writeLocalData(const osg::Object &obj, osgDB::Output &fw)
{
    const osgSim::ConeSector &sector = static_cast<const osgSim::ConeSector &>(obj);

    const osg::Vec3& axis = sector.getAxis();
    fw.indent()<<"axis "<<axis<<std::endl;

    float angle = sector.getAngle();
    float fadeangle = sector.getFadeAngle();
    fw.indent()<<"angle "<<angle<<" "<<fadeangle<<std::endl;
    return true;
}

<|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/RenderStageLighting>

using namespace osg;
using namespace osgUtil;

// register a RenderStageLighting prototype with the RenderBin prototype list.
//RegisterRenderBinProxy<RenderStageLighting> s_registerRenderStageLightingProxy;

RenderStageLighting::RenderStageLighting()
{
}

RenderStageLighting::~RenderStageLighting()
{
}

void RenderStageLighting::reset()
{
    _attrList.clear();
}

void RenderStageLighting::draw(osg::State& state,RenderLeaf*& previous)
{

    if (previous)
    {
        RenderGraph::moveToRootRenderGraph(state,previous->_parent);
        state.apply();
        previous = NULL;
    }

    // apply the light list.
    for(AttrMatrixList::iterator litr=_attrList.begin();
        litr!=_attrList.end();
        ++litr)
    {
        state.applyModelViewMatrix((*litr).second.get());

        // apply the light source.
        litr->first->apply(state);

    }

}
<commit_msg>Added haveAppliedAttribute to allow draw callbacks to get access to the current active lights.<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/RenderStageLighting>

using namespace osg;
using namespace osgUtil;

// register a RenderStageLighting prototype with the RenderBin prototype list.
//RegisterRenderBinProxy<RenderStageLighting> s_registerRenderStageLightingProxy;

RenderStageLighting::RenderStageLighting()
{
}

RenderStageLighting::~RenderStageLighting()
{
}

void RenderStageLighting::reset()
{
    _attrList.clear();
}

void RenderStageLighting::draw(osg::State& state,RenderLeaf*& previous)
{

    if (previous)
    {
        RenderGraph::moveToRootRenderGraph(state,previous->_parent);
        state.apply();
        previous = NULL;
    }

    // apply the light list.
    for(AttrMatrixList::iterator litr=_attrList.begin();
        litr!=_attrList.end();
        ++litr)
    {
        state.applyModelViewMatrix((*litr).second.get());

        // apply the light source.
        litr->first->apply(state);

        // tell state about.
        state.haveAppliedAttribute(litr->first);

    }

}
<|endoftext|>


<commit_before>// @(#)root/geom:$Id$
// Author: Andrei Gheata   02/06/05

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "Riostream.h"

#include "TGeoManager.h"
#include "TGeoVoxelFinder.h"
#include "TGeoMatrix.h"
#include "TGeoVolume.h"
#include "TGeoNode.h"
#include "TGeoShapeAssembly.h"
#include "TBuffer3D.h"
#include "TBuffer3DTypes.h"
#include "TMath.h"

//_____________________________________________________________________________
// TGeoShapeAssembly - The shape encapsulating an assembly (union) of volumes.
//
//_____________________________________________________________________________

ClassImp(TGeoShapeAssembly)

//_____________________________________________________________________________
TGeoShapeAssembly::TGeoShapeAssembly()
{
// Default constructor
   fVolume  = 0;
}

//_____________________________________________________________________________
TGeoShapeAssembly::TGeoShapeAssembly(TGeoVolumeAssembly *vol)
{
// Constructor specifying hyperboloid parameters.
   fVolume  = vol;
}

//_____________________________________________________________________________
TGeoShapeAssembly::~TGeoShapeAssembly()
{
// destructor
}

//_____________________________________________________________________________
void TGeoShapeAssembly::ComputeBBox()
{
// Compute bounding box of the assembly
   if (!fVolume) {
      Error("ComputeBBox", "Assebmly shape %s without volume", GetName());
      return;
   }
   Int_t nd = fVolume->GetNdaughters();
   if (!nd) return;
   TGeoNode *node;
   TGeoBBox *box;
   Double_t xmin, xmax, ymin, ymax, zmin, zmax;
   xmin = ymin = zmin = TGeoShape::Big();
   xmax = ymax = zmax = -TGeoShape::Big();
   Double_t vert[24];
   Double_t pt[3];
   for (Int_t i=0; i<nd; i++) {
      node = fVolume->GetNode(i);
      if (node->GetVolume()->IsAssembly()) node->GetVolume()->GetShape()->ComputeBBox();
      box = (TGeoBBox*)node->GetVolume()->GetShape();
      box->SetBoxPoints(vert);
      for (Int_t ipt=0; ipt<8; ipt++) {
         node->LocalToMaster(&vert[3*ipt], pt);
         if (pt[0]<xmin) xmin=pt[0];
         if (pt[0]>xmax) xmax=pt[0];
         if (pt[1]<ymin) ymin=pt[1];
         if (pt[1]>ymax) ymax=pt[1];
         if (pt[2]<zmin) zmin=pt[2];
         if (pt[2]>zmax) zmax=pt[2];
      }
   }
   fDX = 0.5*(xmax-xmin);
   fOrigin[0] = 0.5*(xmin+xmax);
   fDY = 0.5*(ymax-ymin);
   fOrigin[1] = 0.5*(ymin+ymax);
   fDZ = 0.5*(zmax-zmin);
   fOrigin[2] = 0.5*(zmin+zmax);
}

//_____________________________________________________________________________
void TGeoShapeAssembly::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
{
// Compute normal to closest surface from POINT. Should not be called.
   Int_t inext = fVolume->GetNextNodeIndex();
   if (inext<0) {
      DistFromOutside(point,dir,3);
      inext = fVolume->GetNextNodeIndex();
      if (inext<0) {
         Error("ComputeNormal","Invalid inext=%i (Ncomponents=%i)",inext,fVolume->GetNdaughters());
         return;
      }
   }
   TGeoNode *node = fVolume->GetNode(inext);
   Double_t local[3],ldir[3],lnorm[3];
   node->MasterToLocal(point,local);
   node->MasterToLocalVect(dir,ldir);
   node->GetVolume()->GetShape()->ComputeNormal(local,ldir,lnorm);
   node->LocalToMasterVect(lnorm,norm);
}

//_____________________________________________________________________________
Bool_t TGeoShapeAssembly::Contains(Double_t *point) const
{
// Test if point is inside the assembly
   if (!TGeoBBox::Contains(point)) return kFALSE;
   TGeoVoxelFinder *voxels = fVolume->GetVoxels();
   TGeoNode *node;
   TGeoShape *shape;
   Int_t *check_list = 0;
   Int_t ncheck, id;
   Double_t local[3];
   if (voxels) {
      // get the list of nodes passing thorough the current voxel
      check_list = voxels->GetCheckList(&point[0], ncheck);
      if (!check_list) return kFALSE;
      for (id=0; id<ncheck; id++) {
         node = fVolume->GetNode(check_list[id]);
         shape = node->GetVolume()->GetShape();
         node->MasterToLocal(point,local);
         if (shape->Contains(local)) {
            fVolume->SetCurrentNodeIndex(check_list[id]);
            fVolume->SetNextNodeIndex(check_list[id]);
            return kTRUE;
         }
      }
      return kFALSE;
   }
   Int_t nd = fVolume->GetNdaughters();
   for (id=0; id<nd; id++) {
      node = fVolume->GetNode(id);
      shape = node->GetVolume()->GetShape();
      node->MasterToLocal(point,local);
      if (shape->Contains(local)) {
         fVolume->SetCurrentNodeIndex(id);
         fVolume->SetNextNodeIndex(id);
         return kTRUE;
      }
   }
   return kFALSE;
}

//_____________________________________________________________________________
Int_t TGeoShapeAssembly::DistancetoPrimitive(Int_t /*px*/, Int_t /*py*/)
{
// compute closest distance from point px,py to each vertex. Should not be called.
   return 9999;
}

//_____________________________________________________________________________
Double_t TGeoShapeAssembly::DistFromInside(Double_t * /*point*/, Double_t * /*dir*/, Int_t /*iact*/, Double_t /*step*/, Double_t * /*safe*/) const
{
// Compute distance from inside point to surface of the hyperboloid.
   Info("DistFromInside", "Cannot compute distance from inside the assembly (but from a component)");
   return TGeoShape::Big();
}

//_____________________________________________________________________________
Double_t TGeoShapeAssembly::DistFromOutside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
{
// compute distance from outside point to surface of the hyperboloid.
//   fVolume->SetNextNodeIndex(-1);
   if (iact<3 && safe) {
      *safe = Safety(point, kFALSE);
      if (iact==0) return TGeoShape::Big();
      if ((iact==1) && (step<=*safe)) return TGeoShape::Big();
   }
   // find distance to assembly
   Double_t snext = 0.0;
   Double_t dist;
   Double_t stepmax = step;
   Double_t pt[3];
   Int_t i;
   Bool_t found = kFALSE;
   memcpy(pt,point,3*sizeof(Double_t));
   if (!TGeoBBox::Contains(point)) {
      snext = TGeoBBox::DistFromOutside(point, dir, 3, stepmax);
      if (snext > stepmax) return TGeoShape::Big();
      for (i=0; i<3; i++) pt[i] += (snext+TGeoShape::Tolerance())*dir[i];
      if (Contains(pt)) {
         fVolume->SetNextNodeIndex(fVolume->GetCurrentNodeIndex());
         return snext;
      }
      snext += TGeoShape::Tolerance();
      stepmax -= snext;
   }
   // Point represented by pt is now inside the bounding box - find distance to components
   Int_t nd = fVolume->GetNdaughters();
   TGeoNode *node;
   Double_t lpoint[3],ldir[3];
   TGeoVoxelFinder *voxels = fVolume->GetVoxels();
   if (nd<5 || !voxels) {
      for (i=0; i<nd; i++) {
         node = fVolume->GetNode(i);
         if (voxels && voxels->IsSafeVoxel(pt, i, stepmax)) continue;
         node->MasterToLocal(pt, lpoint);
         node->MasterToLocalVect(dir, ldir);
         dist = node->GetVolume()->GetShape()->DistFromOutside(lpoint, ldir, 3, stepmax);
         if (dist<stepmax) {
            stepmax = dist;
            fVolume->SetNextNodeIndex(i);
            found = kTRUE;
         }
      }
      if (found) {
         snext += stepmax;
         return snext;
      }
      return TGeoShape::Big();
   }
   // current volume is voxelized, first get current voxel
   Int_t ncheck = 0;
   Int_t *vlist = 0;
   voxels->SortCrossedVoxels(pt, dir);
   while ((vlist=voxels->GetNextVoxel(pt, dir, ncheck))) {
      for (i=0; i<ncheck; i++) {
         node = fVolume->GetNode(vlist[i]);
         node->MasterToLocal(pt, lpoint);
         node->MasterToLocalVect(dir, ldir);
         dist = node->GetVolume()->GetShape()->DistFromOutside(lpoint, ldir, 3, stepmax);
         if (dist<stepmax) {
            stepmax = dist;
            fVolume->SetNextNodeIndex(vlist[i]);
            found = kTRUE;
         }
      }
   }
   if (found) {
      snext += stepmax;
      return snext;
   }
   return TGeoShape::Big();
}

//_____________________________________________________________________________
TGeoVolume *TGeoShapeAssembly::Divide(TGeoVolume * /*voldiv*/, const char *divname, Int_t /*iaxis*/, Int_t /*ndiv*/,
                             Double_t /*start*/, Double_t /*step*/)
{
// Cannot divide assemblies.
   Error("Divide", "Assemblies cannot be divided. Division volume %s not created", divname);
   return 0;
}

//_____________________________________________________________________________
TGeoShape *TGeoShapeAssembly::GetMakeRuntimeShape(TGeoShape * /*mother*/, TGeoMatrix * /*mat*/) const
{
// in case shape has some negative parameters, these has to be computed
// in order to fit the mother
   Error("GetMakeRuntimeShape", "Assemblies cannot be parametrized.");
   return NULL;
}

//_____________________________________________________________________________
void TGeoShapeAssembly::InspectShape() const
{
// print shape parameters
   printf("*** Shape %s: TGeoShapeAssembly ***\n", GetName());
   printf("    Volume assembly %s with %i nodes\n", fVolume->GetName(), fVolume->GetNdaughters());
   printf(" Bounding box:\n");
   TGeoBBox::InspectShape();
}

//_____________________________________________________________________________
void TGeoShapeAssembly::SetSegsAndPols(TBuffer3D & /*buff*/) const
{
// Fill TBuffer3D structure for segments and polygons.
   Error("SetSegsAndPols", "Drawing functions should not be called for assemblies, but rather for their content");
}

//_____________________________________________________________________________
Double_t TGeoShapeAssembly::Safety(Double_t *point, Bool_t in) const
{
// computes the closest distance from given point to this shape, according
// to option. The matching point on the shape is stored in spoint.
   Double_t safety = TGeoShape::Big();
   Double_t pt[3], loc[3];
   if (in) {
      Int_t index = fVolume->GetCurrentNodeIndex();
      TGeoVolume *vol = fVolume;
      TGeoNode *node;
      memcpy(loc, point, 3*sizeof(Double_t));
      while (index>=0) {
         memcpy(pt, loc, 3*sizeof(Double_t));
         node = vol->GetNode(index);
         node->GetMatrix()->MasterToLocal(pt,loc);
         vol = node->GetVolume();
         index = vol->GetCurrentNodeIndex();
         if (index<0) {
            safety = vol->GetShape()->Safety(loc, in);
            return safety;
         }
      }
      return TGeoShape::Big();
   }
   Double_t safe;
   TGeoVoxelFinder *voxels = fVolume->GetVoxels();
   Int_t nd = fVolume->GetNdaughters();
   Double_t *boxes = 0;
   if (voxels) boxes = voxels->GetBoxes();
   TGeoNode *node;
   for (Int_t id=0; id<nd; id++) {
      if (boxes && id>0) {
         Int_t ist = 6*id;
         Double_t dxyz = 0.;
         Double_t dxyz0 = TMath::Abs(point[0]-boxes[ist+3])-boxes[ist];
         if (dxyz0 > safety) continue;
         Double_t dxyz1 = TMath::Abs(point[1]-boxes[ist+4])-boxes[ist+1];
         if (dxyz1 > safety) continue;
         Double_t dxyz2 = TMath::Abs(point[2]-boxes[ist+5])-boxes[ist+2];
         if (dxyz2 > safety) continue;
         if (dxyz0>0) dxyz+=dxyz0*dxyz0;
         if (dxyz1>0) dxyz+=dxyz1*dxyz1;
         if (dxyz2>0) dxyz+=dxyz2*dxyz2;
         if (dxyz >= safety*safety) continue;
      }
      node = fVolume->GetNode(id);
      safe = node->Safety(point, kFALSE);
      if (safe<=0.0) return 0.0;
      if (safe<safety) safety = safe;
   }
   return safety;
}

//_____________________________________________________________________________
void TGeoShapeAssembly::SavePrimitive(ostream & /*out*/, Option_t * /*option*/ /*= ""*/)
{
// Save a primitive as a C++ statement(s) on output stream "out".
}

//_____________________________________________________________________________
void TGeoShapeAssembly::SetPoints(Double_t * /*points*/) const
{
// No mesh for assemblies.
   Error("SetPoints", "Drawing functions should not be called for assemblies, but rather for their content");
}

//_____________________________________________________________________________
void TGeoShapeAssembly::SetPoints(Float_t * /*points*/) const
{
// No mesh for assemblies.
   Error("SetPoints", "Drawing functions should not be called for assemblies, but rather for their content");
}

//_____________________________________________________________________________
void TGeoShapeAssembly::GetMeshNumbers(Int_t &nvert, Int_t &nsegs, Int_t &npols) const
{
// Returns numbers of vertices, segments and polygons composing the shape mesh.
   nvert = 0;
   nsegs = 0;
   npols = 0;
}

<commit_msg>Fixed uninitialized variable, coverity # 21469<commit_after>// @(#)root/geom:$Id$
// Author: Andrei Gheata   02/06/05

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "Riostream.h"

#include "TGeoManager.h"
#include "TGeoVoxelFinder.h"
#include "TGeoMatrix.h"
#include "TGeoVolume.h"
#include "TGeoNode.h"
#include "TGeoShapeAssembly.h"
#include "TBuffer3D.h"
#include "TBuffer3DTypes.h"
#include "TMath.h"

//_____________________________________________________________________________
// TGeoShapeAssembly - The shape encapsulating an assembly (union) of volumes.
//
//_____________________________________________________________________________

ClassImp(TGeoShapeAssembly)

//_____________________________________________________________________________
TGeoShapeAssembly::TGeoShapeAssembly()
{
// Default constructor
   fCurrent = 0;
   fNext = 0;
   fVolume  = 0;
}

//_____________________________________________________________________________
TGeoShapeAssembly::TGeoShapeAssembly(TGeoVolumeAssembly *vol)
{
// Constructor specifying hyperboloid parameters.
   fVolume  = vol;
   fCurrent = 0;
   fNext = 0;
}

//_____________________________________________________________________________
TGeoShapeAssembly::~TGeoShapeAssembly()
{
// destructor
}

//_____________________________________________________________________________
void TGeoShapeAssembly::ComputeBBox()
{
// Compute bounding box of the assembly
   if (!fVolume) {
      Error("ComputeBBox", "Assebmly shape %s without volume", GetName());
      return;
   }
   Int_t nd = fVolume->GetNdaughters();
   if (!nd) return;
   TGeoNode *node;
   TGeoBBox *box;
   Double_t xmin, xmax, ymin, ymax, zmin, zmax;
   xmin = ymin = zmin = TGeoShape::Big();
   xmax = ymax = zmax = -TGeoShape::Big();
   Double_t vert[24];
   Double_t pt[3];
   for (Int_t i=0; i<nd; i++) {
      node = fVolume->GetNode(i);
      if (node->GetVolume()->IsAssembly()) node->GetVolume()->GetShape()->ComputeBBox();
      box = (TGeoBBox*)node->GetVolume()->GetShape();
      box->SetBoxPoints(vert);
      for (Int_t ipt=0; ipt<8; ipt++) {
         node->LocalToMaster(&vert[3*ipt], pt);
         if (pt[0]<xmin) xmin=pt[0];
         if (pt[0]>xmax) xmax=pt[0];
         if (pt[1]<ymin) ymin=pt[1];
         if (pt[1]>ymax) ymax=pt[1];
         if (pt[2]<zmin) zmin=pt[2];
         if (pt[2]>zmax) zmax=pt[2];
      }
   }
   fDX = 0.5*(xmax-xmin);
   fOrigin[0] = 0.5*(xmin+xmax);
   fDY = 0.5*(ymax-ymin);
   fOrigin[1] = 0.5*(ymin+ymax);
   fDZ = 0.5*(zmax-zmin);
   fOrigin[2] = 0.5*(zmin+zmax);
}

//_____________________________________________________________________________
void TGeoShapeAssembly::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
{
// Compute normal to closest surface from POINT. Should not be called.
   Int_t inext = fVolume->GetNextNodeIndex();
   if (inext<0) {
      DistFromOutside(point,dir,3);
      inext = fVolume->GetNextNodeIndex();
      if (inext<0) {
         Error("ComputeNormal","Invalid inext=%i (Ncomponents=%i)",inext,fVolume->GetNdaughters());
         return;
      }
   }
   TGeoNode *node = fVolume->GetNode(inext);
   Double_t local[3],ldir[3],lnorm[3];
   node->MasterToLocal(point,local);
   node->MasterToLocalVect(dir,ldir);
   node->GetVolume()->GetShape()->ComputeNormal(local,ldir,lnorm);
   node->LocalToMasterVect(lnorm,norm);
}

//_____________________________________________________________________________
Bool_t TGeoShapeAssembly::Contains(Double_t *point) const
{
// Test if point is inside the assembly
   if (!TGeoBBox::Contains(point)) return kFALSE;
   TGeoVoxelFinder *voxels = fVolume->GetVoxels();
   TGeoNode *node;
   TGeoShape *shape;
   Int_t *check_list = 0;
   Int_t ncheck, id;
   Double_t local[3];
   if (voxels) {
      // get the list of nodes passing thorough the current voxel
      check_list = voxels->GetCheckList(&point[0], ncheck);
      if (!check_list) return kFALSE;
      for (id=0; id<ncheck; id++) {
         node = fVolume->GetNode(check_list[id]);
         shape = node->GetVolume()->GetShape();
         node->MasterToLocal(point,local);
         if (shape->Contains(local)) {
            fVolume->SetCurrentNodeIndex(check_list[id]);
            fVolume->SetNextNodeIndex(check_list[id]);
            return kTRUE;
         }
      }
      return kFALSE;
   }
   Int_t nd = fVolume->GetNdaughters();
   for (id=0; id<nd; id++) {
      node = fVolume->GetNode(id);
      shape = node->GetVolume()->GetShape();
      node->MasterToLocal(point,local);
      if (shape->Contains(local)) {
         fVolume->SetCurrentNodeIndex(id);
         fVolume->SetNextNodeIndex(id);
         return kTRUE;
      }
   }
   return kFALSE;
}

//_____________________________________________________________________________
Int_t TGeoShapeAssembly::DistancetoPrimitive(Int_t /*px*/, Int_t /*py*/)
{
// compute closest distance from point px,py to each vertex. Should not be called.
   return 9999;
}

//_____________________________________________________________________________
Double_t TGeoShapeAssembly::DistFromInside(Double_t * /*point*/, Double_t * /*dir*/, Int_t /*iact*/, Double_t /*step*/, Double_t * /*safe*/) const
{
// Compute distance from inside point to surface of the hyperboloid.
   Info("DistFromInside", "Cannot compute distance from inside the assembly (but from a component)");
   return TGeoShape::Big();
}

//_____________________________________________________________________________
Double_t TGeoShapeAssembly::DistFromOutside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
{
// compute distance from outside point to surface of the hyperboloid.
//   fVolume->SetNextNodeIndex(-1);
   if (iact<3 && safe) {
      *safe = Safety(point, kFALSE);
      if (iact==0) return TGeoShape::Big();
      if ((iact==1) && (step<=*safe)) return TGeoShape::Big();
   }
   // find distance to assembly
   Double_t snext = 0.0;
   Double_t dist;
   Double_t stepmax = step;
   Double_t pt[3];
   Int_t i;
   Bool_t found = kFALSE;
   memcpy(pt,point,3*sizeof(Double_t));
   if (!TGeoBBox::Contains(point)) {
      snext = TGeoBBox::DistFromOutside(point, dir, 3, stepmax);
      if (snext > stepmax) return TGeoShape::Big();
      for (i=0; i<3; i++) pt[i] += (snext+TGeoShape::Tolerance())*dir[i];
      if (Contains(pt)) {
         fVolume->SetNextNodeIndex(fVolume->GetCurrentNodeIndex());
         return snext;
      }
      snext += TGeoShape::Tolerance();
      stepmax -= snext;
   }
   // Point represented by pt is now inside the bounding box - find distance to components
   Int_t nd = fVolume->GetNdaughters();
   TGeoNode *node;
   Double_t lpoint[3],ldir[3];
   TGeoVoxelFinder *voxels = fVolume->GetVoxels();
   if (nd<5 || !voxels) {
      for (i=0; i<nd; i++) {
         node = fVolume->GetNode(i);
         if (voxels && voxels->IsSafeVoxel(pt, i, stepmax)) continue;
         node->MasterToLocal(pt, lpoint);
         node->MasterToLocalVect(dir, ldir);
         dist = node->GetVolume()->GetShape()->DistFromOutside(lpoint, ldir, 3, stepmax);
         if (dist<stepmax) {
            stepmax = dist;
            fVolume->SetNextNodeIndex(i);
            found = kTRUE;
         }
      }
      if (found) {
         snext += stepmax;
         return snext;
      }
      return TGeoShape::Big();
   }
   // current volume is voxelized, first get current voxel
   Int_t ncheck = 0;
   Int_t *vlist = 0;
   voxels->SortCrossedVoxels(pt, dir);
   while ((vlist=voxels->GetNextVoxel(pt, dir, ncheck))) {
      for (i=0; i<ncheck; i++) {
         node = fVolume->GetNode(vlist[i]);
         node->MasterToLocal(pt, lpoint);
         node->MasterToLocalVect(dir, ldir);
         dist = node->GetVolume()->GetShape()->DistFromOutside(lpoint, ldir, 3, stepmax);
         if (dist<stepmax) {
            stepmax = dist;
            fVolume->SetNextNodeIndex(vlist[i]);
            found = kTRUE;
         }
      }
   }
   if (found) {
      snext += stepmax;
      return snext;
   }
   return TGeoShape::Big();
}

//_____________________________________________________________________________
TGeoVolume *TGeoShapeAssembly::Divide(TGeoVolume * /*voldiv*/, const char *divname, Int_t /*iaxis*/, Int_t /*ndiv*/,
                             Double_t /*start*/, Double_t /*step*/)
{
// Cannot divide assemblies.
   Error("Divide", "Assemblies cannot be divided. Division volume %s not created", divname);
   return 0;
}

//_____________________________________________________________________________
TGeoShape *TGeoShapeAssembly::GetMakeRuntimeShape(TGeoShape * /*mother*/, TGeoMatrix * /*mat*/) const
{
// in case shape has some negative parameters, these has to be computed
// in order to fit the mother
   Error("GetMakeRuntimeShape", "Assemblies cannot be parametrized.");
   return NULL;
}

//_____________________________________________________________________________
void TGeoShapeAssembly::InspectShape() const
{
// print shape parameters
   printf("*** Shape %s: TGeoShapeAssembly ***\n", GetName());
   printf("    Volume assembly %s with %i nodes\n", fVolume->GetName(), fVolume->GetNdaughters());
   printf(" Bounding box:\n");
   TGeoBBox::InspectShape();
}

//_____________________________________________________________________________
void TGeoShapeAssembly::SetSegsAndPols(TBuffer3D & /*buff*/) const
{
// Fill TBuffer3D structure for segments and polygons.
   Error("SetSegsAndPols", "Drawing functions should not be called for assemblies, but rather for their content");
}

//_____________________________________________________________________________
Double_t TGeoShapeAssembly::Safety(Double_t *point, Bool_t in) const
{
// computes the closest distance from given point to this shape, according
// to option. The matching point on the shape is stored in spoint.
   Double_t safety = TGeoShape::Big();
   Double_t pt[3], loc[3];
   if (in) {
      Int_t index = fVolume->GetCurrentNodeIndex();
      TGeoVolume *vol = fVolume;
      TGeoNode *node;
      memcpy(loc, point, 3*sizeof(Double_t));
      while (index>=0) {
         memcpy(pt, loc, 3*sizeof(Double_t));
         node = vol->GetNode(index);
         node->GetMatrix()->MasterToLocal(pt,loc);
         vol = node->GetVolume();
         index = vol->GetCurrentNodeIndex();
         if (index<0) {
            safety = vol->GetShape()->Safety(loc, in);
            return safety;
         }
      }
      return TGeoShape::Big();
   }
   Double_t safe;
   TGeoVoxelFinder *voxels = fVolume->GetVoxels();
   Int_t nd = fVolume->GetNdaughters();
   Double_t *boxes = 0;
   if (voxels) boxes = voxels->GetBoxes();
   TGeoNode *node;
   for (Int_t id=0; id<nd; id++) {
      if (boxes && id>0) {
         Int_t ist = 6*id;
         Double_t dxyz = 0.;
         Double_t dxyz0 = TMath::Abs(point[0]-boxes[ist+3])-boxes[ist];
         if (dxyz0 > safety) continue;
         Double_t dxyz1 = TMath::Abs(point[1]-boxes[ist+4])-boxes[ist+1];
         if (dxyz1 > safety) continue;
         Double_t dxyz2 = TMath::Abs(point[2]-boxes[ist+5])-boxes[ist+2];
         if (dxyz2 > safety) continue;
         if (dxyz0>0) dxyz+=dxyz0*dxyz0;
         if (dxyz1>0) dxyz+=dxyz1*dxyz1;
         if (dxyz2>0) dxyz+=dxyz2*dxyz2;
         if (dxyz >= safety*safety) continue;
      }
      node = fVolume->GetNode(id);
      safe = node->Safety(point, kFALSE);
      if (safe<=0.0) return 0.0;
      if (safe<safety) safety = safe;
   }
   return safety;
}

//_____________________________________________________________________________
void TGeoShapeAssembly::SavePrimitive(ostream & /*out*/, Option_t * /*option*/ /*= ""*/)
{
// Save a primitive as a C++ statement(s) on output stream "out".
}

//_____________________________________________________________________________
void TGeoShapeAssembly::SetPoints(Double_t * /*points*/) const
{
// No mesh for assemblies.
   Error("SetPoints", "Drawing functions should not be called for assemblies, but rather for their content");
}

//_____________________________________________________________________________
void TGeoShapeAssembly::SetPoints(Float_t * /*points*/) const
{
// No mesh for assemblies.
   Error("SetPoints", "Drawing functions should not be called for assemblies, but rather for their content");
}

//_____________________________________________________________________________
void TGeoShapeAssembly::GetMeshNumbers(Int_t &nvert, Int_t &nsegs, Int_t &npols) const
{
// Returns numbers of vertices, segments and polygons composing the shape mesh.
   nvert = 0;
   nsegs = 0;
   npols = 0;
}

<|endoftext|>


<commit_before>#include "Expression.hpp"
#include "gtest/gtest.h"

TEST(LMCh04Ex05, DISABLED_willAddNumbers)
{
    auto expression = lm::Expression("1.0 + 2.0");
    ASSERT_DOUBLE_EQ(3.0, expression.getResult());
}

TEST(LMCh04Ex05, DISABLED_willSubtractNumbers)
{
    auto expression = lm::Expression("3.1 - 5.3");
    ASSERT_DOUBLE_EQ(-2.2, expression.getResult());
}

TEST(LMCh04Ex05, DISABLED_willMultiplyNumbers)
{
    auto expression = lm::Expression("20.1 * -0.128");
    ASSERT_DOUBLE_EQ(-2.5728, expression.getResult());
}

TEST(LMCh04Ex05, DISABLED_willDivideNumbers)
{
    auto expression = lm::Expression("128.0 / 64.0");
    ASSERT_DOUBLE_EQ(2.0, expression.getResult());
}

TEST(LMCh04Ex05, willThrowExceptionOnUnknownOp)
{
    std::cout << "start test" << std::endl;
    auto expression = lm::Expression("12.0 ^ 14.1");
    std::cout << "before throw" << std::endl;
    ASSERT_THROW(expression.getResult(), std::runtime_error);
    std::cout << "after throw" << std::endl;
}
<commit_msg>travis test<commit_after>#include "Expression.hpp"
#include "gtest/gtest.h"

TEST(LMCh04Ex05, DISABLED_willAddNumbers)
{
    auto expression = lm::Expression("1.0 + 2.0");
    ASSERT_DOUBLE_EQ(3.0, expression.getResult());
}

TEST(LMCh04Ex05, DISABLED_willSubtractNumbers)
{
    auto expression = lm::Expression("3.1 - 5.3");
    ASSERT_DOUBLE_EQ(-2.2, expression.getResult());
}

TEST(LMCh04Ex05, DISABLED_willMultiplyNumbers)
{
    auto expression = lm::Expression("20.1 * -0.128");
    ASSERT_DOUBLE_EQ(-2.5728, expression.getResult());
}

TEST(LMCh04Ex05, DISABLED_willDivideNumbers)
{
    auto expression = lm::Expression("128.0 / 64.0");
    ASSERT_DOUBLE_EQ(2.0, expression.getResult());
}

TEST(LMCh04Ex05, willThrowExceptionOnUnknownOp)
{
    std::cout << "start test" << std::endl;
    std::string input{"12.0 ^ 14.1"};
    auto expression = lm::Expression(input);
    std::cout << "before throw" << std::endl;
    ASSERT_THROW(expression.getResult(), std::runtime_error);
    std::cout << "after throw" << std::endl;
}
<|endoftext|>


<commit_before>#ifndef utf8_iterator_hh_INCLUDED
#define utf8_iterator_hh_INCLUDED

#include "utf8.hh"

#include <iterator>

namespace Kakoune
{

namespace utf8
{

// adapter for an iterator on bytes which permits to iterate
// on unicode codepoints instead.
template<typename Iterator,
         typename InvalidPolicy = utf8::InvalidPolicy::Pass>
class iterator : public std::iterator<std::forward_iterator_tag,
                                      Codepoint, CharCount>
{
public:
    iterator(Iterator it, Iterator begin, Iterator end)
        : m_it{std::move(it)}, m_begin{std::move(begin)}, m_end{std::move(end)}
    {}

    template<typename Container>
    iterator(Iterator it, const Container& c)
        : m_it{std::move(it)}, m_begin{std::begin(c)}, m_end{std::end(c)}
    {}

    iterator& operator++()
    {
        m_it = utf8::next(m_it, m_end);
        invalidate_value();
        return *this;
    }

    iterator operator++(int)
    {
        iterator save = *this;
        ++*this;
        return save;
    }

    iterator& operator--()
    {
        m_it = utf8::previous(m_it, m_begin);
        invalidate_value();
        return *this;
    }

    iterator operator--(int)
    {
        iterator save = *this;
        --*this;
        return save;
    }

    iterator operator+(CharCount count) const
    {
        if (count < 0)
            return operator-(-count);

        iterator res = *this;
        while (count--)
            ++res;
        return res;
    }

    iterator operator-(CharCount count) const
    {
        if (count < 0)
            return operator+(-count);

        iterator res = *this;
        while (count--)
            --res;
        return res;
    }

    bool operator==(const iterator& other) { return m_it == other.m_it; }
    bool operator!=(const iterator& other) { return m_it != other.m_it; }

    bool operator< (const iterator& other) const { return m_it < other.m_it; }
    bool operator<= (const iterator& other) const { return m_it <= other.m_it; }

    bool operator> (const iterator& other) const { return m_it > other.m_it; }
    bool operator>= (const iterator& other) const { return m_it >= other.m_it; }

    bool operator==(const Iterator& other) { return m_it == other; }
    bool operator!=(const Iterator& other) { return m_it != other; }

    bool operator< (const Iterator& other) const { return m_it < other; }
    bool operator<= (const Iterator& other) const { return m_it <= other; }

    bool operator> (const Iterator& other) const { return m_it > other; }
    bool operator>= (const Iterator& other) const { return m_it >= other; }

    CharCount operator-(const iterator& other) const
    {
        return utf8::distance(other.m_it, m_it);
    }

    Codepoint operator*() const
    {
        return get_value();
    }

    const Iterator& base() const { return m_it; }
    Iterator& base() { return m_it; }

private:
    void invalidate_value() { m_value = -1; }
    Codepoint get_value() const
    {
        if (m_value == -1)
            m_value = utf8::codepoint<InvalidPolicy>(m_it, m_end);
        return m_value;
    }

    Iterator m_it;
    Iterator m_begin;
    Iterator m_end;
    mutable Codepoint m_value = -1;
};

}

}
#endif // utf8_iterator_hh_INCLUDED
<commit_msg>Fix comparison operators in utf8_iterator and tag it as bidirectional<commit_after>#ifndef utf8_iterator_hh_INCLUDED
#define utf8_iterator_hh_INCLUDED

#include "utf8.hh"

#include <iterator>

namespace Kakoune
{

namespace utf8
{

// adapter for an iterator on bytes which permits to iterate
// on unicode codepoints instead.
template<typename Iterator,
         typename InvalidPolicy = utf8::InvalidPolicy::Pass>
class iterator : public std::iterator<std::bidirectional_iterator_tag,
                                      Codepoint, CharCount>
{
public:
    iterator() = default;

    iterator(Iterator it, Iterator begin, Iterator end)
        : m_it{std::move(it)}, m_begin{std::move(begin)}, m_end{std::move(end)}
    {}

    template<typename Container>
    iterator(Iterator it, const Container& c)
        : m_it{std::move(it)}, m_begin{std::begin(c)}, m_end{std::end(c)}
    {}

    iterator& operator++()
    {
        m_it = utf8::next(m_it, m_end);
        invalidate_value();
        return *this;
    }

    iterator operator++(int)
    {
        iterator save = *this;
        ++*this;
        return save;
    }

    iterator& operator--()
    {
        m_it = utf8::previous(m_it, m_begin);
        invalidate_value();
        return *this;
    }

    iterator operator--(int)
    {
        iterator save = *this;
        --*this;
        return save;
    }

    iterator operator+(CharCount count) const
    {
        if (count < 0)
            return operator-(-count);

        iterator res = *this;
        while (count--)
            ++res;
        return res;
    }

    iterator operator-(CharCount count) const
    {
        if (count < 0)
            return operator+(-count);

        iterator res = *this;
        while (count--)
            --res;
        return res;
    }

    bool operator==(const iterator& other) const { return m_it == other.m_it; }
    bool operator!=(const iterator& other) const { return m_it != other.m_it; }

    bool operator< (const iterator& other) const { return m_it < other.m_it; }
    bool operator<= (const iterator& other) const { return m_it <= other.m_it; }

    bool operator> (const iterator& other) const { return m_it > other.m_it; }
    bool operator>= (const iterator& other) const { return m_it >= other.m_it; }

    bool operator==(const Iterator& other) { return m_it == other; }
    bool operator!=(const Iterator& other) { return m_it != other; }

    bool operator< (const Iterator& other) const { return m_it < other; }
    bool operator<= (const Iterator& other) const { return m_it <= other; }

    bool operator> (const Iterator& other) const { return m_it > other; }
    bool operator>= (const Iterator& other) const { return m_it >= other; }

    CharCount operator-(const iterator& other) const
    {
        return utf8::distance(other.m_it, m_it);
    }

    Codepoint operator*() const
    {
        return get_value();
    }

    const Iterator& base() const { return m_it; }
    Iterator& base() { return m_it; }

private:
    void invalidate_value() { m_value = -1; }
    Codepoint get_value() const
    {
        if (m_value == -1)
            m_value = utf8::codepoint<InvalidPolicy>(m_it, m_end);
        return m_value;
    }

    Iterator m_it;
    Iterator m_begin;
    Iterator m_end;
    mutable Codepoint m_value = -1;
};

}

}
#endif // utf8_iterator_hh_INCLUDED
<|endoftext|>


<commit_before>#include "Data.h"

<commit_msg>Read data from file<commit_after>#include "Data.h"
#include <fstream>
#include <vector>

using namespace std;

Data::Data()
{

}

void Data::load(const char* filename)
{
	// Vectors to hold the data
	std::vector<double> _x;
	std::vector<double> _y;

	// Open the file
	fstream fin(filename, ios::in);

	// Temporary variables
	double temp1, temp2;

	// Read until end of file
	while(fin>>temp1 && fin>>temp2)
	{
		_x.push_back(temp1);
		_y.push_back(temp2);
	}

	// Close the file
	fin.close();

	// Copy the data to the valarrays
	x = valarray<double>(&_x[0], _x.size());
	y = valarray<double>(&_y[0], _y.size());
}

<|endoftext|>


<commit_before>/*
 * ============================================================================
 *
 *       Filename:  trim.cc
 *    Description:  Trim reads using the Needleman-Wunsch trimer/merger
 *        License:  LGPL-3+
 *         Author:  Kevin Murray, spam@kdmurray.id.au
 *
 * ============================================================================
 */

#include <iostream>
#include <string>
#include <thread>

#include "qcpp.hh"
#include "qc-qualtrim.hh"
#include "qc-measure.hh"

std::mutex _cout_mutex;

void parse_and_print(qcpp::ProcessedReadStream *stream)
{
    qcpp::ReadPair rp;
    bool not_at_end = stream->parse_read_pair(rp);
    while (not_at_end) {
        std::string rp_str = rp.str();
        {
            std::lock_guard<std::mutex> lg(_cout_mutex);
            std::cout << rp_str;
        }
        not_at_end = stream->parse_read_pair(rp);
    }
}

int
main (int argc, char *argv[])
{
    qcpp::ProcessedReadStream stream;
    std::vector<std::thread> threads;
    unsigned int n_threads = std::thread::hardware_concurrency();
    n_threads = 1;

    if (argc != 2) {
        std::cerr << "USAGE: " << argv[0] << " <read_file>" << std::endl;
        return EXIT_FAILURE;
    }

    stream.open(argv[1]);
    stream.append_processor<qcpp::PerBaseQuality>("Before QC");
    stream.append_processor<qcpp::WindowedQualTrim>("Qual Trim", 20, 33, 4);
    stream.append_processor<qcpp::PerBaseQuality>("after qc");

    for (size_t i = 0; i < n_threads; i++) {
        threads.push_back(std::thread(parse_and_print, &stream));
    }
    for (size_t i = 0; i < n_threads; i++) {
        threads[i].join();
    }
    std::cerr << stream.report();
    return EXIT_SUCCESS;
}
<commit_msg>Update qualtrim demo<commit_after>/*
 * ============================================================================
 *
 *       Filename:  trim.cc
 *    Description:  Trim reads using the windowed quality trimming algorithm
 *        License:  LGPL-3+
 *         Author:  Kevin Murray, spam@kdmurray.id.au
 *
 * ============================================================================
 */

#include <iostream>
#include <string>

#include "qcpp.hh"
#include "qc-qualtrim.hh"
#include "qc-measure.hh"

#if 0
#include <thread>
std::mutex _cout_mutex;

void parse_and_print(qcpp::ProcessedReadStream *stream)
{
    qcpp::ReadPair rp;
    bool not_at_end = stream->parse_read_pair(rp);
    while (not_at_end) {
        std::string rp_str = rp.str();
        {
            std::lock_guard<std::mutex> lg(_cout_mutex);
            std::cout << rp_str;
        }
        not_at_end = stream->parse_read_pair(rp);
    }
}

int
main (int argc, char *argv[])
{
    qcpp::ProcessedReadStream stream;
    std::vector<std::thread> threads;
    unsigned int n_threads = std::thread::hardware_concurrency() - 1;

    if (argc != 2) {
        std::cerr << "USAGE: " << argv[0] << " <read_file>" << std::endl;
        return EXIT_FAILURE;
    }

    stream.open(argv[1]);
    //stream.append_processor<qcpp::PerBaseQuality>("Before QC");
    stream.append_processor<qcpp::WindowedQualTrim>("Qual Trim", 33, 20, 4);
    //stream.append_processor<qcpp::PerBaseQuality>("after qc");

    for (size_t i = 0; i < n_threads; i++) {
        threads.push_back(std::thread(parse_and_print, &stream));
    }
    for (size_t i = 0; i < n_threads; i++) {
        threads[i].join();
    }
    std::cerr << stream.report();
    return EXIT_SUCCESS;
}

#else
int
main (int argc, char *argv[])
{
    qcpp::ProcessedReadStream stream;
    qcpp::ReadPair rp;

    if (argc != 2) {
        std::cerr << "USAGE: " << argv[0] << " <read_file>" << std::endl;
        return EXIT_FAILURE;
    }

    stream.open(argv[1]);
    //stream.append_processor<qcpp::PerBaseQuality>("Before QC");
    stream.append_processor<qcpp::WindowedQualTrim>("Qual Trim", 33, 20, 4);
    //stream.append_processor<qcpp::PerBaseQuality>("after qc");

    while (stream.parse_read_pair(rp)) {
        std::cout << rp.str();
    }

    std::cerr << stream.report();
    return EXIT_SUCCESS;
}
#endif
<|endoftext|>


<commit_before>
#include <QPaintEvent>
#include <QPainter>
#include <QMenu>
#include <QPoint>
#include <limits>
#include "PGTATrackView.h"
#include "ui_PGTATrackView.h"
#include "PGTATreeView.h"
#include "PGTAPropertiesView.h"
#include "ui_PGTAPropertiesView.h"
#include "PGTATrackTreeModel.h"

PGTATrackView::PGTATrackView(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::PGTATrackView),
    m_treeView(nullptr),
    m_dataWidgetMapper(nullptr),
    m_propertiesView(nullptr)
{
    ui->setupUi(this);
    m_treeView = new PGTATreeView(this);
    m_treeView->header()->hide();
    ui->mainLayout->addWidget(m_treeView);
    SetupAddButtonMenu();
    ConnectSignals();
}

PGTATrackView::~PGTATrackView()
{
    delete m_treeView;
    delete m_dataWidgetMapper;
    delete ui;
}

void PGTATrackView::ConnectSignals()
{
    // connect singnals and slots
    connect(m_treeView, SIGNAL(customContextMenuRequested(QPoint)), this,
            SLOT(onCustomContextMenu(const QPoint &)));
    connect(ui->removeTrackItemButton, SIGNAL(clicked()), this, SLOT(slotRemoveTrackItem()));
    connect(ui->BeatsCheckBox, SIGNAL(toggled(bool)), this, SLOT(slotMeasuredInBeats(bool)));
}

void PGTATrackView::SetupAddButtonMenu()
{
    // setup tool button context menu for add sample/group button
    QMenu *menu = new QMenu();
    QAction *addGroup = menu->addAction("Add Group");
    connect(addGroup, SIGNAL(triggered()), this, SLOT(slotInsertGroup()));
    QAction *addSample = menu->addAction("Add Sample");
    connect(addSample, SIGNAL(triggered()), this, SLOT(slotInsertSample()));
    ui->addTrackItemButton->setPopupMode(QToolButton::InstantPopup);
    ui->addTrackItemButton->setMenu(menu);
}

void PGTATrackView::paintEvent(QPaintEvent *)
{
    QStyleOption opt;
    opt.init(this);
    QPainter p(this);
    style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}

void PGTATrackView::SetTreeViewModel(QAbstractItemModel *model)
{
    if (!model)
    {
        return;
    }

    m_treeView->setModel(model);
    // only show first column track tree view
    for (int i = 1; i < model->columnCount(); ++i)
    {
        m_treeView->hideColumn(i);
    }

    //HACKHACKHACK
    PGTATrackTreeModel *model1 = static_cast<PGTATrackTreeModel*>(model);
    ui->BeatsCheckBox->setChecked(model1->getIsMeasuredInBeats());
    ConnectDataWidgetMapper(model);
}

void PGTATrackView::SetPropertiesView(PGTAPropertiesView *propertiesView)
{
    m_propertiesView = propertiesView;
    if (!m_treeView)
    {
        return;
    }

    QAbstractItemModel *model = m_treeView->model();
    if (model)
    {
        ConnectDataWidgetMapper(model);
    }
}

void PGTATrackView::ConnectDataWidgetMapper(QAbstractItemModel *model)
{
    if (!m_propertiesView || !model)
    {
        return;
    }

    if (m_dataWidgetMapper)
    {
        delete m_dataWidgetMapper;
    }

    Ui::PGTAPropertiesView *propertiesUi = m_propertiesView->GetUi();
    m_dataWidgetMapper = new QDataWidgetMapper(this);
    m_dataWidgetMapper->setSubmitPolicy(QDataWidgetMapper::AutoSubmit);
    m_dataWidgetMapper->setModel(model);
    m_dataWidgetMapper->addMapping(propertiesUi->EditName, PGTATrackTreeModel::SampleColumn_Name);
    m_dataWidgetMapper->addMapping(propertiesUi->EditDefaultFile, PGTATrackTreeModel::SampleColumn_DefaultFile);
    m_dataWidgetMapper->addMapping(propertiesUi->EditStartTime, PGTATrackTreeModel::SampleColumn_StartTime);
    m_dataWidgetMapper->addMapping(propertiesUi->EditPeriod, PGTATrackTreeModel::SampleColumn_Period);
    m_dataWidgetMapper->addMapping(propertiesUi->EditDeviation, PGTATrackTreeModel::SampleColumn_PeriodDeviation);
    m_dataWidgetMapper->addMapping(propertiesUi->EditProbability, PGTATrackTreeModel::SampleColumn_Probability);
    m_dataWidgetMapper->addMapping(propertiesUi->EditGain, PGTATrackTreeModel::SampleColumn_Gain);
    connect(m_treeView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
        this, SLOT(treeViewRowColChange(QModelIndex)));
}

void PGTATrackView::treeViewRowColChange(const QModelIndex &index)
{
    if (!m_treeView)
    {
        return;
    }

    m_dataWidgetMapper->setRootIndex(index.parent());
    m_dataWidgetMapper->setCurrentModelIndex(index);
    if (static_cast<PGTATrackTreeModel*>(m_treeView->model())->isGroup(index))
    {
        m_propertiesView->SetSamplePropertiesShown(false);
    }
    else
    {
        m_propertiesView->SetSamplePropertiesShown(true);
    }
}

void PGTATrackView::onCustomContextMenu(const QPoint &point)
{
    if (!m_treeView)
    {
        return;
    }

    QModelIndex index = m_treeView->indexAt(point);
    QPoint globalPos = m_treeView->mapToGlobal(point);
    PGTATrackTreeModel *model = static_cast<PGTATrackTreeModel*>(m_treeView->model());
    QMenu myMenu;

    QAction *insertSampleAction = myMenu.addAction("Insert Sample");
    connect(insertSampleAction, SIGNAL(triggered()), this, SLOT(slotInsertSample()));

    if (index.isValid())
    {
        QString removeText = "Remove Sample";
        if (model->isGroup(index))
        {
            removeText = "Remove Group";
        }
        QAction *removeTrackItemAction = myMenu.addAction(removeText);
        connect(removeTrackItemAction, SIGNAL(triggered()), this, SLOT(slotRemoveTrackItem()));
    }
    else
    {
        QAction *insertGroupAction = myMenu.addAction("Insert Group");
        connect(insertGroupAction, SIGNAL(triggered()), this, SLOT(slotInsertGroup()));
    }
    myMenu.exec(globalPos);
}

void PGTATrackView::slotInsertGroup()
{
    if (!m_treeView)
    {
        return;
    }

    PGTATrackTreeModel *model = static_cast<PGTATrackTreeModel*>(m_treeView->model());
    QModelIndex rootIndex = m_treeView->rootIndex();
    QModelIndex index = m_treeView->selectionModel()->currentIndex();
    if (index.parent() != rootIndex)
    {
        index = rootIndex;
    }

    if (!model->insertRow(index.row()+1, index.parent()))
    {
        return;
    }
    QModelIndex child = model->index(index.row()+1, 0, index.parent());
    model->setIsGroup(child);
    for (int column = 0; column < model->columnCount(index.parent()); ++column)
    {
        child = model->index(index.row()+1, column, index.parent());
        switch (column)
        {
            case PGTATrackTreeModel::GroupColumn_Name :
                model->setData(child, QVariant("[Group Name]"), Qt::EditRole);
                break;
            case PGTATrackTreeModel::GroupColumn_UUID :
                model->setData(child, model->getUuid(child), Qt::EditRole);
                break;
            default:
                break;
        }
    }
}

void PGTATrackView::slotInsertSample()
{
    if (!m_treeView)
    {
        return;
    }

    QModelIndex selectedIndex = m_treeView->selectionModel()->currentIndex();
    PGTATrackTreeModel *model = static_cast<PGTATrackTreeModel*>(m_treeView->model());

    int position = 0;
    // set column to column 0 otherwise inserting child doesn't work
    QModelIndex index = model->index(selectedIndex.row(), 0, selectedIndex.parent());

    // check if selection is on first level
    if (!model->isGroup(index))
    {
        position = index.row() + 1; // index of current selection + 1
        index = index.parent();
    }

    if (!model->insertRow(position, index))
    {
        return;
    }

    for (int column = 0; column < model->columnCount(index); ++column)
    {
        QModelIndex child = model->index(position, column, index);
        switch (column)
        {
            case PGTATrackTreeModel::SampleColumn_Name :
                model->setData(child, QVariant("[Sample Name]"), Qt::EditRole);
                break;
            case PGTATrackTreeModel::SampleColumn_GroupUUID :
                model->setData(child, model->getUuid(index), Qt::EditRole);
                break;
            case PGTATrackTreeModel::SampleColumn_Gain :
                model->setData(child, QVariant(std::numeric_limits<int>::max()/2.0f), Qt::EditRole);
                break;
            default:
                model->setData(child, QVariant("[No data]"), Qt::EditRole);
                break;
        }

        if (!model->headerData(column, Qt::Horizontal).isValid())
        {
            model->setHeaderData(column, Qt::Horizontal, QVariant("[No header]"), Qt::EditRole);
        }
    }
    m_treeView->selectionModel()->setCurrentIndex(model->index(position, 0, index),
                                            QItemSelectionModel::ClearAndSelect);
}

void PGTATrackView::slotRemoveTrackItem()
{
    if (!m_treeView)
    {
        return;
    }

    QModelIndex index = m_treeView->selectionModel()->currentIndex();
    if (!index.isValid())
    {
        return;
    }

    PGTATrackTreeModel *model = static_cast<PGTATrackTreeModel*>(m_treeView->model());
    if(model->removeRow(index.row(), index.parent()))
    {
        m_treeView->selectionModel()->clear();
        if (m_propertiesView)
        {
            m_propertiesView->ClearProperyValues();
        }
    }
}

void PGTATrackView::slotMeasuredInBeats(bool isChecked)
{
     PGTATrackTreeModel *model = static_cast<PGTATrackTreeModel*>(m_treeView->model());
     model->setIsMeasuredInBeats(isChecked);
}

<commit_msg>Added default values for samples.<commit_after>
#include <QPaintEvent>
#include <QPainter>
#include <QMenu>
#include <QPoint>
#include <limits>
#include "PGTATrackView.h"
#include "ui_PGTATrackView.h"
#include "PGTATreeView.h"
#include "PGTAPropertiesView.h"
#include "ui_PGTAPropertiesView.h"
#include "PGTATrackTreeModel.h"

PGTATrackView::PGTATrackView(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::PGTATrackView),
    m_treeView(nullptr),
    m_dataWidgetMapper(nullptr),
    m_propertiesView(nullptr)
{
    ui->setupUi(this);
    m_treeView = new PGTATreeView(this);
    m_treeView->header()->hide();
    ui->mainLayout->addWidget(m_treeView);
    SetupAddButtonMenu();
    ConnectSignals();
}

PGTATrackView::~PGTATrackView()
{
    delete m_treeView;
    delete m_dataWidgetMapper;
    delete ui;
}

void PGTATrackView::ConnectSignals()
{
    // connect singnals and slots
    connect(m_treeView, SIGNAL(customContextMenuRequested(QPoint)), this,
            SLOT(onCustomContextMenu(const QPoint &)));
    connect(ui->removeTrackItemButton, SIGNAL(clicked()), this, SLOT(slotRemoveTrackItem()));
    connect(ui->BeatsCheckBox, SIGNAL(toggled(bool)), this, SLOT(slotMeasuredInBeats(bool)));
}

void PGTATrackView::SetupAddButtonMenu()
{
    // setup tool button context menu for add sample/group button
    QMenu *menu = new QMenu();
    QAction *addGroup = menu->addAction("Add Group");
    connect(addGroup, SIGNAL(triggered()), this, SLOT(slotInsertGroup()));
    QAction *addSample = menu->addAction("Add Sample");
    connect(addSample, SIGNAL(triggered()), this, SLOT(slotInsertSample()));
    ui->addTrackItemButton->setPopupMode(QToolButton::InstantPopup);
    ui->addTrackItemButton->setMenu(menu);
}

void PGTATrackView::paintEvent(QPaintEvent *)
{
    QStyleOption opt;
    opt.init(this);
    QPainter p(this);
    style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}

void PGTATrackView::SetTreeViewModel(QAbstractItemModel *model)
{
    if (!model)
    {
        return;
    }

    m_treeView->setModel(model);
    // only show first column track tree view
    for (int i = 1; i < model->columnCount(); ++i)
    {
        m_treeView->hideColumn(i);
    }

    //HACKHACKHACK
    PGTATrackTreeModel *model1 = static_cast<PGTATrackTreeModel*>(model);
    ui->BeatsCheckBox->setChecked(model1->getIsMeasuredInBeats());
    ConnectDataWidgetMapper(model);
}

void PGTATrackView::SetPropertiesView(PGTAPropertiesView *propertiesView)
{
    m_propertiesView = propertiesView;
    if (!m_treeView)
    {
        return;
    }

    QAbstractItemModel *model = m_treeView->model();
    if (model)
    {
        ConnectDataWidgetMapper(model);
    }
}

void PGTATrackView::ConnectDataWidgetMapper(QAbstractItemModel *model)
{
    if (!m_propertiesView || !model)
    {
        return;
    }

    if (m_dataWidgetMapper)
    {
        delete m_dataWidgetMapper;
    }

    Ui::PGTAPropertiesView *propertiesUi = m_propertiesView->GetUi();
    m_dataWidgetMapper = new QDataWidgetMapper(this);
    m_dataWidgetMapper->setSubmitPolicy(QDataWidgetMapper::AutoSubmit);
    m_dataWidgetMapper->setModel(model);
    m_dataWidgetMapper->addMapping(propertiesUi->EditName, PGTATrackTreeModel::SampleColumn_Name);
    m_dataWidgetMapper->addMapping(propertiesUi->EditDefaultFile, PGTATrackTreeModel::SampleColumn_DefaultFile);
    m_dataWidgetMapper->addMapping(propertiesUi->EditStartTime, PGTATrackTreeModel::SampleColumn_StartTime);
    m_dataWidgetMapper->addMapping(propertiesUi->EditPeriod, PGTATrackTreeModel::SampleColumn_Period);
    m_dataWidgetMapper->addMapping(propertiesUi->EditDeviation, PGTATrackTreeModel::SampleColumn_PeriodDeviation);
    m_dataWidgetMapper->addMapping(propertiesUi->EditProbability, PGTATrackTreeModel::SampleColumn_Probability);
    m_dataWidgetMapper->addMapping(propertiesUi->EditGain, PGTATrackTreeModel::SampleColumn_Gain);
    connect(m_treeView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
        this, SLOT(treeViewRowColChange(QModelIndex)));
}

void PGTATrackView::treeViewRowColChange(const QModelIndex &index)
{
    if (!m_treeView)
    {
        return;
    }

    m_dataWidgetMapper->setRootIndex(index.parent());
    m_dataWidgetMapper->setCurrentModelIndex(index);
    if (static_cast<PGTATrackTreeModel*>(m_treeView->model())->isGroup(index))
    {
        m_propertiesView->SetSamplePropertiesShown(false);
    }
    else
    {
        m_propertiesView->SetSamplePropertiesShown(true);
    }
}

void PGTATrackView::onCustomContextMenu(const QPoint &point)
{
    if (!m_treeView)
    {
        return;
    }

    QModelIndex index = m_treeView->indexAt(point);
    QPoint globalPos = m_treeView->mapToGlobal(point);
    PGTATrackTreeModel *model = static_cast<PGTATrackTreeModel*>(m_treeView->model());
    QMenu myMenu;

    QAction *insertSampleAction = myMenu.addAction("Insert Sample");
    connect(insertSampleAction, SIGNAL(triggered()), this, SLOT(slotInsertSample()));

    if (index.isValid())
    {
        QString removeText = "Remove Sample";
        if (model->isGroup(index))
        {
            removeText = "Remove Group";
        }
        QAction *removeTrackItemAction = myMenu.addAction(removeText);
        connect(removeTrackItemAction, SIGNAL(triggered()), this, SLOT(slotRemoveTrackItem()));
    }
    else
    {
        QAction *insertGroupAction = myMenu.addAction("Insert Group");
        connect(insertGroupAction, SIGNAL(triggered()), this, SLOT(slotInsertGroup()));
    }
    myMenu.exec(globalPos);
}

void PGTATrackView::slotInsertGroup()
{
    if (!m_treeView)
    {
        return;
    }

    PGTATrackTreeModel *model = static_cast<PGTATrackTreeModel*>(m_treeView->model());
    QModelIndex rootIndex = m_treeView->rootIndex();
    QModelIndex index = m_treeView->selectionModel()->currentIndex();
    if (index.parent() != rootIndex)
    {
        index = rootIndex;
    }

    if (!model->insertRow(index.row()+1, index.parent()))
    {
        return;
    }
    QModelIndex child = model->index(index.row()+1, 0, index.parent());
    model->setIsGroup(child);
    for (int column = 0; column < model->columnCount(index.parent()); ++column)
    {
        child = model->index(index.row()+1, column, index.parent());
        switch (column)
        {
            case PGTATrackTreeModel::GroupColumn_Name :
                model->setData(child, QVariant("[Group Name]"), Qt::EditRole);
                break;
            case PGTATrackTreeModel::GroupColumn_UUID :
                model->setData(child, model->getUuid(child), Qt::EditRole);
                break;
            default:
                break;
        }
    }
}

void PGTATrackView::slotInsertSample()
{
    if (!m_treeView)
    {
        return;
    }

    QModelIndex selectedIndex = m_treeView->selectionModel()->currentIndex();
    PGTATrackTreeModel *model = static_cast<PGTATrackTreeModel*>(m_treeView->model());

    int position = 0;
    // set column to column 0 otherwise inserting child doesn't work
    QModelIndex index = model->index(selectedIndex.row(), 0, selectedIndex.parent());

    // check if selection is on first level
    if (!model->isGroup(index))
    {
        position = index.row() + 1; // index of current selection + 1
        index = index.parent();
    }

    if (!model->insertRow(position, index))
    {
        return;
    }

    for (int column = 0; column < model->columnCount(index); ++column)
    {
        QModelIndex child = model->index(position, column, index);
        switch (column)
        {
            case PGTATrackTreeModel::SampleColumn_Name:
                model->setData(child, QVariant("[Sample Name]"), Qt::EditRole);
                break;
            case PGTATrackTreeModel::SampleColumn_DefaultFile:
                model->setData(child, QVariant(), Qt::EditRole);
                break;
            case PGTATrackTreeModel::SampleColumn_StartTime:
                model->setData(child, QVariant(0), Qt::EditRole);
                break;
            case PGTATrackTreeModel::SampleColumn_Period:
                model->setData(child, QVariant(0), Qt::EditRole);
                break;
            case PGTATrackTreeModel::SampleColumn_PeriodDeviation:
                model->setData(child, QVariant(0), Qt::EditRole);
                break;
            case PGTATrackTreeModel::SampleColumn_Probability:
                model->setData(child, QVariant(1), Qt::EditRole);
                break;
            case PGTATrackTreeModel::SampleColumn_GroupUUID :
                model->setData(child, model->getUuid(index), Qt::EditRole);
                break;
            case PGTATrackTreeModel::SampleColumn_Gain :
                model->setData(child, QVariant(std::numeric_limits<int>::max()/2.0f), Qt::EditRole);
                break;
            default:
                break;
        }

        if (!model->headerData(column, Qt::Horizontal).isValid())
        {
            model->setHeaderData(column, Qt::Horizontal, QVariant("[No header]"), Qt::EditRole);
        }
    }
    m_treeView->selectionModel()->setCurrentIndex(model->index(position, 0, index),
                                            QItemSelectionModel::ClearAndSelect);
}

void PGTATrackView::slotRemoveTrackItem()
{
    if (!m_treeView)
    {
        return;
    }

    QModelIndex index = m_treeView->selectionModel()->currentIndex();
    if (!index.isValid())
    {
        return;
    }

    PGTATrackTreeModel *model = static_cast<PGTATrackTreeModel*>(m_treeView->model());
    if(model->removeRow(index.row(), index.parent()))
    {
        m_treeView->selectionModel()->clear();
        if (m_propertiesView)
        {
            m_propertiesView->ClearProperyValues();
        }
    }
}

void PGTATrackView::slotMeasuredInBeats(bool isChecked)
{
     PGTATrackTreeModel *model = static_cast<PGTATrackTreeModel*>(m_treeView->model());
     model->setIsMeasuredInBeats(isChecked);
}

<|endoftext|>