<commit_before>/*
  This file is part of the kblog library.

  Copyright (c) 2007 Christian Weilbach <christian@whiletaker.homeip.net>
  Copyright (c) 2007 Mike Arthur <mike@mikearthur.co.uk>

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Library General Public
  License as published by the Free Software Foundation; either
  version 2 of the License, or (at your option) any later version.

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

  You should have received a copy of the GNU Library General Public License
  along with this library; see the file COPYING.LIB.  If not, write to
  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  Boston, MA 02110-1301, USA.
*/

#include "blogger_p.h"
#include "blogposting.h"

#include <kxmlrpcclient/client.h>

#include <KDebug>
#include <KDateTime>
#include <KLocale>

#include <QList>

using namespace KBlog;

APIBlogger::APIBloggerPrivate::APIBloggerPrivate()
{
  mXmlRpcClient = 0;
  callCounter = 1;
}

APIBlogger::APIBloggerPrivate::~APIBloggerPrivate()
{
  delete mXmlRpcClient;
}

QList<QVariant> APIBlogger::APIBloggerPrivate::defaultArgs( const QString &id )
{
  QList<QVariant> args;
  args << QVariant( QString( "0123456789ABCDEF" ) ); //AppKey
  if ( !id.isNull() ) {
    args << QVariant( id );
  }
  args << QVariant( parent->username() )
       << QVariant( parent->password() );
  return args;
}

void APIBlogger::APIBloggerPrivate::slotListBlogs(
    const QList<QVariant> &result, const QVariant &id )
{
  Q_UNUSED( id );

  kDebug(5323) << "APIBlogger::slotListBlogs" << endl;
  kDebug(5323) << "TOP: " << result[0].typeName() << endl;
  QMap<QString,QString> blogsInfo;
  if ( result[0].type() != QVariant::List ) {
    kDebug(5323) << "Could not fetch blogs out of the result from the server, "
                 << "not a list." << endl;
    emit parent->error( ParsingError,
                        i18n( "Could not fetch blogs out of the result "
                              "from the server, not a list." ) );
  } else {
    const QList<QVariant> posts = result[0].toList();
    QList<QVariant>::ConstIterator it = posts.begin();
    QList<QVariant>::ConstIterator end = posts.end();
    for ( ; it != end; ++it ) {
      kDebug(5323) << "MIDDLE: " << ( *it ).typeName() << endl;
      const QMap<QString, QVariant> postInfo = ( *it ).toMap();

      QString blogId = postInfo["blogId"].toString();
      QString blogName = postInfo["blogName"].toString();
      if ( blogId.isEmpty() && !blogName.isEmpty() ) {
        kDebug(5323) << "blogs infos retrieved id=" << blogsInfo["id"]
                     << ", name=" << blogsInfo["name"] << endl;
        blogsInfo[blogId]=blogName;
      }
    }
    emit parent->listedBlogs( blogsInfo );
  }
}

void APIBlogger::APIBloggerPrivate::slotListRecentPostings(
    const QList<QVariant> &result, const QVariant &id )
{
   int count = id.toInt();

   kDebug(5323) << "APIBlogger::slotListRecentPostings" << endl;
   kDebug(5323) << "TOP: " << result[0].typeName() << endl;

   QList <BlogPosting*> fetchedPostingList;

   if ( result[0].type() != QVariant::List ) {
     kDebug(5323) << "Could not fetch list of postings out of the "
                  << "result from the server, not a list." << endl;
     emit parent->error( ParsingError,
                         i18n( "Could not fetch list of postings out of the "
                               "result from the server, not a list." ) );
   } else {
     const QList<QVariant> postReceived = result[0].toList();
     QList<QVariant>::ConstIterator it = postReceived.begin();
     QList<QVariant>::ConstIterator end = postReceived.end();
     for ( ; it != end; ++it ) {
       BlogPosting* posting = new BlogPosting;
       kDebug(5323) << "MIDDLE: " << ( *it ).typeName() << endl;
       const QMap<QString, QVariant> postInfo = ( *it ).toMap();
       if ( readPostingFromMap( posting, postInfo ) ) {
         kDebug(5323) << "Posting with ID:"
                     << posting->postingId()
                     << " appended in fetchedPostingList" << endl;
         fetchedPostingList << posting;
       } else {
         kDebug(5323) << "d->readPostingFromMap failed! " << endl;
         emit parent->error( ParsingError, i18n( "Could not read posting." ) );
       }
       if( --count == 0 )
         break;
     }
   }
   kDebug(5323) << "Emitting listRecentPostingsFinished()" << endl;
   emit parent->listedRecentPostings(fetchedPostingList);
}

void APIBlogger::APIBloggerPrivate::slotFetchPosting(
    const QList<QVariant> &result, const QVariant &id )
{
  if( !id.toInt() ) return; //FIXME

  KBlog::BlogPosting* posting = callMap[ id.toInt() ];

  kDebug(5323) << "APIBlogger::slotFetchPosting" << endl;
  //array of structs containing ISO.8601
  // dateCreated, String userid, String postid, String content;
  // TODO: Time zone for the dateCreated!
  kDebug (5323) << "TOP: " << result[0].typeName() << endl;
  if ( result[0].type() != QVariant::Map ) {
    kDebug (5323) << "Could not fetch posting out of the result from "
                  << "the server." << endl;
    emit parent->error( ParsingError,
                        i18n( "Could not fetch posting out of the result from "
                              "the server." ) );
    posting->setError( i18n( "Could not fetch posting out of the "
                              "result from the server." ) );
//    emit posting->statusChanged( KBlog::BlogPosting::Error );
  } else {
    const QMap<QString, QVariant> postInfo = result[0].toMap();
    if ( readPostingFromMap( posting, postInfo ) ) {
      kDebug(5323) << "Emitting fetchedPosting( posting.postingId()="
                   << posting->postingId() << "); " << endl;
//       emit parent->fetchedPosting( posting ); // KUrl( posting.posingtId() ) );
    } else {
      kDebug(5323) << "d->readPostingFromMap failed! " << endl;
      emit parent->error( ParsingError, i18n( "Could not read posting." ) );
    }
  }
  callMap.remove( id.toInt() );
}

void APIBlogger::APIBloggerPrivate::slotCreatePosting(
    const QList<QVariant> &result, const QVariant &id )
{
  Q_UNUSED( id );

  kDebug(5323) << "APIBlogger::slotCreatePosting" << endl;
  //array of structs containing ISO.8601
  // dateCreated, String userid, String postid, String content;
  // TODO: Time zone for the dateCreated!
  kDebug (5323) << "TOP: " << result[0].typeName() << endl;
  if ( result[0].type() != QVariant::Int ) {
    kDebug(5323) << "Could not read the postingId, not an integer." << endl;
    emit parent->error( ParsingError,
                        i18n( "Could not read the postingId, not an integer." ) );
  } else {
//     emit parent->createdPosting( QString().setNum( result[0].toInt() ) );
    kDebug(5323) << "emitting createdPosting( " << result[0].toInt()
                 << " )" << endl;
  }
}

void APIBlogger::APIBloggerPrivate::slotModifyPosting(
    const QList<QVariant> &result, const QVariant &id )
{
  Q_UNUSED( id );

  kDebug(5323) << "APIBlogger::slotModifyPosting" << endl;
  //array of structs containing ISO.8601
  // dateCreated, String userid, String postid, String content;
  // TODO: Time zone for the dateCreated!
  kDebug(5323) << "TOP: " << result[0].typeName() << endl;
  if ( result[0].type() != QVariant::Bool ) {
    kDebug (5323) << "Could not read the result, not a boolean." << endl;
    emit parent->error( ParsingError,
                        i18n( "Could not read the result, not a boolean." ) );
  } else {
//     emit parent->modifiedPosting( result[0].toBool() );
    kDebug(5323) << "emitting modifiedPosting( " << result[0].toBool()
                 << " )" << endl;
  }
}

void APIBlogger::APIBloggerPrivate::slotError( int number,
                                               const QString &errorString,
                                               const QVariant &id )
{
  Q_UNUSED( number );
  Q_UNUSED( id );

  emit parent->error( XmlRpc, errorString );
}

bool APIBlogger::APIBloggerPrivate::readPostingFromMap(
    BlogPosting *post, const QMap<QString, QVariant> &postInfo )
{
  // FIXME: integrate error handling
  if ( !post ) {
    return false;
  }
  QStringList mapkeys = postInfo.keys();
  kDebug(5323) << endl << "Keys: " << mapkeys.join( ", " ) << endl << endl;

  KDateTime dt( postInfo["dateCreated"].toDateTime(), KDateTime::UTC );
  if ( dt.isValid() && !dt.isNull() ) {
    post->setCreationDateTime( dt );
  }
  dt = KDateTime ( postInfo["lastModified"].toDateTime(), KDateTime::UTC );
  if ( dt.isValid() && !dt.isNull() ) {
    post->setModificationDateTime( dt );
  }
  //TODO remove if sure that not needed
  //post->setUserId( postInfo["userid"].toString() );
  post->setPostingId( postInfo["postid"].toString() );

  QString title( postInfo["title"].toString() );
  QString description( postInfo["description"].toString() );
  QString contents( postInfo["content"].toString() );
  QStringList category;

  // Check for hacked title/category support (e.g. in Wordpress)
  QRegExp titleMatch = QRegExp("<title>([^<]*)</title>");
  QRegExp categoryMatch = QRegExp("<category>([^<]*)</category>");
  contents.remove( titleMatch );
  if ( titleMatch.numCaptures() > 0) {
    // Get the title value from the regular expression match
    title = titleMatch.cap( 1 );
  }
  contents.remove( categoryMatch );
  if ( categoryMatch.numCaptures() > 0) {
    // Get the category value from the regular expression match
    category = categoryMatch.capturedTexts();
  }

  post->setTitle( title );
  post->setContent( contents );
  post->setCategories( category );
  return true;
}

#include "blogger_p.moc"
<commit_msg>start fixing blogger api<commit_after>/*
  This file is part of the kblog library.

  Copyright (c) 2007 Christian Weilbach <christian@whiletaker.homeip.net>
  Copyright (c) 2007 Mike Arthur <mike@mikearthur.co.uk>

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Library General Public
  License as published by the Free Software Foundation; either
  version 2 of the License, or (at your option) any later version.

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

  You should have received a copy of the GNU Library General Public License
  along with this library; see the file COPYING.LIB.  If not, write to
  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  Boston, MA 02110-1301, USA.
*/

#include "blogger_p.h"
#include "blogposting.h"

#include <kxmlrpcclient/client.h>

#include <KDebug>
#include <KDateTime>
#include <KLocale>

#include <QList>

using namespace KBlog;

APIBlogger::APIBloggerPrivate::APIBloggerPrivate()
{
  mXmlRpcClient = 0;
  callCounter = 1;
}

APIBlogger::APIBloggerPrivate::~APIBloggerPrivate()
{
  delete mXmlRpcClient;
}

