<commit_before>#include "Unit.h"
#include "CCBot.h"

Unit::Unit()
    : m_bot(nullptr)
    , m_unit(nullptr)
    , m_unitID(0)
{

}

#ifdef SC2API
Unit::Unit(const sc2::Unit * unit, CCBot & bot)
    : m_bot(&bot)
    , m_unit(unit)
    , m_unitID(unit->tag)
    , m_unitType(unit->unit_type, bot)
{

}

const sc2::Unit * Unit::getUnitPtr() const
{
    return m_unit;
}

const sc2::UnitTypeID & Unit::getAPIUnitType() const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
    return m_unit->unit_type;
}

#else
Unit::Unit(const BWAPI::Unit unit, CCBot & bot)
    : m_bot(&bot)
    , m_unit(unit)
    , m_unitID(unit->getID())
    , m_unitType(unit->getType(), bot)
{

}

const BWAPI::Unit Unit::getUnitPtr() const
{
    return m_unit;
}

const BWAPI::UnitType & Unit::getAPIUnitType() const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
    return m_unit->getType();
}

#endif
bool Unit::operator < (const Unit & rhs) const
{
    return m_unit < rhs.m_unit;
}

bool Unit::operator == (const Unit & rhs) const
{
    return m_unit == rhs.m_unit;
}

const UnitType & Unit::getType() const
{
    return m_unitType;
}

CCPosition Unit::getPosition() const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
    return m_unit->pos;
#else
    return m_unit->getPosition();
#endif
}

CCTilePosition Unit::getTilePosition() const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
    return Util::GetTilePosition(m_unit->pos);
#else
    return m_unit->getTilePosition();
#endif
}

CCHealth Unit::getHitPoints() const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
    return m_unit->health;
#else
    return m_unit->getHitPoints();
#endif
}

CCHealth Unit::getShields() const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
    return m_unit->shield;
#else
    return m_unit->getShields();
#endif
}

CCHealth Unit::getEnergy() const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
    return m_unit->energy;
#else
    return m_unit->getEnergy();
#endif
}

float Unit::getBuildPercentage() const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
    return m_unit->build_progress;
#else
    if (getType().isBuilding()) { return m_unit->getRemainingBuildTime() / (float)getType().getAPIUnitType().buildTime(); }
    else { return m_unit->getRemainingTrainTime() / (float)getType().getAPIUnitType().buildTime(); }
#endif
}

CCPlayer Unit::getPlayer() const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
    if (m_unit->alliance == sc2::Unit::Alliance::Self) { return 0; }
    else if (m_unit->alliance == sc2::Unit::Alliance::Enemy) { return 1; }
    else { return 2; }
#else
    if (m_unit->getPlayer() == BWAPI::Broodwar->self()) { return 0; }
    else if (m_unit->getPlayer() == BWAPI::Broodwar->enemy()) { return 1; }
    else { return 2; }
#endif
}

CCUnitID Unit::getID() const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
    CCUnitID id = m_unit->tag;
#else
    CCUnitID id = m_unit->getID();
#endif

    BOT_ASSERT(id == m_unitID, "Unit ID changed somehow");
    return id;
}

bool Unit::isCompleted() const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
    return m_unit->build_progress >= 1.0f;
#else
    return m_unit->isCompleted();
#endif
}

bool Unit::isTraining() const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
    return m_unit->orders.size() > 0;
#else
    return m_unit->isTraining();
#endif
}

bool Unit::isBeingConstructed() const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
    return !isCompleted() && m_unit->build_progress > 0.0f;
#else
    return m_unit->isBeingConstructed();
#endif
}

int Unit::getWeaponCooldown() const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
    return (int)m_unit->weapon_cooldown;
#else
    return std::max(m_unit->getGroundWeaponCooldown(), m_unit->getAirWeaponCooldown());
#endif
}

bool Unit::isCloaked() const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
    return m_unit->cloak;
#else
    return m_unit->isCloaked();
#endif
}

bool Unit::isFlying() const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
    return m_unit->is_flying;
#else
    return m_unit->isFlying();
#endif
}

bool Unit::isAlive() const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
    return m_unit->is_alive;
#else
    return m_unit->getHitPoints() > 0;
#endif
}

bool Unit::isPowered() const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
    return m_unit->is_powered;
#else
    return m_unit->isPowered();
#endif
}

bool Unit::isIdle() const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
    return m_unit->orders.empty();
#else
    return m_unit->isIdle();
#endif
}

bool Unit::isBurrowed() const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
    return m_unit->is_burrowed;
#else
    return m_unit->isBurrowed();
#endif
}

bool Unit::isValid() const
{
    return m_unit != nullptr;
}

void Unit::stop() const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
    m_bot->Actions()->UnitCommand(m_unit, sc2::ABILITY_ID::STOP);
#else
    m_unit->stop();
#endif
}

void Unit::attackUnit(const Unit & target) const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
    BOT_ASSERT(target.isValid(), "Target is not valid");
#ifdef SC2API
    m_bot->Actions()->UnitCommand(m_unit, sc2::ABILITY_ID::ATTACK_ATTACK, target.getUnitPtr());
#else
    m_unit->attack(target.getUnitPtr());
#endif
}

void Unit::attackMove(const CCPosition & targetPosition) const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
    m_bot->Actions()->UnitCommand(m_unit, sc2::ABILITY_ID::ATTACK_ATTACK, targetPosition);
#else
    m_unit->attack(targetPosition);
#endif
}

void Unit::move(const CCPosition & targetPosition) const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
    m_bot->Actions()->UnitCommand(m_unit, sc2::ABILITY_ID::MOVE, targetPosition);
#else
    m_unit->move(targetPosition);
#endif
}

void Unit::move(const CCTilePosition & targetPosition) const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
    m_bot->Actions()->UnitCommand(m_unit, sc2::ABILITY_ID::MOVE, CCPosition((float)targetPosition.x, (float)targetPosition.y));
#else
    m_unit->move(CCPosition(targetPosition));
#endif
}

void Unit::rightClick(const Unit & target) const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
    m_bot->Actions()->UnitCommand(m_unit, sc2::ABILITY_ID::SMART, target.getUnitPtr());
#else
    m_unit->rightClick(target.getUnitPtr());
#endif
}

void Unit::repair(const Unit & target) const
{
    rightClick(target);
}

void Unit::build(const UnitType & buildingType, CCTilePosition pos) const
{
    BOT_ASSERT(m_bot->Map().isConnected(getTilePosition(), pos), "Error: Build Position is not connected to worker");
    BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
    m_bot->Actions()->UnitCommand(m_unit, m_bot->Data(buildingType).buildAbility, Util::GetPosition(pos));
#else
    m_unit->build(buildingType.getAPIUnitType(), pos);
#endif
}

void Unit::buildTarget(const UnitType & buildingType, const Unit & target) const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
    m_bot->Actions()->UnitCommand(m_unit, m_bot->Data(buildingType).buildAbility, target.getUnitPtr());
#else
    BOT_ASSERT(false, "buildTarget shouldn't be called for BWAPI bots");
#endif
}

void Unit::train(const UnitType & type) const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
    m_bot->Actions()->UnitCommand(m_unit, m_bot->Data(type).buildAbility);
#else
    m_unit->train(type.getAPIUnitType());
#endif
}

bool Unit::isConstructing(const UnitType & type) const
{
#ifdef SC2API
    sc2::AbilityID buildAbility = m_bot->Data(type).buildAbility;
    return (getUnitPtr()->orders.size() > 0) && (getUnitPtr()->orders[0].ability_id == buildAbility);
#else
    return m_unit->isConstructing();
#endif
}<commit_msg>unit fix<commit_after>#include "Unit.h"
#include "CCBot.h"

Unit::Unit()
    : m_bot(nullptr)
    , m_unit(nullptr)
    , m_unitID(0)
{

}

#ifdef SC2API
Unit::Unit(const sc2::Unit * unit, CCBot & bot)
    : m_bot(&bot)
    , m_unit(unit)
    , m_unitID(unit->tag)
    , m_unitType(unit->unit_type, bot)
{

}

const sc2::Unit * Unit::getUnitPtr() const
{
    return m_unit;
}

const sc2::UnitTypeID & Unit::getAPIUnitType() const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
    return m_unit->unit_type;
}

#else
Unit::Unit(const BWAPI::Unit unit, CCBot & bot)
    : m_bot(&bot)
    , m_unit(unit)
    , m_unitID(unit->getID())
    , m_unitType(unit->getType(), bot)
{

}

const BWAPI::Unit Unit::getUnitPtr() const
{
    return m_unit;
}

const BWAPI::UnitType & Unit::getAPIUnitType() const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
    return m_unit->getType();
}

#endif
bool Unit::operator < (const Unit & rhs) const
{
    return m_unit < rhs.m_unit;
}

bool Unit::operator == (const Unit & rhs) const
{
    return m_unit == rhs.m_unit;
}

const UnitType & Unit::getType() const
{
    return m_unitType;
}

CCPosition Unit::getPosition() const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
    return m_unit->pos;
#else
    return m_unit->getPosition();
#endif
}

CCTilePosition Unit::getTilePosition() const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
    return Util::GetTilePosition(m_unit->pos);
#else
    return m_unit->getTilePosition();
#endif
}

CCHealth Unit::getHitPoints() const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
    return m_unit->health;
#else
    return m_unit->getHitPoints();
#endif
}

CCHealth Unit::getShields() const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
    return m_unit->shield;
#else
    return m_unit->getShields();
#endif
}

CCHealth Unit::getEnergy() const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
    return m_unit->energy;
#else
    return m_unit->getEnergy();
#endif
}

float Unit::getBuildPercentage() const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
    return m_unit->build_progress;
#else
    if (getType().isBuilding()) { return m_unit->getRemainingBuildTime() / (float)getType().getAPIUnitType().buildTime(); }
    else { return m_unit->getRemainingTrainTime() / (float)getType().getAPIUnitType().buildTime(); }
#endif
}

CCPlayer Unit::getPlayer() const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
    if (m_unit->alliance == sc2::Unit::Alliance::Self) { return 0; }
    else if (m_unit->alliance == sc2::Unit::Alliance::Enemy) { return 1; }
    else { return 2; }
#else
    if (m_unit->getPlayer() == BWAPI::Broodwar->self()) { return 0; }
    else if (m_unit->getPlayer() == BWAPI::Broodwar->enemy()) { return 1; }
    else { return 2; }
#endif
}

