<commit_before>/*
 * IncrementalKMeans.cpp
 *
 *  Created on: May 13, 2015
 *      Author: andresf
 */

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

namespace vlr {

static const int MAX_OUTLIERS = 10;

IncrementalKMeans::IncrementalKMeans(vlr::Mat data, const cvflann::IndexParams& params) :
		m_dataset(data), m_dim(data.cols), m_numDatapoints(data.rows) {

	// Attributes initialization
	m_numClusters = cvflann::get_param<int>(params, "num.clusters");

	// Compute the global data set mean
	m_miu = cv::Mat::zeros(1, m_dim * 8, cv::DataType<double>::type);
	for (int i = 0; i < m_numDatapoints; ++i) {
		cv::Mat row = m_dataset.row(i);
		uchar byte = 0;
		for (int l = 0; l < m_miu.cols; l++) {
			if ((l % 8) == 0) {
				byte = *(row.col((int) l / 8).data);
			}
			m_miu.at<double>(0, l) += ((int) ((byte >> (7 - (l % 8))) % 2));
		}
	}
	m_miu /= m_numDatapoints;

	// Compute the global data set standard deviations
	m_sigma = cv::Mat::zeros(1, m_dim * 8, cv::DataType<double>::type);
	for (int i = 0; i < m_numDatapoints; ++i) {
		cv::Mat row = m_dataset.row(i);
		uchar byte = 0;
		for (int l = 0; l < m_sigma.cols; l++) {
			if ((l % 8) == 0) {
				byte = *(row.col((int) l / 8).data);
			}
			m_sigma.at<double>(0, l) += pow(((int) ((byte >> (7 - (l % 8))) % 2)) - m_miu.at<double>(0, l), 2);
		}
	}
	m_sigma /= m_numDatapoints;
	cv::sqrt(m_sigma, m_sigma);

	m_centroids.create(m_numClusters, m_dim * 8, cv::DataType<double>::type);
	m_clustersVariances.create(m_numClusters, m_dim * 8, cv::DataType<double>::type);
	m_clustersWeights.create(1, m_numClusters, cv::DataType<double>::type);
	m_clustersSums.create(m_numClusters, m_dim * 8, cv::DataType<int>::type);
	m_clustersCounts.create(1, m_numClusters, cv::DataType<int>::type);
	m_clusterDistancesToNullTransaction.create(1, m_numClusters, cv::DataType<double>::type);
	m_outliers.resize(m_numClusters);

}

// --------------------------------------------------------------------------

IncrementalKMeans::~IncrementalKMeans() {
}

// --------------------------------------------------------------------------

void IncrementalKMeans::build() {

	// Mean-based initialization
	initCentroids();
	// Compute distances between clusters centers and the null transaction
	preComputeDistances();
	// Nj <- 0
	// Mj <- 0
	// Wj <- 1/k
	initClustersCounters();

	double L = sqrt(m_numDatapoints);
	int clusterIndex;
	double distanceToCluster;

	for (int i = 0; i < m_numDatapoints; ++i) {
		cv::Mat transaction = m_dataset.row(i);
		// Cluster assignment
		// j = NN(ti)
		findNearestNeighbor(transaction, clusterIndex, distanceToCluster);
		// Insert transaction in the list of outliers
		bool isOutlier = insertOutlier(i, clusterIndex, distanceToCluster);
		// If the transaction is not an outlier then assign it to the jth cluster
		if (isOutlier) {
			// If the transaction is an outlier and is the farthest one on the jth cluster
			// then pop and assign the nearest outlier on the jth cluster
			if (m_outliers.at(clusterIndex).size() > MAX_OUTLIERS) {
				transaction = m_dataset.row(m_outliers.at(clusterIndex).back().first);
				m_outliers.at(clusterIndex).pop_back();
				// Mj <- Mj + ti
				sparseSum(transaction, clusterIndex);
				// Nj <- Nj + 1
				m_clustersCounts.col(clusterIndex) += 1;
			}
		} else {
			// Mj <- Mj + ti
			sparseSum(transaction, clusterIndex);
			// Nj <- Nj + 1
			m_clustersCounts.col(clusterIndex) += 1;
		}

		// Update clusters centers every L times
		if (i % ((int) (m_numDatapoints / L)) == 0) {
			// Re-compute clusters centers
			computeCentroids(i);
			// Compute distances between clusters centers and the null transaction
			preComputeDistances();
			// Re-seeding
			handleEmptyClusters();
		}
	}

}

// --------------------------------------------------------------------------

void IncrementalKMeans::save(const std::string& filename) const {
	// TODO Implement this method
}

// --------------------------------------------------------------------------

void IncrementalKMeans::load(const std::string& filename) {
	// TODO Implement this method
}

// --------------------------------------------------------------------------

void IncrementalKMeans::initCentroids() {
	for (int j = 0; j < m_numClusters; ++j) {
		// Cj <- miu +/-sigma*r/d
		double r = (double) rand() / RAND_MAX;
		if (rand() % 2 == 0) {
			m_centroids.row(j) = (m_miu + m_sigma * r / (m_dim * 8));
		} else {
			m_centroids.row(j) = (m_miu - m_sigma * r / (m_dim * 8));
		}
	}
}

// --------------------------------------------------------------------------

void IncrementalKMeans::preComputeDistances() {
	cv::Mat nullTransaction = cv::Mat::zeros(1, m_dim * 8, cv::DataType<double>::type);
	for (int j = 0; j < m_numClusters; ++j) {
		cv::mulTransposed(nullTransaction - m_centroids.row(j), m_clusterDistancesToNullTransaction.col(j), false);
	}
}

// --------------------------------------------------------------------------

void IncrementalKMeans::initClustersCounters() {
	m_clustersCounts = cv::Mat::zeros(1, m_numClusters, cv::DataType<int>::type);
	m_clustersSums = cv::Mat::zeros(m_numClusters, m_dim * 8, cv::DataType<int>::type);
	m_clustersWeights = cv::Mat::ones(1, m_numClusters, cv::DataType<double>::type) / m_numClusters;
}

// --------------------------------------------------------------------------

void IncrementalKMeans::findNearestNeighbor(cv::Mat transaction, int& clusterIndex, double& distanceToCluster) {

	clusterIndex = 0;
	distanceToCluster = std::numeric_limits<double>::max();

	double tempDistanceToCluster;
	uchar byte = 0;
	for (int j = 0; j < m_centroids.rows; ++j) {
		tempDistanceToCluster = m_clusterDistancesToNullTransaction.at<double>(0, j);
		for (int l = 0; l < m_centroids.cols; l++) {
			if ((l % 8) == 0) {
				byte = *(transaction.col((int) l / 8).data);
			}
			int bit = ((int) ((byte >> (7 - (l % 8))) % 2));
			// Compute only differences for non-null dimensions
			if (bit == 1) {
				tempDistanceToCluster += pow(bit - m_centroids.at<double>(j, l), 2) - pow(m_centroids.at<double>(j, l), 2);
			}
		}
		if (tempDistanceToCluster < distanceToCluster) {
			clusterIndex = j;
			distanceToCluster = tempDistanceToCluster;
		}
	}

}

// --------------------------------------------------------------------------

bool IncrementalKMeans::insertOutlier(const int& transactionIndex, const int& clusterIndex, const double& distanceToCluster) {
	// Retrieve list of outliers for the given cluster index
//	std::vector<std::pair<int, double>> clusterOutliers = m_outliers.at(clusterIndex);
	// Insert item into the list of outliers for the given cluster index
	std::pair<int, double> item(transactionIndex, distanceToCluster);
	// Limit size of outliers list
	if(m_outliers.at(clusterIndex).size() < MAX_OUTLIERS) {
		std::vector<std::pair<int, double>>::iterator position = std::upper_bound(m_outliers.at(clusterIndex).begin(), m_outliers.at(clusterIndex).end(), item, [](const std::pair<int, double>& lhs, const std::pair<int, double>& rhs) {return lhs.second >= rhs.second;});
		m_outliers.at(clusterIndex).insert(position, item);
		return true;
	} else {
		if (item.second >= m_outliers.at(clusterIndex).front().second) {
			m_outliers.at(clusterIndex).insert(m_outliers.at(clusterIndex).begin(), item);
			return true;
		} else {
			return false;
		}
	}
}

// --------------------------------------------------------------------------

void IncrementalKMeans::sparseSum(cv::Mat transaction, const int& rowIndex) {
	uchar byte = 0;
	for (int l = 0; l < m_clustersSums.cols; l++) {
		if ((l % 8) == 0) {
			byte = *(transaction.col((int) l / 8).data);
		}
		m_clustersSums.at<int>(rowIndex, l) += ((int) ((byte >> (7 - (l % 8))) % 2));
	}
}

// --------------------------------------------------------------------------

void IncrementalKMeans::sparseSubtraction(cv::Mat transaction, const int& rowIndex) {
	uchar byte = 0;
	for (int l = 0; l < m_clustersSums.cols; l++) {
		if ((l % 8) == 0) {
			byte = *(transaction.col((int) l / 8).data);
		}
		m_clustersSums.at<int>(rowIndex, l) -= ((int) ((byte >> (7 - (l % 8))) % 2));
	}
}

// --------------------------------------------------------------------------

void IncrementalKMeans::computeCentroids(const int& i) {
	for (int j = 0; j < m_numClusters; ++j) {
		// Cj <- Mj/Nj
		m_clustersSums.row(j).convertTo(m_centroids.row(j), cv::DataType<double>::type);
		m_centroids.row(j) = m_centroids.row(j) / ((double) m_clustersCounts.at<int>(0, j));
		// Rj <- Cj - diag(Cj*Cj')
		cv::Mat clusterVariance(m_dim * 8, m_dim * 8, cv::DataType<double>::type);
		cv::mulTransposed(m_centroids.row(j), clusterVariance, true);
		m_clustersVariances.row(j) = m_centroids.row(j) - clusterVariance.diag(0).t();
		// Wj <- Nj/i
		m_clustersWeights.col(j) = ((double) m_clustersCounts.at<int>(0, j)) / ((double) i);
	}
}

// --------------------------------------------------------------------------

void IncrementalKMeans::handleEmptyClusters() {
	for (unsigned int j = 0; j < m_numClusters; ++j) {
		bool allEmpty = true;
		for (unsigned int i = 0; i < m_outliers.size(); ++i) {
			allEmpty = allEmpty && m_outliers.at(i).empty();
		}
		if (allEmpty) {
			break;
		}
		// if Wj = 0 then Cj <- to
		if (m_clustersWeights.at<double>(0, j) != 0) {
			continue;
		}
		// Get an outlier transaction assigned to a cluster different than the jth cluster
		int outlierTransactionIndex;
		for (unsigned int i = 0; i < m_outliers.size(); ++i) {
			if (i !=j && !m_outliers.at(i).empty()) {
				outlierTransactionIndex = m_outliers.at(i).front().first;
				m_outliers.at(i).pop_back();
				break;
			}
		}
		cv::Mat outlierTransaction = m_dataset.row(outlierTransactionIndex);
		// Assign outlier transaction to the jth cluster
		// Mj <- Mj + ti
		sparseSum(outlierTransaction, j);
		// Nj <- Nj + 1
		m_clustersCounts.col(j) += 1;
	}
}

} /* namespace vlr */
<commit_msg>Implement save method<commit_after>/*
 * IncrementalKMeans.cpp
 *
 *  Created on: May 13, 2015
 *      Author: andresf
 */

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

