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

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "mitkNavigationDataToPointSetFilter.h"
#include "mitkNavigationDataSequentialPlayer.h"
#include "mitkNavigationDataReaderXML.h"
#include <mitkIGTConfig.h>
#include <mitkTestingMacros.h>

#include <iostream>

/**
*  Simple example for a test for the (non-existent) class "NavigationDataToPointSetFilter".
*
*  argc and argv are the command line parameters which were passed to
*  the ADD_TEST command in the CMakeLists.txt file. For the automatic
*  tests, argv is either empty for the simple tests or contains the filename
*  of a test image for the image tests (see CMakeLists.txt).
*/

mitk::NavigationDataToPointSetFilter::Pointer m_NavigationDataToPointSetFilter;

static void Setup()
{
  m_NavigationDataToPointSetFilter = mitk::NavigationDataToPointSetFilter::New();
}

static void TestMode3D()
{
  Setup();
  m_NavigationDataToPointSetFilter->SetOperationMode(mitk::NavigationDataToPointSetFilter::Mode3D);

  //Build up test data
  mitk::NavigationData::Pointer nd0 = mitk::NavigationData::New();
  mitk::NavigationData::Pointer nd1 = mitk::NavigationData::New();
  mitk::NavigationData::Pointer nd2 = mitk::NavigationData::New();
  mitk::NavigationData::Pointer nd3 = mitk::NavigationData::New();

  mitk::NavigationData::PositionType point0;
  point0[0] = 1.0;
  point0[1] = 2.0;
  point0[2] = 3.0;
  nd0->SetPosition(point0);
  nd0->SetDataValid(true);

  mitk::NavigationData::PositionType point1;
  point1[0] = 4.0;
  point1[1] = 5.0;
  point1[2] = 6.0;
  nd1->SetPosition(point1);
  nd1->SetDataValid(true);

  mitk::NavigationData::PositionType point2;
  point2[0] = 7.0;
  point2[1] = 8.0;
  point2[2] = 9.0;
  nd2->SetPosition(point2);
  nd2->SetDataValid(true);

  mitk::NavigationData::PositionType point3;
  point3[0] = 10.0;
  point3[1] = 11.0;
  point3[2] = 12.0;
  nd3->SetPosition(point3);
  nd3->SetDataValid(true);

  m_NavigationDataToPointSetFilter->SetInput(0, nd0);
  m_NavigationDataToPointSetFilter->SetInput(1, nd1);
  m_NavigationDataToPointSetFilter->SetInput(2, nd2);
  m_NavigationDataToPointSetFilter->SetInput(3, nd3);

  //Process
  mitk::PointSet::Pointer pointSet0 = m_NavigationDataToPointSetFilter->GetOutput();
  mitk::PointSet::Pointer pointSet1 = m_NavigationDataToPointSetFilter->GetOutput(1);
  mitk::PointSet::Pointer pointSet2 = m_NavigationDataToPointSetFilter->GetOutput(2);
  mitk::PointSet::Pointer pointSet3 = m_NavigationDataToPointSetFilter->GetOutput(3);

  pointSet0->Update();

  MITK_TEST_OUTPUT(<< "Testing the conversion of navigation data object to PointSets in Mode 3D:");
  MITK_TEST_CONDITION(mitk::Equal(pointSet0->GetPoint(0), point0), "Pointset 0 correct?");
  MITK_TEST_CONDITION(mitk::Equal(pointSet1->GetPoint(0), point1), "Pointset 1 correct?");
  MITK_TEST_CONDITION(mitk::Equal(pointSet2->GetPoint(0), point2), "Pointset 2 correct?");
  MITK_TEST_CONDITION(mitk::Equal(pointSet3->GetPoint(0), point3), "Pointset 3 correct?");
}

static void TestMode4D()
{
  Setup();
  m_NavigationDataToPointSetFilter->SetOperationMode(mitk::NavigationDataToPointSetFilter::Mode4D);
  m_NavigationDataToPointSetFilter->SetRingBufferSize(2);

  //Build up test data
  mitk::NavigationData::Pointer nd = mitk::NavigationData::New();
  mitk::NavigationData::Pointer nd2 = mitk::NavigationData::New();
  mitk::NavigationData::Pointer nd3 = mitk::NavigationData::New();
  mitk::NavigationData::Pointer nd4 = mitk::NavigationData::New();

  mitk::NavigationData::PositionType point;

  point[0] = 1.0;
  point[1] = 2.0;
  point[2] = 3.0;
  nd->SetPosition(point);

  point[0] = 4.0;
  point[1] = 5.0;
  point[2] = 6.0;
  nd2->SetPosition(point);

  point[0] = 7.0;
  point[1] = 8.0;
  point[2] = 9.0;
  nd3->SetPosition(point);

  point[0] = 10.0;
  point[1] = 11.0;
  point[2] = 12.0;
  nd4->SetPosition(point);

  m_NavigationDataToPointSetFilter->SetInput(0, nd);
  m_NavigationDataToPointSetFilter->SetInput(1, nd2);

  mitk::PointSet::Pointer pointSet = m_NavigationDataToPointSetFilter->GetOutput();
  pointSet->Update();

  MITK_TEST_CONDITION( pointSet->GetPoint(0,0)[0] == 1.0 && pointSet->GetPoint(0,0)[1] == 2.0 && pointSet->GetPoint(0,0)[2] == 3.0 &&
    pointSet->GetPoint(1,0)[0] == 4.0 && pointSet->GetPoint(1,0)[1] == 5.0 && pointSet->GetPoint(1,0)[2] == 6.0
    , "Testing the conversion of navigation data object to one point set in Mode 4D in first timestep" );

  m_NavigationDataToPointSetFilter->SetInput(0, nd3);
  m_NavigationDataToPointSetFilter->SetInput(1, nd4);
  m_NavigationDataToPointSetFilter->Update();
  pointSet = m_NavigationDataToPointSetFilter->GetOutput();

  MITK_TEST_CONDITION( pointSet->GetPoint(0,0)[0] == 1.0 && pointSet->GetPoint(0,0)[1] == 2.0 && pointSet->GetPoint(0,0)[2] == 3.0 &&
    pointSet->GetPoint(1,0)[0] == 4.0 && pointSet->GetPoint(1,0)[1] == 5.0 && pointSet->GetPoint(1,0)[2] == 6.0 &&
    pointSet->GetPoint(0,1)[0] == 7.0 && pointSet->GetPoint(0,1)[1] == 8.0 && pointSet->GetPoint(0,1)[2] == 9.0 &&
    pointSet->GetPoint(1,1)[0] == 10.0 && pointSet->GetPoint(1,1)[1] == 11.0 && pointSet->GetPoint(1,1)[2] == 12.0
    , "Testing the conversion of navigation data object to one point set in Mode 4D in second timestep" );

  m_NavigationDataToPointSetFilter->SetInput(0, nd3);
  m_NavigationDataToPointSetFilter->SetInput(1, nd4);
  pointSet = m_NavigationDataToPointSetFilter->GetOutput();
  pointSet->Update();

  MITK_TEST_CONDITION( pointSet->GetPoint(0,0)[0] == 7.0 && pointSet->GetPoint(0,0)[1] == 8.0 && pointSet->GetPoint(0,0)[2] == 9.0 &&
    pointSet->GetPoint(1,0)[0] == 10.0 && pointSet->GetPoint(1,0)[1] == 11.0 && pointSet->GetPoint(1,0)[2] == 12.0 &&
    pointSet->GetPoint(0,1)[0] == 7.0 && pointSet->GetPoint(0,1)[1] == 8.0 && pointSet->GetPoint(0,1)[2] == 9.0 &&
    pointSet->GetPoint(1,1)[0] == 10.0 && pointSet->GetPoint(1,1)[1] == 11.0 && pointSet->GetPoint(1,1)[2] == 12.0
    , "Testing the correct ring buffer behavior" );
}

static void TestMode3DMean()
{
  Setup();
  m_NavigationDataToPointSetFilter->SetOperationMode(mitk::NavigationDataToPointSetFilter::Mode3DMean);
  int numberForMean = 5;
  m_NavigationDataToPointSetFilter->SetNumberForMean(numberForMean);

  MITK_TEST_CONDITION(mitk::Equal(m_NavigationDataToPointSetFilter->GetNumberForMean(), numberForMean), "Testing get/set for numberForMean");

  mitk::NavigationDataSequentialPlayer::Pointer player = mitk::NavigationDataSequentialPlayer::New();

  std::string file(MITK_IGT_DATA_DIR);
  file.append("/NavigationDataTestData_2Tools.xml");

  mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New();

  player->SetNavigationDataSet( reader->Read(file) );

  for (unsigned int i = 0; i< player->GetNumberOfOutputs(); i++)
  {
    m_NavigationDataToPointSetFilter->SetInput(i, player->GetOutput(i));
  }

  mitk::PointSet::Pointer pointSet0 = m_NavigationDataToPointSetFilter->GetOutput();
  mitk::PointSet::Pointer pointSet1 = m_NavigationDataToPointSetFilter->GetOutput(1);

  m_NavigationDataToPointSetFilter->Update();

  MITK_TEST_CONDITION(pointSet0->GetPoint(0)[0]==3.0 && pointSet0->GetPoint(0)[1]==2.0 && pointSet0->GetPoint(0)[2]==5.0,
    "Testing the average of first input");

  MITK_TEST_CONDITION(pointSet1->GetPoint(0)[0]==30.0 && pointSet1->GetPoint(0)[1]==20.0 && pointSet1->GetPoint(0)[2]==50.0,
    "Testing the average of second input");
}

static void NavigationDataToPointSetFilterContructor_DefaultCall_IsNotEmpty()
{
  Setup();
  MITK_TEST_CONDITION_REQUIRED(m_NavigationDataToPointSetFilter.IsNotNull(),"Testing instantiation");
  //I think this test is meaningless, because it will never ever fail. I keep it for know just to be save.
}

static void NavigationDataToPointSetFilterSetInput_SimplePoint_EqualsGroundTruth()
{
  Setup();

  mitk::NavigationData::Pointer nd_in = mitk::NavigationData::New();
  const mitk::NavigationData* nd_out = mitk::NavigationData::New();
  mitk::NavigationData::PositionType point;

  point[0] = 1.0;
  point[1] = 2.0;
  point[2] = 3.0;
  nd_in->SetPosition(point);

  m_NavigationDataToPointSetFilter->SetInput(nd_in);
  nd_out = m_NavigationDataToPointSetFilter->GetInput();

  MITK_TEST_CONDITION( nd_out->GetPosition() == nd_in->GetPosition(),
    "Testing get/set input" );
}

