<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: colrdlg.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-19 20:59:12 $
 *
 *  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
 *
 ************************************************************************/
#ifndef GCC
#pragma hdrstop
#endif

#include "svtdata.hxx"
#include "colrdlg.hrc"
#include "colrdlg.hxx"

// ---------------
// - ColorDialog -
// ---------------

SvColorDialog::SvColorDialog( Window* pWindow ) :
        ModalDialog     ( pWindow, SvtResId( DLG_COLOR ) ),
        maColMixCtrl    ( this, SvtResId( VAL_SET_COLOR ), 8, 8 ),
        maBtn1          ( this, SvtResId( BTN_1 ) ),
        maBtn2          ( this, SvtResId( BTN_2 ) ),
        //maBtn3            ( this, SvtResId( BTN_3 ) ),
        //maBtn4            ( this, SvtResId( BTN_4 ) ),
        //maFtRGB           ( this, SvtResId( FT_RGB ) ),
        maCtlColor      ( this, SvtResId( CTL_COLOR ) ),

        maFtCyan        ( this, SvtResId( FT_CYAN ) ),
        maNumCyan       ( this, SvtResId( NUM_CYAN ) ),
        maFtMagenta     ( this, SvtResId( FT_MAGENTA ) ),
        maNumMagenta    ( this, SvtResId( NUM_MAGENTA ) ),
        maFtYellow      ( this, SvtResId( FT_YELLOW ) ),
        maNumYellow     ( this, SvtResId( NUM_YELLOW ) ),
        maFtKey         ( this, SvtResId( FT_KEY ) ),
        maNumKey        ( this, SvtResId( NUM_KEY ) ),

        maFtRed         ( this, SvtResId( FT_RED ) ),
        maNumRed        ( this, SvtResId( NUM_RED ) ),
        maFtGreen       ( this, SvtResId( FT_GREEN ) ),
        maNumGreen      ( this, SvtResId( NUM_GREEN ) ),
        maFtBlue        ( this, SvtResId( FT_BLUE ) ),
        maNumBlue       ( this, SvtResId( NUM_BLUE ) ),

        maFtHue         ( this, SvtResId( FT_HUE ) ),
        maNumHue        ( this, SvtResId( NUM_HUE ) ),
        maFtSaturation  ( this, SvtResId( FT_SATURATION ) ),
        maNumSaturation ( this, SvtResId( NUM_SATURATION ) ),
        maFtLuminance   ( this, SvtResId( FT_LUMINANCE ) ),
        maNumLuminance  ( this, SvtResId( NUM_LUMINANCE ) ),

        maCtlPreview    ( this, SvtResId( CTL_PREVIEW ) ),
        maCtlPreviewOld ( this, SvtResId( CTL_PREVIEW_OLD ) ),

        maBtnOK         ( this, SvtResId( BTN_OK ) ),
        maBtnCancel     ( this, SvtResId( BTN_CANCEL ) ),
        maBtnHelp       ( this, SvtResId( BTN_HELP ) )
{
    FreeResource();

    maColMixCtrl.SetDoubleClickHdl( LINK( this, SvColorDialog, ClickMixCtrlHdl ) );
    maColMixCtrl.SetSelectHdl( LINK( this, SvColorDialog, SelectMixCtrlHdl ) );

    Link aLink( LINK( this, SvColorDialog, ColorModifyHdl ) );
    maCtlColor.SetModifyHdl( aLink );

    maNumRed.SetModifyHdl( aLink );
    maNumGreen.SetModifyHdl( aLink );
    maNumBlue.SetModifyHdl( aLink );

    maNumCyan.SetModifyHdl( aLink );
    maNumMagenta.SetModifyHdl( aLink );
    maNumYellow.SetModifyHdl( aLink );
    maNumKey.SetModifyHdl( aLink );

    maNumHue.SetModifyHdl( aLink );
    maNumSaturation.SetModifyHdl( aLink );
    maNumLuminance.SetModifyHdl( aLink );

    aLink = ( LINK( this, SvColorDialog, ClickBtnHdl ) );
    maBtn1.SetClickHdl( aLink );
    maBtn2.SetClickHdl( aLink );
    //maBtn3.SetClickHdl( aLink );
    //maBtn4.SetClickHdl( aLink );

    maColMixCtrl.SetExtraSpacing( 0 );
}

// -----------------------------------------------------------------------
SvColorDialog::~SvColorDialog()
{
}

// -----------------------------------------------------------------------
void SvColorDialog::Initialize()
{
    maNumRed.SetValue( maColor.GetRed() );
    maNumGreen.SetValue( maColor.GetGreen() );
    maNumBlue.SetValue( maColor.GetBlue() );

    ColorCMYK aColorCMYK( maColor );

    long aCyan    = (long) ( (double)aColorCMYK.GetCyan() * 100.0 / 255.0 + 0.5 );
    long aMagenta = (long) ( (double)aColorCMYK.GetMagenta() * 100.0 / 255.0 + 0.5 );
    long aYellow  = (long) ( (double)aColorCMYK.GetYellow() * 100.0 / 255.0 + 0.5 );
    long aKey     = (long) ( (double)aColorCMYK.GetKey() * 100.0 / 255.0 + 0.5 );
    maNumCyan.SetValue( aCyan );
    maNumMagenta.SetValue( aMagenta );
    maNumYellow.SetValue( aYellow );
    maNumKey.SetValue( aKey );

    ColorHSB aColorHSB( maColor );
    maNumHue.SetValue( aColorHSB.GetHue() );
    maNumSaturation.SetValue( aColorHSB.GetSat() );
    maNumLuminance.SetValue( aColorHSB.GetBri() );

    maCtlColor.SetColor( aColorHSB );

    maColMixCtrl.SelectItem( 1 );

    maCtlPreview.SetColor( maColor );
    maCtlPreviewOld.SetColor( maColor );
}

// -----------------------------------------------------------------------
void SvColorDialog::SetColor( const Color& rColor )
{
    maColor = rColor;
}

// -----------------------------------------------------------------------
const Color& SvColorDialog::GetColor() const
{
    return( maColor );
}

// -----------------------------------------------------------------------
IMPL_LINK( SvColorDialog, ColorModifyHdl, void *, p )
{
    UINT16 n = 0x00; // 1 == RGB, 2 == CMYK, 4 == HSB

    if( p == &maCtlColor )
    {
        maColor = maCtlColor.GetColor();
        maNumRed.SetValue( maColor.GetRed() );
        maNumGreen.SetValue( maColor.GetGreen() );
        maNumBlue.SetValue( maColor.GetBlue() );

        n = 7;
    }
    else if( p == &maNumRed )
    {
        maColor.SetRed( (UINT8)maNumRed.GetValue() );
        maCtlColor.SetColor( maColor );
        n = 6;
    }
    else if( p == &maNumGreen )
    {
        maColor.SetGreen( (UINT8)maNumGreen.GetValue() );
        maCtlColor.SetColor( maColor );
        n = 6;
    }
    else if( p == &maNumBlue )
    {
        maColor.SetBlue( (UINT8)maNumBlue.GetValue() );
        maCtlColor.SetColor( maColor );
        n = 6;
    }
    else if( p == &maNumHue ||
             p == &maNumSaturation ||
             p == &maNumLuminance )
    {

        ColorHSB aColorHSB( (UINT16) maNumHue.GetValue(),
                            (UINT16) maNumSaturation.GetValue(),
                            (UINT16) maNumLuminance.GetValue() );
        maCtlColor.SetColor( aColorHSB );
        maColor = maCtlColor.GetColor();
        n = 3;
    }
    else if( p == &maNumCyan ||
             p == &maNumMagenta ||
             p == &maNumYellow ||
             p == &maNumKey )
    {
        long aCyan    = (long) ( (double)maNumCyan.GetValue() * 255.0 / 100.0 + 0.5 );
        long aMagenta = (long) ( (double)maNumMagenta.GetValue() * 255.0 / 100.0 + 0.5 );
        long aYellow  = (long) ( (double)maNumYellow.GetValue() * 255.0 / 100.0 + 0.5 );
        long aKey     = (long) ( (double)maNumKey.GetValue() * 255.0 / 100.0 + 0.5 );

        ColorCMYK aColorCMYK( (UINT16) aCyan,
                              (UINT16) aMagenta,
                              (UINT16) aYellow,
                              (UINT16) aKey );
        maColor = aColorCMYK.GetRGB();
        maCtlColor.SetColor( maColor );
        n = 5;
    }

    if( n & 1 ) // RGB setzen
    {
        maNumRed.SetValue( maColor.GetRed() );
        maNumGreen.SetValue( maColor.GetGreen() );
        maNumBlue.SetValue( maColor.GetBlue() );
    }
    if( n & 2 ) // CMYK setzen
    {
        ColorCMYK aColorCMYK( maColor );
        long aCyan    = (long) ( (double)aColorCMYK.GetCyan() * 100.0 / 255.0 + 0.5 );
        long aMagenta = (long) ( (double)aColorCMYK.GetMagenta() * 100.0 / 255.0 + 0.5 );
        long aYellow  = (long) ( (double)aColorCMYK.GetYellow() * 100.0 / 255.0 + 0.5 );
        long aKey     = (long) ( (double)aColorCMYK.GetKey() * 100.0 / 255.0 + 0.5 );
        maNumCyan.SetValue( aCyan );
        maNumMagenta.SetValue( aMagenta );
        maNumYellow.SetValue( aYellow );
        maNumKey.SetValue( aKey );
    }
    if( n & 4 ) // HSB setzen
    {
        ColorHSB aColorHSB( maColor );
        maNumHue.SetValue( aColorHSB.GetHue() );
        maNumSaturation.SetValue( aColorHSB.GetSat() );
        maNumLuminance.SetValue( aColorHSB.GetBri() );
    }

    maCtlPreview.SetColor( maColor );

    return 0;
}

// -----------------------------------------------------------------------
IMPL_LINK( SvColorDialog, ClickBtnHdl, void *, p )
{
    /*
    Color aColor = maCtlColor.GetColor();
    if( p == &maBtn1 )
        maColMixCtrl.SetColor( CMC_TOPLEFT, aColor );
    if( p == &maBtn2 )
        maColMixCtrl.SetColor( CMC_TOPRIGHT, aColor );
    if( p == &maBtn3 )
        maColMixCtrl.SetColor( CMC_BOTTOMLEFT, aColor );
    if( p == &maBtn4 )
        maColMixCtrl.SetColor( CMC_BOTTOMRIGHT, aColor );
    */

    if( p == &maBtn1 )
    {
        CMCPosition ePos = maColMixCtrl.GetCMCPosition();
        if( ePos != CMC_OTHER )
            maColMixCtrl.SetColor( ePos, maColor );
    }
    else if( p == &maBtn2 )
    {
        USHORT nPos = maColMixCtrl.GetSelectItemId();
        maColor = maColMixCtrl.GetItemColor( nPos );
        maCtlColor.SetColor( maColor );
        ColorModifyHdl( &maCtlColor );
    }

    return 0;
}