namespace vlr {

static const int MAX_OUTLIERS = 10;

IncrementalKMeans::IncrementalKMeans(vlr::Mat data, const cvflann::IndexParams& params) :
		m_dataset(data), m_dim(data.cols), m_numDatapoints(data.rows) {

	// Attributes initialization
	m_numClusters = cvflann::get_param<int>(params, "num.clusters");

	// Compute the global data set mean
	m_miu = cv::Mat::zeros(1, m_dim * 8, cv::DataType<double>::type);
	for (int i = 0; i < m_numDatapoints; ++i) {
		cv::Mat row = m_dataset.row(i);
		uchar byte = 0;
		for (int l = 0; l < m_miu.cols; l++) {
			if ((l % 8) == 0) {
				byte = *(row.col((int) l / 8).data);
			}
			m_miu.at<double>(0, l) += ((int) ((byte >> (7 - (l % 8))) % 2));
		}
	}
	m_miu /= m_numDatapoints;

	// Compute the global data set standard deviations
	m_sigma = cv::Mat::zeros(1, m_dim * 8, cv::DataType<double>::type);
	for (int i = 0; i < m_numDatapoints; ++i) {
		cv::Mat row = m_dataset.row(i);
		uchar byte = 0;
		for (int l = 0; l < m_sigma.cols; l++) {
			if ((l % 8) == 0) {
				byte = *(row.col((int) l / 8).data);
			}
			m_sigma.at<double>(0, l) += pow(((int) ((byte >> (7 - (l % 8))) % 2)) - m_miu.at<double>(0, l), 2);
		}
	}
	m_sigma /= m_numDatapoints;
	cv::sqrt(m_sigma, m_sigma);

	m_centroids.create(m_numClusters, m_dim * 8, cv::DataType<double>::type);
	m_clustersVariances.create(m_numClusters, m_dim * 8, cv::DataType<double>::type);
	m_clustersWeights.create(1, m_numClusters, cv::DataType<double>::type);
	m_clustersSums.create(m_numClusters, m_dim * 8, cv::DataType<int>::type);
	m_clustersCounts.create(1, m_numClusters, cv::DataType<int>::type);
	m_clusterDistancesToNullTransaction.create(1, m_numClusters, cv::DataType<double>::type);
	m_outliers.resize(m_numClusters);

}

// --------------------------------------------------------------------------

IncrementalKMeans::~IncrementalKMeans() {
}

// --------------------------------------------------------------------------

void IncrementalKMeans::build() {

	// Mean-based initialization
	initCentroids();
	// Compute distances between clusters centers and the null transaction
	preComputeDistances();
	// Nj <- 0
	// Mj <- 0
	// Wj <- 1/k
	initClustersCounters();

	double L = sqrt(m_numDatapoints);
	int clusterIndex;
	double distanceToCluster;

	for (int i = 0; i < m_numDatapoints; ++i) {
		cv::Mat transaction = m_dataset.row(i);
		// Cluster assignment
		// j = NN(ti)
		findNearestNeighbor(transaction, clusterIndex, distanceToCluster);
		// Insert transaction in the list of outliers
		bool isOutlier = insertOutlier(i, clusterIndex, distanceToCluster);
		// If the transaction is not an outlier then assign it to the jth cluster
		if (isOutlier) {
			// If the transaction is an outlier and is the farthest one on the jth cluster
			// then pop and assign the nearest outlier on the jth cluster
			if (m_outliers.at(clusterIndex).size() > MAX_OUTLIERS) {
				transaction = m_dataset.row(m_outliers.at(clusterIndex).back().first);
				m_outliers.at(clusterIndex).pop_back();
				// Mj <- Mj + ti
				sparseSum(transaction, clusterIndex);
				// Nj <- Nj + 1
				m_clustersCounts.col(clusterIndex) += 1;
			}
		} else {
			// Mj <- Mj + ti
			sparseSum(transaction, clusterIndex);
			// Nj <- Nj + 1
			m_clustersCounts.col(clusterIndex) += 1;
		}

		// Update clusters centers every L times
		if (i % ((int) (m_numDatapoints / L)) == 0) {
			// Re-compute clusters centers
			computeCentroids(i);
			// Compute distances between clusters centers and the null transaction
			preComputeDistances();
			// Re-seeding
			handleEmptyClusters();
		}
	}

}

// --------------------------------------------------------------------------

void IncrementalKMeans::save(const std::string& filename) const {

	if (m_centroids.empty()) {
		throw std::runtime_error("[IncrementalKMeans::save] Vocabulary is empty");
	}

	cv::FileStorage fs(filename.c_str(), cv::FileStorage::WRITE);

	if (fs.isOpened() == false) {
		throw std::runtime_error("[IncrementalKMeans::save] "
				"Unable to open file [" + filename + "] for writing");
	}

	fs << "type" << "IKM";
	fs << "C" << m_centroids;
	fs << "R" << m_clustersVariances;
	fs << "W" << m_clustersWeights;

	fs.release();

}

// --------------------------------------------------------------------------

void IncrementalKMeans::load(const std::string& filename) {
	// TODO Implement this method
}

// --------------------------------------------------------------------------

void IncrementalKMeans::initCentroids() {
	for (int j = 0; j < m_numClusters; ++j) {
		// Cj <- miu +/-sigma*r/d
		double r = (double) rand() / RAND_MAX;
		if (rand() % 2 == 0) {
			m_centroids.row(j) = (m_miu + m_sigma * r / (m_dim * 8));
		} else {
			m_centroids.row(j) = (m_miu - m_sigma * r / (m_dim * 8));
		}
	}
}

// --------------------------------------------------------------------------

void IncrementalKMeans::preComputeDistances() {
	cv::Mat nullTransaction = cv::Mat::zeros(1, m_dim * 8, cv::DataType<double>::type);
	for (int j = 0; j < m_numClusters; ++j) {
		cv::mulTransposed(nullTransaction - m_centroids.row(j), m_clusterDistancesToNullTransaction.col(j), false);
	}
}

// --------------------------------------------------------------------------

void IncrementalKMeans::initClustersCounters() {
	m_clustersCounts = cv::Mat::zeros(1, m_numClusters, cv::DataType<int>::type);
	m_clustersSums = cv::Mat::zeros(m_numClusters, m_dim * 8, cv::DataType<int>::type);
	m_clustersWeights = cv::Mat::ones(1, m_numClusters, cv::DataType<double>::type) / m_numClusters;
}

// --------------------------------------------------------------------------

void IncrementalKMeans::findNearestNeighbor(cv::Mat transaction, int& clusterIndex, double& distanceToCluster) {

	clusterIndex = 0;
	distanceToCluster = std::numeric_limits<double>::max();

	double tempDistanceToCluster;
	uchar byte = 0;
	for (int j = 0; j < m_centroids.rows; ++j) {
		tempDistanceToCluster = m_clusterDistancesToNullTransaction.at<double>(0, j);
		for (int l = 0; l < m_centroids.cols; l++) {
			if ((l % 8) == 0) {
				byte = *(transaction.col((int) l / 8).data);
			}
			int bit = ((int) ((byte >> (7 - (l % 8))) % 2));
			// Compute only differences for non-null dimensions
			if (bit == 1) {
				tempDistanceToCluster += pow(bit - m_centroids.at<double>(j, l), 2) - pow(m_centroids.at<double>(j, l), 2);
			}
		}
		if (tempDistanceToCluster < distanceToCluster) {
			clusterIndex = j;
			distanceToCluster = tempDistanceToCluster;
		}
	}

}

// --------------------------------------------------------------------------

bool IncrementalKMeans::insertOutlier(const int& transactionIndex, const int& clusterIndex, const double& distanceToCluster) {
	// Retrieve list of outliers for the given cluster index
//	std::vector<std::pair<int, double>> clusterOutliers = m_outliers.at(clusterIndex);
	// Insert item into the list of outliers for the given cluster index
	std::pair<int, double> item(transactionIndex, distanceToCluster);
	// Limit size of outliers list
	if(m_outliers.at(clusterIndex).size() < MAX_OUTLIERS) {
		std::vector<std::pair<int, double>>::iterator position = std::upper_bound(m_outliers.at(clusterIndex).begin(), m_outliers.at(clusterIndex).end(), item, [](const std::pair<int, double>& lhs, const std::pair<int, double>& rhs) {return lhs.second >= rhs.second;});
		m_outliers.at(clusterIndex).insert(position, item);
		return true;
	} else {
		if (item.second >= m_outliers.at(clusterIndex).front().second) {
			m_outliers.at(clusterIndex).insert(m_outliers.at(clusterIndex).begin(), item);
			return true;
		} else {
			return false;
		}
	}
}

// --------------------------------------------------------------------------

void IncrementalKMeans::sparseSum(cv::Mat transaction, const int& rowIndex) {
	uchar byte = 0;
	for (int l = 0; l < m_clustersSums.cols; l++) {
		if ((l % 8) == 0) {
			byte = *(transaction.col((int) l / 8).data);
		}
		m_clustersSums.at<int>(rowIndex, l) += ((int) ((byte >> (7 - (l % 8))) % 2));
	}
}

// --------------------------------------------------------------------------

void IncrementalKMeans::sparseSubtraction(cv::Mat transaction, const int& rowIndex) {
	uchar byte = 0;
	for (int l = 0; l < m_clustersSums.cols; l++) {
		if ((l % 8) == 0) {
			byte = *(transaction.col((int) l / 8).data);
		}
		m_clustersSums.at<int>(rowIndex, l) -= ((int) ((byte >> (7 - (l % 8))) % 2));
	}
}

// --------------------------------------------------------------------------

void IncrementalKMeans::computeCentroids(const int& i) {
	for (int j = 0; j < m_numClusters; ++j) {
		// Cj <- Mj/Nj
		m_clustersSums.row(j).convertTo(m_centroids.row(j), cv::DataType<double>::type);
		m_centroids.row(j) = m_centroids.row(j) / ((double) m_clustersCounts.at<int>(0, j));
		// Rj <- Cj - diag(Cj*Cj')
		cv::Mat clusterVariance(m_dim * 8, m_dim * 8, cv::DataType<double>::type);
		cv::mulTransposed(m_centroids.row(j), clusterVariance, true);
		m_clustersVariances.row(j) = m_centroids.row(j) - clusterVariance.diag(0).t();
		// Wj <- Nj/i
		m_clustersWeights.col(j) = ((double) m_clustersCounts.at<int>(0, j)) / ((double) i);
	}
}

// --------------------------------------------------------------------------

void IncrementalKMeans::handleEmptyClusters() {
	for (unsigned int j = 0; j < m_numClusters; ++j) {
		bool allEmpty = true;
		for (unsigned int i = 0; i < m_outliers.size(); ++i) {
			allEmpty = allEmpty && m_outliers.at(i).empty();
		}
		if (allEmpty) {
			break;
		}
		// if Wj = 0 then Cj <- to
		if (m_clustersWeights.at<double>(0, j) != 0) {
			continue;
		}
		// Get an outlier transaction assigned to a cluster different than the jth cluster
		int outlierTransactionIndex;
		for (unsigned int i = 0; i < m_outliers.size(); ++i) {
			if (i !=j && !m_outliers.at(i).empty()) {
				outlierTransactionIndex = m_outliers.at(i).front().first;
				m_outliers.at(i).pop_back();
				break;
			}
		}
		cv::Mat outlierTransaction = m_dataset.row(outlierTransactionIndex);
		// Assign outlier transaction to the jth cluster
		// Mj <- Mj + ti
		sparseSum(outlierTransaction, j);
		// Nj <- Nj + 1
		m_clustersCounts.col(j) += 1;
	}
}

} /* namespace vlr */
<|endoftext|>