int mitkNavigationDataToPointSetFilterTest(int /* argc */, char* /*argv*/[])
{
  MITK_TEST_BEGIN("NavigationDataToPointSetFilter");

  NavigationDataToPointSetFilterContructor_DefaultCall_IsNotEmpty();
  NavigationDataToPointSetFilterSetInput_SimplePoint_EqualsGroundTruth();
  TestMode3D();
  TestMode4D();
  TestMode3DMean();

  MITK_TEST_END();
}
<commit_msg>TestMode3DMean doesn't work in debug mode. See bug 17763.<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "mitkNavigationDataToPointSetFilter.h"
#include "mitkNavigationDataSequentialPlayer.h"
#include "mitkNavigationDataReaderXML.h"
#include <mitkIGTConfig.h>
#include <mitkTestingMacros.h>

#include <iostream>

/**
*  Simple example for a test for the (non-existent) class "NavigationDataToPointSetFilter".
*
*  argc and argv are the command line parameters which were passed to
*  the ADD_TEST command in the CMakeLists.txt file. For the automatic
*  tests, argv is either empty for the simple tests or contains the filename
*  of a test image for the image tests (see CMakeLists.txt).
*/

mitk::NavigationDataToPointSetFilter::Pointer m_NavigationDataToPointSetFilter;

static void Setup()
{
  m_NavigationDataToPointSetFilter = mitk::NavigationDataToPointSetFilter::New();
}

static void TestMode3D()
{
  Setup();
  m_NavigationDataToPointSetFilter->SetOperationMode(mitk::NavigationDataToPointSetFilter::Mode3D);

  //Build up test data
  mitk::NavigationData::Pointer nd0 = mitk::NavigationData::New();
  mitk::NavigationData::Pointer nd1 = mitk::NavigationData::New();
  mitk::NavigationData::Pointer nd2 = mitk::NavigationData::New();
  mitk::NavigationData::Pointer nd3 = mitk::NavigationData::New();

  mitk::NavigationData::PositionType point0;
  point0[0] = 1.0;
  point0[1] = 2.0;
  point0[2] = 3.0;
  nd0->SetPosition(point0);
  nd0->SetDataValid(true);

  mitk::NavigationData::PositionType point1;
  point1[0] = 4.0;
  point1[1] = 5.0;
  point1[2] = 6.0;
  nd1->SetPosition(point1);
  nd1->SetDataValid(true);

  mitk::NavigationData::PositionType point2;
  point2[0] = 7.0;
  point2[1] = 8.0;
  point2[2] = 9.0;
  nd2->SetPosition(point2);
  nd2->SetDataValid(true);

  mitk::NavigationData::PositionType point3;
  point3[0] = 10.0;
  point3[1] = 11.0;
  point3[2] = 12.0;
  nd3->SetPosition(point3);
  nd3->SetDataValid(true);

  m_NavigationDataToPointSetFilter->SetInput(0, nd0);
  m_NavigationDataToPointSetFilter->SetInput(1, nd1);
  m_NavigationDataToPointSetFilter->SetInput(2, nd2);
  m_NavigationDataToPointSetFilter->SetInput(3, nd3);

  //Process
  mitk::PointSet::Pointer pointSet0 = m_NavigationDataToPointSetFilter->GetOutput();
  mitk::PointSet::Pointer pointSet1 = m_NavigationDataToPointSetFilter->GetOutput(1);
  mitk::PointSet::Pointer pointSet2 = m_NavigationDataToPointSetFilter->GetOutput(2);
  mitk::PointSet::Pointer pointSet3 = m_NavigationDataToPointSetFilter->GetOutput(3);

  pointSet0->Update();

  MITK_TEST_OUTPUT(<< "Testing the conversion of navigation data object to PointSets in Mode 3D:");
  MITK_TEST_CONDITION(mitk::Equal(pointSet0->GetPoint(0), point0), "Pointset 0 correct?");
  MITK_TEST_CONDITION(mitk::Equal(pointSet1->GetPoint(0), point1), "Pointset 1 correct?");
  MITK_TEST_CONDITION(mitk::Equal(pointSet2->GetPoint(0), point2), "Pointset 2 correct?");
  MITK_TEST_CONDITION(mitk::Equal(pointSet3->GetPoint(0), point3), "Pointset 3 correct?");
}

static void TestMode4D()
{
  Setup();
  m_NavigationDataToPointSetFilter->SetOperationMode(mitk::NavigationDataToPointSetFilter::Mode4D);
  m_NavigationDataToPointSetFilter->SetRingBufferSize(2);

  //Build up test data
  mitk::NavigationData::Pointer nd = mitk::NavigationData::New();
  mitk::NavigationData::Pointer nd2 = mitk::NavigationData::New();
  mitk::NavigationData::Pointer nd3 = mitk::NavigationData::New();
  mitk::NavigationData::Pointer nd4 = mitk::NavigationData::New();

  mitk::NavigationData::PositionType point;

  point[0] = 1.0;
  point[1] = 2.0;
  point[2] = 3.0;
  nd->SetPosition(point);

  point[0] = 4.0;
  point[1] = 5.0;
  point[2] = 6.0;
  nd2->SetPosition(point);

  point[0] = 7.0;
  point[1] = 8.0;
  point[2] = 9.0;
  nd3->SetPosition(point);

  point[0] = 10.0;
  point[1] = 11.0;
  point[2] = 12.0;
  nd4->SetPosition(point);

  m_NavigationDataToPointSetFilter->SetInput(0, nd);
  m_NavigationDataToPointSetFilter->SetInput(1, nd2);

  mitk::PointSet::Pointer pointSet = m_NavigationDataToPointSetFilter->GetOutput();
  pointSet->Update();

  MITK_TEST_CONDITION( pointSet->GetPoint(0,0)[0] == 1.0 && pointSet->GetPoint(0,0)[1] == 2.0 && pointSet->GetPoint(0,0)[2] == 3.0 &&
    pointSet->GetPoint(1,0)[0] == 4.0 && pointSet->GetPoint(1,0)[1] == 5.0 && pointSet->GetPoint(1,0)[2] == 6.0
    , "Testing the conversion of navigation data object to one point set in Mode 4D in first timestep" );

  m_NavigationDataToPointSetFilter->SetInput(0, nd3);
  m_NavigationDataToPointSetFilter->SetInput(1, nd4);
  m_NavigationDataToPointSetFilter->Update();
  pointSet = m_NavigationDataToPointSetFilter->GetOutput();

  MITK_TEST_CONDITION( pointSet->GetPoint(0,0)[0] == 1.0 && pointSet->GetPoint(0,0)[1] == 2.0 && pointSet->GetPoint(0,0)[2] == 3.0 &&
    pointSet->GetPoint(1,0)[0] == 4.0 && pointSet->GetPoint(1,0)[1] == 5.0 && pointSet->GetPoint(1,0)[2] == 6.0 &&
    pointSet->GetPoint(0,1)[0] == 7.0 && pointSet->GetPoint(0,1)[1] == 8.0 && pointSet->GetPoint(0,1)[2] == 9.0 &&
    pointSet->GetPoint(1,1)[0] == 10.0 && pointSet->GetPoint(1,1)[1] == 11.0 && pointSet->GetPoint(1,1)[2] == 12.0
    , "Testing the conversion of navigation data object to one point set in Mode 4D in second timestep" );

  m_NavigationDataToPointSetFilter->SetInput(0, nd3);
  m_NavigationDataToPointSetFilter->SetInput(1, nd4);
  pointSet = m_NavigationDataToPointSetFilter->GetOutput();
  pointSet->Update();

  MITK_TEST_CONDITION( pointSet->GetPoint(0,0)[0] == 7.0 && pointSet->GetPoint(0,0)[1] == 8.0 && pointSet->GetPoint(0,0)[2] == 9.0 &&
    pointSet->GetPoint(1,0)[0] == 10.0 && pointSet->GetPoint(1,0)[1] == 11.0 && pointSet->GetPoint(1,0)[2] == 12.0 &&
    pointSet->GetPoint(0,1)[0] == 7.0 && pointSet->GetPoint(0,1)[1] == 8.0 && pointSet->GetPoint(0,1)[2] == 9.0 &&
    pointSet->GetPoint(1,1)[0] == 10.0 && pointSet->GetPoint(1,1)[1] == 11.0 && pointSet->GetPoint(1,1)[2] == 12.0
    , "Testing the correct ring buffer behavior" );
}

static void TestMode3DMean()
{
  Setup();
  m_NavigationDataToPointSetFilter->SetOperationMode(mitk::NavigationDataToPointSetFilter::Mode3DMean);
  int numberForMean = 5;
  m_NavigationDataToPointSetFilter->SetNumberForMean(numberForMean);

  MITK_TEST_CONDITION(mitk::Equal(m_NavigationDataToPointSetFilter->GetNumberForMean(), numberForMean), "Testing get/set for numberForMean");

  mitk::NavigationDataSequentialPlayer::Pointer player = mitk::NavigationDataSequentialPlayer::New();

  std::string file(MITK_IGT_DATA_DIR);
  file.append("/NavigationDataTestData_2Tools.xml");

  mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New();

  player->SetNavigationDataSet( reader->Read(file) );

  for (unsigned int i = 0; i< player->GetNumberOfOutputs(); i++)
  {
    m_NavigationDataToPointSetFilter->SetInput(i, player->GetOutput(i));
  }

  mitk::PointSet::Pointer pointSet0 = m_NavigationDataToPointSetFilter->GetOutput();
  mitk::PointSet::Pointer pointSet1 = m_NavigationDataToPointSetFilter->GetOutput(1);

  m_NavigationDataToPointSetFilter->Update();

  MITK_TEST_CONDITION(pointSet0->GetPoint(0)[0]==3.0 && pointSet0->GetPoint(0)[1]==2.0 && pointSet0->GetPoint(0)[2]==5.0,
    "Testing the average of first input");

  MITK_TEST_CONDITION(pointSet1->GetPoint(0)[0]==30.0 && pointSet1->GetPoint(0)[1]==20.0 && pointSet1->GetPoint(0)[2]==50.0,
    "Testing the average of second input");
}

static void NavigationDataToPointSetFilterContructor_DefaultCall_IsNotEmpty()
{
  Setup();
  MITK_TEST_CONDITION_REQUIRED(m_NavigationDataToPointSetFilter.IsNotNull(),"Testing instantiation");
  //I think this test is meaningless, because it will never ever fail. I keep it for know just to be save.
}

static void NavigationDataToPointSetFilterSetInput_SimplePoint_EqualsGroundTruth()
{
  Setup();

  mitk::NavigationData::Pointer nd_in = mitk::NavigationData::New();
  const mitk::NavigationData* nd_out = mitk::NavigationData::New();
  mitk::NavigationData::PositionType point;

  point[0] = 1.0;
  point[1] = 2.0;
  point[2] = 3.0;
  nd_in->SetPosition(point);

  m_NavigationDataToPointSetFilter->SetInput(nd_in);
  nd_out = m_NavigationDataToPointSetFilter->GetInput();

  MITK_TEST_CONDITION( nd_out->GetPosition() == nd_in->GetPosition(),
    "Testing get/set input" );
}

