<commit_before>/* Copyright 2017 Kristofer Björnson
 *
 * 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.
 */

/** @file Plotter.cpp
 *
 *  @author Kristofer Björnson
 */

#include "../../../include/Utilities/Plotter/Plotter.h"
#include "Smooth.h"
#include "Streams.h"

#include <sstream>

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>

using namespace std;
using namespace cv;

namespace TBTK{
namespace Plot{

Plotter::Plotter(){
	autoScaleX = true;
	autoScaleY = true;
}

Plotter::~Plotter(){
}

void Plotter::plot(
	double x,
	double y,
	const Decoration &decoration
){
	if(!hold)
		clearDataStorage();

	Decoration modifiedDecoration = decoration;
	if(decoration.getColor().size() != 3)
		modifiedDecoration.setColor({0, 0, 0});

	Point *point = new Point();
	point->setDecoration(modifiedDecoration);
	point->setCoordinate({x, y});
	dataStorage.push_back(point);

/*	if(drawToCanvas){
		drawDataStorage();
		canvas.drawAxes();
	}*/
}

void Plotter::plot(
	const vector<double> &axis,
	const vector<double> &data,
	const Decoration &decoration
){
	TBTKAssert(
		axis.size() == data.size(),
		"Plotter::plot()",
		"Incompatible axis and data. Axis size is " << axis.size()
			<< " while data size is " << data.size() << ".",
		""
	);

	if(!hold)
		clearDataStorage();

	Decoration modifiedDecoration = decoration;
	if(decoration.getColor().size() != 3)
		modifiedDecoration.setColor({0, 0, 0});

	Path *path = new Path();
	path->setDecoration(modifiedDecoration);
	for(unsigned int n = 0; n < axis.size(); n++)
		path->add({axis[n], data[n]});
	dataStorage.push_back(path);

/*	drawDataStorage();
	canvas.drawAxes();*/
}

void Plotter::plot(
	const vector<double> &data,
	const Decoration &decoration
){
	vector<double> axis;
	for(unsigned int n = 0; n < data.size(); n++)
		axis.push_back(n);

	plot(axis, data, decoration);
}

void Plotter::plot(
	const Property::DOS &dos,
	double sigma,
	unsigned int windowSize
){
	vector<double> data;
	vector<double> axis;
	double dE = (dos.getUpperBound() - dos.getLowerBound())/dos.getResolution();
	for(unsigned int n = 0; n < dos.getSize(); n++){
		axis.push_back(dos.getLowerBound() + n*dE);
		data.push_back(dos(n));
	}

	if(sigma != 0){
		double scaledSigma = sigma/(dos.getUpperBound() - dos.getLowerBound())*dos.getResolution();
		data = Smooth::gaussian(data, scaledSigma, windowSize);
	}

	plot(axis, data);
}

void Plotter::plot(
	const vector<vector<double>> &data
){
	if(data.size() == 0)
		return;
	if(data[0].size() == 0)
		return;

	unsigned int sizeY = data[0].size();
	for(unsigned int x = 1; x < data.size(); x++){
		TBTKAssert(
			data[x].size() == sizeY,
			"Plotter:plot()",
			"Incompatible array dimensions. 'data[0]' has "
				<< sizeY << " elements, while 'data[" << x
				<< "]' has " << data[x].size() << " elements.",
			""
		);
	}
	canvas.setBounds(0, data.size()-1, 0, sizeY-1);

	clearDataStorage();
	canvas.clear();

	double minValue = data[0][0];
	double maxValue = data[0][0];
	for(unsigned int x = 0; x < data.size(); x++){
		for(unsigned int y = 0; y < data[x].size(); y++){
			if(data[x][y] < minValue)
				minValue = data[x][y];
			if(data[x][y] > maxValue)
				maxValue = data[x][y];
		}
	}

	for(unsigned int x = 0; x < data.size()-1; x++){
		for(unsigned int y = 0; y < sizeY-1; y++){
			double value00 = data[x][y];
			double value01 = data[x][y+1];
			double value10 = data[x+1][y];
			double value11 = data[x+1][y+1];

			cv::Point p00 = canvas.getCVPoint(x, y);
			cv::Point p01 = canvas.getCVPoint(x, y+1);
			cv::Point p10 = canvas.getCVPoint(x+1, y);
			for(int x = p00.x; x <= p10.x; x++){
				for(int y = p00.y; y >= p01.y; y--){
					double distanceX = (x-p00.x)/(double)(p10.x - p00.x);
					double distanceY = (y-p00.y)/(double)(p01.y - p00.y);
					double value0 = value00*(1 - distanceX) + value10*distanceX;
					double value1 = value01*(1 - distanceX) + value11*distanceX;
					double averagedValue = value0*(1 - distanceY) + value1*distanceY;
					canvas.setPixel(
						x,
						y,
						(255 - 255*(averagedValue - minValue)/(maxValue - minValue)),
						(255 - 255*(averagedValue - minValue)/(maxValue - minValue)),
						255
					);
				}
			}
		}
	}

	canvas.drawAxes();
}

void Plotter::plot(
	const Array<double> &data,
	const Decoration &decoration
){
	const vector<unsigned int> &ranges = data.getRanges();
	switch(ranges.size()){
	case 1:
	{
		vector<double> d;
		for(unsigned int n = 0; n < ranges[0]; n++)
			d.push_back(data[{n}]);
		plot(d, decoration);

		break;
	}
	case 2:
	{
		vector<vector<double>> d;
		for(unsigned int m = 0; m < ranges[0]; m++){
			d.push_back(vector<double>());
			for(unsigned int n = 0; n < ranges[1]; n++)
				d[m].push_back(data[{m, n}]);
		}
		plot(d);

		break;
	}
	default:
		TBTKExit(
			"Plotter:plot()",
			"Array size not supported.",
			"Only arrays with one or two dimensions can be"
			<< " plotter."
		);
	}
}

void Plotter::plot(
	const vector<vector<double>> &data,
	const vector<vector<double>> &intensities,
	const Decoration &decoration
){
	TBTKAssert(
		data.size() == intensities.size(),
		"Plotter::plot()",
		"The dimensions of 'data' and 'intensities' do not agree."
		<< " 'data' has size '" << data.size() << "', while"
		<< " 'intensities' have size '" << intensities.size() << "'.",
		""
	);

	bool tempHold = hold;
	if(!hold){
		clearDataStorage();
		hold = true;
	}

	bool isInitialized = false;
	double min = 0;
	double max = 1;
	for(unsigned int n = 0; n < data.size(); n++){
		TBTKAssert(
			data[n].size() == intensities[n].size(),
			"Plotter::plot()",
			"The dimensions of 'data[" << n << "]' and"
			<< " 'intensities[" << n << "]' do not agree. 'data["
			<< n << "]'" << " has size '" << data[n].size() << "',"
			<< " while 'intensities[" << n << "]' has size '"
			<< intensities.size() << "'.",
			""
		);

		for(unsigned int c = 0; c < data[n].size(); c++){
			if(!isInitialized){
				min = intensities[n][c];
				max = intensities[n][c];
				isInitialized = true;
			}

			if(intensities[n][c] < min)
				min = intensities[n][c];
			if(intensities[n][c] > max)
				max = intensities[n][c];
		}
	}
	if(min == max)
		min = max -1;

	for(unsigned int n = 0; n < data.size(); n++){
		for(unsigned int c = 0; c < data[n].size(); c++){
			plot(
				n,
				data[n][c],
				Decoration(
					{
						(unsigned char)(255 - 255*(intensities[n][c] - min)/(max - min)),
						0,
						(unsigned char)(255*(intensities[n][c] - min)/(max-min))
					},
					Decoration::LineStyle::Point,
					decoration.getSize()
				)
			);
		}
	}

/*	drawDataStorage();
	canvas.drawAxes();*/

	hold = tempHold;
}

void Plotter::plot(
	const Array<double> &data,
	const Array<double> &intensities,
	const Decoration &decoration
){
	const vector<unsigned int> &ranges = data.getRanges();
	switch(ranges.size()){
/*	case 1:
	{
		vector<double> d;
		vector<double> i;
		for(unsigned int n = 0; n < ranges[0]; n++){
			d.push_back(data[{n}]);
			i.push_back(intensities[{n}]);
		}
		plot(d, i, decoration);

		break;
	}*/
	case 2:
	{
		vector<vector<double>> d;
		vector<vector<double>> i;
		for(unsigned int m = 0; m < ranges[0]; m++){
			d.push_back(vector<double>());
			i.push_back(vector<double>());
			for(unsigned int n = 0; n < ranges[1]; n++){
				d[m].push_back(data[{m, n}]);
				i[m].push_back(intensities[{m, n}]);
			}
		}
		plot(d, i, decoration);

		break;
	}
	default:
		TBTKExit(
			"Plotter:plot()",
			"Array size not supported.",
			"Only arrays with one or two dimensions can be"
			<< " plotter."
		);
	}
}

void Plotter::drawDataStorage(){
	if(dataStorage.size() == 0)
		return;

	if(autoScaleX){
		double minX = dataStorage[0]->getMinX();
		double maxX = dataStorage[0]->getMaxX();
		for(unsigned int n = 1; n < dataStorage.size(); n++){
			double min = dataStorage[n]->getMinX();
			double max = dataStorage[n]->getMaxX();
			if(min < minX)
				minX = min;
			if(max > maxX)
				maxX = max;
		}
		canvas.setBoundsX(minX, maxX);
	}
	if(autoScaleY){
		double minY = dataStorage[0]->getMinY();
		double maxY = dataStorage[0]->getMaxY();
		for(unsigned int n = 1; n < dataStorage.size(); n++){
			double min = dataStorage[n]->getMinY();
			double max = dataStorage[n]->getMaxY();
			if(min < minY)
				minY = min;
			if(max > maxY)
				maxY = max;
		}
		canvas.setBoundsY(minY, maxY);
	}

	canvas.clear();

	for(unsigned int n = 0; n < dataStorage.size(); n++)
		dataStorage[n]->draw(canvas);
}

};	//End of namespace Plot
};	//End of namespace TBTK
<commit_msg>Removed commented out legacy code.<commit_after>/* Copyright 2017 Kristofer Björnson
 *
 * 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.
 */

/** @file Plotter.cpp
 *
 *  @author Kristofer Björnson
 */

#include "../../../include/Utilities/Plotter/Plotter.h"
#include "Smooth.h"
#include "Streams.h"

#include <sstream>

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>

using namespace std;
using namespace cv;