<commit_before>/*
 For more information, please see: http://software.sci.utah.edu

 The MIT License

 Copyright (c) 2012 Scientific Computing and Imaging Institute,
 University of Utah.

 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.
 */

/**
 \brief A Lua class proxy for IO's dataset class.
 */

#include <vector>

#include "3rdParty/LUA/lua.hpp"
#include "Controller/Controller.h"
#include "IO/DynamicBrickingDS.h"
#include "IO/FileBackedDataset.h"
#include "IO/IOManager.h"
#include "IO/uvfDataset.h"
#include "../LuaClassRegistration.h"
#include "../LuaScripting.h"
#include "LuaDatasetProxy.h"
#include "LuaTuvokTypes.h"

using namespace std;

namespace tuvok
{

namespace Registrar {
void addIOInterface(LuaClassRegistration<Dataset>& reg, Dataset*,
                    LuaScripting*) {
  reg.function(&Dataset::GetLODLevelCount, "LODs", "help?", false);
}
// exposes "IOManager::ExportDataset".
bool exportDS(LuaClassInstance lua_ds, uint64_t LOD,
              const std::string& filename) {
  const LuaDatasetProxy* datasetProxy =
    lua_ds.getRawPointer<LuaDatasetProxy>(Controller::Instance().LuaScript());
  const tuvok::Dataset* ds = datasetProxy->getDataset();
  const IOManager& ioman = Controller::Const().IOMan();
  return ioman.ExportDataset(dynamic_cast<const tuvok::UVFDataset*>(ds),
                             LOD, filename, ".");
}

void dataset(std::shared_ptr<LuaScripting>& ss) {
  LuaDatasetProxy* proxy = new LuaDatasetProxy;
  ss->registerClass<Dataset>(
    proxy, &LuaDatasetProxy::CreateDS, "tuvok.dataset", "creates a new dataset",
    LuaClassRegCallback<Dataset>::Type(addIOInterface)
  );
  delete proxy;

  ss->registerFunction(&exportDS, "tuvok.dataset.export", "exports a DS", true);
}
}

LuaDatasetProxy::LuaDatasetProxy()
    : mReg(NULL)
    , mDS(NULL)
    , mDatasetType(Unknown) { }

LuaDatasetProxy::~LuaDatasetProxy()
{
  delete mReg; mReg = NULL;
  mDS = NULL;
}

Dataset* LuaDatasetProxy::CreateDS(const std::string& uvf, unsigned bricksize) {
  return Controller::Const().IOMan().CreateDataset(uvf,
    uint64_t(bricksize), false
  );
}

void LuaDatasetProxy::bind(Dataset* ds, shared_ptr<LuaScripting> ss)
{
  if (mReg == NULL)
    throw LuaError("Unable to bind dataset, no class registration available.");

  mReg->clearProxyFunctions();

  mDS = ds;
  if (ds != NULL)
  {
    // Register dataset functions using ds.
    string id;

    id = mReg->functionProxy(ds, &Dataset::GetDomainSize,
                             "getDomainSize", "", false);
    id = mReg->functionProxy(ds, &Dataset::GetRange,
                             "getRange", "", false);
    id = mReg->functionProxy(ds, &Dataset::GetLODLevelCount,
                             "getLODLevelCount", "", false);
    id = mReg->functionProxy(ds, &Dataset::GetNumberOfTimesteps,
                             "getNumberOfTimesteps", "", false);
    id = mReg->functionProxy(ds, &Dataset::GetMeshes,
                             "getMeshes", "", false);
    // We do NOT want the return values from GetMeshes stuck in the provenance
    // system (Okay, so the provenance system doesn't store return values, just
    // function parameters. But it's best to be safe).
    ss->setProvenanceExempt(id);
    id = mReg->functionProxy(ds, &Dataset::GetBitWidth,
                             "getBitWidth", "", false);
    id = mReg->functionProxy(ds, &Dataset::Get1DHistogram,
                             "get1DHistogram", "", false);
    id = mReg->functionProxy(ds, &Dataset::Get2DHistogram,
                             "get2DHistogram", "", false);
    id = mReg->functionProxy(ds, &Dataset::SaveRescaleFactors,
                             "saveRescaleFactors", "", false);
    id = mReg->functionProxy(ds, &Dataset::GetRescaleFactors,
                             "getRescaleFactors", "", false);
    id = mReg->functionProxy(ds, &Dataset::Clear,
                             "clear", "clears cache data", false);

    // Attempt to cast the dataset to a file backed dataset.
    FileBackedDataset* fileDataset = dynamic_cast<FileBackedDataset*>(ds);
    if (fileDataset != NULL)
    {
      MESSAGE("Binding extra FileBackedDS functions.");
      id = mReg->functionProxy(fileDataset, &FileBackedDataset::Filename,
                               "fullpath", "Full path to the dataset.", false);
      id = mReg->functionProxy(ds, &FileBackedDataset::Name,
                               "name", "Dataset descriptive name.", false);
    }

    try {
      BrickedDataset& bds = dynamic_cast<BrickedDataset&>(*ds);
      id = mReg->functionProxy(&bds, &BrickedDataset::GetMaxUsedBrickSizes,
                               "maxUsedBrickSize",
                               "the size of the largest brick", false);
    } catch(const std::bad_cast&) {
      WARNING("Not binding BrickedDataset functions.");
    }

    try {
      UVFDataset& uvfDataset = dynamic_cast<UVFDataset&>(*ds);
      MESSAGE("Binding extra UVF functions.");
      mDatasetType = UVF;
      mReg->functionProxy(&uvfDataset, &UVFDataset::RemoveMesh, "removeMesh",
                          "", true);
      mReg->functionProxy(&uvfDataset, &UVFDataset::AppendMesh,
                          "appendMesh", "", false);
      id = mReg->functionProxy(&uvfDataset,
        &UVFDataset::GeometryTransformToFile, "geomTransformToFile", "",
        false
      );
      ss->setProvenanceExempt(id);
    } catch(const std::bad_cast&) {
      WARNING("Not a uvf; not binding mesh functions.");
    }

    try {
      DynamicBrickingDS& dynDS = dynamic_cast<DynamicBrickingDS&>(*ds);
      MESSAGE("Binding dynamic bricking cache control functions");
      id = mReg->functionProxy(&dynDS, &DynamicBrickingDS::SetCacheSize,
                               "setCacheSize",
                               "sets the size of the cache, in megabytes.",
                               false);
      ss->addParamInfo(id, 0, "cacheMB", "cache size (megabytes)");
    } catch(const std::bad_cast&) {
      MESSAGE("Not dynamically bricked; not adding cache control functions.");
    }

    /// @todo Expose 1D/2D histogram? Currently, it is being transfered
    ///       via shared_ptr. If lua wants to interpret this, the histogram
    ///       will need to be placed in terms that lua can understand.
    ///       Two approaches:
    ///       1) Add Grid1D to the LuaStrictStack.
    ///       2) Create a Histogram1D and Histogram2D proxy.
    ///
    ///       The second solution would be more efficient, since there wouldn't
    ///       be any time spent converting datatypes to and from Lua (and with
    ///       histograms, that time wouldn't be negligible).
  }

}

void LuaDatasetProxy::defineLuaInterface(
    LuaClassRegistration<LuaDatasetProxy>& reg,
    LuaDatasetProxy* me,
    LuaScripting* ss)
{
  me->mReg = new LuaClassRegistration<LuaDatasetProxy>(reg);

  string id;

  // Register our functions
  id = reg.function(&LuaDatasetProxy::getDatasetType, "getDSType", "", false);
  id = reg.function(&LuaDatasetProxy::proxyGetMetadata, "getMetadata", "",
                    false);

  lua_State* L = ss->getLuaState();
  lua_pushinteger(L, DynamicBrickingDS::MM_SOURCE);
  lua_setglobal(L, "MM_SOURCE");
  lua_pushinteger(L, DynamicBrickingDS::MM_PRECOMPUTE);
  lua_setglobal(L, "MM_PRECOMPUTE");
  lua_pushinteger(L, DynamicBrickingDS::MM_DYNAMIC);
  lua_setglobal(L, "MM_DYNAMIC");
}

std::vector<std::pair<std::string, std::string>>
LuaDatasetProxy::proxyGetMetadata()
{
  return mDS->GetMetadata();
}

} /* namespace tuvok */
<commit_msg>lua interface to retrieve dyn brick cache size<commit_after>/*
 For more information, please see: http://software.sci.utah.edu

 The MIT License

 Copyright (c) 2012 Scientific Computing and Imaging Institute,
 University of Utah.

 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.
 */