int mitkNavigationDataToPointSetFilterTest(int /* argc */, char* /*argv*/[])
{
  MITK_TEST_BEGIN("NavigationDataToPointSetFilter");

  NavigationDataToPointSetFilterContructor_DefaultCall_IsNotEmpty();
  NavigationDataToPointSetFilterSetInput_SimplePoint_EqualsGroundTruth();
  TestMode3D();
  TestMode4D();
//  TestMode3DMean(); //infinite loop in debug mode, see bug 17763

  MITK_TEST_END();
}
<|endoftext|>


<commit_before>#include "bim.hpp"

namespace bim {

	Chunk::Chunk() :
		m_address(0),
		m_properties(Property::DONT_CARE),
		m_numTrianglesPerLeaf(0),
		m_numTreeLevels(0)
	{
	}

	void Chunk::addVertex(const FullVertex& _properties)
	{
		if(m_positions.empty())
			m_boundingBox.min = m_boundingBox.max = _properties.position;
		else {
			m_boundingBox.min = min(_properties.position, m_boundingBox.min);
			m_boundingBox.max = max(_properties.position, m_boundingBox.max);
		}
		m_positions.push_back(_properties.position);
		if(m_properties & Property::NORMAL)
			m_normals.push_back(_properties.normal);
		if(m_properties & Property::TANGENT)
			m_tangents.push_back(_properties.tangent);
		if(m_properties & Property::BITANGENT)
			m_bitangents.push_back(_properties.bitangent);
		if(m_properties & Property::QORMAL)
			m_qormals.push_back(_properties.qormal);
		if(m_properties & Property::TEXCOORD0)
			m_texCoords0.push_back(_properties.texCoord0);
		if(m_properties & Property::TEXCOORD1)
			m_texCoords1.push_back(_properties.texCoord1);
		if(m_properties & Property::TEXCOORD2)
			m_texCoords2.push_back(_properties.texCoord2);
		if(m_properties & Property::TEXCOORD3)
			m_texCoords3.push_back(_properties.texCoord3);
		if(m_properties & Property::COLOR)
			m_colors.push_back(_properties.color);
	}

	void Chunk::addTriangle(const ei::UVec3& _indices, uint32 _material)
	{
		m_triangles.push_back(_indices);
		if(m_properties & Property::TRIANGLE_MAT)
			m_triangleMaterials.push_back(_material);
	}

	static ei::Vec3 denoise(const ei::Vec3& _x)
	{
		 return *reinterpret_cast<const ei::Vec3*>(&(*reinterpret_cast<const ei::UVec3*>(&_x) & 0xfffffff0));
	}
	static ei::Vec2 denoise(const ei::Vec2& _x)
	{
		return *reinterpret_cast<const ei::Vec2*>(&(*reinterpret_cast<const ei::UVec2*>(&_x) & 0xfffffff0));
	}

	void Chunk::removeRedundantVertices()
	{
		invalidateHierarchy();

		std::unordered_map<FullVertex, uint> vertexToIndex;
		uint index = 0;
		size_t numVertices = m_positions.size();
		// Initialize the index mapping to index->self
		std::vector<uint> indexToIndex(numVertices);
		for(size_t i = 0; i < numVertices; ++i)
			indexToIndex[i] = (uint)i;
		// For each vertex
		for(size_t i = 0; i < numVertices; ++i)
		{
			// Create a key
			FullVertex key;
			// Round properties (denoise) in vertices (otherwise hashing will miss many)
			key.position = denoise(m_positions[i]);
			if(!m_normals.empty()) key.normal = normalize(denoise(m_normals[i]));
			if(!m_tangents.empty()) key.tangent = normalize(denoise(m_tangents[i]));
			if(!m_bitangents.empty()) key.bitangent = normalize(denoise(m_bitangents[i]));
			if(!m_qormals.empty()) key.qormal = m_qormals[i]; // TODO denoise
			if(!m_texCoords0.empty()) key.texCoord0 = denoise(m_texCoords0[i]);
			if(!m_texCoords1.empty()) key.texCoord1 = denoise(m_texCoords1[i]);
			if(!m_texCoords2.empty()) key.texCoord2 = denoise(m_texCoords2[i]);
			if(!m_texCoords3.empty()) key.texCoord3 = denoise(m_texCoords3[i]);
			if(!m_colors.empty()) key.color = m_colors[i];
			// Get the index
			auto it = vertexToIndex.find(key);
			if(it == vertexToIndex.end())
			{
				// This is a new vertex -> keep (but move to index)
				vertexToIndex[key] = index;
				indexToIndex[i] = index;
				// Move data from i -> index
				m_positions[index] = m_positions[i];
				if(!m_normals.empty()) m_normals[index] = m_normals[i];
				if(!m_tangents.empty()) m_tangents[index] = m_tangents[i];
				if(!m_bitangents.empty()) m_bitangents[index] = m_bitangents[i];
				if(!m_qormals.empty()) m_qormals[index] = m_qormals[i];
				if(!m_texCoords0.empty()) m_texCoords0[index] = m_texCoords0[i];
				if(!m_texCoords1.empty()) m_texCoords1[index] = m_texCoords1[i];
				if(!m_texCoords2.empty()) m_texCoords2[index] = m_texCoords2[i];
				if(!m_texCoords3.empty()) m_texCoords3[index] = m_texCoords3[i];
				if(!m_colors.empty()) m_colors[index] = m_colors[i];
				++index;
			} else {
				indexToIndex[i] = it->second;
			}
		}
		// All vertices we kept are moved to a block of size 'index'. The remaining
		// part can be removed.
		m_positions.resize(index);
		if(!m_normals.empty()) m_normals.resize(index);
		if(!m_tangents.empty()) m_tangents.resize(index);
		if(!m_bitangents.empty()) m_bitangents.resize(index);
		if(!m_qormals.empty()) m_qormals.resize(index);
		if(!m_texCoords0.empty()) m_texCoords0.resize(index);
		if(!m_texCoords1.empty()) m_texCoords1.resize(index);
		if(!m_texCoords2.empty()) m_texCoords2.resize(index);
		if(!m_texCoords3.empty()) m_texCoords3.resize(index);
		if(!m_colors.empty()) m_colors.resize(index);

		// Rebuild index buffer
		for(size_t i = 0; i < m_triangles.size(); ++i)
		{
			m_triangles[i].x = indexToIndex[m_triangles[i].x];
			m_triangles[i].y = indexToIndex[m_triangles[i].y];
			m_triangles[i].z = indexToIndex[m_triangles[i].z];
		}
	}

	void Chunk::rebuildHierarchy(BuildMethod _method, uint _numTrianglesPerLeaf)
	{
		m_numTrianglesPerLeaf = _numTrianglesPerLeaf;
		switch(_method)
		{
		case BuildMethod::KD_TREE:
			buildBVH_kdtree();
			break;
		case BuildMethod::SAH:
			buildBVH_SAHsplit();
			break;
		}

		m_numTreeLevels = remapNodePointers(0, 0, 0);
		m_properties = Property::Val(m_properties | Property::HIERARCHY);
	}

	void Chunk::addProperty(Property::Val _property)
	{
		if(!(m_properties & _property))
		{
			switch(_property)
			{
			case Property::NORMAL: swap(m_normals, std::vector<ei::Vec3>(m_positions.size(), FullVertex().position)); break;
			case Property::TANGENT: swap(m_tangents, std::vector<ei::Vec3>(m_positions.size(), FullVertex().tangent)); break;
			case Property::BITANGENT: swap(m_bitangents, std::vector<ei::Vec3>(m_positions.size(), FullVertex().bitangent)); break;
			case Property::QORMAL: swap(m_qormals, std::vector<ei::Quaternion>(m_positions.size(), FullVertex().qormal)); break;
			case Property::TEXCOORD0: swap(m_texCoords0, std::vector<ei::Vec2>(m_positions.size(), FullVertex().texCoord0)); break;
			case Property::TEXCOORD1: swap(m_texCoords0, std::vector<ei::Vec2>(m_positions.size(), FullVertex().texCoord1)); break;
			case Property::TEXCOORD2: swap(m_texCoords0, std::vector<ei::Vec2>(m_positions.size(), FullVertex().texCoord2)); break;
			case Property::TEXCOORD3: swap(m_texCoords0, std::vector<ei::Vec2>(m_positions.size(), FullVertex().texCoord3)); break;
			case Property::COLOR: swap(m_colors, std::vector<uint32>(m_positions.size(), FullVertex().color)); break;
			case Property::TRIANGLE_MAT: swap(m_triangleMaterials, std::vector<uint32>(m_triangles.size(), 0)); break;
			case Property::AABOX_BVH: swap(m_aaBoxes, std::vector<ei::Box>(m_hierarchy.size())); break;
			case Property::OBOX_BVH: //swap(m_aaBoxes, std::vector<ei::Box>(m_hierarchy.size())); break;
			case Property::SPHERE_BVH: //swap(m_aaBoxes, std::vector<ei::Box>(m_hierarchy.size())); break;
			case Property::NDF_SGGX: swap(m_nodeNDFs, std::vector<SGGX>(m_hierarchy.size())); break;
			default: return;
			}
			m_properties = Property::Val(m_properties | _property);
		}
	}

	void Chunk::invalidateHierarchy()
	{
		// Remove all data, it needs to be recomputed anyway
		m_hierarchy.clear();
		m_hierarchyLeaves.clear();
		m_aaBoxes.clear();
		m_nodeNDFs.clear();
		m_properties = Property::Val(m_properties
			& ~(Property::HIERARCHY | Property::AABOX_BVH
			  | Property::OBOX_BVH | Property::SPHERE_BVH | Property::NDF_SGGX));
		m_numTreeLevels = 0;
	}

	// ********************************************************************* //
	Chunk::FullVertex::FullVertex() :
		position(0.0f),
		normal(0.0f, 1.0f, 0.0),
		tangent(1.0f, 0.0f, 0.0f),
		bitangent(0.0f, 0.0f, 1.0f),
		qormal(ei::qidentity()),
		texCoord0(0.0f),
		texCoord1(0.0f),
		texCoord2(0.0f),
		texCoord3(0.0f),
		color(0)
	{
	}

	bool Chunk::FullVertex::operator == (const FullVertex& _rhs) const
	{
		if(any(position != _rhs.position)) return false;
		if(any(normal != _rhs.normal)) return false;
		if(any(tangent != _rhs.tangent)) return false;
		if(any(bitangent != _rhs.bitangent)) return false;
		if(qormal != _rhs.qormal) return false;
		if(any(texCoord0 != _rhs.texCoord0)) return false;
		if(any(texCoord1 != _rhs.texCoord1)) return false;
		if(any(texCoord2 != _rhs.texCoord2)) return false;
		if(any(texCoord3 != _rhs.texCoord3)) return false;
		if(color != _rhs.color) return false;
		return true;
	}

} // namespace bim<commit_msg>removeRedundantVertices also removes degenerated triangles<commit_after>#include "bim.hpp"

