Initial commit of ResInsight version 0.4.8

This commit is contained in:
Alf B. Rustad committed 2012-05-18 09:45:23 +02:00
1 parent a680bf941e
commit dfe97efb1b
657 files changed
+176690

No files matched your search

@@ -0,0 +1,78 @@
cmake_minimum_required(VERSION 2.8)
project(LibCore)
# Use our strict compile flags
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CEE_STRICT_CXX_FLAGS}")
set(CEE_HEADER_FILES
cvfArray.h
cvfArray.inl
cvfAssert.h
cvfBase.h
cvfBase64.h
cvfCharArray.h
cvfCollection.h
cvfCollection.inl
cvfColor3.h
cvfColor4.h
cvfConfigCore.h
cvfDebugTimer.h
cvfFlags.h
cvfFlags.inl
cvfFunctorRange.h
cvfLibCore.h
cvfLogger.h
cvfMath.h
cvfMath.inl
cvfMatrix3.h
cvfMatrix3.inl
cvfMatrix4.h
cvfMatrix4.inl
cvfObject.h
cvfObject.inl
cvfPlane.h
cvfQuat.h
cvfQuat.inl
cvfRect.h
cvfRect.inl
cvfString.h
cvfSystem.h
cvfTBBControl.h
cvfTimer.h
cvfTrace.h
cvfValueArray.h
cvfVector2.h
cvfVector2.inl
cvfVector3.h
cvfVector3.inl
cvfVector4.h
cvfVector4.inl
cvfVersion.h
)
set(CEE_SOURCE_FILES
cvfAssert.cpp
cvfBase64.cpp
cvfCharArray.cpp
cvfColor3.cpp
cvfColor4.cpp
cvfDebugTimer.cpp
cvfLogger.cpp
cvfMath.cpp
cvfObject.cpp
cvfPlane.cpp
cvfString.cpp
cvfSystem.cpp
cvfTimer.cpp
cvfTBBControl.cpp
cvfTrace.cpp
cvfVector2.cpp
cvfVector3.cpp
cvfVector4.cpp
)
add_library(${PROJECT_NAME} ${CEE_HEADER_FILES} ${CEE_SOURCE_FILES})
+133
View File
@@ -0,0 +1,133 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include "cvfObject.h"
#include "cvfValueArray.h"
#include <vector>
namespace cvf {
//==================================================================================================
//
// Templated array designed for high performance and no overhead over C arrays.
//
//==================================================================================================
template <typename T>
class Array : public Object, public ValueArray<T>
{
public:
Array();
Array(const Array& other);
Array(const T* data, size_t size);
explicit Array(size_t size);
explicit Array(const ValueArray<T>& other);
explicit Array(const std::vector<T>& other);
~Array();
inline const T& operator[](size_t index) const;
inline T& operator[](size_t index);
Array& operator=(Array rhs);
void assign(const T* data, size_t size);
void assign(const std::vector<T>& data);
void resize(size_t size);
void clear();
inline virtual size_t size() const;
inline void set(size_t index, const T& val);
inline void setAll(const T& val);
inline void setConsecutive(const T& startVal);
inline const T& get(size_t index) const;
inline virtual T val(size_t index) const;
inline const T* ptr() const;
inline T* ptr();
inline const T* ptr(size_t index) const;
inline T* ptr(size_t index);
void setSharedPtr(T* data, size_t size);
void setPtr(T* data, size_t size);
void copyData(const T* source, size_t numElementsToCopy, size_t destIndex);
void copyData(const Array<T>& source, size_t numElementsToCopy, size_t destIndex, size_t sourceIndex);
template<typename U>
void copyConvertedData(const Array<U>& source, size_t numElementsToCopy, size_t destIndex, size_t sourceIndex);
template<typename U>
ref<Array<T> > extractElements(const Array<U>& elementIndices) const;
void toStdVector(std::vector<T>* vec) const;
size_t capacity() const;
void reserve(size_t capacity);
void squeeze();
void setSizeZero();
inline void add(const T& val);
T min(size_t* index = 0) const;
T max(size_t* index = 0) const;
void swap(Array& other);
// Basic iterator support to be able to utilize STL algorithms
public:
typedef T* iterator;
typedef const T* const_iterator;
inline iterator begin() { return m_data; }
inline iterator end() { return m_data + m_size; }
inline const_iterator begin() const { return m_data; }
inline const_iterator end() const { return m_data + m_size; }
private:
void ground();
private:
size_t m_size; ///< Number of elements/items in array
size_t m_capacity; ///< Size of the allocated buffer
T* m_data; ///< Array holding the actual data
bool m_sharedData; ///< True if the data member is shared with another object and cannot be changed
};
// Only works for simple types that don't require copy operators.
typedef Array<int> IntArray;
typedef Array<uint> UIntArray;
typedef Array<ushort> UShortArray;
typedef Array<ubyte> UByteArray;
typedef Array<float> FloatArray;
typedef Array<double> DoubleArray;
typedef Array<Vec2f> Vec2fArray;
typedef Array<Vec2d> Vec2dArray;
typedef Array<Vec3f> Vec3fArray;
typedef Array<Vec3d> Vec3dArray;
typedef Array<Vec4f> Vec4fArray;
typedef Array<Vec4d> Vec4dArray;
typedef Array<Color3ub> Color3ubArray;
typedef Array<Color3f> Color3fArray;
typedef Array<Color4ub> Color4ubArray;
}
#include "cvfArray.inl"
+769
View File
@@ -0,0 +1,769 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
namespace cvf {
//==================================================================================================
///
/// \class cvf::Array
/// \ingroup Core
///
/// Templated version of a simple array designed for high performance and no overhead over C arrays
/// in release (non-check builds).
///
/// Will only work on simple types and classes that do not rely on a constructor or
/// destructor (as they are not called).
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
/// Create an empty array
//--------------------------------------------------------------------------------------------------
template <typename T>
Array<T>::Array()
{
ground();
}
//--------------------------------------------------------------------------------------------------
/// Create an array with the given number of elements
//--------------------------------------------------------------------------------------------------
template <typename T>
Array<T>::Array(size_t size)
{
CVF_ASSERT(size > 0);
ground();
resize(size);
}
//--------------------------------------------------------------------------------------------------
/// Create the array and assign (copy) the given data
//--------------------------------------------------------------------------------------------------
template <typename T>
Array<T>::Array(const T* data, size_t size)
{
CVF_ASSERT(data);
CVF_ASSERT(size > 0);
ground();
assign(data, size);
}
//--------------------------------------------------------------------------------------------------
/// Create the array and assign (copy) the given data
//--------------------------------------------------------------------------------------------------
template <typename T>
Array<T>::Array(const Array& other)
: Object(), ValueArray<T>()
{
ground();
if (other.size() > 0)
{
assign(other.m_data, other.size());
}
}
//--------------------------------------------------------------------------------------------------
/// Explicit constructor to create the array and assign (copy) the passed value array
//--------------------------------------------------------------------------------------------------
template <typename T>
Array<T>::Array(const ValueArray<T>& other)
{
ground();
if (other.size() > 0)
{
resize(other.size());
size_t i;
for (i = 0; i < other.size(); i++)
{
set(i, other.val(i));
}
}
}
//--------------------------------------------------------------------------------------------------
/// Explicit constructor to create the array and assign (copy) the passed std::vector
//--------------------------------------------------------------------------------------------------
template <typename T>
Array<T>::Array(const std::vector<T>& other)
{
ground();
if (other.size() > 0)
{
assign(other);
}
}
//--------------------------------------------------------------------------------------------------
/// Init all members
//--------------------------------------------------------------------------------------------------
template <typename T>
void Array<T>::ground()
{
m_size = 0;
m_data = NULL;
m_capacity = 0;
m_sharedData = false;
}
//--------------------------------------------------------------------------------------------------
/// Destructor. Deletes the data.
//--------------------------------------------------------------------------------------------------
template <typename T>
Array<T>::~Array()
{
clear();
}
//--------------------------------------------------------------------------------------------------
/// Returns a const reference to the element at the given index.
//--------------------------------------------------------------------------------------------------
template <typename T>
inline const T& Array<T>::operator[] (size_t index) const
{
CVF_TIGHT_ASSERT(this && m_data);
CVF_TIGHT_ASSERT(index < m_size);
return m_data[index];
}
//--------------------------------------------------------------------------------------------------
/// Returns a modifiable reference to the element at the given index.
//--------------------------------------------------------------------------------------------------
template <typename T>
inline T& Array<T>::operator[] (size_t index)
{
CVF_TIGHT_ASSERT(this && m_data);
CVF_TIGHT_ASSERT(index < m_size);
return m_data[index];
}
//--------------------------------------------------------------------------------------------------
/// Assign (copy) the data in the given array
//--------------------------------------------------------------------------------------------------
template <typename T>
Array<T>& Array<T>::operator=(Array rhs)
{
CVF_TIGHT_ASSERT(!m_sharedData);
rhs.swap(*this);
return *this;
}
//--------------------------------------------------------------------------------------------------
/// Resize the array to the given size.
/// The current contents (data) will be kept (as much as possible). Any new elements will be unassigned.
/// Calling resize(0) is the same as clear().
//--------------------------------------------------------------------------------------------------
template <typename T>
void Array<T>::resize(size_t size)
{
CVF_ASSERT(!m_sharedData);
if (size > 0)
{
if (m_data)
{
// Copy old data
T* pTmp = m_data;
m_data = new T[size];
size_t numToCopy = CVF_MIN(size, m_size);
cvf::System::memcpy(m_data, size*sizeof(T), pTmp, numToCopy*sizeof(T));
delete[] pTmp;
}
else
{
m_data = new T[size];
}
m_size = size;
m_capacity = size;
}
else
{
clear();
}
}
//--------------------------------------------------------------------------------------------------
/// Clear the array, freeing all memory (if not shared) and setting capacity and size to zero.
/// If the array was in shared mode, it will not be in shared mode anymore.
//--------------------------------------------------------------------------------------------------
template <typename T>
void Array<T>::clear()
{
if (!m_sharedData)
{
delete[] m_data;
}
ground();
}
//--------------------------------------------------------------------------------------------------
/// Returns the number of elements in the array
//--------------------------------------------------------------------------------------------------
template <typename T>
inline size_t Array<T>::size() const
{
return m_size;
}
//--------------------------------------------------------------------------------------------------
/// Set the element at the given index. Index must be < size()
//--------------------------------------------------------------------------------------------------
template <typename T>
inline void Array<T>::set(size_t index, const T& val)
{
CVF_TIGHT_ASSERT(index < m_size);
m_data[index] = val;
}
//--------------------------------------------------------------------------------------------------
/// Set all elements in the array to the given value
//--------------------------------------------------------------------------------------------------
template <typename T>
inline void Array<T>::setAll(const T& val)
{
size_t i;
for (i = 0; i < m_size; i++)
{
set(i, val);
}
}
//--------------------------------------------------------------------------------------------------
/// Assign consecutive values to the elements in the array
///
/// Example: setConsecutive(2) on an array with size=3 gives: {2,3,4}
//--------------------------------------------------------------------------------------------------
template <typename T>
void Array<T>::setConsecutive(const T& startValue)
{
T val = startValue;
size_t i;
for (i = 0; i < m_size; i++)
{
set(i, val++);
}
}
//--------------------------------------------------------------------------------------------------
/// Returns a const reference to the element at the given index
//--------------------------------------------------------------------------------------------------
template <typename T>
const T& cvf::Array<T>::get(size_t index) const
{
CVF_TIGHT_ASSERT(index < m_size);
return m_data[index];
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template <typename T>
T cvf::Array<T>::val(size_t index) const
{
CVF_TIGHT_ASSERT(index < m_size);
return m_data[index];
}
//--------------------------------------------------------------------------------------------------
/// Returns a const native pointer to the array storing the data
//--------------------------------------------------------------------------------------------------
template <typename T>
inline const T* Array<T>::ptr() const
{
CVF_TIGHT_ASSERT(this);
return m_data;
}
//--------------------------------------------------------------------------------------------------
/// Returns the native pointer to the array storing the data
//--------------------------------------------------------------------------------------------------
template <typename T>
inline T* Array<T>::ptr()
{
CVF_TIGHT_ASSERT(this);
return m_data;
}
//--------------------------------------------------------------------------------------------------
/// Returns a const native pointer to the array storing the data
//--------------------------------------------------------------------------------------------------
template <typename T>
inline const T* Array<T>::ptr(size_t index) const
{
CVF_TIGHT_ASSERT(this);
CVF_TIGHT_ASSERT(index < m_size);
return &m_data[index];
}
//--------------------------------------------------------------------------------------------------
/// Returns the native pointer to the array storing the data
//--------------------------------------------------------------------------------------------------
template <typename T>
inline T* Array<T>::ptr(size_t index)
{
CVF_TIGHT_ASSERT(this);
CVF_TIGHT_ASSERT(index < m_size);
return &m_data[index];
}
//--------------------------------------------------------------------------------------------------
/// Data shared with another class. Will not delete on destruction.
///
/// Any method that reallocates data (resize, assign & setPtr) is not allowed and will assert
/// The only way to break the shared 'connection' is via clear()
//--------------------------------------------------------------------------------------------------
template <typename T>
void Array<T>::setSharedPtr(T* data, size_t size)
{
CVF_ASSERT((data && size > 0) || (!data && size == 0));
clear();
m_data = data;
m_size = size;
m_sharedData = true;
}
//--------------------------------------------------------------------------------------------------
/// Set the data in the array to use the passed array.
///
/// This class takes ownership of the passed data.
//--------------------------------------------------------------------------------------------------
template <typename T>
void Array<T>::setPtr(T* data, size_t size)
{
CVF_ASSERT((data && size > 0) || (!data && size == 0));
// Not allowed
// The only way to break the shared 'connection' is via clear()
CVF_ASSERT(!m_sharedData);
clear();
m_data = data;
m_size = size;
}
//--------------------------------------------------------------------------------------------------
/// Delete any current data and set from the given data pointer
//--------------------------------------------------------------------------------------------------
template <typename T>
void Array<T>::assign(const T* data, size_t size)
{
CVF_ASSERT(data);
CVF_ASSERT(size > 0);
CVF_ASSERT(!m_sharedData);
clear();
resize(size);
// copy
cvf::System::memcpy(m_data, m_size*sizeof(T), data, size*sizeof(T));
}
//--------------------------------------------------------------------------------------------------
/// Delete any current data and set from the given data
//--------------------------------------------------------------------------------------------------
template <typename T>
void Array<T>::assign(const std::vector<T>& data)
{
CVF_ASSERT(!m_sharedData);
clear();
size_t newSize = data.size();
if (newSize > 0)
{
resize(newSize);
cvf::System::memcpy(m_data, m_size*sizeof(T), &data[0], newSize*sizeof(T));
}
}
//--------------------------------------------------------------------------------------------------
/// Copy data into the array
///
/// \warning Must have enough room for the new data, meaning the array must be resize()'ed before use
//--------------------------------------------------------------------------------------------------
template <typename T>
void Array<T>::copyData(const T* pSource, size_t numElementsToCopy, size_t destIndex)
{
CVF_ASSERT(pSource);
CVF_ASSERT(numElementsToCopy > 0);
CVF_ASSERT(destIndex < m_size);
CVF_ASSERT(destIndex + numElementsToCopy <= m_size);
cvf::System::memcpy(m_data + destIndex, (m_size - destIndex)*sizeof(T), pSource, numElementsToCopy*sizeof(T));
}
//--------------------------------------------------------------------------------------------------
/// Copy data into the array
///
/// \warning Must have enough room for the new data, meaning the array must be resize()'ed before use
//--------------------------------------------------------------------------------------------------
template <typename T>
void Array<T>::copyData(const Array<T>& source, size_t numElementsToCopy, size_t destIndex, size_t sourceIndex)
{
CVF_ASSERT(numElementsToCopy > 0);
CVF_ASSERT(destIndex < m_size);
CVF_ASSERT(numElementsToCopy + destIndex <= m_size);
cvf::System::memcpy(m_data + destIndex, (m_size - destIndex)*sizeof(T), source.ptr() + sourceIndex, numElementsToCopy*sizeof(T));
}
//--------------------------------------------------------------------------------------------------
/// Copy data into this array with conversion.
/// Data in source array will be converted using static_cast
//--------------------------------------------------------------------------------------------------
template <typename T>
template <typename U>
void Array<T>::copyConvertedData(const Array<U>& source, size_t numElementsToCopy, size_t destIndex, size_t sourceIndex)
{
CVF_ASSERT(numElementsToCopy > 0);
CVF_ASSERT(destIndex < m_size);
CVF_ASSERT(numElementsToCopy + destIndex <= m_size);
size_t dst = destIndex;
size_t i;
for (i = sourceIndex; i < sourceIndex + numElementsToCopy; i++)
{
m_data[dst++] = static_cast<T>(source[i]);
}
}
//--------------------------------------------------------------------------------------------------
/// Returns an array containing the specified elements
///
/// Example:
/// <PRE>
/// this = {2.0, 5.5, 100.0}
/// elementIndices = { 0, 2, 1, 0, 2}
/// -> output = {2.0, 100.0, 5.5, 2.0, 100.0}
/// </PRE>
//--------------------------------------------------------------------------------------------------
template <typename T>
template <typename U>
ref<Array<T> > Array<T>::extractElements(const Array<U>& elementIndices) const
{
ref<Array<T> > arr = new Array<T>;
size_t numItems = elementIndices.size();
if (numItems > 0)
{
arr->resize(numItems);
size_t i;
for (i = 0; i < numItems; i++)
{
U idx = elementIndices[i];
arr->set(i, get(idx));
}
}
return arr;
}
//--------------------------------------------------------------------------------------------------
/// Copy the contents of the array to the given std::vector
//--------------------------------------------------------------------------------------------------
template <typename T>
void Array<T>::toStdVector(std::vector<T>* vec) const
{
CVF_ASSERT(vec);
size_t numItems = size();
vec->resize(numItems);
size_t i;
for (i = 0; i < numItems; i++)
{
(*vec)[i] = (*this)[i];
}
}
//--------------------------------------------------------------------------------------------------
/// Get the current capacity of the array (the size of the buffer). This will return a number >= size(),
/// depending on if reserve() has been used or not.
/// If capacity() > size(), then add() is allowed on the array.
///
/// \sa
/// - reserve()
/// - add()
/// - squeeze()
/// - setSizeZero()
//--------------------------------------------------------------------------------------------------
template <typename T>
size_t Array<T>::capacity() const
{
return m_capacity;
}
//--------------------------------------------------------------------------------------------------
/// Reserve (allocate) at least the given number of items.
/// If capacity is less than the current buffer, nothing is done.
/// size() of the array is not changed.
///
/// \sa
/// - capacity()
/// - add()
/// - squeeze()
/// - setSizeZero()
//--------------------------------------------------------------------------------------------------
template <typename T>
void Array<T>::reserve(size_t capacity)
{
CVF_ASSERT(!m_sharedData);
if ((capacity <= m_size) || (capacity <= m_capacity))
{
// Required capacity is less than current capacity, done!
return;
}
CVF_ASSERT(capacity > 0);
CVF_ASSERT(capacity > m_size);
if (m_data)
{
// Copy old data
T* pTmp = m_data;
m_data = new T[capacity];
m_capacity = capacity;
cvf::System::memcpy(m_data, capacity*sizeof(T), pTmp, m_size*sizeof(T));
delete[] pTmp;
}
else
{
// alloc
m_data = new T[capacity];
m_capacity = capacity;
}
CVF_ASSERT(m_size <= m_capacity);
}
//--------------------------------------------------------------------------------------------------
/// Realloc the array to the current size(). Removing any reserved memory created by reserve().
///
/// \sa
/// - reserve()
/// - capacity()
/// - add()
/// - setSizeZero()
//--------------------------------------------------------------------------------------------------
template <typename T>
void Array<T>::squeeze()
{
CVF_ASSERT(!m_sharedData);
if (m_data && (m_size < m_capacity))
{
if (m_size > 0)
{
// Copy old data
T* pTmp = m_data;
m_data = new T[m_size];
cvf::System::memcpy(m_data, m_capacity*sizeof(T), pTmp, m_size*sizeof(T));
delete[] pTmp;
m_capacity = m_size;
}
else
{
clear();
}
}
}
//--------------------------------------------------------------------------------------------------
/// Set the size (number of items) in the array to zero, but keep the buffer. Items in the buffer
/// are not modified.
///
/// \sa
/// - reserve()
/// - capacity()
/// - add()
/// - squeeze()
//--------------------------------------------------------------------------------------------------
template <typename T>
void Array<T>::setSizeZero()
{
CVF_TIGHT_ASSERT(!m_sharedData);
m_size = 0;
}
//--------------------------------------------------------------------------------------------------
/// Add an item to the array.
///
/// Note that this will not grow the array, so the array needs to be pre-allocated with reserve()
/// before calling this method. The method will assert if not enough space.
///
/// \sa
/// - reserve()
/// - capacity()
/// - squeeze()
/// - setSizeZero()
//--------------------------------------------------------------------------------------------------
template <typename T>
inline void Array<T>::add(const T& val)
{
CVF_TIGHT_ASSERT(!m_sharedData);
CVF_TIGHT_ASSERT(m_size < m_capacity);
m_data[m_size] = val;
m_size++;
}
//--------------------------------------------------------------------------------------------------
/// Get the min value and optionally the index of the (first) min value
/// Works only on arrays with types that implement comparison operators
/// Empty arrays will return std::numeric_limits<T>::max() and not modify index
//--------------------------------------------------------------------------------------------------
template <typename T>
T Array<T>::min(size_t* index) const
{
T minVal = std::numeric_limits<T>::max();
size_t i;
for (i = 0; i < m_size; i++)
{
if (m_data[i] < minVal)
{
minVal = m_data[i];
if (index)
{
*index = i;
}
}
}
return minVal;
}
//--------------------------------------------------------------------------------------------------
/// Get the min value and optionally the index of the (first) min value
/// Works only on arrays with types that implement comparison operators
/// Empty arrays will return std::numeric_limits<T>::max() and not modify index
//--------------------------------------------------------------------------------------------------
template <typename T>
T Array<T>::max(size_t* index) const
{
T maxVal = std::numeric_limits<T>::min();
size_t i;
for (i = 0; i < m_size; i++)
{
if (m_data[i] > maxVal)
{
maxVal = m_data[i];
if (index)
{
*index = i;
}
}
}
return maxVal;
}
//--------------------------------------------------------------------------------------------------
/// Exchanges the contents of the two arrays.
///
/// \param other Modifiable reference to the array that should have its contents swapped.
///
/// \warning Note that signature differs from normal CeeVizFramework practice. This is done to be
/// consistent with the signature of std::swap()
//--------------------------------------------------------------------------------------------------
template <typename T>
void Array<T>::swap(Array& other)
{
using std::swap;
swap(m_size, other.m_size);
swap(m_capacity, other.m_capacity);
swap(m_data, other.m_data);
swap(m_sharedData, other.m_sharedData);
}
} // namespace cvf
+462
View File
@@ -0,0 +1,462 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#include "cvfBase.h"
#include "cvfAssert.h"
#include "cvfSystem.h"
#include <cstdlib>
#include <iostream>
#include <string>
#ifdef WIN32
#pragma warning (push)
#pragma warning (disable: 4668)
#include <windows.h>
#pragma warning (pop)
#include <io.h>
#include <signal.h>
#include <fcntl.h>
#endif
namespace cvf {
// User actions (interactive responses)
static const int USERACTION_CONTINUE = 0;
static const int USERACTION_DEBUGBREAK = 1;
static const int USERACTION_ABORT = 2;
//==================================================================================================
///
/// \class cvf::AssertHandler
/// \ingroup Core
///
/// Base class for assert handlers
///
//==================================================================================================
class AssertHandler
{
public:
virtual ~AssertHandler() {}
virtual Assert::FailAction handleAssert(const char* fileName, int lineNumber, const char* expr, const char* msg) = 0;
};
//==================================================================================================
///
/// \class cvf::AssertHandlerConsole
/// \ingroup Core
///
/// Assert handler for basic assert output to console
///
//==================================================================================================
class AssertHandlerConsole : public AssertHandler
{
public:
virtual Assert::FailAction handleAssert(const char* fileName, int lineNumber, const char* expr, const char* msg);
private:
static void reportToConsole(const char* fileName, int lineNumber, const char* expr, const char* msg);
static int askForUserActionUsingConsole();
#ifdef WIN32
static void winCreateConsoleAndRedirectIO(bool redirectInput);
#endif
};
//--------------------------------------------------------------------------------------------------
/// Show report of a failed assert in console and abort execution
///
/// On Windows, a console will be created if one doesn't exist (GUI applications)
//--------------------------------------------------------------------------------------------------
Assert::FailAction AssertHandlerConsole::handleAssert(const char* fileName, int lineNumber, const char* expr, const char* msg)
{
// Just shows assert message in console.
// Does the job on both Windows and Linux (creates a console on Windows if one doesn't exist)
reportToConsole(fileName, lineNumber, expr, msg);
abort();
// Shouldn't really matter since we always abort
return Assert::CONTINUE;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void AssertHandlerConsole::reportToConsole(const char* fileName, int lineNumber, const char* expr, const char* msg)
{
#ifdef WIN32
// Make sure we have a console (applicable to Windows GUI applications)
winCreateConsoleAndRedirectIO(false);
#endif
std::cerr << "Assertion failed:";
if (expr)
{
std::cerr << " (" << expr << ")";
}
if (msg)
{
std::cerr << " '" << msg << "'";
}
if (expr || msg)
{
std::cerr << ",";
}
std::cerr << " file " << fileName << ", line " << lineNumber << std::endl;
}
//--------------------------------------------------------------------------------------------------
/// Ask for user action using console input
///
/// \return One of the USERACTION_ constants
//--------------------------------------------------------------------------------------------------
int AssertHandlerConsole::askForUserActionUsingConsole()
{
#ifdef WIN32
// Make sure we have a console (applicable to Windows GUI applications)
// Also ensures that input is redirected
winCreateConsoleAndRedirectIO(true);
#endif
// Let abort be the default choice
#ifdef WIN32
std::cerr << "Choose action: [A]bort, [R]etry (debug) or [I]gnore: default [A]\n";
#else
std::cerr << "Choose action: [A]bort or [I]gnore: default [A]\n";
#endif
// Reset failstate, just in case.
std::cin.clear();
std::string line;
while (std::getline(std::cin, line))
{
int ch = 0;
if (!std::cin.fail() && line.length() == 1)
{
ch = tolower(line[0]);
}
if (ch == 'i')
{
return USERACTION_CONTINUE;
}
#ifdef WIN32
else if (ch == 'r')
{
return USERACTION_DEBUGBREAK;
}
#endif
else if (ch == 'a' || line.length() == 0)
{
return USERACTION_ABORT;
}
}
return USERACTION_ABORT;
}
//--------------------------------------------------------------------------------------------------
/// Creates a console and redirects I/O from/to it (Windows only)
///
/// \param redirectInput If true, input will also be redirected.
///
/// Function is useful for Windows GUI applications. Allocates a console if it doesn't exist and
/// then redirects output to the console. Also redirects input if \a redirectInput is true
//--------------------------------------------------------------------------------------------------
#ifdef WIN32
void AssertHandlerConsole::winCreateConsoleAndRedirectIO(bool redirectInput)
{
// Allocate a new console for this app
// Only one console can be associated with an app, so should fail if a console is already present.
AllocConsole();
bool redirStdOut = true;
bool redirStdErr = true;
bool redirStdIn = redirectInput;
if (redirStdOut)
{
HANDLE stdHandle = GetStdHandle(STD_OUTPUT_HANDLE);
int fileDescriptor = _open_osfhandle((intptr_t)stdHandle, _O_TEXT);
FILE* fp = _fdopen(fileDescriptor, "w");
*stdout = *fp;
setvbuf(stdout, NULL, _IONBF, 0);
}
if (redirStdErr)
{
HANDLE stdHandle = GetStdHandle(STD_ERROR_HANDLE);
int fileDescriptor = _open_osfhandle((intptr_t)stdHandle, _O_TEXT);
FILE* fp = _fdopen(fileDescriptor, "w");
*stderr = *fp;
setvbuf(stderr, NULL, _IONBF, 0);
}
if (redirStdIn)
{
HANDLE stdHandle = GetStdHandle(STD_INPUT_HANDLE);
int fileDescriptor = _open_osfhandle((intptr_t)stdHandle, _O_TEXT);
FILE* fp = _fdopen(fileDescriptor, "r");
*stdin = *fp;
setvbuf(stdin, NULL, _IONBF, 0);
}
// Make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog point to console as well
std::ios::sync_with_stdio();
}
#endif
//==================================================================================================
///
/// \class cvf::AssertHandlerWinDialog
/// \ingroup Core
///
/// Assert handler for Windows, using a dialog with interaction
///
//==================================================================================================
#ifdef WIN32
class AssertHandlerWinDialog : public AssertHandler
{
public:
virtual Assert::FailAction handleAssert(const char* fileName, int lineNumber, const char* expr, const char* msg);
private:
static int handleUsingDialog(const char* fileName, int lineNumber, const char* expr, const char* msg);
#ifdef _DEBUG
static int handleUsingCrtDbgReport(const char* fileName, int lineNumber, const char* expr, const char* msg);
#endif
};
#endif
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
#ifdef WIN32
Assert::FailAction AssertHandlerWinDialog::handleAssert(const char* fileName, int lineNumber, const char* expr, const char* msg)
{
//int retVal = handleUsingCrtDbgReport(fileName, lineNumber, expr, msg);
int retVal = handleUsingDialog(fileName, lineNumber, expr, msg);
if (retVal == USERACTION_CONTINUE)
{
return Assert::CONTINUE;
}
else if (retVal == USERACTION_DEBUGBREAK)
{
return Assert::DEBUGBREAK;
}
else if (retVal == USERACTION_ABORT)
{
// From __crtMessageWindow() in response to user clicking abort button
// Note that it is better NOT to call abort() here, because the default implementation of abort() will call Watson
// raise abort signal
raise(SIGABRT);
// We usually won't get here, but it's possible that SIGABRT was ignored.
// So exit the program anyway.
_exit(3);
}
// Shouldn't be getting here
abort();
return Assert::CONTINUE;
}
#endif
//--------------------------------------------------------------------------------------------------
/// Shows message in interactive dialog and lets user choose how to proceed
///
/// \return Returns one of the USERACTION_ constants depending on which button the user chooses.
///
/// Compared to the handleUsingCrtDbgReport() function, this function will also work in release builds
/// As opposed to the handleUsingCrtDbgReport(), this function will not call abort, but will return
/// USERACTION_ABORT instead.
///
/// \todo Must add code to handle case where new assert is triggered while handling an assert
//--------------------------------------------------------------------------------------------------
#ifdef WIN32
int AssertHandlerWinDialog::handleUsingDialog(const char* fileName, int lineNumber, const char* expr, const char* msg)
{
char szMsgBuf[2048];
System::strcpy(szMsgBuf, sizeof(szMsgBuf), "Assertion failed\n");
System::strcat(szMsgBuf, sizeof(szMsgBuf), "\nFile: ");
if (fileName)
{
System::strcat(szMsgBuf, sizeof(szMsgBuf), fileName);
}
System::strcat(szMsgBuf, sizeof(szMsgBuf), "\nLine: ");
if (lineNumber >= 0)
{
char szLinNumBuf[20];
System::sprintf(szLinNumBuf, sizeof(szLinNumBuf), "%d", lineNumber);
System::strcat(szMsgBuf, sizeof(szMsgBuf), szLinNumBuf);
}
if (expr)
{
System::strcat(szMsgBuf, sizeof(szMsgBuf), "\n\n");
System::strcat(szMsgBuf, sizeof(szMsgBuf), "Expression: ");
System::strcat(szMsgBuf, sizeof(szMsgBuf), expr);
}
if (msg)
{
System::strcat(szMsgBuf, sizeof(szMsgBuf), "\n\n");
System::strcat(szMsgBuf, sizeof(szMsgBuf), msg);
}
System::strcat(szMsgBuf, sizeof(szMsgBuf), "\n\n(Press Retry to debug application)");
int retVal = ::MessageBoxA(NULL, szMsgBuf, "Assertion Failed", MB_TASKMODAL|MB_ICONHAND|MB_ABORTRETRYIGNORE|MB_SETFOREGROUND);
if (retVal == IDIGNORE) return USERACTION_CONTINUE;
else if (retVal == IDRETRY) return USERACTION_DEBUGBREAK;
else return USERACTION_ABORT;
}
#endif
//--------------------------------------------------------------------------------------------------
/// Wrapper function for the CRT _CrtDbgReport() function
///
/// This function never returns if the user chooses 'Abort'
/// Note that the underlying function is only available in debug builds
//--------------------------------------------------------------------------------------------------
#if defined WIN32 && defined _DEBUG
int AssertHandlerWinDialog::handleUsingCrtDbgReport(const char* fileName, int lineNumber, const char* expr, const char* msg)
{
// Create message combining expression and message
char szMsgBuf[2048];
szMsgBuf[0] = '\0';
if (expr)
{
System::strcat(szMsgBuf, sizeof(szMsgBuf), expr);
}
if (msg)
{
System::strcat(szMsgBuf, sizeof(szMsgBuf), "\n");
System::strcat(szMsgBuf, sizeof(szMsgBuf), msg);
}
int retVal = _CrtDbgReport(_CRT_ASSERT, fileName, lineNumber, NULL, szMsgBuf);
if (retVal == 0) return USERACTION_CONTINUE;
else if (retVal == 1) return USERACTION_DEBUGBREAK;
else return USERACTION_ABORT;
}
#endif
//==================================================================================================
///
/// \class cvf::Assert
/// \ingroup Core
///
/// Helper class to customize assert
///
//==================================================================================================
#ifdef WIN32
AssertHandler* Assert::sm_handler = new AssertHandlerWinDialog;
#else
AssertHandler* Assert::sm_handler = new AssertHandlerConsole;
#endif
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Assert::setReportMode(ReportMode reportMode)
{
#ifndef WIN32
if (reportMode == INTERACTIVE_DIALOG) return;
#endif
delete sm_handler;
sm_handler = NULL;
if (reportMode == CONSOLE)
{
sm_handler = new AssertHandlerConsole;
}
#ifdef WIN32
else if (reportMode == INTERACTIVE_DIALOG)
{
sm_handler = new AssertHandlerWinDialog;
}
#endif
}
//--------------------------------------------------------------------------------------------------
/// Show report of a failed assert
///
/// If assertions are configured to be interactive, a message box will be shown on Windows and
/// the user may opt to ignore or trigger debugging.
/// On Linux, or if interactive asserts are disabled, the application will terminate.
///
/// \todo Add handling of cases where we get another assert while processing the first one AND
/// asserts from multiple threads.
//--------------------------------------------------------------------------------------------------
Assert::FailAction Assert::reportFailedAssert(const char* fileName, int lineNumber, const char* expr, const char* msg)
{
if (sm_handler)
{
return sm_handler->handleAssert(fileName, lineNumber, expr, msg);
}
else
{
abort();
return CONTINUE;
}
}
} // namespace cvf
+87
View File
@@ -0,0 +1,87 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
namespace cvf {
// Forward of base class for assert handlers
class AssertHandler;
//==================================================================================================
//
// Helper class to customize assert behavior
//
//==================================================================================================
class Assert
{
public:
enum ReportMode
{
CONSOLE, // Report asserts to console only and then abort. (default mode for Linux)
INTERACTIVE_DIALOG // Show message in dialog and ask for user action (Windows only, default mode on Windows)
};
enum FailAction
{
CONTINUE, // Continue execution
DEBUGBREAK // Execution should be stopped and debugger should be triggered (currently windows only)
};
public:
static void setReportMode(ReportMode reportMode);
static FailAction reportFailedAssert(const char* fileName, int lineNumber, const char* expr, const char* msg);
private:
static AssertHandler* sm_handler;
};
} // cvf
// Define to trigger debug trap for use with assert macros
// Currently only useful and in action on windows
#ifdef WIN32
#define CVF_DEBUGTRAP() __debugbreak()
#else
#define CVF_DEBUGTRAP() ((void)0)
#endif
// Define our assert macros
#if CVF_ENABLE_ASSERTS == 1
# define CVF_ASSERT(expr) (void)( (!!(expr)) || (cvf::Assert::CONTINUE == cvf::Assert::reportFailedAssert(__FILE__, __LINE__, #expr, NULL)) || (CVF_DEBUGTRAP(), 0) )
# define CVF_ASSERT_MSG(expr, msg) (void)( (!!(expr)) || (cvf::Assert::CONTINUE == cvf::Assert::reportFailedAssert(__FILE__, __LINE__, #expr, (msg))) || (CVF_DEBUGTRAP(), 0) )
# define CVF_FAIL_MSG(msg) (void)( (cvf::Assert::CONTINUE == cvf::Assert::reportFailedAssert(__FILE__, __LINE__, NULL, (msg))) || (CVF_DEBUGTRAP(), 0) )
#else
# define CVF_ASSERT(expr) ((void)0)
# define CVF_ASSERT_MSG(expr, msg) ((void)0)
# define CVF_FAIL_MSG(msg) ((void)0)
#endif
#if CVF_ENABLE_TIGHT_ASSERTS == 1 && CVF_ENABLE_ASSERTS == 1
# define CVF_TIGHT_ASSERT(expr) CVF_ASSERT(expr)
# define CVF_TIGHT_ASSERT_MSG(expr, msg) CVF_ASSERT_MSG(expr, msg)
#else
# define CVF_TIGHT_ASSERT(expr) ((void)0)
# define CVF_TIGHT_ASSERT_MSG(expr, msg) ((void)0)
#endif
+99
View File
@@ -0,0 +1,99 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
#if !defined(WIN32) && !defined(CVF_LINUX) && !defined(CVF_IOS) && !defined(CVF_OSX)
#error No platform defined
#endif
// Global include file with definitions useful for all CeeVizFramework files
// Disable some annoying warnings so we can compile with warning level Wall
#ifdef WIN32
// 4512 'class' : assignment operator could not be generated : Due to problems with classes with reference member variables (e.g. VertexCompactor)
// 4514 unreferenced inline/local function has been removed
// 4625 copy constructor could not be generated because a base class copy constructor is inaccessible
// 4626 assignment operator could not be generated because a base class assignment operator is inaccessible
// 4640 'staticInstance' : construction of local static object is not thread-safe -> used by singletons. To be revisited.
// 4710 function 'func_name' not inlined
// 4711 function 'func_name' selected for automatic inline expansion
// 4738 storing 32-bit float result in memory, possible loss of performance
// 4820 'bytes' bytes padding added after construct 'member_name'
// 4986 'operator new[]': exception specification does not match previous declaration
#pragma warning (disable: 4512 4514 4625 4626 4640 4710 4711 4738 4820 4986)
#endif
// Helper macro to disable (ignore) compiler warnings on GCC
// The needed pragma is only available in GCC for versions 4.2.x and above
#if defined __GNUC__ && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 402)
#define CVF_DO_PRAGMA(x) _Pragma(#x)
#define CVF_GCC_DIAGNOSTIC_IGNORE(OPTION_STRING) CVF_DO_PRAGMA(GCC diagnostic ignored OPTION_STRING)
#else
#define CVF_GCC_DIAGNOSTIC_IGNORE(OPTION_STRING)
#endif
#if defined(CVF_LINUX) || defined(CVF_IOS) || defined(CVF_OSX)
// Used by int64_t on *nix below
#include <stdint.h>
#endif
// Brings in size_t and definition of NULL
#include <cstddef>
// Added due to conflict between std::min/max and define in Windows.h
#define CVF_MIN(X, Y) ((X) < (Y) ? (X) : (Y))
#define CVF_MAX(X, Y) ((X) > (Y) ? (X) : (Y))
// Macro for avoiding "unused parameter" warnings
// The bottom one is the best alternative, but unfortunately doesn't work on VS2010
#ifdef WIN32
#define CVF_UNUSED(EXPR) (void)(EXPR);
#else
#define CVF_UNUSED(EXPR) (void)sizeof(EXPR);
#endif
// Macro to disable the copy constructor and assignment operator
// Should be used in the private section of a class
#define CVF_DISABLE_COPY_AND_ASSIGN(CLASS_NAME) \
CLASS_NAME(const CLASS_NAME&); \
void operator=(const CLASS_NAME&)
/// Ceetron Visualization Framework namespace
namespace cvf {
typedef unsigned char ubyte;
typedef unsigned short ushort;
typedef unsigned int uint;
// 64bit integer support via the int64 type
#ifdef WIN32
typedef __int64 int64;
#elif defined(CVF_LINUX) || defined(CVF_IOS) || defined(CVF_OSX)
typedef int64_t int64;
#endif
}
#include "cvfConfigCore.h"
#include "cvfVersion.h"
#include "cvfAssert.h"
+208
View File
@@ -0,0 +1,208 @@
//##################################################################################################
//
// CeeVizFramework
// Lib: LibCore
//
// --------------------------------------------------------------------------------------------
// Please see references below for copyright, usage rights and license for this file.
//##################################################################################################
#include "cvfBase.h"
#include "cvfBase64.h"
#ifdef WIN32
#pragma warning (disable: 4242 4244 4267 4365)
#endif
CVF_GCC_DIAGNOSTIC_IGNORE("-Wconversion")
CVF_GCC_DIAGNOSTIC_IGNORE("-Wunused-parameter")
#ifdef CVF_LINUX
#include <stdio.h>
#include <stdlib.h>
#endif
// Doxygen conditional section to hide contents of the cvf_base64 namespace
/// \cond CVF_NEVER_INCLUDE
namespace cvf_base64
{
//## START -- base64.cpp
//////////////////////////////////////////////////////////////////////////
// start include
// base64.h
//////////////////////////////////////////////////////////////////////////
/*
base64.cpp and base64.h
Copyright (C) 2004-2008 Rene Nyffenegger
This source code is provided 'as-is', without any express or implied
warranty. In no event will the author be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this source code must not be misrepresented; you must not
claim that you wrote the original source code. If you use this source code
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original source code.
3. This notice may not be removed or altered from any source distribution.
Rene Nyffenegger rene.nyffenegger@adp-gmbh.ch
*/
// Commented out by Ceetron
//#include "base64.h"
//#include <iostream>
static const std::string base64_chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";
static inline bool is_base64(unsigned char c) {
return (isalnum(c) || (c == '+') || (c == '/'));
}
std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len) {
std::string ret;
int i = 0;
int j = 0;
unsigned char char_array_3[3];
unsigned char char_array_4[4];
while (in_len--) {
char_array_3[i++] = *(bytes_to_encode++);
if (i == 3) {
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;
for(i = 0; (i <4) ; i++)
ret += base64_chars[char_array_4[i]];
i = 0;
}
}
if (i)
{
for(j = i; j < 3; j++)
char_array_3[j] = '\0';
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;
for (j = 0; (j < i + 1); j++)
ret += base64_chars[char_array_4[j]];
while((i++ < 3))
ret += '=';
}
return ret;
}
std::string base64_decode(std::string const& encoded_string) {
int in_len = encoded_string.size();
int i = 0;
int j = 0;
int in_ = 0;
unsigned char char_array_4[4], char_array_3[3];
std::string ret;
while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
char_array_4[i++] = encoded_string[in_]; in_++;
if (i ==4) {
for (i = 0; i <4; i++)
char_array_4[i] = base64_chars.find(char_array_4[i]);
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
for (i = 0; (i < 3); i++)
ret += char_array_3[i];
i = 0;
}
}
if (i) {
for (j = i; j <4; j++)
char_array_4[j] = 0;
for (j = 0; j <4; j++)
char_array_4[j] = base64_chars.find(char_array_4[j]);
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
for (j = 0; (j < i - 1); j++) ret += char_array_3[j];
}
return ret;
}
//## END -- base64.cpp
} // namespace cvf_base64
// End of Doxygen conditional section
/// \endcond
namespace cvf {
//==================================================================================================
///
/// \class cvf::Base64
/// \ingroup Core
///
///
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
/// Encode a binary buffer
//--------------------------------------------------------------------------------------------------
std::string Base64::encode(const cvf::UByteArray& data)
{
return (data.size() > 0) ? cvf_base64::base64_encode(data.ptr(), data.size()) : "";
}
//--------------------------------------------------------------------------------------------------
/// Decode already encoded data. Array returned is NULL if unable to decode
//--------------------------------------------------------------------------------------------------
cvf::ref<cvf::UByteArray> Base64::decode(const std::string& encodedData)
{
if (encodedData.size() < 1) return NULL;
std::string decodedData = cvf_base64::base64_decode(encodedData);
size_t numDecodedBytes = decodedData.length();
if (numDecodedBytes == 0) return NULL;
cvf::UByteArray* data = new cvf::UByteArray;
data->resize(numDecodedBytes);
data->copyData(reinterpret_cast<const unsigned char*>(decodedData.c_str()), numDecodedBytes, 0);
return data;
}
} // namespace cvf
+42
View File
@@ -0,0 +1,42 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include "cvfString.h"
#include "cvfArray.h"
namespace cvf {
//==================================================================================================
//
// Base64 encoding and decoding for representing binary data in an ASCII string format by
// translating it into a radix-64 representation.
//
//==================================================================================================
class Base64
{
public:
static std::string encode(const cvf::UByteArray& data);
static cvf::ref<cvf::UByteArray> decode(const std::string& encodedData);
};
}
@@ -0,0 +1,165 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#include "cvfBase.h"
#include "cvfCharArray.h"
#include "cvfSystem.h"
#include <sstream>
#include <iomanip>
namespace cvf {
//==================================================================================================
///
/// \class cvf::CharArray
/// \ingroup Core
///
/// 8 bit zero terminated char array.
///
/// Behind the scenes, the array always has a 0 termination sentinel.
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
CharArray::CharArray()
{
m_data.push_back('\0');
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
CharArray::CharArray(size_t size, char c)
{
resize(size);
size_t i;
for (i = 0; i < size; i++)
{
m_data[i] = c;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
CharArray::CharArray(const char* str)
{
size_t numChars = System::strlen(str);
resize(numChars);
size_t i;
for (i = 0; i < numChars; i++)
{
m_data[i] = str[i];
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
char& CharArray::operator[](size_t i)
{
CVF_TIGHT_ASSERT(i < m_data.size() - 1);
return m_data[i];
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const char& CharArray::operator[](size_t i) const
{
CVF_TIGHT_ASSERT(i < m_data.size() - 1);
return m_data[i];
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void CharArray::resize(size_t size)
{
m_data.resize(size + 1, '\0');
m_data[size] = '\0';
}
//--------------------------------------------------------------------------------------------------
/// Add a character to the array. Array grows if necessary.
//--------------------------------------------------------------------------------------------------
void CharArray::push_back(char c)
{
CVF_TIGHT_ASSERT(m_data.size() > 0);
m_data[m_data.size() - 1] = c;
m_data.push_back('\0');
}
//--------------------------------------------------------------------------------------------------
/// Get the size of the character array.
///
/// Note that this is not necessarily the length of the contained string. In order to get the string
/// length, you must call System::strlen().
//--------------------------------------------------------------------------------------------------
size_t CharArray::size() const
{
CVF_TIGHT_ASSERT(m_data.size() > 0);
return m_data.size() - 1;
}
//--------------------------------------------------------------------------------------------------
/// Get a const char* pointer to the string
//--------------------------------------------------------------------------------------------------
const char* CharArray::ptr() const
{
CVF_ASSERT(m_data.size() > 0);
CVF_ASSERT(m_data[m_data.size() - 1] == '\0');
return &m_data[0];
}
//--------------------------------------------------------------------------------------------------
/// Get a const char* pointer to the string
//--------------------------------------------------------------------------------------------------
char* CharArray::ptr()
{
CVF_ASSERT(m_data.size() > 0);
CVF_ASSERT(m_data[m_data.size() - 1] == '\0');
return &m_data[0];
}
} // namespace cvf
@@ -0,0 +1,53 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include <vector>
namespace cvf {
//==================================================================================================
//
// 8 bit zero terminated char array
//
//==================================================================================================
class CharArray
{
public:
CharArray();
CharArray(size_t size, char c);
explicit CharArray(const char* str);
char& operator[](size_t i);
const char& operator[](size_t i) const;
void resize(size_t size);
void push_back(char c);
size_t size() const;
const char* ptr() const;
char* ptr();
private:
std::vector<char> m_data;
};
}
@@ -0,0 +1,83 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include "cvfObject.h"
#include "cvfMath.h"
#include <vector>
#include <algorithm>
namespace cvf {
//==================================================================================================
//
// A collection class for reference counted objects (that derive from Object)
//
//==================================================================================================
template<typename T>
class Collection
{
public:
Collection();
Collection(const Collection& other);
explicit Collection(const std::vector< ref<T> >& vector);
Collection& operator=(Collection rhs);
Collection& operator=(const std::vector< ref<T> >& vector);
const ref<T>& operator[](size_t index) const;
ref<T>& operator[](size_t index);
void push_back(T* data);
const T* at(size_t index) const;
T* at(size_t index);
void resize(size_t size);
size_t size() const;
void reserve(size_t capacity);
size_t capacity() const;
void clear();
bool empty() const;
bool contains(const T* data) const;
size_t indexOf(const T* data) const;
void erase(const T* data);
void eraseAt(size_t index);
void swap(Collection& other);
// Iterator support
public:
typedef typename std::vector<ref<T> >::iterator iterator;
typedef typename std::vector<ref<T> >::const_iterator const_iterator;
iterator begin();
iterator end();
const_iterator begin() const;
const_iterator end() const;
private:
std::vector<ref<T> > m_vector;
};
}
#include "cvfCollection.inl"
@@ -0,0 +1,314 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
namespace cvf {
//==================================================================================================
///
/// \class cvf::Collection
/// \ingroup Core
///
/// A collection class for reference counted objects (that derive from Object).
///
/// The class add a reference to all objects when added to the array, and releases them when removed
/// from the array.
///
/// The class exposes the same public interface as a std::vector, so see the STL documentation
/// for documentation on most of the methods.
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
/// Default constructor. Create an empty collection
//--------------------------------------------------------------------------------------------------
template<typename T>
Collection<T>::Collection()
{
}
//--------------------------------------------------------------------------------------------------
/// Copy constructor
//--------------------------------------------------------------------------------------------------
template<typename T>
Collection<T>::Collection(const Collection& other)
: m_vector(other.m_vector)
{
}
//--------------------------------------------------------------------------------------------------
/// Create a collection and copy the contents from the passed collection
//--------------------------------------------------------------------------------------------------
template<typename T>
Collection<T>::Collection(const std::vector< ref<T> >& vector)
: m_vector(vector)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename T>
Collection<T>& Collection<T>::operator=(Collection rhs)
{
rhs.swap(*this);
return *this;
}
//--------------------------------------------------------------------------------------------------
/// Set the collection to contain the same elements as the passed collection
//--------------------------------------------------------------------------------------------------
template<typename T>
Collection<T>& Collection<T>::operator=(const std::vector< ref<T> >& vector)
{
m_vector = vector;
return *this;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename T>
const ref<T>& Collection<T>::operator[](size_t index) const
{
return m_vector[index];
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename T>
ref<T>& Collection<T>::operator[](size_t index)
{
return m_vector[index];
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename T>
void Collection<T>::push_back(T* data)
{
m_vector.push_back(data);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename T>
const T* Collection<T>::at(size_t index) const
{
return m_vector[index].p();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename T>
T* Collection<T>::at(size_t index)
{
return m_vector[index].p();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename T>
void Collection<T>::resize(size_t size)
{
m_vector.resize(size);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename T>
size_t Collection<T>::size() const
{
return m_vector.size();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename T>
void Collection<T>::reserve(size_t capacity)
{
m_vector.reserve(capacity);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename T>
size_t Collection<T>::capacity() const
{
return m_vector.capacity();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename T>
void Collection<T>::clear()
{
m_vector.clear();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename T>
bool Collection<T>::empty() const
{
return m_vector.empty();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename T>
bool Collection<T>::contains(const T* data) const
{
if (std::find(m_vector.begin(), m_vector.end(), data) != m_vector.end())
{
return true;
}
else
{
return false;
}
}
//--------------------------------------------------------------------------------------------------
/// Find index of the first occurence of the specified element
///
/// Returns UNDEFINED_SIZE_T if element could not be found
//--------------------------------------------------------------------------------------------------
template<typename T>
size_t Collection<T>::indexOf(const T* data) const
{
typename std::vector<ref<T> >::const_iterator it = std::find(m_vector.begin(), m_vector.end(), data);
if (it != m_vector.end())
{
return static_cast<size_t>(it - m_vector.begin());
}
else
{
return UNDEFINED_SIZE_T;
}
}
//--------------------------------------------------------------------------------------------------
/// Erase the specified element
//--------------------------------------------------------------------------------------------------
template<typename T>
void Collection<T>::erase(const T* data)
{
typename std::vector<ref<T> >::iterator it = std::find(m_vector.begin(), m_vector.end(), data);
if (it != m_vector.end())
{
m_vector.erase(it);
}
}
//--------------------------------------------------------------------------------------------------
/// Erase the element at the specified index
//--------------------------------------------------------------------------------------------------
template<typename T>
void Collection<T>::eraseAt(size_t index)
{
CVF_ASSERT(index < m_vector.size());
// Cast may have to be to std::vector<T>::difference_type
m_vector.erase(m_vector.begin() + static_cast<ptrdiff_t>(index));
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename T>
void Collection<T>::swap(Collection& other)
{
m_vector.swap(other.m_vector);
}
//--------------------------------------------------------------------------------------------------
/// Return iterator to beginning
//--------------------------------------------------------------------------------------------------
template<typename T>
typename Collection<T>::iterator Collection<T>::begin()
{
return m_vector.begin();
}
//--------------------------------------------------------------------------------------------------
/// Return iterator to end
//--------------------------------------------------------------------------------------------------
template<typename T>
typename Collection<T>::iterator Collection<T>::end()
{
return m_vector.end();
}
//--------------------------------------------------------------------------------------------------
/// Return const iterator to beginning
//--------------------------------------------------------------------------------------------------
template<typename T>
typename Collection<T>::const_iterator Collection<T>::begin() const
{
return m_vector.begin();
}
//--------------------------------------------------------------------------------------------------
/// Return const iterator to end
//--------------------------------------------------------------------------------------------------
template<typename T>
typename Collection<T>::const_iterator Collection<T>::end() const
{
return m_vector.end();
}
} // namespace cvf
+532
View File
@@ -0,0 +1,532 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#include "cvfBase.h"
#include "cvfColor3.h"
#include "cvfMath.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::Color3
/// \ingroup Core
///
/// Abstract base class for 3-component RGB colors.
///
/// Currently, this class only contains the ColorIdent enums,
//==================================================================================================
//==================================================================================================
///
/// \class cvf::Color3f
/// \ingroup Core
///
/// Class for storing and manipulating 3-component RGB floating point colors
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
/// Default constructor, initializes all color components to 0.0
//--------------------------------------------------------------------------------------------------
Color3f::Color3f()
{
m_rgb[0] = 0.0f;
m_rgb[1] = 0.0f;
m_rgb[2] = 0.0f;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Color3f::Color3f(float r, float g, float b)
{
m_rgb[0] = r;
m_rgb[1] = g;
m_rgb[2] = b;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Color3f::Color3f(const Color3f& other)
{
m_rgb[0] = other.m_rgb[0];
m_rgb[1] = other.m_rgb[1];
m_rgb[2] = other.m_rgb[2];
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Color3f::Color3f(ColorIdent colorIdent)
{
Color3ub byteColor(colorIdent);
*this = Color3f::fromByteColor(byteColor.r(), byteColor.g(), byteColor.b());
}
//--------------------------------------------------------------------------------------------------
/// Explicit conversion constructor from byte color
//--------------------------------------------------------------------------------------------------
Color3f::Color3f(const Color3ub& byteColor)
{
*this = Color3f::fromByteColor(byteColor.r(), byteColor.g(), byteColor.b());
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Color3f& Color3f::operator=(const Color3f& rhs)
{
m_rgb[0] = rhs.m_rgb[0];
m_rgb[1] = rhs.m_rgb[1];
m_rgb[2] = rhs.m_rgb[2];
return *this;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Color3f& Color3f::operator=(ColorIdent colorIdent)
{
return operator=(Color3f(colorIdent));
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool Color3f::operator==(const Color3f& rhs) const
{
if (m_rgb[0] == rhs.m_rgb[0] &&
m_rgb[1] == rhs.m_rgb[1] &&
m_rgb[2] == rhs.m_rgb[2])
{
return true;
}
else
{
return false;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool Color3f::operator!=(const Color3f& rhs) const
{
return !operator==(rhs);
}
//--------------------------------------------------------------------------------------------------
/// Returns the red color component of this color
//--------------------------------------------------------------------------------------------------
float Color3f::r() const
{
return m_rgb[0];
}
//--------------------------------------------------------------------------------------------------
/// Returns the green color component of this color
//--------------------------------------------------------------------------------------------------
float Color3f::g() const
{
return m_rgb[1];
}
//--------------------------------------------------------------------------------------------------
/// Returns the blue color component of this color
//--------------------------------------------------------------------------------------------------
float Color3f::b() const
{
return m_rgb[2];
}
//--------------------------------------------------------------------------------------------------
/// Get modifiable reference to the red color component.
///
/// Used for setting the color, e.g. <tt>r() = 0.5f</tt>
//--------------------------------------------------------------------------------------------------
float& Color3f::r()
{
return m_rgb[0];
}
//--------------------------------------------------------------------------------------------------
/// Get modifiable reference to the green color component.
///
/// Used for setting the color, e.g. <tt>g() = 0.5f</tt>
//--------------------------------------------------------------------------------------------------
float& Color3f::g()
{
return m_rgb[1];
}
//--------------------------------------------------------------------------------------------------
/// Get modifiable reference to the blue color component.
///
/// Used for setting the color, e.g. <tt>b() = 0.5f</tt>
//--------------------------------------------------------------------------------------------------
float& Color3f::b()
{
return m_rgb[2];
}
//--------------------------------------------------------------------------------------------------
/// Sets all color components
//--------------------------------------------------------------------------------------------------
void Color3f::set(float r, float g, float b)
{
m_rgb[0] = r;
m_rgb[1] = g;
m_rgb[2] = b;
}
//--------------------------------------------------------------------------------------------------
/// Query whether this color is valid
///
/// For a color to be considered valid, all the component values must be in the range 0.0 to 1.0
//--------------------------------------------------------------------------------------------------
bool Color3f::isValid() const
{
if (!Math::valueInRange(m_rgb[0], 0.0f, 1.0f)) return false;
if (!Math::valueInRange(m_rgb[1], 0.0f, 1.0f)) return false;
if (!Math::valueInRange(m_rgb[2], 0.0f, 1.0f)) return false;
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const float* Color3f::ptr() const
{
return m_rgb;
}
//--------------------------------------------------------------------------------------------------
/// Get red component as byte color (unsigned char)
//--------------------------------------------------------------------------------------------------
unsigned char Color3f::rByte() const
{
int val = static_cast<int>(m_rgb[0]*255.0f + 0.5f);
if (val < 0) return 0;
else if (val > 255) return 255;
else return static_cast<unsigned char>(val);
}
//--------------------------------------------------------------------------------------------------
/// Get green component as byte color (unsigned char)
//--------------------------------------------------------------------------------------------------
unsigned char Color3f::gByte() const
{
int val = static_cast<int>(m_rgb[1]*255.0f + 0.5f);
if (val < 0) return 0;
else if (val > 255) return 255;
else return static_cast<unsigned char>(val);
}
//--------------------------------------------------------------------------------------------------
/// Get blue component as a byte color (unsigned char)
//--------------------------------------------------------------------------------------------------
unsigned char Color3f::bByte() const
{
int val = static_cast<int>(m_rgb[2]*255.0f + 0.5f);
if (val < 0) return 0;
else if (val > 255) return 255;
else return static_cast<unsigned char>(val);
}
//--------------------------------------------------------------------------------------------------
/// Static function to construct a Color3f object from byte RGB values.
///
/// All the values parameter values should be in the range 0-255. The returned object will always
/// have its components clamped to the range 0.0 to 1.0
//--------------------------------------------------------------------------------------------------
Color3f Color3f::fromByteColor(ubyte r, ubyte g, ubyte b)
{
// Constructor sets all elements to 0
Color3f c;
c.m_rgb[0] = static_cast<float>(r)/255.0f;
c.m_rgb[1] = static_cast<float>(g)/255.0f;
c.m_rgb[2] = static_cast<float>(b)/255.0f;
return c;
}
//==================================================================================================
///
/// \class cvf::Color3ub
/// \ingroup Core
///
/// Class for storing unsigned byte RGB colors
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
/// Default constructor, initializes all color components to 0
//--------------------------------------------------------------------------------------------------
Color3ub::Color3ub()
{
m_rgb[0] = 0;
m_rgb[1] = 0;
m_rgb[2] = 0;
}
//--------------------------------------------------------------------------------------------------
/// Constructor with initialization of all components
//--------------------------------------------------------------------------------------------------
Color3ub::Color3ub(ubyte r, ubyte g, ubyte b)
{
m_rgb[0] = r;
m_rgb[1] = g;
m_rgb[2] = b;
}
//--------------------------------------------------------------------------------------------------
/// Copy constructor
//--------------------------------------------------------------------------------------------------
Color3ub::Color3ub(const Color3ub& other)
{
m_rgb[0] = other.m_rgb[0];
m_rgb[1] = other.m_rgb[1];
m_rgb[2] = other.m_rgb[2];
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Color3ub::Color3ub(ColorIdent colorIdent)
{
switch (colorIdent)
{
case RED: set(255, 0, 0); break;
case GREEN: set( 0, 255, 0); break;
case BLUE: set( 0, 0, 255); break;
case YELLOW: set(255, 255, 0); break;
case CYAN: set( 0, 255, 255); break;
case MAGENTA: set(255, 0, 255); break;
case WHITE: set(255, 255, 255); break;
case BLACK: set( 0, 0, 0); break;
case LIGHT_GRAY: set(192, 192, 192); break;
case GRAY: set(128, 128, 128); break;
case DARK_GRAY: set( 64, 64, 64); break;
case BROWN: set(165, 42, 42); break;
case CRIMSON: set(220, 20, 60); break;
case DARK_BLUE: set( 0, 0, 139); break;
case DARK_YELLOW: set(139, 139, 0); break;
case DARK_CYAN: set( 0, 139, 139); break;
case DARK_GREEN: set( 0, 100, 0); break;
case DARK_MAGENTA: set(139, 0, 139); break;
case DARK_ORANGE: set(255, 140, 0); break;
case DARK_RED: set(139, 0, 0); break;
case DARK_VIOLET: set(148, 0, 211); break;
case DEEP_PINK: set(255, 20, 147); break;
case FOREST_GREEN: set( 34, 139, 34); break;
case GOLD: set(255, 215, 0); break;
case GREEN_YELLOW: set(173, 255, 47); break;
case INDIGO: set( 75, 0, 130); break;
case OLIVE: set(128, 128, 0); break;
case ORANGE: set(255, 165, 0); break;
case ORANGE_RED: set(255, 69, 0); break;
case ORCHID: set(218, 112, 214); break;
case PINK: set(255, 192, 203); break;
case PURPLE: set(128, 0, 128); break;
case SEA_GREEN: set( 46, 139, 87); break;
case SKY_BLUE: set(135, 206, 235); break;
case VIOLET: set(238, 130, 238); break;
case YELLOW_GREEN: set(154, 205, 50); break;
default: CVF_FAIL_MSG("Unknown ColorIdent");
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Color3ub::Color3ub(const Color3f& other)
{
m_rgb[0] = static_cast<ubyte>(other.r()*255.0f);
m_rgb[1] = static_cast<ubyte>(other.g()*255.0f);
m_rgb[2] = static_cast<ubyte>(other.b()*255.0f);
}
//--------------------------------------------------------------------------------------------------
/// Assignment operator
//--------------------------------------------------------------------------------------------------
Color3ub& Color3ub::operator=(const Color3ub& rhs)
{
m_rgb[0] = rhs.m_rgb[0];
m_rgb[1] = rhs.m_rgb[1];
m_rgb[2] = rhs.m_rgb[2];
return *this;
}
//--------------------------------------------------------------------------------------------------
/// Assignment from ColorIdent
//--------------------------------------------------------------------------------------------------
Color3ub& Color3ub::operator=(ColorIdent colorIdent)
{
return operator=(Color3ub(colorIdent));
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool Color3ub::operator==(const Color3ub& rhs) const
{
if (m_rgb[0] == rhs.m_rgb[0] &&
m_rgb[1] == rhs.m_rgb[1] &&
m_rgb[2] == rhs.m_rgb[2])
{
return true;
}
else
{
return false;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool Color3ub::operator!=(const Color3ub& rhs) const
{
return !operator==(rhs);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
ubyte Color3ub::r() const
{
return m_rgb[0];
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
ubyte Color3ub::g() const
{
return m_rgb[1];
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
ubyte Color3ub::b() const
{
return m_rgb[2];
}
//--------------------------------------------------------------------------------------------------
/// Get modifiable reference to the red color component.
//--------------------------------------------------------------------------------------------------
ubyte& Color3ub::r()
{
return m_rgb[0];
}
//--------------------------------------------------------------------------------------------------
/// Get modifiable reference to the green color component.
//--------------------------------------------------------------------------------------------------
ubyte& Color3ub::g()
{
return m_rgb[1];
}
//--------------------------------------------------------------------------------------------------
/// Get modifiable reference to the blue color component.
//--------------------------------------------------------------------------------------------------
ubyte& Color3ub::b()
{
return m_rgb[2];
}
//--------------------------------------------------------------------------------------------------
/// Sets all color components
//--------------------------------------------------------------------------------------------------
void Color3ub::set(ubyte r, ubyte g, ubyte b)
{
m_rgb[0] = r;
m_rgb[1] = g;
m_rgb[2] = b;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const ubyte* Color3ub::ptr() const
{
return m_rgb;
}
} // namespace cvf
+157
View File
@@ -0,0 +1,157 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
namespace cvf {
// Forward declarations
class Color3ub;
//==================================================================================================
//
// Abstract base class for RGB colors
//
//==================================================================================================
class Color3
{
public:
enum ColorIdent
{
RED, ///< Pure red (255, 0, 0)
GREEN, ///< Pure greed (0, 255, 0)
BLUE, ///< Pure blue (0, 0, 255)
YELLOW, ///< Yellow (255, 255, 0)
CYAN, ///< Cyan (0, 255, 255)
MAGENTA, ///< Magenta (255, 0, 255)
WHITE, ///< White
BLACK, ///< Black
LIGHT_GRAY, ///< Light gray (192, 192, 192)
GRAY, ///< Gray (128, 128, 128)
DARK_GRAY, ///< Dark gray (64, 64, 64)
BROWN, ///< Brown (165, 42, 42)
CRIMSON, ///< Crimson (220, 20, 60)
DARK_BLUE, ///< Dark blue (0, 0, 139)
DARK_YELLOW, ///< Dark yellow (139, 139, 0)
DARK_CYAN, ///< Dark cyan (0, 139, 139)
DARK_GREEN, ///< Dark green (0, 100, 0)
DARK_MAGENTA, ///< Dark magenta (139, 0, 139)
DARK_ORANGE, ///< Dark orange (255, 140, 0)
DARK_RED, ///< Dark red (139, 0, 0)
DARK_VIOLET, ///< Dark violet (148, 0, 211)
DEEP_PINK, ///< Deep pink (255, 20, 147)
FOREST_GREEN, ///< Forest green (34, 139, 34)
GOLD, ///< Gold (255, 215, 0)
GREEN_YELLOW, ///< Green yellow (173, 255, 47)
INDIGO, ///< Indigo (75, 0, 130)
OLIVE, ///< Olive (128, 128, 0)
ORANGE, ///< Orange (255, 165, 0)
ORANGE_RED, ///< Orange red (255, 69, 0)
ORCHID, ///< Orchid (218, 112, 214)
PINK, ///< Pink (255, 192, 203)
PURPLE, ///< Purple (128, 0, 128)
SEA_GREEN, ///< Sea green (46, 139, 87)
SKY_BLUE, ///< Sky blue (135, 206, 235)
VIOLET, ///< Violet (238, 130, 238)
YELLOW_GREEN ///< Yellow green (154, 205, 50)
};
};
//==================================================================================================
//
// Floating point RGB colors
//
//==================================================================================================
class Color3f : public Color3
{
public:
Color3f();
Color3f(float r, float g, float b);
Color3f(const Color3f& other);
Color3f(ColorIdent colorIdent);
explicit Color3f(const Color3ub& other);
Color3f& operator=(const Color3f& rhs);
Color3f& operator=(ColorIdent colorIdent);
bool operator==(const Color3f& rhs) const;
bool operator!=(const Color3f& rhs) const;
float r() const;
float g() const;
float b() const;
float& r();
float& g();
float& b();
void set(float r, float g, float b);
bool isValid() const;
const float* ptr() const;
ubyte rByte() const;
ubyte gByte() const;
ubyte bByte() const;
static Color3f fromByteColor(ubyte r, ubyte g, ubyte b);
private:
float m_rgb[3];
};
//==================================================================================================
//
// Unsigned byte RGB colors
//
//==================================================================================================
class Color3ub : public Color3
{
public:
Color3ub();
Color3ub(ubyte r, ubyte g, ubyte b);
Color3ub(const Color3ub& other);
Color3ub(ColorIdent colorIdent);
explicit Color3ub(const Color3f& other);
Color3ub& operator=(const Color3ub& rhs);
Color3ub& operator=(ColorIdent colorIdent);
bool operator==(const Color3ub& rhs) const;
bool operator!=(const Color3ub& rhs) const;
ubyte r() const;
ubyte g() const;
ubyte b() const;
ubyte& r();
ubyte& g();
ubyte& b();
void set(ubyte r, ubyte g, ubyte b);
const ubyte* ptr() const;
private:
ubyte m_rgb[3];
};
}
+541
View File
@@ -0,0 +1,541 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#include "cvfBase.h"
#include "cvfColor4.h"
#include "cvfColor3.h"
#include "cvfMath.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::Color4f
/// \ingroup Core
///
/// Class for storing and manipulating 4-component RGBA colors
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
/// Default constructor, initializes object to RGB=0.0 and Alpha=1.0
//--------------------------------------------------------------------------------------------------
Color4f::Color4f()
{
m_rgba[0] = 0.0f;
m_rgba[1] = 0.0f;
m_rgba[2] = 0.0f;
m_rgba[3] = 1.0f;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Color4f::Color4f(float r, float g, float b, float alpha)
{
m_rgba[0] = r;
m_rgba[1] = g;
m_rgba[2] = b;
m_rgba[3] = alpha;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Color4f::Color4f(const Color4f& other)
{
m_rgba[0] = other.m_rgba[0];
m_rgba[1] = other.m_rgba[1];
m_rgba[2] = other.m_rgba[2];
m_rgba[3] = other.m_rgba[3];
}
//--------------------------------------------------------------------------------------------------
/// Construct from 3 component RGB color. Alpha value will be set to 1.0
//--------------------------------------------------------------------------------------------------
Color4f::Color4f(const Color3f& rgbColor)
{
m_rgba[0] = rgbColor.r();
m_rgba[1] = rgbColor.g();
m_rgba[2] = rgbColor.b();
m_rgba[3] = 1.0f;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Color4f::Color4f(const Color3f& rgbColor, float alpha)
{
m_rgba[0] = rgbColor.r();
m_rgba[1] = rgbColor.g();
m_rgba[2] = rgbColor.b();
m_rgba[3] = alpha;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Color4f::Color4f(Color3::ColorIdent colorIdent)
{
Color3f rgb(colorIdent);
m_rgba[0] = rgb.r();
m_rgba[1] = rgb.g();
m_rgba[2] = rgb.b();
m_rgba[3] = 1.0f;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Color4f::Color4f(const Color4ub& other)
{
m_rgba[0] = static_cast<float>(other.r())/255.0f;
m_rgba[1] = static_cast<float>(other.g())/255.0f;
m_rgba[2] = static_cast<float>(other.b())/255.0f;
m_rgba[3] = static_cast<float>(other.a())/255.0f;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Color4f& Color4f::operator=(const Color4f& rhs)
{
m_rgba[0] = rhs.m_rgba[0];
m_rgba[1] = rhs.m_rgba[1];
m_rgba[2] = rhs.m_rgba[2];
m_rgba[3] = rhs.m_rgba[3];
return *this;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool Color4f::operator==(const Color4f& rhs) const
{
if (m_rgba[0] == rhs.m_rgba[0] &&
m_rgba[1] == rhs.m_rgba[1] &&
m_rgba[2] == rhs.m_rgba[2] &&
m_rgba[3] == rhs.m_rgba[3])
{
return true;
}
else
{
return false;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool Color4f::operator!=(const Color4f& rhs) const
{
return !operator==(rhs);
}
//--------------------------------------------------------------------------------------------------
/// Returns the red color component of this color
//--------------------------------------------------------------------------------------------------
const float& Color4f::r() const
{
return m_rgba[0];
}
//--------------------------------------------------------------------------------------------------
/// Returns the green color component of this color
//--------------------------------------------------------------------------------------------------
const float& Color4f::g() const
{
return m_rgba[1];
}
//--------------------------------------------------------------------------------------------------
/// Returns the blue color component of this color
//--------------------------------------------------------------------------------------------------
const float& Color4f::b() const
{
return m_rgba[2];
}
//--------------------------------------------------------------------------------------------------
/// Returns the alpha color component of this color
//--------------------------------------------------------------------------------------------------
const float& Color4f::a() const
{
return m_rgba[3];
}
//--------------------------------------------------------------------------------------------------
/// Get modifiable reference to the red color component.
///
/// Used for setting the color, e.g. <tt>r() = 0.5f</tt>
//--------------------------------------------------------------------------------------------------
float& Color4f::r()
{
return m_rgba[0];
}
//--------------------------------------------------------------------------------------------------
/// Get modifiable reference to the green color component.
///
/// Used for setting the color, e.g. <tt>g() = 0.5f</tt>
//--------------------------------------------------------------------------------------------------
float& Color4f::g()
{
return m_rgba[1];
}
//--------------------------------------------------------------------------------------------------
/// Get modifiable reference to the blue color component.
///
/// Used for setting the color, e.g. <tt>b() = 0.5f</tt>
//--------------------------------------------------------------------------------------------------
float& Color4f::b()
{
return m_rgba[2];
}
//--------------------------------------------------------------------------------------------------
/// Get modifiable reference to the alpha component.
///
/// Used for setting the color, e.g. <tt>a() = 0.5f</tt>
//--------------------------------------------------------------------------------------------------
float& Color4f::a()
{
return m_rgba[3];
}
//--------------------------------------------------------------------------------------------------
/// Sets all color components
//--------------------------------------------------------------------------------------------------
void Color4f::set(float r, float g, float b, float alpha)
{
m_rgba[0] = r;
m_rgba[1] = g;
m_rgba[2] = b;
m_rgba[3] = alpha;
}
//--------------------------------------------------------------------------------------------------
/// Set from 3-component RGB color and separate alpha factor
//--------------------------------------------------------------------------------------------------
void Color4f::set(const Color3f& rgbColor, float alpha)
{
m_rgba[0] = rgbColor.r();
m_rgba[1] = rgbColor.g();
m_rgba[2] = rgbColor.b();
m_rgba[3] = alpha;
}
//--------------------------------------------------------------------------------------------------
/// Set from 3-component RGB color. Alpha will be set to 1.0
//--------------------------------------------------------------------------------------------------
void Color4f::set(const Color3f& rgbColor)
{
m_rgba[0] = rgbColor.r();
m_rgba[1] = rgbColor.g();
m_rgba[2] = rgbColor.b();
m_rgba[3] = 1.0f;
}
//--------------------------------------------------------------------------------------------------
/// Query whether this color is valid
///
/// For a color to be considered valid, all the component values must be in the range 0.0 to 1.0
//--------------------------------------------------------------------------------------------------
bool Color4f::isValid() const
{
if (!Math::valueInRange(m_rgba[0], 0.0f, 1.0f)) return false;
if (!Math::valueInRange(m_rgba[1], 0.0f, 1.0f)) return false;
if (!Math::valueInRange(m_rgba[2], 0.0f, 1.0f)) return false;
if (!Math::valueInRange(m_rgba[3], 0.0f, 1.0f)) return false;
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const float* Color4f::ptr() const
{
return m_rgba;
}
//--------------------------------------------------------------------------------------------------
/// Convert to 3-component RGB color by dropping the alpha value
//--------------------------------------------------------------------------------------------------
Color3f Color4f::toColor3f() const
{
return Color3f(m_rgba[0], m_rgba[1], m_rgba[2]);
}
//==================================================================================================
///
/// \class cvf::Color4ub
/// \ingroup Core
///
/// Class for storing unsigned byte RGBA colors
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
/// Default constructor, initializes object to RGB=0.0 and Alpha=1.0
//--------------------------------------------------------------------------------------------------
Color4ub::Color4ub()
{
m_rgba[0] = 0;
m_rgba[1] = 0;
m_rgba[2] = 0;
m_rgba[3] = 255;
}
//--------------------------------------------------------------------------------------------------
/// Constructor with initialization of all components
//--------------------------------------------------------------------------------------------------
Color4ub::Color4ub(ubyte r, ubyte g, ubyte b, ubyte a)
{
m_rgba[0] = r;
m_rgba[1] = g;
m_rgba[2] = b;
m_rgba[3] = a;
}
//--------------------------------------------------------------------------------------------------
/// Copy constructor
//--------------------------------------------------------------------------------------------------
Color4ub::Color4ub(const Color4ub& other)
{
m_rgba[0] = other.m_rgba[0];
m_rgba[1] = other.m_rgba[1];
m_rgba[2] = other.m_rgba[2];
m_rgba[3] = other.m_rgba[3];
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Color4ub::Color4ub(const Color3ub& rgbColor, ubyte a)
{
m_rgba[0] = rgbColor.r();
m_rgba[1] = rgbColor.g();
m_rgba[2] = rgbColor.b();
m_rgba[3] = a;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Color4ub::Color4ub(const Color3ub& rgbColor)
{
m_rgba[0] = rgbColor.r();
m_rgba[1] = rgbColor.g();
m_rgba[2] = rgbColor.b();
m_rgba[3] = 255;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Color4ub::Color4ub(Color3::ColorIdent colorIdent)
{
Color3ub color3(colorIdent);
set(color3.r(), color3.g(), color3.b(), 255);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Color4ub::Color4ub(const Color4f& other)
{
m_rgba[0] = static_cast<ubyte>(other.r()*255.0f);
m_rgba[1] = static_cast<ubyte>(other.g()*255.0f);
m_rgba[2] = static_cast<ubyte>(other.b()*255.0f);
m_rgba[3] = static_cast<ubyte>(other.a()*255.0f);
}
//--------------------------------------------------------------------------------------------------
/// Assignment operator
//--------------------------------------------------------------------------------------------------
Color4ub& Color4ub::operator=(const Color4ub& rhs)
{
m_rgba[0] = rhs.m_rgba[0];
m_rgba[1] = rhs.m_rgba[1];
m_rgba[2] = rhs.m_rgba[2];
m_rgba[3] = rhs.m_rgba[3];
return *this;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool Color4ub::operator==(const Color4ub& rhs) const
{
if (m_rgba[0] == rhs.m_rgba[0] &&
m_rgba[1] == rhs.m_rgba[1] &&
m_rgba[2] == rhs.m_rgba[2] &&
m_rgba[3] == rhs.m_rgba[3])
{
return true;
}
else
{
return false;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool Color4ub::operator!=(const Color4ub& rhs) const
{
return !operator==(rhs);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
ubyte Color4ub::r() const
{
return m_rgba[0];
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
ubyte Color4ub::g() const
{
return m_rgba[1];
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
ubyte Color4ub::b() const
{
return m_rgba[2];
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
ubyte Color4ub::a() const
{
return m_rgba[3];
}
//--------------------------------------------------------------------------------------------------
/// Get modifiable reference to the red color component.
//--------------------------------------------------------------------------------------------------
ubyte& Color4ub::r()
{
return m_rgba[0];
}
//--------------------------------------------------------------------------------------------------
/// Get modifiable reference to the green color component.
//--------------------------------------------------------------------------------------------------
ubyte& Color4ub::g()
{
return m_rgba[1];
}
//--------------------------------------------------------------------------------------------------
/// Get modifiable reference to the blue color component.
//--------------------------------------------------------------------------------------------------
ubyte& Color4ub::b()
{
return m_rgba[2];
}
//--------------------------------------------------------------------------------------------------
/// Get modifiable reference to the alpha color component.
//--------------------------------------------------------------------------------------------------
ubyte& Color4ub::a()
{
return m_rgba[3];
}
//--------------------------------------------------------------------------------------------------
/// Sets all color components
//--------------------------------------------------------------------------------------------------
void Color4ub::set(ubyte r, ubyte g, ubyte b, ubyte a)
{
m_rgba[0] = r;
m_rgba[1] = g;
m_rgba[2] = b;
m_rgba[3] = a;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const ubyte* Color4ub::ptr() const
{
return m_rgba;
}
} // namespace cvf
+107
View File
@@ -0,0 +1,107 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include "cvfColor3.h"
namespace cvf {
class Color4ub;
//==================================================================================================
//
// Class for RGBA colors
//
//==================================================================================================
class Color4f
{
public:
Color4f();
Color4f(float r, float g, float b, float alpha);
Color4f(const Color4f& other);
Color4f(const Color3f& rgbColor, float alpha);
explicit Color4f(const Color3f& rgbColor);
explicit Color4f(Color3::ColorIdent colorIdent);
explicit Color4f(const Color4ub& other);
Color4f& operator=(const Color4f& rhs);
bool operator==(const Color4f& rhs) const;
bool operator!=(const Color4f& rhs) const;
const float& r() const;
const float& g() const;
const float& b() const;
const float& a() const;
float& r();
float& g();
float& b();
float& a();
void set(float r, float g, float b, float alpha);
void set(const Color3f& rgbColor, float alpha);
void set(const Color3f& rgbColor);
bool isValid() const;
const float* ptr() const;
Color3f toColor3f() const;
private:
float m_rgba[4];
};
//==================================================================================================
//
// Unsigned byte RGBA colors
//
//==================================================================================================
class Color4ub
{
public:
Color4ub();
Color4ub(ubyte r, ubyte g, ubyte b, ubyte a);
Color4ub(const Color4ub& other);
Color4ub(const Color3ub& rgbColor, ubyte a);
explicit Color4ub(const Color3ub& rgbColor);
explicit Color4ub(Color3::ColorIdent colorIdent);
explicit Color4ub(const Color4f& other);
Color4ub& operator=(const Color4ub& rhs);
bool operator==(const Color4ub& rhs) const;
bool operator!=(const Color4ub& rhs) const;
ubyte r() const;
ubyte g() const;
ubyte b() const;
ubyte a() const;
ubyte& r();
ubyte& g();
ubyte& b();
ubyte& a();
void set(ubyte r, ubyte g, ubyte b, ubyte a);
const ubyte* ptr() const;
private:
ubyte m_rgba[4];
};
}
@@ -0,0 +1,58 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
// Define this one to tell windows.h to not define min() and max() as macros
#if defined WIN32 && !defined NOMINMAX
#define NOMINMAX
#endif
// Used to keep track of all instances of classes derived from Object.
// Can be used to detect memory leaks in combination with the static member
// functions: Object::activeObjectInstances() and Object::dumpActiveObjectInstances()
// 0 - disable tracking of active object instances
// 1 - track active instances in debug builds
// 2 - track active instances in BOTH debug and release builds
#ifndef CVF_TRACK_ACTIVE_OBJECT_INSTANCES
#define CVF_TRACK_ACTIVE_OBJECT_INSTANCES 0
#endif
// Behavior of assert macros
// In debug builds, all asserts are in action, including tight asserts
// In release builds, tight asserts are disabled by default. Normal asserts are still in action (including CVF_FAIL_...)
#ifndef CVF_ENABLE_ASSERTS
#define CVF_ENABLE_ASSERTS 1
#endif
#ifndef CVF_ENABLE_TIGHT_ASSERTS
#ifdef _DEBUG
#define CVF_ENABLE_TIGHT_ASSERTS 1
#else
#define CVF_ENABLE_TIGHT_ASSERTS 0
#endif
#endif
@@ -0,0 +1,204 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#include "cvfBase.h"
#include "cvfDebugTimer.h"
#include "cvfTimer.h"
#include "cvfTrace.h"
#include <cstdio>
#include <cstdarg>
namespace cvf {
//==================================================================================================
///
/// \class cvf::DebugTimer
/// \ingroup Core
///
/// Debug timer class for reporting timing info via the static Trace class
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
/// Constructor, starts the timer
///
/// \param prefix This text will be prepended for all trace outputs. Can be NULL
/// \param operationMode Either NORMAL (the default) or DISABLED. Specifying DISABLED effectively
/// disables all functionality in the class.
//--------------------------------------------------------------------------------------------------
DebugTimer::DebugTimer(const char* prefix, OperationMode operationMode)
: m_timer(NULL),
m_prefix(NULL),
m_messageCount(0)
{
if (operationMode == NORMAL)
{
if (prefix)
{
m_prefix = new String(prefix);
}
m_timer = new Timer();
}
}
//--------------------------------------------------------------------------------------------------
/// Destructor
//--------------------------------------------------------------------------------------------------
DebugTimer::~DebugTimer()
{
delete m_prefix;
delete m_timer;
}
//--------------------------------------------------------------------------------------------------
/// Restart timer.
///
/// If msg is specified this method will show this text as trace output. Else nothing is shown.
//--------------------------------------------------------------------------------------------------
void DebugTimer::restart(const char* msg)
{
if (!m_timer) return;
m_timer->restart();
if (msg)
{
String outputText = makeMessageStartString(msg);
Trace::show(outputText);
}
}
//--------------------------------------------------------------------------------------------------
/// Report elapsed time, in seconds. msg is appended if provided.
//--------------------------------------------------------------------------------------------------
void DebugTimer::reportTime(const char* msg)
{
if (!m_timer) return;
double time = m_timer->time();
String outputText = makeMessageStartString(msg) + ": " + String::number(time, 'f', 6) + " sec";
Trace::show(outputText);
}
//--------------------------------------------------------------------------------------------------
/// Report elapsed time, in milliseconds. msg is appended if provided.
//--------------------------------------------------------------------------------------------------
void DebugTimer::reportTimeMS(const char* msg )
{
if (!m_timer) return;
double timeMS = m_timer->time() * 1000.0;
String outputText = makeMessageStartString(msg) + ": " + String::number(timeMS, 'f', 3) + " ms";
Trace::show(outputText);
}
//--------------------------------------------------------------------------------------------------
/// Report lap time, in seconds. msg is appended if provided.
//--------------------------------------------------------------------------------------------------
void DebugTimer::reportLapTime(const char* msg)
{
if (!m_timer) return;
double lapTime = m_timer->lapTime();
String outputText = makeMessageStartString(msg) + ": " + String::number(lapTime, 'f', 6) + " sec";
Trace::show(outputText);
}
//--------------------------------------------------------------------------------------------------
/// Report lap time, in milliseconds. msg is appended if provided.
//--------------------------------------------------------------------------------------------------
void DebugTimer::reportLapTimeMS(const char* msg)
{
if (!m_timer) return;
double lapTimeMS = m_timer->lapTime() * 1000.0;
String outputText = makeMessageStartString(msg) + ": " + String::number(lapTimeMS, 'f', 3) + " ms";
Trace::show(outputText);
}
//--------------------------------------------------------------------------------------------------
/// Show trace output with message count, optional prefix and provided text.
//--------------------------------------------------------------------------------------------------
void DebugTimer::echoMessage(const char* format, ...)
{
if (!m_timer) return;
// Create the printf-style string and send it to the console and trace file
// TODO! Note: var-arg is solved locally here, but needs to be revisited e.g. in String class
va_list argList;
va_start(argList, format);
const int maxFormatLength = 4000;
char temp[maxFormatLength + 1];
#ifdef WIN32
_vsnprintf_s(temp, maxFormatLength, format, argList);
#else
vsprintf(temp, format, argList);
#endif
va_end(argList);
String outputText = makeMessageStartString(temp);
Trace::show(outputText);
}
//--------------------------------------------------------------------------------------------------
/// Generate message string with message count, optional prefix and optional msg text.
//--------------------------------------------------------------------------------------------------
String DebugTimer::makeMessageStartString(const char* msg)
{
String outputText = String(m_messageCount);
m_messageCount++;
if (m_prefix)
{
outputText += String(": ");
outputText += *m_prefix;
}
if (msg)
{
outputText += ": ";
outputText += msg;
}
return outputText;
}
} // namespace cvf
@@ -0,0 +1,68 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include "cvfString.h"
namespace cvf {
class Timer;
//=================================================================================================
//
// Timer class
//
//=================================================================================================
class DebugTimer
{
public:
enum OperationMode
{
NORMAL, ///< Normal operation
DISABLED ///< Disables all functionality in the class
};
public:
DebugTimer(const char* prefix, OperationMode operationMode = NORMAL);
~DebugTimer();
void restart(const char* msg = NULL);
void reportTime(const char* msg = NULL);
void reportTimeMS(const char* msg = NULL);
void reportLapTime(const char* msg = NULL);
void reportLapTimeMS(const char* msg = NULL);
void echoMessage(const char* format, ...);
private:
String makeMessageStartString(const char* msg);
private:
Timer* m_timer; ///< The actual timer object to use
String* m_prefix; ///< String to prefix all output
int m_messageCount; ///< Counts number of messages returned
CVF_DISABLE_COPY_AND_ASSIGN(DebugTimer);
};
}
+58
View File
@@ -0,0 +1,58 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
namespace cvf {
//=================================================================================================
//
// Flags class
//
//=================================================================================================
template<typename FlagEnum>
class Flags
{
public:
inline Flags();
inline Flags(const Flags& other);
inline Flags(FlagEnum flag);
inline Flags& operator=(const Flags& rhs);
inline Flags& operator=(FlagEnum flag);
inline Flags& operator|=(const Flags& rhs);
inline Flags operator|(const Flags& rhs) const;
inline Flags& operator&=(const Flags& rhs);
inline Flags operator&(const Flags& rhs) const;
inline bool operator==(const Flags& rhs) const;
inline bool operator==(int rhs) const;
inline bool operator!=(const Flags& rhs) const;
inline bool operator!=(int rhs) const;
inline bool testFlag(FlagEnum flag) const;
private:
int m_bitfield;
};
}
#include "cvfFlags.inl"
+179
View File
@@ -0,0 +1,179 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
namespace cvf {
//==================================================================================================
///
/// \class cvf::Flags
/// \ingroup Core
///
/// The Flags class provides a type-safe way of storing OR-combinations of enum values
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
/// Default constructor
//--------------------------------------------------------------------------------------------------
template<typename FlagEnum>
inline Flags<FlagEnum>::Flags()
: m_bitfield(0)
{
}
//--------------------------------------------------------------------------------------------------
/// Copy constructor
//--------------------------------------------------------------------------------------------------
template<typename FlagEnum>
inline Flags<FlagEnum>::Flags(const Flags& other)
: m_bitfield(other.m_bitfield)
{
}
//--------------------------------------------------------------------------------------------------
/// Constructor with initialization
//--------------------------------------------------------------------------------------------------
template<typename FlagEnum>
inline Flags<FlagEnum>::Flags(FlagEnum flag)
: m_bitfield(flag)
{
}
//--------------------------------------------------------------------------------------------------
/// Assignment operator
//--------------------------------------------------------------------------------------------------
template<typename FlagEnum>
inline Flags<FlagEnum>& Flags<FlagEnum>::operator=(const Flags& rhs)
{
m_bitfield = rhs.m_bitfield;
return *this;
}
//--------------------------------------------------------------------------------------------------
/// Assignment operator
//--------------------------------------------------------------------------------------------------
template<typename FlagEnum>
inline Flags<FlagEnum>& Flags<FlagEnum>::operator=(FlagEnum flag)
{
m_bitfield = flag;
return *this;
}
//--------------------------------------------------------------------------------------------------
/// Performs a bitwise OR operation with rhs and stores the result in this Flags object.
//--------------------------------------------------------------------------------------------------
template<typename FlagEnum>
inline Flags<FlagEnum>& Flags<FlagEnum>::operator|=(const Flags& rhs)
{
m_bitfield |= rhs.m_bitfield;
return *this;
}
//--------------------------------------------------------------------------------------------------
/// Performs a bitwise OR operation with rhs and returns new object
//--------------------------------------------------------------------------------------------------
template<typename FlagEnum>
inline Flags<FlagEnum> Flags<FlagEnum>::operator|(const Flags& rhs) const
{
Flags ret(*this);
return (ret |= rhs);
}
//--------------------------------------------------------------------------------------------------
/// Performs a bitwise AND operation with rhs and stores the result in this Flags object.
//--------------------------------------------------------------------------------------------------
template<typename FlagEnum>
inline Flags<FlagEnum>& Flags<FlagEnum>::operator&=(const Flags& rhs)
{
m_bitfield &= rhs.m_bitfield;
return *this;
}
//--------------------------------------------------------------------------------------------------
/// Performs a bitwise AND operation with rhs and returns new object
//--------------------------------------------------------------------------------------------------
template<typename FlagEnum>
inline Flags<FlagEnum> Flags<FlagEnum>::operator&(const Flags& rhs) const
{
Flags ret(*this);
return (ret &= rhs);
}
//--------------------------------------------------------------------------------------------------
/// Comparison operator, equality
//--------------------------------------------------------------------------------------------------
template<typename FlagEnum>
inline bool Flags<FlagEnum>::operator==(const Flags& rhs) const
{
return m_bitfield == rhs.m_bitfield;
}
//--------------------------------------------------------------------------------------------------
/// Comparison operator, equality
//--------------------------------------------------------------------------------------------------
template<typename FlagEnum>
inline bool Flags<FlagEnum>::operator==(int rhs) const
{
return m_bitfield == rhs;
}
//--------------------------------------------------------------------------------------------------
/// Comparison operator, not equal
//--------------------------------------------------------------------------------------------------
template<typename FlagEnum>
inline bool Flags<FlagEnum>::operator!=(const Flags& rhs) const
{
return m_bitfield != rhs.m_bitfield;
}
//--------------------------------------------------------------------------------------------------
/// Comparison operator, not equal
//--------------------------------------------------------------------------------------------------
template<typename FlagEnum>
inline bool Flags<FlagEnum>::operator!=(int rhs) const
{
return m_bitfield != rhs;
}
//--------------------------------------------------------------------------------------------------
/// Return true only if ALL bits in flag are set
//--------------------------------------------------------------------------------------------------
template<typename FlagEnum>
inline bool Flags<FlagEnum>::testFlag(FlagEnum flag) const
{
return ((m_bitfield & flag) == flag);
}
} // namespace cvf
@@ -0,0 +1,53 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
namespace cvf {
//==================================================================================================
///
/// \class cvf::FunctorRange
/// \ingroup Core
///
/// Implements an iteration range for use with our functors.
/// The class is designed to be compatible with TBB's blocked_range class with regards to
/// the functor's requirements
///
//==================================================================================================
template <typename T>
class FunctorRange
{
public:
FunctorRange(T beginIndex, T endIndex)
: m_beginIndex(beginIndex), m_endIndex(endIndex) {}
inline T begin() const { return m_beginIndex; } ///< The first index included in the range
inline T end() const { return m_endIndex; } ///< Index one past last the last index to be included in the range
private:
T m_beginIndex; // The first index to be included in the iteration.
T m_endIndex; // The index one past the last index to be included in the iteration
};
} // cvf
+56
View File
@@ -0,0 +1,56 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
// Doxygen module definition
/// \ingroup CeeVizFramework
/// @{
/// \defgroup Core Core module
/// @}
/// \defgroup CeeVizFramework CeeViz Framework Basis
// Intentionally on top to be included first
#include "cvfBase.h"
#include "cvfArray.h"
#include "cvfAssert.h"
#include "cvfBase64.h"
#include "cvfCharArray.h"
#include "cvfCollection.h"
#include "cvfColor3.h"
#include "cvfColor4.h"
#include "cvfDebugTimer.h"
#include "cvfFlags.h"
#include "cvfFunctorRange.h"
#include "cvfLogger.h"
#include "cvfMath.h"
#include "cvfMatrix4.h"
#include "cvfObject.h"
#include "cvfPlane.h"
#include "cvfRect.h"
#include "cvfQuat.h"
#include "cvfString.h"
#include "cvfSystem.h"
#include "cvfTBBControl.h"
#include "cvfTimer.h"
#include "cvfTrace.h"
#include "cvfVector2.h"
#include "cvfVector3.h"
#include "cvfVector4.h"
#include "cvfVersion.h"
+112
View File
@@ -0,0 +1,112 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#include "cvfBase.h"
#include "cvfLogger.h"
#include "cvfTrace.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::Logger
/// \ingroup Core
///
/// Logger class
///
/// Currently, output is written using Trace, and special formatting of the string makes it possible
/// to navigate to source code using F4 in Visual Studio. See http://msdn.microsoft.com/en-us/library/yxkt8b26.aspx
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
/// Constructor
//--------------------------------------------------------------------------------------------------
Logger::Logger()
: m_debugLogging(false)
{
}
//--------------------------------------------------------------------------------------------------
/// Destructor
//--------------------------------------------------------------------------------------------------
Logger::~Logger()
{
}
//--------------------------------------------------------------------------------------------------
/// Use file and line to create a specially formatted string for Visual Studio.
///
/// \param message The actual error message
/// \param fileName Use system macro __FILE__ for source code file name
/// \param line Use system macro __LINE__ for source code line number
///
/// __FILE__ and __LINE__ are used to create the variables used to navigate to the line in the
/// source code file the error message was logged at.
//--------------------------------------------------------------------------------------------------
void Logger::error(const String& message, const char* fileName, int lineNumber)
{
String tmp;
tmp = String(fileName) + "(" + String(lineNumber) + "): error: " + message;
Trace::show(tmp);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Logger::enableDebug(bool enableDebugLogging)
{
m_debugLogging = enableDebugLogging;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool Logger::isDebugEnabled() const
{
return m_debugLogging;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Logger::debug(const String& message, const char* /*fileName*/, int /*lineNumber*/)
{
if (m_debugLogging)
{
// For now, don't report file and line
String tmp;
tmp = "debug: " + message;
Trace::show(tmp);
}
}
} // namespace cvf
+52
View File
@@ -0,0 +1,52 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include "cvfObject.h"
#include "cvfString.h"
namespace cvf {
//==================================================================================================
//
// Logger class
//
//==================================================================================================
class Logger : public Object
{
public:
Logger();
~Logger();
void error(const String& message, const char* fileName, int lineNumber);
void enableDebug(bool enableDebugLogging);
bool isDebugEnabled() const;
void debug(const String& message, const char* fileName, int lineNumber);
private:
bool m_debugLogging; // Whether debug messages get logged or not
};
} // cvf
+334
View File
@@ -0,0 +1,334 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#include "cvfBase.h"
#include "cvfMath.h"
#include <cmath>
namespace cvf {
//==================================================================================================
///
/// \class cvf::Math
/// \ingroup Core
///
/// Static class providing basic math operations
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
float Math::toRadians(float degrees)
{
return degrees*PI_F/180.0f;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double Math::toRadians(double degrees)
{
return degrees*PI_D/180.0;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
float Math::toDegrees(float radians)
{
return radians*180.0f/PI_F;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double Math::toDegrees(double radians)
{
return radians*180.0/PI_D;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double Math::cos(double val)
{
return ::cos(val);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
float Math::cos(float val)
{
return ::cosf(val);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double Math::acos(double val)
{
return ::acos(val);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
float Math::acos(float val)
{
return ::acosf(val);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double Math::sin(double val)
{
return ::sin(val);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
float Math::sin(float val)
{
return ::sinf(val);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double Math::asin(double val)
{
return ::asin(val);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
float Math::asin(float val)
{
return ::asinf(val);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double Math::tan(double val)
{
return ::tan(val);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
float Math::tan(float val)
{
return ::tanf(val);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double Math::atan(double val)
{
return ::atan(val);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
float Math::atan(float val)
{
return ::atanf(val);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double Math::sqrt(double val)
{
return ::sqrt(val);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
float Math::sqrt(float val)
{
return ::sqrtf(val);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double Math::floor(double val)
{
return ::floor(val);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
float Math::floor(float val)
{
return ::floorf(val);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double Math::ceil(double val)
{
return ::ceil(val);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
float Math::ceil(float val)
{
return ::ceilf(val);
}
//--------------------------------------------------------------------------------------------------
/// Returns the floating-point remainder of x / y
//--------------------------------------------------------------------------------------------------
double Math::fmod(double x, double y)
{
return ::fmod(x, y);
}
//--------------------------------------------------------------------------------------------------
/// Returns the floating-point remainder of x / y
//--------------------------------------------------------------------------------------------------
float Math::fmod(float x, float y)
{
return ::fmodf(x, y);
}
//--------------------------------------------------------------------------------------------------
/// Returns true if the number is a power of 2
///
/// The number 0 is not considered a power of 2.
//--------------------------------------------------------------------------------------------------
bool Math::isPow2(uint number)
{
// From Bit Twiddling Hacks
// http://graphics.stanford.edu/~seander/bithacks.html
return (number && !(number & (number - 1)));
}
//--------------------------------------------------------------------------------------------------
/// Round up to the next highest power of 2
///
/// If the number is already a power of 2 this function will return the same value
/// If number if out of range (greater than 2147483648) we cannot represent the next power of 2 and 0 is returned
//--------------------------------------------------------------------------------------------------
uint Math::roundUpPow2(uint number)
{
// From Bit Twiddling Hacks
// http://graphics.stanford.edu/~seander/bithacks.html
if (number == 0)
{
// Handle edge case where number is 0, algo returns 0, which isn't a power of 2;
return 1;
}
if (number > 2147483648u)
{
// Input is too large, we cannot represent the next power of two
return 0;
}
number--;
number |= number >> 1;
number |= number >> 2;
number |= number >> 4;
number |= number >> 8;
number |= number >> 16;
number++;
return number;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool Math::isUndefined(double val)
{
if (val < UNDEFINED_DOUBLE_THRESHOLD)
{
return false;
}
else
{
return true;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool Math::isUndefined(float val)
{
if (val < UNDEFINED_FLOAT_THRESHOLD)
{
return false;
}
else
{
return true;
}
}
} // namespace cvf
+95
View File
@@ -0,0 +1,95 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
namespace cvf {
//==================================================================================================
//
// Static class providing basic math operations
//
//==================================================================================================
class Math
{
public:
static float toRadians(float degrees);
static double toRadians(double degrees);
static float toDegrees(float radians);
static double toDegrees(double radians);
static double cos(double val);
static float cos(float val);
static double acos(double val);
static float acos(float val);
static double sin(double val);
static float sin(float val);
static double asin(double val);
static float asin(float val);
static double tan(double val);
static float tan(float val);
static double atan(double val);
static float atan(float val);
static double sqrt(double val);
static float sqrt(float val);
static double floor(double val);
static float floor(float val);
static double ceil(double val);
static float ceil(float val);
static double fmod(double x, double y);
static float fmod(float x, float y);
static bool isPow2(uint number);
static uint roundUpPow2(uint number);
static bool isUndefined(double val);
static bool isUndefined(float val);
template<typename T> static bool valueInRange(T val, T min, T max);
template<typename T> static T clamp(T val, T minVal, T maxVal);
template<typename T> static inline T abs(const T& val);
template<typename T> static int sign(const T& val);
};
const float PI_F = 3.14159265f;
const double PI_D = 3.14159265358979323846;
const float ONE_THIRD_F = 1.0f/3.0f;
const double ONE_THIRD_D = 1.0/3.0;
const double SQRT2_F = 1.41421356f; // sqrt(2)
const double SQRT2_D = 1.41421356237309504880; // sqrt(2)
const double SQRT1_2_F = 0.70710678f; // 1/sqrt(2)
const double SQRT1_2_D = 0.70710678118654752440; // 1/sqrt(2)
const int UNDEFINED_INT = 2147483647;
const uint UNDEFINED_UINT = static_cast<uint>(-1); // 4294967295u
const size_t UNDEFINED_SIZE_T = static_cast<size_t>(-1);// 18446744073709551615u
const double UNDEFINED_DOUBLE = 1.7976931348623158e+308;
const double UNDEFINED_DOUBLE_THRESHOLD = 1.00e+308;
const float UNDEFINED_FLOAT = 3.402823466e+38f;
const float UNDEFINED_FLOAT_THRESHOLD = 2.99e+38f;
} // namespace cvf
#include "cvfMath.inl"
+89
View File
@@ -0,0 +1,89 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
namespace cvf {
//--------------------------------------------------------------------------------------------------
/// Check if a value is within the specified range, inclusive.
///
/// \return Returns true if \a val >= \a min and \a val <= \a max.
//--------------------------------------------------------------------------------------------------
template<typename T>
bool Math::valueInRange(T val, T minVal, T maxVal)
{
CVF_ASSERT(minVal <= maxVal);
if (val >= minVal && val <= maxVal)
{
return true;
}
else
{
return false;
}
}
//--------------------------------------------------------------------------------------------------
/// Clamp a value within an inclusive range.
///
/// \return The clamped value
//--------------------------------------------------------------------------------------------------
template<typename T>
T Math::clamp(T val, T minVal, T maxVal)
{
CVF_ASSERT(minVal <= maxVal);
if (val >= minVal && val <= maxVal)
{
return val;
}
else if (val > maxVal)
{
return maxVal;
}
else
{
return minVal;
}
}
//--------------------------------------------------------------------------------------------------
/// Returns the absolute value of val
//--------------------------------------------------------------------------------------------------
template<typename T>
T Math::abs(const T& val)
{
return val >= 0 ? val : -val;
}
//--------------------------------------------------------------------------------------------------
/// Returns the sign of val
//--------------------------------------------------------------------------------------------------
template<typename T>
int Math::sign(const T& val)
{
return val < 0 ? -1 : 1;
}
} // namespace cvf
+88
View File
@@ -0,0 +1,88 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include "cvfSystem.h"
#include "cvfVector3.h"
namespace cvf {
//==================================================================================================
//
// Template matrix class for 3x3 matrices
//
//==================================================================================================
template<typename S>
class Matrix3
{
public:
Matrix3();
Matrix3(const Matrix3& other);
Matrix3(S m00, S m01, S m02, S m10, S m11, S m12, S m20, S m21, S m22);
template<typename T>
explicit Matrix3(const T& other);
inline Matrix3& operator=(const Matrix3& rhs);
bool operator==(const Matrix3& rhs) const;
bool operator!=(const Matrix3& rhs) const;
const Matrix3 operator*(const Matrix3& rhs) const;
void setIdentity();
bool isIdentity() const;
void setZero();
bool isZero() const;
inline S& operator()(int row, int col);
inline S operator()(int row, int col) const;
inline void setRowCol(int row, int col, S value);
inline S rowCol(int row, int col) const;
bool invert();
const Matrix3 getInverted(bool* pInvertible = NULL) const;
S determinant() const;
void transpose();
inline const S* ptr() const;
static Matrix3 fromRotation(Vector3<S> axis, S angle);
public:
static const Matrix3 IDENTITY; ///< Identity matrix
static const Matrix3 ZERO; ///< Matrix with all zeros
private:
// Constants for accessing our internal array using standard matrix notation
static const int e00 = 0; static const int e01 = 3; static const int e02 = 6;
static const int e10 = 1; static const int e11 = 4; static const int e12 = 7;
static const int e20 = 2; static const int e21 = 5; static const int e22 = 8;
private:
S m_v[9];
};
typedef Matrix3<float> Mat3f;
typedef Matrix3<double> Mat3d;
}
#include "cvfMatrix3.inl"
+449
View File
@@ -0,0 +1,449 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
namespace cvf {
//==================================================================================================
///
/// \class cvf::Matrix3
/// \ingroup Core
///
/// Matrices are stored internally as a one dimensional array for performance reasons.
///
/// The internal indices into the 1D array are as follows:
///
/// <PRE>
/// | m00 m01 m02 | | 0 3 6 |
/// | m10 m11 m12 | | 1 4 7 |
/// | m20 m21 m22 | | 2 5 18 |
/// </PRE>
///
/// See description of Matrix4 for more details on storage
///
//==================================================================================================
template<typename S> Matrix3<S> const Matrix3<S>::IDENTITY;
template<typename S> Matrix3<S> const Matrix3<S>::ZERO(0, 0, 0, 0, 0, 0, 0, 0, 0);
//----------------------------------------------------------------------------------------------------
/// Default constructor. Initializes matrix to identity
//----------------------------------------------------------------------------------------------------
template <typename S>
Matrix3<S>::Matrix3()
{
setIdentity();
}
//----------------------------------------------------------------------------------------------------
/// Copy constructor
//----------------------------------------------------------------------------------------------------
template <typename S>
inline Matrix3<S>::Matrix3(const Matrix3& other)
{
System::memcpy(m_v, sizeof(m_v), other.m_v, sizeof(other.m_v));
}
//----------------------------------------------------------------------------------------------------
/// Constructor with explicit initialization of all matrix elements.
///
/// The value of the parameter \a mrc will be placed in row r and column c of the matrix, eg m12
/// goes into row 1, column 2.
//----------------------------------------------------------------------------------------------------
template <typename S>
Matrix3<S>::Matrix3(S m00, S m01, S m02, S m10, S m11, S m12, S m20, S m21, S m22)
{
m_v[e00] = m00;
m_v[e10] = m10;
m_v[e20] = m20;
m_v[e01] = m01;
m_v[e11] = m11;
m_v[e21] = m21;
m_v[e02] = m02;
m_v[e12] = m12;
m_v[e22] = m22;
}
//----------------------------------------------------------------------------------------------------
///
//----------------------------------------------------------------------------------------------------
template<typename S>
template<typename T>
Matrix3<S>::Matrix3(const T& other)
{
m_v[e00] = static_cast<S>(other.rowCol(0, 0));
m_v[e01] = static_cast<S>(other.rowCol(0, 1));
m_v[e02] = static_cast<S>(other.rowCol(0, 2));
m_v[e10] = static_cast<S>(other.rowCol(1, 0));
m_v[e11] = static_cast<S>(other.rowCol(1, 1));
m_v[e12] = static_cast<S>(other.rowCol(1, 2));
m_v[e20] = static_cast<S>(other.rowCol(2, 0));
m_v[e21] = static_cast<S>(other.rowCol(2, 1));
m_v[e22] = static_cast<S>(other.rowCol(2, 2));
}
//----------------------------------------------------------------------------------------------------
/// Assignment operator
//----------------------------------------------------------------------------------------------------
template <typename S>
inline Matrix3<S>& Matrix3<S>::operator=(const Matrix3& obj)
{
System::memcpy(m_v, sizeof(m_v), obj.m_v, sizeof(obj.m_v));
return *this;
}
//----------------------------------------------------------------------------------------------------
/// Comparison operator. Checks for equality using exact comparisons.
//----------------------------------------------------------------------------------------------------
template <typename S>
bool Matrix3<S>::operator==(const Matrix3& rhs) const
{
int i;
for (i = 0; i < 9; i++)
{
if (m_v[i] != rhs.m_v[i]) return false;
}
return true;
}
//----------------------------------------------------------------------------------------------------
/// Comparison operator. Checks for not equal using exact comparisons.
//----------------------------------------------------------------------------------------------------
template <typename S>
bool Matrix3<S>::operator!=(const Matrix3& rhs) const
{
int i;
for (i = 0; i < 9; i++)
{
if (m_v[i] != rhs.m_v[i]) return true;
}
return false;
}
//----------------------------------------------------------------------------------------------------
///
//----------------------------------------------------------------------------------------------------
template <typename S>
const Matrix3<S> Matrix3<S>::operator*(const Matrix3& rhs) const
{
Matrix3 m;
int r;
for (r = 0; r < 3; r++)
{
int c;
for (c = 0; c < 3; c++)
{
S val = 0;
int a;
for (a = 0; a < 3; a++)
{
val += rowCol(r, a)*rhs.rowCol(a, c);
}
m.setRowCol(r, c, val);
}
}
return m;
}
//----------------------------------------------------------------------------------------------------
/// Sets this matrix to identity
//----------------------------------------------------------------------------------------------------
template <typename S>
void Matrix3<S>::setIdentity()
{
m_v[0] = 1;
m_v[1] = 0;
m_v[2] = 0;
m_v[3] = 0;
m_v[4] = 1;
m_v[5] = 0;
m_v[6] = 0;
m_v[7] = 0;
m_v[8] = 1;
}
//----------------------------------------------------------------------------------------------------
/// Check if this matrix is identity using exact comparisons
//----------------------------------------------------------------------------------------------------
template <typename S>
bool Matrix3<S>::isIdentity() const
{
if (m_v[0] != 1) return false;
if (m_v[1] != 0) return false;
if (m_v[2] != 0) return false;
if (m_v[3] != 0) return false;
if (m_v[4] != 1) return false;
if (m_v[5] != 0) return false;
if (m_v[6] != 0) return false;
if (m_v[7] != 0) return false;
if (m_v[8] != 1) return false;
return true;
}
//----------------------------------------------------------------------------------------------------
/// Set all matrix elements to 0
//----------------------------------------------------------------------------------------------------
template <typename S>
void Matrix3<S>::setZero()
{
m_v[0] = 0;
m_v[1] = 0;
m_v[2] = 0;
m_v[3] = 0;
m_v[4] = 0;
m_v[5] = 0;
m_v[6] = 0;
m_v[7] = 0;
m_v[8] = 0;
}
//----------------------------------------------------------------------------------------------------
/// Returns true if all elements of the matrix are 0. Uses exact comparison.
//----------------------------------------------------------------------------------------------------
template <typename S>
bool Matrix3<S>::isZero() const
{
if (m_v[0] != 0) return false;
if (m_v[1] != 0) return false;
if (m_v[2] != 0) return false;
if (m_v[3] != 0) return false;
if (m_v[4] != 0) return false;
if (m_v[5] != 0) return false;
if (m_v[6] != 0) return false;
if (m_v[7] != 0) return false;
if (m_v[8] != 0) return false;
return true;
}
//----------------------------------------------------------------------------------------------------
/// Set the matrix element at the specified row and column
//----------------------------------------------------------------------------------------------------
template <typename S>
inline void Matrix3<S>::setRowCol(int row, int col, S value)
{
CVF_TIGHT_ASSERT(row >= 0 && row < 3);
CVF_TIGHT_ASSERT(col >= 0 && col < 3);
m_v[3*col + row] = value;
}
//----------------------------------------------------------------------------------------------------
/// Get the matrix element at the specified row and column
//----------------------------------------------------------------------------------------------------
template <typename S>
inline S Matrix3<S>::rowCol(int row, int col) const
{
CVF_TIGHT_ASSERT(row >= 0 && row < 3);
CVF_TIGHT_ASSERT(col >= 0 && col < 3);
return m_v[3*col + row];
}
//--------------------------------------------------------------------------------------------------
/// Get modifiable reference to the the matrix element at the specified row and column
//--------------------------------------------------------------------------------------------------
template <typename S>
inline S& Matrix3<S>::operator()(int row, int col)
{
CVF_TIGHT_ASSERT(row >= 0 && row < 3);
CVF_TIGHT_ASSERT(col >= 0 && col < 3);
return m_v[3*col + row];
}
//--------------------------------------------------------------------------------------------------
/// Get the matrix element at the specified row and column
//--------------------------------------------------------------------------------------------------
template <typename S>
inline S Matrix3<S>::operator()(int row, int col) const
{
CVF_TIGHT_ASSERT(row >= 0 && row < 3);
CVF_TIGHT_ASSERT(col >= 0 && col < 3);
return m_v[3*col + row];
}
//----------------------------------------------------------------------------------------------------
///
//----------------------------------------------------------------------------------------------------
template <typename S>
bool Matrix3<S>::invert()
{
// Use double internally here
double m00 = static_cast<double>(m_v[e00]);
double m10 = static_cast<double>(m_v[e10]);
double m20 = static_cast<double>(m_v[e20]);
double m01 = static_cast<double>(m_v[e01]);
double m11 = static_cast<double>(m_v[e11]);
double m21 = static_cast<double>(m_v[e21]);
double m02 = static_cast<double>(m_v[e02]);
double m12 = static_cast<double>(m_v[e12]);
double m22 = static_cast<double>(m_v[e22]);
double det = m00*m11*m22 + m01*m12*m20 + m02*m10*m21 - m00*m12*m21 - m01*m10*m22 - m02*m11*m20;
if (Math::abs(det) > std::numeric_limits<double>::epsilon())
{
double invDet = 1/det;
m_v[e00] = static_cast<S>( (m11*m22 - m12*m21) * invDet );
m_v[e01] = static_cast<S>( (m02*m21 - m01*m22) * invDet );
m_v[e02] = static_cast<S>( (m01*m12 - m02*m11) * invDet );
m_v[e10] = static_cast<S>( (m12*m20 - m10*m22) * invDet );
m_v[e11] = static_cast<S>( (m00*m22 - m02*m20) * invDet );
m_v[e12] = static_cast<S>( (m02*m10 - m00*m12) * invDet );
m_v[e20] = static_cast<S>( (m10*m21 - m11*m20) * invDet );
m_v[e21] = static_cast<S>( (m01*m20 - m00*m21) * invDet );
m_v[e22] = static_cast<S>( (m00*m11 - m01*m10) * invDet );
return true;
}
else
{
return false;
}
}
//----------------------------------------------------------------------------------------------------
///
//----------------------------------------------------------------------------------------------------
template <typename S>
const Matrix3<S> Matrix3<S>::getInverted(bool* pInvertible) const
{
Matrix3 m(*this);
if (m.invert())
{
if (pInvertible) *pInvertible = true;
}
else
{
if (pInvertible) *pInvertible = false;
m.setZero();
}
return m;
}
//----------------------------------------------------------------------------------------------------
///
//----------------------------------------------------------------------------------------------------
template <typename S>
S Matrix3<S>::determinant() const
{
S det = m_v[e00]*m_v[e11]*m_v[e22] +
m_v[e01]*m_v[e12]*m_v[e20] +
m_v[e02]*m_v[e10]*m_v[e21] -
m_v[e00]*m_v[e12]*m_v[e21] -
m_v[e01]*m_v[e10]*m_v[e22] -
m_v[e02]*m_v[e11]*m_v[e20];
return det;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template <typename S>
void Matrix3<S>::transpose()
{
S tmp;
int i, j;
for (i = 0; i < 3; i++)
{
for (j = i + 1; j < 3; j++)
{
tmp = m_v[j + 3*i];
m_v[j + 3*i] = m_v[3*j + i];
m_v[3*j + i] = tmp;
}
}
}
//----------------------------------------------------------------------------------------------------
///
//----------------------------------------------------------------------------------------------------
template <typename S>
const S* Matrix3<S>::ptr() const
{
return m_v;
}
//----------------------------------------------------------------------------------------------------
///
//----------------------------------------------------------------------------------------------------
template <typename S>
Matrix3<S> Matrix3<S>::fromRotation(Vector3<S> axis, S angle)
{
axis.normalize();
S rcos = Math::cos(angle);
S rsin = Math::sin(angle);
Matrix3 m;
m.m_v[e00] = rcos + axis.x()*axis.x()*(1 - rcos);
m.m_v[e10] = axis.z() * rsin + axis.y()*axis.x()*(1 - rcos);
m.m_v[e20] = -axis.y() * rsin + axis.z()*axis.x()*(1 - rcos);
m.m_v[e01] = -axis.z() * rsin + axis.x()*axis.y()*(1 - rcos);
m.m_v[e11] = rcos + axis.y()*axis.y()*(1 - rcos);
m.m_v[e21] = axis.x() * rsin + axis.z()*axis.y()*(1 - rcos);
m.m_v[e02] = axis.y() * rsin + axis.x()*axis.z()*(1 - rcos);
m.m_v[e12] = -axis.x() * rsin + axis.y()*axis.z()*(1 - rcos);
m.m_v[e22] = rcos + axis.z()*axis.z()*(1 - rcos);
return m;
}
}
+118
View File
@@ -0,0 +1,118 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include "cvfSystem.h"
#include "cvfVector3.h"
#include "cvfVector4.h"
#include "cvfMatrix3.h"
namespace cvf {
//==================================================================================================
//
// Template matrix class for 4x4 matrices
//
//==================================================================================================
template<typename S>
class Matrix4
{
public:
Matrix4();
Matrix4(const Matrix4& other);
Matrix4(S m00, S m01, S m02, S m03, S m10, S m11, S m12, S m13, S m20, S m21, S m22, S m23, S m30, S m31, S m32, S m33);
explicit Matrix4(const Matrix3<S>& other);
template<typename T>
explicit Matrix4(const T& other);
inline Matrix4& operator=(const Matrix4& rhs);
bool operator==(const Matrix4& rhs) const;
bool operator!=(const Matrix4& rhs) const;
const Matrix4 operator*(const Matrix4& rhs) const;
const Vector4<S> operator*(const Vector4<S>& rhs) const;
void setIdentity();
bool isIdentity() const;
void setZero();
bool isZero() const;
inline S& operator()(int row, int col);
inline S operator()(int row, int col) const;
inline void setRowCol(int row, int col, S value);
inline S rowCol(int row, int col) const;
void setRow(int row, const Vector4<S>& vector);
Vector4<S> row(int row) const;
void setCol(int column, const Vector4<S>& vector);
Vector4<S> col(int column) const;
template<typename T>
void set(const Matrix4<T>& mat);
Vector3<S> translation() const;
void setTranslation(const Vector3<S>& trans);
void translatePreMultiply(const Vector3<S>& trans);
void translatePostMultiply(const Vector3<S>& trans);
bool invert();
const Matrix4 getInverted(bool* pInvertible = NULL) const;
S determinant() const;
void transpose();
const Matrix4 getTransposed() const;
void setFromMatrix3(const Matrix3<S>& mat3);
Matrix3<S> toMatrix3() const;
void toMatrix3(Matrix3<S>* mat3) const;
inline const S* ptr() const;
static Matrix4 fromTranslation(const Vector3<S>& trans);
static Matrix4 fromRotation(Vector3<S> axis, S angle);
static Matrix4 fromCoordSystemAxes(const Vector3<S>* xAxis, const Vector3<S>* yAxis, const Vector3<S>* zAxis);
public:
static const Matrix4 IDENTITY; ///< Identity matrix
static const Matrix4 ZERO; ///< Matrix with all zeros
private:
// Constants for accessing our internal array using standard matrix notation
static const int e00 = 0; static const int e01 = 4; static const int e02 = 8; static const int e03 = 12;
static const int e10 = 1; static const int e11 = 5; static const int e12 = 9; static const int e13 = 13;
static const int e20 = 2; static const int e21 = 6; static const int e22 = 10; static const int e23 = 14;
static const int e30 = 3; static const int e31 = 7; static const int e32 = 11; static const int e33 = 15;
private:
S m_v[16];
};
template<typename S>
Vector4<S> operator*(const Matrix4<S>& m, const Vector4<S>& v);
typedef Matrix4<float> Mat4f;
typedef Matrix4<double> Mat4d;
}
#include "cvfMatrix4.inl"
+886
View File
@@ -0,0 +1,886 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
namespace cvf {
//==================================================================================================
///
/// \class cvf::Matrix4
/// \ingroup Core
///
/// Matrices are stored internally as a one dimensional array for performance reasons.
///
/// The internal indices into the 1D array are as follows:
///
/// <PRE>
/// | m00 m01 m02 m03 | | 0 4 8 12 |
/// | m10 m11 m12 m13 | | 1 5 9 13 |
/// | m20 m21 m22 m23 | | 2 6 10 14 |
/// | m30 m31 m32 m33 | | 3 7 11 15 |
/// </PRE>
///
/// This is consistent with the way matrices are represented in %OpenGL.
/// To exemplify, translation values are stored in elements 12,13,14; see figure below
///
/// <PRE>
/// | 1 0 0 Tx |
/// | 0 1 0 Ty |
/// | 0 0 1 Tz |
/// | 0 0 0 1 |
/// </PRE>
///
/// From the %OpenGL red book (page 68) v' = M*v
///
/// <PRE>
/// | X'| | 1 0 0 Tx | | X |
/// | Y'| | 0 1 0 Ty | | Y |
/// | Z'| = | 0 0 1 Tz | * | Z |
/// | 1 | | 0 0 0 1 | | 1 |
/// </PRE>
///
/// Beware when porting code that uses C style double array indexing. In this case, the first
/// index given will corrspond to the columnd, eg M[3][0] = Tx, M[3][1] = Ty, M[3][2] = Tz
///
/// To ease accessing the internal 1D array in implementations, the private eij constants can be used.
/// These are consistent with the normal row column ordering, so that e02 accesses the element
/// in the first row and the third column.
///
//==================================================================================================
template<typename S> Matrix4<S> const Matrix4<S>::IDENTITY;
template<typename S> Matrix4<S> const Matrix4<S>::ZERO(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
//----------------------------------------------------------------------------------------------------
/// Default constructor. Initializes matrix to identity
//----------------------------------------------------------------------------------------------------
template <typename S>
Matrix4<S>::Matrix4()
{
setIdentity();
}
//----------------------------------------------------------------------------------------------------
/// Copy constructor
//----------------------------------------------------------------------------------------------------
template <typename S>
inline Matrix4<S>::Matrix4(const Matrix4& other)
{
System::memcpy(m_v, sizeof(m_v), other.m_v, sizeof(other.m_v));
}
//----------------------------------------------------------------------------------------------------
/// Constructor with explicit initialization of all matrix elements.
///
/// The value of the parameter \a mrc will be placed in row r and column c of the matrix, eg m23
/// goes into row 2, column 3.
//----------------------------------------------------------------------------------------------------
template <typename S>
Matrix4<S>::Matrix4(S m00, S m01, S m02, S m03, S m10, S m11, S m12, S m13, S m20, S m21, S m22, S m23, S m30, S m31, S m32, S m33)
{
m_v[e00] = m00;
m_v[e10] = m10;
m_v[e20] = m20;
m_v[e30] = m30;
m_v[e01] = m01;
m_v[e11] = m11;
m_v[e21] = m21;
m_v[e31] = m31;
m_v[e02] = m02;
m_v[e12] = m12;
m_v[e22] = m22;
m_v[e32] = m32;
m_v[e03] = m03;
m_v[e13] = m13;
m_v[e23] = m23;
m_v[e33] = m33;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename S>
Matrix4<S>::Matrix4(const Matrix3<S>& other)
{
setFromMatrix3(other);
}
//----------------------------------------------------------------------------------------------------
///
//----------------------------------------------------------------------------------------------------
template<typename S>
template<typename T>
Matrix4<S>::Matrix4(const T& other)
{
m_v[e00] = static_cast<S>(other.rowCol(0, 0));
m_v[e10] = static_cast<S>(other.rowCol(1, 0));
m_v[e20] = static_cast<S>(other.rowCol(2, 0));
m_v[e30] = static_cast<S>(other.rowCol(3, 0));
m_v[e01] = static_cast<S>(other.rowCol(0, 1));
m_v[e11] = static_cast<S>(other.rowCol(1, 1));
m_v[e21] = static_cast<S>(other.rowCol(2, 1));
m_v[e31] = static_cast<S>(other.rowCol(3, 1));
m_v[e02] = static_cast<S>(other.rowCol(0, 2));
m_v[e12] = static_cast<S>(other.rowCol(1, 2));
m_v[e22] = static_cast<S>(other.rowCol(2, 2));
m_v[e32] = static_cast<S>(other.rowCol(3, 2));
m_v[e03] = static_cast<S>(other.rowCol(0, 3));
m_v[e13] = static_cast<S>(other.rowCol(1, 3));
m_v[e23] = static_cast<S>(other.rowCol(2, 3));
m_v[e33] = static_cast<S>(other.rowCol(3, 3));
}
//----------------------------------------------------------------------------------------------------
/// Assignment operator
//----------------------------------------------------------------------------------------------------
template <typename S>
inline Matrix4<S>& Matrix4<S>::operator=(const Matrix4& obj)
{
System::memcpy(m_v, sizeof(m_v), obj.m_v, sizeof(obj.m_v));
return *this;
}
//----------------------------------------------------------------------------------------------------
/// Comparison operator. Checks for equality using exact comparisons.
//----------------------------------------------------------------------------------------------------
template <typename S>
bool Matrix4<S>::operator==(const Matrix4& rhs) const
{
int i;
for (i = 0; i < 16; i++)
{
if (m_v[i] != rhs.m_v[i]) return false;
}
return true;
}
//----------------------------------------------------------------------------------------------------
/// Comparison operator. Checks for not equal using exact comparisons.
//----------------------------------------------------------------------------------------------------
template <typename S>
bool Matrix4<S>::operator!=(const Matrix4& rhs) const
{
int i;
for (i = 0; i < 16; i++)
{
if (m_v[i] != rhs.m_v[i]) return true;
}
return false;
}
//----------------------------------------------------------------------------------------------------
///
//----------------------------------------------------------------------------------------------------
template <typename S>
const Matrix4<S> Matrix4<S>::operator*(const Matrix4& rhs) const
{
Matrix4 m;
m.m_v[e00] = m_v[e00] * rhs.m_v[e00] + m_v[e01] * rhs.m_v[e10] + m_v[e02] * rhs.m_v[e20] + m_v[e03] * rhs.m_v[e30];
m.m_v[e01] = m_v[e00] * rhs.m_v[e01] + m_v[e01] * rhs.m_v[e11] + m_v[e02] * rhs.m_v[e21] + m_v[e03] * rhs.m_v[e31];
m.m_v[e02] = m_v[e00] * rhs.m_v[e02] + m_v[e01] * rhs.m_v[e12] + m_v[e02] * rhs.m_v[e22] + m_v[e03] * rhs.m_v[e32];
m.m_v[e03] = m_v[e00] * rhs.m_v[e03] + m_v[e01] * rhs.m_v[e13] + m_v[e02] * rhs.m_v[e23] + m_v[e03] * rhs.m_v[e33];
m.m_v[e10] = m_v[e10] * rhs.m_v[e00] + m_v[e11] * rhs.m_v[e10] + m_v[e12] * rhs.m_v[e20] + m_v[e13] * rhs.m_v[e30];
m.m_v[e11] = m_v[e10] * rhs.m_v[e01] + m_v[e11] * rhs.m_v[e11] + m_v[e12] * rhs.m_v[e21] + m_v[e13] * rhs.m_v[e31];
m.m_v[e12] = m_v[e10] * rhs.m_v[e02] + m_v[e11] * rhs.m_v[e12] + m_v[e12] * rhs.m_v[e22] + m_v[e13] * rhs.m_v[e32];
m.m_v[e13] = m_v[e10] * rhs.m_v[e03] + m_v[e11] * rhs.m_v[e13] + m_v[e12] * rhs.m_v[e23] + m_v[e13] * rhs.m_v[e33];
m.m_v[e20] = m_v[e20] * rhs.m_v[e00] + m_v[e21] * rhs.m_v[e10] + m_v[e22] * rhs.m_v[e20] + m_v[e23] * rhs.m_v[e30];
m.m_v[e21] = m_v[e20] * rhs.m_v[e01] + m_v[e21] * rhs.m_v[e11] + m_v[e22] * rhs.m_v[e21] + m_v[e23] * rhs.m_v[e31];
m.m_v[e22] = m_v[e20] * rhs.m_v[e02] + m_v[e21] * rhs.m_v[e12] + m_v[e22] * rhs.m_v[e22] + m_v[e23] * rhs.m_v[e32];
m.m_v[e23] = m_v[e20] * rhs.m_v[e03] + m_v[e21] * rhs.m_v[e13] + m_v[e22] * rhs.m_v[e23] + m_v[e23] * rhs.m_v[e33];
m.m_v[e30] = m_v[e30] * rhs.m_v[e00] + m_v[e31] * rhs.m_v[e10] + m_v[e32] * rhs.m_v[e20] + m_v[e33] * rhs.m_v[e30];
m.m_v[e31] = m_v[e30] * rhs.m_v[e01] + m_v[e31] * rhs.m_v[e11] + m_v[e32] * rhs.m_v[e21] + m_v[e33] * rhs.m_v[e31];
m.m_v[e32] = m_v[e30] * rhs.m_v[e02] + m_v[e31] * rhs.m_v[e12] + m_v[e32] * rhs.m_v[e22] + m_v[e33] * rhs.m_v[e32];
m.m_v[e33] = m_v[e30] * rhs.m_v[e03] + m_v[e31] * rhs.m_v[e13] + m_v[e32] * rhs.m_v[e23] + m_v[e33] * rhs.m_v[e33];
return m;
}
//----------------------------------------------------------------------------------------------------
///
//----------------------------------------------------------------------------------------------------
template <typename S>
const Vector4<S> Matrix4<S>::operator*(const Vector4<S>& rhs) const
{
return Vector4<S>(m_v[e00]*rhs.x() + m_v[e01]*rhs.y() + m_v[e02]*rhs.z() + m_v[e03]*rhs.w(),
m_v[e10]*rhs.x() + m_v[e11]*rhs.y() + m_v[e12]*rhs.z() + m_v[e13]*rhs.w(),
m_v[e20]*rhs.x() + m_v[e21]*rhs.y() + m_v[e22]*rhs.z() + m_v[e23]*rhs.w(),
m_v[e30]*rhs.x() + m_v[e31]*rhs.y() + m_v[e32]*rhs.z() + m_v[e33]*rhs.w());
}
//----------------------------------------------------------------------------------------------------
/// Sets this matrix to identity
//----------------------------------------------------------------------------------------------------
template <typename S>
void Matrix4<S>::setIdentity()
{
m_v[0] = 1;
m_v[1] = 0;
m_v[2] = 0;
m_v[3] = 0;
m_v[4] = 0;
m_v[5] = 1;
m_v[6] = 0;
m_v[7] = 0;
m_v[8] = 0;
m_v[9] = 0;
m_v[10] = 1;
m_v[11] = 0;
m_v[12] = 0;
m_v[13] = 0;
m_v[14] = 0;
m_v[15] = 1;
}
//----------------------------------------------------------------------------------------------------
/// Check if this matrix is identity using exact comparisons
//----------------------------------------------------------------------------------------------------
template <typename S>
bool Matrix4<S>::isIdentity() const
{
if (m_v[0] != 1) return false;
if (m_v[1] != 0) return false;
if (m_v[2] != 0) return false;
if (m_v[3] != 0) return false;
if (m_v[4] != 0) return false;
if (m_v[5] != 1) return false;
if (m_v[6] != 0) return false;
if (m_v[7] != 0) return false;
if (m_v[8] != 0) return false;
if (m_v[9] != 0) return false;
if (m_v[10] != 1) return false;
if (m_v[11] != 0) return false;
if (m_v[12] != 0) return false;
if (m_v[13] != 0) return false;
if (m_v[14] != 0) return false;
if (m_v[15] != 1) return false;
return true;
}
//----------------------------------------------------------------------------------------------------
/// Set all matrix elements to 0
//----------------------------------------------------------------------------------------------------
template <typename S>
void Matrix4<S>::setZero()
{
m_v[0] = 0;
m_v[1] = 0;
m_v[2] = 0;
m_v[3] = 0;
m_v[4] = 0;
m_v[5] = 0;
m_v[6] = 0;
m_v[7] = 0;
m_v[8] = 0;
m_v[9] = 0;
m_v[10] = 0;
m_v[11] = 0;
m_v[12] = 0;
m_v[13] = 0;
m_v[14] = 0;
m_v[15] = 0;
}
//----------------------------------------------------------------------------------------------------
/// Returns true if all elements of the matrix are 0. Uses exact comparison.
//----------------------------------------------------------------------------------------------------
template <typename S>
bool Matrix4<S>::isZero() const
{
if (m_v[0] != 0) return false;
if (m_v[1] != 0) return false;
if (m_v[2] != 0) return false;
if (m_v[3] != 0) return false;
if (m_v[4] != 0) return false;
if (m_v[5] != 0) return false;
if (m_v[6] != 0) return false;
if (m_v[7] != 0) return false;
if (m_v[8] != 0) return false;
if (m_v[9] != 0) return false;
if (m_v[10] != 0) return false;
if (m_v[11] != 0) return false;
if (m_v[12] != 0) return false;
if (m_v[13] != 0) return false;
if (m_v[14] != 0) return false;
if (m_v[15] != 0) return false;
return true;
}
//----------------------------------------------------------------------------------------------------
/// Set the matrix element at the specified row and column
//----------------------------------------------------------------------------------------------------
template <typename S>
inline void Matrix4<S>::setRowCol(int row, int col, S value)
{
CVF_TIGHT_ASSERT(row >= 0 && row < 4);
CVF_TIGHT_ASSERT(col >= 0 && col < 4);
m_v[4*col + row] = value;
}
//----------------------------------------------------------------------------------------------------
/// Get the matrix element at the specified row and column
//----------------------------------------------------------------------------------------------------
template <typename S>
inline S Matrix4<S>::rowCol(int row, int col) const
{
CVF_TIGHT_ASSERT(row >= 0 && row < 4);
CVF_TIGHT_ASSERT(col >= 0 && col < 4);
return m_v[4*col + row];
}
//--------------------------------------------------------------------------------------------------
/// Get modifiable reference to the the matrix element at the specified row and column
//--------------------------------------------------------------------------------------------------
template <typename S>
inline S& Matrix4<S>::operator()(int row, int col)
{
CVF_TIGHT_ASSERT(row >= 0 && row < 4);
CVF_TIGHT_ASSERT(col >= 0 && col < 4);
return m_v[4*col + row];
}
//--------------------------------------------------------------------------------------------------
/// Get the matrix element at the specified row and column
//--------------------------------------------------------------------------------------------------
template <typename S>
inline S Matrix4<S>::operator()(int row, int col) const
{
CVF_TIGHT_ASSERT(row >= 0 && row < 4);
CVF_TIGHT_ASSERT(col >= 0 && col < 4);
return m_v[4*col + row];
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template <typename S>
void Matrix4<S>::setRow(int row, const Vector4<S>& vector)
{
CVF_TIGHT_ASSERT(row >= 0 && row < 4);
m_v[row] = vector.x();
m_v[row + 4] = vector.y();
m_v[row + 8] = vector.z();
m_v[row + 12] = vector.w();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template <typename S>
Vector4<S> Matrix4<S>::row(int row) const
{
CVF_TIGHT_ASSERT(row >= 0 && row < 4);
return Vector4<S>(m_v[row], m_v[row + 4], m_v[row + 8], m_v[row + 12]);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template <typename S>
void Matrix4<S>::setCol(int column, const Vector4<S>& vector)
{
CVF_TIGHT_ASSERT(column >= 0 && column < 4);
m_v[4*column] = vector.x();
m_v[4*column + 1] = vector.y();
m_v[4*column + 2] = vector.z();
m_v[4*column + 3] = vector.w();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template <typename S>
Vector4<S> Matrix4<S>::col(int column) const
{
CVF_TIGHT_ASSERT(column >= 0 && column < 4);
return Vector4<S>(m_v[4*column], m_v[4*column + 1], m_v[4*column + 2], m_v[4*column + 3]);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename S>
template<typename T>
void Matrix4<S>::set(const Matrix4<T>& mat)
{
const T* matPtr = mat.ptr();
for (int i = 0; i < 16; i++)
{
m_v[i] = static_cast<S>(matPtr[i]);
}
}
//----------------------------------------------------------------------------------------------------
/// Extracts the translation part of the transformation matrix
//----------------------------------------------------------------------------------------------------
template <typename S>
Vector3<S> Matrix4<S>::translation() const
{
return Vector3<S>(m_v[e03], m_v[e13], m_v[e23]);
}
//----------------------------------------------------------------------------------------------------
/// Sets the translation transformation part of the matrix
//----------------------------------------------------------------------------------------------------
template <typename S>
void Matrix4<S>::setTranslation(const Vector3<S>& trans)
{
m_v[e03] = trans.x();
m_v[e13] = trans.y();
m_v[e23] = trans.z();
}
//----------------------------------------------------------------------------------------------------
/// Adds translation by pre-multiplying the matrix with a matrix containing the specified translation
///
/// Adds translation to this (transformation) matrix by pre multiplying the current matrix M with
/// a matrix containing the specified translation. Calling this function has the effect of doing the
/// multiplication T x M where T is a matrix that only contains translation.
///
/// \param trans Specifies the X, Y and Z components of the translation.
//----------------------------------------------------------------------------------------------------
template <typename S>
void Matrix4<S>::translatePreMultiply(const Vector3<S>& trans)
{
m_v[e00] += trans.x()*m_v[e30];
m_v[e01] += trans.x()*m_v[e31];
m_v[e02] += trans.x()*m_v[e32];
m_v[e03] += trans.x()*m_v[e33];
m_v[e10] += trans.y()*m_v[e30];
m_v[e11] += trans.y()*m_v[e31];
m_v[e12] += trans.y()*m_v[e32];
m_v[e13] += trans.y()*m_v[e33];
m_v[e20] += trans.z()*m_v[e30];
m_v[e21] += trans.z()*m_v[e31];
m_v[e22] += trans.z()*m_v[e32];
m_v[e23] += trans.z()*m_v[e33];
}
//----------------------------------------------------------------------------------------------------
/// Adds translation by post-multiplying the matrix with a matrix containing the specified translation
///
/// Adds translation to this (transformation) matrix by post multiplying the current matrix M with
/// a matrix containing the specified translation. Calling this function has the effect of doing the
/// multiplication M x T where T is a matrix that only contains translation.
///
/// \param trans Specifies the X, Y and Z coordinates of the translation.
//----------------------------------------------------------------------------------------------------
template <typename S>
void Matrix4<S>::translatePostMultiply(const Vector3<S>& trans)
{
m_v[e03] += trans.x()*m_v[e00] + trans.y()*m_v[e01] + trans.z()*m_v[e02];
m_v[e13] += trans.x()*m_v[e10] + trans.y()*m_v[e11] + trans.z()*m_v[e12];
m_v[e23] += trans.x()*m_v[e20] + trans.y()*m_v[e21] + trans.z()*m_v[e22];
m_v[e33] += trans.x()*m_v[e30] + trans.y()*m_v[e31] + trans.z()*m_v[e32];
}
//----------------------------------------------------------------------------------------------------
///
//----------------------------------------------------------------------------------------------------
template <typename S>
bool Matrix4<S>::invert()
{
// Use double internally here
const double m00 = static_cast<double>(m_v[e00]);
const double m10 = static_cast<double>(m_v[e10]);
const double m20 = static_cast<double>(m_v[e20]);
const double m30 = static_cast<double>(m_v[e30]);
const double m01 = static_cast<double>(m_v[e01]);
const double m11 = static_cast<double>(m_v[e11]);
const double m21 = static_cast<double>(m_v[e21]);
const double m31 = static_cast<double>(m_v[e31]);
const double m02 = static_cast<double>(m_v[e02]);
const double m12 = static_cast<double>(m_v[e12]);
const double m22 = static_cast<double>(m_v[e22]);
const double m32 = static_cast<double>(m_v[e32]);
const double m03 = static_cast<double>(m_v[e03]);
const double m13 = static_cast<double>(m_v[e13]);
const double m23 = static_cast<double>(m_v[e23]);
const double m33 = static_cast<double>(m_v[e33]);
const double s0 = m00 * m11 - m01 * m10;
const double s1 = m00 * m12 - m02 * m10;
const double s2 = m00 * m13 - m03 * m10;
const double s3 = m01 * m12 - m02 * m11;
const double s4 = m01 * m13 - m03 * m11;
const double s5 = m02 * m13 - m03 * m12;
const double c5 = m22 * m33 - m23 * m32;
const double c4 = m21 * m33 - m23 * m31;
const double c3 = m21 * m32 - m22 * m31;
const double c2 = m20 * m33 - m23 * m30;
const double c1 = m20 * m32 - m22 * m30;
const double c0 = m20 * m31 - m21 * m30;
const double det = s0*c5 - s1*c4 + s2*c3 + s3*c2 - s4*c1 + s5*c0;
if (Math::abs(det) > std::numeric_limits<double>::epsilon())
{
const double invDet = 1/det;
m_v[e00] = static_cast<S>( ( m11 * c5 - m12 * c4 + m13 * c3 ) * invDet );
m_v[e10] = static_cast<S>( ( - m10 * c5 + m12 * c2 - m13 * c1 ) * invDet );
m_v[e20] = static_cast<S>( ( m10 * c4 - m11 * c2 + m13 * c0 ) * invDet );
m_v[e30] = static_cast<S>( ( - m10 * c3 + m11 * c1 - m12 * c0 ) * invDet );
m_v[e01] = static_cast<S>( ( - m01 * c5 + m02 * c4 - m03 * c3 ) * invDet );
m_v[e11] = static_cast<S>( ( m00 * c5 - m02 * c2 + m03 * c1 ) * invDet );
m_v[e21] = static_cast<S>( ( - m00 * c4 + m01 * c2 - m03 * c0 ) * invDet );
m_v[e31] = static_cast<S>( ( m00 * c3 - m01 * c1 + m02 * c0 ) * invDet );
m_v[e02] = static_cast<S>( ( m31 * s5 - m32 * s4 + m33 * s3 ) * invDet );
m_v[e12] = static_cast<S>( ( - m30 * s5 + m32 * s2 - m33 * s1 ) * invDet );
m_v[e22] = static_cast<S>( ( m30 * s4 - m31 * s2 + m33 * s0 ) * invDet );
m_v[e32] = static_cast<S>( ( - m30 * s3 + m31 * s1 - m32 * s0 ) * invDet );
m_v[e03] = static_cast<S>( ( - m21 * s5 + m22 * s4 - m23 * s3 ) * invDet );
m_v[e13] = static_cast<S>( ( m20 * s5 - m22 * s2 + m23 * s1 ) * invDet );
m_v[e23] = static_cast<S>( ( - m20 * s4 + m21 * s2 - m23 * s0 ) * invDet );
m_v[e33] = static_cast<S>( ( m20 * s3 - m21 * s1 + m22 * s0 ) * invDet );
return true;
}
else
{
return false;
}
}
//----------------------------------------------------------------------------------------------------
///
//----------------------------------------------------------------------------------------------------
template <typename S>
const Matrix4<S> Matrix4<S>::getInverted(bool* pInvertible) const
{
Matrix4 m(*this);
if (m.invert())
{
if (pInvertible) *pInvertible = true;
}
else
{
if (pInvertible) *pInvertible = false;
m.setZero();
}
return m;
}
//----------------------------------------------------------------------------------------------------
///
//----------------------------------------------------------------------------------------------------
template <typename S>
S Matrix4<S>::determinant() const
{
// Consider using double precision for the intermediate calculations here
// Haven't seen any direct need for it yet, but good old GLview API did that
const S a0 = m_v[e00]*m_v[e11] - m_v[e01]*m_v[e10];
const S a1 = m_v[e00]*m_v[e12] - m_v[e02]*m_v[e10];
const S a2 = m_v[e00]*m_v[e13] - m_v[e03]*m_v[e10];
const S a3 = m_v[e01]*m_v[e12] - m_v[e02]*m_v[e11];
const S a4 = m_v[e01]*m_v[e13] - m_v[e03]*m_v[e11];
const S a5 = m_v[e02]*m_v[e13] - m_v[e03]*m_v[e12];
const S b0 = m_v[e20]*m_v[e31] - m_v[e21]*m_v[e30];
const S b1 = m_v[e20]*m_v[e32] - m_v[e22]*m_v[e30];
const S b2 = m_v[e20]*m_v[e33] - m_v[e23]*m_v[e30];
const S b3 = m_v[e21]*m_v[e32] - m_v[e22]*m_v[e31];
const S b4 = m_v[e21]*m_v[e33] - m_v[e23]*m_v[e31];
const S b5 = m_v[e22]*m_v[e33] - m_v[e23]*m_v[e32];
return (a0*b5 - a1*b4 + a2*b3 + a3*b2 - a4*b1 + a5*b0);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template <typename S>
void Matrix4<S>::transpose()
{
S tmp;
int i, j;
for (i = 0; i < 4; i++)
{
for (j = i + 1; j < 4; j++)
{
tmp = m_v[j + 4*i];
m_v[j + 4*i] = m_v[4*j + i];
m_v[4*j + i] = tmp;
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template <typename S>
const Matrix4<S> Matrix4<S>::getTransposed() const
{
Matrix4 m(*this);
m.transpose();
return m;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename S>
void Matrix4<S>::setFromMatrix3(const Matrix3<S>& mat3)
{
m_v[e00] = mat3.rowCol(0, 0);
m_v[e01] = mat3.rowCol(0, 1);
m_v[e02] = mat3.rowCol(0, 2);
m_v[e03] = 0;
m_v[e10] = mat3.rowCol(1, 0);
m_v[e11] = mat3.rowCol(1, 1);
m_v[e12] = mat3.rowCol(1, 2);
m_v[e13] = 0;
m_v[e20] = mat3.rowCol(2, 0);
m_v[e21] = mat3.rowCol(2, 1);
m_v[e22] = mat3.rowCol(2, 2);
m_v[e23] = 0;
m_v[e30] = 0;
m_v[e31] = 0;
m_v[e32] = 0;
m_v[e33] = 1;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename S>
Matrix3<S> Matrix4<S>::toMatrix3() const
{
return Matrix3<S>(m_v[e00], m_v[e01], m_v[e02],
m_v[e10], m_v[e11], m_v[e12],
m_v[e20], m_v[e21], m_v[e22]);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename S>
void Matrix4<S>::toMatrix3(Matrix3<S>* mat3) const
{
CVF_ASSERT(mat3);
mat3->setRowCol(0, 0, m_v[e00]);
mat3->setRowCol(0, 1, m_v[e01]);
mat3->setRowCol(0, 2, m_v[e02]);
mat3->setRowCol(1, 0, m_v[e10]);
mat3->setRowCol(1, 1, m_v[e11]);
mat3->setRowCol(1, 2, m_v[e12]);
mat3->setRowCol(2, 0, m_v[e20]);
mat3->setRowCol(2, 1, m_v[e21]);
mat3->setRowCol(2, 2, m_v[e22]);
}
//----------------------------------------------------------------------------------------------------
///
//----------------------------------------------------------------------------------------------------
template <typename S>
const S* Matrix4<S>::ptr() const
{
return m_v;
}
//----------------------------------------------------------------------------------------------------
/// Static member function that creates a transformation matrix containing only translation
//----------------------------------------------------------------------------------------------------
template <typename S>
Matrix4<S> Matrix4<S>::fromTranslation(const Vector3<S>& trans)
{
return Matrix4(1, 0, 0, trans.x(),
0, 1, 0, trans.y(),
0, 0, 1, trans.z(),
0, 0, 0, 1);
}
//----------------------------------------------------------------------------------------------------
///
//----------------------------------------------------------------------------------------------------
template <typename S>
Matrix4<S> Matrix4<S>::fromRotation(Vector3<S> axis, S angle)
{
axis.normalize();
S rcos = Math::cos(angle);
S rsin = Math::sin(angle);
Matrix4 m;
m.m_v[e00] = rcos + axis.x()*axis.x()*(1 - rcos);
m.m_v[e10] = axis.z() * rsin + axis.y()*axis.x()*(1 - rcos);
m.m_v[e20] = -axis.y() * rsin + axis.z()*axis.x()*(1 - rcos);
m.m_v[e01] = -axis.z() * rsin + axis.x()*axis.y()*(1 - rcos);
m.m_v[e11] = rcos + axis.y()*axis.y()*(1 - rcos);
m.m_v[e21] = axis.x() * rsin + axis.z()*axis.y()*(1 - rcos);
m.m_v[e02] = axis.y() * rsin + axis.x()*axis.z()*(1 - rcos);
m.m_v[e12] = -axis.x() * rsin + axis.y()*axis.z()*(1 - rcos);
m.m_v[e22] = rcos + axis.z()*axis.z()*(1 - rcos);
return m;
}
//----------------------------------------------------------------------------------------------------
/// Create a rotation matrix that will align the global X, Y and Z axes with the specified axes.
///
/// Note that at least one axis must be specified and all specified axes must be normalized.
/// If two or three axes are specified, they must be orthogonal to each other.
///
/// \param xAxis Orientation of x axis
/// \param yAxis Orientation of y axis
/// \param zAxis Orientation of z axis
//----------------------------------------------------------------------------------------------------
template <typename S>
Matrix4<S> Matrix4<S>::fromCoordSystemAxes(const Vector3<S>* xAxis, const Vector3<S>* yAxis, const Vector3<S>* zAxis)
{
Vector3<S> x(0, 0, 0);
Vector3<S> y(0, 0, 0);
Vector3<S> z(0, 0, 0);
if (xAxis && yAxis && zAxis)
{
x = *xAxis;
y = *yAxis;
z = *zAxis;
}
else if (xAxis && yAxis)
{
x = *xAxis;
y = *yAxis;
z = x ^ y;
}
else if (xAxis && zAxis)
{
x = *xAxis;
z = *zAxis;
y = z ^ x;
}
else if (yAxis && zAxis)
{
y = *yAxis;
z = *zAxis;
x = y ^ z;
}
else if (xAxis)
{
xAxis->createOrthonormalBasis(0, &x, &y, &z);
}
else if (yAxis)
{
yAxis->createOrthonormalBasis(1, &x, &y, &z);
}
else if (zAxis)
{
zAxis->createOrthonormalBasis(2, &x, &y, &z);
}
else
{
CVF_FAIL_MSG("Must specify at least one axis");
}
Matrix4 m;
m.setIdentity();
m.setCol(0, Vector4<S>(x, 0));
m.setCol(1, Vector4<S>(y, 0));
m.setCol(2, Vector4<S>(z, 0));
return m;
}
//--------------------------------------------------------------------------------------------------
/// Post multiplication: matrix * column vector
///
/// v' = M*v
//--------------------------------------------------------------------------------------------------
template<typename S>
cvf::Vector4<S> operator*(const cvf::Matrix4<S>& m, const cvf::Vector4<S>& v)
{
cvf::Vector4<S> vec(
v.x()*m.rowCol(0,0) + v.y()*m.rowCol(0,1) + v.z()*m.rowCol(0,2) + v.w()*m.rowCol(0,3),
v.x()*m.rowCol(1,0) + v.y()*m.rowCol(1,1) + v.z()*m.rowCol(1,2) + v.w()*m.rowCol(1,3),
v.x()*m.rowCol(2,0) + v.y()*m.rowCol(2,1) + v.z()*m.rowCol(2,2) + v.w()*m.rowCol(2,3),
v.x()*m.rowCol(3,0) + v.y()*m.rowCol(3,1) + v.z()*m.rowCol(3,2) + v.w()*m.rowCol(3,3)
);
return vec;
}
}
+117
View File
@@ -0,0 +1,117 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#include "cvfBase.h"
#include "cvfObject.h"
#include "cvfTrace.h"
#include <map>
namespace cvf {
//==================================================================================================
///
/// \class cvf::Object
/// \ingroup Core
///
/// Base class for all reference counted objects
///
/// Very often used in conjunction with the ref<> class (smart pointer) which wraps the
/// reference counting. Thus direct use of addRef() and release() is seldom needed.
///
/// The copy constructor and assignment operator is disabled by default so you will get compiler errors
/// instead of unexpected behavior if you pass objects (that derive from Object) by value or assign objects.
//==================================================================================================
//--------------------------------------------------------------------------------------------------
/// Get the set of currently active/allocated object instances
///
/// Note that unless the define CVF_TRACK_ACTIVE_OBJECT_INSTANCES is set to 1, this function
/// will always return an empty set.
//--------------------------------------------------------------------------------------------------
std::set<Object*>* Object::activeObjectInstances()
{
static std::set<Object*>* sl_activeObjects = NULL;
if (!sl_activeObjects)
{
sl_activeObjects = new std::set<Object*>;
}
return sl_activeObjects;
}
//--------------------------------------------------------------------------------------------------
/// Dump list of active object instances using Trace class
///
/// Currently this function utilizes RTTI and typeid to get the class names.
/// Data on active instances will only be present if CVF_TRACK_ACTIVE_OBJECT_INSTANCES is defined
//--------------------------------------------------------------------------------------------------
void Object::dumpActiveObjectInstances()
{
Trace::show("Dumping active object instances:");
std::set<Object*>* objInstances = Object::activeObjectInstances();
size_t numInstances = objInstances->size();
#if ((CVF_TRACK_ACTIVE_OBJECT_INSTANCES >= 1 && defined(_DEBUG)) || CVF_TRACK_ACTIVE_OBJECT_INSTANCES == 2)
// Use a map to count the number of occurences of each class
std::map<std::string, int> occurences;
std::set<Object*>::iterator it;
for (it = objInstances->begin(); it != objInstances->end(); ++it)
{
Object* obj = *it;
const type_info& typeInfo = typeid(*obj);
const char* className = typeInfo.name();
if (occurences.find(className) != occurences.end())
{
occurences[className] += 1;
}
else
{
occurences[className] = 1;
}
}
if (occurences.size() > 0)
{
std::map<std::string, int>::iterator it;
for (it = occurences.begin(); it != occurences.end(); ++it)
{
Trace::show("%6d instances of: %s", it->second, it->first.data());
}
}
#else
Trace::show(" Tracking of active instances not enabled!");
#endif
Trace::show("Total number of active object instances: %d", numInstances);
}
} // namespace cvf
+156
View File
@@ -0,0 +1,156 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include "cvfSystem.h"
#include <set>
namespace cvf {
//==================================================================================================
//
// Base class for all reference counted objects
//
//==================================================================================================
class Object
{
public:
inline Object();
inline virtual ~Object();
inline int addRef() const;
inline int release() const;
inline int refCount() const;
// Helpers for debugging, see the CVF_TRACK_ACTIVE_OBJECT_INSTANCES define
static std::set<Object*>* activeObjectInstances();
static void dumpActiveObjectInstances();
private:
mutable int m_refCount;
CVF_DISABLE_COPY_AND_ASSIGN(Object);
};
//==================================================================================================
//
// Smart pointer class
//
//==================================================================================================
template <typename T>
class ref
{
public:
ref(T* object = NULL);
ref(const ref& other);
template<typename T2> ref(const ref<T2>& other);
~ref();
ref& operator=(T* rhs);
ref& operator=(ref rhs);
template<typename T2> ref& operator=(const ref<T2>& rhs);
inline T* operator->();
inline const T* operator->() const;
inline T& operator*();
inline const T& operator*() const;
inline T* p();
inline const T* p() const;
inline bool isNull() const;
inline bool notNull() const;
bool operator<(const ref& rhs) const;
void swap(ref& other);
private:
T* m_object;
};
/// \relates cvf::ref
/// @{
template<typename T1, typename T2> inline bool operator==(const ref<T1>& a, const ref<T2>& b) { return a.p() == b.p(); } ///< Returns true if the internal pointers of refs \a a and \a b are equal.
template<typename T1, typename T2> inline bool operator!=(const ref<T1>& a, const ref<T2>& b) { return a.p() != b.p(); } ///< Returns true if the internal pointers of refs \a a and \a b are different.
template<typename T1, typename T2> inline bool operator==(const ref<T1>& a, T2* b) { return a.p() == b; } ///< Returns true if the internal pointer of ref \a a is equal to the naked pointer \a b.
template<typename T1, typename T2> inline bool operator!=(const ref<T1>& a, T2* b) { return a.p() != b; } ///< Returns true if the internal pointer of ref \a a is different from the naked pointer \a b.
template<typename T1, typename T2> inline bool operator==(T1* a, const ref<T2>& b) { return a == b.p(); } ///< Returns true if the naked pointer \a a is equal to the internal pointer of ref \a b.
template<typename T1, typename T2> inline bool operator!=(T1* a, const ref<T2>& b) { return a != b.p(); } ///< Returns true if the naked pointer \a a is different from the internal pointer of ref \a b.
/// Swap contents of \a a and \a b. Matches signature of std::swap().
/// \todo Need to investigate which STL algorithms actually utilize the swap() function.
template<typename T> inline void swap(ref<T>& a, ref<T>& b) { a.swap(b); }
/// @}
//==================================================================================================
//
// Smart pointer class for const pointers
//
//==================================================================================================
template <typename T>
class cref
{
public:
cref(const T* object = NULL);
cref(const cref& other);
template<typename T2> cref(const cref<T2>& other);
~cref();
cref& operator=(const T* rhs);
cref& operator=(cref rhs);
template<typename T2> cref& operator=(const cref<T2>& rhs);
inline const T* operator->() const;
inline const T& operator*() const;
inline const T* p() const;
inline bool isNull() const;
inline bool notNull() const;
bool operator<(const cref& rhs) const;
void swap(cref& other);
private:
const T* m_object;
};
/// \relates cvf::cref
/// @{
template<typename T1, typename T2> inline bool operator==(const cref<T1>& a, const cref<T2>& b) { return a.p() == b.p(); } ///< Returns true if the internal pointers of refs \a a and \a b are equal.
template<typename T1, typename T2> inline bool operator!=(const cref<T1>& a, const cref<T2>& b) { return a.p() != b.p(); } ///< Returns true if the internal pointers of refs \a a and \a b are different.
template<typename T1, typename T2> inline bool operator==(const cref<T1>& a, T2* b) { return a.p() == b; } ///< Returns true if the internal pointer of ref \a a is equal to the naked pointer \a b.
template<typename T1, typename T2> inline bool operator!=(const cref<T1>& a, T2* b) { return a.p() != b; } ///< Returns true if the internal pointer of ref \a a is different from the naked pointer \a b.
template<typename T1, typename T2> inline bool operator==(T1* a, const cref<T2>& b) { return a == b.p(); } ///< Returns true if the naked pointer \a a is equal to the internal pointer of ref \a b.
template<typename T1, typename T2> inline bool operator!=(T1* a, const cref<T2>& b) { return a != b.p(); } ///< Returns true if the naked pointer \a a is different from the internal pointer of ref \a b.
/// @}
}
#include "cvfObject.inl"
+559
View File
@@ -0,0 +1,559 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
namespace cvf {
//--------------------------------------------------------------------------------------------------
/// Constructor. Set the ref count to zero
//--------------------------------------------------------------------------------------------------
inline Object::Object()
: m_refCount(0)
{
#if ((CVF_TRACK_ACTIVE_OBJECT_INSTANCES >= 1 && defined(_DEBUG)) || CVF_TRACK_ACTIVE_OBJECT_INSTANCES == 2)
activeObjectInstances()->insert(this);
#endif
}
//--------------------------------------------------------------------------------------------------
/// Destructor. Asserts that the ref count is zero.
//--------------------------------------------------------------------------------------------------
inline Object::~Object()
{
CVF_ASSERT(m_refCount == 0);
#if ((CVF_TRACK_ACTIVE_OBJECT_INSTANCES >= 1 && defined(_DEBUG)) || CVF_TRACK_ACTIVE_OBJECT_INSTANCES == 2)
activeObjectInstances()->erase(this);
#endif
}
//--------------------------------------------------------------------------------------------------
/// Increments reference count.
///
/// \return The new reference count.
//--------------------------------------------------------------------------------------------------
inline int Object::addRef() const
{
CVF_TIGHT_ASSERT(this);
return ++m_refCount;
}
//--------------------------------------------------------------------------------------------------
/// Decrements the reference count. Returns the new reference count.
///
/// \return The new reference count.
///
/// If the new reference count is zero, the object (this) is deleted.\n
/// Legal to call on NULL objects, will then return zero.
//--------------------------------------------------------------------------------------------------
inline int Object::release() const
{
// Release on a NULL object ok, just return 0
// This is symmetric with being able to call delete on a NULL pointer
if (!this) return 0;
CVF_TIGHT_ASSERT(m_refCount > 0);
m_refCount--;
if (m_refCount == 0)
{
delete this;
return 0;
}
else
{
return m_refCount;
}
}
//--------------------------------------------------------------------------------------------------
/// Returns the current reference count
//--------------------------------------------------------------------------------------------------
inline int Object::refCount() const
{
CVF_TIGHT_ASSERT(this);
return m_refCount;
}
//==================================================================================================
///
/// \class cvf::ref
/// \ingroup Core
///
/// Smart pointer class used for handling reference counted objects (that derive from Object).
///
/// The ref<T> class encapsulates reference counting by calling Object::addRef() and Object::release()
/// on the internally stored object pointer.
///
/// \internal Inspired by boost's intrusive_ptr class.
//==================================================================================================
//--------------------------------------------------------------------------------------------------
/// Constructor from naked pointer
///
/// Will call addRef() on the passed object.
//--------------------------------------------------------------------------------------------------
template<typename T>
ref<T>::ref(T* object)
{
if (object)
{
object->addRef();
m_object = object;
}
else
{
m_object = NULL;
}
}
//--------------------------------------------------------------------------------------------------
/// Copy constructor
///
/// Copies the internal pointer from the passed ref object and calls addRef() on the object.
//--------------------------------------------------------------------------------------------------
template<typename T>
ref<T>::ref(const ref& other)
{
if (other.m_object)
{
other.m_object->addRef();
m_object = other.m_object;
}
else
{
m_object = NULL;
}
}
//--------------------------------------------------------------------------------------------------
/// Construct from related.
///
/// Copies the internal pointer from the passed ref object and calls addRef() on the object.
//--------------------------------------------------------------------------------------------------
template<typename T>
template<typename T2>
ref<T>::ref(const ref<T2>& other)
{
if (other.notNull())
{
other->addRef();
// Escape const
m_object = const_cast<T2*>(other.p());
}
else
{
m_object = NULL;
}
}
//--------------------------------------------------------------------------------------------------
/// Destructor.
///
/// Will call release() on the internal pointer.
//--------------------------------------------------------------------------------------------------
template<typename T>
ref<T>::~ref()
{
if (m_object)
{
m_object->release();
m_object = NULL;
}
}
//--------------------------------------------------------------------------------------------------
/// Assignment from raw pointer.
//--------------------------------------------------------------------------------------------------
template<typename T>
ref<T>& ref<T>::operator=(T* rhs)
{
// Copy-and-swap (on temporary obj)
ref<T>(rhs).swap(*this);
return *this;
}
//--------------------------------------------------------------------------------------------------
/// Assignment operator
///
/// Copies the internal pointer from \a rhs and calls addRef().
/// If we're already storing an internal pointer, this pointer will be release()'ed.
//--------------------------------------------------------------------------------------------------
template<typename T>
ref<T>& ref<T>::operator=(ref rhs)
{
// Copy-and-swap (copy already done since parameter is passed by value)
rhs.swap(*this);
return *this;
}
//--------------------------------------------------------------------------------------------------
/// Assignment from related.
///
/// Copies the internal pointer from \a rhs and calls addRef().
/// If we're already storing an internal pointer, this pointer will be release()'ed.
//--------------------------------------------------------------------------------------------------
template<typename T>
template<typename T2>
ref<T>& ref<T>::operator=(const ref<T2>& rhs)
{
// Copy-and-swap (on temporary obj)
ref<T>(rhs).swap(*this);
return *this;
}
//--------------------------------------------------------------------------------------------------
/// Returns the naked pointer this object is associated with.
///
/// Added to be able to write the same code for smart pointers as for normal naked pointers.
///
/// \code
/// ref<MyObject> myObject = new MyObject;
/// myObject->doSomething(); // Easier than myObject.p()->doSomething()
/// \endcode
//--------------------------------------------------------------------------------------------------
template<typename T>
inline T* ref<T>::operator->()
{
CVF_TIGHT_ASSERT(m_object);
return m_object;
}
//--------------------------------------------------------------------------------------------------
/// Returns naked const pointer this object is associated with.
//--------------------------------------------------------------------------------------------------
template<typename T>
inline const T* ref<T>::operator->() const
{
CVF_TIGHT_ASSERT(m_object);
return m_object;
}
//--------------------------------------------------------------------------------------------------
/// Dereference operator returning a modifiable reference to the associated object.
///
/// Added to be able to write the same code for smart pointers as for normal naked pointers.
/// \code
/// ref<MyObject> myObject = new MyObject;
/// *myObject.doSomething();
/// \endcode
//--------------------------------------------------------------------------------------------------
template<typename T>
inline T& ref<T>::operator*()
{
CVF_TIGHT_ASSERT(m_object);
return *m_object;
}
//--------------------------------------------------------------------------------------------------
/// Dereference operator returning a const reference to the associated object.
//--------------------------------------------------------------------------------------------------
template<typename T>
inline const T& ref<T>::operator*() const
{
CVF_TIGHT_ASSERT(m_object);
return *m_object;
}
//--------------------------------------------------------------------------------------------------
/// Returns the naked pointer
//--------------------------------------------------------------------------------------------------
template<typename T>
inline T* ref<T>::p()
{
return m_object;
}
//--------------------------------------------------------------------------------------------------
/// Returns naked const pointer
//--------------------------------------------------------------------------------------------------
template<typename T>
inline const T* ref<T>::p() const
{
return m_object;
}
//--------------------------------------------------------------------------------------------------
/// Returns true if the internal pointer is NULL
//--------------------------------------------------------------------------------------------------
template<typename T>
inline bool ref<T>::isNull() const
{
return m_object == NULL;
}
//--------------------------------------------------------------------------------------------------
/// Returns true if the internal pointer is different from NULL
//--------------------------------------------------------------------------------------------------
template<typename T>
inline bool ref<T>::notNull() const
{
return m_object != NULL;
}
//--------------------------------------------------------------------------------------------------
/// Does less than comparison of two ref objects.
///
/// \return Returns true if this object's internal pointer is less than the internal pointer of \a rhs.
///
/// The comparison is done by comparing the internal pointer values ( this.p() < rhs.p() )
/// This operator is used in several STL collections (e.g. std::set) as well as in many STL algorithms
/// (e.g. std::sort() ).
//--------------------------------------------------------------------------------------------------
template<typename T>
bool ref<T>::operator<(const ref& rhs) const
{
CVF_TIGHT_ASSERT((m_object != NULL) && (rhs.p() != NULL));
return std::less<T*>()(m_object, rhs.m_object);
}
//--------------------------------------------------------------------------------------------------
/// Exchanges the contents of the two smart pointers.
///
/// \param other Modifiable reference to the ref object that should have its contents swapped.
///
/// Swap the associated pointer in this and the passed ref object. Will not modify the reference
/// count of any of the associated objects.
///
/// \warning Note that signature differs from normal CeeVizFramework practice. This is done to be
/// consistent with the signature of std::swap()
//--------------------------------------------------------------------------------------------------
template<typename T>
void ref<T>::swap(ref& other)
{
T* tmp = other.m_object;
other.m_object = m_object;
m_object = tmp;
}
//==================================================================================================
///
/// \class cvf::cref
/// \ingroup Core
///
/// Smart pointer class used for handling const reference counted objects
//==================================================================================================
//--------------------------------------------------------------------------------------------------
/// Construct from naked pointer
//--------------------------------------------------------------------------------------------------
template<typename T>
cref<T>::cref(const T* object)
{
if (object)
{
object->addRef();
m_object = object;
}
else
{
m_object = NULL;
}
}
//--------------------------------------------------------------------------------------------------
/// Copy constructor
//--------------------------------------------------------------------------------------------------
template<typename T>
cref<T>::cref(const cref& other)
{
if (other.m_object)
{
other.m_object->addRef();
m_object = other.m_object;
}
else
{
m_object = NULL;
}
}
//--------------------------------------------------------------------------------------------------
/// Construct from related
//--------------------------------------------------------------------------------------------------
template<typename T>
template<typename T2>
cref<T>::cref(const cref<T2>& other)
{
if (other.notNull())
{
other->addRef();
m_object = other.p();
}
else
{
m_object = NULL;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename T>
cref<T>::~cref()
{
if (m_object)
{
m_object->release();
m_object = NULL;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename T>
cref<T>& cref<T>::operator=(const T* rhs)
{
// Copy-and-swap (on temporary obj)
cref<T>(rhs).swap(*this);
return *this;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename T>
cref<T>& cref<T>::operator=(cref rhs)
{
// Copy-and-swap (copy already done since parameter is passed by value)
rhs.swap(*this);
return *this;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename T>
template<typename T2>
cref<T>& cref<T>::operator=(const cref<T2>& rhs)
{
// Copy-and-swap (on temporary obj)
cref<T>(rhs).swap(*this);
return *this;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename T>
inline const T* cref<T>::operator->() const
{
CVF_TIGHT_ASSERT(m_object);
return m_object;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename T>
inline const T& cref<T>::operator*() const
{
CVF_TIGHT_ASSERT(m_object);
return *m_object;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename T>
inline const T* cref<T>::p() const
{
return m_object;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename T>
inline bool cref<T>::isNull() const
{
return m_object == NULL;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename T>
inline bool cref<T>::notNull() const
{
return m_object != NULL;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename T>
bool cref<T>::operator<(const cref& rhs) const
{
CVF_TIGHT_ASSERT((m_object != NULL) && (rhs.p() != NULL));
return std::less<const T*>()(m_object, rhs.m_object);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename T>
void cref<T>::swap(cref& other)
{
const T* tmp = other.m_object;
other.m_object = m_object;
m_object = tmp;
}
} // namespace cvf
+430
View File
@@ -0,0 +1,430 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#include "cvfBase.h"
#include "cvfPlane.h"
#include "cvfMath.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::Plane
/// \ingroup Core
///
/// Class defining a plane in space
///
/// The class describes a plane by the equation: \f$Ax + By + Cz + Dx = 0\f$
/// The plane's normal is defined by the coefficients \f$[A, B, C]\f$
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
/// Default constructor
///
/// The plane will be set to invalid
//--------------------------------------------------------------------------------------------------
Plane::Plane()
{
// Invalidate plane coefficients
// Note: Coefficients set to zero will still comply with the line equation but
// the normal is of zero length which is considered an invalid state in this class.
m_A = m_B = m_C = m_D = 0.0;
}
//--------------------------------------------------------------------------------------------------
/// Constructor with plane equation coefficients
///
/// Define a plane by the plane equation coefficients.
/// Setting at least the A, B and C coefficients to zero will effectually set the plane to invalid.
//--------------------------------------------------------------------------------------------------
Plane::Plane(double A, double B, double C, double D)
{
m_A = A;
m_B = B;
m_C = C;
m_D = D;
}
//--------------------------------------------------------------------------------------------------
/// Copy constructor
//--------------------------------------------------------------------------------------------------
Plane::Plane(const Plane& other)
: Object()
{
*this = other;
}
//--------------------------------------------------------------------------------------------------
/// Destructor
//--------------------------------------------------------------------------------------------------
Plane::~Plane()
{
}
//--------------------------------------------------------------------------------------------------
/// Assignment operator
//--------------------------------------------------------------------------------------------------
const Plane& Plane::operator=(const Plane& rhs)
{
m_A = rhs.m_A;
m_B = rhs.m_B;
m_C = rhs.m_C;
m_D = rhs.m_D;
return *this;
}
//--------------------------------------------------------------------------------------------------
/// Equality operator
///
/// Check if the two planes are identically defined. Note, equal planes may be defined differently
/// and are as such considered not to be identical to each other. (Different plane coefficients)
//--------------------------------------------------------------------------------------------------
bool Plane::operator==(const Plane& rhs) const
{
if (m_A != rhs.m_A) return false;
if (m_B != rhs.m_B) return false;
if (m_C != rhs.m_C) return false;
if (m_D != rhs.m_D) return false;
return true;
}
//--------------------------------------------------------------------------------------------------
/// Inequality operator
///
/// Check if the two planes are not identically defined. Note, equal planes may be defined differently
/// and are as such considered not to be identical to each other. (Different plane coefficients)
//--------------------------------------------------------------------------------------------------
bool Plane::operator!=(const Plane& rhs) const
{
return !operator==(rhs);
}
//--------------------------------------------------------------------------------------------------
/// Is the plane definition valid or not
///
/// The plane is considered invalid if the normal is of zero length
//--------------------------------------------------------------------------------------------------
bool Plane::isValid() const
{
return !((m_A == 0.0) && (m_B == 0.0) && (m_C == 0.0));
}
//--------------------------------------------------------------------------------------------------
/// Define a plane by the plane equation coefficients
///
/// \param A Plane coefficient A
/// \param B Plane coefficient B
/// \param C Plane coefficient C
/// \param D Plane coefficient D
///
/// The coefficients defines a plane by the equation: \f$Ax + By + Cz + D = 0\f$
/// The plane coefficients \f$[A, B, C]\f$ defines the normal to the plane
//--------------------------------------------------------------------------------------------------
void Plane::set(double A, double B, double C, double D)
{
CVF_ASSERT(!(A == 0.0 && B == 0.0 && C == 0.0));
m_A = A;
m_B = B;
m_C = C;
m_D = D;
}
//--------------------------------------------------------------------------------------------------
/// Compute the plane equation from the given point and normal
///
/// \param point Point on the plane
/// \param normal The plane's normal
//--------------------------------------------------------------------------------------------------
bool Plane::setFromPointAndNormal(const Vec3d& point, const Vec3d& normal)
{
if (normal.isZero()) return false;
m_A = normal.x();
m_B = normal.y();
m_C = normal.z();
m_D = -(normal*point);
return true;
}
//--------------------------------------------------------------------------------------------------
/// Compute the plane equation from the given three points
///
/// \param p1 First point on the plane
/// \param p2 Second point on the plane
/// \param p3 Third point on the plane
///
/// \return true if successfully set. false if points are on the same line.
///
/// The three points must be different from each other and cannot be on the same line in space
//--------------------------------------------------------------------------------------------------
bool Plane::setFromPoints(const Vec3d& p1, const Vec3d& p2, const Vec3d& p3)
{
Vec3d v1 = p2 - p1;
Vec3d v2 = p3 - p1;
Vec3d normal = v1 ^ v2;
if (normal.isZero()) return false;
setFromPointAndNormal(p1, normal);
return true;
}
//--------------------------------------------------------------------------------------------------
/// Get the normal of the plane
///
/// The normal may not be normalized
//--------------------------------------------------------------------------------------------------
Vec3d Plane::normal() const
{
Vec3d normal = Vec3d(m_A, m_B, m_C);
CVF_ASSERT(!normal.isZero());
return normal;
}
//--------------------------------------------------------------------------------------------------
/// Get a point located on the plane
//--------------------------------------------------------------------------------------------------
Vec3d Plane::pointInPlane() const
{
double distToOrigin = distanceToOrigin();
Vec3d point(m_A, m_B, m_C);
point *= distToOrigin;
return point;
}
//--------------------------------------------------------------------------------------------------
/// Flip the plane
//--------------------------------------------------------------------------------------------------
void Plane::flip()
{
m_A *= -1.0;
m_B *= -1.0;
m_C *= -1.0;
m_D *= -1.0;
}
//--------------------------------------------------------------------------------------------------
/// Transforms the plane with the given homogeneous transformation \a matrix
//--------------------------------------------------------------------------------------------------
void Plane::transform(const Mat4d& matrix)
{
Vec3d n = normal();
Vec3d point = pointInPlane();
n.transformVector(matrix);
point.transformPoint(matrix);
setFromPointAndNormal(point, n);
}
//--------------------------------------------------------------------------------------------------
/// Get the distance from the point to the plane
//--------------------------------------------------------------------------------------------------
double Plane::distance(const Vec3d& point) const
{
double factor = Math::sqrt(m_A*m_A + m_B*m_B + m_C*m_C);
CVF_ASSERT(factor > 0.0);
double dist = distanceSquared(point) / factor;
return dist;
}
//--------------------------------------------------------------------------------------------------
/// Get the square of the distance from the point to the plane
///
/// The square of the distance is relatively fast to compute (no \a sqrt) and is useful for determine
/// which side the point is on. To obtain the actual distance, divide by \f$\sqrt{(A^2 + B^2 + C^2)}\f$
/// or use the distance() function directly.
//--------------------------------------------------------------------------------------------------
double Plane::distanceSquared(const Vec3d& point) const
{
return m_A*point.x() + m_B*point.y() + m_C*point.z() + m_D;
}
//--------------------------------------------------------------------------------------------------
/// Get the distance from the plane to the origin
//--------------------------------------------------------------------------------------------------
double Plane::distanceToOrigin() const
{
double factor = m_A*m_A + m_B*m_B + m_C*m_C;
CVF_ASSERT(factor > 0.0);
return -m_D/factor;
}
//--------------------------------------------------------------------------------------------------
/// Project the given vector onto the plane
///
/// \param vector Vector to be projected
/// \param projectedVector Projected vector to be returned by pointer
///
/// \return true if successfully projected.
/// false if the given \a vector is parallel with the plane's normal
//--------------------------------------------------------------------------------------------------
bool Plane::projectVector(const Vec3d& vector, Vec3d* projectedVector) const
{
CVF_ASSERT(projectedVector);
Vec3d n = normal();
Vec3d tmp = n ^ vector;
Vec3d k = tmp ^ n;
double length = k.length();
if (length <= 0.0) return false;
k *= 1.0/length;
length = vector*k;
*projectedVector = k;
*projectedVector *= length;
return true;
}
//--------------------------------------------------------------------------------------------------
/// Project the given point onto the plane
//--------------------------------------------------------------------------------------------------
Vec3d Plane::projectPoint(const Vec3d& point) const
{
Vec3d pip = pointInPlane();
// Create vector from point in plane to node
Vec3d vector = point - pip;
// Project vector to find node in plane
Vec3d projectedPoint;
if (projectVector(vector, &projectedPoint))
{
projectedPoint += pip;
}
else
{
// The <point - pip> vector is parallel with the normal vector, use the point in plane as the projected
projectedPoint = pip;
}
return projectedPoint;
}
//--------------------------------------------------------------------------------------------------
/// Find intersection line between two planes
///
/// \param other The other plane to find intersection line with
/// \param point Point on line
/// \param direction Normalized direction of line
///
/// \return true if success. false if direction is zero -> no point of intersection exists
//--------------------------------------------------------------------------------------------------
bool Plane::intersect(const Plane& other, Vec3d* point, Vec3d* direction) const
{
// Note: Ripped from Graphics Gems III page 233.
CVF_ASSERT(point);
double invdet = UNDEFINED_DOUBLE;
Vec3d normal1 = this->normal();
Vec3d normal2 = other.normal();
Vec3d vector = normal1 ^ normal2;
Vec3d dir2(vector.x()*vector.x(), vector.y()*vector.y(), vector.z()*vector.z());
// Todo: VTFIsGreater(...) and VTFeqZero(..) replacement
if ((dir2.z() > dir2.y()) && (dir2.z() > dir2.x()) && (dir2.z() != 0.0))
{
// then get a point on the XY plane
invdet = 1.0 / vector.z();
// solve < pl1.x() * xpt.x() + pl1.y() * xpt.y() = - pl1.w > < pl2.x() * xpt.x() + pl2.y() * xpt.y() = - pl2.w >
point->x() = m_B*other.m_D - other.m_B*m_D;
point->y() = other.m_A*m_D - m_A*other.m_D;
point->z() = 0.0;
}
// Todo: VTFIsGreater(...) and VTFeqZero(..) replacement
else if ((dir2.y() > dir2.x()) && (dir2.y() != 0.0))
{
// then get a point on the XZ plane
invdet = 1.0f / vector.y();
// solve < pl1.x() * xpt.x() + pl1.z() * xpt.z() = -pl1.w > < pl2.x() * xpt.x() + pl2.z() * xpt.z() = -pl2.w >
point->x() = other.m_C*m_D - m_C*other.m_D;
point->y() = 0.0;
point->z() = m_A*other.m_D - other.m_A*m_D;
}
// Todo: VTFeqZero(..) replacement
else if (dir2.x() != 0.0)
{
// then get a point on the YZ plane
invdet = 1.0 / vector.x();
// solve < pl1.y() * xpt.y() + pl1.z() * xpt.z() = - pl1.w > < pl2.y() * xpt.y() + pl2.z() * xpt.z() = - pl2.w >
point->x() = 0.0;
point->y() = m_C*other.m_D - other.m_C*m_D;
point->z() = other.m_B*m_D - m_B*other.m_D;
}
else
{
// direction is zero, then no point of intersection exists
return false;
}
*point *= invdet;
if (direction)
{
*direction = vector;
direction->normalize();
}
return true;
}
} // namespace cvf
+79
View File
@@ -0,0 +1,79 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include "cvfObject.h"
#include "cvfVector3.h"
#include "cvfMatrix4.h"
namespace cvf {
//=================================================================================================
//
// Plane class
//
//=================================================================================================
class Plane : public Object
{
public:
Plane();
Plane(double A, double B, double C, double D);
Plane(const Plane& other);
~Plane();
const Plane& operator=(const Plane& other);
bool operator==(const Plane& other) const;
bool operator!=(const Plane& other) const;
inline double A() const { return m_A; } ///< Get plane coefficient A
inline double B() const { return m_B; } ///< Get plane coefficient B
inline double C() const { return m_C; } ///< Get plane coefficient C
inline double D() const { return m_D; } ///< Get plane coefficient D
bool isValid() const;
void set(double A, double B, double C, double D);
bool setFromPointAndNormal(const Vec3d& point, const Vec3d& normal);
bool setFromPoints(const Vec3d& p1, const Vec3d& p2, const Vec3d& p3);
Vec3d normal() const;
Vec3d pointInPlane() const;
void flip();
void transform(const Mat4d& matrix);
double distance(const Vec3d& point) const;
double distanceSquared(const Vec3d& point) const;
double distanceToOrigin() const;
bool projectVector(const Vec3d& vector, Vec3d* projectedVector) const;
Vec3d projectPoint(const Vec3d& point) const;
bool intersect(const Plane& other, Vec3d* point, Vec3d* direction = NULL) const;
private:
double m_A; // Plane equation coefficients
double m_B; //
double m_C; //
double m_D; //
};
}
+82
View File
@@ -0,0 +1,82 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include "cvfVector3.h"
namespace cvf {
//==================================================================================================
//
// This class implements a quaternion
//
//==================================================================================================
template<typename S>
class Quat
{
public:
Quat();
Quat(S x, S y, S z, S w);
Quat(const Quat& other);
template<typename T>
explicit Quat(const T& other);
Quat& operator=(const Quat& rhs);
bool operator==(const Quat& rhs) const;
bool operator!=(const Quat& rhs) const;
const S& x() const { return m_x; } ///< Get the X element of the quaternion
const S& y() const { return m_y; } ///< Get the Y element of the quaternion
const S& z() const { return m_z; } ///< Get the Z element of the quaternion
const S& w() const { return m_w; } ///< Get the W element of the quaternion
S& x() { return m_x; } ///< Get a reference to the X element of the quaternion. E.g. x() = 2;
S& y() { return m_y; } ///< Get a reference to the Y element of the quaternion. E.g. y() = 2;
S& z() { return m_z; } ///< Get a reference to the Z element of the quaternion. E.g. z() = 2;
S& w() { return m_w; } ///< Get a reference to the W element of the quaternion. E.g. w() = 2;
void set(S x, S y, S z, S w);
bool normalize();
// The setFromAxisAngle() function is left as a placeholder to illustrate naming of functions
void setFromAxisAngle(Vector3<S> rotationAxis, S angle);
void toAxisAngle(Vector3<S>* rotationAxis, S* angle) const;
Matrix3<S> toMatrix3() const;
Matrix4<S> toMatrix4() const;
static Quat fromAxisAngle(Vector3<S> rotationAxis, S angle);
static Quat fromRotationMatrix(const Matrix4<S>& rotMat);
private:
S m_x;
S m_y;
S m_z;
S m_w;
};
typedef Quat<float> Quatf;
typedef Quat<double> Quatd;
}
#include "cvfQuat.inl"
+376
View File
@@ -0,0 +1,376 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
namespace cvf {
//==================================================================================================
///
/// \class cvf::Quat
/// \ingroup Core
///
/// Templated quaternion
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
/// Default constructor, initializes all elements to 0
//--------------------------------------------------------------------------------------------------
template<typename S>
Quat<S>::Quat()
: m_x(0),
m_y(0),
m_z(0),
m_w(0)
{
}
//--------------------------------------------------------------------------------------------------
/// Constructor with initialization
//--------------------------------------------------------------------------------------------------
template<typename S>
Quat<S>::Quat(S x, S y, S z, S w)
: m_x(x),
m_y(y),
m_z(z),
m_w(w)
{
}
//--------------------------------------------------------------------------------------------------
/// Copy constructor
//--------------------------------------------------------------------------------------------------
template<typename S>
Quat<S>::Quat(const Quat& other)
: m_x(other.m_x),
m_y(other.m_y),
m_z(other.m_z),
m_w(other.m_w)
{
}
//--------------------------------------------------------------------------------------------------
/// Conversion constructor for explicit conversion
//--------------------------------------------------------------------------------------------------
template<typename S>
template<typename T>
Quat<S>::Quat(const T& other)
{
m_x = static_cast<S>(other.x());
m_y = static_cast<S>(other.y());
m_z = static_cast<S>(other.z());
m_w = static_cast<S>(other.w());
}
//--------------------------------------------------------------------------------------------------
/// Assignment operator
//--------------------------------------------------------------------------------------------------
template<typename S>
Quat<S>& Quat<S>::operator=(const Quat& rhs)
{
m_x = rhs.m_x;
m_y = rhs.m_y;
m_z = rhs.m_z;
m_w = rhs.m_w;
return *this;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename S>
bool Quat<S>::operator==(const Quat& rhs) const
{
if (m_x != rhs.m_x) return false;
if (m_y != rhs.m_y) return false;
if (m_z != rhs.m_z) return false;
if (m_w != rhs.m_w) return false;
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename S>
bool Quat<S>::operator!=(const Quat& rhs) const
{
if (m_x != rhs.m_x) return true;
if (m_y != rhs.m_y) return true;
if (m_z != rhs.m_z) return true;
if (m_w != rhs.m_w) return true;
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename S>
void Quat<S>::set(S x, S y, S z, S w)
{
m_x = x;
m_y = y;
m_z = z;
m_w = w;
}
//--------------------------------------------------------------------------------------------------
/// Normalize the quaternion
//--------------------------------------------------------------------------------------------------
template<typename S>
bool Quat<S>::normalize()
{
// Quaternions always obey: a^2 + b^2 + c^2 + d^2 = 1.0.
// If they don't add up to 1.0, dividing by their magnitude will re-normalize them.
S len = Math::sqrt(m_x*m_x + m_y*m_y + m_z*m_z + m_w*m_w);
if (len > 0)
{
// Pre-compute 1/length and do multiplication instead of division
S oneOverLen = static_cast<S>(1.0/len);
m_x *= oneOverLen;
m_y *= oneOverLen;
m_z *= oneOverLen;
m_w *= oneOverLen;
return true;
}
else
{
// Might be NaN, so set it to zero
m_x = 0;
m_y = 0;
m_z = 0;
m_w = 0;
return false;
}
}
//--------------------------------------------------------------------------------------------------
/// Sets the quaternion from a rotation axis and an angle (in radians)
//--------------------------------------------------------------------------------------------------
template<typename S>
void Quat<S>::setFromAxisAngle(Vector3<S> rotationAxis, S angle)
{
*this = Quat::fromAxisAngle(rotationAxis, angle);
}
//--------------------------------------------------------------------------------------------------
/// Extracts the rotation in this quaternion as an axis and an angle (in radians)
//--------------------------------------------------------------------------------------------------
template<typename S>
void Quat<S>::toAxisAngle(Vector3<S>* rotationAxis, S* angle) const
{
// From matrix an quaternion FAQ
CVF_ASSERT(rotationAxis);
CVF_ASSERT(angle);
// Need a normalized quaternion
Quat nQ(*this);
nQ.normalize();
S cos_a = nQ.m_w;
*angle = 2*Math::acos(cos_a);
S sin_a = Math::sqrt(1 - cos_a*cos_a);
if (Math::abs(sin_a) < 0.0005) sin_a = 1;
rotationAxis->x() = nQ.m_x/sin_a;
rotationAxis->y() = nQ.m_y/sin_a;
rotationAxis->z() = nQ.m_z/sin_a;
}
//--------------------------------------------------------------------------------------------------
/// Constructs a rotation matrix from this quaternion
//--------------------------------------------------------------------------------------------------
template<typename S>
Matrix3<S> Quat<S>::toMatrix3() const
{
// Based on Quaternions paper by Ken Shoemake
// The current version works even if quaternion isn't normalized
// If we assume that the quaternion is normalized, this function can be made simpler/quicker
S Nq = m_x*m_x + m_y*m_y + m_z*m_z + m_w*m_w;
S s = (Nq > 0) ? (2/Nq) : 0;
S xs = m_x*s;
S ys = m_y*s;
S zs = m_z*s;
S wx = m_w*xs;
S wy = m_w*ys;
S wz = m_w*zs;
S xx = m_x*xs;
S xy = m_x*ys;
S xz = m_x*zs;
S yy = m_y*ys;
S yz = m_y*zs;
S zz = m_z*zs;
// Default constructor initializes to identity
Matrix3<S> m;
m.setRowCol( 0, 0, 1 - (yy + zz));
m.setRowCol( 0, 1, xy - wz );
m.setRowCol( 0, 2, xz + wy );
m.setRowCol( 1, 0, xy + wz );
m.setRowCol( 1, 1, 1 - (xx + zz));
m.setRowCol( 1, 2, yz - wx );
m.setRowCol( 2, 0, xz - wy );
m.setRowCol( 2, 1, yz + wx );
m.setRowCol( 2, 2, 1 - (xx + yy));
return m;
}
//--------------------------------------------------------------------------------------------------
/// Constructs a rotation matrix from this quaternion
//--------------------------------------------------------------------------------------------------
template<typename S>
Matrix4<S> Quat<S>::toMatrix4() const
{
// Create via the Matrix3 version
return Matrix4<S>(toMatrix3());
}
//--------------------------------------------------------------------------------------------------
/// Creates a quaternion from specified rotation axis and angle (in radians)
//--------------------------------------------------------------------------------------------------
template<typename S>
Quat<S> Quat<S>::fromAxisAngle(Vector3<S> rotationAxis, S angle)
{
// From matrix an quaternion FAQ
rotationAxis.normalize();
S halfAngle = static_cast<S>(angle/2.0);
S sinHalfAngle = Math::sin(halfAngle);
Quat q;
q.m_x = rotationAxis.x()*sinHalfAngle;;
q.m_y = rotationAxis.y()*sinHalfAngle;
q.m_z = rotationAxis.z()*sinHalfAngle;
q.m_w = Math::cos(halfAngle);
return q;
}
//--------------------------------------------------------------------------------------------------
/// Creates a quaternion from the passed rotation matrix
//--------------------------------------------------------------------------------------------------
template<typename S>
Quat<S> Quat<S>::fromRotationMatrix(const Matrix4<S>& rotMat)
{
const S m00 = rotMat.rowCol(0, 0);
const S m01 = rotMat.rowCol(0, 1);
const S m02 = rotMat.rowCol(0, 2);
const S m10 = rotMat.rowCol(1, 0);
const S m11 = rotMat.rowCol(1, 1);
const S m12 = rotMat.rowCol(1, 2);
const S m20 = rotMat.rowCol(2, 0);
const S m21 = rotMat.rowCol(2, 1);
const S m22 = rotMat.rowCol(2, 2);
// If the trace of the matrix is greater than zero, then perform an "instant" calculation.
S trace = m00 + m11 + m22;
Quat q(0, 0, 0, 1);
// Try and test against a very small value instead of 0 here
// The FAQ suggests testing against ( T > 0.00000001 ) to avoid large distortions
if (trace > 0.00000001)
{
S s = Math::sqrt(trace + 1)*2;
q.m_x = (m21 - m12)/s;
q.m_y = (m02 - m20)/s;
q.m_z = (m10 - m01)/s;
q.m_w = static_cast<S>(0.25*s);
}
else
{
// If the trace of the matrix is equal to zero then identify
// which major diagonal element has the greatest value.
int iDominantColumn = 0;
if (m11 > m00) iDominantColumn = 1;
if (m22 > m11) iDominantColumn = 2;
if (iDominantColumn == 0)
{
S s = Math::sqrt(1 + m00 - m11 - m22)*2;
if (s > 0)
{
q.m_x = static_cast<S>(0.25*s);
q.m_y = (m10 + m01)/s;
q.m_z = (m20 + m02)/s;
q.m_w = (m21 - m12)/s;
}
}
else if (iDominantColumn == 1)
{
S s = Math::sqrt(1 + m11 - m00 - m22)*2;
if (s > 0)
{
q.m_x = (m10 + m01)/s;
q.m_y = static_cast<S>(0.25*s);
q.m_z = (m21 + m12)/s;
q.m_w = (m02 - m20)/s;
}
}
else
{
S s = Math::sqrt(1 + m22 - m00 - m11)*2;
if (s > 0)
{
q.m_x = (m20 + m02)/s;
q.m_y = (m21 + m12)/s;
q.m_z = static_cast<S>(0.25*s);
q.m_w = (m10 - m01)/s;
}
}
}
return q;
}
} // namespace cvf
+84
View File
@@ -0,0 +1,84 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include "cvfVector2.h"
namespace cvf {
//==================================================================================================
//
//
//
//==================================================================================================
template <typename T>
class Rect
{
public:
Rect();
Rect(T minX, T minY, T width, T height);
Rect(const Vector2<T>& min, T width, T height);
Rect(const Rect& rect);
Rect& operator=(const Rect& rhs);
Vector2<T> min() const;
Vector2<T> max() const;
T width() const;
T height() const;
Vector2<T> center() const;
void setMin(const Vector2<T>& min);
void setWidth(T width);
void setHeight(T height);
bool isValid() const;
void include(const Vector2<T>& coord);
void include(const Rect& rect);
bool contains(const Vector2<T>& coord) const;
bool intersects(const Rect& rect) const;
void normalize();
void translate(const Vector2<T>& offset);
bool segmentIntersect(const Vec2d& p1, const Vec2d& p2, Vec2d* intersect1, Vec2d* intersect2);
static Rect fromMinMax(const Vector2<T>& min, const Vector2<T>& max);
private:
static bool clipTest(double p, double q, double *u1, double *u2);
private:
Vector2<T> m_minPos; ///< Position of left lower corner
T m_width; ///< Width
T m_height; ///< Height
};
typedef Rect<float> Rectf; ///< A rect with float components
typedef Rect<double> Rectd; ///< A rect with double components
typedef Rect<int> Recti; ///< A rect with integer components
typedef Rect<uint> Rectui; ///< A rect with unsigned integer components
}
#include "cvfRect.inl"
+575
View File
@@ -0,0 +1,575 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
namespace cvf {
//==================================================================================================
///
/// \class cvf::Rect
/// \ingroup Core
///
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template <typename T>
Rect<T>::Rect()
{
m_minPos.setZero();
m_width = 0;
m_height = 0;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template <typename T>
Rect<T>::Rect(T minX, T minY, T width, T height)
{
m_minPos.set(minX, minY);
m_width = width;
m_height = height;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template <typename T>
Rect<T>::Rect(const Vector2<T>& min, T width, T height)
{
m_minPos = min;
m_width = width;
m_height = height;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template <typename T>
Rect<T>::Rect(const Rect& rect)
{
m_minPos = rect.min();
m_width = rect.width();
m_height = rect.height();
}
//--------------------------------------------------------------------------------------------------
/// Assignment operator
//--------------------------------------------------------------------------------------------------
template<typename T>
Rect<T>& Rect<T>::operator=(const Rect& rhs)
{
m_minPos = rhs.min();
m_width = rhs.max().x() - rhs.min().x();
m_height = rhs.max().y() - rhs.min().y();
return *this;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template <typename T>
Vector2<T> Rect<T>::min() const
{
return m_minPos;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template <typename T>
Vector2<T> Rect<T>::max() const
{
Vector2<T> max(m_minPos);
max.x() += m_width;
max.y() += m_height;
return max;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template <typename T>
T Rect<T>::width() const
{
return m_width;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template <typename T>
T Rect<T>::height() const
{
return m_height;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template <typename T>
Vector2<T> Rect<T>::center() const
{
Vector2<T> center(m_minPos);
center.x() += m_width / 2.0;
center.y() += m_height / 2.0;
return center;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template <typename T>
void Rect<T>::setMin(const Vector2<T>& min)
{
m_minPos = min;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template <typename T>
void Rect<T>::setWidth(T width)
{
m_width = width;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template <typename T>
void Rect<T>::setHeight(T height)
{
m_height = height;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template <typename T>
bool Rect<T>::isValid() const
{
return m_width > 0.0 && m_height > 0.0;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template <typename T>
void Rect<T>::include(const Vector2<T>& coord)
{
if (!isValid())
{
Vector2<T> diff = coord - m_minPos;
m_width = diff.x();
m_height = diff.y();
return;
}
if (coord.x() < m_minPos.x())
{
T deltaX = m_minPos.x() - coord.x();
m_minPos.x() -= deltaX;
m_width += deltaX;
}
else if (coord.x() > m_minPos.x() + m_width)
{
T deltaX = coord.x() - (m_minPos.x() + m_width);
m_width += deltaX;
}
if (coord.y() < m_minPos.y())
{
T deltaY = m_minPos.y() - coord.y();
m_minPos.y() -= deltaY;
m_height += deltaY;
}
else if (coord.y() > m_minPos.y() + m_height)
{
T deltaY = coord.y() - (m_minPos.y() + m_height);
m_height += deltaY;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template <typename T>
void Rect<T>::include(const Rect& rect)
{
if (!rect.isValid()) return;
T left = m_minPos.x();
T right = m_minPos.x();
if (m_width < 0)
left += m_width;
else
right += m_width;
if (rect.width() < 0)
{
left = CVF_MIN(left, rect.min().x() + rect.width());
right = CVF_MAX(right, rect.min().x());
}
else
{
left = CVF_MIN(left, rect.min().x());
right = CVF_MAX(right, rect.min().x() + rect.width());
}
T bottom = m_minPos.y();
T top = m_minPos.y();
if (m_height < 0)
{
bottom += m_height;
}
else
{
top += m_height;
}
if (rect.height() < 0)
{
bottom = CVF_MIN(bottom, rect.min().y() + rect.height());
top = CVF_MAX(top, rect.min().y());
}
else
{
bottom = CVF_MIN(bottom, rect.min().y());
top = CVF_MAX(top, rect.min().y() + rect.height());
}
m_minPos.set(left, bottom);
m_width = right - left;
m_height = top - bottom;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template <typename T>
bool Rect<T>::contains(const Vector2<T>& coord) const
{
T left = m_minPos.x();
T right = m_minPos.x();
if (m_width < 0)
{
left += m_width;
}
else
{
right += m_width;
}
if (left == right)
{
// null rect
return false;
}
if (coord.x() < left || coord.x() > right)
{
return false;
}
T bot = m_minPos.y();
T top = m_minPos.y();
if (m_height < 0)
{
bot += m_height;
}
else
{
top += m_height;
}
if (bot == top)
{
// null rect
return false;
}
if (coord.y() < bot || coord.y() > top)
{
return false;
}
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template <typename T>
bool Rect<T>::intersects(const Rect& rect) const
{
T left1 = m_minPos.x();
T right1 = m_minPos.x();
if (m_width < 0)
{
left1 += m_width;
}
else
{
right1 += m_width;
}
if (left1 == right1)
{
// null rect
return false;
}
T left2 = rect.min().x();
T right2 = rect.min().x();
if (rect.width() < 0)
{
left2 += rect.width();
}
else
{
right2 += rect.width();
}
if (left2 == right2)
{
// null rect
return false;
}
if (left1 >= right2 || left2 >= right1)
{
return false;
}
T bot1 = m_minPos.y();
T top1 = m_minPos.y();
if (m_height < 0)
{
bot1 += m_height;
}
else
{
top1 += m_height;
}
if (bot1 == top1)
{
// null rect
return false;
}
T bot2 = rect.min().y();
T top2 = rect.min().y();
if (rect.height() < 0)
{
bot2 += rect.height();
}
else
{
top2 += rect.height();
}
if (bot2 == top2)
{
// null rect
return false;
}
if (bot1 >= top2 || bot2 >= top1)
{
return false;
}
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template <typename T>
void Rect<T>::normalize()
{
if (m_width < 0)
{
m_width = -m_width;
m_minPos.x() -= m_width;
}
if (m_height < 0)
{
m_height = -m_height;
m_minPos.y() -= m_height;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template <typename T>
void Rect<T>::translate(const Vector2<T>& offset)
{
m_minPos += offset;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template <typename T>
Rect<T> Rect<T>::fromMinMax(const Vector2<T>& min, const Vector2<T>& max)
{
Rect<T> rect(min, max.x() - min.x(), max.y() - min.y());
return rect;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template <typename T>
bool Rect<T>::segmentIntersect(const Vec2d& p1, const Vec2d& p2, Vec2d* intersect1, Vec2d* intersect2)
{
// Uses Liang-Barsky line clipping algorithm
// See http://stackoverflow.com/questions/99353/how-to-test-if-a-line-segment-intersects-an-axis-aligned-rectange-in-2d
CVF_ASSERT(intersect1);
CVF_ASSERT(intersect2);
if (!isValid()) return false;
double u1 = 0.0;
double u2 = 1.0;
double dx = p2.x() - p1.x();
double dy;
Vec2d maxPos = max();
if (clipTest(-dx, p1.x() - m_minPos.x(), &u1, &u2))
{
if (clipTest(dx, maxPos.x() - p1.x(), &u1, &u2))
{
dy = p2.y() - p1.y();
if (clipTest (-dy, p1.y() - m_minPos.y(), &u1, &u2))
{
if (clipTest (dy, maxPos.y() - p1.y(), &u1, &u2))
{
*intersect1 = p1;
*intersect2 = p2;
if (u2 < 1.0)
{
intersect2->x() = p1.x() + u2 * dx;
intersect2->y() = p1.y() + u2 * dy;
}
if (u1 > 0.0)
{
intersect1->x() += u1 * dx;
intersect1->y() += u1 * dy;
}
return true;
}
}
}
}
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template <typename T>
bool Rect<T>::clipTest(double p, double q, double *u1, double *u2)
{
// Uses Liang-Barsky line clipping algorithm
// See also http://stackoverflow.com/questions/99353/how-to-test-if-a-line-segment-intersects-an-axis-aligned-rectange-in-2d
CVF_ASSERT(u1);
CVF_ASSERT(u2);
bool retval = true;
if (p < 0.0)
{
double r = q / p;
if (r > *u2)
{
retval = false;
}
else if (r > *u1)
{
*u1 = r;
}
}
else if (p > 0.0)
{
double r = q / p;
if (r < *u1)
{
retval = false;
}
else if (r < *u2)
{
*u2 = r;
}
}
else
{
// p = 0, so line is parallel to this clipping edge
if(q < 0.0)
{
// Line is outside clipping edge
retval = false;
}
}
return retval;
}
} // namespace cvf
File diff suppressed because it is too large. Load diff
+118
View File
@@ -0,0 +1,118 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include "cvfCharArray.h"
#include <string>
namespace cvf {
//==================================================================================================
//
// A general unicode based string class
//
//==================================================================================================
class String
{
public:
String();
String(const std::string& str);
String(const std::wstring& str);
String(const String& str);
String(const char* str);
String(const wchar_t* str);
explicit String(char c);
explicit String(int number);
explicit String(int64 number);
explicit String(uint number);
explicit String(float number);
explicit String(double number);
String& operator=(String rhs);
bool operator==(const String& rhs) const;
bool operator==(const wchar_t* rhs) const;
bool operator<(const String& rhs) const;
bool operator!=(const String& rhs) const;
const String operator+(const String& rhs) const;
String& operator+=(const String& rhs);
const wchar_t& operator[](size_t pos) const;
wchar_t& operator[](size_t pos);
String toLower() const;
String toUpper() const;
String trimmedRight() const;
String trimmedLeft() const;
String trimmed() const;
String simplified() const;
std::vector<String> split(const String& delimiters = " ") const;
size_t find(const String& str, size_t start = 0) const;
String subString(size_t start, size_t length = npos) const;
void replace(const String& before, const String& after);
CharArray toAscii() const; // Useful when you need a const char* pointer.
std::string toStdString() const;
std::wstring toStdWString() const;
CharArray toUtf8() const;
static String fromUtf8(const char* str);
bool isEmpty() const;
size_t size() const;
void resize(size_t size);
const wchar_t* ptr() const;
wchar_t* ptr();
static String number(float n, char format = 'g', int precision = -1);
static String number(double n, char format = 'g', int precision = -1);
double toDouble(bool* ok = NULL) const;
double toDouble(double defaultValue) const;
float toFloat(bool* ok = NULL) const;
float toFloat(float defaultValue) const;
int toInt(bool* ok = NULL) const;
int toInt(int defaultValue) const;
String arg(const String& a, int fieldWidth = 0, const wchar_t& fillChar = ' ') const;
String arg(char a, int fieldWidth = 0, const wchar_t& fillChar = ' ') const;
String arg(int a, int fieldWidth = 0, const wchar_t& fillChar = ' ') const;
String arg(int64 a, int fieldWidth = 0, const wchar_t& fillChar = ' ') const;
String arg(uint a, int fieldWidth = 0, const wchar_t& fillChar = ' ') const;
String arg(float a, int fieldWidth = 0, char format = 'g', int precision = -1, const wchar_t& fillChar = ' ') const;
String arg(double a, int fieldWidth = 0, char format = 'g', int precision = -1, const wchar_t& fillChar = ' ') const;
void swap(String& other);
static const size_t npos; // Same as std::string::npos. This value, when used as the value for a count parameter n in string's member functions, roughly indicates "as many as possible".
// As a return value it is usually used to indicate failure.
private:
std::wstring m_string;
};
String operator+(const char* str1, const String& str2);
}
+313
View File
@@ -0,0 +1,313 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#include "cvfBase.h"
#include "cvfSystem.h"
#include "cvfString.h"
#include <memory>
#include <cstring>
#include <cstdio>
#include <cstdarg>
namespace cvf {
//==================================================================================================
///
/// \class cvf::System
/// \ingroup Core
///
/// Static wrapper class for system functions
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
/// Check if we're running 64bit
//--------------------------------------------------------------------------------------------------
bool System::is64Bit()
{
return (sizeof(void*) == 8) ? true : false;
}
//--------------------------------------------------------------------------------------------------
/// Check if we are running on a big endian system.
///
/// \return Returns true if we're on big endian, false for little endian.
//--------------------------------------------------------------------------------------------------
bool System::isBigEndian()
{
int iInt = 1;
char* pcChar = reinterpret_cast<char*>(&iInt);
return !(*pcChar);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool System::memcpy(void* dst, size_t dstSizeInBytes, const void* src, size_t numBytesToCopy)
{
#if WIN32
// Debug version asserts
errno_t err = memcpy_s(dst, dstSizeInBytes, src, numBytesToCopy);
if (err == 0)
{
return true;
}
else
{
return false;
}
#else
if (!dst || dstSizeInBytes == 0 || !src)
{
// Be consistent with the behavior of memcpy_s.
return false;
}
if (numBytesToCopy > dstSizeInBytes)
{
// The source memory is too large to copy to the destination.
// To be consistent with memcpy_s, return false to indicate failure
return false;
}
::memcpy(dst, src, numBytesToCopy);
return true;
#endif
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool System::strcpy(char* strDestination, size_t maxNumElementsInDestination, const char* strSource)
{
#ifdef WIN32
// Debug version asserts
// Note that on windows the debug versions functions first fills the buffer with 0xFD
errno_t err = strcpy_s(strDestination, maxNumElementsInDestination, strSource);
if (err == 0)
{
return true;
}
else
{
return false;
}
#else
CVF_UNUSED(maxNumElementsInDestination);
::strcpy(strDestination, strSource);
return true;
#endif
}
//--------------------------------------------------------------------------------------------------
/// Append a string
///
/// \param strDestination Null-terminated destination string buffer
/// \param maxNumElementsInDestination Total size of the destination string buffer in characters
/// \param strSource Null-terminated source string buffer
//--------------------------------------------------------------------------------------------------
bool System::strcat(char* strDestination, size_t maxNumElementsInDestination, const char* strSource)
{
#ifdef WIN32
errno_t err = strcat_s(strDestination, maxNumElementsInDestination, strSource);
if (err == 0)
{
return true;
}
else
{
return false;
}
#else
if (!strDestination || maxNumElementsInDestination == 0 || !strSource)
{
// Be consistent with the behavior of strcat_s.
return false;
}
size_t dstLen = strlen(strDestination);
size_t srcLen = strlen(strSource);
size_t sumLen = srcLen + dstLen;
if (sumLen + 1 > maxNumElementsInDestination)
{
return false;
}
strncat(strDestination, strSource, srcLen);
strDestination[sumLen] = 0;
return true;
#endif
}
//--------------------------------------------------------------------------------------------------
/// Wrapper for sprintf
///
/// \param buffer The buffer to write into
/// \param maxNumElementsInBuffer Size of the buffer in number of characters
/// \param format Format string
///
/// \return Number of character written into buffer, excluding the terminating NULL character.
/// If the function fails the return is -1
///
/// Not that at most maxNumElementsInBuffer - 1 characters are ever written into the buffer since
/// a termination character is always written to the last position in the buffer.
//--------------------------------------------------------------------------------------------------
int System::sprintf(char* buffer, size_t maxNumElementsInBuffer, const char* format, ...)
{
if (!buffer || maxNumElementsInBuffer == 0 || !format)
{
return -1;
}
va_list argList;
va_start(argList, format);
#ifdef WIN32
int numWritten = vsnprintf_s(buffer, maxNumElementsInBuffer*sizeof(char), maxNumElementsInBuffer - 1, format, argList);
#else
int numWritten = vsnprintf(buffer, maxNumElementsInBuffer, format, argList);
// Linux will fill the buffer without adding a NULL
// Catch this and report as error
if (numWritten == static_cast<int>(maxNumElementsInBuffer))
{
numWritten = -1;
}
#endif
va_end(argList);
// Ensure buffer is NULL terminated
buffer[maxNumElementsInBuffer - 1] = '\0';
return numWritten;
}
//--------------------------------------------------------------------------------------------------
/// Wrapper for sprintf
///
/// \param buffer The buffer to write into
/// \param maxNumElementsInBuffer Size of the buffer in number of wide characters (not bytes)
/// \param format Format string
///
/// \return Number of wide character written into buffer, excluding the terminating NULL character.
/// If the function fails the return is -1
///
/// Not that at most maxNumElementsInBuffer - 1 characters are ever written into the buffer since
/// a termination character is always written to the last position in the buffer.
//--------------------------------------------------------------------------------------------------
int System::swprintf(wchar_t* buffer, size_t maxNumElementsInBuffer, const wchar_t* format, ...)
{
if (!buffer || maxNumElementsInBuffer == 0 || !format)
{
return -1;
}
va_list argList;
va_start(argList, format);
#ifdef WIN32
int numWritten = _vsnwprintf_s(buffer, maxNumElementsInBuffer, maxNumElementsInBuffer - 1, format, argList);
#else
int numWritten = vswprintf(buffer, maxNumElementsInBuffer, format, argList);
#endif
va_end(argList);
buffer[maxNumElementsInBuffer - 1] = L'\0';
return numWritten;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t System::strlen(const char* str)
{
if (str)
{
return ::strlen(str);
}
else
{
return 0;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int System::strcmp(const char* str1, const char* str2)
{
if (str1 == NULL || str2 == NULL)
{
if (str1 == NULL && str2 == NULL)
{
return 0;
}
if (str1 == NULL)
{
return -1;
}
else
{
return 1;
}
}
else
{
return ::strcmp(str1, str2);
}
}
} // namespace cvf
+45
View File
@@ -0,0 +1,45 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
namespace cvf {
//==================================================================================================
//
// Static wrapper class for system functions
//
//==================================================================================================
class System
{
public:
static bool is64Bit();
static bool isBigEndian();
static bool memcpy(void* dst, size_t dstSizeInBytes, const void* src, size_t numBytesToCopy);
static bool strcpy(char* strDestination, size_t maxNumElementsInDestination, const char* strSource);
static bool strcat(char* strDestination, size_t maxNumElementsInDestination, const char* strSource);
static int sprintf(char* buffer, size_t maxNumElementsInBuffer, const char* format, ...);
static int swprintf(wchar_t* buffer, size_t maxNumElementsInBuffer, const wchar_t* format, ...);
static size_t strlen(const char* str);
static int strcmp(const char* str1, const char* str2);
};
}
@@ -0,0 +1,68 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#include "cvfBase.h"
#include "cvfTBBControl.h"
namespace cvf {
//==================================================================================================
///
/// \class cvf::TBBControl
/// \ingroup Core
///
/// Static class used to enable or disable the use of Intel TBB inside the libraries.
/// Only relevant if the libraries are being built with TBB support, in which case the default
/// enable setting will be true. If no TBB support is compiled in, the default enable state is false.
///
//==================================================================================================
#ifdef CVF_USE_TBB
bool TBBControl::sm_useTBB = true;
#else
bool TBBControl::sm_useTBB = false;
#endif
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void TBBControl::enable(bool enableTBB)
{
#ifdef CVF_USE_TBB
sm_useTBB = enableTBB;
#else
CVF_UNUSED(enableTBB);
#endif
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool TBBControl::isEnabled()
{
return sm_useTBB;
}
} // namespace cvf
@@ -0,0 +1,43 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
namespace cvf {
//==================================================================================================
//
// Static wrapper class to control usage of TBB
//
//==================================================================================================
class TBBControl
{
public:
static void enable(bool enableTBB);
static bool isEnabled();
private:
static bool sm_useTBB;
};
} // cvf
+257
View File
@@ -0,0 +1,257 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#include "cvfBase.h"
#include "cvfTimer.h"
#ifdef WIN32
#pragma warning (push)
#pragma warning (disable: 4668)
#include <windows.h>
#pragma warning (pop)
#endif
#ifdef CVF_LINUX
#include <time.h>
#endif
#if defined(CVF_IOS) || defined(CVF_OSX)
#include "mach/mach_time.h"
#endif
namespace cvf {
//=================================================================================================
//
// PrivateTimerState
//
//=================================================================================================
#ifdef WIN32
class PrivateTimerState
{
public:
PrivateTimerState()
{
m_ticksPerSecond = 0;
m_startTick = 0;
m_lastLapTick = 0;
LARGE_INTEGER freq;
if (QueryPerformanceFrequency(&freq))
{
m_ticksPerSecond = freq.QuadPart;
}
}
__int64 m_ticksPerSecond;
__int64 m_startTick;
__int64 m_lastLapTick;
};
#endif //WIN32
#ifdef CVF_LINUX
class PrivateTimerState
{
public:
PrivateTimerState()
{
m_timeStart.tv_sec = 0;
m_timeStart.tv_nsec = 0;
m_timeMark.tv_sec = 0;
m_timeMark.tv_nsec = 0;
}
timespec m_timeStart;
timespec m_timeMark;
};
#endif // CVF_LINUX
#if defined(CVF_IOS) || defined(CVF_OSX)
class PrivateTimerState
{
public:
PrivateTimerState()
{
mach_timebase_info(&m_info);
m_startTime = 0;
m_lastLapTime = 0;
}
mach_timebase_info_data_t m_info;
uint64_t m_startTime;
uint64_t m_lastLapTime;
};
#endif // CVF_IOS || CVF_OSX
//--------------------------------------------------------------------------------------------------
/// Static helper on Linux to compute difference between two timespecs
//--------------------------------------------------------------------------------------------------
#ifdef CVF_LINUX
static timespec ComputeTimespecDiff(const timespec start, const timespec end)
{
timespec temp;
if ((end.tv_nsec - start.tv_nsec) < 0)
{
temp.tv_sec = end.tv_sec - start.tv_sec - 1;
temp.tv_nsec = 1000000000 + end.tv_nsec-start.tv_nsec;
}
else
{
temp.tv_sec = end.tv_sec - start.tv_sec;
temp.tv_nsec = end.tv_nsec - start.tv_nsec;
}
return temp;
}
#endif
//==================================================================================================
///
/// \class cvf::Timer
/// \ingroup Core
///
/// Timer class
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
/// Start the timer.
//--------------------------------------------------------------------------------------------------
Timer::Timer()
{
m_timerState = new PrivateTimerState;
restart();
}
//--------------------------------------------------------------------------------------------------
/// Cleanup
//--------------------------------------------------------------------------------------------------
Timer::~Timer()
{
delete m_timerState;
}
//--------------------------------------------------------------------------------------------------
/// Restart timer and laptime
//--------------------------------------------------------------------------------------------------
void Timer::restart()
{
CVF_ASSERT(m_timerState);
#ifdef WIN32
LARGE_INTEGER tick;
QueryPerformanceCounter(&tick);
m_timerState->m_startTick = tick.QuadPart;
m_timerState->m_lastLapTick = m_timerState->m_startTick;
#elif CVF_LINUX
clock_gettime(CLOCK_MONOTONIC, &m_timerState->m_timeStart);
m_timerState->m_timeMark = m_timerState->m_timeStart;
#elif defined(CVF_IOS) || defined(CVF_OSX)
m_timerState->m_startTime = mach_absolute_time();
m_timerState->m_lastLapTime = m_timerState->m_startTime;
#endif
}
//--------------------------------------------------------------------------------------------------
/// Get the time elapsed since the start, in seconds
//--------------------------------------------------------------------------------------------------
double Timer::time() const
{
#ifdef WIN32
if (m_timerState->m_ticksPerSecond == 0) return 0.0;
LARGE_INTEGER nowTick;
QueryPerformanceCounter(&nowTick);
return static_cast<double>((nowTick.QuadPart - m_timerState->m_startTick))/static_cast<double>(m_timerState->m_ticksPerSecond);
#elif CVF_LINUX
timespec timeNow;
clock_gettime(CLOCK_MONOTONIC, &timeNow);
timespec timeDiff = ComputeTimespecDiff(m_timerState->m_timeStart, timeNow);
double timeUsedSec = static_cast<double>(timeDiff.tv_sec) + static_cast<double>(timeDiff.tv_nsec)/1000000000.0;
return timeUsedSec;
#elif defined(CVF_IOS) || defined(CVF_OSX)
uint64_t timeNow = mach_absolute_time();
uint64_t timeUsed = timeNow - m_timerState->m_startTime;
timeUsed *= m_timerState->m_info.numer;
uint64_t timeUsedNanoSec = timeUsed/m_timerState->m_info.denom;
double timeUsedSec = timeUsedNanoSec/1.0e9;
return timeUsedSec;
#endif
}
//--------------------------------------------------------------------------------------------------
/// Get elapsed time since last lap, in seconds
//--------------------------------------------------------------------------------------------------
double Timer::lapTime()
{
#ifdef WIN32
if (m_timerState->m_ticksPerSecond == 0) return 0.0;
LARGE_INTEGER nowTick;
QueryPerformanceCounter(&nowTick);
double lapTime = static_cast<double>((nowTick.QuadPart - m_timerState->m_lastLapTick))/static_cast<double>(m_timerState->m_ticksPerSecond);
m_timerState->m_lastLapTick = nowTick.QuadPart;
#elif CVF_LINUX
timespec timeNow;
clock_gettime(CLOCK_MONOTONIC, &timeNow);
timespec timeDiff = ComputeTimespecDiff(m_timerState->m_timeMark, timeNow);
m_timerState->m_timeMark = timeNow;
double lapTime = static_cast<double>(timeDiff.tv_sec) + static_cast<double>(timeDiff.tv_nsec)/1000000000.0;
#elif defined(CVF_IOS) || defined(CVF_OSX)
uint64_t timeNow = mach_absolute_time();
uint64_t timeUsed = timeNow - m_timerState->m_lastLapTime;
timeUsed *= m_timerState->m_info.numer;
uint64_t timeUsedNanoSec = timeUsed/m_timerState->m_info.denom;
double lapTime = timeUsedNanoSec/1.0e9;
m_timerState->m_lastLapTime = timeNow;
#endif
return lapTime;
}
} // namespace cvf
+49
View File
@@ -0,0 +1,49 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include "cvfObject.h"
namespace cvf {
class PrivateTimerState;
//=================================================================================================
//
// Timer class
//
//=================================================================================================
class Timer : public Object
{
public:
Timer();
~Timer();
void restart();
double time() const;
double lapTime();
private:
PrivateTimerState* m_timerState;
};
}
+139
View File
@@ -0,0 +1,139 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#include "cvfBase.h"
#include "cvfTrace.h"
#include "cvfSystem.h"
#ifdef WIN32
#pragma warning (push)
#pragma warning (disable: 4668)
#include <windows.h>
#pragma warning (pop)
#else
#include <cstdio>
#include <cstdarg>
#endif
namespace cvf {
//==================================================================================================
///
/// \class cvf::Trace
/// \ingroup Core
///
/// Class for writing debug text to console, DevStudio output window and file (future)
///
/// TODO: Create file output.
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
/// Write debug text to console, DevStudio output window and file (future)
//--------------------------------------------------------------------------------------------------
void Trace::show(String message)
{
showTraceOutput(message, true);
}
//--------------------------------------------------------------------------------------------------
/// Write printf formatted debug text to console, DevStudio output window and file (future)
//--------------------------------------------------------------------------------------------------
void Trace::show(const char* format, ...)
{
// Create the printf-style string and send it to the console and trace file
// TODO! Note: var-arg is solved locally here, but needs to be revisited e.g. in String class
va_list argList;
va_start(argList, format);
const int maxFormatLength = 4000;
char temp[maxFormatLength + 1];
#ifdef WIN32
_vsnprintf_s(temp, maxFormatLength, format, argList);
#else
vsprintf(temp, format, argList);
#endif
va_end(argList);
showTraceOutput(temp, true);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void Trace::showFileLineNumber(const String& file, int line, const String& message)
{
String tmp = file + "(" + String(line) + ")";
if (!message.isEmpty())
{
tmp += ": msg: " + message;
}
Trace::show(tmp);
}
//--------------------------------------------------------------------------------------------------
/// Show the trace output in console and DevStudio output window
//--------------------------------------------------------------------------------------------------
void Trace::showTraceOutput(String text, bool addNewLine)
{
#ifdef WIN32
AllocConsole();
HANDLE hStdOutputHandle = GetStdHandle(STD_OUTPUT_HANDLE);
if (hStdOutputHandle)
{
unsigned long iDum = 0;
CharArray ascii = text.toAscii();
DWORD stringLength = static_cast<DWORD>(System::strlen(ascii.ptr()));
WriteConsoleA(hStdOutputHandle, ascii.ptr(), stringLength, &iDum, NULL);
if (addNewLine) WriteConsole(hStdOutputHandle, "\n", 1, &iDum, NULL);
}
#else
fprintf(stderr, "%s", text.toAscii().ptr());
if (addNewLine)
{
fprintf(stderr, "\n");
}
#endif
// Show output in "Output window" in Visual Studio
#if defined(WIN32) && defined(_DEBUG)
// Alternativly use OutputDebugStringA(text.toAscii().ptr()); if this does not work on some platforms
_RPT0(_CRT_WARN, text.toAscii().ptr());
if (addNewLine)
{
_RPT0(_CRT_WARN, "\n");
}
#endif
}
} // namespace cvf
+46
View File
@@ -0,0 +1,46 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include "cvfString.h"
namespace cvf {
//=================================================================================================
//
// Trace class
//
//=================================================================================================
class Trace
{
public:
static void show(String message);
static void show(const char* format, ...);
static void showFileLineNumber(const String& file, int line, const String& message);
private:
static void showTraceOutput(String text, bool addNewLine);
};
#define CVF_TRACE_FILELINE Trace::showFileLineNumber(__FILE__, __LINE__, "");
#define CVF_TRACE_FILELINE_MSG(message) Trace::showFileLineNumber(__FILE__, __LINE__, message);
}
@@ -0,0 +1,58 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include "cvfVector4.h"
#include "cvfColor4.h"
namespace cvf {
//==================================================================================================
//
// Abstract base class for templated read-only array that returns elements by value
//
//==================================================================================================
template <typename T>
class ValueArray
{
public:
virtual ~ValueArray() {}
virtual T val(size_t index) const = 0;
virtual size_t size() const = 0;
};
typedef ValueArray<int> IntValueArray;
typedef ValueArray<uint> UIntValueArray;
typedef ValueArray<ushort> UShortValueArray;
typedef ValueArray<ubyte> UByteValueArray;
typedef ValueArray<float> FloatValueArray;
typedef ValueArray<double> DoubleValueArray;
typedef ValueArray<Vec2f> Vec2fValueArray;
typedef ValueArray<Vec3f> Vec3fValueArray;
typedef ValueArray<Vec3d> Vec3dValueArray;
typedef ValueArray<Color3ub> Color3ubValueArray;
typedef ValueArray<Color3f> Color3fValueArray;
typedef ValueArray<Color4ub> Color4ubValueArray;
}
@@ -0,0 +1,32 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#include "cvfBase.h"
#include "cvfVector2.h"
namespace cvf {
template<> Vector2<double> const Vector2<double>::UNDEFINED(UNDEFINED_DOUBLE, UNDEFINED_DOUBLE);
template<> Vector2<float> const Vector2<float>::UNDEFINED(UNDEFINED_FLOAT, UNDEFINED_FLOAT);
template<> Vector2<int> const Vector2<int>::UNDEFINED(UNDEFINED_INT, UNDEFINED_INT);
} // namespace cvf
+110
View File
@@ -0,0 +1,110 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include "cvfMath.h"
#include <limits>
namespace cvf {
//==================================================================================================
//
// Vector class for 2D vectors
//
//==================================================================================================
template<typename S>
class Vector2
{
public:
Vector2() {}
Vector2(S x, S y);
Vector2(const Vector2& other);
template<typename T>
explicit Vector2(const T& other);
inline Vector2& operator=(const Vector2& rhs);
inline bool operator==(const Vector2& rhs) const;
inline bool operator!=(const Vector2& rhs) const;
inline const Vector2 operator+(const Vector2& rhs) const;
inline const Vector2 operator-(const Vector2& rhs) const;
inline const Vector2 operator*(S scalar) const;
inline const Vector2 operator/(S scalar) const;
template<typename T>
friend inline const Vector2<T> operator*(T scalar, const Vector2<T>& rhs);
inline const Vector2 operator-() const;
inline Vector2& operator+=(const Vector2& rhs);
inline Vector2& operator-=(const Vector2& rhs);
inline Vector2& operator*=(S scalar);
inline Vector2& operator/=(S scalar);
inline const S& operator[](int index) const; // Get component 0 or 1. E.g. x = v[0];
inline S& operator[](int index); // Set component 0 or 1. E.g. v[0] = x;
inline S operator*(const Vector2& rhs) const; // Dot product
inline const S& x() const { return m_v[0]; } ///< Get the X element of the vector
inline const S& y() const { return m_v[1]; } ///< Get the Y element of the vector
inline S& x() { return m_v[0]; } ///< Get a reference to the X element of the vector. E.g. x() = 1;
inline S& y() { return m_v[1]; } ///< Get a reference to the Y element of the vector. E.g. y() = 2;
inline S* ptr() { return m_v; } ///< Get a raw pointer to the internal c array of type S.
inline const S* ptr() const { return m_v; } ///< Get a const raw pointer to the internal c array of type S.
inline void set(S x, S y);
inline void setZero();
inline bool isZero() const;
inline bool isUndefined() const;
template<typename T>
void set(const T& other);
bool normalize();
const Vector2 getNormalized(bool* normalizationOK = NULL) const;
inline S length() const;
inline S lengthSquared() const;
bool setLength(S newLength);
public:
static const Vector2 X_AXIS; ///< X axis vector <1, 0>
static const Vector2 Y_AXIS; ///< Y axis vector <0, 1>
static const Vector2 ZERO; ///< Null vector <0, 0>
static const Vector2 UNDEFINED; ///< Undefined vector
private:
S m_v[2];
};
typedef Vector2<float> Vec2f; ///< A vector with float components
typedef Vector2<double> Vec2d; ///< A vector with double components
typedef Vector2<int> Vec2i; ///< A vector with int components
typedef Vector2<uint> Vec2ui; ///< A vector with uint components
typedef Vector2<ushort> Vec2us; ///< A vector with ushort components
}
#include "cvfVector2.inl"
+432
View File
@@ -0,0 +1,432 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
namespace cvf {
//==================================================================================================
///
/// \class cvf::Vector2
/// \ingroup Core
///
/// Templated vector class for a 2 component vector.
///
/// Three ready-to-use typedefs are defined:\n
/// - cvf::Vec2f (Vector2<float>)
/// - cvf::Vec2d (Vector2<double>)
/// - cvf::Vec2i (Vector2<int>)
///
//==================================================================================================
template<typename S> Vector2<S> const Vector2<S>::X_AXIS(1, 0);
template<typename S> Vector2<S> const Vector2<S>::Y_AXIS(0, 1);
template<typename S> Vector2<S> const Vector2<S>::ZERO(0, 0);
//--------------------------------------------------------------------------------------------------
/// Set the vector to <x,y>
//--------------------------------------------------------------------------------------------------
template<typename S>
Vector2<S>::Vector2(S x, S y)
{
m_v[0] = x;
m_v[1] = y;
}
//--------------------------------------------------------------------------------------------------
/// Set the vector to the same as other
//--------------------------------------------------------------------------------------------------
template<typename S>
Vector2<S>::Vector2(const Vector2& other)
{
*this = other;
}
//--------------------------------------------------------------------------------------------------
/// An explicit cast constructor to convert from one vector type to another.
//--------------------------------------------------------------------------------------------------
template<typename S>
template<typename T>
Vector2<S>::Vector2(const T& other)
{
m_v[0] = static_cast<S>(other.x());
m_v[1] = static_cast<S>(other.y());
}
//--------------------------------------------------------------------------------------------------
/// Assign the vector to the contents of other
//--------------------------------------------------------------------------------------------------
template<typename S>
Vector2<S>& Vector2<S>::operator=(const Vector2& other)
{
m_v[0] = other.m_v[0];
m_v[1] = other.m_v[1];
return *this;
}
//--------------------------------------------------------------------------------------------------
/// Check if two vectors are equal. An exact match is required.
//--------------------------------------------------------------------------------------------------
template<typename S>
inline bool Vector2<S>::operator==(const Vector2& rhs) const
{
return (m_v[0] == rhs.m_v[0]) && (m_v[1] == rhs.m_v[1]);
}
//--------------------------------------------------------------------------------------------------
/// Check if two vectors are different. Returns true if not an exact match
//--------------------------------------------------------------------------------------------------
template<typename S>
inline bool Vector2<S>::operator!=(const Vector2& rhs) const
{
return !operator==(rhs);
}
//--------------------------------------------------------------------------------------------------
/// Returns the sum of this vector and the rhs vector
//--------------------------------------------------------------------------------------------------
template<typename S>
inline const Vector2<S> Vector2<S>::operator+(const Vector2& rhs) const
{
return Vector2(m_v[0]+rhs.m_v[0], m_v[1]+rhs.m_v[1]);
}
//--------------------------------------------------------------------------------------------------
/// Compute this-rhs and return the result.
//--------------------------------------------------------------------------------------------------
template<typename S>
inline const Vector2<S> Vector2<S>::operator-(const Vector2& rhs) const
{
return Vector2(m_v[0] - rhs.m_v[0], m_v[1] - rhs.m_v[1]);
}
//--------------------------------------------------------------------------------------------------
/// Return this vector scaled by the given scalar
//--------------------------------------------------------------------------------------------------
template<typename S>
const Vector2<S> Vector2<S>::operator*(S scalar) const
{
return Vector2(m_v[0]*scalar, m_v[1]*scalar);
}
//--------------------------------------------------------------------------------------------------
/// Return vector scaled by the given scalar
//--------------------------------------------------------------------------------------------------
template<typename T>
const Vector2<T> operator*(T scalar, const Vector2<T>& rhs)
{
// Note that this is a friend function
return Vector2<T>(rhs.m_v[0]*scalar, rhs.m_v[1]*scalar);
}
//--------------------------------------------------------------------------------------------------
/// Return a vector where each component is the corresponding component in this divided by scalar
//--------------------------------------------------------------------------------------------------
template<typename S>
const Vector2<S> Vector2<S>::operator/(S scalar) const
{
return Vector2(m_v[0]/scalar, m_v[1]/scalar);
}
//--------------------------------------------------------------------------------------------------
/// Return a vector which is the negation of this
//--------------------------------------------------------------------------------------------------
template<typename S>
const Vector2<S> Vector2<S>::operator-() const
{
return Vector2(-m_v[0], -m_v[1]);
}
//--------------------------------------------------------------------------------------------------
/// Add the given vector to this
//--------------------------------------------------------------------------------------------------
template<typename S>
inline Vector2<S>& Vector2<S>::operator+=(const Vector2& v)
{
m_v[0] += v.x();
m_v[1] += v.y();
return *this;
}
//--------------------------------------------------------------------------------------------------
/// Subtract the given vector from this
//--------------------------------------------------------------------------------------------------
template<typename S>
inline Vector2<S>& Vector2<S>::operator-=(const Vector2& v)
{
m_v[0] -= v.x();
m_v[1] -= v.y();
return *this;
}
//--------------------------------------------------------------------------------------------------
/// Scale this with the given scalar. Each component is multiplied with the given value
//--------------------------------------------------------------------------------------------------
template<typename S>
inline Vector2<S>& Vector2<S>::operator*=(S scalar)
{
m_v[0] *= scalar;
m_v[1] *= scalar;
return *this;
}
//--------------------------------------------------------------------------------------------------
/// Divide this with the given scalar. Each component is divided by the given scalar
//--------------------------------------------------------------------------------------------------
template<typename S>
inline Vector2<S>& Vector2<S>::operator/=(S scalar)
{
m_v[0] /= scalar;
m_v[1] /= scalar;
return *this;
}
//--------------------------------------------------------------------------------------------------
/// Get component 0 or 1. E.g. x = v[0];
//--------------------------------------------------------------------------------------------------
template<typename S>
inline const S& Vector2<S>::operator[](int index) const
{
CVF_TIGHT_ASSERT(index >= 0);
CVF_TIGHT_ASSERT(index < 2);
return m_v[index];
}
//--------------------------------------------------------------------------------------------------
/// Set component 0 or 1. E.g. v[0] = x;
//--------------------------------------------------------------------------------------------------
template<typename S>
inline S& Vector2<S>::operator[](int index)
{
CVF_TIGHT_ASSERT(index >= 0);
CVF_TIGHT_ASSERT(index < 2);
return m_v[index];
}
//--------------------------------------------------------------------------------------------------
/// Compute the dot product of this and rhs and return the result (scalar)
///
/// Formula:
/// \code
/// S = tx*rx + ty*ry
/// \endcode
//--------------------------------------------------------------------------------------------------
template<typename S>
inline S Vector2<S>::operator*(const Vector2& rhs) const
{
return m_v[0]*rhs.m_v[0] + m_v[1]*rhs.m_v[1];
}
//--------------------------------------------------------------------------------------------------
/// Set the vector from the other vector (of different type). Cast each component to convert it.
//--------------------------------------------------------------------------------------------------
template<typename S>
template<typename T>
void Vector2<S>::set(const T& other)
{
m_v[0] = static_cast<S>(other.x());
m_v[1] = static_cast<S>(other.y());
}
//--------------------------------------------------------------------------------------------------
/// Get the length of the vector
///
/// Formula:
/// \code
/// len = sqrt(x*x + y*y)
/// \endcode
//--------------------------------------------------------------------------------------------------
template<typename S>
inline S Vector2<S>::length() const
{
return Math::sqrt(m_v[0]*m_v[0] + m_v[1]*m_v[1]);
}
//--------------------------------------------------------------------------------------------------
/// Get the squared length (L2) of the vector
///
/// Formula:
/// \code
/// len = x*x + y*y
/// \endcode
//--------------------------------------------------------------------------------------------------
template<typename S>
inline S Vector2<S>::lengthSquared() const
{
return m_v[0]*m_v[0] + m_v[1]*m_v[1];
}
//--------------------------------------------------------------------------------------------------
/// Set the length of the vector to \a newLength.
///
/// \sa Vector3::setLength()
//--------------------------------------------------------------------------------------------------
template<typename S>
bool Vector2<S>::setLength(S newLength)
{
CVF_ASSERT(newLength >= 0);
S currLen = length();
if (currLen > std::numeric_limits<S>::epsilon() && newLength > 0)
{
S scale = newLength/currLen;
m_v[0] *= scale;
m_v[1] *= scale;
return true;
}
else
{
setZero();
return (newLength == 0) ? true : false;
}
}
//--------------------------------------------------------------------------------------------------
/// Normalize the vector (make sure the length is 1.0).
///
/// \return Returns true if normalization was possible. Returns false if length is zero or a NaN vector.
//--------------------------------------------------------------------------------------------------
template<typename S>
bool Vector2<S>::normalize()
{
S len = length();
if (len > 0.0)
{
// Precompute 1/length and do multiplication instead of division
S oneOverLen = (static_cast<S>(1.0)/len);
m_v[0] *= oneOverLen;
m_v[1] *= oneOverLen;
return true;
}
else
{
// Might be NaN, so set it to zero
m_v[0] = 0;
m_v[1] = 0;
return false;
}
}
//--------------------------------------------------------------------------------------------------
/// Returns a normalized version of the current vector. The vector is unchanged.
//--------------------------------------------------------------------------------------------------
template<typename S>
const Vector2<S> Vector2<S>::getNormalized(bool* normalizationOK) const
{
S len = length();
if (len > 0.0)
{
if (normalizationOK) *normalizationOK = true;
S oneOverLen = (static_cast<S>(1.0)/len);
return Vector2<S>(m_v[0]*oneOverLen, m_v[1]*oneOverLen);
}
else
{
if (normalizationOK) *normalizationOK = false;
return Vector2<S>::ZERO;
}
}
//--------------------------------------------------------------------------------------------------
/// Set all components to 0
//--------------------------------------------------------------------------------------------------
template<typename S>
inline void Vector2<S>::setZero()
{
m_v[0] = 0;
m_v[1] = 0;
}
//--------------------------------------------------------------------------------------------------
/// Check if all components are zero (exact match)
//--------------------------------------------------------------------------------------------------
template<typename S>
inline bool Vector2<S>::isZero() const
{
return (m_v[0] == 0) && (m_v[1] == 0);
}
//--------------------------------------------------------------------------------------------------
/// Check if vector is undefined
///
/// \return Returns true if any one of the components is undefined
//--------------------------------------------------------------------------------------------------
template<typename S>
inline bool Vector2<S>::isUndefined() const
{
if (Math::isUndefined(m_v[0]) ||
Math::isUndefined(m_v[1]))
{
return true;
}
else
{
return false;
}
}
//--------------------------------------------------------------------------------------------------
/// Set the components of the vector
//--------------------------------------------------------------------------------------------------
template<typename S>
inline void Vector2<S>::set(S x, S y)
{
m_v[0] = x;
m_v[1] = y;
}
} // namespace cvf
@@ -0,0 +1,32 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#include "cvfBase.h"
#include "cvfVector3.h"
namespace cvf {
template<> Vector3<double> const Vector3<double>::UNDEFINED(UNDEFINED_DOUBLE, UNDEFINED_DOUBLE, UNDEFINED_DOUBLE);
template<> Vector3<float> const Vector3<float>::UNDEFINED(UNDEFINED_FLOAT, UNDEFINED_FLOAT, UNDEFINED_FLOAT);
template<> Vector3<int> const Vector3<int>::UNDEFINED(UNDEFINED_INT, UNDEFINED_INT, UNDEFINED_INT);
template<> Vector3<size_t> const Vector3<size_t>::UNDEFINED(UNDEFINED_SIZE_T, UNDEFINED_SIZE_T, UNDEFINED_SIZE_T);
} // namespace cvf
+137
View File
@@ -0,0 +1,137 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include "cvfVector2.h"
namespace cvf {
// Forward declaration of templated matrix class
template<typename S>
class Matrix4;
template<typename S>
class Matrix3;
//==================================================================================================
//
// Vector class for 3D vectors
//
//==================================================================================================
template<typename S>
class Vector3
{
public:
Vector3() {}
Vector3(S x, S y, S z);
Vector3(const Vector3& other);
explicit Vector3(const Vector2<S>& other);
Vector3(const Vector2<S>& other, S z);
template<typename T>
explicit Vector3(const T& other);
inline Vector3& operator=(const Vector3& rhs);
inline bool operator==(const Vector3& rhs) const;
inline bool operator!=(const Vector3& rhs) const;
inline const Vector3 operator+(const Vector3& rhs) const;
inline const Vector3 operator-(const Vector3& rhs) const;
inline const Vector3 operator*(S scalar) const;
inline const Vector3 operator/(S scalar) const;
template<typename T>
friend inline const Vector3<T> operator*(T scalar, const Vector3<T>& rhs);
inline const Vector3 operator-() const;
inline Vector3& operator+=(const Vector3& rhs);
inline Vector3& operator-=(const Vector3& rhs);
inline Vector3& operator*=(S scalar);
inline Vector3& operator/=(S scalar);
inline const S& operator[](int index) const; // Get component 0,1,2. E.g. x = v[0];
inline S& operator[](int index); // Set component 0,1,2. E.g. v[0] = x;
inline S operator*(const Vector3& rhs) const; // Dot product
inline const Vector3 operator^(const Vector3& rhs) const; // Cross product
inline const S& x() const { return m_v[0]; } ///< Get the X element of the vector
inline const S& y() const { return m_v[1]; } ///< Get the Y element of the vector
inline const S& z() const { return m_v[2]; } ///< Get the Z element of the vector
inline S& x() { return m_v[0]; } ///< Get a reference to the X element of the vector. E.g. x() = 1;
inline S& y() { return m_v[1]; } ///< Get a reference to the Y element of the vector. E.g. y() = 2;
inline S& z() { return m_v[2]; } ///< Get a reference to the Z element of the vector. E.g. z() = 3;
inline S* ptr() { return m_v; } ///< Get a raw pointer to the internal c array of type S.
inline const S* ptr() const { return m_v; } ///< Get a const raw pointer to the internal c array of type S.
inline void set(S x, S y, S z);
inline void setZero();
inline bool isZero() const;
inline bool isUndefined() const;
template<typename T>
void set(const T& other);
bool normalize();
const Vector3 getNormalized(bool* normalizationOK = NULL) const;
inline S length() const;
inline S lengthSquared() const;
bool setLength(S newLength);
inline S pointDistance(const Vector3& otherPoint) const;
inline S pointDistanceSquared(const Vector3& otherPoint) const;
void transformPoint(const Matrix4<S>& m);
const Vector3 getTransformedPoint(const Matrix4<S>& m) const;
void transformVector(const Matrix4<S>& m);
const Vector3 getTransformedVector(const Matrix4<S>& m) const;
void transformVector(const Matrix3<S>& m);
const Vector3 getTransformedVector(const Matrix3<S>& m) const;
bool createOrthonormalBasis(int mapToAxis, Vector3<S>* uAxis, Vector3<S>* vAxis, Vector3<S>* wAxis) const;
const Vector3 perpendicularVector(bool* perpendicularOK = NULL) const;
public:
static const Vector3 X_AXIS; ///< X axis vector <1, 0, 0>
static const Vector3 Y_AXIS; ///< Y axis vector <0, 1, 0>
static const Vector3 Z_AXIS; ///< Z axis vector <0, 0, 1>
static const Vector3 ZERO; ///< Null vector <0, 0, 0>
static const Vector3 UNDEFINED; ///< Undefined vector
private:
S m_v[3];
};
typedef Vector3<float> Vec3f; ///< A vector with float components
typedef Vector3<double> Vec3d; ///< A vector with double components
typedef Vector3<int> Vec3i; ///< A vector with int components
typedef Vector3<uint> Vec3ui; ///< A vector with uint components
typedef Vector3<size_t> Vec3st; ///< A vector with size_t components
}
#include "cvfVector3.inl"
+707
View File
@@ -0,0 +1,707 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
namespace cvf {
//==================================================================================================
///
/// \class cvf::Vector3
/// \ingroup Core
///
/// Templated vector class for a 3 component vector.
///
/// Three ready-to-use typedefs are defined:\n
/// - cvf::Vec3f (Vector3<float>)
/// - cvf::Vec3d (Vector3<double>)
/// - cvf::Vec3i (Vector3<int>)
///
//==================================================================================================
template<typename S> Vector3<S> const Vector3<S>::X_AXIS(1,0,0);
template<typename S> Vector3<S> const Vector3<S>::Y_AXIS(0,1,0);
template<typename S> Vector3<S> const Vector3<S>::Z_AXIS(0,0,1);
template<typename S> Vector3<S> const Vector3<S>::ZERO(0,0,0);
//--------------------------------------------------------------------------------------------------
/// Set the vector to <x,y,z>
//--------------------------------------------------------------------------------------------------
template<typename S>
Vector3<S>::Vector3(S x, S y, S z)
{
m_v[0] = x;
m_v[1] = y;
m_v[2] = z;
}
//--------------------------------------------------------------------------------------------------
/// Set the vector to the same as other
//--------------------------------------------------------------------------------------------------
template<typename S>
Vector3<S>::Vector3(const Vector3& other)
{
*this = other;
}
//--------------------------------------------------------------------------------------------------
/// An explicit cast constructor to convert from one vector type to another.
//--------------------------------------------------------------------------------------------------
template<typename S>
template<typename T>
Vector3<S>::Vector3(const T& other)
{
m_v[0] = static_cast<S>(other.x());
m_v[1] = static_cast<S>(other.y());
m_v[2] = static_cast<S>(other.z());
}
//--------------------------------------------------------------------------------------------------
/// Explicit constructor from 2D vector.
///
/// Will initialize x and y components from the 2D vector, z will be set to 0.
//--------------------------------------------------------------------------------------------------
template<typename S>
Vector3<S>::Vector3(const Vector2<S>& other)
{
m_v[0] = other.x();
m_v[1] = other.y();
m_v[2] = 0.0;
}
//--------------------------------------------------------------------------------------------------
/// Constructor
//--------------------------------------------------------------------------------------------------
template<typename S>
Vector3<S>::Vector3(const Vector2<S>& other, S z)
{
m_v[0] = other.x();
m_v[1] = other.y();
m_v[2] = z;
}
//--------------------------------------------------------------------------------------------------
/// Assign the vector to the contents of other
//--------------------------------------------------------------------------------------------------
template<typename S>
Vector3<S>& Vector3<S>::operator=(const Vector3& other)
{
m_v[0] = other.m_v[0];
m_v[1] = other.m_v[1];
m_v[2] = other.m_v[2];
return *this;
}
//--------------------------------------------------------------------------------------------------
/// Check if two vectors are equal. An exact match is required.
//--------------------------------------------------------------------------------------------------
template<typename S>
inline bool Vector3<S>::operator==(const Vector3& rhs) const
{
return (m_v[0] == rhs.m_v[0]) && (m_v[1] == rhs.m_v[1]) && (m_v[2] == rhs.m_v[2]);
}
//--------------------------------------------------------------------------------------------------
/// Check if two vectors are different. Returns true if not an exact match
//--------------------------------------------------------------------------------------------------
template<typename S>
inline bool Vector3<S>::operator!=(const Vector3& rhs) const
{
return !operator==(rhs);
}
//--------------------------------------------------------------------------------------------------
/// Returns the sum of this vector and the rhs vector
//--------------------------------------------------------------------------------------------------
template<typename S>
inline const Vector3<S> Vector3<S>::operator+(const Vector3& rhs) const
{
return Vector3(m_v[0]+rhs.m_v[0], m_v[1]+rhs.m_v[1], m_v[2]+rhs.m_v[2]);
}
//--------------------------------------------------------------------------------------------------
/// Compute this-rhs and return the result.
//--------------------------------------------------------------------------------------------------
template<typename S>
inline const Vector3<S> Vector3<S>::operator-(const Vector3& rhs) const
{
return Vector3(m_v[0] - rhs.m_v[0], m_v[1] - rhs.m_v[1], m_v[2] - rhs.m_v[2]);
}
//--------------------------------------------------------------------------------------------------
/// Return this vector scaled by the given scalar
//--------------------------------------------------------------------------------------------------
template<typename S>
const Vector3<S> Vector3<S>::operator*(S scalar) const
{
return Vector3(m_v[0]*scalar, m_v[1]*scalar, m_v[2]*scalar);
}
//--------------------------------------------------------------------------------------------------
/// Return vector scaled by the given scalar
//--------------------------------------------------------------------------------------------------
template<typename T>
const Vector3<T> operator*(T scalar, const Vector3<T>& rhs)
{
// Note that this is a friend function
return Vector3<T>(rhs.m_v[0]*scalar, rhs.m_v[1]*scalar, rhs.m_v[2]*scalar);
}
//--------------------------------------------------------------------------------------------------
/// Return a vector where each component is the corresponding component in this divided by scalar
//--------------------------------------------------------------------------------------------------
template<typename S>
const Vector3<S> Vector3<S>::operator/(S scalar) const
{
return Vector3(m_v[0]/scalar, m_v[1]/scalar, m_v[2]/scalar);
}
//--------------------------------------------------------------------------------------------------
/// Return a vector which is the negation of this
//--------------------------------------------------------------------------------------------------
template<typename S>
const Vector3<S> Vector3<S>::operator-() const
{
return Vector3(-m_v[0], -m_v[1], -m_v[2]);
}
//--------------------------------------------------------------------------------------------------
/// Add the given vector to this
//--------------------------------------------------------------------------------------------------
template<typename S>
inline Vector3<S>& Vector3<S>::operator+=(const Vector3& v)
{
m_v[0] += v.x();
m_v[1] += v.y();
m_v[2] += v.z();
return *this;
}
//--------------------------------------------------------------------------------------------------
/// Subtract the given vector from this
//--------------------------------------------------------------------------------------------------
template<typename S>
inline Vector3<S>& Vector3<S>::operator-=(const Vector3& v)
{
m_v[0] -= v.x();
m_v[1] -= v.y();
m_v[2] -= v.z();
return *this;
}
//--------------------------------------------------------------------------------------------------
/// Scale this with the given scalar. Each component is multiplied with the given value
//--------------------------------------------------------------------------------------------------
template<typename S>
inline Vector3<S>& Vector3<S>::operator*=(S scalar)
{
m_v[0] *= scalar;
m_v[1] *= scalar;
m_v[2] *= scalar;
return *this;
}
//--------------------------------------------------------------------------------------------------
/// Divide this with the given scalar. Each component is divided by the given scalar
//--------------------------------------------------------------------------------------------------
template<typename S>
inline Vector3<S>& Vector3<S>::operator/=(S scalar)
{
m_v[0] /= scalar;
m_v[1] /= scalar;
m_v[2] /= scalar;
return *this;
}
//--------------------------------------------------------------------------------------------------
/// Get component 0,1,2. E.g. x = v[0];
//--------------------------------------------------------------------------------------------------
template<typename S>
inline const S& Vector3<S>::operator[](int index) const
{
CVF_TIGHT_ASSERT(index >= 0);
CVF_TIGHT_ASSERT(index < 3);
return m_v[index];
}
//--------------------------------------------------------------------------------------------------
/// Set component 0,1,2. E.g. v[0] = x;
//--------------------------------------------------------------------------------------------------
template<typename S>
inline S& Vector3<S>::operator[](int index)
{
CVF_TIGHT_ASSERT(index >= 0);
CVF_TIGHT_ASSERT(index < 3);
return m_v[index];
}
//--------------------------------------------------------------------------------------------------
/// Compute the dot product of this and rhs and return the result (scalar)
///
/// Formula:
/// \code
/// S = tx*rx + ty*ry + tz*rz
/// \endcode
//--------------------------------------------------------------------------------------------------
template<typename S>
inline S Vector3<S>::operator*(const Vector3& rhs) const
{
return m_v[0]*rhs.m_v[0] + m_v[1]*rhs.m_v[1] + m_v[2]*rhs.m_v[2];
}
//--------------------------------------------------------------------------------------------------
/// Compute the cross product of this and rhs and return the result (vector)
///
/// Formula:
/// \code
/// vec = <ty*rz - tz*ry, tz*rx - tx*rz, tx*ry - ty*rx>
/// \endcode
//--------------------------------------------------------------------------------------------------
template<typename S>
inline const Vector3<S> Vector3<S>::operator^(const Vector3& rhs) const
{
return Vector3(m_v[1]*rhs.m_v[2] - m_v[2]*rhs.m_v[1], m_v[2]*rhs.m_v[0] - m_v[0]*rhs.m_v[2], m_v[0]*rhs.m_v[1] - m_v[1]*rhs.m_v[0]);
}
//--------------------------------------------------------------------------------------------------
/// Set the vector from the other vector (of different type). Cast each component to convert it.
//--------------------------------------------------------------------------------------------------
template<typename S>
template<typename T>
void Vector3<S>::set(const T& other)
{
m_v[0] = static_cast<S>(other.x());
m_v[1] = static_cast<S>(other.y());
m_v[2] = static_cast<S>(other.z());
}
//--------------------------------------------------------------------------------------------------
/// Get the length of the vector
///
/// Formula:
/// \code
/// len = sqrt(x*x + y*y + z*z)
/// \endcode
//--------------------------------------------------------------------------------------------------
template<typename S>
inline S Vector3<S>::length() const
{
return Math::sqrt(m_v[0]*m_v[0] + m_v[1]*m_v[1] + m_v[2]*m_v[2]);
}
//--------------------------------------------------------------------------------------------------
/// Get the squared length (L2) of the vector
///
/// Formula:
/// \code
/// len = x*x + y*y + z*z
/// \endcode
//--------------------------------------------------------------------------------------------------
template<typename S>
inline S Vector3<S>::lengthSquared() const
{
return m_v[0]*m_v[0] + m_v[1]*m_v[1] + m_v[2]*m_v[2];
}
//--------------------------------------------------------------------------------------------------
/// Set the length of the vector to \a newLength.
///
/// \return The method returns true if scaling was a success. Returns false if the vector was of
/// zero length and \a newLength was different from 0.
///
/// This is the same as calling normalize() and then scaling with \a newLength.
/// If the current vector length is 0 or \a newLength is 0, the vector is set to all zeros.
//--------------------------------------------------------------------------------------------------
template<typename S>
bool Vector3<S>::setLength(S newLength)
{
CVF_ASSERT(newLength >= 0);
S currLen = length();
if (currLen > std::numeric_limits<S>::epsilon() && newLength > 0)
{
S scale = newLength/currLen;
m_v[0] *= scale;
m_v[1] *= scale;
m_v[2] *= scale;
return true;
}
else
{
setZero();
return (newLength == 0) ? true : false;
}
}
//--------------------------------------------------------------------------------------------------
/// Get the distance between this point and the point specified in \a otherPoint
//--------------------------------------------------------------------------------------------------
template<typename S>
inline S Vector3<S>::pointDistance(const Vector3& otherPoint) const
{
return Math::sqrt(pointDistanceSquared(otherPoint));
}
//--------------------------------------------------------------------------------------------------
/// Get the squared distance between this point and the point specified in \a otherPoint
//--------------------------------------------------------------------------------------------------
template<typename S>
inline S Vector3<S>::pointDistanceSquared(const Vector3& otherPoint) const
{
S x = otherPoint.m_v[0] - m_v[0];
S y = otherPoint.m_v[1] - m_v[1];
S z = otherPoint.m_v[2] - m_v[2];
return (x*x + y*y + z*z);
}
//--------------------------------------------------------------------------------------------------
/// Normalize the vector (make sure the length is 1.0).
///
/// \return Returns true if normalization was possible. Returns false if length is zero or a NaN vector.
//--------------------------------------------------------------------------------------------------
template<typename S>
bool Vector3<S>::normalize()
{
S len = length();
if (len > 0.0)
{
// Precompute 1/length and do multiplication instead of division
S oneOverLen = (static_cast<S>(1.0)/len);
m_v[0] *= oneOverLen;
m_v[1] *= oneOverLen;
m_v[2] *= oneOverLen;
return true;
}
else
{
// Might be NaN, so set it to zero
m_v[0] = 0;
m_v[1] = 0;
m_v[2] = 0;
return false;
}
}
//--------------------------------------------------------------------------------------------------
/// Returns a normalized version of the current vector. The vector is unchanged.
//--------------------------------------------------------------------------------------------------
template<typename S>
const Vector3<S> Vector3<S>::getNormalized(bool* normalizationOK) const
{
S len = length();
if (len > 0.0)
{
if (normalizationOK) *normalizationOK = true;
S oneOverLen = (static_cast<S>(1.0)/len);
return Vector3<S>(m_v[0]*oneOverLen, m_v[1]*oneOverLen, m_v[2]*oneOverLen);
}
else
{
if (normalizationOK) *normalizationOK = false;
return Vector3<S>::ZERO;
}
}
//--------------------------------------------------------------------------------------------------
/// Set all components to 0
//--------------------------------------------------------------------------------------------------
template<typename S>
inline void Vector3<S>::setZero()
{
m_v[0] = 0;
m_v[1] = 0;
m_v[2] = 0;
}
//--------------------------------------------------------------------------------------------------
/// Check if all components are zero (exact match)
//--------------------------------------------------------------------------------------------------
template<typename S>
inline bool Vector3<S>::isZero() const
{
return (m_v[0] == 0) && (m_v[1] == 0) && (m_v[2] == 0);
}
//--------------------------------------------------------------------------------------------------
/// Check if vector is undefined
///
/// \return Returns true if any one of the components is undefined
//--------------------------------------------------------------------------------------------------
template<typename S>
inline bool Vector3<S>::isUndefined() const
{
if (Math::isUndefined(m_v[0]) ||
Math::isUndefined(m_v[1]) ||
Math::isUndefined(m_v[2]))
{
return true;
}
else
{
return false;
}
}
//--------------------------------------------------------------------------------------------------
/// Set the components of the vector
//--------------------------------------------------------------------------------------------------
template<typename S>
inline void Vector3<S>::set(S x, S y, S z)
{
m_v[0] = x;
m_v[1] = y;
m_v[2] = z;
}
//--------------------------------------------------------------------------------------------------
/// Transforms this vector as a point.
///
/// Transforms this vector as a point by multiplying it with the passed matrix.
/// This will both rotate and translate this.
/// Assumes the matrix m doesn't contain any perspective projection
//--------------------------------------------------------------------------------------------------
template<typename S>
void Vector3<S>::transformPoint(const Matrix4<S>& m)
{
const S* pV = m.ptr();
S valX = pV[0]*x() + pV[4]*y() + pV[8]*z() + pV[12];
S valY = pV[1]*x() + pV[5]*y() + pV[9]*z() + pV[13];
S valZ = pV[2]*x() + pV[6]*y() + pV[10]*z() + pV[14];
x() = valX;
y() = valY;
z() = valZ;
}
//--------------------------------------------------------------------------------------------------
/// Return this vector transformed as a point (rotation and translation) with the given matrix.
/// \sa
/// transformPoint
//--------------------------------------------------------------------------------------------------
template<typename S>
const Vector3<S> Vector3<S>::getTransformedPoint(const Matrix4<S>& m) const
{
Vector3<S> pt(*this);
pt.transformPoint(m);
return pt;
}
//--------------------------------------------------------------------------------------------------
/// Transforms this vector as a vector.
///
/// Transforms this vector as a vector by multiplying it with the passed matrix.
/// This will only rotate the vector, but not consider the translation part of the matrix.
/// Assumes the matrix m doesn't contain any perspective projection.
//--------------------------------------------------------------------------------------------------
template<typename S>
void Vector3<S>::transformVector(const Matrix4<S>& m)
{
const S* pV = m.ptr();
S valX = pV[0]*x() + pV[4]*y() + pV[8]*z();
S valY = pV[1]*x() + pV[5]*y() + pV[9]*z();
S valZ = pV[2]*x() + pV[6]*y() + pV[10]*z();
x() = valX;
y() = valY;
z() = valZ;
}
//--------------------------------------------------------------------------------------------------
/// Return this vector transformed as a vector (rotation only) with the given matrix.
/// \sa
/// transformVector
//--------------------------------------------------------------------------------------------------
template<typename S>
const Vector3<S> Vector3<S>::getTransformedVector(const Matrix4<S>& m) const
{
Vector3<S> vec(*this);
vec.transformVector(m);
return vec;
}
//--------------------------------------------------------------------------------------------------
/// Transforms this vector.
///
/// Transforms this vector by multiplying it with the passed matrix.
//--------------------------------------------------------------------------------------------------
template<typename S>
void Vector3<S>::transformVector(const Matrix3<S>& m)
{
const S* pV = m.ptr();
S valX = pV[0]*x() + pV[3]*y() + pV[6]*z();
S valY = pV[1]*x() + pV[4]*y() + pV[7]*z();
S valZ = pV[2]*x() + pV[5]*y() + pV[8]*z();
x() = valX;
y() = valY;
z() = valZ;
}
//--------------------------------------------------------------------------------------------------
/// Return this vector transformed with the given matrix.
/// \sa
/// transformVector
//--------------------------------------------------------------------------------------------------
template<typename S>
const Vector3<S> Vector3<S>::getTransformedVector(const Matrix3<S>& m) const
{
Vector3<S> vec(*this);
vec.transformVector(m);
return vec;
}
//----------------------------------------------------------------------------------------------------
/// Create an orthonormal basis from this vector
///
/// \param mapToAxis Specifies which axis this vector should be mapped onto (0=u, 1=v, 2=w)
/// \param uAxis Output u vector
/// \param vAxis Output v vector
/// \param wAxis Output w vector
///
/// Will create an orthonormal basis from this vector. The returned u, v and w axes will all be unit
/// length and will be perpendicular to each other.
/// The vector does not have to be normalized before calling this function.
//----------------------------------------------------------------------------------------------------
template<typename S>
bool Vector3<S>::createOrthonormalBasis(int mapToAxis, Vector3<S>* uAxis, Vector3<S>* vAxis, Vector3<S>* wAxis) const
{
bool normalizedOK = false;
Vector3<S> W = getNormalized(&normalizedOK);
if (!normalizedOK)
{
return false;
}
Vector3<S> U(0, 0, 0);
if (Math::abs(W.x()) >= Math::abs(W.y()))
{
// W.x or W.z component has largest magnitude
S length = Math::sqrt(W.x()*W.x() + W.z()*W.z());
U.x() = -W.z()/length;
U.y() = 0.0;
U.z() = +W.x()/length;
}
else
{
// W.y or W.z component has largest magnitude
S length = Math::sqrt(W.y()*W.y() + W.z()*W.z());
U.x() = 0.0;
U.y() = +W.z()/length;
U.z() = -W.y()/length;
}
// Get V as cross product of WxU
// Could be optimized by taking into account the fact that either the y or x component of U will be 0
Vector3<S> V = W^U;
// Algorithm above maps our vector onto W axis
// If another axis is requested, we need to shuffle the vectors
if (mapToAxis == 0)
{
if (uAxis) *uAxis = W;
if (vAxis) *vAxis = U;
if (wAxis) *wAxis = V;
}
else if (mapToAxis == 1)
{
if (uAxis) *uAxis = V;
if (vAxis) *vAxis = W;
if (wAxis) *wAxis = U;
}
else
{
if (uAxis) *uAxis = U;
if (vAxis) *vAxis = V;
if (wAxis) *wAxis = W;
}
return true;
}
//--------------------------------------------------------------------------------------------------
/// Return a unit length perpendicular vector
//--------------------------------------------------------------------------------------------------
template<typename S>
const Vector3<S> Vector3<S>::perpendicularVector(bool* perpendicularOK) const
{
Vector3<S> perpendic(0, 0, 0);
bool ok = createOrthonormalBasis(0, NULL, &perpendic, NULL);
if (perpendicularOK)
{
*perpendicularOK = ok;
}
return perpendic;
}
} // namespace cvf
@@ -0,0 +1,32 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#include "cvfBase.h"
#include "cvfVector4.h"
#include "cvfMath.h"
namespace cvf {
template<> Vector4<double> const Vector4<double>::UNDEFINED(UNDEFINED_DOUBLE, UNDEFINED_DOUBLE, UNDEFINED_DOUBLE, UNDEFINED_DOUBLE);
template<> Vector4<float> const Vector4<float>::UNDEFINED(UNDEFINED_FLOAT, UNDEFINED_FLOAT, UNDEFINED_FLOAT, UNDEFINED_FLOAT);
template<> Vector4<int> const Vector4<int>::UNDEFINED(UNDEFINED_INT, UNDEFINED_INT, UNDEFINED_INT, UNDEFINED_INT);
} // namespace cvf
+105
View File
@@ -0,0 +1,105 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include "cvfVector3.h"
namespace cvf {
//==================================================================================================
//
// Vector class for 3D vectors
//
//==================================================================================================
template<typename S>
class Vector4
{
public:
Vector4() {}
Vector4(S x, S y, S z, S w);
Vector4(const Vector4& other);
Vector4(const Vector3<S>& other, S w);
template<typename T>
explicit Vector4(const T& other);
inline Vector4& operator=(const Vector4& rhs);
inline bool operator==(const Vector4& rhs) const;
inline bool operator!=(const Vector4& rhs) const;
inline const Vector4 operator+(const Vector4& rhs) const;
inline const Vector4 operator-(const Vector4& rhs) const;
inline const Vector4 operator*(S scalar) const;
inline const Vector4 operator/(S scalar) const;
inline const Vector4 operator-() const;
inline Vector4& operator+=(const Vector4& rhs);
inline Vector4& operator-=(const Vector4& rhs);
inline Vector4& operator*=(S scalar);
inline Vector4& operator/=(S scalar);
inline const S& operator[](int index) const; // Get component 0,1,2,3. E.g. x = v[0];
inline S& operator[](int index); // Set component 0,1,2,3. E.g. v[0] = x;
inline S operator*(const Vector4& rhs) const; // Dot product
inline const S& x() const { return m_v[0]; } ///< Get the X element of the vector
inline const S& y() const { return m_v[1]; } ///< Get the Y element of the vector
inline const S& z() const { return m_v[2]; } ///< Get the Z element of the vector
inline const S& w() const { return m_v[3]; } ///< Get the W element of the vector
inline S& x() { return m_v[0]; } ///< Get a reference to the X element of the vector. E.g. x() = 1;
inline S& y() { return m_v[1]; } ///< Get a reference to the Y element of the vector. E.g. y() = 2;
inline S& z() { return m_v[2]; } ///< Get a reference to the Z element of the vector. E.g. z() = 3;
inline S& w() { return m_v[3]; } ///< Get a reference to the W element of the vector. E.g. w() = 3;
inline S* ptr() { return m_v; } ///< Get a raw pointer to the internal c array of type S.
inline const S* ptr() const { return m_v; } ///< Get a const raw pointer to the internal c array of type S.
inline void set(S x, S y, S z, S w);
inline void setZero();
inline bool isZero() const;
template<typename T>
void set(const T& other);
bool normalize();
Vector4 normalized(bool* normalizationOK = NULL) const;
inline S length() const;
inline S lengthSquared() const;
bool setLength(S newLength);
public:
static const Vector4 ZERO; ///< Null vector <0, 0, 0>
static const Vector4 UNDEFINED; ///< Undefined vector
private:
S m_v[4];
};
typedef Vector4<float> Vec4f; ///< A vector with float components
typedef Vector4<double> Vec4d; ///< A vector with double components
typedef Vector4<int> Vec4i; ///< A vector with int components
}
#include "cvfVector4.inl"
+440
View File
@@ -0,0 +1,440 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
namespace cvf {
//==================================================================================================
///
/// \class cvf::Vector4
/// \ingroup Core
///
/// Templated vector class for a 4 component vector.
///
/// Three ready-to-use typedefs are defined:\n
/// - cvf::Vec4f (Vector4<float>)
/// - cvf::Vec4d (Vector4<double>)
/// - cvf::Vec4i (Vector4<int>)
///
//==================================================================================================
template<typename S> Vector4<S> const Vector4<S>::ZERO(0,0,0,0);
//--------------------------------------------------------------------------------------------------
/// Set the vector to <x,y,z>
//--------------------------------------------------------------------------------------------------
template<typename S>
Vector4<S>::Vector4(S x, S y, S z, S w)
{
m_v[0] = x;
m_v[1] = y;
m_v[2] = z;
m_v[3] = w;
}
//--------------------------------------------------------------------------------------------------
/// Set the vector to the same as other
//--------------------------------------------------------------------------------------------------
template<typename S>
Vector4<S>::Vector4(const Vector4& other)
{
*this = other;
}
//--------------------------------------------------------------------------------------------------
/// An explicit cast constructor to convert from one vector type to another.
//--------------------------------------------------------------------------------------------------
template<typename S>
template<typename T>
Vector4<S>::Vector4(const T& other)
{
m_v[0] = static_cast<S>(other.x());
m_v[1] = static_cast<S>(other.y());
m_v[2] = static_cast<S>(other.z());
m_v[3] = static_cast<S>(other.w());
}
//--------------------------------------------------------------------------------------------------
/// Assign the vector to the contents of other
//--------------------------------------------------------------------------------------------------
template<typename S>
Vector4<S>& Vector4<S>::operator=(const Vector4& other)
{
m_v[0] = other.m_v[0];
m_v[1] = other.m_v[1];
m_v[2] = other.m_v[2];
m_v[3] = other.m_v[3];
return *this;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename S>
Vector4<S>::Vector4(const Vector3<S>& other, S w)
{
m_v[0] = other.x();
m_v[1] = other.y();
m_v[2] = other.z();
m_v[3] = w;
}
//--------------------------------------------------------------------------------------------------
/// Check if two vectors are equal. An exact match is required.
//--------------------------------------------------------------------------------------------------
template<typename S>
inline bool Vector4<S>::operator==(const Vector4& rhs) const
{
return (m_v[0] == rhs.m_v[0]) && (m_v[1] == rhs.m_v[1]) && (m_v[2] == rhs.m_v[2]) && (m_v[3] == rhs.m_v[3]);
}
//--------------------------------------------------------------------------------------------------
/// Check if two vectors are different. Returns true if not an exact match
//--------------------------------------------------------------------------------------------------
template<typename S>
inline bool Vector4<S>::operator!=(const Vector4& rhs) const
{
return !operator==(rhs);
}
//--------------------------------------------------------------------------------------------------
/// Returns the sum of this vector and the rhs vector
//--------------------------------------------------------------------------------------------------
template<typename S>
inline const Vector4<S> Vector4<S>::operator+(const Vector4& rhs) const
{
return Vector4(m_v[0] + rhs.m_v[0], m_v[1] + rhs.m_v[1], m_v[2] + rhs.m_v[2], m_v[3] + rhs.m_v[3]);
}
//--------------------------------------------------------------------------------------------------
/// Compute this-rhs and return the result.
//--------------------------------------------------------------------------------------------------
template<typename S>
inline const Vector4<S> Vector4<S>::operator-(const Vector4& rhs) const
{
return Vector4(m_v[0] - rhs.m_v[0], m_v[1] - rhs.m_v[1], m_v[2] - rhs.m_v[2], m_v[3] - rhs.m_v[3]);
}
//--------------------------------------------------------------------------------------------------
/// Return this vector scaled by the given scalar
//--------------------------------------------------------------------------------------------------
template<typename S>
const Vector4<S> Vector4<S>::operator*(S scalar) const
{
return Vector4(m_v[0]*scalar, m_v[1]*scalar, m_v[2]*scalar, m_v[3]*scalar);
}
//--------------------------------------------------------------------------------------------------
/// Return a vector where each component is the corresponding component in this divided by scalar
//--------------------------------------------------------------------------------------------------
template<typename S>
const Vector4<S> Vector4<S>::operator/(S scalar) const
{
return Vector4(m_v[0]/scalar, m_v[1]/scalar, m_v[2]/scalar, m_v[3]/scalar);
}
//--------------------------------------------------------------------------------------------------
/// Return a vector which is the negation of this
//--------------------------------------------------------------------------------------------------
template<typename S>
const Vector4<S> Vector4<S>::operator-() const
{
return Vector4(-m_v[0], -m_v[1], -m_v[2], -m_v[3]);
}
//--------------------------------------------------------------------------------------------------
/// Add the given vector to this
//--------------------------------------------------------------------------------------------------
template<typename S>
inline Vector4<S>& Vector4<S>::operator+=(const Vector4& v)
{
m_v[0] += v.x();
m_v[1] += v.y();
m_v[2] += v.z();
m_v[3] += v.w();
return *this;
}
//--------------------------------------------------------------------------------------------------
/// Subtract the given vector from this
//--------------------------------------------------------------------------------------------------
template<typename S>
inline Vector4<S>& Vector4<S>::operator-=(const Vector4& v)
{
m_v[0] -= v.x();
m_v[1] -= v.y();
m_v[2] -= v.z();
m_v[3] -= v.w();
return *this;
}
//--------------------------------------------------------------------------------------------------
/// Scale this with the given scalar. Each component is multiplied with the given value
//--------------------------------------------------------------------------------------------------
template<typename S>
inline Vector4<S>& Vector4<S>::operator*=(S scalar)
{
m_v[0] *= scalar;
m_v[1] *= scalar;
m_v[2] *= scalar;
m_v[3] *= scalar;
return *this;
}
//--------------------------------------------------------------------------------------------------
/// Divide this with the given scalar. Each component is divided by the given scalar
//--------------------------------------------------------------------------------------------------
template<typename S>
inline Vector4<S>& Vector4<S>::operator/=(S scalar)
{
m_v[0] /= scalar;
m_v[1] /= scalar;
m_v[2] /= scalar;
m_v[3] /= scalar;
return *this;
}
//--------------------------------------------------------------------------------------------------
/// Get component 0,1,2,3. E.g. x = v[0];
//--------------------------------------------------------------------------------------------------
template<typename S>
inline const S& Vector4<S>::operator[](int index) const
{
CVF_TIGHT_ASSERT(index >= 0);
CVF_TIGHT_ASSERT(index < 4);
return m_v[index];
}
//--------------------------------------------------------------------------------------------------
/// Set component 0,1,2,3. E.g. v[0] = x;
//--------------------------------------------------------------------------------------------------
template<typename S>
inline S& Vector4<S>::operator[](int index)
{
CVF_TIGHT_ASSERT(index >= 0);
CVF_TIGHT_ASSERT(index < 4);
return m_v[index];
}
//--------------------------------------------------------------------------------------------------
/// Compute the dot product of this and rhs and return the result (scalar)
///
/// Formula:
/// \code
/// S = tx*rx + ty*ry + tz*rz + tw*rw
/// \endcode
//--------------------------------------------------------------------------------------------------
template<typename S>
inline S Vector4<S>::operator*(const Vector4& rhs) const
{
return m_v[0]*rhs.m_v[0] + m_v[1]*rhs.m_v[1] + m_v[2]*rhs.m_v[2] + m_v[3]*rhs.m_v[3];
}
//--------------------------------------------------------------------------------------------------
/// Set the vector from the other vector (of different type). Cast each component to convert it.
//--------------------------------------------------------------------------------------------------
template<typename S>
template<typename T>
void Vector4<S>::set(const T& other)
{
m_v[0] = static_cast<S>(other.x());
m_v[1] = static_cast<S>(other.y());
m_v[2] = static_cast<S>(other.z());
m_v[3] = static_cast<S>(other.w());
}
//--------------------------------------------------------------------------------------------------
/// Get the length of the vector
///
/// Formula:
/// \code
/// len = sqrt(x*x + y*y + z*z)
/// \endcode
//--------------------------------------------------------------------------------------------------
template<typename S>
inline S Vector4<S>::length() const
{
return Math::sqrt(m_v[0]*m_v[0] + m_v[1]*m_v[1] + m_v[2]*m_v[2] + m_v[3]*m_v[3]);
}
//--------------------------------------------------------------------------------------------------
/// Get the squared length (L2) of the vector
///
/// Formula:
/// \code
/// len = x*x + y*y + z*z
/// \endcode
//--------------------------------------------------------------------------------------------------
template<typename S>
inline S Vector4<S>::lengthSquared() const
{
return m_v[0]*m_v[0] + m_v[1]*m_v[1] + m_v[2]*m_v[2] + m_v[3]*m_v[3];
}
//--------------------------------------------------------------------------------------------------
/// Set the length of the vector to \a newLength.
///
/// \sa Vector3::setLength()
//--------------------------------------------------------------------------------------------------
template<typename S>
bool Vector4<S>::setLength(S newLength)
{
CVF_ASSERT(newLength >= 0);
S currLen = length();
if (currLen > std::numeric_limits<S>::epsilon() && newLength > 0)
{
S scale = newLength/currLen;
m_v[0] *= scale;
m_v[1] *= scale;
m_v[2] *= scale;
m_v[3] *= scale;
return true;
}
else
{
setZero();
return (newLength == 0) ? true : false;
}
}
//--------------------------------------------------------------------------------------------------
/// Normalize the vector (make sure the length is 1.0).
/// Returns true if normalization was possible. Returns false if length is zero or a NaN vector.
//--------------------------------------------------------------------------------------------------
template<typename S>
bool Vector4<S>::normalize()
{
S len = length();
if (len > 0.0)
{
// Precompute 1/length and do multiplication instead of division
S oneOverLen = (static_cast<S>(1.0)/len);
m_v[0] *= oneOverLen;
m_v[1] *= oneOverLen;
m_v[2] *= oneOverLen;
m_v[3] *= oneOverLen;
return true;
}
else
{
// Might be NaN, so set it to zero
m_v[0] = 0.0f;
m_v[1] = 0.0f;
m_v[2] = 0.0f;
m_v[3] = 0.0f;
return false;
}
}
//--------------------------------------------------------------------------------------------------
/// Returns a normalized version of the current vector. The vector is unchanged.
//--------------------------------------------------------------------------------------------------
template<typename S>
Vector4<S> Vector4<S>::normalized(bool* normalizationOK) const
{
S len = length();
if (len > 0.0)
{
if (normalizationOK) *normalizationOK = true;
S oneOverLen = (static_cast<S>(1.0)/len);
return Vector4<S>(m_v[0]*oneOverLen, m_v[1]*oneOverLen, m_v[2]*oneOverLen, m_v[3]*oneOverLen);
}
else
{
if (normalizationOK) *normalizationOK = false;
return Vector4<S>::ZERO;
}
}
//--------------------------------------------------------------------------------------------------
/// Set all components to 0
//--------------------------------------------------------------------------------------------------
template<typename S>
inline void Vector4<S>::setZero()
{
m_v[0] = 0;
m_v[1] = 0;
m_v[2] = 0;
m_v[3] = 0;
}
//--------------------------------------------------------------------------------------------------
/// Check if all components are zero (exact match)
//--------------------------------------------------------------------------------------------------
template<typename S>
inline bool Vector4<S>::isZero() const
{
return (m_v[0] == 0) && (m_v[1] == 0) && (m_v[2] == 0) && (m_v[2] == 0);
}
//--------------------------------------------------------------------------------------------------
/// Set the components of the vector
//--------------------------------------------------------------------------------------------------
template<typename S>
inline void Vector4<S>::set(S x, S y, S z, S w)
{
m_v[0] = x;
m_v[1] = y;
m_v[2] = z;
m_v[3] = w;
}
} // namespace cvf
+27
View File
@@ -0,0 +1,27 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library 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 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
#define CVF_MAJOR_VERSION "0" // Major version number
#define CVF_MINOR_VERSION "1" // Minor version number
#define CVF_SPECIAL_BUILD "" // Special build description
#define CVF_BUILD_NUMBER "2" // Build number. Increase for each shipment