/**
 \brief A Lua class proxy for IO's dataset class.
 */

#include <vector>

#include "3rdParty/LUA/lua.hpp"
#include "Controller/Controller.h"
#include "IO/DynamicBrickingDS.h"
#include "IO/FileBackedDataset.h"
#include "IO/IOManager.h"
#include "IO/uvfDataset.h"
#include "../LuaClassRegistration.h"
#include "../LuaScripting.h"
#include "LuaDatasetProxy.h"
#include "LuaTuvokTypes.h"

using namespace std;

namespace tuvok
{

namespace Registrar {
void addIOInterface(LuaClassRegistration<Dataset>& reg, Dataset*,
                    LuaScripting*) {
  reg.function(&Dataset::GetLODLevelCount, "LODs", "help?", false);
}
// exposes "IOManager::ExportDataset".
bool exportDS(LuaClassInstance lua_ds, uint64_t LOD,
              const std::string& filename) {
  const LuaDatasetProxy* datasetProxy =
    lua_ds.getRawPointer<LuaDatasetProxy>(Controller::Instance().LuaScript());
  const tuvok::Dataset* ds = datasetProxy->getDataset();
  const IOManager& ioman = Controller::Const().IOMan();
  return ioman.ExportDataset(dynamic_cast<const tuvok::UVFDataset*>(ds),
                             LOD, filename, ".");
}

void dataset(std::shared_ptr<LuaScripting>& ss) {
  LuaDatasetProxy* proxy = new LuaDatasetProxy;
  ss->registerClass<Dataset>(
    proxy, &LuaDatasetProxy::CreateDS, "tuvok.dataset", "creates a new dataset",
    LuaClassRegCallback<Dataset>::Type(addIOInterface)
  );
  delete proxy;

  ss->registerFunction(&exportDS, "tuvok.dataset.export", "exports a DS", true);
}
}

LuaDatasetProxy::LuaDatasetProxy()
    : mReg(NULL)
    , mDS(NULL)
    , mDatasetType(Unknown) { }

LuaDatasetProxy::~LuaDatasetProxy()
{
  delete mReg; mReg = NULL;
  mDS = NULL;
}

Dataset* LuaDatasetProxy::CreateDS(const std::string& uvf, unsigned bricksize) {
  return Controller::Const().IOMan().CreateDataset(uvf,
    uint64_t(bricksize), false
  );
}

void LuaDatasetProxy::bind(Dataset* ds, shared_ptr<LuaScripting> ss)
{
  if (mReg == NULL)
    throw LuaError("Unable to bind dataset, no class registration available.");

  mReg->clearProxyFunctions();

  mDS = ds;
  if (ds != NULL)
  {
    // Register dataset functions using ds.
    string id;

    id = mReg->functionProxy(ds, &Dataset::GetDomainSize,
                             "getDomainSize", "", false);
    id = mReg->functionProxy(ds, &Dataset::GetRange,
                             "getRange", "", false);
    id = mReg->functionProxy(ds, &Dataset::GetLODLevelCount,
                             "getLODLevelCount", "", false);
    id = mReg->functionProxy(ds, &Dataset::GetNumberOfTimesteps,
                             "getNumberOfTimesteps", "", false);
    id = mReg->functionProxy(ds, &Dataset::GetMeshes,
                             "getMeshes", "", false);
    // We do NOT want the return values from GetMeshes stuck in the provenance
    // system (Okay, so the provenance system doesn't store return values, just
    // function parameters. But it's best to be safe).
    ss->setProvenanceExempt(id);
    id = mReg->functionProxy(ds, &Dataset::GetBitWidth,
                             "getBitWidth", "", false);
    id = mReg->functionProxy(ds, &Dataset::Get1DHistogram,
                             "get1DHistogram", "", false);
    id = mReg->functionProxy(ds, &Dataset::Get2DHistogram,
                             "get2DHistogram", "", false);
    id = mReg->functionProxy(ds, &Dataset::SaveRescaleFactors,
                             "saveRescaleFactors", "", false);
    id = mReg->functionProxy(ds, &Dataset::GetRescaleFactors,
                             "getRescaleFactors", "", false);
    id = mReg->functionProxy(ds, &Dataset::Clear,
                             "clear", "clears cache data", false);

    // Attempt to cast the dataset to a file backed dataset.
    FileBackedDataset* fileDataset = dynamic_cast<FileBackedDataset*>(ds);
    if (fileDataset != NULL)
    {
      MESSAGE("Binding extra FileBackedDS functions.");
      id = mReg->functionProxy(fileDataset, &FileBackedDataset::Filename,
                               "fullpath", "Full path to the dataset.", false);
      id = mReg->functionProxy(ds, &FileBackedDataset::Name,
                               "name", "Dataset descriptive name.", false);
    }

    try {
      BrickedDataset& bds = dynamic_cast<BrickedDataset&>(*ds);
      id = mReg->functionProxy(&bds, &BrickedDataset::GetMaxUsedBrickSizes,
                               "maxUsedBrickSize",
                               "the size of the largest brick", false);
    } catch(const std::bad_cast&) {
      WARNING("Not binding BrickedDataset functions.");
    }

    try {
      UVFDataset& uvfDataset = dynamic_cast<UVFDataset&>(*ds);
      MESSAGE("Binding extra UVF functions.");
      mDatasetType = UVF;
      mReg->functionProxy(&uvfDataset, &UVFDataset::RemoveMesh, "removeMesh",
                          "", true);
      mReg->functionProxy(&uvfDataset, &UVFDataset::AppendMesh,
                          "appendMesh", "", false);
      id = mReg->functionProxy(&uvfDataset,
        &UVFDataset::GeometryTransformToFile, "geomTransformToFile", "",
        false
      );
      ss->setProvenanceExempt(id);
    } catch(const std::bad_cast&) {
      WARNING("Not a uvf; not binding mesh functions.");
    }

    try {
      DynamicBrickingDS& dynDS = dynamic_cast<DynamicBrickingDS&>(*ds);
      MESSAGE("Binding dynamic bricking cache control functions");
      id = mReg->functionProxy(&dynDS, &DynamicBrickingDS::SetCacheSize,
                               "setCacheSize",
                               "sets the size of the cache, in megabytes.",
                               false);
      ss->addParamInfo(id, 0, "cacheMB", "cache size (megabytes)");
      id = mReg->functionProxy(&dynDS, &DynamicBrickingDS::GetCacheSize,
                              "getCacheSize",
                              "gets the size of the cache, in megabytes.",
                              false);
    } catch(const std::bad_cast&) {
      MESSAGE("Not dynamically bricked; not adding cache control functions.");
    }

    /// @todo Expose 1D/2D histogram? Currently, it is being transfered
    ///       via shared_ptr. If lua wants to interpret this, the histogram
    ///       will need to be placed in terms that lua can understand.
    ///       Two approaches:
    ///       1) Add Grid1D to the LuaStrictStack.
    ///       2) Create a Histogram1D and Histogram2D proxy.
    ///
    ///       The second solution would be more efficient, since there wouldn't
    ///       be any time spent converting datatypes to and from Lua (and with
    ///       histograms, that time wouldn't be negligible).
  }

}

void LuaDatasetProxy::defineLuaInterface(
    LuaClassRegistration<LuaDatasetProxy>& reg,
    LuaDatasetProxy* me,
    LuaScripting* ss)
{
  me->mReg = new LuaClassRegistration<LuaDatasetProxy>(reg);

  string id;

  // Register our functions
  id = reg.function(&LuaDatasetProxy::getDatasetType, "getDSType", "", false);
  id = reg.function(&LuaDatasetProxy::proxyGetMetadata, "getMetadata", "",
                    false);

  lua_State* L = ss->getLuaState();
  lua_pushinteger(L, DynamicBrickingDS::MM_SOURCE);
  lua_setglobal(L, "MM_SOURCE");
  lua_pushinteger(L, DynamicBrickingDS::MM_PRECOMPUTE);
  lua_setglobal(L, "MM_PRECOMPUTE");
  lua_pushinteger(L, DynamicBrickingDS::MM_DYNAMIC);
  lua_setglobal(L, "MM_DYNAMIC");
}

std::vector<std::pair<std::string, std::string>>
LuaDatasetProxy::proxyGetMetadata()
{
  return mDS->GetMetadata();
}

} /* namespace tuvok */
<|endoftext|>