namespace bim {

	Chunk::Chunk() :
		m_address(0),
		m_properties(Property::DONT_CARE),
		m_numTrianglesPerLeaf(0),
		m_numTreeLevels(0)
	{
	}

	void Chunk::addVertex(const FullVertex& _properties)
	{
		if(m_positions.empty())
			m_boundingBox.min = m_boundingBox.max = _properties.position;
		else {
			m_boundingBox.min = min(_properties.position, m_boundingBox.min);
			m_boundingBox.max = max(_properties.position, m_boundingBox.max);
		}
		m_positions.push_back(_properties.position);
		if(m_properties & Property::NORMAL)
			m_normals.push_back(_properties.normal);
		if(m_properties & Property::TANGENT)
			m_tangents.push_back(_properties.tangent);
		if(m_properties & Property::BITANGENT)
			m_bitangents.push_back(_properties.bitangent);
		if(m_properties & Property::QORMAL)
			m_qormals.push_back(_properties.qormal);
		if(m_properties & Property::TEXCOORD0)
			m_texCoords0.push_back(_properties.texCoord0);
		if(m_properties & Property::TEXCOORD1)
			m_texCoords1.push_back(_properties.texCoord1);
		if(m_properties & Property::TEXCOORD2)
			m_texCoords2.push_back(_properties.texCoord2);
		if(m_properties & Property::TEXCOORD3)
			m_texCoords3.push_back(_properties.texCoord3);
		if(m_properties & Property::COLOR)
			m_colors.push_back(_properties.color);
	}

	void Chunk::addTriangle(const ei::UVec3& _indices, uint32 _material)
	{
		m_triangles.push_back(_indices);
		if(m_properties & Property::TRIANGLE_MAT)
			m_triangleMaterials.push_back(_material);
	}

	static ei::Vec3 denoise(const ei::Vec3& _x)
	{
		 return *reinterpret_cast<const ei::Vec3*>(&(*reinterpret_cast<const ei::UVec3*>(&_x) & 0xfffffff0));
	}
	static ei::Vec2 denoise(const ei::Vec2& _x)
	{
		return *reinterpret_cast<const ei::Vec2*>(&(*reinterpret_cast<const ei::UVec2*>(&_x) & 0xfffffff0));
	}

	void Chunk::removeRedundantVertices()
	{
		invalidateHierarchy();

		std::unordered_map<FullVertex, uint> vertexToIndex;
		uint index = 0;
		size_t numVertices = m_positions.size();
		// Initialize the index mapping to index->self
		std::vector<uint> indexToIndex(numVertices);
		for(size_t i = 0; i < numVertices; ++i)
			indexToIndex[i] = (uint)i;
		// For each vertex
		for(size_t i = 0; i < numVertices; ++i)
		{
			// Create a key
			FullVertex key;
			// Round properties (denoise) in vertices (otherwise hashing will miss many)
			key.position = denoise(m_positions[i]);
			if(!m_normals.empty()) key.normal = normalize(denoise(m_normals[i]));
			if(!m_tangents.empty()) key.tangent = normalize(denoise(m_tangents[i]));
			if(!m_bitangents.empty()) key.bitangent = normalize(denoise(m_bitangents[i]));
			if(!m_qormals.empty()) key.qormal = m_qormals[i]; // TODO denoise
			if(!m_texCoords0.empty()) key.texCoord0 = denoise(m_texCoords0[i]);
			if(!m_texCoords1.empty()) key.texCoord1 = denoise(m_texCoords1[i]);
			if(!m_texCoords2.empty()) key.texCoord2 = denoise(m_texCoords2[i]);
			if(!m_texCoords3.empty()) key.texCoord3 = denoise(m_texCoords3[i]);
			if(!m_colors.empty()) key.color = m_colors[i];
			// Get the index
			auto it = vertexToIndex.find(key);
			if(it == vertexToIndex.end())
			{
				// This is a new vertex -> keep (but move to index)
				vertexToIndex[key] = index;
				indexToIndex[i] = index;
				// Move data from i -> index
				m_positions[index] = m_positions[i];
				if(!m_normals.empty()) m_normals[index] = m_normals[i];
				if(!m_tangents.empty()) m_tangents[index] = m_tangents[i];
				if(!m_bitangents.empty()) m_bitangents[index] = m_bitangents[i];
				if(!m_qormals.empty()) m_qormals[index] = m_qormals[i];
				if(!m_texCoords0.empty()) m_texCoords0[index] = m_texCoords0[i];
				if(!m_texCoords1.empty()) m_texCoords1[index] = m_texCoords1[i];
				if(!m_texCoords2.empty()) m_texCoords2[index] = m_texCoords2[i];
				if(!m_texCoords3.empty()) m_texCoords3[index] = m_texCoords3[i];
				if(!m_colors.empty()) m_colors[index] = m_colors[i];
				++index;
			} else {
				indexToIndex[i] = it->second;
			}
		}
		// All vertices we kept are moved to a block of size 'index'. The remaining
		// part can be removed.
		m_positions.resize(index);
		if(!m_normals.empty()) m_normals.resize(index);
		if(!m_tangents.empty()) m_tangents.resize(index);
		if(!m_bitangents.empty()) m_bitangents.resize(index);
		if(!m_qormals.empty()) m_qormals.resize(index);
		if(!m_texCoords0.empty()) m_texCoords0.resize(index);
		if(!m_texCoords1.empty()) m_texCoords1.resize(index);
		if(!m_texCoords2.empty()) m_texCoords2.resize(index);
		if(!m_texCoords3.empty()) m_texCoords3.resize(index);
		if(!m_colors.empty()) m_colors.resize(index);

		// Rebuild index buffer
		size_t numInvalidTriangles = 0;
		for(size_t i = 0; i < m_triangles.size(); ++i)
		{
			if(m_triangles[i].x == m_triangles[i].y
				|| m_triangles[i].x == m_triangles[i].z
				|| m_triangles[i].y == m_triangles[i].z)
				++numInvalidTriangles;
			else {
				m_triangles[i-numInvalidTriangles].x = indexToIndex[m_triangles[i].x];
				m_triangles[i-numInvalidTriangles].y = indexToIndex[m_triangles[i].y];
				m_triangles[i-numInvalidTriangles].z = indexToIndex[m_triangles[i].z];
			}
		}
		m_triangles.resize(m_triangles.size() - numInvalidTriangles);
	}

	void Chunk::rebuildHierarchy(BuildMethod _method, uint _numTrianglesPerLeaf)
	{
		m_numTrianglesPerLeaf = _numTrianglesPerLeaf;
		switch(_method)
		{
		case BuildMethod::KD_TREE:
			buildBVH_kdtree();
			break;
		case BuildMethod::SAH:
			buildBVH_SAHsplit();
			break;
		}

		m_numTreeLevels = remapNodePointers(0, 0, 0);
		m_properties = Property::Val(m_properties | Property::HIERARCHY);
	}

	void Chunk::addProperty(Property::Val _property)
	{
		if(!(m_properties & _property))
		{
			switch(_property)
			{
			case Property::NORMAL: swap(m_normals, std::vector<ei::Vec3>(m_positions.size(), FullVertex().position)); break;
			case Property::TANGENT: swap(m_tangents, std::vector<ei::Vec3>(m_positions.size(), FullVertex().tangent)); break;
			case Property::BITANGENT: swap(m_bitangents, std::vector<ei::Vec3>(m_positions.size(), FullVertex().bitangent)); break;
			case Property::QORMAL: swap(m_qormals, std::vector<ei::Quaternion>(m_positions.size(), FullVertex().qormal)); break;
			case Property::TEXCOORD0: swap(m_texCoords0, std::vector<ei::Vec2>(m_positions.size(), FullVertex().texCoord0)); break;
			case Property::TEXCOORD1: swap(m_texCoords0, std::vector<ei::Vec2>(m_positions.size(), FullVertex().texCoord1)); break;
			case Property::TEXCOORD2: swap(m_texCoords0, std::vector<ei::Vec2>(m_positions.size(), FullVertex().texCoord2)); break;
			case Property::TEXCOORD3: swap(m_texCoords0, std::vector<ei::Vec2>(m_positions.size(), FullVertex().texCoord3)); break;
			case Property::COLOR: swap(m_colors, std::vector<uint32>(m_positions.size(), FullVertex().color)); break;
			case Property::TRIANGLE_MAT: swap(m_triangleMaterials, std::vector<uint32>(m_triangles.size(), 0)); break;
			case Property::AABOX_BVH: swap(m_aaBoxes, std::vector<ei::Box>(m_hierarchy.size())); break;
			case Property::OBOX_BVH: //swap(m_aaBoxes, std::vector<ei::Box>(m_hierarchy.size())); break;
			case Property::SPHERE_BVH: //swap(m_aaBoxes, std::vector<ei::Box>(m_hierarchy.size())); break;
			case Property::NDF_SGGX: swap(m_nodeNDFs, std::vector<SGGX>(m_hierarchy.size())); break;
			default: return;
			}
			m_properties = Property::Val(m_properties | _property);
		}
	}

	void Chunk::invalidateHierarchy()
	{
		// Remove all data, it needs to be recomputed anyway
		m_hierarchy.clear();
		m_hierarchyLeaves.clear();
		m_aaBoxes.clear();
		m_nodeNDFs.clear();
		m_properties = Property::Val(m_properties
			& ~(Property::HIERARCHY | Property::AABOX_BVH
			  | Property::OBOX_BVH | Property::SPHERE_BVH | Property::NDF_SGGX));
		m_numTreeLevels = 0;
	}

	// ********************************************************************* //
	Chunk::FullVertex::FullVertex() :
		position(0.0f),
		normal(0.0f, 1.0f, 0.0),
		tangent(1.0f, 0.0f, 0.0f),
		bitangent(0.0f, 0.0f, 1.0f),
		qormal(ei::qidentity()),
		texCoord0(0.0f),
		texCoord1(0.0f),
		texCoord2(0.0f),
		texCoord3(0.0f),
		color(0)
	{
	}

	bool Chunk::FullVertex::operator == (const FullVertex& _rhs) const
	{
		if(any(position != _rhs.position)) return false;
		if(any(normal != _rhs.normal)) return false;
		if(any(tangent != _rhs.tangent)) return false;
		if(any(bitangent != _rhs.bitangent)) return false;
		if(qormal != _rhs.qormal) return false;
		if(any(texCoord0 != _rhs.texCoord0)) return false;
		if(any(texCoord1 != _rhs.texCoord1)) return false;
		if(any(texCoord2 != _rhs.texCoord2)) return false;
		if(any(texCoord3 != _rhs.texCoord3)) return false;
		if(color != _rhs.color) return false;
		return true;
	}

} // namespace bim<|endoftext|>


