<commit_before>/*=========================================================================
 *
 *  Copyright Leiden University Medical Center, Erasmus University Medical
 *  Center and contributors
 *
 *  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 "selxBlueprintImpl.h"
#include "selxBlueprint.h"

#include "selxDataManager.h"
#include "gtest/gtest.h"

using namespace selx;

class BlueprintTest : public ::testing::Test
{
public:

  typedef BlueprintImpl::ParameterMapType   ParameterMapType;
  typedef BlueprintImpl::ParameterValueType ParameterValueType;

  virtual void SetUp()
  {
    parameterMap[ "NameOfClass" ]        = ParameterValueType( 1, "TestClassName" );
    anotherParameterMap[ "NameOfClass" ] = ParameterValueType( 1, "AnotherTestClassName" );
    dataManager = DataManager::New();
  }

  typedef Blueprint::Pointer BlueprintPointer;

  DataManager::Pointer dataManager;
  ParameterMapType parameterMap;
  ParameterMapType anotherParameterMap;
};

TEST_F( BlueprintTest, SetGetDeleteComponent )
{
  auto blueprint = Blueprint::New();

  bool success0;
  EXPECT_NO_THROW( success0 = blueprint->SetComponent( "MyComponentName", parameterMap ) );
  EXPECT_TRUE( success0 );

  bool success1;
  EXPECT_NO_THROW( blueprint->SetComponent( "MyComponentName", parameterMap ) );
  EXPECT_NO_THROW( success1 = blueprint->SetComponent( "MyComponentName", anotherParameterMap ) );
  EXPECT_TRUE( success1 );
  EXPECT_EQ( anotherParameterMap, blueprint->GetComponent( "MyComponentName" ) );
}

TEST_F( BlueprintTest, BlueprintObjectSetGetDeleteComponent )
{
  BlueprintPointer blueprint;
  EXPECT_NO_THROW( blueprint = Blueprint::New() );

  bool success0;
  EXPECT_NO_THROW( success0 = blueprint->SetComponent( "MyComponentName", parameterMap ) );
  EXPECT_TRUE( success0 );

  bool success1;
  EXPECT_NO_THROW( blueprint->SetComponent( "MyComponentName", parameterMap ) );
  EXPECT_NO_THROW( success1 = blueprint->SetComponent( "MyComponentName", anotherParameterMap ) );
  EXPECT_TRUE( success1 );
  EXPECT_EQ( anotherParameterMap, blueprint->GetComponent( "MyComponentName" ) );
}

TEST_F( BlueprintTest, SetGetDeleteConnection )
{
  auto blueprint = Blueprint::New();

  blueprint->SetComponent( "Component0", parameterMap );
  blueprint->SetComponent( "Component1", parameterMap );
  blueprint->SetComponent( "Component2", parameterMap );

  // Connection should not exist
  bool connectionExists;
  EXPECT_NO_THROW( connectionExists = blueprint->ConnectionExists( "Component0", "Component1" ) );
  EXPECT_FALSE( connectionExists );

  // Connection should be set
  bool connectionSet;
  EXPECT_NO_THROW( connectionSet = blueprint->SetConnection( "Component0", "Component1", parameterMap ) );
  EXPECT_TRUE( connectionSet );

  // Connection should now exist
  bool connectionNowExists;
  EXPECT_NO_THROW( connectionNowExists = blueprint->ConnectionExists( "Component0", "Component1" ) );
  EXPECT_TRUE( connectionNowExists );

  // Connection should have parameter map
  ParameterMapType parameterMap0;
  EXPECT_NO_THROW( parameterMap0 = blueprint->GetConnection( "Component0", "Component1" ) );
  EXPECT_EQ( parameterMap[ "NameOfClass" ], parameterMap0[ "NameOfClass" ] );

  // Another parameter map should transparently added
  bool anotherParameterMapSet;
  EXPECT_NO_THROW( anotherParameterMapSet = blueprint->SetConnection( "Component0", "Component1", anotherParameterMap ) );
  EXPECT_TRUE( anotherParameterMapSet );
  EXPECT_EQ( anotherParameterMap, blueprint->GetConnection( "Component0", "Component1" ) );

  // Connection should be deleted
  bool connectionDeleted;
  EXPECT_NO_THROW( connectionDeleted = blueprint->DeleteConnection( "Component0", "Component1" ) );
  EXPECT_TRUE( connectionDeleted );

  // Connection should not exist
  EXPECT_FALSE( blueprint->ConnectionExists( "Component0", "Component1" ) );

  EXPECT_THROW( blueprint->GetConnection( "Component0", "Component1" ), std::runtime_error );
}

//TEST_F( BlueprintTest, CopyConstuctor )
//{
//  std::unique_ptr< BlueprintImpl > baseBlueprint;
//  EXPECT_NO_THROW( baseBlueprint = std::unique_ptr< BlueprintImpl >( new BlueprintImpl() ) );
//
//  baseBlueprint->SetComponent( "Component0", { { "OperationType", { "Transform" } } } );
//  std::unique_ptr< BlueprintImpl > clonedBaseBlueprint;
//  EXPECT_NO_THROW( clonedBaseBlueprint = std::make_unique< BlueprintImpl >( *baseBlueprint.get() ) );
//
//  EXPECT_NO_THROW( clonedBaseBlueprint->SetComponent( "Component1", { { "OperationType", { "Source" } }, { "Dimensionality", { "3" } } } ) );
//
//  BlueprintImpl::ParameterMapType clonedComponent0;
//  EXPECT_NO_THROW( clonedComponent0 = clonedBaseBlueprint->GetComponent( "Component0" ) );
//
//  BlueprintImpl::ParameterMapType component1;
//  EXPECT_THROW( component1 = baseBlueprint->GetComponent( "Component1" ), std::runtime_error );
//}

TEST_F( BlueprintTest, Compose )
{
  auto baseBlueprint = Blueprint::New();

  baseBlueprint->SetComponent( "Component0", { { "OperationType", { "Transform" } } } );
  baseBlueprint->SetComponent( "Component1", { { "OperationType", { "Source" } }, { "Dimensionality", { "3" } } } );

  // compose-in a new 3rd component Component2
  auto nonConflictingBlueprint0 = Blueprint::New();

  nonConflictingBlueprint0->SetComponent( "Component2", { { "OperationType", { "Sink" } } } );

  EXPECT_TRUE( baseBlueprint->ComposeWith( nonConflictingBlueprint0 ) );
  EXPECT_STREQ( "Sink", baseBlueprint->GetComponent( "Component2" )[ "OperationType" ][ 0 ].c_str() );

  // compose-in additional properties of Component0 and Component1
  auto nonConflictingBlueprint1 = Blueprint::New();

  nonConflictingBlueprint1->SetComponent( "Component0", { { "TranformationGroup", { "Diffeomorphic" } }, { "PixelType", { "float" } } } );
  nonConflictingBlueprint1->SetComponent( "Component1", { { "NameOfClass", { "ImageSourceClass" } } } );

  EXPECT_TRUE( baseBlueprint->ComposeWith( nonConflictingBlueprint1 ) );
  EXPECT_STREQ( "Transform", baseBlueprint->GetComponent( "Component0" )[ "OperationType" ][ 0 ].c_str() );
  EXPECT_STREQ( "Diffeomorphic", baseBlueprint->GetComponent( "Component0" )[ "TranformationGroup" ][ 0 ].c_str() );
  EXPECT_STREQ( "ImageSourceClass", baseBlueprint->GetComponent( "Component1" )[ "NameOfClass" ][ 0 ].c_str() );

  // compose-in existing component with existing property key, but equal property value(s). Nothing happens actually (i.e. idempotency)
  auto nonConflictingBlueprint2 = Blueprint::New();

  nonConflictingBlueprint2->SetComponent( "Component0", { { "PixelType", { "float" } } } );

  EXPECT_TRUE( baseBlueprint->ComposeWith( nonConflictingBlueprint2 ) );

  // trying to overwrite properties fails
  auto conflictingBlueprint0 = Blueprint::New();
  conflictingBlueprint0->SetComponent( "Component1", { { "Dimensionality", { "2" } }, { "InternalComputationValueType", { "float" } } } );

  // Compose fails and returns false
  EXPECT_FALSE( baseBlueprint->ComposeWith( conflictingBlueprint0 ) );

  //baseBlueprint should not have been altered by a failing compose operation
  EXPECT_STREQ( "3", baseBlueprint->GetComponent( "Component1" )[ "Dimensionality" ][ 0 ].c_str() );

  EXPECT_EQ( 0, baseBlueprint->GetComponent( "Component1" ).count( "InternalComputationValueType" ) );
}
//TEST_F( BlueprintTest, WriteBlueprint )
//{
//  std::unique_ptr< BlueprintImpl > blueprint;
//  EXPECT_NO_THROW( blueprint = std::unique_ptr< BlueprintImpl >( new BlueprintImpl() ) );
//
//  // create some made up configuration to show graphviz output
//  ParameterMapType component0Parameters;
//  component0Parameters[ "NameOfClass" ]    = { "MyMetric" };
//  component0Parameters[ "Dimensionality" ] = { "3" };
//  component0Parameters[ "Kernel" ]         = { "5", "5", "5" };
//  blueprint->SetComponent( "Metric", component0Parameters );
//
//  ParameterMapType component1Parameters;
//  component1Parameters[ "NameOfClass" ] = { "MyFiniteDifferenceCalculator" };
//  component1Parameters[ "Delta" ]       = { "0.01" };
//  blueprint->SetComponent( "MetricGradient", component1Parameters );
//
//  ParameterMapType component2Parameters;
//  component2Parameters[ "NameOfClass" ] = { "MyOptimizer" };
//  blueprint->SetComponent( "Optimizer", component2Parameters );
//
//  ParameterMapType component3Parameters;
//  component3Parameters[ "NameOfClass" ] = { "MyTransform" };
//  blueprint->SetComponent( "Transform", component3Parameters );
//
//  blueprint->SetConnection( "Metric", "MetricGradient", parameterMap );
//  blueprint->SetConnection( "MetricGradient", "Optimizer", parameterMap );
//
//  ParameterMapType connection0Parameters;
//  // Example use case: The connection between the metric and optimizer should
//  // only be by "MetricValue", not by "MetricDerivative" as well. Since we want
//  // to redirect the "MetricDerivative" through the MetricGradient component,
//  // we need to specify "NameOfInterface" otherwise there is an ambiguity in
//  // which "MetricDerivative" to connect to the optimizer.
//
//  connection0Parameters[ "NameOfInterface" ] = { "MetricValue" };
//  blueprint->SetConnection( "Metric", "Optimizer", connection0Parameters );
//
//  blueprint->SetConnection( "MetricGradient", "Optimizer", parameterMap );
//  blueprint->SetConnection( "Optimizer", "Transform", parameterMap );
//  blueprint->SetConnection( "Transform", "Metric", parameterMap );
//
//  EXPECT_NO_THROW( blueprint->Write( "blueprint.dot" ) );
//}

TEST_F(BlueprintTest, ReadXML)
{
  auto blueprint = Blueprint::New();

  EXPECT_NO_THROW(blueprint->MergeFromFile(this->dataManager->GetConfigurationFile("itkv4_SVF_ANTsCC.xml")));
  blueprint->Write(this->dataManager->GetOutputFile("configurationReaderTest_itkv4_SVF_ANTsCC.xml.dot"));
}

TEST_F(BlueprintTest, ReadJson)
{
  auto blueprint = Blueprint::New();

  EXPECT_NO_THROW(blueprint->MergeFromFile(this->dataManager->GetConfigurationFile("itkv4_SVF_ANTsCC.json")));
  blueprint->Write(this->dataManager->GetOutputFile("configurationReaderTest_itkv4_SVF_ANTsCC.json.dot"));
}<commit_msg>ENH: restored copy constructor test Blueprint<commit_after>/*=========================================================================
 *
 *  Copyright Leiden University Medical Center, Erasmus University Medical
 *  Center and contributors
 *
 *  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 "selxBlueprintImpl.h"
#include "selxBlueprint.h"

#include "selxDataManager.h"
#include "gtest/gtest.h"

using namespace selx;

class BlueprintTest : public ::testing::Test
{
public:

  typedef BlueprintImpl::ParameterMapType   ParameterMapType;
  typedef BlueprintImpl::ParameterValueType ParameterValueType;

  virtual void SetUp()
  {
    parameterMap[ "NameOfClass" ]        = ParameterValueType( 1, "TestClassName" );
    anotherParameterMap[ "NameOfClass" ] = ParameterValueType( 1, "AnotherTestClassName" );
    dataManager = DataManager::New();
  }

  typedef Blueprint::Pointer BlueprintPointer;

  DataManager::Pointer dataManager;
  ParameterMapType parameterMap;
  ParameterMapType anotherParameterMap;
};

TEST_F( BlueprintTest, SetGetDeleteComponent )
{
  auto blueprint = Blueprint::New();

  bool success0;
  EXPECT_NO_THROW( success0 = blueprint->SetComponent( "MyComponentName", parameterMap ) );
  EXPECT_TRUE( success0 );

  bool success1;
  EXPECT_NO_THROW( blueprint->SetComponent( "MyComponentName", parameterMap ) );
  EXPECT_NO_THROW( success1 = blueprint->SetComponent( "MyComponentName", anotherParameterMap ) );
  EXPECT_TRUE( success1 );
  EXPECT_EQ( anotherParameterMap, blueprint->GetComponent( "MyComponentName" ) );
}

TEST_F( BlueprintTest, BlueprintObjectSetGetDeleteComponent )
{
  BlueprintPointer blueprint;
  EXPECT_NO_THROW( blueprint = Blueprint::New() );

  bool success0;
  EXPECT_NO_THROW( success0 = blueprint->SetComponent( "MyComponentName", parameterMap ) );
  EXPECT_TRUE( success0 );

  bool success1;
  EXPECT_NO_THROW( blueprint->SetComponent( "MyComponentName", parameterMap ) );
  EXPECT_NO_THROW( success1 = blueprint->SetComponent( "MyComponentName", anotherParameterMap ) );
  EXPECT_TRUE( success1 );
  EXPECT_EQ( anotherParameterMap, blueprint->GetComponent( "MyComponentName" ) );
}

TEST_F( BlueprintTest, SetGetDeleteConnection )
{
  auto blueprint = Blueprint::New();

  blueprint->SetComponent( "Component0", parameterMap );
  blueprint->SetComponent( "Component1", parameterMap );
  blueprint->SetComponent( "Component2", parameterMap );

  // Connection should not exist
  bool connectionExists;
  EXPECT_NO_THROW( connectionExists = blueprint->ConnectionExists( "Component0", "Component1" ) );
  EXPECT_FALSE( connectionExists );

  // Connection should be set
  bool connectionSet;
  EXPECT_NO_THROW( connectionSet = blueprint->SetConnection( "Component0", "Component1", parameterMap ) );
  EXPECT_TRUE( connectionSet );

  // Connection should now exist
  bool connectionNowExists;
  EXPECT_NO_THROW( connectionNowExists = blueprint->ConnectionExists( "Component0", "Component1" ) );
  EXPECT_TRUE( connectionNowExists );

  // Connection should have parameter map
  ParameterMapType parameterMap0;
  EXPECT_NO_THROW( parameterMap0 = blueprint->GetConnection( "Component0", "Component1" ) );
  EXPECT_EQ( parameterMap[ "NameOfClass" ], parameterMap0[ "NameOfClass" ] );

  // Another parameter map should transparently added
  bool anotherParameterMapSet;
  EXPECT_NO_THROW( anotherParameterMapSet = blueprint->SetConnection( "Component0", "Component1", anotherParameterMap ) );
  EXPECT_TRUE( anotherParameterMapSet );
  EXPECT_EQ( anotherParameterMap, blueprint->GetConnection( "Component0", "Component1" ) );

  // Connection should be deleted
  bool connectionDeleted;
  EXPECT_NO_THROW( connectionDeleted = blueprint->DeleteConnection( "Component0", "Component1" ) );
  EXPECT_TRUE( connectionDeleted );

  // Connection should not exist
  EXPECT_FALSE( blueprint->ConnectionExists( "Component0", "Component1" ) );

  EXPECT_THROW( blueprint->GetConnection( "Component0", "Component1" ), std::runtime_error );
}

TEST_F( BlueprintTest, CopyConstuctor )
{
  auto baseBlueprint = Blueprint::New();
  baseBlueprint->SetComponent( "Component0", { { "OperationType", { "Transform" } } } );

  auto baseBlueprintImpl = baseBlueprint->GetBlueprintImpl();

  std::unique_ptr< BlueprintImpl > clonedBaseBlueprint;
  EXPECT_NO_THROW( clonedBaseBlueprint = std::make_unique< BlueprintImpl >( baseBlueprintImpl ) );

  EXPECT_NO_THROW( clonedBaseBlueprint->SetComponent( "Component1", { { "OperationType", { "Source" } }, { "Dimensionality", { "3" } } } ) );

  BlueprintImpl::ParameterMapType clonedComponent0;
  EXPECT_NO_THROW( clonedComponent0 = clonedBaseBlueprint->GetComponent( "Component0" ) );

  BlueprintImpl::ParameterMapType component1;
  EXPECT_THROW( component1 = baseBlueprint->GetComponent( "Component1" ), std::runtime_error );
}

TEST_F( BlueprintTest, Compose )
{
  auto baseBlueprint = Blueprint::New();

  baseBlueprint->SetComponent( "Component0", { { "OperationType", { "Transform" } } } );
  baseBlueprint->SetComponent( "Component1", { { "OperationType", { "Source" } }, { "Dimensionality", { "3" } } } );

  // compose-in a new 3rd component Component2
  auto nonConflictingBlueprint0 = Blueprint::New();

  nonConflictingBlueprint0->SetComponent( "Component2", { { "OperationType", { "Sink" } } } );

  EXPECT_TRUE( baseBlueprint->ComposeWith( nonConflictingBlueprint0 ) );
  EXPECT_STREQ( "Sink", baseBlueprint->GetComponent( "Component2" )[ "OperationType" ][ 0 ].c_str() );

  // compose-in additional properties of Component0 and Component1
  auto nonConflictingBlueprint1 = Blueprint::New();

  nonConflictingBlueprint1->SetComponent( "Component0", { { "TranformationGroup", { "Diffeomorphic" } }, { "PixelType", { "float" } } } );
  nonConflictingBlueprint1->SetComponent( "Component1", { { "NameOfClass", { "ImageSourceClass" } } } );

  EXPECT_TRUE( baseBlueprint->ComposeWith( nonConflictingBlueprint1 ) );
  EXPECT_STREQ( "Transform", baseBlueprint->GetComponent( "Component0" )[ "OperationType" ][ 0 ].c_str() );
  EXPECT_STREQ( "Diffeomorphic", baseBlueprint->GetComponent( "Component0" )[ "TranformationGroup" ][ 0 ].c_str() );
  EXPECT_STREQ( "ImageSourceClass", baseBlueprint->GetComponent( "Component1" )[ "NameOfClass" ][ 0 ].c_str() );

  // compose-in existing component with existing property key, but equal property value(s). Nothing happens actually (i.e. idempotency)
  auto nonConflictingBlueprint2 = Blueprint::New();

  nonConflictingBlueprint2->SetComponent( "Component0", { { "PixelType", { "float" } } } );

  EXPECT_TRUE( baseBlueprint->ComposeWith( nonConflictingBlueprint2 ) );

  // trying to overwrite properties fails
  auto conflictingBlueprint0 = Blueprint::New();
  conflictingBlueprint0->SetComponent( "Component1", { { "Dimensionality", { "2" } }, { "InternalComputationValueType", { "float" } } } );

  // Compose fails and returns false
  EXPECT_FALSE( baseBlueprint->ComposeWith( conflictingBlueprint0 ) );

  //baseBlueprint should not have been altered by a failing compose operation
  EXPECT_STREQ( "3", baseBlueprint->GetComponent( "Component1" )[ "Dimensionality" ][ 0 ].c_str() );

  EXPECT_EQ( 0, baseBlueprint->GetComponent( "Component1" ).count( "InternalComputationValueType" ) );
}
//TEST_F( BlueprintTest, WriteBlueprint )
//{
//  std::unique_ptr< BlueprintImpl > blueprint;
//  EXPECT_NO_THROW( blueprint = std::unique_ptr< BlueprintImpl >( new BlueprintImpl() ) );
//
//  // create some made up configuration to show graphviz output
//  ParameterMapType component0Parameters;
//  component0Parameters[ "NameOfClass" ]    = { "MyMetric" };
//  component0Parameters[ "Dimensionality" ] = { "3" };
//  component0Parameters[ "Kernel" ]         = { "5", "5", "5" };
//  blueprint->SetComponent( "Metric", component0Parameters );
//
//  ParameterMapType component1Parameters;
//  component1Parameters[ "NameOfClass" ] = { "MyFiniteDifferenceCalculator" };
//  component1Parameters[ "Delta" ]       = { "0.01" };
//  blueprint->SetComponent( "MetricGradient", component1Parameters );
//
//  ParameterMapType component2Parameters;
//  component2Parameters[ "NameOfClass" ] = { "MyOptimizer" };
//  blueprint->SetComponent( "Optimizer", component2Parameters );
//
//  ParameterMapType component3Parameters;
//  component3Parameters[ "NameOfClass" ] = { "MyTransform" };
//  blueprint->SetComponent( "Transform", component3Parameters );
//
//  blueprint->SetConnection( "Metric", "MetricGradient", parameterMap );
//  blueprint->SetConnection( "MetricGradient", "Optimizer", parameterMap );
//
//  ParameterMapType connection0Parameters;
//  // Example use case: The connection between the metric and optimizer should
//  // only be by "MetricValue", not by "MetricDerivative" as well. Since we want
//  // to redirect the "MetricDerivative" through the MetricGradient component,
//  // we need to specify "NameOfInterface" otherwise there is an ambiguity in
//  // which "MetricDerivative" to connect to the optimizer.
//
//  connection0Parameters[ "NameOfInterface" ] = { "MetricValue" };
//  blueprint->SetConnection( "Metric", "Optimizer", connection0Parameters );
//
//  blueprint->SetConnection( "MetricGradient", "Optimizer", parameterMap );
//  blueprint->SetConnection( "Optimizer", "Transform", parameterMap );
//  blueprint->SetConnection( "Transform", "Metric", parameterMap );
//
//  EXPECT_NO_THROW( blueprint->Write( "blueprint.dot" ) );
//}

TEST_F(BlueprintTest, ReadXML)
{
  auto blueprint = Blueprint::New();

  EXPECT_NO_THROW(blueprint->MergeFromFile(this->dataManager->GetConfigurationFile("itkv4_SVF_ANTsCC.xml")));
  blueprint->Write(this->dataManager->GetOutputFile("configurationReaderTest_itkv4_SVF_ANTsCC.xml.dot"));
}

TEST_F(BlueprintTest, ReadJson)
{
  auto blueprint = Blueprint::New();

  EXPECT_NO_THROW(blueprint->MergeFromFile(this->dataManager->GetConfigurationFile("itkv4_SVF_ANTsCC.json")));
  blueprint->Write(this->dataManager->GetOutputFile("configurationReaderTest_itkv4_SVF_ANTsCC.json.dot"));
}<|endoftext|>


<commit_before>#include "KeyboardInputComponent.h"
#include "SDL2/SDL_events.h"
#include "SDL2/SDL_keyboard.h"
#include "SDL2/SDL_keycode.h"

void KeyboardInputComponent::Init()
{
	//init keys I want to use for the game....
	//should probably read from some file what keys I want to bind to..
	//but this should be good enough for now..
	keys["left"] = KeyStates::NA;
	keys["right"] = KeyStates::NA;
	keys["up"] = KeyStates::NA;
	keys["down"] = KeyStates::NA;
	keys["a"] = KeyStates::NA;
	keys["s"] = KeyStates::NA;
	keys["d"] = KeyStates::NA;
	keys["space"] = KeyStates::NA;

	startPressedTime = 0;
	counter = 0;
}

bool KeyboardInputComponent::KeyPressed(std::string keyName)
{
	return keys.at(keyName) == KeyStates::PRESSED;
}

bool KeyboardInputComponent::KeyHeld(std::string keyName)
{
	return keys.at(keyName) == KeyStates::HELD;
}

bool KeyboardInputComponent::KeyReleased(std::string keyName)
{
	return keys.at(keyName) == KeyStates::RELEASED;
}

//may need to rewrite this component since multiple functions that poll for events
//may have the information this keyboard component needs e.g. if I did not hit x to exit the application and have hit a keybinding instead,
//it may not record the keybinding in a separate event poll...

//the subtle difference between gamepad controller events
//and key events is that key events get checked every update
//e.g. if key is down for more than 1 frame, it will continue to
//process that input as a key down again...
void KeyboardInputComponent::Update(float deltaTime)
{
	SDL_Event event;
	while(SDL_PollEvent(&event))
	{
		if (event.type == SDL_KEYDOWN)//this statement will be true as long as a key is held down...
		{
			SDL_Keycode keycode = event.key.keysym.sym;
			//y-axis movement
			if (keycode == SDLK_UP)
			{
				if (keys["up"] == KeyStates::RELEASED)
					keys["up"] = KeyStates::PRESSED;
				else
					keys["up"] = KeyStates::HELD;
			}
			else if (keycode == SDLK_DOWN)
			{
				if (keys["down"] == KeyStates::RELEASED)
					keys["down"] = KeyStates::PRESSED;
				else
					keys["down"] = KeyStates::HELD;
			}

			//x-axis movement
			if (keycode == SDLK_LEFT)
			{
				if (keys["left"] == KeyStates::RELEASED)
					keys["left"] = KeyStates::PRESSED;
				else
					keys["left"] = KeyStates::HELD;
			}
			else if (keycode == SDLK_RIGHT)
			{
				if (keys["right"] == KeyStates::RELEASED)
					keys["right"] = KeyStates::PRESSED;
				else
					keys["right"] = KeyStates::HELD;
			}

			//action keys and space
			if (keycode == SDLK_a)
			{
				if (keys["a"] == KeyStates::RELEASED)
					keys["a"] = KeyStates::PRESSED;
				else
					keys["a"] = KeyStates::HELD;
			}
			if (keycode == SDLK_s)
			{
				if (keys["s"] == KeyStates::RELEASED)
					keys["s"] = KeyStates::PRESSED;
				else
					keys["s"] = KeyStates::HELD;
			}
			if (keycode == SDLK_d)
			{
				if (keys["d"] == KeyStates::RELEASED)
					keys["d"] = KeyStates::PRESSED;
				else
					keys["d"] = KeyStates::HELD;
			}
			if (keycode == SDLK_SPACE)
			{
				if (keys["space"] == KeyStates::RELEASED)
					keys["space"] = KeyStates::PRESSED;
				else
					keys["space"] = KeyStates::HELD;
			}

		}

		if (event.type == SDL_KEYUP)
		{
			SDL_Keycode keycode = event.key.keysym.sym;

			//y-axis movement
			if (keycode == SDLK_UP)
			{
				keys["up"] = KeyStates::RELEASED;
			}
			if (keycode == SDLK_DOWN)
			{
				keys["down"] = KeyStates::RELEASED;
			}

			//x-axis movement
			if (keycode == SDLK_LEFT)
			{
				keys["left"] = KeyStates::RELEASED;
			}
			if (keycode == SDLK_RIGHT)
			{
				keys["right"] = KeyStates::RELEASED;
			}

			//action keys and space
			if (keycode == SDLK_a)
			{
				keys["a"] = KeyStates::RELEASED;
			}
			if (keycode == SDLK_s)
			{
				keys["s"] = KeyStates::RELEASED;
			}
			if (keycode == SDLK_d)
			{
				keys["d"] = KeyStates::RELEASED;
			}
			if (keycode == SDLK_SPACE)
			{
				keys["space"] = KeyStates::RELEASED;
			}
		}
		else //if key was released for more than one frame set it back to NA
		{
			if (keys["up"] == KeyStates::RELEASED)
				keys["up"] = KeyStates::NA;
			if (keys["down"] == KeyStates::RELEASED)
				keys["down"] = KeyStates::NA;
			if (keys["left"] == KeyStates::RELEASED)
				keys["left"] = KeyStates::NA;
			if (keys["right"] == KeyStates::RELEASED)
				keys["right"] = KeyStates::NA;
		}
	}
}
<commit_msg>Minor tweaks<commit_after>#include "KeyboardInputComponent.h"
#include "SDL2/SDL_events.h"
#include "SDL2/SDL_keyboard.h"
#include "SDL2/SDL_keycode.h"

void KeyboardInputComponent::Init()
{
	//init keys I want to use for the game....
	//should probably read from some file what keys I want to bind to..
	//but this should be good enough for now..
	keys["left"] = KeyStates::NA;
	keys["right"] = KeyStates::NA;
	keys["up"] = KeyStates::NA;
	keys["down"] = KeyStates::NA;
	keys["a"] = KeyStates::NA;
	keys["s"] = KeyStates::NA;
	keys["d"] = KeyStates::NA;
	keys["space"] = KeyStates::NA;

	startPressedTime = 0;
	counter = 0;
}

bool KeyboardInputComponent::KeyPressed(std::string keyName)
{
	return keys.at(keyName) == KeyStates::PRESSED;
}

bool KeyboardInputComponent::KeyHeld(std::string keyName)
{
	return keys.at(keyName) == KeyStates::HELD;
}

bool KeyboardInputComponent::KeyReleased(std::string keyName)
{
	return keys.at(keyName) == KeyStates::RELEASED;
}

//may need to rewrite this component since multiple functions that poll for events
//may have the information this keyboard component needs e.g. if I did not hit x to exit the application and have hit a keybinding instead,
//it may not record the keybinding in a separate event poll...

//the subtle difference between gamepad controller events
//and key events is that key events get checked every update
//e.g. if key is down for more than 1 frame, it will continue to
//process that input as a key down again...
void KeyboardInputComponent::Update(float deltaTime)
{
	SDL_Event event;
	while(SDL_PollEvent(&event))
	{
		if (event.type == SDL_KEYDOWN)//this statement will be true as long as a key is held down...
		{
			SDL_Keycode keycode = event.key.keysym.sym;
			//y-axis movement
			if (keycode == SDLK_UP)
			{
				if (keys["up"] == KeyStates::RELEASED)
					keys["up"] = KeyStates::PRESSED;
				else
					keys["up"] = KeyStates::HELD;
			}
			if (keycode == SDLK_DOWN)
			{
				if (keys["down"] == KeyStates::RELEASED)
					keys["down"] = KeyStates::PRESSED;
				else
					keys["down"] = KeyStates::HELD;
			}

			//x-axis movement
			if (keycode == SDLK_LEFT)
			{
				if (keys["left"] == KeyStates::RELEASED)
					keys["left"] = KeyStates::PRESSED;
				else
					keys["left"] = KeyStates::HELD;
			}
			if (keycode == SDLK_RIGHT)
			{
				if (keys["right"] == KeyStates::RELEASED)
					keys["right"] = KeyStates::PRESSED;
				else
					keys["right"] = KeyStates::HELD;
			}

			//action keys and space
			if (keycode == SDLK_a)
			{
				if (keys["a"] == KeyStates::RELEASED)
					keys["a"] = KeyStates::PRESSED;
				else
					keys["a"] = KeyStates::HELD;
			}
			if (keycode == SDLK_s)
			{
				if (keys["s"] == KeyStates::RELEASED)
					keys["s"] = KeyStates::PRESSED;
				else
					keys["s"] = KeyStates::HELD;
			}
			if (keycode == SDLK_d)
			{
				if (keys["d"] == KeyStates::RELEASED)
					keys["d"] = KeyStates::PRESSED;
				else
					keys["d"] = KeyStates::HELD;
			}
			if (keycode == SDLK_SPACE)
			{
				if (keys["space"] == KeyStates::RELEASED)
					keys["space"] = KeyStates::PRESSED;
				else
					keys["space"] = KeyStates::HELD;
			}

		}

		if (event.type == SDL_KEYUP)
		{
			SDL_Keycode keycode = event.key.keysym.sym;

			//y-axis movement
			if (keycode == SDLK_UP)
			{
				keys["up"] = KeyStates::RELEASED;
			}
			if (keycode == SDLK_DOWN)
			{
				keys["down"] = KeyStates::RELEASED;
			}

			//x-axis movement
			if (keycode == SDLK_LEFT)
			{
				keys["left"] = KeyStates::RELEASED;
			}
			if (keycode == SDLK_RIGHT)
			{
				keys["right"] = KeyStates::RELEASED;
			}

			//action keys and space
			if (keycode == SDLK_a)
			{
				keys["a"] = KeyStates::RELEASED;
			}
			if (keycode == SDLK_s)
			{
				keys["s"] = KeyStates::RELEASED;
			}
			if (keycode == SDLK_d)
			{
				keys["d"] = KeyStates::RELEASED;
			}
			if (keycode == SDLK_SPACE)
			{
				keys["space"] = KeyStates::RELEASED;
			}
		}
		else //if key was released for more than one frame set it back to NA
		{
			if (keys["up"] == KeyStates::RELEASED)
				keys["up"] = KeyStates::NA;
			if (keys["down"] == KeyStates::RELEASED)
				keys["down"] = KeyStates::NA;
			if (keys["left"] == KeyStates::RELEASED)
				keys["left"] = KeyStates::NA;
			if (keys["right"] == KeyStates::RELEASED)
				keys["right"] = KeyStates::NA;
		}
	}
}
<|endoftext|>


<commit_before>/*
   Copyright (c) 2012-2013, Jack Poulson
   All rights reserved.

   This file is part of Choice and is under the BSD 2-Clause License,
   which can be found in the LICENSE file in the root directory, or at
   http://opensource.org/licenses/BSD-2-Clause
*/
#ifndef CHOICE_H
#define CHOICE_H 1

