<commit_before>/**
*  Copyright (C) 2016 3D Repo Ltd
*
*  This program is free software: you can redistribute it and/or modify
*  it under the terms of the GNU Affero General Public License as
*  published by the Free Software Foundation, either version 3 of the
*  License, or (at your option) any later version.
*
*  This program 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 Affero General Public License for more details.
*
*  You should have received a copy of the GNU Affero General Public License
*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include "repo_mesh_map_reorganiser.h"
#include "../../core/model/bson/repo_bson_factory.h"

using namespace repo::manipulator::modelutility;

MeshMapReorganiser::MeshMapReorganiser(
	const repo::core::model::MeshNode *mesh,
	const size_t                      &vertThreshold):
	mesh(mesh),
	maxVertices(vertThreshold),
	oldFaces(mesh->getFaces()),
	oldVertices(mesh->getVertices()),
	oldNormals(mesh->getNormals())
{
	if (mesh && mesh->getMeshMapping().size())
	{

		newVertices = oldVertices;
		newNormals = oldNormals;
		performSplitting();
	}
	else
	{
		repoError << "Failed to remap mesh.";
		repoDebug << "Failed @ MeshMapRerganiser:  Null ptr to mesh or trying to remap a mesh without mesh mapping!";
	}
}

MeshMapReorganiser::~MeshMapReorganiser(){}

void MeshMapReorganiser::finishSubMesh(
	repo_mesh_mapping_t &mapping,
	std::vector<float>  &minBox,
	std::vector<float>  &maxBox,
	const size_t        &nVertices,
	const size_t        &nFaces
	)
{
	mapping.vertTo = mapping.vertFrom + nVertices;
	mapping.triTo = mapping.triFrom + nFaces;

	if (minBox.size() == 3)
	{
		mapping.min = { minBox[0], minBox[1], minBox[2] };
	}
	else
	{
		repoError << "MeshMapReorganiser: Failed to find minimum bounding box value : Information is incomplete";
	}

	if (maxBox.size() == 3)
	{
		mapping.min = { maxBox[0], maxBox[1], maxBox[2] };
	}
	else
	{
		repoError << "MeshMapReorganiser: Failed to find maximum bounding box value : Information is incomplete";
	}

	minBox.clear();
	maxBox.clear();

	matMap.back().push_back(mapping);
}

repo::core::model::MeshNode MeshMapReorganiser::getRemappedMesh() const
{

	auto bbox = mesh->getBoundingBox();
	std::vector<std::vector<float>> bboxArr;
	if (bbox.size())
	{
		bboxArr.push_back({ bbox[0].x, bbox[0].y, bbox[0].z });
		bboxArr.push_back({ bbox[1].x, bbox[1].y, bbox[1].z });
	}

	auto newMesh =  repo::core::model::RepoBSONFactory::makeMeshNode(newVertices, newFaces, newNormals, bboxArr);
	repo::core::model::RepoBSONBuilder builder;
	builder.append(REPO_NODE_LABEL_ID, mesh->getUniqueID());
	builder.append(REPO_NODE_LABEL_SHARED_ID, mesh->getSharedID());
	auto changes = builder.obj();
	newMesh = newMesh.cloneAndAddFields(&changes, false);
	return newMesh.cloneAndUpdateMeshMapping(reMappedMappings, true);
}

void MeshMapReorganiser::performSplitting()
{
	std::vector<repo_mesh_mapping_t> newMappings;
	std::vector<repo_mesh_mapping_t> orgMappings = mesh->getMeshMapping();

	std::vector<repo_face_t> faces;

	size_t subMeshVertexCount = 0;
	size_t subMeshFaceCount = 0;

	size_t totalVertexCount = 0;
	size_t totalFaceCount = 0;

	size_t idMapIdx = 0;
	size_t orgFaceIdx = 0;

	bool finishedSubMesh = true;

	std::vector<float> bboxMin;
	std::vector<float> bboxMax;

	//Resources
	repoUUID superMeshID = mesh->getUniqueID();

	repoTrace << "Performing splitting on mesh: " << mesh->getUniqueID();
	for (const auto &currentSubMesh : orgMappings)
	{
		splitMap[currentSubMesh.mesh_id] = std::vector < uint32_t >();

		auto currentMeshVFrom = currentSubMesh.vertFrom;
		auto currentMeshVTo = currentSubMesh.vertTo;
		auto currentMeshTFrom = currentSubMesh.triFrom;
		auto currentMeshTTo = currentSubMesh.triTo;

		auto currentMeshNumVertices = currentMeshVTo - currentMeshVFrom;
		auto currentMeshNumFaces = currentMeshTTo - currentMeshTFrom;

		// If the current cumulative count of vertices is greater than the
		// vertex limit then start a new mesh.
		// If newMappings === 0 we need to initialize the first mesh
		if (((subMeshVertexCount + currentMeshNumVertices) > maxVertices) || finishedSubMesh) {
			// Close off the previous sub mesh
			if (!finishedSubMesh) // Have we already finished this one
			{
				finishSubMesh(newMappings.back(), bboxMin, bboxMax, subMeshVertexCount, subMeshFaceCount);
			}

			//Reset the counters for the submesh vertex and face count
			// and begin a new sub mesh with a new ID
			subMeshVertexCount = 0;
			subMeshFaceCount = 0;
			finishedSubMesh = false;

			newMappings.resize(newMappings.size() + 1);
			startSubMesh(newMappings.back(), superMeshID, currentSubMesh.material_id, totalVertexCount, totalFaceCount);
		}

		// Now we've started a new mesh is the mesh that we're trying to add greater than
		// the limit itself. In the case that it is, this will always flag as above.
		if (currentMeshNumVertices > maxVertices) {

			size_t retTotalVCount, retTotalFCount;
			splitLargeMesh(currentSubMesh, newMappings, idMapIdx, orgFaceIdx, retTotalVCount, retTotalFCount);

			totalVertexCount += retTotalVCount;
			totalFaceCount   += retTotalFCount;

			finishedSubMesh = true;
		}
		else
		{
			for (uint32_t fIdx = 0; fIdx < currentMeshNumFaces; fIdx++)
			{
				repo_face_t currentFace = oldFaces[orgFaceIdx++];
				auto        nSides      = currentFace.size();

				if (nSides != 3)
				{
					repoError << "Non triangulated face with " << nSides << " vertices.";
				}
				else
				{
					repo_face_t newFace;
					for (const auto &indexValue : currentFace)
					{
						// Take currentMeshVFrom from Index Value to reset to zero start,
						// then add back in the current running total to append after
						// previous mesh.
						auto newIdx = indexValue + (subMeshVertexCount - currentMeshVFrom);
						newFace.push_back(newIdx);
						serialisedFaces.push_back(newIdx);
					}
					newFaces.push_back(newFace);
				}
			}

			updateIDMapArray(currentMeshNumVertices, idMapIdx++);

			updateBoundingBoxes(bboxMin, bboxMax, currentSubMesh.min, currentSubMesh.max);

			subMeshVertexCount += currentMeshNumVertices;
			subMeshFaceCount   += currentMeshNumFaces;

			totalVertexCount += currentMeshNumVertices;
			totalFaceCount   += currentMeshNumFaces;

			splitMap[currentSubMesh.mesh_id].push_back(newMappings.size());
		}
	}

	if (subMeshVertexCount) {
		finishSubMesh(newMappings.back(), bboxMin, bboxMax, subMeshVertexCount, subMeshFaceCount);
	}

	reMappedMappings = newMappings;

}

void MeshMapReorganiser::splitLargeMesh(
	const repo_mesh_mapping_t        currentSubMesh,
	std::vector<repo_mesh_mapping_t> &newMappings,
	size_t                           &idMapIdx,
	size_t                           &orgFaceIdx,
	size_t                           &totalVertexCount,
	size_t                           &totalFaceCount)
{
	std::unordered_map<uint32_t, uint32_t> reIndexMap;
	std::vector<repo_vector_t> reMappedVertices, reMappedNormals;

	repoTrace << currentSubMesh.mesh_id << " Exceed the maximum amount of vertices, splitting it into multiple super meshes...";

	auto currentMeshVFrom = currentSubMesh.vertFrom;
	auto currentMeshVTo = currentSubMesh.vertTo;
	auto currentMeshTFrom = currentSubMesh.triFrom;
	auto currentMeshTTo = currentSubMesh.triTo;

	auto currentMeshNumVertices = currentMeshVTo - currentMeshVFrom;
	auto currentMeshNumFaces = currentMeshTTo - currentMeshTFrom;

	//When split mesh is called, it's guaranteed that a new mesh mapping has been created for it
	auto newVerticesVFrom = newMappings.back().vertFrom;

	const bool hasNormal = oldNormals.size();

	// Split mesh information
	bool startedLargeMeshSplit = true;
	size_t splitMeshVertexCount = 0;
	size_t splitMeshFaceCount = 0;
	std::vector<float> bboxMin;
	std::vector<float> bboxMax;

	totalVertexCount = 0;
	totalFaceCount = 0;

	// Perform quick and dirty splitting algorithm
	// Loop over all faces in the giant mesh

	for (uint32_t fIdx = 0; fIdx < currentMeshNumFaces; ++fIdx) {
		repo_face_t currentFace = oldFaces[orgFaceIdx++];
		auto        nSides = currentFace.size();
		if (nSides != 3)
		{
			repoError << "Non triangulated face with " << nSides << " vertices.";
		}
		else
		{
			// If we haven't started yet, or the current number of vertices that we have
			// split is greater than the limit we need to start a new subMesh
			if (((splitMeshVertexCount + nSides) > maxVertices) || !startedLargeMeshSplit) {
				// If we have started we must be here because we have created a split mesh
				// greater than the required number of vertices

				if (fIdx)
					splitMap[currentSubMesh.mesh_id].push_back(newMappings.size());

				if (startedLargeMeshSplit) {
					updateIDMapArray(splitMeshVertexCount, idMapIdx++);
					finishSubMesh(newMappings.back(), bboxMin, bboxMax, splitMeshVertexCount, splitMeshFaceCount);

				}

				totalVertexCount += splitMeshVertexCount;
				totalFaceCount   += splitMeshFaceCount;
				startedLargeMeshSplit = true;
				newMappings.resize(newMappings.size() + 1);
				startSubMesh(newMappings.back(), mesh->getUniqueID(), currentSubMesh.material_id, totalVertexCount, totalFaceCount);
				splitMeshVertexCount = 0;
				splitMeshFaceCount = 0;
				reIndexMap.clear();
			}//if (((splitMeshVertexCount + nSides) > maxVertices) || !startedLargeMeshSplit)

			repo_face_t newFace;
			for (const auto &indexValue : currentFace)
			{
				const auto it = reIndexMap.find(indexValue);
				if (it == reIndexMap.end())
				{
					reIndexMap[indexValue] = splitMeshVertexCount;
					repo_vector_t vertex = oldVertices[indexValue];
					reMappedVertices.push_back(vertex);

					if (hasNormal)
					{
						reMappedNormals.push_back(oldNormals[indexValue]);
					}

					updateBoundingBoxes(bboxMin, bboxMax, vertex, vertex);
					splitMeshVertexCount++;
				}
				newFace.push_back(reIndexMap[indexValue]);
				serialisedFaces.push_back(reIndexMap[indexValue]);
			}//for (const auto &indexValue : currentFace)
			newFaces.push_back(newFace);

		}//else nSides != 3
		splitMeshFaceCount++;
	}//for (uint32_t fIdx = 0; fIdx < currentMeshNumFaces; ++fIdx)

	//Modify the vertices as it may be rearranged within this region
	std::copy(reMappedVertices.begin(), reMappedVertices.end(), newVertices.begin() + newVerticesVFrom);
	if (hasNormal)
		std::copy(reMappedNormals.begin(), reMappedNormals.end(), newNormals.begin() + newVerticesVFrom);

	updateIDMapArray(splitMeshVertexCount, idMapIdx);

	totalVertexCount += splitMeshVertexCount;
	totalFaceCount += splitMeshFaceCount;

	auto leftOverVertices = currentMeshNumVertices - totalVertexCount;

	if (leftOverVertices)
	{
		auto startingPos = newVertices.begin() + newMappings.back().vertFrom + totalVertexCount;

		//Chop out the unwanted vertices
		newVertices.erase(startingPos, startingPos + leftOverVertices);
		if (hasNormal)
			newNormals.erase(startingPos, startingPos + leftOverVertices);
	}

	splitMap[currentSubMesh.mesh_id].push_back(newMappings.size());
	finishSubMesh(newMappings.back(), bboxMin, bboxMax, splitMeshVertexCount, splitMeshFaceCount);
}

void MeshMapReorganiser::startSubMesh(
	repo_mesh_mapping_t &mapping,
	const repoUUID      &meshID,
	const repoUUID      &matID,
	const size_t        &sVertices,
	const size_t        &sFaces
	)
{
	mapping.vertFrom = sVertices;
	mapping.vertFrom = sFaces;
	mapping.material_id = matID; //Not a reliable source. Just filled in for completeness
	mapping.mesh_id = meshID;

	idMapBuf.resize(idMapBuf.size() + 1);
	idMapBuf.back().clear();
	matMap.resize(matMap.size() + 1);
	matMap.back().clear();
}

void MeshMapReorganiser::updateBoundingBoxes(
	std::vector<float>  &min,
	std::vector<float>  &max,
	const repo_vector_t &smMin,
	const repo_vector_t &smMax)
{
	//Update Bounding box
	if (min.size())
	{
		if (min[0] > smMin.x)
			min[0] = smMin.x;

		if (min[1] > smMin.y)
			min[1] = smMin.y;

		if (min[2] > smMin.z)
			min[2] = smMin.z;
	}
	else
	{
		min = { smMin.x, smMin.y, smMin.z };
	}

	if (max.size())
	{
		if (max[0] < smMax.x)
			max[0] = smMax.x;

		if (max[1] < smMax.y)
			max[1] = smMax.y;

		if (max[2] < smMax.z)
			max[2] = smMax.z;
	}
	else
	{
		max = { smMax.x, smMax.y, smMax.z };
	}
}

void MeshMapReorganiser::updateIDMapArray(
	const size_t &n,
	const size_t &value)
{
	auto idMapLength = idMapBuf.back().size();
	idMapBuf.back().resize(idMapLength + n);

	float value_f = value;
	std::fill(idMapBuf.back().begin() + idMapLength, idMapBuf.back().end(), value_f);
}<commit_msg>#106 fix erroneous id mapping for material<commit_after>/**
*  Copyright (C) 2016 3D Repo Ltd
*
*  This program is free software: you can redistribute it and/or modify
*  it under the terms of the GNU Affero General Public License as
*  published by the Free Software Foundation, either version 3 of the
*  License, or (at your option) any later version.
*
*  This program 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 Affero General Public License for more details.
*
*  You should have received a copy of the GNU Affero General Public License
*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include "repo_mesh_map_reorganiser.h"
#include "../../core/model/bson/repo_bson_factory.h"

using namespace repo::manipulator::modelutility;

MeshMapReorganiser::MeshMapReorganiser(
	const repo::core::model::MeshNode *mesh,
	const size_t                      &vertThreshold):
	mesh(mesh),
	maxVertices(vertThreshold),
	oldFaces(mesh->getFaces()),
	oldVertices(mesh->getVertices()),
	oldNormals(mesh->getNormals())
{
	if (mesh && mesh->getMeshMapping().size())
	{

		newVertices = oldVertices;
		newNormals = oldNormals;
		performSplitting();
	}
	else
	{
		repoError << "Failed to remap mesh.";
		repoDebug << "Failed @ MeshMapRerganiser:  Null ptr to mesh or trying to remap a mesh without mesh mapping!";
	}
}

MeshMapReorganiser::~MeshMapReorganiser(){}

void MeshMapReorganiser::finishSubMesh(
	repo_mesh_mapping_t &mapping,
	std::vector<float>  &minBox,
	std::vector<float>  &maxBox,
	const size_t        &nVertices,
	const size_t        &nFaces
	)
{
	mapping.vertTo = mapping.vertFrom + nVertices;
	mapping.triTo = mapping.triFrom + nFaces;

	if (minBox.size() == 3)
	{
		mapping.min = { minBox[0], minBox[1], minBox[2] };
	}
	else
	{
		repoError << "MeshMapReorganiser: Failed to find minimum bounding box value : Information is incomplete";
	}

	if (maxBox.size() == 3)
	{
		mapping.min = { maxBox[0], maxBox[1], maxBox[2] };
	}
	else
	{
		repoError << "MeshMapReorganiser: Failed to find maximum bounding box value : Information is incomplete";
	}

	minBox.clear();
	maxBox.clear();

	matMap.back().push_back(mapping);
}

repo::core::model::MeshNode MeshMapReorganiser::getRemappedMesh() const
{

	auto bbox = mesh->getBoundingBox();
	std::vector<std::vector<float>> bboxArr;
	if (bbox.size())
	{
		bboxArr.push_back({ bbox[0].x, bbox[0].y, bbox[0].z });
		bboxArr.push_back({ bbox[1].x, bbox[1].y, bbox[1].z });
	}

	auto newMesh =  repo::core::model::RepoBSONFactory::makeMeshNode(newVertices, newFaces, newNormals, bboxArr);
	repo::core::model::RepoBSONBuilder builder;
	builder.append(REPO_NODE_LABEL_ID, mesh->getUniqueID());
	builder.append(REPO_NODE_LABEL_SHARED_ID, mesh->getSharedID());
	auto changes = builder.obj();
	newMesh = newMesh.cloneAndAddFields(&changes, false);
	return newMesh.cloneAndUpdateMeshMapping(reMappedMappings, true);
}

void MeshMapReorganiser::performSplitting()
{
	std::vector<repo_mesh_mapping_t> newMappings;
	std::vector<repo_mesh_mapping_t> orgMappings = mesh->getMeshMapping();

	std::vector<repo_face_t> faces;

	size_t subMeshVertexCount = 0;
	size_t subMeshFaceCount = 0;

	size_t totalVertexCount = 0;
	size_t totalFaceCount = 0;

	size_t idMapIdx = 0;
	size_t orgFaceIdx = 0;

	bool finishedSubMesh = true;

	std::vector<float> bboxMin;
	std::vector<float> bboxMax;

	//Resources
	repoUUID superMeshID = mesh->getUniqueID();

	repoTrace << "Performing splitting on mesh: " << mesh->getUniqueID();
	for (const auto &currentSubMesh : orgMappings)
	{
		splitMap[currentSubMesh.mesh_id] = std::vector < uint32_t >();

		auto currentMeshVFrom = currentSubMesh.vertFrom;
		auto currentMeshVTo = currentSubMesh.vertTo;
		auto currentMeshTFrom = currentSubMesh.triFrom;
		auto currentMeshTTo = currentSubMesh.triTo;

		auto currentMeshNumVertices = currentMeshVTo - currentMeshVFrom;
		auto currentMeshNumFaces = currentMeshTTo - currentMeshTFrom;

		// If the current cumulative count of vertices is greater than the
		// vertex limit then start a new mesh.
		// If newMappings === 0 we need to initialize the first mesh
		if (((subMeshVertexCount + currentMeshNumVertices) > maxVertices) || finishedSubMesh) {
			// Close off the previous sub mesh
			if (!finishedSubMesh) // Have we already finished this one
			{
				finishSubMesh(newMappings.back(), bboxMin, bboxMax, subMeshVertexCount, subMeshFaceCount);
			}

			//Reset the counters for the submesh vertex and face count
			// and begin a new sub mesh with a new ID
			subMeshVertexCount = 0;
			subMeshFaceCount = 0;
			finishedSubMesh = false;

			newMappings.resize(newMappings.size() + 1);
			startSubMesh(newMappings.back(), superMeshID, currentSubMesh.material_id, totalVertexCount, totalFaceCount);
		}

		// Now we've started a new mesh is the mesh that we're trying to add greater than
		// the limit itself. In the case that it is, this will always flag as above.
		if (currentMeshNumVertices > maxVertices) {

			size_t retTotalVCount, retTotalFCount;
			splitLargeMesh(currentSubMesh, newMappings, idMapIdx, orgFaceIdx, retTotalVCount, retTotalFCount);

			++idMapIdx;
			totalVertexCount += retTotalVCount;
			totalFaceCount   += retTotalFCount;

			finishedSubMesh = true;
		}
		else
		{
			for (uint32_t fIdx = 0; fIdx < currentMeshNumFaces; fIdx++)
			{
				repo_face_t currentFace = oldFaces[orgFaceIdx++];
				auto        nSides      = currentFace.size();

				if (nSides != 3)
				{
					repoError << "Non triangulated face with " << nSides << " vertices.";
				}
				else
				{
					repo_face_t newFace;
					for (const auto &indexValue : currentFace)
					{
						// Take currentMeshVFrom from Index Value to reset to zero start,
						// then add back in the current running total to append after
						// previous mesh.
						auto newIdx = indexValue + (subMeshVertexCount - currentMeshVFrom);
						newFace.push_back(newIdx);
						serialisedFaces.push_back(newIdx);
					}
					newFaces.push_back(newFace);
				}
			}

			updateIDMapArray(currentMeshNumVertices, idMapIdx++);

			updateBoundingBoxes(bboxMin, bboxMax, currentSubMesh.min, currentSubMesh.max);

			subMeshVertexCount += currentMeshNumVertices;
			subMeshFaceCount   += currentMeshNumFaces;

			totalVertexCount += currentMeshNumVertices;
			totalFaceCount   += currentMeshNumFaces;

			splitMap[currentSubMesh.mesh_id].push_back(newMappings.size());
		}
	}

	if (subMeshVertexCount) {
		finishSubMesh(newMappings.back(), bboxMin, bboxMax, subMeshVertexCount, subMeshFaceCount);
	}

	reMappedMappings = newMappings;

}

void MeshMapReorganiser::splitLargeMesh(
	const repo_mesh_mapping_t        currentSubMesh,
	std::vector<repo_mesh_mapping_t> &newMappings,
	size_t                           &idMapIdx,
	size_t                           &orgFaceIdx,
	size_t                           &totalVertexCount,
	size_t                           &totalFaceCount)
{
	std::unordered_map<uint32_t, uint32_t> reIndexMap;
	std::vector<repo_vector_t> reMappedVertices, reMappedNormals;

	repoTrace << currentSubMesh.mesh_id << " Exceed the maximum amount of vertices, splitting it into multiple super meshes...";

	auto currentMeshVFrom = currentSubMesh.vertFrom;
	auto currentMeshVTo = currentSubMesh.vertTo;
	auto currentMeshTFrom = currentSubMesh.triFrom;
	auto currentMeshTTo = currentSubMesh.triTo;

	auto currentMeshNumVertices = currentMeshVTo - currentMeshVFrom;
	auto currentMeshNumFaces = currentMeshTTo - currentMeshTFrom;

	//When split mesh is called, it's guaranteed that a new mesh mapping has been created for it
	auto newVerticesVFrom = newMappings.back().vertFrom;

	const bool hasNormal = oldNormals.size();

	// Split mesh information
	bool startedLargeMeshSplit = true;
	size_t splitMeshVertexCount = 0;
	size_t splitMeshFaceCount = 0;
	std::vector<float> bboxMin;
	std::vector<float> bboxMax;

	totalVertexCount = 0;
	totalFaceCount = 0;

	// Perform quick and dirty splitting algorithm
	// Loop over all faces in the giant mesh

	for (uint32_t fIdx = 0; fIdx < currentMeshNumFaces; ++fIdx) {
		repo_face_t currentFace = oldFaces[orgFaceIdx++];
		auto        nSides = currentFace.size();
		if (nSides != 3)
		{
			repoError << "Non triangulated face with " << nSides << " vertices.";
		}
		else
		{
			// If we haven't started yet, or the current number of vertices that we have
			// split is greater than the limit we need to start a new subMesh
			if (((splitMeshVertexCount + nSides) > maxVertices) || !startedLargeMeshSplit) {
				// If we have started we must be here because we have created a split mesh
				// greater than the required number of vertices

				if (fIdx)
					splitMap[currentSubMesh.mesh_id].push_back(newMappings.size());

				if (startedLargeMeshSplit) {
					updateIDMapArray(splitMeshVertexCount, idMapIdx++);
					finishSubMesh(newMappings.back(), bboxMin, bboxMax, splitMeshVertexCount, splitMeshFaceCount);

				}

				totalVertexCount += splitMeshVertexCount;
				totalFaceCount   += splitMeshFaceCount;
				startedLargeMeshSplit = true;
				newMappings.resize(newMappings.size() + 1);
				startSubMesh(newMappings.back(), mesh->getUniqueID(), currentSubMesh.material_id, totalVertexCount, totalFaceCount);
				splitMeshVertexCount = 0;
				splitMeshFaceCount = 0;
				reIndexMap.clear();
			}//if (((splitMeshVertexCount + nSides) > maxVertices) || !startedLargeMeshSplit)

			repo_face_t newFace;
			for (const auto &indexValue : currentFace)
			{
				const auto it = reIndexMap.find(indexValue);
				if (it == reIndexMap.end())
				{
					reIndexMap[indexValue] = splitMeshVertexCount;
					repo_vector_t vertex = oldVertices[indexValue];
					reMappedVertices.push_back(vertex);

					if (hasNormal)
					{
						reMappedNormals.push_back(oldNormals[indexValue]);
					}

					updateBoundingBoxes(bboxMin, bboxMax, vertex, vertex);
					splitMeshVertexCount++;
				}
				newFace.push_back(reIndexMap[indexValue]);
				serialisedFaces.push_back(reIndexMap[indexValue]);
			}//for (const auto &indexValue : currentFace)
			newFaces.push_back(newFace);

		}//else nSides != 3
		splitMeshFaceCount++;
	}//for (uint32_t fIdx = 0; fIdx < currentMeshNumFaces; ++fIdx)

	//Modify the vertices as it may be rearranged within this region
	std::copy(reMappedVertices.begin(), reMappedVertices.end(), newVertices.begin() + newVerticesVFrom);
	if (hasNormal)
		std::copy(reMappedNormals.begin(), reMappedNormals.end(), newNormals.begin() + newVerticesVFrom);

	updateIDMapArray(splitMeshVertexCount, idMapIdx);

	totalVertexCount += splitMeshVertexCount;
	totalFaceCount += splitMeshFaceCount;

	auto leftOverVertices = currentMeshNumVertices - totalVertexCount;

	if (leftOverVertices)
	{
		auto startingPos = newVertices.begin() + newMappings.back().vertFrom + totalVertexCount;

		//Chop out the unwanted vertices
		newVertices.erase(startingPos, startingPos + leftOverVertices);
		if (hasNormal)
			newNormals.erase(startingPos, startingPos + leftOverVertices);
	}

	splitMap[currentSubMesh.mesh_id].push_back(newMappings.size());
	finishSubMesh(newMappings.back(), bboxMin, bboxMax, splitMeshVertexCount, splitMeshFaceCount);
}

void MeshMapReorganiser::startSubMesh(
	repo_mesh_mapping_t &mapping,
	const repoUUID      &meshID,
	const repoUUID      &matID,
	const size_t        &sVertices,
	const size_t        &sFaces
	)
{
	mapping.vertFrom = sVertices;
	mapping.vertFrom = sFaces;
	mapping.material_id = matID; //Not a reliable source. Just filled in for completeness
	mapping.mesh_id = meshID;

	idMapBuf.resize(idMapBuf.size() + 1);
	idMapBuf.back().clear();
	matMap.resize(matMap.size() + 1);
	matMap.back().clear();
}

void MeshMapReorganiser::updateBoundingBoxes(
	std::vector<float>  &min,
	std::vector<float>  &max,
	const repo_vector_t &smMin,
	const repo_vector_t &smMax)
{
	//Update Bounding box
	if (min.size())
	{
		if (min[0] > smMin.x)
			min[0] = smMin.x;

		if (min[1] > smMin.y)
			min[1] = smMin.y;

		if (min[2] > smMin.z)
			min[2] = smMin.z;
	}
	else
	{
		min = { smMin.x, smMin.y, smMin.z };
	}

	if (max.size())
	{
		if (max[0] < smMax.x)
			max[0] = smMax.x;

		if (max[1] < smMax.y)
			max[1] = smMax.y;

		if (max[2] < smMax.z)
			max[2] = smMax.z;
	}
	else
	{
		max = { smMax.x, smMax.y, smMax.z };
	}
}

void MeshMapReorganiser::updateIDMapArray(
	const size_t &n,
	const size_t &value)
{
	auto idMapLength = idMapBuf.back().size();
	idMapBuf.back().resize(idMapLength + n);

	float value_f = value;
	std::fill(idMapBuf.back().begin() + idMapLength, idMapBuf.back().end(), value_f);
}<|endoftext|>


<commit_before>#include "QPlayControl.h"

#include <QToolButton>
#include <QWidget>
#include <QComboBox>

QPlayControl::QPlayControl( QWidget *parent /*= 0 */ ) :
currentTime( 0.0 ),
skipTime( 0.01 ),
slomoFactor( 1.0 ),
minTime( 0.0 ),
maxTime( 1.0 ),
autoExtendRange( false )
{
	playButton = new QToolButton( this );
	playButton->setIcon( style()->standardIcon( QStyle::SP_MediaPlay ) );
	connect( playButton, SIGNAL( clicked() ), this, SLOT( play() ) );

	stopButton = new QToolButton( this );
	stopButton->setIcon( style()->standardIcon( QStyle::SP_MediaStop ) );
	connect( stopButton, SIGNAL( clicked() ), this, SLOT( stop() ) );

	nextButton = new QToolButton( this );
	nextButton->setIcon( style()->standardIcon( QStyle::SP_MediaSkipForward ) );
	connect( nextButton, SIGNAL( clicked() ), this, SLOT( next() ) );

	previousButton = new QToolButton( this );
	previousButton->setIcon( style()->standardIcon( QStyle::SP_MediaSkipBackward ) );
	connect( previousButton, SIGNAL( clicked() ), this, SLOT( previous() ) );

	loopButton = new QToolButton( this );
	loopButton->setCheckable( true );
	loopButton->setIcon( style()->standardIcon( QStyle::SP_BrowserReload ) );

	label = new QLCDNumber( this );
	label->setDigitCount( 5 );
	label->setSmallDecimalPoint( true );
	label->setFrameStyle( QFrame::Box );
	label->setSegmentStyle( QLCDNumber::Flat );
	label->display( "0.00" );

	slider = new QSlider( Qt::Horizontal, this );
	slider->setSingleStep( 10 );
	slider->setPageStep( 100 );
	connect( slider, SIGNAL( valueChanged( int ) ), this, SLOT( updateSlider( int ) ) );
	connect( slider, SIGNAL( sliderReleased() ), this, SIGNAL( sliderReleased() ) );

	slowMotionBox = new QComboBox( this );
	for ( int slomo = 2; slomo >= -5; --slomo )
	{
		QString label = slomo >= 0 ? QString().sprintf( "%d x", (int)pow( 2, slomo ) ) : QString().sprintf( "1/%d x", (int)pow( 2, -slomo ) );
		slowMotionBox->addItem( label, QVariant( pow( 2, slomo ) ) );
	}
	slowMotionBox->setCurrentIndex( 2 );
	connect( slowMotionBox, SIGNAL( activated( int ) ), SLOT( updateSlowMotion( int ) ) );

	QBoxLayout *lo = new QHBoxLayout;
	lo->setMargin( 0 );
	lo->setSpacing( 2 );
	lo->addWidget( previousButton );
	lo->addWidget( playButton );
	lo->addWidget( stopButton );
	lo->addWidget( nextButton );
	lo->addWidget( label );
	lo->addWidget( slider );
	lo->addWidget( loopButton );
	lo->addWidget( slowMotionBox );
	setLayout( lo );

	connect( &qtimer, SIGNAL( timeout() ), this, SLOT( timeout() ) );
}