<commit_before>/*
    kopeteaway.cpp  -  Kopete Away

    Copyright (c) 2002      by Hendrik vom Lehn       <hvl@linux-4-ever.de>
    Copyright (c) 2003      Olivier Goffart           <ogoffart@tiscalinet.be>

    Kopete    (c) 2002-2003 by the Kopete developers  <kopete-devel@kde.org>

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

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include "kopeteaway.h"

#include "kopeteaccountmanager.h"
#include "kopeteaccount.h"

#include <kconfig.h>
#include <qtimer.h>
#include <kapplication.h>

#include <klocale.h>
#include <kglobal.h>
#include <kdebug.h>
#include <ksettings/dispatcher.h>

#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/Xresource.h>
// The following include is to make --enable-final work
#include <X11/Xutil.h>

#ifdef HAVE_XSCREENSAVER
#define HasScreenSaver
#include <X11/extensions/scrnsaver.h>
#endif

// As this is an untested X extension we better leave it off
#undef HAVE_XIDLE
#undef HasXidle

struct KopeteAwayPrivate
{
	QString awayMessage;
	bool globalAway;
	QValueList<KopeteAwayMessage> awayMessageList;
	QTime idleTime;
	QTimer *timer;
	bool autoaway;
	bool goAvailable;
	int awayTimeout;
	bool useAutoAway;
	QPtrList<KopeteAccount> autoAwayAccounts;

	int mouse_x;
	int mouse_y;
	unsigned int mouse_mask;
	Window    root;               /* root window the pointer is on */
	Screen*   screen;             /* screen the pointer is on      */

	Time xIdleTime;
	bool useXidle;
	bool useMit;
};

KopeteAway *KopeteAway::instance = 0L;

KopeteAway::KopeteAway() : QObject( kapp , "KopeteAway")
{
	int dummy = 0;
	dummy = dummy; // shut up

	d = new KopeteAwayPrivate;

	// Set up the away messages
	d->awayMessage = "";
	d->globalAway = false;
	d->autoaway = false;
	d->useAutoAway = true;

	// Empty the list
	d->awayMessageList.clear();

	// set the XAutoLock info
	Display *dsp = qt_xdisplay();
	d->mouse_x = d->mouse_y=0;
	d->mouse_mask = 0;
	d->root = DefaultRootWindow (dsp);
	d->screen = ScreenOfDisplay (dsp, DefaultScreen (dsp));

	d->useXidle = false;
	d->useMit = false;
#ifdef HasXidle
	d->useXidle = XidleQueryExtension(qt_xdisplay(), &dummy, &dummy);
#endif
#ifdef HasScreenSaver
	if(!d->useXidle)
		d->useMit = XScreenSaverQueryExtension(qt_xdisplay(), &dummy, &dummy);
#endif
	d->xIdleTime = 0;

	if (d->useXidle)
		kdDebug(14010) << "using X11 Xidle extension" << endl;
	if(d->useMit)
		kdDebug(14010) << "using X11 MIT Screensaver extension" << endl;

	load();
	KSettings::Dispatcher::self()->registerInstance( KGlobal::instance(), this, SLOT( load() ) );
	// Set up the config object
	KConfig *config = KGlobal::config();
	/* Load the saved away messages */
	config->setGroup("Away Messages");

	/* If Kopete has been run before, this will be true.
	* It's only false the first time Kopete is run
	*/
	if(config->hasKey("Titles"))
	{
		QStringList titles = config->readListEntry("Titles");  // Get the titles
		KopeteAwayMessage temp; // Temporary away message....
		for(QStringList::iterator i = titles.begin(); i != titles.end(); i++)
		{
			temp.title = (*i); // Grab the title from the list of messages
			temp.message = config->readEntry(temp.title); // And the message (from disk)
			d->awayMessageList.append(temp); // And add it to the list
		}
	}
	else
	{
		/* There are no away messages, so we'll create a default one */
		/* Create an away message */
		KopeteAwayMessage temp;
		temp.title = i18n("Busy");
		temp.message = i18n("Sorry, I'm busy right now");

		/* Add it to the vector */
		d->awayMessageList.append(temp);

		temp.title = i18n("Gone");
		temp.message = i18n("I'm gone right now, but I'll be back later");
		d->awayMessageList.append(temp);

		/* Save this list to disk */
		save();
	}

	// init the timer
	d->timer = new QTimer(this, "AwayTimer");
	connect(d->timer, SIGNAL(timeout()), this, SLOT(slotTimerTimeout()));
	d->timer->start(2000);

	//init the time and other
	setActivity();
}

KopeteAway::~KopeteAway()
{
	delete d;
}

QString KopeteAway::message()
{
	return getInstance()->d->awayMessage;
}

void KopeteAway::setGlobalAwayMessage(const QString &message)
{
	if( !message.isEmpty() )
	{
		kdDebug(14010) << k_funcinfo <<
			"Setting global away message: " << message << endl;
		d->awayMessage = message;
	}
}

KopeteAway *KopeteAway::getInstance()
{
	if (!instance)
		instance = new KopeteAway;
	return instance;
}

bool KopeteAway::globalAway()
{
	return getInstance()->d->globalAway;
}

void KopeteAway::setGlobalAway(bool status)
{
	getInstance()->d->globalAway = status;
}

void KopeteAway::save()
{
	KConfig *config = KGlobal::config();
	/* Set the away message settings in the Away Messages config group */
	config->setGroup("Away Messages");
	QStringList titles;
	/* For each message, keep track of the title, and write out the message */
	for(QValueList<KopeteAwayMessage>::iterator i = d->awayMessageList.begin(); i != d->awayMessageList.end(); i++)
	{
		titles.append((*i).title); // Append the title to list of titles
		config->writeEntry((*i).title, (*i).message); // Append Title->message pair to the config
	}

	/* Write out the titles */
	config->writeEntry("Titles", titles);
	config->sync();
}

void KopeteAway::load()
{
	KConfig *config = KGlobal::config();
	config->setGroup("AutoAway");
	d->awayTimeout=config->readNumEntry("Timeout", 600);
	d->goAvailable=config->readBoolEntry("GoAvailable", true);
	d->useAutoAway=config->readBoolEntry("UseAutoAway", true);

}

QStringList KopeteAway::getTitles()
{
	QStringList titles;
	for(QValueList<KopeteAwayMessage>::iterator i = d->awayMessageList.begin(); i != d->awayMessageList.end(); i++)
		titles.append((*i).title);

	return titles;
}

QString KopeteAway::getMessage(const QString &title)
{
	for(QValueList<KopeteAwayMessage>::iterator i = d->awayMessageList.begin(); i != d->awayMessageList.end(); i++)
	{
		if((*i).title == title)
			return (*i).message;
	}

	/* Return an empty string if none was found */
	return QString::null;
}

bool KopeteAway::addMessage(const QString &title, const QString &message)
{
	bool found = false;
	/* Check to see if it exists already */
	for(QValueList<KopeteAwayMessage>::iterator i = d->awayMessageList.begin(); i != d->awayMessageList.end(); i++)
	{
		if((*i).title == title)
		{
			found = true;
			break;
		}
	}

	/* If not, add it */
	if(!found)
	{
		KopeteAwayMessage temp;
		temp.title = title;
		temp.message = message;
		d->awayMessageList.append(temp);
		save();
		return true;
	}
	else
	{
		return false;
	}
}

bool KopeteAway::deleteMessage(const QString &title)
{
	/* Search for the message */
	QValueList<KopeteAwayMessage>::iterator itemToDelete = d->awayMessageList.begin();
	while( (itemToDelete != d->awayMessageList.end()) && ((*itemToDelete).title != title) )
		itemToDelete++;

	/* If it was found, delete it */
	if(itemToDelete != d->awayMessageList.end())
	{
		/* Remove it from the config entry, if it's there */
		if(KGlobal::config()->hasKey((*itemToDelete).title))
			KGlobal::config()->deleteEntry((*itemToDelete).title);

		/* Remove it from the list */
		d->awayMessageList.remove(itemToDelete);
		save();
		return true;
	}
	else
	{
		return false;
	}
}

bool KopeteAway::updateMessage(const QString &title, const QString &message)
{
	/* Search for the message */
	QValueList<KopeteAwayMessage>::iterator itemToUpdate = d->awayMessageList.begin();
	while( (itemToUpdate != d->awayMessageList.end()) && ((*itemToUpdate).title != title) )
		itemToUpdate++;

	/* If it was found, update it */
	if(itemToUpdate != d->awayMessageList.end())
	{
		(*itemToUpdate).message = message;
		save();
		return true;
	}
	else
	{
		return false;
	}
}

long int KopeteAway::idleTime()
{
	//FIXME: the time is reset to zero if more than 24 hours are elapsed
	// we can imagine someone who leave his PC for several weeks
	return (d->idleTime.elapsed() / 1000);
}

void KopeteAway::slotTimerTimeout()
{
	// Copyright (c) 1999 Martin R. Jones <mjones@kde.org>
	//
	// KDE screensaver engine
	//
	// This module is a heavily modified xautolock.
	// In fact as of KDE 2.0 this code is practically unrecognisable as xautolock.

	Display *dsp = qt_xdisplay();
	Window           dummy_w;
	int              dummy_c;
	unsigned int     mask;               /* modifier mask                 */
	int              root_x;
	int              root_y;

	/*
	*  Find out whether the pointer has moved. Using XQueryPointer for this
	*  is gross, but it also is the only way never to mess up propagation
	*  of pointer events.
	*
	*  Remark : Unlike XNextEvent(), XPending () doesn't notice if the
	*           connection to the server is lost. For this reason, earlier
	*           versions of xautolock periodically called XNoOp (). But
	*           why not let XQueryPointer () do the job for us, since
	*           we now call that periodically anyway?
	*/
	if (!XQueryPointer (dsp, d->root, &(d->root), &dummy_w, &root_x, &root_y,
			&dummy_c, &dummy_c, &mask))
	{
		/*
		*  Pointer has moved to another screen, so let's find out which one.
		*/
		for (int i = 0; i < ScreenCount(dsp); i++)
		{
			if (d->root == RootWindow(dsp, i))
			{
				d->screen = ScreenOfDisplay (dsp, i);
				break;
			}
		}
	}

	// =================================================================================

	Time xIdleTime = 0; // millisecs since last input event

	#ifdef HasXidle
	if (d->useXidle)
	{
		XGetIdleTime(dsp, &xIdleTime);
	}
	else
	#endif /* HasXIdle */

	{
	#ifdef HasScreenSaver
		if(d->useMit)
		{
			static XScreenSaverInfo* mitInfo = 0;
			if (!mitInfo) mitInfo = XScreenSaverAllocInfo();
			XScreenSaverQueryInfo (dsp, d->root, mitInfo);
			xIdleTime = mitInfo->idle;
		}
	#endif /* HasScreenSaver */
	}

	// =================================================================================

	if (root_x != d->mouse_x || root_y != d->mouse_y || mask != d->mouse_mask || xIdleTime < d->xIdleTime+2000)
	{
		d->mouse_x = root_x;
		d->mouse_y = root_y;
		d->mouse_mask = mask;
		d->xIdleTime = xIdleTime;
		setActivity();
	}

	// =================================================================================

	if(!d->autoaway && d->useAutoAway && idleTime() > d->awayTimeout)
	{
		setAutoAway();
	}
}