#include <algorithm>
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <typeinfo>
#include <vector>

namespace choice {

template<typename TOut,typename TIn>
TOut Cast( const TIn& input )
{
    std::stringstream stream;
    TOut output;

    stream << input;
    stream >> output;

    return output;
}

template<>
bool Cast( const std::string& input )
{
    std::string trueString("true");
    std::string falseString("false");
    if( input.compare(trueString) == 0 )
        return true;
    else if( input.compare(falseString) == 0 )
        return false;
    else
    {
        bool output;
        std::stringstream stream;
        stream << input;
        stream >> output;
        return output;
    }
}

class ArgException : public std::logic_error
{
public:
    ArgException( const char* msg="Argument exception" )
    : std::logic_error( msg ) { }
};

class Args
{
public:
    Args( int argc, char** argv, std::ostream& error=std::cerr );

    template<typename T>
    T Input( std::string name, std::string desc );
    template<typename T>
    T Input( std::string name, std::string desc, T defaultVal );

    void Process( std::ostream& output=std::cout ) const;
    void PrintReport( std::ostream& output=std::cout ) const;

private:
    int argc_;
    char** argv_;
    std::vector<bool> usedArgs_;
    std::ostream& error_;

    struct RequiredArg
    {
        std::string name, desc, typeInfo, usedVal;
        bool found;