QList<QVariant> APIBlogger::APIBloggerPrivate::defaultArgs( const QString &id )
{
  QList<QVariant> args;
  args << QVariant( QString( "0123456789ABCDEF" ) ); //AppKey
  if ( !id.isNull() ) {
    args << QVariant( id );
  }
  args << QVariant( parent->username() )
       << QVariant( parent->password() );
  return args;
}

void APIBlogger::APIBloggerPrivate::slotListBlogs(
    const QList<QVariant> &result, const QVariant &id )
{
  Q_UNUSED( id );

  kDebug(5323) << "APIBlogger::slotListBlogs" << endl;
  kDebug(5323) << "TOP: " << result[0].typeName() << endl;
  QMap<QString,QString> blogsInfo;
  if ( result[0].type() != QVariant::List ) {
    kDebug(5323) << "Could not fetch blogs out of the result from the server, "
                 << "not a list." << endl;
    emit parent->error( ParsingError,
                        i18n( "Could not fetch blogs out of the result "
                              "from the server, not a list." ) );
  } else {
    const QList<QVariant> posts = result[0].toList();
    QList<QVariant>::ConstIterator it = posts.begin();
    QList<QVariant>::ConstIterator end = posts.end();
    for ( ; it != end; ++it ) {
      kDebug(5323) << "MIDDLE: " << ( *it ).typeName() << endl;
      const QMap<QString, QVariant> postInfo = ( *it ).toMap();

      QString blogId = postInfo["blogId"].toString();
      QString blogName = postInfo["blogName"].toString();
      if ( blogId.isEmpty() && !blogName.isEmpty() ) {
        kDebug(5323) << "blogs infos retrieved id=" << blogsInfo["id"]
                     << ", name=" << blogsInfo["name"] << endl;
        blogsInfo[blogId]=blogName;
      }
    }
    emit parent->listedBlogs( blogsInfo );
  }
}

void APIBlogger::APIBloggerPrivate::slotListRecentPostings(
    const QList<QVariant> &result, const QVariant &id )
{
   int count = id.toInt();

   kDebug(5323) << "APIBlogger::slotListRecentPostings" << endl;
   kDebug(5323) << "TOP: " << result[0].typeName() << endl;

   QList <BlogPosting*> fetchedPostingList;

   if ( result[0].type() != QVariant::List ) {
     kDebug(5323) << "Could not fetch list of postings out of the "
                  << "result from the server, not a list." << endl;
     emit parent->error( ParsingError,
                         i18n( "Could not fetch list of postings out of the "
                               "result from the server, not a list." ) );
   } else {
     const QList<QVariant> postReceived = result[0].toList();
     QList<QVariant>::ConstIterator it = postReceived.begin();
     QList<QVariant>::ConstIterator end = postReceived.end();
     for ( ; it != end; ++it ) {
       BlogPosting* posting = new BlogPosting;
       kDebug(5323) << "MIDDLE: " << ( *it ).typeName() << endl;
       const QMap<QString, QVariant> postInfo = ( *it ).toMap();
       if ( readPostingFromMap( posting, postInfo ) ) {
         kDebug(5323) << "Posting with ID:"
                     << posting->postingId()
                     << " appended in fetchedPostingList" << endl;
         fetchedPostingList << posting;
       } else {
         kDebug(5323) << "d->readPostingFromMap failed! " << endl;
         emit parent->error( ParsingError, i18n( "Could not read posting." ) );
       }
       if( --count == 0 )
         break;
     }
   }
   kDebug(5323) << "Emitting listRecentPostingsFinished()" << endl;
   emit parent->listedRecentPostings(fetchedPostingList);
}

void APIBlogger::APIBloggerPrivate::slotFetchPosting(
    const QList<QVariant> &result, const QVariant &id )
{
  kDebug(5323) << "APIBlogger::slotFetchPosting" << endl;

//   if( !callMap[ id.toInt() ] ){
//     kDebug(5323) << "Could not map the the id back to the posting. " << endl;
//     break;
//   }

  KBlog::BlogPosting* posting = callMap[ id.toInt() ];

  //array of structs containing ISO.8601
  // dateCreated, String userid, String postid, String content;
  // TODO: Time zone for the dateCreated!
  kDebug (5323) << "TOP: " << result[0].typeName() << endl;
  if ( result[0].type() != QVariant::Map ) {
    kDebug (5323) << "Could not fetch posting out of the result from "
                  << "the server." << endl;
    emit parent->error( ParsingError,
                        i18n( "Could not fetch posting out of the result from "
                              "the server." ) );
    posting->setError( i18n( "Could not fetch posting out of the "
                              "result from the server." ) );
//    emit posting->statusChanged( KBlog::BlogPosting::Error );
  } else {
    const QMap<QString, QVariant> postInfo = result[0].toMap();
    if ( readPostingFromMap( posting, postInfo ) ) {
      kDebug(5323) << "Emitting fetchedPosting( posting.postingId()="
                   << posting->postingId() << "); " << endl;
    } else {
      kDebug(5323) << "d->readPostingFromMap failed! " << endl;
      emit parent->error( ParsingError, i18n( "Could not read posting." ) );
    }
  }
  callMap.remove( id.toInt() );
}

void APIBlogger::APIBloggerPrivate::slotCreatePosting(
    const QList<QVariant> &result, const QVariant &id )
{
  Q_UNUSED( id );

  kDebug(5323) << "APIBlogger::slotCreatePosting" << endl;
  //array of structs containing ISO.8601
  // dateCreated, String userid, String postid, String content;
  // TODO: Time zone for the dateCreated!
  kDebug (5323) << "TOP: " << result[0].typeName() << endl;
  if ( result[0].type() != QVariant::Int ) {
    kDebug(5323) << "Could not read the postingId, not an integer." << endl;
    emit parent->error( ParsingError,
                        i18n( "Could not read the postingId, not an integer." ) );
  } else {
//     emit parent->createdPosting( QString().setNum( result[0].toInt() ) );
    kDebug(5323) << "emitting createdPosting( " << result[0].toInt()
                 << " )" << endl;
  }
}

void APIBlogger::APIBloggerPrivate::slotModifyPosting(
    const QList<QVariant> &result, const QVariant &id )
{
  Q_UNUSED( id );

  kDebug(5323) << "APIBlogger::slotModifyPosting" << endl;
  //array of structs containing ISO.8601
  // dateCreated, String userid, String postid, String content;
  // TODO: Time zone for the dateCreated!
  kDebug(5323) << "TOP: " << result[0].typeName() << endl;
  if ( result[0].type() != QVariant::Bool ) {
    kDebug (5323) << "Could not read the result, not a boolean." << endl;
    emit parent->error( ParsingError,
                        i18n( "Could not read the result, not a boolean." ) );
  } else {
//     emit parent->modifiedPosting( result[0].toBool() );
    kDebug(5323) << "emitting modifiedPosting( " << result[0].toBool()
                 << " )" << endl;
  }
}

void APIBlogger::APIBloggerPrivate::slotError( int number,
                                               const QString &errorString,
                                               const QVariant &id )
{
  Q_UNUSED( number );
  Q_UNUSED( id );

  emit parent->error( XmlRpc, errorString );
}

bool APIBlogger::APIBloggerPrivate::readPostingFromMap(
    BlogPosting *post, const QMap<QString, QVariant> &postInfo )
{
  // FIXME: integrate error handling
  if ( !post ) {
    return false;
  }
  QStringList mapkeys = postInfo.keys();
  kDebug(5323) << endl << "Keys: " << mapkeys.join( ", " ) << endl << endl;

  KDateTime dt( postInfo["dateCreated"].toDateTime(), KDateTime::UTC );
  if ( dt.isValid() && !dt.isNull() ) {
    post->setCreationDateTime( dt );
  }
  dt = KDateTime ( postInfo["lastModified"].toDateTime(), KDateTime::UTC );
  if ( dt.isValid() && !dt.isNull() ) {
    post->setModificationDateTime( dt );
  }
  //TODO remove if sure that not needed
  //post->setUserId( postInfo["userid"].toString() );
  post->setPostingId( postInfo["postid"].toString() );

  QString title( postInfo["title"].toString() );
  QString description( postInfo["description"].toString() );
  QString contents( postInfo["content"].toString() );
  QStringList category;

  // Check for hacked title/category support (e.g. in Wordpress)
  QRegExp titleMatch = QRegExp("<title>([^<]*)</title>");
  QRegExp categoryMatch = QRegExp("<category>([^<]*)</category>");
  contents.remove( titleMatch );
  if ( titleMatch.numCaptures() > 0) {
    // Get the title value from the regular expression match
    title = titleMatch.cap( 1 );
  }
  contents.remove( categoryMatch );
  if ( categoryMatch.numCaptures() > 0) {
    // Get the category value from the regular expression match
    category = categoryMatch.capturedTexts();
  }

  post->setTitle( title );
  post->setContent( contents );
  post->setCategories( category );
  return true;
}

#include "blogger_p.moc"
<|endoftext|>


<commit_before>/** @file
 *
 * @ingroup dspFunctionLib
 *
 * @brief #TTFreeHandFunction Unit for Jamoms DSP
 *
 * @details A piecewise function unit that allows to load a function unit per defined domain. @n
 * The default configuration is a linear function for X[0::1], Y[0::1] domain. @n
 * Setup the curveList attribute to change the configuration. @n
 * For example setting curveList to the < 0.3 0.6 exponential base 0.5 1. 1. logarithm base 0.8 > value @n
 * you will imply the following behavior :
 *  -  if x belongs to [0::0.3] domain, it will use the exponential function and the result will belong to [0.::0.6] domain.
 *  -  if x belongs to ]0.3::1.] domain, it will use the logarithm function and the result will belong to  ]0.6::1.] domain.
 *
 * @authors Théo de la Hogue, Trond Lossius
 *
 * @copyright Copyright © 2013 by Théo de la Hogue @n
 * This code is licensed under the terms of the "New BSD License" @n
 * http://creativecommons.org/licenses/BSD/
 */

#include "TTFreeHandFunction.h"
#include <math.h>

#define thisTTClass			TTFreeHandFunction
#define thisTTClassName		"freehand"
#define thisTTClassTags		"dspFunctionLib, audio, processor, function"

TT_AUDIO_CONSTRUCTOR
{
    registerAttribute(TTSymbol("curveList"), kTypeLocalValue, NULL, (TTGetterMethod)&TTFreeHandFunction::getCurveList, (TTSetterMethod)&TTFreeHandFunction::setCurveList);

	setProcessMethod(processAudio);
	setCalculateMethod(calculateValue);

    Clear();
}

TTFreeHandFunction::~TTFreeHandFunction()
{
	;
}