CCUnitID Unit::getID() const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
    CCUnitID id = m_unit->tag;
#else
    CCUnitID id = m_unit->getID();
#endif

    BOT_ASSERT(id == m_unitID, "Unit ID changed somehow");
    return id;
}

bool Unit::isCompleted() const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
    return m_unit->build_progress >= 1.0f;
#else
    return m_unit->isCompleted();
#endif
}

bool Unit::isTraining() const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
    return m_unit->orders.size() > 0;
#else
    return m_unit->isTraining();
#endif
}

bool Unit::isBeingConstructed() const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
    return !isCompleted() && m_unit->build_progress > 0.0f;
#else
    return m_unit->isBeingConstructed();
#endif
}

int Unit::getWeaponCooldown() const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
    return (int)m_unit->weapon_cooldown;
#else
    return std::max(m_unit->getGroundWeaponCooldown(), m_unit->getAirWeaponCooldown());
#endif
}

bool Unit::isCloaked() const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
    return m_unit->cloak;
#else
    return m_unit->isCloaked();
#endif
}

bool Unit::isFlying() const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
    return m_unit->is_flying;
#else
    return m_unit->isFlying();
#endif
}

bool Unit::isAlive() const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
    return m_unit->is_alive;
#else
    return m_unit->getHitPoints() > 0;
#endif
}

bool Unit::isPowered() const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
    return m_unit->is_powered;
#else
    return m_unit->isPowered();
#endif
}

bool Unit::isIdle() const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
    return m_unit->orders.empty();
#else
    return m_unit->isIdle() && !m_unit->isMoving() && !m_unit->isGatheringGas() && !m_unit->isGatheringMinerals();
#endif
}

bool Unit::isBurrowed() const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
    return m_unit->is_burrowed;
#else
    return m_unit->isBurrowed();
#endif
}

bool Unit::isValid() const
{
    return m_unit != nullptr;
}

void Unit::stop() const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
    m_bot->Actions()->UnitCommand(m_unit, sc2::ABILITY_ID::STOP);
#else
    m_unit->stop();
#endif
}

void Unit::attackUnit(const Unit & target) const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
    BOT_ASSERT(target.isValid(), "Target is not valid");
#ifdef SC2API
    m_bot->Actions()->UnitCommand(m_unit, sc2::ABILITY_ID::ATTACK_ATTACK, target.getUnitPtr());
#else
    m_unit->attack(target.getUnitPtr());
#endif
}

void Unit::attackMove(const CCPosition & targetPosition) const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
    m_bot->Actions()->UnitCommand(m_unit, sc2::ABILITY_ID::ATTACK_ATTACK, targetPosition);
#else
    m_unit->attack(targetPosition);
#endif
}

void Unit::move(const CCPosition & targetPosition) const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
    m_bot->Actions()->UnitCommand(m_unit, sc2::ABILITY_ID::MOVE, targetPosition);
#else
    m_unit->move(targetPosition);
#endif
}

void Unit::move(const CCTilePosition & targetPosition) const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
    m_bot->Actions()->UnitCommand(m_unit, sc2::ABILITY_ID::MOVE, CCPosition((float)targetPosition.x, (float)targetPosition.y));
#else
    m_unit->move(CCPosition(targetPosition));
#endif
}

void Unit::rightClick(const Unit & target) const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
    m_bot->Actions()->UnitCommand(m_unit, sc2::ABILITY_ID::SMART, target.getUnitPtr());
#else
    m_unit->rightClick(target.getUnitPtr());
#endif
}

void Unit::repair(const Unit & target) const
{
    rightClick(target);
}

void Unit::build(const UnitType & buildingType, CCTilePosition pos) const
{
    BOT_ASSERT(m_bot->Map().isConnected(getTilePosition(), pos), "Error: Build Position is not connected to worker");
    BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
    m_bot->Actions()->UnitCommand(m_unit, m_bot->Data(buildingType).buildAbility, Util::GetPosition(pos));
#else
    m_unit->build(buildingType.getAPIUnitType(), pos);
#endif
}

void Unit::buildTarget(const UnitType & buildingType, const Unit & target) const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
    m_bot->Actions()->UnitCommand(m_unit, m_bot->Data(buildingType).buildAbility, target.getUnitPtr());
#else
    BOT_ASSERT(false, "buildTarget shouldn't be called for BWAPI bots");
#endif
}

void Unit::train(const UnitType & type) const
{
    BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
    m_bot->Actions()->UnitCommand(m_unit, m_bot->Data(type).buildAbility);
#else
    m_unit->train(type.getAPIUnitType());
#endif
}

bool Unit::isConstructing(const UnitType & type) const
{
#ifdef SC2API
    sc2::AbilityID buildAbility = m_bot->Data(type).buildAbility;
    return (getUnitPtr()->orders.size() > 0) && (getUnitPtr()->orders[0].ability_id == buildAbility);
#else
    return m_unit->isConstructing();
#endif
}<|endoftext|>


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

  Program:   Visualization Toolkit
  Module:    vtkBlankStructuredGridWithImage.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

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

=========================================================================*/
#include "vtkBlankStructuredGridWithImage.h"

#include "vtkCellData.h"
#include "vtkFieldData.h"
#include "vtkImageData.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkStructuredGrid.h"
#include "vtkUnsignedCharArray.h"

vtkCxxRevisionMacro(vtkBlankStructuredGridWithImage, "1.10");
vtkStandardNewMacro(vtkBlankStructuredGridWithImage);

//----------------------------------------------------------------------------
vtkBlankStructuredGridWithImage::vtkBlankStructuredGridWithImage()
{
  this->NumberOfRequiredInputs = 2;
}

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

//----------------------------------------------------------------------------
// Specify the input data or filter.
void vtkBlankStructuredGridWithImage::SetBlankingInput(vtkImageData *input)
{
  this->vtkProcessObject::SetNthInput(1, input);
}

//----------------------------------------------------------------------------
// Specify the input data or filter.
vtkImageData *vtkBlankStructuredGridWithImage::GetBlankingInput()
{
  if (this->NumberOfInputs < 2)
    {
    return NULL;
    }

  return (vtkImageData *)(this->Inputs[1]);
}

void vtkBlankStructuredGridWithImage::Execute()
{
  vtkStructuredGrid *grid = this->GetInput();
  vtkStructuredGrid *output = this->GetOutput();
  vtkImageData *image = this->GetBlankingInput();
  int gridDims[3], imageDims[3];

  vtkDebugMacro(<< "Adding image blanking");

  // Perform error checking
  grid->GetDimensions(gridDims);
  image->GetDimensions(imageDims);
  if ( gridDims[0] != imageDims[0] || gridDims[1] != imageDims[1] ||
       gridDims[2] != imageDims[2] )
    {
    vtkErrorMacro(<< "Blanking dimensions must be identical with grid dimensions");
    return;
    }

  if ( image->GetScalarType() != VTK_UNSIGNED_CHAR ||
       image->GetNumberOfScalarComponents() != 1 )
    {
    vtkErrorMacro(<<"This filter requires unsigned char images with one component");
    return;
    }

  // Get the image, set it as the blanking array.
  unsigned char *data = (unsigned char *)image->GetScalarPointer();
  vtkUnsignedCharArray *dataArray = vtkUnsignedCharArray::New();
  dataArray->SetArray(data, gridDims[0]*gridDims[1]*gridDims[2], 1);

  output->CopyStructure(grid);
  output->GetPointData()->PassData(grid->GetPointData());
  output->GetCellData()->PassData(grid->GetCellData());
  output->SetPointVisibilityArray(dataArray);

  dataArray->Delete();
}

//----------------------------------------------------------------------------
void vtkBlankStructuredGridWithImage::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);
}
<commit_msg>ENH: Added more verbose error message for bad inputs.<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkBlankStructuredGridWithImage.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

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

=========================================================================*/
#include "vtkBlankStructuredGridWithImage.h"

#include "vtkCellData.h"
#include "vtkFieldData.h"
#include "vtkImageData.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkStructuredGrid.h"
#include "vtkUnsignedCharArray.h"

vtkCxxRevisionMacro(vtkBlankStructuredGridWithImage, "1.11");
vtkStandardNewMacro(vtkBlankStructuredGridWithImage);

//----------------------------------------------------------------------------
vtkBlankStructuredGridWithImage::vtkBlankStructuredGridWithImage()
{
  this->NumberOfRequiredInputs = 2;
}

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

//----------------------------------------------------------------------------
// Specify the input data or filter.
void vtkBlankStructuredGridWithImage::SetBlankingInput(vtkImageData *input)
{
  this->vtkProcessObject::SetNthInput(1, input);
}

//----------------------------------------------------------------------------
// Specify the input data or filter.
vtkImageData *vtkBlankStructuredGridWithImage::GetBlankingInput()
{
  if (this->NumberOfInputs < 2)
    {
    return NULL;
    }

  return (vtkImageData *)(this->Inputs[1]);
}

void vtkBlankStructuredGridWithImage::Execute()
{
  vtkStructuredGrid *grid = this->GetInput();
  vtkStructuredGrid *output = this->GetOutput();
  vtkImageData *image = this->GetBlankingInput();
  int gridDims[3], imageDims[3];

  vtkDebugMacro(<< "Adding image blanking");

  // Perform error checking
  grid->GetDimensions(gridDims);
  image->GetDimensions(imageDims);
  if ( gridDims[0] != imageDims[0] || gridDims[1] != imageDims[1] ||
       gridDims[2] != imageDims[2] )
    {
    vtkErrorMacro("Blanking dimensions must be identical with grid dimensions. "
                  "Blanking dimensions are " << imageDims[0] << " "
                  << imageDims[1] << " " << imageDims[2]
                  << ". Grid dimensions are " << gridDims[0] << " "
                  << gridDims[1] << " " << gridDims[2] << ".");
    return;
    }

  if ( image->GetScalarType() != VTK_UNSIGNED_CHAR ||
       image->GetNumberOfScalarComponents() != 1 )
    {
    vtkErrorMacro(<<"This filter requires unsigned char images with one component");
    return;
    }

  // Get the image, set it as the blanking array.
  unsigned char *data = (unsigned char *)image->GetScalarPointer();
  vtkUnsignedCharArray *dataArray = vtkUnsignedCharArray::New();
  dataArray->SetArray(data, gridDims[0]*gridDims[1]*gridDims[2], 1);

  output->CopyStructure(grid);
  output->GetPointData()->PassData(grid->GetPointData());
  output->GetCellData()->PassData(grid->GetCellData());
  output->SetPointVisibilityArray(dataArray);

  dataArray->Delete();
}