<commit_before>/*************************************************************************
> File Name: PlayerLoader.cpp
> Project Name: Hearthstone++
> Author: Chan-Ho Chris Ohk
> Purpose: Player loader that loads data from <playerName>.json.
> Created Time: 2017/10/19
> Copyright (c) 2017, Chan-Ho Chris Ohk
*************************************************************************/
#include <Loaders/PlayerLoader.h>

#include <fstream>

namespace Hearthstonepp
{
	Player* PlayerLoader::Load(std::string playerName) const
	{
		// Read player data from JSON file
		std::ifstream playerFile("Datas/" + playerName + ".json");
		json j;

		if (!playerFile.is_open())
		{
			return nullptr;
		}

		playerFile >> j;
	}
}<commit_msg>Update PlayerLoader - Implement Load method (parse some player data)<commit_after>/*************************************************************************
> File Name: PlayerLoader.cpp
> Project Name: Hearthstone++
> Author: Chan-Ho Chris Ohk
> Purpose: Player loader that loads data from <playerName>.json.
> Created Time: 2017/10/19
> Copyright (c) 2017, Chan-Ho Chris Ohk
*************************************************************************/
#include <Loaders/PlayerLoader.h>

#include <fstream>

namespace Hearthstonepp
{
	Player* PlayerLoader::Load(std::string playerName) const
	{
		// Read player data from JSON file
		std::ifstream playerFile("Datas/" + playerName + ".json");
		json j;

		if (!playerFile.is_open())
		{
			return nullptr;
		}

		playerFile >> j;

		Player* p = nullptr;

		const std::string name = std::move(j["name"].get<std::string>());

		std::vector<Deck*> decks;
		if (!j["decks"].is_null())
		{
			for (auto& deck : j["decks"])
			{
				std::string playerClass = std::move(deck["class"].get<std::string>());
				std::string deckName = std::move(deck["name"].get<std::string>());

				// TODO: Parse cards
			}
		}
	}
}<|endoftext|>


<commit_before>//
//  TapeUEF.cpp
//  Clock Signal
//
//  Created by Thomas Harte on 18/01/2016.
//  Copyright 2016 Thomas Harte. All rights reserved.
//

#include "TapeUEF.hpp"
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cmath>

#include "../../../Outputs/Log.hpp"

// MARK: - ZLib extensions

static float gzgetfloat(gzFile file) {
	uint8_t bytes[4];
	gzread(file, bytes, 4);

	/* assume a four byte array named Float exists, where Float[0]
	was the first byte read from the UEF, Float[1] the second, etc */

	/* decode mantissa */
	int mantissa;
	mantissa = bytes[0] | (bytes[1] << 8) | ((bytes[2]&0x7f)|0x80) << 16;

	float result = float(mantissa);
	result = float(ldexp(result, -23));

	/* decode exponent */
	int exponent;
	exponent = ((bytes[2]&0x80) >> 7) | (bytes[3]&0x7f) << 1;
	exponent -= 127;
	result = float(ldexp(result, exponent));

	/* flip sign if necessary */
	if(bytes[3]&0x80)
		result = -result;

	return result;
}

static uint8_t gzget8(gzFile file) {
	// This is a workaround for gzgetc, which seems to be broken in ZLib 1.2.8.
	uint8_t result;
	gzread(file, &result, 1);
	return result;
}

static int gzget16(gzFile file) {
	uint8_t bytes[2];
	gzread(file, bytes, 2);
	return bytes[0] | (bytes[1] << 8);
}

static int gzget24(gzFile file) {
	uint8_t bytes[3];
	gzread(file, bytes, 3);
	return bytes[0] | (bytes[1] << 8) | (bytes[2] << 16);
}

static int gzget32(gzFile file) {
	uint8_t bytes[4];
	gzread(file, bytes, 4);
	return bytes[0] | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24);
}

using namespace Storage::Tape;

UEF::UEF(const std::string &file_name) {
	file_ = gzopen(file_name.c_str(), "rb");

	char identifier[10];
	int bytes_read = gzread(file_, identifier, 10);
	if(bytes_read < 10 || std::strcmp(identifier, "UEF File!")) {
		throw ErrorNotUEF;
	}

	uint8_t version[2];
	gzread(file_, version, 2);

	if(version[1] > 0 || version[0] > 10) {
		throw ErrorNotUEF;
	}

	set_platform_type();
}

UEF::~UEF() {
	gzclose(file_);
}

// MARK: - Public methods

void UEF::virtual_reset() {
	gzseek(file_, 12, SEEK_SET);
	set_is_at_end(false);
	clear();
}

// MARK: - Chunk navigator

bool UEF::get_next_chunk(UEF::Chunk &result) {
	const uint16_t chunk_id = uint16_t(gzget16(file_));
	const uint32_t chunk_length = uint32_t(gzget32(file_));
	const z_off_t start_of_next_chunk = gztell(file_) + chunk_length;

	if(gzeof(file_)) {
		return false;
	}

	result.id = chunk_id;
	result.length = chunk_length;
	result.start_of_next_chunk = start_of_next_chunk;

	return true;
}

void UEF::get_next_pulses() {
	while(empty()) {
		// read chunk details
		Chunk next_chunk;
		if(!get_next_chunk(next_chunk)) {
			set_is_at_end(true);
			return;
		}

		switch(next_chunk.id) {
			case 0x0100:	queue_implicit_bit_pattern(next_chunk.length);	break;
			case 0x0102:	queue_explicit_bit_pattern(next_chunk.length);	break;
			case 0x0112:	queue_integer_gap();							break;
			case 0x0116:	queue_floating_point_gap();						break;

			case 0x0110:	queue_carrier_tone();							break;
			case 0x0111:	queue_carrier_tone_with_dummy();				break;

			case 0x0114:	queue_security_cycles();						break;
			case 0x0104:	queue_defined_data(next_chunk.length);			break;

			// change of base rate
			case 0x0113: {
				// TODO: something smarter than just converting this to an int
				const float new_time_base = gzgetfloat(file_);
				time_base_ = unsigned(roundf(new_time_base));
			}
			break;

			case 0x0117: {
				const int baud_rate = gzget16(file_);
				is_300_baud_ = (baud_rate == 300);
			}
			break;

			default:
				LOG("!!! Skipping " << std::hex << next_chunk.id << std::endl);
			break;
		}

		gzseek(file_, next_chunk.start_of_next_chunk, SEEK_SET);
	}
}

// MARK: - Chunk parsers

void UEF::queue_implicit_bit_pattern(uint32_t length) {
	while(length--) {
		queue_implicit_byte(gzget8(file_));
	}
}

void UEF::queue_explicit_bit_pattern(uint32_t length) {
	const std::size_t length_in_bits = (length << 3) - size_t(gzget8(file_));
	uint8_t current_byte = 0;
	for(std::size_t bit = 0; bit < length_in_bits; bit++) {
		if(!(bit&7)) current_byte = gzget8(file_);
		queue_bit(current_byte&1);
		current_byte >>= 1;
	}
}

void UEF::queue_integer_gap() {
	Time duration;
	duration.length = unsigned(gzget16(file_));
	duration.clock_rate = time_base_;
	emplace_back(Pulse::Zero, duration);
}