void QPlayControl::setRange( double min, double max )
{
	minTime = min;
	maxTime = max;
	slider->setRange( static_cast< int >( 1000 * minTime + 0.5 ), static_cast< int >( 1000 * maxTime + 0.5 ) );
}

void QPlayControl::setTime( double time )
{
	currentTime = time;

	if ( currentTime > maxTime )
	{
		if ( getAutoExtendRange() )
		{
			// adjust maximum
			setRange( minTime, currentTime );
		}
		else if ( getLoop() )
		{
			// restart
			currentTime = minTime;
		}
		else
		{
			// stop playing
			currentTime = maxTime;
			stop();
		}
	}

	slider->setValue( int( currentTime * 1000 ) );
	label->display( QString().sprintf( "%.2f", currentTime ) );

	emit timeChanged( currentTime );
}

bool QPlayControl::getLoop()
{
	return loopButton->isChecked();
}

bool QPlayControl::isPlaying()
{
	return qtimer.isActive();
}

void QPlayControl::setLoop( bool b )
{
	loopButton->setChecked( b );
}

void QPlayControl::play()
{
	if ( currentTime >= maxTime )
		reset();
	qtimer.start( 10 );
	timer.reset();
	timer_delta.reset();
	emit playTriggered();
}

void QPlayControl::stop()
{
	if ( qtimer.isActive() )
	{
		qtimer.stop();
		emit stopTriggered();
	}
	else reset();
}