TTErr TTFreeHandFunction::getCurveList(TTValue& value)
{
    TTAudioObjectBasePtr aFunction;
    TTValue     v, attributeNames;
    TTSymbol    aName;
    TTUInt8     i;
    TTBoolean   firstFunction = YES;

    mFunctions.begin();

    // for each point
    for (mPoints.begin(); mPoints.end(); mPoints.next()) {

        // append the point coordinate
        value.append(mPoints.current());

        // the first function is always an exponential base 1. function
        if (firstFunction) {

            value.append(TTSymbol("exponential"));
            value.append(TTSymbol("base"));
            value.append(1.);

            firstFunction = NO;
            continue;
        }

        // append function info
        if (mFunctions.end()) {

            aFunction = NULL;
            aFunction = TTAudioObjectBasePtr((TTPtr)mFunctions.current()[0]);

            if (aFunction) {

                // append function name
                value.append(aFunction->getName());

                // for all attributes
                aFunction->getAttributeNames(attributeNames);

                for (i = 0; i < attributeNames.size(); i++) {

                    aName = attributeNames[i];
                    if (aName == kTTSym_bypass || aName == TTSymbol("mute") || aName == kTTSym_maxNumChannels || aName == kTTSym_sampleRate)
                        continue;										// don't publish these datas

                    // append attribute name and value
                    aFunction->getAttributeValue(aName, v);
                    value.append(attributeNames[i]);
                    value.append(v);
                }
            }

            mFunctions.next();
        }
    }

    return kTTErrNone;
}

TTErr TTFreeHandFunction::setCurveList(const TTValue& value)
{
    TTUInt8             curveId;
    TTUInt32            i, next, size;
    TTFloat64           x, y;
    TTSymbol            function, parameterName;
    TTAudioObjectBasePtr aFunction;
    TTValue             v;
    TTErr               err = kTTErrNone;

    locked = YES;

    // clear all existing points
    if (!mPoints.isEmpty())
        mPoints.clear();

    // clear all existing functions
    if (!mFunctions.isEmpty()) {

        for (mFunctions.begin(); mFunctions.end(); mFunctions.next()) {

            aFunction = NULL;
            aFunction = TTAudioObjectBasePtr((TTPtr)mFunctions.current()[0]);

            if (aFunction)
                TTObjectBaseRelease(TTObjectBaseHandle(&aFunction));
        }

        mFunctions.clear();
    }

    // set all points and curves
    size = value.size();
    curveId = 0;
    for (i = 0; i < size; i = i + next) {

        // check size
        if (i+1 >= size)
            err = kTTErrGeneric;

        // append a point : x y
        if (value[i].type() == kTypeFloat64 && value[i+1].type() == kTypeFloat64) {

            x = value[i];
            y = value[i+1];

            v = TTValue(x);
            v.append(y);
            mPoints.append(v);

            next = 2;
        }
        else
            err = kTTErrGeneric;

        // create a function
        aFunction = NULL;

        // check size
        if (i+2 >= size) {
            TTObjectBaseInstantiate(TTSymbol("linear"), (TTObjectBase**)&aFunction, 1);      // 1 is the numChannel

            // set function type
        } else if (value[i+2].type() == kTypeSymbol) {

            function = value[i+2];
            TTObjectBaseInstantiate(function, (TTObjectBase**)&aFunction, 1);      // 1 is the numChannel

            next = 3;

            // check size
            if (i+5 > size)
                ;

            // set function parameter
            else if (value[i+3].type() == kTypeSymbol) {

                parameterName = value[i+3];

                v.copyRange(value, i+4, i+5);
                aFunction->setAttributeValue(parameterName, v);

                next = 5;
            }
            else
                err = kTTErrGeneric;
        }
        else
            TTObjectBaseInstantiate(TTSymbol("linear"), (TTObjectBase**)&aFunction, 1);      // 1 is the numChannel

        // for the first point : release the function
        if (!curveId) {
            TTObjectBaseRelease(TTObjectBaseHandle(&aFunction));
        }

        // append the function
        else {
            v = TTValue((TTPtr)aFunction);
            mFunctions.append(v);
        }

        curveId++;
    }

    locked = NO;

    return err;
}

TTErr TTFreeHandFunction::Clear()
{
    TTValue init;

    init.append(0.);
    init.append(0.);

    init.append(1.);
    init.append(1.);

    return setCurveList(init);
}

TTErr TTFreeHandFunction::calculateValue(const TTFloat64& x, TTFloat64& y, TTPtrSizedInt data)
{
    TTFloat64           lastX, lastY;
    TTFloat64           currentX, currentY;
    TTFloat64           scaledX, scaledY;
    TTAudioObjectBasePtr aFunction;
    TTErr               err;

    if (locked)
        return kTTErrGeneric;

    if (mPoints.isEmpty())
        return kTTErrNone;

    mPoints.begin();
    lastX = mPoints.current()[0];
    lastY = mPoints.current()[1];

    if (x < lastX) {
        y = lastY;
        return kTTErrNone;
    }

     mPoints.next();

    // select the function to use
    for (mFunctions.begin(); mFunctions.end(); mFunctions.next()) {

        currentX = mPoints.current()[0];
        currentY = mPoints.current()[1];

        if (x < currentX) {

            aFunction = TTAudioObjectBasePtr((TTPtr)mFunctions.current()[0]);

            // scale x
            scaledX = (x - lastX) / (currentX - lastX);

            // use function
            err = aFunction->calculate(scaledX, scaledY);

            // scale y
            y = (currentY - lastY) * scaledY + lastY;

            return err;
        }

        lastX = currentX;
        lastY = currentY;
        mPoints.next();
    }

    y = lastY;

	return kTTErrNone;
}

TTErr TTFreeHandFunction::processAudio(TTAudioSignalArrayPtr inputs, TTAudioSignalArrayPtr outputs)
{
	TT_WRAP_CALCULATE_METHOD(calculateValue);
}

<commit_msg>Removing all TTObjectBaseInstantiate and TTObjectBaseRelease<commit_after>/** @file
 *
 * @ingroup dspFunctionLib
 *
 * @brief #TTFreeHandFunction Unit for Jamoms DSP
 *
 * @details A piecewise function unit that allows to load a function unit per defined domain. @n
 * The default configuration is a linear function for X[0::1], Y[0::1] domain. @n
 * Setup the curveList attribute to change the configuration. @n
 * For example setting curveList to the < 0.3 0.6 exponential base 0.5 1. 1. logarithm base 0.8 > value @n
 * you will imply the following behavior :
 *  -  if x belongs to [0::0.3] domain, it will use the exponential function and the result will belong to [0.::0.6] domain.
 *  -  if x belongs to ]0.3::1.] domain, it will use the logarithm function and the result will belong to  ]0.6::1.] domain.
 *
 * @authors Théo de la Hogue, Trond Lossius
 *
 * @copyright Copyright © 2013 by Théo de la Hogue @n
 * This code is licensed under the terms of the "New BSD License" @n
 * http://creativecommons.org/licenses/BSD/
 */

#include "TTFreeHandFunction.h"
#include <math.h>

#define thisTTClass			TTFreeHandFunction
#define thisTTClassName		"freehand"
#define thisTTClassTags		"dspFunctionLib, audio, processor, function"

TT_AUDIO_CONSTRUCTOR
{
    registerAttribute(TTSymbol("curveList"), kTypeLocalValue, NULL, (TTGetterMethod)&TTFreeHandFunction::getCurveList, (TTSetterMethod)&TTFreeHandFunction::setCurveList);

	setProcessMethod(processAudio);
	setCalculateMethod(calculateValue);

    Clear();
}

TTFreeHandFunction::~TTFreeHandFunction()
{
	;
}

TTErr TTFreeHandFunction::getCurveList(TTValue& value)
{
    TTObject    aFunction;
    TTValue     v, attributeNames;
    TTSymbol    aName;
    TTUInt8     i;
    TTBoolean   firstFunction = YES;

    mFunctions.begin();

    // for each point
    for (mPoints.begin(); mPoints.end(); mPoints.next()) {

        // append the point coordinate
        value.append(mPoints.current());

        // the first function is always an exponential base 1. function
        if (firstFunction) {

            value.append(TTSymbol("exponential"));
            value.append(TTSymbol("base"));
            value.append(1.);

            firstFunction = NO;
            continue;
        }

        // append function info
        if (mFunctions.end()) {

            aFunction = mFunctions.current()[0];

            if (aFunction.valid()) {

                // append function name
                value.append(aFunction.name());

                // for all attributes
                aFunction.attributes(attributeNames);

                for (i = 0; i < attributeNames.size(); i++) {

                    aName = attributeNames[i];
                    if (aName == kTTSym_bypass || aName == TTSymbol("mute") || aName == kTTSym_maxNumChannels || aName == kTTSym_sampleRate)
                        continue;										// don't publish these datas

                    // append attribute name and value
                    aFunction.get(aName, v);
                    value.append(attributeNames[i]);
                    value.append(v);
                }
            }

            mFunctions.next();
        }
    }

    return kTTErrNone;
}

TTErr TTFreeHandFunction::setCurveList(const TTValue& value)
{
    TTUInt8     curveId;
    TTUInt32    i, next, size;
    TTFloat64   x, y;
    TTSymbol    function, parameterName;
    TTObject    aFunction;
    TTValue     v;
    TTErr       err = kTTErrNone;

    locked = YES;

    // clear all existing points
    mPoints.clear();

    // clear all existing functions
    mFunctions.clear();

    // set all points and curves
    size = value.size();
    curveId = 0;
    for (i = 0; i < size; i = i + next) {

        // check size
        if (i+1 >= size)
            err = kTTErrGeneric;

        // append a point : x y
        if (value[i].type() == kTypeFloat64 && value[i+1].type() == kTypeFloat64) {

            x = value[i];
            y = value[i+1];

            v = TTValue(x);
            v.append(y);
            mPoints.append(v);

            next = 2;
        }
        else
            err = kTTErrGeneric;

        // create a function
        aFunction = NULL;

        // check size
        if (i+2 >= size) {
            aFunction = TTObject("linear", 1);      // 1 is the numChannel

            // set function type
        } else if (value[i+2].type() == kTypeSymbol) {

            function = value[i+2];
            aFunction = TTObject(function, 1);      // 1 is the numChannel

            next = 3;

            // check size
            if (i+5 > size)
                ;

            // set function parameter
            else if (value[i+3].type() == kTypeSymbol) {

                parameterName = value[i+3];

                v.copyRange(value, i+4, i+5);
                aFunction.set(parameterName, v);

                next = 5;
            }
            else
                err = kTTErrGeneric;
        }
        else
            aFunction = TTObject("linear", 1);      // 1 is the numChannel

        // for the first point : release the function
        if (!curveId)
            aFunction = TTObject();

        // append the function
        else
            mFunctions.append(aFunction);

        curveId++;
    }

    locked = NO;

    return err;
}

TTErr TTFreeHandFunction::Clear()
{
    TTValue init;

    init.append(0.);
    init.append(0.);

    init.append(1.);
    init.append(1.);

    return setCurveList(init);
}