void UEF::queue_floating_point_gap() {
	const float length = gzgetfloat(file_);
	Time duration;
	duration.length = unsigned(length * 4000000);
	duration.clock_rate = 4000000;
	emplace_back(Pulse::Zero, duration);
}

void UEF::queue_carrier_tone() {
	unsigned int number_of_cycles = unsigned(gzget16(file_));
	while(number_of_cycles--) queue_bit(1);
}

void UEF::queue_carrier_tone_with_dummy() {
	unsigned int pre_cycles = unsigned(gzget16(file_));
	unsigned int post_cycles = unsigned(gzget16(file_));
	while(pre_cycles--) queue_bit(1);
	queue_implicit_byte(0xaa);
	while(post_cycles--) queue_bit(1);
}

void UEF::queue_security_cycles() {
	int number_of_cycles = gzget24(file_);
	bool first_is_pulse = gzget8(file_) == 'P';
	bool last_is_pulse = gzget8(file_) == 'P';

	uint8_t current_byte = 0;
	for(int cycle = 0; cycle < number_of_cycles; cycle++) {
		if(!(cycle&7)) current_byte = gzget8(file_);
		int bit = (current_byte >> 7);
		current_byte <<= 1;

		Time duration;
		duration.length = bit ? 1 : 2;
		duration.clock_rate = time_base_ * 4;

		if(!cycle && first_is_pulse) {
			emplace_back(Pulse::High, duration);
		} else if(cycle == number_of_cycles-1 && last_is_pulse) {
			emplace_back(Pulse::Low, duration);
		} else {
			emplace_back(Pulse::Low, duration);
			emplace_back(Pulse::High, duration);
		}
	}
}

void UEF::queue_defined_data(uint32_t length) {
	if(length < 3) return;

	const int bits_per_packet = gzget8(file_);
	const char parity_type = char(gzget8(file_));
	int number_of_stop_bits = gzget8(file_);

	const bool has_extra_stop_wave = (number_of_stop_bits < 0);
	number_of_stop_bits = abs(number_of_stop_bits);

	length -= 3;
	while(length--) {
		uint8_t byte = gzget8(file_);

		uint8_t parity_value = byte;
		parity_value ^= (parity_value >> 4);
		parity_value ^= (parity_value >> 2);
		parity_value ^= (parity_value >> 1);

		queue_bit(0);
		int c = bits_per_packet;
		while(c--) {
			queue_bit(byte&1);
			byte >>= 1;
		}

		switch(parity_type) {
			default: break;
			case 'E': queue_bit(parity_value&1);		break;
			case 'O': queue_bit((parity_value&1) ^ 1);	break;
		}

		int stop_bits = number_of_stop_bits;
		while(stop_bits--) queue_bit(1);
		if(has_extra_stop_wave) {
			Time duration;
			duration.length = 1;
			duration.clock_rate = time_base_ * 4;
			emplace_back(Pulse::Low, duration);
			emplace_back(Pulse::High, duration);
		}
	}
}

// MARK: - Queuing helpers

void UEF::queue_implicit_byte(uint8_t byte) {
	queue_bit(0);
	int c = 8;
	while(c--) {
		queue_bit(byte&1);
		byte >>= 1;
	}
	queue_bit(1);
}

void UEF::queue_bit(int bit) {
	int number_of_cycles;
	Time duration;
	duration.clock_rate = time_base_ * 4;

	if(bit) {
		// encode high-frequency waves
		duration.length = 1;
		number_of_cycles = 2;
	} else {
		// encode low-frequency waves
		duration.length = 2;
		number_of_cycles = 1;
	}

	if(is_300_baud_) number_of_cycles *= 4;

	while(number_of_cycles--) {
		emplace_back(Pulse::Low, duration);
		emplace_back(Pulse::High, duration);
	}
}

// MARK: - TypeDistinguisher

TargetPlatform::Type UEF::target_platform_type() {
	return platform_type_;
}

void UEF::set_platform_type() {
	// If a chunk of type 0005 exists anywhere in the UEF then the UEF specifies its target machine.
	// So check and, if so, update the list of machines for which this file thinks it is suitable.
	Chunk next_chunk;
	while(get_next_chunk(next_chunk)) {
		if(next_chunk.id == 0x0005) {
			uint8_t target = gzget8(file_);
			switch(target >> 4) {
				case 0:	platform_type_ = TargetPlatform::BBCModelA;		break;
				case 1:	platform_type_ = TargetPlatform::AcornElectron;	break;
				case 2:	platform_type_ = TargetPlatform::BBCModelB;		break;
				case 3:	platform_type_ = TargetPlatform::BBCMaster;		break;
				case 4:	platform_type_ = TargetPlatform::AcornAtom;		break;
				default: break;
			}
		}
		gzseek(file_, next_chunk.start_of_next_chunk, SEEK_SET);
	}
	reset();
}
<commit_msg>Normalises logging.<commit_after>//
//  TapeUEF.cpp
//  Clock Signal
//
//  Created by Thomas Harte on 18/01/2016.
//  Copyright 2016 Thomas Harte. All rights reserved.
//

#include "TapeUEF.hpp"
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cmath>

#define LOG_PREFIX "[UEF] "
#include "../../../Outputs/Log.hpp"

// MARK: - ZLib extensions

static float gzgetfloat(gzFile file) {
	uint8_t bytes[4];
	gzread(file, bytes, 4);

	/* assume a four byte array named Float exists, where Float[0]
	was the first byte read from the UEF, Float[1] the second, etc */

	/* decode mantissa */
	int mantissa;
	mantissa = bytes[0] | (bytes[1] << 8) | ((bytes[2]&0x7f)|0x80) << 16;

	float result = float(mantissa);
	result = float(ldexp(result, -23));

	/* decode exponent */
	int exponent;
	exponent = ((bytes[2]&0x80) >> 7) | (bytes[3]&0x7f) << 1;
	exponent -= 127;
	result = float(ldexp(result, exponent));

	/* flip sign if necessary */
	if(bytes[3]&0x80)
		result = -result;

	return result;
}

static uint8_t gzget8(gzFile file) {
	// This is a workaround for gzgetc, which seems to be broken in ZLib 1.2.8.
	uint8_t result;
	gzread(file, &result, 1);
	return result;
}

static int gzget16(gzFile file) {
	uint8_t bytes[2];
	gzread(file, bytes, 2);
	return bytes[0] | (bytes[1] << 8);
}

static int gzget24(gzFile file) {
	uint8_t bytes[3];
	gzread(file, bytes, 3);
	return bytes[0] | (bytes[1] << 8) | (bytes[2] << 16);
}

static int gzget32(gzFile file) {
	uint8_t bytes[4];
	gzread(file, bytes, 4);
	return bytes[0] | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24);
}

using namespace Storage::Tape;

UEF::UEF(const std::string &file_name) {
	file_ = gzopen(file_name.c_str(), "rb");

	char identifier[10];
	int bytes_read = gzread(file_, identifier, 10);
	if(bytes_read < 10 || std::strcmp(identifier, "UEF File!")) {
		throw ErrorNotUEF;
	}

	uint8_t version[2];
	gzread(file_, version, 2);

	if(version[1] > 0 || version[0] > 10) {
		throw ErrorNotUEF;
	}

	set_platform_type();
}

UEF::~UEF() {
	gzclose(file_);
}

// MARK: - Public methods

void UEF::virtual_reset() {
	gzseek(file_, 12, SEEK_SET);
	set_is_at_end(false);
	clear();
}

// MARK: - Chunk navigator

bool UEF::get_next_chunk(UEF::Chunk &result) {
	const uint16_t chunk_id = uint16_t(gzget16(file_));
	const uint32_t chunk_length = uint32_t(gzget32(file_));
	const z_off_t start_of_next_chunk = gztell(file_) + chunk_length;

	if(gzeof(file_)) {
		return false;
	}

	result.id = chunk_id;
	result.length = chunk_length;
	result.start_of_next_chunk = start_of_next_chunk;

	return true;
}

void UEF::get_next_pulses() {
	while(empty()) {
		// read chunk details
		Chunk next_chunk;
		if(!get_next_chunk(next_chunk)) {
			set_is_at_end(true);
			return;
		}

		switch(next_chunk.id) {
			case 0x0100:	queue_implicit_bit_pattern(next_chunk.length);	break;
			case 0x0102:	queue_explicit_bit_pattern(next_chunk.length);	break;
			case 0x0112:	queue_integer_gap();							break;
			case 0x0116:	queue_floating_point_gap();						break;

			case 0x0110:	queue_carrier_tone();							break;
			case 0x0111:	queue_carrier_tone_with_dummy();				break;

			case 0x0114:	queue_security_cycles();						break;
			case 0x0104:	queue_defined_data(next_chunk.length);			break;

			// change of base rate
			case 0x0113: {
				// TODO: something smarter than just converting this to an int
				const float new_time_base = gzgetfloat(file_);
				time_base_ = unsigned(roundf(new_time_base));
			}
			break;

			case 0x0117: {
				const int baud_rate = gzget16(file_);
				is_300_baud_ = (baud_rate == 300);
			}
			break;

			default:
				LOG("Skipping chunk of type " << PADHEX(4) << next_chunk.id);
			break;
		}

		gzseek(file_, next_chunk.start_of_next_chunk, SEEK_SET);
	}
}

// MARK: - Chunk parsers