void QPlayControl::toggle()
{
	if ( isPlaying() )
		stop();
	else play();
}

void QPlayControl::reset()
{
	if ( qtimer.isActive() )
		qtimer.stop();

	setTime( 0 );
	emit resetTriggered();
}

void QPlayControl::previous()
{
	setTime( currentTime - skipTime );
	emit previousTriggered();
}

void QPlayControl::next()
{
	setTime( currentTime + skipTime );
	emit nextTriggered();
}

void QPlayControl::updateSlowMotion( int idx )
{
	slomoFactor = slowMotionBox->itemData( idx ).toDouble();
	emit slowMotionChanged( slowMotionBox->itemData( idx ).toInt() );
}

void QPlayControl::updateSlider( int value )
{
	setTime( value / 1000.0 );
	emit timeChanged( currentTime );
	emit sliderChanged( value );
}

void QPlayControl::timeout()
{
	setTime( currentTime + slomoFactor * timer_delta( timer.seconds() ) );
}
<commit_msg>qplaycontrol fix: now blocks redundant inputs from slider<commit_after>#include "QPlayControl.h"

#include <QToolButton>
#include <QWidget>
#include <QComboBox>
#include "flut/system/log.hpp"

QPlayControl::QPlayControl( QWidget *parent /*= 0 */ ) :
currentTime( 0.0 ),
skipTime( 0.01 ),
slomoFactor( 1.0 ),
minTime( 0.0 ),
maxTime( 1.0 ),
autoExtendRange( false )
{
	playButton = new QToolButton( this );
	playButton->setIcon( style()->standardIcon( QStyle::SP_MediaPlay ) );
	connect( playButton, SIGNAL( clicked() ), this, SLOT( play() ) );

	stopButton = new QToolButton( this );
	stopButton->setIcon( style()->standardIcon( QStyle::SP_MediaStop ) );
	connect( stopButton, SIGNAL( clicked() ), this, SLOT( stop() ) );

	nextButton = new QToolButton( this );
	nextButton->setIcon( style()->standardIcon( QStyle::SP_MediaSkipForward ) );
	connect( nextButton, SIGNAL( clicked() ), this, SLOT( next() ) );

	previousButton = new QToolButton( this );
	previousButton->setIcon( style()->standardIcon( QStyle::SP_MediaSkipBackward ) );
	connect( previousButton, SIGNAL( clicked() ), this, SLOT( previous() ) );

	loopButton = new QToolButton( this );
	loopButton->setCheckable( true );
	loopButton->setIcon( style()->standardIcon( QStyle::SP_BrowserReload ) );

	label = new QLCDNumber( this );
	label->setDigitCount( 5 );
	label->setSmallDecimalPoint( true );
	label->setFrameStyle( QFrame::Box );
	label->setSegmentStyle( QLCDNumber::Flat );
	label->display( "0.00" );

	slider = new QSlider( Qt::Horizontal, this );
	slider->setSingleStep( 10 );
	slider->setPageStep( 100 );
	connect( slider, SIGNAL( valueChanged( int ) ), this, SLOT( updateSlider( int ) ) );
	connect( slider, SIGNAL( sliderReleased() ), this, SIGNAL( sliderReleased() ) );

	slowMotionBox = new QComboBox( this );
	for ( int slomo = 2; slomo >= -5; --slomo )
	{
		QString label = slomo >= 0 ? QString().sprintf( "%d x", (int)pow( 2, slomo ) ) : QString().sprintf( "1/%d x", (int)pow( 2, -slomo ) );
		slowMotionBox->addItem( label, QVariant( pow( 2, slomo ) ) );
	}
	slowMotionBox->setCurrentIndex( 2 );
	connect( slowMotionBox, SIGNAL( activated( int ) ), SLOT( updateSlowMotion( int ) ) );

	QBoxLayout *lo = new QHBoxLayout;
	lo->setMargin( 0 );
	lo->setSpacing( 2 );
	lo->addWidget( previousButton );
	lo->addWidget( playButton );
	lo->addWidget( stopButton );
	lo->addWidget( nextButton );
	lo->addWidget( label );
	lo->addWidget( slider );
	lo->addWidget( loopButton );
	lo->addWidget( slowMotionBox );
	setLayout( lo );

	connect( &qtimer, SIGNAL( timeout() ), this, SLOT( timeout() ) );
}

void QPlayControl::setRange( double min, double max )
{
	minTime = min;
	maxTime = max;
	slider->setRange( static_cast< int >( 1000 * minTime + 0.5 ), static_cast< int >( 1000 * maxTime + 0.5 ) );
}

void QPlayControl::setTime( double time )
{
	currentTime = time;

	if ( currentTime > maxTime )
	{
		if ( getAutoExtendRange() )
		{
			// adjust maximum
			setRange( minTime, currentTime );
		}
		else if ( getLoop() )
		{
			// restart
			currentTime = minTime;
		}
		else
		{
			// stop playing
			currentTime = maxTime;
			stop();
		}
	}

	slider->blockSignals( true );
	slider->setValue( int( currentTime * 1000 ) );
	slider->blockSignals( false );

	label->display( QString().sprintf( "%.2f", currentTime ) );

	emit timeChanged( currentTime );
}

bool QPlayControl::getLoop()
{
	return loopButton->isChecked();
}

bool QPlayControl::isPlaying()
{
	return qtimer.isActive();
}

void QPlayControl::setLoop( bool b )
{
	loopButton->setChecked( b );
}

void QPlayControl::play()
{
	if ( !isPlaying() )
	{
		if ( currentTime >= maxTime )
			reset();
		qtimer.start( 10 );
		timer.reset();
		timer_delta.reset();
		emit playTriggered();
	}
}

void QPlayControl::stop()
{
	if ( qtimer.isActive() )
	{
		qtimer.stop();
		emit stopTriggered();
	}
	else reset();
}

void QPlayControl::toggle()
{
	if ( isPlaying() )
		stop();
	else play();
}

void QPlayControl::reset()
{
	if ( qtimer.isActive() )
		qtimer.stop();

	setTime( 0 );
	emit resetTriggered();
}

void QPlayControl::previous()
{
	setTime( currentTime - skipTime );
	emit previousTriggered();
}

void QPlayControl::next()
{
	setTime( currentTime + skipTime );
	emit nextTriggered();
}

void QPlayControl::updateSlowMotion( int idx )
{
	slomoFactor = slowMotionBox->itemData( idx ).toDouble();
	emit slowMotionChanged( slowMotionBox->itemData( idx ).toInt() );
}

void QPlayControl::updateSlider( int value )
{
	setTime( value / 1000.0 );
	emit sliderChanged( value );
}