void KopeteAway::setActivity()
{
//	kdDebug(14010) << k_funcinfo << "Found activity on desktop, resetting away timer" << endl;
	d->idleTime.start();

	if(d->autoaway)
	{
		d->autoaway = false;
		emit activity();
		if (d->goAvailable)
		{
			d->autoAwayAccounts.setAutoDelete(false);
			for(KopeteAccount *i=d->autoAwayAccounts.first() ; i; i=d->autoAwayAccounts.current() )
			{
				if(i->isConnected() && i->isAway()) {
					i->setAway(false);
				}

				// remove() makes the next entry in the list the current one,
				// that's why we use current() above
				d->autoAwayAccounts.remove();
			}
		}
	}
}

void KopeteAway::setAutoAway()
{
//	kdDebug(14010) << k_funcinfo << "Going AutoAway!" << endl;
	d->autoaway = true;

	// Set all accounts that are not away already to away.
	// We remember them so later we only set the accounts to
	// available that we set to away (and not the user).
	QPtrList<KopeteAccount> accounts = KopeteAccountManager::manager()->accounts();
	for(KopeteAccount *i=accounts.first() ; i; i=accounts.next() )
	{
		if(i->isConnected() && !i->isAway())
		{
			d->autoAwayAccounts.append(i);
			i->setAway( true, getInstance()->d->awayMessage);
		}
	}
}

#include "kopeteaway.moc"
// vim: set et ts=4 sts=4 sw=4:
<commit_msg>Do not go availiable immediatly if we just gone autoaway<commit_after>/*
    kopeteaway.cpp  -  Kopete Away

    Copyright (c) 2002      by Hendrik vom Lehn       <hvl@linux-4-ever.de>
    Copyright (c) 2003      Olivier Goffart           <ogoffart@tiscalinet.be>

    Kopete    (c) 2002-2003 by the Kopete developers  <kopete-devel@kde.org>

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

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include "kopeteaway.h"

#include "kopeteaccountmanager.h"
#include "kopeteaccount.h"

#include <kconfig.h>
#include <qtimer.h>
#include <kapplication.h>

#include <klocale.h>
#include <kglobal.h>
#include <kdebug.h>
#include <ksettings/dispatcher.h>

#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/Xresource.h>
// The following include is to make --enable-final work
#include <X11/Xutil.h>

#ifdef HAVE_XSCREENSAVER
#define HasScreenSaver
#include <X11/extensions/scrnsaver.h>
#endif

// As this is an untested X extension we better leave it off
#undef HAVE_XIDLE
#undef HasXidle

struct KopeteAwayPrivate
{
	QString awayMessage;
	bool globalAway;
	QValueList<KopeteAwayMessage> awayMessageList;
	QTime idleTime;
	QTimer *timer;
	bool autoaway;
	bool goAvailable;
	int awayTimeout;
	bool useAutoAway;
	QPtrList<KopeteAccount> autoAwayAccounts;

	int mouse_x;
	int mouse_y;
	unsigned int mouse_mask;
	Window    root;               /* root window the pointer is on */
	Screen*   screen;             /* screen the pointer is on      */

	Time xIdleTime;
	bool useXidle;
	bool useMit;
};

KopeteAway *KopeteAway::instance = 0L;

KopeteAway::KopeteAway() : QObject( kapp , "KopeteAway")
{
	int dummy = 0;
	dummy = dummy; // shut up

	d = new KopeteAwayPrivate;

	// Set up the away messages
	d->awayMessage = "";
	d->globalAway = false;
	d->autoaway = false;
	d->useAutoAway = true;

	// Empty the list
	d->awayMessageList.clear();

	// set the XAutoLock info
	Display *dsp = qt_xdisplay();
	d->mouse_x = d->mouse_y=0;
	d->mouse_mask = 0;
	d->root = DefaultRootWindow (dsp);
	d->screen = ScreenOfDisplay (dsp, DefaultScreen (dsp));

	d->useXidle = false;
	d->useMit = false;
#ifdef HasXidle
	d->useXidle = XidleQueryExtension(qt_xdisplay(), &dummy, &dummy);
#endif
#ifdef HasScreenSaver
	if(!d->useXidle)
		d->useMit = XScreenSaverQueryExtension(qt_xdisplay(), &dummy, &dummy);
#endif
	d->xIdleTime = 0;

	if (d->useXidle)
		kdDebug(14010) << "using X11 Xidle extension" << endl;
	if(d->useMit)
		kdDebug(14010) << "using X11 MIT Screensaver extension" << endl;

	load();
	KSettings::Dispatcher::self()->registerInstance( KGlobal::instance(), this, SLOT( load() ) );
	// Set up the config object
	KConfig *config = KGlobal::config();
	/* Load the saved away messages */
	config->setGroup("Away Messages");

	/* If Kopete has been run before, this will be true.
	* It's only false the first time Kopete is run
	*/
	if(config->hasKey("Titles"))
	{
		QStringList titles = config->readListEntry("Titles");  // Get the titles
		KopeteAwayMessage temp; // Temporary away message....
		for(QStringList::iterator i = titles.begin(); i != titles.end(); i++)
		{
			temp.title = (*i); // Grab the title from the list of messages
			temp.message = config->readEntry(temp.title); // And the message (from disk)
			d->awayMessageList.append(temp); // And add it to the list
		}
	}
	else
	{
		/* There are no away messages, so we'll create a default one */
		/* Create an away message */
		KopeteAwayMessage temp;
		temp.title = i18n("Busy");
		temp.message = i18n("Sorry, I'm busy right now");

		/* Add it to the vector */
		d->awayMessageList.append(temp);

		temp.title = i18n("Gone");
		temp.message = i18n("I'm gone right now, but I'll be back later");
		d->awayMessageList.append(temp);

		/* Save this list to disk */
		save();
	}

	// init the timer
	d->timer = new QTimer(this, "AwayTimer");
	connect(d->timer, SIGNAL(timeout()), this, SLOT(slotTimerTimeout()));
	d->timer->start(4000);

	//init the time and other
	setActivity();
}

KopeteAway::~KopeteAway()
{
	delete d;
}

QString KopeteAway::message()
{
	return getInstance()->d->awayMessage;
}

void KopeteAway::setGlobalAwayMessage(const QString &message)
{
	if( !message.isEmpty() )
	{
		kdDebug(14010) << k_funcinfo <<
			"Setting global away message: " << message << endl;
		d->awayMessage = message;
	}
}

KopeteAway *KopeteAway::getInstance()
{
	if (!instance)
		instance = new KopeteAway;
	return instance;
}

bool KopeteAway::globalAway()
{
	return getInstance()->d->globalAway;
}

void KopeteAway::setGlobalAway(bool status)
{
	getInstance()->d->globalAway = status;
}

void KopeteAway::save()
{
	KConfig *config = KGlobal::config();
	/* Set the away message settings in the Away Messages config group */
	config->setGroup("Away Messages");
	QStringList titles;
	/* For each message, keep track of the title, and write out the message */
	for(QValueList<KopeteAwayMessage>::iterator i = d->awayMessageList.begin(); i != d->awayMessageList.end(); i++)
	{
		titles.append((*i).title); // Append the title to list of titles
		config->writeEntry((*i).title, (*i).message); // Append Title->message pair to the config
	}

	/* Write out the titles */
	config->writeEntry("Titles", titles);
	config->sync();
}

void KopeteAway::load()
{
	KConfig *config = KGlobal::config();
	config->setGroup("AutoAway");
	d->awayTimeout=config->readNumEntry("Timeout", 600);
	d->goAvailable=config->readBoolEntry("GoAvailable", true);
	d->useAutoAway=config->readBoolEntry("UseAutoAway", true);

}

QStringList KopeteAway::getTitles()
{
	QStringList titles;
	for(QValueList<KopeteAwayMessage>::iterator i = d->awayMessageList.begin(); i != d->awayMessageList.end(); i++)
		titles.append((*i).title);

	return titles;
}

QString KopeteAway::getMessage(const QString &title)
{
	for(QValueList<KopeteAwayMessage>::iterator i = d->awayMessageList.begin(); i != d->awayMessageList.end(); i++)
	{
		if((*i).title == title)
			return (*i).message;
	}

	/* Return an empty string if none was found */
	return QString::null;
}

bool KopeteAway::addMessage(const QString &title, const QString &message)
{
	bool found = false;
	/* Check to see if it exists already */
	for(QValueList<KopeteAwayMessage>::iterator i = d->awayMessageList.begin(); i != d->awayMessageList.end(); i++)
	{
		if((*i).title == title)
		{
			found = true;
			break;
		}
	}

	/* If not, add it */
	if(!found)
	{
		KopeteAwayMessage temp;
		temp.title = title;
		temp.message = message;
		d->awayMessageList.append(temp);
		save();
		return true;
	}
	else
	{
		return false;
	}
}

bool KopeteAway::deleteMessage(const QString &title)
{
	/* Search for the message */
	QValueList<KopeteAwayMessage>::iterator itemToDelete = d->awayMessageList.begin();
	while( (itemToDelete != d->awayMessageList.end()) && ((*itemToDelete).title != title) )
		itemToDelete++;

	/* If it was found, delete it */
	if(itemToDelete != d->awayMessageList.end())
	{
		/* Remove it from the config entry, if it's there */
		if(KGlobal::config()->hasKey((*itemToDelete).title))
			KGlobal::config()->deleteEntry((*itemToDelete).title);

		/* Remove it from the list */
		d->awayMessageList.remove(itemToDelete);
		save();
		return true;
	}
	else
	{
		return false;
	}
}

bool KopeteAway::updateMessage(const QString &title, const QString &message)
{
	/* Search for the message */
	QValueList<KopeteAwayMessage>::iterator itemToUpdate = d->awayMessageList.begin();
	while( (itemToUpdate != d->awayMessageList.end()) && ((*itemToUpdate).title != title) )
		itemToUpdate++;

	/* If it was found, update it */
	if(itemToUpdate != d->awayMessageList.end())
	{
		(*itemToUpdate).message = message;
		save();
		return true;
	}
	else
	{
		return false;
	}
}

