<commit_before>#ifndef MR_TR_PARSER_C
#define MR_TR_PARSER_C

#include <stdexcept>
#include <ctype.h>
#include <iostream>

#include <maproute/tr_parser.hpp>
#include <maproute/stringhelp.hpp>
#include <maproute/input_walker.hpp>
#include <maproute/ip_convertor.hpp>

typedef enum TraceTokenKind {
    TRACE_TOKEN_SPACE, // whitespace token
    TRACE_TOKEN_NUMBER,
    TRACE_TOKEN_DOT, // the . in floating point numbers or IP addreses
    TRACE_TOKEN_MS, // ms keyword
    TRACE_TOKEN_STAR // '*' characther
} TraceTokenKind;

typedef struct TraceToken {
    TraceTokenKind kind;
    std::string contents;
} TraceToken;

typedef int (*iskind_cb)(int c);

int take_while(std::string *line, int index, iskind_cb f) {

    char c;
    std::string input = *line;
    int len = input.length();

    while (index < len && (c = input[index])) {
        if (f(c)) {
            index++;
        } else {
            return index;
        }
    }
    return index;

}

bool expect(TraceToken*self, TraceToken *other) {
    if (self->kind == other->kind) {
        return true;
    } else {
        return false;
    }
}

bool tokenize(std::string *line, std::vector<TraceToken> *out) {
    std::string input = *line;
    int len = input.length();

    for (int i = 0; i < len; i++) {
        int si = i;
        char c = input[i];
        TraceToken token;

        if (isspace(c)) {
            i = take_while(line, i, isspace);
            token.kind = TRACE_TOKEN_SPACE;
            token.contents = string_get(line, si, i);
            i--;

        } else if (isdigit(c)) {
            i = take_while(line, i, isdigit);
            token.kind = TRACE_TOKEN_NUMBER;
            token.contents = string_get(line, si, i);
            i--;

        } else if (c == '.') {
            token.kind = TRACE_TOKEN_DOT;
            token.contents = ".";

        } else if (c == '*') {
            token.kind = TRACE_TOKEN_STAR;
            token.contents = "*";

        } else if (c == 'm') {

            i++;
            c = input[i];

            if (c == 's') {
                token.kind = TRACE_TOKEN_MS;
                token.contents = "ms";
            } else {
                return false;
            }

        } else {
            return false;
        }

        out->push_back(token);

    }

    return true;
}

bool expect(InputWalker<TraceToken> *walker, TraceTokenKind kind) {
    TraceToken token = walker->advance();

    if (token.kind == kind) {
        return true;

    } else {
        walker->backtrack();
        std::cout << "[WARNING] - Wrong token kind." << std::endl;

        return false;
    }

}

bool expect_ip(InputWalker<TraceToken> *inputs, IPV4 *out) {
    bool result;
    std::string ip_string;
    IPV4Convertor convertor;

    result = expect(inputs, TRACE_TOKEN_NUMBER);
    ip_string.append(inputs->get_current().contents);
    result = expect(inputs, TRACE_TOKEN_DOT);
    ip_string.append(inputs->get_current().contents);

    result = expect(inputs, TRACE_TOKEN_NUMBER);
    ip_string.append(inputs->get_current().contents);
    result = expect(inputs, TRACE_TOKEN_DOT);
    ip_string.append(inputs->get_current().contents);

    result = expect(inputs, TRACE_TOKEN_NUMBER);
    ip_string.append(inputs->get_current().contents);
    result = expect(inputs, TRACE_TOKEN_DOT);
    ip_string.append(inputs->get_current().contents);

    result = expect(inputs, TRACE_TOKEN_NUMBER);
    ip_string.append(inputs->get_current().contents);

    convertor.string_to_ip(&ip_string, out);

    return result;

}

bool parse_gateway(std::vector<TraceToken> *tokens, IPV4 *out) {

    InputWalker<TraceToken> inputs {*tokens};
    bool result;

    // the hop number
    result = expect(&inputs, TRACE_TOKEN_SPACE);
    result = expect(&inputs, TRACE_TOKEN_NUMBER);
    result = expect(&inputs, TRACE_TOKEN_SPACE);

    // the ip address
    result = expect_ip(&inputs, out);
    result = expect(&inputs, TRACE_TOKEN_SPACE);

    return result;
}

bool TracerouteLineParser::parse(std::string *line, IPV4 *out) {

    std::vector<TraceToken> tokens;
    bool valid = tokenize(line, &tokens);

    if (valid) {
        return parse_gateway(&tokens, out);
    } else {
        return false;
    }
}

#endif
<commit_msg>Removed the space tokens<commit_after>#ifndef MR_TR_PARSER_C
#define MR_TR_PARSER_C

#include <stdexcept>
#include <ctype.h>
#include <iostream>

#include <maproute/tr_parser.hpp>
#include <maproute/stringhelp.hpp>
#include <maproute/input_walker.hpp>
#include <maproute/ip_convertor.hpp>

typedef enum TraceTokenKind {
    TRACE_TOKEN_SPACE, // whitespace token
    TRACE_TOKEN_NUMBER,
    TRACE_TOKEN_DOT, // the . in floating point numbers or IP addreses
    TRACE_TOKEN_MS, // ms keyword
    TRACE_TOKEN_STAR // '*' characther
} TraceTokenKind;

typedef struct TraceToken {
    TraceTokenKind kind;
    std::string contents;
} TraceToken;

typedef int (*iskind_cb)(int c);

int take_while(std::string *line, int index, iskind_cb f) {

    char c;
    std::string input = *line;
    int len = input.length();

    while (index < len && (c = input[index])) {
        if (f(c)) {
            index++;
        } else {
            return index;
        }
    }
    return index;

}

bool expect(TraceToken*self, TraceToken *other) {
    if (self->kind == other->kind) {
        return true;
    } else {
        return false;
    }
}

bool tokenize(std::string *line, std::vector<TraceToken> *out) {
    std::string input = *line;
    int len = input.length();

    for (int i = 0; i < len; i++) {
        int si = i;
        char c = input[i];
        TraceToken token;

        if (isspace(c)) {
            i = take_while(line, i, isspace);
            token.kind = TRACE_TOKEN_SPACE;
            token.contents = string_get(line, si, i);
            i--;

        } else if (isdigit(c)) {
            i = take_while(line, i, isdigit);
            token.kind = TRACE_TOKEN_NUMBER;
            token.contents = string_get(line, si, i);
            i--;

        } else if (c == '.') {
            token.kind = TRACE_TOKEN_DOT;
            token.contents = ".";

        } else if (c == '*') {
            token.kind = TRACE_TOKEN_STAR;
            token.contents = "*";

        } else if (c == 'm') {
            i++;
            c = input[i];

            if (c == 's') {
                token.kind = TRACE_TOKEN_MS;
                token.contents = "ms";
            } else {
                return false;
            }

        } else {
            return false;
        }

        if (token.kind != TRACE_TOKEN_SPACE) {
            out->push_back(token);
        }

    }

    return true;
}

bool expect(InputWalker<TraceToken> *walker, TraceTokenKind kind) {
    TraceToken token = walker->advance();

    if (token.kind == kind) {
        return true;

    } else {
        walker->backtrack();
        std::cout << "[WARNING] - Wrong token kind." << std::endl;

        return false;
    }

}

bool expect_ip(InputWalker<TraceToken> *inputs, IPV4 *out) {
    bool result;
    std::string ip_string;
    IPV4Convertor convertor;

    result = expect(inputs, TRACE_TOKEN_NUMBER);
    ip_string.append(inputs->get_current().contents);
    result = expect(inputs, TRACE_TOKEN_DOT);
    ip_string.append(inputs->get_current().contents);

    result = expect(inputs, TRACE_TOKEN_NUMBER);
    ip_string.append(inputs->get_current().contents);
    result = expect(inputs, TRACE_TOKEN_DOT);
    ip_string.append(inputs->get_current().contents);

    result = expect(inputs, TRACE_TOKEN_NUMBER);
    ip_string.append(inputs->get_current().contents);
    result = expect(inputs, TRACE_TOKEN_DOT);
    ip_string.append(inputs->get_current().contents);

    result = expect(inputs, TRACE_TOKEN_NUMBER);
    ip_string.append(inputs->get_current().contents);

    convertor.string_to_ip(&ip_string, out);

    return result;

}

bool parse_gateway(std::vector<TraceToken> *tokens, IPV4 *out) {

    InputWalker<TraceToken> inputs {*tokens};
    bool result;

    // the hop number
    result = expect(&inputs, TRACE_TOKEN_NUMBER);

    // the ip address
    result = expect_ip(&inputs, out);

    return result;
}

bool TracerouteLineParser::parse(std::string *line, IPV4 *out) {

    std::vector<TraceToken> tokens;
    bool valid = tokenize(line, &tokens);

    if (valid) {
        return parse_gateway(&tokens, out);
    } else {
        return false;
    }
}

#endif
<|endoftext|>


<commit_before><commit_msg>reduce the scope a bit further<commit_after><|endoftext|>


<commit_before>#include <cctype>
#include "error.h"
#include "lexer.h"

Lexer::Token_stream Lexer::ts {cin};

Lexer::Token Lexer::Token_stream::get() {
    // read 1 char, decide what kind of token is incoming,
    // appropriately read more char then return Token
    char c = 0;

    do {  // skip all whitespace except newline
        if(!ip->get(c)) return ct = {Kind::end};  // no char can be read from ip
    } while (c != '\n' && isspace(c));

    switch (c) {
        case ';':
        case '\n':
            return ct = {Kind::print};
        case '-':
            if (ct.kind != Kind::number && ct.kind != Kind::name) return ct = {Kind::mag_neg};
        case '*':
        case '/':
        case '+':
        case '(':
        case ')':
        case '<':
        case '>':
        case '&':
        case '|':
        case '^':
        case '~':
        case '\\':
        case '=':
            return ct = {static_cast<Kind>(c)};
        case '0':
            if (isalnum(ip->peek())) // else use 0 as number
                return ct = {Kind::oct};
        case '1':
        case '2':
        case '3':
        case '4':
        case '5':
        case '6':
        case '7':
        case '8':
        case '9':
            ip->putback(c);
            if (ct.kind == Kind::hex) { int tmp; *ip >> hex >> tmp; ct.number_val = static_cast<rep_type>(tmp); }
            else if (ct.kind == Kind::oct) { int tmp; *ip >> oct >> tmp; ct.number_val = static_cast<rep_type>(tmp); }
            else *ip >> ct.number_val;
            ct.kind = Kind::number;
            return ct;
        case 'x':
            if (ct.kind == Kind::oct)   // fall down to default otherwise
                return ct = {Kind::hex};
        default:    // name, name =, or error
            if (isalpha(c)) {
                if (ct.kind == Kind::lit) { // character is a literal rather than a name
                    ct.number_val = static_cast<int>(c);
                    ct.kind = Kind::number;
                    return ct;
                }
                ct.string_val = c;
                while (ip->get(c) && isalnum(c))
                    ct.string_val += c;    // append each letter of name
                ip->putback(c);     // while loop reads 1 extra char
                ct.kind = Kind::name;
                return ct;
            }
            Error::error("bad token");
            return ct = {Kind::print};
    }
}