void QPlayControl::timeout()
{
	setTime( currentTime + slomoFactor * timer_delta( timer.seconds() ) );
}
<|endoftext|>


<commit_before>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org

Copyright (c) 2000-2012 Torus Knot Software Ltd

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 "OgreGLSLESExtSupport.h"
#include "OgreLogManager.h"
#include "OgreRoot.h"

namespace Ogre
{
    //-----------------------------------------------------------------------------
	String logObjectInfo(const String& msg, const GLuint obj)
	{
		String logMessage = msg;

		if (obj > 0)
		{
			GLint infologLength = 0;

            if(glIsShader(obj))
            {
                glGetShaderiv(obj, GL_INFO_LOG_LENGTH, &infologLength);
                GL_CHECK_ERROR
            }
#if GL_EXT_separate_shader_objects
            else if(glIsProgramPipelineEXT(obj))
            {
                glValidateProgramPipelineEXT(obj);
                glGetProgramPipelineivEXT(obj, GL_INFO_LOG_LENGTH, &infologLength);
                GL_CHECK_ERROR
            }
#endif
            else if(glIsProgram(obj))
            {
                glValidateProgram(obj);
                glGetProgramiv(obj, GL_INFO_LOG_LENGTH, &infologLength);
                GL_CHECK_ERROR
            }

			if (infologLength > 1)
			{
				GLint charsWritten  = 0;

				char * infoLog = new char [infologLength];
				infoLog[0] = 0;

                if(glIsShader(obj))
                {
                    glGetShaderInfoLog(obj, infologLength, &charsWritten, infoLog);
                    GL_CHECK_ERROR
                }
#if GL_EXT_separate_shader_objects
                else if(Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability(RSC_SEPARATE_SHADER_OBJECTS) &&
                        glIsProgramPipelineEXT(obj))
                {
                    glGetProgramPipelineInfoLogEXT(obj, infologLength, &charsWritten, infoLog);
                    GL_CHECK_ERROR
                }
#endif
                else if(glIsProgram(obj))
                {
                    glGetProgramInfoLog(obj, infologLength, &charsWritten, infoLog);
                    GL_CHECK_ERROR
                }

				if (strlen(infoLog) > 0)
				{
					logMessage += "\n" + String(infoLog);
				}

				OGRE_DELETE [] infoLog;

				if (logMessage.size() > 0)
				{
					// remove ends of line in the end - so there will be no empty lines in the log.
					while( logMessage[logMessage.size() - 1] == '\n' )
					{
						logMessage.erase(logMessage.size() - 1, 1);
					}
					LogManager::getSingleton().logMessage(logMessage);
				}
			}
		}

		return logMessage;
	}

} // namespace Ogre
<commit_msg>iOS: Fix crash caused by missing GL function pointers with GLES 2 on iOS 4<commit_after>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org

Copyright (c) 2000-2012 Torus Knot Software Ltd

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 "OgreGLSLESExtSupport.h"
#include "OgreLogManager.h"
#include "OgreRoot.h"

namespace Ogre
{
    //-----------------------------------------------------------------------------
	String logObjectInfo(const String& msg, const GLuint obj)
	{
		String logMessage = msg;

		if (obj > 0)
		{
			GLint infologLength = 0;

            if(glIsShader(obj))
            {
                glGetShaderiv(obj, GL_INFO_LOG_LENGTH, &infologLength);
                GL_CHECK_ERROR
            }
#if GL_EXT_separate_shader_objects
            else if(Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability(RSC_SEPARATE_SHADER_OBJECTS) &&
                    glIsProgramPipelineEXT(obj))
            {
                glValidateProgramPipelineEXT(obj);
                glGetProgramPipelineivEXT(obj, GL_INFO_LOG_LENGTH, &infologLength);
                GL_CHECK_ERROR
            }
#endif
            else if(glIsProgram(obj))
            {
                glValidateProgram(obj);
                glGetProgramiv(obj, GL_INFO_LOG_LENGTH, &infologLength);
                GL_CHECK_ERROR
            }

			if (infologLength > 1)
			{
				GLint charsWritten  = 0;

				char * infoLog = new char [infologLength];
				infoLog[0] = 0;

                if(glIsShader(obj))
                {
                    glGetShaderInfoLog(obj, infologLength, &charsWritten, infoLog);
                    GL_CHECK_ERROR
                }
#if GL_EXT_separate_shader_objects
                else if(Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability(RSC_SEPARATE_SHADER_OBJECTS) &&
                        glIsProgramPipelineEXT(obj))
                {
                    glGetProgramPipelineInfoLogEXT(obj, infologLength, &charsWritten, infoLog);
                    GL_CHECK_ERROR
                }
#endif
                else if(glIsProgram(obj))
                {
                    glGetProgramInfoLog(obj, infologLength, &charsWritten, infoLog);
                    GL_CHECK_ERROR
                }

				if (strlen(infoLog) > 0)
				{
					logMessage += "\n" + String(infoLog);
				}

				OGRE_DELETE [] infoLog;

				if (logMessage.size() > 0)
				{
					// remove ends of line in the end - so there will be no empty lines in the log.
					while( logMessage[logMessage.size() - 1] == '\n' )
					{
						logMessage.erase(logMessage.size() - 1, 1);
					}
					LogManager::getSingleton().logMessage(logMessage);
				}
			}
		}

		return logMessage;
	}

} // namespace Ogre
<|endoftext|>


<commit_before>#include <SensekitUL/streams/Depth.h>
#include <SenseKit/Plugins/plugin_capi.h>
#include <SenseKit/sensekit_capi.h>
#include <Sensekit/SenseKit.h>
#include <SenseKit/sensekit_types.h>

#include <memory>
#include <chrono>
#include <iostream>
#include <iomanip>

#include <SFML/Graphics.hpp>

#include "LitDepthVisualizer.h"
#include <common/serialization/FrameStreamWriter.h>
#include <common/serialization/FrameOutputStream.h>

using namespace sensekit::serialization;

class PointFrameListener : public sensekit::FrameReadyListener
{
public:
    PointFrameListener(sensekit::PointStream& pointStream)
    {
        m_lastTimepoint = clock_type::now();
    }

    ~PointFrameListener()
    {

    }

    void init_texture(int width, int height)
    {
        if (m_displayBuffer == nullptr || width != m_displayWidth || height != m_displayHeight)
        {
            m_displayWidth = width;
            m_displayHeight = height;

            // texture is RGBA
            int byteLength = m_displayWidth * m_displayHeight * 4;

            m_displayBuffer = BufferPtr(new uint8_t[byteLength]);
            memset(m_displayBuffer.get(), 0, byteLength);

            m_texture.create(m_displayWidth, m_displayHeight);
            m_sprite.setTexture(m_texture);
            m_sprite.setPosition(0, 0);
        }
    }

    void check_fps()
    {
        const double frameWeight = 0.2;

        auto newTimepoint = clock_type::now();
        auto frameDuration = std::chrono::duration_cast<duration_type>(newTimepoint - m_lastTimepoint);

        m_frameDuration = frameDuration * frameWeight + m_frameDuration * (1 - frameWeight);
        m_lastTimepoint = newTimepoint;

        double fps = 1.0 / m_frameDuration.count();

        auto precision = std::cout.precision();
        std::cout << std::fixed
            << std::setprecision(1)
            << fps << " fps ("
            << std::setprecision(2)
            << frameDuration.count() * 1000 << " ms)"
            << std::setprecision(precision)
            << std::endl;
    }

    virtual void on_frame_ready(sensekit::StreamReader& reader,
                                sensekit::Frame& frame) override
    {
        sensekit::PointFrame pointFrame = frame.get<sensekit::PointFrame>();

        int width = pointFrame.resolutionX();
        int height = pointFrame.resolutionY();

        init_texture(width, height);

        m_visualizer.update(pointFrame);

        sensekit_rgb_pixel_t* vizBuffer = m_visualizer.get_output();
        for (int i = 0; i < width * height; i++)
        {
            int rgbaOffset = i * 4;
            m_displayBuffer[rgbaOffset] = vizBuffer[i].r;
            m_displayBuffer[rgbaOffset + 1] = vizBuffer[i].b;
            m_displayBuffer[rgbaOffset + 2] = vizBuffer[i].g;
            m_displayBuffer[rgbaOffset + 3] = 255;
        }
        m_texture.update(m_displayBuffer.get());

        if (m_shouldCheckFps)
        {
            check_fps();
        }
    }

    void set_shouldcheckfps(bool shouldCheckFps)
    {
        m_shouldCheckFps = shouldCheckFps;
    }

    void drawTo(sf::RenderWindow& window)
    {
        if (m_displayBuffer != nullptr)
        {
            float depthScale = window.getView().getSize().x / m_displayWidth;

            m_sprite.setScale(depthScale, depthScale);

            window.draw(m_sprite);
        }
    }

private:
    samples::common::LitDepthVisualizer m_visualizer;

    using duration_type = std::chrono::duration<double>;
    duration_type m_frameDuration{0.0};

    using clock_type = std::chrono::system_clock;
    std::chrono::time_point<clock_type> m_lastTimepoint;
    sf::Texture m_texture;
    sf::Sprite m_sprite;

    using BufferPtr = std::unique_ptr<uint8_t[]>;
    BufferPtr m_displayBuffer{ nullptr };
    int m_displayWidth{0};
    int m_displayHeight{0};

    bool m_shouldCheckFps{false};
};

class DepthFrameListener : public sensekit::FrameReadyListener
{
public:
    DepthFrameListener(sensekit::DepthStream& depthStream, FrameStreamWriter& serializer)
        : m_frameStreamWriter(serializer)
    {

    }

    ~DepthFrameListener()
    {

    }

    virtual void on_frame_ready(sensekit::StreamReader& reader,
                                sensekit::Frame& frame) override
    {
        sensekit::DepthFrame depthFrame = frame.get<sensekit::DepthFrame>();

        m_frameStreamWriter.write(depthFrame);
    }

private:

    FrameStreamWriter& m_frameStreamWriter;
};

enum class AppState
{
    STANDBY,
    PLAY,
    RECORD
};

class AppStateManager
{
public:
    AppStateManager()
        : m_appState(AppState::STANDBY)
    {

    }

    AppState get_app_state()
    {
        return m_appState;
    }

    void set_app_state(AppState appState)
    {
        m_appState = appState;
    }

private:
    AppState m_appState;
};

void handle_escape_event(sf::Keyboard::Key key, sf::RenderWindow& window, AppStateManager& appStateManager)
{
    AppState appState = appStateManager.get_app_state();

    if (key == sf::Keyboard::Escape)
    {
        window.close();
    }
}

void handle_play_event(sf::Keyboard::Key key, PointFrameListener& streamPlayerPsListener, AppStateManager& appStateManager)
{
    AppState appState = appStateManager.get_app_state();

    if (key == sf::Keyboard::P && appState == AppState::STANDBY)
    {
        streamPlayerPsListener.set_shouldcheckfps(true);
        appStateManager.set_app_state(AppState::PLAY);
    }
}

void handle_stop_event(sf::Keyboard::Key key, PointFrameListener& streamPlayerPsListener, AppStateManager& appStateManager)
{
    AppState appState = appStateManager.get_app_state();

    if (key == sf::Keyboard::S && appState == AppState::PLAY)
    {
        streamPlayerPsListener.set_shouldcheckfps(false);
        appStateManager.set_app_state(AppState::STANDBY);
    }
}

void handle_record_event(sf::Keyboard::Key key, PointFrameListener& sensorPsListener, FrameStreamWriter& streamWriter, AppStateManager& appStateManager)
{
    AppState appState = appStateManager.get_app_state();

    if (key == sf::Keyboard::R)
    {
        if (appState == AppState::STANDBY)
        {
            sensorPsListener.set_shouldcheckfps(true);
            streamWriter.begin_write();
            appStateManager.set_app_state(AppState::RECORD);
        }
        if (appState == AppState::RECORD)
        {
            sensorPsListener.set_shouldcheckfps(false);
            streamWriter.end_write();
            appStateManager.set_app_state(AppState::STANDBY);
        }
    }
}