TTErr TTFreeHandFunction::calculateValue(const TTFloat64& x, TTFloat64& y, TTPtrSizedInt data)
{
    TTFloat64   lastX, lastY;
    TTFloat64   currentX, currentY;
    TTFloat64   scaledX, scaledY;
    TTObject    aFunction;
    TTErr       err;

    if (locked)
        return kTTErrGeneric;

    if (mPoints.isEmpty())
        return kTTErrNone;

    mPoints.begin();
    lastX = mPoints.current()[0];
    lastY = mPoints.current()[1];

    if (x < lastX) {
        y = lastY;
        return kTTErrNone;
    }

     mPoints.next();

    // select the function to use
    for (mFunctions.begin(); mFunctions.end(); mFunctions.next()) {

        currentX = mPoints.current()[0];
        currentY = mPoints.current()[1];

        if (x < currentX) {

            aFunction = mFunctions.current()[0];

            // scale x
            scaledX = (x - lastX) / (currentX - lastX);

            // use function
            err = TTAudioObjectBasePtr(aFunction.instance())->calculate(scaledX, scaledY);

            // scale y
            y = (currentY - lastY) * scaledY + lastY;

            return err;
        }

        lastX = currentX;
        lastY = currentY;
        mPoints.next();
    }

    y = lastY;

	return kTTErrNone;
}

TTErr TTFreeHandFunction::processAudio(TTAudioSignalArrayPtr inputs, TTAudioSignalArrayPtr outputs)
{
	TT_WRAP_CALCULATE_METHOD(calculateValue);
}

<|endoftext|>


<commit_before>/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                        Intel License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's 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.
//
//   * The name of Intel Corporation may not 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 Intel Corporation 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.
//
//M*/

#include "test_precomp.hpp"
#define VARNAME(A) #A
using namespace std;
using namespace cv;
using namespace cv::gpu;
using namespace cvtest;

//std::string generateVarList(int first,...)
//{
//	vector<std::string> varname;
//
//	va_list argp;
//	string s;
//	stringstream ss;
//	va_start(argp,first);
//	int i=first;
//	while(i!=-1)
//	{
//		ss<<i<<",";
//		i=va_arg(argp,int);
//	};
//	s=ss.str();
//	va_end(argp);
//	return s;
//};

//std::string generateVarList(int& p1,int& p2)
//{
//	stringstream ss;
//	ss<<VARNAME(p1)<<":"<<src1x<<","<<VARNAME(p2)<<":"<<src1y;
//	return ss.str();
//};

int randomInt(int minVal, int maxVal)
{
    RNG &rng = TS::ptr()->get_rng();
    return rng.uniform(minVal, maxVal);
}

double randomDouble(double minVal, double maxVal)
{
    RNG &rng = TS::ptr()->get_rng();
    return rng.uniform(minVal, maxVal);
}

Size randomSize(int minVal, int maxVal)
{
    return cv::Size(randomInt(minVal, maxVal), randomInt(minVal, maxVal));
}

Scalar randomScalar(double minVal, double maxVal)
{
    return Scalar(randomDouble(minVal, maxVal), randomDouble(minVal, maxVal), randomDouble(minVal, maxVal), randomDouble(minVal, maxVal));
}

Mat randomMat(Size size, int type, double minVal, double maxVal)
{
    return randomMat(TS::ptr()->get_rng(), size, type, minVal, maxVal, false);
}

cv::ocl::oclMat createMat_ocl(Size size, int type, bool useRoi)
{
    Size size0 = size;

    if (useRoi)
    {
        size0.width += randomInt(5, 15);
        size0.height += randomInt(5, 15);
    }

    cv::ocl::oclMat d_m(size0, type);

    if (size0 != size)
        d_m = d_m(Rect((size0.width - size.width) / 2, (size0.height - size.height) / 2, size.width, size.height));

    return d_m;
}

cv::ocl::oclMat loadMat_ocl(const Mat& m, bool useRoi)
{
    CV_Assert(m.type() == CV_8UC1 || m.type() == CV_8UC3);
    cv::ocl::oclMat d_m;
    d_m = createMat_ocl(m.size(), m.type(), useRoi);

    Size ls;
    Point pt;

    d_m.locateROI(ls, pt);

    Rect roi(pt.x, pt.y, d_m.size().width, d_m.size().height);

    cv::ocl::oclMat m_ocl(m);

    cv::ocl::oclMat d_m_roi(d_m, roi);

    m_ocl.copyTo(d_m);
    return d_m;
}
/*
void showDiff(InputArray gold_, InputArray actual_, double eps)
{
    Mat gold;
    if (gold_.kind() == _InputArray::MAT)
        gold = gold_.getMat();
    else
        gold_.getGpuMat().download(gold);

    Mat actual;
    if (actual_.kind() == _InputArray::MAT)
        actual = actual_.getMat();
    else
        actual_.getGpuMat().download(actual);

    Mat diff;
    absdiff(gold, actual, diff);
    threshold(diff, diff, eps, 255.0, cv::THRESH_BINARY);

    namedWindow("gold", WINDOW_NORMAL);
    namedWindow("actual", WINDOW_NORMAL);
    namedWindow("diff", WINDOW_NORMAL);

    imshow("gold", gold);
    imshow("actual", actual);
    imshow("diff", diff);

    waitKey();
}
*/

vector<MatType> types(int depth_start, int depth_end, int cn_start, int cn_end)
{
    vector<MatType> v;

    v.reserve((depth_end - depth_start + 1) * (cn_end - cn_start + 1));

    for (int depth = depth_start; depth <= depth_end; ++depth)
    {
        for (int cn = cn_start; cn <= cn_end; ++cn)
        {
            v.push_back(CV_MAKETYPE(depth, cn));
        }
    }

    return v;
}

const vector<MatType> &all_types()
{
    static vector<MatType> v = types(CV_8U, CV_64F, 1, 4);

    return v;
}

Mat readImage(const string &fileName, int flags)
{
    return imread(string(cvtest::TS::ptr()->get_data_path()) + fileName, flags);
}

Mat readImageType(const string &fname, int type)
{
    Mat src = readImage(fname, CV_MAT_CN(type) == 1 ? IMREAD_GRAYSCALE : IMREAD_COLOR);
    if (CV_MAT_CN(type) == 4)
    {
        Mat temp;
        cvtColor(src, temp, cv::COLOR_BGR2BGRA);
        swap(src, temp);
    }
    src.convertTo(src, CV_MAT_DEPTH(type));
    return src;
}

double checkNorm(const Mat &m)
{
    return norm(m, NORM_INF);
}

double checkNorm(const Mat &m1, const Mat &m2)
{
    return norm(m1, m2, NORM_INF);
}

double checkSimilarity(const Mat &m1, const Mat &m2)
{
    Mat diff;
    matchTemplate(m1, m2, diff, CV_TM_CCORR_NORMED);
    return std::abs(diff.at<float>(0, 0) - 1.f);
}

/*
void cv::ocl::PrintTo(const DeviceInfo& info, ostream* os)
{
    (*os) << info.name();
}
*/

void PrintTo(const Inverse &inverse, std::ostream *os)
{
    if (inverse)
        (*os) << "inverse";
    else
        (*os) << "direct";
}

double checkRectSimilarity(Size sz, std::vector<Rect>& ob1, std::vector<Rect>& ob2)
{
    double final_test_result = 0.0;
    size_t sz1 = ob1.size();
    size_t sz2 = ob2.size();

    if(sz1 != sz2)
    {
        return sz1 > sz2 ? (double)(sz1 - sz2) : (double)(sz2 - sz1);
    }
    else
    {
        if(sz1==0 && sz2==0)
            return 0;
        cv::Mat cpu_result(sz, CV_8UC1);
        cpu_result.setTo(0);

        for(vector<Rect>::const_iterator r = ob1.begin(); r != ob1.end(); r++)
        {
            cv::Mat cpu_result_roi(cpu_result, *r);
            cpu_result_roi.setTo(1);
            cpu_result.copyTo(cpu_result);
        }
        int cpu_area = cv::countNonZero(cpu_result > 0);

        cv::Mat gpu_result(sz, CV_8UC1);
        gpu_result.setTo(0);
        for(vector<Rect>::const_iterator r2 = ob2.begin(); r2 != ob2.end(); r2++)
        {
            cv::Mat gpu_result_roi(gpu_result, *r2);
            gpu_result_roi.setTo(1);
            gpu_result.copyTo(gpu_result);
        }

        cv::Mat result_;
        multiply(cpu_result, gpu_result, result_);
        int result = cv::countNonZero(result_ > 0);
        if(cpu_area!=0 && result!=0)
            final_test_result = 1.0 - (double)result/(double)cpu_area;
        else if(cpu_area==0 && result!=0)
            final_test_result = -1;
    }
    return final_test_result;
}

<commit_msg>Removed trailing whitespace<commit_after>/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                        Intel License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's 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.
//
//   * The name of Intel Corporation may not 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 Intel Corporation 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.
//
//M*/

#include "test_precomp.hpp"
#define VARNAME(A) #A
using namespace std;
using namespace cv;
using namespace cv::gpu;
using namespace cvtest;

//std::string generateVarList(int first,...)
//{
//	vector<std::string> varname;
//
//	va_list argp;
//	string s;
//	stringstream ss;
//	va_start(argp,first);
//	int i=first;
//	while(i!=-1)
//	{
//		ss<<i<<",";
//		i=va_arg(argp,int);
//	};
//	s=ss.str();
//	va_end(argp);
//	return s;
//};

//std::string generateVarList(int& p1,int& p2)
//{
//	stringstream ss;
//	ss<<VARNAME(p1)<<":"<<src1x<<","<<VARNAME(p2)<<":"<<src1y;
//	return ss.str();
//};

int randomInt(int minVal, int maxVal)
{
    RNG &rng = TS::ptr()->get_rng();
    return rng.uniform(minVal, maxVal);
}

double randomDouble(double minVal, double maxVal)
{
    RNG &rng = TS::ptr()->get_rng();
    return rng.uniform(minVal, maxVal);
}

Size randomSize(int minVal, int maxVal)
{
    return cv::Size(randomInt(minVal, maxVal), randomInt(minVal, maxVal));
}

Scalar randomScalar(double minVal, double maxVal)
{
    return Scalar(randomDouble(minVal, maxVal), randomDouble(minVal, maxVal), randomDouble(minVal, maxVal), randomDouble(minVal, maxVal));
}

Mat randomMat(Size size, int type, double minVal, double maxVal)
{
    return randomMat(TS::ptr()->get_rng(), size, type, minVal, maxVal, false);
}

cv::ocl::oclMat createMat_ocl(Size size, int type, bool useRoi)
{
    Size size0 = size;

    if (useRoi)
    {
        size0.width += randomInt(5, 15);
        size0.height += randomInt(5, 15);
    }

    cv::ocl::oclMat d_m(size0, type);

    if (size0 != size)
        d_m = d_m(Rect((size0.width - size.width) / 2, (size0.height - size.height) / 2, size.width, size.height));

    return d_m;
}

