Work on error handling. I replaced some asserts with exceptions and also added basic error handling documentation.
This commit is contained in:
		| @@ -298,7 +298,7 @@ namespace PolyVox | ||||
| 			hVal = SixConnectedCost(a, b); | ||||
| 			break; | ||||
| 		default: | ||||
| 			POLYVOX_ASSERT(false, "Invalid case"); | ||||
| 			POLYVOX_THROW(std::invalid_argument, "Connectivity parameter has an unrecognised value."); | ||||
| 		} | ||||
|  | ||||
| 		//Sanity checks in debug mode. These can come out eventually, but I | ||||
|   | ||||
| @@ -34,15 +34,24 @@ namespace PolyVox | ||||
| 	template<typename VolumeType, typename IsVoxelTransparentCallback> | ||||
| 	void calculateAmbientOcclusion(VolumeType* volInput, Array<3, uint8_t>* arrayResult, Region region, float fRayLength, uint8_t uNoOfSamplesPerOutputElement, IsVoxelTransparentCallback isVoxelTransparentCallback) | ||||
| 	{ | ||||
| 		//Make sure that the size of the volume is an exact multiple of the size of the array. | ||||
| 		if(volInput->getWidth() % arrayResult->getDimension(0) != 0) | ||||
| 		{ | ||||
| 			POLYVOX_THROW(std::invalid_argument, "Volume width must be an exact multiple of array width."); | ||||
| 		} | ||||
| 		if(volInput->getHeight() % arrayResult->getDimension(1) != 0) | ||||
| 		{ | ||||
| 			POLYVOX_THROW(std::invalid_argument, "Volume width must be an exact multiple of array height."); | ||||
| 		} | ||||
| 		if(volInput->getDepth() % arrayResult->getDimension(2) != 0) | ||||
| 		{ | ||||
| 			POLYVOX_THROW(std::invalid_argument, "Volume width must be an exact multiple of array depth."); | ||||
| 		} | ||||
|  | ||||
| 		uint16_t uRandomUnitVectorIndex = 0; | ||||
| 		uint16_t uRandomVectorIndex = 0; | ||||
| 		uint16_t uIndexIncreament; | ||||
|  | ||||
| 		//Make sure that the size of the volume is an exact multiple of the size of the array. | ||||
| 		POLYVOX_ASSERT(volInput->getWidth() % arrayResult->getDimension(0) == 0, "Volume width must be an exact multiple of array width."); | ||||
| 		POLYVOX_ASSERT(volInput->getHeight() % arrayResult->getDimension(1) == 0, "Volume height must be an exact multiple of array height."); | ||||
| 		POLYVOX_ASSERT(volInput->getDepth() % arrayResult->getDimension(2) == 0, "Volume depth must be an exact multiple of array depth."); | ||||
|  | ||||
| 		//Our initial indices. It doesn't matter exactly what we set here, but the code below makes  | ||||
| 		//sure they are different for different regions which helps reduce tiling patterns in the results. | ||||
| 		uRandomUnitVectorIndex += region.getLowerX() + region.getLowerY() + region.getLowerZ(); | ||||
|   | ||||
| @@ -73,7 +73,11 @@ namespace PolyVox | ||||
| 	template <uint32_t noOfDims, typename ElementType> | ||||
| 	SubArray<noOfDims-1, ElementType> Array<noOfDims, ElementType>::operator[](uint32_t uIndex) | ||||
| 	{ | ||||
| 		POLYVOX_ASSERT(uIndex < m_pDimensions[0], "Index out of range"); | ||||
| 		if(uIndex >= m_pDimensions[0]) | ||||
| 		{ | ||||
| 			POLYVOX_THROW(std::out_of_range, "Array index out of range"); | ||||
| 		} | ||||
|  | ||||
| 		return | ||||
| 			SubArray<noOfDims-1, ElementType>(&m_pElements[uIndex*m_pOffsets[0]], | ||||
| 			m_pDimensions+1, m_pOffsets+1); | ||||
| @@ -91,7 +95,11 @@ namespace PolyVox | ||||
| 	template <uint32_t noOfDims, typename ElementType> | ||||
| 	const SubArray<noOfDims-1, ElementType> Array<noOfDims, ElementType>::operator[](uint32_t uIndex) const | ||||
| 	{ | ||||
| 		POLYVOX_ASSERT(uIndex < m_pDimensions[0], "Index out of range"); | ||||
| 		if(uIndex >= m_pDimensions[0]) | ||||
| 		{ | ||||
| 			POLYVOX_THROW(std::out_of_range, "Array index out of range"); | ||||
| 		} | ||||
|  | ||||
| 		return | ||||
| 			SubArray<noOfDims-1, ElementType>(&m_pElements[uIndex*m_pOffsets[0]], | ||||
| 			m_pDimensions+1, m_pOffsets+1); | ||||
| @@ -139,7 +147,10 @@ namespace PolyVox | ||||
| 		m_uNoOfElements = 1; | ||||
| 		for (uint32_t i = 0; i<noOfDims; i++) | ||||
| 		{ | ||||
| 			POLYVOX_ASSERT(pDimensions[i] != 0, "Invalid dimension"); | ||||
| 			if(pDimensions[i] == 0) | ||||
| 			{ | ||||
| 				POLYVOX_THROW(std::out_of_range, "Invalid array dimension"); | ||||
| 			} | ||||
|  | ||||
| 			m_uNoOfElements *= pDimensions[i]; | ||||
| 			m_pDimensions[i] = pDimensions[i]; | ||||
| @@ -186,7 +197,11 @@ namespace PolyVox | ||||
| 	template <uint32_t noOfDims, typename ElementType> | ||||
| 	uint32_t Array<noOfDims, ElementType>::getDimension(uint32_t uDimension) | ||||
| 	{ | ||||
| 		POLYVOX_ASSERT(uDimension < noOfDims, "Dimension out of range"); | ||||
| 		if(uDimension >= noOfDims) | ||||
| 		{ | ||||
| 			POLYVOX_THROW(std::out_of_range, "Array dimension out of range"); | ||||
| 		} | ||||
|  | ||||
| 		return m_pDimensions[uDimension]; | ||||
| 	} | ||||
|  | ||||
| @@ -198,14 +213,14 @@ namespace PolyVox | ||||
| 		,m_uNoOfElements(0) | ||||
| 	{ | ||||
| 		//Not implemented | ||||
| 		POLYVOX_ASSERT(false, "Not implemented."); | ||||
| 		POLYVOX_THROW(not_implemented, "This function is not implemented and should never be called!"); | ||||
| 	} | ||||
|  | ||||
| 	template <uint32_t noOfDims, typename ElementType> | ||||
| 	Array<noOfDims, ElementType>& Array<noOfDims, ElementType>::operator=(const Array<noOfDims, ElementType>& rhs) | ||||
| 	{ | ||||
| 		//Not implemented | ||||
| 		POLYVOX_ASSERT(false, "Not implemented."); | ||||
| 		POLYVOX_THROW(not_implemented, "This function is not implemented and should never be called!"); | ||||
|  | ||||
| 		return *this; | ||||
| 	} | ||||
| @@ -251,14 +266,22 @@ namespace PolyVox | ||||
| 	template <typename ElementType> | ||||
| 	ElementType& Array<1, ElementType>::operator[] (uint32_t uIndex) | ||||
| 	{ | ||||
| 		POLYVOX_ASSERT(uIndex < m_pDimensions[0], "Index out of range"); | ||||
| 		if(uIndex >= m_pDimensions[0]) | ||||
| 		{ | ||||
| 			POLYVOX_THROW(std::out_of_range, "Array index out of range"); | ||||
| 		} | ||||
|  | ||||
| 		return m_pElements[uIndex]; | ||||
| 	} | ||||
|  | ||||
| 	template <typename ElementType> | ||||
| 	const ElementType& Array<1, ElementType>::operator[] (uint32_t uIndex) const | ||||
| 	{ | ||||
| 		POLYVOX_ASSERT(uIndex < m_pDimensions[0], "Index out of range"); | ||||
| 		if(uIndex >= m_pDimensions[0]) | ||||
| 		{ | ||||
| 			POLYVOX_THROW(std::out_of_range, "Array index out of range"); | ||||
| 		} | ||||
|  | ||||
| 		return m_pElements[uIndex]; | ||||
| 	} | ||||
|  | ||||
| @@ -307,14 +330,14 @@ namespace PolyVox | ||||
| 		,m_pDimensions(0) | ||||
| 	{ | ||||
| 		//Not implemented | ||||
| 		POLYVOX_ASSERT(false, "Not implemented."); | ||||
| 		POLYVOX_THROW(not_implemented, "This function is not implemented and should never be called!"); | ||||
| 	} | ||||
|  | ||||
| 	template <typename ElementType> | ||||
| 	Array<1, ElementType>& Array<1, ElementType>::operator=(const Array<1, ElementType>& rhs) | ||||
| 	{ | ||||
| 		//Not implemented | ||||
| 		POLYVOX_ASSERT(false, "Not implemented."); | ||||
| 		POLYVOX_THROW(not_implemented, "This function is not implemented and should never be called!"); | ||||
|  | ||||
| 		return *this; | ||||
| 	} | ||||
|   | ||||
| @@ -45,7 +45,7 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	BaseVolume<VoxelType>::BaseVolume(const BaseVolume<VoxelType>& /*rhs*/) | ||||
| 	{ | ||||
| 		POLYVOX_ASSERT(false, "Copy constructor not implemented."); // See function comment above. | ||||
| 		POLYVOX_THROW(not_implemented, "Volume copy constructor not implemented for performance reasons."); | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| @@ -59,14 +59,14 @@ namespace PolyVox | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	/// This function should never be called. Copying volumes by value would be expensive, and we want to prevent users from doing | ||||
| 	/// it by accident (such as when passing them as paramenters to functions). That said, there are times when you really do want to | ||||
| 	/// make a copy of a volume and in this case you should look at the Volumeresampler. | ||||
| 	/// make a copy of a volume and in this case you should look at the VolumeResampler. | ||||
| 	/// | ||||
| 	/// \sa VolumeResampler | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	template <typename VoxelType> | ||||
| 	BaseVolume<VoxelType>& BaseVolume<VoxelType>::operator=(const BaseVolume<VoxelType>& /*rhs*/) | ||||
| 	{ | ||||
| 		POLYVOX_ASSERT(false, "Assignment operator not implemented."); // See function comment above. | ||||
| 		POLYVOX_THROW(not_implemented, "Volume assignment operator not implemented for performance reasons."); | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| @@ -162,7 +162,7 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType BaseVolume<VoxelType>::getVoxel(int32_t /*uXPos*/, int32_t /*uYPos*/, int32_t /*uZPos*/) const | ||||
| 	{ | ||||
| 		POLYVOX_ASSERT(false, "You should never call the base class version of this function."); | ||||
| 		POLYVOX_THROW(not_implemented, "You should never call the base class version of this function."); | ||||
| 		return VoxelType(); | ||||
| 	} | ||||
|  | ||||
| @@ -173,7 +173,7 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType BaseVolume<VoxelType>::getVoxel(const Vector3DInt32& /*v3dPos*/) const | ||||
| 	{ | ||||
| 		POLYVOX_ASSERT(false, "You should never call the base class version of this function."); | ||||
| 		POLYVOX_THROW(not_implemented, "You should never call the base class version of this function."); | ||||
| 		return VoxelType(); | ||||
| 	} | ||||
|  | ||||
| @@ -186,7 +186,7 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType BaseVolume<VoxelType>::getVoxelAt(int32_t /*uXPos*/, int32_t /*uYPos*/, int32_t /*uZPos*/) const | ||||
| 	{ | ||||
| 		POLYVOX_ASSERT(false, "You should never call the base class version of this function."); | ||||
| 		POLYVOX_THROW(not_implemented, "You should never call the base class version of this function."); | ||||
| 		return VoxelType(); | ||||
| 	} | ||||
|  | ||||
| @@ -197,7 +197,7 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType BaseVolume<VoxelType>::getVoxelAt(const Vector3DInt32& /*v3dPos*/) const | ||||
| 	{ | ||||
| 		POLYVOX_ASSERT(false, "You should never call the base class version of this function."); | ||||
| 		POLYVOX_THROW(not_implemented, "You should never call the base class version of this function."); | ||||
| 		return VoxelType(); | ||||
| 	} | ||||
|  | ||||
| @@ -210,7 +210,7 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType BaseVolume<VoxelType>::getVoxelWithWrapping(int32_t /*uXPos*/, int32_t /*uYPos*/, int32_t /*uZPos*/, WrapMode /*eWrapMode*/, VoxelType /*tBorder*/) const | ||||
| 	{ | ||||
| 		POLYVOX_ASSERT(false, "You should never call the base class version of this function."); | ||||
| 		POLYVOX_THROW(not_implemented, "You should never call the base class version of this function."); | ||||
| 		return VoxelType(); | ||||
| 	} | ||||
|  | ||||
| @@ -221,7 +221,7 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType BaseVolume<VoxelType>::getVoxelWithWrapping(const Vector3DInt32& /*v3dPos*/, WrapMode /*eWrapMode*/, VoxelType /*tBorder*/) const | ||||
| 	{ | ||||
| 		POLYVOX_ASSERT(false, "You should never call the base class version of this function."); | ||||
| 		POLYVOX_THROW(not_implemented, "You should never call the base class version of this function."); | ||||
| 		return VoxelType(); | ||||
| 	} | ||||
|  | ||||
| @@ -244,7 +244,7 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	bool BaseVolume<VoxelType>::setVoxelAt(int32_t /*uXPos*/, int32_t /*uYPos*/, int32_t /*uZPos*/, VoxelType /*tValue*/) | ||||
| 	{ | ||||
| 		POLYVOX_ASSERT(false, "You should never call the base class version of this function."); | ||||
| 		POLYVOX_THROW(not_implemented, "You should never call the base class version of this function."); | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| @@ -256,7 +256,7 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	bool BaseVolume<VoxelType>::setVoxelAt(const Vector3DInt32& /*v3dPos*/, VoxelType /*tValue*/) | ||||
| 	{ | ||||
| 		POLYVOX_ASSERT(false, "You should never call the base class version of this function."); | ||||
| 		POLYVOX_THROW(not_implemented, "You should never call the base class version of this function."); | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
|   | ||||
| @@ -375,7 +375,7 @@ namespace PolyVox | ||||
| 				default: | ||||
| 				{ | ||||
| 					//Should never happen | ||||
| 					POLYVOX_ASSERT(false, "Invalid case."); | ||||
| 					POLYVOX_THROW(std::invalid_argument, "Wrap mode parameter has an unrecognised value."); | ||||
| 					return VoxelType(); | ||||
| 				} | ||||
| 			} | ||||
|   | ||||
| @@ -37,24 +37,28 @@ namespace PolyVox | ||||
| 	public: | ||||
| 		VoxelType getVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos) const | ||||
| 		{ | ||||
| 			// PolyVox does not throw an exception when a voxel is out of range. Please see 'Error Handling' in the User Manual. | ||||
| 			POLYVOX_ASSERT(m_regValid.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)), "Position is outside valid region"); | ||||
| 			return m_pVolume.getVoxelAt(uXPos, uYPos, uZPos); | ||||
| 		} | ||||
|  | ||||
| 		VoxelType getVoxelAt(const Vector3DInt32& v3dPos) const | ||||
| 		{ | ||||
| 			// PolyVox does not throw an exception when a voxel is out of range. Please see 'Error Handling' in the User Manual. | ||||
| 			POLYVOX_ASSERT(m_regValid.containsPoint(v3dPos), "Position is outside valid region"); | ||||
| 			return getVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ()); | ||||
| 		} | ||||
|  | ||||
| 		void setVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue) const | ||||
| 		{ | ||||
| 			// PolyVox does not throw an exception when a voxel is out of range. Please see 'Error Handling' in the User Manual. | ||||
| 			POLYVOX_ASSERT(m_regValid.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)), "Position is outside valid region"); | ||||
| 			m_pVolume.setVoxelAtConst(uXPos, uYPos, uZPos, tValue); | ||||
| 		} | ||||
|  | ||||
| 		void setVoxelAt(const Vector3DInt32& v3dPos, VoxelType tValue) const | ||||
| 		{ | ||||
| 			// PolyVox does not throw an exception when a voxel is out of range. Please see 'Error Handling' in the User Manual. | ||||
| 			POLYVOX_ASSERT(m_regValid.containsPoint(v3dPos), "Position is outside valid region"); | ||||
| 			setVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), tValue); | ||||
| 		} | ||||
|   | ||||
| @@ -220,9 +220,9 @@ namespace PolyVox | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		// If we exit the loop here then apparently all the slots were full but none of them matched. I don't think | ||||
| 		// this can happen so let's put an assert to make sure. If you hit this assert then please report it to us! | ||||
| 		POLYVOX_ASSERT(false, "All slots full but no matches."); | ||||
| 		// If we exit the loop here then apparently all the slots were full but none of them matched. | ||||
| 		// This shouldn't ever happen, so if it does it is probably a bug in PolyVox. Please report it to us! | ||||
| 		POLYVOX_THROW(std::runtime_error, "All slots full but no matches during cubic surface extraction. This is probably a bug in PolyVox"); | ||||
| 		return -1; //Should never happen. | ||||
| 	} | ||||
|  | ||||
|   | ||||
| @@ -60,10 +60,10 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType Block<VoxelType>::getVoxelAt(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos) const | ||||
| 	{ | ||||
| 		// This is internal code not directly called by the user. For efficiency we assert rather than throwing. | ||||
| 		POLYVOX_ASSERT(uXPos < m_uSideLength, "Supplied position is outside of the block"); | ||||
| 		POLYVOX_ASSERT(uYPos < m_uSideLength, "Supplied position is outside of the block"); | ||||
| 		POLYVOX_ASSERT(uZPos < m_uSideLength, "Supplied position is outside of the block"); | ||||
|  | ||||
| 		POLYVOX_ASSERT(m_tUncompressedData, "No uncompressed data - block must be decompressed before accessing voxels."); | ||||
|  | ||||
| 		return m_tUncompressedData | ||||
| @@ -83,10 +83,10 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	void Block<VoxelType>::setVoxelAt(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos, VoxelType tValue) | ||||
| 	{ | ||||
| 		// This is internal code not directly called by the user. For efficiency we assert rather than throwing. | ||||
| 		POLYVOX_ASSERT(uXPos < m_uSideLength, "Supplied position is outside of the block"); | ||||
| 		POLYVOX_ASSERT(uYPos < m_uSideLength, "Supplied position is outside of the block"); | ||||
| 		POLYVOX_ASSERT(uZPos < m_uSideLength, "Supplied position is outside of the block"); | ||||
|  | ||||
| 		POLYVOX_ASSERT(m_tUncompressedData, "No uncompressed data - block must be decompressed before accessing voxels."); | ||||
|  | ||||
| 		m_tUncompressedData | ||||
| @@ -108,9 +108,6 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	void Block<VoxelType>::initialise(uint16_t uSideLength) | ||||
| 	{ | ||||
| 		//Debug mode validation | ||||
| 		POLYVOX_ASSERT(isPowerOf2(uSideLength), "Block side length must be a power of two."); | ||||
|  | ||||
| 		//Release mode validation | ||||
| 		if(!isPowerOf2(uSideLength)) | ||||
| 		{ | ||||
| @@ -141,8 +138,16 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	void Block<VoxelType>::compress(Compressor* pCompressor) | ||||
| 	{ | ||||
| 		POLYVOX_ASSERT(pCompressor, "Compressor is not valid"); | ||||
| 		POLYVOX_ASSERT(m_bIsCompressed == false, "Attempted to compress block which is already flagged as compressed."); | ||||
| 		if(m_bIsCompressed) | ||||
| 		{  | ||||
| 			POLYVOX_THROW(invalid_operation, "Attempted to compress block which is already flagged as compressed."); | ||||
| 		} | ||||
|  | ||||
| 		if(!pCompressor) | ||||
| 		{ | ||||
| 			POLYVOX_THROW(std::invalid_argument, "A valid compressor must be provided"); | ||||
| 		} | ||||
|  | ||||
| 		POLYVOX_ASSERT(m_tUncompressedData != 0, "No uncompressed data is present."); | ||||
|  | ||||
| 		//If the uncompressed data hasn't actually been | ||||
| @@ -212,8 +217,16 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	void Block<VoxelType>::uncompress(Compressor* pCompressor) | ||||
| 	{ | ||||
| 		POLYVOX_ASSERT(pCompressor, "Compressor is not valid"); | ||||
| 		POLYVOX_ASSERT(m_bIsCompressed == true, "Attempted to uncompress block which is not flagged as compressed."); | ||||
| 		if(!m_bIsCompressed) | ||||
| 		{ | ||||
| 			POLYVOX_THROW(invalid_operation, "Attempted to uncompress block which is not flagged as compressed."); | ||||
| 		} | ||||
|  | ||||
| 		if(!pCompressor) | ||||
| 		{ | ||||
| 			POLYVOX_THROW(std::invalid_argument, "A valid compressor must be provided"); | ||||
| 		} | ||||
|  | ||||
| 		POLYVOX_ASSERT(m_tUncompressedData == 0, "Uncompressed data already exists."); | ||||
|  | ||||
| 		m_tUncompressedData = new VoxelType[m_uSideLength * m_uSideLength * m_uSideLength]; | ||||
|   | ||||
| @@ -26,9 +26,10 @@ freely, subject to the following restrictions: | ||||
|  | ||||
| #include "PolyVoxCore/Impl/Config.h" | ||||
|  | ||||
| #include <cstdlib>  //For std::exit | ||||
| #include <iostream> //For std::cerr | ||||
| #include <cstdlib>  // For std::exit | ||||
| #include <iostream> // For std::cerr | ||||
| #include <stdexcept> | ||||
| #include <string.h> // Exception constuctors take strings. | ||||
|  | ||||
| #if defined(_MSC_VER) | ||||
| 	// In Visual Studio we can use this function to go into the debugger. | ||||
| @@ -148,4 +149,32 @@ freely, subject to the following restrictions: | ||||
| 		getThrowHandler()((except), __FILE__, __LINE__) | ||||
| #endif | ||||
|  | ||||
| namespace PolyVox | ||||
| { | ||||
| 	/// A general purpose exception to indicate that an operation cannot be peformed. | ||||
| 	class invalid_operation : public std::logic_error | ||||
| 	{ | ||||
| 	public: | ||||
| 	explicit invalid_operation(const std::string& message) | ||||
| 		: logic_error(message.c_str()) {} | ||||
|  | ||||
| 	explicit invalid_operation(const char *message) | ||||
| 		: logic_error(message) {} | ||||
| 	}; | ||||
|  | ||||
| 	/// Thrown to indicate that a function is deliberatly not implmented. For example, perhaps you called a function | ||||
| 	/// in a base class whereas you are supposed to use a derived class which implements the function, or perhaps the | ||||
| 	/// function is not defined for a particular template parameter. It may be that the function is required to | ||||
| 	/// compile sucessfully but it should not be called. | ||||
| 	class not_implemented : public std::logic_error | ||||
| 	{ | ||||
| 	public: | ||||
| 	explicit not_implemented(const std::string& message) | ||||
| 		: logic_error(message.c_str()) {} | ||||
|  | ||||
| 	explicit not_implemented(const char *message) | ||||
| 		: logic_error(message) {} | ||||
| 	}; | ||||
| } | ||||
|  | ||||
| #endif //__PolyVox_ErrorHandling_H__ | ||||
|   | ||||
| @@ -28,7 +28,11 @@ namespace PolyVox | ||||
| 	template <uint32_t noOfDims, typename ElementType> | ||||
| 	SubArray<noOfDims-1, ElementType> SubArray<noOfDims, ElementType>::operator[](uint32_t uIndex) | ||||
| 	{ | ||||
| 		POLYVOX_ASSERT(uIndex < m_pDimensions[0], "Index out of range"); | ||||
| 		if(uIndex >= m_pDimensions[0]) | ||||
| 		{ | ||||
| 			POLYVOX_THROW(std::out_of_range, "Array index out of range"); | ||||
| 		} | ||||
|  | ||||
| 		return | ||||
| 			SubArray<noOfDims-1, ElementType>(&m_pElements[uIndex*m_pOffsets[0]], | ||||
| 			m_pDimensions+1, m_pOffsets+1); | ||||
| @@ -37,7 +41,11 @@ namespace PolyVox | ||||
| 	template <uint32_t noOfDims, typename ElementType> | ||||
| 	const SubArray<noOfDims-1, ElementType> SubArray<noOfDims, ElementType>::operator[](uint32_t uIndex) const | ||||
| 	{ | ||||
| 		POLYVOX_ASSERT(uIndex < m_pDimensions[0], "Index out of range"); | ||||
| 		if(uIndex >= m_pDimensions[0]) | ||||
| 		{ | ||||
| 			POLYVOX_THROW(std::out_of_range, "Array index out of range"); | ||||
| 		} | ||||
|  | ||||
| 		return | ||||
| 			SubArray<noOfDims-1, ElementType>(&m_pElements[uIndex*m_pOffsets[0]], | ||||
| 			m_pDimensions+1, m_pOffsets+1); | ||||
| @@ -56,14 +64,22 @@ namespace PolyVox | ||||
| 	template <typename ElementType> | ||||
| 	ElementType& SubArray<1, ElementType>::operator[] (uint32_t uIndex) | ||||
| 	{ | ||||
| 		POLYVOX_ASSERT(uIndex < m_pDimensions[0], "Index out of range"); | ||||
| 		if(uIndex >= m_pDimensions[0]) | ||||
| 		{ | ||||
| 			POLYVOX_THROW(std::out_of_range, "Array index out of range"); | ||||
| 		} | ||||
|  | ||||
| 		return m_pElements[uIndex]; | ||||
| 	} | ||||
|  | ||||
| 	template <typename ElementType> | ||||
| 	const ElementType& SubArray<1, ElementType>::operator[] (uint32_t uIndex) const | ||||
| 	{ | ||||
| 		POLYVOX_ASSERT(uIndex < m_pDimensions[0], "Index out of range"); | ||||
| 		if(uIndex >= m_pDimensions[0]) | ||||
| 		{ | ||||
| 			POLYVOX_THROW(std::out_of_range, "Array index out of range"); | ||||
| 		} | ||||
|  | ||||
| 		return m_pElements[uIndex]; | ||||
| 	} | ||||
|  | ||||
|   | ||||
| @@ -31,6 +31,7 @@ namespace PolyVox | ||||
|         const Type& v0,const Type& v1, | ||||
|         const float x) | ||||
|     { | ||||
| 		//This function is called frequently and is very short, so assert rather than exceptions. | ||||
|         POLYVOX_ASSERT((x >= 0.0f) && (x <= 1.0f), "Interpolation input out of 0.0 to 1.0 range."); | ||||
|  | ||||
| 		//Interpolate along X | ||||
| @@ -44,6 +45,7 @@ namespace PolyVox | ||||
|         const Type& v00,const Type& v10,const Type& v01,const Type& v11, | ||||
|         const float x, const float y) | ||||
|     { | ||||
| 		//This function is called frequently and is very short, so assert rather than exceptions. | ||||
|         POLYVOX_ASSERT((x >= 0.0f) && (y >= 0.0f) &&  | ||||
|             (x <= 1.0f) && (y <= 1.0f), "Interpolation input out of 0.0 to 1.0 range."); | ||||
|  | ||||
| @@ -63,6 +65,7 @@ namespace PolyVox | ||||
|         const Type& v001,const Type& v101,const Type& v011,const Type& v111, | ||||
|         const float x, const float y, const float z) | ||||
|     { | ||||
| 		//This function is called frequently and is very short, so assert rather than exceptions. | ||||
|         POLYVOX_ASSERT((x >= 0.0f) && (y >= 0.0f) && (z >= 0.0f) &&  | ||||
|             (x <= 1.0f) && (y <= 1.0f) && (z <= 1.0f), "Interpolation input out of 0.0 to 1.0 range."); | ||||
|  | ||||
|   | ||||
| @@ -90,7 +90,7 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	LargeVolume<VoxelType>::LargeVolume(const LargeVolume<VoxelType>& /*rhs*/) | ||||
| 	{ | ||||
| 		POLYVOX_ASSERT(false, "Copy constructor not implemented."); // See function comment above. | ||||
| 		POLYVOX_THROW(not_implemented, "Volume copy constructor not implemented for performance reasons."); | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| @@ -112,7 +112,7 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	LargeVolume<VoxelType>& LargeVolume<VoxelType>::operator=(const LargeVolume<VoxelType>& /*rhs*/) | ||||
| 	{ | ||||
| 		POLYVOX_ASSERT(false, "Assignment operator not implemented."); // See function comment above. | ||||
| 		POLYVOX_THROW(not_implemented, "Volume assignment operator not implemented for performance reasons."); | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| @@ -124,6 +124,7 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType LargeVolume<VoxelType>::getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos) const | ||||
| 	{ | ||||
| 		// PolyVox does not throw an exception when a voxel is out of range. Please see 'Error Handling' in the User Manual. | ||||
| 		POLYVOX_ASSERT(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)), "Position is outside valid region"); | ||||
|  | ||||
| 		const int32_t blockX = uXPos >> m_uBlockSideLengthPower; | ||||
| @@ -228,7 +229,7 @@ namespace PolyVox | ||||
| 			default: | ||||
| 			{ | ||||
| 				//Should never happen | ||||
| 				POLYVOX_ASSERT(false, "Invlaid case."); | ||||
| 				POLYVOX_THROW(std::invalid_argument, "Wrap mode parameter has an unrecognised value."); | ||||
| 				return VoxelType(); | ||||
| 			} | ||||
| 		} | ||||
| @@ -282,6 +283,7 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	bool LargeVolume<VoxelType>::setVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue) | ||||
| 	{ | ||||
| 		// PolyVox does not throw an exception when a voxel is out of range. Please see 'Error Handling' in the User Manual. | ||||
| 		POLYVOX_ASSERT(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)), "Position is outside valid region"); | ||||
|  | ||||
| 		const int32_t blockX = uXPos >> m_uBlockSideLengthPower; | ||||
| @@ -445,13 +447,8 @@ namespace PolyVox | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	template <typename VoxelType> | ||||
| 	void LargeVolume<VoxelType>::initialise(const Region& regValidRegion, uint16_t uBlockSideLength) | ||||
| 	{ | ||||
| 		//Debug mode validation | ||||
| 		POLYVOX_ASSERT(uBlockSideLength > 0, "Block side length cannot be zero."); | ||||
| 		POLYVOX_ASSERT(isPowerOf2(uBlockSideLength), "Block side length must be a power of two."); | ||||
| 		POLYVOX_ASSERT(m_pCompressor, "You must provide a compressor for the LargeVolume to use."); | ||||
| 		 | ||||
| 		//Release mode validation | ||||
| 	{		 | ||||
| 		//Validate parameters | ||||
| 		if(uBlockSideLength == 0) | ||||
| 		{ | ||||
| 			POLYVOX_THROW(std::invalid_argument, "Block side length cannot be zero."); | ||||
|   | ||||
| @@ -143,7 +143,7 @@ namespace PolyVox | ||||
| 		}*/ | ||||
|  | ||||
| 		//Need to think what effect this has on any existing iterators. | ||||
| 		POLYVOX_ASSERT(false, "This function cnnot be used on LargeVolume samplers."); | ||||
| 		POLYVOX_THROW(not_implemented, "This function cannot be used on LargeVolume samplers."); | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
|   | ||||
| @@ -39,14 +39,15 @@ namespace PolyVox | ||||
| 		,m_uKernelSize(uKernelSize) | ||||
| 	{ | ||||
| 		//Kernel size must be at least three | ||||
| 		POLYVOX_ASSERT(m_uKernelSize >= 3, "Kernel size must be at least three"); | ||||
| 		m_uKernelSize = std::max(m_uKernelSize, static_cast<uint32_t>(3)); //For release builds | ||||
| 		if(m_uKernelSize < 3) | ||||
| 		{ | ||||
| 			POLYVOX_THROW(std::invalid_argument, "Kernel size must be at least three"); | ||||
| 		} | ||||
|  | ||||
| 		//Kernel size must be odd | ||||
| 		POLYVOX_ASSERT(m_uKernelSize % 2 == 1, "Kernel size must be odd"); | ||||
| 		if(m_uKernelSize % 2 == 0) //For release builds | ||||
| 		if(m_uKernelSize % 2 == 0) | ||||
| 		{ | ||||
| 			m_uKernelSize++; | ||||
| 			POLYVOX_THROW(std::invalid_argument, "Kernel size must be odd"); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
|   | ||||
| @@ -47,7 +47,7 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	RawVolume<VoxelType>::RawVolume(const RawVolume<VoxelType>& /*rhs*/) | ||||
| 	{ | ||||
| 		POLYVOX_ASSERT(false, "Copy constructor not implemented."); // See function comment above. | ||||
| 		POLYVOX_THROW(not_implemented, "Volume copy constructor not implemented for performance reasons."); | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| @@ -70,7 +70,7 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	RawVolume<VoxelType>& RawVolume<VoxelType>::operator=(const RawVolume<VoxelType>& /*rhs*/) | ||||
| 	{ | ||||
| 		POLYVOX_ASSERT(false, "Assignment operator not implemented."); // See function comment above. | ||||
| 		POLYVOX_THROW(not_implemented, "Volume assignment operator not implemented for performance reasons."); | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| @@ -82,6 +82,7 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType RawVolume<VoxelType>::getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos) const | ||||
| 	{ | ||||
| 		// PolyVox does not throw an exception when a voxel is out of range. Please see 'Error Handling' in the User Manual. | ||||
| 		POLYVOX_ASSERT(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)), "Position is outside valid region"); | ||||
|  | ||||
| 		const Vector3DInt32& v3dLowerCorner = this->m_regValidRegion.getLowerCorner(); | ||||
| @@ -186,7 +187,7 @@ namespace PolyVox | ||||
| 			default: | ||||
| 			{ | ||||
| 				//Should never happen | ||||
| 				POLYVOX_ASSERT(false, "Invalid case."); | ||||
| 				POLYVOX_THROW(std::invalid_argument, "Wrap mode parameter has an unrecognised value."); | ||||
| 				return VoxelType(); | ||||
| 			} | ||||
| 		} | ||||
| @@ -254,10 +255,18 @@ namespace PolyVox | ||||
| 	{ | ||||
| 		this->m_regValidRegion = regValidRegion; | ||||
|  | ||||
| 		//Ensure dimensions of the specified Region are valid | ||||
| 		POLYVOX_ASSERT(this->getWidth() > 0, "Volume width must be greater than zero."); | ||||
| 		POLYVOX_ASSERT(this->getHeight() > 0, "Volume width must be greater than zero."); | ||||
| 		POLYVOX_ASSERT(this->getDepth() > 0, "Volume width must be greater than zero."); | ||||
| 		if(this->getWidth() <= 0) | ||||
| 		{ | ||||
| 			POLYVOX_THROW(std::invalid_argument, "Volume width must be greater than zero."); | ||||
| 		} | ||||
| 		if(this->getHeight() <= 0) | ||||
| 		{ | ||||
| 			POLYVOX_THROW(std::invalid_argument, "Volume height must be greater than zero."); | ||||
| 		} | ||||
| 		if(this->getDepth() <= 0) | ||||
| 		{ | ||||
| 			POLYVOX_THROW(std::invalid_argument, "Volume depth must be greater than zero."); | ||||
| 		} | ||||
|  | ||||
| 		//Create the data | ||||
| 		m_pData = new VoxelType[this->getWidth() * this->getHeight()* this->getDepth()]; | ||||
|   | ||||
| @@ -48,7 +48,7 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	SimpleVolume<VoxelType>::SimpleVolume(const SimpleVolume<VoxelType>& /*rhs*/) | ||||
| 	{ | ||||
| 		POLYVOX_ASSERT(false, "Copy constructor not implemented."); // See function comment above. | ||||
| 		POLYVOX_THROW(not_implemented, "Volume copy constructor not implemented for performance reasons."); | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| @@ -70,7 +70,7 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	SimpleVolume<VoxelType>& SimpleVolume<VoxelType>::operator=(const SimpleVolume<VoxelType>& /*rhs*/) | ||||
| 	{ | ||||
| 		POLYVOX_ASSERT(false, "Assignment operator not implemented."); // See function comment above. | ||||
| 		POLYVOX_THROW(not_implemented, "Volume assignment operator not implemented for performance reasons."); | ||||
| 	} | ||||
|  | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| @@ -82,6 +82,7 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType SimpleVolume<VoxelType>::getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos) const | ||||
| 	{ | ||||
| 		// PolyVox does not throw an exception when a voxel is out of range. Please see 'Error Handling' in the User Manual. | ||||
| 		POLYVOX_ASSERT(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)), "Position is outside valid region"); | ||||
|  | ||||
| 		const int32_t blockX = uXPos >> m_uBlockSideLengthPower; | ||||
| @@ -186,7 +187,7 @@ namespace PolyVox | ||||
| 			default: | ||||
| 			{ | ||||
| 				//Should never happen | ||||
| 				POLYVOX_ASSERT(false, "Invalid case."); | ||||
| 				POLYVOX_THROW(std::invalid_argument, "Wrap mode parameter has an unrecognised value."); | ||||
| 				return VoxelType(); | ||||
| 			} | ||||
| 		} | ||||
| @@ -212,6 +213,7 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	bool SimpleVolume<VoxelType>::setVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue) | ||||
| 	{ | ||||
| 		// PolyVox does not throw an exception when a voxel is out of range. Please see 'Error Handling' in the User Manual. | ||||
| 		POLYVOX_ASSERT(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)), "Position is outside valid region"); | ||||
|  | ||||
| 		const int32_t blockX = uXPos >> m_uBlockSideLengthPower; | ||||
| @@ -246,12 +248,7 @@ namespace PolyVox | ||||
| 	//////////////////////////////////////////////////////////////////////////////// | ||||
| 	template <typename VoxelType> | ||||
| 	void SimpleVolume<VoxelType>::initialise(const Region& regValidRegion, uint16_t uBlockSideLength) | ||||
| 	{ | ||||
| 		//Debug mode validation | ||||
| 		POLYVOX_ASSERT(uBlockSideLength >= 8, "Block side length should be at least 8"); | ||||
| 		POLYVOX_ASSERT(uBlockSideLength <= 256, "Block side length should not be more than 256"); | ||||
| 		POLYVOX_ASSERT(isPowerOf2(uBlockSideLength), "Block side length must be a power of two."); | ||||
| 		 | ||||
| 	{		 | ||||
| 		//Release mode validation | ||||
| 		if(uBlockSideLength < 8) | ||||
| 		{ | ||||
|   | ||||
| @@ -52,10 +52,10 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	VoxelType SimpleVolume<VoxelType>::Block::getVoxelAt(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos) const | ||||
| 	{ | ||||
| 		// This is internal code not directly called by the user. For efficiency we assert rather than throwing. | ||||
| 		POLYVOX_ASSERT(uXPos < m_uSideLength, "Position is outside of the block."); | ||||
| 		POLYVOX_ASSERT(uYPos < m_uSideLength, "Position is outside of the block."); | ||||
| 		POLYVOX_ASSERT(uZPos < m_uSideLength, "Position is outside of the block."); | ||||
|  | ||||
| 		POLYVOX_ASSERT(m_tUncompressedData, "No uncompressed data available"); | ||||
|  | ||||
| 		return m_tUncompressedData | ||||
| @@ -75,10 +75,10 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	void SimpleVolume<VoxelType>::Block::setVoxelAt(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos, VoxelType tValue) | ||||
| 	{ | ||||
| 		// This is internal code not directly called by the user. For efficiency we assert rather than throwing. | ||||
| 		POLYVOX_ASSERT(uXPos < m_uSideLength, "Position is outside of the block."); | ||||
| 		POLYVOX_ASSERT(uYPos < m_uSideLength, "Position is outside of the block."); | ||||
| 		POLYVOX_ASSERT(uZPos < m_uSideLength, "Position is outside of the block."); | ||||
|  | ||||
| 		POLYVOX_ASSERT(m_tUncompressedData, "No uncompressed data available"); | ||||
|  | ||||
| 		m_tUncompressedData | ||||
| @@ -105,9 +105,6 @@ namespace PolyVox | ||||
| 	template <typename VoxelType> | ||||
| 	void SimpleVolume<VoxelType>::Block::initialise(uint16_t uSideLength) | ||||
| 	{ | ||||
| 		//Debug mode validation | ||||
| 		POLYVOX_ASSERT(isPowerOf2(uSideLength), "Block side length must be a power of two."); | ||||
|  | ||||
| 		//Release mode validation | ||||
| 		if(!isPowerOf2(uSideLength)) | ||||
| 		{ | ||||
|   | ||||
| @@ -414,7 +414,11 @@ namespace PolyVox | ||||
| 	template <uint32_t Size, typename StorageType, typename OperationType> | ||||
| 	inline StorageType Vector<Size, StorageType, OperationType>::getElement(uint32_t index) const | ||||
| 	{ | ||||
| 		POLYVOX_ASSERT(index < Size, "Attempted to access invalid vector element."); | ||||
| 		if(index >= Size) | ||||
| 		{ | ||||
| 			POLYVOX_THROW(std::out_of_range, "Attempted to access invalid vector element."); | ||||
| 		} | ||||
|  | ||||
| 		return m_tElements[index]; | ||||
| 	} | ||||
|  | ||||
| @@ -465,7 +469,11 @@ namespace PolyVox | ||||
| 	template <uint32_t Size, typename StorageType, typename OperationType> | ||||
| 	inline void Vector<Size, StorageType, OperationType>::setElement(uint32_t index, StorageType tValue) | ||||
| 	{ | ||||
| 		POLYVOX_ASSERT(index < Size, "Attempted to access invalid vector element."); | ||||
| 		if(index >= Size) | ||||
| 		{ | ||||
| 			POLYVOX_THROW(std::out_of_range, "Attempted to access invalid vector element."); | ||||
| 		} | ||||
|  | ||||
| 		m_tElements[index] = tValue; | ||||
| 	} | ||||
|  | ||||
| @@ -645,10 +653,17 @@ namespace PolyVox | ||||
| 	inline void Vector<Size, StorageType, OperationType>::normalise(void) | ||||
|     { | ||||
|         float fLength = this->length(); | ||||
| 		if(fLength <= 0.0) | ||||
| 		{ | ||||
| 			POLYVOX_THROW(invalid_operation, "Cannot normalise a vector with a length of zero"); | ||||
| 		} | ||||
|  | ||||
| 		for(uint32_t ct = 0; ct < Size; ++ct) | ||||
| 		{ | ||||
| 			// Standard float rules apply for divide-by-zero | ||||
| 			m_tElements[ct] /= fLength; | ||||
|  | ||||
| 			//This shouldn't happen as we had the length check earlier. So it's probably a bug if it does happen. | ||||
| 			POLYVOX_ASSERT(m_tElements[ct] == m_tElements[ct], "Obtained NAN during vector normalisation. Perhaps the input vector was too short?"); | ||||
| 		} | ||||
|     } | ||||
|   | ||||
| @@ -30,10 +30,6 @@ namespace PolyVox | ||||
| 	//If this is not the case then the output is undefined. | ||||
| 	uint8_t logBase2(uint32_t uInput) | ||||
| 	{ | ||||
| 		//Debug mode validation | ||||
| 		POLYVOX_ASSERT(uInput != 0, "Cannot compute the log of zero."); | ||||
| 		POLYVOX_ASSERT(isPowerOf2(uInput), "Input must be a power of two in order to compute the log."); | ||||
|  | ||||
| 		//Release mode validation | ||||
| 		if(uInput == 0) | ||||
| 		{ | ||||
|   | ||||
| @@ -78,7 +78,10 @@ namespace PolyVox | ||||
| 	 */ | ||||
| 	void Region::accumulate(const Region& reg) | ||||
| 	{ | ||||
| 		POLYVOX_ASSERT(reg.isValid(), "You cannot accumulate an invalid region."); //The result of accumulating an invalid region is not defined. | ||||
| 		if(!reg.isValid()) | ||||
| 		{ | ||||
| 			POLYVOX_THROW(invalid_operation, "You cannot accumulate an invalid region."); //The result of accumulating an invalid region is not defined. | ||||
| 		}  | ||||
|  | ||||
| 		m_iLowerX = ((std::min)(m_iLowerX, reg.getLowerX())); | ||||
| 		m_iLowerY = ((std::min)(m_iLowerY, reg.getLowerY())); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user