// -----------------------------------------------------------------------
IMPL_LINK( SvColorDialog, ClickMixCtrlHdl, void *, EMPTYARG )
{
    USHORT nPos = maColMixCtrl.GetSelectItemId();
    CMCPosition ePos = maColMixCtrl.GetCMCPosition();

    if( ePos != CMC_OTHER )
        maColMixCtrl.SetColor( ePos, maColor );
    else
    {
        maColor = maColMixCtrl.GetItemColor( nPos );
        maCtlColor.SetColor( maColor );
        ColorModifyHdl( &maCtlColor );
    }

    return 0;
}

// -----------------------------------------------------------------------
IMPL_LINK( SvColorDialog, SelectMixCtrlHdl, void *, EMPTYARG )
{
    //USHORT nPos = maColMixCtrl.GetSelectItemId();
    //maFtRGB.SetText( maColMixCtrl.GetItemText( nPos ) );

    CMCPosition ePos = maColMixCtrl.GetCMCPosition();
    if( ePos == CMC_OTHER )
        maBtn1.Enable( FALSE );
    else
        maBtn1.Enable();

    return 0;
}

// -----------------------------------------------------------------------
short SvColorDialog::Execute()
{
    Initialize();

    short nRet = ModalDialog::Execute();

    return( nRet );
}

<commit_msg>INTEGRATION: CWS pchfix02 (1.4.92); FILE MERGED 2006/09/01 17:42:59 kaib 1.4.92.1: #i68856# Added header markers and pch files<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: colrdlg.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 14:43:51 $
 *
 *  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_svtools.hxx"
#ifndef GCC
#endif

#include "svtdata.hxx"
#include "colrdlg.hrc"
#include "colrdlg.hxx"

// ---------------
// - ColorDialog -
// ---------------

SvColorDialog::SvColorDialog( Window* pWindow ) :
        ModalDialog     ( pWindow, SvtResId( DLG_COLOR ) ),
        maColMixCtrl    ( this, SvtResId( VAL_SET_COLOR ), 8, 8 ),
        maBtn1          ( this, SvtResId( BTN_1 ) ),
        maBtn2          ( this, SvtResId( BTN_2 ) ),
        //maBtn3            ( this, SvtResId( BTN_3 ) ),
        //maBtn4            ( this, SvtResId( BTN_4 ) ),
        //maFtRGB           ( this, SvtResId( FT_RGB ) ),
        maCtlColor      ( this, SvtResId( CTL_COLOR ) ),

        maFtCyan        ( this, SvtResId( FT_CYAN ) ),
        maNumCyan       ( this, SvtResId( NUM_CYAN ) ),
        maFtMagenta     ( this, SvtResId( FT_MAGENTA ) ),
        maNumMagenta    ( this, SvtResId( NUM_MAGENTA ) ),
        maFtYellow      ( this, SvtResId( FT_YELLOW ) ),
        maNumYellow     ( this, SvtResId( NUM_YELLOW ) ),
        maFtKey         ( this, SvtResId( FT_KEY ) ),
        maNumKey        ( this, SvtResId( NUM_KEY ) ),

        maFtRed         ( this, SvtResId( FT_RED ) ),
        maNumRed        ( this, SvtResId( NUM_RED ) ),
        maFtGreen       ( this, SvtResId( FT_GREEN ) ),
        maNumGreen      ( this, SvtResId( NUM_GREEN ) ),
        maFtBlue        ( this, SvtResId( FT_BLUE ) ),
        maNumBlue       ( this, SvtResId( NUM_BLUE ) ),

        maFtHue         ( this, SvtResId( FT_HUE ) ),
        maNumHue        ( this, SvtResId( NUM_HUE ) ),
        maFtSaturation  ( this, SvtResId( FT_SATURATION ) ),
        maNumSaturation ( this, SvtResId( NUM_SATURATION ) ),
        maFtLuminance   ( this, SvtResId( FT_LUMINANCE ) ),
        maNumLuminance  ( this, SvtResId( NUM_LUMINANCE ) ),

        maCtlPreview    ( this, SvtResId( CTL_PREVIEW ) ),
        maCtlPreviewOld ( this, SvtResId( CTL_PREVIEW_OLD ) ),

        maBtnOK         ( this, SvtResId( BTN_OK ) ),
        maBtnCancel     ( this, SvtResId( BTN_CANCEL ) ),
        maBtnHelp       ( this, SvtResId( BTN_HELP ) )
{
    FreeResource();

    maColMixCtrl.SetDoubleClickHdl( LINK( this, SvColorDialog, ClickMixCtrlHdl ) );
    maColMixCtrl.SetSelectHdl( LINK( this, SvColorDialog, SelectMixCtrlHdl ) );

    Link aLink( LINK( this, SvColorDialog, ColorModifyHdl ) );
    maCtlColor.SetModifyHdl( aLink );

    maNumRed.SetModifyHdl( aLink );
    maNumGreen.SetModifyHdl( aLink );
    maNumBlue.SetModifyHdl( aLink );

    maNumCyan.SetModifyHdl( aLink );
    maNumMagenta.SetModifyHdl( aLink );
    maNumYellow.SetModifyHdl( aLink );
    maNumKey.SetModifyHdl( aLink );

    maNumHue.SetModifyHdl( aLink );
    maNumSaturation.SetModifyHdl( aLink );
    maNumLuminance.SetModifyHdl( aLink );

    aLink = ( LINK( this, SvColorDialog, ClickBtnHdl ) );
    maBtn1.SetClickHdl( aLink );
    maBtn2.SetClickHdl( aLink );
    //maBtn3.SetClickHdl( aLink );
    //maBtn4.SetClickHdl( aLink );

    maColMixCtrl.SetExtraSpacing( 0 );
}

// -----------------------------------------------------------------------
SvColorDialog::~SvColorDialog()
{
}

// -----------------------------------------------------------------------
void SvColorDialog::Initialize()
{
    maNumRed.SetValue( maColor.GetRed() );
    maNumGreen.SetValue( maColor.GetGreen() );
    maNumBlue.SetValue( maColor.GetBlue() );

    ColorCMYK aColorCMYK( maColor );

    long aCyan    = (long) ( (double)aColorCMYK.GetCyan() * 100.0 / 255.0 + 0.5 );
    long aMagenta = (long) ( (double)aColorCMYK.GetMagenta() * 100.0 / 255.0 + 0.5 );
    long aYellow  = (long) ( (double)aColorCMYK.GetYellow() * 100.0 / 255.0 + 0.5 );
    long aKey     = (long) ( (double)aColorCMYK.GetKey() * 100.0 / 255.0 + 0.5 );
    maNumCyan.SetValue( aCyan );
    maNumMagenta.SetValue( aMagenta );
    maNumYellow.SetValue( aYellow );
    maNumKey.SetValue( aKey );

    ColorHSB aColorHSB( maColor );
    maNumHue.SetValue( aColorHSB.GetHue() );
    maNumSaturation.SetValue( aColorHSB.GetSat() );
    maNumLuminance.SetValue( aColorHSB.GetBri() );

    maCtlColor.SetColor( aColorHSB );

    maColMixCtrl.SelectItem( 1 );

    maCtlPreview.SetColor( maColor );
    maCtlPreviewOld.SetColor( maColor );
}

// -----------------------------------------------------------------------
void SvColorDialog::SetColor( const Color& rColor )
{
    maColor = rColor;
}

// -----------------------------------------------------------------------
const Color& SvColorDialog::GetColor() const
{
    return( maColor );
}

// -----------------------------------------------------------------------
IMPL_LINK( SvColorDialog, ColorModifyHdl, void *, p )
{
    UINT16 n = 0x00; // 1 == RGB, 2 == CMYK, 4 == HSB

    if( p == &maCtlColor )
    {
        maColor = maCtlColor.GetColor();
        maNumRed.SetValue( maColor.GetRed() );
        maNumGreen.SetValue( maColor.GetGreen() );
        maNumBlue.SetValue( maColor.GetBlue() );

        n = 7;
    }
    else if( p == &maNumRed )
    {
        maColor.SetRed( (UINT8)maNumRed.GetValue() );
        maCtlColor.SetColor( maColor );
        n = 6;
    }
    else if( p == &maNumGreen )
    {
        maColor.SetGreen( (UINT8)maNumGreen.GetValue() );
        maCtlColor.SetColor( maColor );
        n = 6;
    }
    else if( p == &maNumBlue )
    {
        maColor.SetBlue( (UINT8)maNumBlue.GetValue() );
        maCtlColor.SetColor( maColor );
        n = 6;
    }
    else if( p == &maNumHue ||
             p == &maNumSaturation ||
             p == &maNumLuminance )
    {

        ColorHSB aColorHSB( (UINT16) maNumHue.GetValue(),
                            (UINT16) maNumSaturation.GetValue(),
                            (UINT16) maNumLuminance.GetValue() );
        maCtlColor.SetColor( aColorHSB );
        maColor = maCtlColor.GetColor();
        n = 3;
    }
    else if( p == &maNumCyan ||
             p == &maNumMagenta ||
             p == &maNumYellow ||
             p == &maNumKey )
    {
        long aCyan    = (long) ( (double)maNumCyan.GetValue() * 255.0 / 100.0 + 0.5 );
        long aMagenta = (long) ( (double)maNumMagenta.GetValue() * 255.0 / 100.0 + 0.5 );
        long aYellow  = (long) ( (double)maNumYellow.GetValue() * 255.0 / 100.0 + 0.5 );
        long aKey     = (long) ( (double)maNumKey.GetValue() * 255.0 / 100.0 + 0.5 );

        ColorCMYK aColorCMYK( (UINT16) aCyan,
                              (UINT16) aMagenta,
                              (UINT16) aYellow,
                              (UINT16) aKey );
        maColor = aColorCMYK.GetRGB();
        maCtlColor.SetColor( maColor );
        n = 5;
    }

    if( n & 1 ) // RGB setzen
    {
        maNumRed.SetValue( maColor.GetRed() );
        maNumGreen.SetValue( maColor.GetGreen() );
        maNumBlue.SetValue( maColor.GetBlue() );
    }
    if( n & 2 ) // CMYK setzen
    {
        ColorCMYK aColorCMYK( maColor );
        long aCyan    = (long) ( (double)aColorCMYK.GetCyan() * 100.0 / 255.0 + 0.5 );
        long aMagenta = (long) ( (double)aColorCMYK.GetMagenta() * 100.0 / 255.0 + 0.5 );
        long aYellow  = (long) ( (double)aColorCMYK.GetYellow() * 100.0 / 255.0 + 0.5 );
        long aKey     = (long) ( (double)aColorCMYK.GetKey() * 100.0 / 255.0 + 0.5 );
        maNumCyan.SetValue( aCyan );
        maNumMagenta.SetValue( aMagenta );
        maNumYellow.SetValue( aYellow );
        maNumKey.SetValue( aKey );
    }
    if( n & 4 ) // HSB setzen
    {
        ColorHSB aColorHSB( maColor );
        maNumHue.SetValue( aColorHSB.GetHue() );
        maNumSaturation.SetValue( aColorHSB.GetSat() );
        maNumLuminance.SetValue( aColorHSB.GetBri() );
    }

    maCtlPreview.SetColor( maColor );

    return 0;
}