//----------------------------------------------------------------------------
void vtkBlankStructuredGridWithImage::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);
}
<|endoftext|>


<commit_before>/*=========================================================================
 *
 *  Copyright David Doria 2011 daviddoria@gmail.com
 *
 *  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.
 *
 *=========================================================================*/

#include "PatchBasedInpaintingGUI.h"

// Custom
#include "InteractorStyleImageWithDrag.h"
#include "FileSelector.h"
#include "HelpersOutput.h"

// VTK
#include <vtkImageSlice.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>

// QT
#include <QFileDialog>
#include <QTextEdit>

void PatchBasedInpaintingGUI::on_chkDisplayUserPatch_clicked()
{
  this->UserPatchLayer.ImageSlice->SetVisibility(this->chkDisplayUserPatch->isChecked());
  Refresh();
}

void PatchBasedInpaintingGUI::on_radDisplayColorImage_clicked()
{
  this->spinChannelToDisplay->setEnabled(false);
  this->ImageDisplayStyle.Style = DisplayStyle::COLOR;
  Refresh();
}

void PatchBasedInpaintingGUI::on_radDisplayMagnitudeImage_clicked()
{
  this->spinChannelToDisplay->setEnabled(false);
  this->ImageDisplayStyle.Style = DisplayStyle::MAGNITUDE;
  Refresh();
}

void PatchBasedInpaintingGUI::on_radDisplayChannel_clicked()
{
  this->spinChannelToDisplay->setEnabled(true);
  this->ImageDisplayStyle.Style = DisplayStyle::CHANNEL;
  this->ImageDisplayStyle.Channel = this->spinChannelToDisplay->value();
  Refresh();
}

void PatchBasedInpaintingGUI::on_spinChannelToDisplay_valueChanged(int unused)
{
  this->ImageDisplayStyle.Channel = this->spinChannelToDisplay->value();
  Refresh();
}

void PatchBasedInpaintingGUI::on_radCompareOriginal_clicked()
{
  this->Inpainting.SetCompareToOriginal();
}

void PatchBasedInpaintingGUI::on_radCompareBlurred_clicked()
{
  this->Inpainting.SetCompareToBlurred();
}

void PatchBasedInpaintingGUI::on_radCompareCIELAB_clicked()
{
  this->Inpainting.SetCompareToCIELAB();
}

void PatchBasedInpaintingGUI::on_chkLive_clicked()
{
  // When "Live" is checked, we do not want to be able to click 'next' and 'previous'
  this->btnDisplayNextStep->setEnabled(!this->chkLive->isChecked());
  this->btnDisplayPreviousStep->setEnabled(!this->chkLive->isChecked());

  this->btnGoToIteration->setEnabled(!this->chkLive->isChecked());
  this->txtGoToIteration->setEnabled(!this->chkLive->isChecked());
}

void PatchBasedInpaintingGUI::on_btnGoToIteration_clicked()
{
  if(this->GoToIteration < this->AllPotentialCandidatePairs.size() && this->GoToIteration >= 0)
    {
    this->IterationToDisplay = this->GoToIteration;
    ChangeDisplayedIteration();
    }
}

void PatchBasedInpaintingGUI::on_btnResort_clicked()
{
  for(unsigned int iteration = 0; iteration < this->AllPotentialCandidatePairs.size(); iteration++)
    {
    for(unsigned int forwardLookId = 0; forwardLookId < this->AllPotentialCandidatePairs[iteration].size(); forwardLookId++)
      {
      CandidatePairs& candidatePairs = this->AllPotentialCandidatePairs[iteration][forwardLookId];

      if(this->radSortByAverageAbsoluteDifference->isChecked())
        {
        std::sort(candidatePairs.begin(), candidatePairs.end(), SortByAverageAbsoluteDifference);
        }
      else if(this->radSortByAverageSquaredDifference->isChecked())
        {
        std::sort(candidatePairs.begin(), candidatePairs.end(), SortByAverageSquaredDifference);
        }
      else if(this->radSortByBoundaryPixelDifference->isChecked())
        {
        std::sort(candidatePairs.begin(), candidatePairs.end(), SortByBoundaryPixelDifference);
        }
      else if(this->radSortByBoundaryIsophoteAngleDifference->isChecked())
        {
        std::sort(candidatePairs.begin(), candidatePairs.end(), SortByBoundaryIsophoteAngleDifference);
        }
      else if(this->radSortByBoundaryIsophoteStrengthDifference->isChecked())
        {
        std::sort(candidatePairs.begin(), candidatePairs.end(), SortByBoundaryIsophoteStrengthDifference);
        }
      else if(this->radSortByTotalScore->isChecked())
        {
        std::sort(candidatePairs.begin(), candidatePairs.end(), SortByTotalScore);
        }
      else
        {
        std::cerr << "No valid sorting criterion selected." << std::endl;
        }
      }
    }

  SetupTopPatchesTable();
  //on_topPatchesTableWidget_currentCellChanged(0, 0);

  Refresh();
}

void PatchBasedInpaintingGUI::on_chkHighlightUsedPatches_clicked()
{
  RefreshVTK();
}

void PatchBasedInpaintingGUI::on_chkImage_clicked()
{
  this->ImageLayer.ImageSlice->SetVisibility(this->chkImage->isChecked());
  RefreshVTK();
}

void PatchBasedInpaintingGUI::on_chkMask_clicked()
{
  this->MaskLayer.ImageSlice->SetVisibility(this->chkMask->isChecked());
  RefreshVTK();
}

void PatchBasedInpaintingGUI::on_chkPriority_clicked()
{
  this->PriorityLayer.ImageSlice->SetVisibility(this->chkPriority->isChecked());
  RefreshVTK();
}

void PatchBasedInpaintingGUI::on_chkDisplayForwardLookPatchLocations_clicked()
{
  RefreshVTK();
}

void PatchBasedInpaintingGUI::on_chkDisplaySourcePatchLocations_clicked()
{
  RefreshVTK();
}

void PatchBasedInpaintingGUI::on_chkBoundary_clicked()
{
  this->BoundaryLayer.ImageSlice->SetVisibility(this->chkBoundary->isChecked());
  RefreshVTK();
}

void PatchBasedInpaintingGUI::SetCameraPosition()
{
  double leftToRight[3] = {this->CameraLeftToRightVector[0], this->CameraLeftToRightVector[1], this->CameraLeftToRightVector[2]};
  double bottomToTop[3] = {this->CameraBottomToTopVector[0], this->CameraBottomToTopVector[1], this->CameraBottomToTopVector[2]};
  this->InteractorStyle->SetImageOrientation(leftToRight, bottomToTop);

  this->Renderer->ResetCamera();
  this->Renderer->ResetCameraClippingRange();
  this->qvtkWidget->GetRenderWindow()->Render();
}

void PatchBasedInpaintingGUI::on_actionFlipImageVertically_activated()
{
  this->CameraBottomToTopVector[1] *= -1;
  SetCameraPosition();
}

void PatchBasedInpaintingGUI::on_actionFlipImageHorizontally_activated()
{
  this->CameraLeftToRightVector[0] *= -1;
  SetCameraPosition();
}

void PatchBasedInpaintingGUI::SetCheckboxVisibility(const bool visible)
{
  chkImage->setEnabled(visible);
  chkPriority->setEnabled(visible);
  chkBoundary->setEnabled(visible);
  chkMask->setEnabled(visible);
}

void PatchBasedInpaintingGUI::on_btnDisplayPreviousStep_clicked()
{
  if(this->IterationToDisplay > 0)
    {
    this->IterationToDisplay--;
    DebugMessage<unsigned int>("Displaying iteration: ", this->IterationToDisplay);
    ChangeDisplayedIteration();
    }
  else
    {
    DebugMessage("Iteration not changed.");
    }
}

void PatchBasedInpaintingGUI::on_btnDisplayNextStep_clicked()
{
  //std::cout << "IterationToDisplay: " << this->IterationToDisplay
    //        << " Inpainting iteration: " <<  static_cast<int>(this->Inpainting.GetIteration()) << std::endl;

  //if(this->IterationToDisplay < this->Inpainting.GetNumberOfCompletedIterations() - 1)
  if(this->IterationToDisplay < this->IntermediateImages.size() - 1)
    {
    this->IterationToDisplay++;
    DebugMessage<unsigned int>("Displaying iteration: ", this->IterationToDisplay);
    ChangeDisplayedIteration();
    }
  else
    {
    DebugMessage("Iteration not changed.");
    }
}

void PatchBasedInpaintingGUI::on_actionOpen_activated()
{
  FileSelector* fileSelector(new FileSelector);
  fileSelector->exec();

  int result = fileSelector->result();
  if(result) // The user clicked 'ok'
    {
    std::cout << "User clicked ok." << std::endl;
    OpenImage(fileSelector->GetImageFileName());
    OpenMask(fileSelector->GetMaskFileName(), fileSelector->IsMaskInverted());
    Initialize();
    }
  else
    {
    std::cout << "User clicked cancel." << std::endl;
    // The user clicked 'cancel' or closed the dialog, do nothing.
    }
}

void PatchBasedInpaintingGUI::on_actionSaveResult_activated()
{
  // Get a filename to save
  QString fileName = QFileDialog::getSaveFileName(this, "Save File", ".", "Image Files (*.jpg *.jpeg *.bmp *.png *.mha)");

  DebugMessage<std::string>("Got filename: ", fileName.toStdString());
  if(fileName.toStdString().empty())
    {
    std::cout << "Filename was empty." << std::endl;
    return;
    }

  HelpersOutput::WriteImage<FloatVectorImageType>(this->Inpainting.GetCurrentOutputImage(), fileName.toStdString());

  this->statusBar()->showMessage("Saved result.");
}

void PatchBasedInpaintingGUI::on_chkDebugImages_clicked()
{
  QDir directoryMaker;
  directoryMaker.mkdir("Debug");

  this->Inpainting.SetDebugImages(this->chkDebugImages->isChecked());
  this->DebugImages = this->chkDebugImages->isChecked();

  DebugMessage<bool>("DebugImages: ", this->DebugImages);
}

void PatchBasedInpaintingGUI::on_chkDebugMessages_clicked()
{
  this->Inpainting.SetDebugMessages(this->chkDebugMessages->isChecked());
  this->DebugMessages = this->chkDebugMessages->isChecked();
}

