<commit_before>#include "stdafx.h"
#include "Filing.h"

Filing::Filing()
{
	this->Startup();
	this->getDrives();
}

Filing::~Filing()
{
	delete this->ExePath;
	delete this->LogDirectoryPath;
}

void Filing::Startup()
{
	bool a = CreateDirectory(LogDirectoryPath->c_str(), NULL);

	//Session log directory.
	bool b = CreateDirectory(this->currentInstanceLog->c_str(), NULL);

	const char* driveLetters = this->getDrives();
	wstring* time = this->getTime();

	//Get size of driveLetters
	register unsigned __int8 length = 0;

	while (driveLetters[length] != '\n')
	{
		++length;
	}

	this->instanceRootDirs = new wstring[length];
	this->arraySize = length;

	register unsigned __int8 i = 0;
	while (i != length)
	{
		this->instanceRootDirs[i] = driveLetters[i];
		this->instanceRootDirs[i].append(L":\\CE\\");
		this->instanceRootDirs[i].append(*time);
		this->instanceRootDirs[i].append(L"\\");
		bool c = CreateDirectory(this->instanceRootDirs[i].c_str(), NULL);

		if (!c)
		{
			cout << "Error! Unable to create directory! This could cause critical errors.";
		}

		++i;
	}
	delete driveLetters;
}

bool Filing::DoesDirectoryExist(string* Path)
{
	DWORD ftyp = GetFileAttributesA(Path->c_str());

	if (ftyp == INVALID_FILE_ATTRIBUTES)
	{
		cout << "Invalid path!\r\n";
		return false;  //something is wrong with your path!
	}

	if (ftyp & FILE_ATTRIBUTE_DIRECTORY)
	{
		return true;   // this is a directory!
	}

	return false;    // this is not a directory!
}

wstring* Filing::GetPathToExe()
{
#ifdef UNICODE
	TCHAR ownPth[260];
#else
	char ownPth[MAX_Path];
#endif // UNICODE

	// Will contain exe path
	HMODULE hModule = GetModuleHandle(NULL);
	if (hModule != NULL)
	{
		// When passing NULL to GetModuleHandle, it returns handle of exe itself
		GetModuleFileName(hModule, ownPth, (sizeof(ownPth)));
		return new wstring(ownPth);
	}
	else
	{
		cout << "Error! NullPointerException!";
		return NULL;
	}
}

wstring* Filing::GetLogDirectoryPath()
{
	wstring *directory;
	const size_t last_slash_idx = ExePath->rfind('\\');
	if (string::npos != last_slash_idx)
	{
		directory = new wstring(ExePath->substr(0, last_slash_idx));
		directory->append(L"\\Logs");
	}
	else
	{
		Console->WriteLine("Error! Directory not found from path!");
	}
	return directory;
}

wstring* Filing::getInstanceDirPath()
{
	wstring* dir = new wstring(*this->LogDirectoryPath);
	dir->append(L"\\");

	string* Formatted = new string("[");
	time_t rawtime;
	tm* timeinfo;
	char buffer[80];
	time(&rawtime);
	timeinfo = std::localtime(&rawtime);

	strftime(buffer, 80, "%Y-%m-%d-%H-%M-%S", timeinfo);
	Formatted->append(buffer);
	Formatted->append("]");
	wstring time(Formatted->begin(), Formatted->end());
	dir->append(time);

	delete Formatted;
	return dir;
}

char* Filing::getDrives()
{
	unsigned long mydrives = 100; // buffer length
	wchar_t lpBuffer[100]; // buffer for drive string storage
	unsigned long test = GetLogicalDriveStrings(mydrives, lpBuffer); //Gets size of drive string.
	unsigned __int8 drives = test / 4; //Gets the number of drives.
	char* driveLetters = new char[drives];//We will hold the actual drive letters here.
	char* strbuffer = new char[1];//Holds the 1 character drive letter here.
	wstring drive = L"";
	string drivePath;
	unsigned __int8 drivesUsable = 0;
	int dir;//Holds whether the create directory succeeded or not.
	unsigned __int64 error;//Holds the last error code fetched.

	for (unsigned __int8 i = 0; i < drives; i++)
	{
		drive = L"";
		wctomb(strbuffer, lpBuffer[i * 4]);
		drivePath = string(strbuffer, 1);
		drivePath.append(":\\CE");
		//Check drive accessibility here
		drive.append(Utility->stringToWString(drivePath));
		dir = CreateDirectory(drive.c_str(), NULL);

		error = GetLastError();
		if (dir != 0 || error  == ERROR_ALREADY_EXISTS)
		{
			{
				driveLetters[drivesUsable] = strbuffer[0];
				++drivesUsable;
			}
		}
	}
	driveLetters[drivesUsable] = '\n';
	delete strbuffer;

	return driveLetters;
}

wstring* Filing::getTime()
{
	wstring* dir = new wstring();
	string* Formatted = new string("[");
	time_t rawtime;
	tm* timeinfo;
	char buffer[80];
	time(&rawtime);
	timeinfo = std::localtime(&rawtime);

	strftime(buffer, 80, "%Y-%m-%d-%H-%M-%S", timeinfo);
	Formatted->append(buffer);
	Formatted->append("]");
	wstring time(Formatted->begin(), Formatted->end());
	dir->append(time);

	delete Formatted;
	return dir;
}

void Filing::createDirRaid(const char* path)
{
	register unsigned __int8 i = 0;

	while (i != this->arraySize)
	{

	}
}<commit_msg>Creating directories works great.<commit_after>#include "stdafx.h"
#include "Filing.h"

Filing::Filing()
{
	this->Startup();
	this->getDrives();
}

Filing::~Filing()
{
	delete this->ExePath;
	delete this->LogDirectoryPath;
}

void Filing::Startup()
{
	//bool a = CreateDirectory(LogDirectoryPath->c_str(), NULL);

	//Session log directory.
	bool b = CreateDirectory(this->currentInstanceLog->c_str(), NULL);

	const char* driveLetters = this->getDrives();
	wstring* time = this->getTime();

	//Get size of driveLetters
	register unsigned __int8 length = 0;

	while (driveLetters[length] != '\n')
	{
		++length;
	}

	this->instanceRootDirs = new wstring[length];
	this->arraySize = length;

	register unsigned __int8 i = 0;
	while (i != length)
	{
		this->instanceRootDirs[i] = driveLetters[i];
		this->instanceRootDirs[i].append(L":\\CE\\");
		this->instanceRootDirs[i].append(*time);
		this->instanceRootDirs[i].append(L"\\");
		bool c = CreateDirectory(this->instanceRootDirs[i].c_str(), NULL);

		if (!c)
		{
			cout << "Error! Unable to create directory! This could cause critical errors.\r\n";
		}

		++i;
	}

	this->createDirRaid("Logs");

	delete time;
	delete driveLetters;
}

bool Filing::DoesDirectoryExist(string* Path)
{
	DWORD ftyp = GetFileAttributesA(Path->c_str());

	if (ftyp == INVALID_FILE_ATTRIBUTES)
	{
		cout << "Invalid path!\r\n";
		return false;  //something is wrong with your path!
	}

	if (ftyp & FILE_ATTRIBUTE_DIRECTORY)
	{
		return true;   // this is a directory!
	}

	return false;    // this is not a directory!
}

wstring* Filing::GetPathToExe()
{
#ifdef UNICODE
	TCHAR ownPth[260];
#else
	char ownPth[MAX_Path];
#endif // UNICODE

	// Will contain exe path
	HMODULE hModule = GetModuleHandle(NULL);
	if (hModule != NULL)
	{
		// When passing NULL to GetModuleHandle, it returns handle of exe itself
		GetModuleFileName(hModule, ownPth, (sizeof(ownPth)));
		return new wstring(ownPth);
	}
	else
	{
		cout << "Error! NullPointerException!\r\n";
		return NULL;
	}
}

wstring* Filing::GetLogDirectoryPath()
{
	wstring *directory;
	const size_t last_slash_idx = ExePath->rfind('\\');
	if (string::npos != last_slash_idx)
	{
		directory = new wstring(ExePath->substr(0, last_slash_idx));
		directory->append(L"\\Logs");
	}
	else
	{
		Console->WriteLine("Error! Directory not found from path!");
	}
	return directory;
}

wstring* Filing::getInstanceDirPath()
{
	wstring* dir = new wstring(*this->LogDirectoryPath);
	dir->append(L"\\");

	string* Formatted = new string("[");
	time_t rawtime;
	tm* timeinfo;
	char buffer[80];
	time(&rawtime);
	timeinfo = std::localtime(&rawtime);

	strftime(buffer, 80, "%Y-%m-%d-%H-%M-%S", timeinfo);
	Formatted->append(buffer);
	Formatted->append("]");
	wstring time(Formatted->begin(), Formatted->end());
	dir->append(time);

	delete Formatted;
	return dir;
}

char* Filing::getDrives()
{
	unsigned long mydrives = 100; // buffer length
	wchar_t lpBuffer[100]; // buffer for drive string storage
	unsigned long test = GetLogicalDriveStrings(mydrives, lpBuffer); //Gets size of drive string.
	unsigned __int8 drives = test / 4; //Gets the number of drives.
	char* driveLetters = new char[drives];//We will hold the actual drive letters here.
	char* strbuffer = new char[1];//Holds the 1 character drive letter here.
	wstring drive = L"";
	string drivePath;
	unsigned __int8 drivesUsable = 0;
	int dir;//Holds whether the create directory succeeded or not.
	unsigned __int64 error;//Holds the last error code fetched.

	for (unsigned __int8 i = 0; i < drives; i++)
	{
		drive = L"";
		wctomb(strbuffer, lpBuffer[i * 4]);
		drivePath = string(strbuffer, 1);
		drivePath.append(":\\CE");
		//Check drive accessibility here
		drive.append(Utility->stringToWString(drivePath));
		dir = CreateDirectory(drive.c_str(), NULL);

		error = GetLastError();
		if (dir != 0 || error  == ERROR_ALREADY_EXISTS)
		{
			{
				driveLetters[drivesUsable] = strbuffer[0];
				++drivesUsable;
			}
		}
	}
	driveLetters[drivesUsable] = '\n';
	delete strbuffer;

	return driveLetters;
}