<commit_msg>Added support for using .5 instead of 0.5 to specify decimal < 1<commit_after>#include <cctype>
#include "error.h"
#include "lexer.h"

Lexer::Token_stream Lexer::ts {cin};

Lexer::Token Lexer::Token_stream::get() {
    // read 1 char, decide what kind of token is incoming,
    // appropriately read more char then return Token
    char c = 0;

    do {  // skip all whitespace except newline
        if(!ip->get(c)) return ct = {Kind::end};  // no char can be read from ip
    } while (c != '\n' && isspace(c));

    switch (c) {
        case ';':
        case '\n':
            return ct = {Kind::print};
        case '-':
            if (ct.kind != Kind::number && ct.kind != Kind::name) return ct = {Kind::mag_neg};
        case '*':
        case '/':
        case '+':
        case '(':
        case ')':
        case '<':
        case '>':
        case '&':
        case '|':
        case '^':
        case '~':
        case '\\':
        case '=':
            return ct = {static_cast<Kind>(c)};
        case '0':
            if (isalnum(ip->peek())) // else use 0 as number
                return ct = {Kind::oct};
        case '1':
        case '2':
        case '3':
        case '4':
        case '5':
        case '6':
        case '7':
        case '8':
        case '9':
        case '.':
            ip->putback(c);
            if (ct.kind == Kind::hex) { int tmp; *ip >> hex >> tmp; ct.number_val = static_cast<rep_type>(tmp); }
            else if (ct.kind == Kind::oct) { int tmp; *ip >> oct >> tmp; ct.number_val = static_cast<rep_type>(tmp); }
            else *ip >> ct.number_val;
            ct.kind = Kind::number;
            return ct;
        case 'x':
            if (ct.kind == Kind::oct)   // fall down to default otherwise
                return ct = {Kind::hex};
        default:    // name, name =, or error
            if (isalpha(c)) {
                if (ct.kind == Kind::lit) { // character is a literal rather than a name
                    ct.number_val = static_cast<int>(c);
                    ct.kind = Kind::number;
                    return ct;
                }
                ct.string_val = c;
                while (ip->get(c) && isalnum(c))
                    ct.string_val += c;    // append each letter of name
                ip->putback(c);     // while loop reads 1 extra char
                ct.kind = Kind::name;
                return ct;
            }
            Error::error("bad token");
            return ct = {Kind::print};
    }
}

<|endoftext|>


<commit_before>void runGlauberMC(Bool_t doPartProd=0,Int_t option=0,Int_t N=250000)
{
  //load libraries
  gSystem->Load("libVMC");
  gSystem->Load("libPhysics");
  gSystem->Load("libTree");
  gSystem->Load("libPWGGlauber");

  //set the random seed from current time
  TTimeStamp time;
  Int_t seed = time.GetSec();
  gRandom->SetSeed(seed);

  Int_t nevents = N; // number of events to simulate
  // supported systems are e.g. "p", "d", "Si", "Au", "Pb", "U"
  Option_t *sysA="Pb";
  Option_t *sysB="Pb";
  Double_t signn=64; // inelastic nucleon nucleon cross section
  //const char *fname="GlauberMC_PbPb_ntuple.root"; // name output file

  // run the code to produce an ntuple:
  //  AliGlauberMC::runAndSaveNucleons(10000,"Pb","Pb",72);
  Double_t mind=0.4;
  //  AliGlauberMC::RunAndSaveNtuple(nevents,sysA,sysB,signn,mind);
  Double_t r=6.62;
  Double_t a=0.546;
  const char *fname="glau_pbpb_ntuple.root";

  AliGlauberMC mcg(sysA,sysB,signn);
  mcg.SetMinDistance(mind);
  mcg.Setr(r);
  mcg.Seta(a);
  if (option==1)
    mcg.SetDoFluc(0.55,78.5*0.92,0.82,kTRUE);
  else if (option==2)
    mcg.SetDoFluc(1.01,72.5*0.92,0.74,kTRUE);
  mcg.SetDoPartProduction(doPartProd);

  //////////////////
  mcg.SetdNdEtaType(AliGlauberMC::kNBDSV);
  mcg.GetdNdEtaParam()[0] = 2.49;    //npp
  mcg.GetdNdEtaParam()[1] = 1.7;  //ratioSgm2Mu
  mcg.GetdNdEtaParam()[2] = 0.13; //xhard
  //////////////////

  mcg.Run(nevents);

  TNtuple  *nt = mcg.GetNtuple();
  TFile out(fname,"recreate",fname,9);
  if(nt) nt->Write();
  printf("total cross section with a nucleon-nucleon cross section %.4f is %.4f\n\n",signn,mcg.GetTotXSect());
  out.Close();
}
<commit_msg>setters for sigmaNN<commit_after>void runGlauberMC(Double_t sigNN=64, Bool_t doPartProd=0, Int_t option=0, Int_t N=250000)
{
  //load libraries
  gSystem->Load("libVMC");
  gSystem->Load("libPhysics");
  gSystem->Load("libTree");
  gSystem->Load("libPWGGlauber");

  //set the random seed from current time
  TTimeStamp time;
  Int_t seed = time.GetSec();
  gRandom->SetSeed(seed);

  Int_t nevents = N; // number of events to simulate
  // supported systems are e.g. "p", "d", "Si", "Au", "Pb", "U"
  Option_t *sysA="Pb";
  Option_t *sysB="Pb";
  Double_t mind=0.4;
  Double_t r=6.62;
  Double_t a=0.546;
  const char *fname="glau_pbpb_ntuple.root";

  AliGlauberMC mcg(sysA,sysB,sigNN);
  mcg.SetMinDistance(mind);
  mcg.Setr(r);
  mcg.Seta(a);
  if (option==1)
    mcg.SetDoFluc(0.55,78.5*0.92,0.82,kTRUE);
  else if (option==2)
    mcg.SetDoFluc(1.01,72.5*0.92,0.74,kTRUE);

  mcg.SetDoPartProduction(doPartProd);
  mcg.SetdNdEtaType(AliGlauberMC::kNBDSV);
  mcg.GetdNdEtaParam()[0] = 2.49;    //npp
  mcg.GetdNdEtaParam()[1] = 1.7;  //ratioSgm2Mu
  mcg.GetdNdEtaParam()[2] = 0.13; //xhard

  mcg.Run(nevents);

  TNtuple  *nt = mcg.GetNtuple();
  TFile out(fname,"recreate",fname,9);
  if(nt) nt->Write();
  printf("total cross section with a nucleon-nucleon cross section %.4f is %.4f\n\n",signn,mcg.GetTotXSect());
  out.Close();
}
<|endoftext|>


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

  Program:   Visualization Toolkit
  Module:    vtkOutputPort.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-2000 Ken Martin, Will Schroeder, Bill Lorensen
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 name of Ken Martin, Will Schroeder, or Bill Lorensen nor the names
   of any contributors may be used to endorse or promote products derived
   from this software without specific prior written permission.

 * Modified source versions must be plainly marked as such, and must not be
   misrepresented as being the original software.

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 REGENTS 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.

=========================================================================*/
#include "vtkOutputPort.h"
#include "vtkInputPort.h"
#include "vtkMultiProcessController.h"
#include "vtkObjectFactory.h"

//------------------------------------------------------------------------------
vtkOutputPort* vtkOutputPort::New()
{
  // First try to create the object from the vtkObjectFactory
  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkOutputPort");
  if(ret)
    {
    return (vtkOutputPort*)ret;
    }
  // If the factory was unable to create the object, then create it here.
  return new vtkOutputPort;
}

//----------------------------------------------------------------------------
vtkOutputPort::vtkOutputPort()
{
  this->Tag = -1;

  // Controller keeps a reference to this object as well.
  this->Controller =
    vtkMultiProcessController::GetGlobalController();

  this->PipelineFlag = 0;
  this->ParameterMethod = NULL;
  this->ParameterMethodArgDelete = NULL;
  this->ParameterMethodArg = NULL;
}

//----------------------------------------------------------------------------
// We need to have a "GetNetReferenceCount" to avoid memory leaks.
vtkOutputPort::~vtkOutputPort()
{
  this->Controller = NULL;

  if ((this->ParameterMethodArg)&&(this->ParameterMethodArgDelete))
    {
    (*this->ParameterMethodArgDelete)(this->ParameterMethodArg);
    }
}

//----------------------------------------------------------------------------
void vtkOutputPort::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkProcessObject::PrintSelf(os,indent);
  os << indent << "Tag: " << this->Tag << endl;
  os << indent << "Controller: (" << this->Controller << ")\n";
  os << indent << "Pipeline Flag: "
     << (this->PipelineFlag ? "On\n" : "Off\n");
}

//----------------------------------------------------------------------------
// Remote method call to UpdateInformation and send the information downstream.
// This should be a friend.
void vtkOutputPortUpdateInformationCallBack(void *arg, void *remoteArgs,
		  	            int remoteArgsLength, int remoteProcessId)
{
  vtkOutputPort *self = (vtkOutputPort*)arg;

  remoteArgs = remoteArgs;
  remoteArgsLength = remoteArgsLength;
  // Just call a method
  self->TriggerUpdateInformation(remoteProcessId);
}
//----------------------------------------------------------------------------
void vtkOutputPort::TriggerUpdateInformation(int remoteProcessId)
{
  vtkDataObject *input = this->GetInput();

  // Handle no input gracefully.
  if ( input != NULL )
    {
    input->UpdateInformation();
    }

  // The MTime of the input should also be considered.
  // Important for pipeline parallelism.
  // Include it in the information for efficiency.
  unsigned long t1, t2;
  t1 = input->GetMTime();
  t2 = input->GetPipelineMTime();
  if (t1 > t2)
    {
    input->SetPipelineMTime(t1);
    }

  // Now just send the information downstream.
  // PipelineMTime is part of information, so downstream
  // port will make the time comparison, and call Update if necessary.
  int wholeInformation[8];
  input->GetWholeExtent( wholeInformation );
  wholeInformation[6] = input->GetMaximumNumberOfPieces();

  this->Controller->Send( wholeInformation, 7,
                          remoteProcessId, VTK_PORT_INFORMATION_TRANSFER_TAG);

  unsigned long mtime = input->GetPipelineMTime();

  this->Controller->Send( &mtime, 1,
                          remoteProcessId, VTK_PORT_INFORMATION_TRANSFER_TAG );
}