cv::ocl::oclMat loadMat_ocl(const Mat& m, bool useRoi)
{
    CV_Assert(m.type() == CV_8UC1 || m.type() == CV_8UC3);
    cv::ocl::oclMat d_m;
    d_m = createMat_ocl(m.size(), m.type(), useRoi);

    Size ls;
    Point pt;

    d_m.locateROI(ls, pt);

    Rect roi(pt.x, pt.y, d_m.size().width, d_m.size().height);

    cv::ocl::oclMat m_ocl(m);

    cv::ocl::oclMat d_m_roi(d_m, roi);

    m_ocl.copyTo(d_m);
    return d_m;
}
/*
void showDiff(InputArray gold_, InputArray actual_, double eps)
{
    Mat gold;
    if (gold_.kind() == _InputArray::MAT)
        gold = gold_.getMat();
    else
        gold_.getGpuMat().download(gold);

    Mat actual;
    if (actual_.kind() == _InputArray::MAT)
        actual = actual_.getMat();
    else
        actual_.getGpuMat().download(actual);

    Mat diff;
    absdiff(gold, actual, diff);
    threshold(diff, diff, eps, 255.0, cv::THRESH_BINARY);

    namedWindow("gold", WINDOW_NORMAL);
    namedWindow("actual", WINDOW_NORMAL);
    namedWindow("diff", WINDOW_NORMAL);

    imshow("gold", gold);
    imshow("actual", actual);
    imshow("diff", diff);

    waitKey();
}
*/

vector<MatType> types(int depth_start, int depth_end, int cn_start, int cn_end)
{
    vector<MatType> v;

    v.reserve((depth_end - depth_start + 1) * (cn_end - cn_start + 1));

    for (int depth = depth_start; depth <= depth_end; ++depth)
    {
        for (int cn = cn_start; cn <= cn_end; ++cn)
        {
            v.push_back(CV_MAKETYPE(depth, cn));
        }
    }

    return v;
}

const vector<MatType> &all_types()
{
    static vector<MatType> v = types(CV_8U, CV_64F, 1, 4);

    return v;
}

Mat readImage(const string &fileName, int flags)
{
    return imread(string(cvtest::TS::ptr()->get_data_path()) + fileName, flags);
}

Mat readImageType(const string &fname, int type)
{
    Mat src = readImage(fname, CV_MAT_CN(type) == 1 ? IMREAD_GRAYSCALE : IMREAD_COLOR);
    if (CV_MAT_CN(type) == 4)
    {
        Mat temp;
        cvtColor(src, temp, cv::COLOR_BGR2BGRA);
        swap(src, temp);
    }
    src.convertTo(src, CV_MAT_DEPTH(type));
    return src;
}

double checkNorm(const Mat &m)
{
    return norm(m, NORM_INF);
}

double checkNorm(const Mat &m1, const Mat &m2)
{
    return norm(m1, m2, NORM_INF);
}

double checkSimilarity(const Mat &m1, const Mat &m2)
{
    Mat diff;
    matchTemplate(m1, m2, diff, CV_TM_CCORR_NORMED);
    return std::abs(diff.at<float>(0, 0) - 1.f);
}

/*
void cv::ocl::PrintTo(const DeviceInfo& info, ostream* os)
{
    (*os) << info.name();
}
*/

void PrintTo(const Inverse &inverse, std::ostream *os)
{
    if (inverse)
        (*os) << "inverse";
    else
        (*os) << "direct";
}

double checkRectSimilarity(Size sz, std::vector<Rect>& ob1, std::vector<Rect>& ob2)
{
    double final_test_result = 0.0;
    size_t sz1 = ob1.size();
    size_t sz2 = ob2.size();

    if(sz1 != sz2)
    {
        return sz1 > sz2 ? (double)(sz1 - sz2) : (double)(sz2 - sz1);
    }
    else
    {
        if(sz1==0 && sz2==0)
            return 0;
        cv::Mat cpu_result(sz, CV_8UC1);
        cpu_result.setTo(0);

        for(vector<Rect>::const_iterator r = ob1.begin(); r != ob1.end(); r++)
        {
            cv::Mat cpu_result_roi(cpu_result, *r);
            cpu_result_roi.setTo(1);
            cpu_result.copyTo(cpu_result);
        }
        int cpu_area = cv::countNonZero(cpu_result > 0);

        cv::Mat gpu_result(sz, CV_8UC1);
        gpu_result.setTo(0);
        for(vector<Rect>::const_iterator r2 = ob2.begin(); r2 != ob2.end(); r2++)
        {
            cv::Mat gpu_result_roi(gpu_result, *r2);
            gpu_result_roi.setTo(1);
            gpu_result.copyTo(gpu_result);
        }

        cv::Mat result_;
        multiply(cpu_result, gpu_result, result_);
        int result = cv::countNonZero(result_ > 0);
        if(cpu_area!=0 && result!=0)
            final_test_result = 1.0 - (double)result/(double)cpu_area;
        else if(cpu_area==0 && result!=0)
            final_test_result = -1;
    }
    return final_test_result;
}
<|endoftext|>


<commit_before>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/

// Software Guide : BeginLatex
//
// \index{itk::TreeContainer}
//
// This example shows how to use the \doxygen{TreeContainer} and the
// associated TreeIterators.
// The \doxygen{TreeContainer} implements the notion of tree and is
// templated over the type of node so it can virtually handle any
// objects. Each node is supposed to have only one parent so no cycle
// is present in the tree. No checking is done to ensure a cycle-free
// tree.
//
// Let's begin by including the appropriate header file.
//
// Software Guide : EndLatex

// Software Guide : BeginCodeSnippet
#include "itkTreeContainer.h"
#include "itkTreeContainer.h"
#include "itkChildTreeIterator.h"
#include "itkLeafTreeIterator.h"
#include "itkLevelOrderTreeIterator.h"
#include "itkInOrderTreeIterator.h"
#include "itkPostOrderTreeIterator.h"
#include "itkRootTreeIterator.h"
#include "itkTreeIteratorClone.h"
// Software Guide : EndCodeSnippet

int main(int, char* [])
{
  // Software Guide : BeginLatex
  //
  // First, we create a tree of integers.
  // The TreeContainer is templated over the type of nodes.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef int                          NodeType;
  typedef itk::TreeContainer<NodeType> TreeType;
  TreeType::Pointer tree = TreeType::New();
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // Next we set the value of the root node using \code{SetRoot()}.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  tree->SetRoot(0);
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // Then we use the \code{Add()} function to add nodes to the tree
  // The first argument is the value of the new node and the second
  // argument is the value of the parent node. If two nodes have
  // the same values then the first one is picked. In this particular
  // case it is better to use an iterator to fill the tree.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  tree->Add(1,0);
  tree->Add(2,0);
  tree->Add(3,0);
  tree->Add(4,2);
  tree->Add(5,2);
  tree->Add(6,5);
  tree->Add(7,1);
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // We define an \doxygen{LevelOrderTreeIterator} to parse the tree in level order.
  // This particular iterator takes three arguments. The first one is the actual tree
  // to be parsed, the second one is the maximum depth level and the third one is the
  // starting node. The \code{GetNode()} function return a node given its value. Once
  // again the first node that corresponds to the value is returned.
  //
  // Software Guide : EndLatex

  std::cout << "LevelOrderTreeIterator:" << std::endl;

  // Software Guide : BeginCodeSnippet
  itk::LevelOrderTreeIterator<TreeType> levelIt(tree,10,tree->GetNode(2));
  levelIt.GoToBegin();
  while(!levelIt.IsAtEnd())
    {
    std::cout << levelIt.Get()
              << " ("<< levelIt.GetLevel()
              << ")" << std::endl;
    ++levelIt;
    }
  std::cout << std::endl;
  // Software Guide : EndCodeSnippet
  levelIt.GoToBegin();
  // Software Guide : BeginLatex
  //
  // The TreeIterators have useful functions to test the property of the current
  // pointed node. Among these functions: \code{IsLeaf{}} returns true if the current
  // node is a leaf, \code{IsRoot{}} returns true if the node is a root,
  // \code{HasParent{}} returns true if the node has a parent and
  // \code{CountChildren{}} returns the number of children for this particular node.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  levelIt.IsLeaf();
  levelIt.IsRoot();
  levelIt.HasParent();
  levelIt.CountChildren();
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // The \doxygen{ChildTreeIterator} provides another way to iterate through a tree
  // by listing all the children of a node.
  //
  // Software Guide : EndLatex
  std::cout << "ChildTreeIterator:" << std::endl;
  // Software Guide : BeginCodeSnippet
  itk::ChildTreeIterator<TreeType> childIt(tree);
  childIt.GoToBegin();
  while(!childIt.IsAtEnd())
    {
    std::cout << childIt.Get() << std::endl;
    ++childIt;
    }
  std::cout << std::endl;
  // Software Guide : EndCodeSnippet
  childIt.GoToBegin();
  // Software Guide : BeginLatex
  //
  // The \code{GetType()} function returns the type of iterator used.
  // The list of enumerated types is as follow:
  // PREORDER, INORDER, POSTORDER, LEVELORDER, CHILD, ROOT and LEAF.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  if(childIt.GetType() != itk::TreeIteratorBase<TreeType>::CHILD)
    {
    std::cout << "[FAILURE]" << std::endl;
    return EXIT_FAILURE;
    }
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // Every TreeIterator has a \code{Clone()} function which returns
  // a copy of the current iterator. Note that the user should delete
  // the created iterator by hand.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  childIt.GoToParent();
  itk::TreeIteratorBase<TreeType>* childItClone = childIt.Clone();
  delete childItClone;
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // The \doxygen{LeafTreeIterator} iterates through the leaves of the tree.
  //
  // Software Guide : EndLatex
  std::cout << "LeafTreeIterator:" << std::endl;
  // Software Guide : BeginCodeSnippet
  itk::LeafTreeIterator<TreeType> leafIt(tree);
  leafIt.GoToBegin();
  while(!leafIt.IsAtEnd())
    {
    std::cout << leafIt.Get() << std::endl;
    ++leafIt;
    }
  std::cout << std::endl;
  // Software Guide : EndCodeSnippet
  // Software Guide : BeginLatex
  //
  // The \doxygen{InOrderTreeIterator} iterates through the tree
  // in the order from left to right.
  //
  // Software Guide : EndLatex
  std::cout << "InOrderTreeIterator:" << std::endl;
  // Software Guide : BeginCodeSnippet
  itk::InOrderTreeIterator<TreeType> InOrderIt(tree);
  InOrderIt.GoToBegin();
  while(!InOrderIt.IsAtEnd())
    {
    std::cout << InOrderIt.Get() << std::endl;
    ++InOrderIt;
    }
  std::cout << std::endl;
  // Software Guide : EndCodeSnippet
  // Software Guide : BeginLatex
  //
  // The \doxygen{PreOrderTreeIterator} iterates through the tree
  // from left to right but do a depth first search.
  //
  // Software Guide : EndLatex
  std::cout << "PreOrderTreeIterator:" << std::endl;
  // Software Guide : BeginCodeSnippet
  itk::PreOrderTreeIterator<TreeType> PreOrderIt(tree);
  PreOrderIt.GoToBegin();
  while(!PreOrderIt.IsAtEnd())
    {
    std::cout << PreOrderIt.Get() << std::endl;
    ++PreOrderIt;
    }
  std::cout << std::endl;
  // Software Guide : EndCodeSnippet
  // Software Guide : BeginLatex
  //
  // The \doxygen{PostOrderTreeIterator} iterates through the tree
  // from left to right but goes from the leaves to the root in the search.
  //
  // Software Guide : EndLatex
  std::cout << "PostOrderTreeIterator:" << std::endl;
  // Software Guide : BeginCodeSnippet
  itk::PostOrderTreeIterator<TreeType> PostOrderIt(tree);
  PostOrderIt.GoToBegin();
  while(!PostOrderIt.IsAtEnd())
    {
    std::cout << PostOrderIt.Get() << std::endl;
    ++PostOrderIt;
    }
  std::cout << std::endl;
  // Software Guide : EndCodeSnippet
  // Software Guide : BeginLatex
  //
  // The \doxygen{RootTreeIterator} goes from one node to the
  // root. The second arguments is the starting node. Here we go from the leaf
  // node (value = 6) up to the root.
  //
  // Software Guide : EndLatex
  std::cout << "RootTreeIterator:" << std::endl;
  // Software Guide : BeginCodeSnippet
  itk::RootTreeIterator<TreeType> RootIt(tree,tree->GetNode(6));
  RootIt.GoToBegin();
  while(!RootIt.IsAtEnd())
    {
    std::cout << RootIt.Get() << std::endl;
    ++RootIt;
    }
  std::cout << std::endl;
  // Software Guide : EndCodeSnippet
  // Software Guide : BeginLatex
  //
  // All the nodes of the tree can be removed by using the
  // \code{Clear()} function.
  //
  // Software Guide : EndLatex
  // Software Guide : BeginCodeSnippet
  tree->Clear();
  // Software Guide : EndCodeSnippet
  // Software Guide : BeginLatex
  //
  // We show how to use a TreeIterator to form a tree by creating nodes.
  // The \code{Add()} function is used to add a node and put a value on it.
  // The \code{GoToChild()} is used to jump to a node.
  //
  // Software Guide : EndLatex
  // Software Guide : BeginCodeSnippet
  itk::PreOrderTreeIterator<TreeType> PreOrderIt2(tree);
  PreOrderIt2.Add(0);
  PreOrderIt2.Add(1);
  PreOrderIt2.Add(2);
  PreOrderIt2.Add(3);
  PreOrderIt2.GoToChild(2);
  PreOrderIt2.Add(4);
  PreOrderIt2.Add(5);
  // Software Guide : EndCodeSnippet
  // Software Guide : BeginLatex
  //
  // The \doxygen{TreeIteratorClone} can be used to have a generic copy of
  // an iterator.
  //
  // Software Guide : EndLatex
  // Software Guide : BeginCodeSnippet
  typedef itk::TreeIteratorBase<TreeType>      IteratorType;
  typedef itk::TreeIteratorClone<IteratorType> IteratorCloneType;
  itk::PreOrderTreeIterator<TreeType> anIterator(tree);
  IteratorCloneType aClone = anIterator;
  // Software Guide : EndCodeSnippet

  return EXIT_SUCCESS;
}
<commit_msg>DOC: Expanded TreeContainer Example<commit_after>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/