int main(int argc, char** argv)
{
    AppStateManager appStateManager;

    FILE* outputFile = fopen("test.df", "wb");;

    std::unique_ptr<FrameOutputStream> outputStream =
        std::unique_ptr<FrameOutputStream>(open_frame_output_stream(outputFile));
    FrameStreamWriter streamWriter(*outputStream.get());

    sensekit::SenseKit::initialize();

    sf::RenderWindow window(sf::VideoMode(1280, 960), "Stream Recorder");

    sensekit::Sensor sensor;
    sensekit::StreamReader sensorReader = sensor.create_reader();

    sensekit::Sensor streamPlayer("stream_player");
    sensekit::StreamReader streamPlayerReader = streamPlayer.create_reader();

    auto sensorDs = sensorReader.stream<sensekit::DepthStream>();
    auto sensorPs = sensorReader.stream<sensekit::PointStream>();
    auto streamPlayerPs = streamPlayerReader.stream<sensekit::PointStream>();

    sensorDs.start();
    sensorPs.start();

    DepthFrameListener sensorDsListener(sensorDs, streamWriter);
    PointFrameListener sensorPsListener(sensorPs);
    PointFrameListener streamPlayerPsListener(streamPlayerPs);

    sensorReader.addListener(sensorDsListener);
    sensorReader.addListener(sensorPsListener);
    streamPlayerReader.addListener(streamPlayerPsListener);

    while (window.isOpen())
    {
        sensekit_temp_update();

        sf::Event event;

        window.clear(sf::Color::Black);

        while (window.pollEvent(event))
        {
            switch (event.type)
            {
                case sf::Event::Closed:
                    window.close();
                    break;
                case sf::Event::KeyPressed:
                    sf::Keyboard::Key key = event.key.code;
                    handle_escape_event(key, window, appStateManager);
                    handle_stop_event(key, streamPlayerPsListener, appStateManager);
                    handle_record_event(key, sensorPsListener, streamWriter, appStateManager);
                    handle_play_event(key, streamPlayerPsListener, appStateManager);
                    break;
            }
        }

        AppState appState = appStateManager.get_app_state();

        if (appState == AppState::PLAY)
        {
            streamPlayerPsListener.drawTo(window);
        }
        else if (appState == AppState::RECORD)
        {
            sensorPsListener.drawTo(window);
        }

        window.display();
    }

    sensekit::SenseKit::terminate();

    outputStream.reset();
    fclose(outputFile);

    return 0;
}
<commit_msg>Removes unnecessary parameter from handle_escape_event in StreamRecorder.<commit_after>#include <SensekitUL/streams/Depth.h>
#include <SenseKit/Plugins/plugin_capi.h>
#include <SenseKit/sensekit_capi.h>
#include <Sensekit/SenseKit.h>
#include <SenseKit/sensekit_types.h>

#include <memory>
#include <chrono>
#include <iostream>
#include <iomanip>

#include <SFML/Graphics.hpp>

#include "LitDepthVisualizer.h"
#include <common/serialization/FrameStreamWriter.h>
#include <common/serialization/FrameOutputStream.h>

using namespace sensekit::serialization;

class PointFrameListener : public sensekit::FrameReadyListener
{
public:
    PointFrameListener(sensekit::PointStream& pointStream)
    {
        m_lastTimepoint = clock_type::now();
    }

    ~PointFrameListener()
    {

    }

    void init_texture(int width, int height)
    {
        if (m_displayBuffer == nullptr || width != m_displayWidth || height != m_displayHeight)
        {
            m_displayWidth = width;
            m_displayHeight = height;

            // texture is RGBA
            int byteLength = m_displayWidth * m_displayHeight * 4;

            m_displayBuffer = BufferPtr(new uint8_t[byteLength]);
            memset(m_displayBuffer.get(), 0, byteLength);

            m_texture.create(m_displayWidth, m_displayHeight);
            m_sprite.setTexture(m_texture);
            m_sprite.setPosition(0, 0);
        }
    }

    void check_fps()
    {
        const double frameWeight = 0.2;

        auto newTimepoint = clock_type::now();
        auto frameDuration = std::chrono::duration_cast<duration_type>(newTimepoint - m_lastTimepoint);

        m_frameDuration = frameDuration * frameWeight + m_frameDuration * (1 - frameWeight);
        m_lastTimepoint = newTimepoint;

        double fps = 1.0 / m_frameDuration.count();

        auto precision = std::cout.precision();
        std::cout << std::fixed
            << std::setprecision(1)
            << fps << " fps ("
            << std::setprecision(2)
            << frameDuration.count() * 1000 << " ms)"
            << std::setprecision(precision)
            << std::endl;
    }

    virtual void on_frame_ready(sensekit::StreamReader& reader,
                                sensekit::Frame& frame) override
    {
        sensekit::PointFrame pointFrame = frame.get<sensekit::PointFrame>();

        int width = pointFrame.resolutionX();
        int height = pointFrame.resolutionY();

        init_texture(width, height);

        m_visualizer.update(pointFrame);

        sensekit_rgb_pixel_t* vizBuffer = m_visualizer.get_output();
        for (int i = 0; i < width * height; i++)
        {
            int rgbaOffset = i * 4;
            m_displayBuffer[rgbaOffset] = vizBuffer[i].r;
            m_displayBuffer[rgbaOffset + 1] = vizBuffer[i].b;
            m_displayBuffer[rgbaOffset + 2] = vizBuffer[i].g;
            m_displayBuffer[rgbaOffset + 3] = 255;
        }
        m_texture.update(m_displayBuffer.get());

        if (m_shouldCheckFps)
        {
            check_fps();
        }
    }

    void set_shouldcheckfps(bool shouldCheckFps)
    {
        m_shouldCheckFps = shouldCheckFps;
    }

    void drawTo(sf::RenderWindow& window)
    {
        if (m_displayBuffer != nullptr)
        {
            float depthScale = window.getView().getSize().x / m_displayWidth;

            m_sprite.setScale(depthScale, depthScale);

            window.draw(m_sprite);
        }
    }

private:
    samples::common::LitDepthVisualizer m_visualizer;

    using duration_type = std::chrono::duration<double>;
    duration_type m_frameDuration{0.0};

    using clock_type = std::chrono::system_clock;
    std::chrono::time_point<clock_type> m_lastTimepoint;
    sf::Texture m_texture;
    sf::Sprite m_sprite;

    using BufferPtr = std::unique_ptr<uint8_t[]>;
    BufferPtr m_displayBuffer{ nullptr };
    int m_displayWidth{0};
    int m_displayHeight{0};

    bool m_shouldCheckFps{false};
};

class DepthFrameListener : public sensekit::FrameReadyListener
{
public:
    DepthFrameListener(sensekit::DepthStream& depthStream, FrameStreamWriter& serializer)
        : m_frameStreamWriter(serializer)
    {

    }

    ~DepthFrameListener()
    {

    }

    virtual void on_frame_ready(sensekit::StreamReader& reader,
                                sensekit::Frame& frame) override
    {
        sensekit::DepthFrame depthFrame = frame.get<sensekit::DepthFrame>();

        m_frameStreamWriter.write(depthFrame);
    }

private:

    FrameStreamWriter& m_frameStreamWriter;
};

enum class AppState
{
    STANDBY,
    PLAY,
    RECORD
};

class AppStateManager
{
public:
    AppStateManager()
        : m_appState(AppState::STANDBY)
    {

    }

    AppState get_app_state()
    {
        return m_appState;
    }

    void set_app_state(AppState appState)
    {
        m_appState = appState;
    }

private:
    AppState m_appState;
};

void handle_escape_event(sf::Keyboard::Key key, sf::RenderWindow& window)
{
    if (key == sf::Keyboard::Escape)
    {
        window.close();
    }
}

void handle_play_event(sf::Keyboard::Key key, PointFrameListener& streamPlayerPsListener, AppStateManager& appStateManager)
{
    AppState appState = appStateManager.get_app_state();

    if (key == sf::Keyboard::P && appState == AppState::STANDBY)
    {
        streamPlayerPsListener.set_shouldcheckfps(true);
        appStateManager.set_app_state(AppState::PLAY);
    }
}

void handle_stop_event(sf::Keyboard::Key key, PointFrameListener& streamPlayerPsListener, AppStateManager& appStateManager)
{
    AppState appState = appStateManager.get_app_state();

    if (key == sf::Keyboard::S && appState == AppState::PLAY)
    {
        streamPlayerPsListener.set_shouldcheckfps(false);
        appStateManager.set_app_state(AppState::STANDBY);
    }
}

void handle_record_event(sf::Keyboard::Key key, PointFrameListener& sensorPsListener, FrameStreamWriter& streamWriter, AppStateManager& appStateManager)
{
    AppState appState = appStateManager.get_app_state();

    if (key == sf::Keyboard::R)
    {
        if (appState == AppState::STANDBY)
        {
            sensorPsListener.set_shouldcheckfps(true);
            streamWriter.begin_write();
            appStateManager.set_app_state(AppState::RECORD);
        }
        if (appState == AppState::RECORD)
        {
            sensorPsListener.set_shouldcheckfps(false);
            streamWriter.end_write();
            appStateManager.set_app_state(AppState::STANDBY);
        }
    }
}

int main(int argc, char** argv)
{
    AppStateManager appStateManager;

    FILE* outputFile = fopen("test.df", "wb");;

    std::unique_ptr<FrameOutputStream> outputStream =
        std::unique_ptr<FrameOutputStream>(open_frame_output_stream(outputFile));
    FrameStreamWriter streamWriter(*outputStream.get());

    sensekit::SenseKit::initialize();

    sf::RenderWindow window(sf::VideoMode(1280, 960), "Stream Recorder");

    sensekit::Sensor sensor;
    sensekit::StreamReader sensorReader = sensor.create_reader();

    sensekit::Sensor streamPlayer("stream_player");
    sensekit::StreamReader streamPlayerReader = streamPlayer.create_reader();

    auto sensorDs = sensorReader.stream<sensekit::DepthStream>();
    auto sensorPs = sensorReader.stream<sensekit::PointStream>();
    auto streamPlayerPs = streamPlayerReader.stream<sensekit::PointStream>();

    sensorDs.start();
    sensorPs.start();

    DepthFrameListener sensorDsListener(sensorDs, streamWriter);
    PointFrameListener sensorPsListener(sensorPs);
    PointFrameListener streamPlayerPsListener(streamPlayerPs);

    sensorReader.addListener(sensorDsListener);
    sensorReader.addListener(sensorPsListener);
    streamPlayerReader.addListener(streamPlayerPsListener);

    while (window.isOpen())
    {
        sensekit_temp_update();

        sf::Event event;

        window.clear(sf::Color::Black);

        while (window.pollEvent(event))
        {
            switch (event.type)
            {
                case sf::Event::Closed:
                    window.close();
                    break;
                case sf::Event::KeyPressed:
                    sf::Keyboard::Key key = event.key.code;
                    handle_escape_event(key, window);
                    handle_stop_event(key, streamPlayerPsListener, appStateManager);
                    handle_record_event(key, sensorPsListener, streamWriter, appStateManager);
                    handle_play_event(key, streamPlayerPsListener, appStateManager);
                    break;
            }
        }

        AppState appState = appStateManager.get_app_state();

        if (appState == AppState::PLAY)
        {
            streamPlayerPsListener.drawTo(window);
        }
        else if (appState == AppState::RECORD)
        {
            sensorPsListener.drawTo(window);
        }

        window.display();
    }

    sensekit::SenseKit::terminate();

    outputStream.reset();
    fclose(outputFile);

    return 0;
}
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include <sal/config.h>
#include <unotest/filters-test.hxx>
#include <test/bootstrapfixture.hxx>
#include <rtl/strbuf.hxx>
#include <osl/file.hxx>

#include <sfx2/app.hxx>
#include <sfx2/docfilt.hxx>
#include <sfx2/docfile.hxx>
#include <sfx2/frame.hxx>
#include <sfx2/sfxmodelfactory.hxx>
#include <svl/stritem.hxx>

#include <unotools/tempfile.hxx>
#include <comphelper/storagehelper.hxx>

#define CALC_DEBUG_OUTPUT 0
#define TEST_BUG_FILES 0

#include "helper/qahelper.hxx"

#include "docsh.hxx"
#include "postit.hxx"
#include "patattr.hxx"
#include "scitems.hxx"
#include "document.hxx"
#include "cellform.hxx"

#define ODS_FORMAT_TYPE 50331943
#define XLS_FORMAT_TYPE 318767171
#define XLSX_FORMAT_TYPE 268959811
#define LOTUS123_FORMAT_TYPE 268435649

#define ODS     0
#define XLS     1
#define XLSX    2
#define LOTUS123 3

using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;

namespace {

struct FileFormat {
    const char* pName; const char* pFilterName; const char* pTypeName; sal_uLong nFormatType;
};

FileFormat aFileFormats[] = {
    { "ods" , "calc8", "", ODS_FORMAT_TYPE },
    { "xls" , "MS Excel 97", "calc_MS_EXCEL_97", XLS_FORMAT_TYPE },
    { "xlsx", "Calc MS Excel 2007 XML" , "MS Excel 2007 XML", XLSX_FORMAT_TYPE },
    { "123" , "Lotus", "calc_Lotus", LOTUS123_FORMAT_TYPE }
};

}

class ScExportTest : public test::BootstrapFixture
{
public:
    ScExportTest();

    virtual void setUp();
    virtual void tearDown();

    ScDocShellRef saveAndReload( ScDocShell*, const rtl::OUString&, const rtl::OUString&, const rtl::OUString&, sal_uLong );
    ScDocShellRef saveAndReloadPassword( ScDocShell*, const rtl::OUString&, const rtl::OUString&, const rtl::OUString&, sal_uLong );

    void test();
    void testPasswordExport();

    CPPUNIT_TEST_SUITE(ScExportTest);
    CPPUNIT_TEST(test);
#if !defined(MACOSX) && !defined(DRAGONFLY) && !defined(WNT)
    CPPUNIT_TEST(testPasswordExport);
#endif
    CPPUNIT_TEST_SUITE_END();

private:
    rtl::OUString m_aBaseString;
    uno::Reference<uno::XInterface> m_xCalcComponent;
};

/*
void ScFiltersTest::createFileURL(const rtl::OUString& aFileBase, const rtl::OUString& aFileExtension, rtl::OUString& rFilePath)
{
    rtl::OUString aSep(RTL_CONSTASCII_USTRINGPARAM("/"));
    rtl::OUStringBuffer aBuffer( getSrcRootURL() );
    aBuffer.append(m_aBaseString).append(aSep).append(aFileExtension);
    aBuffer.append(aSep).append(aFileBase).append(aFileExtension);
    rFilePath = aBuffer.makeStringAndClear();
}
*/