//----------------------------------------------------------------------------
// Remote method call to Update and send data downstream.
// This should be a friend.
void vtkOutputPortUpdateCallBack(void *arg, void *remoteArgs,
				 int remoteArgsLength, int remoteProcessId)
{
  vtkOutputPort *self = (vtkOutputPort*)arg;

  remoteArgs = remoteArgs;
  remoteArgsLength = remoteArgsLength;
  // Just call a method
  self->TriggerUpdate(remoteProcessId);
}
//----------------------------------------------------------------------------
void vtkOutputPort::TriggerUpdate(int remoteProcessId)
{
  unsigned long downDataTime;
  vtkDataObject *input = this->GetInput();

  // First get the update extent requested.
  int extent[8];
  this->Controller->Receive( extent, 8, remoteProcessId,
			    VTK_PORT_UPDATE_EXTENT_TAG);
  input->SetUpdateExtent( extent );
  input->SetUpdatePiece( extent[6] );
  input->SetUpdateNumberOfPieces( extent[7] );

  // Note:  Receiving DataTime was the start of a more intelligent promotion
  // for pipeline parallism.  Unfortunately there was no way (I knew of)
  // for us to not promote on the first Update.  I backed off, and am
  // requiring either 1: Filters handle Update Not returning correct data,
  // or 2: Pipeline parallelism must be primed with Updates on the Output
  // ports (giving correct data).  This Receive can be removed.

  // This is for pipeline parallism.
  // This Output port may or may not promote our data (execute).
  // We need the data time of the last transfer to compare to the mtime
  // of our input to determine if it should send the data (execute).
  this->Controller->Receive( &(downDataTime), 1, remoteProcessId,
			     VTK_PORT_NEW_DATA_TIME_TAG);

  // Postpone the update if we want pipeline parallism.
  // Handle no input gracefully. (Not true: Later we will send a NULL input.)
  if ( input != NULL && input->GetDataReleased())
    {
    input->UpdateInformation();
    input->PropagateUpdateExtent();
    input->TriggerAsynchronousUpdate();
    input->UpdateData();
    }

  // Did the input change?
  // If it did then we should execute (i.e. we should send the data).
  // Note: We may need some logic to catch the case where the down port
  // has released its data.
  //if (downDataTime < input->GetMTime())
  if (input->GetDataReleased() == 0)
    {
    if ( this->StartMethod )
      {
      (*this->StartMethod)(this->StartMethodArg);
      }
    // First transfer the new data.
    this->Controller->Send( input, remoteProcessId,
			    VTK_PORT_DATA_TRANSFER_TAG);
    if ( this->EndMethod )
      {
      (*this->EndMethod)(this->EndMethodArg);
      }

    // Since this time has to be local to downstream process
    // and we have no data, we have to create a time here.
    // (The output data usually does this.)
    this->UpdateTime.Modified();

    // Since this OutputPort can have multiple InputPorts
    // and the InputPort makes the update-descision time comparison,
    // the InputPort has to store this time.
    downDataTime = this->UpdateTime.GetMTime();
    this->Controller->Send( &downDataTime, 1, remoteProcessId,
			    VTK_PORT_NEW_DATA_TIME_TAG);
    }
  else
    {  // Nothing to send.  We have to signal somehow.
    vtkDebugMacro("Promoting NULL (" << input << ") to process "
		  << remoteProcessId);
    this->Controller->Send( (vtkDataObject*)(NULL), remoteProcessId,
			    VTK_PORT_DATA_TRANSFER_TAG);

    // Go through the motions of sending the data time,
    // but just send the same data time back. (nothing changed).
    this->Controller->Send( &downDataTime, 1, remoteProcessId,
			    VTK_PORT_NEW_DATA_TIME_TAG);
    }

  // Postpone the update if we want pipeline parallism.
  // Handle no input gracefully. (Not true: Later we will send a NULL input.)
  if (this->PipelineFlag)
    {
    // change any parameters if the user wants to.
    if ( this->ParameterMethod )
      {
      (*this->ParameterMethod)(this->ParameterMethodArg);
      input->UpdateInformation();
      }

    // Update to anticipate the next request.
    if ( input != NULL )
      {
      input->UpdateInformation();
      input->PropagateUpdateExtent();
      input->TriggerAsynchronousUpdate();
      input->UpdateData();
      }
    }
}

//----------------------------------------------------------------------------
void vtkOutputPort::SetInput(vtkDataObject *input)
{
  this->vtkProcessObject::SetNthInput(0, input);
}

//----------------------------------------------------------------------------
vtkDataObject *vtkOutputPort::GetInput()
{
  if (this->Inputs == NULL)
    {
    return NULL;
    }
  return this->Inputs[0];
}

//----------------------------------------------------------------------------
// We need to create two RMIs when the tag is set.
// This means we must generate two tags form this ports tag.
// The ports tag should be even.
// (I do not like this, but is there another solution?)
void vtkOutputPort::SetTag(int tag)
{
  if (this->Tag == tag)
    {
    return;
    }

  this->Modified();

  // remove old RMI.
  if (this->Tag != -1)
    {
//    this->Controller->RemoveRMI(vtkOutputPortUpdateInformationCallBack,
//                                (void *)this, this->Tag);
//    this->Controller->RemoveRMI(vtkOutputPortUpdateCallBack,
//                                (void *)this, this->Tag + 1);
    }

  this->Tag = tag;
  this->Controller->AddRMI(vtkOutputPortUpdateInformationCallBack,
			   (void *)this, tag);
  this->Controller->AddRMI(vtkOutputPortUpdateCallBack,
                           (void *)this, tag+1);
}

//----------------------------------------------------------------------------
void vtkOutputPort::SetParameterMethod(void (*f)(void *), void *arg)
{
  if ( f != this->ParameterMethod || arg != this->ParameterMethodArg )
    {
    // delete the current arg if there is one and a delete meth
    if ((this->ParameterMethodArg)&&(this->ParameterMethodArgDelete))
      {
      (*this->ParameterMethodArgDelete)(this->ParameterMethodArg);
      }
    this->ParameterMethod = f;
    this->ParameterMethodArg = arg;
    this->Modified();
    }
}

//----------------------------------------------------------------------------
void vtkOutputPort::SetParameterMethodArgDelete(void (*f)(void *))
{
  if ( f != this->ParameterMethodArgDelete)
    {
    this->ParameterMethodArgDelete = f;
    this->Modified();
    }
}
<commit_msg>change comment<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkOutputPort.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-2000 Ken Martin, Will Schroeder, Bill Lorensen
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 name of Ken Martin, Will Schroeder, or Bill Lorensen nor the names
   of any contributors may be used to endorse or promote products derived
   from this software without specific prior written permission.

 * Modified source versions must be plainly marked as such, and must not be
   misrepresented as being the original software.

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 REGENTS 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.

=========================================================================*/
#include "vtkOutputPort.h"
#include "vtkInputPort.h"
#include "vtkMultiProcessController.h"
#include "vtkObjectFactory.h"

//----------------------------------------------------------------------------
vtkOutputPort* vtkOutputPort::New()
{
  // First try to create the object from the vtkObjectFactory
  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkOutputPort");
  if(ret)
    {
    return (vtkOutputPort*)ret;
    }
  // If the factory was unable to create the object, then create it here.
  return new vtkOutputPort;
}

//----------------------------------------------------------------------------
vtkOutputPort::vtkOutputPort()
{
  this->Tag = -1;

  // Controller keeps a reference to this object as well.
  this->Controller =
    vtkMultiProcessController::GetGlobalController();

  this->PipelineFlag = 0;
  this->ParameterMethod = NULL;
  this->ParameterMethodArgDelete = NULL;
  this->ParameterMethodArg = NULL;
}

//----------------------------------------------------------------------------
// We need to have a "GetNetReferenceCount" to avoid memory leaks.
vtkOutputPort::~vtkOutputPort()
{
  this->Controller = NULL;

  if ((this->ParameterMethodArg)&&(this->ParameterMethodArgDelete))
    {
    (*this->ParameterMethodArgDelete)(this->ParameterMethodArg);
    }
}

//----------------------------------------------------------------------------
void vtkOutputPort::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkProcessObject::PrintSelf(os,indent);
  os << indent << "Tag: " << this->Tag << endl;
  os << indent << "Controller: (" << this->Controller << ")\n";
  os << indent << "Pipeline Flag: "
     << (this->PipelineFlag ? "On\n" : "Off\n");
}

//----------------------------------------------------------------------------
// Remote method call to UpdateInformation and send the information downstream.
// This should be a friend.
void vtkOutputPortUpdateInformationCallBack(void *arg, void *remoteArgs,
		  	            int remoteArgsLength, int remoteProcessId)
{
  vtkOutputPort *self = (vtkOutputPort*)arg;

  remoteArgs = remoteArgs;
  remoteArgsLength = remoteArgsLength;
  // Just call a method
  self->TriggerUpdateInformation(remoteProcessId);
}
//----------------------------------------------------------------------------
void vtkOutputPort::TriggerUpdateInformation(int remoteProcessId)
{
  vtkDataObject *input = this->GetInput();

  // Handle no input gracefully.
  if ( input != NULL )
    {
    input->UpdateInformation();
    }

  // The MTime of the input should also be considered.
  // Important for pipeline parallelism.
  // Include it in the information for efficiency.
  unsigned long t1, t2;
  t1 = input->GetMTime();
  t2 = input->GetPipelineMTime();
  if (t1 > t2)
    {
    input->SetPipelineMTime(t1);
    }

  // Now just send the information downstream.
  // PipelineMTime is part of information, so downstream
  // port will make the time comparison, and call Update if necessary.
  int wholeInformation[8];
  input->GetWholeExtent( wholeInformation );
  wholeInformation[6] = input->GetMaximumNumberOfPieces();

  this->Controller->Send( wholeInformation, 7,
                          remoteProcessId, VTK_PORT_INFORMATION_TRANSFER_TAG);

  unsigned long mtime = input->GetPipelineMTime();

  this->Controller->Send( &mtime, 1,
                          remoteProcessId, VTK_PORT_INFORMATION_TRANSFER_TAG );
}