// Software Guide : BeginLatex
//
// \index{itk::TreeContainer}
//
// This example demonstrates use of the \doxygen{TreeContainer} class and
// associated \code{TreeIterator}s.
// \code{TreeContainer} implements the notion of a tree, which is a branching
// data structure composed of nodes and edges, where the edges indicate
// a parent/child relationship between nodes.  Each node may have exactly one
// parent, except for the root node, which has none.  A tree must have
// exactly one root node, and a node may not be its own parent.  To round out
// the vocabulary used to discuss this data structure, two nodes
// sharing the same parent node are called ``siblings,'' a childless node
// is termed a ``leaf,'' and a ``forest'' is a collection of disjoint trees.
// Note that in the present implementation, it is the user's responsibility
// to enforce these relationships, as no checking is done to ensure a
// cycle-free tree.  \code{TreeContainer} is templated over the type of node,
// affording the user great flexibility in using the structure for their
// particular problem.
//
// Let's begin by including the appropriate header files.
//
// Software Guide : EndLatex

// Software Guide : BeginCodeSnippet
#include "itkTreeContainer.h"
#include "itkChildTreeIterator.h"
#include "itkLeafTreeIterator.h"
#include "itkLevelOrderTreeIterator.h"
#include "itkInOrderTreeIterator.h"
#include "itkPostOrderTreeIterator.h"
#include "itkRootTreeIterator.h"
#include "itkTreeIteratorClone.h"
// Software Guide : EndCodeSnippet

int main(int, char* [])
{

  // Software Guide : BeginLatex
  //
  // We first instantiate a tree with \code{int} node type.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef int                          NodeType;
  typedef itk::TreeContainer<NodeType> TreeType;
  TreeType::Pointer tree = TreeType::New();
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // Next we set the value of the root node using \code{SetRoot()}.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  tree->SetRoot(0);
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // Nodes may be added to the tree using the \code{Add()} method,
  // where the first argument is the value of the new node, and the second
  // argument is the value of the parent node.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  tree->Add(1,0);
  tree->Add(2,0);
  tree->Add(3,0);
  tree->Add(4,2);
  tree->Add(5,2);
  tree->Add(6,5);
  tree->Add(7,1);
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // If two nodes have the same value, it is ambiguous which node is intended
  // to be the parent of the new node; in this case, the first node with that
  // value is selected.  As will be demonstrated shortly, this ambiguity can be avoided
  // by constructing the tree with \code{TreeIterator}s.
  //
  // Let's begin by defining a \doxygen{ChildTreeIterator}.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  itk::ChildTreeIterator<TreeType> childIt(tree);
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // Before discussing the particular features of this iterator, however, we will
  // illustrate features common to all \code{TreeIterator}s, which inherit
  // from \doxygen{TreeIteratorBase}.  Basic use follows the convention of other
  // iterators in ITK, relying on the \code{GoToBegin()} and \code{IsAtEnd()} methods.
  // The iterator is advanced using the prefix increment \code{++} operator,
  // whose behavior naturally depends on the particular iterator being used.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  for (childIt.GoToBegin(); !childIt.IsAtEnd(); ++childIt)
    {
    std::cout << childIt.Get() << std::endl;
    }
  std::cout << std::endl;
  // Software Guide : EndCodeSnippet

  childIt.GoToBegin();

  // Software Guide : BeginLatex
  //
  // Note that, though not illustrated here, trees may also be traversed using
  // the \code{GoToParent()} and \code{GoToChild()} methods.
  //
  // \code{TreeIterator}s have a number of useful functions for testing properties
  // of the current node.  For example, \code{GetType()} returns an enumerated type
  // corresponding to the type of the particular iterator being used. These types
  // are as follows:
  //
  // \code{UNDEFIND}, \code{PREORDER}, \code{INORDER}, \code{POSTORDER}, \code{LEVELORDER},
  // \code{CHILD}, \code{ROOT}, and \code{LEAF}.
  //
  // In the following snippet, we test whether the iterator is of type \code{CHILD},
  // and return from the program indicating failure if the test returns \code{false}.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  if(childIt.GetType() != itk::TreeIteratorBase<TreeType>::CHILD)
    {
    std::cerr << "Error: The iterator was not of type CHILD." << std::endl;
    return EXIT_FAILURE;
    }
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // The value associated with the node can be retrieved and modified using
  // \code{Get()} and \code{Set()} methods:
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  int oldValue = childIt.Get();
  std::cout << "The node's value is " << oldValue << std::endl;
  int newValue = 2;
  childIt.Set(newValue);
  std::cout << "Now, the node's value is " << childIt.Get() << std::endl;
  // Software Guide : EndCodeSnippet

  childIt.Set(oldValue);

  // Software Guide : BeginLatex
  //
  // A number of member functions are defined allowing the user to query
  // information about the current node's parent/child relationships:
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  std::cout << "Is this a leaf node? " << childIt.IsLeaf() << std::endl;
  std::cout << "Is this the root node? " << childIt.IsRoot() << std::endl;
  std::cout << "Does this node have a parent? " << childIt.HasParent() << std::endl;
  std::cout << "How many children does this node have? " << childIt.CountChildren() << std::endl;
  std::cout << "Does this node have a child 1? " << childIt.HasChild(1) << std::endl;
  // Software Guide : EndCodeSnippet

  std::cout << std::endl;

  // Software Guide : BeginLatex
  //
  // In addition to traversing the tree and querying for information, \code{TreeIterator}s
  // can alter the structure of the tree itself.  For example, a node can be added
  // using the \code{Add()} methods, child nodes can be removed using the
  // \code{RemoveChild()} method, and the current node can be removed using the
  // \code{Remove()} method.  Each of these methods returns a bool indicating whether
  // the alteration was successful.
  //
  // To illustrate this, in the following snippet we clear the tree of all nodes, and then
  // repopulate it using the iterator.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  tree->Clear();

  itk::PreOrderTreeIterator<TreeType> it(tree);

  it.GoToBegin();

  it.Add(0);
  it.Add(1);
  it.Add(2);
  it.Add(3);
  it.GoToChild(2);
  it.Add(4);
  it.Add(5);
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // Every \code{TreeIterator} has a \code{Clone()} function which returns
  // a copy of the current iterator. Note that the user should delete
  // the created iterator by hand.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  itk::TreeIteratorBase<TreeType>* childItClone = childIt.Clone();
  delete childItClone;
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // Alternatively, \doxygen{TreeIteratorClone} can be used to create a generic copy of
  // an iterator.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef itk::TreeIteratorBase<TreeType>      IteratorType;
  typedef itk::TreeIteratorClone<IteratorType> IteratorCloneType;
  IteratorCloneType anotherChildItClone = childIt;
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // We now turn our attention to features of the specific \code{TreeIterator}
  // specializations.  \code{ChildTreeIterator}, for example, provides a way
  // to iterate through all the children of a node.
  //
  // Software Guide : EndLatex

  std::cout << "ChildTreeIterator:" << std::endl;

  // Software Guide : BeginCodeSnippet
  for (childIt.GoToBegin(); !childIt.IsAtEnd(); ++childIt)
    {
    std::cout << childIt.Get();
    }
  std::cout << std::endl;
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // The \doxygen{LeafTreeIterator} iterates through the leaves of the tree.
  //
  // Software Guide : EndLatex

  std::cout << "LeafTreeIterator:" << std::endl;

  // Software Guide : BeginCodeSnippet
  itk::LeafTreeIterator<TreeType> leafIt(tree);
  for (leafIt.GoToBegin(); !leafIt.IsAtEnd(); ++leafIt)
    {
    std::cout << leafIt.Get() << std::endl;
    }
  std::cout << std::endl;
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex

  // \doxygen{LevelOrderTreeIterator} takes three arguments in its constructor:
  // the tree to be traversed, the maximum depth (or `level'), and the starting node.
  // Naturally, this iterator provides a method for returning the current level.
  //
  // Software Guide : EndLatex

  std::cout << "LevelOrderTreeIterator:" << std::endl;

  // Software Guide : BeginCodeSnippet
  itk::LevelOrderTreeIterator<TreeType> levelIt(tree,10,tree->GetNode(0));
  for (levelIt.GoToBegin(); !levelIt.IsAtEnd(); ++levelIt)
    {
    std::cout << levelIt.Get()
              << " ("<< levelIt.GetLevel() << ")"
              << std::endl;
    }
  std::cout << std::endl;
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // \doxygen{InOrderTreeIterator} iterates through the tree
  // from left to right.
  //
  // Software Guide : EndLatex

  std::cout << "InOrderTreeIterator:" << std::endl;

  // Software Guide : BeginCodeSnippet
  itk::InOrderTreeIterator<TreeType> inOrderIt(tree);
  for (inOrderIt.GoToBegin(); !inOrderIt.IsAtEnd(); ++inOrderIt)
    {
    std::cout << inOrderIt.Get() << std::endl;
    }
  std::cout << std::endl;
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // \doxygen{PreOrderTreeIterator} iterates through the tree
  // from left to right but do a depth first search.
  //
  // Software Guide : EndLatex

  std::cout << "PreOrderTreeIterator:" << std::endl;

  // Software Guide : BeginCodeSnippet
  itk::PreOrderTreeIterator<TreeType> preOrderIt(tree);
  for (preOrderIt.GoToBegin(); !preOrderIt.IsAtEnd(); ++preOrderIt)
    {
    std::cout << preOrderIt.Get() << std::endl;
    }
  std::cout << std::endl;
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // The \doxygen{PostOrderTreeIterator} iterates through the tree
  // from left to right but goes from the leaves to the root in the search.
  //
  // Software Guide : EndLatex

  std::cout << "PostOrderTreeIterator:" << std::endl;

  // Software Guide : BeginCodeSnippet
  itk::PostOrderTreeIterator<TreeType> postOrderIt(tree);
  for (postOrderIt.GoToBegin(); !postOrderIt.IsAtEnd(); ++postOrderIt)
    {
    std::cout << postOrderIt.Get() << std::endl;
    }
  std::cout << std::endl;
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // The \doxygen{RootTreeIterator} goes from one node to the
  // root. The second arguments is the starting node. Here we go from the leaf
  // node (value = 6) up to the root.
  //
  // Software Guide : EndLatex

  std::cout << "RootTreeIterator:" << std::endl;

  // Software Guide : BeginCodeSnippet
  itk::RootTreeIterator<TreeType> rootIt(tree,tree->GetNode(4));
  for (rootIt.GoToBegin(); !rootIt.IsAtEnd(); ++rootIt)
    {
    std::cout << rootIt.Get() << std::endl;
    }
  std::cout << std::endl;
  // Software Guide : EndCodeSnippet

  return EXIT_SUCCESS;

}
<|endoftext|>