        RequiredArg
        ( std::string n, std::string d, std::string t, std::string uv, bool f )
        : name(n), desc(d), typeInfo(t), usedVal(uv), found(f) { };
    };

    struct OptionalArg
    {
        std::string name, desc, typeInfo, defaultVal, usedVal;
        bool found;

        OptionalArg
        ( std::string n, std::string d, std::string t,
          std::string dv, std::string uv, bool f )
        : name(n), desc(d), typeInfo(t),
          defaultVal(dv), usedVal(uv), found(f) { }
    };

    std::vector<RequiredArg> requiredArgs_;
    std::vector<OptionalArg> optionalArgs_;
};

inline
Args::Args( int argc, char** argv, std::ostream& error )
: argc_(argc), argv_(argv), usedArgs_(argc,false), error_(error)
{ }

template<typename T>
inline T
Args::Input( std::string name, std::string desc )
{
    char** arg = std::find( argv_, argv_+argc_, name );
    const bool found = ( arg != argv_+argc_ );
    const bool invalidFound = ( arg == argv_+argc_-1 );
    if( invalidFound )
    {
        error_ << "Missing value for last command-line argument" << std::endl;
        throw ArgException();
    }

    std::string typeInfo( typeid(T).name() );
    std::string usedVal = ( found ? arg[1] : "N/A" );
    requiredArgs_.push_back( RequiredArg(name,desc,typeInfo,usedVal,found) );

    // Before returning, store the used indices and check for duplication
    if( found )
    {
        const int offset = arg - argv_;
        if( usedArgs_[offset] || usedArgs_[offset+1] )
        {
            error_ << "WARNING: conflict with " << name << " detected at ";
            if( usedArgs_[offset] && usedArgs_[offset+1] )
                error_ << "arguments " << offset << " and " << offset+1
                       << std::endl;
            else if( usedArgs_[offset] )
                error_ << "argument " << offset << std::endl;
            else
                error_ << "argument " << offset+1 << std::endl;
            error_ << "Please ensure that you did request argument "
                   << name << " multiple times" << std::endl;
        }
        usedArgs_[offset+0] = true;
        usedArgs_[offset+1] = true;

        arg = std::find( arg+1, argv_+argc_, name );
        if( arg != argv_+argc_ )
            error_ << "WARNING: " << name << " was specified twice and only "
                   << "the first instance is used" << std::endl;
    }

    return Cast<T>( usedVal );
}

template<typename T>
inline T
Args::Input( std::string name, std::string desc, T defaultVal )
{
    char** arg = std::find( argv_, argv_+argc_, name );
    const bool found = ( arg != argv_+argc_ );
    const bool invalidFound = ( arg == argv_+argc_-1 );
    if( invalidFound )
    {
        error_ << "Missing value for last command-line argument" << std::endl;
        throw ArgException();
    }

    std::string typeInfo( typeid(T).name() );

    std::string defValString = Cast<std::string>( defaultVal );
    std::string usedVal = ( found ? arg[1] : defValString );

    optionalArgs_.push_back
    ( OptionalArg(name,desc,typeInfo,defValString,usedVal,found) );

    // Before returning, store the used indices and check for duplication
    if( found )
    {
        const int offset = arg - argv_;
        if( usedArgs_[offset] || usedArgs_[offset+1] )
        {
            error_ << "WARNING: conflict with " << name << " detected at ";
            if( usedArgs_[offset] && usedArgs_[offset+1] )
                error_ << "arguments " << offset << " and " << offset+1
                       << std::endl;
            else if( usedArgs_[offset] )
                error_ << "argument " << offset << std::endl;
            else
                error_ << "argument " << offset+1 << std::endl;
            error_ << "Please ensure that you did request argument "
                   << name << " multiple times" << std::endl;
        }
        usedArgs_[offset+0] = true;
        usedArgs_[offset+1] = true;

        arg = std::find( arg+1, argv_+argc_, name );
        if( arg != argv_+argc_ )
            error_ << "WARNING: " << name << " was specified twice and only "
                   << "the first instance is used" << std::endl;
    }

    if( found )
        return Cast<T>( usedVal );
    else
        return defaultVal; // avoid the double-cast
}

inline void
Args::Process( std::ostream& output ) const
{
    std::string help = "--help";
    char** arg = std::find( argv_, argv_+argc_, help );
    const bool foundHelp = ( arg != argv_+argc_ );

    int numFailed = 0;
    const int numRequired = requiredArgs_.size();
    for( int i=0; i<numRequired; ++i )
        if( !requiredArgs_[i].found )
            ++numFailed;
    if( numFailed > 0 || foundHelp )
    {
        PrintReport( output );
        throw ArgException();
    }
}

inline void
Args::PrintReport( std::ostream& output ) const
{
    const int numRequired = requiredArgs_.size();
    const int numOptional = optionalArgs_.size();

    if( numRequired > 0 )
        output << "Required arguments:\n";
    int numReqFailed = 0;
    for( int i=0; i<numRequired; ++i )
    {
        const RequiredArg& reqArg = requiredArgs_[i];
        if( !reqArg.found )
            ++numReqFailed;
        std::string foundString = ( reqArg.found ? "found" : "NOT found" );
        output << "  " << reqArg.name
               << " [" << reqArg.typeInfo << "," << reqArg.usedVal << ","
               << foundString << "]\n"
               << "    " << reqArg.desc << "\n\n";
    }

    if( numOptional > 0 )
        output << "Optional arguments:\n";
    int numOptFailed = 0;
    for( int i=0; i<numOptional; ++i )
    {
        const OptionalArg& optArg = optionalArgs_[i];
        if( !optArg.found )
            ++numOptFailed;
        std::string foundString = ( optArg.found ? "found" : "NOT found" );
        output << "  " << optArg.name
               << " [" << optArg.typeInfo
               << "," << optArg.defaultVal << "," << optArg.usedVal << ","
               << foundString << "]\n"
               << "    " << optArg.desc << "\n\n";
    }

    output << "Out of " << numRequired << " required arguments, "
           << numReqFailed << " were not specified." << std::endl;

    output << "Out of " << numOptional << " optional arguments, "
           << numOptFailed << " were not specified.\n" << std::endl;
}

} // namespace choice

