<commit_before>//
//  parser_tables.cpp
//  Parse
//
//  Created by Andrew Hunter on 07/05/2011.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#include <algorithm>

#include "parser_tables.h"

using namespace std;
using namespace contextfree;
using namespace lr;

/// \brief Ranks actions in the order they should appear in the final table
static inline int action_score(int action) {
    switch (action) {
        case lr_action::act_guard:
            // Guard actions are always evaluated first, so we can substitute the guard symbol if it's matched
            return 0;

        case lr_action::act_weakreduce:
            // Weak reduce actions come first as they should always be performed if their symbol will produce a shift
            return 1;

        case lr_action::act_shift:
        case lr_action::act_divert:
            // Shift actions are preferred if there's a conflict
            return 2;

        case lr_action::act_reduce:
            // Reduce actions have the lowest priority
            return 3;

        case lr_action::act_goto:
            // Gotos never actually produce a clash
            return 4;

        default:
            return 5;
    }
}

static inline bool compare_actions(const parser_tables::action& a, const parser_tables::action& b) {
    // First, compare on symbol IDs
    if (a.m_SymbolId < b.m_SymbolId) return true;

    // Next, compare on action types
    if (action_score(a.m_Type) < action_score(b.m_Type)) return true;

    // Actions are equal
    return false;
}

/// \brief Creates a parser from the result of the specified builder class
parser_tables::parser_tables(const lalr_builder& builder) {
    // Allocate the tables
    m_NumStates             = builder.count_states();
    m_NonterminalActions    = new action*[m_NumStates];
    m_TerminalActions       = new action*[m_NumStates];
    m_Counts                = new action_count[m_NumStates];

    contextfree::end_of_input eoi;
    m_EndOfInput            = builder.gram().identifier_for_item(eoi);

    const grammar& gram = builder.gram();

    map<int, int> ruleIds;                          // Maps their rule IDs to our rule IDs

    // Build up the tables for each state
    for (int stateId = 0; stateId < m_NumStates; stateId++) {
        // Get the actions for this state
        const lr_action_set& actions = builder.actions_for_state(stateId);

        // Count the number of terminal and nonterminal actions
        int termCount       = 0;
        int nontermCount    = 0;

        for (lr_action_set::const_iterator nextAction = actions.begin(); nextAction != actions.end(); nextAction++) {
            if ((*nextAction)->item()->type() == item::terminal) {
                termCount++;
            } else {
                nontermCount++;
            }
        }

        // Allocate action tables of the appropriate size
        action* termActions     = new action[termCount];
        action* nontermActions  = new action[nontermCount];

        int     termPos         = 0;                    // Current item in the terminal table
        int     nontermPos      = 0;                    // Current item in the nonterminal table

        // Fill up the actions (not in order)
        for (lr_action_set::const_iterator nextAction = actions.begin(); nextAction != actions.end(); nextAction++) {
            // Get the next state
            int nextState   = (*nextAction)->next_state();
            int type        = (*nextAction)->type();

            // If the next action is a reduce action, then the next state should actually be the rule to reduce
            if (type == lr_action::act_reduce || type == lr_action::act_weakreduce || type == lr_action::act_accept) {
                // Look up the ID we assigned this rule
                int                     ruleId  = (*nextAction)->rule()->identifier(gram);
                map<int, int>::iterator found   = ruleIds.find(ruleId);

                if (found == ruleIds.end()) {
                    nextState       = (int)ruleIds.size();
                    ruleIds[ruleId] = nextState;
                } else {
                    nextState       = found->second;
                }
            }

            if ((*nextAction)->item()->type() == item::terminal) {
                // Add a new terminal action
                termActions[termPos].m_Type             = type;
                termActions[termPos].m_NextState        = nextState;
                termActions[termPos].m_SymbolId         = (*nextAction)->item()->symbol();

                termPos++;
            } else {
                // Add a new nonterminal action
                nontermActions[nontermPos].m_Type       = type;
                nontermActions[nontermPos].m_NextState  = nextState;
                nontermActions[nontermPos].m_SymbolId   = gram.identifier_for_item((*nextAction)->item());

                nontermPos++;
            }
        }

        // Sort the actions for this state
        std::sort(termActions, termActions + termCount, compare_actions);
        std::sort(nontermActions, nontermActions + nontermCount, compare_actions);

        // Store the actions in the table
        m_TerminalActions[stateId]      = termActions;
        m_NonterminalActions[stateId]   = nontermActions;
        m_Counts[stateId].m_NumTerms    = termCount;
        m_Counts[stateId].m_NumNonterms = nontermCount;
    }

    // Fill in the rule table
    m_NumRules  = (int)ruleIds.size();
    m_Rules     = new reduce_rule[ruleIds.size()];

    for (map<int, int>::iterator ruleId = ruleIds.begin(); ruleId != ruleIds.end(); ruleId++) {
        const rule_container& rule = gram.rule_with_identifier(ruleId->first);

        m_Rules[ruleId->second].m_Identifier    = gram.identifier_for_item(rule->nonterminal());
        m_Rules[ruleId->second].m_Length        = (int)rule->items().size();
    }
}

/// \brief Copy constructor
parser_tables::parser_tables(const parser_tables& copyFrom)
: m_NumStates(copyFrom.m_NumStates)
, m_NumRules(copyFrom.m_NumRules)
, m_EndOfInput(copyFrom.m_EndOfInput) {
    // Allocate the action tables
    m_TerminalActions       = new action*[m_NumStates];
    m_NonterminalActions    = new action*[m_NumStates];
    m_Counts                = new action_count[m_NumStates];

    // Copy the states
    for (int stateId=0; stateId<m_NumStates; stateId++) {
        // Copy the counts
        m_Counts[stateId] = copyFrom.m_Counts[stateId];

        // Allocate the array for this state
        m_TerminalActions[stateId]      = new action[m_Counts[stateId].m_NumTerms];
        m_NonterminalActions[stateId]   = new action[m_Counts[stateId].m_NumNonterms];

        // Copy the terminals and nonterminals
        for (int x=0; x<m_Counts[stateId].m_NumTerms; x++) {
            m_TerminalActions[stateId][x] = copyFrom.m_TerminalActions[stateId][x];
        }
        for (int x=0; x<m_Counts[stateId].m_NumNonterms; x++) {
            m_NonterminalActions[stateId][x] = copyFrom.m_NonterminalActions[stateId][x];
        }
    }

    // Allocate the rule table
    m_Rules = new reduce_rule[m_NumRules];
    for (int ruleId=0; ruleId<m_NumRules; ruleId++) {
        m_Rules[ruleId] = copyFrom.m_Rules[ruleId];
    }
}

/// \brief Assignment
parser_tables& parser_tables::operator=(const parser_tables& copyFrom) {
    if (&copyFrom == this) return *this;

    // TODO

    return *this;
}