// -----------------------------------------------------------------------
IMPL_LINK( SvColorDialog, ClickBtnHdl, void *, p )
{
    /*
    Color aColor = maCtlColor.GetColor();
    if( p == &maBtn1 )
        maColMixCtrl.SetColor( CMC_TOPLEFT, aColor );
    if( p == &maBtn2 )
        maColMixCtrl.SetColor( CMC_TOPRIGHT, aColor );
    if( p == &maBtn3 )
        maColMixCtrl.SetColor( CMC_BOTTOMLEFT, aColor );
    if( p == &maBtn4 )
        maColMixCtrl.SetColor( CMC_BOTTOMRIGHT, aColor );
    */

    if( p == &maBtn1 )
    {
        CMCPosition ePos = maColMixCtrl.GetCMCPosition();
        if( ePos != CMC_OTHER )
            maColMixCtrl.SetColor( ePos, maColor );
    }
    else if( p == &maBtn2 )
    {
        USHORT nPos = maColMixCtrl.GetSelectItemId();
        maColor = maColMixCtrl.GetItemColor( nPos );
        maCtlColor.SetColor( maColor );
        ColorModifyHdl( &maCtlColor );
    }

    return 0;
}

// -----------------------------------------------------------------------
IMPL_LINK( SvColorDialog, ClickMixCtrlHdl, void *, EMPTYARG )
{
    USHORT nPos = maColMixCtrl.GetSelectItemId();
    CMCPosition ePos = maColMixCtrl.GetCMCPosition();

    if( ePos != CMC_OTHER )
        maColMixCtrl.SetColor( ePos, maColor );
    else
    {
        maColor = maColMixCtrl.GetItemColor( nPos );
        maCtlColor.SetColor( maColor );
        ColorModifyHdl( &maCtlColor );
    }

    return 0;
}

// -----------------------------------------------------------------------
IMPL_LINK( SvColorDialog, SelectMixCtrlHdl, void *, EMPTYARG )
{
    //USHORT nPos = maColMixCtrl.GetSelectItemId();
    //maFtRGB.SetText( maColMixCtrl.GetItemText( nPos ) );

    CMCPosition ePos = maColMixCtrl.GetCMCPosition();
    if( ePos == CMC_OTHER )
        maBtn1.Enable( FALSE );
    else
        maBtn1.Enable();

    return 0;
}

// -----------------------------------------------------------------------
short SvColorDialog::Execute()
{
    Initialize();

    short nRet = ModalDialog::Execute();

    return( nRet );
}

<|endoftext|>


<commit_before>//=============================================================================================================
/**
 * @file     icp.cpp
 * @author   Ruben Dörfel <doerfelruben@aol.com>
 * @since    0.1.0
 * @date     July, 2020
 *
 * @section  LICENSE
 *
 * Copyright (C) 2020, Ruben Dörfel. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that
 * the following conditions are met:
 *     * Redistributions of source code must retain the above copyright notice, this list of conditions and the
 *       following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
 *       the following disclaimer in the documentation and/or other materials provided with the distribution.
 *     * Neither the name of MNE-CPP authors nor the names of its contributors may be used
 *       to endorse or promote products derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 *
 * @brief    ICP class definition.
 *
 */

//=============================================================================================================
// INCLUDES
//=============================================================================================================

#include "icp.h"
#include <iostream>

#include "fiff/fiff_coord_trans.h"
#include "mne/mne_project_to_surface.h"

//=============================================================================================================
// QT INCLUDES
//=============================================================================================================

#include <QSharedPointer>
#include <QDebug>

//=============================================================================================================
// EIGEN INCLUDES
//=============================================================================================================

#include <Eigen/Core>
#include <Eigen/Dense>
#include <Eigen/Eigenvalues>
#include <Eigen/Geometry>

//=============================================================================================================
// USED NAMESPACES
//=============================================================================================================

using namespace MNELIB;
using namespace RTPROCESSINGLIB;
using namespace Eigen;
using namespace FIFFLIB;

//=============================================================================================================
// DEFINE GLOBAL METHODS
//=============================================================================================================

//=============================================================================================================
// DEFINE MEMBER METHODS
//=============================================================================================================

ICP::ICP()
{
}

//=============================================================================================================

bool RTPROCESSINGLIB::icp(const MNEProjectToSurface::SPtr mneSurfacePoints,
                          const Eigen::MatrixXf& matPointCloud,
                          FiffCoordTrans& transFromTo,
                          const int iMaxIter,
                          const float fTol,
                          const VectorXf& vecWeitgths)
/**
 * Follow notation of P.J. Besl and N.D. McKay, A Method for
 * Registration of 3-D Shapes, IEEE Trans. Patt. Anal. Machine Intell., 14,
 * 239 - 255, 1992.
 */
{
    // Initialization
    int iNP = matPointCloud.rows();               // The number of points
    float fMSEPrev,fMSE = 0.0;                  // The mean square error
    float fScale = 1.0;
    float bScale = true;
    MatrixXf matP0 = matPointCloud;               // Initial Set of points
    MatrixXf matPk = matP0;                     // Transformed Set of points
    MatrixXf matYk(matPk.rows(),matPk.cols());  // Iterative losest points on the surface
    MatrixXf matDiff = matYk;
    VectorXf vecSE(matDiff.rows());
    Matrix4f matTrans;                          // the transformation matrix
    VectorXi vecNearest;                        // Triangle of the new point
    VectorXf vecDist;                           // The Distance between matX and matP

    // Initial transformation - apply inverse because we are computing in Model space
    FiffCoordTrans transToFrom = transFromTo;
    transToFrom.invert_transform();
    matPk = transToFrom.apply_trans(matPk);

    // Icp algorithm:
    for(int iIter = 0; iIter < iMaxIter; ++iIter) {

        // Step a: compute the closest point on the surface; eq 29
        if(!mneSurfacePoints->mne_find_closest_on_surface(matPk, iNP, matYk, vecNearest, vecDist)) {
            qWarning() << "RTPROCESSINGLIB::icp: mne_find_closest_on_surface was not sucessfull.";
            return false;
        }

        // Step b: compute the registration; eq 30
        if(!fitMatched(matP0, matYk, matTrans, fScale, bScale, vecWeitgths)) {
            qWarning() << "RTPROCESSINGLIB::icp: point cloud registration not succesfull";
        }

        // Step c: apply registration
        transToFrom.trans = matTrans;
        matPk = transToFrom.apply_trans(matP0);

        // step d: compute mean-square-error and terminate if below fTol
        vecDist = vecDist.cwiseProduct(vecDist);
        fMSE = vecDist.sum() / iNP;
        if(std::fabs(fMSE - fMSEPrev) < fTol) {
            transToFrom.invert_transform();
            transFromTo = transToFrom;
            qInfo() << "RTPROCESSINGLIB::icp: ICP was succesfull and exceeded after " << iIter +1 << " Iterations with MSE dist: " << fMSE * 1000 << " mm.";
            return true;
        }
        fMSEPrev = fMSE;
        qInfo() << "RTPROCESSINGLIB::icp: ICP iteration " << iIter + 1 << " with MSE: " << fMSE * 1000 << " mm.";

    }

    qWarning() << "RTPROCESSINGLIB::icp: ICP was not succesfull and exceeded after " << iMaxIter << " Iterations with MSE: " << fMSE * 1000 << " mm.";
    return false;
}

//=============================================================================================================

bool RTPROCESSINGLIB::fitMatched(const MatrixXf& matSrcPoint,
                                 const MatrixXf& matDstPoint,
                                 Eigen::Matrix4f& matTrans,
                                 float fScale,
                                 const bool bScale,
                                 const VectorXf& vecWeitgths)