#endif // ifndef CHOICE_H
<commit_msg>Adding missing inline qualifiers for Cast function<commit_after>/*
   Copyright (c) 2012-2013, Jack Poulson
   All rights reserved.

   This file is part of Choice and is under the BSD 2-Clause License,
   which can be found in the LICENSE file in the root directory, or at
   http://opensource.org/licenses/BSD-2-Clause
*/
#ifndef CHOICE_H
#define CHOICE_H 1

#include <algorithm>
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <typeinfo>
#include <vector>

namespace choice {

template<typename TOut,typename TIn>
inline TOut Cast( const TIn& input )
{
    std::stringstream stream;
    TOut output;

    stream << input;
    stream >> output;

    return output;
}

template<>
inline bool Cast( const std::string& input )
{
    std::string trueString("true");
    std::string falseString("false");
    if( input.compare(trueString) == 0 )
        return true;
    else if( input.compare(falseString) == 0 )
        return false;
    else
    {
        bool output;
        std::stringstream stream;
        stream << input;
        stream >> output;
        return output;
    }
}

class ArgException : public std::logic_error
{
public:
    ArgException( const char* msg="Argument exception" )
    : std::logic_error( msg ) { }
};

class Args
{
public:
    Args( int argc, char** argv, std::ostream& error=std::cerr );