namespace TBTK{
namespace Plot{

Plotter::Plotter(){
	autoScaleX = true;
	autoScaleY = true;
}

Plotter::~Plotter(){
}

void Plotter::plot(
	double x,
	double y,
	const Decoration &decoration
){
	if(!hold)
		clearDataStorage();

	Decoration modifiedDecoration = decoration;
	if(decoration.getColor().size() != 3)
		modifiedDecoration.setColor({0, 0, 0});

	Point *point = new Point();
	point->setDecoration(modifiedDecoration);
	point->setCoordinate({x, y});
	dataStorage.push_back(point);
}

void Plotter::plot(
	const vector<double> &axis,
	const vector<double> &data,
	const Decoration &decoration
){
	TBTKAssert(
		axis.size() == data.size(),
		"Plotter::plot()",
		"Incompatible axis and data. Axis size is " << axis.size()
			<< " while data size is " << data.size() << ".",
		""
	);

	if(!hold)
		clearDataStorage();

	Decoration modifiedDecoration = decoration;
	if(decoration.getColor().size() != 3)
		modifiedDecoration.setColor({0, 0, 0});

	Path *path = new Path();
	path->setDecoration(modifiedDecoration);
	for(unsigned int n = 0; n < axis.size(); n++)
		path->add({axis[n], data[n]});
	dataStorage.push_back(path);
}

void Plotter::plot(
	const vector<double> &data,
	const Decoration &decoration
){
	vector<double> axis;
	for(unsigned int n = 0; n < data.size(); n++)
		axis.push_back(n);

	plot(axis, data, decoration);
}

void Plotter::plot(
	const Property::DOS &dos,
	double sigma,
	unsigned int windowSize
){
	vector<double> data;
	vector<double> axis;
	double dE = (dos.getUpperBound() - dos.getLowerBound())/dos.getResolution();
	for(unsigned int n = 0; n < dos.getSize(); n++){
		axis.push_back(dos.getLowerBound() + n*dE);
		data.push_back(dos(n));
	}

	if(sigma != 0){
		double scaledSigma = sigma/(dos.getUpperBound() - dos.getLowerBound())*dos.getResolution();
		data = Smooth::gaussian(data, scaledSigma, windowSize);
	}

	plot(axis, data);
}

void Plotter::plot(
	const vector<vector<double>> &data
){
	if(data.size() == 0)
		return;
	if(data[0].size() == 0)
		return;

	unsigned int sizeY = data[0].size();
	for(unsigned int x = 1; x < data.size(); x++){
		TBTKAssert(
			data[x].size() == sizeY,
			"Plotter:plot()",
			"Incompatible array dimensions. 'data[0]' has "
				<< sizeY << " elements, while 'data[" << x
				<< "]' has " << data[x].size() << " elements.",
			""
		);
	}
	canvas.setBounds(0, data.size()-1, 0, sizeY-1);

	clearDataStorage();
	canvas.clear();

	double minValue = data[0][0];
	double maxValue = data[0][0];
	for(unsigned int x = 0; x < data.size(); x++){
		for(unsigned int y = 0; y < data[x].size(); y++){
			if(data[x][y] < minValue)
				minValue = data[x][y];
			if(data[x][y] > maxValue)
				maxValue = data[x][y];
		}
	}

	for(unsigned int x = 0; x < data.size()-1; x++){
		for(unsigned int y = 0; y < sizeY-1; y++){
			double value00 = data[x][y];
			double value01 = data[x][y+1];
			double value10 = data[x+1][y];
			double value11 = data[x+1][y+1];

			cv::Point p00 = canvas.getCVPoint(x, y);
			cv::Point p01 = canvas.getCVPoint(x, y+1);
			cv::Point p10 = canvas.getCVPoint(x+1, y);
			for(int x = p00.x; x <= p10.x; x++){
				for(int y = p00.y; y >= p01.y; y--){
					double distanceX = (x-p00.x)/(double)(p10.x - p00.x);
					double distanceY = (y-p00.y)/(double)(p01.y - p00.y);
					double value0 = value00*(1 - distanceX) + value10*distanceX;
					double value1 = value01*(1 - distanceX) + value11*distanceX;
					double averagedValue = value0*(1 - distanceY) + value1*distanceY;
					canvas.setPixel(
						x,
						y,
						(255 - 255*(averagedValue - minValue)/(maxValue - minValue)),
						(255 - 255*(averagedValue - minValue)/(maxValue - minValue)),
						255
					);
				}
			}
		}
	}

	canvas.drawAxes();
}

void Plotter::plot(
	const Array<double> &data,
	const Decoration &decoration
){
	const vector<unsigned int> &ranges = data.getRanges();
	switch(ranges.size()){
	case 1:
	{
		vector<double> d;
		for(unsigned int n = 0; n < ranges[0]; n++)
			d.push_back(data[{n}]);
		plot(d, decoration);

		break;
	}
	case 2:
	{
		vector<vector<double>> d;
		for(unsigned int m = 0; m < ranges[0]; m++){
			d.push_back(vector<double>());
			for(unsigned int n = 0; n < ranges[1]; n++)
				d[m].push_back(data[{m, n}]);
		}
		plot(d);

		break;
	}
	default:
		TBTKExit(
			"Plotter:plot()",
			"Array size not supported.",
			"Only arrays with one or two dimensions can be"
			<< " plotter."
		);
	}
}

void Plotter::plot(
	const vector<vector<double>> &data,
	const vector<vector<double>> &intensities,
	const Decoration &decoration
){
	TBTKAssert(
		data.size() == intensities.size(),
		"Plotter::plot()",
		"The dimensions of 'data' and 'intensities' do not agree."
		<< " 'data' has size '" << data.size() << "', while"
		<< " 'intensities' have size '" << intensities.size() << "'.",
		""
	);

	bool tempHold = hold;
	if(!hold){
		clearDataStorage();
		hold = true;
	}

	bool isInitialized = false;
	double min = 0;
	double max = 1;
	for(unsigned int n = 0; n < data.size(); n++){
		TBTKAssert(
			data[n].size() == intensities[n].size(),
			"Plotter::plot()",
			"The dimensions of 'data[" << n << "]' and"
			<< " 'intensities[" << n << "]' do not agree. 'data["
			<< n << "]'" << " has size '" << data[n].size() << "',"
			<< " while 'intensities[" << n << "]' has size '"
			<< intensities.size() << "'.",
			""
		);

		for(unsigned int c = 0; c < data[n].size(); c++){
			if(!isInitialized){
				min = intensities[n][c];
				max = intensities[n][c];
				isInitialized = true;
			}

			if(intensities[n][c] < min)
				min = intensities[n][c];
			if(intensities[n][c] > max)
				max = intensities[n][c];
		}
	}
	if(min == max)
		min = max -1;

	for(unsigned int n = 0; n < data.size(); n++){
		for(unsigned int c = 0; c < data[n].size(); c++){
			plot(
				n,
				data[n][c],
				Decoration(
					{
						(unsigned char)(255 - 255*(intensities[n][c] - min)/(max - min)),
						0,
						(unsigned char)(255*(intensities[n][c] - min)/(max-min))
					},
					Decoration::LineStyle::Point,
					decoration.getSize()
				)
			);
		}
	}

	hold = tempHold;
}

void Plotter::plot(
	const Array<double> &data,
	const Array<double> &intensities,
	const Decoration &decoration
){
	const vector<unsigned int> &ranges = data.getRanges();
	switch(ranges.size()){
/*	case 1:
	{
		vector<double> d;
		vector<double> i;
		for(unsigned int n = 0; n < ranges[0]; n++){
			d.push_back(data[{n}]);
			i.push_back(intensities[{n}]);
		}
		plot(d, i, decoration);

		break;
	}*/
	case 2:
	{
		vector<vector<double>> d;
		vector<vector<double>> i;
		for(unsigned int m = 0; m < ranges[0]; m++){
			d.push_back(vector<double>());
			i.push_back(vector<double>());
			for(unsigned int n = 0; n < ranges[1]; n++){
				d[m].push_back(data[{m, n}]);
				i[m].push_back(intensities[{m, n}]);
			}
		}
		plot(d, i, decoration);

		break;
	}
	default:
		TBTKExit(
			"Plotter:plot()",
			"Array size not supported.",
			"Only arrays with one or two dimensions can be"
			<< " plotter."
		);
	}
}

void Plotter::drawDataStorage(){
	if(dataStorage.size() == 0)
		return;

	if(autoScaleX){
		double minX = dataStorage[0]->getMinX();
		double maxX = dataStorage[0]->getMaxX();
		for(unsigned int n = 1; n < dataStorage.size(); n++){
			double min = dataStorage[n]->getMinX();
			double max = dataStorage[n]->getMaxX();
			if(min < minX)
				minX = min;
			if(max > maxX)
				maxX = max;
		}
		canvas.setBoundsX(minX, maxX);
	}
	if(autoScaleY){
		double minY = dataStorage[0]->getMinY();
		double maxY = dataStorage[0]->getMaxY();
		for(unsigned int n = 1; n < dataStorage.size(); n++){
			double min = dataStorage[n]->getMinY();
			double max = dataStorage[n]->getMaxY();
			if(min < minY)
				minY = min;
			if(max > maxY)
				maxY = max;
		}
		canvas.setBoundsY(minY, maxY);
	}

	canvas.clear();

	for(unsigned int n = 0; n < dataStorage.size(); n++)
		dataStorage[n]->draw(canvas);
}

};	//End of namespace Plot
};	//End of namespace TBTK
<|endoftext|>