/**
 * Follow notation of P.J. Besl and N.D. McKay, A Method for
 * Registration of 3-D Shapes, IEEE Trans. Patt. Anal. Machine Intell., 14,
 * 239 - 255, 1992.
 *
 * The code is further adapted from MNE Python function _fitMatched_points(...).
 */
{
    // init values
    MatrixXf matP = matSrcPoint;
    MatrixXf matX = matDstPoint;
    VectorXf vecW = vecWeitgths;
    VectorXf vecMuP;                                // column wise mean - center of mass
    VectorXf vecMuX;                                // column wise mean - center of mass
    MatrixXf matDot;
    MatrixXf matSigmaPX;                            // cross-covariance
    MatrixXf matAij;                                // Anti-Symmetric matrix
    Vector3f vecDelta;                              // column vector, elements of matAij
    Matrix4f matQ = Matrix4f::Identity(4,4);
    Matrix3f matScale = Matrix3f::Identity(3,3);    // scaling matrix
    Matrix3f matRot = Matrix3f::Identity(3,3);
    Vector3f vecTrans;
    float fTrace = 0.0;
    fScale = 1.0;

    // test size of point clouds
    if(matSrcPoint.size() != matDstPoint.size()) {
        qWarning() << "RTPROCESSINGLIB::fitMatched: Point clouds do not match.";
        return false;
    }

    // get center of mass
    if(vecWeitgths.isZero()) {
        vecMuP = matP.colwise().mean(); // eq 23
        vecMuX = matX.colwise().mean();
        matDot = matP.transpose() * matX;
        matDot = matDot / matP.rows();
    } else {
        vecW = vecWeitgths / vecWeitgths.sum();
        vecMuP = vecW.transpose() * matP;
        vecMuX = vecW.transpose() * matX;

        MatrixXf matXWeighted = matX;
        for(int i = 0; i < (vecW.size()); ++i) {
            matXWeighted.row(i) = matXWeighted.row(i) * vecW(i);
        }
        matDot = matP.transpose() * (matXWeighted);
    }

    // get cross-covariance
    matSigmaPX = matDot - (vecMuP * vecMuX.transpose());  // eq 24
    matAij = matSigmaPX - matSigmaPX.transpose();
    vecDelta(0) = matAij(1,2); vecDelta(1) = matAij(2,0); vecDelta(2) = matAij(0,1);
    fTrace = matSigmaPX.trace();
    matQ(0,0) = fTrace; // eq 25
    matQ.block(0,1,1,3) = vecDelta.transpose();
    matQ.block(1,0,3,1) = vecDelta;
    matQ.block(1,1,3,3) = matSigmaPX + matSigmaPX.transpose() - fTrace * MatrixXf::Identity(3,3);

    // unit eigenvector coresponding to maximum eigenvalue of matQ is selected as optimal rotation quaterions q0,q1,q2,q3
    SelfAdjointEigenSolver<MatrixXf> es(matQ);
    Vector4f vecEigVec = es.eigenvectors().col(matQ.cols()-1);  // only take last Eigen-Vector since this corresponds to the maximum Eigenvalue

    // quatRot(w,x,y,z)
    Quaternionf quatRot(vecEigVec(0),vecEigVec(1),vecEigVec(2),vecEigVec(3));
    quatRot.normalize();
    matRot = quatRot.matrix();

    // get scaling factor and matrix
    if(bScale) {
        MatrixXf matDevX = matX.rowwise() - vecMuX.transpose();
        MatrixXf matDevP = matP.rowwise() - vecMuP.transpose();
        matDevX = matDevX.cwiseProduct(matDevX);
        matDevP = matDevP.cwiseProduct(matDevP);

        if(!vecWeitgths.isZero()) {
            for(int i = 0; i < (vecW.size()); ++i) {
                matDevX.row(i) = matDevX.row(i) * vecW(i);
                matDevP.row(i) = matDevP.row(i) * vecW(i);
            }
        }
        // get scaling factor and set scaling matrix
        fScale = std::sqrt(matDevX.sum() / matDevP.sum());
        matScale *= fScale;
    }

    // get translation and Rotation
    vecTrans = vecMuX - fScale * matRot * vecMuP;
    matRot *= matScale;

    matTrans.block<3,3>(0,0) = matRot;
    matTrans.block<3,1>(0,3) = vecTrans;
    matTrans(3,3) = 1.0f;
    matTrans.block<1,3>(3,0) = MatrixXf::Zero(1,3);
    return true;
}

//=========================================================================================================

bool RTPROCESSINGLIB::discardOutliers(const QSharedPointer<MNELIB::MNEProjectToSurface> mneSurfacePoints,
                                      const MatrixXf& matPointCloud,
                                      const FiffCoordTrans& transFromTo,
                                      VectorXi& vecTake,
                                      MatrixXf& matTakePoint,
                                      const float fMaxDist)
{
    // Initialization
    int iNP = matPointCloud.rows();               // The number of points
    MatrixXf matP = matPointCloud;                // Initial Set of points
    MatrixXf matYk(matPointCloud.rows(),matPointCloud.cols());  // Iterative losest points on the surface
    VectorXi vecNearest;                        // Triangle of the new point
    VectorXf vecDist;                           // The Distance between matX and matP

    // Initial transformation - apply inverse because we are computing in Model space
    FiffCoordTrans transToFrom = transFromTo;
    transToFrom.invert_transform();
    matP = transToFrom.apply_trans(matP);

    int iDiscarded = 0;

    // discard outliers if necessary
    if(fMaxDist > 0.0) {
        if(!mneSurfacePoints->mne_find_closest_on_surface(matP, iNP, matYk, vecNearest, vecDist)) {
            qWarning() << "RTPROCESSINGLIB::icp: mne_find_closest_on_surface was not sucessfull.";
            return false;
        }

        for(int i = 0; i < vecDist.size(); ++i) {
            if(std::fabs(vecDist(i)) < fMaxDist) {
                vecTake.conservativeResize(vecTake.size()+1);
                vecTake(vecTake.size()-1) = i;
                matTakePoint.conservativeResize(matTakePoint.rows()+1,3);
                matTakePoint.row(matTakePoint.rows()-1) = matPointCloud.row(i);
            } else {
                iDiscarded++;
            }
        }
    }
    qInfo() << "RTPROCESSINGLIB::discardOutliers: " << iDiscarded << "digitizers discarded.";
}
<commit_msg>Enh: invert coordinate transformtion From point cloud To surface<commit_after>//=============================================================================================================
/**
 * @file     icp.cpp
 * @author   Ruben Dörfel <doerfelruben@aol.com>
 * @since    0.1.0
 * @date     July, 2020
 *
 * @section  LICENSE
 *
 * Copyright (C) 2020, Ruben Dörfel. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that
 * the following conditions are met:
 *     * Redistributions of source code must retain the above copyright notice, this list of conditions and the
 *       following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
 *       the following disclaimer in the documentation and/or other materials provided with the distribution.
 *     * Neither the name of MNE-CPP authors nor the names of its contributors may be used
 *       to endorse or promote products derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 *
 * @brief    ICP class definition.
 *
 */

//=============================================================================================================
// INCLUDES
//=============================================================================================================

#include "icp.h"
#include <iostream>

#include "fiff/fiff_coord_trans.h"
#include "mne/mne_project_to_surface.h"

//=============================================================================================================
// QT INCLUDES
//=============================================================================================================

#include <QSharedPointer>
#include <QDebug>

//=============================================================================================================
// EIGEN INCLUDES
//=============================================================================================================

#include <Eigen/Core>
#include <Eigen/Dense>
#include <Eigen/Eigenvalues>
#include <Eigen/Geometry>

//=============================================================================================================
// USED NAMESPACES
//=============================================================================================================

using namespace MNELIB;
using namespace RTPROCESSINGLIB;
using namespace Eigen;
using namespace FIFFLIB;

//=============================================================================================================
// DEFINE GLOBAL METHODS
//=============================================================================================================

//=============================================================================================================
// DEFINE MEMBER METHODS
//=============================================================================================================

ICP::ICP()
{
}

//=============================================================================================================

bool RTPROCESSINGLIB::icp(const MNEProjectToSurface::SPtr mneSurfacePoints,
                          const Eigen::MatrixXf& matPointCloud,
                          FiffCoordTrans& transFromTo,
                          const int iMaxIter,
                          const float fTol,
                          const VectorXf& vecWeitgths)
/**
 * Follow notation of P.J. Besl and N.D. McKay, A Method for
 * Registration of 3-D Shapes, IEEE Trans. Patt. Anal. Machine Intell., 14,
 * 239 - 255, 1992.
 */
{
    // Initialization
    int iNP = matPointCloud.rows();             // The number of points
    float fMSEPrev,fMSE = 0.0;                  // The mean square error
    float fScale = 1.0;
    float bScale = true;
    MatrixXf matP0 = matPointCloud;             // Initial Set of points
    MatrixXf matPk = matP0;                     // Transformed Set of points
    MatrixXf matYk(matPk.rows(),matPk.cols());  // Iterative closest points on the surface
    MatrixXf matDiff = matYk;
    VectorXf vecSE(matDiff.rows());
    Matrix4f matTrans;                          // the transformation matrix
    VectorXi vecNearest;                        // Triangle of the new point
    VectorXf vecDist;                           // The Distance between matX and matP

    // Initial transformation - From point cloud To surface
    FiffCoordTrans transICP = transFromTo;
    matPk = transICP.apply_trans(matPk);

    // Icp algorithm:
    for(int iIter = 0; iIter < iMaxIter; ++iIter) {

        // Step a: compute the closest point on the surface; eq 29
        if(!mneSurfacePoints->mne_find_closest_on_surface(matPk, iNP, matYk, vecNearest, vecDist)) {
            qWarning() << "RTPROCESSINGLIB::icp: mne_find_closest_on_surface was not sucessfull.";
            return false;
        }

        // Step b: compute the registration; eq 30
        if(!fitMatched(matP0, matYk, matTrans, fScale, bScale, vecWeitgths)) {
            qWarning() << "RTPROCESSINGLIB::icp: point cloud registration not succesfull";
        }

        // Step c: apply registration
        transICP.trans = matTrans;
        matPk = transICP.apply_trans(matP0);

        // step d: compute mean-square-error and terminate if below fTol
        vecDist = vecDist.cwiseProduct(vecDist);
        fMSE = vecDist.sum() / iNP;
        if(std::fabs(fMSE - fMSEPrev) < fTol) {
            transFromTo = transICP;
            qInfo() << "RTPROCESSINGLIB::icp: ICP was succesfull and exceeded after " << iIter +1 << " Iterations with MSE dist: " << fMSE * 1000 << " mm.";
            return true;
        }
        fMSEPrev = fMSE;
        qInfo() << "RTPROCESSINGLIB::icp: ICP iteration " << iIter + 1 << " with MSE: " << fMSE * 1000 << " mm.";

    }

    qWarning() << "RTPROCESSINGLIB::icp: ICP was not succesfull and exceeded after " << iMaxIter << " Iterations with MSE: " << fMSE * 1000 << " mm.";
    return false;
}

//=============================================================================================================

bool RTPROCESSINGLIB::fitMatched(const MatrixXf& matSrcPoint,
                                 const MatrixXf& matDstPoint,
                                 Eigen::Matrix4f& matTrans,
                                 float fScale,
                                 const bool bScale,
                                 const VectorXf& vecWeitgths)