void PatchBasedInpaintingGUI::on_actionQuit_activated()
{
  exit(0);
}

void PatchBasedInpaintingGUI::slot_ForwardLookTableView_changed(const QModelIndex& currentIndex, const QModelIndex& previousIndex)
{
  std::cout << "on_ForwardLookTableView_currentCellChanged" << std::endl;

  if(currentIndex.row() < 0)
    {
    std::cout << "on_ForwardLookTableView_currentCellChanged: row < 0!" << std::endl;
    return;
    }

  if(currentIndex.row() > static_cast<int>(this->AllPotentialCandidatePairs[this->IterationToDisplay - 1].size() - 1))
    {
    std::cerr << "Requested display of forward look patch " << currentIndex.row() << " but there are only " << this->AllPotentialCandidatePairs[this->IterationToDisplay - 1].size() - 1 << std::endl;
    }

  std::cerr << "Requested display of forward look patch " << currentIndex.row() << std::endl;

  this->ForwardLookToDisplay = currentIndex.row();
  this->SourcePatchToDisplay = 0;

  ChangeDisplayedForwardLookPatch();

  SetupTopPatchesTable();
  ChangeDisplayedTopPatch();

}

void PatchBasedInpaintingGUI::slot_TopPatchesTableView_changed(const QModelIndex& currentIndex, const QModelIndex& previousIndex)
{
  try
  {
    if(currentIndex.row() < 0)
      {
      std::cout << "Selected row is < 0!" << std::endl;
      return;
      }

    if(currentIndex.row() == previousIndex.row())
      {
      std::cout << "Nothing changed!" << std::endl;
      return;
      }

    this->SourcePatchToDisplay = currentIndex.row();
    ChangeDisplayedTopPatch();

  }// end try
  catch( itk::ExceptionObject & err )
  {
    std::cerr << "ExceptionObject caught in on_topPatchesTableWidget_currentCellChanged!" << std::endl;
    std::cerr << err << std::endl;
    exit(-1);
  }
}

void PatchBasedInpaintingGUI::on_btnInpaint_clicked()
{
  EnterFunction("on_btnInpaint_clicked()");

  //Initialize();

  //Refresh();

  this->Inpainting.SetMaxForwardLookPatches(this->NumberOfForwardLook);
  this->Inpainting.SetNumberOfTopPatchesToSave(this->NumberOfTopPatchesToSave);

  ComputationThread.start();
}

void PatchBasedInpaintingGUI::on_btnStep_clicked()
{
  this->Inpainting.SetDebugImages(this->chkDebugImages->isChecked());
  this->Inpainting.SetDebugMessages(this->chkDebugMessages->isChecked());
  this->Inpainting.SetMaxForwardLookPatches(this->NumberOfForwardLook);
  this->Inpainting.SetNumberOfTopPatchesToSave(this->NumberOfTopPatchesToSave);
  PatchPair usedPair = this->Inpainting.Iterate();

  this->UsedPatchPairs.push_back(usedPair);

  IterationComplete();
}

void PatchBasedInpaintingGUI::on_btnStop_clicked()
{
  this->ComputationThread.StopInpainting();
}

void PatchBasedInpaintingGUI::on_btnReset_clicked()
{
  slot_Refresh();
}

void PatchBasedInpaintingGUI::on_btnInitialize_clicked()
{
  Initialize();
}