<commit_before>/*
MIT License

Copyright (c) 2017 Chris McArthur, prince.chrismc(at)gmail(dot)com

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

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

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

#include "Loader.h"
#include <sstream>
#include <future>

void Obj::Loader::ExtractData()
{
   /// This code can NOT be parallelized because the order needs to be maintained
   for (auto line : m_File.m_Lines)
   {
      switch (line.at(0))
      {
      case 'v':
         switch (line.at(1))
         {
         case ' ': ExtractVertice(line.substr((size_t)Offset::VERTICE)); break;
         case 'n': ExtractNormal(line.substr((size_t)Offset::NORMAL)); break;
         case 't': ExtractTexture(line.substr((size_t)Offset::TEXTURE)); break;
         default:
            break;
         }
         break;
      case 'f': m_Indicies.emplace_back(line.substr((size_t)Offset::INDEX)); break;
      default:
         break;
      }
   }

   ExtractIndexing();
}

void Obj::Loader::ExtractVertice(const std::string & line)
{
   float buffer[3];
   std::stringstream ss(line);
   for (int i = 0; i < 3; i++)
      ss >> buffer[i];

   m_Model.m_Vertices.emplace_back(buffer[0], buffer[1], buffer[2]);
}

void Obj::Loader::ExtractNormal(const std::string & line)
{
   float buffer[3];
   std::stringstream ss(line);;
   for (int i = 0; i < 3; i++)
      ss >> buffer[i];

   m_Model.m_Normals.emplace_back(buffer[0], buffer[1], buffer[2]);
}

void Obj::Loader::ExtractTexture(const std::string & line)
{
   float buffer[2];
   std::stringstream ss(line);
   for (int i = 0; i < 2; i++)
      ss >> buffer[i];

   m_Model.m_Textures.emplace_back(buffer[0], buffer[1]);
}

void Obj::Loader::ExtractIndexing()
{
   for (auto line : m_Indicies)
   {
      std::stringstream ss(line);
      unsigned int vertex_index[3], uv_index[3], normal_index[3];
      for (int i = 0; i < 3; i++)
      {
         ss >> vertex_index[i];
         ss >> uv_index[i];
         ss >> normal_index[i];
      }

      for (auto vertex : vertex_index) m_VerticeIndicies.push_back(vertex);
      for (auto uv : uv_index) m_TextureIndicies.push_back(uv);
      for (auto normal : normal_index) m_NormalsIndicies.push_back(normal);
   }
}

void Obj::Loader::SortCoords()
{
   auto temp_vertices = std::async(std::launch::async, [this] {
      std::vector<glm::vec3> temp_vertices;
      for (unsigned int i = 0; i < m_VerticeIndicies.size(); i++)
         temp_vertices.push_back(m_Model.m_Vertices.at(m_VerticeIndicies.at(i) - 1));
      return temp_vertices;
   });

   auto temp_uvs = std::async(std::launch::async, [this] {
   std::vector<glm::vec2> temp_uvs;
   for (unsigned int i = 0; i < m_TextureIndicies.size(); i++)
      temp_uvs.push_back(m_Model.m_Textures.at(m_TextureIndicies.at(i) - 1));
   return temp_uvs;
   });

   auto temp_normals = std::async(std::launch::async, [this] {
   std::vector<glm::vec3> temp_normals;
   for (unsigned int i = 0; i < m_NormalsIndicies.size(); i++)
      temp_normals.push_back(m_Model.m_Normals.at(m_NormalsIndicies.at(i) - 1));
   return temp_normals;
   });

   m_Model.m_Vertices = temp_vertices.get();
   m_Model.m_Textures = temp_uvs.get();
   m_Model.m_Normals = temp_normals.get();
}
<commit_msg>formatting indexing line for parser<commit_after>/*
MIT License

Copyright (c) 2017 Chris McArthur, prince.chrismc(at)gmail(dot)com

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

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

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

#include "Loader.h"
#include <sstream>
#include <future>

void Obj::Loader::ExtractData()
{
   /// This code can NOT be parallelized because the order needs to be maintained
   for (auto line : m_File.m_Lines)
   {
      switch (line.at(0))
      {
      case 'v':
         switch (line.at(1))
         {
         case ' ': ExtractVertice(line.substr((size_t)Offset::VERTICE)); break;
         case 'n': ExtractNormal(line.substr((size_t)Offset::NORMAL)); break;
         case 't': ExtractTexture(line.substr((size_t)Offset::TEXTURE)); break;
         default:
            break;
         }
         break;
      case 'f': m_Indicies.emplace_back(line.substr((size_t)Offset::INDEX)); break;
      default:
         break;
      }
   }

   ExtractIndexing();
}

void Obj::Loader::ExtractVertice(const std::string & line)
{
   float buffer[3];
   std::stringstream ss(line);
   for (int i = 0; i < 3; i++)
      ss >> buffer[i];

   m_Model.m_Vertices.emplace_back(buffer[0], buffer[1], buffer[2]);
}

void Obj::Loader::ExtractNormal(const std::string & line)
{
   float buffer[3];
   std::stringstream ss(line);;
   for (int i = 0; i < 3; i++)
      ss >> buffer[i];

   m_Model.m_Normals.emplace_back(buffer[0], buffer[1], buffer[2]);
}

void Obj::Loader::ExtractTexture(const std::string & line)
{
   float buffer[2];
   std::stringstream ss(line);
   for (int i = 0; i < 2; i++)
      ss >> buffer[i];

   m_Model.m_Textures.emplace_back(buffer[0], buffer[1]);
}

void Obj::Loader::ExtractIndexing()
{
   for (auto line : m_Indicies)
   {
      std::replace(line.begin(), line.end(), '/', ' ');
      std::stringstream ss(line);
      unsigned int vertex_index[3], uv_index[3], normal_index[3];
      for (int i = 0; i < 3; i++)
      {
         ss >> vertex_index[i];
         ss >> uv_index[i];
         ss >> normal_index[i];
      }

      for (auto vertex : vertex_index) m_VerticeIndicies.push_back(vertex);
      for (auto uv : uv_index) m_TextureIndicies.push_back(uv);
      for (auto normal : normal_index) m_NormalsIndicies.push_back(normal);
   }
}

void Obj::Loader::SortCoords()
{
   auto temp_vertices = std::async(std::launch::async, [this] {
      std::vector<glm::vec3> temp_vertices;
      for (unsigned int i = 0; i < m_VerticeIndicies.size(); i++)
         temp_vertices.push_back(m_Model.m_Vertices.at(m_VerticeIndicies.at(i) - 1));
      return temp_vertices;
   });

   auto temp_uvs = std::async(std::launch::async, [this] {
   std::vector<glm::vec2> temp_uvs;
   for (unsigned int i = 0; i < m_TextureIndicies.size(); i++)
      temp_uvs.push_back(m_Model.m_Textures.at(m_TextureIndicies.at(i) - 1));
   return temp_uvs;
   });

   auto temp_normals = std::async(std::launch::async, [this] {
   std::vector<glm::vec3> temp_normals;
   for (unsigned int i = 0; i < m_NormalsIndicies.size(); i++)
      temp_normals.push_back(m_Model.m_Normals.at(m_NormalsIndicies.at(i) - 1));
   return temp_normals;
   });

   m_Model.m_Vertices = temp_vertices.get();
   m_Model.m_Textures = temp_uvs.get();
   m_Model.m_Normals = temp_normals.get();
}
<|endoftext|>


<commit_before>//-----------------------------------------------
//
//	This file is part of the Siv3D Engine.
//
//	Copyright (c) 2008-2019 Ryo Suzuki
//	Copyright (c) 2016-2019 OpenSiv3D Project
//
//	Licensed under the MIT License.
//
//-----------------------------------------------

# include <string>

# define __STDC_CONSTANT_MACROS
extern "C"
{
# include <libavformat/avformat.h>
# include <libavcodec/avcodec.h>
# include <libavutil/avutil.h>
# include <libswresample/swresample.h>
}

# include <Siv3D/EngineLog.hpp>

# include "AudioFormat_AAC.hpp"

namespace s3d
{
	namespace detail
	{
		class AACDecoder
		{
		private:
			AVFormatContext* m_format_context = nullptr;
			AVCodecContext* m_codec_context = nullptr;
			AVFrame* m_frame = nullptr;
			AVPacket* m_packet = nullptr;
			struct SwrContext* m_swr_context = nullptr;
			uint8_t* m_out_buf = nullptr;

			AVStream* m_audio_stream = nullptr;
			int m_audio_stream_idx = 0;
			AVCodec* m_codec = nullptr;
			int m_out_count = 0;
			int m_out_sample_rate = 0;
			int64_t m_duration = 0;
			size_t m_wave_idx = 0;

			FilePath m_path;

			void setSample(Wave& wave, float* buf, size_t idx, size_t count)
			{
				WaveSample sample;
				for (size_t i = 0; i < count; ++i)
				{
					sample.set(buf[0], buf[1]);

					if (idx < wave.size())
						wave[idx] = sample;
					else
						wave.push_back(sample);

					buf += 2;
					idx++;
				}
			}

			bool decode_by_avcodec(Wave& wave, bool do_flush)
			{
				int ret;

				ret = avcodec_send_packet(m_codec_context, (do_flush ? nullptr : m_packet));
				if (ret < 0)
				{
					LOG_FAIL(U"AACDecoder: load() failed (avcodec_send_packet()) ({})"_fmt(m_path));
					return false;
				}

				while (avcodec_receive_frame(m_codec_context, m_frame) == 0)
				{
					ret = swr_convert(m_swr_context, &m_out_buf, m_out_count,
							(const uint8_t**)(m_frame->data), m_frame->nb_samples);
					if (ret < 0)
					{
						LOG_FAIL(U"AACDecoder: load() failed (avcodec_receive_frame()) ({})"_fmt(m_path));
						return false;
					}

					setSample(wave, (float*)m_out_buf, m_wave_idx, ret);
					m_wave_idx += ret;
				}

				return true;
			}

		public:
			~AACDecoder()
			{
				if (m_out_buf != nullptr)
					av_free(m_out_buf);
				if (m_swr_context != nullptr)
					swr_free(&m_swr_context);
				if (m_frame != nullptr)
					av_frame_free(&m_frame);
				if (m_packet != nullptr)
					av_packet_free(&m_packet);
				if (m_codec_context != nullptr)
					avcodec_free_context(&m_codec_context);
				if (m_format_context != nullptr)
					avformat_close_input(&m_format_context);
			}

			bool init(const FilePath& path)
			{
				const std::string pathUTF8 = path.toUTF8();
				const char* path_char = pathUTF8.c_str();

				m_path = path;

				// open file.
				if (avformat_open_input(&m_format_context, path_char, nullptr, nullptr) != 0)
				{
					LOG_DEBUG(U"AACDecoder: avformat_open_input() failed ({}})"_fmt(m_path));
					return false;
				}

				if (avformat_find_stream_info(m_format_context, nullptr) < 0)
				{
					LOG_DEBUG(U"AACDecoder: avformat_find_stream_info() failed ({})"_fmt(m_path));
					return false;
				}

				// search audio stream
				for (size_t i = 0; i < m_format_context->nb_streams; ++i)
				{
					if (m_format_context->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
					{
						m_audio_stream = m_format_context->streams[i];
						m_audio_stream_idx = i;
						break;
					}
				}
				if (m_audio_stream == nullptr)
				{
					LOG_DEBUG(U"AACDecoder: There are no audio stream ({})"_fmt(m_path));
					return false;
				}
				m_duration = m_audio_stream->duration;

				// setup codec.
				m_codec = avcodec_find_decoder(m_audio_stream->codecpar->codec_id);
				if (m_codec == nullptr)
				{
					LOG_DEBUG(U"AACDecoder: avcodec_find_decoder() failed ({})"_fmt(m_path));
					return false;
				}
				m_codec_context = avcodec_alloc_context3(m_codec);
				if (m_codec_context == nullptr)
				{
					LOG_DEBUG(U"AACDecoder: avcodec_alloc_context3() failed ({})"_fmt(m_path));
					return false;
				}
				if (avcodec_parameters_to_context(m_codec_context, m_audio_stream->codecpar) < 0)
				{
					LOG_DEBUG(U"AACDecoder: avcodec_parameters_to_context() failed ({})"_fmt(m_path));
					return false;
				}
				if (avcodec_open2(m_codec_context, m_codec, nullptr) != 0)
				{
					LOG_DEBUG(U"AACDecoder: avcodec_open2() failed ({})"_fmt(m_path));
					return false;
				}

				// allocate packet
				m_packet = (AVPacket*)av_malloc(sizeof(AVPacket));
				if (m_packet == nullptr)
				{
					LOG_DEBUG(U"AACDecoder: av_malloc() failed (packet) ({})"_fmt(m_path));
					return false;
				}
				av_init_packet(m_packet);

				// allocate frame
				m_frame = av_frame_alloc();
				if (m_frame == nullptr)
				{
					LOG_DEBUG(U"AACDecoder: av_frame_alloc() failed ({})"_fmt(m_path));
					return false;
				}

				// initialize swr context
				int64_t out_channel_layout = AV_CH_LAYOUT_STEREO;
				int out_nb_samples = m_codec_context->frame_size;
				AVSampleFormat out_sample_fmt = AV_SAMPLE_FMT_FLT;
				m_out_sample_rate = m_codec_context->sample_rate;
				m_swr_context = swr_alloc_set_opts(m_swr_context,
						out_channel_layout, out_sample_fmt, m_out_sample_rate,
						av_get_default_channel_layout(m_codec_context->channels),
						m_codec_context->sample_fmt, m_codec_context->sample_rate, 0, nullptr);
				if (m_swr_context == nullptr)
				{
					LOG_DEBUG(U"AACDecoder: swr_alloc() failed ({})"_fmt(m_path));
					return false;
				}
				int averr = swr_init(m_swr_context);
				if (swr_is_initialized(m_swr_context) == 0)
				{
					LOG_DEBUG(U"AACDecoder: swr_init() failed (AVERROR: {}) ({})"_fmt(Unicode::Widen(av_err2str(averr)), m_path));
					return false;
				}

				// allocate output buffer
				int out_nb_channels = av_get_channel_layout_nb_channels(out_channel_layout);
				int buf_size = av_samples_get_buffer_size(nullptr,
						out_nb_channels, out_nb_samples, out_sample_fmt, 0);
				m_out_buf = (uint8_t*)av_malloc(buf_size);
				if (m_out_buf == nullptr)
				{
					LOG_DEBUG(U"AACDecoder: av_malloc() failed (m_out_buf) ({})"_fmt(m_path));
					return false;
				}

				m_out_count = buf_size / out_nb_channels;

				return true;
			}

			Wave load()
			{
				Wave wave(m_duration, Arg::samplingRate = static_cast<uint32>(m_out_sample_rate));

				while (0 <= av_read_frame(m_format_context, m_packet))
				{
					if (m_packet->stream_index == m_audio_stream_idx)
					{
						if(!decode_by_avcodec(wave, false))
							return Wave();
					}
					av_packet_unref(m_packet);
				}

				// flush decoder
				if(!decode_by_avcodec(wave, true))
					return Wave();

				wave.resize(m_wave_idx);
				return wave;
			}
		};
	}

	AudioFormat_AAC::AudioFormat_AAC()
	{

	}

	AudioFormat_AAC::~AudioFormat_AAC()
	{

	}

	AudioFormat AudioFormat_AAC::format() const
	{
		return AudioFormat::AAC;
	}

	const Array<String>& AudioFormat_AAC::possibleExtexsions() const
	{
		static const Array<String> extensions = { U"m4a" };

		return extensions;
	}

	bool AudioFormat_AAC::isHeader(const uint8(&bytes)[16], const IReader&) const
	{
		// M4V MPEG-4 video/QuickTime file
		static constexpr uint8 M4V_SIGNx[] = { 0x66, 0x74, 0x79, 0x70, 0x6D, 0x70, 0x34, 0x32 };

		// M4A Apple Lossless Audio Codec file
		static constexpr uint8 M4A_SIGNx[] = { 0x66, 0x74, 0x79, 0x70, 0x4D, 0x34, 0x41, 0x20 };

		// MP4 ftypisom
		static constexpr uint8 MP4ISOM_SIGNx[] = { 0x66, 0x74, 0x79, 0x70, 0x69, 0x73, 0x6F, 0x6D };

		return (::memcmp(bytes + 4, M4V_SIGNx, sizeof(M4V_SIGNx)) == 0
				|| ::memcmp(bytes + 4, M4A_SIGNx, sizeof(M4A_SIGNx)) == 0
				|| ::memcmp(bytes + 4, MP4ISOM_SIGNx, sizeof(MP4ISOM_SIGNx)) == 0);
	}

	Wave AudioFormat_AAC::decodeFromFile(const FilePath& path) const
	{
		detail::AACDecoder decoder;

		if (!decoder.init(path))
		{
			LOG_FAIL(U"AACDecoder: init() failed.\n");
			return Wave();
		}

		return decoder.load();
	}

	Wave AudioFormat_AAC::decode(IReader&) const
	{
		// not supported
		return Wave();
	}
}
<commit_msg>AudioFormat_AAC.cppをGCCでコンパイルするとエラーが出る問題を修正<commit_after>//-----------------------------------------------
//
//	This file is part of the Siv3D Engine.
//
//	Copyright (c) 2008-2019 Ryo Suzuki
//	Copyright (c) 2016-2019 OpenSiv3D Project
//
//	Licensed under the MIT License.
//
//-----------------------------------------------

# include <string>

# define __STDC_CONSTANT_MACROS
extern "C"
{
# include <libavformat/avformat.h>
# include <libavcodec/avcodec.h>
# include <libavutil/avutil.h>
# include <libswresample/swresample.h>
}

// https://ffmpeg.org/pipermail/libav-user/2013-January/003458.html
#undef av_err2str
#define av_err2str(errnum) av_make_error_string((char*)__builtin_alloca(AV_ERROR_MAX_STRING_SIZE), AV_ERROR_MAX_STRING_SIZE, errnum)

# include <Siv3D/EngineLog.hpp>

# include "AudioFormat_AAC.hpp"

namespace s3d
{
	namespace detail
	{
		class AACDecoder
		{
		private:
			AVFormatContext* m_format_context = nullptr;
			AVCodecContext* m_codec_context = nullptr;
			AVFrame* m_frame = nullptr;
			AVPacket* m_packet = nullptr;
			struct SwrContext* m_swr_context = nullptr;
			uint8_t* m_out_buf = nullptr;

			AVStream* m_audio_stream = nullptr;
			int m_audio_stream_idx = 0;
			AVCodec* m_codec = nullptr;
			int m_out_count = 0;
			int m_out_sample_rate = 0;
			int64_t m_duration = 0;
			size_t m_wave_idx = 0;

			FilePath m_path;

			void setSample(Wave& wave, float* buf, size_t idx, size_t count)
			{
				WaveSample sample;
				for (size_t i = 0; i < count; ++i)
				{
					sample.set(buf[0], buf[1]);

					if (idx < wave.size())
						wave[idx] = sample;
					else
						wave.push_back(sample);

					buf += 2;
					idx++;
				}
			}

			bool decode_by_avcodec(Wave& wave, bool do_flush)
			{
				int ret;

				ret = avcodec_send_packet(m_codec_context, (do_flush ? nullptr : m_packet));
				if (ret < 0)
				{
					LOG_FAIL(U"AACDecoder: load() failed (avcodec_send_packet()) ({})"_fmt(m_path));
					return false;
				}

				while (avcodec_receive_frame(m_codec_context, m_frame) == 0)
				{
					ret = swr_convert(m_swr_context, &m_out_buf, m_out_count,
							(const uint8_t**)(m_frame->data), m_frame->nb_samples);
					if (ret < 0)
					{
						LOG_FAIL(U"AACDecoder: load() failed (avcodec_receive_frame()) ({})"_fmt(m_path));
						return false;
					}

					setSample(wave, (float*)m_out_buf, m_wave_idx, ret);
					m_wave_idx += ret;
				}

				return true;
			}

		public:
			~AACDecoder()
			{
				if (m_out_buf != nullptr)
					av_free(m_out_buf);
				if (m_swr_context != nullptr)
					swr_free(&m_swr_context);
				if (m_frame != nullptr)
					av_frame_free(&m_frame);
				if (m_packet != nullptr)
					av_packet_free(&m_packet);
				if (m_codec_context != nullptr)
					avcodec_free_context(&m_codec_context);
				if (m_format_context != nullptr)
					avformat_close_input(&m_format_context);
			}

			bool init(const FilePath& path)
			{
				const std::string pathUTF8 = path.toUTF8();
				const char* path_char = pathUTF8.c_str();

				m_path = path;

				// open file.
				if (avformat_open_input(&m_format_context, path_char, nullptr, nullptr) != 0)
				{
					LOG_DEBUG(U"AACDecoder: avformat_open_input() failed ({}})"_fmt(m_path));
					return false;
				}

				if (avformat_find_stream_info(m_format_context, nullptr) < 0)
				{
					LOG_DEBUG(U"AACDecoder: avformat_find_stream_info() failed ({})"_fmt(m_path));
					return false;
				}

				// search audio stream
				for (size_t i = 0; i < m_format_context->nb_streams; ++i)
				{
					if (m_format_context->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
					{
						m_audio_stream = m_format_context->streams[i];
						m_audio_stream_idx = i;
						break;
					}
				}
				if (m_audio_stream == nullptr)
				{
					LOG_DEBUG(U"AACDecoder: There are no audio stream ({})"_fmt(m_path));
					return false;
				}
				m_duration = m_audio_stream->duration;

				// setup codec.
				m_codec = avcodec_find_decoder(m_audio_stream->codecpar->codec_id);
				if (m_codec == nullptr)
				{
					LOG_DEBUG(U"AACDecoder: avcodec_find_decoder() failed ({})"_fmt(m_path));
					return false;
				}
				m_codec_context = avcodec_alloc_context3(m_codec);
				if (m_codec_context == nullptr)
				{
					LOG_DEBUG(U"AACDecoder: avcodec_alloc_context3() failed ({})"_fmt(m_path));
					return false;
				}
				if (avcodec_parameters_to_context(m_codec_context, m_audio_stream->codecpar) < 0)
				{
					LOG_DEBUG(U"AACDecoder: avcodec_parameters_to_context() failed ({})"_fmt(m_path));
					return false;
				}
				if (avcodec_open2(m_codec_context, m_codec, nullptr) != 0)
				{
					LOG_DEBUG(U"AACDecoder: avcodec_open2() failed ({})"_fmt(m_path));
					return false;
				}

				// allocate packet
				m_packet = (AVPacket*)av_malloc(sizeof(AVPacket));
				if (m_packet == nullptr)
				{
					LOG_DEBUG(U"AACDecoder: av_malloc() failed (packet) ({})"_fmt(m_path));
					return false;
				}
				av_init_packet(m_packet);

				// allocate frame
				m_frame = av_frame_alloc();
				if (m_frame == nullptr)
				{
					LOG_DEBUG(U"AACDecoder: av_frame_alloc() failed ({})"_fmt(m_path));
					return false;
				}

				// initialize swr context
				int64_t out_channel_layout = AV_CH_LAYOUT_STEREO;
				int out_nb_samples = m_codec_context->frame_size;
				AVSampleFormat out_sample_fmt = AV_SAMPLE_FMT_FLT;
				m_out_sample_rate = m_codec_context->sample_rate;
				m_swr_context = swr_alloc_set_opts(m_swr_context,
						out_channel_layout, out_sample_fmt, m_out_sample_rate,
						av_get_default_channel_layout(m_codec_context->channels),
						m_codec_context->sample_fmt, m_codec_context->sample_rate, 0, nullptr);
				if (m_swr_context == nullptr)
				{
					LOG_DEBUG(U"AACDecoder: swr_alloc() failed ({})"_fmt(m_path));
					return false;
				}
				int averr = swr_init(m_swr_context);
				if (swr_is_initialized(m_swr_context) == 0)
				{
					LOG_DEBUG(U"AACDecoder: swr_init() failed (AVERROR: {}) ({})"_fmt(Unicode::Widen(av_err2str(averr)), m_path));
					return false;
				}

				// allocate output buffer
				int out_nb_channels = av_get_channel_layout_nb_channels(out_channel_layout);
				int buf_size = av_samples_get_buffer_size(nullptr,
						out_nb_channels, out_nb_samples, out_sample_fmt, 0);
				m_out_buf = (uint8_t*)av_malloc(buf_size);
				if (m_out_buf == nullptr)
				{
					LOG_DEBUG(U"AACDecoder: av_malloc() failed (m_out_buf) ({})"_fmt(m_path));
					return false;
				}

				m_out_count = buf_size / out_nb_channels;

				return true;
			}

			Wave load()
			{
				Wave wave(m_duration, Arg::samplingRate = static_cast<uint32>(m_out_sample_rate));

				while (0 <= av_read_frame(m_format_context, m_packet))
				{
					if (m_packet->stream_index == m_audio_stream_idx)
					{
						if(!decode_by_avcodec(wave, false))
							return Wave();
					}
					av_packet_unref(m_packet);
				}

				// flush decoder
				if(!decode_by_avcodec(wave, true))
					return Wave();

				wave.resize(m_wave_idx);
				return wave;
			}
		};
	}

	AudioFormat_AAC::AudioFormat_AAC()
	{

	}

	AudioFormat_AAC::~AudioFormat_AAC()
	{

	}

	AudioFormat AudioFormat_AAC::format() const
	{
		return AudioFormat::AAC;
	}

	const Array<String>& AudioFormat_AAC::possibleExtexsions() const
	{
		static const Array<String> extensions = { U"m4a" };

		return extensions;
	}

	bool AudioFormat_AAC::isHeader(const uint8(&bytes)[16], const IReader&) const
	{
		// M4V MPEG-4 video/QuickTime file
		static constexpr uint8 M4V_SIGNx[] = { 0x66, 0x74, 0x79, 0x70, 0x6D, 0x70, 0x34, 0x32 };

		// M4A Apple Lossless Audio Codec file
		static constexpr uint8 M4A_SIGNx[] = { 0x66, 0x74, 0x79, 0x70, 0x4D, 0x34, 0x41, 0x20 };

		// MP4 ftypisom
		static constexpr uint8 MP4ISOM_SIGNx[] = { 0x66, 0x74, 0x79, 0x70, 0x69, 0x73, 0x6F, 0x6D };

		return (::memcmp(bytes + 4, M4V_SIGNx, sizeof(M4V_SIGNx)) == 0
				|| ::memcmp(bytes + 4, M4A_SIGNx, sizeof(M4A_SIGNx)) == 0
				|| ::memcmp(bytes + 4, MP4ISOM_SIGNx, sizeof(MP4ISOM_SIGNx)) == 0);
	}

	Wave AudioFormat_AAC::decodeFromFile(const FilePath& path) const
	{
		detail::AACDecoder decoder;

		if (!decoder.init(path))
		{
			LOG_FAIL(U"AACDecoder: init() failed.\n");
			return Wave();
		}

		return decoder.load();
	}

	Wave AudioFormat_AAC::decode(IReader&) const
	{
		// not supported
		return Wave();
	}
}
<|endoftext|>


<commit_before>// The libMesh Finite Element Library.
// Copyright (C) 2002-2012 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

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

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// 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

// C++ includes
#include <iostream>
#include <iomanip> // for std::setw, std::setiosflags

// Local includes
#include "libmesh/type_tensor.h"

namespace libMesh
{

// ------------------------------------------------------------
// TypeTensor<T> class member funcions

template <typename T>
void TypeTensor<T>::print(std::ostream& os) const
{
#if LIBMESH_DIM == 1

  os << "x=" << (*this)(0,0) << std::endl;

#endif
#if LIBMESH_DIM == 2

  os << "(xx,xy)=("
     << std::setw(8) << (*this)(0,0) << ", "
     << std::setw(8) << (*this)(0,1) << ")"
     << std::endl;
  os << "(yx,yy)=("
     << std::setw(8) << (*this)(1,0) << ", "
     << std::setw(8) << (*this)(1,1) << ")"
     << std::endl;

#endif
#if LIBMESH_DIM == 3

  os <<  "(xx,xy,xz)=("
     << std::setw(8) << (*this)(0,0) << ", "
     << std::setw(8) << (*this)(0,1) << ", "
     << std::setw(8) << (*this)(0,2) << ")"
     << std::endl;
  os <<  "(yx,yy,yz)=("
     << std::setw(8) << (*this)(1,0) << ", "
     << std::setw(8) << (*this)(1,1) << ", "
     << std::setw(8) << (*this)(1,2) << ")"
     << std::endl;
  os <<  "(zx,zy,zz)=("
     << std::setw(8) << (*this)(2,0) << ", "
     << std::setw(8) << (*this)(2,1) << ", "
     << std::setw(8) << (*this)(2,2) << ")"
     << std::endl;
#endif
}

template <typename T>
void TypeTensor<T>::write_unformatted (std::ostream &out,
				       const bool newline) const
{
  libmesh_assert (out);

  out << std::setiosflags(std::ios::showpoint)
      << (*this)(0,0) << " "
      << (*this)(0,1) << " "
      << (*this)(0,2) << " ";
  if (newline)
    out << '\n';

  out << std::setiosflags(std::ios::showpoint)
      << (*this)(1,0) << " "
      << (*this)(1,1) << " "
      << (*this)(1,2) << " ";
  if (newline)
    out << '\n';

  out << std::setiosflags(std::ios::showpoint)
      << (*this)(2,0) << " "
      << (*this)(2,1) << " "
      << (*this)(2,2) << " ";
  if (newline)
    out << '\n';
}

template <>
bool TypeTensor<Real>::operator < (const TypeTensor<Real>& rhs) const
{
  for (unsigned int i=0; i<LIBMESH_DIM; i++)
    for (unsigned int j=0; j<LIBMESH_DIM; j++)
      {
        if ((*this)(i,j) < rhs(i,j))
          return true;
        if ((*this)(i,j) > rhs(i,j))
          return false;
      }
  return false;
}

template <>
bool TypeTensor<Real>::operator > (const TypeTensor<Real>& rhs) const
{
  for (unsigned int i=0; i<LIBMESH_DIM; i++)
    for (unsigned int j=0; j<LIBMESH_DIM; j++)
      {
        if ((*this)(i,j) > rhs(i,j))
          return true;
        if ((*this)(i,j) < rhs(i,j))
          return false;
      }
  return false;
}

#ifdef LIBMESH_USE_COMPLEX_NUMBERS
template <>
bool TypeTensor<Complex>::operator < (const TypeTensor<Complex>& rhs) const
{
  for (unsigned int i=0; i<LIBMESH_DIM; i++)
    for (unsigned int j=0; j<LIBMESH_DIM; j++)
      {
        if ((*this)(i,j).real() < rhs(i,j).real())
          return true;
        if ((*this)(i,j).real() > rhs(i,j).real())
          return false;
        if ((*this)(i,j).imag() < rhs(i,j).imag())
          return true;
        if ((*this)(i,j).imag() > rhs(i,j).imag())
          return false;
      }
  return false;
}

template <>
bool TypeTensor<Complex>::operator > (const TypeTensor<Complex>& rhs) const
{
  for (unsigned int i=0; i<LIBMESH_DIM; i++)
    for (unsigned int j=0; j<LIBMESH_DIM; j++)
      {
        if ((*this)(i,j).real() > rhs(i,j).real())
          return true;
        if ((*this)(i,j).real() < rhs(i,j).real())
          return false;
        if ((*this)(i,j).imag() > rhs(i,j).imag())
          return true;
        if ((*this)(i,j).imag() < rhs(i,j).imag())
          return false;
      }
  return false;
}

#endif

// ------------------------------------------------------------
// Explicit instantiations
template class TypeTensor<Real>;

#ifdef LIBMESH_USE_COMPLEX_NUMBERS
template class TypeTensor<Complex>;
#endif

} // namespace libMesh
<commit_msg>Changes in type_tensor.C for -Wshadow.<commit_after>// The libMesh Finite Element Library.
// Copyright (C) 2002-2012 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

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

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// 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

// C++ includes
#include <iostream>
#include <iomanip> // for std::setw, std::setiosflags

// Local includes
#include "libmesh/type_tensor.h"

namespace libMesh
{

// ------------------------------------------------------------
// TypeTensor<T> class member funcions

template <typename T>
void TypeTensor<T>::print(std::ostream& os) const
{
#if LIBMESH_DIM == 1

  os << "x=" << (*this)(0,0) << std::endl;

#endif
#if LIBMESH_DIM == 2

  os << "(xx,xy)=("
     << std::setw(8) << (*this)(0,0) << ", "
     << std::setw(8) << (*this)(0,1) << ")"
     << std::endl;
  os << "(yx,yy)=("
     << std::setw(8) << (*this)(1,0) << ", "
     << std::setw(8) << (*this)(1,1) << ")"
     << std::endl;

#endif
#if LIBMESH_DIM == 3

  os <<  "(xx,xy,xz)=("
     << std::setw(8) << (*this)(0,0) << ", "
     << std::setw(8) << (*this)(0,1) << ", "
     << std::setw(8) << (*this)(0,2) << ")"
     << std::endl;
  os <<  "(yx,yy,yz)=("
     << std::setw(8) << (*this)(1,0) << ", "
     << std::setw(8) << (*this)(1,1) << ", "
     << std::setw(8) << (*this)(1,2) << ")"
     << std::endl;
  os <<  "(zx,zy,zz)=("
     << std::setw(8) << (*this)(2,0) << ", "
     << std::setw(8) << (*this)(2,1) << ", "
     << std::setw(8) << (*this)(2,2) << ")"
     << std::endl;
#endif
}

template <typename T>
void TypeTensor<T>::write_unformatted (std::ostream &out_stream,
				       const bool newline) const
{
  libmesh_assert (out_stream);

  out_stream << std::setiosflags(std::ios::showpoint)
      << (*this)(0,0) << " "
      << (*this)(0,1) << " "
      << (*this)(0,2) << " ";
  if (newline)
    out_stream << '\n';

  out_stream << std::setiosflags(std::ios::showpoint)
      << (*this)(1,0) << " "
      << (*this)(1,1) << " "
      << (*this)(1,2) << " ";
  if (newline)
    out_stream << '\n';

  out_stream << std::setiosflags(std::ios::showpoint)
      << (*this)(2,0) << " "
      << (*this)(2,1) << " "
      << (*this)(2,2) << " ";
  if (newline)
    out_stream << '\n';
}

template <>
bool TypeTensor<Real>::operator < (const TypeTensor<Real>& rhs) const
{
  for (unsigned int i=0; i<LIBMESH_DIM; i++)
    for (unsigned int j=0; j<LIBMESH_DIM; j++)
      {
        if ((*this)(i,j) < rhs(i,j))
          return true;
        if ((*this)(i,j) > rhs(i,j))
          return false;
      }
  return false;
}

template <>
bool TypeTensor<Real>::operator > (const TypeTensor<Real>& rhs) const
{
  for (unsigned int i=0; i<LIBMESH_DIM; i++)
    for (unsigned int j=0; j<LIBMESH_DIM; j++)
      {
        if ((*this)(i,j) > rhs(i,j))
          return true;
        if ((*this)(i,j) < rhs(i,j))
          return false;
      }
  return false;
}

#ifdef LIBMESH_USE_COMPLEX_NUMBERS
template <>
bool TypeTensor<Complex>::operator < (const TypeTensor<Complex>& rhs) const
{
  for (unsigned int i=0; i<LIBMESH_DIM; i++)
    for (unsigned int j=0; j<LIBMESH_DIM; j++)
      {
        if ((*this)(i,j).real() < rhs(i,j).real())
          return true;
        if ((*this)(i,j).real() > rhs(i,j).real())
          return false;
        if ((*this)(i,j).imag() < rhs(i,j).imag())
          return true;
        if ((*this)(i,j).imag() > rhs(i,j).imag())
          return false;
      }
  return false;
}

template <>
bool TypeTensor<Complex>::operator > (const TypeTensor<Complex>& rhs) const
{
  for (unsigned int i=0; i<LIBMESH_DIM; i++)
    for (unsigned int j=0; j<LIBMESH_DIM; j++)
      {
        if ((*this)(i,j).real() > rhs(i,j).real())
          return true;
        if ((*this)(i,j).real() < rhs(i,j).real())
          return false;
        if ((*this)(i,j).imag() > rhs(i,j).imag())
          return true;
        if ((*this)(i,j).imag() < rhs(i,j).imag())
          return false;
      }
  return false;
}

#endif

// ------------------------------------------------------------
// Explicit instantiations
template class TypeTensor<Real>;

#ifdef LIBMESH_USE_COMPLEX_NUMBERS
template class TypeTensor<Complex>;
#endif

} // namespace libMesh
<|endoftext|>


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

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkCannyEdgeDetectionImageFilterTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/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 notices for more information.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#include <iostream>
#include "itkImage.h"
#include "itkCannyEdgeDetectionImageFilter.h"
#include "itkNullImageToImageFilterDriver.txx"
#include "itkVector.h"
#include "itkFilterWatcher.h"

int itkCannyEdgeDetectionImageFilterTest(int , char * [] )
{
  try
    {
      typedef itk::Image<float, 2> ImageType;

      // Set up filter
      itk::CannyEdgeDetectionImageFilter<ImageType, ImageType>::Pointer
        filter =
        itk::CannyEdgeDetectionImageFilter<ImageType, ImageType>::New();
      filter->DebugOn();
      FilterWatcher watcher(filter);
      filter->SetThreshold(5);
      filter->SetUpperThreshold(30);
      filter->SetLowerThreshold(10);
      filter->SetVariance(1.0f);
      filter->SetMaximumError(.01f);
      std::cout << "filter: " << filter;

      // Run Test
      itk::Size<2> sz;
      sz[0] = 100 ; //atoi(argv[1]);
      sz[1] = 100 ; // atoi(argv[2]);
      //      sz[2] = 10;//atoi(argv[3]);
      //      sz[3] = 5;//atoi(argv[4]);
      itk::NullImageToImageFilterDriver< ImageType, ImageType > test1;
      test1.SetImageSize(sz);
      test1.SetFilter(filter.GetPointer());
      test1.Execute();
    }
  catch(itk::ExceptionObject &err)
    {
      (&err)->Print(std::cerr);
      return 1;
    }
  return 0;
}
<commit_msg>BUG: revert ack to original parameters.<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkCannyEdgeDetectionImageFilterTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/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 notices for more information.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#include <iostream>
#include "itkImage.h"
#include "itkCannyEdgeDetectionImageFilter.h"
#include "itkNullImageToImageFilterDriver.txx"
#include "itkVector.h"
#include "itkFilterWatcher.h"

int itkCannyEdgeDetectionImageFilterTest(int , char * [] )
{
  try
    {
      typedef itk::Image<float, 2> ImageType;

      // Set up filter
      itk::CannyEdgeDetectionImageFilter<ImageType, ImageType>::Pointer
        filter =
        itk::CannyEdgeDetectionImageFilter<ImageType, ImageType>::New();
      filter->DebugOn();
      FilterWatcher watcher(filter);
      filter->SetUpperThreshold(30);
      filter->SetLowerThreshold(10);
      filter->SetThreshold(0);
      filter->SetVariance(1.0f);
      filter->SetMaximumError(.01f);
      std::cout << "filter: " << filter;

      // Run Test
      itk::Size<2> sz;
      sz[0] = 100 ; //atoi(argv[1]);
      sz[1] = 100 ; // atoi(argv[2]);
      //      sz[2] = 10;//atoi(argv[3]);
      //      sz[3] = 5;//atoi(argv[4]);
      itk::NullImageToImageFilterDriver< ImageType, ImageType > test1;
      test1.SetImageSize(sz);
      test1.SetFilter(filter.GetPointer());
      test1.Execute();
    }
  catch(itk::ExceptionObject &err)
    {
      (&err)->Print(std::cerr);
      return 1;
    }
  return 0;
}
<|endoftext|>


<commit_before>/* BZWorkbench
 * Copyright (c) 1993 - 2008 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#include "objects/waterLevel.h"

#include "objects/material.h"

waterLevel::waterLevel() : DataEntry("waterLevel", "<name><height><matref>") {
	name = string("");
	waterMaterial = NULL;
	height = -1.0f;
}

// get method
string waterLevel::get(void) {
	return toString();
}

// bzw methods
bool waterLevel::parse( std::string& line ) {
	// check if we reached the end of the section
	if ( line == "end" )
		return false;

	string key = BZWParser::key( line.c_str() );
	string value = BZWParser::value( key.c_str(), line.c_str() );

	if ( key == "name" ) {
		name = value;
	}
	else if ( key == "matref" ) {
		material* mat = (material*)Model::command( MODEL_GET, "material", value );
		if( mat )
			waterMaterial = mat;
		else
			throw BZWReadError( this, string( "Couldn't find material, " ) + value );

	}
	else if ( key == "height" ) {
		height = atof( value.c_str() );
	}
	else {
		throw BZWReadError( this, string( "Unknown key, " ) + key );
	}

	return true;
}

void waterLevel::finalize() {

}

// toString method
string waterLevel::toString(void) {
	string waterLevelStr = string(ftoa(height));

	return string(string("waterLevel\n") +
						 "  name " + name + "\n" +
						 "  height " + waterLevelStr + "\n" +
						 waterMaterial->getName() +
						 getUnusedText() +
						 "end\n");
}

waterLevel::~waterLevel() { }
<commit_msg>- fixed crash when calling waterLevel::toString: added test if waterMaterial is null before trying to getName() - fixed output of waterLevel::toString - added default waterLevel name = "water"<commit_after>/* BZWorkbench
 * Copyright (c) 1993 - 2008 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#include "objects/waterLevel.h"

#include "objects/material.h"

waterLevel::waterLevel() : DataEntry("waterLevel", "<name><height><matref>") {
	name = string("water");
	waterMaterial = NULL;
	height = -1.0f;
}

// get method
string waterLevel::get(void) {
	return toString();
}

// bzw methods
bool waterLevel::parse( std::string& line ) {
	// check if we reached the end of the section
	if ( line == "end" )
		return false;

	string key = BZWParser::key( line.c_str() );
	string value = BZWParser::value( key.c_str(), line.c_str() );

	if ( key == "name" ) {
		name = value;
	}
	else if ( key == "matref" ) {
		material* mat = (material*)Model::command( MODEL_GET, "material", value );
		if( mat )
			waterMaterial = mat;
		else
			throw BZWReadError( this, string( "Couldn't find material, " ) + value );

	}
	else if ( key == "height" ) {
		height = atof( value.c_str() );
	}
	else {
		throw BZWReadError( this, string( "Unknown key, " ) + key );
	}

	return true;
}

void waterLevel::finalize() {

}

// toString method
string waterLevel::toString(void) {
	string waterLevelHeightStr = string("  height " + ftoa(height) + "\n" );
	string waterLevelMatStr = string("");
	if(waterMaterial != NULL){
		waterLevelMatStr = string("  matref " + waterMaterial->getName() + "\n" );
	}

	return string(string("waterLevel\n") +
						 "  name " + name + "\n" +
						 waterLevelHeightStr +
						 waterLevelMatStr +
						 getUnusedText() + "\n" +
						 "end\n");
}

waterLevel::~waterLevel() { }
<|endoftext|>


<commit_before>/*    Copyright (c) 2010-2019, Delft University of Technology
 *    All rigths reserved
 *
 *    This file is part of the Tudat. Redistribution and use in source and
 *    binary forms, with or without modification, are permitted exclusively
 *    under the terms of the Modified BSD license. You should have received
 *    a copy of the license with this file. If not, please or visit:
 *    http://tudat.tudelft.nl/LICENSE.
 */