//----------------------------------------------------------------------------
// Remote method call to Update and send data downstream.
// This should be a friend.
void vtkOutputPortUpdateCallBack(void *arg, void *remoteArgs,
				 int remoteArgsLength, int remoteProcessId)
{
  vtkOutputPort *self = (vtkOutputPort*)arg;

  remoteArgs = remoteArgs;
  remoteArgsLength = remoteArgsLength;
  // Just call a method
  self->TriggerUpdate(remoteProcessId);
}
//----------------------------------------------------------------------------
void vtkOutputPort::TriggerUpdate(int remoteProcessId)
{
  unsigned long downDataTime;
  vtkDataObject *input = this->GetInput();

  // First get the update extent requested.
  int extent[8];
  this->Controller->Receive( extent, 8, remoteProcessId,
			    VTK_PORT_UPDATE_EXTENT_TAG);
  input->SetUpdateExtent( extent );
  input->SetUpdatePiece( extent[6] );
  input->SetUpdateNumberOfPieces( extent[7] );

  // Note:  Receiving DataTime was the start of a more intelligent promotion
  // for pipeline parallism.  Unfortunately there was no way (I knew of)
  // for us to not promote on the first Update.  I backed off, and am
  // requiring either 1: Filters handle Update Not returning correct data,
  // or 2: Pipeline parallelism must be primed with Updates on the Output
  // ports (giving correct data).  This Receive can be removed.

  // This is for pipeline parallism.
  // This Output port may or may not promote our data (execute).
  // We need the data time of the last transfer to compare to the mtime
  // of our input to determine if it should send the data (execute).
  this->Controller->Receive( &(downDataTime), 1, remoteProcessId,
			     VTK_PORT_NEW_DATA_TIME_TAG);

  // Postpone the update if we want pipeline parallism.
  // Handle no input gracefully. (Not true: Later we will send a NULL input.)
  if ( input != NULL && input->GetDataReleased())
    {
    input->UpdateInformation();
    input->PropagateUpdateExtent();
    input->TriggerAsynchronousUpdate();
    input->UpdateData();
    }

  // Did the input change?
  // If it did then we should execute (i.e. we should send the data).
  // Note: We may need some logic to catch the case where the down port
  // has released its data.
  //if (downDataTime < input->GetMTime())
  if (input->GetDataReleased() == 0)
    {
    if ( this->StartMethod )
      {
      (*this->StartMethod)(this->StartMethodArg);
      }
    // First transfer the new data.
    this->Controller->Send( input, remoteProcessId,
			    VTK_PORT_DATA_TRANSFER_TAG);
    if ( this->EndMethod )
      {
      (*this->EndMethod)(this->EndMethodArg);
      }

    // Since this time has to be local to downstream process
    // and we have no data, we have to create a time here.
    // (The output data usually does this.)
    this->UpdateTime.Modified();

    // Since this OutputPort can have multiple InputPorts
    // and the InputPort makes the update-descision time comparison,
    // the InputPort has to store this time.
    downDataTime = this->UpdateTime.GetMTime();
    this->Controller->Send( &downDataTime, 1, remoteProcessId,
			    VTK_PORT_NEW_DATA_TIME_TAG);
    }
  else
    {  // Nothing to send.  We have to signal somehow.
    vtkDebugMacro("Promoting NULL (" << input << ") to process "
		  << remoteProcessId);
    this->Controller->Send( (vtkDataObject*)(NULL), remoteProcessId,
			    VTK_PORT_DATA_TRANSFER_TAG);

    // Go through the motions of sending the data time,
    // but just send the same data time back. (nothing changed).
    this->Controller->Send( &downDataTime, 1, remoteProcessId,
			    VTK_PORT_NEW_DATA_TIME_TAG);
    }

  // Postpone the update if we want pipeline parallism.
  // Handle no input gracefully. (Not true: Later we will send a NULL input.)
  if (this->PipelineFlag)
    {
    // change any parameters if the user wants to.
    if ( this->ParameterMethod )
      {
      (*this->ParameterMethod)(this->ParameterMethodArg);
      input->UpdateInformation();
      }

    // Update to anticipate the next request.
    if ( input != NULL )
      {
      input->UpdateInformation();
      input->PropagateUpdateExtent();
      input->TriggerAsynchronousUpdate();
      input->UpdateData();
      }
    }
}

//----------------------------------------------------------------------------
void vtkOutputPort::SetInput(vtkDataObject *input)
{
  this->vtkProcessObject::SetNthInput(0, input);
}

//----------------------------------------------------------------------------
vtkDataObject *vtkOutputPort::GetInput()
{
  if (this->Inputs == NULL)
    {
    return NULL;
    }
  return this->Inputs[0];
}

//----------------------------------------------------------------------------
// We need to create two RMIs when the tag is set.
// This means we must generate two tags form this ports tag.
// The ports tag should be even.
// (I do not like this, but is there another solution?)
void vtkOutputPort::SetTag(int tag)
{
  if (this->Tag == tag)
    {
    return;
    }

  this->Modified();

  // remove old RMI.
  if (this->Tag != -1)
    {
//    this->Controller->RemoveRMI(vtkOutputPortUpdateInformationCallBack,
//                                (void *)this, this->Tag);
//    this->Controller->RemoveRMI(vtkOutputPortUpdateCallBack,
//                                (void *)this, this->Tag + 1);
    }

  this->Tag = tag;
  this->Controller->AddRMI(vtkOutputPortUpdateInformationCallBack,
			   (void *)this, tag);
  this->Controller->AddRMI(vtkOutputPortUpdateCallBack,
                           (void *)this, tag+1);
}

//----------------------------------------------------------------------------
void vtkOutputPort::SetParameterMethod(void (*f)(void *), void *arg)
{
  if ( f != this->ParameterMethod || arg != this->ParameterMethodArg )
    {
    // delete the current arg if there is one and a delete meth
    if ((this->ParameterMethodArg)&&(this->ParameterMethodArgDelete))
      {
      (*this->ParameterMethodArgDelete)(this->ParameterMethodArg);
      }
    this->ParameterMethod = f;
    this->ParameterMethodArg = arg;
    this->Modified();
    }
}

//----------------------------------------------------------------------------
void vtkOutputPort::SetParameterMethodArgDelete(void (*f)(void *))
{
  if ( f != this->ParameterMethodArgDelete)
    {
    this->ParameterMethodArgDelete = f;
    this->Modified();
    }
}
<|endoftext|>


<commit_before>/*
* Software License Agreement (BSD License)
*
*  Copyright (c) 2010, Willow Garage, Inc.
*  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 Willow Garage, Inc. 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.
*
* $Id$
*
*/

#define MEASURE_FUNCTION_TIME
#include <pcl/common/time.h> //fps calculations
#include <pcl/common/angles.h>
#include <pcl/io/openni2_grabber.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/visualization/boost.h>
#include <pcl/visualization/image_viewer.h>
#include <pcl/console/print.h>
#include <pcl/console/parse.h>
#include <pcl/console/time.h>

#include <boost/chrono.hpp>

#include "pcl/io/openni2/openni.h"

typedef boost::chrono::high_resolution_clock HRClock;

#define SHOW_FPS 1
#if SHOW_FPS
#define FPS_CALC(_WHAT_) \
  do \
{ \
  static unsigned count = 0;\
  static double last = pcl::getTime ();\
  double now = pcl::getTime (); \
  ++count; \
  if (now - last >= 1.0) \
{ \
  std::cout << "Average framerate ("<< _WHAT_ << "): " << double (count)/double (now - last) << " Hz" <<  std::endl; \
  count = 0; \
  last = now; \
} \
}while (false)
#else
#define FPS_CALC (_WHAT_) \
  do \
{ \
}while (false)
#endif