ScDocShellRef ScExportTest::saveAndReloadPassword(ScDocShell* pShell, const rtl::OUString &rFilter,
    const rtl::OUString &rUserData, const rtl::OUString& rTypeName, sal_uLong nFormatType)
{

    utl::TempFile aTempFile;
    //aTempFile.EnableKillingFile();
    SfxMedium aStoreMedium( aTempFile.GetURL(), STREAM_STD_WRITE );
    sal_uInt32 nExportFormat = 0;
    if (nFormatType)
        nExportFormat = SFX_FILTER_EXPORT | SFX_FILTER_USESOPTIONS;
    SfxFilter* pExportFilter = new SfxFilter(
        rFilter,
        rtl::OUString(), nFormatType, nExportFormat, rTypeName, 0, rtl::OUString(),
        rUserData, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("private:factory/scalc*")) );
    pExportFilter->SetVersion(SOFFICE_FILEFORMAT_CURRENT);
    aStoreMedium.SetFilter(pExportFilter);
    SfxItemSet* pExportSet = aStoreMedium.GetItemSet();
    uno::Sequence< beans::NamedValue > aEncryptionData = comphelper::OStorageHelper::CreatePackageEncryptionData( rtl::OUString("test") );
    uno::Any xEncryptionData;
    xEncryptionData <<= aEncryptionData;
    pExportSet->Put(SfxUnoAnyItem(SID_ENCRYPTIONDATA, xEncryptionData));

    uno::Reference< embed::XStorage > xMedStorage = aStoreMedium.GetStorage();
    ::comphelper::OStorageHelper::SetCommonStorageEncryptionData( xMedStorage, aEncryptionData );

    pShell->DoSaveAs( aStoreMedium );
    pShell->DoClose();

    std::cout << "File: " << aTempFile.GetURL() << std::endl;

    sal_uInt32 nFormat = 0;
    if (nFormatType)
        nFormat = SFX_FILTER_IMPORT | SFX_FILTER_USESOPTIONS;
    SfxFilter* pFilter = new SfxFilter(
        rFilter,
        rtl::OUString(), nFormatType, nFormat, rTypeName, 0, rtl::OUString(),
        rUserData, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("private:factory/scalc*")) );
    pFilter->SetVersion(SOFFICE_FILEFORMAT_CURRENT);

    ScDocShellRef xDocShRef = new ScDocShell;
    SfxMedium* pSrcMed = new SfxMedium(aTempFile.GetURL(), STREAM_STD_READ);
    SfxItemSet* pSet = pSrcMed->GetItemSet();
    pSet->Put(SfxStringItem(SID_PASSWORD, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("test"))));
    pSrcMed->SetFilter(pFilter);
    if (!xDocShRef->DoLoad(pSrcMed))
    {
        xDocShRef->DoClose();
        // load failed.
        xDocShRef.Clear();
    }

    return xDocShRef;
}

ScDocShellRef ScExportTest::saveAndReload(ScDocShell* pShell, const rtl::OUString &rFilter,
    const rtl::OUString &rUserData, const rtl::OUString& rTypeName, sal_uLong nFormatType)
{

    utl::TempFile aTempFile;
    aTempFile.EnableKillingFile();
    SfxMedium aStoreMedium( aTempFile.GetURL(), STREAM_STD_WRITE );
    sal_uInt32 nExportFormat = 0;
    if (nFormatType)
        nExportFormat = SFX_FILTER_EXPORT | SFX_FILTER_USESOPTIONS;
    SfxFilter* pExportFilter = new SfxFilter(
        rFilter,
        rtl::OUString(), nFormatType, nExportFormat, rTypeName, 0, rtl::OUString(),
        rUserData, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("private:factory/scalc*")) );
    pExportFilter->SetVersion(SOFFICE_FILEFORMAT_CURRENT);
    aStoreMedium.SetFilter(pExportFilter);
    pShell->DoSaveAs( aStoreMedium );
    pShell->DoClose();

    //std::cout << "File: " << aTempFile.GetURL() << std::endl;

    sal_uInt32 nFormat = 0;
    if (nFormatType)
        nFormat = SFX_FILTER_IMPORT | SFX_FILTER_USESOPTIONS;
    SfxFilter* pFilter = new SfxFilter(
        rFilter,
        rtl::OUString(), nFormatType, nFormat, rTypeName, 0, rtl::OUString(),
        rUserData, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("private:factory/scalc*")) );
    pFilter->SetVersion(SOFFICE_FILEFORMAT_CURRENT);

    ScDocShellRef xDocShRef = new ScDocShell;
    SfxMedium* pSrcMed = new SfxMedium(aTempFile.GetURL(), STREAM_STD_READ);
    pSrcMed->SetFilter(pFilter);
    if (!xDocShRef->DoLoad(pSrcMed))
    {
        xDocShRef->DoClose();
        // load failed.
        xDocShRef.Clear();
    }

    return xDocShRef;
}

void ScExportTest::test()
{
    ScDocShell* pShell = new ScDocShell(
        SFXMODEL_STANDARD |
        SFXMODEL_DISABLE_EMBEDDED_SCRIPTS |
        SFXMODEL_DISABLE_DOCUMENT_RECOVERY);
    pShell->DoInitNew();

    ScDocument* pDoc = pShell->GetDocument();

    pDoc->SetValue(0,0,0, 1.0);
    CPPUNIT_ASSERT(pDoc);

    sal_Int32 nFormat = ODS;
    rtl::OUString aFileExtension(aFileFormats[nFormat].pName, strlen(aFileFormats[nFormat].pName), RTL_TEXTENCODING_UTF8 );
    rtl::OUString aFilterName(aFileFormats[nFormat].pFilterName, strlen(aFileFormats[nFormat].pFilterName), RTL_TEXTENCODING_UTF8) ;
    rtl::OUString aFilterType(aFileFormats[nFormat].pTypeName, strlen(aFileFormats[nFormat].pTypeName), RTL_TEXTENCODING_UTF8);
    ScDocShellRef xDocSh = saveAndReload(pShell, aFilterName, rtl::OUString(), aFilterType, aFileFormats[nFormat].nFormatType);

    CPPUNIT_ASSERT(xDocSh.Is());
    ScDocument* pLoadedDoc = xDocSh->GetDocument();
    double aVal = pLoadedDoc->GetValue(0,0,0);
    CPPUNIT_ASSERT_DOUBLES_EQUAL(aVal, 1.0, 1e-8);
}

void ScExportTest::testPasswordExport()
{
    ScDocShell* pShell = new ScDocShell(
        SFXMODEL_STANDARD |
        SFXMODEL_DISABLE_EMBEDDED_SCRIPTS |
        SFXMODEL_DISABLE_DOCUMENT_RECOVERY);
    pShell->DoInitNew();

    ScDocument* pDoc = pShell->GetDocument();

    pDoc->SetValue(0,0,0, 1.0);
    CPPUNIT_ASSERT(pDoc);

    sal_Int32 nFormat = ODS;
    rtl::OUString aFileExtension(aFileFormats[nFormat].pName, strlen(aFileFormats[nFormat].pName), RTL_TEXTENCODING_UTF8 );
    rtl::OUString aFilterName(aFileFormats[nFormat].pFilterName, strlen(aFileFormats[nFormat].pFilterName), RTL_TEXTENCODING_UTF8) ;
    rtl::OUString aFilterType(aFileFormats[nFormat].pTypeName, strlen(aFileFormats[nFormat].pTypeName), RTL_TEXTENCODING_UTF8);
    ScDocShellRef xDocSh = saveAndReloadPassword(pShell, aFilterName, rtl::OUString(), aFilterType, aFileFormats[nFormat].nFormatType);

    CPPUNIT_ASSERT(xDocSh.Is());
    ScDocument* pLoadedDoc = xDocSh->GetDocument();
    double aVal = pLoadedDoc->GetValue(0,0,0);
    CPPUNIT_ASSERT_DOUBLES_EQUAL(aVal, 1.0, 1e-8);
}

ScExportTest::ScExportTest()
      : m_aBaseString(RTL_CONSTASCII_USTRINGPARAM("/sc/qa/unit/data"))
{
}

void ScExportTest::setUp()
{
    test::BootstrapFixture::setUp();

    // This is a bit of a fudge, we do this to ensure that ScGlobals::ensure,
    // which is a private symbol to us, gets called
    m_xCalcComponent =
        getMultiServiceFactory()->createInstance(rtl::OUString(
        RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.Calc.SpreadsheetDocument")));
    CPPUNIT_ASSERT_MESSAGE("no calc component!", m_xCalcComponent.is());
}

void ScExportTest::tearDown()
{
    uno::Reference< lang::XComponent >( m_xCalcComponent, UNO_QUERY_THROW )->dispose();
    test::BootstrapFixture::tearDown();
}

CPPUNIT_TEST_SUITE_REGISTRATION(ScExportTest);

CPPUNIT_PLUGIN_IMPLEMENT();

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>remove the temp file after loading<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include <sal/config.h>
#include <unotest/filters-test.hxx>
#include <test/bootstrapfixture.hxx>
#include <rtl/strbuf.hxx>
#include <osl/file.hxx>

#include <sfx2/app.hxx>
#include <sfx2/docfilt.hxx>
#include <sfx2/docfile.hxx>
#include <sfx2/frame.hxx>
#include <sfx2/sfxmodelfactory.hxx>
#include <svl/stritem.hxx>

#include <unotools/tempfile.hxx>
#include <comphelper/storagehelper.hxx>

#define CALC_DEBUG_OUTPUT 0
#define TEST_BUG_FILES 0

#include "helper/qahelper.hxx"

#include "docsh.hxx"
#include "postit.hxx"
#include "patattr.hxx"
#include "scitems.hxx"
#include "document.hxx"
#include "cellform.hxx"

#define ODS_FORMAT_TYPE 50331943
#define XLS_FORMAT_TYPE 318767171
#define XLSX_FORMAT_TYPE 268959811
#define LOTUS123_FORMAT_TYPE 268435649

#define ODS     0
#define XLS     1
#define XLSX    2
#define LOTUS123 3

using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;

namespace {

struct FileFormat {
    const char* pName; const char* pFilterName; const char* pTypeName; sal_uLong nFormatType;
};

FileFormat aFileFormats[] = {
    { "ods" , "calc8", "", ODS_FORMAT_TYPE },
    { "xls" , "MS Excel 97", "calc_MS_EXCEL_97", XLS_FORMAT_TYPE },
    { "xlsx", "Calc MS Excel 2007 XML" , "MS Excel 2007 XML", XLSX_FORMAT_TYPE },
    { "123" , "Lotus", "calc_Lotus", LOTUS123_FORMAT_TYPE }
};

}

class ScExportTest : public test::BootstrapFixture
{
public:
    ScExportTest();

    virtual void setUp();
    virtual void tearDown();

    ScDocShellRef saveAndReload( ScDocShell*, const rtl::OUString&, const rtl::OUString&, const rtl::OUString&, sal_uLong );
    ScDocShellRef saveAndReloadPassword( ScDocShell*, const rtl::OUString&, const rtl::OUString&, const rtl::OUString&, sal_uLong );

    void test();
    void testPasswordExport();

    CPPUNIT_TEST_SUITE(ScExportTest);
    CPPUNIT_TEST(test);
#if !defined(MACOSX) && !defined(DRAGONFLY) && !defined(WNT)
    CPPUNIT_TEST(testPasswordExport);
#endif
    CPPUNIT_TEST_SUITE_END();

private:
    rtl::OUString m_aBaseString;
    uno::Reference<uno::XInterface> m_xCalcComponent;
};

/*
void ScFiltersTest::createFileURL(const rtl::OUString& aFileBase, const rtl::OUString& aFileExtension, rtl::OUString& rFilePath)
{
    rtl::OUString aSep(RTL_CONSTASCII_USTRINGPARAM("/"));
    rtl::OUStringBuffer aBuffer( getSrcRootURL() );
    aBuffer.append(m_aBaseString).append(aSep).append(aFileExtension);
    aBuffer.append(aSep).append(aFileBase).append(aFileExtension);
    rFilePath = aBuffer.makeStringAndClear();
}
*/

ScDocShellRef ScExportTest::saveAndReloadPassword(ScDocShell* pShell, const rtl::OUString &rFilter,
    const rtl::OUString &rUserData, const rtl::OUString& rTypeName, sal_uLong nFormatType)
{

    utl::TempFile aTempFile;
    aTempFile.EnableKillingFile();
    SfxMedium aStoreMedium( aTempFile.GetURL(), STREAM_STD_WRITE );
    sal_uInt32 nExportFormat = 0;
    if (nFormatType)
        nExportFormat = SFX_FILTER_EXPORT | SFX_FILTER_USESOPTIONS;
    SfxFilter* pExportFilter = new SfxFilter(
        rFilter,
        rtl::OUString(), nFormatType, nExportFormat, rTypeName, 0, rtl::OUString(),
        rUserData, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("private:factory/scalc*")) );
    pExportFilter->SetVersion(SOFFICE_FILEFORMAT_CURRENT);
    aStoreMedium.SetFilter(pExportFilter);
    SfxItemSet* pExportSet = aStoreMedium.GetItemSet();
    uno::Sequence< beans::NamedValue > aEncryptionData = comphelper::OStorageHelper::CreatePackageEncryptionData( rtl::OUString("test") );
    uno::Any xEncryptionData;
    xEncryptionData <<= aEncryptionData;
    pExportSet->Put(SfxUnoAnyItem(SID_ENCRYPTIONDATA, xEncryptionData));

    uno::Reference< embed::XStorage > xMedStorage = aStoreMedium.GetStorage();
    ::comphelper::OStorageHelper::SetCommonStorageEncryptionData( xMedStorage, aEncryptionData );

    pShell->DoSaveAs( aStoreMedium );
    pShell->DoClose();

    //std::cout << "File: " << aTempFile.GetURL() << std::endl;

    sal_uInt32 nFormat = 0;
    if (nFormatType)
        nFormat = SFX_FILTER_IMPORT | SFX_FILTER_USESOPTIONS;
    SfxFilter* pFilter = new SfxFilter(
        rFilter,
        rtl::OUString(), nFormatType, nFormat, rTypeName, 0, rtl::OUString(),
        rUserData, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("private:factory/scalc*")) );
    pFilter->SetVersion(SOFFICE_FILEFORMAT_CURRENT);

    ScDocShellRef xDocShRef = new ScDocShell;
    SfxMedium* pSrcMed = new SfxMedium(aTempFile.GetURL(), STREAM_STD_READ);
    SfxItemSet* pSet = pSrcMed->GetItemSet();
    pSet->Put(SfxStringItem(SID_PASSWORD, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("test"))));
    pSrcMed->SetFilter(pFilter);
    if (!xDocShRef->DoLoad(pSrcMed))
    {
        xDocShRef->DoClose();
        // load failed.
        xDocShRef.Clear();
    }

    return xDocShRef;
}