#include <boost/make_shared.hpp>

#include "Tudat/Astrodynamics/Propagators/stateTransitionMatrixInterface.h"

namespace tudat
{

namespace propagators
{

//! Function to reset the state transition and sensitivity matrix interpolators
void SingleArcCombinedStateTransitionAndSensitivityMatrixInterface::updateMatrixInterpolators(
        const std::shared_ptr< interpolators::OneDimensionalInterpolator< double, Eigen::MatrixXd > >
        stateTransitionMatrixInterpolator,
        const std::shared_ptr< interpolators::OneDimensionalInterpolator< double, Eigen::MatrixXd > >
        sensitivityMatrixInterpolator,
        const std::vector< std::pair< int, int > >& statePartialAdditionIndices )
{
    stateTransitionMatrixInterpolator_ = stateTransitionMatrixInterpolator;
    sensitivityMatrixInterpolator_ = sensitivityMatrixInterpolator;
    statePartialAdditionIndices_ = statePartialAdditionIndices;
}

//! Function to get the concatenated state transition and sensitivity matrix at a given time.
Eigen::MatrixXd SingleArcCombinedStateTransitionAndSensitivityMatrixInterface::getCombinedStateTransitionAndSensitivityMatrix(
        const double evaluationTime )
{
    combinedStateTransitionMatrix_.setZero( );

    // Set Phi and S matrices.
    combinedStateTransitionMatrix_.block( 0, 0, stateTransitionMatrixSize_, stateTransitionMatrixSize_ ) =
            stateTransitionMatrixInterpolator_->interpolate( evaluationTime );

    if( sensitivityMatrixSize_ > 0 )
    {
        combinedStateTransitionMatrix_.block( 0, stateTransitionMatrixSize_, stateTransitionMatrixSize_, sensitivityMatrixSize_ ) =
                sensitivityMatrixInterpolator_->interpolate( evaluationTime );
    }

    for( unsigned int i = 0; i < statePartialAdditionIndices_.size( ); i++ )
    {
        combinedStateTransitionMatrix_.block( statePartialAdditionIndices_.at( i ).first, 0, 6, stateTransitionMatrixSize_ + sensitivityMatrixSize_ ) +=
                combinedStateTransitionMatrix_.block( statePartialAdditionIndices_.at( i ).second, 0, 6, stateTransitionMatrixSize_ + sensitivityMatrixSize_ );
    }

    return combinedStateTransitionMatrix_;
}

//! Constructor
MultiArcCombinedStateTransitionAndSensitivityMatrixInterface::MultiArcCombinedStateTransitionAndSensitivityMatrixInterface(
        const std::vector< std::shared_ptr< interpolators::OneDimensionalInterpolator< double, Eigen::MatrixXd > > >
        stateTransitionMatrixInterpolators,
        const std::vector< std::shared_ptr< interpolators::OneDimensionalInterpolator< double, Eigen::MatrixXd > > >
        sensitivityMatrixInterpolators,
        const std::vector< double >& arcStartTimes,
        const std::vector< double >& arcEndTimes,
        const int numberOfInitialDynamicalParameters,
        const int numberOfParameters,
        const std::vector< std::vector< std::pair< int, int > > >& statePartialAdditionIndices ):
    CombinedStateTransitionAndSensitivityMatrixInterface( numberOfInitialDynamicalParameters, numberOfParameters ),
    stateTransitionMatrixInterpolators_( stateTransitionMatrixInterpolators ),
    sensitivityMatrixInterpolators_( sensitivityMatrixInterpolators ),
    arcStartTimes_( arcStartTimes ),
    arcEndTimes_( arcEndTimes ),
    statePartialAdditionIndices_( statePartialAdditionIndices )
{
    if( arcStartTimes_.size( ) != arcEndTimes_.size( ) )
    {
        throw std::runtime_error( "Error when making MultiArcCombinedStateTransitionAndSensitivityMatrixInterface, incompatible time lists" );
    }
    numberOfStateArcs_ = arcStartTimes_.size( );

    sensitivityMatrixSize_ = numberOfParameters - numberOfStateArcs_ * stateTransitionMatrixSize_;

    if( stateTransitionMatrixInterpolators_.size( ) != sensitivityMatrixInterpolators_.size( ) ||
            stateTransitionMatrixInterpolators_.size( ) != static_cast< unsigned int >( numberOfStateArcs_ ) )
    {
        throw std::runtime_error(
                    "Error when making multi arc state transition and sensitivity interface, vector sizes are inconsistent" );
    }

    std::vector< double > arcSplitTimes = arcStartTimes_;
    arcSplitTimes.push_back(  std::numeric_limits< double >::max( ));
    lookUpscheme_ = std::make_shared< interpolators::HuntingAlgorithmLookupScheme< double > >(
                arcSplitTimes );
}

//! Function to reset the state transition and sensitivity matrix interpolators
void MultiArcCombinedStateTransitionAndSensitivityMatrixInterface::updateMatrixInterpolators(
        const std::vector< std::shared_ptr< interpolators::OneDimensionalInterpolator< double, Eigen::MatrixXd > > >
        stateTransitionMatrixInterpolators,
        const std::vector< std::shared_ptr< interpolators::OneDimensionalInterpolator< double, Eigen::MatrixXd > > >
        sensitivityMatrixInterpolators,
        const std::vector< double >& arcStartTimes,
        const std::vector< double >& arcEndTimes,
        const std::vector< std::vector< std::pair< int, int > > >& statePartialAdditionIndices )
{
    stateTransitionMatrixInterpolators_ = stateTransitionMatrixInterpolators;
    sensitivityMatrixInterpolators_ = sensitivityMatrixInterpolators;
    arcStartTimes_ =  arcStartTimes;
    arcEndTimes_ = arcEndTimes;
    statePartialAdditionIndices_ = statePartialAdditionIndices;

    if( stateTransitionMatrixInterpolators_.size( ) != sensitivityMatrixInterpolators_.size( ) ||
            stateTransitionMatrixInterpolators_.size( ) != static_cast< unsigned int >( numberOfStateArcs_ ) )
    {
        throw std::runtime_error(
                    "Error when resetting multi arc state transition and sensitivity interface, vector sizes are inconsistent." );
    }

    std::vector< double > arcSplitTimes = arcStartTimes_;
    arcSplitTimes.push_back( std::numeric_limits< double >::max( ) );

    lookUpscheme_ = std::make_shared< interpolators::HuntingAlgorithmLookupScheme< double > >(
                arcSplitTimes );
}

//! Function to get the concatenated single-arc state transition and sensitivity matrix at a given time.
Eigen::MatrixXd MultiArcCombinedStateTransitionAndSensitivityMatrixInterface::getCombinedStateTransitionAndSensitivityMatrix(
        const double evaluationTime,
        const bool addCentralBodySensitivity )
{
    Eigen::MatrixXd combinedStateTransitionMatrix = Eigen::MatrixXd::Zero(
                stateTransitionMatrixSize_, stateTransitionMatrixSize_ + sensitivityMatrixSize_ );

    int currentArc = getCurrentArc( evaluationTime ).first;

    // Set Phi and S matrices.
    if( currentArc >= 0 )
    {
        combinedStateTransitionMatrix.block( 0, 0, stateTransitionMatrixSize_, stateTransitionMatrixSize_ ) =
                stateTransitionMatrixInterpolators_.at( currentArc )->interpolate( evaluationTime );
        combinedStateTransitionMatrix.block( 0, stateTransitionMatrixSize_, stateTransitionMatrixSize_, sensitivityMatrixSize_ ) =
                sensitivityMatrixInterpolators_.at( currentArc )->interpolate( evaluationTime );

        for( unsigned int i = 0; i < statePartialAdditionIndices_.at( currentArc ).size( ); i++ )
        {
            int indicesToAdd = addCentralBodySensitivity ?
                        ( stateTransitionMatrixSize_ + sensitivityMatrixSize_ ) : stateTransitionMatrixSize_;
            combinedStateTransitionMatrix.block(
                        statePartialAdditionIndices_.at( currentArc ).at( i ).first, 0, 6, indicesToAdd ) +=
                    combinedStateTransitionMatrix.block(
                        statePartialAdditionIndices_.at( currentArc ).at( i ).second, 0, 6, indicesToAdd );
        }
    }
    return combinedStateTransitionMatrix;
}

//! Function to get the concatenated single-arc state transition and sensitivity matrix at a given time.
Eigen::MatrixXd MultiArcCombinedStateTransitionAndSensitivityMatrixInterface::getCombinedStateTransitionAndSensitivityMatrix(
        const double evaluationTime )
{
    return getCombinedStateTransitionAndSensitivityMatrix( evaluationTime, true );
}

//! Function to get the concatenated state transition matrices for each arc and sensitivity matrix at a given time.
Eigen::MatrixXd MultiArcCombinedStateTransitionAndSensitivityMatrixInterface::getFullCombinedStateTransitionAndSensitivityMatrix(
        const double evaluationTime,
        const bool addCentralBodySensitivity )
{
    Eigen::MatrixXd combinedStateTransitionMatrix = getCombinedStateTransitionAndSensitivityMatrix(
                evaluationTime, addCentralBodySensitivity );
    Eigen::MatrixXd fullCombinedStateTransitionMatrix = Eigen::MatrixXd::Zero(
                stateTransitionMatrixSize_, numberOfStateArcs_ * stateTransitionMatrixSize_ + sensitivityMatrixSize_ );

    int currentArc = getCurrentArc( evaluationTime ).first;

    // Set Phi and S matrices of current arc.
    if( currentArc >= 0 )
    {
        fullCombinedStateTransitionMatrix.block(
                    0, currentArc * stateTransitionMatrixSize_, stateTransitionMatrixSize_, stateTransitionMatrixSize_ ) =
                stateTransitionMatrixInterpolators_.at( currentArc )->interpolate( evaluationTime );
        fullCombinedStateTransitionMatrix.block(
                    0, numberOfStateArcs_ * stateTransitionMatrixSize_, stateTransitionMatrixSize_, sensitivityMatrixSize_ ) =
                combinedStateTransitionMatrix.block( 0, 0, stateTransitionMatrixSize_, sensitivityMatrixSize_ );
    }
    return fullCombinedStateTransitionMatrix;
}

//! Function to get the concatenated state transition matrices for each arc and sensitivity matrix at a given time.
Eigen::MatrixXd MultiArcCombinedStateTransitionAndSensitivityMatrixInterface::getFullCombinedStateTransitionAndSensitivityMatrix(
        const double evaluationTime )
{
    return getFullCombinedStateTransitionAndSensitivityMatrix( evaluationTime, true );
}

//! Function to retrieve the current arc for a given time
std::pair< int, double > MultiArcCombinedStateTransitionAndSensitivityMatrixInterface::getCurrentArc( const double evaluationTime )
{

    int currentArc =  lookUpscheme_->findNearestLowerNeighbour( evaluationTime );
    if( evaluationTime < arcEndTimes_.at( currentArc ) && evaluationTime > arcStartTimes_.at( currentArc ) )
    {
        return std::make_pair( currentArc, arcStartTimes_.at( currentArc ) );
    }
    else
    {
        return std::make_pair( -1, TUDAT_NAN );
    }
}

//! Function to get the concatenated state transition and sensitivity matrix at a given time.
Eigen::MatrixXd HybridArcCombinedStateTransitionAndSensitivityMatrixInterface::getCombinedStateTransitionAndSensitivityMatrix(
        const double evaluationTime )
{
    Eigen::MatrixXd combinedStateTransitionMatrix = Eigen::MatrixXd::Zero(
                stateTransitionMatrixSize_, stateTransitionMatrixSize_ + sensitivityMatrixSize_ );

    // Get single-arc matrices
    Eigen::MatrixXd singleArcStateTransition = singleArcInterface_->getCombinedStateTransitionAndSensitivityMatrix(
                evaluationTime );

    // Get multi-arc matrices
    Eigen::MatrixXd multiArcStateTransition = multiArcInterface_->getCombinedStateTransitionAndSensitivityMatrix(
                evaluationTime, false );
    std::pair< int, double >  currentArc = multiArcInterface_->getCurrentArc( evaluationTime );

    // Set single-arc block
    combinedStateTransitionMatrix.block( 0, 0, singleArcStateSize_, singleArcStateSize_ ) =
            singleArcStateTransition.block( 0, 0, singleArcStateSize_, singleArcStateSize_ );

    // Set single-arc sensitivity block
    combinedStateTransitionMatrix.block( 0, multiArcStateSize_, singleArcStateSize_, sensitivityMatrixSize_ ) =
            singleArcStateTransition.block( 0, singleArcStateSize_, singleArcStateSize_, sensitivityMatrixSize_ );

    if( !( currentArc.first < 0 ) )
    {
        // Set multi-arc block
        combinedStateTransitionMatrix.block(
                    singleArcStateSize_, singleArcStateSize_, originalMultiArcStateSize_, originalMultiArcStateSize_ ) =
                multiArcStateTransition.block(
                    singleArcStateSize_, singleArcStateSize_, originalMultiArcStateSize_, originalMultiArcStateSize_ );

        // Get single-arc matrices at current arc start
        Eigen::MatrixXd singleArcStateTransitionAtArcStart = singleArcInterface_->getCombinedStateTransitionAndSensitivityMatrix(
                    currentArc.second );

        // Set coupled block
        combinedStateTransitionMatrix.block(
                    singleArcStateSize_, 0, originalMultiArcStateSize_, singleArcStateSize_ ) =
                multiArcStateTransition.block(
                    singleArcStateSize_, 0, originalMultiArcStateSize_, singleArcStateSize_ ) *
                singleArcStateTransitionAtArcStart.block(
                    0, 0, singleArcStateSize_, singleArcStateSize_ );

        // Set multi-arc sensitivity block
        combinedStateTransitionMatrix.block(
                    singleArcStateSize_, multiArcStateSize_, originalMultiArcStateSize_, sensitivityMatrixSize_ ) =
                multiArcStateTransition.block(
                    singleArcStateSize_, multiArcStateSize_, originalMultiArcStateSize_, sensitivityMatrixSize_ );

        std::vector< std::pair< int, int > > statePartialAdditionIndices =
                multiArcInterface_->getStatePartialAdditionIndices( currentArc.first );

        for( unsigned int i = 0; i < statePartialAdditionIndices.size( ); i++ )
        {
            combinedStateTransitionMatrix.block(
                        statePartialAdditionIndices.at( i ).first, multiArcStateSize_,
                        6, sensitivityMatrixSize_ ) +=
                    combinedStateTransitionMatrix.block(
                        statePartialAdditionIndices.at( i ).second, multiArcStateSize_,
                        6, sensitivityMatrixSize_ );

        }
    }

    return combinedStateTransitionMatrix;

}

//! Function to get the concatenated state transition matrices for each arc and sensitivity matrix at a given time.
Eigen::MatrixXd HybridArcCombinedStateTransitionAndSensitivityMatrixInterface::getFullCombinedStateTransitionAndSensitivityMatrix(
        const double evaluationTime )
{
    Eigen::MatrixXd combinedStateTransitionMatrix = getCombinedStateTransitionAndSensitivityMatrix( evaluationTime );
    Eigen::MatrixXd fullCombinedStateTransitionMatrix = Eigen::MatrixXd::Zero(
                stateTransitionMatrixSize_, singleArcStateSize_ + numberOfMultiArcs_ * originalMultiArcStateSize_ + sensitivityMatrixSize_ );

    fullCombinedStateTransitionMatrix.block(
                0, 0, singleArcStateSize_, singleArcStateSize_ ) =
            combinedStateTransitionMatrix.block(
                0, 0, singleArcStateSize_, singleArcStateSize_ );

    fullCombinedStateTransitionMatrix.block(
                0, singleArcStateSize_ + numberOfMultiArcs_ * originalMultiArcStateSize_, singleArcStateSize_, sensitivityMatrixSize_ ) =
            combinedStateTransitionMatrix.block(
                0, multiArcStateSize_, singleArcStateSize_, sensitivityMatrixSize_ );

    int currentArc = multiArcInterface_->getCurrentArc( evaluationTime ).first;

    // Set Phi and S matrices of current arc.
    if( currentArc >= 0 )
    {

        // Set multi-arc block
        fullCombinedStateTransitionMatrix.block(
                    singleArcStateSize_, singleArcStateSize_ + currentArc * originalMultiArcStateSize_,
                    originalMultiArcStateSize_, originalMultiArcStateSize_ ) =
                combinedStateTransitionMatrix.block(
                    singleArcStateSize_, singleArcStateSize_, originalMultiArcStateSize_, originalMultiArcStateSize_ );

        // Set coupled block
        fullCombinedStateTransitionMatrix.block(
                    singleArcStateSize_, 0, originalMultiArcStateSize_, singleArcStateSize_ ) =
                combinedStateTransitionMatrix.block(
                    singleArcStateSize_, 0, originalMultiArcStateSize_, singleArcStateSize_ );

        // Set multi-arc sensitivity block
        fullCombinedStateTransitionMatrix.block(
                    singleArcStateSize_, singleArcStateSize_ + numberOfMultiArcs_ * originalMultiArcStateSize_,
                    originalMultiArcStateSize_, sensitivityMatrixSize_ ) =
                combinedStateTransitionMatrix.block(
                    singleArcStateSize_, multiArcStateSize_, originalMultiArcStateSize_, sensitivityMatrixSize_ );

    }

    return fullCombinedStateTransitionMatrix;
}

}

}