wstring* Filing::getTime()
{
	wstring* dir = new wstring();
	string* Formatted = new string("[");
	time_t rawtime;
	tm* timeinfo;
	char buffer[80];
	time(&rawtime);
	timeinfo = std::localtime(&rawtime);

	strftime(buffer, 80, "%Y-%m-%d-%H-%M-%S", timeinfo);
	Formatted->append(buffer);
	Formatted->append("]");
	wstring time(Formatted->begin(), Formatted->end());
	dir->append(time);

	delete Formatted;
	return dir;
}

void Filing::createDirRaid(const char* path)
{
	register unsigned __int8 i = 0;
	wstring p;
	string pat = path;
	bool success;
	while (i != this->arraySize)
	{
		p = this->instanceRootDirs[i];
		p.append(wstring(pat.begin(), pat.end()));
		success = CreateDirectory(p.c_str(), NULL);

		if (!success && GetLastError() != ERROR_ALREADY_EXISTS)
		{
			cout << "Failed to create a directory\r\n";
		}
		++i;
	}
}<|endoftext|>


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

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

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

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

namespace Ogre {
namespace Volume {

    TextureSource::TextureSource(const String &volumeTextureName, const Real worldWidth, const Real worldHeight, const Real worldDepth, const bool trilinearValue, const bool trilinearNormal, const bool sobelNormal) :
        mTrilinearValue(trilinearValue), mTrilinearNormal(trilinearNormal), mSobelNormal(sobelNormal)
    {

        Timer t;
        TexturePtr tex = TextureManager::getSingleton().load(volumeTextureName,
            ResourceGroupManager::getSingleton().getWorldResourceGroupName(),
            TEX_TYPE_3D,
            0);
        LogManager::getSingleton().stream() << "Loaded texture in " << t.getMilliseconds() << "ms.";
        t.reset();

        mWidth = tex->getSrcWidth();
        mHeight= tex->getSrcHeight();
        mWidthTimesHeight = mWidth * mHeight;
        mDepth = tex->getSrcDepth();

        mPosXScale = (Real)1.0 / (Real)worldWidth * (Real)mWidth;
        mPosYScale = (Real)1.0 / (Real)worldHeight * (Real)mHeight;
        mPosZScale = (Real)1.0 / (Real)worldDepth * (Real)mDepth;

        HardwarePixelBufferSharedPtr buffer = tex->getBuffer(0, 0);
        buffer->lock(HardwareBuffer::HBL_READ_ONLY);
        const PixelBox &pb = buffer->getCurrentLock();
        float *pbptr = static_cast<float*>(pb.data);
        mData = OGRE_ALLOC_T(float, mWidth * mHeight * mDepth, MEMCATEGORY_GENERAL);
        float * dataRunner = mData;
        ColourValue cv;
        size_t x, y;
        size_t zEnd = pb.back;
        size_t yStart = pb.top;
        size_t yEnd = pb.bottom;
        size_t xStart = pb.left;
        size_t xEnd = pb.right;
        size_t sliceSkip = pb.getSliceSkip();
        for (size_t z = pb.front; z < zEnd; ++z)
        {
            for (y = yStart; y < yEnd; ++y)
            {
                for (x = xStart; x < xEnd; ++x)
                {
                    *dataRunner++ = pbptr[x];
                }
                pbptr += pb.rowPitch;
            }
            pbptr += sliceSkip;
        }
        buffer->unlock();
        LogManager::getSingleton().stream() << "Processed texture in " << t.getMilliseconds() << "ms.";
    }

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

    TextureSource::~TextureSource(void)
    {
        OGRE_FREE(mData, MEMCATEGORY_GENERAL);
    }

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

    Real TextureSource::getValueAndGradient(const Vector3 &position, Vector3 &normal) const
    {
        Vector3 scaledPosition(position.x * mPosXScale, position.y * mPosYScale, position.z * mPosZScale);
        if (mTrilinearNormal)
        {
            // http://en.wikipedia.org/wiki/Trilinear_interpolation
            size_t x0 = (size_t)scaledPosition.x;
            size_t x1 = (size_t)ceil(scaledPosition.x);
            size_t y0 = (size_t)scaledPosition.y;
            size_t y1 = (size_t)ceil(scaledPosition.y);
            size_t z0 = (size_t)scaledPosition.z;
            size_t z1 = (size_t)ceil(scaledPosition.z);

            Real dX = scaledPosition.x - (Real)x0;
            Real dY = scaledPosition.y - (Real)y0;
            Real dZ = scaledPosition.z - (Real)z0;

            Vector3 i1 = getGradient(x0, y0, z0) * ((Real)1.0 - dZ) + getGradient(x0, y0, z1) * dZ;
            Vector3 i2 = getGradient(x0, y1, z0) * ((Real)1.0 - dZ) + getGradient(x0, y1, z1) * dZ;
            Vector3 j1 = getGradient(x1, y0, z0) * ((Real)1.0 - dZ) + getGradient(x1, y0, z1) * dZ;
            Vector3 j2 = getGradient(x1, y1, z0) * ((Real)1.0 - dZ) + getGradient(x1, y1, z1) * dZ;
            Vector3 w1 = i1 * ((Real)1.0 - dY) + i2 * dY;
            Vector3 w2 = j1 * ((Real)1.0 - dY) + j2 * dY;
            normal = w1 * ((Real)1.0 - dX) + w2 * dX;
            normal *= (Real)-1.0;
        }
        else
        {
            normal = getGradient((size_t)scaledPosition.x, (size_t)scaledPosition.y, (size_t)scaledPosition.z);
            normal *= (Real)-1.0;
        }
        return getValue(position);
    }

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

    Real TextureSource::getValue(const Vector3 &position) const
    {
        Vector3 scaledPosition(position.x * mPosXScale, position.y * mPosYScale, position.z * mPosZScale);
        Real value;
        if (mTrilinearValue)
        {
            // http://en.wikipedia.org/wiki/Trilinear_interpolation
            size_t x0 = (size_t)scaledPosition.x;
            size_t x1 = (size_t)ceil(scaledPosition.x);
            size_t y0 = (size_t)scaledPosition.y;
            size_t y1 = (size_t)ceil(scaledPosition.y);
            size_t z0 = (size_t)scaledPosition.z;
            size_t z1 = (size_t)ceil(scaledPosition.z);

            Real dX = scaledPosition.x - (Real)x0;
            Real dY = scaledPosition.y - (Real)y0;
            Real dZ = scaledPosition.z - (Real)z0;

            Real i1 = getVolumeArrayValue(x0, y0, z0) * ((Real)1.0 - dZ) + getVolumeArrayValue(x0, y0, z1) * dZ;
            Real i2 = getVolumeArrayValue(x0, y1, z0) * ((Real)1.0 - dZ) + getVolumeArrayValue(x0, y1, z1) * dZ;
            Real j1 = getVolumeArrayValue(x1, y0, z0) * ((Real)1.0 - dZ) + getVolumeArrayValue(x1, y0, z1) * dZ;
            Real j2 = getVolumeArrayValue(x1, y1, z0) * ((Real)1.0 - dZ) + getVolumeArrayValue(x1, y1, z1) * dZ;
            Real w1 = i1 * ((Real)1.0 - dY) + i2 * dY;
            Real w2 = j1 * ((Real)1.0 - dY) + j2 * dY;
            value = w1 * ((Real)1.0 - dX) + w2 * dX;
        }
        else
        {
            // Nearest neighbour else
            size_t x = (size_t)(scaledPosition.x + (Real)0.5);
            size_t y = (size_t)(scaledPosition.y + (Real)0.5);
            size_t z = (size_t)(scaledPosition.z + (Real)0.5);
            value = (Real)getVolumeArrayValue(x, y, z);
        }
        return value;
    }

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

    size_t TextureSource::getWidth(void) const
    {
        return mWidth;
    }

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

    size_t TextureSource::getHeight(void) const
    {
        return mHeight;
    }

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