/**
 * Follow notation of P.J. Besl and N.D. McKay, A Method for
 * Registration of 3-D Shapes, IEEE Trans. Patt. Anal. Machine Intell., 14,
 * 239 - 255, 1992.
 *
 * The code is further adapted from MNE Python function _fitMatched_points(...).
 */
{
    // init values
    MatrixXf matP = matSrcPoint;
    MatrixXf matX = matDstPoint;
    VectorXf vecW = vecWeitgths;
    VectorXf vecMuP;                                // column wise mean - center of mass
    VectorXf vecMuX;                                // column wise mean - center of mass
    MatrixXf matDot;
    MatrixXf matSigmaPX;                            // cross-covariance
    MatrixXf matAij;                                // Anti-Symmetric matrix
    Vector3f vecDelta;                              // column vector, elements of matAij
    Matrix4f matQ = Matrix4f::Identity(4,4);
    Matrix3f matScale = Matrix3f::Identity(3,3);    // scaling matrix
    Matrix3f matRot = Matrix3f::Identity(3,3);
    Vector3f vecTrans;
    float fTrace = 0.0;
    fScale = 1.0;

    // test size of point clouds
    if(matSrcPoint.size() != matDstPoint.size()) {
        qWarning() << "RTPROCESSINGLIB::fitMatched: Point clouds do not match.";
        return false;
    }

    // get center of mass
    if(vecWeitgths.isZero()) {
        vecMuP = matP.colwise().mean(); // eq 23
        vecMuX = matX.colwise().mean();
        matDot = matP.transpose() * matX;
        matDot = matDot / matP.rows();
    } else {
        vecW = vecWeitgths / vecWeitgths.sum();
        vecMuP = vecW.transpose() * matP;
        vecMuX = vecW.transpose() * matX;

        MatrixXf matXWeighted = matX;
        for(int i = 0; i < (vecW.size()); ++i) {
            matXWeighted.row(i) = matXWeighted.row(i) * vecW(i);
        }
        matDot = matP.transpose() * (matXWeighted);
    }

    // get cross-covariance
    matSigmaPX = matDot - (vecMuP * vecMuX.transpose());  // eq 24
    matAij = matSigmaPX - matSigmaPX.transpose();
    vecDelta(0) = matAij(1,2); vecDelta(1) = matAij(2,0); vecDelta(2) = matAij(0,1);
    fTrace = matSigmaPX.trace();
    matQ(0,0) = fTrace; // eq 25
    matQ.block(0,1,1,3) = vecDelta.transpose();
    matQ.block(1,0,3,1) = vecDelta;
    matQ.block(1,1,3,3) = matSigmaPX + matSigmaPX.transpose() - fTrace * MatrixXf::Identity(3,3);

    // unit eigenvector coresponding to maximum eigenvalue of matQ is selected as optimal rotation quaterions q0,q1,q2,q3
    SelfAdjointEigenSolver<MatrixXf> es(matQ);
    Vector4f vecEigVec = es.eigenvectors().col(matQ.cols()-1);  // only take last Eigen-Vector since this corresponds to the maximum Eigenvalue

    // quatRot(w,x,y,z)
    Quaternionf quatRot(vecEigVec(0),vecEigVec(1),vecEigVec(2),vecEigVec(3));
    quatRot.normalize();
    matRot = quatRot.matrix();

    // get scaling factor and matrix
    if(bScale) {
        MatrixXf matDevX = matX.rowwise() - vecMuX.transpose();
        MatrixXf matDevP = matP.rowwise() - vecMuP.transpose();
        matDevX = matDevX.cwiseProduct(matDevX);
        matDevP = matDevP.cwiseProduct(matDevP);

        if(!vecWeitgths.isZero()) {
            for(int i = 0; i < (vecW.size()); ++i) {
                matDevX.row(i) = matDevX.row(i) * vecW(i);
                matDevP.row(i) = matDevP.row(i) * vecW(i);
            }
        }
        // get scaling factor and set scaling matrix
        fScale = std::sqrt(matDevX.sum() / matDevP.sum());
        matScale *= fScale;
    }

    // get translation and Rotation
    vecTrans = vecMuX - fScale * matRot * vecMuP;
    matRot *= matScale;

    matTrans.block<3,3>(0,0) = matRot;
    matTrans.block<3,1>(0,3) = vecTrans;
    matTrans(3,3) = 1.0f;
    matTrans.block<1,3>(3,0) = MatrixXf::Zero(1,3);
    return true;
}

//=========================================================================================================

bool RTPROCESSINGLIB::discardOutliers(const QSharedPointer<MNELIB::MNEProjectToSurface> mneSurfacePoints,
                                      const MatrixXf& matPointCloud,
                                      const FiffCoordTrans& transFromTo,
                                      VectorXi& vecTake,
                                      MatrixXf& matTakePoint,
                                      const float fMaxDist)
{
    // Initialization
    int iNP = matPointCloud.rows();               // The number of points
    MatrixXf matP = matPointCloud;                // Initial Set of points
    MatrixXf matYk(matPointCloud.rows(),matPointCloud.cols());  // Iterative losest points on the surface
    VectorXi vecNearest;                        // Triangle of the new point
    VectorXf vecDist;                           // The Distance between matX and matP

    // Initial transformation - From point cloud To surface
    matP = transFromTo.apply_trans(matP);

    int iDiscarded = 0;

    // discard outliers if necessary
    if(fMaxDist > 0.0) {
        if(!mneSurfacePoints->mne_find_closest_on_surface(matP, iNP, matYk, vecNearest, vecDist)) {
            qWarning() << "RTPROCESSINGLIB::icp: mne_find_closest_on_surface was not sucessfull.";
            return false;
        }

        for(int i = 0; i < vecDist.size(); ++i) {
            if(std::fabs(vecDist(i)) < fMaxDist) {
                vecTake.conservativeResize(vecTake.size()+1);
                vecTake(vecTake.size()-1) = i;
                matTakePoint.conservativeResize(matTakePoint.rows()+1,3);
                matTakePoint.row(matTakePoint.rows()-1) = matPointCloud.row(i);
            } else {
                iDiscarded++;
            }
        }
    }
    qInfo() << "RTPROCESSINGLIB::discardOutliers: " << iDiscarded << "digitizers discarded.";
}
<|endoftext|>


<commit_before>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)
//
// Contributors: Kirsten Weber

#ifndef DUNE_GDT_EVALUATION_ELLIPTIC_HH
#define DUNE_GDT_EVALUATION_ELLIPTIC_HH

#include <tuple>
#include <type_traits>

#include <dune/stuff/common/disable_warnings.hh>
# include <dune/common/dynmatrix.hh>
# include <dune/common/typetraits.hh>
#include <dune/stuff/common/reenable_warnings.hh>
#include <type_traits>

#include <dune/stuff/functions/interfaces.hh>

#include "interface.hh"