<commit_msg>Fixed bookkeeping bug<commit_after>/*    Copyright (c) 2010-2019, Delft University of Technology
 *    All rigths reserved
 *
 *    This file is part of the Tudat. Redistribution and use in source and
 *    binary forms, with or without modification, are permitted exclusively
 *    under the terms of the Modified BSD license. You should have received
 *    a copy of the license with this file. If not, please or visit:
 *    http://tudat.tudelft.nl/LICENSE.
 */

#include <boost/make_shared.hpp>

#include "Tudat/Astrodynamics/Propagators/stateTransitionMatrixInterface.h"

namespace tudat
{

namespace propagators
{

//! Function to reset the state transition and sensitivity matrix interpolators
void SingleArcCombinedStateTransitionAndSensitivityMatrixInterface::updateMatrixInterpolators(
        const std::shared_ptr< interpolators::OneDimensionalInterpolator< double, Eigen::MatrixXd > >
        stateTransitionMatrixInterpolator,
        const std::shared_ptr< interpolators::OneDimensionalInterpolator< double, Eigen::MatrixXd > >
        sensitivityMatrixInterpolator,
        const std::vector< std::pair< int, int > >& statePartialAdditionIndices )
{
    stateTransitionMatrixInterpolator_ = stateTransitionMatrixInterpolator;
    sensitivityMatrixInterpolator_ = sensitivityMatrixInterpolator;
    statePartialAdditionIndices_ = statePartialAdditionIndices;
}

//! Function to get the concatenated state transition and sensitivity matrix at a given time.
Eigen::MatrixXd SingleArcCombinedStateTransitionAndSensitivityMatrixInterface::getCombinedStateTransitionAndSensitivityMatrix(
        const double evaluationTime )
{
    combinedStateTransitionMatrix_.setZero( );

    // Set Phi and S matrices.
    combinedStateTransitionMatrix_.block( 0, 0, stateTransitionMatrixSize_, stateTransitionMatrixSize_ ) =
            stateTransitionMatrixInterpolator_->interpolate( evaluationTime );

    if( sensitivityMatrixSize_ > 0 )
    {
        combinedStateTransitionMatrix_.block( 0, stateTransitionMatrixSize_, stateTransitionMatrixSize_, sensitivityMatrixSize_ ) =
                sensitivityMatrixInterpolator_->interpolate( evaluationTime );
    }

    for( unsigned int i = 0; i < statePartialAdditionIndices_.size( ); i++ )
    {
        combinedStateTransitionMatrix_.block( statePartialAdditionIndices_.at( i ).first, 0, 6, stateTransitionMatrixSize_ + sensitivityMatrixSize_ ) +=
                combinedStateTransitionMatrix_.block( statePartialAdditionIndices_.at( i ).second, 0, 6, stateTransitionMatrixSize_ + sensitivityMatrixSize_ );
    }

    return combinedStateTransitionMatrix_;
}

//! Constructor
MultiArcCombinedStateTransitionAndSensitivityMatrixInterface::MultiArcCombinedStateTransitionAndSensitivityMatrixInterface(
        const std::vector< std::shared_ptr< interpolators::OneDimensionalInterpolator< double, Eigen::MatrixXd > > >
        stateTransitionMatrixInterpolators,
        const std::vector< std::shared_ptr< interpolators::OneDimensionalInterpolator< double, Eigen::MatrixXd > > >
        sensitivityMatrixInterpolators,
        const std::vector< double >& arcStartTimes,
        const std::vector< double >& arcEndTimes,
        const int numberOfInitialDynamicalParameters,
        const int numberOfParameters,
        const std::vector< std::vector< std::pair< int, int > > >& statePartialAdditionIndices ):
    CombinedStateTransitionAndSensitivityMatrixInterface( numberOfInitialDynamicalParameters, numberOfParameters ),
    stateTransitionMatrixInterpolators_( stateTransitionMatrixInterpolators ),
    sensitivityMatrixInterpolators_( sensitivityMatrixInterpolators ),
    arcStartTimes_( arcStartTimes ),
    arcEndTimes_( arcEndTimes ),
    statePartialAdditionIndices_( statePartialAdditionIndices )
{
    if( arcStartTimes_.size( ) != arcEndTimes_.size( ) )
    {
        throw std::runtime_error( "Error when making MultiArcCombinedStateTransitionAndSensitivityMatrixInterface, incompatible time lists" );
    }
    numberOfStateArcs_ = arcStartTimes_.size( );

    sensitivityMatrixSize_ = numberOfParameters - numberOfStateArcs_ * stateTransitionMatrixSize_;

    if( stateTransitionMatrixInterpolators_.size( ) != sensitivityMatrixInterpolators_.size( ) ||
            stateTransitionMatrixInterpolators_.size( ) != static_cast< unsigned int >( numberOfStateArcs_ ) )
    {
        throw std::runtime_error(
                    "Error when making multi arc state transition and sensitivity interface, vector sizes are inconsistent" );
    }

    std::vector< double > arcSplitTimes = arcStartTimes_;
    arcSplitTimes.push_back(  std::numeric_limits< double >::max( ));
    lookUpscheme_ = std::make_shared< interpolators::HuntingAlgorithmLookupScheme< double > >(
                arcSplitTimes );
}

//! Function to reset the state transition and sensitivity matrix interpolators
void MultiArcCombinedStateTransitionAndSensitivityMatrixInterface::updateMatrixInterpolators(
        const std::vector< std::shared_ptr< interpolators::OneDimensionalInterpolator< double, Eigen::MatrixXd > > >
        stateTransitionMatrixInterpolators,
        const std::vector< std::shared_ptr< interpolators::OneDimensionalInterpolator< double, Eigen::MatrixXd > > >
        sensitivityMatrixInterpolators,
        const std::vector< double >& arcStartTimes,
        const std::vector< double >& arcEndTimes,
        const std::vector< std::vector< std::pair< int, int > > >& statePartialAdditionIndices )
{
    stateTransitionMatrixInterpolators_ = stateTransitionMatrixInterpolators;
    sensitivityMatrixInterpolators_ = sensitivityMatrixInterpolators;
    arcStartTimes_ =  arcStartTimes;
    arcEndTimes_ = arcEndTimes;
    statePartialAdditionIndices_ = statePartialAdditionIndices;

    if( stateTransitionMatrixInterpolators_.size( ) != sensitivityMatrixInterpolators_.size( ) ||
            stateTransitionMatrixInterpolators_.size( ) != static_cast< unsigned int >( numberOfStateArcs_ ) )
    {
        throw std::runtime_error(
                    "Error when resetting multi arc state transition and sensitivity interface, vector sizes are inconsistent." );
    }

    std::vector< double > arcSplitTimes = arcStartTimes_;
    arcSplitTimes.push_back( std::numeric_limits< double >::max( ) );

    lookUpscheme_ = std::make_shared< interpolators::HuntingAlgorithmLookupScheme< double > >(
                arcSplitTimes );
}

//! Function to get the concatenated single-arc state transition and sensitivity matrix at a given time.
Eigen::MatrixXd MultiArcCombinedStateTransitionAndSensitivityMatrixInterface::getCombinedStateTransitionAndSensitivityMatrix(
        const double evaluationTime,
        const bool addCentralBodySensitivity )
{
    Eigen::MatrixXd combinedStateTransitionMatrix = Eigen::MatrixXd::Zero(
                stateTransitionMatrixSize_, stateTransitionMatrixSize_ + sensitivityMatrixSize_ );

    int currentArc = getCurrentArc( evaluationTime ).first;

    // Set Phi and S matrices.
    if( currentArc >= 0 )
    {
        combinedStateTransitionMatrix.block( 0, 0, stateTransitionMatrixSize_, stateTransitionMatrixSize_ ) =
                stateTransitionMatrixInterpolators_.at( currentArc )->interpolate( evaluationTime );
        combinedStateTransitionMatrix.block( 0, stateTransitionMatrixSize_, stateTransitionMatrixSize_, sensitivityMatrixSize_ ) =
                sensitivityMatrixInterpolators_.at( currentArc )->interpolate( evaluationTime );

        for( unsigned int i = 0; i < statePartialAdditionIndices_.at( currentArc ).size( ); i++ )
        {
            int indicesToAdd = addCentralBodySensitivity ?
                        ( stateTransitionMatrixSize_ + sensitivityMatrixSize_ ) : stateTransitionMatrixSize_;
            combinedStateTransitionMatrix.block(
                        statePartialAdditionIndices_.at( currentArc ).at( i ).first, 0, 6, indicesToAdd ) +=
                    combinedStateTransitionMatrix.block(
                        statePartialAdditionIndices_.at( currentArc ).at( i ).second, 0, 6, indicesToAdd );
        }
    }
    return combinedStateTransitionMatrix;
}

//! Function to get the concatenated single-arc state transition and sensitivity matrix at a given time.
Eigen::MatrixXd MultiArcCombinedStateTransitionAndSensitivityMatrixInterface::getCombinedStateTransitionAndSensitivityMatrix(
        const double evaluationTime )
{
    return getCombinedStateTransitionAndSensitivityMatrix( evaluationTime, true );
}

//! Function to get the concatenated state transition matrices for each arc and sensitivity matrix at a given time.
Eigen::MatrixXd MultiArcCombinedStateTransitionAndSensitivityMatrixInterface::getFullCombinedStateTransitionAndSensitivityMatrix(
        const double evaluationTime,
        const bool addCentralBodySensitivity )
{
    Eigen::MatrixXd combinedStateTransitionMatrix = getCombinedStateTransitionAndSensitivityMatrix(
                evaluationTime, addCentralBodySensitivity );
    Eigen::MatrixXd fullCombinedStateTransitionMatrix = Eigen::MatrixXd::Zero(
                stateTransitionMatrixSize_, numberOfStateArcs_ * stateTransitionMatrixSize_ + sensitivityMatrixSize_ );

    int currentArc = getCurrentArc( evaluationTime ).first;

    // Set Phi and S matrices of current arc.
    if( currentArc >= 0 )
    {
        fullCombinedStateTransitionMatrix.block(
                    0, currentArc * stateTransitionMatrixSize_, stateTransitionMatrixSize_, stateTransitionMatrixSize_ ) =
                stateTransitionMatrixInterpolators_.at( currentArc )->interpolate( evaluationTime );
        fullCombinedStateTransitionMatrix.block(
                    0, numberOfStateArcs_ * stateTransitionMatrixSize_, stateTransitionMatrixSize_, sensitivityMatrixSize_ ) =
                combinedStateTransitionMatrix.block( 0, stateTransitionMatrixSize_, stateTransitionMatrixSize_, sensitivityMatrixSize_ );
    }
    return fullCombinedStateTransitionMatrix;
}

//! Function to get the concatenated state transition matrices for each arc and sensitivity matrix at a given time.
Eigen::MatrixXd MultiArcCombinedStateTransitionAndSensitivityMatrixInterface::getFullCombinedStateTransitionAndSensitivityMatrix(
        const double evaluationTime )
{
    return getFullCombinedStateTransitionAndSensitivityMatrix( evaluationTime, true );
}

//! Function to retrieve the current arc for a given time
std::pair< int, double > MultiArcCombinedStateTransitionAndSensitivityMatrixInterface::getCurrentArc( const double evaluationTime )
{

    int currentArc =  lookUpscheme_->findNearestLowerNeighbour( evaluationTime );
    if( evaluationTime < arcEndTimes_.at( currentArc ) && evaluationTime > arcStartTimes_.at( currentArc ) )
    {
        return std::make_pair( currentArc, arcStartTimes_.at( currentArc ) );
    }
    else
    {
        return std::make_pair( -1, TUDAT_NAN );
    }
}

//! Function to get the concatenated state transition and sensitivity matrix at a given time.
Eigen::MatrixXd HybridArcCombinedStateTransitionAndSensitivityMatrixInterface::getCombinedStateTransitionAndSensitivityMatrix(
        const double evaluationTime )
{
    Eigen::MatrixXd combinedStateTransitionMatrix = Eigen::MatrixXd::Zero(
                stateTransitionMatrixSize_, stateTransitionMatrixSize_ + sensitivityMatrixSize_ );

    // Get single-arc matrices
    Eigen::MatrixXd singleArcStateTransition = singleArcInterface_->getCombinedStateTransitionAndSensitivityMatrix(
                evaluationTime );

    // Get multi-arc matrices
    Eigen::MatrixXd multiArcStateTransition = multiArcInterface_->getCombinedStateTransitionAndSensitivityMatrix(
                evaluationTime, false );
    std::pair< int, double >  currentArc = multiArcInterface_->getCurrentArc( evaluationTime );

    // Set single-arc block
    combinedStateTransitionMatrix.block( 0, 0, singleArcStateSize_, singleArcStateSize_ ) =
            singleArcStateTransition.block( 0, 0, singleArcStateSize_, singleArcStateSize_ );

    // Set single-arc sensitivity block
    combinedStateTransitionMatrix.block( 0, multiArcStateSize_, singleArcStateSize_, sensitivityMatrixSize_ ) =
            singleArcStateTransition.block( 0, singleArcStateSize_, singleArcStateSize_, sensitivityMatrixSize_ );

    if( !( currentArc.first < 0 ) )
    {
        // Set multi-arc block
        combinedStateTransitionMatrix.block(
                    singleArcStateSize_, singleArcStateSize_, originalMultiArcStateSize_, originalMultiArcStateSize_ ) =
                multiArcStateTransition.block(
                    singleArcStateSize_, singleArcStateSize_, originalMultiArcStateSize_, originalMultiArcStateSize_ );

        // Get single-arc matrices at current arc start
        Eigen::MatrixXd singleArcStateTransitionAtArcStart = singleArcInterface_->getCombinedStateTransitionAndSensitivityMatrix(
                    currentArc.second );

        // Set coupled block
        combinedStateTransitionMatrix.block(
                    singleArcStateSize_, 0, originalMultiArcStateSize_, singleArcStateSize_ ) =
                multiArcStateTransition.block(
                    singleArcStateSize_, 0, originalMultiArcStateSize_, singleArcStateSize_ ) *
                singleArcStateTransitionAtArcStart.block(
                    0, 0, singleArcStateSize_, singleArcStateSize_ );

        // Set multi-arc sensitivity block
        combinedStateTransitionMatrix.block(
                    singleArcStateSize_, multiArcStateSize_, originalMultiArcStateSize_, sensitivityMatrixSize_ ) =
                multiArcStateTransition.block(
                    singleArcStateSize_, multiArcStateSize_, originalMultiArcStateSize_, sensitivityMatrixSize_ );

        std::vector< std::pair< int, int > > statePartialAdditionIndices =
                multiArcInterface_->getStatePartialAdditionIndices( currentArc.first );

        for( unsigned int i = 0; i < statePartialAdditionIndices.size( ); i++ )
        {
            combinedStateTransitionMatrix.block(
                        statePartialAdditionIndices.at( i ).first, multiArcStateSize_,
                        6, sensitivityMatrixSize_ ) +=
                    combinedStateTransitionMatrix.block(
                        statePartialAdditionIndices.at( i ).second, multiArcStateSize_,
                        6, sensitivityMatrixSize_ );

        }
    }

    return combinedStateTransitionMatrix;

}

//! Function to get the concatenated state transition matrices for each arc and sensitivity matrix at a given time.
Eigen::MatrixXd HybridArcCombinedStateTransitionAndSensitivityMatrixInterface::getFullCombinedStateTransitionAndSensitivityMatrix(
        const double evaluationTime )
{
    Eigen::MatrixXd combinedStateTransitionMatrix = getCombinedStateTransitionAndSensitivityMatrix( evaluationTime );
    Eigen::MatrixXd fullCombinedStateTransitionMatrix = Eigen::MatrixXd::Zero(
                stateTransitionMatrixSize_, singleArcStateSize_ + numberOfMultiArcs_ * originalMultiArcStateSize_ + sensitivityMatrixSize_ );

    fullCombinedStateTransitionMatrix.block(
                0, 0, singleArcStateSize_, singleArcStateSize_ ) =
            combinedStateTransitionMatrix.block(
                0, 0, singleArcStateSize_, singleArcStateSize_ );

    fullCombinedStateTransitionMatrix.block(
                0, singleArcStateSize_ + numberOfMultiArcs_ * originalMultiArcStateSize_, singleArcStateSize_, sensitivityMatrixSize_ ) =
            combinedStateTransitionMatrix.block(
                0, multiArcStateSize_, singleArcStateSize_, sensitivityMatrixSize_ );

    int currentArc = multiArcInterface_->getCurrentArc( evaluationTime ).first;

    // Set Phi and S matrices of current arc.
    if( currentArc >= 0 )
    {

        // Set multi-arc block
        fullCombinedStateTransitionMatrix.block(
                    singleArcStateSize_, singleArcStateSize_ + currentArc * originalMultiArcStateSize_,
                    originalMultiArcStateSize_, originalMultiArcStateSize_ ) =
                combinedStateTransitionMatrix.block(
                    singleArcStateSize_, singleArcStateSize_, originalMultiArcStateSize_, originalMultiArcStateSize_ );

        // Set coupled block
        fullCombinedStateTransitionMatrix.block(
                    singleArcStateSize_, 0, originalMultiArcStateSize_, singleArcStateSize_ ) =
                combinedStateTransitionMatrix.block(
                    singleArcStateSize_, 0, originalMultiArcStateSize_, singleArcStateSize_ );

        // Set multi-arc sensitivity block
        fullCombinedStateTransitionMatrix.block(
                    singleArcStateSize_, singleArcStateSize_ + numberOfMultiArcs_ * originalMultiArcStateSize_,
                    originalMultiArcStateSize_, sensitivityMatrixSize_ ) =
                combinedStateTransitionMatrix.block(
                    singleArcStateSize_, multiArcStateSize_, originalMultiArcStateSize_, sensitivityMatrixSize_ );

    }

    return fullCombinedStateTransitionMatrix;
}

}

}

<|endoftext|>