void UEF::queue_implicit_bit_pattern(uint32_t length) {
	while(length--) {
		queue_implicit_byte(gzget8(file_));
	}
}

void UEF::queue_explicit_bit_pattern(uint32_t length) {
	const std::size_t length_in_bits = (length << 3) - size_t(gzget8(file_));
	uint8_t current_byte = 0;
	for(std::size_t bit = 0; bit < length_in_bits; bit++) {
		if(!(bit&7)) current_byte = gzget8(file_);
		queue_bit(current_byte&1);
		current_byte >>= 1;
	}
}

void UEF::queue_integer_gap() {
	Time duration;
	duration.length = unsigned(gzget16(file_));
	duration.clock_rate = time_base_;
	emplace_back(Pulse::Zero, duration);
}

void UEF::queue_floating_point_gap() {
	const float length = gzgetfloat(file_);
	Time duration;
	duration.length = unsigned(length * 4000000);
	duration.clock_rate = 4000000;
	emplace_back(Pulse::Zero, duration);
}

void UEF::queue_carrier_tone() {
	unsigned int number_of_cycles = unsigned(gzget16(file_));
	while(number_of_cycles--) queue_bit(1);
}

void UEF::queue_carrier_tone_with_dummy() {
	unsigned int pre_cycles = unsigned(gzget16(file_));
	unsigned int post_cycles = unsigned(gzget16(file_));
	while(pre_cycles--) queue_bit(1);
	queue_implicit_byte(0xaa);
	while(post_cycles--) queue_bit(1);
}

void UEF::queue_security_cycles() {
	int number_of_cycles = gzget24(file_);
	bool first_is_pulse = gzget8(file_) == 'P';
	bool last_is_pulse = gzget8(file_) == 'P';

	uint8_t current_byte = 0;
	for(int cycle = 0; cycle < number_of_cycles; cycle++) {
		if(!(cycle&7)) current_byte = gzget8(file_);
		int bit = (current_byte >> 7);
		current_byte <<= 1;

		Time duration;
		duration.length = bit ? 1 : 2;
		duration.clock_rate = time_base_ * 4;

		if(!cycle && first_is_pulse) {
			emplace_back(Pulse::High, duration);
		} else if(cycle == number_of_cycles-1 && last_is_pulse) {
			emplace_back(Pulse::Low, duration);
		} else {
			emplace_back(Pulse::Low, duration);
			emplace_back(Pulse::High, duration);
		}
	}
}

void UEF::queue_defined_data(uint32_t length) {
	if(length < 3) return;

	const int bits_per_packet = gzget8(file_);
	const char parity_type = char(gzget8(file_));
	int number_of_stop_bits = gzget8(file_);

	const bool has_extra_stop_wave = (number_of_stop_bits < 0);
	number_of_stop_bits = abs(number_of_stop_bits);

	length -= 3;
	while(length--) {
		uint8_t byte = gzget8(file_);

		uint8_t parity_value = byte;
		parity_value ^= (parity_value >> 4);
		parity_value ^= (parity_value >> 2);
		parity_value ^= (parity_value >> 1);

		queue_bit(0);
		int c = bits_per_packet;
		while(c--) {
			queue_bit(byte&1);
			byte >>= 1;
		}

		switch(parity_type) {
			default: break;
			case 'E': queue_bit(parity_value&1);		break;
			case 'O': queue_bit((parity_value&1) ^ 1);	break;
		}

		int stop_bits = number_of_stop_bits;
		while(stop_bits--) queue_bit(1);
		if(has_extra_stop_wave) {
			Time duration;
			duration.length = 1;
			duration.clock_rate = time_base_ * 4;
			emplace_back(Pulse::Low, duration);
			emplace_back(Pulse::High, duration);
		}
	}
}

// MARK: - Queuing helpers

void UEF::queue_implicit_byte(uint8_t byte) {
	queue_bit(0);
	int c = 8;
	while(c--) {
		queue_bit(byte&1);
		byte >>= 1;
	}
	queue_bit(1);
}

void UEF::queue_bit(int bit) {
	int number_of_cycles;
	Time duration;
	duration.clock_rate = time_base_ * 4;

	if(bit) {
		// encode high-frequency waves
		duration.length = 1;
		number_of_cycles = 2;
	} else {
		// encode low-frequency waves
		duration.length = 2;
		number_of_cycles = 1;
	}

	if(is_300_baud_) number_of_cycles *= 4;

	while(number_of_cycles--) {
		emplace_back(Pulse::Low, duration);
		emplace_back(Pulse::High, duration);
	}
}

// MARK: - TypeDistinguisher

TargetPlatform::Type UEF::target_platform_type() {
	return platform_type_;
}

void UEF::set_platform_type() {
	// If a chunk of type 0005 exists anywhere in the UEF then the UEF specifies its target machine.
	// So check and, if so, update the list of machines for which this file thinks it is suitable.
	Chunk next_chunk;
	while(get_next_chunk(next_chunk)) {
		if(next_chunk.id == 0x0005) {
			uint8_t target = gzget8(file_);
			switch(target >> 4) {
				case 0:	platform_type_ = TargetPlatform::BBCModelA;		break;
				case 1:	platform_type_ = TargetPlatform::AcornElectron;	break;
				case 2:	platform_type_ = TargetPlatform::BBCModelB;		break;
				case 3:	platform_type_ = TargetPlatform::BBCMaster;		break;
				case 4:	platform_type_ = TargetPlatform::AcornAtom;		break;
				default: break;
			}
		}
		gzseek(file_, next_chunk.start_of_next_chunk, SEEK_SET);
	}
	reset();
}
<|endoftext|>


<commit_before>// This file is a part of the OpenSurgSim project.
// Copyright 2013, SimQuest Solutions Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <vector>

#include "SurgSim/Collision/CollisionPair.h"
#include "SurgSim/Collision/ContactCalculation.h"
#include "SurgSim/Collision/DcdCollision.h"
#include "SurgSim/Collision/Representation.h"
#include "SurgSim/Framework/Runtime.h"
#include "SurgSim/Framework/ThreadPool.h"
#include "SurgSim/Physics/DcdCollision.h"
#include "SurgSim/Physics/PhysicsManagerState.h"

using SurgSim::Collision::CollisionPair;
using SurgSim::Collision::ContactCalculation;

namespace SurgSim
{
namespace Physics
{

DcdCollision::DcdCollision(bool doCopyState) :
	Computation(doCopyState)
{
	populateCalculationTable();
}

DcdCollision::~DcdCollision()
{
}

std::shared_ptr<PhysicsManagerState> DcdCollision::doUpdate(
	const double& dt,
	const std::shared_ptr<PhysicsManagerState>& state)
{
	std::shared_ptr<PhysicsManagerState> result = state;
	auto threadPool = Framework::Runtime::getThreadPool();
	auto const& representations = state->getActiveCollisionRepresentations();
	std::vector<std::future<void>> tasks;

	updatePairs(result);

	for (auto& pair : result->getCollisionPairs())
	{
		tasks.push_back(threadPool->enqueue<void>([&] ()
		{
			m_contactCalculations[pair->getFirst()->getShapeType()]
								 [pair->getSecond()->getShapeType()]->calculateContact(pair);
		}));
	}

	std::for_each(tasks.begin(), tasks.end(), [](std::future<void>& p){p.wait();});

	return result;
}

void DcdCollision::populateCalculationTable()
{
	for (int i = 0; i < SurgSim::Math::SHAPE_TYPE_COUNT; ++i)
	{
		for (int j = 0; j < SurgSim::Math::SHAPE_TYPE_COUNT; ++j)
		{
			m_contactCalculations[i][j].reset(new Collision::DefaultContactCalculation(false));
		}
	}
	setDcdContactInTable(std::make_shared<Collision::BoxCapsuleDcdContact>());
	setDcdContactInTable(std::make_shared<Collision::BoxDoubleSidedPlaneDcdContact>());
	setDcdContactInTable(std::make_shared<Collision::BoxPlaneDcdContact>());
	setDcdContactInTable(std::make_shared<Collision::BoxSphereDcdContact>());
	setDcdContactInTable(std::make_shared<Collision::CapsuleSphereDcdContact>());
	setDcdContactInTable(std::make_shared<Collision::OctreeCapsuleDcdContact>());
	setDcdContactInTable(std::make_shared<Collision::OctreeDoubleSidedPlaneDcdContact>());
	setDcdContactInTable(std::make_shared<Collision::OctreePlaneDcdContact>());
	setDcdContactInTable(std::make_shared<Collision::OctreeSphereDcdContact>());
	setDcdContactInTable(std::make_shared<Collision::SphereSphereDcdContact>());
	setDcdContactInTable(std::make_shared<Collision::SphereDoubleSidedPlaneDcdContact>());
	setDcdContactInTable(std::make_shared<Collision::SpherePlaneDcdContact>());
	setDcdContactInTable(std::make_shared<Collision::TriangleMeshParticlesDcdContact>());
	setDcdContactInTable(std::make_shared<Collision::TriangleMeshPlaneDcdContact>());
	setDcdContactInTable(std::make_shared<Collision::TriangleMeshTriangleMeshDcdContact>());
}

void DcdCollision::updatePairs(std::shared_ptr<PhysicsManagerState> state)
{
	auto& representations = state->getActiveCollisionRepresentations();

	if (representations.size() > 1)
	{
		std::vector<std::shared_ptr<CollisionPair>> pairs;
		auto firstEnd = std::end(representations);
		--firstEnd;
		for (auto first = std::begin(representations); first != firstEnd; ++first)
		{
			auto second = first;
			++second;
			for (; second != std::end(representations); ++second)
			{
				std::shared_ptr<CollisionPair> pair = std::make_shared<CollisionPair>();
				pair->setRepresentations(*first,*second);
				pairs.push_back(pair);
			}
		}

		auto& excludedPairs = state->getExcludedCollisionPairs();
		for (auto it = excludedPairs.cbegin(); it != excludedPairs.cend(); ++it)
		{
			auto candidate = std::find_if(pairs.begin(), pairs.end(), [&it](const std::shared_ptr<CollisionPair> &pair)
			{
				return (pair->getFirst() == (*it)->getFirst() && pair->getSecond() == (*it)->getSecond())
					|| (pair->getFirst() == (*it)->getSecond() && pair->getSecond() == (*it)->getFirst());
			});

			if (candidate != pairs.end())
			{
				pairs.erase(candidate);
			}
		}

		state->setCollisionPairs(pairs);
	}
}

void DcdCollision::setDcdContactInTable(std::shared_ptr<ContactCalculation> dcdContact)
{
	std::pair<int,int> shapeTypes = dcdContact->getShapeTypes();
	m_contactCalculations[shapeTypes.first][shapeTypes.second] = dcdContact;
	if (shapeTypes.first != shapeTypes.second)
	{
		m_contactCalculations[shapeTypes.second][shapeTypes.first] = dcdContact;
	}
}

}; // Physics
}; // SurgSim