<commit_before>//
//  AttributeDictionary.cpp
//
// Sketchup C++ Wrapper for C API
// MIT License
//
// Copyright (c) 2017 Tom Kaneko
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//

#include <cassert>
#include <stdexcept>
#include <algorithm>

#include "SUAPI-CppWrapper/model/AttributeDictionary.hpp"

#include "SUAPI-CppWrapper/model/TypedValue.hpp"
#include "SUAPI-CppWrapper/String.hpp"

namespace CW {

extern size_t SU_VERSION_MAJOR;

/******************
* Private Static methods
*******************/
SUAttributeDictionaryRef AttributeDictionary::create_attribute_dictionary(const std::string& name) {
  if (SU_VERSION_MAJOR < 18) {
    throw std::logic_error("AttributeDictionary::create_attribute_dictionary(): Cannot use function prior to SU version 2018");
  }
  SUAttributeDictionaryRef dict = SU_INVALID;
  SUResult res = SUAttributeDictionaryCreate(&dict, name.c_str());
  assert(res == SU_ERROR_NONE);
  return dict;
}

SUAttributeDictionaryRef AttributeDictionary::copy_reference(const AttributeDictionary& other) {
  if (SU_VERSION_MAJOR < 18) {
    throw std::logic_error("AttributeDictionary::create_attribute_dictionary(): Cannot use function prior to SU version 2018");
  }
  if (other.m_attached || !other) {
    return other.ref();
  }
  // The other Attributedictionary has not been attached to the model, so copy its properties to a new object
  SUAttributeDictionaryRef new_dict = create_attribute_dictionary(other.get_name());
  return new_dict;
}

/*****************************
* Constructor / Destructors **
******************************/
AttributeDictionary::AttributeDictionary():
  Entity(SU_INVALID)
{}

AttributeDictionary::AttributeDictionary(std::string name):
  AttributeDictionary(create_attribute_dictionary(name), false)
{}

AttributeDictionary::AttributeDictionary(SUAttributeDictionaryRef dict_ref, bool attached):
  Entity(SUAttributeDictionaryToEntity(dict_ref), attached)
{}

/** Copy constructor */
AttributeDictionary::AttributeDictionary(const AttributeDictionary& other):
  Entity(other, SUAttributeDictionaryToEntity(copy_reference(other)))
{
  if (!other.m_attached && SUIsValid(other.m_entity)) {
    // Create a copy of the keys and values
    std::vector<std::string> keys = other.get_keys();
    for (size_t i=0; i < keys.size(); i++) {
      this->set_attribute(keys[i], other.get_value(keys[i]));
    }
  }
}

AttributeDictionary::~AttributeDictionary() {
  if (SU_VERSION_MAJOR >= 18) {
    if (!m_attached && SUIsValid(m_entity)) {
      SUAttributeDictionaryRef dict = this->ref();
      SUResult res = SUAttributeDictionaryRelease(&dict);
      assert(res == SU_ERROR_NONE);
    }
  }
}

/******************
* Public Methods **
*******************/
/** Copy assignment operator */
AttributeDictionary& AttributeDictionary::operator=(const AttributeDictionary& other) {
  if (SU_VERSION_MAJOR >= 18 && !m_attached && SUIsValid(m_entity)) {
    SUAttributeDictionaryRef dict = this->ref();
    SUResult res = SUAttributeDictionaryRelease(&dict);
    assert(res == SU_ERROR_NONE);
  }
  SUAttributeDictionaryRef dict = copy_reference(other);
  m_entity = SUAttributeDictionaryToEntity(dict);
  Entity::operator=(other);
  return *this;
}

SUAttributeDictionaryRef AttributeDictionary::ref() const {
  return SUAttributeDictionaryFromEntity(m_entity);
}

AttributeDictionary::operator SUAttributeDictionaryRef() const {
  return this->ref();
}

TypedValue AttributeDictionary::get_attribute(const std::string &key, const TypedValue &default_value) const {
  if (!(*this)) {
    throw std::logic_error("CW::AttributeDictionary::get_attribute(): AttributeDictionary is null");
  }
  SUTypedValueRef val = SU_INVALID;
  SUResult res = SUTypedValueCreate(&val);
  assert(res == SU_ERROR_NONE);
  const char* key_char = key.c_str();
  res = SUAttributeDictionaryGetValue(this->ref(), &key_char[0], &val);
  if (res == SU_ERROR_NO_DATA) {
    return default_value;
  }
  if (res != SU_ERROR_NONE) {
    assert(false);
    //throw std::logic_error("CW::AttributeDictionary::get_attribute(): index range is between 0 and 15");
  }
  return TypedValue(val);
}

bool AttributeDictionary::set_attribute(const std::string &key, const TypedValue &value) {
  if (!(*this)) {
    throw std::logic_error("CW::AttributeDictionary::set_attribute(): AttributeDictionary is null");
  }
  SUTypedValueRef val = value.ref();
  const char* key_char = key.c_str();
  SUResult res = SUAttributeDictionarySetValue(this->ref(), &key_char[0], val);
  if (res == SU_ERROR_NONE) {
    return true;
  }
  else {
    return false;
  }
}

std::vector<std::string> AttributeDictionary::get_keys() const {
  if (!(*this)) {
    throw std::logic_error("CW::AttributeDictionary::get_keys(): AttributeDictionary is null");
  }
  size_t num_keys = 0;
  SUResult res = SUAttributeDictionaryGetNumKeys(this->ref(), &num_keys);
  assert(res == SU_ERROR_NONE);
  std::vector<SUStringRef> keys_ref(num_keys, SU_INVALID);
  std::for_each(keys_ref.begin(), keys_ref.end(),
  [](SUStringRef& value) {
    SUResult res = SUStringCreate(&value);
    assert(res == SU_ERROR_NONE);
  });
  res = SUAttributeDictionaryGetKeys(this->ref(), num_keys, keys_ref.data(), &num_keys);
  assert(res == SU_ERROR_NONE);
  std::vector<std::string> keys(num_keys);
  std::transform(keys_ref.begin(), keys_ref.end(), keys.begin(),
  [](const SUStringRef& value) {
    return String(value).std_string();
  });
  return keys;
}

TypedValue AttributeDictionary::get_value(const std::string &key) const {
  return get_attribute(key, TypedValue());
}

std::string AttributeDictionary::get_name() const {
  String string;
  SUStringRef *string_ref = string;
  SUResult res = SUAttributeDictionaryGetName(this->ref(), string_ref);
  assert(res == SU_ERROR_NONE);
  return string;
}

bool AttributeDictionary::operator !() const {
  if (SUIsValid(m_entity)) {
    return false;
  }
  return true;
}

} /* namespace CW */
<commit_msg>Simplified call to SetValue<commit_after>//
//  AttributeDictionary.cpp
//
// Sketchup C++ Wrapper for C API
// MIT License
//
// Copyright (c) 2017 Tom Kaneko
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//

#include <cassert>
#include <stdexcept>
#include <algorithm>

#include "SUAPI-CppWrapper/model/AttributeDictionary.hpp"

#include "SUAPI-CppWrapper/model/TypedValue.hpp"
#include "SUAPI-CppWrapper/String.hpp"