/// \brief Destructor
parser_tables::~parser_tables() {
    // Destroy each entry in the parser table
    for (int x=0; x<m_NumStates; x++) {
        delete[] m_NonterminalActions[x];
        delete[] m_TerminalActions[x];
    }

    // Destroy the tables themselves
    delete[] m_NonterminalActions;
    delete[] m_TerminalActions;
    delete[] m_Rules;
    delete[] m_Counts;
}
<commit_msg>Fixed very stupid bug with the way comparisons were done (if we want to compare < for something with multiple components, we need to make sure they're actually not equal before comparing the next item)<commit_after>//
//  parser_tables.cpp
//  Parse
//
//  Created by Andrew Hunter on 07/05/2011.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#include <algorithm>

#include "parser_tables.h"

using namespace std;
using namespace contextfree;
using namespace lr;

/// \brief Ranks actions in the order they should appear in the final table
static inline int action_score(int action) {
    switch (action) {
        case lr_action::act_guard:
            // Guard actions are always evaluated first, so we can substitute the guard symbol if it's matched
            return 0;

        case lr_action::act_weakreduce:
            // Weak reduce actions come first as they should always be performed if their symbol will produce a shift
            return 1;

        case lr_action::act_shift:
        case lr_action::act_divert:
            // Shift actions are preferred if there's a conflict
            return 2;

        case lr_action::act_reduce:
            // Reduce actions have the lowest priority
            return 3;

        case lr_action::act_goto:
            // Gotos never actually produce a clash
            return 4;

        default:
            return 5;
    }
}

static inline bool compare_actions(const parser_tables::action& a, const parser_tables::action& b) {
    // First, compare on symbol IDs
    if (a.m_SymbolId < b.m_SymbolId) return true;
    if (a.m_SymbolId > b.m_SymbolId) return false;

    // Next, compare on action types
    int aScore = action_score(a.m_Type);
    int bScore = action_score(b.m_Type);

    if (aScore < bScore) return true;
    if (aScore > bScore) return false;

    // Actions are equal
    return false;
}

/// \brief Creates a parser from the result of the specified builder class
parser_tables::parser_tables(const lalr_builder& builder) {
    // Allocate the tables
    m_NumStates             = builder.count_states();
    m_NonterminalActions    = new action*[m_NumStates];
    m_TerminalActions       = new action*[m_NumStates];
    m_Counts                = new action_count[m_NumStates];

    contextfree::end_of_input eoi;
    m_EndOfInput            = builder.gram().identifier_for_item(eoi);

    const grammar& gram = builder.gram();

    map<int, int> ruleIds;                          // Maps their rule IDs to our rule IDs

    // Build up the tables for each state
    for (int stateId = 0; stateId < m_NumStates; stateId++) {
        // Get the actions for this state
        const lr_action_set& actions = builder.actions_for_state(stateId);

        // Count the number of terminal and nonterminal actions
        int termCount       = 0;
        int nontermCount    = 0;

        for (lr_action_set::const_iterator nextAction = actions.begin(); nextAction != actions.end(); nextAction++) {
            if ((*nextAction)->item()->type() == item::terminal) {
                termCount++;
            } else {
                nontermCount++;
            }
        }

        // Allocate action tables of the appropriate size
        action* termActions     = new action[termCount];
        action* nontermActions  = new action[nontermCount];

        int     termPos         = 0;                    // Current item in the terminal table
        int     nontermPos      = 0;                    // Current item in the nonterminal table

        // Fill up the actions (not in order)
        for (lr_action_set::const_iterator nextAction = actions.begin(); nextAction != actions.end(); nextAction++) {
            // Get the next state
            int nextState   = (*nextAction)->next_state();
            int type        = (*nextAction)->type();

            // If the next action is a reduce action, then the next state should actually be the rule to reduce
            if (type == lr_action::act_reduce || type == lr_action::act_weakreduce || type == lr_action::act_accept) {
                // Look up the ID we assigned this rule
                int                     ruleId  = (*nextAction)->rule()->identifier(gram);
                map<int, int>::iterator found   = ruleIds.find(ruleId);

                if (found == ruleIds.end()) {
                    nextState       = (int)ruleIds.size();
                    ruleIds[ruleId] = nextState;
                } else {
                    nextState       = found->second;
                }
            }

            if ((*nextAction)->item()->type() == item::terminal) {
                // Add a new terminal action
                termActions[termPos].m_Type             = type;
                termActions[termPos].m_NextState        = nextState;
                termActions[termPos].m_SymbolId         = (*nextAction)->item()->symbol();

                termPos++;
            } else {
                // Add a new nonterminal action
                nontermActions[nontermPos].m_Type       = type;
                nontermActions[nontermPos].m_NextState  = nextState;
                nontermActions[nontermPos].m_SymbolId   = gram.identifier_for_item((*nextAction)->item());

                nontermPos++;
            }
        }

        // Sort the actions for this state
        std::sort(termActions, termActions + termCount, compare_actions);
        std::sort(nontermActions, nontermActions + nontermCount, compare_actions);

        // Store the actions in the table
        m_TerminalActions[stateId]      = termActions;
        m_NonterminalActions[stateId]   = nontermActions;
        m_Counts[stateId].m_NumTerms    = termCount;
        m_Counts[stateId].m_NumNonterms = nontermCount;
    }

    // Fill in the rule table
    m_NumRules  = (int)ruleIds.size();
    m_Rules     = new reduce_rule[ruleIds.size()];

    for (map<int, int>::iterator ruleId = ruleIds.begin(); ruleId != ruleIds.end(); ruleId++) {
        const rule_container& rule = gram.rule_with_identifier(ruleId->first);

        m_Rules[ruleId->second].m_Identifier    = gram.identifier_for_item(rule->nonterminal());
        m_Rules[ruleId->second].m_Length        = (int)rule->items().size();
    }
}

/// \brief Copy constructor
parser_tables::parser_tables(const parser_tables& copyFrom)
: m_NumStates(copyFrom.m_NumStates)
, m_NumRules(copyFrom.m_NumRules)
, m_EndOfInput(copyFrom.m_EndOfInput) {
    // Allocate the action tables
    m_TerminalActions       = new action*[m_NumStates];
    m_NonterminalActions    = new action*[m_NumStates];
    m_Counts                = new action_count[m_NumStates];

    // Copy the states
    for (int stateId=0; stateId<m_NumStates; stateId++) {
        // Copy the counts
        m_Counts[stateId] = copyFrom.m_Counts[stateId];

        // Allocate the array for this state
        m_TerminalActions[stateId]      = new action[m_Counts[stateId].m_NumTerms];
        m_NonterminalActions[stateId]   = new action[m_Counts[stateId].m_NumNonterms];

        // Copy the terminals and nonterminals
        for (int x=0; x<m_Counts[stateId].m_NumTerms; x++) {
            m_TerminalActions[stateId][x] = copyFrom.m_TerminalActions[stateId][x];
        }
        for (int x=0; x<m_Counts[stateId].m_NumNonterms; x++) {
            m_NonterminalActions[stateId][x] = copyFrom.m_NonterminalActions[stateId][x];
        }
    }

    // Allocate the rule table
    m_Rules = new reduce_rule[m_NumRules];
    for (int ruleId=0; ruleId<m_NumRules; ruleId++) {
        m_Rules[ruleId] = copyFrom.m_Rules[ruleId];
    }
}

/// \brief Assignment
parser_tables& parser_tables::operator=(const parser_tables& copyFrom) {
    if (&copyFrom == this) return *this;

    // TODO

    return *this;
}

/// \brief Destructor
parser_tables::~parser_tables() {
    // Destroy each entry in the parser table
    for (int x=0; x<m_NumStates; x++) {
        delete[] m_NonterminalActions[x];
        delete[] m_TerminalActions[x];
    }

    // Destroy the tables themselves
    delete[] m_NonterminalActions;
    delete[] m_TerminalActions;
    delete[] m_Rules;
    delete[] m_Counts;
}
<|endoftext|>


<commit_before>#ifndef LIB_PROPERTIES_HPP
#define LIB_PROPERTIES_HPP

#include "types.hpp"

namespace lib
{
	template <typename T,class ACCESSOR>
	class Property
	{
	public:
		const T &get() const { return m_value; }
	private:
		Property() : m_value{} {}
		Property(Property&&r) : m_value{ std::move(p); } {}
		explicit Property(const T&iv) :m_value{ iv } {}
		explicit Property(const T&&iv) :m_value{ std::move(iv); } {}
		explicit Property(const Property &p) : m_value{ p } {}
		T m_value;
		void set(const T&nv) { m_value = nv; }
		Property &operator=(const T&nv) { m_value = nv; return *this; }
		Property &operator=(T&&nv) { m_value = nv; return *this; }

		friend ACCESSOR;
	};

	template <typename T, class ACCESSOR> using PropertySptr = Property<sptr<T>,ACCESSOR>;
}
#endif
<commit_msg>wip properties<commit_after>#ifndef LIB_PROPERTIES_HPP
#define LIB_PROPERTIES_HPP

#include "types.hpp"

namespace lib
{
	template <typename T>
	class Property
	{
	public:
		Property() : m_value{} {}
		Property(Property&&r) : m_value{ std::move(p); } {}
		explicit Property(const T&iv) :m_value{ iv } {}
		explicit Property(const T&&iv) :m_value{ std::move(iv); } {}
		explicit Property(const Property &p) : m_value{ p } {}
		T m_value;
		Property &operator=(const T&nv) { m_value = nv; return *this; }
		Property &operator=(T&&nv) { m_value = nv; return *this; }
	};
}
#endif
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: ViewElementListProvider.cxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 00:20:24 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#include "ViewElementListProvider.hxx"
#include "DrawModelWrapper.hxx"
#include "chartview/NumberFormatterWrapper.hxx"
#include "chartview/DataPointSymbolSupplier.hxx"
#include "macros.hxx"

/*
#ifndef _SVDMODEL_HXX
#include <svx/svdmodel.hxx>
#endif
*/

//------------
//oldChartModelWrapper
/*
// header for class SfxPrinter
#ifndef _SFX_PRINTER_HXX
#include <sfx2/printer.hxx>
#endif
*/
// header for class FontList
#ifndef _CTRLTOOL_HXX
#include <svtools/ctrltool.hxx>
#endif
// header for class Application
#ifndef _SV_SVAPP_HXX
#include <vcl/svapp.hxx>
#endif
//------------
// header for class SvxShape
#ifndef _SVX_UNOSHAPE_HXX
#include <svx/unoshape.hxx>
#endif
// header for class SdrObject
#ifndef _SVDOBJ_HXX
#include <svx/svdobj.hxx>
#endif

//---------------
//for creation of a symbol Graphic
// header for class VirtualDevice
#ifndef _SV_VIRDEV_HXX
#include <vcl/virdev.hxx>
#endif
// header for class SdrView
#ifndef _SVDVIEW_HXX
#include <svx/svdview.hxx>
#endif
//---------------

/*
//for creation of own number formatter
#ifndef _COMPHELPER_PROCESSFACTORY_HXX_
#include <comphelper/processfactory.hxx>
#endif
*/

#ifndef _COM_SUN_STAR_DRAWING_XDRAWPAGESSUPPLIER_HPP_
#include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XUNOTUNNEL_HPP_
#include <com/sun/star/lang/XUnoTunnel.hpp>
#endif

//.............................................................................
namespace chart
{
//.............................................................................
using namespace ::com::sun::star;
//using namespace ::com::sun::star::chart2;

ViewElementListProvider::ViewElementListProvider( DrawModelWrapper* pDrawModelWrapper
                                                 , NumberFormatterWrapper* pNumberFormatterWrapper )
                        : m_pDrawModelWrapper( pDrawModelWrapper )
                        , m_pFontList(NULL)
                        , m_pNumberFormatterWrapper(pNumberFormatterWrapper)
{
    DBG_ASSERT(m_pDrawModelWrapper,"A DrawModelWrapper is missing - maybe not all services can be provided");
    DBG_ASSERT(m_pNumberFormatterWrapper,"A Numberformatter is missing - maybe not all services can be provided");
}

ViewElementListProvider::~ViewElementListProvider()
{
    if(m_pFontList)
        delete m_pFontList;
}

XColorTable*   ViewElementListProvider::GetColorTable() const
{
    if(m_pDrawModelWrapper)
        return m_pDrawModelWrapper->GetColorTable();
    return NULL;
}
XDashList*     ViewElementListProvider::GetDashList() const
{
    if(m_pDrawModelWrapper)
        return m_pDrawModelWrapper->GetDashList();
    return NULL;
}
XLineEndList*  ViewElementListProvider::GetLineEndList() const
{
    if(m_pDrawModelWrapper)
        return m_pDrawModelWrapper->GetLineEndList();
    return NULL;
}
XGradientList* ViewElementListProvider::GetGradientList() const
{
    if(m_pDrawModelWrapper)
        return m_pDrawModelWrapper->GetGradientList();
    return NULL;
}
XHatchList*    ViewElementListProvider::GetHatchList() const
{
    if(m_pDrawModelWrapper)
        return m_pDrawModelWrapper->GetHatchList();
    return NULL;
}
XBitmapList*   ViewElementListProvider::GetBitmapList() const
{
    if(m_pDrawModelWrapper)
        return m_pDrawModelWrapper->GetBitmapList();
    return NULL;
}

//create chartspecific symbols for linecharts
SdrObjList* ViewElementListProvider::GetSymbolList() const
{
    static SdrObjList* m_pSymbolList = NULL;
    static uno::Reference< drawing::XShapes > m_xSymbols(NULL);//@todo this keeps the first drawinglayer alive ...
    try
    {
        if(!m_pSymbolList || !m_pSymbolList->GetObjCount())
        {
            //@todo use mutex

            //get factory from draw model
            uno::Reference< drawing::XDrawPagesSupplier > xDrawPagesSuplier( m_pDrawModelWrapper->getUnoModel(), uno::UNO_QUERY );
            uno::Reference< lang::XMultiServiceFactory > xShapeFactory( xDrawPagesSuplier, uno::UNO_QUERY );

            //create hidden draw page (target):
            uno::Reference< drawing::XDrawPages > xDrawPages( xDrawPagesSuplier->getDrawPages () );
            uno::Reference< drawing::XDrawPage >  xDrawPage( xDrawPages->insertNewByIndex ( 1 ) );
            uno::Reference<drawing::XShapes>      xTarget( xDrawPage, uno::UNO_QUERY );

            //create symbols via uno and convert to native sdr objects
            drawing::Direction3D aSymbolSize(1000,1000,1000);//this size is somehow arbitrary - nneds only to be big thus the dialog restricts the symbols to its own maximum value
            m_xSymbols =  DataPointSymbolSupplier::create2DSymbolList( xShapeFactory, xTarget, aSymbolSize );
            uno::Reference< lang::XUnoTunnel > xUnoTunnel( m_xSymbols, uno::UNO_QUERY );
            uno::Reference< lang::XTypeProvider > xTypeProvider( m_xSymbols, uno::UNO_QUERY );
            if(xUnoTunnel.is()&&xTypeProvider.is())
            {
                SvxShape* pSvxShape = reinterpret_cast<SvxShape*>(xUnoTunnel->getSomething( SvxShape::getUnoTunnelId() ));
                if(pSvxShape)
                {
                    SdrObject* pSdrObject = pSvxShape->GetSdrObject();
                    if(pSdrObject)
                        m_pSymbolList = pSdrObject->GetSubList();
                }
            }
        }
    }
    catch( uno::Exception& e )
    {
        ASSERT_EXCEPTION( e );
    }
    return m_pSymbolList;
}

Graphic ViewElementListProvider::GetSymbolGraphic( sal_Int32 nStandardSymbol, const SfxItemSet* pSymbolShapeProperties ) const
{
    SdrObjList* pSymbolList = this->GetSymbolList();
    if( !pSymbolList->GetObjCount() )
        return Graphic();
    if(nStandardSymbol<0)
        nStandardSymbol*=-1;
    if( nStandardSymbol >= static_cast<sal_Int32>(pSymbolList->GetObjCount()) )
        nStandardSymbol %= pSymbolList->GetObjCount();
    SdrObject* pObj = pSymbolList->GetObj(nStandardSymbol);

    VirtualDevice aVDev;
    aVDev.SetMapMode(MapMode(MAP_100TH_MM));
    SdrModel* pModel = new SdrModel();
    pModel->GetItemPool().FreezeIdRanges();
    SdrPage* pPage = new SdrPage( *pModel, FALSE );
    pPage->SetSize(Size(1000,1000));
    pModel->InsertPage( pPage, 0 );
    SdrView* pView = new SdrView( pModel, &aVDev );
    pView->SetMarkHdlHidden( TRUE );
    SdrPageView* pPageView = pView->ShowPage(pPage, Point());

    pObj=pObj->Clone();
    pPage->NbcInsertObject(pObj);
    pView->MarkObj(pObj,pPageView);
    if( pSymbolShapeProperties )
        pObj->SetMergedItemSet(*pSymbolShapeProperties);

    GDIMetaFile aMeta(pView->GetAllMarkedMetaFile());

    Graphic aGraph(aMeta);
    Size aSize = pObj->GetSnapRect().GetSize();
    aGraph.SetPrefSize(aSize);
    aGraph.SetPrefMapMode(MAP_100TH_MM);

    pView->UnmarkAll();
    pObj=pPage->RemoveObject(0);
    if(pObj)
        delete pObj;
    delete pView;
    delete pModel;

    return aGraph;
}

FontList* ViewElementListProvider::getFontList() const
{
    //was old chart:
    //SvxFontListItem* SfxObjectShell::.GetItem(SID_ATTR_CHAR_FONTLIST)

    if(!m_pFontList)
    {
        OutputDevice* pPrinter    = NULL;//getPrinter();
        OutputDevice* pDefaultOut = Application::GetDefaultDevice();    // #67730#
        m_pFontList = new FontList( pPrinter ? pPrinter    : pDefaultOut
                                , pPrinter ? pDefaultOut : NULL
                                , FALSE );
    }
    return m_pFontList;
}

/*
SfxPrinter* ObjectPropertiesDialogParameter::getPrinter()
{
    //was old chart:
    //SfxPrinter* SchChartDocShell::GetPrinter()

    // OLE-Objekt: kein Printer anlegen ??? see old chart: :UpdateTablePointers
    //@todo get printer from calc or other container
    //return NULL;

    SfxPrinter* pPrinter = NULL;
    bool bOwnPrinter = true;
    if (!pPrinter)
    {
        SfxBoolItem aItem(SID_PRINTER_NOTFOUND_WARN, TRUE);
        // ItemSet mit speziellem Poolbereich anlegen
        SfxItemSet* pSet = new SfxItemSet(GetPool(),
                                          SID_PRINTER_NOTFOUND_WARN,
                                          SID_PRINTER_NOTFOUND_WARN, 0);
        pSet->Put(aItem);
        pPrinter = new SfxPrinter(pSet); //@todo ->need to remember and delete
        bOwnPrinter = TRUE;

        MapMode aMapMode = pPrinter->GetMapMode();
        aMapMode.SetMapUnit(MAP_100TH_MM);
        pPrinter->SetMapMode(aMapMode);

        if (pChDoc)
        {
            if (pPrinter != pChDoc->GetRefDevice())
                pChDoc->SetRefDevice(pPrinter);

            if (pPrinter != pChDoc->GetOutliner()->GetRefDevice())
                pChDoc->GetOutliner()->SetRefDevice(pPrinter);
        }
    }
    return pPrinter;
}
*/

SvNumberFormatter* ViewElementListProvider::GetOwnNumberFormatter() const
{
    if( m_pNumberFormatterWrapper )
        return m_pNumberFormatterWrapper->getSvNumberFormatter();
    return NULL;
    /*
        static SvNumberFormatter aNumberFormatter = SvNumberFormatter(
                ::comphelper::getProcessServiceFactory(),
                LANGUAGE_SYSTEM );
        return &aNumberFormatter;
    */
}
SvNumberFormatter* ViewElementListProvider::GetNumFormatter() const
{
    //@todo
    return GetOwnNumberFormatter();
}

//.............................................................................
} //namespace chart
//.............................................................................
<commit_msg>INTEGRATION: CWS pchfix02 (1.7.78); FILE MERGED 2006/09/01 17:18:36 kaib 1.7.78.1: #i68856# Added header markers and pch files<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: ViewElementListProvider.cxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 13:01:03 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_chart2.hxx"
#include "ViewElementListProvider.hxx"
#include "DrawModelWrapper.hxx"
#include "chartview/NumberFormatterWrapper.hxx"
#include "chartview/DataPointSymbolSupplier.hxx"
#include "macros.hxx"

/*
#ifndef _SVDMODEL_HXX
#include <svx/svdmodel.hxx>
#endif
*/

//------------
//oldChartModelWrapper
/*
// header for class SfxPrinter
#ifndef _SFX_PRINTER_HXX
#include <sfx2/printer.hxx>
#endif
*/
// header for class FontList
#ifndef _CTRLTOOL_HXX
#include <svtools/ctrltool.hxx>
#endif
// header for class Application
#ifndef _SV_SVAPP_HXX
#include <vcl/svapp.hxx>
#endif
//------------
// header for class SvxShape
#ifndef _SVX_UNOSHAPE_HXX
#include <svx/unoshape.hxx>
#endif
// header for class SdrObject
#ifndef _SVDOBJ_HXX
#include <svx/svdobj.hxx>
#endif

//---------------
//for creation of a symbol Graphic
// header for class VirtualDevice
#ifndef _SV_VIRDEV_HXX
#include <vcl/virdev.hxx>
#endif
// header for class SdrView
#ifndef _SVDVIEW_HXX
#include <svx/svdview.hxx>
#endif
//---------------

/*
//for creation of own number formatter
#ifndef _COMPHELPER_PROCESSFACTORY_HXX_
#include <comphelper/processfactory.hxx>
#endif
*/

#ifndef _COM_SUN_STAR_DRAWING_XDRAWPAGESSUPPLIER_HPP_
#include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XUNOTUNNEL_HPP_
#include <com/sun/star/lang/XUnoTunnel.hpp>
#endif

//.............................................................................
namespace chart
{
//.............................................................................
using namespace ::com::sun::star;
//using namespace ::com::sun::star::chart2;

ViewElementListProvider::ViewElementListProvider( DrawModelWrapper* pDrawModelWrapper
                                                 , NumberFormatterWrapper* pNumberFormatterWrapper )
                        : m_pDrawModelWrapper( pDrawModelWrapper )
                        , m_pFontList(NULL)
                        , m_pNumberFormatterWrapper(pNumberFormatterWrapper)
{
    DBG_ASSERT(m_pDrawModelWrapper,"A DrawModelWrapper is missing - maybe not all services can be provided");
    DBG_ASSERT(m_pNumberFormatterWrapper,"A Numberformatter is missing - maybe not all services can be provided");
}

ViewElementListProvider::~ViewElementListProvider()
{
    if(m_pFontList)
        delete m_pFontList;
}

XColorTable*   ViewElementListProvider::GetColorTable() const
{
    if(m_pDrawModelWrapper)
        return m_pDrawModelWrapper->GetColorTable();
    return NULL;
}
XDashList*     ViewElementListProvider::GetDashList() const
{
    if(m_pDrawModelWrapper)
        return m_pDrawModelWrapper->GetDashList();
    return NULL;
}
XLineEndList*  ViewElementListProvider::GetLineEndList() const
{
    if(m_pDrawModelWrapper)
        return m_pDrawModelWrapper->GetLineEndList();
    return NULL;
}
XGradientList* ViewElementListProvider::GetGradientList() const
{
    if(m_pDrawModelWrapper)
        return m_pDrawModelWrapper->GetGradientList();
    return NULL;
}
XHatchList*    ViewElementListProvider::GetHatchList() const
{
    if(m_pDrawModelWrapper)
        return m_pDrawModelWrapper->GetHatchList();
    return NULL;
}
XBitmapList*   ViewElementListProvider::GetBitmapList() const
{
    if(m_pDrawModelWrapper)
        return m_pDrawModelWrapper->GetBitmapList();
    return NULL;
}

//create chartspecific symbols for linecharts
SdrObjList* ViewElementListProvider::GetSymbolList() const
{
    static SdrObjList* m_pSymbolList = NULL;
    static uno::Reference< drawing::XShapes > m_xSymbols(NULL);//@todo this keeps the first drawinglayer alive ...
    try
    {
        if(!m_pSymbolList || !m_pSymbolList->GetObjCount())
        {
            //@todo use mutex

            //get factory from draw model
            uno::Reference< drawing::XDrawPagesSupplier > xDrawPagesSuplier( m_pDrawModelWrapper->getUnoModel(), uno::UNO_QUERY );
            uno::Reference< lang::XMultiServiceFactory > xShapeFactory( xDrawPagesSuplier, uno::UNO_QUERY );

            //create hidden draw page (target):
            uno::Reference< drawing::XDrawPages > xDrawPages( xDrawPagesSuplier->getDrawPages () );
            uno::Reference< drawing::XDrawPage >  xDrawPage( xDrawPages->insertNewByIndex ( 1 ) );
            uno::Reference<drawing::XShapes>      xTarget( xDrawPage, uno::UNO_QUERY );

            //create symbols via uno and convert to native sdr objects
            drawing::Direction3D aSymbolSize(1000,1000,1000);//this size is somehow arbitrary - nneds only to be big thus the dialog restricts the symbols to its own maximum value
            m_xSymbols =  DataPointSymbolSupplier::create2DSymbolList( xShapeFactory, xTarget, aSymbolSize );
            uno::Reference< lang::XUnoTunnel > xUnoTunnel( m_xSymbols, uno::UNO_QUERY );
            uno::Reference< lang::XTypeProvider > xTypeProvider( m_xSymbols, uno::UNO_QUERY );
            if(xUnoTunnel.is()&&xTypeProvider.is())
            {
                SvxShape* pSvxShape = reinterpret_cast<SvxShape*>(xUnoTunnel->getSomething( SvxShape::getUnoTunnelId() ));
                if(pSvxShape)
                {
                    SdrObject* pSdrObject = pSvxShape->GetSdrObject();
                    if(pSdrObject)
                        m_pSymbolList = pSdrObject->GetSubList();
                }
            }
        }
    }
    catch( uno::Exception& e )
    {
        ASSERT_EXCEPTION( e );
    }
    return m_pSymbolList;
}

Graphic ViewElementListProvider::GetSymbolGraphic( sal_Int32 nStandardSymbol, const SfxItemSet* pSymbolShapeProperties ) const
{
    SdrObjList* pSymbolList = this->GetSymbolList();
    if( !pSymbolList->GetObjCount() )
        return Graphic();
    if(nStandardSymbol<0)
        nStandardSymbol*=-1;
    if( nStandardSymbol >= static_cast<sal_Int32>(pSymbolList->GetObjCount()) )
        nStandardSymbol %= pSymbolList->GetObjCount();
    SdrObject* pObj = pSymbolList->GetObj(nStandardSymbol);

    VirtualDevice aVDev;
    aVDev.SetMapMode(MapMode(MAP_100TH_MM));
    SdrModel* pModel = new SdrModel();
    pModel->GetItemPool().FreezeIdRanges();
    SdrPage* pPage = new SdrPage( *pModel, FALSE );
    pPage->SetSize(Size(1000,1000));
    pModel->InsertPage( pPage, 0 );
    SdrView* pView = new SdrView( pModel, &aVDev );
    pView->SetMarkHdlHidden( TRUE );
    SdrPageView* pPageView = pView->ShowPage(pPage, Point());

    pObj=pObj->Clone();
    pPage->NbcInsertObject(pObj);
    pView->MarkObj(pObj,pPageView);
    if( pSymbolShapeProperties )
        pObj->SetMergedItemSet(*pSymbolShapeProperties);

    GDIMetaFile aMeta(pView->GetAllMarkedMetaFile());

    Graphic aGraph(aMeta);
    Size aSize = pObj->GetSnapRect().GetSize();
    aGraph.SetPrefSize(aSize);
    aGraph.SetPrefMapMode(MAP_100TH_MM);

    pView->UnmarkAll();
    pObj=pPage->RemoveObject(0);
    if(pObj)
        delete pObj;
    delete pView;
    delete pModel;

    return aGraph;
}

FontList* ViewElementListProvider::getFontList() const
{
    //was old chart:
    //SvxFontListItem* SfxObjectShell::.GetItem(SID_ATTR_CHAR_FONTLIST)

    if(!m_pFontList)
    {
        OutputDevice* pPrinter    = NULL;//getPrinter();
        OutputDevice* pDefaultOut = Application::GetDefaultDevice();    // #67730#
        m_pFontList = new FontList( pPrinter ? pPrinter    : pDefaultOut
                                , pPrinter ? pDefaultOut : NULL
                                , FALSE );
    }
    return m_pFontList;
}

/*
SfxPrinter* ObjectPropertiesDialogParameter::getPrinter()
{
    //was old chart:
    //SfxPrinter* SchChartDocShell::GetPrinter()

    // OLE-Objekt: kein Printer anlegen ??? see old chart: :UpdateTablePointers
    //@todo get printer from calc or other container
    //return NULL;

    SfxPrinter* pPrinter = NULL;
    bool bOwnPrinter = true;
    if (!pPrinter)
    {
        SfxBoolItem aItem(SID_PRINTER_NOTFOUND_WARN, TRUE);
        // ItemSet mit speziellem Poolbereich anlegen
        SfxItemSet* pSet = new SfxItemSet(GetPool(),
                                          SID_PRINTER_NOTFOUND_WARN,
                                          SID_PRINTER_NOTFOUND_WARN, 0);
        pSet->Put(aItem);
        pPrinter = new SfxPrinter(pSet); //@todo ->need to remember and delete
        bOwnPrinter = TRUE;

        MapMode aMapMode = pPrinter->GetMapMode();
        aMapMode.SetMapUnit(MAP_100TH_MM);
        pPrinter->SetMapMode(aMapMode);

        if (pChDoc)
        {
            if (pPrinter != pChDoc->GetRefDevice())
                pChDoc->SetRefDevice(pPrinter);

            if (pPrinter != pChDoc->GetOutliner()->GetRefDevice())
                pChDoc->GetOutliner()->SetRefDevice(pPrinter);
        }
    }
    return pPrinter;
}
*/

SvNumberFormatter* ViewElementListProvider::GetOwnNumberFormatter() const
{
    if( m_pNumberFormatterWrapper )
        return m_pNumberFormatterWrapper->getSvNumberFormatter();
    return NULL;
    /*
        static SvNumberFormatter aNumberFormatter = SvNumberFormatter(
                ::comphelper::getProcessServiceFactory(),
                LANGUAGE_SYSTEM );
        return &aNumberFormatter;
    */
}
SvNumberFormatter* ViewElementListProvider::GetNumFormatter() const
{
    //@todo
    return GetOwnNumberFormatter();
}

//.............................................................................
} //namespace chart
//.............................................................................
<|endoftext|>


<commit_before>// Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl.html
#include "bsesequencer.hh"

#include <bse/bseengine.hh>
#include <bse/bsecxxplugin.hh>

enum {
  PARAM_0,
  PARAM_NOTES,
  PARAM_LENGTH,
  PARAM_TRANSPOSE,
  PARAM_COUNTER
};

/* --- prototypes --- */
static void	bse_sequencer_init		(BseSequencer		*sequencer);
static void	bse_sequencer_class_init	(BseSequencerClass	*klass);
static void	bse_sequencer_finalize		(GObject		*object);
static void	bse_sequencer_set_property	(BseSequencer           *sequencer,
						 guint                   param_id,
						 GValue                 *value,
						 GParamSpec             *pspec);
static void	bse_sequencer_get_property	(BseSequencer           *sequencer,
						 guint                   param_id,
						 GValue                 *value,
						 GParamSpec             *pspec);
static void	bse_sequencer_prepare		(BseSource		*source);
static void	bse_sequencer_context_create	(BseSource		*source,
						 guint			 context_handle,
						 BseTrans		*trans);
static void	bse_sequencer_reset		(BseSource		*source);
static void	bse_sequencer_update_modules	(BseSequencer		*seq);

// == Type Registration ==
#include "./icons/sequencer.c"
BSE_RESIDENT_SOURCE_DEF (BseSequencer, bse_sequencer, N_("Other Sources/Sequencer"),
                         "The Sequencer produces a frequency signal according to a sequence of notes",
                         sequencer_icon);

/* --- variables --- */
static gpointer		 parent_class = NULL;

/* --- functions --- */
static void
bse_sequencer_class_init (BseSequencerClass *klass)
{
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
  BseObjectClass *object_class = BSE_OBJECT_CLASS (klass);
  BseSourceClass *source_class = BSE_SOURCE_CLASS (klass);
  guint ochannel;

  parent_class = g_type_class_peek_parent (klass);

  gobject_class->set_property = (GObjectSetPropertyFunc) bse_sequencer_set_property;
  gobject_class->get_property = (GObjectGetPropertyFunc) bse_sequencer_get_property;
  gobject_class->finalize = bse_sequencer_finalize;

  source_class->prepare = bse_sequencer_prepare;
  source_class->context_create = bse_sequencer_context_create;
  source_class->reset = bse_sequencer_reset;

  bse_object_class_add_param (object_class, "Sequence",
			      PARAM_LENGTH,
			      sfi_pspec_int ("length", "Length", NULL,
					     8, 1, 128, 4,
					     SFI_PARAM_GUI ":scale"));
  bse_object_class_add_param (object_class, "Sequence",
			      PARAM_NOTES,
			      bse_param_spec_boxed ("notes", "Notes", NULL,
						    BSE_TYPE_NOTE_SEQUENCE,
						    "note-sequence:" SFI_PARAM_STANDARD));
  bse_object_class_add_param (object_class, "Sequence",
			      PARAM_TRANSPOSE,
			      sfi_pspec_int ("transpose", "Transpose", NULL,
					     0, -36, +36, 3,
					     SFI_PARAM_STANDARD ":scale:skip-default"));
  bse_object_class_add_param (object_class, "Sequence",
			      PARAM_COUNTER,
			      sfi_pspec_real ("counter", "Timing [ms]", NULL,
					      100, 0, 1000, 5,
					      SFI_PARAM_STANDARD ":f:scale"));

  ochannel = bse_source_class_add_ochannel (source_class, "freq-out", _("Freq Out"), _("Frequency Signal"));
  assert (ochannel == BSE_SEQUENCER_OCHANNEL_FREQ);
  ochannel = bse_source_class_add_ochannel (source_class, "note-sync", _("Note Sync"), _("Note Sync Signal"));
  assert (ochannel == BSE_SEQUENCER_OCHANNEL_NOTE_SYNC);
}

static void
bse_sequencer_init (BseSequencer *seq)
{
  seq->sdata = bse_note_sequence_new ();
  bse_note_sequence_resize (seq->sdata, 8);
  seq->sdata->offset = SFI_NOTE_C (SFI_KAMMER_OCTAVE);
  seq->n_freq_values = 0;
  seq->freq_values = NULL;
  seq->transpose = 0;
}

static void
bse_sequencer_finalize (GObject *object)
{
  BseSequencer *seq = BSE_SEQUENCER (object);

  bse_note_sequence_free (seq->sdata);

  /* chain parent class' handler */
  G_OBJECT_CLASS (parent_class)->finalize (object);
}

static void
bse_sequencer_set_property (BseSequencer *seq,
			    guint         param_id,
			    GValue       *value,
			    GParamSpec   *pspec)
{
  switch (param_id)
    {
      BseNoteSequence *sdata;
    case PARAM_LENGTH:
      if (sfi_value_get_int (value) != (int) bse_note_sequence_length (seq->sdata))
	{
	  bse_note_sequence_resize (seq->sdata, sfi_value_get_int (value));
	  bse_sequencer_update_modules (seq);
	  g_object_notify ((GObject*) seq, "notes");
	}
      break;
    case PARAM_NOTES:
      bse_note_sequence_free (seq->sdata);
      sdata = (BseNoteSequence*) bse_value_get_boxed (value);
      if (sdata)
	{
	  guint i, l, mnote = SFI_MAX_NOTE;
	  seq->sdata = bse_note_sequence_copy_shallow (sdata);
	  /* fixup offset */
	  l = bse_note_sequence_length (seq->sdata);
	  for (i = 0; i < l; i++)
	    mnote = MIN (mnote, seq->sdata->notes->notes[i]);
	  if (l && ABS (mnote - seq->sdata->offset) >= 12)
	    seq->sdata->offset = (mnote < SFI_NOTE_A (SFI_NOTE_OCTAVE (mnote)) ?
				  SFI_NOTE_C (SFI_NOTE_OCTAVE (mnote)) :
				  SFI_NOTE_A (SFI_NOTE_OCTAVE (mnote)));
	}
      else
	{
	  seq->sdata = bse_note_sequence_new ();
	  bse_note_sequence_resize (seq->sdata, 8);
	  seq->sdata->offset = SFI_NOTE_C (SFI_KAMMER_OCTAVE);
	}
      bse_sequencer_update_modules (seq);
      g_object_notify ((GObject*) seq, "length");
      break;
    case PARAM_COUNTER:
      seq->counter = sfi_value_get_real (value);
      bse_sequencer_update_modules (seq);
      break;
    case PARAM_TRANSPOSE:
      seq->transpose = sfi_value_get_int (value);
      bse_sequencer_update_modules (seq);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (seq, param_id, pspec);
      break;
    }
}

static void
bse_sequencer_get_property (BseSequencer *seq,
			    guint         param_id,
			    GValue       *value,
			    GParamSpec   *pspec)
{
  switch (param_id)
    {
    case PARAM_NOTES:
      bse_value_set_boxed (value, seq->sdata);
      break;
    case PARAM_LENGTH:
      sfi_value_set_int (value, bse_note_sequence_length (seq->sdata));
      break;
    case PARAM_COUNTER:
      sfi_value_set_real (value, seq->counter);
      break;
    case PARAM_TRANSPOSE:
      sfi_value_set_int (value, seq->transpose);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (seq, param_id, pspec);
      break;
    }
}

static gfloat*
freq_values_from_seq (BseMusicalTuningType musical_tuning,
                      BseNoteSequence     *sdata,
		      gint                 transpose)
{
  gfloat *v = g_new (gfloat, bse_note_sequence_length (sdata));
  guint i;

  for (i = 0; i < bse_note_sequence_length (sdata); i++)
    {
      gint note = sdata->notes->notes[i];

      if (note == SFI_NOTE_VOID)
	v[i] = 0;
      else
	v[i] = BSE_VALUE_FROM_FREQ (bse_note_to_freq (musical_tuning, CLAMP (note + transpose, SFI_MIN_NOTE, SFI_MAX_NOTE)));
    }

  return v;
}

typedef struct {
  guint	       n_values;
  gfloat      *values;	/* notes */
  guint	       counter;
  guint        index;	/* nth_note */
  guint	       c;	/* timing */
} SeqModule;
typedef struct {
  guint   n_values;
  gfloat *new_values;
  guint   counter;
  gfloat *old_values;
} AccessData;

static void
seq_access (BseModule *module,
	    gpointer   data)
{
  SeqModule *smod = (SeqModule*) module->user_data;
  AccessData *d = (AccessData*) data;

  smod->n_values = d->n_values;
  smod->values = d->new_values;
  smod->counter = d->counter;
  smod->index %= smod->n_values;
  smod->c %= smod->counter;
  if (smod->c < 1)
    smod->c = smod->counter;
}

static void
seq_access_free (gpointer data)
{
  AccessData *d = (AccessData*) data;

  g_free (d->old_values);
  g_free (d);
}

static void
bse_sequencer_update_modules (BseSequencer *seq)
{
  if (BSE_SOURCE_PREPARED (seq))
    {
      AccessData *d = g_new (AccessData, 1);

      d->old_values = seq->freq_values;

      seq->n_freq_values = bse_note_sequence_length (seq->sdata);
      seq->freq_values = freq_values_from_seq (bse_source_prepared_musical_tuning (BSE_SOURCE (seq)), seq->sdata, seq->transpose);

      d->n_values = seq->n_freq_values;
      d->new_values = seq->freq_values;
      d->counter = seq->counter / 1000.0 * bse_engine_sample_freq ();
      d->counter = MAX (d->counter, 1);

      bse_source_access_modules (BSE_SOURCE (seq),
				 seq_access, d, seq_access_free,
				 NULL);
    }
}

static void
sequencer_process (BseModule *module,
		   guint      n_values)
{
  SeqModule *smod = (SeqModule*) module->user_data;
  gfloat *freq_out = BSE_MODULE_OBUFFER (module, BSE_SEQUENCER_OCHANNEL_FREQ);
  gfloat *nsync_out = BSE_MODULE_OBUFFER (module, BSE_SEQUENCER_OCHANNEL_NOTE_SYNC);
  gfloat *bound = freq_out + n_values;

  while (freq_out < bound)
    {
      gfloat nval = smod->values[smod->index];

      if (smod->c == 0)
	{
	  smod->c = smod->counter;
	  smod->index++;
	  if (smod->index >= smod->n_values)
	    smod->index = 0;
	  *nsync_out = 1.0;
	}
      else
	*nsync_out = 0.0;
      *freq_out++ = nval;
      nsync_out++;
      smod->c--;
    }
}

static void
bse_sequencer_prepare (BseSource *source)
{
  BseSequencer *seq = BSE_SEQUENCER (source);

  seq->n_freq_values = bse_note_sequence_length (seq->sdata);
  seq->freq_values = freq_values_from_seq (bse_source_prepared_musical_tuning (source), seq->sdata, seq->transpose);

  /* chain parent class' handler */
  BSE_SOURCE_CLASS (parent_class)->prepare (source);
}

static void
bse_sequencer_context_create (BseSource *source,
			      guint      context_handle,
			      BseTrans  *trans)
{
  static const BseModuleClass sequencer_class = {
    0,				/* n_istreams */
    0,                  	/* n_jstreams */
    BSE_SEQUENCER_N_OCHANNELS,	/* n_ostreams */
    sequencer_process,		/* process */
    NULL,                       /* process_defer */
    NULL,                       /* reset */
    (BseModuleFreeFunc) g_free,	/* free */
    BSE_COST_CHEAP,		/* flags */
  };
  BseSequencer *seq = BSE_SEQUENCER (source);
  SeqModule *smod = g_new0 (SeqModule, 1);
  BseModule *module;

  smod->n_values = seq->n_freq_values;
  smod->values = seq->freq_values;
  smod->counter = seq->counter / 1000.0 * bse_engine_sample_freq ();
  smod->counter = MAX (smod->counter, 1);
  smod->index = 0;
  smod->c = smod->counter;

  module = bse_module_new (&sequencer_class, smod);

  /* setup module i/o streams with BseSource i/o channels */
  bse_source_set_context_module (source, context_handle, module);

  /* commit module to engine */
  bse_trans_add (trans, bse_job_integrate (module));

  /* chain parent class' handler */
  BSE_SOURCE_CLASS (parent_class)->context_create (source, context_handle, trans);
}

static void
bse_sequencer_reset (BseSource *source)
{
  BseSequencer *seq = BSE_SEQUENCER (source);

  g_free (seq->freq_values);
  seq->freq_values = NULL;
  seq->n_freq_values = 0;

  /* chain parent class' handler */
  BSE_SOURCE_CLASS (parent_class)->reset (source);
}
<commit_msg>PLUGINS: fix signedness compiler warnings<commit_after>// Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl.html
#include "bsesequencer.hh"

#include <bse/bseengine.hh>
#include <bse/bsecxxplugin.hh>

enum {
  PARAM_0,
  PARAM_NOTES,
  PARAM_LENGTH,
  PARAM_TRANSPOSE,
  PARAM_COUNTER
};

/* --- prototypes --- */
static void	bse_sequencer_init		(BseSequencer		*sequencer);
static void	bse_sequencer_class_init	(BseSequencerClass	*klass);
static void	bse_sequencer_finalize		(GObject		*object);
static void	bse_sequencer_set_property	(BseSequencer           *sequencer,
						 guint                   param_id,
						 GValue                 *value,
						 GParamSpec             *pspec);
static void	bse_sequencer_get_property	(BseSequencer           *sequencer,
						 guint                   param_id,
						 GValue                 *value,
						 GParamSpec             *pspec);
static void	bse_sequencer_prepare		(BseSource		*source);
static void	bse_sequencer_context_create	(BseSource		*source,
						 guint			 context_handle,
						 BseTrans		*trans);
static void	bse_sequencer_reset		(BseSource		*source);
static void	bse_sequencer_update_modules	(BseSequencer		*seq);

// == Type Registration ==
#include "./icons/sequencer.c"
BSE_RESIDENT_SOURCE_DEF (BseSequencer, bse_sequencer, N_("Other Sources/Sequencer"),
                         "The Sequencer produces a frequency signal according to a sequence of notes",
                         sequencer_icon);

/* --- variables --- */
static gpointer		 parent_class = NULL;

/* --- functions --- */
static void
bse_sequencer_class_init (BseSequencerClass *klass)
{
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
  BseObjectClass *object_class = BSE_OBJECT_CLASS (klass);
  BseSourceClass *source_class = BSE_SOURCE_CLASS (klass);
  guint ochannel;

  parent_class = g_type_class_peek_parent (klass);

  gobject_class->set_property = (GObjectSetPropertyFunc) bse_sequencer_set_property;
  gobject_class->get_property = (GObjectGetPropertyFunc) bse_sequencer_get_property;
  gobject_class->finalize = bse_sequencer_finalize;

  source_class->prepare = bse_sequencer_prepare;
  source_class->context_create = bse_sequencer_context_create;
  source_class->reset = bse_sequencer_reset;

  bse_object_class_add_param (object_class, "Sequence",
			      PARAM_LENGTH,
			      sfi_pspec_int ("length", "Length", NULL,
					     8, 1, 128, 4,
					     SFI_PARAM_GUI ":scale"));
  bse_object_class_add_param (object_class, "Sequence",
			      PARAM_NOTES,
			      bse_param_spec_boxed ("notes", "Notes", NULL,
						    BSE_TYPE_NOTE_SEQUENCE,
						    "note-sequence:" SFI_PARAM_STANDARD));
  bse_object_class_add_param (object_class, "Sequence",
			      PARAM_TRANSPOSE,
			      sfi_pspec_int ("transpose", "Transpose", NULL,
					     0, -36, +36, 3,
					     SFI_PARAM_STANDARD ":scale:skip-default"));
  bse_object_class_add_param (object_class, "Sequence",
			      PARAM_COUNTER,
			      sfi_pspec_real ("counter", "Timing [ms]", NULL,
					      100, 0, 1000, 5,
					      SFI_PARAM_STANDARD ":f:scale"));

  ochannel = bse_source_class_add_ochannel (source_class, "freq-out", _("Freq Out"), _("Frequency Signal"));
  assert (ochannel == BSE_SEQUENCER_OCHANNEL_FREQ);
  ochannel = bse_source_class_add_ochannel (source_class, "note-sync", _("Note Sync"), _("Note Sync Signal"));
  assert (ochannel == BSE_SEQUENCER_OCHANNEL_NOTE_SYNC);
}

static void
bse_sequencer_init (BseSequencer *seq)
{
  seq->sdata = bse_note_sequence_new ();
  bse_note_sequence_resize (seq->sdata, 8);
  seq->sdata->offset = SFI_NOTE_C (SFI_KAMMER_OCTAVE);
  seq->n_freq_values = 0;
  seq->freq_values = NULL;
  seq->transpose = 0;
}

static void
bse_sequencer_finalize (GObject *object)
{
  BseSequencer *seq = BSE_SEQUENCER (object);

  bse_note_sequence_free (seq->sdata);

  /* chain parent class' handler */
  G_OBJECT_CLASS (parent_class)->finalize (object);
}

static void
bse_sequencer_set_property (BseSequencer *seq,
			    guint         param_id,
			    GValue       *value,
			    GParamSpec   *pspec)
{
  switch (param_id)
    {
      BseNoteSequence *sdata;
    case PARAM_LENGTH:
      if (sfi_value_get_int (value) != (int) bse_note_sequence_length (seq->sdata))
	{
	  bse_note_sequence_resize (seq->sdata, sfi_value_get_int (value));
	  bse_sequencer_update_modules (seq);
	  g_object_notify ((GObject*) seq, "notes");
	}
      break;
    case PARAM_NOTES:
      bse_note_sequence_free (seq->sdata);
      sdata = (BseNoteSequence*) bse_value_get_boxed (value);
      if (sdata)
	{
	  int mnote = SFI_MAX_NOTE;
	  seq->sdata = bse_note_sequence_copy_shallow (sdata);
	  /* fixup offset */
	  uint l = bse_note_sequence_length (seq->sdata);
	  for (uint i = 0; i < l; i++)
	    mnote = MIN (mnote, seq->sdata->notes->notes[i]);
	  if (l && ABS (mnote - seq->sdata->offset) >= 12)
	    seq->sdata->offset = (mnote < SFI_NOTE_A (SFI_NOTE_OCTAVE (mnote)) ?
				  SFI_NOTE_C (SFI_NOTE_OCTAVE (mnote)) :
				  SFI_NOTE_A (SFI_NOTE_OCTAVE (mnote)));
	}
      else
	{
	  seq->sdata = bse_note_sequence_new ();
	  bse_note_sequence_resize (seq->sdata, 8);
	  seq->sdata->offset = SFI_NOTE_C (SFI_KAMMER_OCTAVE);
	}
      bse_sequencer_update_modules (seq);
      g_object_notify ((GObject*) seq, "length");
      break;
    case PARAM_COUNTER:
      seq->counter = sfi_value_get_real (value);
      bse_sequencer_update_modules (seq);
      break;
    case PARAM_TRANSPOSE:
      seq->transpose = sfi_value_get_int (value);
      bse_sequencer_update_modules (seq);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (seq, param_id, pspec);
      break;
    }
}

static void
bse_sequencer_get_property (BseSequencer *seq,
			    guint         param_id,
			    GValue       *value,
			    GParamSpec   *pspec)
{
  switch (param_id)
    {
    case PARAM_NOTES:
      bse_value_set_boxed (value, seq->sdata);
      break;
    case PARAM_LENGTH:
      sfi_value_set_int (value, bse_note_sequence_length (seq->sdata));
      break;
    case PARAM_COUNTER:
      sfi_value_set_real (value, seq->counter);
      break;
    case PARAM_TRANSPOSE:
      sfi_value_set_int (value, seq->transpose);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (seq, param_id, pspec);
      break;
    }
}

static gfloat*
freq_values_from_seq (BseMusicalTuningType musical_tuning,
                      BseNoteSequence     *sdata,
		      gint                 transpose)
{
  gfloat *v = g_new (gfloat, bse_note_sequence_length (sdata));
  guint i;

  for (i = 0; i < bse_note_sequence_length (sdata); i++)
    {
      gint note = sdata->notes->notes[i];

      if (note == SFI_NOTE_VOID)
	v[i] = 0;
      else
	v[i] = BSE_VALUE_FROM_FREQ (bse_note_to_freq (musical_tuning, CLAMP (note + transpose, SFI_MIN_NOTE, SFI_MAX_NOTE)));
    }

  return v;
}

typedef struct {
  guint	       n_values;
  gfloat      *values;	/* notes */
  guint	       counter;
  guint        index;	/* nth_note */
  guint	       c;	/* timing */
} SeqModule;
typedef struct {
  guint   n_values;
  gfloat *new_values;
  guint   counter;
  gfloat *old_values;
} AccessData;

static void
seq_access (BseModule *module,
	    gpointer   data)
{
  SeqModule *smod = (SeqModule*) module->user_data;
  AccessData *d = (AccessData*) data;

  smod->n_values = d->n_values;
  smod->values = d->new_values;
  smod->counter = d->counter;
  smod->index %= smod->n_values;
  smod->c %= smod->counter;
  if (smod->c < 1)
    smod->c = smod->counter;
}

static void
seq_access_free (gpointer data)
{
  AccessData *d = (AccessData*) data;

  g_free (d->old_values);
  g_free (d);
}

static void
bse_sequencer_update_modules (BseSequencer *seq)
{
  if (BSE_SOURCE_PREPARED (seq))
    {
      AccessData *d = g_new (AccessData, 1);

      d->old_values = seq->freq_values;

      seq->n_freq_values = bse_note_sequence_length (seq->sdata);
      seq->freq_values = freq_values_from_seq (bse_source_prepared_musical_tuning (BSE_SOURCE (seq)), seq->sdata, seq->transpose);

      d->n_values = seq->n_freq_values;
      d->new_values = seq->freq_values;
      d->counter = seq->counter / 1000.0 * bse_engine_sample_freq ();
      d->counter = MAX (d->counter, 1);

      bse_source_access_modules (BSE_SOURCE (seq),
				 seq_access, d, seq_access_free,
				 NULL);
    }
}

static void
sequencer_process (BseModule *module,
		   guint      n_values)
{
  SeqModule *smod = (SeqModule*) module->user_data;
  gfloat *freq_out = BSE_MODULE_OBUFFER (module, BSE_SEQUENCER_OCHANNEL_FREQ);
  gfloat *nsync_out = BSE_MODULE_OBUFFER (module, BSE_SEQUENCER_OCHANNEL_NOTE_SYNC);
  gfloat *bound = freq_out + n_values;

  while (freq_out < bound)
    {
      gfloat nval = smod->values[smod->index];

      if (smod->c == 0)
	{
	  smod->c = smod->counter;
	  smod->index++;
	  if (smod->index >= smod->n_values)
	    smod->index = 0;
	  *nsync_out = 1.0;
	}
      else
	*nsync_out = 0.0;
      *freq_out++ = nval;
      nsync_out++;
      smod->c--;
    }
}

static void
bse_sequencer_prepare (BseSource *source)
{
  BseSequencer *seq = BSE_SEQUENCER (source);

  seq->n_freq_values = bse_note_sequence_length (seq->sdata);
  seq->freq_values = freq_values_from_seq (bse_source_prepared_musical_tuning (source), seq->sdata, seq->transpose);

  /* chain parent class' handler */
  BSE_SOURCE_CLASS (parent_class)->prepare (source);
}

static void
bse_sequencer_context_create (BseSource *source,
			      guint      context_handle,
			      BseTrans  *trans)
{
  static const BseModuleClass sequencer_class = {
    0,				/* n_istreams */
    0,                  	/* n_jstreams */
    BSE_SEQUENCER_N_OCHANNELS,	/* n_ostreams */
    sequencer_process,		/* process */
    NULL,                       /* process_defer */
    NULL,                       /* reset */
    (BseModuleFreeFunc) g_free,	/* free */
    BSE_COST_CHEAP,		/* flags */
  };
  BseSequencer *seq = BSE_SEQUENCER (source);
  SeqModule *smod = g_new0 (SeqModule, 1);
  BseModule *module;

  smod->n_values = seq->n_freq_values;
  smod->values = seq->freq_values;
  smod->counter = seq->counter / 1000.0 * bse_engine_sample_freq ();
  smod->counter = MAX (smod->counter, 1);
  smod->index = 0;
  smod->c = smod->counter;

  module = bse_module_new (&sequencer_class, smod);

  /* setup module i/o streams with BseSource i/o channels */
  bse_source_set_context_module (source, context_handle, module);

  /* commit module to engine */
  bse_trans_add (trans, bse_job_integrate (module));

  /* chain parent class' handler */
  BSE_SOURCE_CLASS (parent_class)->context_create (source, context_handle, trans);
}

static void
bse_sequencer_reset (BseSource *source)
{
  BseSequencer *seq = BSE_SEQUENCER (source);

  g_free (seq->freq_values);
  seq->freq_values = NULL;
  seq->n_freq_values = 0;

  /* chain parent class' handler */
  BSE_SOURCE_CLASS (parent_class)->reset (source);
}
<|endoftext|>


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

Program:   Medical Imaging & Interaction Toolkit
Module:    $RCSfile$
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

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

=========================================================================*/

#include "mitkBoundingObjectGroup.h"
#include "vtkTransform.h"

mitk::BoundingObjectGroup::BoundingObjectGroup()
:  m_Counter(0), m_CSGMode(Difference) //m_CSGMode(Union) m_CSGMode(Intersection)
{
  m_Geometry3D->Initialize();
  m_BoundingObjects = mitk::BoundingObjectGroup::BoundingObjectContainer::New();
  SetVtkPolyData(NULL);
}

mitk::BoundingObjectGroup::~BoundingObjectGroup()
{
}

void mitk::BoundingObjectGroup::SetRequestedRegionToLargestPossibleRegion()
{
}

bool mitk::BoundingObjectGroup::RequestedRegionIsOutsideOfTheBufferedRegion()
{
  return ! VerifyRequestedRegion();
}

bool mitk::BoundingObjectGroup::VerifyRequestedRegion()
{
  assert(m_Geometry3D.IsNotNull());
  return true;
}

void mitk::BoundingObjectGroup::SetRequestedRegion(itk::DataObject *data)
{
}

void mitk::BoundingObjectGroup::UpdateOutputInformation()
{
  ScalarType bounds[6]={0,1,0,1,0,1};  // {xmin,x_max, ymin,y_max,zmin,z_max};

  // calculate global bounding box
  mitk::BoundingObjectGroup::BoundingObjectContainer::ConstIterator boundingObjectsIterator = m_BoundingObjects->Begin();
  const mitk::BoundingObjectGroup::BoundingObjectContainer::ConstIterator boundingObjectsIteratorEnd = m_BoundingObjects->End();

  if(boundingObjectsIterator == boundingObjectsIteratorEnd) // if there is no BoundingObject, the bounding box is zero
  {
    bounds[0] = bounds[1] = bounds[2] = bounds[3] = bounds[4] = bounds[5] = 0.0;
    return;
  }
  mitk::BoundingBox::Pointer boundingBox;
  mitk::BoundingBox::PointType minPoint;
  mitk::BoundingBox::PointType globalMinPoint;
  mitk::BoundingBox::PointType globalMaxPoint;

  /* Initialize globalMin/MaxPoints */
  boundingObjectsIterator.Value()->UpdateOutputInformation();
  boundingBox = const_cast<mitk::BoundingBox*>(boundingObjectsIterator.Value()->GetGeometry()->GetBoundingBox());

  minPoint = boundingBox->GetMinimum();
  mitk::ScalarType min[3];
  min[0] = minPoint[0];   min[1] = minPoint[1];   min[2] = minPoint[2];
  boundingObjectsIterator.Value()->GetGeometry()->GetVtkTransform()->TransformPoint(min, min);
  globalMinPoint[0] = min[0];   globalMinPoint[1] = min[1];   globalMinPoint[2] = min[2];
  globalMaxPoint[0] = min[0];   globalMaxPoint[1] = min[1];   globalMaxPoint[2] = min[2];
  //boundingObjectsIterator++;
  while (boundingObjectsIterator != boundingObjectsIteratorEnd) // calculate a bounding box that includes all BoundingObjects
  {
    boundingObjectsIterator.Value()->UpdateOutputInformation();
    boundingBox = const_cast<mitk::BoundingBox*>(boundingObjectsIterator.Value()->GetGeometry()->GetBoundingBox());

    /* create all 8 points of the bounding box */
    mitk::BoundingBox::PointsContainerPointer points = mitk::BoundingBox::PointsContainer::New();
    mitk::Point3D p;
    p = boundingBox->GetMinimum();
    points->InsertElement(0, p);
    p[0] = -p[0];
    points->InsertElement(1, p);
    p = boundingBox->GetMinimum();
    p[1] = -p[1];
    points->InsertElement(2, p);
    p = boundingBox->GetMinimum();
    p[2] = -p[2];
    points->InsertElement(3, p);
    p = boundingBox->GetMaximum();
    points->InsertElement(4, p);
    p[0] = -p[0];
    points->InsertElement(5, p);
    p = boundingBox->GetMaximum();
    p[1] = -p[1];
    points->InsertElement(6, p);
    p = boundingBox->GetMaximum();
    p[2] = -p[2];
    points->InsertElement(7, p);
    mitk::BoundingBox::PointsContainerConstIterator pointsIterator = points->Begin();
    mitk::BoundingBox::PointsContainerConstIterator pointsIteratorEnd = points->End();
    while (pointsIterator != pointsIteratorEnd) // for each vertex of the bounding box
    {
      minPoint = pointsIterator->Value();
      min[0] = minPoint[0];   min[1] = minPoint[1];   min[2] = minPoint[2];
      boundingObjectsIterator.Value()->GetGeometry()->GetVtkTransform()->TransformPoint(min, min);  // transform vertex point to world coordinates

      globalMinPoint[0] = (min[0] < globalMinPoint[0]) ? min[0] : globalMinPoint[0];  // check if world point
      globalMinPoint[1] = (min[1] < globalMinPoint[1]) ? min[1] : globalMinPoint[1];  // has a lower or a
      globalMinPoint[2] = (min[2] < globalMinPoint[2]) ? min[2] : globalMinPoint[2];  // higher value as
      globalMaxPoint[0] = (min[0] > globalMaxPoint[0]) ? min[0] : globalMaxPoint[0];  // the last known highest
      globalMaxPoint[1] = (min[1] > globalMaxPoint[1]) ? min[1] : globalMaxPoint[1];  // value
      globalMaxPoint[2] = (min[2] > globalMaxPoint[2]) ? min[2] : globalMaxPoint[2];  // in each axis
      pointsIterator++;
    }
    boundingObjectsIterator++;
  }

  /* BoundingBox is centered around the center of all sub bounding objects */
  mitk::BoundingBox::PointType centerPoint;
  centerPoint[0] = (globalMinPoint[0] + globalMaxPoint[0])/ 2.0;
  centerPoint[1] = (globalMinPoint[1] + globalMaxPoint[1])/ 2.0;
  centerPoint[2] = (globalMinPoint[2] + globalMaxPoint[2])/ 2.0;

  bounds[0] = globalMinPoint[0] - centerPoint[0]; // x Min
  bounds[1] = globalMaxPoint[0] - centerPoint[0]; // x Max
  bounds[2] = globalMinPoint[1] - centerPoint[1]; // y Min
  bounds[3] = globalMaxPoint[1] - centerPoint[1]; // y Max
  bounds[4] = globalMinPoint[2] - centerPoint[2]; // z Min
  bounds[5] = globalMaxPoint[2] - centerPoint[2]; // z Max
  m_Geometry3D->SetBounds(bounds);

  /* the objects position is the center of all sub bounding objects */
  m_Geometry3D->GetVtkTransform()->Identity();
  m_Geometry3D->GetVtkTransform()->Translate(centerPoint[0], centerPoint[1], centerPoint[2]);
  m_Geometry3D->TransferVtkToITKTransform();
}

void mitk::BoundingObjectGroup::AddBoundingObject(mitk::BoundingObject::Pointer boundingObject)
{
  m_BoundingObjects->InsertElement( m_Counter++, boundingObject);
  UpdateOutputInformation();
}

bool mitk::BoundingObjectGroup::IsInside(mitk::Point3D p)
{
  mitk::BoundingObjectGroup::BoundingObjectContainer::ConstIterator boundingObjectsIterator = m_BoundingObjects->Begin();
  const mitk::BoundingObjectGroup::BoundingObjectContainer::ConstIterator boundingObjectsIteratorEnd = m_BoundingObjects->End();

  bool inside; // initialize with true for intersection, with false for union

  switch(m_CSGMode)
  {
    case Intersection:
    {
      inside = true;
      while (boundingObjectsIterator != boundingObjectsIteratorEnd) // check each BoundingObject
      {       // calculate intersection: each point, that is inside each BoundingObject is considered inside the group
        inside = boundingObjectsIterator.Value()->IsInside(p) && inside;
        if (!inside) // shortcut, it is enough to find one object that does not contain the point
          break;
        boundingObjectsIterator++;
      }
      break;
    }
    case Difference:
    {
      bool posInside = false;
      bool negInside = false;
      while (boundingObjectsIterator != boundingObjectsIteratorEnd) // check each BoundingObject
      {
        // calculate union: each point, that is inside least one BoundingObject is considered inside the group
        if (boundingObjectsIterator.Value()->GetPositive())
          posInside = boundingObjectsIterator.Value()->IsInside(p) || posInside;
        else
          negInside = boundingObjectsIterator.Value()->IsInside(p) || negInside;

        boundingObjectsIterator++;
      }
      if (posInside && !negInside)
        inside = true;
      else
        inside = false;
      break;
    }
    case Union:
    default:
    {
      inside = false;
      while (boundingObjectsIterator != boundingObjectsIteratorEnd) // check each BoundingObject
      {       // calculate union: each point, that is inside least one BoundingObject is considered inside the group
        inside = boundingObjectsIterator.Value()->IsInside(p) || inside;
        if (inside) // shortcut, it is enough to find one object that contains the point
          break;
        boundingObjectsIterator++;
      }
      break;
    }
  }
  return inside;
}

unsigned int mitk::BoundingObjectGroup::GetCount() const
{
  return m_Counter;
}
<commit_msg>FIX: bounds calculation of bounding object group is no longer overwritten; works now<commit_after>/*=========================================================================

Program:   Medical Imaging & Interaction Toolkit
Module:    $RCSfile$
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

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

=========================================================================*/

#include "mitkBoundingObjectGroup.h"
#include "vtkTransform.h"

mitk::BoundingObjectGroup::BoundingObjectGroup()
:  m_Counter(0), m_CSGMode(Difference) //m_CSGMode(Union) m_CSGMode(Intersection)
{
  m_Geometry3D->Initialize();
  m_BoundingObjects = mitk::BoundingObjectGroup::BoundingObjectContainer::New();
  SetVtkPolyData(NULL);
}

mitk::BoundingObjectGroup::~BoundingObjectGroup()
{
}

void mitk::BoundingObjectGroup::SetRequestedRegionToLargestPossibleRegion()
{
}

bool mitk::BoundingObjectGroup::RequestedRegionIsOutsideOfTheBufferedRegion()
{
  return ! VerifyRequestedRegion();
}

bool mitk::BoundingObjectGroup::VerifyRequestedRegion()
{
  assert(m_Geometry3D.IsNotNull());
  return true;
}

void mitk::BoundingObjectGroup::SetRequestedRegion(itk::DataObject *data)
{
}

void mitk::BoundingObjectGroup::UpdateOutputInformation()
{
  ScalarType bounds[6]={0,1,0,1,0,1};  // {xmin,x_max, ymin,y_max,zmin,z_max};

  // calculate global bounding box
  mitk::BoundingObjectGroup::BoundingObjectContainer::ConstIterator boundingObjectsIterator = m_BoundingObjects->Begin();
  const mitk::BoundingObjectGroup::BoundingObjectContainer::ConstIterator boundingObjectsIteratorEnd = m_BoundingObjects->End();

  if(boundingObjectsIterator == boundingObjectsIteratorEnd) // if there is no BoundingObject, the bounding box is zero
  {
    bounds[0] = bounds[1] = bounds[2] = bounds[3] = bounds[4] = bounds[5] = 0.0;
    return;
  }
  mitk::BoundingBox::Pointer boundingBox;
  mitk::BoundingBox::PointType minPoint;
  mitk::BoundingBox::PointType globalMinPoint;
  mitk::BoundingBox::PointType globalMaxPoint;

  /* Initialize globalMin/MaxPoints */
  boundingObjectsIterator.Value()->UpdateOutputInformation();
  boundingBox = const_cast<mitk::BoundingBox*>(boundingObjectsIterator.Value()->GetGeometry()->GetBoundingBox());

  minPoint = boundingBox->GetMinimum();
  mitk::ScalarType min[3];
  min[0] = minPoint[0];   min[1] = minPoint[1];   min[2] = minPoint[2];
  boundingObjectsIterator.Value()->GetGeometry()->GetVtkTransform()->TransformPoint(min, min);
  globalMinPoint[0] = min[0];   globalMinPoint[1] = min[1];   globalMinPoint[2] = min[2];
  globalMaxPoint[0] = min[0];   globalMaxPoint[1] = min[1];   globalMaxPoint[2] = min[2];
  //boundingObjectsIterator++;
  while (boundingObjectsIterator != boundingObjectsIteratorEnd) // calculate a bounding box that includes all BoundingObjects
  {
    boundingObjectsIterator.Value()->UpdateOutputInformation();
    boundingBox = const_cast<mitk::BoundingBox*>(boundingObjectsIterator.Value()->GetGeometry()->GetBoundingBox());

    /* create all 8 points of the bounding box */
    mitk::BoundingBox::PointsContainerPointer points = mitk::BoundingBox::PointsContainer::New();
    mitk::Point3D p;
    p = boundingBox->GetMinimum();
    points->InsertElement(0, p);
    p[0] = -p[0];
    points->InsertElement(1, p);
    p = boundingBox->GetMinimum();
    p[1] = -p[1];
    points->InsertElement(2, p);
    p = boundingBox->GetMinimum();
    p[2] = -p[2];
    points->InsertElement(3, p);
    p = boundingBox->GetMaximum();
    points->InsertElement(4, p);
    p[0] = -p[0];
    points->InsertElement(5, p);
    p = boundingBox->GetMaximum();
    p[1] = -p[1];
    points->InsertElement(6, p);
    p = boundingBox->GetMaximum();
    p[2] = -p[2];
    points->InsertElement(7, p);
    mitk::BoundingBox::PointsContainerConstIterator pointsIterator = points->Begin();
    mitk::BoundingBox::PointsContainerConstIterator pointsIteratorEnd = points->End();
    while (pointsIterator != pointsIteratorEnd) // for each vertex of the bounding box
    {
      minPoint = pointsIterator->Value();
      min[0] = minPoint[0];   min[1] = minPoint[1];   min[2] = minPoint[2];
      boundingObjectsIterator.Value()->GetGeometry()->GetVtkTransform()->TransformPoint(min, min);  // transform vertex point to world coordinates

      globalMinPoint[0] = (min[0] < globalMinPoint[0]) ? min[0] : globalMinPoint[0];  // check if world point
      globalMinPoint[1] = (min[1] < globalMinPoint[1]) ? min[1] : globalMinPoint[1];  // has a lower or a
      globalMinPoint[2] = (min[2] < globalMinPoint[2]) ? min[2] : globalMinPoint[2];  // higher value as
      globalMaxPoint[0] = (min[0] > globalMaxPoint[0]) ? min[0] : globalMaxPoint[0];  // the last known highest
      globalMaxPoint[1] = (min[1] > globalMaxPoint[1]) ? min[1] : globalMaxPoint[1];  // value
      globalMaxPoint[2] = (min[2] > globalMaxPoint[2]) ? min[2] : globalMaxPoint[2];  // in each axis
      pointsIterator++;
    }
    boundingObjectsIterator++;
  }

  /* BoundingBox is centered around the center of all sub bounding objects */
  mitk::BoundingBox::PointType centerPoint;
  centerPoint[0] = (globalMinPoint[0] + globalMaxPoint[0])/ 2.0;
  centerPoint[1] = (globalMinPoint[1] + globalMaxPoint[1])/ 2.0;
  centerPoint[2] = (globalMinPoint[2] + globalMaxPoint[2])/ 2.0;

  bounds[0] = globalMinPoint[0] - centerPoint[0]; // x Min
  bounds[1] = globalMaxPoint[0] - centerPoint[0]; // x Max
  bounds[2] = globalMinPoint[1] - centerPoint[1]; // y Min
  bounds[3] = globalMaxPoint[1] - centerPoint[1]; // y Max
  bounds[4] = globalMinPoint[2] - centerPoint[2]; // z Min
  bounds[5] = globalMaxPoint[2] - centerPoint[2]; // z Max

  mitk::TimeSlicedGeometry::Pointer timeGeometry = const_cast< mitk::TimeSlicedGeometry *>(this->GetTimeSlicedGeometry());
  mitk::Geometry3D::Pointer geometry3d = timeGeometry->GetGeometry3D(0);
  unsigned int timesteps = timeGeometry->GetTimeSteps();
  if(geometry3d.IsNull())
  {
    assert(timesteps==0);
    timeGeometry->SetBounds(bounds);

    /* the objects position is the center of all sub bounding objects */
    timeGeometry->GetVtkTransform()->Identity();
    timeGeometry->GetVtkTransform()->Translate(centerPoint[0], centerPoint[1], centerPoint[2]);
    timeGeometry->TransferVtkToITKTransform();
  }
  else
  {
    assert(timesteps>0);
    geometry3d->SetBounds(bounds);

    /* the objects position is the center of all sub bounding objects */
    geometry3d->GetVtkTransform()->Identity();
    geometry3d->GetVtkTransform()->Translate(centerPoint[0], centerPoint[1], centerPoint[2]);
    geometry3d->TransferVtkToITKTransform();

    timeGeometry->InitializeEvenlyTimed(geometry3d, timesteps);
  }
}

void mitk::BoundingObjectGroup::AddBoundingObject(mitk::BoundingObject::Pointer boundingObject)
{
  m_BoundingObjects->InsertElement( m_Counter++, boundingObject);
  UpdateOutputInformation();
}

bool mitk::BoundingObjectGroup::IsInside(mitk::Point3D p)
{
  mitk::BoundingObjectGroup::BoundingObjectContainer::ConstIterator boundingObjectsIterator = m_BoundingObjects->Begin();
  const mitk::BoundingObjectGroup::BoundingObjectContainer::ConstIterator boundingObjectsIteratorEnd = m_BoundingObjects->End();

  bool inside; // initialize with true for intersection, with false for union

  switch(m_CSGMode)
  {
    case Intersection:
    {
      inside = true;
      while (boundingObjectsIterator != boundingObjectsIteratorEnd) // check each BoundingObject
      {       // calculate intersection: each point, that is inside each BoundingObject is considered inside the group
        inside = boundingObjectsIterator.Value()->IsInside(p) && inside;
        if (!inside) // shortcut, it is enough to find one object that does not contain the point
          break;
        boundingObjectsIterator++;
      }
      break;
    }
    case Difference:
    {
      bool posInside = false;
      bool negInside = false;
      while (boundingObjectsIterator != boundingObjectsIteratorEnd) // check each BoundingObject
      {
        // calculate union: each point, that is inside least one BoundingObject is considered inside the group
        if (boundingObjectsIterator.Value()->GetPositive())
          posInside = boundingObjectsIterator.Value()->IsInside(p) || posInside;
        else
          negInside = boundingObjectsIterator.Value()->IsInside(p) || negInside;

        boundingObjectsIterator++;
      }
      if (posInside && !negInside)
        inside = true;
      else
        inside = false;
      break;
    }
    case Union:
    default:
    {
      inside = false;
      while (boundingObjectsIterator != boundingObjectsIteratorEnd) // check each BoundingObject
      {       // calculate union: each point, that is inside least one BoundingObject is considered inside the group
        inside = boundingObjectsIterator.Value()->IsInside(p) || inside;
        if (inside) // shortcut, it is enough to find one object that contains the point
          break;
        boundingObjectsIterator++;
      }
      break;
    }
  }
  return inside;
}

unsigned int mitk::BoundingObjectGroup::GetCount() const
{
  return m_Counter;
}
<|endoftext|>


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

Program:   Medical Imaging & Interaction Toolkit
Module:    $RCSfile$
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

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

=========================================================================*/

#include "mitkBoundingObjectGroup.h"
#include <vtkLinearTransform.h>

mitk::BoundingObjectGroup::BoundingObjectGroup()
:  m_Counter(0), m_CSGMode(Difference) //m_CSGMode(Union) m_CSGMode(Intersection)
{
  m_Geometry3D->Initialize();
  m_BoundingObjects = mitk::BoundingObjectGroup::BoundingObjectContainer::New();
  SetVtkPolyData(NULL);
}

mitk::BoundingObjectGroup::~BoundingObjectGroup()
{
}

bool mitk::BoundingObjectGroup::VerifyRequestedRegion()
{
  assert(m_Geometry3D.IsNotNull());
  return true; //Superclass::VerifyRequestedRegion();
}

void mitk::BoundingObjectGroup::UpdateOutputInformation()
{
  ScalarType bounds[6]={0,1,0,1,0,1};  // {xmin,x_max, ymin,y_max,zmin,z_max};

  // calculate global bounding box
  mitk::BoundingObjectGroup::BoundingObjectContainer::ConstIterator boundingObjectsIterator = m_BoundingObjects->Begin();
  const mitk::BoundingObjectGroup::BoundingObjectContainer::ConstIterator boundingObjectsIteratorEnd = m_BoundingObjects->End();

  if(boundingObjectsIterator == boundingObjectsIteratorEnd) // if there is no BoundingObject, the bounding box is zero
  {
    bounds[0] = bounds[1] = bounds[2] = bounds[3] = bounds[4] = bounds[5] = 0.0;
    return;
  }
  mitk::BoundingBox::Pointer boundingBox;
  mitk::BoundingBox::PointType minPoint;
  mitk::BoundingBox::PointType globalMinPoint;
  mitk::BoundingBox::PointType globalMaxPoint;

  /* Initialize globalMin/MaxPoints */
  boundingObjectsIterator.Value()->UpdateOutputInformation();
  boundingBox = const_cast<mitk::BoundingBox*>(boundingObjectsIterator.Value()->GetGeometry()->GetBoundingBox());

  minPoint = boundingBox->GetMinimum();
  mitk::ScalarType min[3];
  min[0] = minPoint[0];   min[1] = minPoint[1];   min[2] = minPoint[2];
  boundingObjectsIterator.Value()->GetGeometry()->GetVtkTransform()->TransformPoint(min, min);
  globalMinPoint[0] = min[0];   globalMinPoint[1] = min[1];   globalMinPoint[2] = min[2];
  globalMaxPoint[0] = min[0];   globalMaxPoint[1] = min[1];   globalMaxPoint[2] = min[2];
  //boundingObjectsIterator++;
  while (boundingObjectsIterator != boundingObjectsIteratorEnd) // calculate a bounding box that includes all BoundingObjects
  {
    boundingObjectsIterator.Value()->UpdateOutputInformation();
    boundingBox = const_cast<mitk::BoundingBox*>(boundingObjectsIterator.Value()->GetGeometry()->GetBoundingBox());

    /* create all 8 points of the bounding box */
    mitk::BoundingBox::PointsContainerPointer points = mitk::BoundingBox::PointsContainer::New();
    mitk::Point3D p;
    p = boundingBox->GetMinimum();
    points->InsertElement(0, p);
    p[0] = -p[0];
    points->InsertElement(1, p);
    p = boundingBox->GetMinimum();
    p[1] = -p[1];
    points->InsertElement(2, p);
    p = boundingBox->GetMinimum();
    p[2] = -p[2];
    points->InsertElement(3, p);
    p = boundingBox->GetMaximum();
    points->InsertElement(4, p);
    p[0] = -p[0];
    points->InsertElement(5, p);
    p = boundingBox->GetMaximum();
    p[1] = -p[1];
    points->InsertElement(6, p);
    p = boundingBox->GetMaximum();
    p[2] = -p[2];
    points->InsertElement(7, p);
    mitk::BoundingBox::PointsContainerConstIterator pointsIterator = points->Begin();
    mitk::BoundingBox::PointsContainerConstIterator pointsIteratorEnd = points->End();
    while (pointsIterator != pointsIteratorEnd) // for each vertex of the bounding box
    {
      minPoint = pointsIterator->Value();
      min[0] = minPoint[0];   min[1] = minPoint[1];   min[2] = minPoint[2];
      boundingObjectsIterator.Value()->GetGeometry()->GetVtkTransform()->TransformPoint(min, min);  // transform vertex point to world coordinates

      globalMinPoint[0] = (min[0] < globalMinPoint[0]) ? min[0] : globalMinPoint[0];  // check if world point
      globalMinPoint[1] = (min[1] < globalMinPoint[1]) ? min[1] : globalMinPoint[1];  // has a lower or a
      globalMinPoint[2] = (min[2] < globalMinPoint[2]) ? min[2] : globalMinPoint[2];  // higher value as
      globalMaxPoint[0] = (min[0] > globalMaxPoint[0]) ? min[0] : globalMaxPoint[0];  // the last known highest
      globalMaxPoint[1] = (min[1] > globalMaxPoint[1]) ? min[1] : globalMaxPoint[1];  // value
      globalMaxPoint[2] = (min[2] > globalMaxPoint[2]) ? min[2] : globalMaxPoint[2];  // in each axis
      pointsIterator++;
    }
    boundingObjectsIterator++;
  }

  /* BoundingBox is centered around the center of all sub bounding objects */
  Vector3D centerPoint;
  centerPoint[0] = (globalMinPoint[0] + globalMaxPoint[0])/ 2.0;
  centerPoint[1] = (globalMinPoint[1] + globalMaxPoint[1])/ 2.0;
  centerPoint[2] = (globalMinPoint[2] + globalMaxPoint[2])/ 2.0;

  bounds[0] = globalMinPoint[0] - centerPoint[0]; // x Min
  bounds[1] = globalMaxPoint[0] - centerPoint[0]; // x Max
  bounds[2] = globalMinPoint[1] - centerPoint[1]; // y Min
  bounds[3] = globalMaxPoint[1] - centerPoint[1]; // y Max
  bounds[4] = globalMinPoint[2] - centerPoint[2]; // z Min
  bounds[5] = globalMaxPoint[2] - centerPoint[2]; // z Max

  mitk::TimeSlicedGeometry::Pointer timeGeometry = const_cast< mitk::TimeSlicedGeometry *>(this->GetTimeSlicedGeometry());
  mitk::Geometry3D::Pointer geometry3d = timeGeometry->GetGeometry3D(0);
  unsigned int timesteps = timeGeometry->GetTimeSteps();
  if(geometry3d.IsNull())
  {
    assert(timesteps==0);
    geometry3d = mitk::Geometry3D::New();
    timesteps = 1;
  }
  else
  {
    assert(timesteps>0);
  }

  /* the objects position is the center of all sub bounding objects */
  geometry3d->SetBounds(bounds);
  geometry3d->Translate(centerPoint);
  geometry3d->TransferItkToVtkTransform();

  timeGeometry->InitializeEvenlyTimed(geometry3d, timesteps);
}

void mitk::BoundingObjectGroup::AddBoundingObject(mitk::BoundingObject::Pointer boundingObject)
{
  m_BoundingObjects->InsertElement( m_Counter++, boundingObject);
  UpdateOutputInformation();
}

bool mitk::BoundingObjectGroup::IsInside(const mitk::Point3D& p) const
{
  mitk::BoundingObjectGroup::BoundingObjectContainer::ConstIterator boundingObjectsIterator = m_BoundingObjects->Begin();
  const mitk::BoundingObjectGroup::BoundingObjectContainer::ConstIterator boundingObjectsIteratorEnd = m_BoundingObjects->End();

  bool inside; // initialize with true for intersection, with false for union

  switch(m_CSGMode)
  {
    case Intersection:
    {
      inside = true;
      while (boundingObjectsIterator != boundingObjectsIteratorEnd) // check each BoundingObject
      {       // calculate intersection: each point, that is inside each BoundingObject is considered inside the group
        inside = boundingObjectsIterator.Value()->IsInside(p) && inside;
        if (!inside) // shortcut, it is enough to find one object that does not contain the point
          break;
        boundingObjectsIterator++;
      }
      break;
    }
    case Difference:
    {
      bool posInside = false;
      bool negInside = false;
      while (boundingObjectsIterator != boundingObjectsIteratorEnd) // check each BoundingObject
      {
        // calculate union: each point, that is inside least one BoundingObject is considered inside the group
        if (boundingObjectsIterator.Value()->GetPositive())
          posInside = boundingObjectsIterator.Value()->IsInside(p) || posInside;
        else
          negInside = boundingObjectsIterator.Value()->IsInside(p) || negInside;

        boundingObjectsIterator++;
      }
      if (posInside && !negInside)
        inside = true;
      else
        inside = false;
      break;
    }
    case Union:
    default:
    {
      inside = false;
      while (boundingObjectsIterator != boundingObjectsIteratorEnd) // check each BoundingObject
      {       // calculate union: each point, that is inside least one BoundingObject is considered inside the group
        inside = boundingObjectsIterator.Value()->IsInside(p) || inside;
        if (inside) // shortcut, it is enough to find one object that contains the point
          break;
        boundingObjectsIterator++;
      }
      break;
    }
  }
  return inside;
}

unsigned int mitk::BoundingObjectGroup::GetCount() const
{
  return m_Counter;
}
<commit_msg>ENH: calculation of boundingbox of all contained boundingboxes (not yet tested) ENH: changes according to general availability of TimeSlicedGeometry in BaseData ENH: removed obsolete VerifyRequestedRegion<commit_after>/*=========================================================================

Program:   Medical Imaging & Interaction Toolkit
Module:    $RCSfile$
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

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

=========================================================================*/

#include "mitkBoundingObjectGroup.h"
#include "mitkBaseProcess.h"
#include <vtkLinearTransform.h>

mitk::BoundingObjectGroup::BoundingObjectGroup()
:  m_Counter(0), m_CSGMode(Difference) //m_CSGMode(Union) m_CSGMode(Intersection)
{
  GetTimeSlicedGeometry()->Initialize(1);
  GetGeometry(0)->SetIndexToWorldTransform(GetTimeSlicedGeometry()->GetIndexToWorldTransform());
  m_BoundingObjects = mitk::BoundingObjectGroup::BoundingObjectContainer::New();
  SetVtkPolyData(NULL);
}

mitk::BoundingObjectGroup::~BoundingObjectGroup()
{
}

void mitk::BoundingObjectGroup::UpdateOutputInformation()
{
  if ( this->GetSource() )
  {
    this->GetSource()->UpdateOutputInformation();
  }

  // calculate global bounding box
  mitk::BoundingObjectGroup::BoundingObjectContainer::ConstIterator boundingObjectsIterator = m_BoundingObjects->Begin();
  const mitk::BoundingObjectGroup::BoundingObjectContainer::ConstIterator boundingObjectsIteratorEnd = m_BoundingObjects->End();

  if(boundingObjectsIterator == boundingObjectsIteratorEnd) // if there is no BoundingObject, the bounding box is zero
  {
    mitk::BoundingBox::BoundsArrayType boundsArray;
    boundsArray.Fill(0);
    GetTimeSlicedGeometry()->Initialize(1);
    GetGeometry()->SetBounds(boundsArray);
    GetTimeSlicedGeometry()->UpdateInformation();
    return;
  }

  // initialize container
  mitk::BoundingBox::PointsContainer::Pointer pointscontainer=mitk::BoundingBox::PointsContainer::New();

  mitk::BoundingBox::PointIdentifier pointid=0;
  mitk::Point3D point;

  mitk::AffineTransform3D* transform = GetTimeSlicedGeometry()->GetIndexToWorldTransform();

  // calculate a bounding box that includes all BoundingObjects
  // \todo probably we should do this additionally for each time-step
  while (boundingObjectsIterator != boundingObjectsIteratorEnd)
  {
    const Geometry3D* geometry = boundingObjectsIterator.Value()->GetUpdatedTimeSlicedGeometry();
    unsigned char i;
    for(i=0; i<8; ++i)
    {
      point = transform->BackTransformPoint(geometry->GetCornerPoint(i));
      if(point[0]*point[0]+point[1]*point[1]+point[2]*point[2] < mitk::large)
        pointscontainer->InsertElement( pointid++, point);
      else
      {
        itkGenericOutputMacro( << "Unrealistically distant corner point encountered. Ignored. BoundingObject: " << boundingObjectsIterator.Value() );
      }
    }
    ++boundingObjectsIterator;
  }

  mitk::BoundingBox::Pointer boundingBox = mitk::BoundingBox::New();
  boundingBox->SetPoints(pointscontainer);
  boundingBox->ComputeBoundingBox();

  /* BoundingBox is centered around the center of all sub bounding objects */
  Point3D center = boundingBox->GetCenter();

  Point3D minimum, maximum;
  minimum.Fill(0); maximum.Fill(0);
  minimum += boundingBox->GetMinimum() - center;
  maximum += boundingBox->GetMaximum() - center;

  boundingBox->SetMinimum(minimum);
  boundingBox->SetMaximum(maximum);

  Geometry3D* geometry3d = GetGeometry(0);
  geometry3d->SetIndexToWorldTransform(transform);
  geometry3d->SetBounds(boundingBox->GetBounds());
  /* the objects position is the center of all sub bounding objects */
  geometry3d->SetOrigin(center);

  GetTimeSlicedGeometry()->InitializeEvenlyTimed(geometry3d, GetTimeSlicedGeometry()->GetTimeSteps());
}

void mitk::BoundingObjectGroup::AddBoundingObject(mitk::BoundingObject::Pointer boundingObject)
{
  m_BoundingObjects->InsertElement( m_Counter++, boundingObject);
  UpdateOutputInformation();
}

bool mitk::BoundingObjectGroup::IsInside(const mitk::Point3D& p) const
{
  mitk::BoundingObjectGroup::BoundingObjectContainer::ConstIterator boundingObjectsIterator = m_BoundingObjects->Begin();
  const mitk::BoundingObjectGroup::BoundingObjectContainer::ConstIterator boundingObjectsIteratorEnd = m_BoundingObjects->End();

  bool inside; // initialize with true for intersection, with false for union

  switch(m_CSGMode)
  {
    case Intersection:
    {
      inside = true;
      while (boundingObjectsIterator != boundingObjectsIteratorEnd) // check each BoundingObject
      {       // calculate intersection: each point, that is inside each BoundingObject is considered inside the group
        inside = boundingObjectsIterator.Value()->IsInside(p) && inside;
        if (!inside) // shortcut, it is enough to find one object that does not contain the point
          break;
        boundingObjectsIterator++;
      }
      break;
    }
    case Difference:
    {
      bool posInside = false;
      bool negInside = false;
      while (boundingObjectsIterator != boundingObjectsIteratorEnd) // check each BoundingObject
      {
        // calculate union: each point, that is inside least one BoundingObject is considered inside the group
        if (boundingObjectsIterator.Value()->GetPositive())
          posInside = boundingObjectsIterator.Value()->IsInside(p) || posInside;
        else
          negInside = boundingObjectsIterator.Value()->IsInside(p) || negInside;

        boundingObjectsIterator++;
      }
      if (posInside && !negInside)
        inside = true;
      else
        inside = false;
      break;
    }
    case Union:
    default:
    {
      inside = false;
      while (boundingObjectsIterator != boundingObjectsIteratorEnd) // check each BoundingObject
      {       // calculate union: each point, that is inside least one BoundingObject is considered inside the group
        inside = boundingObjectsIterator.Value()->IsInside(p) || inside;
        if (inside) // shortcut, it is enough to find one object that contains the point
          break;
        boundingObjectsIterator++;
      }
      break;
    }
  }
  return inside;
}

unsigned int mitk::BoundingObjectGroup::GetCount() const
{
  return m_Counter;
}
<|endoftext|>