    size_t TextureSource::getDepth(void) const
    {
        return mDepth;
    }

}
}<commit_msg>Volume Rendering: correct nearest neighbor for normal interpolation<commit_after>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
(Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org

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

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

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

namespace Ogre {
namespace Volume {

    TextureSource::TextureSource(const String &volumeTextureName, const Real worldWidth, const Real worldHeight, const Real worldDepth, const bool trilinearValue, const bool trilinearNormal, const bool sobelNormal) :
        mTrilinearValue(trilinearValue), mTrilinearNormal(trilinearNormal), mSobelNormal(sobelNormal)
    {

        Timer t;
        TexturePtr tex = TextureManager::getSingleton().load(volumeTextureName,
            ResourceGroupManager::getSingleton().getWorldResourceGroupName(),
            TEX_TYPE_3D,
            0);
        LogManager::getSingleton().stream() << "Loaded texture in " << t.getMilliseconds() << "ms.";
        t.reset();

        mWidth = tex->getSrcWidth();
        mHeight= tex->getSrcHeight();
        mWidthTimesHeight = mWidth * mHeight;
        mDepth = tex->getSrcDepth();

        mPosXScale = (Real)1.0 / (Real)worldWidth * (Real)mWidth;
        mPosYScale = (Real)1.0 / (Real)worldHeight * (Real)mHeight;
        mPosZScale = (Real)1.0 / (Real)worldDepth * (Real)mDepth;

        HardwarePixelBufferSharedPtr buffer = tex->getBuffer(0, 0);
        buffer->lock(HardwareBuffer::HBL_READ_ONLY);
        const PixelBox &pb = buffer->getCurrentLock();
        float *pbptr = static_cast<float*>(pb.data);
        mData = OGRE_ALLOC_T(float, mWidth * mHeight * mDepth, MEMCATEGORY_GENERAL);
        float * dataRunner = mData;
        ColourValue cv;
        size_t x, y;
        size_t zEnd = pb.back;
        size_t yStart = pb.top;
        size_t yEnd = pb.bottom;
        size_t xStart = pb.left;
        size_t xEnd = pb.right;
        size_t sliceSkip = pb.getSliceSkip();
        for (size_t z = pb.front; z < zEnd; ++z)
        {
            for (y = yStart; y < yEnd; ++y)
            {
                for (x = xStart; x < xEnd; ++x)
                {
                    *dataRunner++ = pbptr[x];
                }
                pbptr += pb.rowPitch;
            }
            pbptr += sliceSkip;
        }
        buffer->unlock();
        LogManager::getSingleton().stream() << "Processed texture in " << t.getMilliseconds() << "ms.";
    }

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

    TextureSource::~TextureSource(void)
    {
        OGRE_FREE(mData, MEMCATEGORY_GENERAL);
    }

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

    Real TextureSource::getValueAndGradient(const Vector3 &position, Vector3 &normal) const
    {
        Vector3 scaledPosition(position.x * mPosXScale, position.y * mPosYScale, position.z * mPosZScale);
        if (mTrilinearNormal)
        {
            // http://en.wikipedia.org/wiki/Trilinear_interpolation
            size_t x0 = (size_t)scaledPosition.x;
            size_t x1 = (size_t)ceil(scaledPosition.x);
            size_t y0 = (size_t)scaledPosition.y;
            size_t y1 = (size_t)ceil(scaledPosition.y);
            size_t z0 = (size_t)scaledPosition.z;
            size_t z1 = (size_t)ceil(scaledPosition.z);

            Real dX = scaledPosition.x - (Real)x0;
            Real dY = scaledPosition.y - (Real)y0;
            Real dZ = scaledPosition.z - (Real)z0;

            Vector3 i1 = getGradient(x0, y0, z0) * ((Real)1.0 - dZ) + getGradient(x0, y0, z1) * dZ;
            Vector3 i2 = getGradient(x0, y1, z0) * ((Real)1.0 - dZ) + getGradient(x0, y1, z1) * dZ;
            Vector3 j1 = getGradient(x1, y0, z0) * ((Real)1.0 - dZ) + getGradient(x1, y0, z1) * dZ;
            Vector3 j2 = getGradient(x1, y1, z0) * ((Real)1.0 - dZ) + getGradient(x1, y1, z1) * dZ;
            Vector3 w1 = i1 * ((Real)1.0 - dY) + i2 * dY;
            Vector3 w2 = j1 * ((Real)1.0 - dY) + j2 * dY;
            normal = w1 * ((Real)1.0 - dX) + w2 * dX;
            normal *= (Real)-1.0;
        }
        else
        {
            normal = getGradient((size_t)(scaledPosition.x + (Real)0.5), (size_t)(scaledPosition.y + (Real)0.5), (size_t)(scaledPosition.z + (Real)0.5));
            normal *= (Real)-1.0;
        }
        return getValue(position);
    }

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

    Real TextureSource::getValue(const Vector3 &position) const
    {
        Vector3 scaledPosition(position.x * mPosXScale, position.y * mPosYScale, position.z * mPosZScale);
        Real value;
        if (mTrilinearValue)
        {
            // http://en.wikipedia.org/wiki/Trilinear_interpolation
            size_t x0 = (size_t)scaledPosition.x;
            size_t x1 = (size_t)ceil(scaledPosition.x);
            size_t y0 = (size_t)scaledPosition.y;
            size_t y1 = (size_t)ceil(scaledPosition.y);
            size_t z0 = (size_t)scaledPosition.z;
            size_t z1 = (size_t)ceil(scaledPosition.z);

            Real dX = scaledPosition.x - (Real)x0;
            Real dY = scaledPosition.y - (Real)y0;
            Real dZ = scaledPosition.z - (Real)z0;

            Real i1 = getVolumeArrayValue(x0, y0, z0) * ((Real)1.0 - dZ) + getVolumeArrayValue(x0, y0, z1) * dZ;
            Real i2 = getVolumeArrayValue(x0, y1, z0) * ((Real)1.0 - dZ) + getVolumeArrayValue(x0, y1, z1) * dZ;
            Real j1 = getVolumeArrayValue(x1, y0, z0) * ((Real)1.0 - dZ) + getVolumeArrayValue(x1, y0, z1) * dZ;
            Real j2 = getVolumeArrayValue(x1, y1, z0) * ((Real)1.0 - dZ) + getVolumeArrayValue(x1, y1, z1) * dZ;
            Real w1 = i1 * ((Real)1.0 - dY) + i2 * dY;
            Real w2 = j1 * ((Real)1.0 - dY) + j2 * dY;
            value = w1 * ((Real)1.0 - dX) + w2 * dX;
        }
        else
        {
            // Nearest neighbour else
            size_t x = (size_t)(scaledPosition.x + (Real)0.5);
            size_t y = (size_t)(scaledPosition.y + (Real)0.5);
            size_t z = (size_t)(scaledPosition.z + (Real)0.5);
            value = (Real)getVolumeArrayValue(x, y, z);
        }
        return value;
    }

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

    size_t TextureSource::getWidth(void) const
    {
        return mWidth;
    }

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

    size_t TextureSource::getHeight(void) const
    {
        return mHeight;
    }

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

    size_t TextureSource::getDepth(void) const
    {
        return mDepth;
    }

}
}<|endoftext|>


<commit_before>/*
* Copyright (C) 2008-2011 J-P Nurmi jpnurmi@gmail.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*/

#include "messageformatter.h"
#include <ircsender.h>
#include <ircutil.h>
#include <irc.h>
#include <QHash>
#include <QTime>
#include <QColor>

static bool nameLessThan(const QString &n1, const QString &n2)
{
    const bool o1 = n1.startsWith("@");
    const bool o2 = n2.startsWith("@");

    if (o1 && !o2)
        return true;
    if (!o1 && o2)
        return false;

    const bool v1 = n1.startsWith("+");
    const bool v2 = n2.startsWith("+");

    if (v1 && !v2 && !o2)
        return true;
    if (!v1 && !o1 && v2)
        return false;

    return QString::localeAwareCompare(n1.toLower(), n2.toLower()) < 0;
}

MessageFormatter::MessageFormatter(QObject* parent) : QObject(parent)
{
    d.highlight = false;
    d.timeStamp = false;
}

MessageFormatter::~MessageFormatter()
{
}

QStringList MessageFormatter::highlights() const
{
    return d.highlights;
}

void MessageFormatter::setHighlights(const QStringList& highlights)
{
    d.highlights = highlights;
}

bool MessageFormatter::timeStamp() const
{
    return d.timeStamp;
}

void MessageFormatter::setTimeStamp(bool timeStamp)
{
    d.timeStamp = timeStamp;
}

QString MessageFormatter::messageFormat() const
{
    return d.messageFormat;
}

void MessageFormatter::setMessageFormat(const QString& format)
{
    d.messageFormat = format;
}

QString MessageFormatter::eventFormat() const
{
    return d.prefixedFormats.value("!");
}

void MessageFormatter::setEventFormat(const QString& format)
{
    d.prefixedFormats.insert("!", format);
}

QString MessageFormatter::noticeFormat() const
{
    return d.prefixedFormats.value("[");
}

void MessageFormatter::setNoticeFormat(const QString& format)
{
    d.prefixedFormats.insert("[", format);
}

QString MessageFormatter::actionFormat() const
{
    return d.prefixedFormats.value("*");
}

void MessageFormatter::setActionFormat(const QString& format)
{
    d.prefixedFormats.insert("*", format);
}

QString MessageFormatter::unknownFormat() const
{
    return d.prefixedFormats.value("?");
}

void MessageFormatter::setUnknownFormat(const QString& format)
{
    d.prefixedFormats.insert("?", format);
}

QString MessageFormatter::highlightFormat() const
{
    return d.highlightFormat;
}

void MessageFormatter::setHighlightFormat(const QString& format)
{
    d.highlightFormat = format;
}

QStringList MessageFormatter::currentNames() const
{
    qSort(d.names.begin(), d.names.end(), nameLessThan);
    return d.names;
}

QString MessageFormatter::formatMessage(IrcMessage* message) const
{
    QString formatted;
    d.highlight = false;
    switch (message->type())
    {
    case IrcMessage::Invite:
        formatted = formatInviteMessage(static_cast<IrcInviteMessage*>(message));
        break;
    case IrcMessage::Join:
        formatted = formatJoinMessage(static_cast<IrcJoinMessage*>(message));
        break;
    case IrcMessage::Kick:
        formatted = formatKickMessage(static_cast<IrcKickMessage*>(message));
        break;
    case IrcMessage::Mode:
        formatted = formatModeMessage(static_cast<IrcModeMessage*>(message));
        break;
    case IrcMessage::Nick:
        formatted = formatNickMessage(static_cast<IrcNickMessage*>(message));
        break;
    case IrcMessage::Notice:
        formatted = formatNoticeMessage(static_cast<IrcNoticeMessage*>(message));
        break;
    case IrcMessage::Numeric:
        formatted = formatNumericMessage(static_cast<IrcNumericMessage*>(message));
        break;
    case IrcMessage::Part:
        formatted = formatPartMessage(static_cast<IrcPartMessage*>(message));
        break;
    case IrcMessage::Pong:
        formatted = formatPongMessage(static_cast<IrcPongMessage*>(message));
        break;
    case IrcMessage::Private:
        formatted = formatPrivateMessage(static_cast<IrcPrivateMessage*>(message));
        break;
    case IrcMessage::Quit:
        formatted = formatQuitMessage(static_cast<IrcQuitMessage*>(message));
        break;
    case IrcMessage::Topic:
        formatted = formatTopicMessage(static_cast<IrcTopicMessage*>(message));
        break;
    case IrcMessage::Unknown:
        formatted = formatUnknownMessage(static_cast<IrcMessage*>(message));
        break;
    default:
        break;
    }

    if (formatted.isEmpty())
        return QString();

    QString format = d.messageFormat;
    if (d.highlight && !d.highlightFormat.isEmpty())
        format = d.highlightFormat;
    else
        format = d.prefixedFormats.value(formatted.left(1));

    if (d.timeStamp)
        formatted = tr("[%1] %2").arg(QTime::currentTime().toString(), formatted);

    if (!format.isNull())
        formatted = tr("%2").arg(format, formatted);

    return formatted;
}

QString MessageFormatter::formatInviteMessage(IrcInviteMessage* message) const
{
    const QString sender = prettyUser(message->sender());
    return tr("! %1 invited to %3").arg(sender, message->channel());
}

QString MessageFormatter::formatJoinMessage(IrcJoinMessage* message) const
{
    const QString sender = prettyUser(message->sender());
    return tr("! %1 joined %2").arg(sender, message->channel());
}

QString MessageFormatter::formatKickMessage(IrcKickMessage* message) const
{
    const QString sender = prettyUser(message->sender());
    const QString user = prettyUser(message->user());
    if (!message->reason().isEmpty())
        return tr("! %1 kicked %2 (%3)").arg(sender, user, message->reason());
    else
        return tr("! %1 kicked %2").arg(sender, user);
}

QString MessageFormatter::formatModeMessage(IrcModeMessage* message) const
{
    const QString sender = prettyUser(message->sender());
    return tr("! %1 sets mode %2 %3").arg(sender, message->mode(), message->argument());
}

QString MessageFormatter::formatNickMessage(IrcNickMessage* message) const
{
    const QString sender = prettyUser(message->sender());
    const QString nick = prettyUser(message->nick());
    return tr("! %1 changed nick to %2").arg(sender, nick);
}

QString MessageFormatter::formatNoticeMessage(IrcNoticeMessage* message) const
{
    if (message->isReply())
    {
        const QStringList params = message->message().split(" ", QString::SkipEmptyParts);
        const QString cmd = params.value(0);
        const QString arg = params.value(1);
        if (cmd.toUpper() == "PING")
            return formatPingReply(message->sender(), arg);
        else if (cmd.toUpper() == "TIME")
            return tr("! %1 time is %2").arg(prettyUser(message->sender()), QStringList(params.mid(1)).join(" "));
        else if (cmd.toUpper() == "VERSION")
            return tr("! %1 version is %2").arg(prettyUser(message->sender()), QStringList(params.mid(1)).join(" "));
    }

    foreach (const QString& hilite, d.highlights)
        if (message->message().contains(hilite))
            d.highlight = true;
    const QString sender = prettyUser(message->sender());
    const QString msg = IrcUtil::messageToHtml(message->message());
    return tr("[%1] %2").arg(sender, msg);
}

#define P_(x) message->parameters().value(x)
#define MID_(x) QStringList(message->parameters().mid(x)).join(" ")

QString MessageFormatter::formatNumericMessage(IrcNumericMessage* message) const
{
    if (message->code() < 300)
        return tr("[INFO] %1").arg(IrcUtil::messageToHtml(MID_(1)));
    if (QByteArray(Irc::toString(message->code())).startsWith("ERR_"))
        return tr("[ERROR] %1").arg(IrcUtil::messageToHtml(MID_(1)));

    switch (message->code())
    {
    case Irc::RPL_MOTDSTART:
    case Irc::RPL_MOTD:
        return tr("[MOTD] %1").arg(IrcUtil::messageToHtml(MID_(1)));
    case Irc::RPL_AWAY:
    case Irc::RPL_WHOISOPERATOR:
    case Irc::RPL_WHOISHELPOP: // "is available for help"
    case Irc::RPL_WHOISSPECIAL: // "is identified to services"
    case Irc::RPL_WHOISSECURE: // nick is using a secure connection
        return tr("! %1 %2").arg(message->sender().name(), message->parameters().join(" "));
    case Irc::RPL_WHOISHOST: // nick is connecting from <...>
        return tr("! %1").arg(MID_(1));
    case Irc::RPL_WHOISUSER:
        return tr("! %1 is %2@%3 (%4)").arg(P_(1), P_(2), P_(3), IrcUtil::messageToHtml(MID_(5)));
    case Irc::RPL_WHOISSERVER:
        return tr("! %1 is online via %2 (%3)").arg(P_(1), P_(2), P_(3));
    case Irc::RPL_WHOISACCOUNT: // nick user is logged in as
        return tr("! %1 %3 %2").arg(P_(1), P_(2), P_(3));
    case Irc::RPL_WHOWASUSER:
        return tr("! %1 was %2@%3 %4 %5").arg(P_(1), P_(2), P_(3), P_(4), P_(5));
    case Irc::RPL_WHOISIDLE: {
        QDateTime signon = QDateTime::fromTime_t(P_(3).toInt());
        QTime idle = QTime().addSecs(P_(2).toInt());
        return tr("! %1 has been online since %2 (idle for %3)").arg(P_(1), signon.toString(), idle.toString());
    }
    case Irc::RPL_WHOISCHANNELS:
        return tr("! %1 is on channels %2").arg(P_(1), P_(2));
    case Irc::RPL_CHANNELMODEIS:
        return tr("! %1 mode is %2").arg(P_(1), P_(2));
    case Irc::RPL_CHANNEL_URL:
        return tr("! %1 url is %2").arg(P_(1), IrcUtil::messageToHtml(P_(2)));
    case Irc::RPL_CREATIONTIME: {
        QDateTime dateTime = QDateTime::fromTime_t(P_(2).toInt());
        return tr("! %1 was created %2").arg(P_(1), dateTime.toString());
    }
    case Irc::RPL_NOTOPIC:
        return tr("! %1 has no topic set").arg(P_(1));
    case Irc::RPL_TOPIC:
        return tr("! %1 topic is \"%2\"").arg(P_(1), IrcUtil::messageToHtml(P_(2)));
    case Irc::RPL_TOPICWHOTIME: {
        QDateTime dateTime = QDateTime::fromTime_t(P_(3).toInt());
        return tr("! %1 topic was set %2 by %3").arg(P_(1), dateTime.toString(), P_(2));
    }
    case Irc::RPL_INVITING:
        return tr("! inviting %1 to %2").arg(prettyUser(P_(1)), P_(2));
    case Irc::RPL_VERSION:
        return tr("! %1 version is %2").arg(prettyUser(message->sender()), P_(1));
    case Irc::RPL_TIME:
        return tr("! %1 time is %2").arg(prettyUser(P_(1)), P_(2));
    case Irc::RPL_UNAWAY:
    case Irc::RPL_NOWAWAY:
        return tr("! %1").arg(P_(1));

    case Irc::RPL_NAMREPLY:
        foreach (const QString& name, P_(3).split(" ", QString::SkipEmptyParts))
            d.names.append(name);
        return QString();

    case Irc::RPL_ENDOFNAMES: {
        QString msg = tr("! %1 has %2 users").arg(P_(1)).arg(d.names.count());
        d.names.clear();
        return msg;
    }

    default:
        return tr("[%1] %2").arg(message->code()).arg(QStringList(message->parameters().mid(1)).join(" "));
    }
}

QString MessageFormatter::formatPartMessage(IrcPartMessage* message) const
{
    const QString sender = prettyUser(message->sender());
    if (!message->reason().isEmpty())
        return tr("! %1 parted %2 (%3)").arg(sender, message->channel(), IrcUtil::messageToHtml(message->reason()));
    else
        return tr("! %1 parted %2").arg(sender, message->channel());
}

QString MessageFormatter::formatPongMessage(IrcPongMessage* message) const
{
    return formatPingReply(message->sender(), message->argument());
}

QString MessageFormatter::formatPrivateMessage(IrcPrivateMessage* message) const
{
    foreach (const QString& hilite, d.highlights)
        if (message->message().contains(hilite))
            d.highlight = true;
    const QString sender = prettyUser(message->sender());
    const QString msg = IrcUtil::messageToHtml(message->message());
    if (message->isAction())
        return tr("* %1 %2").arg(sender, msg);
    else if (message->isRequest())
        return tr("! %1 requested %2").arg(sender, msg.split(" ").value(0).toLower());
    else
        return tr("<%1> %2").arg(sender, msg);
}

QString MessageFormatter::formatQuitMessage(IrcQuitMessage* message) const
{
    const QString sender = prettyUser(message->sender());
    if (!message->reason().isEmpty())
        return tr("! %1 has quit (%2)").arg(sender, IrcUtil::messageToHtml(message->reason()));
    else
        return tr("! %1 has quit").arg(sender);
}

QString MessageFormatter::formatTopicMessage(IrcTopicMessage* message) const
{
    const QString sender = prettyUser(message->sender());
    const QString topic = IrcUtil::messageToHtml(message->topic());
    return tr("! %1 sets topic \"%2\" on %3").arg(sender, topic, message->channel());
}

QString MessageFormatter::formatUnknownMessage(IrcMessage* message) const
{
    const QString sender = prettyUser(message->sender());
    return tr("? %1 %2 %3").arg(sender, message->command(), message->parameters().join(" "));
}

QString MessageFormatter::formatPingReply(const IrcSender& sender, const QString& arg)
{
    bool ok;
    int seconds = arg.toInt(&ok);
    if (ok)
    {
        QDateTime time = QDateTime::fromTime_t(seconds);
        QString result = QString::number(time.secsTo(QDateTime::currentDateTime()));
        return tr("! %1 replied in %2s").arg(prettyUser(sender), result);
    }
    return QString();
}

QString MessageFormatter::prettyUser(const IrcSender& sender)
{
    const QString name = sender.name();
    if (sender.isValid())
        return colorize(name);
    return name;
}

QString MessageFormatter::prettyUser(const QString& user)
{
    return prettyUser(IrcSender(user));
}

QString MessageFormatter::colorize(const QString& str)
{
    QColor color = QColor::fromHsl(qHash(str) % 359, 255, 64);
    return QString("%2").arg(color.name()).arg(str);
}
<commit_msg>MessageFormatter: fix away/whois formatting<commit_after>/*
* Copyright (C) 2008-2011 J-P Nurmi jpnurmi@gmail.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*/

#include "messageformatter.h"
#include <ircsender.h>
#include <ircutil.h>
#include <irc.h>
#include <QHash>
#include <QTime>
#include <QColor>

static bool nameLessThan(const QString &n1, const QString &n2)
{
    const bool o1 = n1.startsWith("@");
    const bool o2 = n2.startsWith("@");

    if (o1 && !o2)
        return true;
    if (!o1 && o2)
        return false;

    const bool v1 = n1.startsWith("+");
    const bool v2 = n2.startsWith("+");

    if (v1 && !v2 && !o2)
        return true;
    if (!v1 && !o1 && v2)
        return false;

    return QString::localeAwareCompare(n1.toLower(), n2.toLower()) < 0;
}

MessageFormatter::MessageFormatter(QObject* parent) : QObject(parent)
{
    d.highlight = false;
    d.timeStamp = false;
}

MessageFormatter::~MessageFormatter()
{
}

QStringList MessageFormatter::highlights() const
{
    return d.highlights;
}

void MessageFormatter::setHighlights(const QStringList& highlights)
{
    d.highlights = highlights;
}

bool MessageFormatter::timeStamp() const
{
    return d.timeStamp;
}

void MessageFormatter::setTimeStamp(bool timeStamp)
{
    d.timeStamp = timeStamp;
}

QString MessageFormatter::messageFormat() const
{
    return d.messageFormat;
}

void MessageFormatter::setMessageFormat(const QString& format)
{
    d.messageFormat = format;
}

QString MessageFormatter::eventFormat() const
{
    return d.prefixedFormats.value("!");
}

void MessageFormatter::setEventFormat(const QString& format)
{
    d.prefixedFormats.insert("!", format);
}

QString MessageFormatter::noticeFormat() const
{
    return d.prefixedFormats.value("[");
}

void MessageFormatter::setNoticeFormat(const QString& format)
{
    d.prefixedFormats.insert("[", format);
}

QString MessageFormatter::actionFormat() const
{
    return d.prefixedFormats.value("*");
}

void MessageFormatter::setActionFormat(const QString& format)
{
    d.prefixedFormats.insert("*", format);
}

QString MessageFormatter::unknownFormat() const
{
    return d.prefixedFormats.value("?");
}

void MessageFormatter::setUnknownFormat(const QString& format)
{
    d.prefixedFormats.insert("?", format);
}

QString MessageFormatter::highlightFormat() const
{
    return d.highlightFormat;
}

void MessageFormatter::setHighlightFormat(const QString& format)
{
    d.highlightFormat = format;
}

QStringList MessageFormatter::currentNames() const
{
    qSort(d.names.begin(), d.names.end(), nameLessThan);
    return d.names;
}

QString MessageFormatter::formatMessage(IrcMessage* message) const
{
    QString formatted;
    d.highlight = false;
    switch (message->type())
    {
    case IrcMessage::Invite:
        formatted = formatInviteMessage(static_cast<IrcInviteMessage*>(message));
        break;
    case IrcMessage::Join:
        formatted = formatJoinMessage(static_cast<IrcJoinMessage*>(message));
        break;
    case IrcMessage::Kick:
        formatted = formatKickMessage(static_cast<IrcKickMessage*>(message));
        break;
    case IrcMessage::Mode:
        formatted = formatModeMessage(static_cast<IrcModeMessage*>(message));
        break;
    case IrcMessage::Nick:
        formatted = formatNickMessage(static_cast<IrcNickMessage*>(message));
        break;
    case IrcMessage::Notice:
        formatted = formatNoticeMessage(static_cast<IrcNoticeMessage*>(message));
        break;
    case IrcMessage::Numeric:
        formatted = formatNumericMessage(static_cast<IrcNumericMessage*>(message));
        break;
    case IrcMessage::Part:
        formatted = formatPartMessage(static_cast<IrcPartMessage*>(message));
        break;
    case IrcMessage::Pong:
        formatted = formatPongMessage(static_cast<IrcPongMessage*>(message));
        break;
    case IrcMessage::Private:
        formatted = formatPrivateMessage(static_cast<IrcPrivateMessage*>(message));
        break;
    case IrcMessage::Quit:
        formatted = formatQuitMessage(static_cast<IrcQuitMessage*>(message));
        break;
    case IrcMessage::Topic:
        formatted = formatTopicMessage(static_cast<IrcTopicMessage*>(message));
        break;
    case IrcMessage::Unknown:
        formatted = formatUnknownMessage(static_cast<IrcMessage*>(message));
        break;
    default:
        break;
    }

    if (formatted.isEmpty())
        return QString();

    QString format = d.messageFormat;
    if (d.highlight && !d.highlightFormat.isEmpty())
        format = d.highlightFormat;
    else
        format = d.prefixedFormats.value(formatted.left(1));

    if (d.timeStamp)
        formatted = tr("[%1] %2").arg(QTime::currentTime().toString(), formatted);

    if (!format.isNull())
        formatted = tr("%2").arg(format, formatted);

    return formatted;
}

QString MessageFormatter::formatInviteMessage(IrcInviteMessage* message) const
{
    const QString sender = prettyUser(message->sender());
    return tr("! %1 invited to %3").arg(sender, message->channel());
}

QString MessageFormatter::formatJoinMessage(IrcJoinMessage* message) const
{
    const QString sender = prettyUser(message->sender());
    return tr("! %1 joined %2").arg(sender, message->channel());
}

QString MessageFormatter::formatKickMessage(IrcKickMessage* message) const
{
    const QString sender = prettyUser(message->sender());
    const QString user = prettyUser(message->user());
    if (!message->reason().isEmpty())
        return tr("! %1 kicked %2 (%3)").arg(sender, user, message->reason());
    else
        return tr("! %1 kicked %2").arg(sender, user);
}

QString MessageFormatter::formatModeMessage(IrcModeMessage* message) const
{
    const QString sender = prettyUser(message->sender());
    return tr("! %1 sets mode %2 %3").arg(sender, message->mode(), message->argument());
}

QString MessageFormatter::formatNickMessage(IrcNickMessage* message) const
{
    const QString sender = prettyUser(message->sender());
    const QString nick = prettyUser(message->nick());
    return tr("! %1 changed nick to %2").arg(sender, nick);
}

QString MessageFormatter::formatNoticeMessage(IrcNoticeMessage* message) const
{
    if (message->isReply())
    {
        const QStringList params = message->message().split(" ", QString::SkipEmptyParts);
        const QString cmd = params.value(0);
        const QString arg = params.value(1);
        if (cmd.toUpper() == "PING")
            return formatPingReply(message->sender(), arg);
        else if (cmd.toUpper() == "TIME")
            return tr("! %1 time is %2").arg(prettyUser(message->sender()), QStringList(params.mid(1)).join(" "));
        else if (cmd.toUpper() == "VERSION")
            return tr("! %1 version is %2").arg(prettyUser(message->sender()), QStringList(params.mid(1)).join(" "));
    }

    foreach (const QString& hilite, d.highlights)
        if (message->message().contains(hilite))
            d.highlight = true;
    const QString sender = prettyUser(message->sender());
    const QString msg = IrcUtil::messageToHtml(message->message());
    return tr("[%1] %2").arg(sender, msg);
}

#define P_(x) message->parameters().value(x)
#define MID_(x) QStringList(message->parameters().mid(x)).join(" ")

QString MessageFormatter::formatNumericMessage(IrcNumericMessage* message) const
{
    if (message->code() < 300)
        return tr("[INFO] %1").arg(IrcUtil::messageToHtml(MID_(1)));
    if (QByteArray(Irc::toString(message->code())).startsWith("ERR_"))
        return tr("[ERROR] %1").arg(IrcUtil::messageToHtml(MID_(1)));

    switch (message->code())
    {
    case Irc::RPL_MOTDSTART:
    case Irc::RPL_MOTD:
        return tr("[MOTD] %1").arg(IrcUtil::messageToHtml(MID_(1)));
    case Irc::RPL_AWAY:
        return tr("! %1 is away (%2)").arg(P_(1), MID_(2));
    case Irc::RPL_WHOISOPERATOR:
    case Irc::RPL_WHOISHELPOP: // "is available for help"
    case Irc::RPL_WHOISSPECIAL: // "is identified to services"
    case Irc::RPL_WHOISSECURE: // nick is using a secure connection
    case Irc::RPL_WHOISHOST: // nick is connecting from <...>
        return tr("! %1").arg(MID_(1));
    case Irc::RPL_WHOISUSER:
        return tr("! %1 is %2@%3 (%4)").arg(P_(1), P_(2), P_(3), IrcUtil::messageToHtml(MID_(5)));
    case Irc::RPL_WHOISSERVER:
        return tr("! %1 is online via %2 (%3)").arg(P_(1), P_(2), P_(3));
    case Irc::RPL_WHOISACCOUNT: // nick user is logged in as
        return tr("! %1 %3 %2").arg(P_(1), P_(2), P_(3));
    case Irc::RPL_WHOWASUSER:
        return tr("! %1 was %2@%3 %4 %5").arg(P_(1), P_(2), P_(3), P_(4), P_(5));
    case Irc::RPL_WHOISIDLE: {
        QDateTime signon = QDateTime::fromTime_t(P_(3).toInt());
        QTime idle = QTime().addSecs(P_(2).toInt());
        return tr("! %1 has been online since %2 (idle for %3)").arg(P_(1), signon.toString(), idle.toString());
    }
    case Irc::RPL_WHOISCHANNELS:
        return tr("! %1 is on channels %2").arg(P_(1), P_(2));
    case Irc::RPL_CHANNELMODEIS:
        return tr("! %1 mode is %2").arg(P_(1), P_(2));
    case Irc::RPL_CHANNEL_URL:
        return tr("! %1 url is %2").arg(P_(1), IrcUtil::messageToHtml(P_(2)));
    case Irc::RPL_CREATIONTIME: {
        QDateTime dateTime = QDateTime::fromTime_t(P_(2).toInt());
        return tr("! %1 was created %2").arg(P_(1), dateTime.toString());
    }
    case Irc::RPL_NOTOPIC:
        return tr("! %1 has no topic set").arg(P_(1));
    case Irc::RPL_TOPIC:
        return tr("! %1 topic is \"%2\"").arg(P_(1), IrcUtil::messageToHtml(P_(2)));
    case Irc::RPL_TOPICWHOTIME: {
        QDateTime dateTime = QDateTime::fromTime_t(P_(3).toInt());
        return tr("! %1 topic was set %2 by %3").arg(P_(1), dateTime.toString(), P_(2));
    }
    case Irc::RPL_INVITING:
        return tr("! inviting %1 to %2").arg(prettyUser(P_(1)), P_(2));
    case Irc::RPL_VERSION:
        return tr("! %1 version is %2").arg(prettyUser(message->sender()), P_(1));
    case Irc::RPL_TIME:
        return tr("! %1 time is %2").arg(prettyUser(P_(1)), P_(2));
    case Irc::RPL_UNAWAY:
    case Irc::RPL_NOWAWAY:
        return tr("! %1").arg(P_(1));

    case Irc::RPL_NAMREPLY:
        foreach (const QString& name, P_(3).split(" ", QString::SkipEmptyParts))
            d.names.append(name);
        return QString();

    case Irc::RPL_ENDOFNAMES: {
        QString msg = tr("! %1 has %2 users").arg(P_(1)).arg(d.names.count());
        d.names.clear();
        return msg;
    }

    default:
        return tr("[%1] %2").arg(message->code()).arg(QStringList(message->parameters().mid(1)).join(" "));
    }
}

QString MessageFormatter::formatPartMessage(IrcPartMessage* message) const
{
    const QString sender = prettyUser(message->sender());
    if (!message->reason().isEmpty())
        return tr("! %1 parted %2 (%3)").arg(sender, message->channel(), IrcUtil::messageToHtml(message->reason()));
    else
        return tr("! %1 parted %2").arg(sender, message->channel());
}

QString MessageFormatter::formatPongMessage(IrcPongMessage* message) const
{
    return formatPingReply(message->sender(), message->argument());
}

QString MessageFormatter::formatPrivateMessage(IrcPrivateMessage* message) const
{
    foreach (const QString& hilite, d.highlights)
        if (message->message().contains(hilite))
            d.highlight = true;
    const QString sender = prettyUser(message->sender());
    const QString msg = IrcUtil::messageToHtml(message->message());
    if (message->isAction())
        return tr("* %1 %2").arg(sender, msg);
    else if (message->isRequest())
        return tr("! %1 requested %2").arg(sender, msg.split(" ").value(0).toLower());
    else
        return tr("<%1> %2").arg(sender, msg);
}

QString MessageFormatter::formatQuitMessage(IrcQuitMessage* message) const
{
    const QString sender = prettyUser(message->sender());
    if (!message->reason().isEmpty())
        return tr("! %1 has quit (%2)").arg(sender, IrcUtil::messageToHtml(message->reason()));
    else
        return tr("! %1 has quit").arg(sender);
}

QString MessageFormatter::formatTopicMessage(IrcTopicMessage* message) const
{
    const QString sender = prettyUser(message->sender());
    const QString topic = IrcUtil::messageToHtml(message->topic());
    return tr("! %1 sets topic \"%2\" on %3").arg(sender, topic, message->channel());
}

QString MessageFormatter::formatUnknownMessage(IrcMessage* message) const
{
    const QString sender = prettyUser(message->sender());
    return tr("? %1 %2 %3").arg(sender, message->command(), message->parameters().join(" "));
}

QString MessageFormatter::formatPingReply(const IrcSender& sender, const QString& arg)
{
    bool ok;
    int seconds = arg.toInt(&ok);
    if (ok)
    {
        QDateTime time = QDateTime::fromTime_t(seconds);
        QString result = QString::number(time.secsTo(QDateTime::currentDateTime()));
        return tr("! %1 replied in %2s").arg(prettyUser(sender), result);
    }
    return QString();
}

QString MessageFormatter::prettyUser(const IrcSender& sender)
{
    const QString name = sender.name();
    if (sender.isValid())
        return colorize(name);
    return name;
}

QString MessageFormatter::prettyUser(const QString& user)
{
    return prettyUser(IrcSender(user));
}

QString MessageFormatter::colorize(const QString& str)
{
    QColor color = QColor::fromHsl(qHash(str) % 359, 255, 64);
    return QString("%2").arg(color.name()).arg(str);
}
<|endoftext|>


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

Program:   Medical Imaging & Interaction Toolkit
Module:    $RCSfile$
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

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

#include "mitkConnectPointsInteractor.h"
#include <mitkLineOperation.h>
#include <mitkPositionEvent.h>
#include "mitkMesh.h"
#include <mitkDataTreeNode.h>
#include <mitkInteractionConst.h>
#include "mitkAction.h"

//how precise must the user pick the point
//default value
const int PRECISION = 5;

mitk::ConnectPointsInteractor::ConnectPointsInteractor(const char * type, DataTreeNode* dataTreeNode, int n)
:Interactor(type, dataTreeNode), m_N(n), m_CurrentCellId(0), m_Precision(PRECISION)
{
  m_LastPoint.Fill(0);
  m_SumVec.Fill(0);
}

mitk::ConnectPointsInteractor::~ConnectPointsInteractor()
{
}

void mitk::ConnectPointsInteractor::SetPrecision(unsigned int precision)
{
  m_Precision = precision;
}

//##Documentation
//## overwritten cause this class can handle it better!
float mitk::ConnectPointsInteractor::CalculateJurisdiction(StateEvent const* stateEvent) const
{
  float returnvalue = 0.0;
  //if it is a key event that can be handled in the current state, then return 0.5
  mitk::DisplayPositionEvent const  *disPosEvent = dynamic_cast <const mitk::DisplayPositionEvent *> (stateEvent->GetEvent());

  //Key event handling:
  if (disPosEvent == NULL)
  {
    //check, if the current state has a transition waiting for that key event.
    if (this->GetCurrentState()->GetTransition(stateEvent->GetId())!=NULL)
    {
      return 0.5;
    }
    else
    {
      return 0;
    }
  }

  //on MouseMove do nothing!
  if (stateEvent->GetEvent()->GetType() == mitk::Type_MouseMove)
  {
    return 0;
  }

  //if we don't have a Point in our PointSet, then return with 0.5
  mitk::PointSet* pointSet = dynamic_cast<mitk::PointSet*>(m_DataTreeNode->GetData());
  if (pointSet != NULL)
  {
    if (pointSet->GetSize()<1)
      returnvalue = 0.5;
  }

  return returnvalue;
}

bool mitk::ConnectPointsInteractor::ExecuteAction( Action* action, mitk::StateEvent const* stateEvent )
{
  bool ok = false;//for return type bool

  //checking corresponding Data; has to be a Mesh or a subclass
  mitk::Mesh* mesh = dynamic_cast<mitk::Mesh*>(m_DataTreeNode->GetData());
  if (mesh == NULL)
    return false;

  //for reading on the points, Id's etc
  //mitk::PointSet::DataType *itkpointSet = mesh->GetPointSet();
  //mitk::PointSet::PointsContainer *points = itkpointSet->GetPoints();//Warning Fix: not used!

  /*Each case must watch the type of the event!*/
  switch (action->GetActionId())
  {
  case AcDONOTHING:
    ok = true;
    break;
  case AcADDPOINT:
    {
      mitk::DisplayPositionEvent const  *posEvent = dynamic_cast <const mitk::DisplayPositionEvent *> (stateEvent->GetEvent());
      if (posEvent == NULL)
        return false;

      mitk::Point3D worldPoint;
      worldPoint = posEvent->GetWorldPosition();

      int position = mesh->SearchPoint(worldPoint, m_Precision);
      if (position >= 0)//found a point near enough to the given point
      {
        // if the point is the last in current cell, remove it (this has to be moved in a separate action)
        bool deleteLine=false;
        if(mesh->GetMesh()->GetCells()->Size() > 0)
        {
          Mesh::CellAutoPointer cellAutoPointer;
          ok = mesh->GetMesh()->GetCell(m_CurrentCellId, cellAutoPointer);
          if(ok)
          {
            Mesh::PointIdIterator last = cellAutoPointer->PointIdsEnd();
            --last;
            int foundCell = mesh->SearchFirstCell( (unsigned long) position );
            if (foundCell != -1)//not found
              deleteLine = ((unsigned int)foundCell == m_CurrentCellId) && (*last == (unsigned int)position);
          }
        }
        if(deleteLine)
        {
          LineOperation* doOp = new mitk::LineOperation(OpDELETELINE, m_CurrentCellId, position);
          if (m_UndoEnabled)
          {
            LineOperation* undoOp = new mitk::LineOperation(OpADDLINE, m_CurrentCellId, position);
            OperationEvent *operationEvent = new OperationEvent(mesh, doOp, undoOp, "Delete line");
            m_UndoController->SetOperationEvent(operationEvent);
          }
          //execute the Operation
          mesh->ExecuteOperation(doOp );
        }
        else
        {
          // add new cell if necessary
          if(mesh->GetNewCellId() == 0) //allow single line only
            //allow multiple lines:          if((mesh->SearchFirstCell(position) >= 0) || ((m_CurrentCellId == 0) && (mesh->GetNewCellId() == 0)))
          {
            //get the next cellId and set m_CurrentCellId
            m_CurrentCellId = mesh->GetNewCellId();

            //now reserv a new cell in m_ItkData
            LineOperation* doOp = new mitk::LineOperation(OpNEWCELL, m_CurrentCellId);
            if (m_UndoEnabled)
            {
              LineOperation* undoOp = new mitk::LineOperation(OpDELETECELL, m_CurrentCellId);
              OperationEvent *operationEvent = new OperationEvent(mesh, doOp, undoOp, "Add cell");
              m_UndoController->SetOperationEvent(operationEvent);
            }
            mesh->ExecuteOperation(doOp);
          }
          // add line if point is not yet included in current cell
          if(mesh->SearchFirstCell(position) < 0)
          {
            LineOperation* doOp = new mitk::LineOperation(OpADDLINE, m_CurrentCellId, position);
            if (m_UndoEnabled)
            {
              LineOperation* undoOp = new mitk::LineOperation(OpDELETELINE, m_CurrentCellId, position);
              OperationEvent *operationEvent = new OperationEvent(mesh, doOp, undoOp, "Add line");
              m_UndoController->SetOperationEvent(operationEvent);
            }
            //execute the Operation
            mesh->ExecuteOperation(doOp );
          }
        }
      }
      ok = true;
      break;
    }
  case AcREMOVEPOINT:
    {
      //mitk::DisplayPositionEvent const  *posEvent = dynamic_cast <const mitk::DisplayPositionEvent *> (stateEvent->GetEvent());
      //if (posEvent == NULL)
      //  return false;

      //mitk::Point3D worldPoint;
      //worldPoint = posEvent->GetWorldPosition();

      //int position = mesh->SearchPoint(worldPoint, m_Precision);
      //if (position>=0)//found a point near enough to the given point
      //{
      //  // if the point is in the current cell, remove it (this has to be moved in a separate action)
      //  if(mesh->SearchFirstCell(position) == m_CurrentCellId)
      //  {
      //    LineOperation* doOp = new mitk::LineOperation(OpDELETELINE, m_CurrentCellId, position);
      //  if (m_UndoEnabled)
      //  {
      //   LineOperation* undoOp = new mitk::LineOperation(OpADDLINE, m_CurrentCellId, position);
      //   OperationEvent *operationEvent = new OperationEvent(mesh, doOp, undoOp);
      //   m_UndoController->SetOperationEvent(operationEvent);
      //  }
      //  //execute the Operation
      //    mesh->ExecuteOperation(doOp );
      //  }
      //}
      ok = true;
      break;
    }
  case AcCHECKELEMENT:
    /*checking if the Point transmitted is close enough to one point. Then generate a new event with the point and let this statemaschine handle the event.*/
    {
      mitk::DisplayPositionEvent const  *posEvent = dynamic_cast <const mitk::DisplayPositionEvent *> (stateEvent->GetEvent());
      if (posEvent != NULL)
      {
        mitk::Point3D worldPoint = posEvent->GetWorldPosition();

        int position = mesh->SearchPoint(worldPoint, m_Precision);
        if (position>=0)//found a point near enough to the given point
        {
          PointSet::PointType pt = mesh->GetPoint(position);//get that point, the one meant by the user!
          mitk::Point2D displPoint;
          displPoint[0] = worldPoint[0]; displPoint[1] = worldPoint[1];
          //new Event with information YES and with the correct point
          mitk::PositionEvent const* newPosEvent = new mitk::PositionEvent(posEvent->GetSender(), Type_None, BS_NoButton, BS_NoButton, Key_none, displPoint, pt);
          mitk::StateEvent* newStateEvent = new mitk::StateEvent(EIDYES, newPosEvent);
          //call HandleEvent to leave the guard-state
          this->HandleEvent( newStateEvent );
          ok = true;
        }
        else
        {
          //new Event with information NO
          mitk::StateEvent* newStateEvent = new mitk::StateEvent(EIDNO, posEvent);
          this->HandleEvent(newStateEvent );
          ok = true;
        }
      }
      else
      {
        mitk::DisplayPositionEvent const  *disPosEvent = dynamic_cast <const mitk::DisplayPositionEvent *> (stateEvent->GetEvent());
        if (disPosEvent != NULL)
        {//2d Koordinates for 3D Interaction; return false to redo the last statechange
          mitk::StateEvent* newStateEvent = new mitk::StateEvent(EIDNO, posEvent);
          this->HandleEvent(newStateEvent );
          ok = true;
        }
      }
      break;
    }
  case AcCHECKNMINUS1://generate Events if the set will be full after the addition of the point or not.
    {
      if (m_N<0)//number of points not limited->pass on "Amount of points in Set is smaller then N-1"
      {
        mitk::StateEvent* newStateEvent = new mitk::StateEvent(EIDSTSMALERNMINUS1, stateEvent->GetEvent());
        this->HandleEvent( newStateEvent );
        ok = true;
      }
      else
      {
        if (mesh->GetSize()<(m_N-1))
          //pointset after addition won't be full
        {
          mitk::StateEvent* newStateEvent = new mitk::StateEvent(EIDSTSMALERNMINUS1, stateEvent->GetEvent());
          this->HandleEvent( newStateEvent );
          ok = true;
        }
        else //(mesh->GetSize()>=(m_N-1))
          //after the addition of a point, the container will be full
        {
          mitk::StateEvent* newStateEvent = new mitk::StateEvent(EIDSTLARGERNMINUS1, stateEvent->GetEvent());
          this->HandleEvent(newStateEvent );
          ok = true;
        }//else
      }//else
    }
    break;
  case AcCHECKEQUALS1:
    {
      if (mesh->GetSize()<=1)//the number of points in the list is 1 (or smaler)
      {
        mitk::StateEvent* newStateEvent = new mitk::StateEvent(EIDYES, stateEvent->GetEvent());
        this->HandleEvent( newStateEvent );
        ok = true;
      }
      else //more than 1 points in list, so stay in the state!
      {
        mitk::StateEvent* newStateEvent = new mitk::StateEvent(EIDNO, stateEvent->GetEvent());
        this->HandleEvent(newStateEvent );
        ok = true;
      }
    }
    break;
  default:
    return Superclass::ExecuteAction( action, stateEvent );
    //mitk::StatusBar::DisplayText("Message from mitkConnectPointsInteractor: I do not understand the Action!", 10000);
    //ok = false;
    //a false here causes the statemachine to undo its last statechange.
    //otherwise it will end up in a different state, but without done Action.
    //if a transition really has no Action, than call donothing
  }

  return ok;
}
<commit_msg>FIC: CalculateJurisdiction did not work anymore due to stricter juristiction handling in GlobalInteraction<commit_after>/*=========================================================================

Program:   Medical Imaging & Interaction Toolkit
Module:    $RCSfile$
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

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

#include "mitkConnectPointsInteractor.h"
#include <mitkLineOperation.h>
#include <mitkPositionEvent.h>
#include <mitkMesh.h>
#include <mitkDataTreeNode.h>
#include <mitkInteractionConst.h>
#include <mitkAction.h>
#include <vtkLinearTransform.h>

//how precise must the user pick the point
//default value
const int PRECISION = 5;

mitk::ConnectPointsInteractor::ConnectPointsInteractor(const char * type, DataTreeNode* dataTreeNode, int n)
:Interactor(type, dataTreeNode), m_N(n), m_CurrentCellId(0), m_Precision(PRECISION)
{
  m_LastPoint.Fill(0);
  m_SumVec.Fill(0);
}

mitk::ConnectPointsInteractor::~ConnectPointsInteractor()
{
}

void mitk::ConnectPointsInteractor::SetPrecision(unsigned int precision)
{
  m_Precision = precision;
}

//##Documentation
//## overwritten cause this class can handle it better!
float mitk::ConnectPointsInteractor::CalculateJurisdiction(StateEvent const* stateEvent) const
{
  float returnValue = 0;

  mitk::PositionEvent const  *posEvent = dynamic_cast <const mitk::PositionEvent *> (stateEvent->GetEvent());
  //checking if a keyevent can be handled:
  if (posEvent == NULL)
  {
    //check, if the current state has a transition waiting for that key event.
    if (this->GetCurrentState()->GetTransition(stateEvent->GetId())!=NULL)
    {
      return 0.5;
    }
    else
    {
      return 0;
    }
  }

  //Mouse event handling:
  //on MouseMove do nothing! reimplement if needed differently
  if (stateEvent->GetEvent()->GetType() == mitk::Type_MouseMove)
  {
    return 0;
  }

  //check on the right data-type
  mitk::PointSet* pointSet = dynamic_cast<mitk::PointSet*>(m_DataTreeNode->GetData());
  if (pointSet == NULL)
    return 0;

  //since we now have 3D picking in GlobalInteraction and all events send are DisplayEvents with 3D information,
  //we concentrate on 3D coordinates
  mitk::Point3D worldPoint = posEvent->GetWorldPosition();
  float p[3];
  itk2vtk(worldPoint, p);
  //transforming the Worldposition to local coordinatesystem
  m_DataTreeNode->GetData()->GetGeometry()->GetVtkTransform()->GetInverse()->TransformPoint(p, p);
  vtk2itk(p, worldPoint);

  float distance = 5;
  int index = pointSet->SearchPoint(worldPoint, distance);
  if (index>-1)
    //how far away is the line from the point?
  {
    //get the point and calculate the jurisdiction out of it.
    mitk::PointSet::PointType point;
    pointSet->GetPointSet()->GetPoint(index, &point);
    returnValue = point.EuclideanDistanceTo(worldPoint);

    //between 1 and 0.     1 if directly hit
    returnValue = 1 - ( returnValue / distance );
    if (returnValue<0 || returnValue>1)
    {
      itkWarningMacro("Difficulties in calculating Jurisdiction. Check PointInteractor");
      return 0;
    }

    //and now between 0,5 and 1
    returnValue = 0.5 + (returnValue / 2);

    return returnValue;
  }
  else //not found
  {
    return 0;
  }
}

bool mitk::ConnectPointsInteractor::ExecuteAction( Action* action, mitk::StateEvent const* stateEvent )
{
  bool ok = false;//for return type bool

  //checking corresponding Data; has to be a Mesh or a subclass
  mitk::Mesh* mesh = dynamic_cast<mitk::Mesh*>(m_DataTreeNode->GetData());
  if (mesh == NULL)
    return false;

  //for reading on the points, Id's etc
  //mitk::PointSet::DataType *itkpointSet = mesh->GetPointSet();
  //mitk::PointSet::PointsContainer *points = itkpointSet->GetPoints();//Warning Fix: not used!

  /*Each case must watch the type of the event!*/
  switch (action->GetActionId())
  {
  case AcDONOTHING:
    ok = true;
    break;
  case AcADDPOINT:
    {
      mitk::DisplayPositionEvent const  *posEvent = dynamic_cast <const mitk::DisplayPositionEvent *> (stateEvent->GetEvent());
      if (posEvent == NULL)
        return false;

      mitk::Point3D worldPoint;
      worldPoint = posEvent->GetWorldPosition();

      int position = mesh->SearchPoint(worldPoint, m_Precision);
      if (position >= 0)//found a point near enough to the given point
      {
        // if the point is the last in current cell, remove it (this has to be moved in a separate action)
        bool deleteLine=false;
        if(mesh->GetMesh()->GetCells()->Size() > 0)
        {
          Mesh::CellAutoPointer cellAutoPointer;
          ok = mesh->GetMesh()->GetCell(m_CurrentCellId, cellAutoPointer);
          if(ok)
          {
            Mesh::PointIdIterator last = cellAutoPointer->PointIdsEnd();
            --last;
            int foundCell = mesh->SearchFirstCell( (unsigned long) position );
            if (foundCell != -1)//not found
              deleteLine = ((unsigned int)foundCell == m_CurrentCellId) && (*last == (unsigned int)position);
          }
        }
        if(deleteLine)
        {
          LineOperation* doOp = new mitk::LineOperation(OpDELETELINE, m_CurrentCellId, position);
          if (m_UndoEnabled)
          {
            LineOperation* undoOp = new mitk::LineOperation(OpADDLINE, m_CurrentCellId, position);
            OperationEvent *operationEvent = new OperationEvent(mesh, doOp, undoOp, "Delete line");
            m_UndoController->SetOperationEvent(operationEvent);
          }
          //execute the Operation
          mesh->ExecuteOperation(doOp );
        }
        else
        {
          // add new cell if necessary
          if(mesh->GetNewCellId() == 0) //allow single line only
            //allow multiple lines:          if((mesh->SearchFirstCell(position) >= 0) || ((m_CurrentCellId == 0) && (mesh->GetNewCellId() == 0)))
          {
            //get the next cellId and set m_CurrentCellId
            m_CurrentCellId = mesh->GetNewCellId();

            //now reserv a new cell in m_ItkData
            LineOperation* doOp = new mitk::LineOperation(OpNEWCELL, m_CurrentCellId);
            if (m_UndoEnabled)
            {
              LineOperation* undoOp = new mitk::LineOperation(OpDELETECELL, m_CurrentCellId);
              OperationEvent *operationEvent = new OperationEvent(mesh, doOp, undoOp, "Add cell");
              m_UndoController->SetOperationEvent(operationEvent);
            }
            mesh->ExecuteOperation(doOp);
          }
          // add line if point is not yet included in current cell
          if(mesh->SearchFirstCell(position) < 0)
          {
            LineOperation* doOp = new mitk::LineOperation(OpADDLINE, m_CurrentCellId, position);
            if (m_UndoEnabled)
            {
              LineOperation* undoOp = new mitk::LineOperation(OpDELETELINE, m_CurrentCellId, position);
              OperationEvent *operationEvent = new OperationEvent(mesh, doOp, undoOp, "Add line");
              m_UndoController->SetOperationEvent(operationEvent);
            }
            //execute the Operation
            mesh->ExecuteOperation(doOp );
          }
        }
      }
      ok = true;
      break;
    }
  case AcREMOVEPOINT:
    {
      //mitk::DisplayPositionEvent const  *posEvent = dynamic_cast <const mitk::DisplayPositionEvent *> (stateEvent->GetEvent());
      //if (posEvent == NULL)
      //  return false;

      //mitk::Point3D worldPoint;
      //worldPoint = posEvent->GetWorldPosition();

      //int position = mesh->SearchPoint(worldPoint, m_Precision);
      //if (position>=0)//found a point near enough to the given point
      //{
      //  // if the point is in the current cell, remove it (this has to be moved in a separate action)
      //  if(mesh->SearchFirstCell(position) == m_CurrentCellId)
      //  {
      //    LineOperation* doOp = new mitk::LineOperation(OpDELETELINE, m_CurrentCellId, position);
      //  if (m_UndoEnabled)
      //  {
      //   LineOperation* undoOp = new mitk::LineOperation(OpADDLINE, m_CurrentCellId, position);
      //   OperationEvent *operationEvent = new OperationEvent(mesh, doOp, undoOp);
      //   m_UndoController->SetOperationEvent(operationEvent);
      //  }
      //  //execute the Operation
      //    mesh->ExecuteOperation(doOp );
      //  }
      //}
      ok = true;
      break;
    }
  case AcCHECKELEMENT:
    /*checking if the Point transmitted is close enough to one point. Then generate a new event with the point and let this statemaschine handle the event.*/
    {
      mitk::DisplayPositionEvent const  *posEvent = dynamic_cast <const mitk::DisplayPositionEvent *> (stateEvent->GetEvent());
      if (posEvent != NULL)
      {
        mitk::Point3D worldPoint = posEvent->GetWorldPosition();

        int position = mesh->SearchPoint(worldPoint, m_Precision);
        if (position>=0)//found a point near enough to the given point
        {
          PointSet::PointType pt = mesh->GetPoint(position);//get that point, the one meant by the user!
          mitk::Point2D displPoint;
          displPoint[0] = worldPoint[0]; displPoint[1] = worldPoint[1];
          //new Event with information YES and with the correct point
          mitk::PositionEvent const* newPosEvent = new mitk::PositionEvent(posEvent->GetSender(), Type_None, BS_NoButton, BS_NoButton, Key_none, displPoint, pt);
          mitk::StateEvent* newStateEvent = new mitk::StateEvent(EIDYES, newPosEvent);
          //call HandleEvent to leave the guard-state
          this->HandleEvent( newStateEvent );
          ok = true;
        }
        else
        {
          //new Event with information NO
          mitk::StateEvent* newStateEvent = new mitk::StateEvent(EIDNO, posEvent);
          this->HandleEvent(newStateEvent );
          ok = true;
        }
      }
      else
      {
        mitk::DisplayPositionEvent const  *disPosEvent = dynamic_cast <const mitk::DisplayPositionEvent *> (stateEvent->GetEvent());
        if (disPosEvent != NULL)
        {//2d Koordinates for 3D Interaction; return false to redo the last statechange
          mitk::StateEvent* newStateEvent = new mitk::StateEvent(EIDNO, posEvent);
          this->HandleEvent(newStateEvent );
          ok = true;
        }
      }
      break;
    }
  case AcCHECKNMINUS1://generate Events if the set will be full after the addition of the point or not.
    {
      if (m_N<0)//number of points not limited->pass on "Amount of points in Set is smaller then N-1"
      {
        mitk::StateEvent* newStateEvent = new mitk::StateEvent(EIDSTSMALERNMINUS1, stateEvent->GetEvent());
        this->HandleEvent( newStateEvent );
        ok = true;
      }
      else
      {
        if (mesh->GetSize()<(m_N-1))
          //pointset after addition won't be full
        {
          mitk::StateEvent* newStateEvent = new mitk::StateEvent(EIDSTSMALERNMINUS1, stateEvent->GetEvent());
          this->HandleEvent( newStateEvent );
          ok = true;
        }
        else //(mesh->GetSize()>=(m_N-1))
          //after the addition of a point, the container will be full
        {
          mitk::StateEvent* newStateEvent = new mitk::StateEvent(EIDSTLARGERNMINUS1, stateEvent->GetEvent());
          this->HandleEvent(newStateEvent );
          ok = true;
        }//else
      }//else
    }
    break;
  case AcCHECKEQUALS1:
    {
      if (mesh->GetSize()<=1)//the number of points in the list is 1 (or smaler)
      {
        mitk::StateEvent* newStateEvent = new mitk::StateEvent(EIDYES, stateEvent->GetEvent());
        this->HandleEvent( newStateEvent );
        ok = true;
      }
      else //more than 1 points in list, so stay in the state!
      {
        mitk::StateEvent* newStateEvent = new mitk::StateEvent(EIDNO, stateEvent->GetEvent());
        this->HandleEvent(newStateEvent );
        ok = true;
      }
    }
    break;
  default:
    return Superclass::ExecuteAction( action, stateEvent );
    //mitk::StatusBar::DisplayText("Message from mitkConnectPointsInteractor: I do not understand the Action!", 10000);
    //ok = false;
    //a false here causes the statemachine to undo its last statechange.
    //otherwise it will end up in a different state, but without done Action.
    //if a transition really has no Action, than call donothing
  }

  return ok;
}
<|endoftext|>