    template<typename T>
    T Input( std::string name, std::string desc );
    template<typename T>
    T Input( std::string name, std::string desc, T defaultVal );

    void Process( std::ostream& output=std::cout ) const;
    void PrintReport( std::ostream& output=std::cout ) const;

private:
    int argc_;
    char** argv_;
    std::vector<bool> usedArgs_;
    std::ostream& error_;

    struct RequiredArg
    {
        std::string name, desc, typeInfo, usedVal;
        bool found;

        RequiredArg
        ( std::string n, std::string d, std::string t, std::string uv, bool f )
        : name(n), desc(d), typeInfo(t), usedVal(uv), found(f) { };
    };

    struct OptionalArg
    {
        std::string name, desc, typeInfo, defaultVal, usedVal;
        bool found;

        OptionalArg
        ( std::string n, std::string d, std::string t,
          std::string dv, std::string uv, bool f )
        : name(n), desc(d), typeInfo(t),
          defaultVal(dv), usedVal(uv), found(f) { }
    };

    std::vector<RequiredArg> requiredArgs_;
    std::vector<OptionalArg> optionalArgs_;
};

inline
Args::Args( int argc, char** argv, std::ostream& error )
: argc_(argc), argv_(argv), usedArgs_(argc,false), error_(error)
{ }

template<typename T>
inline T
Args::Input( std::string name, std::string desc )
{
    char** arg = std::find( argv_, argv_+argc_, name );
    const bool found = ( arg != argv_+argc_ );
    const bool invalidFound = ( arg == argv_+argc_-1 );
    if( invalidFound )
    {
        error_ << "Missing value for last command-line argument" << std::endl;
        throw ArgException();
    }

    std::string typeInfo( typeid(T).name() );
    std::string usedVal = ( found ? arg[1] : "N/A" );
    requiredArgs_.push_back( RequiredArg(name,desc,typeInfo,usedVal,found) );

    // Before returning, store the used indices and check for duplication
    if( found )
    {
        const int offset = arg - argv_;
        if( usedArgs_[offset] || usedArgs_[offset+1] )
        {
            error_ << "WARNING: conflict with " << name << " detected at ";
            if( usedArgs_[offset] && usedArgs_[offset+1] )
                error_ << "arguments " << offset << " and " << offset+1
                       << std::endl;
            else if( usedArgs_[offset] )
                error_ << "argument " << offset << std::endl;
            else
                error_ << "argument " << offset+1 << std::endl;
            error_ << "Please ensure that you did request argument "
                   << name << " multiple times" << std::endl;
        }
        usedArgs_[offset+0] = true;
        usedArgs_[offset+1] = true;

        arg = std::find( arg+1, argv_+argc_, name );
        if( arg != argv_+argc_ )
            error_ << "WARNING: " << name << " was specified twice and only "
                   << "the first instance is used" << std::endl;
    }

    return Cast<T>( usedVal );
}

template<typename T>
inline T
Args::Input( std::string name, std::string desc, T defaultVal )
{
    char** arg = std::find( argv_, argv_+argc_, name );
    const bool found = ( arg != argv_+argc_ );
    const bool invalidFound = ( arg == argv_+argc_-1 );
    if( invalidFound )
    {
        error_ << "Missing value for last command-line argument" << std::endl;
        throw ArgException();
    }

    std::string typeInfo( typeid(T).name() );

    std::string defValString = Cast<std::string>( defaultVal );
    std::string usedVal = ( found ? arg[1] : defValString );

    optionalArgs_.push_back
    ( OptionalArg(name,desc,typeInfo,defValString,usedVal,found) );

    // Before returning, store the used indices and check for duplication
    if( found )
    {
        const int offset = arg - argv_;
        if( usedArgs_[offset] || usedArgs_[offset+1] )
        {
            error_ << "WARNING: conflict with " << name << " detected at ";
            if( usedArgs_[offset] && usedArgs_[offset+1] )
                error_ << "arguments " << offset << " and " << offset+1
                       << std::endl;
            else if( usedArgs_[offset] )
                error_ << "argument " << offset << std::endl;
            else
                error_ << "argument " << offset+1 << std::endl;
            error_ << "Please ensure that you did request argument "
                   << name << " multiple times" << std::endl;
        }
        usedArgs_[offset+0] = true;
        usedArgs_[offset+1] = true;

        arg = std::find( arg+1, argv_+argc_, name );
        if( arg != argv_+argc_ )
            error_ << "WARNING: " << name << " was specified twice and only "
                   << "the first instance is used" << std::endl;
    }

    if( found )
        return Cast<T>( usedVal );
    else
        return defaultVal; // avoid the double-cast
}

inline void
Args::Process( std::ostream& output ) const
{
    std::string help = "--help";
    char** arg = std::find( argv_, argv_+argc_, help );
    const bool foundHelp = ( arg != argv_+argc_ );

    int numFailed = 0;
    const int numRequired = requiredArgs_.size();
    for( int i=0; i<numRequired; ++i )
        if( !requiredArgs_[i].found )
            ++numFailed;
    if( numFailed > 0 || foundHelp )
    {
        PrintReport( output );
        throw ArgException();
    }
}

inline void
Args::PrintReport( std::ostream& output ) const
{
    const int numRequired = requiredArgs_.size();
    const int numOptional = optionalArgs_.size();

    if( numRequired > 0 )
        output << "Required arguments:\n";
    int numReqFailed = 0;
    for( int i=0; i<numRequired; ++i )
    {
        const RequiredArg& reqArg = requiredArgs_[i];
        if( !reqArg.found )
            ++numReqFailed;
        std::string foundString = ( reqArg.found ? "found" : "NOT found" );
        output << "  " << reqArg.name
               << " [" << reqArg.typeInfo << "," << reqArg.usedVal << ","
               << foundString << "]\n"
               << "    " << reqArg.desc << "\n\n";
    }

    if( numOptional > 0 )
        output << "Optional arguments:\n";
    int numOptFailed = 0;
    for( int i=0; i<numOptional; ++i )
    {
        const OptionalArg& optArg = optionalArgs_[i];
        if( !optArg.found )
            ++numOptFailed;
        std::string foundString = ( optArg.found ? "found" : "NOT found" );
        output << "  " << optArg.name
               << " [" << optArg.typeInfo
               << "," << optArg.defaultVal << "," << optArg.usedVal << ","
               << foundString << "]\n"
               << "    " << optArg.desc << "\n\n";
    }

    output << "Out of " << numRequired << " required arguments, "
           << numReqFailed << " were not specified." << std::endl;

    output << "Out of " << numOptional << " optional arguments, "
           << numOptFailed << " were not specified.\n" << std::endl;
}

} // namespace choice

#endif // ifndef CHOICE_H
<|endoftext|>