void
printHelp (int, char **argv)
{
  using pcl::console::print_error;
  using pcl::console::print_info;

  print_error ("Syntax is: %s [((<device_id> | <path-to-oni-file>) [-depthmode <mode>] [-imagemode <mode>] [-xyz] | -l [<device_id>]| -h | --help)]\n", argv [0]);
  print_info ("%s -h | --help : shows this help\n", argv [0]);
  print_info ("%s -xyz : use only XYZ values and ignore RGB components (this flag is required for use with ASUS Xtion Pro) \n", argv [0]);
  print_info ("%s -l : list all available devices\n", argv [0]);
  print_info ("%s -l <device-id> :list all available modes for specified device\n", argv [0]);
  print_info ("\t\t<device_id> may be \"#1\", \"#2\", ... for the first, second etc device in the list\n");
#ifndef _WIN32
  print_info ("\t\t                   bus@address for the device connected to a specific usb-bus / address combination\n");
  print_info ("\t\t                   <serial-number>\n");
#endif
  print_info ("\n\nexamples:\n");
  print_info ("%s \"#1\"\n", argv [0]);
  print_info ("\t\t uses the first device.\n");
  print_info ("%s  \"./temp/test.oni\"\n", argv [0]);
  print_info ("\t\t uses the oni-player device to play back oni file given by path.\n");
  print_info ("%s -l\n", argv [0]);
  print_info ("\t\t list all available devices.\n");
  print_info ("%s -l \"#2\"\n", argv [0]);
  print_info ("\t\t list all available modes for the second device.\n");
#ifndef _WIN32
  print_info ("%s A00361800903049A\n", argv [0]);
  print_info ("\t\t uses the device with the serial number \'A00361800903049A\'.\n");
  print_info ("%s 1@16\n", argv [0]);
  print_info ("\t\t uses the device on address 16 at USB bus 1.\n");
#endif
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointType>
class OpenNI2Viewer
{
public:
  typedef pcl::PointCloud<PointType> Cloud;
  typedef typename Cloud::ConstPtr CloudConstPtr;

  OpenNI2Viewer (pcl::io::OpenNI2Grabber& grabber)
    : cloud_viewer_ (new pcl::visualization::PCLVisualizer ("PCL OpenNI2 cloud"))
    , image_viewer_ ()
    , grabber_ (grabber)
    , rgb_data_ (0), rgb_data_size_ (0)
  {
  }

  void
  cloud_callback (const CloudConstPtr& cloud)
  {
    FPS_CALC ("cloud callback");
    boost::mutex::scoped_lock lock (cloud_mutex_);
    cloud_ = cloud;
  }

  void
  image_callback (const boost::shared_ptr<pcl::io::openni2::Image>& image)
  {
    FPS_CALC ("image callback");
    boost::mutex::scoped_lock lock (image_mutex_);
    image_ = image;

    if (image->getEncoding () != pcl::io::openni2::Image::RGB)
    {
      if (rgb_data_size_ < image->getWidth () * image->getHeight ())
      {
        if (rgb_data_)
          delete [] rgb_data_;
        rgb_data_size_ = image->getWidth () * image->getHeight ();
        rgb_data_ = new unsigned char [rgb_data_size_ * 3];
      }
      image_->fillRGB (image_->getWidth (), image_->getHeight (), rgb_data_);
    }
  }

  void
  keyboard_callback (const pcl::visualization::KeyboardEvent& event, void*)
  {
    if (event.getKeyCode ())
      cout << "the key \'" << event.getKeyCode () << "\' (" << event.getKeyCode () << ") was";
    else
      cout << "the special key \'" << event.getKeySym () << "\' was";
    if (event.keyDown ())
      cout << " pressed" << endl;
    else
      cout << " released" << endl;
  }

  void
  mouse_callback (const pcl::visualization::MouseEvent& mouse_event, void*)
  {
    if (mouse_event.getType () == pcl::visualization::MouseEvent::MouseButtonPress && mouse_event.getButton () == pcl::visualization::MouseEvent::LeftButton)
    {
      cout << "left button pressed @ " << mouse_event.getX () << " , " << mouse_event.getY () << endl;
    }
  }

  /**
  * @brief starts the main loop
  */
  void
  run ()
  {
    cloud_viewer_->registerMouseCallback (&OpenNI2Viewer::mouse_callback, *this);
    cloud_viewer_->registerKeyboardCallback (&OpenNI2Viewer::keyboard_callback, *this);
    cloud_viewer_->setCameraFieldOfView (1.02259994f);
    boost::function<void (const CloudConstPtr&) > cloud_cb = boost::bind (&OpenNI2Viewer::cloud_callback, this, _1);
    boost::signals2::connection cloud_connection = grabber_.registerCallback (cloud_cb);

    boost::signals2::connection image_connection;
    if (grabber_.providesCallback<void (const boost::shared_ptr<pcl::io::openni2::Image>&)>())
    {
      image_viewer_.reset (new pcl::visualization::ImageViewer ("PCL OpenNI image"));
      image_viewer_->registerMouseCallback (&OpenNI2Viewer::mouse_callback, *this);
      image_viewer_->registerKeyboardCallback (&OpenNI2Viewer::keyboard_callback, *this);
      boost::function<void (const boost::shared_ptr<pcl::io::openni2::Image>&) > image_cb = boost::bind (&OpenNI2Viewer::image_callback, this, _1);
      image_connection = grabber_.registerCallback (image_cb);
    }

    bool image_init = false, cloud_init = false;

    grabber_.start ();

    while (!cloud_viewer_->wasStopped () && (image_viewer_ && !image_viewer_->wasStopped ()))
    {
      boost::shared_ptr<pcl::io::openni2::Image> image;
      CloudConstPtr cloud;

      cloud_viewer_->spinOnce ();

      // See if we can get a cloud
      if (cloud_mutex_.try_lock ())
      {
        cloud_.swap (cloud);
        cloud_mutex_.unlock ();
      }

      if (cloud)
      {
        FPS_CALC("drawing cloud");

        if (!cloud_init)
        {
          cloud_viewer_->setPosition (0, 0);
          cloud_viewer_->setSize (cloud->width, cloud->height);
          cloud_init = !cloud_init;
        }

        if (!cloud_viewer_->updatePointCloud (cloud, "OpenNICloud"))
        {
          cloud_viewer_->addPointCloud (cloud, "OpenNICloud");
          cloud_viewer_->resetCameraViewpoint ("OpenNICloud");
          cloud_viewer_->setCameraPosition (
            0,0,0,		// Position
            0,0,1,		// Viewpoint
            0,-1,0);	// Up
        }
      }

      // See if we can get an image
      if (image_mutex_.try_lock ())
      {
        image_.swap (image);
        image_mutex_.unlock ();
      }

      if (image)
      {
        if (!image_init && cloud && cloud->width != 0)
        {
          image_viewer_->setPosition (cloud->width, 0);
          image_viewer_->setSize (cloud->width, cloud->height);
          image_init = !image_init;
        }

        if (image->getEncoding () == pcl::io::openni2::Image::RGB)
          image_viewer_->addRGBImage ( (const unsigned char*)image->getData (), image->getWidth (), image->getHeight ());
        else
          image_viewer_->addRGBImage (rgb_data_, image->getWidth (), image->getHeight ());
        image_viewer_->spinOnce ();

      }
    }

    grabber_.stop ();

    cloud_connection.disconnect ();
    image_connection.disconnect ();
    if (rgb_data_)
      delete[] rgb_data_;
  }

  boost::shared_ptr<pcl::visualization::PCLVisualizer> cloud_viewer_;
  boost::shared_ptr<pcl::visualization::ImageViewer> image_viewer_;

  pcl::io::OpenNI2Grabber& grabber_;
  boost::mutex cloud_mutex_;
  boost::mutex image_mutex_;

  CloudConstPtr cloud_;
  boost::shared_ptr<pcl::io::openni2::Image> image_;
  unsigned char* rgb_data_;
  unsigned rgb_data_size_;
};

// Create the PCLVisualizer object
boost::shared_ptr<pcl::visualization::PCLVisualizer> cld;
boost::shared_ptr<pcl::visualization::ImageViewer> img;

/* ---[ */
int
main (int argc, char** argv)
{
  std::string device_id ("");
  pcl::io::OpenNI2Grabber::Mode depth_mode = pcl::io::OpenNI2Grabber::OpenNI_Default_Mode;
  pcl::io::OpenNI2Grabber::Mode image_mode = pcl::io::OpenNI2Grabber::OpenNI_Default_Mode;
  bool xyz = false;

  if (argc >= 2)
  {
    device_id = argv[1];
    if (device_id == "--help" || device_id == "-h")
    {
      printHelp (argc, argv);
      return 0;
    }
    else if (device_id == "-l")
    {
      if (argc >= 3)
      {
        pcl::io::OpenNI2Grabber grabber (argv[2]);
        boost::shared_ptr<pcl::io::openni2::OpenNI2Device> device = grabber.getDevice ();
        cout << *device;		// Prints out all sensor data, including supported video modes
      }
      else
      {
        boost::shared_ptr<pcl::io::openni2::OpenNI2DeviceManager> deviceManager = pcl::io::openni2::OpenNI2DeviceManager::getInstance ();
        if (deviceManager->getNumOfConnectedDevices () > 0)
        {
          for (unsigned deviceIdx = 0; deviceIdx < deviceManager->getNumOfConnectedDevices (); ++deviceIdx)
          {
            boost::shared_ptr<pcl::io::openni2::OpenNI2Device> device = deviceManager->getDeviceByIndex (deviceIdx);
            cout << "Device " << device->getStringID () << "connected." << endl;
          }

        }
        else
          cout << "No devices connected." << endl;

        cout <<"Virtual Devices available: ONI player" << endl;
      }
      return 0;
    }
  }
  else
  {
    boost::shared_ptr<pcl::io::openni2::OpenNI2DeviceManager> deviceManager = pcl::io::openni2::OpenNI2DeviceManager::getInstance ();
    if (deviceManager->getNumOfConnectedDevices () > 0)
    {
      boost::shared_ptr<pcl::io::openni2::OpenNI2Device> device = deviceManager->getAnyDevice ();
      cout << "Device ID not set, using default device: " << device->getStringID () << endl;
    }
  }

  unsigned mode;
  if (pcl::console::parse (argc, argv, "-depthmode", mode) != -1)
    depth_mode = pcl::io::OpenNI2Grabber::Mode (mode);

  if (pcl::console::parse (argc, argv, "-imagemode", mode) != -1)
    image_mode = pcl::io::OpenNI2Grabber::Mode (mode);

  if (pcl::console::find_argument (argc, argv, "-xyz") != -1)
    xyz = true;

  pcl::io::OpenNI2Grabber grabber (device_id, depth_mode, image_mode);

  if (xyz || !grabber.providesCallback<pcl::io::OpenNI2Grabber::sig_cb_openni_point_cloud_rgb> ())
  {
    OpenNI2Viewer<pcl::PointXYZ> openni_viewer (grabber);
    openni_viewer.run ();
  }
  else
  {
    OpenNI2Viewer<pcl::PointXYZRGBA> openni_viewer (grabber);
    openni_viewer.run ();
  }

  return (0);
}
/* ]--- */
<commit_msg>Add Catch I/O Exception to OpenNI2 Viewer<commit_after>/*
* Software License Agreement (BSD License)
*
*  Copyright (c) 2010, Willow Garage, Inc.
*  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 Willow Garage, Inc. 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.
*
* $Id$
*
*/

#define MEASURE_FUNCTION_TIME
#include <pcl/common/time.h> //fps calculations
#include <pcl/common/angles.h>
#include <pcl/io/openni2_grabber.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/visualization/boost.h>
#include <pcl/visualization/image_viewer.h>
#include <pcl/console/print.h>
#include <pcl/console/parse.h>
#include <pcl/console/time.h>

#include <boost/chrono.hpp>

#include "pcl/io/openni2/openni.h"

typedef boost::chrono::high_resolution_clock HRClock;

#define SHOW_FPS 1
#if SHOW_FPS
#define FPS_CALC(_WHAT_) \
  do \
{ \
  static unsigned count = 0;\
  static double last = pcl::getTime ();\
  double now = pcl::getTime (); \
  ++count; \
  if (now - last >= 1.0) \
{ \
  std::cout << "Average framerate ("<< _WHAT_ << "): " << double (count)/double (now - last) << " Hz" <<  std::endl; \
  count = 0; \
  last = now; \
} \
}while (false)
#else
#define FPS_CALC (_WHAT_) \
  do \
{ \
}while (false)
#endif

void
printHelp (int, char **argv)
{
  using pcl::console::print_error;
  using pcl::console::print_info;

  print_error ("Syntax is: %s [((<device_id> | <path-to-oni-file>) [-depthmode <mode>] [-imagemode <mode>] [-xyz] | -l [<device_id>]| -h | --help)]\n", argv [0]);
  print_info ("%s -h | --help : shows this help\n", argv [0]);
  print_info ("%s -xyz : use only XYZ values and ignore RGB components (this flag is required for use with ASUS Xtion Pro) \n", argv [0]);
  print_info ("%s -l : list all available devices\n", argv [0]);
  print_info ("%s -l <device-id> :list all available modes for specified device\n", argv [0]);
  print_info ("\t\t<device_id> may be \"#1\", \"#2\", ... for the first, second etc device in the list\n");
#ifndef _WIN32
  print_info ("\t\t                   bus@address for the device connected to a specific usb-bus / address combination\n");
  print_info ("\t\t                   <serial-number>\n");
#endif
  print_info ("\n\nexamples:\n");
  print_info ("%s \"#1\"\n", argv [0]);
  print_info ("\t\t uses the first device.\n");
  print_info ("%s  \"./temp/test.oni\"\n", argv [0]);
  print_info ("\t\t uses the oni-player device to play back oni file given by path.\n");
  print_info ("%s -l\n", argv [0]);
  print_info ("\t\t list all available devices.\n");
  print_info ("%s -l \"#2\"\n", argv [0]);
  print_info ("\t\t list all available modes for the second device.\n");
#ifndef _WIN32
  print_info ("%s A00361800903049A\n", argv [0]);
  print_info ("\t\t uses the device with the serial number \'A00361800903049A\'.\n");
  print_info ("%s 1@16\n", argv [0]);
  print_info ("\t\t uses the device on address 16 at USB bus 1.\n");
#endif
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointType>
class OpenNI2Viewer
{
public:
  typedef pcl::PointCloud<PointType> Cloud;
  typedef typename Cloud::ConstPtr CloudConstPtr;

  OpenNI2Viewer (pcl::io::OpenNI2Grabber& grabber)
    : cloud_viewer_ (new pcl::visualization::PCLVisualizer ("PCL OpenNI2 cloud"))
    , image_viewer_ ()
    , grabber_ (grabber)
    , rgb_data_ (0), rgb_data_size_ (0)
  {
  }

  void
  cloud_callback (const CloudConstPtr& cloud)
  {
    FPS_CALC ("cloud callback");
    boost::mutex::scoped_lock lock (cloud_mutex_);
    cloud_ = cloud;
  }

  void
  image_callback (const boost::shared_ptr<pcl::io::openni2::Image>& image)
  {
    FPS_CALC ("image callback");
    boost::mutex::scoped_lock lock (image_mutex_);
    image_ = image;

    if (image->getEncoding () != pcl::io::openni2::Image::RGB)
    {
      if (rgb_data_size_ < image->getWidth () * image->getHeight ())
      {
        if (rgb_data_)
          delete [] rgb_data_;
        rgb_data_size_ = image->getWidth () * image->getHeight ();
        rgb_data_ = new unsigned char [rgb_data_size_ * 3];
      }
      image_->fillRGB (image_->getWidth (), image_->getHeight (), rgb_data_);
    }
  }

  void
  keyboard_callback (const pcl::visualization::KeyboardEvent& event, void*)
  {
    if (event.getKeyCode ())
      cout << "the key \'" << event.getKeyCode () << "\' (" << event.getKeyCode () << ") was";
    else
      cout << "the special key \'" << event.getKeySym () << "\' was";
    if (event.keyDown ())
      cout << " pressed" << endl;
    else
      cout << " released" << endl;
  }

  void
  mouse_callback (const pcl::visualization::MouseEvent& mouse_event, void*)
  {
    if (mouse_event.getType () == pcl::visualization::MouseEvent::MouseButtonPress && mouse_event.getButton () == pcl::visualization::MouseEvent::LeftButton)
    {
      cout << "left button pressed @ " << mouse_event.getX () << " , " << mouse_event.getY () << endl;
    }
  }

  /**
  * @brief starts the main loop
  */
  void
  run ()
  {
    cloud_viewer_->registerMouseCallback (&OpenNI2Viewer::mouse_callback, *this);
    cloud_viewer_->registerKeyboardCallback (&OpenNI2Viewer::keyboard_callback, *this);
    cloud_viewer_->setCameraFieldOfView (1.02259994f);
    boost::function<void (const CloudConstPtr&) > cloud_cb = boost::bind (&OpenNI2Viewer::cloud_callback, this, _1);
    boost::signals2::connection cloud_connection = grabber_.registerCallback (cloud_cb);

    boost::signals2::connection image_connection;
    if (grabber_.providesCallback<void (const boost::shared_ptr<pcl::io::openni2::Image>&)>())
    {
      image_viewer_.reset (new pcl::visualization::ImageViewer ("PCL OpenNI image"));
      image_viewer_->registerMouseCallback (&OpenNI2Viewer::mouse_callback, *this);
      image_viewer_->registerKeyboardCallback (&OpenNI2Viewer::keyboard_callback, *this);
      boost::function<void (const boost::shared_ptr<pcl::io::openni2::Image>&) > image_cb = boost::bind (&OpenNI2Viewer::image_callback, this, _1);
      image_connection = grabber_.registerCallback (image_cb);
    }

    bool image_init = false, cloud_init = false;

    grabber_.start ();

    while (!cloud_viewer_->wasStopped () && (image_viewer_ && !image_viewer_->wasStopped ()))
    {
      boost::shared_ptr<pcl::io::openni2::Image> image;
      CloudConstPtr cloud;

      cloud_viewer_->spinOnce ();

      // See if we can get a cloud
      if (cloud_mutex_.try_lock ())
      {
        cloud_.swap (cloud);
        cloud_mutex_.unlock ();
      }

      if (cloud)
      {
        FPS_CALC("drawing cloud");

        if (!cloud_init)
        {
          cloud_viewer_->setPosition (0, 0);
          cloud_viewer_->setSize (cloud->width, cloud->height);
          cloud_init = !cloud_init;
        }

        if (!cloud_viewer_->updatePointCloud (cloud, "OpenNICloud"))
        {
          cloud_viewer_->addPointCloud (cloud, "OpenNICloud");
          cloud_viewer_->resetCameraViewpoint ("OpenNICloud");
          cloud_viewer_->setCameraPosition (
            0,0,0,		// Position
            0,0,1,		// Viewpoint
            0,-1,0);	// Up
        }
      }

      // See if we can get an image
      if (image_mutex_.try_lock ())
      {
        image_.swap (image);
        image_mutex_.unlock ();
      }

      if (image)
      {
        if (!image_init && cloud && cloud->width != 0)
        {
          image_viewer_->setPosition (cloud->width, 0);
          image_viewer_->setSize (cloud->width, cloud->height);
          image_init = !image_init;
        }

        if (image->getEncoding () == pcl::io::openni2::Image::RGB)
          image_viewer_->addRGBImage ( (const unsigned char*)image->getData (), image->getWidth (), image->getHeight ());
        else
          image_viewer_->addRGBImage (rgb_data_, image->getWidth (), image->getHeight ());
        image_viewer_->spinOnce ();

      }
    }

    grabber_.stop ();

    cloud_connection.disconnect ();
    image_connection.disconnect ();
    if (rgb_data_)
      delete[] rgb_data_;
  }

  boost::shared_ptr<pcl::visualization::PCLVisualizer> cloud_viewer_;
  boost::shared_ptr<pcl::visualization::ImageViewer> image_viewer_;

  pcl::io::OpenNI2Grabber& grabber_;
  boost::mutex cloud_mutex_;
  boost::mutex image_mutex_;

  CloudConstPtr cloud_;
  boost::shared_ptr<pcl::io::openni2::Image> image_;
  unsigned char* rgb_data_;
  unsigned rgb_data_size_;
};

// Create the PCLVisualizer object
boost::shared_ptr<pcl::visualization::PCLVisualizer> cld;
boost::shared_ptr<pcl::visualization::ImageViewer> img;

/* ---[ */
int
main (int argc, char** argv)
{
  std::string device_id ("");
  pcl::io::OpenNI2Grabber::Mode depth_mode = pcl::io::OpenNI2Grabber::OpenNI_Default_Mode;
  pcl::io::OpenNI2Grabber::Mode image_mode = pcl::io::OpenNI2Grabber::OpenNI_Default_Mode;
  bool xyz = false;

  if (argc >= 2)
  {
    device_id = argv[1];
    if (device_id == "--help" || device_id == "-h")
    {
      printHelp (argc, argv);
      return 0;
    }
    else if (device_id == "-l")
    {
      if (argc >= 3)
      {
        pcl::io::OpenNI2Grabber grabber (argv[2]);
        boost::shared_ptr<pcl::io::openni2::OpenNI2Device> device = grabber.getDevice ();
        cout << *device;		// Prints out all sensor data, including supported video modes
      }
      else
      {
        boost::shared_ptr<pcl::io::openni2::OpenNI2DeviceManager> deviceManager = pcl::io::openni2::OpenNI2DeviceManager::getInstance ();
        if (deviceManager->getNumOfConnectedDevices () > 0)
        {
          for (unsigned deviceIdx = 0; deviceIdx < deviceManager->getNumOfConnectedDevices (); ++deviceIdx)
          {
            boost::shared_ptr<pcl::io::openni2::OpenNI2Device> device = deviceManager->getDeviceByIndex (deviceIdx);
            cout << "Device " << device->getStringID () << "connected." << endl;
          }

        }
        else
          cout << "No devices connected." << endl;

        cout <<"Virtual Devices available: ONI player" << endl;
      }
      return 0;
    }
  }
  else
  {
    boost::shared_ptr<pcl::io::openni2::OpenNI2DeviceManager> deviceManager = pcl::io::openni2::OpenNI2DeviceManager::getInstance ();
    if (deviceManager->getNumOfConnectedDevices () > 0)
    {
      boost::shared_ptr<pcl::io::openni2::OpenNI2Device> device = deviceManager->getAnyDevice ();
      cout << "Device ID not set, using default device: " << device->getStringID () << endl;
    }
  }

  unsigned mode;
  if (pcl::console::parse (argc, argv, "-depthmode", mode) != -1)
    depth_mode = pcl::io::OpenNI2Grabber::Mode (mode);

  if (pcl::console::parse (argc, argv, "-imagemode", mode) != -1)
    image_mode = pcl::io::OpenNI2Grabber::Mode (mode);

  if (pcl::console::find_argument (argc, argv, "-xyz") != -1)
    xyz = true;

  try
  {
    pcl::io::OpenNI2Grabber grabber (device_id, depth_mode, image_mode);

    if (xyz || !grabber.providesCallback<pcl::io::OpenNI2Grabber::sig_cb_openni_point_cloud_rgb> ())
    {
      OpenNI2Viewer<pcl::PointXYZ> openni_viewer (grabber);
      openni_viewer.run ();
    }
    else
    {
      OpenNI2Viewer<pcl::PointXYZRGBA> openni_viewer (grabber);
      openni_viewer.run ();
    }
  }
  catch (pcl::IOException& e)
  {
    pcl::console::print_error ("Failed to create a grabber: %s\n", e.what ());
    return (1);
  }

  return (0);
}
/* ]--- */
<|endoftext|>


<commit_before>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010-2013 Francois Beaune, Jupiter Jazz Limited
// Copyright (c) 2014-2017 Francois Beaune, The appleseedhq Organization
//
// 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.
//

// Interface header.
#include "edf.h"

// appleseed.renderer headers.
#include "renderer/global/globallogger.h"
#include "renderer/kernel/shading/shadingcontext.h"
#include "renderer/kernel/shading/shadingpoint.h"
#include "renderer/modeling/input/source.h"

// appleseed.foundation headers.
#include "foundation/utility/api/apistring.h"
#include "foundation/utility/arena.h"

// Standard headers.
#include <string>

using namespace foundation;
using namespace std;

namespace renderer
{

//
// EDF class implementation.
//

namespace
{
    const UniqueID g_class_uid = new_guid();
}

UniqueID EDF::get_class_uid()
{
    return g_class_uid;
}

EDF::EDF(
    const char*             name,
    const ParamArray&       params)
  : ConnectableEntity(g_class_uid, params)
  , m_flags(0)
  , m_light_near_start(0.0)
{
    set_name(name);
}

float EDF::get_uncached_importance_multiplier() const
{
    return m_params.get_optional<float>("importance_multiplier", 1.0f);
}

double EDF::get_uncached_light_near_start() const
{
    return m_params.get_optional<double>("light_near_start", 0.0);
}

bool EDF::on_frame_begin(
    const Project&          project,
    const BaseGroup*        parent,
    OnFrameBeginRecorder&   recorder,
    IAbortSwitch*           abort_switch)
{
    if (!ConnectableEntity::on_frame_begin(project, parent, recorder, abort_switch))
        return false;

    m_flags = 0;

    if (m_params.get_optional<bool>("cast_indirect_light", true))
        m_flags |= CastIndirectLight;

    m_light_near_start = get_uncached_light_near_start();

    if (m_light_near_start < 0.0)
    {
        RENDERER_LOG_WARNING(
            "edf \"%s\" has a negative light near start value; expect artifacts and/or slowdowns.",
            get_path().c_str());
    }

    m_max_contribution = get_uncached_max_contribution();

    if (get_uncached_importance_multiplier() <= 0.0f)
    {
        RENDERER_LOG_WARNING(
            "edf \"%s\" has negative or zero importance; expect artifacts and/or slowdowns.",
            get_path().c_str());
    }

    return true;
}

void* EDF::evaluate_inputs(
    const ShadingContext&   shading_context,
    const ShadingPoint&     shading_point) const
{
    void* data = shading_context.get_arena().allocate(get_inputs().compute_data_size());

    get_inputs().evaluate(
        shading_context.get_texture_cache(),
        shading_point.get_uv(0),
        data);

    return data;
}

float EDF::get_max_contribution_scalar(const Source* source) const
{
    assert(source);

    if (!source || !source->is_uniform())
        return numeric_limits<float>::max();

    float value;

    source->evaluate_uniform(value);

    return value;
}

float EDF::get_max_contribution_spectrum(const Source* source) const
{
    assert(source);

    if (!source || !source->is_uniform())
        return numeric_limits<float>::max();

    Spectrum spectrum;

    source->evaluate_uniform(spectrum);

    return max_value(spectrum);
}

float EDF::get_max_contribution(const Source* input, const Source* multiplier) const
{
    const float max_contribution_spectrum = get_max_contribution_spectrum(input);

    if (max_contribution_spectrum == numeric_limits<float>::max())
        return numeric_limits<float>::max();

    const float max_contribution_scalar = get_max_contribution_scalar(multiplier);

    if (max_contribution_scalar == numeric_limits<float>::max())
        return numeric_limits<float>::max();

    return max_contribution_spectrum * max_contribution_scalar;
}

float EDF::get_max_contribution(const char* input_name, const char* multiplier_name) const
{
    return get_max_contribution(m_inputs.source(input_name), m_inputs.source(multiplier_name));
}

}   // namespace renderer
<commit_msg>Remove invalid assertions<commit_after>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010-2013 Francois Beaune, Jupiter Jazz Limited
// Copyright (c) 2014-2017 Francois Beaune, The appleseedhq Organization
//
// 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.
//

// Interface header.
#include "edf.h"

// appleseed.renderer headers.
#include "renderer/global/globallogger.h"
#include "renderer/kernel/shading/shadingcontext.h"
#include "renderer/kernel/shading/shadingpoint.h"
#include "renderer/modeling/input/source.h"

// appleseed.foundation headers.
#include "foundation/utility/api/apistring.h"
#include "foundation/utility/arena.h"

// Standard headers.
#include <string>

using namespace foundation;
using namespace std;

namespace renderer
{

//
// EDF class implementation.
//

namespace
{
    const UniqueID g_class_uid = new_guid();
}

UniqueID EDF::get_class_uid()
{
    return g_class_uid;
}

EDF::EDF(
    const char*             name,
    const ParamArray&       params)
  : ConnectableEntity(g_class_uid, params)
  , m_flags(0)
  , m_light_near_start(0.0)
{
    set_name(name);
}

float EDF::get_uncached_importance_multiplier() const
{
    return m_params.get_optional<float>("importance_multiplier", 1.0f);
}

double EDF::get_uncached_light_near_start() const
{
    return m_params.get_optional<double>("light_near_start", 0.0);
}

bool EDF::on_frame_begin(
    const Project&          project,
    const BaseGroup*        parent,
    OnFrameBeginRecorder&   recorder,
    IAbortSwitch*           abort_switch)
{
    if (!ConnectableEntity::on_frame_begin(project, parent, recorder, abort_switch))
        return false;

    m_flags = 0;

    if (m_params.get_optional<bool>("cast_indirect_light", true))
        m_flags |= CastIndirectLight;

    m_light_near_start = get_uncached_light_near_start();

    if (m_light_near_start < 0.0)
    {
        RENDERER_LOG_WARNING(
            "edf \"%s\" has a negative light near start value; expect artifacts and/or slowdowns.",
            get_path().c_str());
    }

    m_max_contribution = get_uncached_max_contribution();

    if (get_uncached_importance_multiplier() <= 0.0f)
    {
        RENDERER_LOG_WARNING(
            "edf \"%s\" has negative or zero importance; expect artifacts and/or slowdowns.",
            get_path().c_str());
    }

    return true;
}

void* EDF::evaluate_inputs(
    const ShadingContext&   shading_context,
    const ShadingPoint&     shading_point) const
{
    void* data = shading_context.get_arena().allocate(get_inputs().compute_data_size());

    get_inputs().evaluate(
        shading_context.get_texture_cache(),
        shading_point.get_uv(0),
        data);

    return data;
}

float EDF::get_max_contribution_scalar(const Source* source) const
{
    if (!source || !source->is_uniform())
        return numeric_limits<float>::max();

    float value;
    source->evaluate_uniform(value);

    return value;
}

float EDF::get_max_contribution_spectrum(const Source* source) const
{
    if (!source || !source->is_uniform())
        return numeric_limits<float>::max();

    Spectrum spectrum;
    source->evaluate_uniform(spectrum);

    return max_value(spectrum);
}

float EDF::get_max_contribution(const Source* input, const Source* multiplier) const
{
    const float max_contribution_spectrum = get_max_contribution_spectrum(input);

    if (max_contribution_spectrum == numeric_limits<float>::max())
        return numeric_limits<float>::max();

    const float max_contribution_scalar = get_max_contribution_scalar(multiplier);

    if (max_contribution_scalar == numeric_limits<float>::max())
        return numeric_limits<float>::max();

    return max_contribution_spectrum * max_contribution_scalar;
}

float EDF::get_max_contribution(const char* input_name, const char* multiplier_name) const
{
    return get_max_contribution(m_inputs.source(input_name), m_inputs.source(multiplier_name));
}

}   // namespace renderer
<|endoftext|>


<commit_before>// -*-c++-*-

/*
* Copyright (C) 2004 Stephan Huber http://digitalmind.de
*
*
* The Open Scene Graph (OSG) is a cross platform C++/OpenGL library for
* real-time rendering of large 3D photo-realistic models.
* The OSG homepage is http://www.openscenegraph.org/
*
* This software is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include "QuicktimeImageStream.h"
#include <osg/Notify>
#include <osg/Timer>

#include <OpenThreads/ScopedLock>
#include <OpenThreads/Thread>

#include "QTUtils.h"
#include "MovieData.h"

#define IDLE_TIMEOUT 150000L
#define ERR_MSG(no,msg) osg::notify(osg::WARN) << "QT-ImageStream: " << msg << " failed with error " << no << std::endl;

int QuicktimeImageStream::_qtInstanceCount = 0;

// Constructor: setup and start thread
QuicktimeImageStream::QuicktimeImageStream(std::string fileName) : ImageStream()
{
   /*
   // ricky
   if(_qtInstanceCount == 0)
   {
      osg::notify(osg::NOTICE) << "quicktime Init" << std::endl;
      initQuicktime();
   }
   ++ _qtInstanceCount;
   // end ricky
   */

   _len = 0;
   _data = new MovieData();

   for (int i = 0; i < NUM_CMD_INDEX; i++)
      _cmd[i] = THREAD_IDLE;
   _wrIndex = _rdIndex = 0;

   load(fileName);

   if (!fileName.empty())
      setFileName(fileName);

   // ricky
   _status = ImageStream::PAUSED;
}

// Deconstructor: stop and terminate thread
QuicktimeImageStream::~QuicktimeImageStream()
{
   if( isRunning() )
   {
      quit(true);
   }

   /*
   // ricky
   -- _qtInstanceCount;
   if(_qtInstanceCount == 0)
   {
      osg::notify(osg::NOTICE) << "quicktime Exit" << std::endl;
      exitQuicktime();
   }
   // end ricky
   */

   // clean up quicktime movies.
   delete _data;

}

// Set command
void QuicktimeImageStream::setCmd(ThreadCommand cmd, float rate)
{
   OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);

   _cmd[_wrIndex] = cmd;
   _rates[_wrIndex] = rate;
   _wrIndex = (_wrIndex + 1) % NUM_CMD_INDEX;
}