ScDocShellRef ScExportTest::saveAndReload(ScDocShell* pShell, const rtl::OUString &rFilter,
    const rtl::OUString &rUserData, const rtl::OUString& rTypeName, sal_uLong nFormatType)
{

    utl::TempFile aTempFile;
    aTempFile.EnableKillingFile();
    SfxMedium aStoreMedium( aTempFile.GetURL(), STREAM_STD_WRITE );
    sal_uInt32 nExportFormat = 0;
    if (nFormatType)
        nExportFormat = SFX_FILTER_EXPORT | SFX_FILTER_USESOPTIONS;
    SfxFilter* pExportFilter = new SfxFilter(
        rFilter,
        rtl::OUString(), nFormatType, nExportFormat, rTypeName, 0, rtl::OUString(),
        rUserData, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("private:factory/scalc*")) );
    pExportFilter->SetVersion(SOFFICE_FILEFORMAT_CURRENT);
    aStoreMedium.SetFilter(pExportFilter);
    pShell->DoSaveAs( aStoreMedium );
    pShell->DoClose();

    //std::cout << "File: " << aTempFile.GetURL() << std::endl;

    sal_uInt32 nFormat = 0;
    if (nFormatType)
        nFormat = SFX_FILTER_IMPORT | SFX_FILTER_USESOPTIONS;
    SfxFilter* pFilter = new SfxFilter(
        rFilter,
        rtl::OUString(), nFormatType, nFormat, rTypeName, 0, rtl::OUString(),
        rUserData, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("private:factory/scalc*")) );
    pFilter->SetVersion(SOFFICE_FILEFORMAT_CURRENT);

    ScDocShellRef xDocShRef = new ScDocShell;
    SfxMedium* pSrcMed = new SfxMedium(aTempFile.GetURL(), STREAM_STD_READ);
    pSrcMed->SetFilter(pFilter);
    if (!xDocShRef->DoLoad(pSrcMed))
    {
        xDocShRef->DoClose();
        // load failed.
        xDocShRef.Clear();
    }

    return xDocShRef;
}

void ScExportTest::test()
{
    ScDocShell* pShell = new ScDocShell(
        SFXMODEL_STANDARD |
        SFXMODEL_DISABLE_EMBEDDED_SCRIPTS |
        SFXMODEL_DISABLE_DOCUMENT_RECOVERY);
    pShell->DoInitNew();

    ScDocument* pDoc = pShell->GetDocument();

    pDoc->SetValue(0,0,0, 1.0);
    CPPUNIT_ASSERT(pDoc);

    sal_Int32 nFormat = ODS;
    rtl::OUString aFileExtension(aFileFormats[nFormat].pName, strlen(aFileFormats[nFormat].pName), RTL_TEXTENCODING_UTF8 );
    rtl::OUString aFilterName(aFileFormats[nFormat].pFilterName, strlen(aFileFormats[nFormat].pFilterName), RTL_TEXTENCODING_UTF8) ;
    rtl::OUString aFilterType(aFileFormats[nFormat].pTypeName, strlen(aFileFormats[nFormat].pTypeName), RTL_TEXTENCODING_UTF8);
    ScDocShellRef xDocSh = saveAndReload(pShell, aFilterName, rtl::OUString(), aFilterType, aFileFormats[nFormat].nFormatType);

    CPPUNIT_ASSERT(xDocSh.Is());
    ScDocument* pLoadedDoc = xDocSh->GetDocument();
    double aVal = pLoadedDoc->GetValue(0,0,0);
    CPPUNIT_ASSERT_DOUBLES_EQUAL(aVal, 1.0, 1e-8);
}

void ScExportTest::testPasswordExport()
{
    ScDocShell* pShell = new ScDocShell(
        SFXMODEL_STANDARD |
        SFXMODEL_DISABLE_EMBEDDED_SCRIPTS |
        SFXMODEL_DISABLE_DOCUMENT_RECOVERY);
    pShell->DoInitNew();

    ScDocument* pDoc = pShell->GetDocument();

    pDoc->SetValue(0,0,0, 1.0);
    CPPUNIT_ASSERT(pDoc);

    sal_Int32 nFormat = ODS;
    rtl::OUString aFileExtension(aFileFormats[nFormat].pName, strlen(aFileFormats[nFormat].pName), RTL_TEXTENCODING_UTF8 );
    rtl::OUString aFilterName(aFileFormats[nFormat].pFilterName, strlen(aFileFormats[nFormat].pFilterName), RTL_TEXTENCODING_UTF8) ;
    rtl::OUString aFilterType(aFileFormats[nFormat].pTypeName, strlen(aFileFormats[nFormat].pTypeName), RTL_TEXTENCODING_UTF8);
    ScDocShellRef xDocSh = saveAndReloadPassword(pShell, aFilterName, rtl::OUString(), aFilterType, aFileFormats[nFormat].nFormatType);

    CPPUNIT_ASSERT(xDocSh.Is());
    ScDocument* pLoadedDoc = xDocSh->GetDocument();
    double aVal = pLoadedDoc->GetValue(0,0,0);
    CPPUNIT_ASSERT_DOUBLES_EQUAL(aVal, 1.0, 1e-8);
}

ScExportTest::ScExportTest()
      : m_aBaseString(RTL_CONSTASCII_USTRINGPARAM("/sc/qa/unit/data"))
{
}

