IFACEMETHODIMP RP_ShellIconOverlayIdentifier::GetPriority(_Out_ int *pPriority)

/***************************************************************************
 * ROM Properties Page shell extension. (Win32)                            *
 * RP_ShellIconOverlayIdentifier.cpp: IShellIconOverlayIdentifier          *
 *                                                                         *
 ***************************************************************************/

#include "stdafx.h"
#include "RP_ShellIconOverlayIdentifier.hpp"
#include "res/resource.h"

// librpbase, librpfile, libromdata
using namespace LibRpBase;
using namespace LibRpFile;
using LibRomData::RomDataFactory;

// from DllMain.cpp
extern "C" {
	extern TCHAR dll_filename[];
}

using std::string;

// CLSID
const CLSID CLSID_RP_ShellIconOverlayIdentifier =
	{0x02c6Af01, 0x3c99, 0x497d, {0xb3, 0xfc, 0xe3, 0x8c, 0xe5, 0x26, 0x78, 0x6b}};

/** RP_ShellIconOverlayIdentifier_Private **/
#include "RP_ShellIconOverlayIdentifier_p.hpp"

// FIXME: Crashing when scrolling through %TEMP%...

RP_ShellIconOverlayIdentifier_Private::RP_ShellIconOverlayIdentifier_Private()
#if 0
	: romData(nullptr)
#endif
	: hShell32_dll(nullptr)
	, pfnSHGetStockIconInfo(nullptr)
{
	hShell32_dll = LoadLibrary(_T("shell32.dll"));
	if (hShell32_dll) {
		pfnSHGetStockIconInfo = (PFNSHGETSTOCKICONINFO)GetProcAddress(hShell32_dll, "SHGetStockIconInfo");
	}
}

RP_ShellIconOverlayIdentifier_Private::~RP_ShellIconOverlayIdentifier_Private()
{
	if (hShell32_dll) {
		FreeLibrary(hShell32_dll);
	}
}

/** RP_PropertyStore **/

RP_ShellIconOverlayIdentifier::RP_ShellIconOverlayIdentifier()
	: d_ptr(new RP_ShellIconOverlayIdentifier_Private())
{ }

RP_ShellIconOverlayIdentifier::~RP_ShellIconOverlayIdentifier()
{
	delete d_ptr;
}

/** IUnknown **/

IFACEMETHODIMP RP_ShellIconOverlayIdentifier::QueryInterface(_In_ REFIID riid, _Outptr_ LPVOID *ppvObj)
{
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable: 4365 4838)
#endif /* _MSC_VER */
	static const QITAB rgqit[] = {
		QITABENT(RP_ShellIconOverlayIdentifier, IShellIconOverlayIdentifier),
		{ 0, 0 }
	};
#ifdef _MSC_VER
# pragma warning(pop)
#endif /* _MSC_VER */
	return LibWin32Common::rp_QISearch(this, rgqit, riid, ppvObj);
}

/** IShellIconOverlayIdentifier **/

IFACEMETHODIMP RP_ShellIconOverlayIdentifier::IsMemberOf(_In_ PCWSTR pwszPath, DWORD dwAttrib)
{
	if (!pwszPath) {
		return E_POINTER;
	}

	const Config *const config = Config::instance();
	if (!config->showDangerousPermissionsOverlayIcon()) {
		// Overlay icon is disabled.
		return S_FALSE;
	}

	// Don't check the file if it's "slow", unavailable, or a directory.
	if (dwAttrib & (SFGAO_ISSLOW | SFGAO_GHOSTED | SFGAO_FOLDER)) {
		// Don't bother checking this file.
		return S_FALSE;
	}

	// Convert the filename to UTF-8.
	const string u8filename = W2U8(pwszPath);

	// TODO: Combine with the above "slow" check?
	if (FileSystem::isOnBadFS(u8filename.c_str(),
	    config->enableThumbnailOnNetworkFS()))
	{
		// This file is on a "bad" file system.
		return S_FALSE;
	}

	// Open the ROM file.
	RpFile *const file = new RpFile(u8filename.c_str(), RpFile::FM_OPEN_READ_GZ);
	if (!file->isOpen()) {
		// Error opening the ROM file.
		file->unref();
		return E_FAIL;
	}

	// Attempt to create a RomData object.
	RomData *const romData = RomDataFactory::create(file, RomDataFactory::RDA_HAS_DPOVERLAY);
	file->unref();
	if (!romData) {
		// ROM is not supported.
		return S_FALSE;
	}

	HRESULT hr = (romData->hasDangerousPermissions() ? S_OK : S_FALSE);
	romData->unref();
	return hr;
}

IFACEMETHODIMP RP_ShellIconOverlayIdentifier::GetOverlayInfo(_Out_writes_(cchMax) PWSTR pwszIconFile, int cchMax, _Out_ int *pIndex, _Out_ DWORD *pdwFlags)
{
	if (!pwszIconFile || !pIndex || !pdwFlags) {
		return E_POINTER;
	} else if (cchMax < 1) {
		return E_INVALIDARG;
	}

	// Get the "dangerous" permissions overlay.
	HRESULT hr;

	RP_D(const RP_ShellIconOverlayIdentifier);
	if (d->pfnSHGetStockIconInfo) {
		// FIXME: Icon size is a bit too large in some cases.
		SHSTOCKICONINFO sii;
		sii.cbSize = sizeof(sii);
		hr = d->pfnSHGetStockIconInfo(SIID_SHIELD, SHGSI_ICONLOCATION, &sii);
		if (SUCCEEDED(hr)) {
			// Copy the returned filename and index.
			wcscpy_s(pwszIconFile, cchMax, sii.szPath);
			*pIndex = sii.iIcon;
			*pdwFlags = ISIOI_ICONFILE | ISIOI_ICONINDEX;
		} else {
			// Unable to get the filename.
			pwszIconFile[0] = L'\0';
			*pIndex = 0;
			*pdwFlags = 0;
		}
	} else {
		// Use our own shield icon.
		// Based on Windows 7's shield icon from imageres.dll.
		// FIXME: Windows XP requires the overlay icon to be the
		// same size as the regular icon, but with transparency.
		hr = E_FAIL;
#if 0
		wcscpy_s(pwszIconFile, cchMax, dll_filename);
		*pIndex = -IDI_SHIELD;
		*pdwFlags = ISIOI_ICONFILE | ISIOI_ICONINDEX;

		// Assume we're successful.
		hr = S_OK;
#endif
	}

	return hr;
}

{
	if (!pPriority) {
		return E_POINTER;
	}

	const Config *const config = Config::instance();
	if (!config->showDangerousPermissionsOverlayIcon()) {
		// Overlay icon is disabled.
		return S_FALSE;
	}

	// Use the higest priority for the UAC icon.
	*pPriority = 0;
	return S_OK;
}


/***************************************************************************
 * ROM Properties Page shell extension. (Win32)                            *
 * RP_ShellIconOverlayIdentifier.cpp: IShellIconOverlayIdentifier          *
 *                                                                         *
 ***************************************************************************/

#include "stdafx.h"
#include "RP_ShellIconOverlayIdentifier.hpp"
#include "res/resource.h"

// librpbase, librpfile, libromdata
using namespace LibRpBase;
using namespace LibRpFile;
using LibRomData::RomDataFactory;

// from DllMain.cpp
extern "C" {
	extern TCHAR dll_filename[];
}

using std::string;

// CLSID
const CLSID CLSID_RP_ShellIconOverlayIdentifier =
	{0x02c6Af01, 0x3c99, 0x497d, {0xb3, 0xfc, 0xe3, 0x8c, 0xe5, 0x26, 0x78, 0x6b}};

/** RP_ShellIconOverlayIdentifier_Private **/
#include "RP_ShellIconOverlayIdentifier_p.hpp"

// FIXME: Crashing when scrolling through %TEMP%...

RP_ShellIconOverlayIdentifier_Private::RP_ShellIconOverlayIdentifier_Private()
#if 0
	: romData(nullptr)
#endif
	: hShell32_dll(nullptr)
	, pfnSHGetStockIconInfo(nullptr)
{
	hShell32_dll = LoadLibrary(_T("shell32.dll"));
	if (hShell32_dll) {
		pfnSHGetStockIconInfo = (PFNSHGETSTOCKICONINFO)GetProcAddress(hShell32_dll, "SHGetStockIconInfo");
	}
}

RP_ShellIconOverlayIdentifier_Private::~RP_ShellIconOverlayIdentifier_Private()
{
	if (hShell32_dll) {
		FreeLibrary(hShell32_dll);
	}
}

/** RP_PropertyStore **/

RP_ShellIconOverlayIdentifier::RP_ShellIconOverlayIdentifier()
	: d_ptr(new RP_ShellIconOverlayIdentifier_Private())

RP_ShellIconOverlayIdentifier::~RP_ShellIconOverlayIdentifier()
{
	delete d_ptr;
}

/** IUnknown **/

IFACEMETHODIMP RP_ShellIconOverlayIdentifier::QueryInterface(_In_ REFIID riid, _Outptr_ LPVOID *ppvObj)
{
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable: 4365 4838)
#endif /* _MSC_VER */
	static const QITAB rgqit[] = {
		QITABENT(RP_ShellIconOverlayIdentifier, IShellIconOverlayIdentifier),
		{ 0, 0 }
	};
#ifdef _MSC_VER
# pragma warning(pop)
#endif /* _MSC_VER */
	return LibWin32Common::rp_QISearch(this, rgqit, riid, ppvObj);
}

/** IShellIconOverlayIdentifier **/

IFACEMETHODIMP RP_ShellIconOverlayIdentifier::IsMemberOf(_In_ PCWSTR pwszPath, DWORD dwAttrib)
{
	if (!pwszPath) {
		return E_POINTER;
	}

	const Config *const config = Config::instance();
	if (!config->showDangerousPermissionsOverlayIcon()) {
		// Overlay icon is disabled.
		return S_FALSE;
	}

	// Don't check the file if it's "slow", unavailable, or a directory.
	if (dwAttrib & (SFGAO_ISSLOW | SFGAO_GHOSTED | SFGAO_FOLDER)) {
		// Don't bother checking this file.
		return S_FALSE;
	}

	// Convert the filename to UTF-8.
	const string u8filename = W2U8(pwszPath);

	// TODO: Combine with the above "slow" check?
	if (FileSystem::isOnBadFS(u8filename.c_str(),
	    config->enableThumbnailOnNetworkFS()))
	{
		// This file is on a "bad" file system.
		return S_FALSE;
	}

	// Open the ROM file.
	RpFile *const file = new RpFile(u8filename.c_str(), RpFile::FM_OPEN_READ_GZ);
	if (!file->isOpen()) {
		// Error opening the ROM file.
		file->unref();
		return E_FAIL;
	}

	// Attempt to create a RomData object.
	RomData *const romData = RomDataFactory::create(file, RomDataFactory::RDA_HAS_DPOVERLAY);
	file->unref();
	if (!romData) {
		// ROM is not supported.
		return S_FALSE;
	}

	HRESULT hr = (romData->hasDangerousPermissions() ? S_OK : S_FALSE);
	romData->unref();
	return hr;
}