namespace Dune {
namespace GDT {
namespace LocalEvaluation {

// forwards
template< class DiffusionFactorType, class DiffusionTensorType = void >
class Elliptic;

namespace internal {

/**
 *  \brief  Traits for the Elliptic evaluation.
 */
template< class DiffusionFactorType, class DiffusionTensorType >
class EllipticTraits
{
  static_assert(std::is_base_of< Dune::Stuff::IsLocalizableFunction, DiffusionFactorType >::value,
                "DiffusionFactorType has to be derived from Stuff::IsLocalizableFunction.");
  static_assert(std::is_base_of< Dune::Stuff::IsLocalizableFunction, DiffusionTensorType >::value,
                "DiffusionTensorType has to be derived from Stuff::IsLocalizableFunction.");
public:
  typedef Elliptic< DiffusionFactorType, DiffusionTensorType > derived_type;

};

template< class LocalizableFunctionImp >
class EllipticTraits< LocalizableFunctionImp, void >
{
  static_assert(std::is_base_of< Dune::Stuff::IsLocalizableFunction, LocalizableFunctionImp >::value,
                 "LocalizableFunctionImp has to be derived from Stuff::IsLocalizableFunction.");
 public:
   typedef LocalizableFunctionImp                                LocalizableFunctionType;
   typedef Elliptic< LocalizableFunctionType, void > derived_type;
   typedef typename LocalizableFunctionType::EntityType          EntityType;
   typedef typename LocalizableFunctionType::DomainFieldType     DomainFieldType;
   typedef typename LocalizableFunctionType::LocalfunctionType   LocalfunctionType;
   typedef std::tuple< std::shared_ptr< LocalfunctionType > >    LocalfunctionTupleType;
   static const unsigned int dimDomain = LocalizableFunctionType::dimDomain;

};
} // namespace internal

/**
 *  \brief  Computes an elliptic evaluation.
 */
template< class LocalizableFunctionImp >
class Elliptic< LocalizableFunctionImp, void >
  : public LocalEvaluation::Codim0Interface< internal::EllipticTraits< LocalizableFunctionImp, void >, 2 >
{
public:
  typedef internal::EllipticTraits< LocalizableFunctionImp, void > Traits;
  typedef typename Traits::LocalizableFunctionType  LocalizableFunctionType;
  typedef typename Traits::LocalfunctionTupleType   LocalfunctionTupleType;
  typedef typename Traits::EntityType               EntityType;
  typedef typename Traits::DomainFieldType          DomainFieldType;
  static const unsigned int dimDomain = Traits::dimDomain;

  Elliptic(const LocalizableFunctionType& inducingFunction)
    : inducingFunction_(inducingFunction)
  {}

  LocalfunctionTupleType localFunctions(const EntityType& entity) const
  {
    return std::make_tuple(inducingFunction_.local_function(entity));
  }

  /**
   * \brief extracts the local functions and calls the correct order() method
   */
  template< class R, int rT, int rCT, int rA, int rCA >
  size_t order(const LocalfunctionTupleType& localFuncs,
               const Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain, R, rT, rCT >& testBase,
               const Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain, R, rA, rCA >& ansatzBase) const
  {
    const auto localFunction = std::get< 0 >(localFuncs);
    return redirect_order(*localFunction, testBase, ansatzBase);
  }

  /**
   * \brief extracts the local functions and calls the correct evaluate() method
   */
  template< class R, int rT, int rCT, int rA, int rCA >
  void evaluate(const LocalfunctionTupleType& localFuncs,
                const Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain, R, rT, rCT >& testBase,
                const Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain, R, rA, rCA >& ansatzBase,
                const Dune::FieldVector< DomainFieldType, dimDomain >& localPoint,
                Dune::DynamicMatrix< R >& ret) const
  {
    const auto localFunction = std::get< 0 >(localFuncs);
    redirect_evaluate(*localFunction, testBase, ansatzBase, localPoint, ret);
  }

  /**
   *  \brief  Computes an elliptic evaluation for a 2x2 matrix-valued local function and matrix-valued basefunctionsets.
   *  \tparam R RangeFieldType
   *  \note   Unfortunately we need this explicit specialization, otherwise the compiler will complain for 1d grids.
   */
  template< class R >
  void evaluate(const Stuff::LocalfunctionInterface< EntityType, DomainFieldType, dimDomain, R, 2, 2 >& localFunction,
                const Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain, R, 1, 1 >& testBase,
                const Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain, R, 1, 1 >& ansatzBase,
                const Dune::FieldVector< DomainFieldType, dimDomain >& localPoint,
                Dune::DynamicMatrix< R >& ret) const
  {
    evaluate_matrix_valued_(localFunction, testBase, ansatzBase, localPoint, ret);
  }

  /**
   *  \brief  Computes an elliptic evaluation for a 3x3 matrix-valued local function and matrix-valued basefunctionsets.
   *  \tparam R RangeFieldType
   *  \note   Unfortunately we need this explicit specialization, otherwise the compiler will complain for 1d grids.
   */
  template< class R >
  void evaluate(const Stuff::LocalfunctionInterface< EntityType, DomainFieldType, dimDomain, R, 3, 3 >& localFunction,
                const Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain, R, 1, 1 >& testBase,
                const Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain, R, 1, 1 >& ansatzBase,
                const Dune::FieldVector< DomainFieldType, dimDomain >& localPoint,
                Dune::DynamicMatrix< R >& ret) const
  {
    evaluate_matrix_valued_(localFunction, testBase, ansatzBase, localPoint, ret);
  }

private:
  /**
   *  \return localFunction.order() + (testBase.order() - 1) + (ansatzBase.order() - 1)
   */
  template< class R, int rL, int rCL, int rT, int rCT, int rA, int rCA >
  size_t redirect_order(const Stuff::LocalfunctionInterface< EntityType, DomainFieldType, dimDomain, R, rL, rCL >& localFunction,
               const Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain, R, rT, rCT >& testBase,
               const Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain, R, rA, rCA >& ansatzBase) const
  {
    return localFunction.order()
        + std::max(ssize_t(testBase.order()) - 1, ssize_t(0))
        + std::max(ssize_t(ansatzBase.order()) - 1, ssize_t(0));
  } // size_t redirect_order( ... )

  template< class R, int rL, int rCL, int rT, int rCT, int rA, int rCA >
  void redirect_evaluate(const Stuff::LocalfunctionInterface< EntityType, DomainFieldType, dimDomain, R, rL, rCL >& /*localFunction*/,
                const Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain, R, rT, rCT >& /*testBase*/,
                const Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain, R, rA, rCA >& /*ansatzBase*/,
                const Dune::FieldVector< DomainFieldType, dimDomain >& /*localPoint*/,
                Dune::DynamicMatrix< R >& /*ret*/) const
  {
    static_assert(Dune::AlwaysFalse< R >::value, "Not implemented for these dimensions!");
  } // ... redirect_evaluate< ... >(...)

  /**
   *  \brief  Computes an elliptic evaluation for a scalar local function and scalar or vector valued basefunctionsets.
   *  \tparam R RangeFieldType
   */
  template< class R, int r >
  void redirect_evaluate(const Stuff::LocalfunctionInterface< EntityType, DomainFieldType, dimDomain, R, 1, 1 >& localFunction,
                const Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain, R, r, 1 >& testBase,
                const Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain, R, r, 1 >& ansatzBase,
                const Dune::FieldVector< DomainFieldType, dimDomain >& localPoint,
                Dune::DynamicMatrix< R >& ret) const
  {
    typedef typename Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain, R, r, 1 >::JacobianRangeType JacobianRangeType;
    // evaluate local function
    const auto functionValue = localFunction.evaluate(localPoint);
    // evaluate test gradient
    const size_t rows = testBase.size();
    std::vector< JacobianRangeType > testGradients(rows, JacobianRangeType(0));
    testBase.jacobian(localPoint, testGradients);
    // evaluate ansatz gradient
    const size_t cols = ansatzBase.size();
    std::vector< JacobianRangeType > ansatzGradients(cols, JacobianRangeType(0));
    ansatzBase.jacobian(localPoint, ansatzGradients);
    // compute products
    assert(ret.rows() >= rows);
    assert(ret.cols() >= cols);
    for (size_t ii = 0; ii < rows; ++ii) {
      auto& retRow = ret[ii];
      for (size_t jj = 0; jj < cols; ++jj) {
        retRow[jj] = functionValue * (ansatzGradients[jj][0] * testGradients[ii][0]);
      }
    }
  } // ... redirect_evaluate< ..., 1, 1 >(...)

  template< class R >
  void evaluate_matrix_valued_(const Stuff::LocalfunctionInterface< EntityType, DomainFieldType, dimDomain, R, dimDomain, dimDomain >& localFunction,
                               const Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain, R, 1, 1 >& testBase,
                               const Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain, R, 1, 1 >& ansatzBase,
                               const Dune::FieldVector< DomainFieldType, dimDomain >& localPoint,
                               Dune::DynamicMatrix< R >& ret) const
  {
    typedef typename Stuff::LocalfunctionInterface< EntityType, DomainFieldType, dimDomain, R, dimDomain, dimDomain >::RangeType             DiffusionRangeType;
    typedef typename Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain, R, 1, 1 >::JacobianRangeType  JacobianRangeType;
    // evaluate local function
    const DiffusionRangeType functionValue = localFunction.evaluate(localPoint);
    // evaluate test gradient
    const size_t rows = testBase.size();
    std::vector< JacobianRangeType > testGradients(rows, JacobianRangeType(0));
    testBase.jacobian(localPoint, testGradients);
    // evaluate ansatz gradient
    const size_t cols = ansatzBase.size();
    std::vector< JacobianRangeType > ansatzGradients(cols, JacobianRangeType(0));
    ansatzBase.jacobian(localPoint, ansatzGradients);
    // compute products
    assert(ret.rows() >= rows);
    assert(ret.cols() >= cols);
    FieldVector< DomainFieldType, dimDomain > product(0.0);
    for (size_t ii = 0; ii < rows; ++ii) {
      auto& retRow = ret[ii];
      for (size_t jj = 0; jj < cols; ++jj) {
        functionValue.mv(ansatzGradients[jj][0], product);
        retRow[jj] = product * testGradients[ii][0];
      }
    }
  } // ... evaluate_matrix_valued_(...)

  const LocalizableFunctionType& inducingFunction_;
}; // class LocalElliptic

} // namespace Evaluation
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_EVALUATION_ELLIPTIC_HH
<commit_msg>[localevaluation.elliptic} whitespace<commit_after>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)
//
// Contributors: Kirsten Weber

#ifndef DUNE_GDT_EVALUATION_ELLIPTIC_HH
#define DUNE_GDT_EVALUATION_ELLIPTIC_HH

#include <tuple>
#include <type_traits>

#include <dune/stuff/common/disable_warnings.hh>
# include <dune/common/dynmatrix.hh>
# include <dune/common/typetraits.hh>
#include <dune/stuff/common/reenable_warnings.hh>
#include <type_traits>

#include <dune/stuff/functions/interfaces.hh>

#include "interface.hh"

namespace Dune {
namespace GDT {
namespace LocalEvaluation {

// forwards
template< class DiffusionFactorType, class DiffusionTensorType = void >
class Elliptic;

namespace internal {

/**
 *  \brief  Traits for the Elliptic evaluation.
 */
template< class DiffusionFactorType, class DiffusionTensorType >
class EllipticTraits
{
  static_assert(std::is_base_of< Dune::Stuff::IsLocalizableFunction, DiffusionFactorType >::value,
                "DiffusionFactorType has to be derived from Stuff::IsLocalizableFunction.");
  static_assert(std::is_base_of< Dune::Stuff::IsLocalizableFunction, DiffusionTensorType >::value,
                "DiffusionTensorType has to be derived from Stuff::IsLocalizableFunction.");
public:
  typedef Elliptic< DiffusionFactorType, DiffusionTensorType > derived_type;

};

template< class LocalizableFunctionImp >
class EllipticTraits< LocalizableFunctionImp, void >
{
  static_assert(std::is_base_of< Dune::Stuff::IsLocalizableFunction, LocalizableFunctionImp >::value,
                "LocalizableFunctionImp has to be derived from Stuff::IsLocalizableFunction.");
public:
  typedef LocalizableFunctionImp                                LocalizableFunctionType;
  typedef Elliptic< LocalizableFunctionType, void >             derived_type;
  typedef typename LocalizableFunctionType::EntityType          EntityType;
  typedef typename LocalizableFunctionType::DomainFieldType     DomainFieldType;
  typedef typename LocalizableFunctionType::LocalfunctionType   LocalfunctionType;
  typedef std::tuple< std::shared_ptr< LocalfunctionType > >    LocalfunctionTupleType;
  static const unsigned int dimDomain = LocalizableFunctionType::dimDomain;
};
} // namespace internal

/**
 *  \brief  Computes an elliptic evaluation.
 */
template< class LocalizableFunctionImp >
class Elliptic< LocalizableFunctionImp, void >
    : public LocalEvaluation::Codim0Interface< internal::EllipticTraits< LocalizableFunctionImp, void >, 2 >
{
public:
  typedef internal::EllipticTraits< LocalizableFunctionImp, void > Traits;
  typedef typename Traits::LocalizableFunctionType  LocalizableFunctionType;
  typedef typename Traits::LocalfunctionTupleType   LocalfunctionTupleType;
  typedef typename Traits::EntityType               EntityType;
  typedef typename Traits::DomainFieldType          DomainFieldType;
  static const unsigned int dimDomain = Traits::dimDomain;

  Elliptic(const LocalizableFunctionType& inducingFunction)
    : inducingFunction_(inducingFunction)
  {}

  LocalfunctionTupleType localFunctions(const EntityType& entity) const
  {
    return std::make_tuple(inducingFunction_.local_function(entity));
  }

  /**
   * \brief extracts the local functions and calls the correct order() method
   */
  template< class R, int rT, int rCT, int rA, int rCA >
  size_t order(const LocalfunctionTupleType& localFuncs,
               const Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain, R, rT, rCT >& testBase,
               const Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain, R, rA, rCA >& ansatzBase) const
  {
    const auto localFunction = std::get< 0 >(localFuncs);
    return redirect_order(*localFunction, testBase, ansatzBase);
  }

  /**
   * \brief extracts the local functions and calls the correct evaluate() method
   */
  template< class R, int rT, int rCT, int rA, int rCA >
  void evaluate(const LocalfunctionTupleType& localFuncs,
                const Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain, R, rT, rCT >& testBase,
                const Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain, R, rA, rCA >& ansatzBase,
                const Dune::FieldVector< DomainFieldType, dimDomain >& localPoint,
                Dune::DynamicMatrix< R >& ret) const
  {
    const auto localFunction = std::get< 0 >(localFuncs);
    redirect_evaluate(*localFunction, testBase, ansatzBase, localPoint, ret);
  }

  /**
   *  \brief  Computes an elliptic evaluation for a 2x2 matrix-valued local function and matrix-valued basefunctionsets.
   *  \tparam R RangeFieldType
   *  \note   Unfortunately we need this explicit specialization, otherwise the compiler will complain for 1d grids.
   */
  template< class R >
  void evaluate(const Stuff::LocalfunctionInterface< EntityType, DomainFieldType, dimDomain, R, 2, 2 >& localFunction,
                const Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain, R, 1, 1 >& testBase,
                const Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain, R, 1, 1 >& ansatzBase,
                const Dune::FieldVector< DomainFieldType, dimDomain >& localPoint,
                Dune::DynamicMatrix< R >& ret) const
  {
    evaluate_matrix_valued_(localFunction, testBase, ansatzBase, localPoint, ret);
  }

  /**
   *  \brief  Computes an elliptic evaluation for a 3x3 matrix-valued local function and matrix-valued basefunctionsets.
   *  \tparam R RangeFieldType
   *  \note   Unfortunately we need this explicit specialization, otherwise the compiler will complain for 1d grids.
   */
  template< class R >
  void evaluate(const Stuff::LocalfunctionInterface< EntityType, DomainFieldType, dimDomain, R, 3, 3 >& localFunction,
                const Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain, R, 1, 1 >& testBase,
                const Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain, R, 1, 1 >& ansatzBase,
                const Dune::FieldVector< DomainFieldType, dimDomain >& localPoint,
                Dune::DynamicMatrix< R >& ret) const
  {
    evaluate_matrix_valued_(localFunction, testBase, ansatzBase, localPoint, ret);
  }

private:
  /**
   *  \return localFunction.order() + (testBase.order() - 1) + (ansatzBase.order() - 1)
   */
  template< class R, int rL, int rCL, int rT, int rCT, int rA, int rCA >
  size_t redirect_order(const Stuff::LocalfunctionInterface< EntityType, DomainFieldType, dimDomain, R, rL, rCL >& localFunction,
                        const Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain, R, rT, rCT >& testBase,
                        const Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain, R, rA, rCA >& ansatzBase) const
  {
    return localFunction.order()
        + std::max(ssize_t(testBase.order()) - 1, ssize_t(0))
        + std::max(ssize_t(ansatzBase.order()) - 1, ssize_t(0));
  } // size_t redirect_order( ... )

  template< class R, int rL, int rCL, int rT, int rCT, int rA, int rCA >
  void redirect_evaluate(const Stuff::LocalfunctionInterface< EntityType, DomainFieldType, dimDomain, R, rL, rCL >& /*localFunction*/,
                         const Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain, R, rT, rCT >& /*testBase*/,
                         const Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain, R, rA, rCA >& /*ansatzBase*/,
                         const Dune::FieldVector< DomainFieldType, dimDomain >& /*localPoint*/,
                         Dune::DynamicMatrix< R >& /*ret*/) const
  {
    static_assert(Dune::AlwaysFalse< R >::value, "Not implemented for these dimensions!");
  } // ... redirect_evaluate< ... >(...)

  /**
   *  \brief  Computes an elliptic evaluation for a scalar local function and scalar or vector valued basefunctionsets.
   *  \tparam R RangeFieldType
   */
  template< class R, int r >
  void redirect_evaluate(const Stuff::LocalfunctionInterface< EntityType, DomainFieldType, dimDomain, R, 1, 1 >& localFunction,
                         const Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain, R, r, 1 >& testBase,
                         const Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain, R, r, 1 >& ansatzBase,
                         const Dune::FieldVector< DomainFieldType, dimDomain >& localPoint,
                         Dune::DynamicMatrix< R >& ret) const
  {
    typedef typename Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain, R, r, 1 >::JacobianRangeType JacobianRangeType;
    // evaluate local function
    const auto functionValue = localFunction.evaluate(localPoint);
    // evaluate test gradient
    const size_t rows = testBase.size();
    std::vector< JacobianRangeType > testGradients(rows, JacobianRangeType(0));
    testBase.jacobian(localPoint, testGradients);
    // evaluate ansatz gradient
    const size_t cols = ansatzBase.size();
    std::vector< JacobianRangeType > ansatzGradients(cols, JacobianRangeType(0));
    ansatzBase.jacobian(localPoint, ansatzGradients);
    // compute products
    assert(ret.rows() >= rows);
    assert(ret.cols() >= cols);
    for (size_t ii = 0; ii < rows; ++ii) {
      auto& retRow = ret[ii];
      for (size_t jj = 0; jj < cols; ++jj) {
        retRow[jj] = functionValue * (ansatzGradients[jj][0] * testGradients[ii][0]);
      }
    }
  } // ... redirect_evaluate< ..., 1, 1 >(...)

  template< class R >
  void evaluate_matrix_valued_(const Stuff::LocalfunctionInterface< EntityType, DomainFieldType, dimDomain, R, dimDomain, dimDomain >& localFunction,
                               const Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain, R, 1, 1 >& testBase,
                               const Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain, R, 1, 1 >& ansatzBase,
                               const Dune::FieldVector< DomainFieldType, dimDomain >& localPoint,
                               Dune::DynamicMatrix< R >& ret) const
  {
    typedef typename Stuff::LocalfunctionInterface< EntityType, DomainFieldType, dimDomain, R, dimDomain, dimDomain >::RangeType             DiffusionRangeType;
    typedef typename Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain, R, 1, 1 >::JacobianRangeType  JacobianRangeType;
    // evaluate local function
    const DiffusionRangeType functionValue = localFunction.evaluate(localPoint);
    // evaluate test gradient
    const size_t rows = testBase.size();
    std::vector< JacobianRangeType > testGradients(rows, JacobianRangeType(0));
    testBase.jacobian(localPoint, testGradients);
    // evaluate ansatz gradient
    const size_t cols = ansatzBase.size();
    std::vector< JacobianRangeType > ansatzGradients(cols, JacobianRangeType(0));
    ansatzBase.jacobian(localPoint, ansatzGradients);
    // compute products
    assert(ret.rows() >= rows);
    assert(ret.cols() >= cols);
    FieldVector< DomainFieldType, dimDomain > product(0.0);
    for (size_t ii = 0; ii < rows; ++ii) {
      auto& retRow = ret[ii];
      for (size_t jj = 0; jj < cols; ++jj) {
        functionValue.mv(ansatzGradients[jj][0], product);
        retRow[jj] = product * testGradients[ii][0];
      }
    }
  } // ... evaluate_matrix_valued_(...)

  const LocalizableFunctionType& inducingFunction_;
}; // class LocalElliptic

} // namespace Evaluation
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_EVALUATION_ELLIPTIC_HH
<|endoftext|>


<commit_before>/**
 * @file audio.cpp
 * @brief Purpose: Contains methods to load, free, play and draw audio.
 *
 * MIT License
 * Copyright (c) 2017 MindScape
 *
 * https://github.com/TecProg2017-2/mindscape/blob/master/LICENSE.md
 */

#include "../include/audio.hpp"
#include "game.hpp"
#include <string>
#include <iostream>
#include "../include/log.hpp"

using namespace engine;

Audio::Audio(
    std::string p_name,
    std::string path,
    AudioType m_type,
    int repeat,
    int chanel)