void PatchBasedInpaintingGUI::on_actionHelp_activated()
{
  QTextEdit* help=new QTextEdit();

  help->setReadOnly(true);
  help->append("
Patch Based Inpainting
\
  Load an image and a mask.
\
  Set the settings such as patch size.
\
  To do the complete inpainting, click 'Inpaint'.
\
  To do one step of the inpainting, click 'Step'. This will allow you to inspect forward look candidates and each of their top matches.
\

");
  help->show();
}

void PatchBasedInpaintingGUI::slot_StartProgress()
{
  //std::cout << "Form::StartProgressSlot()" << std::endl;
  // Connected to the StartProgressSignal of the ProgressThread member
  this->progressBar->show();
}

void PatchBasedInpaintingGUI::slot_StopProgress()
{
  //std::cout << "Form::StopProgressSlot()" << std::endl;
  // When the ProgressThread emits the StopProgressSignal, we need to display the result of the segmentation

  this->progressBar->hide();
}

void PatchBasedInpaintingGUI::slot_Refresh()
{
  DebugMessage("RefreshSlot()");

  Refresh();
}

void PatchBasedInpaintingGUI::slot_IterationComplete()
{
  DebugMessage("IterationCompleteSlot()");
  IterationComplete();
}

void PatchBasedInpaintingGUI::on_txtPatchRadius_textEdited ( const QString & text )
{
  this->PatchRadius = text.toUInt();
}

void PatchBasedInpaintingGUI::on_txtNumberOfTopPatchesToSave_textEdited ( const QString & text )
{
  this->NumberOfTopPatchesToSave = text.toUInt();
}

void PatchBasedInpaintingGUI::on_txtNumberOfForwardLook_textEdited ( const QString & text )
{
  this->NumberOfForwardLook = text.toUInt();
}

void PatchBasedInpaintingGUI::on_txtGoToIteration_textEdited ( const QString & text )
{
  this->GoToIteration = text.toUInt();
}

void PatchBasedInpaintingGUI::on_txtNumberOfTopPatchesToDisplay_textEdited ( const QString & text )
{
  this->NumberOfTopPatchesToDisplay = text.toUInt();
}
<commit_msg>Disable some text boxes while inpainting is running.<commit_after>/*=========================================================================
 *
 *  Copyright David Doria 2011 daviddoria@gmail.com
 *
 *  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.
 *
 *=========================================================================*/

#include "PatchBasedInpaintingGUI.h"

// Custom
#include "InteractorStyleImageWithDrag.h"
#include "FileSelector.h"
#include "HelpersOutput.h"

// VTK
#include <vtkImageSlice.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>

// QT
#include <QFileDialog>
#include <QTextEdit>

void PatchBasedInpaintingGUI::on_chkDisplayUserPatch_clicked()
{
  this->UserPatchLayer.ImageSlice->SetVisibility(this->chkDisplayUserPatch->isChecked());
  Refresh();
}

void PatchBasedInpaintingGUI::on_radDisplayColorImage_clicked()
{
  this->spinChannelToDisplay->setEnabled(false);
  this->ImageDisplayStyle.Style = DisplayStyle::COLOR;
  Refresh();
}

void PatchBasedInpaintingGUI::on_radDisplayMagnitudeImage_clicked()
{
  this->spinChannelToDisplay->setEnabled(false);
  this->ImageDisplayStyle.Style = DisplayStyle::MAGNITUDE;
  Refresh();
}

void PatchBasedInpaintingGUI::on_radDisplayChannel_clicked()
{
  this->spinChannelToDisplay->setEnabled(true);
  this->ImageDisplayStyle.Style = DisplayStyle::CHANNEL;
  this->ImageDisplayStyle.Channel = this->spinChannelToDisplay->value();
  Refresh();
}

void PatchBasedInpaintingGUI::on_spinChannelToDisplay_valueChanged(int unused)
{
  this->ImageDisplayStyle.Channel = this->spinChannelToDisplay->value();
  Refresh();
}

void PatchBasedInpaintingGUI::on_radCompareOriginal_clicked()
{
  this->Inpainting.SetCompareToOriginal();
}

void PatchBasedInpaintingGUI::on_radCompareBlurred_clicked()
{
  this->Inpainting.SetCompareToBlurred();
}

void PatchBasedInpaintingGUI::on_radCompareCIELAB_clicked()
{
  this->Inpainting.SetCompareToCIELAB();
}

void PatchBasedInpaintingGUI::on_chkLive_clicked()
{
  // When "Live" is checked, we do not want to be able to click 'next' and 'previous'
  this->btnDisplayNextStep->setEnabled(!this->chkLive->isChecked());
  this->btnDisplayPreviousStep->setEnabled(!this->chkLive->isChecked());

  this->btnGoToIteration->setEnabled(!this->chkLive->isChecked());
  this->txtGoToIteration->setEnabled(!this->chkLive->isChecked());
}

void PatchBasedInpaintingGUI::on_btnGoToIteration_clicked()
{
  if(this->GoToIteration < this->AllPotentialCandidatePairs.size() && this->GoToIteration >= 0)
    {
    this->IterationToDisplay = this->GoToIteration;
    ChangeDisplayedIteration();
    }
}

void PatchBasedInpaintingGUI::on_btnResort_clicked()
{
  for(unsigned int iteration = 0; iteration < this->AllPotentialCandidatePairs.size(); iteration++)
    {
    for(unsigned int forwardLookId = 0; forwardLookId < this->AllPotentialCandidatePairs[iteration].size(); forwardLookId++)
      {
      CandidatePairs& candidatePairs = this->AllPotentialCandidatePairs[iteration][forwardLookId];

      if(this->radSortByAverageAbsoluteDifference->isChecked())
        {
        std::sort(candidatePairs.begin(), candidatePairs.end(), SortByAverageAbsoluteDifference);
        }
      else if(this->radSortByAverageSquaredDifference->isChecked())
        {
        std::sort(candidatePairs.begin(), candidatePairs.end(), SortByAverageSquaredDifference);
        }
      else if(this->radSortByBoundaryPixelDifference->isChecked())
        {
        std::sort(candidatePairs.begin(), candidatePairs.end(), SortByBoundaryPixelDifference);
        }
      else if(this->radSortByBoundaryIsophoteAngleDifference->isChecked())
        {
        std::sort(candidatePairs.begin(), candidatePairs.end(), SortByBoundaryIsophoteAngleDifference);
        }
      else if(this->radSortByBoundaryIsophoteStrengthDifference->isChecked())
        {
        std::sort(candidatePairs.begin(), candidatePairs.end(), SortByBoundaryIsophoteStrengthDifference);
        }
      else if(this->radSortByTotalScore->isChecked())
        {
        std::sort(candidatePairs.begin(), candidatePairs.end(), SortByTotalScore);
        }
      else
        {
        std::cerr << "No valid sorting criterion selected." << std::endl;
        }
      }
    }

  SetupTopPatchesTable();
  //on_topPatchesTableWidget_currentCellChanged(0, 0);

  Refresh();
}

void PatchBasedInpaintingGUI::on_chkHighlightUsedPatches_clicked()
{
  RefreshVTK();
}

void PatchBasedInpaintingGUI::on_chkImage_clicked()
{
  this->ImageLayer.ImageSlice->SetVisibility(this->chkImage->isChecked());
  RefreshVTK();
}

void PatchBasedInpaintingGUI::on_chkMask_clicked()
{
  this->MaskLayer.ImageSlice->SetVisibility(this->chkMask->isChecked());
  RefreshVTK();
}

void PatchBasedInpaintingGUI::on_chkPriority_clicked()
{
  this->PriorityLayer.ImageSlice->SetVisibility(this->chkPriority->isChecked());
  RefreshVTK();
}

void PatchBasedInpaintingGUI::on_chkDisplayForwardLookPatchLocations_clicked()
{
  RefreshVTK();
}

void PatchBasedInpaintingGUI::on_chkDisplaySourcePatchLocations_clicked()
{
  RefreshVTK();
}

void PatchBasedInpaintingGUI::on_chkBoundary_clicked()
{
  this->BoundaryLayer.ImageSlice->SetVisibility(this->chkBoundary->isChecked());
  RefreshVTK();
}

void PatchBasedInpaintingGUI::SetCameraPosition()
{
  double leftToRight[3] = {this->CameraLeftToRightVector[0], this->CameraLeftToRightVector[1], this->CameraLeftToRightVector[2]};
  double bottomToTop[3] = {this->CameraBottomToTopVector[0], this->CameraBottomToTopVector[1], this->CameraBottomToTopVector[2]};
  this->InteractorStyle->SetImageOrientation(leftToRight, bottomToTop);

  this->Renderer->ResetCamera();
  this->Renderer->ResetCameraClippingRange();
  this->qvtkWidget->GetRenderWindow()->Render();
}

void PatchBasedInpaintingGUI::on_actionFlipImageVertically_activated()
{
  this->CameraBottomToTopVector[1] *= -1;
  SetCameraPosition();
}

void PatchBasedInpaintingGUI::on_actionFlipImageHorizontally_activated()
{
  this->CameraLeftToRightVector[0] *= -1;
  SetCameraPosition();
}

void PatchBasedInpaintingGUI::SetCheckboxVisibility(const bool visible)
{
  chkImage->setEnabled(visible);
  chkPriority->setEnabled(visible);
  chkBoundary->setEnabled(visible);
  chkMask->setEnabled(visible);
}

void PatchBasedInpaintingGUI::on_btnDisplayPreviousStep_clicked()
{
  if(this->IterationToDisplay > 0)
    {
    this->IterationToDisplay--;
    DebugMessage<unsigned int>("Displaying iteration: ", this->IterationToDisplay);
    ChangeDisplayedIteration();
    }
  else
    {
    DebugMessage("Iteration not changed.");
    }
}

void PatchBasedInpaintingGUI::on_btnDisplayNextStep_clicked()
{
  //std::cout << "IterationToDisplay: " << this->IterationToDisplay
    //        << " Inpainting iteration: " <<  static_cast<int>(this->Inpainting.GetIteration()) << std::endl;

  //if(this->IterationToDisplay < this->Inpainting.GetNumberOfCompletedIterations() - 1)
  if(this->IterationToDisplay < this->IntermediateImages.size() - 1)
    {
    this->IterationToDisplay++;
    DebugMessage<unsigned int>("Displaying iteration: ", this->IterationToDisplay);
    ChangeDisplayedIteration();
    }
  else
    {
    DebugMessage("Iteration not changed.");
    }
}

void PatchBasedInpaintingGUI::on_actionOpen_activated()
{
  FileSelector* fileSelector(new FileSelector);
  fileSelector->exec();

  int result = fileSelector->result();
  if(result) // The user clicked 'ok'
    {
    std::cout << "User clicked ok." << std::endl;
    OpenImage(fileSelector->GetImageFileName());
    OpenMask(fileSelector->GetMaskFileName(), fileSelector->IsMaskInverted());
    Initialize();
    }
  else
    {
    std::cout << "User clicked cancel." << std::endl;
    // The user clicked 'cancel' or closed the dialog, do nothing.
    }
}

void PatchBasedInpaintingGUI::on_actionSaveResult_activated()
{
  // Get a filename to save
  QString fileName = QFileDialog::getSaveFileName(this, "Save File", ".", "Image Files (*.jpg *.jpeg *.bmp *.png *.mha)");

  DebugMessage<std::string>("Got filename: ", fileName.toStdString());
  if(fileName.toStdString().empty())
    {
    std::cout << "Filename was empty." << std::endl;
    return;
    }

  HelpersOutput::WriteImage<FloatVectorImageType>(this->Inpainting.GetCurrentOutputImage(), fileName.toStdString());

  this->statusBar()->showMessage("Saved result.");
}

void PatchBasedInpaintingGUI::on_chkDebugImages_clicked()
{
  QDir directoryMaker;
  directoryMaker.mkdir("Debug");

  this->Inpainting.SetDebugImages(this->chkDebugImages->isChecked());
  this->DebugImages = this->chkDebugImages->isChecked();

  DebugMessage<bool>("DebugImages: ", this->DebugImages);
}

void PatchBasedInpaintingGUI::on_chkDebugMessages_clicked()
{
  this->Inpainting.SetDebugMessages(this->chkDebugMessages->isChecked());
  this->DebugMessages = this->chkDebugMessages->isChecked();
}

void PatchBasedInpaintingGUI::on_actionQuit_activated()
{
  exit(0);
}

void PatchBasedInpaintingGUI::slot_ForwardLookTableView_changed(const QModelIndex& currentIndex, const QModelIndex& previousIndex)
{
  std::cout << "on_ForwardLookTableView_currentCellChanged" << std::endl;

  if(currentIndex.row() < 0)
    {
    std::cout << "on_ForwardLookTableView_currentCellChanged: row < 0!" << std::endl;
    return;
    }

  if(currentIndex.row() > static_cast<int>(this->AllPotentialCandidatePairs[this->IterationToDisplay - 1].size() - 1))
    {
    std::cerr << "Requested display of forward look patch " << currentIndex.row() << " but there are only " << this->AllPotentialCandidatePairs[this->IterationToDisplay - 1].size() - 1 << std::endl;
    }

  std::cerr << "Requested display of forward look patch " << currentIndex.row() << std::endl;

  this->ForwardLookToDisplay = currentIndex.row();
  this->SourcePatchToDisplay = 0;

  ChangeDisplayedForwardLookPatch();

  SetupTopPatchesTable();
  ChangeDisplayedTopPatch();

}

void PatchBasedInpaintingGUI::slot_TopPatchesTableView_changed(const QModelIndex& currentIndex, const QModelIndex& previousIndex)
{
  try
  {
    if(currentIndex.row() < 0)
      {
      std::cout << "Selected row is < 0!" << std::endl;
      return;
      }

    if(currentIndex.row() == previousIndex.row())
      {
      std::cout << "Nothing changed!" << std::endl;
      return;
      }

    this->SourcePatchToDisplay = currentIndex.row();
    ChangeDisplayedTopPatch();

  }// end try
  catch( itk::ExceptionObject & err )
  {
    std::cerr << "ExceptionObject caught in on_topPatchesTableWidget_currentCellChanged!" << std::endl;
    std::cerr << err << std::endl;
    exit(-1);
  }
}

void PatchBasedInpaintingGUI::on_btnInpaint_clicked()
{
  EnterFunction("on_btnInpaint_clicked()");

  //Initialize();

  //Refresh();

  // Gray out some items that should not be changed while the inpainting is running.
  this->txtNumberOfForwardLook->setEnabled(false);
  this->txtNumberOfTopPatchesToSave->setEnabled(false);

  this->Inpainting.SetMaxForwardLookPatches(this->NumberOfForwardLook);
  this->Inpainting.SetNumberOfTopPatchesToSave(this->NumberOfTopPatchesToSave);

  ComputationThread.start();
}

void PatchBasedInpaintingGUI::on_btnStep_clicked()
{
  this->Inpainting.SetDebugImages(this->chkDebugImages->isChecked());
  this->Inpainting.SetDebugMessages(this->chkDebugMessages->isChecked());
  this->Inpainting.SetMaxForwardLookPatches(this->NumberOfForwardLook);
  this->Inpainting.SetNumberOfTopPatchesToSave(this->NumberOfTopPatchesToSave);
  PatchPair usedPair = this->Inpainting.Iterate();

  this->UsedPatchPairs.push_back(usedPair);

  IterationComplete();
}

void PatchBasedInpaintingGUI::on_btnStop_clicked()
{
  this->ComputationThread.StopInpainting();
}

void PatchBasedInpaintingGUI::on_btnReset_clicked()
{
  slot_Refresh();
}

void PatchBasedInpaintingGUI::on_btnInitialize_clicked()
{
  Initialize();
}

void PatchBasedInpaintingGUI::on_actionHelp_activated()
{
  QTextEdit* help=new QTextEdit();

  help->setReadOnly(true);
  help->append("
Patch Based Inpainting
\
  Load an image and a mask.
\
  Set the settings such as patch size.
\
  To do the complete inpainting, click 'Inpaint'.
\
  To do one step of the inpainting, click 'Step'. This will allow you to inspect forward look candidates and each of their top matches.
\

");
  help->show();
}

void PatchBasedInpaintingGUI::slot_StartProgress()
{
  //std::cout << "Form::StartProgressSlot()" << std::endl;
  // Connected to the StartProgressSignal of the ProgressThread member
  this->progressBar->show();
}

void PatchBasedInpaintingGUI::slot_StopProgress()
{
  //std::cout << "Form::StopProgressSlot()" << std::endl;

  // Re-enable some items that should not be changed while the inpainting is running.
  this->txtNumberOfForwardLook->setEnabled(false);
  this->txtNumberOfTopPatchesToSave->setEnabled(false);

  this->progressBar->hide();
}

void PatchBasedInpaintingGUI::slot_Refresh()
{
  DebugMessage("RefreshSlot()");

  Refresh();
}

void PatchBasedInpaintingGUI::slot_IterationComplete()
{
  DebugMessage("IterationCompleteSlot()");
  IterationComplete();
}

void PatchBasedInpaintingGUI::on_txtPatchRadius_textEdited ( const QString & text )
{
  this->PatchRadius = text.toUInt();
}

void PatchBasedInpaintingGUI::on_txtNumberOfTopPatchesToSave_textEdited ( const QString & text )
{
  this->NumberOfTopPatchesToSave = text.toUInt();
}

void PatchBasedInpaintingGUI::on_txtNumberOfForwardLook_textEdited ( const QString & text )
{
  this->NumberOfForwardLook = text.toUInt();
}

void PatchBasedInpaintingGUI::on_txtGoToIteration_textEdited ( const QString & text )
{
  this->GoToIteration = text.toUInt();
}

void PatchBasedInpaintingGUI::on_txtNumberOfTopPatchesToDisplay_textEdited ( const QString & text )
{
  this->NumberOfTopPatchesToDisplay = text.toUInt();
}
<|endoftext|>


<commit_before>// ======================================================================== //
// Copyright 2009-2015 Intel Corporation                                    //
//                                                                          //
// 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                           //
//                                                                          //
// 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.                                           //
// ======================================================================== //

#include "subdivpatch1cached_intersector1.h"
#include "../bvh4/bvh4.h"
#include "../bvh4/bvh4_intersector1.h"

#define TIMER(x)
#define DBG(x)

namespace embree
{
  namespace isa
  {
    //////////////////////////////////////////////////////////////////////////////////////////////////////

    void verifySubTreeBVH(const BVH4::NodeRef ref)
    {
      assert(ref != BVH4::invalidNode );

      /* this is a leaf node */
      if (unlikely(ref.isLeaf()))
        return;

      const BVH4::Node* node = ref.node();

      for (size_t i=0;i<4;i++)
	{
	  assert(node->child(i) != BVH4::emptyNode);

	  BBox3fa bounds = node->bounds(i);

	  assert( std::isfinite(bounds.lower.x) );
	  assert( std::isfinite(bounds.lower.y) );
	  assert( std::isfinite(bounds.lower.z) );

	  assert( std::isfinite(bounds.upper.x) );
	  assert( std::isfinite(bounds.upper.y) );
	  assert( std::isfinite(bounds.upper.z) );

	  verifySubTreeBVH(node->child(i));
	}
    }

    size_t countBlocks(const BVH4::NodeRef ref, const size_t range0, const size_t range1)
    {

      size_t t = (size_t)ref;

      assert(range0 <= t);
      assert(t <= range1);

      /* this is a leaf node */
      if (unlikely(ref.isLeaf()))
        return 3;

      const BVH4::Node* node = ref.node();

      size_t size = 0;
      for (size_t i=0;i<4;i++)
        if (node->child(i) != BVH4::emptyNode)
          size += countBlocks(node->child(i),range0,range1);

      return 2 + size;
    }

    void updateBVH4Refs(const BVH4::NodeRef &ref, const size_t old_ptr, const size_t new_ptr)
    {
      if (unlikely(ref == BVH4::emptyNode))
        return;

      assert(ref != BVH4::invalidNode);

      /* this is a leaf node */
      if (unlikely(ref.isLeaf()))
        return;

      const BVH4::Node* node = ref.node();

      for (size_t i=0;i<4;i++)
        {
          const BVH4::NodeRef &child = node->child(i);
          if (node->child(i) != BVH4::emptyNode)
            {
              if (child.isNode())
                updateBVH4Refs(child,old_ptr,new_ptr);

              const size_t dest_offset = (size_t)&child - old_ptr;
              const size_t new_ref     = (size_t)child - old_ptr + new_ptr;
              size_t *ptr = (size_t*)((char*)new_ptr + dest_offset);
              *ptr = new_ref;
            }
        }
    }

    /* build lazy subtree over patch */
    size_t SubdivPatch1CachedIntersector1::lazyBuildPatch(Precalculations &pre,
							  SubdivPatch1Cached* const subdiv_patch,
							  const Scene* scene)
    {
      /* unlock previous patch */
      if (pre.current_patch)
      {
        assert(SharedLazyTessellationCache::sharedLazyTessellationCache.isLocked(pre.t_state));
        SharedLazyTessellationCache::sharedLazyTessellationCache.unlockThread(pre.t_state);
      }

      while(1)
      {

        SharedLazyTessellationCache::sharedLazyTessellationCache.lockThreadLoop(pre.t_state);

        const size_t globalTime = scene->commitCounter;
        if (void* ptr = SharedLazyTessellationCache::lookup(&subdiv_patch->root_ref,globalTime))
            return (size_t) ptr;

        SharedLazyTessellationCache::sharedLazyTessellationCache.unlockThread(pre.t_state);

        if (subdiv_patch->try_write_lock())
        {
          if (!SharedLazyTessellationCache::validTag(subdiv_patch->root_ref,globalTime))
          {
            /* generate vertex grid, lock and allocate memory in the cache */
            size_t new_root_ref = (size_t)buildSubdivPatchTreeCompact(*subdiv_patch,pre.t_state,scene->getSubdivMesh(subdiv_patch->geom));

            /* get current commit index */
            //const size_t commitIndex = SharedLazyTessellationCache::sharedLazyTessellationCache.getCurrentIndex();
            const size_t combinedTime = SharedLazyTessellationCache::sharedLazyTessellationCache.getTime(globalTime);

            __memory_barrier();
            /* write new root ref */
            subdiv_patch->root_ref = SharedLazyTessellationCache::Tag((void*)new_root_ref,combinedTime);

#if _DEBUG
            const size_t patchIndex = subdiv_patch - pre.array;
            assert(patchIndex < pre.numPrimitives);
            CACHE_STATS(SharedTessellationCacheStats::incPatchBuild(patchIndex,pre.numPrimitives));
#endif
            assert(SharedLazyTessellationCache::sharedLazyTessellationCache.isLocked(pre.t_state));

            /* unlock current patch */
            subdiv_patch->write_unlock();

            /* memory region still locked, forward progress guaranteed */
            return new_root_ref;
          }
          /* unlock current patch */
          subdiv_patch->write_unlock();
        }
      }
    }
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    BVH4::NodeRef SubdivPatch1CachedIntersector1::buildSubdivPatchTreeCompact(const SubdivPatch1Cached &patch,
                                                                              ThreadWorkState *t_state,
									      const SubdivMesh* const geom, BBox3fa* bounds_o)
    {
      assert( patch.grid_size_simd_blocks >= 1 );

      const size_t array_elements = patch.grid_size_simd_blocks * vfloat::size;
      dynamic_large_stack_array(float,local_grid_u,array_elements,64*64);
      dynamic_large_stack_array(float,local_grid_v,array_elements,64*64);
      dynamic_large_stack_array(float,local_grid_x,array_elements,64*64);
      dynamic_large_stack_array(float,local_grid_y,array_elements,64*64);
      dynamic_large_stack_array(float,local_grid_z,array_elements,64*64);

      /* compute vertex grid (+displacement) */
      evalGrid(patch,0,patch.grid_u_res-1,0,patch.grid_v_res-1,patch.grid_u_res,patch.grid_v_res,local_grid_x,local_grid_y,local_grid_z,local_grid_u,local_grid_v,geom);

      /* lock the cache */
      SharedLazyTessellationCache::sharedLazyTessellationCache.lockThreadLoop(t_state);

      /* allocate memory in cache and get current commit index */
      void *const lazymem = SharedLazyTessellationCache::sharedLazyTessellationCache.allocLoop(t_state,64*patch.grid_subtree_size_64b_blocks);

      /* copy temporary data to tessellation cache */
      const size_t grid_offset = patch.grid_bvh_size_64b_blocks * 16;

      float *const grid_x  = (float*)lazymem + grid_offset + 0 * array_elements;
      float *const grid_y  = (float*)lazymem + grid_offset + 1 * array_elements;
      float *const grid_z  = (float*)lazymem + grid_offset + 2 * array_elements;
      int   *const grid_uv = (int*)  lazymem + grid_offset + 3 * array_elements;
      assert( patch.grid_subtree_size_64b_blocks * 16 >= grid_offset + 4 * array_elements);

      memcpy(grid_x ,local_grid_x ,array_elements*sizeof(float));
      memcpy(grid_y ,local_grid_y ,array_elements*sizeof(float));
      memcpy(grid_z ,local_grid_z ,array_elements*sizeof(float));

      for (size_t i=0;i<array_elements;i++)
        grid_uv[i] = (((int)(local_grid_v[i] * 65535.0f/2.0f)) << 16) | ((int)(local_grid_u[i] * 65535.0f/2.0f));

      /* build bvh tree */
      BVH4::NodeRef subtree_root = 0;
      unsigned int currentIndex = 0;
      BBox3fa bounds = createSubTreeCompact( subtree_root,
					     (float*)lazymem,
					     patch,
					     grid_x,
					     array_elements,
					     GridRange(0,patch.grid_u_res-1,0,patch.grid_v_res-1),
					     currentIndex);
      if (bounds_o) *bounds_o = bounds;

      assert( std::isfinite(bounds.lower.x) );
      assert( std::isfinite(bounds.lower.y) );
      assert( std::isfinite(bounds.lower.z) );

      assert( std::isfinite(bounds.upper.x) );
      assert( std::isfinite(bounds.upper.y) );
      assert( std::isfinite(bounds.upper.z) );

      assert(currentIndex == patch.grid_bvh_size_64b_blocks);

      return subtree_root;
    }

    BBox3fa SubdivPatch1CachedIntersector1::createSubTreeCompact(BVH4::NodeRef &curNode,
								 float *const lazymem,
								 const SubdivPatch1Cached &patch,
								 const float *const grid_array,
								 const size_t grid_array_elements,
								 const GridRange &range,
								 unsigned int &localCounter)
    {
      if (range.hasLeafSize())
	{
	  const float *const grid_x_array = grid_array + 0 * grid_array_elements;
	  const float *const grid_y_array = grid_array + 1 * grid_array_elements;
	  const float *const grid_z_array = grid_array + 2 * grid_array_elements;

	  /* compute the bounds just for the range! */
	  BBox3fa bounds( empty );
	  for (size_t v = range.v_start; v<=range.v_end; v++)
	    for (size_t u = range.u_start; u<=range.u_end; u++)
	      {
		const float x = grid_x_array[ v * patch.grid_u_res + u];
		const float y = grid_y_array[ v * patch.grid_u_res + u];
		const float z = grid_z_array[ v * patch.grid_u_res + u];
		bounds.extend( Vec3fa(x,y,z) );
	      }
	  unsigned int u_start = range.u_start;
	  unsigned int v_start = range.v_start;

	  const unsigned int u_end   = range.u_end;
	  const unsigned int v_end   = range.v_end;

          if (unlikely(u_end-u_start+1 < 3))
	    {
	      const unsigned int delta_u = 3 - (u_end-u_start+1);
	      if (u_start >= delta_u)
		u_start -= delta_u;
	      else
		u_start = 0;
	    }
          if (unlikely(v_end-v_start+1 < 3))
	    {
	      const unsigned int delta_v = 3 - (v_end-v_start+1);
	      if (v_start >= delta_v)
		v_start -= delta_v;
	      else
		v_start = 0;
	    }

	  const unsigned int u_size = u_end-u_start+1;
	  const unsigned int v_size = v_end-v_start+1;

	  assert(u_size >= 1);
	  assert(v_size >= 1);

	  const size_t grid_offset3x3    = v_start * patch.grid_u_res + u_start;

	  size_t offset_bytes = (size_t)&grid_x_array[ grid_offset3x3 ] - (size_t)SharedLazyTessellationCache::sharedLazyTessellationCache.getDataPtr();
	  assert(offset_bytes < 0xffffffff);
	  assert((offset_bytes & 3) == 0);
          size_t value = (offset_bytes << 2) + (size_t)SharedLazyTessellationCache::sharedLazyTessellationCache.getDataPtr();
          assert( (value & 2) == 0 );
	  curNode = BVH4::encodeTypedLeaf((void*)value,2);

	  assert( std::isfinite(bounds.lower.x) );
	  assert( std::isfinite(bounds.lower.y) );
	  assert( std::isfinite(bounds.lower.z) );

	  assert( std::isfinite(bounds.upper.x) );
	  assert( std::isfinite(bounds.upper.y) );
	  assert( std::isfinite(bounds.upper.z) );

	  return bounds;
	}

      /* allocate new bvh4 node */
      const size_t currentIndex = localCounter;

      /* 128 bytes == 2 x 64 bytes cachelines */
      localCounter += 2;

      BVH4::Node *node = (BVH4::Node *)&lazymem[currentIndex*16];

      curNode = BVH4::encodeNode( node );

      node->clear();

      GridRange r[4];

      const unsigned int children = range.splitIntoSubRanges(r);

      /* create four subtrees */
      BBox3fa bounds( empty );

      for (unsigned int i=0;i<children;i++)
	{
	  BBox3fa bounds_subtree = createSubTreeCompact( node->child(i),
							 lazymem,
							 patch,
							 grid_array,
							 grid_array_elements,
							 r[i],
							 localCounter);
	  node->set(i, bounds_subtree);
	  bounds.extend( bounds_subtree );
	}

      return bounds;
    }
  }
}
<commit_msg>bugfix in subdivpatch1_intersector1.cpp, by introducing dynamic_large_stack_array some array padding got lost<commit_after>// ======================================================================== //
// Copyright 2009-2015 Intel Corporation                                    //
//                                                                          //
// 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                           //
//                                                                          //
// 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.                                           //
// ======================================================================== //

#include "subdivpatch1cached_intersector1.h"
#include "../bvh4/bvh4.h"
#include "../bvh4/bvh4_intersector1.h"

#define TIMER(x)
#define DBG(x)

namespace embree
{
  namespace isa
  {
    //////////////////////////////////////////////////////////////////////////////////////////////////////

    void verifySubTreeBVH(const BVH4::NodeRef ref)
    {
      assert(ref != BVH4::invalidNode );

      /* this is a leaf node */
      if (unlikely(ref.isLeaf()))
        return;

      const BVH4::Node* node = ref.node();

      for (size_t i=0;i<4;i++)
	{
	  assert(node->child(i) != BVH4::emptyNode);

	  BBox3fa bounds = node->bounds(i);

	  assert( std::isfinite(bounds.lower.x) );
	  assert( std::isfinite(bounds.lower.y) );
	  assert( std::isfinite(bounds.lower.z) );

	  assert( std::isfinite(bounds.upper.x) );
	  assert( std::isfinite(bounds.upper.y) );
	  assert( std::isfinite(bounds.upper.z) );

	  verifySubTreeBVH(node->child(i));
	}
    }

    size_t countBlocks(const BVH4::NodeRef ref, const size_t range0, const size_t range1)
    {

      size_t t = (size_t)ref;

      assert(range0 <= t);
      assert(t <= range1);

      /* this is a leaf node */
      if (unlikely(ref.isLeaf()))
        return 3;

      const BVH4::Node* node = ref.node();

      size_t size = 0;
      for (size_t i=0;i<4;i++)
        if (node->child(i) != BVH4::emptyNode)
          size += countBlocks(node->child(i),range0,range1);

      return 2 + size;
    }

    void updateBVH4Refs(const BVH4::NodeRef &ref, const size_t old_ptr, const size_t new_ptr)
    {
      if (unlikely(ref == BVH4::emptyNode))
        return;

      assert(ref != BVH4::invalidNode);

      /* this is a leaf node */
      if (unlikely(ref.isLeaf()))
        return;

      const BVH4::Node* node = ref.node();

      for (size_t i=0;i<4;i++)
        {
          const BVH4::NodeRef &child = node->child(i);
          if (node->child(i) != BVH4::emptyNode)
            {
              if (child.isNode())
                updateBVH4Refs(child,old_ptr,new_ptr);

              const size_t dest_offset = (size_t)&child - old_ptr;
              const size_t new_ref     = (size_t)child - old_ptr + new_ptr;
              size_t *ptr = (size_t*)((char*)new_ptr + dest_offset);
              *ptr = new_ref;
            }
        }
    }

    /* build lazy subtree over patch */
    size_t SubdivPatch1CachedIntersector1::lazyBuildPatch(Precalculations &pre,
							  SubdivPatch1Cached* const subdiv_patch,
							  const Scene* scene)
    {
      /* unlock previous patch */
      if (pre.current_patch)
      {
        assert(SharedLazyTessellationCache::sharedLazyTessellationCache.isLocked(pre.t_state));
        SharedLazyTessellationCache::sharedLazyTessellationCache.unlockThread(pre.t_state);
      }

      while(1)
      {

        SharedLazyTessellationCache::sharedLazyTessellationCache.lockThreadLoop(pre.t_state);

        const size_t globalTime = scene->commitCounter;
        if (void* ptr = SharedLazyTessellationCache::lookup(&subdiv_patch->root_ref,globalTime))
            return (size_t) ptr;

        SharedLazyTessellationCache::sharedLazyTessellationCache.unlockThread(pre.t_state);

        if (subdiv_patch->try_write_lock())
        {
          if (!SharedLazyTessellationCache::validTag(subdiv_patch->root_ref,globalTime))
          {
            /* generate vertex grid, lock and allocate memory in the cache */
            size_t new_root_ref = (size_t)buildSubdivPatchTreeCompact(*subdiv_patch,pre.t_state,scene->getSubdivMesh(subdiv_patch->geom));

            /* get current commit index */
            //const size_t commitIndex = SharedLazyTessellationCache::sharedLazyTessellationCache.getCurrentIndex();
            const size_t combinedTime = SharedLazyTessellationCache::sharedLazyTessellationCache.getTime(globalTime);

            __memory_barrier();
            /* write new root ref */
            subdiv_patch->root_ref = SharedLazyTessellationCache::Tag((void*)new_root_ref,combinedTime);

#if _DEBUG
            const size_t patchIndex = subdiv_patch - pre.array;
            assert(patchIndex < pre.numPrimitives);
            CACHE_STATS(SharedTessellationCacheStats::incPatchBuild(patchIndex,pre.numPrimitives));
#endif
            assert(SharedLazyTessellationCache::sharedLazyTessellationCache.isLocked(pre.t_state));

            /* unlock current patch */
            subdiv_patch->write_unlock();

            /* memory region still locked, forward progress guaranteed */
            return new_root_ref;
          }
          /* unlock current patch */
          subdiv_patch->write_unlock();
        }
      }
    }
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    BVH4::NodeRef SubdivPatch1CachedIntersector1::buildSubdivPatchTreeCompact(const SubdivPatch1Cached &patch,
                                                                              ThreadWorkState *t_state,
									      const SubdivMesh* const geom, BBox3fa* bounds_o)
    {
      assert( patch.grid_size_simd_blocks >= 1 );

      const size_t array_elements = patch.grid_size_simd_blocks * vfloat::size;
      dynamic_large_stack_array(float,local_grid_u,array_elements+vfloat::size,64*64);
      dynamic_large_stack_array(float,local_grid_v,array_elements+vfloat::size,64*64);
      dynamic_large_stack_array(float,local_grid_x,array_elements+vfloat::size,64*64);
      dynamic_large_stack_array(float,local_grid_y,array_elements+vfloat::size,64*64);
      dynamic_large_stack_array(float,local_grid_z,array_elements+vfloat::size,64*64);

      /* compute vertex grid (+displacement) */
      evalGrid(patch,0,patch.grid_u_res-1,0,patch.grid_v_res-1,patch.grid_u_res,patch.grid_v_res,local_grid_x,local_grid_y,local_grid_z,local_grid_u,local_grid_v,geom);

      /* lock the cache */
      SharedLazyTessellationCache::sharedLazyTessellationCache.lockThreadLoop(t_state);

      /* allocate memory in cache and get current commit index */
      void *const lazymem = SharedLazyTessellationCache::sharedLazyTessellationCache.allocLoop(t_state,64*patch.grid_subtree_size_64b_blocks);

      /* copy temporary data to tessellation cache */
      const size_t grid_offset = patch.grid_bvh_size_64b_blocks * 16;

      float *const grid_x  = (float*)lazymem + grid_offset + 0 * array_elements;
      float *const grid_y  = (float*)lazymem + grid_offset + 1 * array_elements;
      float *const grid_z  = (float*)lazymem + grid_offset + 2 * array_elements;
      int   *const grid_uv = (int*)  lazymem + grid_offset + 3 * array_elements;
      assert( patch.grid_subtree_size_64b_blocks * 16 >= grid_offset + 4 * array_elements);

      memcpy(grid_x ,local_grid_x ,array_elements*sizeof(float));
      memcpy(grid_y ,local_grid_y ,array_elements*sizeof(float));
      memcpy(grid_z ,local_grid_z ,array_elements*sizeof(float));

      for (size_t i=0;i<array_elements;i++)
        grid_uv[i] = (((int)(local_grid_v[i] * 65535.0f/2.0f)) << 16) | ((int)(local_grid_u[i] * 65535.0f/2.0f));

      /* build bvh tree */
      BVH4::NodeRef subtree_root = 0;
      unsigned int currentIndex = 0;
      BBox3fa bounds = createSubTreeCompact( subtree_root,
					     (float*)lazymem,
					     patch,
					     grid_x,
					     array_elements,
					     GridRange(0,patch.grid_u_res-1,0,patch.grid_v_res-1),
					     currentIndex);
      if (bounds_o) *bounds_o = bounds;

      assert( std::isfinite(bounds.lower.x) );
      assert( std::isfinite(bounds.lower.y) );
      assert( std::isfinite(bounds.lower.z) );

      assert( std::isfinite(bounds.upper.x) );
      assert( std::isfinite(bounds.upper.y) );
      assert( std::isfinite(bounds.upper.z) );

      assert(currentIndex == patch.grid_bvh_size_64b_blocks);

      return subtree_root;
    }

    BBox3fa SubdivPatch1CachedIntersector1::createSubTreeCompact(BVH4::NodeRef &curNode,
								 float *const lazymem,
								 const SubdivPatch1Cached &patch,
								 const float *const grid_array,
								 const size_t grid_array_elements,
								 const GridRange &range,
								 unsigned int &localCounter)
    {
      if (range.hasLeafSize())
	{
	  const float *const grid_x_array = grid_array + 0 * grid_array_elements;
	  const float *const grid_y_array = grid_array + 1 * grid_array_elements;
	  const float *const grid_z_array = grid_array + 2 * grid_array_elements;

	  /* compute the bounds just for the range! */
	  BBox3fa bounds( empty );
	  for (size_t v = range.v_start; v<=range.v_end; v++)
	    for (size_t u = range.u_start; u<=range.u_end; u++)
	      {
		const float x = grid_x_array[ v * patch.grid_u_res + u];
		const float y = grid_y_array[ v * patch.grid_u_res + u];
		const float z = grid_z_array[ v * patch.grid_u_res + u];
		bounds.extend( Vec3fa(x,y,z) );
	      }
	  unsigned int u_start = range.u_start;
	  unsigned int v_start = range.v_start;

	  const unsigned int u_end   = range.u_end;
	  const unsigned int v_end   = range.v_end;

          if (unlikely(u_end-u_start+1 < 3))
	    {
	      const unsigned int delta_u = 3 - (u_end-u_start+1);
	      if (u_start >= delta_u)
		u_start -= delta_u;
	      else
		u_start = 0;
	    }
          if (unlikely(v_end-v_start+1 < 3))
	    {
	      const unsigned int delta_v = 3 - (v_end-v_start+1);
	      if (v_start >= delta_v)
		v_start -= delta_v;
	      else
		v_start = 0;
	    }

	  const unsigned int u_size = u_end-u_start+1;
	  const unsigned int v_size = v_end-v_start+1;

	  assert(u_size >= 1);
	  assert(v_size >= 1);

	  const size_t grid_offset3x3    = v_start * patch.grid_u_res + u_start;

	  size_t offset_bytes = (size_t)&grid_x_array[ grid_offset3x3 ] - (size_t)SharedLazyTessellationCache::sharedLazyTessellationCache.getDataPtr();
	  assert(offset_bytes < 0xffffffff);
	  assert((offset_bytes & 3) == 0);
          size_t value = (offset_bytes << 2) + (size_t)SharedLazyTessellationCache::sharedLazyTessellationCache.getDataPtr();
          assert( (value & 2) == 0 );
	  curNode = BVH4::encodeTypedLeaf((void*)value,2);

	  assert( std::isfinite(bounds.lower.x) );
	  assert( std::isfinite(bounds.lower.y) );
	  assert( std::isfinite(bounds.lower.z) );

	  assert( std::isfinite(bounds.upper.x) );
	  assert( std::isfinite(bounds.upper.y) );
	  assert( std::isfinite(bounds.upper.z) );

	  return bounds;
	}

      /* allocate new bvh4 node */
      const size_t currentIndex = localCounter;

      /* 128 bytes == 2 x 64 bytes cachelines */
      localCounter += 2;

      BVH4::Node *node = (BVH4::Node *)&lazymem[currentIndex*16];

      curNode = BVH4::encodeNode( node );

      node->clear();

      GridRange r[4];

      const unsigned int children = range.splitIntoSubRanges(r);

      /* create four subtrees */
      BBox3fa bounds( empty );

      for (unsigned int i=0;i<children;i++)
	{
	  BBox3fa bounds_subtree = createSubTreeCompact( node->child(i),
							 lazymem,
							 patch,
							 grid_array,
							 grid_array_elements,
							 r[i],
							 localCounter);
	  node->set(i, bounds_subtree);
	  bounds.extend( bounds_subtree );
	}

      return bounds;
    }
  }
}
<|endoftext|>


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

#ifndef INCLUDED_SVTDLLAPI_H
#include "svtools/svtdllapi.h"
#endif

#ifndef _SV_FIXED_HXX
#include <vcl/fixed.hxx>
#endif

//.........................................................................
namespace svt
{
//.........................................................................

    //=====================================================================
    //= FixedHyperlink
    //=====================================================================
    class SVT_DLLPUBLIC FixedHyperlink : public FixedText
    {
    private:
        long                m_nTextLen;
        Pointer             m_aOldPointer;
        Link                m_aClickHdl;
        String              m_sURL;

        /** initializes the font (link color and underline).

            Called by the Ctors.
        */
        void                Initialize();

    protected:
        /** overwrites Window::MouseMove().

            Changes the pointer only over the text.
        */
        virtual void        MouseMove( const MouseEvent& rMEvt );

        /** overwrites Window::MouseButtonUp().

            Calls the set link if the mouse is over the text.
        */
        virtual void        MouseButtonUp( const MouseEvent& rMEvt );

        /** overwrites Window::RequestHelp().

            Shows tooltip only if the mouse is over the text.
        */
        virtual void        RequestHelp( const HelpEvent& rHEvt );

    public:
        /** ctors

            With ResId or WinBits.
        */
        FixedHyperlink( Window* pParent, const ResId& rId );
        FixedHyperlink( Window* pParent, WinBits nWinStyle = 0 );

        /** dtor

        */
        virtual ~FixedHyperlink();

        /** overwrites Window::GetFocus().

            Changes the color of the text and shows a focus rectangle.
        */
        virtual void        GetFocus();

        /** overwrites Window::LoseFocus().

            Changes the color of the text and hides the focus rectangle.
        */
        virtual void        LoseFocus();

        /** overwrites Window::KeyInput().

            KEY_RETURN and KEY_SPACE calls the link handler.
        */
        virtual void        KeyInput( const KeyEvent& rKEvt );

        /** sets <member>m_aClickHdl</member> with <arg>rLink</arg>.

            <member>m_aClickHdl</member> is called if the text is clicked.
        */
        inline void         SetClickHdl( const Link& rLink ) { m_aClickHdl = rLink; }

        /** returns <member>m_aClickHdl</member>.

            @return
                <member>m_aClickHdl</member>
        */
        inline const Link&  GetClickHdl() const { return m_aClickHdl; }

        /** sets the URL of the hyperlink and uses it as tooltip. */
        void         SetURL( const String& rNewURL );

        /** returns the URL of the hyperlink.

            @return
                <member>m_sURL</member>
        */
        inline String       GetURL() const { return m_sURL; }

        /** sets new text and recalculates the text length. */
        void                SetDescription( const String& rNewDescription );
    };

//.........................................................................
} // namespace svt
//.........................................................................

#endif

<commit_msg>INTEGRATION: CWS fwk80_SRC680 (1.3.34); FILE MERGED 2008/01/11 15:12:37 pb 1.3.34.1: fix: #i83756# new base ::toolkit::FixedHyperlinkBase<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: fixedhyper.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2008-01-29 15:24:43 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef SVTOOLS_FIXEDHYPER_HXX
#define SVTOOLS_FIXEDHYPER_HXX

#ifndef INCLUDED_SVTDLLAPI_H
#include "svtools/svtdllapi.h"
#endif

#include <toolkit/helper/fixedhyperbase.hxx>

//.........................................................................
namespace svt
{
//.........................................................................

    //=====================================================================
    //= FixedHyperlink
    //=====================================================================
    class SVT_DLLPUBLIC FixedHyperlink : public ::toolkit::FixedHyperlinkBase
    {
    private:
        long                m_nTextLen;
        Pointer             m_aOldPointer;
        Link                m_aClickHdl;
        String              m_sURL;

        /** initializes the font (link color and underline).

            Called by the Ctors.
        */
        void                Initialize();

    protected:
        /** overwrites Window::MouseMove().

            Changes the pointer only over the text.
        */
        virtual void        MouseMove( const MouseEvent& rMEvt );

        /** overwrites Window::MouseButtonUp().

            Calls the set link if the mouse is over the text.
        */
        virtual void        MouseButtonUp( const MouseEvent& rMEvt );

        /** overwrites Window::RequestHelp().

            Shows tooltip only if the mouse is over the text.
        */
        virtual void        RequestHelp( const HelpEvent& rHEvt );

    public:
        /** ctors

            With ResId or WinBits.
        */
        FixedHyperlink( Window* pParent, const ResId& rId );
        FixedHyperlink( Window* pParent, WinBits nWinStyle = 0 );

        /** dtor

        */
        virtual ~FixedHyperlink();

        /** overwrites Window::GetFocus().

            Changes the color of the text and shows a focus rectangle.
        */
        virtual void        GetFocus();

        /** overwrites Window::LoseFocus().

            Changes the color of the text and hides the focus rectangle.
        */
        virtual void        LoseFocus();

        /** overwrites Window::KeyInput().

            KEY_RETURN and KEY_SPACE calls the link handler.
        */
        virtual void        KeyInput( const KeyEvent& rKEvt );

        /** sets <member>m_aClickHdl</member> with <arg>rLink</arg>.

            <member>m_aClickHdl</member> is called if the text is clicked.
        */
        inline void         SetClickHdl( const Link& rLink ) { m_aClickHdl = rLink; }

        /** returns <member>m_aClickHdl</member>.

            @return
                <member>m_aClickHdl</member>
        */
        inline const Link&  GetClickHdl() const { return m_aClickHdl; }

        // ::toolkit::FixedHyperbaseLink

        /** sets the URL of the hyperlink and uses it as tooltip. */
        virtual void        SetURL( const String& rNewURL );

        /** returns the URL of the hyperlink.

            @return
                <member>m_sURL</member>
        */
        virtual String      GetURL() const;

        /** sets new text and recalculates the text length. */
        virtual void        SetDescription( const String& rNewDescription );
    };

//.........................................................................
} // namespace svt
//.........................................................................

#endif

<|endoftext|>