<commit_msg>Fix Linux warning (unused variable)<commit_after>// This file is a part of the OpenSurgSim project.
// Copyright 2013, SimQuest Solutions Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <vector>

#include "SurgSim/Collision/CollisionPair.h"
#include "SurgSim/Collision/ContactCalculation.h"
#include "SurgSim/Collision/DcdCollision.h"
#include "SurgSim/Collision/Representation.h"
#include "SurgSim/Framework/Runtime.h"
#include "SurgSim/Framework/ThreadPool.h"
#include "SurgSim/Physics/DcdCollision.h"
#include "SurgSim/Physics/PhysicsManagerState.h"

using SurgSim::Collision::CollisionPair;
using SurgSim::Collision::ContactCalculation;

namespace SurgSim
{
namespace Physics
{

DcdCollision::DcdCollision(bool doCopyState) :
	Computation(doCopyState)
{
	populateCalculationTable();
}

DcdCollision::~DcdCollision()
{
}

std::shared_ptr<PhysicsManagerState> DcdCollision::doUpdate(
	const double& dt,
	const std::shared_ptr<PhysicsManagerState>& state)
{
	std::shared_ptr<PhysicsManagerState> result = state;
	auto threadPool = Framework::Runtime::getThreadPool();
	std::vector<std::future<void>> tasks;

	updatePairs(result);

	for (auto& pair : result->getCollisionPairs())
	{
		tasks.push_back(threadPool->enqueue<void>([&] ()
		{
			m_contactCalculations[pair->getFirst()->getShapeType()]
								 [pair->getSecond()->getShapeType()]->calculateContact(pair);
		}));
	}

	std::for_each(tasks.begin(), tasks.end(), [](std::future<void>& p){p.wait();});

	return result;
}

void DcdCollision::populateCalculationTable()
{
	for (int i = 0; i < SurgSim::Math::SHAPE_TYPE_COUNT; ++i)
	{
		for (int j = 0; j < SurgSim::Math::SHAPE_TYPE_COUNT; ++j)
		{
			m_contactCalculations[i][j].reset(new Collision::DefaultContactCalculation(false));
		}
	}
	setDcdContactInTable(std::make_shared<Collision::BoxCapsuleDcdContact>());
	setDcdContactInTable(std::make_shared<Collision::BoxDoubleSidedPlaneDcdContact>());
	setDcdContactInTable(std::make_shared<Collision::BoxPlaneDcdContact>());
	setDcdContactInTable(std::make_shared<Collision::BoxSphereDcdContact>());
	setDcdContactInTable(std::make_shared<Collision::CapsuleSphereDcdContact>());
	setDcdContactInTable(std::make_shared<Collision::OctreeCapsuleDcdContact>());
	setDcdContactInTable(std::make_shared<Collision::OctreeDoubleSidedPlaneDcdContact>());
	setDcdContactInTable(std::make_shared<Collision::OctreePlaneDcdContact>());
	setDcdContactInTable(std::make_shared<Collision::OctreeSphereDcdContact>());
	setDcdContactInTable(std::make_shared<Collision::SphereSphereDcdContact>());
	setDcdContactInTable(std::make_shared<Collision::SphereDoubleSidedPlaneDcdContact>());
	setDcdContactInTable(std::make_shared<Collision::SpherePlaneDcdContact>());
	setDcdContactInTable(std::make_shared<Collision::TriangleMeshParticlesDcdContact>());
	setDcdContactInTable(std::make_shared<Collision::TriangleMeshPlaneDcdContact>());
	setDcdContactInTable(std::make_shared<Collision::TriangleMeshTriangleMeshDcdContact>());
}

void DcdCollision::updatePairs(std::shared_ptr<PhysicsManagerState> state)
{
	auto& representations = state->getActiveCollisionRepresentations();

	if (representations.size() > 1)
	{
		std::vector<std::shared_ptr<CollisionPair>> pairs;
		auto firstEnd = std::end(representations);
		--firstEnd;
		for (auto first = std::begin(representations); first != firstEnd; ++first)
		{
			auto second = first;
			++second;
			for (; second != std::end(representations); ++second)
			{
				std::shared_ptr<CollisionPair> pair = std::make_shared<CollisionPair>();
				pair->setRepresentations(*first,*second);
				pairs.push_back(pair);
			}
		}

		auto& excludedPairs = state->getExcludedCollisionPairs();
		for (auto it = excludedPairs.cbegin(); it != excludedPairs.cend(); ++it)
		{
			auto candidate = std::find_if(pairs.begin(), pairs.end(), [&it](const std::shared_ptr<CollisionPair> &pair)
			{
				return (pair->getFirst() == (*it)->getFirst() && pair->getSecond() == (*it)->getSecond())
					|| (pair->getFirst() == (*it)->getSecond() && pair->getSecond() == (*it)->getFirst());
			});

			if (candidate != pairs.end())
			{
				pairs.erase(candidate);
			}
		}

		state->setCollisionPairs(pairs);
	}
}

void DcdCollision::setDcdContactInTable(std::shared_ptr<ContactCalculation> dcdContact)
{
	std::pair<int,int> shapeTypes = dcdContact->getShapeTypes();
	m_contactCalculations[shapeTypes.first][shapeTypes.second] = dcdContact;
	if (shapeTypes.first != shapeTypes.second)
	{
		m_contactCalculations[shapeTypes.second][shapeTypes.first] = dcdContact;
	}
}

}; // Physics
}; // SurgSim

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: broadcast.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: obo $ $Date: 2005-04-13 09:59:39 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef _SVT_BROADCAST_HXX
#define _SVT_BROADCAST_HXX

#ifndef INCLUDED_SVLDLLAPI_H
#include "svtools/svldllapi.h"
#endif

#ifndef _RTTI_HXX //autogen
#include <tools/rtti.hxx>
#endif

class SvtListener;
class SfxHint;
class SvtListenerBase;

//-------------------------------------------------------------------------

class SVL_DLLPUBLIC SvtBroadcaster
{
friend class SvtListener;
friend class SvtListenerBase;
friend class SvtListenerIter;
    SvtListenerBase* pRoot;

    const SvtBroadcaster&   operator=(const SvtBroadcaster &); // verboten

protected:
    void                    Forward( SvtBroadcaster& rBC,
                                     const SfxHint& rHint );
    virtual void            ListenersGone();

public:
                            TYPEINFO();

                            SvtBroadcaster();
                            SvtBroadcaster( const SvtBroadcaster &rBC );
    virtual                 ~SvtBroadcaster();

    void                    Broadcast( const SfxHint &rHint );

    BOOL                    HasListeners() const { return 0 != pRoot; }
};

#endif

<commit_msg>INTEGRATION: CWS ooo19126 (1.2.140); FILE MERGED 2005/09/05 14:50:28 rt 1.2.140.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: broadcast.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 09:10:34 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef _SVT_BROADCAST_HXX
#define _SVT_BROADCAST_HXX

#ifndef INCLUDED_SVLDLLAPI_H
#include "svtools/svldllapi.h"
#endif

#ifndef _RTTI_HXX //autogen
#include <tools/rtti.hxx>
#endif

class SvtListener;
class SfxHint;
class SvtListenerBase;

//-------------------------------------------------------------------------

class SVL_DLLPUBLIC SvtBroadcaster
{
friend class SvtListener;
friend class SvtListenerBase;
friend class SvtListenerIter;
    SvtListenerBase* pRoot;

    const SvtBroadcaster&   operator=(const SvtBroadcaster &); // verboten

protected:
    void                    Forward( SvtBroadcaster& rBC,
                                     const SfxHint& rHint );
    virtual void            ListenersGone();

public:
                            TYPEINFO();

                            SvtBroadcaster();
                            SvtBroadcaster( const SvtBroadcaster &rBC );
    virtual                 ~SvtBroadcaster();

    void                    Broadcast( const SfxHint &rHint );

    BOOL                    HasListeners() const { return 0 != pRoot; }
};

#endif

<|endoftext|>