IFACEMETHODIMP RP_ShellIconOverlayIdentifier::GetOverlayInfo(_Out_writes_(cchMax) PWSTR pwszIconFile, int cchMax, _Out_ int *pIndex, _Out_ DWORD *pdwFlags)
{
	if (!pwszIconFile || !pIndex || !pdwFlags) {
		return E_POINTER;
	} else if (cchMax < 1) {
		return E_INVALIDARG;
	}

	// Get the "dangerous" permissions overlay.
	HRESULT hr;

	RP_D(const RP_ShellIconOverlayIdentifier);
	if (d->pfnSHGetStockIconInfo) {
		// FIXME: Icon size is a bit too large in some cases.
		SHSTOCKICONINFO sii;
		sii.cbSize = sizeof(sii);
		hr = d->pfnSHGetStockIconInfo(SIID_SHIELD, SHGSI_ICONLOCATION, &sii);
		if (SUCCEEDED(hr)) {
			// Copy the returned filename and index.
			wcscpy_s(pwszIconFile, cchMax, sii.szPath);
			*pIndex = sii.iIcon;
			*pdwFlags = ISIOI_ICONFILE | ISIOI_ICONINDEX;
		} else {
			// Unable to get the filename.
			pwszIconFile[0] = L'\0';
			*pIndex = 0;
			*pdwFlags = 0;
		}
	} else {
		// Use our own shield icon.
		// Based on Windows 7's shield icon from imageres.dll.
		// FIXME: Windows XP requires the overlay icon to be the
		// same size as the regular icon, but with transparency.
		hr = E_FAIL;
#if 0
		wcscpy_s(pwszIconFile, cchMax, dll_filename);
		*pIndex = -IDI_SHIELD;
		*pdwFlags = ISIOI_ICONFILE | ISIOI_ICONINDEX;

		// Assume we're successful.
		hr = S_OK;
#endif
	}

	return hr;
}

IFACEMETHODIMP RP_ShellIconOverlayIdentifier::GetPriority(_Out_ int *pPriority)
{
	if (!pPriority) {
		return E_POINTER;
	}

	const Config *const config = Config::instance();
	if (!config->showDangerousPermissionsOverlayIcon()) {
		// Overlay icon is disabled.
		return S_FALSE;
	}

	// Use the higest priority for the UAC icon.
	*pPriority = 0;
	return S_OK;
}


/***************************************************************************
 * ROM Properties Page shell extension. (Win32)                            *
 * RP_ShellIconOverlayIdentifier.cpp: IShellIconOverlayIdentifier          *
 *                                                                         *
 ***************************************************************************/

#include "stdafx.h"
#include "RP_ShellIconOverlayIdentifier.hpp"
#include "res/resource.h"

// librpbase, librpfile, libromdata
using namespace LibRpBase;
using namespace LibRpFile;
using LibRomData::RomDataFactory;

// from DllMain.cpp
extern "C" {
	extern TCHAR dll_filename[];
}

using std::string;

// CLSID
const CLSID CLSID_RP_ShellIconOverlayIdentifier =
	{0x02c6Af01, 0x3c99, 0x497d, {0xb3, 0xfc, 0xe3, 0x8c, 0xe5, 0x26, 0x78, 0x6b}};

/** RP_ShellIconOverlayIdentifier_Private **/
#include "RP_ShellIconOverlayIdentifier_p.hpp"

// FIXME: Crashing when scrolling through %TEMP%...

RP_ShellIconOverlayIdentifier_Private::RP_ShellIconOverlayIdentifier_Private()
#if 0
	: romData(nullptr)
#endif
	: hShell32_dll(nullptr)
	, pfnSHGetStockIconInfo(nullptr)
{
	hShell32_dll = LoadLibrary(_T("shell32.dll"));
	if (hShell32_dll) {
		pfnSHGetStockIconInfo = (PFNSHGETSTOCKICONINFO)GetProcAddress(hShell32_dll, "SHGetStockIconInfo");
	}
}

RP_ShellIconOverlayIdentifier_Private::~RP_ShellIconOverlayIdentifier_Private()
{
	if (hShell32_dll) {
		FreeLibrary(hShell32_dll);
	}
}

/** RP_PropertyStore **/

RP_ShellIconOverlayIdentifier::RP_ShellIconOverlayIdentifier()
	: d_ptr(new RP_ShellIconOverlayIdentifier_Private())
{ }

RP_ShellIconOverlayIdentifier::~RP_ShellIconOverlayIdentifier()
{
	delete d_ptr;
}

/** IUnknown **/

IFACEMETHODIMP RP_ShellIconOverlayIdentifier::QueryInterface(_In_ REFIID riid, _Outptr_ LPVOID *ppvObj)
{
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable: 4365 4838)
#endif /* _MSC_VER */
	static const QITAB rgqit[] = {
		QITABENT(RP_ShellIconOverlayIdentifier, IShellIconOverlayIdentifier),
		{ 0, 0 }
	};
#ifdef _MSC_VER
# pragma warning(pop)
#endif /* _MSC_VER */
	return LibWin32Common::rp_QISearch(this, rgqit, riid, ppvObj);
}

/** IShellIconOverlayIdentifier **/

IFACEMETHODIMP RP_ShellIconOverlayIdentifier::IsMemberOf(_In_ PCWSTR pwszPath, DWORD dwAttrib)
{
	if (!pwszPath) {
		return E_POINTER;
	}

	const Config *const config = Config::instance();
	if (!config->showDangerousPermissionsOverlayIcon()) {
		// Overlay icon is disabled.
		return S_FALSE;
	}

	// Don't check the file if it's "slow", unavailable, or a directory.
	if (dwAttrib & (SFGAO_ISSLOW | SFGAO_GHOSTED | SFGAO_FOLDER)) {
		// Don't bother checking this file.
		return S_FALSE;
	}

	// Convert the filename to UTF-8.
	const string u8filename = W2U8(pwszPath);

	// TODO: Combine with the above "slow" check?
	if (FileSystem::isOnBadFS(u8filename.c_str(),
	    config->enableThumbnailOnNetworkFS()))
	{
		// This file is on a "bad" file system.
		return S_FALSE;
	}

	// Open the ROM file.
	RpFile *const file = new RpFile(u8filename.c_str(), RpFile::FM_OPEN_READ_GZ);
	if (!file->isOpen()) {
		// Error opening the ROM file.
		file->unref();
		return E_FAIL;
	}

	// Attempt to create a RomData object.
	RomData *const romData = RomDataFactory::create(file, RomDataFactory::RDA_HAS_DPOVERLAY);
	file->unref();
	if (!romData) {
		// ROM is not supported.
		return S_FALSE;
	}

	HRESULT hr = (romData->hasDangerousPermissions() ? S_OK : S_FALSE);
	romData->unref();
	return hr;
}

IFACEMETHODIMP RP_ShellIconOverlayIdentifier::GetOverlayInfo(_Out_writes_(cchMax) PWSTR pwszIconFile, int cchMax, _Out_ int *pIndex, _Out_ DWORD *pdwFlags)
{
	if (!pwszIconFile || !pIndex || !pdwFlags) {
		return E_POINTER;
	} else if (cchMax < 1) {
		return E_INVALIDARG;
	}

	// Get the "dangerous" permissions overlay.
	HRESULT hr;

	RP_D(const RP_ShellIconOverlayIdentifier);
	if (d->pfnSHGetStockIconInfo) {
		// FIXME: Icon size is a bit too large in some cases.
		SHSTOCKICONINFO sii;
		sii.cbSize = sizeof(sii);
		hr = d->pfnSHGetStockIconInfo(SIID_SHIELD, SHGSI_ICONLOCATION, &sii);
		if (SUCCEEDED(hr)) {
			// Copy the returned filename and index.
			wcscpy_s(pwszIconFile, cchMax, sii.szPath);
			*pIndex = sii.iIcon;
			*pdwFlags = ISIOI_ICONFILE | ISIOI_ICONINDEX;
		} else {
			// Unable to get the filename.
			pwszIconFile[0] = L'\0';
			*pIndex = 0;
			*pdwFlags = 0;
		}
	} else {
		// Use our own shield icon.
		// Based on Windows 7's shield icon from imageres.dll.
		// FIXME: Windows XP requires the overlay icon to be the
		// same size as the regular icon, but with transparency.
		hr = E_FAIL;
#if 0
		wcscpy_s(pwszIconFile, cchMax, dll_filename);
		*pIndex = -IDI_SHIELD;
		*pdwFlags = ISIOI_ICONFILE | ISIOI_ICONINDEX;

		// Assume we're successful.
		hr = S_OK;
#endif
	}

	return hr;
}