// Get command
QuicktimeImageStream::ThreadCommand QuicktimeImageStream::getCmd()
{
   ThreadCommand cmd = THREAD_IDLE;

   OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);

   if (_rdIndex != _wrIndex) {
      cmd = _cmd[_rdIndex];
      _currentRate = _rates[_rdIndex];
      _rdIndex = (_rdIndex + 1) % NUM_CMD_INDEX;
   }

   return cmd;
}

void QuicktimeImageStream::load(std::string fileName)
{
   osg::notify(osg::DEBUG_INFO) << "QT-ImageStream: loading quicktime movie from " << fileName << std::endl;

   _data->load(this, fileName);

   _len = _data->getMovieDuration();
   _current = 0;
}

void QuicktimeImageStream::quit(bool wiatForThreadToExit)
{
   osg::notify(osg::DEBUG_INFO)<<"Sending quit"<<this<<std::endl;
   setCmd(THREAD_QUIT);

   if (wiatForThreadToExit)
   {
      while(isRunning())
      {
         osg::notify(osg::DEBUG_INFO)<<"Waiting for QuicktimeImageStream to quit"<<this<<std::endl;
         OpenThreads::Thread::YieldCurrentThread();
      }
      osg::notify(osg::DEBUG_INFO)<<"QuicktimeImageStream has quit"<<this<<std::endl;
   }
}