namespace CW {

extern size_t SU_VERSION_MAJOR;

/******************
* Private Static methods
*******************/
SUAttributeDictionaryRef AttributeDictionary::create_attribute_dictionary(const std::string& name) {
  if (SU_VERSION_MAJOR < 18) {
    throw std::logic_error("AttributeDictionary::create_attribute_dictionary(): Cannot use function prior to SU version 2018");
  }
  SUAttributeDictionaryRef dict = SU_INVALID;
  SUResult res = SUAttributeDictionaryCreate(&dict, name.c_str());
  assert(res == SU_ERROR_NONE);
  return dict;
}

SUAttributeDictionaryRef AttributeDictionary::copy_reference(const AttributeDictionary& other) {
  if (SU_VERSION_MAJOR < 18) {
    throw std::logic_error("AttributeDictionary::create_attribute_dictionary(): Cannot use function prior to SU version 2018");
  }
  if (other.m_attached || !other) {
    return other.ref();
  }
  // The other Attributedictionary has not been attached to the model, so copy its properties to a new object
  SUAttributeDictionaryRef new_dict = create_attribute_dictionary(other.get_name());
  return new_dict;
}

/*****************************
* Constructor / Destructors **
******************************/
AttributeDictionary::AttributeDictionary():
  Entity(SU_INVALID)
{}

AttributeDictionary::AttributeDictionary(std::string name):
  AttributeDictionary(create_attribute_dictionary(name), false)
{}

AttributeDictionary::AttributeDictionary(SUAttributeDictionaryRef dict_ref, bool attached):
  Entity(SUAttributeDictionaryToEntity(dict_ref), attached)
{}

/** Copy constructor */
AttributeDictionary::AttributeDictionary(const AttributeDictionary& other):
  Entity(other, SUAttributeDictionaryToEntity(copy_reference(other)))
{
  if (!other.m_attached && SUIsValid(other.m_entity)) {
    // Create a copy of the keys and values
    std::vector<std::string> keys = other.get_keys();
    for (size_t i=0; i < keys.size(); i++) {
      this->set_attribute(keys[i], other.get_value(keys[i]));
    }
  }
}

AttributeDictionary::~AttributeDictionary() {
  if (SU_VERSION_MAJOR >= 18) {
    if (!m_attached && SUIsValid(m_entity)) {
      SUAttributeDictionaryRef dict = this->ref();
      SUResult res = SUAttributeDictionaryRelease(&dict);
      assert(res == SU_ERROR_NONE);
    }
  }
}

/******************
* Public Methods **
*******************/
/** Copy assignment operator */
AttributeDictionary& AttributeDictionary::operator=(const AttributeDictionary& other) {
  if (SU_VERSION_MAJOR >= 18 && !m_attached && SUIsValid(m_entity)) {
    SUAttributeDictionaryRef dict = this->ref();
    SUResult res = SUAttributeDictionaryRelease(&dict);
    assert(res == SU_ERROR_NONE);
  }
  SUAttributeDictionaryRef dict = copy_reference(other);
  m_entity = SUAttributeDictionaryToEntity(dict);
  Entity::operator=(other);
  return *this;
}

SUAttributeDictionaryRef AttributeDictionary::ref() const {
  return SUAttributeDictionaryFromEntity(m_entity);
}

AttributeDictionary::operator SUAttributeDictionaryRef() const {
  return this->ref();
}

TypedValue AttributeDictionary::get_attribute(const std::string &key, const TypedValue &default_value) const {
  if (!(*this)) {
    throw std::logic_error("CW::AttributeDictionary::get_attribute(): AttributeDictionary is null");
  }
  SUTypedValueRef val = SU_INVALID;
  SUResult res = SUTypedValueCreate(&val);
  assert(res == SU_ERROR_NONE);
  const char* key_char = key.c_str();
  res = SUAttributeDictionaryGetValue(this->ref(), &key_char[0], &val);
  if (res == SU_ERROR_NO_DATA) {
    return default_value;
  }
  if (res != SU_ERROR_NONE) {
    assert(false);
    //throw std::logic_error("CW::AttributeDictionary::get_attribute(): index range is between 0 and 15");
  }
  return TypedValue(val);
}

bool AttributeDictionary::set_attribute(const std::string &key, const TypedValue &value) {
  if (!(*this)) {
    throw std::logic_error("CW::AttributeDictionary::set_attribute(): AttributeDictionary is null");
  }
  SUResult res = SUAttributeDictionarySetValue(this->ref(), key.data(), value.ref());
  if (res == SU_ERROR_NONE) {
    return true;
  }
  else {
    return false;
  }
}

std::vector<std::string> AttributeDictionary::get_keys() const {
  if (!(*this)) {
    throw std::logic_error("CW::AttributeDictionary::get_keys(): AttributeDictionary is null");
  }
  size_t num_keys = 0;
  SUResult res = SUAttributeDictionaryGetNumKeys(this->ref(), &num_keys);
  assert(res == SU_ERROR_NONE);
  std::vector<SUStringRef> keys_ref(num_keys, SU_INVALID);
  std::for_each(keys_ref.begin(), keys_ref.end(),
  [](SUStringRef& value) {
    SUResult res = SUStringCreate(&value);
    assert(res == SU_ERROR_NONE);
  });
  res = SUAttributeDictionaryGetKeys(this->ref(), num_keys, keys_ref.data(), &num_keys);
  assert(res == SU_ERROR_NONE);
  std::vector<std::string> keys(num_keys);
  std::transform(keys_ref.begin(), keys_ref.end(), keys.begin(),
  [](const SUStringRef& value) {
    return String(value).std_string();
  });
  return keys;
}

TypedValue AttributeDictionary::get_value(const std::string &key) const {
  return get_attribute(key, TypedValue());
}

std::string AttributeDictionary::get_name() const {
  String string;
  SUStringRef *string_ref = string;
  SUResult res = SUAttributeDictionaryGetName(this->ref(), string_ref);
  assert(res == SU_ERROR_NONE);
  return string;
}

bool AttributeDictionary::operator !() const {
  if (SUIsValid(m_entity)) {
    return false;
  }
  return true;
}

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


<commit_before>#include "Arduino_I2C_ESC.h"
#include <Wire.h>

namespace {
  uint8_t _buffer[9];
}

Arduino_I2C_ESC::Arduino_I2C_ESC(uint8_t address, uint8_t poleCount) {
	_address = address;
  _poleCount = poleCount;
}

// Read the incoming data buffer from an ESC
void Arduino_I2C_ESC::readBuffer(uint8_t address, uint8_t buffer[]) {
  Wire.beginTransmission(address);
  Wire.write(0x02); // Data start register
  Wire.endTransmission();

  Wire.requestFrom(address,uint8_t(9));
  uint8_t i = 0;
  while(Wire.available()) {
    buffer[i] = Wire.read();
    i++;
  }
}

// Send motor speed command to ESC
void Arduino_I2C_ESC::set(int16_t throttle) {
  Wire.beginTransmission(_address);
  Wire.write(0x00);
  Wire.write(throttle>>8);
  Wire.write(throttle);
  Wire.endTransmission();
}

void Arduino_I2C_ESC::update() {
  _buffer[8] = 0x00; // Reset last byte so we can check for alive

  readBuffer(_address,_buffer);

  _rpm = (_buffer[0] << 8) | _buffer[1];
  _voltage_raw = (_buffer[2] << 8) | _buffer[3];
  _temp_raw = (_buffer[4] << 8) | _buffer[5];
  _current_raw = (_buffer[6] << 8) | _buffer[7];
  _identifier = _buffer[8];

  Serial.println(_rpm);

  _rpm = float(_rpm)/((uint16_t(millis())-_rpmTimer)/1000.0f)*60/float(_poleCount);
  _rpmTimer = millis();
}

bool Arduino_I2C_ESC::isAlive() {
  return (_identifier == 0xab);
}

float Arduino_I2C_ESC::voltage() {
	return float(_voltage_raw)/65536.0f*5.0f*6.45f;
}

float Arduino_I2C_ESC::current() {
  return (float(_current_raw)-32767)/65535.0f*5.0f*14.706f;
}

float Arduino_I2C_ESC::temperature() {
  // This code was taken from an Adafruit
	float resistance = SERIESRESISTOR/(65535/float(_temp_raw)-1);

	float steinhart;
	steinhart = resistance / THERMISTORNOMINAL;  // (R/Ro)
	steinhart = log(steinhart);                  // ln(R/Ro)
	steinhart /= BCOEFFICIENT;                   // 1/B * ln(R/Ro)
	steinhart += 1.0 / (TEMPERATURENOMINAL + 273.15); // + (1/To)
	steinhart = 1.0 / steinhart;                 // Invert
	steinhart -= 273.15;                         // convert to C

	return steinhart;
}

int16_t Arduino_I2C_ESC::rpm() {
  return _rpm;
}
<commit_msg>Removed stray printing characters.<commit_after>#include "Arduino_I2C_ESC.h"
#include <Wire.h>

namespace {
  uint8_t _buffer[9];
}

Arduino_I2C_ESC::Arduino_I2C_ESC(uint8_t address, uint8_t poleCount) {
	_address = address;
  _poleCount = poleCount;
}

// Read the incoming data buffer from an ESC
void Arduino_I2C_ESC::readBuffer(uint8_t address, uint8_t buffer[]) {
  Wire.beginTransmission(address);
  Wire.write(0x02); // Data start register
  Wire.endTransmission();

  Wire.requestFrom(address,uint8_t(9));
  uint8_t i = 0;
  while(Wire.available()) {
    buffer[i] = Wire.read();
    i++;
  }
}

// Send motor speed command to ESC
void Arduino_I2C_ESC::set(int16_t throttle) {
  Wire.beginTransmission(_address);
  Wire.write(0x00);
  Wire.write(throttle>>8);
  Wire.write(throttle);
  Wire.endTransmission();
}

void Arduino_I2C_ESC::update() {
  _buffer[8] = 0x00; // Reset last byte so we can check for alive

  readBuffer(_address,_buffer);

  _rpm = (_buffer[0] << 8) | _buffer[1];
  _voltage_raw = (_buffer[2] << 8) | _buffer[3];
  _temp_raw = (_buffer[4] << 8) | _buffer[5];
  _current_raw = (_buffer[6] << 8) | _buffer[7];
  _identifier = _buffer[8];

  _rpm = float(_rpm)/((uint16_t(millis())-_rpmTimer)/1000.0f)*60/float(_poleCount);
  _rpmTimer = millis();
}

bool Arduino_I2C_ESC::isAlive() {
  return (_identifier == 0xab);
}

float Arduino_I2C_ESC::voltage() {
	return float(_voltage_raw)/65536.0f*5.0f*6.45f;
}

float Arduino_I2C_ESC::current() {
  return (float(_current_raw)-32767)/65535.0f*5.0f*14.706f;
}

float Arduino_I2C_ESC::temperature() {
  // This code was taken from an Adafruit
	float resistance = SERIESRESISTOR/(65535/float(_temp_raw)-1);

	float steinhart;
	steinhart = resistance / THERMISTORNOMINAL;  // (R/Ro)
	steinhart = log(steinhart);                  // ln(R/Ro)
	steinhart /= BCOEFFICIENT;                   // 1/B * ln(R/Ro)
	steinhart += 1.0 / (TEMPERATURENOMINAL + 273.15); // + (1/To)
	steinhart = 1.0 / steinhart;                 // Invert
	steinhart -= 273.15;                         // convert to C

	return steinhart;
}

int16_t Arduino_I2C_ESC::rpm() {
  return _rpm;
}
<|endoftext|>