IFACEMETHODIMP RP_ShellIconOverlayIdentifier::GetPriority(_Out_ int *pPriority)
{
	if (!pPriority) {
		return E_POINTER;
	}

	const Config *const config = Config::instance();
	if (!config->showDangerousPermissionsOverlayIcon()) {
		// Overlay icon is disabled.
		return S_FALSE;
	}

	// Use the higest priority for the UAC icon.
	*pPrio


RP_ShellIconOverlayIdentifier::RP_ShellIconOverlayIdentifier()
	: d_ptr(new RP_ShellIconOverlayIdentifier_Private())
{ }

/***************************************************************************
 * ROM Properties Page shell extension. (Win32)                            *
 * RP_ShellIconOverlayIdentifier.cpp: IShellIconOverlayIdentifier          *
 *                                                                         *
 ***************************************************************************/

#include "stdafx.h"
#include "RP_ShellIconOverlayIdentifier.hpp"
#include "res/resource.h"

// librpbase, librpfile, libromdata
using namespace LibRpBase;
using namespace LibRpFile;
using LibRomData::RomDataFactory;

// from DllMain.cpp
extern "C" {
	extern TCHAR dll_filename[];
}

using std::string;

// CLSID
const CLSID CLSID_RP_ShellIconOverlayIdentifier =
	{0x02c6Af01, 0x3c99, 0x497d, {0xb3, 0xfc, 0xe3, 0x8c, 0xe5, 0x26, 0x78, 0x6b}};

/** RP_ShellIconOverlayIdentifier_Private **/
#include "RP_ShellIconOverlayIdentifier_p.hpp"

// FIXME: Crashing when scrolling through %TEMP%...

RP_ShellIconOverlayIdentifier_Private::RP_ShellIconOverlayIdentifier_Private()
#if 0
	: romData(nullptr)
#endif
	: hShell32_dll(nullptr)
	, pfnSHGetStockIconInfo(nullptr)
{
	hShell32_dll = LoadLibrary(_T("shell32.dll"));
	if (hShell32_dll) {
		pfnSHGetStockIconInfo = (PFNSHGETSTOCKICONINFO)GetProcAddress(hShell32_dll, "SHGetStockIconInfo");
	}
}

RP_ShellIconOverlayIdentifier_Private::~RP_ShellIconOverlayIdentifier_Private()
{
	if (hShell32_dll) {
		FreeLibrary(hShell32_dll);
	}
}

/** RP_PropertyStore **/


if (!pwszIconFile || !pIndex || !pdwFlags) {
		return E_POINTER;
	} else if (cchMax < 1) {
		return E_INVALIDARG;
	}

/***************************************************************************
 * ROM Properties Page shell extension. (Win32)                            *
 * RP_ShellIconOverlayIdentifier.cpp: IShellIconOverlayIdentifier          *
 *                                                                         *
 ***************************************************************************/

#include "stdafx.h"
#include "RP_ShellIconOverlayIdentifier.hpp"
#include "res/resource.h"

// librpbase, librpfile, libromdata
using namespace LibRpBase;
using namespace LibRpFile;
using LibRomData::RomDataFactory;

// from DllMain.cpp
extern "C" {
	extern TCHAR dll_filename[];
}

using std::string;

// CLSID
const CLSID CLSID_RP_ShellIconOverlayIdentifier =
	{0x02c6Af01, 0x3c99, 0x497d, {0xb3, 0xfc, 0xe3, 0x8c, 0xe5, 0x26, 0x78, 0x6b}};

/** RP_ShellIconOverlayIdentifier_Private **/
#include "RP_ShellIconOverlayIdentifier_p.hpp"

// FIXME: Crashing when scrolling through %TEMP%...

RP_ShellIconOverlayIdentifier_Private::RP_ShellIconOverlayIdentifier_Private()
#if 0
	: romData(nullptr)
#endif
	: hShell32_dll(nullptr)
	, pfnSHGetStockIconInfo(nullptr)
{
	hShell32_dll = LoadLibrary(_T("shell32.dll"));
	if (hShell32_dll) {
		pfnSHGetStockIconInfo = (PFNSHGETSTOCKICONINFO)GetProcAddress(hShell32_dll, "SHGetStockIconInfo");
	}
}

RP_ShellIconOverlayIdentifier_Private::~RP_ShellIconOverlayIdentifier_Private()
{
	if (hShell32_dll) {
		FreeLibrary(hShell32_dll);
	}
}

/** RP_PropertyStore **/

RP_ShellIconOverlayIdentifier::RP_ShellIconOverlayIdentifier()
	: d_ptr(new RP_ShellIconOverlayIdentifier_Private())
{ }

RP_ShellIconOverlayIdentifier::~RP_ShellIconOverlayIdentifier()
{
	delete d_ptr;
}

/** IUnknown **/

IFACEMETHODIMP RP_ShellIconOverlayIdentifier::QueryInterface(_In_ REFIID riid, _Outptr_ LPVOID *ppvObj)
{
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable: 4365 4838)
#endif /* _MSC_VER */
	static const QITAB rgqit[] = {
		QITABENT(RP_ShellIconOverlayIdentifier, IShellIconOverlayIdentifier),
		{ 0, 0 }
	};
#ifdef _MSC_VER
# pragma warning(pop)
#endif /* _MSC_VER */
	return LibWin32Common::rp_QISearch(this, rgqit, riid, ppvObj);
}

/** IShellIconOverlayIdentifier **/

IFACEMETHODIMP RP_ShellIconOverlayIdentifier::IsMemberOf(_In_ PCWSTR pwszPath, DWORD dwAttrib)
{
	if (!pwszPath) {
		return E_POINTER;
	}

	const Config *const config = Config::instance();
	if (!config->showDangerousPermissionsOverlayIcon()) {
		// Overlay icon is disabled.
		return S_FALSE;
	}

	// Don't check the file if it's "slow", unavailable, or a directory.
	if (dwAttrib & (SFGAO_ISSLOW | SFGAO_GHOSTED | SFGAO_FOLDER)) {
		// Don't bother checking this file.
		return S_FALSE;
	}

	// Convert the filename to UTF-8.
	const string u8filename = W2U8(pwszPath);

	// TODO: Combine with the above "slow" check?
	if (FileSystem::isOnBadFS(u8filename.c_str(),
	    config->enableThumbnailOnNetworkFS()))
	{
		// This file is on a "bad" file system.
		return S_FALSE;
	}

	// Open the ROM file.
	RpFile *const file = new RpFile(u8filename.c_str(), RpFile::FM_OPEN_READ_GZ);
	if (!file->isOpen()) {
		// Error opening the ROM file.
		file->unref();
		return E_FAIL;
	}

	// Attempt to create a RomData object.
	RomData *const romData = RomDataFactory::create(file, RomDataFactory::RDA_HAS_DPOVERLAY);
	file->unref();
	if (!romData) {
		// ROM is not supported.
		return S_FALSE;
	}

	HRESULT hr = (romData->hasDangerousPermissions() ? S_OK : S_FALSE);
	romData->unref();
	return hr;
}

IFACEMETHODIMP RP_ShellIconOverlayIdentifier::GetOverlayInfo(_Out_writes_(cchMax) PWSTR pwszIconFile, int cchMax, _Out_ int *pIndex, _Out_ DWORD *pdwFlags)
{

	// Get the "dangerous" permissions overlay.
	HRESULT hr;

	RP_D(const RP_ShellIconOverlayIdentifier);
	if (d->pfnSHGetStockIconInfo) {
		// FIXME: Icon size is a bit too large in some cases.
		SHSTOCKICONINFO sii;
		sii.cbSize = sizeof(sii);
		hr = d->pfnSHGetStockIconInfo(SIID_SHIELD, SHGSI_ICONLOCATION, &sii);
		if (SUCCEEDED(hr)) {
			// Copy the returned filename and index.
			wcscpy_s(pwszIconFile, cchMax, sii.szPath);
			*pIndex = sii.iIcon;
			*pdwFlags = ISIOI_ICONFILE | ISIOI_ICONINDEX;
		} else {
			// Unable to get the filename.
			pwszIconFile[0] = L'\0';
			*pIndex = 0;
			*pdwFlags = 0;
		}
	} else {
		// Use our own shield icon.
		// Based on Windows 7's shield icon from imageres.dll.
		// FIXME: Windows XP requires the overlay icon to be the
		// same size as the regular icon, but with transparency.
		hr = E_FAIL;
#if 0
		wcscpy_s(pwszIconFile, cchMax, dll_filename);
		*pIndex = -IDI_SHIELD;
		*pdwFlags = ISIOI_ICONFILE | ISIOI_ICONINDEX;

		// Assume we're successful.
		hr = S_OK;
#endif
	}

	return hr;
}

IFACEMETHODIMP RP_ShellIconOverlayIdentifier::GetPriority(_Out_ int *pPriority)
{
	if (!pPriority) {
		return E_POINTER;
	}

	const Config *const config = Config::instance();
	if (!config->showDangerousPermissionsOverlayIcon()) {
		// Overlay icon is disabled.
		return S_FALSE;
	}

	// Use the higest priority for the UAC icon.
	*pPriority = 0;
	return S_OK;
}


/*
 *   RapCAD - Rapid prototyping CAD IDE (www.rapcad.org)
 *
 */

#include "normalsnode.h"


/*
 *   RapCAD - Rapid prototyping CAD IDE (www.rapcad.org)
 *
 */

#include "normalsnode.h"

void NormalsNode::accept(NodeVisitor& v)


/*
 *   RapCAD - Rapid prototyping CAD IDE (www.rapcad.org)
 *
 */

#include "normalsnode.h"