long int KopeteAway::idleTime()
{
	//FIXME: the time is reset to zero if more than 24 hours are elapsed
	// we can imagine someone who leave his PC for several weeks
	return (d->idleTime.elapsed() / 1000);
}

void KopeteAway::slotTimerTimeout()
{
	// Copyright (c) 1999 Martin R. Jones <mjones@kde.org>
	//
	// KDE screensaver engine
	//
	// This module is a heavily modified xautolock.
	// In fact as of KDE 2.0 this code is practically unrecognisable as xautolock.

	Display *dsp = qt_xdisplay();
	Window           dummy_w;
	int              dummy_c;
	unsigned int     mask;               /* modifier mask                 */
	int              root_x;
	int              root_y;

	/*
	*  Find out whether the pointer has moved. Using XQueryPointer for this
	*  is gross, but it also is the only way never to mess up propagation
	*  of pointer events.
	*
	*  Remark : Unlike XNextEvent(), XPending () doesn't notice if the
	*           connection to the server is lost. For this reason, earlier
	*           versions of xautolock periodically called XNoOp (). But
	*           why not let XQueryPointer () do the job for us, since
	*           we now call that periodically anyway?
	*/
	if (!XQueryPointer (dsp, d->root, &(d->root), &dummy_w, &root_x, &root_y,
			&dummy_c, &dummy_c, &mask))
	{
		/*
		*  Pointer has moved to another screen, so let's find out which one.
		*/
		for (int i = 0; i < ScreenCount(dsp); i++)
		{
			if (d->root == RootWindow(dsp, i))
			{
				d->screen = ScreenOfDisplay (dsp, i);
				break;
			}
		}
	}

	// =================================================================================

	Time xIdleTime = 0; // millisecs since last input event

	#ifdef HasXidle
	if (d->useXidle)
	{
		XGetIdleTime(dsp, &xIdleTime);
	}
	else
	#endif /* HasXIdle */

	{
	#ifdef HasScreenSaver
		if(d->useMit)
		{
			static XScreenSaverInfo* mitInfo = 0;
			if (!mitInfo) mitInfo = XScreenSaverAllocInfo();
			XScreenSaverQueryInfo (dsp, d->root, mitInfo);
			xIdleTime = mitInfo->idle;
		}
	#endif /* HasScreenSaver */
	}

	// =================================================================================

	if (root_x != d->mouse_x || root_y != d->mouse_y || mask != d->mouse_mask || xIdleTime < d->xIdleTime+2000)
	{
		if(d->mouse_x!=-1) //we just gone autoaway, not activity this time
			setActivity();
		d->mouse_x = root_x;
		d->mouse_y = root_y;
		d->mouse_mask = mask;
		d->xIdleTime = xIdleTime;
	}

	// =================================================================================

	if(!d->autoaway && d->useAutoAway && idleTime() > d->awayTimeout)
	{
		setAutoAway();
	}
}

void KopeteAway::setActivity()
{
//	kdDebug(14010) << k_funcinfo << "Found activity on desktop, resetting away timer" << endl;
	d->idleTime.start();

	if(d->autoaway)
	{
		d->autoaway = false;
		emit activity();
		if (d->goAvailable)
		{
			d->autoAwayAccounts.setAutoDelete(false);
			for(KopeteAccount *i=d->autoAwayAccounts.first() ; i; i=d->autoAwayAccounts.current() )
			{
				if(i->isConnected() && i->isAway()) {
					i->setAway(false);
				}

				// remove() makes the next entry in the list the current one,
				// that's why we use current() above
				d->autoAwayAccounts.remove();
			}
		}
	}
}

void KopeteAway::setAutoAway()
{
	d->mouse_x=-1; //do not go availiable automaticaly after

//	kdDebug(14010) << k_funcinfo << "Going AutoAway!" << endl;
	d->autoaway = true;

	// Set all accounts that are not away already to away.
	// We remember them so later we only set the accounts to
	// available that we set to away (and not the user).
	QPtrList<KopeteAccount> accounts = KopeteAccountManager::manager()->accounts();
	for(KopeteAccount *i=accounts.first() ; i; i=accounts.next() )
	{
		if(i->isConnected() && !i->isAway())
		{
			d->autoAwayAccounts.append(i);
			i->setAway( true, getInstance()->d->awayMessage);
		}
	}
}

#include "kopeteaway.moc"
// vim: set et ts=4 sts=4 sw=4:
<|endoftext|>


<commit_before>#ifndef MJOLNIR_INPUT_READ_EXTERNAL_POTENTIAL_HPP
#define MJOLNIR_INPUT_READ_EXTERNAL_POTENTIAL_HPP
#include <extlib/toml/toml.hpp>
#include <mjolnir/potential/external/ImplicitMembranePotential.hpp>
#include <mjolnir/potential/external/LennardJonesWallPotential.hpp>
#include <mjolnir/potential/external/ExcludedVolumeWallPotential.hpp>
#include <mjolnir/core/Topology.hpp>
#include <mjolnir/util/string.hpp>
#include <mjolnir/util/make_unique.hpp>
#include <mjolnir/util/logger.hpp>

namespace mjolnir
{

// ---------------------------------------------------------------------------
// Potential for External Force Fields
// ---------------------------------------------------------------------------

template<typename realT>
ImplicitMembranePotential<realT>
read_implicit_membrane_potential(const toml::value& external)
{
    MJOLNIR_GET_DEFAULT_LOGGER();
    MJOLNIR_LOG_FUNCTION();
    using real_type = realT;

    const auto thickness = toml::find<real_type>(external, "thickness");
    const auto magnitude = toml::find<real_type>(external, "interaction_magnitude");
    const auto bend      = toml::find<real_type>(external, "bend");

    MJOLNIR_LOG_INFO("thickness = ", thickness);
    MJOLNIR_LOG_INFO("magnitude = ", magnitude);
    MJOLNIR_LOG_INFO("bend      = ", bend     );

    const auto& ps = toml::find<toml::array>(external, "parameters");
    MJOLNIR_LOG_INFO(ps.size(), " parameters are found");

    std::vector<real_type> params;
    params.reserve(ps.size());
    for(const auto& param : ps)
    {
        const auto idx = toml::find<std::size_t>(param, "index");
        const auto h   = toml::find<real_type  >(param, "hydrophobicity");
        if(params.size() <= idx) {params.resize(idx+1, real_type(0.0));}
        params.at(idx) = h;

        MJOLNIR_LOG_INFO("idx = ", idx, ", hydrophobicity = ", h);
    }
    return ImplicitMembranePotential<realT>(
            thickness, magnitude, bend, std::move(params));
}

template<typename realT>
LennardJonesWallPotential<realT>
read_lennard_jones_wall_potential(const toml::value& external)
{
    MJOLNIR_GET_DEFAULT_LOGGER();
    MJOLNIR_LOG_FUNCTION();
    using real_type = realT;

    const auto& ps = toml::find<toml::array>(external, "parameters");
    MJOLNIR_LOG_INFO(ps.size(), " parameters are found");

    std::vector<std::pair<real_type, real_type>> params;
    params.reserve(ps.size());
    for(const auto& param : ps)
    {
        const auto idx = toml::find<std::size_t>(param, "index");
        const auto s   = toml::expect<real_type>(param, u8"σ").or_other(
                         toml::expect<real_type>(param, "sigma")).unwrap();
        const auto e   = toml::expect<real_type>(param, u8"ε").or_other(
                         toml::expect<real_type>(param, "epsilon")).unwrap();
        if(params.size() <= idx)
        {
            params.resize(idx+1, std::make_pair(real_type(0), real_type(0)));
        }
        params.at(idx) = std::make_pair(s, e);

        MJOLNIR_LOG_INFO("idx = ", idx, ", sigma = ", s, ", epsilon = ", e);
    }
    return LennardJonesWallPotential<realT>(std::move(params));
}

template<typename realT>
ExcludedVolumeWallPotential<realT>
read_excluded_volume_wall_potential(const toml::value& external)
{
    MJOLNIR_GET_DEFAULT_LOGGER();
    MJOLNIR_LOG_FUNCTION();
    using real_type = realT;

    const auto eps = toml::expect<real_type>(external, u8"ε").or_other(
                     toml::expect<real_type>(external, "epsilon")).unwrap();
    MJOLNIR_LOG_INFO("epsilon = ", eps);

    const auto& ps = toml::find<toml::array>(external, "parameters");
    MJOLNIR_LOG_INFO("number of parameters = ", ps.size());

    std::vector<real_type> params;
    params.reserve(ps.size());
    for(const auto& param : ps)
    {
        const auto idx = toml::find<std::size_t>(param, "index");
        const auto rad = toml::find<real_type>(param, "radius");
        if(params.size() <= idx) {params.resize(idx+1, real_type(0));}
        params.at(idx) = rad;

        MJOLNIR_LOG_INFO("idx = ", idx, ", radius = ", rad);
    }
    return ExcludedVolumeWallPotential<real_type>(eps, std::move(params));
}

} // mjolnir
#endif // MJOLNIR_READ_EXTERNAL_POTENTIAL_HPP
<commit_msg>feat: enable to read HarmonicRestraintPotential<commit_after>#ifndef MJOLNIR_INPUT_READ_EXTERNAL_POTENTIAL_HPP
#define MJOLNIR_INPUT_READ_EXTERNAL_POTENTIAL_HPP
#include <extlib/toml/toml.hpp>
#include <mjolnir/potential/external/HarmonicRestraintPotential.hpp>
#include <mjolnir/potential/external/ImplicitMembranePotential.hpp>
#include <mjolnir/potential/external/LennardJonesWallPotential.hpp>
#include <mjolnir/potential/external/ExcludedVolumeWallPotential.hpp>
#include <mjolnir/core/Topology.hpp>
#include <mjolnir/util/string.hpp>
#include <mjolnir/util/make_unique.hpp>
#include <mjolnir/util/logger.hpp>