void ScExportTest::setUp()
{
    test::BootstrapFixture::setUp();

    // This is a bit of a fudge, we do this to ensure that ScGlobals::ensure,
    // which is a private symbol to us, gets called
    m_xCalcComponent =
        getMultiServiceFactory()->createInstance(rtl::OUString(
        RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.Calc.SpreadsheetDocument")));
    CPPUNIT_ASSERT_MESSAGE("no calc component!", m_xCalcComponent.is());
}

void ScExportTest::tearDown()
{
    uno::Reference< lang::XComponent >( m_xCalcComponent, UNO_QUERY_THROW )->dispose();
    test::BootstrapFixture::tearDown();
}

CPPUNIT_TEST_SUITE_REGISTRATION(ScExportTest);

CPPUNIT_PLUGIN_IMPLEMENT();

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>#include "cinder/app/AppNative.h"
#include "cinder/app/RendererGl.h"
#include "cinder/gl/gl.h"

#include "Choreograph.hpp"
#include "cinder/Easing.h"

using namespace ci;
using namespace ci::app;
using namespace std;

using namespace choreograph;

class ChoreographDevApp : public AppNative {
  public:
	void setup() override;
	void mouseDown( MouseEvent event ) override;
	void update() override;
	void draw() override;
private:
  float                 _ball_y;
  ci::vec2              _ball_2 = ci::vec2( 400.0f, 400.0f );
  float                 _ball_radius = 50.0f;
  co::Timeline          _anim;
};

void ChoreographDevApp::setup()
{
  auto &sequence = _anim.move( &_ball_y )
  .startFn( [] (Motion<float> &c) { cout << "Start red" << endl; } )
  .getSequence().set( 5.0f ).hold( 0.5f ).rampTo( 500.0f, 1.0f, EaseInOutQuad() ).hold( 500.0f, 0.33f ).rampTo( 700.0f, 1.0f ).hold( 20.0f, 1.0f ).set( 400.0f );

  _anim.move( &_ball_2 )
  .startFn( [] (Motion<vec2> &c) { cout << "Start blue" << endl; } )
  .finishFn( [] (Motion<vec2> &c) { c.playbackSpeed( c.getPlaybackSpeed() * -1.0f ); } )
  .continuous( true )
  .updateFn( [&] (const vec2 &v) {
    vec2 size = app::getWindowSize();
    float shortest = std::min( v.x, size.x - v.x );
    shortest = std::min( shortest, size.y - v.y );
    shortest = std::min( shortest, v.y );
    _ball_radius = shortest;
  } )
  .getSequence().rampTo( vec2( app::getWindowSize() ) / 2.0f, 2.0f ).rampTo( vec2( app::getWindowSize() ), 2.0f ).rampTo( vec2( app::getWindowWidth() / 2.0f, 10.0f ), 3.0f ).rampTo( vec2( app::getWindowSize() ) / 2.0f, 0.5f );

}

void ChoreographDevApp::mouseDown( MouseEvent event )
{
}

void ChoreographDevApp::update()
{
    _anim.step( 1.0f / 60.0f );
}

void ChoreographDevApp::draw()
{
	gl::clear( Color( 0, 0, 0 ) );

  gl::disableDepthRead();
  gl::disableDepthWrite();

  gl::clear( Color( 0, 0, 0 ) );
  gl::color( Color( 1.0f, 0.0f, 0.0f ) );
  gl::drawSolidCircle( vec2( 200.0f, _ball_y ), 120.0f );
  gl::color( 0.0f, 0.0f, 1.0f );
  gl::drawSolidCircle( _ball_2, _ball_radius );
}

CINDER_APP_NATIVE( ChoreographDevApp, RendererGl )
<commit_msg>Remove unused variable.<commit_after>#include "cinder/app/AppNative.h"
#include "cinder/app/RendererGl.h"
#include "cinder/gl/gl.h"

#include "Choreograph.hpp"
#include "cinder/Easing.h"

using namespace ci;
using namespace ci::app;
using namespace std;

using namespace choreograph;

class ChoreographDevApp : public AppNative {
  public:
	void setup() override;
	void mouseDown( MouseEvent event ) override;
	void update() override;
	void draw() override;
private:
  float                 _ball_y;
  ci::vec2              _ball_2 = ci::vec2( 400.0f, 400.0f );
  float                 _ball_radius = 50.0f;
  co::Timeline          _anim;
};

void ChoreographDevApp::setup()
{
  _anim.move( &_ball_y )
  .startFn( [] (Motion<float> &c) { cout << "Start red" << endl; } )
  .getSequence().set( 5.0f ).hold( 0.5f ).rampTo( 500.0f, 1.0f, EaseInOutQuad() ).hold( 500.0f, 0.33f ).rampTo( 700.0f, 1.0f ).hold( 20.0f, 1.0f ).set( 400.0f );

  _anim.move( &_ball_2 )
  .startFn( [] (Motion<vec2> &c) { cout << "Start blue" << endl; } )
  .finishFn( [] (Motion<vec2> &c) { c.playbackSpeed( c.getPlaybackSpeed() * -1.0f ); } )
  .continuous( true )
  .updateFn( [&] (const vec2 &v) {
    vec2 size = app::getWindowSize();
    float shortest = std::min( v.x, size.x - v.x );
    shortest = std::min( shortest, size.y - v.y );
    shortest = std::min( shortest, v.y );
    _ball_radius = shortest;
  } )
  .getSequence().rampTo( vec2( app::getWindowSize() ) / 2.0f, 2.0f ).rampTo( vec2( app::getWindowSize() ), 2.0f ).rampTo( vec2( app::getWindowWidth() / 2.0f, 10.0f ), 3.0f ).rampTo( vec2( app::getWindowSize() ) / 2.0f, 0.5f );

}

void ChoreographDevApp::mouseDown( MouseEvent event )
{
}

void ChoreographDevApp::update()
{
    _anim.step( 1.0f / 60.0f );
}

void ChoreographDevApp::draw()
{
	gl::clear( Color( 0, 0, 0 ) );

  gl::disableDepthRead();
  gl::disableDepthWrite();

  gl::clear( Color( 0, 0, 0 ) );
  gl::color( Color( 1.0f, 0.0f, 0.0f ) );
  gl::drawSolidCircle( vec2( 200.0f, _ball_y ), 120.0f );
  gl::color( 0.0f, 0.0f, 1.0f );
  gl::drawSolidCircle( _ball_2, _ball_radius );
}

CINDER_APP_NATIVE( ChoreographDevApp, RendererGl )
<|endoftext|>


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

#include "itkBSplineTransform.h"

namespace itk
{
namespace simple
{
namespace
{
// convert an itk::Array of images to a stl vector of sitk images
template<typename TImageArrayType>
std::vector<Image> sitkImageArrayConvert(const TImageArrayType &a)
{
  std::vector<Image> ret(a.Size());

  for( unsigned int i = 0; i < a.Size(); ++i )
    {
    ret[i] = Image(a[i]);
    }
  return ret;
}
}

// construct identity
BSplineTransform::BSplineTransform(unsigned int dimensions)
  : Transform( CreateBSplinePimpleTransform(dimensions) )
{
  Self::InternalInitialization(Self::GetITKBase());
}

BSplineTransform::BSplineTransform( const BSplineTransform &arg )
  : Transform(arg)
{
  Self::InternalInitialization(Self::GetITKBase());
}

BSplineTransform &BSplineTransform::operator=( const BSplineTransform &arg )
{
  Superclass::operator=(arg);
  return *this;
}

BSplineTransform::Self &BSplineTransform::SetTransformDomainDirection(const std::vector<double> &params)
{
  this->MakeUniqueForWrite();
  this->m_pfSetTransformDomainDirection(params);
  return *this;
}

std::vector<double> BSplineTransform::GetTransformDomainDirection() const
{
  return this->m_pfGetTransformDomainDirection();
}

BSplineTransform::Self &BSplineTransform::SetTransformDomainMeshSize(const std::vector<unsigned int>&params)
{
  this->MakeUniqueForWrite();
  this->m_pfSetTransformDomainMeshSize(params);
  return *this;
}

std::vector<unsigned int> BSplineTransform::GetTransformDomainMeshSize() const
{
  return this->m_pfGetTransformDomainMeshSize();
}

BSplineTransform::Self &BSplineTransform::SetTransformDomainOrigin(const std::vector<double>&params)
{
  this->MakeUniqueForWrite();
  this->m_pfSetTransformDomainOrigin(params);
  return *this;
}

std::vector<double> BSplineTransform::GetTransformDomainOrigin() const
{
  return this->m_pfGetTransformDomainOrigin();
}

BSplineTransform::Self &BSplineTransform::SetTransformDomainPhysicalDimensions(const std::vector<double> &params)
{
  this->MakeUniqueForWrite();
  this->m_pfSetTransformDomainPhysicalDimensions(params);
  return *this;
}

std::vector<double> BSplineTransform::GetTransformDomainPhysicalDimensions() const
{
  return this->m_pfGetTransformDomainPhysicalDimensions();
}

std::vector<Image> BSplineTransform::GetCoefficientImages () const
{
  return this->m_pfGetCoefficientImages();
}

void BSplineTransform::SetPimpleTransform( PimpleTransformBase *pimpleTransform )
{
  Superclass::SetPimpleTransform(pimpleTransform);
  Self::InternalInitialization(this->GetITKBase());
}

void BSplineTransform::InternalInitialization(itk::TransformBase *transform)
{
  MyVisitor visitor;
  visitor.transform = transform;
  visitor.that = this;

  const unsigned int order = 3;

  typedef typelist::MakeTypeList<itk::BSplineTransform<double, 3, order>,
    itk::BSplineTransform<double, 2, order> >::Type TransformTypeList;

  typelist::Visit<TransformTypeList> callInternalInitialization;

  callInternalInitialization(visitor);

}

template<class TransformType>
void BSplineTransform::InternalInitialization(TransformType *t)
{
  { // TransformDomainDirection
  typename TransformType::DirectionType (*pfSTLToITKDirection)(const std::vector<double> &) = &sitkSTLToITKDirection<typename TransformType::DirectionType>;
  this->m_pfSetTransformDomainDirection = nsstd::bind(&TransformType::SetTransformDomainDirection,t,nsstd::bind(pfSTLToITKDirection,nsstd::placeholders::_1));

  std::vector<double> (*pfITKDirectionToSTL)( const typename TransformType::DirectionType &) = &sitkITKDirectionToSTL<typename TransformType::DirectionType>;
  this->m_pfGetTransformDomainDirection = nsstd::bind(pfITKDirectionToSTL,nsstd::bind(&TransformType::GetTransformDomainDirection,t));
  }

#define SITK_SET_MPF(NAME,ITK_TYPENAME, COMPONENT)                      \
  {                                                                     \
  typedef ITK_TYPENAME itkType;                                         \
  itkType (*pfSTLToITK)(const std::vector<COMPONENT> &) = &sitkSTLVectorToITK<itkType, COMPONENT>; \
  this->m_pfSet##NAME = nsstd::bind(&TransformType::Set##NAME,t,nsstd::bind(pfSTLToITK,nsstd::placeholders::_1)); \
                                                                        \
  std::vector<COMPONENT> (*pfITKToSTL)( const itkType &) = &sitkITKVectorToSTL<COMPONENT,itkType>; \
  this->m_pfGet##NAME = nsstd::bind(pfITKToSTL,nsstd::bind(&TransformType::Get##NAME,t)); \
  }

   // TransformDomainMeshSize
  SITK_SET_MPF( TransformDomainMeshSize, typename TransformType::MeshSizeType, unsigned int );
  // TransformDomainOrigin
  SITK_SET_MPF( TransformDomainOrigin, typename TransformType::OriginType, double );
  // TransformDomainPhysicalDimensions
  SITK_SET_MPF( TransformDomainPhysicalDimensions, typename TransformType::PhysicalDimensionsType, double );

  std::vector<Image> (*pfImageArrayConvert)(const typename TransformType::CoefficientImageArray &) = &sitkImageArrayConvert<typename TransformType::CoefficientImageArray>;
  this->m_pfGetCoefficientImages = nsstd::bind(pfImageArrayConvert, nsstd::bind(&TransformType::GetCoefficientImages,t) );
}

PimpleTransformBase *BSplineTransform::CreateBSplinePimpleTransform(unsigned int dimension)
{
  PimpleTransformBase* temp = NULL;
  const unsigned int order = 3;
  switch (dimension)
    {
    case 2:
      temp = new PimpleTransform<itk::BSplineTransform<double,2,order> >();
      break;
    case 3:
      temp = new PimpleTransform<itk::BSplineTransform<double,3,order> >();
      break;
    default:
      sitkExceptionMacro("Invalid dimension for transform");
    }
  return temp;
}

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

#include "itkBSplineTransform.h"

namespace itk
{
namespace simple
{
namespace
{
// convert an itk::Array of images to a stl vector of sitk images
template<typename TImageArrayType>
std::vector<Image> sitkImageArrayConvert(const TImageArrayType &a)
{
  std::vector<Image> ret(a.Size());

  for( unsigned int i = 0; i < a.Size(); ++i )
    {
    ret[i] = Image(a[i]);
    }
  return ret;
}
}

// construct identity
BSplineTransform::BSplineTransform(unsigned int dimensions)
  : Transform( CreateBSplinePimpleTransform(dimensions) )
{
  Self::InternalInitialization(Self::GetITKBase());
}

BSplineTransform::BSplineTransform( const BSplineTransform &arg )
  : Transform(arg)
{
  Self::InternalInitialization(Self::GetITKBase());
}

BSplineTransform &BSplineTransform::operator=( const BSplineTransform &arg )
{
  Superclass::operator=(arg);
  return *this;
}

BSplineTransform::Self &BSplineTransform::SetTransformDomainDirection(const std::vector<double> &params)
{
  this->MakeUniqueForWrite();
  this->m_pfSetTransformDomainDirection(params);
  return *this;
}

std::vector<double> BSplineTransform::GetTransformDomainDirection() const
{
  return this->m_pfGetTransformDomainDirection();
}

BSplineTransform::Self &BSplineTransform::SetTransformDomainMeshSize(const std::vector<unsigned int>&params)
{
  this->MakeUniqueForWrite();
  this->m_pfSetTransformDomainMeshSize(params);
  return *this;
}

std::vector<unsigned int> BSplineTransform::GetTransformDomainMeshSize() const
{
  return this->m_pfGetTransformDomainMeshSize();
}

BSplineTransform::Self &BSplineTransform::SetTransformDomainOrigin(const std::vector<double>&params)
{
  this->MakeUniqueForWrite();
  this->m_pfSetTransformDomainOrigin(params);
  return *this;
}

std::vector<double> BSplineTransform::GetTransformDomainOrigin() const
{
  return this->m_pfGetTransformDomainOrigin();
}

BSplineTransform::Self &BSplineTransform::SetTransformDomainPhysicalDimensions(const std::vector<double> &params)
{
  this->MakeUniqueForWrite();
  this->m_pfSetTransformDomainPhysicalDimensions(params);
  return *this;
}

std::vector<double> BSplineTransform::GetTransformDomainPhysicalDimensions() const
{
  return this->m_pfGetTransformDomainPhysicalDimensions();
}

std::vector<Image> BSplineTransform::GetCoefficientImages () const
{
  return this->m_pfGetCoefficientImages();
}

void BSplineTransform::SetPimpleTransform( PimpleTransformBase *pimpleTransform )
{
  Superclass::SetPimpleTransform(pimpleTransform);
  Self::InternalInitialization(this->GetITKBase());
}

void BSplineTransform::InternalInitialization(itk::TransformBase *transform)
{
  MyVisitor visitor;
  visitor.transform = transform;
  visitor.that = this;

  const unsigned int order = 3;

  typedef typelist::MakeTypeList<itk::BSplineTransform<double, 3, order>,
    itk::BSplineTransform<double, 2, order> >::Type TransformTypeList;

  typelist::Visit<TransformTypeList> callInternalInitialization;

  // explicitly remove all function pointer with reference to prior transform
  this->m_pfGetTransformDomainDirection = SITK_NULLPTR;
  this->m_pfSetTransformDomainDirection = SITK_NULLPTR;
  this->m_pfGetTransformDomainMeshSize = SITK_NULLPTR;
  this->m_pfSetTransformDomainMeshSize = SITK_NULLPTR;
  this->m_pfGetTransformDomainOrigin = SITK_NULLPTR;
  this->m_pfSetTransformDomainOrigin = SITK_NULLPTR;
  this->m_pfGetTransformDomainPhysicalDimensions = SITK_NULLPTR;
  this->m_pfSetTransformDomainPhysicalDimensions = SITK_NULLPTR;
  this->m_pfGetCoefficientImages = SITK_NULLPTR;

  callInternalInitialization(visitor);

}

template<class TransformType>
void BSplineTransform::InternalInitialization(TransformType *t)
{
  { // TransformDomainDirection
  typename TransformType::DirectionType (*pfSTLToITKDirection)(const std::vector<double> &) = &sitkSTLToITKDirection<typename TransformType::DirectionType>;
  this->m_pfSetTransformDomainDirection = nsstd::bind(&TransformType::SetTransformDomainDirection,t,nsstd::bind(pfSTLToITKDirection,nsstd::placeholders::_1));

  std::vector<double> (*pfITKDirectionToSTL)( const typename TransformType::DirectionType &) = &sitkITKDirectionToSTL<typename TransformType::DirectionType>;
  this->m_pfGetTransformDomainDirection = nsstd::bind(pfITKDirectionToSTL,nsstd::bind(&TransformType::GetTransformDomainDirection,t));
  }

#define SITK_SET_MPF(NAME,ITK_TYPENAME, COMPONENT)                      \
  {                                                                     \
  typedef ITK_TYPENAME itkType;                                         \
  itkType (*pfSTLToITK)(const std::vector<COMPONENT> &) = &sitkSTLVectorToITK<itkType, COMPONENT>; \
  this->m_pfSet##NAME = nsstd::bind(&TransformType::Set##NAME,t,nsstd::bind(pfSTLToITK,nsstd::placeholders::_1)); \
                                                                        \
  std::vector<COMPONENT> (*pfITKToSTL)( const itkType &) = &sitkITKVectorToSTL<COMPONENT,itkType>; \
  this->m_pfGet##NAME = nsstd::bind(pfITKToSTL,nsstd::bind(&TransformType::Get##NAME,t)); \
  }

   // TransformDomainMeshSize
  SITK_SET_MPF( TransformDomainMeshSize, typename TransformType::MeshSizeType, unsigned int );
  // TransformDomainOrigin
  SITK_SET_MPF( TransformDomainOrigin, typename TransformType::OriginType, double );
  // TransformDomainPhysicalDimensions
  SITK_SET_MPF( TransformDomainPhysicalDimensions, typename TransformType::PhysicalDimensionsType, double );

  std::vector<Image> (*pfImageArrayConvert)(const typename TransformType::CoefficientImageArray &) = &sitkImageArrayConvert<typename TransformType::CoefficientImageArray>;
  this->m_pfGetCoefficientImages = nsstd::bind(pfImageArrayConvert, nsstd::bind(&TransformType::GetCoefficientImages,t) );
}

PimpleTransformBase *BSplineTransform::CreateBSplinePimpleTransform(unsigned int dimension)
{
  PimpleTransformBase* temp = NULL;
  const unsigned int order = 3;
  switch (dimension)
    {
    case 2:
      temp = new PimpleTransform<itk::BSplineTransform<double,2,order> >();
      break;
    case 3:
      temp = new PimpleTransform<itk::BSplineTransform<double,3,order> >();
      break;
    default:
      sitkExceptionMacro("Invalid dimension for transform");
    }
  return temp;
}

}
}
<|endoftext|>