void NormalsNode::accept(NodeVisitor& v)
{
	v.visit(


// Name:        src/os2/statbox.cpp
// Purpose:     wxStaticBox
// Author:      David Webster
// Modified by:

// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"

#include "wx/statbox.h"

#ifndef WX_PRECOMP
    #include "wx/app.h"
    #include "wx/dcclient.h"
    #include "wx/window.h"
#endif

#include "wx/os2/private.h"

bool wxStaticBox::Create( wxWindow*       pParent,
                          wxWindowID      vId,
                          const wxString& rsLabel,
                          const wxPoint&  rPos,
                          const wxSize&   rSize,
                          long            lStyle,
                          const wxString& rsName )
{
    if(!CreateControl( pParent
                      ,vId
                      ,rPos
                      ,rSize
                      ,lStyle
                      ,wxDefaultValidator
                      ,rsName
                     ))
    {
        return false;
    }

    wxPoint  vPos(0,0);
    wxSize   vSize(0,0);

    if (!OS2CreateControl( wxT("STATIC")
                          ,SS_GROUPBOX
                          ,vPos
                          ,vSize
                          ,rsLabel
                         ))
    {
        return false;
    }

    // To be transparent we should have the same colour as the parent as well
    SetBackgroundColour(GetParent()->GetBackgroundColour());

    LONG lColor = (LONG)wxBLACK->GetPixel();
    ::WinSetPresParam( m_hWnd
                      ,PP_FOREGROUNDCOLOR
                      ,sizeof(LONG)
                      ,(PVOID)&lColor
                     );

    lColor = (LONG)m_backgroundColour.GetPixel();
    ::WinSetPresParam( m_hWnd
                      ,PP_BACKGROUNDCOLOR
                      ,sizeof(LONG)
                      ,(PVOID)&lColor
                     );
    SetSize( rPos.x
            ,rPos.y
            ,rSize.x
            ,rSize.y
           );
    return true;
} // end of wxStaticBox::Create

{
    int                             nCx;
    int                             nCy;
    int                             wBox;

    nCx = GetCharWidth();
    nCy = GetCharHeight();
    GetTextExtent( wxGetWindowText(m_hWnd)
                  ,&wBox
                  ,NULL
                 );
    wBox += 3 * nCx;

    int                             hBox = EDIT_HEIGHT_FROM_CHAR_HEIGHT(nCy);

    return wxSize( wBox
                  ,hBox
                 );
} // end of wxStaticBox::DoGetBestSize

MRESULT wxStaticBox::OS2WindowProc( WXUINT    nMsg,
                                    WXWPARAM  wParam,
                                    WXLPARAM  lParam )
{
    return wxControl::OS2WindowProc(nMsg, wParam, lParam);
} // end of wxStaticBox::OS2WindowProc


{
    int                             nCx;
    int                             nCy;
    int                             wBox;

    nCx = GetCharWidth();
    nCy = GetCharHeight();
    GetTextExtent( wxGetWindowText(m_hWnd)
                  ,&wBox
                  ,NULL
                 );
    wBox += 3 * nCx;

    int                             hBox = EDIT_HEIGHT_FROM_CHAR_HEIGHT(nCy);

    return wxSize( wBox
                  ,hBox
                 );
}

// Name:        src/os2/statbox.cpp
// Purpose:     wxStaticBox
// Author:      David Webster
// Modified by:

// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"

#include "wx/statbox.h"

#ifndef WX_PRECOMP
    #include "wx/app.h"
    #include "wx/dcclient.h"
    #include "wx/window.h"
#endif

#include "wx/os2/private.h"

bool wxStaticBox::Create( wxWindow*       pParent,
                          wxWindowID      vId,
                          const wxString& rsLabel,
                          const wxPoint&  rPos,
                          const wxSize&   rSize,
                          long            lStyle,
                          const wxString& rsName )
{
    if(!CreateControl( pParent
                      ,vId
                      ,rPos
                      ,rSize
                      ,lStyle
                      ,wxDefaultValidator
                      ,rsName
                     ))
    {
        return false;
    }

    wxPoint  vPos(0,0);
    wxSize   vSize(0,0);

    if (!OS2CreateControl( wxT("STATIC")
                          ,SS_GROUPBOX
                          ,vPos
                          ,vSize
                          ,rsLabel
                         ))
    {
        return false;
    }

    // To be transparent we should have the same colour as the parent as well
    SetBackgroundColour(GetParent()->GetBackgroundColour());

    LONG lColor = (LONG)wxBLACK->GetPixel();
    ::WinSetPresParam( m_hWnd
                      ,PP_FOREGROUNDCOLOR
                      ,sizeof(LONG)
                      ,(PVOID)&lColor
                     );

    lColor = (LONG)m_backgroundColour.GetPixel();
    ::WinSetPresParam( m_hWnd
                      ,PP_BACKGROUNDCOLOR
                      ,sizeof(LONG)
                      ,(PVOID)&lColor
                     );
    SetSize( rPos.x
            ,rPos.y
            ,rSize.x
            ,rSize.y
           );
    return true;
} // end of wxStaticBox::Create

wxSize wxStaticBox::DoGetBestSize() const

 // end of wxStaticBox::DoGetBestSize

MRESULT wxStaticBox::OS2WindowProc( WXUINT    nMsg,
                                    WXWPARAM  wParam,
                                    WXLPARAM  lParam )
{
    return wxControl::OS2WindowProc(nMsg, wParam, lParam);
} // end of wxStaticBox::OS2WindowProc


// Name:        src/os2/statbox.cpp
// Purpose:     wxStaticBox
// Author:      David Webster
// Modified by:

// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"

#include "wx/statbox.h"

#ifndef WX_PRECOMP
    #include "wx/app.h"
    #include "wx/dcclient.h"
    #include "wx/window.h"
#endif

#include "wx/os2/private.h"

bool wxStaticBox::Create( wxWindow*       pParent,
                          wxWindowID      vId,
                          const wxString& rsLabel,
                          const wxPoint&  rPos,
                          const wxSize&   rSize,
                          long            lStyle,
                          const wxString& rsName )
{
    if(!CreateControl( pParent
                      ,vId
                      ,rPos
                      ,rSize
                      ,lStyle
                      ,wxDefaultValidator
                      ,rsName
                     ))
    {
        return false;
    }

    wxPoint  vPos(0,0);
    wxSize   vSize(0,0);

    if (!OS2CreateControl( wxT("STATIC")
                          ,SS_GROUPBOX
                          ,vPos
                          ,vSize
                          ,rsLabel
                         ))
    {
        return false;
    }

    // To be transparent we should have the same colour as the parent as well
    SetBackgroundColour(GetParent()->GetBackgroundColour());

    LONG lColor = (LONG)wxBLACK->GetPixel();
    ::WinSetPresParam( m_hWnd
                      ,PP_FOREGROUNDCOLOR
                      ,sizeof(LONG)
                      ,(PVOID)&lColor
                     );

    lColor =

    ::WinSetPresParam( m_hWnd
                      ,PP_BACKGROUNDCOLOR
                      ,sizeof(LONG)
                      ,(PVOID)&lColor
                     );
    SetSize( rPos.x
            ,rPos.y
            ,rSize.x
            ,rSize.y
           );
    return true;
} // end of wxStaticBox::Create

wxSize wxStaticBox::DoGetBestSize() const
{
    int                             nCx;
    int                             nCy;
    int                             wBox;

    nCx = GetCharWidth();
    nCy = GetCharHeight();
    GetTextExtent( wxGetWindowText(m_hWnd)
                  ,&wBox
                  ,NULL
                 );
    wBox += 3 * nCx;

    int                             hBox = EDIT_HEIGHT_FROM_CHAR_HEIGHT(nCy);

    return wxSize( wBox
                  ,hBox
                 );
} // end of wxStaticBox::DoGetBestSize

MRESULT wxStaticBox::OS2WindowProc( WXUINT    nMsg,
                                    WXWPARAM  wParam,
                                    WXLPARAM  lParam )
{
    return wxControl::OS2WindowProc(nMsg, wParam, lParam);
} // end of wxStaticBox::OS2WindowProc


MRESULT wxStaticBox::OS2WindowProc( WXUINT    nMsg,
                                    WXWPARAM  wParam,
                                    WXLPARAM  lParam )
{
    return wxControl::OS2WindowProc(nMsg, wParam, lParam);
}

// Name:        src/os2/statbox.cpp
// Purpose:     wxStaticBox
// Author:      David Webster
// Modified by:

// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"

#include "wx/statbox.h"

#ifndef WX_PRECOMP
    #include "wx/app.h"
    #include "wx/dcclient.h"
    #include "wx/window.h"
#endif

#include "wx/os2/private.h"

bool wxStaticBox::Create( wxWindow*       pParent,
                          wxWindowID      vId,
                          const wxString& rsLabel,
                          const wxPoint&  rPos,
                          const wxSize&   rSize,
                          long            lStyle,
                          const wxString& rsName )
{
    if(!CreateControl( pParent
                      ,vId
                      ,rPos
                      ,rSize
                      ,lStyle
                      ,wxDefaultValidator
                      ,rsName
                     ))
    {
        return false;
    }

    wxPoint  vPos(0,0);
    wxSize   vSize(0,0);

    if (!OS2CreateControl( wxT("STATIC")
                          ,SS_GROUPBOX
                          ,vPos
                          ,vSize
                          ,rsLabel
                         ))
    {
        return false;
    }

    // To be transparent we should have the same colour as the parent as well
    SetBackgroundColour(GetParent()->GetBackgroundColour());

    LONG lColor = (LONG)wxBLACK->GetPixel();
    ::WinSetPresParam( m_hWnd
                      ,PP_FOREGROUNDCOLOR
                      ,sizeof(LONG)
                      ,(PVOID)&lColor
                     );

    lColor = (LONG)m_backgroundColour.GetPixel();
    ::WinSetPresParam( m_hWnd
                      ,PP_BACKGROUNDCOLOR
                      ,sizeof(LONG)
                      ,(PVOID)&lColor
                     );
    SetSize( rPos.x
            ,rPos.y
            ,rSize.x
            ,rSize.y
           );
    return true;
} // end of wxStaticBox::Create

wxSize wxStaticBox::DoGetBestSize() const
{
    int                             nCx;
    int                             nCy;
    int                             wBox;

    nCx = GetCharWidth();
    nCy = GetCharHeight();
    GetTextExtent( wxGetWindowText(m_hWnd)
                  ,&wBox
                  ,NULL
                 );
    wBox += 3 * nCx;

    int                             hBox = EDIT_HEIGHT_FROM_CHAR_HEIGHT(nCy);

    return wxSize( wBox
                  ,hBox
                 );
} // end of wxStaticBox::DoGetBestSize


if(!CreateControl( pParent
                      ,vId
                      ,rPos
                      ,rSize
                      ,lStyle
                      ,wxDefaultValidator
                      ,rsName
                     ))
    {
        return false;
    }

// Name:        src/os2/statbox.cpp
// Purpose:     wxStaticBox
// Author:      David Webster
// Modified by:

// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"

#include "wx/statbox.h"

#ifndef WX_PRECOMP
    #include "wx/app.h"
    #include "wx/dcclient.h"
    #include "wx/window.h"
#endif

#include "wx/os2/private.h"

bool wxStaticBox::Create( wxWindow*       pParent,
                          wxWindowID      vId,
                          const wxString& rsLabel,
                          const wxPoint&  rPos,
                          const wxSize&   rSize,
                          long            lStyle,
                          const wxString& rsName )
{

    wxPoint  vPos(0,0);
    wxSize   vSize(0,0);

    if (!OS2CreateControl( wxT("STATIC")
                          ,SS_GROUPBOX
                          ,vPos
                          ,vSize
                          ,rsLabel
                         ))
    {
        return false;
    }

    // To be transparent we should have the same colour as the parent as well
    SetBackgroundColour(GetParent()->GetBackgroundColour());

    LONG lColor = (LONG)wxBLACK->GetPixel();
    ::WinSetPresParam( m_hWnd
                      ,PP_FOREGROUNDCOLOR
                      ,sizeof(LONG)
                      ,(PVOID)&lColor
                     );

    lColor = (LONG)m_backgroundColour.GetPixel();
    ::WinSetPresParam( m_hWnd
                      ,PP_BACKGROUNDCOLOR
                      ,sizeof(LONG)
                      ,(PVOID)&lColor
                     );
    SetSize( rPos.x
            ,rPos.y
            ,rSize.x
            ,rSize.y
           );
    return true;
} // end of wxStaticBox::Create

wxSize wxStaticBox::DoGetBestSize() const
{
    int                             nCx;
    int                             nCy;
    int                             wBox;

    nCx = GetCharWidth();
    nCy = GetCharHeight();
    GetTextExtent( wxGetWindowText(m_hWnd)
                  ,&wBox
                  ,NULL
                 );
    wBox += 3 * nCx;

    int                             hBox = EDIT_HEIGHT_FROM_CHAR_HEIGHT(nCy);

    return wxSize( wBox
                  ,hBox
                 );
} // end of wxStaticBox::DoGetBestSize

MRESULT wxStaticBox::OS2WindowProc( WXUINT    nMsg,
                                    WXWPARAM  wParam,
                                    WXLPARAM  lParam )
{
    return wxControl::OS2WindowProc(nMsg, wParam, lParam);
} // end of wxStaticBox::OS2WindowProc


std::string urlDecode(const std::string & src)

/*
 *
 */

#include "url-encode.hpp"

namespace libdnf {

std::string urlEncode(const std::string & src, const std::string & exclude) {
    auto noEncode = [&exclude](char ch)
    {
        if (isalnum(ch) || ch=='-' || ch == '.' || ch == '_' || ch == '~') {
            return true;
        }

        if (exclude.find(ch) != std::string::npos) {
            return true;
        }

        return false;
    };

    // compute length of encoded string
    auto len = src.length();
    for (auto ch : src) {
        if (!noEncode(ch))
            len += 2;
    }

    // encode the input string
    std::string encoded;
    encoded.reserve(len);
    for (auto ch : src) {
        if (noEncode(ch))
            encoded.push_back(ch);
        else {
            encoded.push_back('%');
            unsigned char hex;
            hex = static_cast<unsigned char>(ch) >> 4;
            hex += hex <= 9 ? '0' : 'a' - 10;
            encoded.push_back(hex);
            hex = static_cast<unsigned char>(ch) & 0x0F;
            hex += hex <= 9 ? '0' : 'a' - 10;
            encoded.push_back(hex);
        }
    }

    return encoded;
}

{
    std::string out;

    for (size_t i = 0; i < src.length(); ++i) {
        char ch = src[i];

        if (ch == '%') {
            out.push_back(stoi(src.substr(i + 1, 2), nullptr, 16));
            i += 2;
        } else {
            out.push_back(ch);
        }
    }

    return out;
}

} // namespace libdnf


{
    std::string out;

    for (size_t i = 0; i < src.length(); ++i) {
        char ch = src[i];

        if (ch == '%') {
            out.push_back(stoi(src.substr(i + 1, 2), nullptr, 16));
            i += 2;
        } else {
            out.push_back(ch);
        }
    }

    return out;
}

/*
 *
 */

#include "url-encode.hpp"

namespace libdnf {

std::string urlEncode(const std::string & src, const std::string & exclude) {
    auto noEncode = [&exclude](char ch)
    {
        if (isalnum(ch) || ch=='-' || ch == '.' || ch == '_' || ch == '~') {
            return true;
        }

        if (exclude.find(ch) != std::string::npos) {
            return true;
        }

        return false;
    };

    // compute length of encoded string
    auto len = src.length();
    for (auto ch : src) {
        if (!noEncode(ch))
            len += 2;
    }

    // encode the input string
    std::string encoded;
    encoded.reserve(len);
    for (auto ch : src) {
        if (noEncode(ch))
            encoded.push_back(ch);
        else {
            encoded.push_back('%');
            unsigned char hex;
            hex = static_cast<unsigned char>(ch) >> 4;
            hex += hex <= 9 ? '0' : 'a' - 10;
            encoded.push_back(hex);
            hex = static_cast<unsigned char>(ch) & 0x0F;
            hex += hex <= 9 ? '0' : 'a' - 10;
            encoded.push_back(hex);
        }
    }

    return encoded;
}

std::string urlDecode(const std::string & src)


/*
 *
 */

#include "url-encode.hpp"

namespace libdnf {

std::string urlEncode(const std::string & src, const std::string & exclude) {
    auto noEncode = [&exclude](char ch)
    {
        if (isalnum(ch) || ch=='-' || ch == '.' || ch == '_' || ch == '~') {
            return true;
        }

        if (exclude.find(ch) != std::string::npos) {
            return true;
        }

        return false;
    };

    // compute length of encoded string
    auto len = src.length();
    for (auto ch : src) {
        if (!noEncode(ch))
            len += 2;
    }

    // encode the input string
    std:

    encoded.reserve(len);
    for (auto ch : src) {
        if (noEncode(ch))
            encoded.push_back(ch);
        else {
            encoded.push_back('%');
            unsigned char hex;
            hex = static_cast<unsigned char>(ch) >> 4;
            hex += hex <= 9 ? '0' : 'a' - 10;
            encoded.push_back(hex);
            hex = static_cast<unsigned char>(ch) & 0x0F;
            hex += hex <= 9 ? '0' : 'a' - 10;
            encoded.push_back(hex);
        }
    }

    return encoded;
}

std::string urlDecode(const std::string & src) {
    std::string out;

    for (size_t i = 0; i < src.length(); ++i) {
        char ch = src[i];

        if (ch == '%') {
            out.push_back(stoi(src.substr(i + 1, 2), nullptr, 16));
            i += 2;
        } else {
            out.push_back(ch);
        }
    }

    return out;
}

} // namespace libdnf


for (size_t i = 0; i < src.length(); ++i) {
        char ch = src[i];

        if (ch == '%') {
            out.push_back(stoi(src.substr(i + 1, 2), nullptr, 16));
            i += 2;
        } else {
            out.push_back(ch);
        }
    }

/*
 *
 */

#include "url-encode.hpp"

namespace libdnf {

std::string urlEncode(const std::string & src, const std::string & exclude) {
    auto noEncode = [&exclude](char ch)
    {
        if (isalnum(ch) || ch=='-' || ch == '.' || ch == '_' || ch == '~') {
            return true;
        }

        if (exclude.find(ch) != std::string::npos) {
            return true;
        }

        return false;
    };

    // compute length of encoded string
    auto len = src.length();
    for (auto ch : src) {
        if (!noEncode(ch))
            len += 2;
    }

    // encode the input string
    std::string encoded;
    encoded.reserve(len);
    for (auto ch : src) {
        if (noEncode(ch))
            encoded.push_back(ch);
        else {
            encoded.push_back('%');
            unsigned char hex;
            hex = static_cast<unsigned char>(ch) >> 4;
            hex += hex <= 9 ? '0' : 'a' - 10;
            encoded.push_back(hex);
            hex = static_cast<unsigned char>(ch) & 0x0F;
            hex += hex <= 9 ? '0' : 'a' - 10;
            encoded.push_back(hex);
        }
    }

    return encoded;
}

std::string urlDecode(const std::string & src) {
    std::string out;

    return out;
}

} // namespace libdnf


/**
 *   SFCGAL
 *
 *
 */
#include <boost/test/unit_test.hpp>

#include <SFCGAL/Kernel.h>
#include <SFCGAL/Point.h>
#include <SFCGAL/LineString.h>
#include <SFCGAL/Polygon.h>
#include <SFCGAL/Triangle.h>
#include <SFCGAL/PolyhedralSurface.h>
#include <SFCGAL/TriangulatedSurface.h>
#include <SFCGAL/Solid.h>
#include <SFCGAL/GeometryCollection.h>
#include <SFCGAL/MultiPoint.h>
#include <SFCGAL/MultiLineString.h>
#include <SFCGAL/MultiPolygon.h>
#include <SFCGAL/MultiSolid.h>
#include <SFCGAL/io/wkt.h>
#include <SFCGAL/algorithm/plane.h>

using namespace SFCGAL ;
using namespace boost::unit_test ;

BOOST_AUTO_TEST_SUITE( SFCGAL_algorithm_PlaneTest )

{
    std::unique_ptr<Geometry> gA( io::readWkt( "POLYGON((0 0,1 0,1 1,0 1,0 0))" ) );

    CGAL::Plane_3<Kernel> plane = algorithm::plane3D<Kernel>( gA->as<Polygon>() );
    BOOST_CHECK_EQUAL( plane.a(), 0.0 );
    BOOST_CHECK_EQUAL( plane.b(), 0.0 );
    BOOST_CHECK_EQUAL( plane.c(), 2.0 );
}

BOOST_AUTO_TEST_CASE( testPlane )
{
    struct TestCase {
        const std::string _wkt;
        const bool        _isPlane;
    };
    const TestCase test[] = {
        {"LINESTRING(1 2 3,4 5 6)", true}, // only two points
        {"LINESTRING(1 2 3,1 2 3,1 2 3,1 2 3)", true}, // all points in the same place
        {"LINESTRING(1 2 3,2 4 6,3 6 9,4 8 12)", true}, // all points aliged
        {"LINESTRING(1 2 3,6 5 4,7 8 9)", true}, // triangle must be plane
        {"LINESTRING(0 0 0,1 0 0,1 1 0,0 1 0,0 0 0)", true}, // all point in the plane z=0
        {"LINESTRING(2 1 0,2 0 0,2 1 0,2 1 0,2 0 3)", true}, // all points in the plane x=2
        {"LINESTRING(2 1 0,2 0 0,2 1 1,2 1 0,1 0 3)", false}, // one point out of plane
    };
    const size_t numTest = sizeof( test ) / sizeof( TestCase );

    for ( size_t t=0; t != numTest; ++t ) {
        std::unique_ptr<Geometry> g( io::readWkt( test[t]._wkt ) );
        const LineString* l = dynamic_cast<LineString*>( g.get() );
        BOOST_CHECK_MESSAGE(
            algorithm::isPlane3D< Kernel >( *l, 1.e-9 ) == test[t]._isPlane,
            ( boost::format( "LineString %d: %s %s" ) % t % test[t]._wkt % ( test[t]._isPlane ? "is plane" : "isn't plane" ) )
        );
    }
}

BOOST_AUTO_TEST_CASE( testPlane3DDivideByZeroCrash )
{
    std::unique_ptr< Geometry > degenerate_polygon = io::readWkt("POLYGON((1 -1 -1,1 0.5 0.5,1 0.5 0.5,1 -1 -1))");
    BOOST_CHECK( degenerate_polygon->geometryTypeId() == TYPE_POLYGON );

    // Should return degenerate plane without throwing
    auto degenerate_plane = algorithm::plane3D< Kernel >( degenerate_polygon->as<Polygon>() );

    // See triangulatePolygon3D for this pattern
    if (algorithm::hasPlane3D< Kernel >(degenerate_polygon->as<Polygon>()))
    {
        // Should not get here, OR plane3D with Plane3DInexactUnsafe should not divide by zero
        auto div_by_zero_check = algorithm::plane3D< Kernel >( degenerate_polygon->as<Polygon>(), algorithm::Plane3DInexactUnsafe() );
    }

    std::unique_ptr< Geometry > ok_polygon = io::readWkt("POLYGON((1 0.5 0.5,1.5 1.5 0.5,1.5 0.5 0.5,1 0.5 0.5))");
    BOOST_CHECK( ok_polygon->geometryTypeId() == TYPE_POLYGON );

    BOOST_CHECK( algorithm::hasPlane3D< Kernel >(ok_polygon->as<Polygon>()) );

    auto valid_plane = algorithm::plane3D< Kernel >( ok_polygon->as<Polygon>(), algorithm::Plane3DInexactUnsafe() );
}

BOOST_AUTO_TEST_SUITE_END()


{
    std::unique_ptr<Geometry> gA( io::readWkt( "POLYGON((0 0,1 0,1 1,0 1,0 0))" ) );

    CGAL::Plane_3<Kernel> plane = algorithm::plane3D<Kernel>( gA->as<Polygon>() );
    BOOST_CHECK_EQUAL( plane.a(), 0.0 );
    BOOST_CHECK_EQUAL( plane.b(), 0.0 );
    BOOST_CHECK_EQUAL( plane.c(), 2.0 );
}

/**
 *   SFCGAL
 *
 *
 */
#include <boost/test/unit_test.hpp>

#include <SFCGAL/Kernel.h>
#include <SFCGAL/Point.h>
#include <SFCGAL/LineString.h>
#include <SFCGAL/Polygon.h>
#include <SFCGAL/Triangle.h>
#include <SFCGAL/PolyhedralSurface.h>
#include <SFCGAL/TriangulatedSurface.h>
#include <SFCGAL/Solid.h>
#include <SFCGAL/GeometryCollection.h>
#include <SFCGAL/MultiPoint.h>
#include <SFCGAL/MultiLineString.h>
#include <SFCGAL/MultiPolygon.h>
#include <SFCGAL/MultiSolid.h>
#include <SFCGAL/io/wkt.h>
#include <SFCGAL/algorithm/plane.h>

using namespace SFCGAL ;
using namespace boost::unit_test ;

BOOST_AUTO_TEST_SUITE( SFCGAL_algorithm_PlaneTest )

BOOST_AUTO_TEST_CASE( testPlane1 )

BOOST_AUTO_TEST_CASE( testPlane )
{
    struct TestCase {
        const std::string _wkt;
        const bool        _isPlane;
    };
    const TestCase test[] = {
        {"LINESTRING(1 2 3,4 5 6)", true}, // only two points
        {"LINESTRING(1 2 3,1 2 3,1 2 3,1 2 3)", true}, // all points in the same place
        {"LINESTRING(1 2 3,2 4 6,3 6 9,4 8 12)", true}, // all points aliged
        {"LINESTRING(1 2 3,6 5 4,7 8 9)", true}, // triangle must be plane
        {"LINESTRING(0 0 0,1 0 0,1 1 0,0 1 0,0 0 0)", true}, // all point in the plane z=0
        {"LINESTRING(2 1 0,2 0 0,2 1 0,2 1 0,2 0 3)", true}, // all points in the plane x=2
        {"LINESTRING(2 1 0,2 0 0,2 1 1,2 1 0,1 0 3)", false}, // one point out of plane
    };
    const size_t numTest = sizeof( test ) / sizeof( TestCase );

    for ( size_t t=0; t != numTest; ++t ) {
        std::unique_ptr<Geometry> g( io::readWkt( test[t]._wkt ) );
        const LineString* l = dynamic_cast<LineString*>( g.get() );
        BOOST_CHECK_MESSAGE(
            algorithm::isPlane3D< Kernel >( *l, 1.e-9 ) == test[t]._isPlane,
            ( boost::format( "LineString %d: %s %s" ) % t % test[t]._wkt % ( test[t]._isPlane ? "is plane" : "isn't plane" ) )
        );
    }
}

BOOST_AUTO_TEST_CASE( testPlane3DDivideByZeroCrash )
{
    std::unique_ptr< Geometry > degenerate_polygon = io::readWkt("POLYGON((1 -1 -1,1 0.5 0.5,1 0.5 0.5,1 -1 -1))");
    BOOST_CHECK( degenerate_polygon->geometryTypeId() == TYPE_POLYGON );

    // Should return degenerate plane without throwing
    auto degenerate_plane = algorithm::plane3D< Kernel >( degenerate_polygon->as<Polygon>() );

    // See triangulatePolygon3D for this pattern
    if (algorithm::hasPlane3D< Kernel >(degenerate_polygon->as<Polygon>()))
    {
        // Should not get here, OR plane3D with Plane3DInexactUnsafe should not divide by zero
        auto div_by_zero_check = algorithm::plane3D< Kernel >( degenerate_polygon->as<Polygon>(), algorithm::Plane3DInexactUnsafe() );
    }

    std::unique_ptr< Geometry > ok_polygon = io::readWkt("POLYGON((1 0.5 0.5,1.5 1.5 0.5,1.5 0.5 0.5,1 0.5 0.5))");
    BOOST_CHECK( ok_polygon->geometryTypeId() == TYPE_POLYGON );

    BOOST_CHECK( algorithm::hasPlane3D< Kernel >(ok_polygon->as<Polygon>()) );

    auto valid_plane = algorithm::plane3D< Kernel >( ok_polygon->as<Polygon>(), algorithm::Plane3DInexactUnsafe() );
}

BOOST_AUTO_TEST_SUITE_END()


/**
 *   SFCGAL
 *
 *
 */
#include <boost/test/unit_test.hpp>

#include <SFCGAL/Kernel.h>
#include <SFCGAL/Point.h>
#include <SFCGAL/LineString.h>
#include <SFCGAL/Polygon.h>
#include <SFCGAL/Triangle.h>
#include <SFCGAL/PolyhedralSurface.h>
#include <SFCGAL/TriangulatedSurface.h>
#include <SFCGAL/Solid.h>
#include <SFCGAL/GeometryCollection.h>
#include <SFCGAL/MultiPoint.h>
#include <SFCGAL/MultiLineString.h>
#include <SFCGAL/MultiPolygon.h>
#include <SFCGAL/MultiSolid.h>
#include <SFCGAL/io/wkt.h>
#include <SFCGAL/algorithm/plane.h>

using namespace SFCGAL ;
using namespace boost::unit_test ;

BOOST_AUTO_TEST_SUITE( SFCGAL_algorithm_PlaneTest )

BOOST_AUTO_TEST_CASE( testPlane1 )
{
    std::unique_ptr<Geometry> gA( io::readWkt( "POLYGON((0 0,1 0,1 1,0 1,0 0))" ) );

    CGAL::Plane_3<Kernel> plane = algorithm::plane3D<Kernel>( gA->as<Polygon>() );
    BOOST_CHECK_EQUAL( plane.a(), 0.0 );
    BOOST_CHECK_EQUAL( plane.b(), 0.0

    BOOST_CHECK_EQUAL( plane.c(), 2.0 );
}

BOOST_AUTO_TEST_CASE( testPlane )
{
    struct TestCase {
        const std::string _wkt;
        const bool        _isPlane;
    };
    const TestCase test[] = {
        {"LINESTRING(1 2 3,4 5 6)", true}, // only two points
        {"LINESTRING(1 2 3,1 2 3,1 2 3,1 2 3)", true}, // all points in the same place
        {"LINESTRING(1 2 3,2 4 6,3 6 9,4 8 12)", true}, // all points aliged
        {"LINESTRING(1 2 3,6 5 4,7 8 9)", true}, // triangle must be plane
        {"LINESTRING(0 0 0,1 0 0,1 1 0,0 1 0,0 0 0)", true}, // all point in the plane z=0
        {"LINESTRING(2 1 0,2 0 0,2 1 0,2 1 0,2 0 3)", true}, // all points in the plane x=2
        {"LINESTRING(2 1 0,2 0 0,2 1 1,2 1 0,1 0 3)", false}, // one point out of plane
    };
    const size_t numTest = sizeof( test ) / sizeof( TestCase );

    for ( size_t t=0; t != numTest; ++t ) {
        std::unique_ptr<Geometry> g( io::readWkt( test[t]._wkt ) );
        const LineString* l = dynamic_cast<LineString*>( g.get() );
        BOOST_CHECK_MESSAGE(
            algorithm::isPlane3D< Kernel >( *l, 1.e-9 ) == test[t]._isPlane,
            ( boost::format( "LineString %d: %s %s" ) % t % test[t]._wkt % ( test[t]._isPlane ? "is plane" : "isn't plane" ) )
        );
    }
}

BOOST_AUTO_TEST_CASE( testPlane3DDivideByZeroCrash )
{
    std::unique_ptr< Geometry > degenerate_polygon = io::readWkt("POLYGON((1 -1 -1,1 0.5 0.5,1 0.5 0.5,1 -1 -1))");
    BOOST_CHECK( degenerate_polygon->geometryTypeId() == TYPE_POLYGON );

    // Should return degenerate plane without throwing
    auto degenerate_plane = algorithm::plane3D< Kernel >( degenerate_polygon->as<Polygon>() );

    // See triangulatePolygon3D for this pattern
    if (algorithm::hasPlane3D< Kernel >(degenerate_polygon->as<Polygon>()))
    {
        // Should not get here, OR plane3D with Plane3DInexactUnsafe should not divide by zero
        auto div_by_zero_check = algorithm::plane3D< Kernel >( degenerate_polygon->as<Polygon>(), algorithm::Plane3DInexactUnsafe() );
    }

    std::unique_ptr< Geometry > ok_polygon = io::readWkt("POLYGON((1 0.5 0.5,1.5 1.5 0.5,1.5 0.5 0.5,1 0.5 0.5))");
    BOOST_CHECK( ok_polygon->geometryTypeId() == TYPE_POLYGON );

    BOOST_CHECK( algorithm::hasPlane3D< Kernel >(ok_polygon->as<Polygon>()) );

    auto valid_plane = algorithm::plane3D< Kernel >( ok_polygon->as<Polygon>(), algorithm::Plane3DInexactUnsafe() );
}

BOOST_AUTO_TEST_SUITE_END()


for ( size_t t=0; t != numTest; ++t ) {
        std::unique_ptr<Geometry> g( io::readWkt( test[t]._wkt ) );
        const LineString* l = dynamic_cast<LineString*>( g.get() );
        BOOST_CHECK_MESSAGE(
            algorithm::isPlane3D< Kernel >( *l, 1.e-9 ) == test[t]._isPlane,
            ( boost::format( "LineString %d: %s %s" ) % t % test[t]._wkt % ( test[t]._isPlane ? "is plane" : "isn't plane" ) )
        );
    }

/**
 *   SFCGAL
 *
 *
 */
#include <boost/test/unit_test.hpp>

#include <SFCGAL/Kernel.h>
#include <SFCGAL/Point.h>
#include <SFCGAL/LineString.h>
#include <SFCGAL/Polygon.h>
#include <SFCGAL/Triangle.h>
#include <SFCGAL/PolyhedralSurface.h>
#include <SFCGAL/TriangulatedSurface.h>
#include <SFCGAL/Solid.h>
#include <SFCGAL/GeometryCollection.h>
#include <SFCGAL/MultiPoint.h>
#include <SFCGAL/MultiLineString.h>
#include <SFCGAL/MultiPolygon.h>
#include <SFCGAL/MultiSolid.h>
#include <SFCGAL/io/wkt.h>
#include <SFCGAL/algorithm/plane.h>

using namespace SFCGAL ;
using namespace boost::unit_test ;

BOOST_AUTO_TEST_SUITE( SFCGAL_algorithm_PlaneTest )

BOOST_AUTO_TEST_CASE( testPlane1 )
{
    std::unique_ptr<Geometry> gA( io::readWkt( "POLYGON((0 0,1 0,1 1,0 1,0 0))" ) );

    CGAL::Plane_3<Kernel> plane = algorithm::plane3D<Kernel>( gA->as<Polygon>() );
    BOOST_CHECK_EQUAL( plane.a(), 0.0 );
    BOOST_CHECK_EQUAL( plane.b(), 0.0 );
    BOOST_CHECK_EQUAL( plane.c(), 2.0 );
}

BOOST_AUTO_TEST_CASE( testPlane )
{
    struct TestCase {
        const std::string _wkt;
        const bool        _isPlane;
    };
    const TestCase test[] = {
        {"LINESTRING(1 2 3,4 5 6)", true}, // only two points
        {"LINESTRING(1 2 3,1 2 3,1 2 3,1 2 3)", true}, // all points in the same place
        {"LINESTRING(1 2 3,2 4 6,3 6 9,4 8 12)", true}, // all points aliged
        {"LINESTRING(1 2 3,6 5 4,7 8 9)", true}, // triangle must be plane
        {"LINESTRING(0 0 0,1 0 0,1 1 0,0 1 0,0 0 0)", true}, // all point in the plane z=0
        {"LINESTRING(2 1 0,2 0 0,2 1 0,2 1 0,2 0 3)", true}, // all points in the plane x=2
        {"LINESTRING(2 1 0,2 0 0,2 1 1,2 1 0,1 0 3)", false}, // one point out of plane
    };
    const size_t numTest = sizeof( test ) / sizeof( TestCase );

}

BOOST_AUTO_TEST_CASE( testPlane3DDivideByZeroCrash )
{
    std::unique_ptr< Geometry > degenerate_polygon = io::readWkt("POLYGON((1 -1 -1,1 0.5 0.5,1 0.5 0.5,1 -1 -1))");
    BOOST_CHECK( degenerate_polygon->geometryTypeId() == TYPE_POLYGON );

    // Should return degenerate plane without throwing
    auto degenerate_plane = algorithm::plane3D< Kernel >( degenerate_polygon->as<Polygon>() );

    // See triangulatePolygon3D for this pattern
    if (algorithm::hasPlane3D< Kernel >(degenerate_polygon->as<Polygon>()))
    {
        // Should not get here, OR plane3D with Plane3DInexactUnsafe should not divide by zero
        auto div_by_zero_check = algorithm::plane3D< Kernel >( degenerate_polygon->as<Polygon>(), algorithm::Plane3DInexactUnsafe() );
    }

    std::unique_ptr< Geometry > ok_polygon = io::readWkt("POLYGON((1 0.5 0.5,1.5 1.5 0.5,1.5 0.5 0.5,1 0.5 0.5))");
    BOOST_CHECK( ok_polygon->geometryTypeId() == TYPE_POLYGON );

    BOOST_CHECK( algorithm::hasPlane3D< Kernel >(ok_polygon->as<Polygon>()) );

    auto valid_plane = algorithm::plane3D< Kernel >( ok_polygon->as<Polygon>(), algorithm::Plane3DInexactUnsafe() );
}

BOOST_AUTO_TEST_SUITE_END()


  /*
 * =====================================================================================
 *
 *       Filename:  xKnotMesh.cpp
 *
 *    Description:  knot tube
 *
 *        Version:  1.0
 *        Created:  10/14/2015 18:51:35
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Pablo Colapinto (), gmail->wolftype
 *   Organization:  wolftype
 *
 * =====================================================================================
 */

#include <vsr/vsr_app.h>

#include <vsr/form/vsr_fiber.h>
#include <vsr/form/vsr_knot.h>
#include <vsr/form/vsr_shapes.h>

using namespace vsr;
using namespace vsr::cga;

struct MyApp : App {

  Point mouse = Construct::point(0,0,0);

  float time;
  float amt;

  TorusKnot tk;

  float mP,mQ,theta,phi;

  float linewidth,pointsize;

  bool bDrawKnot, bDrawHopf,bDrawPreImage;

  void setup(){
      bindGLV();

      gui(amt,"amt",-100,100);
      gui(mP,"p",1,100);
      gui(mQ,"q",1,100);
      gui(theta,"theta",0,1);
      gui(phi,"phi",-1,1);
      gui(bDrawKnot,"bDrawKnot");
      gui(bDrawHopf,"bDrawHopf");
      gui(bDrawPreImage,"bDrawPreImage");
      gui(bSortOutput,"bSort");
      gui(bShadedOutput,"bShade");
      gui(linewidth,"linewidth",0,10);
      gui(pointsize,"pointsize",0,20);

      scene.camera.pos(0,0,10);
  }

  virtual void onDraw(){

    if (bSetMouse) mouse = calcMouse3D();

    tk.P = mP; tk.Q = mQ; tk.amt=amt;

    tk.calc( mouse );

    vector<Cir> cir;

    for (int i=0;i<10;++i){
      auto tcir = CXZ(1).trs(0,3*(float)i/10,0);
      cir.push_back(tcir);
    }

    if (bDrawHopf){
     gl2psPointSize((int)pointsize);
     gl2psLineWidth((int)linewidth);

     tk.HF.vec() = Vec::x.spin( Gen::rot(theta*PI,phi * PIOVERTWO) );

     Draw(tk.HF.fiberA(),.6,.2,.6);
     Draw(tk.HF.fiberB(),.2,.4,.2);

     auto pair = Construct::pair( Dls(0,0,0,1,-.5), tk.HF.vec() );

     if (bDrawPreImage){
     Draw( tk.HF.vec(), .5,.2,0);
     Draw( Construct::pointA(pair), .6,.2,.6);
     Draw( Construct::pointB(pair), .2,.4,.2);
     Draw( Dls(0,0,0,1,-.5), 0,1,1,.4);
     }

    }

    if (bDrawKnot){
     gl2psPointSize(1);
     gl2psLineWidth(1);

     auto m = Shape::Skin(tk.cir, tk.cir.size(), true, 50);
     m.drawElementsColor();
    }

  }

  /*-----------------------------------------------------------------------------
   *  Keyboard control (hit 's' to toggle mouse tracking)
   *-----------------------------------------------------------------------------*/

};

{

  MyApp app;
  app.start();

  return 0;

}


{

  MyApp app;
  app.start();

  return 0;

}

  /*
 * =====================================================================================
 *
 *       Filename:  xKnotMesh.cpp
 *
 *    Description:  knot tube
 *
 *        Version:  1.0
 *        Created:  10/14/2015 18:51:35
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Pablo Colapinto (), gmail->wolftype
 *   Organization:  wolftype
 *
 * =====================================================================================
 */

#include <vsr/vsr_app.h>

#include <vsr/form/vsr_fiber.h>
#include <vsr/form/vsr_knot.h>
#include <vsr/form/vsr_shapes.h>

using namespace vsr;
using namespace vsr::cga;

struct MyApp : App {

  Point mouse = Construct::point(0,0,0);

  float time;
  float amt;

  TorusKnot tk;

  float mP,mQ,theta,phi;

  float linewidth,pointsize;

  bool bDrawKnot, bDrawHopf,bDrawPreImage;

  void setup(){
      bindGLV();

      gui(amt,"amt",-100,100);
      gui(mP,"p",1,100);
      gui(mQ,"q",1,100);
      gui(theta,"theta",0,1);
      gui(phi,"phi",-1,1);
      gui(bDrawKnot,"bDrawKnot");
      gui(bDrawHopf,"bDrawHopf");
      gui(bDrawPreImage,"bDrawPreImage");
      gui(bSortOutput,"bSort");
      gui(bShadedOutput,"bShade");
      gui(linewidth,"linewidth",0,10);
      gui(pointsize,"pointsize",0,20);

      scene.camera.pos(0,0,10);
  }

  virtual void onDraw(){

    if (bSetMouse) mouse = calcMouse3D();

    tk.P = mP; tk.Q = mQ; tk.amt=amt;

    tk.calc( mouse );

    vector<Cir> cir;

    for (int i=0;i<10;++i){
      auto tcir = CXZ(1).trs(0,3*(float)i/10,0);
      cir.push_back(tcir);
    }

    if (bDrawHopf){
     gl2psPointSize((int)pointsize);
     gl2psLineWidth((int)linewidth);

     tk.HF.vec() = Vec::x.spin( Gen::rot(theta*PI,phi * PIOVERTWO) );

     Draw(tk.HF.fiberA(),.6,.2,.6);
     Draw(tk.HF.fiberB(),.2,.4,.2);

     auto pair = Construct::pair( Dls(0,0,0,1,-.5), tk.HF.vec() );

     if (bDrawPreImage){
     Draw( tk.HF.vec(), .5,.2,0);
     Draw( Construct::pointA(pair), .6,.2,.6);
     Draw( Construct::pointB(pair), .2,.4,.2);
     Draw( Dls(0,0,0,1,-.5), 0,1,1,.4);
     }

    }

    if (bDrawKnot){
     gl2psPointSize(1);
     gl2psLineWidth(1);

     auto m = Shape::Skin(tk.cir, tk.cir.size(), true, 50);
     m.drawElementsColor();
    }

  }

  /*-----------------------------------------------------------------------------
   *  Keyboard control (hit 's' to toggle mouse tracking)
   *-----------------------------------------------------------------------------*/

};

int main()


  /*
 * =====================================================================================
 *
 *       Filename:  xKnotMesh.cpp
 *
 *    Description:  knot tube
 *
 *        Version:  1.0
 *        Created:  10/14/2015 18:51:35
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Pablo Colapinto (), gmail->wolftype
 *   Organization:  wolftype
 *
 * =====================================================================================
 */

#include <vsr/vsr_app.h>

#include <vsr/form/vsr_fiber.h>
#include <vsr/form/vsr_knot.h>
#include <vsr/form/vsr_shapes.h>

using namespace vsr;
using namespace vsr::cga;

struct MyApp : App {

  Point mouse = Construct::point(0,0,0);

  float time;
  float amt;

  TorusKnot tk;

  float mP,mQ,theta,phi;

  float linewidth,pointsize;

  bool bDrawKnot, bDrawHopf,bDrawPreImage;

  void setup(){
      bindGLV();

      gui(amt,"amt",-100,100);
      gui(mP,"p",1,100);
      gui(mQ,"q",1,100);
      gui(theta,"theta",0,1);
      gui(phi,"phi",-1,1);
      gui(bDrawKnot,"bDrawKnot");
      gui(bDrawHopf,"bDrawHopf");
      gui(bDrawPreImage,"bDrawPreImage"

      gui(bSortOutput,"bSort");
      gui(bShadedOutput,"bShade");
      gui(linewidth,"linewidth",0,10);
      gui(pointsize,"pointsize",0,20);

      scene.camera.pos(0,0,10);
  }

  virtual void onDraw(){

    if (bSetMouse) mouse = calcMouse3D();

    tk.P = mP; tk.Q = mQ; tk.amt=amt;

    tk.calc( mouse );

    vector<Cir> cir;

    for (int i=0;i<10;++i){
      auto tcir = CXZ(1).trs(0,3*(float)i/10,0);
      cir.push_back(tcir);
    }

    if (bDrawHopf){
     gl2psPointSize((int)pointsize);
     gl2psLineWidth((int)linewidth);

     tk.HF.vec() = Vec::x.spin( Gen::rot(theta*PI,phi * PIOVERTWO) );

     Draw(tk.HF.fiberA(),.6,.2,.6);
     Draw(tk.HF.fiberB(),.2,.4,.2);

     auto pair = Construct::pair( Dls(0,0,0,1,-.5), tk.HF.vec() );

     if (bDrawPreImage){
     Draw( tk.HF.vec(), .5,.2,0);
     Draw( Construct::pointA(pair), .6,.2,.6);
     Draw( Construct::pointB(pair), .2,.4,.2);
     Draw( Dls(0,0,0,1,-.5), 0,1,1,.4);
     }

    }

    if (bDrawKnot){
     gl2psPointSize(1);
     gl2psLineWidth(1);

     auto m = Shape::Skin(tk.cir, tk.cir.size(), true, 50);
     m.drawElementsColor();
    }

  }

  /*-----------------------------------------------------------------------------
   *  Keyboard control (hit 's' to toggle mouse tracking)
   *-----------------------------------------------------------------------------*/

};

int main(){

  MyApp app;
  app.start();

  return 0;

}


for (int i=0;i<10;++i){
      auto tcir = CXZ(1).trs(0,3*(float)i/10,0);
      cir.push_back(tcir);
    }

  /*
 * =====================================================================================
 *
 *       Filename:  xKnotMesh.cpp
 *
 *    Description:  knot tube
 *
 *        Version:  1.0
 *        Created:  10/14/2015 18:51:35
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Pablo Colapinto (), gmail->wolftype
 *   Organization:  wolftype
 *
 * =====================================================================================
 */

#include <vsr/vsr_app.h>

#include <vsr/form/vsr_fiber.h>
#include <vsr/form/vsr_knot.h>
#include <vsr/form/vsr_shapes.h>

using namespace vsr;
using namespace vsr::cga;

struct MyApp : App {

  Point mouse = Construct::point(0,0,0);

  float time;
  float amt;

  TorusKnot tk;

  float mP,mQ,theta,phi;

  float linewidth,pointsize;

  bool bDrawKnot, bDrawHopf,bDrawPreImage;

  void setup(){
      bindGLV();

      gui(amt,"amt",-100,100);
      gui(mP,"p",1,100);
      gui(mQ,"q",1,100);
      gui(theta,"theta",0,1);
      gui(phi,"phi",-1,1);
      gui(bDrawKnot,"bDrawKnot");
      gui(bDrawHopf,"bDrawHopf");
      gui(bDrawPreImage,"bDrawPreImage");
      gui(bSortOutput,"bSort");
      gui(bShadedOutput,"bShade");
      gui(linewidth,"linewidth",0,10);
      gui(pointsize,"pointsize",0,20);

      scene.camera.pos(0,0,10);
  }

  virtual void onDraw(){

    if (bSetMouse) mouse = calcMouse3D();

    tk.P = mP; tk.Q = mQ; tk.amt=amt;

    tk.calc( mouse );

    vector<Cir> cir;

    if (bDrawHopf){
     gl2psPointSize((int)pointsize);
     gl2psLineWidth((int)linewidth);

     tk.HF.vec() = Vec::x.spin( Gen::rot(theta*PI,phi * PIOVERTWO) );

     Draw(tk.HF.fiberA(),.6,.2,.6);
     Draw(tk.HF.fiberB(),.2,.4,.2);

     auto pair = Construct::pair( Dls(0,0,0,1,-.5), tk.HF.vec() );

     if (bDrawPreImage){
     Draw( tk.HF.vec(), .5,.2,0);
     Draw( Construct::pointA(pair), .6,.2,.6);
     Draw( Construct::pointB(pair), .2,.4,.2);
     Draw( Dls(0,0,0,1,-.5), 0,1,1,.4);
     }

    }

    if (bDrawKnot){
     gl2psPointSize(1);
     gl2psLineWidth(1);

     auto m = Shape::Skin(tk.cir, tk.cir.size(), true, 50);
     m.drawElementsColor();
    }

  }

  /*-----------------------------------------------------------------------------
   *  Keyboard control (hit 's' to toggle mouse tracking)
   *-----------------------------------------------------------------------------*/

};

int main(){

  MyApp app;
  app.start();

  return 0;

}


{
    ;
}

void Stress::CalcStress()
{
    Real divv2p3 = two3rd * ( dudx + dvdy + dwdz );

    txx = viscosity * ( two * dudx - divv2p3 );
    tyy = viscosity * ( two * dvdy - divv2p3 );
    tzz = viscosity * ( two * dwdz - divv2p3 );
    txy = viscosity * ( dudy + dvdx );
    txz = viscosity * ( dudz + dwdx );
    tyz = viscosity * ( dvdz + dwdy );
}

void Stress::CalcForce( Force * force )
{
    this->CalcStress();

    Real coef = - two * area * orey;

    force->x = coef * ( fnx * txx + fny * txy + fnz * txz );
    force->y = coef * ( fnx * txy + fny * tyy + fnz * tyz );
    force->z = coef * ( fnx * txz + fny * tyz + fnz * tzz );
}

EndNameSpace


Stress::~Stress()
{
    ;
}

void Stress::CalcStress()
{
    Real divv2p3 = two3rd * ( dudx + dvdy + dwdz );

    txx = viscosity * ( two * dudx - divv2p3 );
    tyy = viscosity * ( two * dvdy - divv2p3 );
    tzz = viscosity * ( two * dwdz - divv2p3 );
    txy = viscosity * ( dudy + dvdx );
    txz = viscosity * ( dudz + dwdx );
    tyz = viscosity * ( dvdz + dwdy );
}

void Stress::CalcForce( Force * force )
{
    this->CalcStress();

    Real coef = - two * area * orey;

    force->x = coef * ( fnx * txx + fny * txy + fnz * txz );
    force->y = coef * ( fnx * txy + fny * tyy + fnz * tyz );
    force->z = coef * ( fnx * txz + fny * tyz + fnz * tzz );
}

EndNameSpace


/*---------------------------------------------------------------------------*\
    OneFLOW - LargeScale Multiphysics Scientific Simulation Environment
-------------------------------------------------------------------------------
License
    This file is part of OneFLOW.

\*---------------------------------------------------------------------------*/

#include "Stress.h"
#include "Force.h"
#include "Constant.h"

BeginNameSpace( ONEFLOW )

Stress stress;

Stress::Stress()
{
    ;
}

Stress::~Stress()
{
    ;
}

void Stress::CalcStress()
{
    Real divv2p3 = two3rd * ( dudx + dvdy + dwdz );

    txx = viscosity * ( two * dudx - divv2p3 );
    tyy = viscosity * ( two * dvdy - divv2p3 );
    tzz = viscosity * ( two * dwdz - divv2p3 );
    txy = viscosity * ( dudy + dvdx );
    txz = viscosity * ( dudz +

    tyz = viscosity * ( dvdz + dwdy );
}

void Stress::CalcForce( Force * force )
{
    this->CalcStress();

    Real coef = - two * area * orey;

    force->x = coef * ( fnx * txx + fny * txy + fnz * txz );
    force->y = coef * ( fnx * txy + fny * tyy + fnz * tyz );
    force->z = coef * ( fnx * txz + fny * tyz + fnz * tzz );
}

EndNameSpace


/* ---------------------------- INCLUDE SECTION ----------------------------- */

#include <cstring>
#include <cstdint>
#include <string>

#include "tweaks.h"
#include "xmath.h"
#include "xutl.h"
#include <SDL.h>

int64_t tick_per_sec=0;
int64_t beg_tick=0;

#if defined(_MSC_VER) && _MSC_VER >= 1310
__declspec (noinline)
#endif // _MSC_VER >= 1310

int64_t getRDTSC() {
    return static_cast<int64_t>(SDL_GetPerformanceCounter());
}

{
	if(tick_per_sec!=0)
		return;
	/*
	timeBeginPeriod(1);

	unsigned int t2=timeGetTime(), t1 = t2;

	while(t1==t2){
		t2=timeGetTime();
	};

    int64_t tickb=getRDTSC();
	t1=t2;
	while(t1+MS_PER_PERIOD > t2){
		t2=timeGetTime();
	}
    int64_t ticke=getRDTSC();
	tick_per_sec = (ticke-tickb)/MS_PER_PERIOD;
	beg_tick=getRDTSC();
	*/

	tick_per_sec = static_cast<int64_t>(SDL_GetPerformanceFrequency() / 1000);
    beg_tick=getRDTSC();

}

double clockf()
{
	return (double)(getRDTSC() - beg_tick) / (double)tick_per_sec;
}

int clocki()
{
	return (int)((getRDTSC() - beg_tick) / tick_per_sec);
}


{
	return (int)((getRDTSC() - beg_tick) / tick_per_sec);
}

/* ---------------------------- INCLUDE SECTION ----------------------------- */

#include <cstring>
#include <cstdint>
#include <string>

#include "tweaks.h"
#include "xmath.h"
#include "xutl.h"
#include <SDL.h>

int64_t tick_per_sec=0;
int64_t beg_tick=0;

#if defined(_MSC_VER) && _MSC_VER >= 1310
__declspec (noinline)
#endif // _MSC_VER >= 1310

int64_t getRDTSC() {
    return static_cast<int64_t>(SDL_GetPerformanceCounter());
}

void initclock()
{
	if(tick_per_sec!=0)
		return;
	/*
	timeBeginPeriod(1);

	unsigned int t2=timeGetTime(), t1 = t2;

	while(t1==t2){
		t2=timeGetTime();
	};

    int64_t tickb=getRDTSC();
	t1=t2;
	while(t1+MS_PER_PERIOD > t2){
		t2=timeGetTime();
	}
    int64_t ticke=getRDTSC();
	tick_per_sec = (ticke-tickb)/MS_PER_PERIOD;
	beg_tick=getRDTSC();
	*/

	tick_per_sec = static_cast<int64_t>(SDL_GetPerformanceFrequency() / 1000);
    beg_tick=getRDTSC();

}

double clockf()
{
	return (double)(getRDTSC() - beg_tick) / (double)tick_per_sec;
}

int clocki()


/* ---------------------------- INCLUDE SECTION ----------------------------- */

#include <cstring>
#include <cstdint>
#include <string>

#include "tweaks.h"
#include "xmath.h"
#include "xutl.h"
#include <SDL.h>

int64_t tick_per_sec=0;
int64_t beg_tick=0;

#if defined(_MSC_VER) && _MSC_VER >= 1310
__declspec (noinline)
#endif // _MSC_VER >= 1310

int64_t getRDTSC() {
    return static_cast<int64_t>(SDL_GetPerformanceCounter());
}

void initclock()
{
	if(tick_per_sec!=0)
		return;
	/*
	timeBeginPeriod(1);

	unsigned int t2=timeGetTime(), t1 = t2;

	while(t1==t2){
		t2=timeGetTime();
	};

    int64_t tickb=getRDTSC();
	t1=t2;
	while(t1+MS_PER_PERIOD > t2){
		t2=timeGetTime();
	}
    int64_t ticke=getRDTSC();
	tick_per_sec = (ticke-tickb)/MS_PER_PERIOD;
	beg_tick=getRDTSC();
	*/

	tick_per_sec = s

    beg_tick=getRDTSC();

}

double clockf()
{
	return (double)(getRDTSC() - beg_tick) / (double)tick_per_sec;
}

int clocki()
{
	return (int)((getRDTSC() - beg_tick) / tick_per_sec);
}