    :audio_path(path),
    m_audio_type(m_type),
    audio_repeat(repeat),
    audio_chanel(chanel),
    audio_music(NULL),
    audio_chunk(NULL),
    Component(p_name, std::make_pair(0, 0), true, 1) {}

/**
 * @brief This method load the audio.
 *
 * It is important to load and activate the audio, music or chunk, at the game.
 * True to load is OK and false its not OK.
 *
 * @return true or false based in its situation.
 */
bool Audio::load() {
    timer->init();

    if (m_audio_type == MUSIC) {
    /* Separate MUSIC from  CHUNK */
        audio_music = Mix_LoadMUS(audio_path.c_str());

        if (!audio_music) {
        /* Verifys if music is not an null object */
            WARN(("Audio error %s", Mix_GetError()));
            exit(1);

            return false;
        }
        else {
            DEBUG("Music successfully loaded");
        }
    }
    else if (m_audio_type == CHUNK) {
    /* Separate CHUNK from  MUSIC*/
        audio_chunk = Mix_LoadWAV(audio_path.c_str());

        if (!audio_chunk) {
        /* Verifys if chuck is not an null object */
            WARN(("Audio error %s", Mix_GetError()));
            exit(1);

            return false;
        }
        else {
            DEBUG("Chunk successfully loaded");
        }
    }
    else {
    /* In case of there is no audio type called MUSIC or CHUCK it will be dispared and hadle the error */
        WARN(("Error loading the audio in this path: %s",
        audio_path.c_str()));

        return false;
    }

    activate();

    return true;
}

/**
 * @brief Stop the audio of the game.
 *
 * It is important to free audio, chunk and free memory, when program was closed.
 *
 * @return void.
 */
void Audio::free() {
    /* SDL function to delete music and chunk */
    Mix_FreeMusic(audio_music);
    Mix_FreeChunk(audio_chunk);

    /* Poiting music and chuck to NULL */
    audio_music = NULL;
    audio_chunk = NULL;
}

/**
 * @brief This method play effects.
 *
 * It is important to play a effect based in the time and in the scene wheres player is.
 *
 * @return void.
 */
void Audio::play_effect() {
    /* Stores the time of song */
    time += timer->time_elapsed() - aux_time;
    aux_time = timer->time_elapsed();

    if (audio_chunk != NULL) {
    /* Validates audio chuck */
        if (time >= effect_duration) {
        /* Effect will only be stoped when time is bigger than the effect duration */
            playing = false;
            time = 0;
        }
        else {
            /*Do nothing*/
        }

        if (!playing) {
        /* Plays the sound effect */
            time = 0;
            playing = true;

            /* Apply volume and play with random chanel */
            Mix_VolumeChunk(audio_chunk, volume);
            Mix_PlayChannel(audio_chanel, audio_chunk, audio_repeat);
        }
        else {
            /*Do nothing*/
        }
    }
    else {
        /*Do nothing*/
    }
}

/**
 * @brief This method set the volume of the effect.
 *
 * It is important to dont pass the limit of the volume.
 * That is a condition to validate the limit.
 *
 * @param integer to identify the nivel of the effect volume.
 * @return void.
 */
 void Audio::set_effect_volume(int _volume) {
    if (_volume > -1 && volume < 129) {
    /* Limits volume to be in a rate of 0 to 128 */
        volume = _volume;
        DEBUG(("Sound effect volume set to %d", _volume));
    }
    else {
        WARN("The volume must be between 0 and 128");
    }
}

void Audio::draw(int x, int y) {
  // if(m_audio_type == MUSIC){
  //   is_active();
  //   if( Mix_PlayingMusic() == 0 )
  //     {
  //       //Play the music
  //       Mix_PlayMusic(audio_music, -1 );
  //     }
  //     if(Mix_PlayingMusic() == 1){
  //       Mix_ResumeMusic();
  //     }
  //   }
}

/**
 * @brief This method play music type.
 *
 * It is important to play music based in the theme and to ambientize the player at the game.
 * That is a validation to know if resume or play the music.
 *
 * @return void.
 */
void Audio::play_music_type() {
    if (audio_music != NULL) {
    /* Validates audio chuck */
        is_active();

        if (Mix_PlayingMusic() == 0) {
        /* Verification to know if will play or resume music */

            const int fade_time = 500;

            if(Mix_FadeInMusic(audio_music, -1, fade_time)==-1) {
                INFO("Fade in is finished.");
            } else {
                /* Applies the fade in to starts the music. */
            }

            DEBUG("Music is being played");
        }
        else if (Mix_PlayingMusic() == 1) {
        /* Verification to know if will play or resume music */
            Mix_ResumeMusic();
            DEBUG("Music is being resumed");
        }
        else {
            /*Do nothing*/
        }
    }
    else {
        /*Do nothing*/
    }
}

/**
 * @brief This method pause the music of the game.
 *
 * It is important to pause a music when the player think it is necessary.
 *
 * @return void.
 */
void Audio::pause_music() {
    if (m_audio_type == MUSIC && Mix_PlayingMusic()) {
    /* Case is a music and is playing it, it can be paused here */
        Mix_PauseMusic();

        /* Constants to define the fade time and the delay of the fade. */
        const int fade_time = 500;
        const int delay = 100;

        while(!Mix_FadeOutMusic(fade_time) && Mix_PlayingMusic()) {
            SDL_Delay(delay);
        }
        DEBUG("Music is being paused");
    }
    else {
        /*Do nothing*/
    }
}

/**
 * @brief This method set the quantity of repetitions of the music.
 *
 * That is a condition to set the repeat.
 *
 * @param integer to know how many times is to repeat the music.
 * @return void.
 */
void Audio::set_repetitions(int repeat) {
    if (audio_music != NULL) {
    /* Validates if music is not a null object */
        audio_repeat = repeat;
        //load();
    }
    else {
        /*Do nothing*/
    }
}

/**
 * @brief This method set the duration of the effect.
 *
 * It is important for the effect of the audio to last longer.
 *
 * @param integer to know how the duration of the effect.
 * @return void.
 */
void Audio::set_duration(float duration) {
    effect_duration = 0;
    effect_duration = duration * 1000;
    DEBUG(("Function: %s - effect_duration: %f", __func__, effect_duration));
}

/**
 * @brief This method stop the effect.
 *
 * It is important to aplly this method to stop the effect after finish the duration/action.
 *
 * @return void.
 */
void Audio::stop_effect() {
    if (audio_chunk != NULL) {
    /* Validates if chuck is not a null object */
        Mix_VolumeChunk(audio_chunk, 0);
        DEBUG("Audio effect stopped");
    }

    else {
        /*Do nothing*/
    }
}

/**
 * @brief This method set the volume of the music.
 *
 * It is important to dont pass the limit of the volume.
 * That is a validate to increase and to decrease volume of the music.
 *
 * @param integer to identify the nivel of the music volume.
 * @return void.
 */
void Audio::set_music_volume(int _volume) {
    if (audio_music != NULL) {
        if (_volume > -1 && volume < 129) {
        /* Limits volume to be in a rate of 0 to 128 */
            Mix_VolumeMusic(_volume);
            DEBUG(("Music volume set to %d", _volume));
        }
        else {
            WARN("The volume must be between 0 and 128");
        }
    }
}
<commit_msg>[FIX] Modifies loop repetitions when plays the music<commit_after>/**
 * @file audio.cpp
 * @brief Purpose: Contains methods to load, free, play and draw audio.
 *
 * MIT License
 * Copyright (c) 2017 MindScape
 *
 * https://github.com/TecProg2017-2/mindscape/blob/master/LICENSE.md
 */

#include "../include/audio.hpp"
#include "game.hpp"
#include <string>
#include <iostream>
#include "../include/log.hpp"

using namespace engine;

Audio::Audio(
    std::string p_name,
    std::string path,
    AudioType m_type,
    int repeat,
    int chanel)