void QuicktimeImageStream::run()
{

   bool playing = false;
   bool done = false;

   /*
   OSErr err;
   err = EnterMoviesOnThread(0);
   ERR_MSG(err,"EnterMoviesOnThread");
   err = AttachMovieToCurrentThread(_data->getMovie());
   */
   while (!done) {

      ThreadCommand cmd = getCmd();
      osg::notify(osg::DEBUG_INFO) << "movietime: " << _data->getMovieTime() << " rate: " << _data->getMovieRate() << " state " << cmd << " playing: " << playing << " done " << done << "  " << _wrIndex << "/" << _rdIndex << std::endl;
      // Handle commands
      {
         if (cmd != THREAD_IDLE) {
            osg::notify(osg::DEBUG_INFO) << "new cmd: " << cmd << std::endl;
            switch (cmd) {
                    case THREAD_START: // Start or continue stream
                       _data->setMovieRate(1.0f);

                       playing = true;
                       break;

                    case THREAD_STOP:
                       _data->setMovieRate(0);
                       osg::notify(osg::INFO) << "QT-ImageStream: stop at "<< std::endl;
                       playing = false;
                       break;

                    case THREAD_REWIND:
                       SetMovieRate(_data->getMovie(),0);
                       GoToBeginningOfMovie(_data->getMovie());
                       break;

                    case THREAD_FORWARD:
                       SetMovieRate(_data->getMovie(),0);
                       GoToEndOfMovie(_data->getMovie());
                       break;

                    case THREAD_SEEK:
                       _data->setMovieTime(_currentRate);
                       playing = true;
                       break;

                    case THREAD_SETRATE:
                       _data->setMovieRate(_currentRate);
                       playing = (_currentRate != 0.0f);
                       break;

                    case THREAD_CLOSE:
                       _data->setMovieRate(0);
                       break;

                    case THREAD_QUIT: // TODO
                       _data->setMovieRate(0);
                       osg::notify(osg::INFO) << "QT-ImageStream: quit" << std::endl;
                       //playing = false;
                       done = true;
                       break;
                    default:
                       osg::notify(osg::WARN) << "QT-ImageStream: Unknown command " << cmd << std::endl;
                       break;
            }
         }

         MoviesTask(_data->getMovie(),0);
         _current = _data->getMovieTime();
      }

      if (_lastUpdate!= _current)
      {
         // force the texture to update the image
         dirty();
         // update internal time and take care of looping
         _lastUpdate = _current;

         if (getLoopingMode() == LOOPING)
         {
            // loopen wir rueckwaerts?
            if ((_current <= 0.0f) && (_data->getCachedMovieRate() < 0.0f)) {
               forward();
               setMovieRate(_data->getCachedMovieRate());
            }
            // loppen wir vorwrts?
            else if ((_current >= _len) && (_data->getCachedMovieRate() > 0.0f))
            {
               rewind();
               setMovieRate(_data->getCachedMovieRate());
            }
         }
         else
         { // NO LOOPING
            //ricky
            if(_current >= _len)
            {
               pause();
               rewind();
            }
            // orig
            //pause();

            //end ricky
         }
      }

      if (playing)
      {
         OpenThreads::Thread::microSleep(16000);
      }
      else if (!done)
      {
         OpenThreads::Thread::microSleep(IDLE_TIMEOUT);
      }
   }
   /*
   err = DetachMovieFromCurrentThread(_data->getMovie());
   err = ExitMoviesOnThread();
   ERR_MSG(err,"ExitMoviesOnThread");
   */
}
<commit_msg>From Brad Colbert, removed inappropriate rewind on non looping code path.<commit_after>// -*-c++-*-