<commit_before>/*
 * Medical Image Registration ToolKit (MIRTK)
 *
 * Copyright 2013-2015 Imperial College London
 * Copyright 2013-2015 Andreas Schuh
 *
 * 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 "mirtk/InterpolateImageFunction.hxx"

#include "mirtk/GenericImage.h"

namespace mirtk {

// =============================================================================
// Construction/Destruction
// =============================================================================

// -----------------------------------------------------------------------------
InterpolateImageFunction::InterpolateImageFunction()
:
  _NumberOfDimensions(0),
  _InfiniteInput     (NULL),
  _InfiniteInputOwner(false),
  _x1(.0), _y1(.0), _z1(.0), _t1(.0),
  _x2(.0), _y2(.0), _z2(.0), _t2(.0)
{
}

// -----------------------------------------------------------------------------
InterpolateImageFunction::~InterpolateImageFunction()
{
  if (_InfiniteInputOwner) delete _InfiniteInput;
}

// -----------------------------------------------------------------------------
template <class TImage>
InterpolateImageFunction *NewInterpolator(enum InterpolationMode mode, int dim = 0)
{
  if (mode == Interpolation_Default) {
    mode = DefaultInterpolationMode();
  } else {
    mode = InterpolationWithoutPadding(mode);
  }
  switch (dim) {
    case 2: {
      switch (mode) {
        case Interpolation_NN:               return new GenericNearestNeighborInterpolateImageFunction<TImage>();
        case Interpolation_Linear:           return new GenericLinearInterpolateImageFunction2D<TImage>();
        case Interpolation_FastLinear:       return new GenericLinearInterpolateImageFunction2D<TImage>();
        case Interpolation_BSpline:          return new GenericBSplineInterpolateImageFunction2D<TImage>();
        case Interpolation_CubicBSpline:     return new GenericCubicBSplineInterpolateImageFunction2D<TImage>();
        case Interpolation_FastCubicBSpline: return new GenericFastCubicBSplineInterpolateImageFunction2D<TImage>();
        case Interpolation_CSpline:          return new GenericCSplineInterpolateImageFunction2D<TImage>();
        case Interpolation_Gaussian:         return new GenericGaussianInterpolateImageFunction2D<TImage>();
        case Interpolation_Sinc:             return new GenericSincInterpolateImageFunction2D<TImage>();
        default:                             return NULL;
      }
    }
    case 3: {
      switch (mode) {
        case Interpolation_NN:               return new GenericNearestNeighborInterpolateImageFunction<TImage>();
        case Interpolation_Linear:           return new GenericLinearInterpolateImageFunction3D<TImage>();
        case Interpolation_FastLinear:       return new GenericLinearInterpolateImageFunction3D<TImage>();
        case Interpolation_BSpline:          return new GenericBSplineInterpolateImageFunction3D<TImage>();
        case Interpolation_CubicBSpline:     return new GenericCubicBSplineInterpolateImageFunction3D<TImage>();
        case Interpolation_FastCubicBSpline: return new GenericFastCubicBSplineInterpolateImageFunction3D<TImage>();
        case Interpolation_CSpline:          return new GenericCSplineInterpolateImageFunction3D<TImage>();
        case Interpolation_Gaussian:         return new GenericGaussianInterpolateImageFunction3D<TImage>();
        case Interpolation_Sinc:             return new GenericSincInterpolateImageFunction3D<TImage>();
        default:                             return NULL;
      }
    }
    case 4: {
      switch (mode) {
        case Interpolation_NN:               return new GenericNearestNeighborInterpolateImageFunction<TImage>();
        case Interpolation_Linear:           return new GenericLinearInterpolateImageFunction4D<TImage>();
        case Interpolation_FastLinear:       return new GenericLinearInterpolateImageFunction4D<TImage>();
        case Interpolation_BSpline:          return new GenericBSplineInterpolateImageFunction4D<TImage>();
        case Interpolation_CubicBSpline:     return new GenericCubicBSplineInterpolateImageFunction4D<TImage>();
        case Interpolation_FastCubicBSpline: return new GenericFastCubicBSplineInterpolateImageFunction4D<TImage>();
        case Interpolation_CSpline:          return new GenericCSplineInterpolateImageFunction4D<TImage>();
        case Interpolation_Gaussian:         return new GenericGaussianInterpolateImageFunction4D<TImage>();
        case Interpolation_Sinc:             return new GenericSincInterpolateImageFunction4D<TImage>();
        default:                             return NULL;
      }
    }
    default: {
      switch (mode) {
        case Interpolation_NN:               return new GenericNearestNeighborInterpolateImageFunction<TImage>();
        case Interpolation_Linear:           return new GenericLinearInterpolateImageFunction<TImage>();
        case Interpolation_FastLinear:       return new GenericLinearInterpolateImageFunction<TImage>();
        case Interpolation_BSpline:          return new GenericBSplineInterpolateImageFunction<TImage>();
        case Interpolation_CubicBSpline:     return new GenericCubicBSplineInterpolateImageFunction<TImage>();
        case Interpolation_FastCubicBSpline: return new GenericFastCubicBSplineInterpolateImageFunction<TImage>();
        case Interpolation_CSpline:          return new GenericCSplineInterpolateImageFunction<TImage>();
        case Interpolation_Gaussian:         return new GenericGaussianInterpolateImageFunction<TImage>();
        case Interpolation_Sinc:             return new GenericSincInterpolateImageFunction<TImage>();
        default:                             return NULL;
      }
    }
  }
}

// -----------------------------------------------------------------------------
InterpolateImageFunction *
InterpolateImageFunction::New(enum InterpolationMode mode, const BaseImage *image)
{
  InterpolateImageFunction *p = NULL;
  if (mode == Interpolation_Default) {
    mode = DefaultInterpolationMode();
  } else {
    mode = InterpolationWithoutPadding(mode);
  }

  // Dimensionality of image to interpolate
  int dim  = 0;
  if (image) {
    if      (image->Z() == 1)                            dim = 2;
    else if (image->T() == 1 || image->GetTSize() == .0) dim = 3;
    else                                                 dim = 4;
  }
  // Instantiate special purpose interpolators
  if (mode == Interpolation_SBased) {
    // Only implemented for 3D scalar images
    if (dim == 3 && (!image || image->N() == 1)) {
      p = new ShapeBasedInterpolateImageFunction();
    }
  }
  // Instantiate interpolator for generic image (i.e., instance of GenericImage)
  if (!p && image) {
    typedef GenericImage<char>           CharImage;
    typedef GenericImage<unsigned char>  UCharImage;
    typedef GenericImage<short>          ShortImage;
    typedef GenericImage<unsigned short> UShortImage;
    typedef GenericImage<int>            IntImage;
    typedef GenericImage<unsigned int>   UIntImage;
    typedef GenericImage<float>          FloatImage;
    typedef GenericImage<double>         DoubleImage;

    if      (dynamic_cast<const CharImage   *>(image)) p = NewInterpolator<CharImage>  (mode, dim);
    else if (dynamic_cast<const UCharImage  *>(image)) p = NewInterpolator<UCharImage> (mode, dim);
    else if (dynamic_cast<const ShortImage  *>(image)) p = NewInterpolator<ShortImage> (mode, dim);
    else if (dynamic_cast<const UShortImage *>(image)) p = NewInterpolator<UShortImage>(mode, dim);
    else if (dynamic_cast<const IntImage    *>(image)) p = NewInterpolator<IntImage>   (mode, dim);
    else if (dynamic_cast<const UIntImage   *>(image)) p = NewInterpolator<UIntImage>  (mode, dim);
    else if (dynamic_cast<const FloatImage  *>(image)) p = NewInterpolator<FloatImage> (mode, dim);
    else if (dynamic_cast<const DoubleImage *>(image)) p = NewInterpolator<DoubleImage>(mode, dim);
  }
  // Instantiate interpolator for general image (i.e., subclass of BaseImage)
  if (!p) p = NewInterpolator<BaseImage>(mode, dim);
  // Initialize interpolator
  if (p) {
    p->NumberOfDimensions(dim);
    p->Input(image);
  // Throw error if no suitable interpolator available
  } else {
    cerr << "InterpolateImageFunction::New: Interpolation mode (" << mode;
    cerr << ") not supported for " << (dim ? ToString(dim) : "N") << "D images" << endl;
    exit(1);
  }

  return p;
}

// -----------------------------------------------------------------------------
ExtrapolateImageFunction *
InterpolateImageFunction::New(enum ExtrapolationMode mode, const BaseImage *image)
{
  return ExtrapolateImageFunction::New(mode, image);
}

// -----------------------------------------------------------------------------
InterpolateImageFunction *
InterpolateImageFunction::New(enum InterpolationMode imode,
                                  enum ExtrapolationMode emode, const BaseImage *image)
{
  InterpolateImageFunction *p = InterpolateImageFunction::New(imode, image);
  if (emode != Extrapolation_Default) p->Extrapolator(p->New(emode, image), true);
  return p;
}

// -----------------------------------------------------------------------------
void InterpolateImageFunction::Initialize(bool)
{
  // Initialize image function
  ImageFunction::Initialize();

  // Check if input is a valid image
  if (Input()->IsEmpty()) {
    cerr << this->NameOfClass() << "::Initialize: Input image has zero extent" << endl;
    exit(1);
  }

  // Determine dimensionality of input (if not specified by subclass/New)
  if (_NumberOfDimensions == 0) {
    if (Input()->Z() > 1) {
      if (Input()->T() > 1 && Input()->GetTSize() != .0) _NumberOfDimensions = 4;
      else                                               _NumberOfDimensions = 3;
    } else                                               _NumberOfDimensions = 2;
  }

  // Default domain within which interpolation can be performed is assumed
  // to be identical to the entire finite image domain
  _x1 = .0;
  _y1 = .0;
  _z1 = .0;
  _t1 = .0;
  _x2 = Input()->X() - 1;
  _y2 = Input()->Y() - 1;
  _z2 = Input()->Z() - 1;
  _t2 = Input()->T() - 1;

  // Initialize extrapolator, i.e., infinite discrete image
  if (_InfiniteInput) {
    _InfiniteInput->Input(this->Input());
    _InfiniteInput->Initialize();
  }
}

} // namespace mirtk

////////////////////////////////////////////////////////////////////////////////
// Explicit instantiations
////////////////////////////////////////////////////////////////////////////////

// ND
#include "mirtk/NearestNeighborInterpolateImageFunction.hxx"
#include "mirtk/LinearInterpolateImageFunction.hxx"
#include "mirtk/BSplineInterpolateImageFunction.hxx"
#include "mirtk/CubicBSplineInterpolateImageFunction.hxx"
#include "mirtk/FastCubicBSplineInterpolateImageFunction.hxx"
#include "mirtk/CSplineInterpolateImageFunction.hxx"
#include "mirtk/GaussianInterpolateImageFunction.hxx"
#include "mirtk/SincInterpolateImageFunction.hxx"

// 2D
#include "mirtk/LinearInterpolateImageFunction2D.hxx"
#include "mirtk/BSplineInterpolateImageFunction2D.hxx"
#include "mirtk/CubicBSplineInterpolateImageFunction2D.hxx"
#include "mirtk/FastCubicBSplineInterpolateImageFunction2D.hxx"
#include "mirtk/CSplineInterpolateImageFunction2D.hxx"
#include "mirtk/GaussianInterpolateImageFunction2D.hxx"
#include "mirtk/SincInterpolateImageFunction2D.hxx"

// 3D
#include "mirtk/LinearInterpolateImageFunction3D.hxx"
#include "mirtk/BSplineInterpolateImageFunction3D.hxx"
#include "mirtk/CubicBSplineInterpolateImageFunction3D.hxx"
#include "mirtk/FastCubicBSplineInterpolateImageFunction3D.hxx"
#include "mirtk/CSplineInterpolateImageFunction3D.hxx"
#include "mirtk/GaussianInterpolateImageFunction3D.hxx"
#include "mirtk/SincInterpolateImageFunction3D.hxx"

// 4D
#include "mirtk/LinearInterpolateImageFunction4D.hxx"
#include "mirtk/BSplineInterpolateImageFunction4D.hxx"
#include "mirtk/CubicBSplineInterpolateImageFunction4D.hxx"
#include "mirtk/FastCubicBSplineInterpolateImageFunction4D.hxx"
#include "mirtk/CSplineInterpolateImageFunction4D.hxx"
#include "mirtk/GaussianInterpolateImageFunction4D.hxx"
#include "mirtk/SincInterpolateImageFunction4D.hxx"

namespace mirtk {

// Base class
mirtkInterpolatorInstantiations(GenericInterpolateImageFunction);

// ND
template class GenericNearestNeighborInterpolateImageFunction<ByteImage>;
mirtkInterpolatorInstantiations(GenericNearestNeighborInterpolateImageFunction);
mirtkInterpolatorInstantiations(GenericLinearInterpolateImageFunction);
mirtkInterpolatorInstantiations(GenericBSplineInterpolateImageFunction);
mirtkInterpolatorInstantiations(GenericCubicBSplineInterpolateImageFunction);
mirtkInterpolatorInstantiations(GenericFastCubicBSplineInterpolateImageFunction);
mirtkInterpolatorInstantiations(GenericCSplineInterpolateImageFunction);
mirtkInterpolatorInstantiations(GenericGaussianInterpolateImageFunction);
mirtkInterpolatorInstantiations(GenericSincInterpolateImageFunction);

// 2D
mirtkInterpolatorInstantiations(GenericLinearInterpolateImageFunction2D);
mirtkInterpolatorInstantiations(GenericBSplineInterpolateImageFunction2D);
mirtkInterpolatorInstantiations(GenericCubicBSplineInterpolateImageFunction2D);
mirtkInterpolatorInstantiations(GenericFastCubicBSplineInterpolateImageFunction2D);
mirtkInterpolatorInstantiations(GenericCSplineInterpolateImageFunction2D);
mirtkInterpolatorInstantiations(GenericGaussianInterpolateImageFunction2D);
mirtkInterpolatorInstantiations(GenericSincInterpolateImageFunction2D);

// 3D
mirtkInterpolatorInstantiations(GenericLinearInterpolateImageFunction3D);
mirtkInterpolatorInstantiations(GenericBSplineInterpolateImageFunction3D);
mirtkInterpolatorInstantiations(GenericCubicBSplineInterpolateImageFunction3D);
mirtkInterpolatorInstantiations(GenericFastCubicBSplineInterpolateImageFunction3D);
mirtkInterpolatorInstantiations(GenericCSplineInterpolateImageFunction3D);
mirtkInterpolatorInstantiations(GenericGaussianInterpolateImageFunction3D);
mirtkInterpolatorInstantiations(GenericSincInterpolateImageFunction3D);

// 4D
mirtkInterpolatorInstantiations(GenericLinearInterpolateImageFunction4D);
mirtkInterpolatorInstantiations(GenericBSplineInterpolateImageFunction4D);
mirtkInterpolatorInstantiations(GenericCubicBSplineInterpolateImageFunction4D);
mirtkInterpolatorInstantiations(GenericFastCubicBSplineInterpolateImageFunction4D);
mirtkInterpolatorInstantiations(GenericCSplineInterpolateImageFunction4D);
mirtkInterpolatorInstantiations(GenericGaussianInterpolateImageFunction4D);
mirtkInterpolatorInstantiations(GenericSincInterpolateImageFunction4D);

} // namespace mirtk
<commit_msg>enh: Add template instantiations for linear interpolation of ByteImage [Image]<commit_after>/*
 * Medical Image Registration ToolKit (MIRTK)
 *
 * Copyright 2013-2015 Imperial College London
 * Copyright 2013-2015 Andreas Schuh
 *
 * 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 "mirtk/InterpolateImageFunction.hxx"

#include "mirtk/GenericImage.h"

namespace mirtk {

// =============================================================================
// Construction/Destruction
// =============================================================================

// -----------------------------------------------------------------------------
InterpolateImageFunction::InterpolateImageFunction()
:
  _NumberOfDimensions(0),
  _InfiniteInput     (NULL),
  _InfiniteInputOwner(false),
  _x1(.0), _y1(.0), _z1(.0), _t1(.0),
  _x2(.0), _y2(.0), _z2(.0), _t2(.0)
{
}

// -----------------------------------------------------------------------------
InterpolateImageFunction::~InterpolateImageFunction()
{
  if (_InfiniteInputOwner) delete _InfiniteInput;
}

// -----------------------------------------------------------------------------
template <class TImage>
InterpolateImageFunction *NewInterpolator(enum InterpolationMode mode, int dim = 0)
{
  if (mode == Interpolation_Default) {
    mode = DefaultInterpolationMode();
  } else {
    mode = InterpolationWithoutPadding(mode);
  }
  switch (dim) {
    case 2: {
      switch (mode) {
        case Interpolation_NN:               return new GenericNearestNeighborInterpolateImageFunction<TImage>();
        case Interpolation_Linear:           return new GenericLinearInterpolateImageFunction2D<TImage>();
        case Interpolation_FastLinear:       return new GenericLinearInterpolateImageFunction2D<TImage>();
        case Interpolation_BSpline:          return new GenericBSplineInterpolateImageFunction2D<TImage>();
        case Interpolation_CubicBSpline:     return new GenericCubicBSplineInterpolateImageFunction2D<TImage>();
        case Interpolation_FastCubicBSpline: return new GenericFastCubicBSplineInterpolateImageFunction2D<TImage>();
        case Interpolation_CSpline:          return new GenericCSplineInterpolateImageFunction2D<TImage>();
        case Interpolation_Gaussian:         return new GenericGaussianInterpolateImageFunction2D<TImage>();
        case Interpolation_Sinc:             return new GenericSincInterpolateImageFunction2D<TImage>();
        default:                             return NULL;
      }
    }
    case 3: {
      switch (mode) {
        case Interpolation_NN:               return new GenericNearestNeighborInterpolateImageFunction<TImage>();
        case Interpolation_Linear:           return new GenericLinearInterpolateImageFunction3D<TImage>();
        case Interpolation_FastLinear:       return new GenericLinearInterpolateImageFunction3D<TImage>();
        case Interpolation_BSpline:          return new GenericBSplineInterpolateImageFunction3D<TImage>();
        case Interpolation_CubicBSpline:     return new GenericCubicBSplineInterpolateImageFunction3D<TImage>();
        case Interpolation_FastCubicBSpline: return new GenericFastCubicBSplineInterpolateImageFunction3D<TImage>();
        case Interpolation_CSpline:          return new GenericCSplineInterpolateImageFunction3D<TImage>();
        case Interpolation_Gaussian:         return new GenericGaussianInterpolateImageFunction3D<TImage>();
        case Interpolation_Sinc:             return new GenericSincInterpolateImageFunction3D<TImage>();
        default:                             return NULL;
      }
    }
    case 4: {
      switch (mode) {
        case Interpolation_NN:               return new GenericNearestNeighborInterpolateImageFunction<TImage>();
        case Interpolation_Linear:           return new GenericLinearInterpolateImageFunction4D<TImage>();
        case Interpolation_FastLinear:       return new GenericLinearInterpolateImageFunction4D<TImage>();
        case Interpolation_BSpline:          return new GenericBSplineInterpolateImageFunction4D<TImage>();
        case Interpolation_CubicBSpline:     return new GenericCubicBSplineInterpolateImageFunction4D<TImage>();
        case Interpolation_FastCubicBSpline: return new GenericFastCubicBSplineInterpolateImageFunction4D<TImage>();
        case Interpolation_CSpline:          return new GenericCSplineInterpolateImageFunction4D<TImage>();
        case Interpolation_Gaussian:         return new GenericGaussianInterpolateImageFunction4D<TImage>();
        case Interpolation_Sinc:             return new GenericSincInterpolateImageFunction4D<TImage>();
        default:                             return NULL;
      }
    }
    default: {
      switch (mode) {
        case Interpolation_NN:               return new GenericNearestNeighborInterpolateImageFunction<TImage>();
        case Interpolation_Linear:           return new GenericLinearInterpolateImageFunction<TImage>();
        case Interpolation_FastLinear:       return new GenericLinearInterpolateImageFunction<TImage>();
        case Interpolation_BSpline:          return new GenericBSplineInterpolateImageFunction<TImage>();
        case Interpolation_CubicBSpline:     return new GenericCubicBSplineInterpolateImageFunction<TImage>();
        case Interpolation_FastCubicBSpline: return new GenericFastCubicBSplineInterpolateImageFunction<TImage>();
        case Interpolation_CSpline:          return new GenericCSplineInterpolateImageFunction<TImage>();
        case Interpolation_Gaussian:         return new GenericGaussianInterpolateImageFunction<TImage>();
        case Interpolation_Sinc:             return new GenericSincInterpolateImageFunction<TImage>();
        default:                             return NULL;
      }
    }
  }
}

// -----------------------------------------------------------------------------
InterpolateImageFunction *
InterpolateImageFunction::New(enum InterpolationMode mode, const BaseImage *image)
{
  InterpolateImageFunction *p = NULL;
  if (mode == Interpolation_Default) {
    mode = DefaultInterpolationMode();
  } else {
    mode = InterpolationWithoutPadding(mode);
  }

  // Dimensionality of image to interpolate
  int dim  = 0;
  if (image) {
    if      (image->Z() == 1)                            dim = 2;
    else if (image->T() == 1 || image->GetTSize() == .0) dim = 3;
    else                                                 dim = 4;
  }
  // Instantiate special purpose interpolators
  if (mode == Interpolation_SBased) {
    // Only implemented for 3D scalar images
    if (dim == 3 && (!image || image->N() == 1)) {
      p = new ShapeBasedInterpolateImageFunction();
    }
  }
  // Instantiate interpolator for generic image (i.e., instance of GenericImage)
  if (!p && image) {
    typedef GenericImage<char>           CharImage;
    typedef GenericImage<unsigned char>  UCharImage;
    typedef GenericImage<short>          ShortImage;
    typedef GenericImage<unsigned short> UShortImage;
    typedef GenericImage<int>            IntImage;
    typedef GenericImage<unsigned int>   UIntImage;
    typedef GenericImage<float>          FloatImage;
    typedef GenericImage<double>         DoubleImage;

    if      (dynamic_cast<const CharImage   *>(image)) p = NewInterpolator<CharImage>  (mode, dim);
    else if (dynamic_cast<const UCharImage  *>(image)) p = NewInterpolator<UCharImage> (mode, dim);
    else if (dynamic_cast<const ShortImage  *>(image)) p = NewInterpolator<ShortImage> (mode, dim);
    else if (dynamic_cast<const UShortImage *>(image)) p = NewInterpolator<UShortImage>(mode, dim);
    else if (dynamic_cast<const IntImage    *>(image)) p = NewInterpolator<IntImage>   (mode, dim);
    else if (dynamic_cast<const UIntImage   *>(image)) p = NewInterpolator<UIntImage>  (mode, dim);
    else if (dynamic_cast<const FloatImage  *>(image)) p = NewInterpolator<FloatImage> (mode, dim);
    else if (dynamic_cast<const DoubleImage *>(image)) p = NewInterpolator<DoubleImage>(mode, dim);
  }
  // Instantiate interpolator for general image (i.e., subclass of BaseImage)
  if (!p) p = NewInterpolator<BaseImage>(mode, dim);
  // Initialize interpolator
  if (p) {
    p->NumberOfDimensions(dim);
    p->Input(image);
  // Throw error if no suitable interpolator available
  } else {
    cerr << "InterpolateImageFunction::New: Interpolation mode (" << mode;
    cerr << ") not supported for " << (dim ? ToString(dim) : "N") << "D images" << endl;
    exit(1);
  }

  return p;
}

// -----------------------------------------------------------------------------
ExtrapolateImageFunction *
InterpolateImageFunction::New(enum ExtrapolationMode mode, const BaseImage *image)
{
  return ExtrapolateImageFunction::New(mode, image);
}

// -----------------------------------------------------------------------------
InterpolateImageFunction *
InterpolateImageFunction::New(enum InterpolationMode imode,
                                  enum ExtrapolationMode emode, const BaseImage *image)
{
  InterpolateImageFunction *p = InterpolateImageFunction::New(imode, image);
  if (emode != Extrapolation_Default) p->Extrapolator(p->New(emode, image), true);
  return p;
}

// -----------------------------------------------------------------------------
void InterpolateImageFunction::Initialize(bool)
{
  // Initialize image function
  ImageFunction::Initialize();

  // Check if input is a valid image
  if (Input()->IsEmpty()) {
    cerr << this->NameOfClass() << "::Initialize: Input image has zero extent" << endl;
    exit(1);
  }

  // Determine dimensionality of input (if not specified by subclass/New)
  if (_NumberOfDimensions == 0) {
    if (Input()->Z() > 1) {
      if (Input()->T() > 1 && Input()->GetTSize() != .0) _NumberOfDimensions = 4;
      else                                               _NumberOfDimensions = 3;
    } else                                               _NumberOfDimensions = 2;
  }

  // Default domain within which interpolation can be performed is assumed
  // to be identical to the entire finite image domain
  _x1 = .0;
  _y1 = .0;
  _z1 = .0;
  _t1 = .0;
  _x2 = Input()->X() - 1;
  _y2 = Input()->Y() - 1;
  _z2 = Input()->Z() - 1;
  _t2 = Input()->T() - 1;

  // Initialize extrapolator, i.e., infinite discrete image
  if (_InfiniteInput) {
    _InfiniteInput->Input(this->Input());
    _InfiniteInput->Initialize();
  }
}

} // namespace mirtk

////////////////////////////////////////////////////////////////////////////////
// Explicit instantiations
////////////////////////////////////////////////////////////////////////////////

// ND
#include "mirtk/NearestNeighborInterpolateImageFunction.hxx"
#include "mirtk/LinearInterpolateImageFunction.hxx"
#include "mirtk/BSplineInterpolateImageFunction.hxx"
#include "mirtk/CubicBSplineInterpolateImageFunction.hxx"
#include "mirtk/FastCubicBSplineInterpolateImageFunction.hxx"
#include "mirtk/CSplineInterpolateImageFunction.hxx"
#include "mirtk/GaussianInterpolateImageFunction.hxx"
#include "mirtk/SincInterpolateImageFunction.hxx"

// 2D
#include "mirtk/LinearInterpolateImageFunction2D.hxx"
#include "mirtk/BSplineInterpolateImageFunction2D.hxx"
#include "mirtk/CubicBSplineInterpolateImageFunction2D.hxx"
#include "mirtk/FastCubicBSplineInterpolateImageFunction2D.hxx"
#include "mirtk/CSplineInterpolateImageFunction2D.hxx"
#include "mirtk/GaussianInterpolateImageFunction2D.hxx"
#include "mirtk/SincInterpolateImageFunction2D.hxx"

// 3D
#include "mirtk/LinearInterpolateImageFunction3D.hxx"
#include "mirtk/BSplineInterpolateImageFunction3D.hxx"
#include "mirtk/CubicBSplineInterpolateImageFunction3D.hxx"
#include "mirtk/FastCubicBSplineInterpolateImageFunction3D.hxx"
#include "mirtk/CSplineInterpolateImageFunction3D.hxx"
#include "mirtk/GaussianInterpolateImageFunction3D.hxx"
#include "mirtk/SincInterpolateImageFunction3D.hxx"

// 4D
#include "mirtk/LinearInterpolateImageFunction4D.hxx"
#include "mirtk/BSplineInterpolateImageFunction4D.hxx"
#include "mirtk/CubicBSplineInterpolateImageFunction4D.hxx"
#include "mirtk/FastCubicBSplineInterpolateImageFunction4D.hxx"
#include "mirtk/CSplineInterpolateImageFunction4D.hxx"
#include "mirtk/GaussianInterpolateImageFunction4D.hxx"
#include "mirtk/SincInterpolateImageFunction4D.hxx"

namespace mirtk {

// Base class
mirtkInterpolatorInstantiations(GenericInterpolateImageFunction);

// ND
template class GenericNearestNeighborInterpolateImageFunction<ByteImage>;
template class GenericLinearInterpolateImageFunction<ByteImage>;
mirtkInterpolatorInstantiations(GenericNearestNeighborInterpolateImageFunction);
mirtkInterpolatorInstantiations(GenericLinearInterpolateImageFunction);
mirtkInterpolatorInstantiations(GenericBSplineInterpolateImageFunction);
mirtkInterpolatorInstantiations(GenericCubicBSplineInterpolateImageFunction);
mirtkInterpolatorInstantiations(GenericFastCubicBSplineInterpolateImageFunction);
mirtkInterpolatorInstantiations(GenericCSplineInterpolateImageFunction);
mirtkInterpolatorInstantiations(GenericGaussianInterpolateImageFunction);
mirtkInterpolatorInstantiations(GenericSincInterpolateImageFunction);

// 2D
template class GenericLinearInterpolateImageFunction2D<ByteImage>;
mirtkInterpolatorInstantiations(GenericLinearInterpolateImageFunction2D);
mirtkInterpolatorInstantiations(GenericBSplineInterpolateImageFunction2D);
mirtkInterpolatorInstantiations(GenericCubicBSplineInterpolateImageFunction2D);
mirtkInterpolatorInstantiations(GenericFastCubicBSplineInterpolateImageFunction2D);
mirtkInterpolatorInstantiations(GenericCSplineInterpolateImageFunction2D);
mirtkInterpolatorInstantiations(GenericGaussianInterpolateImageFunction2D);
mirtkInterpolatorInstantiations(GenericSincInterpolateImageFunction2D);

// 3D
template class GenericLinearInterpolateImageFunction3D<ByteImage>;
mirtkInterpolatorInstantiations(GenericLinearInterpolateImageFunction3D);
mirtkInterpolatorInstantiations(GenericBSplineInterpolateImageFunction3D);
mirtkInterpolatorInstantiations(GenericCubicBSplineInterpolateImageFunction3D);
mirtkInterpolatorInstantiations(GenericFastCubicBSplineInterpolateImageFunction3D);
mirtkInterpolatorInstantiations(GenericCSplineInterpolateImageFunction3D);
mirtkInterpolatorInstantiations(GenericGaussianInterpolateImageFunction3D);
mirtkInterpolatorInstantiations(GenericSincInterpolateImageFunction3D);

// 4D
template class GenericLinearInterpolateImageFunction4D<ByteImage>;
mirtkInterpolatorInstantiations(GenericLinearInterpolateImageFunction4D);
mirtkInterpolatorInstantiations(GenericBSplineInterpolateImageFunction4D);
mirtkInterpolatorInstantiations(GenericCubicBSplineInterpolateImageFunction4D);
mirtkInterpolatorInstantiations(GenericFastCubicBSplineInterpolateImageFunction4D);
mirtkInterpolatorInstantiations(GenericCSplineInterpolateImageFunction4D);
mirtkInterpolatorInstantiations(GenericGaussianInterpolateImageFunction4D);
mirtkInterpolatorInstantiations(GenericSincInterpolateImageFunction4D);

} // namespace mirtk
<|endoftext|>