    :audio_path(path),
    m_audio_type(m_type),
    audio_repeat(repeat),
    audio_chanel(chanel),
    audio_music(NULL),
    audio_chunk(NULL),
    Component(p_name, std::make_pair(0, 0), true, 1) {}

/**
 * @brief This method load the audio.
 *
 * It is important to load and activate the audio, music or chunk, at the game.
 * True to load is OK and false its not OK.
 *
 * @return true or false based in its situation.
 */
bool Audio::load() {
    timer->init();

    if (m_audio_type == MUSIC) {
    /* Separate MUSIC from  CHUNK */
        audio_music = Mix_LoadMUS(audio_path.c_str());

        if (!audio_music) {
        /* Verifys if music is not an null object */
            WARN(("Audio error %s", Mix_GetError()));
            exit(1);

            return false;
        }
        else {
            DEBUG("Music successfully loaded");
        }
    }
    else if (m_audio_type == CHUNK) {
    /* Separate CHUNK from  MUSIC*/
        audio_chunk = Mix_LoadWAV(audio_path.c_str());

        if (!audio_chunk) {
        /* Verifys if chuck is not an null object */
            WARN(("Audio error %s", Mix_GetError()));
            exit(1);

            return false;
        }
        else {
            DEBUG("Chunk successfully loaded");
        }
    }
    else {
    /* In case of there is no audio type called MUSIC or CHUCK it will be dispared and hadle the error */
        WARN(("Error loading the audio in this path: %s",
        audio_path.c_str()));

        return false;
    }

    activate();

    return true;
}

/**
 * @brief Stop the audio of the game.
 *
 * It is important to free audio, chunk and free memory, when program was closed.
 *
 * @return void.
 */
void Audio::free() {
    /* SDL function to delete music and chunk */
    Mix_FreeMusic(audio_music);
    Mix_FreeChunk(audio_chunk);

    /* Poiting music and chuck to NULL */
    audio_music = NULL;
    audio_chunk = NULL;
}

/**
 * @brief This method play effects.
 *
 * It is important to play a effect based in the time and in the scene wheres player is.
 *
 * @return void.
 */
void Audio::play_effect() {
    /* Stores the time of song */
    time += timer->time_elapsed() - aux_time;
    aux_time = timer->time_elapsed();

    if (audio_chunk != NULL) {
    /* Validates audio chuck */
        if (time >= effect_duration) {
        /* Effect will only be stoped when time is bigger than the effect duration */
            playing = false;
            time = 0;
        }
        else {
            /*Do nothing*/
        }

        if (!playing) {
        /* Plays the sound effect */
            time = 0;
            playing = true;

            /* Apply volume and play with random chanel */
            Mix_VolumeChunk(audio_chunk, volume);
            Mix_PlayChannel(audio_chanel, audio_chunk, audio_repeat);
        }
        else {
            /*Do nothing*/
        }
    }
    else {
        /*Do nothing*/
    }
}

/**
 * @brief This method set the volume of the effect.
 *
 * It is important to dont pass the limit of the volume.
 * That is a condition to validate the limit.
 *
 * @param integer to identify the nivel of the effect volume.
 * @return void.
 */
 void Audio::set_effect_volume(int _volume) {
    if (_volume > -1 && volume < 129) {
    /* Limits volume to be in a rate of 0 to 128 */
        volume = _volume;
        DEBUG(("Sound effect volume set to %d", _volume));
    }
    else {
        WARN("The volume must be between 0 and 128");
    }
}

void Audio::draw(int x, int y) {
  // if(m_audio_type == MUSIC){
  //   is_active();
  //   if( Mix_PlayingMusic() == 0 )
  //     {
  //       //Play the music
  //       Mix_PlayMusic(audio_music, -1 );
  //     }
  //     if(Mix_PlayingMusic() == 1){
  //       Mix_ResumeMusic();
  //     }
  //   }
}

/**
 * @brief This method play music type.
 *
 * It is important to play music based in the theme and to ambientize the player at the game.
 * That is a validation to know if resume or play the music.
 *
 * @return void.
 */
void Audio::play_music_type() {
    if (audio_music != NULL) {
    /* Validates audio chuck */
        is_active();

        if (Mix_PlayingMusic() == 0) {
        /* Verification to know if will play or resume music */

            const int fade_time = 500;

            if(Mix_FadeInMusic(audio_music, 0, fade_time)==-1) {
                INFO("Fade in is finished.");
            } else {
                /* Applies the fade in to starts the music. */
            }

            DEBUG("Music is being played");
        }
        else if (Mix_PlayingMusic() == 1) {
        /* Verification to know if will play or resume music */
            Mix_ResumeMusic();
            DEBUG("Music is being resumed");
        }
        else {
            /*Do nothing*/
        }
    }
    else {
        /*Do nothing*/
    }
}

/**
 * @brief This method pause the music of the game.
 *
 * It is important to pause a music when the player think it is necessary.
 *
 * @return void.
 */
void Audio::pause_music() {
    if (m_audio_type == MUSIC && Mix_PlayingMusic()) {
    /* Case is a music and is playing it, it can be paused here */
        Mix_PauseMusic();

        /* Constants to define the fade time and the delay of the fade. */
        const int fade_time = 500;
        const int delay = 100;

        while(!Mix_FadeOutMusic(fade_time) && Mix_PlayingMusic()) {
            SDL_Delay(delay);
        }
        DEBUG("Music is being paused");
    }
    else {
        /*Do nothing*/
    }
}

/**
 * @brief This method set the quantity of repetitions of the music.
 *
 * That is a condition to set the repeat.
 *
 * @param integer to know how many times is to repeat the music.
 * @return void.
 */
void Audio::set_repetitions(int repeat) {
    if (audio_music != NULL) {
    /* Validates if music is not a null object */
        audio_repeat = repeat;
        //load();
    }
    else {
        /*Do nothing*/
    }
}

/**
 * @brief This method set the duration of the effect.
 *
 * It is important for the effect of the audio to last longer.
 *
 * @param integer to know how the duration of the effect.
 * @return void.
 */
void Audio::set_duration(float duration) {
    effect_duration = 0;
    effect_duration = duration * 1000;
    DEBUG(("Function: %s - effect_duration: %f", __func__, effect_duration));
}

/**
 * @brief This method stop the effect.
 *
 * It is important to aplly this method to stop the effect after finish the duration/action.
 *
 * @return void.
 */
void Audio::stop_effect() {
    if (audio_chunk != NULL) {
    /* Validates if chuck is not a null object */
        Mix_VolumeChunk(audio_chunk, 0);
        DEBUG("Audio effect stopped");
    }

    else {
        /*Do nothing*/
    }
}

/**
 * @brief This method set the volume of the music.
 *
 * It is important to dont pass the limit of the volume.
 * That is a validate to increase and to decrease volume of the music.
 *
 * @param integer to identify the nivel of the music volume.
 * @return void.
 */
void Audio::set_music_volume(int _volume) {
    if (audio_music != NULL) {
        if (_volume > -1 && volume < 129) {
        /* Limits volume to be in a rate of 0 to 128 */
            Mix_VolumeMusic(_volume);
            DEBUG(("Music volume set to %d", _volume));
        }
        else {
            WARN("The volume must be between 0 and 128");
        }
    }
}
<|endoftext|>