namespace mjolnir
{

// ---------------------------------------------------------------------------
// Potential for External Force Fields
// ---------------------------------------------------------------------------

template<typename realT>
ImplicitMembranePotential<realT>
read_implicit_membrane_potential(const toml::value& external)
{
    MJOLNIR_GET_DEFAULT_LOGGER();
    MJOLNIR_LOG_FUNCTION();
    using real_type = realT;

    const auto thickness = toml::find<real_type>(external, "thickness");
    const auto magnitude = toml::find<real_type>(external, "interaction_magnitude");
    const auto bend      = toml::find<real_type>(external, "bend");

    MJOLNIR_LOG_INFO("thickness = ", thickness);
    MJOLNIR_LOG_INFO("magnitude = ", magnitude);
    MJOLNIR_LOG_INFO("bend      = ", bend     );

    const auto& ps = toml::find<toml::array>(external, "parameters");
    MJOLNIR_LOG_INFO(ps.size(), " parameters are found");

    std::vector<real_type> params;
    params.reserve(ps.size());
    for(const auto& param : ps)
    {
        const auto idx = toml::find<std::size_t>(param, "index");
        const auto h   = toml::find<real_type  >(param, "hydrophobicity");
        if(params.size() <= idx) {params.resize(idx+1, real_type(0.0));}
        params.at(idx) = h;

        MJOLNIR_LOG_INFO("idx = ", idx, ", hydrophobicity = ", h);
    }
    return ImplicitMembranePotential<realT>(
            thickness, magnitude, bend, std::move(params));
}

template<typename realT>
LennardJonesWallPotential<realT>
read_lennard_jones_wall_potential(const toml::value& external)
{
    MJOLNIR_GET_DEFAULT_LOGGER();
    MJOLNIR_LOG_FUNCTION();
    using real_type = realT;

    const auto& ps = toml::find<toml::array>(external, "parameters");
    MJOLNIR_LOG_INFO(ps.size(), " parameters are found");

    std::vector<std::pair<real_type, real_type>> params;
    params.reserve(ps.size());
    for(const auto& param : ps)
    {
        const auto idx = toml::find<std::size_t>(param, "index");
        const auto s   = toml::expect<real_type>(param, u8"σ").or_other(
                         toml::expect<real_type>(param, "sigma")).unwrap();
        const auto e   = toml::expect<real_type>(param, u8"ε").or_other(
                         toml::expect<real_type>(param, "epsilon")).unwrap();
        if(params.size() <= idx)
        {
            params.resize(idx+1, std::make_pair(real_type(0), real_type(0)));
        }
        params.at(idx) = std::make_pair(s, e);

        MJOLNIR_LOG_INFO("idx = ", idx, ", sigma = ", s, ", epsilon = ", e);
    }
    return LennardJonesWallPotential<realT>(std::move(params));
}

template<typename realT>
ExcludedVolumeWallPotential<realT>
read_excluded_volume_wall_potential(const toml::value& external)
{
    MJOLNIR_GET_DEFAULT_LOGGER();
    MJOLNIR_LOG_FUNCTION();
    using real_type = realT;

    const auto eps = toml::expect<real_type>(external, u8"ε").or_other(
                     toml::expect<real_type>(external, "epsilon")).unwrap();
    MJOLNIR_LOG_INFO("epsilon = ", eps);

    const auto& ps = toml::find<toml::array>(external, "parameters");
    MJOLNIR_LOG_INFO("number of parameters = ", ps.size());

    std::vector<real_type> params;
    params.reserve(ps.size());
    for(const auto& param : ps)
    {
        const auto idx = toml::find<std::size_t>(param, "index");
        const auto rad = toml::find<real_type>(param, "radius");
        if(params.size() <= idx) {params.resize(idx+1, real_type(0));}
        params.at(idx) = rad;

        MJOLNIR_LOG_INFO("idx = ", idx, ", radius = ", rad);
    }
    return ExcludedVolumeWallPotential<real_type>(eps, std::move(params));
}

template<typename realT>
HarmonicRestraintPotential<realT>
read_harmonic_restraint_potential(const toml::value& external)
{
    MJOLNIR_GET_DEFAULT_LOGGER();
    MJOLNIR_LOG_FUNCTION();
    using real_type = realT;
    using potential_type = HarmonicRestraintPotential<real_type>;
    using parameter_type = typename potential_type::parameter_type;

    const auto& ps = toml::find<toml::array>(external, "parameters");
    MJOLNIR_LOG_INFO("number of parameters = ", ps.size());

    std::vector<parameter_type> params;
    params.reserve(ps.size());
    for(const auto& param : ps)
    {
        const auto idx = toml::find<std::size_t>(param, "index");
        const auto k   = toml::find<real_type  >(param, "k");
        const auto v0  = toml::find<real_type  >(param, "v0");
        if(params.size() <= idx)
        {
            params.resize(idx+1, parameter_type(0, 0));
        }
        params.at(idx) = parameter_type(k, v0);

        MJOLNIR_LOG_INFO("idx = ", idx, ", k = ", k, ", v0 = ", v0);
    }
    return HarmonicRestraintPotential<real_type>(std::move(params));
}

} // mjolnir
#endif // MJOLNIR_READ_EXTERNAL_POTENTIAL_HPP
<|endoftext|>


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

# include <Siv3D/Platform.hpp>
# if defined(SIV3D_TARGET_MACOS) || defined(SIV3D_TARGET_LINUX)

# include <GL/glew.h>
# include "../../../../ThirdParty/GLFW/include/GLFW/glfw3.h"
# include "GLSamplerState.hpp"

namespace s3d
{
	namespace detail
	{
		static constexpr GLint minmipTable[4] =
		{
			GL_NEAREST_MIPMAP_NEAREST,
			GL_NEAREST_MIPMAP_LINEAR,
			GL_LINEAR_MIPMAP_NEAREST,
			GL_LINEAR_MIPMAP_LINEAR
		};
	}

	GLSamplerState::GLSamplerState()
	{
		m_currentStates.fill(NullSamplerState);
	}

	void GLSamplerState::set(const uint32 slot, const SamplerState& state)
	{
		assert(slot < SamplerState::MaxSamplerCount);

		if (state == m_currentStates[slot])
		{
			return;
		}

		auto it = m_states.find(state);

		if (it == m_states.end())
		{
			it = create(state);

			if (it == m_states.end())
			{
				return;
			}
		}

		::glBindSampler(slot, it->second->m_sampler);

		m_currentStates[slot] = state;
	}

	GLSamplerState::SamplerStateList::iterator GLSamplerState::create(const SamplerState& state)
	{
		std::unique_ptr<SamplerState_GL> samplerState = std::make_unique<SamplerState_GL>();

		const GLuint sampler = samplerState->m_sampler;
		static const GLfloat border[] = { state.borderColor.x, state.borderColor.y, state.borderColor.z, state.borderColor.w };
		static const GLuint wraps[] = { GL_REPEAT, GL_MIRRORED_REPEAT, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER };

		::glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER,
							  detail::minmipTable[(static_cast<int32>(state.min) << 1) | (static_cast<int32>(state.mip))]);
		::glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, static_cast<bool>(state.mag) ? GL_LINEAR : GL_NEAREST);
		::glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, wraps[static_cast<int32>(state.addressU)]);
		::glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, wraps[static_cast<int32>(state.addressV)]);
		::glSamplerParameteri(sampler, GL_TEXTURE_WRAP_R, wraps[static_cast<int32>(state.addressW)]);
		::glSamplerParameterf(sampler, GL_TEXTURE_LOD_BIAS, state.lodBias);
		::glSamplerParameteri(sampler, GL_TEXTURE_COMPARE_MODE, GL_NONE);
		::glSamplerParameterf(sampler, GL_TEXTURE_MAX_ANISOTROPY_EXT, state.maxAnisotropy);
		::glSamplerParameterfv(sampler, GL_TEXTURE_BORDER_COLOR, border);
		::glSamplerParameterf(sampler, GL_TEXTURE_MIN_LOD, -1000.0f);
		::glSamplerParameterf(sampler, GL_TEXTURE_MAX_LOD, 1000.0f);

		if (m_states.size() >= 1024)
		{
			m_states.clear();
		}

		return m_states.emplace(state, std::move(samplerState)).first;
	}
}

# endif
<commit_msg>GLSamplerState.cppでコンパイルが通らない問題修正<commit_after>//-----------------------------------------------
//
//	This file is part of the Siv3D Engine.
//
//	Copyright (c) 2008-2017 Ryo Suzuki
//	Copyright (c) 2016-2017 OpenSiv3D Project
//
//	Licensed under the MIT License.
//
//-----------------------------------------------

# include <Siv3D/Platform.hpp>
# if defined(SIV3D_TARGET_MACOS) || defined(SIV3D_TARGET_LINUX)

# include <GL/glew.h>
# include "../../../../ThirdParty/GLFW/include/GLFW/glfw3.h"
# include "GLSamplerState.hpp"

namespace s3d
{
	namespace detail
	{
		static constexpr GLint minmipTable[4] =
		{
			GL_NEAREST_MIPMAP_NEAREST,
			GL_NEAREST_MIPMAP_LINEAR,
			GL_LINEAR_MIPMAP_NEAREST,
			GL_LINEAR_MIPMAP_LINEAR
		};
	}

	GLSamplerState::GLSamplerState()
	{
		m_currentStates.fill(NullSamplerState);
	}

	void GLSamplerState::set(const uint32 slot, const SamplerState& state)
	{
		assert(slot < SamplerState::MaxSamplerCount);

		if (state == m_currentStates[slot])
		{
			return;
		}

		auto it = m_states.find(state);

		if (it == m_states.end())
		{
			it = create(state);

			if (it == m_states.end())
			{
				return;
			}
		}

		::glBindSampler(slot, it->second->m_sampler);

		m_currentStates[slot] = state;
	}

	GLSamplerState::SamplerStateList::iterator GLSamplerState::create(const SamplerState& state)
	{
		std::unique_ptr<SamplerState_GL> samplerState = std::make_unique<SamplerState_GL>();

		const GLuint sampler = samplerState->m_sampler;
		static const GLfloat border[] = { state.borderColor[0], state.borderColor[1], state.borderColor[2], state.borderColor[3] };
		static const GLuint wraps[] = { GL_REPEAT, GL_MIRRORED_REPEAT, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER };

		::glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER,
							  detail::minmipTable[(static_cast<int32>(state.min) << 1) | (static_cast<int32>(state.mip))]);
		::glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, static_cast<bool>(state.mag) ? GL_LINEAR : GL_NEAREST);
		::glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, wraps[static_cast<int32>(state.addressU)]);
		::glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, wraps[static_cast<int32>(state.addressV)]);
		::glSamplerParameteri(sampler, GL_TEXTURE_WRAP_R, wraps[static_cast<int32>(state.addressW)]);
		::glSamplerParameterf(sampler, GL_TEXTURE_LOD_BIAS, state.lodBias);
		::glSamplerParameteri(sampler, GL_TEXTURE_COMPARE_MODE, GL_NONE);
		::glSamplerParameterf(sampler, GL_TEXTURE_MAX_ANISOTROPY_EXT, state.maxAnisotropy);
		::glSamplerParameterfv(sampler, GL_TEXTURE_BORDER_COLOR, border);
		::glSamplerParameterf(sampler, GL_TEXTURE_MIN_LOD, -1000.0f);
		::glSamplerParameterf(sampler, GL_TEXTURE_MAX_LOD, 1000.0f);

		if (m_states.size() >= 1024)
		{
			m_states.clear();
		}

		return m_states.emplace(state, std::move(samplerState)).first;
	}
}

# endif
<|endoftext|>