/*
* Copyright (C) 2004 Stephan Huber http://digitalmind.de
*
*
* The Open Scene Graph (OSG) is a cross platform C++/OpenGL library for
* real-time rendering of large 3D photo-realistic models.
* The OSG homepage is http://www.openscenegraph.org/
*
* This software is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include "QuicktimeImageStream.h"
#include <osg/Notify>
#include <osg/Timer>

#include <OpenThreads/ScopedLock>
#include <OpenThreads/Thread>

#include "QTUtils.h"
#include "MovieData.h"

#define IDLE_TIMEOUT 150000L
#define ERR_MSG(no,msg) osg::notify(osg::WARN) << "QT-ImageStream: " << msg << " failed with error " << no << std::endl;

int QuicktimeImageStream::_qtInstanceCount = 0;

// Constructor: setup and start thread
QuicktimeImageStream::QuicktimeImageStream(std::string fileName) : ImageStream()
{
   /*
   // ricky
   if(_qtInstanceCount == 0)
   {
      osg::notify(osg::NOTICE) << "quicktime Init" << std::endl;
      initQuicktime();
   }
   ++ _qtInstanceCount;
   // end ricky
   */

   _len = 0;
   _data = new MovieData();

   for (int i = 0; i < NUM_CMD_INDEX; i++)
      _cmd[i] = THREAD_IDLE;
   _wrIndex = _rdIndex = 0;

   load(fileName);

   if (!fileName.empty())
      setFileName(fileName);

   // ricky
   _status = ImageStream::PAUSED;
}

// Deconstructor: stop and terminate thread
QuicktimeImageStream::~QuicktimeImageStream()
{
   if( isRunning() )
   {
      quit(true);
   }

   /*
   // ricky
   -- _qtInstanceCount;
   if(_qtInstanceCount == 0)
   {
      osg::notify(osg::NOTICE) << "quicktime Exit" << std::endl;
      exitQuicktime();
   }
   // end ricky
   */

   // clean up quicktime movies.
   delete _data;

}

// Set command
void QuicktimeImageStream::setCmd(ThreadCommand cmd, float rate)
{
   OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);

   _cmd[_wrIndex] = cmd;
   _rates[_wrIndex] = rate;
   _wrIndex = (_wrIndex + 1) % NUM_CMD_INDEX;
}

// Get command
QuicktimeImageStream::ThreadCommand QuicktimeImageStream::getCmd()
{
   ThreadCommand cmd = THREAD_IDLE;

   OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);

   if (_rdIndex != _wrIndex) {
      cmd = _cmd[_rdIndex];
      _currentRate = _rates[_rdIndex];
      _rdIndex = (_rdIndex + 1) % NUM_CMD_INDEX;
   }

   return cmd;
}

void QuicktimeImageStream::load(std::string fileName)
{
   osg::notify(osg::DEBUG_INFO) << "QT-ImageStream: loading quicktime movie from " << fileName << std::endl;

   _data->load(this, fileName);

   _len = _data->getMovieDuration();
   _current = 0;
}

void QuicktimeImageStream::quit(bool wiatForThreadToExit)
{
   osg::notify(osg::DEBUG_INFO)<<"Sending quit"<<this<<std::endl;
   setCmd(THREAD_QUIT);

   if (wiatForThreadToExit)
   {
      while(isRunning())
      {
         osg::notify(osg::DEBUG_INFO)<<"Waiting for QuicktimeImageStream to quit"<<this<<std::endl;
         OpenThreads::Thread::YieldCurrentThread();
      }
      osg::notify(osg::DEBUG_INFO)<<"QuicktimeImageStream has quit"<<this<<std::endl;
   }
}

void QuicktimeImageStream::run()
{

   bool playing = false;
   bool done = false;

   /*
   OSErr err;
   err = EnterMoviesOnThread(0);
   ERR_MSG(err,"EnterMoviesOnThread");
   err = AttachMovieToCurrentThread(_data->getMovie());
   */
   while (!done) {

      ThreadCommand cmd = getCmd();
      osg::notify(osg::DEBUG_INFO) << "movietime: " << _data->getMovieTime() << " rate: " << _data->getMovieRate() << " state " << cmd << " playing: " << playing << " done " << done << "  " << _wrIndex << "/" << _rdIndex << std::endl;
      // Handle commands
      {
         if (cmd != THREAD_IDLE) {
            osg::notify(osg::DEBUG_INFO) << "new cmd: " << cmd << std::endl;
            switch (cmd) {
                    case THREAD_START: // Start or continue stream
                       _data->setMovieRate(1.0f);

                       playing = true;
                       break;

                    case THREAD_STOP:
                       _data->setMovieRate(0);
                       osg::notify(osg::INFO) << "QT-ImageStream: stop at "<< std::endl;
                       playing = false;
                       break;

                    case THREAD_REWIND:
                       SetMovieRate(_data->getMovie(),0);
                       GoToBeginningOfMovie(_data->getMovie());
                       break;

                    case THREAD_FORWARD:
                       SetMovieRate(_data->getMovie(),0);
                       GoToEndOfMovie(_data->getMovie());
                       break;

                    case THREAD_SEEK:
                       _data->setMovieTime(_currentRate);
                       playing = true;
                       break;

                    case THREAD_SETRATE:
                       _data->setMovieRate(_currentRate);
                       playing = (_currentRate != 0.0f);
                       break;

                    case THREAD_CLOSE:
                       _data->setMovieRate(0);
                       break;

                    case THREAD_QUIT: // TODO
                       _data->setMovieRate(0);
                       osg::notify(osg::INFO) << "QT-ImageStream: quit" << std::endl;
                       //playing = false;
                       done = true;
                       break;
                    default:
                       osg::notify(osg::WARN) << "QT-ImageStream: Unknown command " << cmd << std::endl;
                       break;
            }
         }

         MoviesTask(_data->getMovie(),0);
         _current = _data->getMovieTime();
      }

      if (_lastUpdate!= _current)
      {
         // force the texture to update the image
         dirty();
         // update internal time and take care of looping
         _lastUpdate = _current;

         if (getLoopingMode() == LOOPING)
         {
            // loopen wir rueckwaerts?
            if ((_current <= 0.0f) && (_data->getCachedMovieRate() < 0.0f)) {
               forward();
               setMovieRate(_data->getCachedMovieRate());
            }
            // loppen wir vorwrts?
            else if ((_current >= _len) && (_data->getCachedMovieRate() > 0.0f))
            {
               rewind();
               setMovieRate(_data->getCachedMovieRate());
            }
         }
         else
         { // NO LOOPING
            //ricky
            if(_current >= _len)
            {
               pause();

               // Don't rewind to the begining if the movie has completed.
               // Someone may want to see the last frame displayed.
               //rewind();
            }
            // orig
            //pause();

            //end ricky
         }
      }

      if (playing)
      {
         OpenThreads::Thread::microSleep(16000);
      }
      else if (!done)
      {
         OpenThreads::Thread::microSleep(IDLE_TIMEOUT);
      }
   }
   /*
   err = DetachMovieFromCurrentThread(_data->getMovie());
   err = ExitMoviesOnThread();
   ERR_MSG(err,"ExitMoviesOnThread");
   */
}
<|endoftext|>