Last active
August 29, 2015 14:07
-
-
Save realazthat/4c2b913c08504fccdaef to your computer and use it in GitHub Desktop.
A cube/corner/face library for reasoning about cubes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Copyright (c) 2012 Azriel Fasten azriel.fasten@gmail.com | |
Permission is hereby granted, free of charge, to any person | |
obtaining a copy of this software and associated documentation | |
files (the "Software"), to deal in the Software without | |
restriction, including without limitation the rights to use, | |
copy, modify, merge, publish, distribute, sublicense, and/or sell | |
copies of the Software, and to permit persons to whom the | |
Software is furnished to do so, subject to the following | |
conditions: | |
The above copyright notice and this permission notice shall be | |
included in all copies or substantial portions of the Software. | |
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES | |
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | |
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | |
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
OTHER DEALINGS IN THE SOFTWARE. | |
*/ | |
#ifndef CUBE_CUBE_H | |
#define CUBE_CUBE_H | |
#include <bitset> | |
#include <boost/array.hpp> | |
#include <boost/integer.hpp> | |
#include <boost/foreach.hpp> | |
#include <boost/type_traits.hpp> | |
#include <boost/static_assert.hpp> | |
#include <boost/mpl/and.hpp> | |
#include <boost/mpl/logical.hpp> | |
#include <boost/utility/enable_if.hpp> | |
namespace cube{ | |
#ifndef CUBE_INLINE | |
#define CUBE_INLINE inline | |
#endif | |
struct face_t; | |
struct face_set_t; | |
struct direction_t; | |
struct direction_set_t; | |
struct corner_t; | |
struct corner_set_t; | |
struct edge_t; | |
struct edge_set_t; | |
struct box_t; | |
template<typename value_type, typename set_type> | |
struct const_element_set_iterator_t | |
: public boost::iterator_facade<const_element_set_iterator_t<value_type, set_type>, | |
value_type, | |
boost::forward_traversal_tag> | |
{ | |
private: | |
struct enabler {}; // a private type avoids misuse | |
public: | |
CUBE_INLINE | |
const_element_set_iterator_t() | |
: mset(NULL), mindex(value_type::SIZE) | |
{ | |
} | |
CUBE_INLINE | |
const_element_set_iterator_t(set_type& set, std::size_t index) | |
: mset(&set), mindex(index) | |
{ | |
BOOST_ASSERT(valid()); | |
} | |
CUBE_INLINE | |
const_element_set_iterator_t(set_type& set) | |
: mset(&set), mindex(0) | |
{ | |
BOOST_ASSERT(valid()); | |
while (mindex < value_type::SIZE) | |
{ | |
if (mset->contains(mindex)) | |
{ | |
break; | |
} | |
++mindex; | |
} | |
BOOST_ASSERT(valid()); | |
BOOST_ASSERT(dereferencable() || mindex == value_type::SIZE); | |
} | |
template <class OtherValue, class OtherSet> | |
CUBE_INLINE | |
const_element_set_iterator_t( | |
const_element_set_iterator_t<OtherValue, OtherSet> const& other | |
, typename boost::enable_if< | |
boost::mpl::and_< | |
boost::is_convertible<OtherValue*,value_type*>, | |
boost::is_convertible<OtherSet*,set_type*> | |
> | |
, enabler | |
>::type = enabler() | |
) | |
: mset(other.mset), mindex(other.mindex) | |
{ | |
BOOST_ASSERT(other.valid()); | |
BOOST_ASSERT(valid()); | |
} | |
template<typename T> | |
CUBE_INLINE | |
const_element_set_iterator_t& operator=(const T& other) | |
{ | |
assign(other); | |
return *this; | |
} | |
private: | |
friend class boost::iterator_core_access; | |
CUBE_INLINE | |
void increment() { | |
BOOST_ASSERT(valid()); | |
BOOST_ASSERT(valid()); | |
BOOST_ASSERT(mset); | |
BOOST_ASSERT(mindex != value_type::SIZE); | |
BOOST_ASSERT(mset->contains(mindex)); | |
BOOST_ASSERT(dereferencable()); | |
++mindex; | |
while (mindex < value_type::SIZE) | |
{ | |
if (dereferencable()) | |
break; | |
++mindex; | |
} | |
BOOST_ASSERT(valid()); | |
} | |
CUBE_INLINE | |
value_type& dereference() const { | |
BOOST_ASSERT(valid()); | |
BOOST_ASSERT(dereferencable()); | |
return value_type::get(mindex); | |
} | |
template <class OtherValue, class OtherSet> | |
CUBE_INLINE | |
bool equal(const_element_set_iterator_t<OtherValue, OtherSet> const& other) const | |
{ | |
return | |
///The two iterators are referring to the same set | |
(this->mset == other.mset | |
///Or one of them is a default constructed iterator | |
|| ( this->mset == NULL || other.mset == NULL )) | |
///And the indices are equal | |
&& this->mindex == other.mindex; | |
} | |
private: | |
CUBE_INLINE | |
bool valid() const{ | |
return mindex <= value_type::SIZE | |
///If not an end iterator, mset should be set, and mindex should be contained in it | |
&& (mindex == value_type::SIZE || ((mset) && mset->contains(mindex))); | |
} | |
CUBE_INLINE | |
bool dereferencable() const{ | |
return valid() && (mset) && mindex != value_type::SIZE && mset->contains(mindex); | |
} | |
template <class OtherValue, class OtherSet> | |
CUBE_INLINE | |
void | |
assign(const_element_set_iterator_t<OtherValue, OtherSet> const& other, | |
typename boost::enable_if< | |
boost::mpl::and_< | |
boost::is_convertible<OtherValue*,value_type*>, | |
boost::is_convertible<OtherSet*,set_type*> | |
> | |
, enabler | |
>::type = enabler() ) | |
{ | |
BOOST_ASSERT(other.valid()); | |
mset = other.mset; | |
mindex = other.mindex; | |
BOOST_ASSERT(valid()); | |
} | |
set_type* mset; | |
std::size_t mindex; | |
}; | |
template<typename derived_t, typename element_t, std::size_t N> | |
struct set_base_t | |
{ | |
typedef element_t value_type; | |
typedef value_type& reference; | |
typedef const value_type& const_reference; | |
typedef const_element_set_iterator_t<value_type const, derived_t const> const_iterator; | |
typedef const_iterator iterator; | |
const_iterator begin() const; | |
const_iterator end() const; | |
template<typename Sequence> | |
set_base_t(const Sequence& sequence); | |
set_base_t(const element_t& element); | |
set_base_t(const derived_t& set); | |
set_base_t(); | |
template<typename Sequence> | |
derived_t& operator=(const Sequence& sequence); | |
derived_t& operator=(const element_t& element); | |
derived_t& operator=(const derived_t& set); | |
template<typename Sequence> | |
derived_t& operator|=(const Sequence& sequence); | |
derived_t& operator|=(const derived_t& set); | |
derived_t& operator|=(const element_t& element); | |
template<typename Sequence> | |
derived_t operator|(const Sequence& sequence); | |
derived_t operator|(const derived_t& set); | |
derived_t operator|(const element_t& element); | |
bool contains(const element_t& element) const; | |
bool contains(const std::size_t& idx) const; | |
std::size_t size() const; | |
void clear(); | |
bool operator==(const derived_t& other) const; | |
private: | |
derived_t& self(); | |
const derived_t& self() const; | |
std::bitset<N> bits; | |
}; | |
struct corner_set_t : public set_base_t<corner_set_t, corner_t, 8> | |
{ | |
typedef corner_set_t self_t; | |
typedef set_base_t<corner_set_t, corner_t, 8> base_t; | |
template<typename T> | |
corner_set_t(const T& v); | |
corner_set_t(); | |
}; | |
struct face_set_t : public set_base_t<face_set_t, face_t, 6> | |
{ | |
typedef face_set_t self_t; | |
typedef set_base_t<face_set_t, face_t, 6> base_t; | |
template<typename T> | |
face_set_t(const T& v); | |
face_set_t(); | |
}; | |
struct direction_set_t : public set_base_t<direction_set_t, direction_t, 6> | |
{ | |
typedef direction_set_t self_t; | |
typedef set_base_t<direction_set_t, direction_t, 6> base_t; | |
template<typename T> | |
direction_set_t(const T& v); | |
direction_set_t(); | |
}; | |
struct direction_t | |
{ | |
const face_t& face() const; | |
const direction_t& opposite() const; | |
boost::array<direction_t, 4> adjacent() const; | |
static const direction_t& get(boost::int8_t x, boost::int8_t y, boost::int8_t z); | |
static const direction_t& get(const direction_t& direction); | |
static const boost::array<direction_t, 6>& all(); | |
boost::int8_t x() const; | |
boost::int8_t y() const; | |
boost::int8_t z() const; | |
bool positive() const; | |
boost::uint8_t index() const; | |
static const direction_t& index(boost::uint8_t idx); | |
bool operator<(const direction_t& other) const; | |
bool operator==(const direction_t& other) const; | |
bool operator!=(const direction_t& other) const; | |
bool valid() const; | |
static const std::size_t SIZE = 6; | |
protected: | |
#ifndef NDEBUG | |
int mx, my, mz; | |
boost::uint8_t mindex; | |
#endif | |
private: | |
std::bitset<3> bits; | |
///Default constructs an invalid direction with index >= @c SIZE | |
direction_t(); | |
direction_t(const std::bitset<3>& bits); | |
}; | |
struct face_t{ | |
const direction_t& direction() const; | |
const face_t& opposite() const; | |
boost::array<face_t, 4> adjacent() const; | |
boost::array<corner_t, 4> corners() const; | |
corner_set_t corner_set() const; | |
boost::array<edge_t, 4> edges() const; | |
static const boost::array<face_t, 6>& all(); | |
static const face_t& get(const direction_t& direction); | |
static const face_t& get(const boost::uint8_t& idx); | |
boost::uint8_t index() const; | |
static const direction_t& index(boost::uint8_t idx); | |
bool operator<(const face_t& other) const; | |
bool operator==(const face_t& other) const; | |
bool operator!=(const face_t& other) const; | |
static const std::size_t SIZE = 6; | |
protected: | |
direction_t mdirection; | |
private: | |
face_t(); | |
face_t(const direction_t& direction); | |
}; | |
/** | |
* Represents a corner of a cube. | |
* | |
*/ | |
struct corner_t{ | |
typedef direction_t direction_type; | |
typedef edge_t edge_type; | |
typedef face_t face_type; | |
/** | |
* Obtain an adjacent corner on the cube, by specifying a direction. | |
*/ | |
const corner_t& adjacent(const direction_t& direction) const; | |
/** | |
* Obtain all three adjacent corners on the cube. | |
*/ | |
boost::array<corner_t, 3> adjacent() const; | |
/** | |
* Obtain all three adjacent corners on the cube, as a @c corner_set_t. | |
*/ | |
corner_set_t adjacent_set() const; | |
/** | |
* Obtain all adjacent faces on the cube. | |
*/ | |
boost::array<face_t, 3> faces() const; | |
/** | |
* Obtain all adjacent faces on the cube, as a @c face_set_t. | |
*/ | |
face_set_t face_set() const; | |
/** | |
* Obtain all adjacent edges on the cube. | |
*/ | |
boost::array<edge_t, 3> edges() const; | |
/** | |
* Obtain an adjacent edge on the cube, by specifying a direction. | |
*/ | |
edge_t edge(const direction_t& direction); | |
/** | |
* Obtain the opposite corner on the cube. | |
*/ | |
const corner_t& opposite() const; | |
static const corner_t& get(boost::uint8_t i); | |
/** | |
* Obtain a corner on the cube by specifying x,y,z. | |
*/ | |
static const corner_t& get(bool x, bool y, bool z); | |
static const corner_t& get(const corner_t& corner); | |
/** | |
* Obtain a corner by its hash index in the range of [0,8). | |
* | |
* @see corner_t::index() | |
*/ | |
static const corner_t& index(boost::uint8_t idx); | |
/** | |
* Obtain a hash index of the corner in the range of [0,8). | |
*/ | |
boost::uint8_t index() const; | |
/** | |
* An arbitrary ordering, for use in an ordered container. | |
*/ | |
bool operator<(const corner_t& other) const; | |
bool operator==(const corner_t& other) const; | |
bool operator!=(const corner_t& other) const; | |
/** | |
* Obtain a container of all the corners on a cube. | |
*/ | |
static const boost::array<corner_t, 8>& all(); | |
/** | |
* Obtain the x coordinate of this corner. | |
*/ | |
bool x() const; | |
/** | |
* Obtain the y coordinate of this corner. | |
*/ | |
bool y() const; | |
/** | |
* Obtain the z coordinate of this corner. | |
*/ | |
bool z() const; | |
/** | |
* Obtain the x coordinate of this corner, as an integer. | |
* | |
* @see corner_t::x() | |
*/ | |
unsigned short int x_i() const; | |
/** | |
* Obtain the y coordinate of this corner, as an integer. | |
* | |
* @see corner_t::y() | |
*/ | |
unsigned short int y_i() const; | |
/** | |
* Obtain the z coordinate of this corner, as an integer. | |
* | |
* @see corner_t::z() | |
*/ | |
unsigned short int z_i() const; | |
///Number of corners | |
static const std::size_t SIZE = 8; | |
corner_t(); | |
protected: | |
#ifndef NDEBUG | |
bool mx, my, mz; | |
#endif | |
private: | |
corner_t(bool x, bool y, bool z); | |
corner_t(const std::bitset<3>& bits); | |
std::bitset<3> bits; | |
}; | |
struct edge_t{ | |
const boost::array<corner_t, 2>& corners() const; | |
boost::array<edge_t, 4> adjacent() const; | |
boost::array<face_t, 2> faces() const; | |
corner_set_t corner_set() const; | |
static const boost::array<edge_t, 12>& all(); | |
bool operator<(const edge_t& other) const; | |
private: | |
edge_t(const corner_t& a, const corner_t& b); | |
edge_t(); | |
boost::array<corner_t, 2> mcorners; | |
}; | |
struct box_t{ | |
boost::array<face_t, 6> faces() const; | |
const boost::array<corner_t, 8>& corners() const; | |
boost::array<edge_t, 12> edges() const; | |
boost::array<direction_t, 6> directions() const; | |
static const box_t& identity(); | |
private: | |
box_t(); | |
}; | |
} // namespace cube | |
#include <cube/cube.inl.hpp> | |
#endif // CUBE_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Copyright (c) 2012 Azriel Fasten azriel.fasten@gmail.com | |
Permission is hereby granted, free of charge, to any person | |
obtaining a copy of this software and associated documentation | |
files (the "Software"), to deal in the Software without | |
restriction, including without limitation the rights to use, | |
copy, modify, merge, publish, distribute, sublicense, and/or sell | |
copies of the Software, and to permit persons to whom the | |
Software is furnished to do so, subject to the following | |
conditions: | |
The above copyright notice and this permission notice shall be | |
included in all copies or substantial portions of the Software. | |
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES | |
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | |
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | |
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
OTHER DEALINGS IN THE SOFTWARE. | |
*/ | |
#include <cube/cube.hpp> | |
#include <cube/logic_utility.hpp> | |
#include <vector> | |
#include <boost/range/irange.hpp> | |
#include <boost/utility.hpp> | |
//################################################################### | |
//#### face_t | |
//################################################################### | |
namespace cube{ | |
CUBE_INLINE | |
face_t:: | |
face_t(const direction_t& direction) | |
: mdirection(direction) | |
{ | |
} | |
CUBE_INLINE | |
boost::uint8_t | |
face_t::index() const | |
{ | |
return mdirection.index(); | |
} | |
CUBE_INLINE | |
const boost::array< face_t, 6 >& | |
face_t::all() | |
{ | |
static const boost::array<face_t, 6> faces = | |
{{ | |
face_t(direction_t::index(0)), | |
face_t(direction_t::index(1)), | |
face_t(direction_t::index(2)), | |
face_t(direction_t::index(3)), | |
face_t(direction_t::index(4)), | |
face_t(direction_t::index(5)) | |
}}; | |
return faces; | |
} | |
CUBE_INLINE | |
const face_t& | |
face_t::get(const direction_t& direction) | |
{ | |
BOOST_ASSERT(direction.index() < all().size()); | |
return all()[direction.index()]; | |
} | |
CUBE_INLINE | |
const cube::face_t& | |
face_t::get(const boost::uint8_t& idx) | |
{ | |
BOOST_ASSERT(idx < all().size()); | |
return all()[idx]; | |
} | |
CUBE_INLINE | |
const direction_t& face_t::direction() const | |
{ | |
return mdirection; | |
} | |
CUBE_INLINE | |
const face_t& face_t::opposite() const | |
{ | |
return face_t::get(mdirection.opposite()); | |
} | |
CUBE_INLINE | |
boost::array<corner_t, 4> | |
face_t::corners() const | |
{ | |
/* | |
boost::array<boost::int8_t, 3> direction_components = | |
{{ | |
direction.x(), | |
direction.y(), | |
direction.z() | |
}}; | |
*/ | |
//bool positive_direction = direction.positive(); | |
std::bitset<3> direction_bits; | |
direction_bits.set(2, mdirection.x() != 0); | |
direction_bits.set(1, mdirection.y() != 0); | |
direction_bits.set(0, mdirection.z() != 0); | |
corner_set_t corner_set; | |
BOOST_FOREACH(const corner_t& corner, corner_t::all()) | |
{ | |
std::bitset<3> corner_bits; | |
corner_bits.set(2, corner.x() != 0); | |
corner_bits.set(1, corner.y() != 0); | |
corner_bits.set(0, corner.z() != 0); | |
corner_bits &= direction_bits; | |
if (corner_bits.any()) | |
{ | |
if (mdirection.positive()) | |
corner_set |= corner; | |
else | |
corner_set |= corner.opposite(); | |
} | |
} | |
BOOST_ASSERT(corner_set.size() == 4); | |
std::vector<corner_t> tmp; | |
BOOST_FOREACH(const corner_t& corner, corner_t::all()) | |
{ | |
if (corner_set.contains(corner)) | |
tmp.push_back(corner); | |
} | |
///FIXME: begin() end() broken | |
/* | |
corner_set_t::const_iterator w = corner_set.begin(); | |
corner_set_t::const_iterator wend = corner_set.end(); | |
for ( ; w != wend; ++w ) | |
{ | |
tmp.push_back(*w); | |
} | |
*/ | |
BOOST_ASSERT(tmp.size() == 4); | |
boost::array<corner_t, 4> result = | |
{{ | |
tmp[0], | |
tmp[1], | |
tmp[2], | |
tmp[3] | |
}}; | |
return result; | |
} | |
CUBE_INLINE | |
bool | |
face_t::operator==(const cube::face_t& other) const | |
{ | |
return mdirection == other.mdirection; | |
} | |
CUBE_INLINE | |
bool | |
face_t::operator!=(const cube::face_t& other) const | |
{ | |
return mdirection != other.mdirection; | |
} | |
CUBE_INLINE | |
bool | |
face_t::operator<(const cube::face_t& other) const | |
{ | |
return mdirection < other.mdirection; | |
} | |
//################################################################### | |
//################################################################### | |
//#### direction_t | |
//################################################################### | |
CUBE_INLINE | |
direction_t:: | |
direction_t() | |
: bits(BOOST_BINARY(111)) | |
{ | |
#ifndef NDEBUG | |
mx = x(); | |
my = y(); | |
mz = z(); | |
mindex = index(); | |
#endif | |
} | |
CUBE_INLINE | |
direction_t::direction_t(const std::bitset< 3 >& bits) | |
: bits(bits) | |
{ | |
#ifndef NDEBUG | |
mx = x(); | |
my = y(); | |
mz = z(); | |
mindex = index(); | |
#endif | |
} | |
CUBE_INLINE | |
const direction_t& | |
direction_t:: | |
get(boost::int8_t x, boost::int8_t y, boost::int8_t z) | |
{ | |
BOOST_ASSERT(lxor(lxor(x != 0, y != 0), z != 0)); | |
BOOST_ASSERT(std::abs(x) == 1 || x == 0); | |
BOOST_ASSERT(std::abs(y) == 1 || y == 0); | |
BOOST_ASSERT(std::abs(z) == 1 || z == 0); | |
/** | |
* [2 bit number][1 bit indicating "direction is positive"] | |
* | |
* [1 bit indicating "direction is positive"]: If the direction is positive, this bit is set to 1. | |
* | |
* [2 bit number]: A number calculated as follows: | |
* | |
* direction is in z: 00 | |
* direction is in y: 01 | |
* direction is in x: 10 | |
*/ | |
direction_t direction(std::bitset<3>(0)); | |
std::bitset<3>& bits = direction.bits; | |
if ( x != 0 ) | |
{ | |
bits.set(2); | |
} else if ( y != 0 ) { | |
bits.set(1); | |
} else if ( z != 0 ) { | |
} | |
if (x + y + z > 0) | |
{ | |
bits.set(0); | |
} | |
return direction_t::get( direction ); | |
} | |
CUBE_INLINE | |
const direction_t& | |
direction_t:: | |
get(const direction_t& direction) | |
{ | |
BOOST_ASSERT(direction.bits.to_ulong() < SIZE); | |
return all()[direction.bits.to_ulong()]; | |
} | |
CUBE_INLINE | |
const boost::array< direction_t, 6 >& | |
direction_t:: | |
all() | |
{ | |
static const boost::array<direction_t, 6> directions = | |
{{ | |
direction_t(std::bitset<3>(0)), | |
direction_t(std::bitset<3>(1)), | |
direction_t(std::bitset<3>(2)), | |
direction_t(std::bitset<3>(3)), | |
direction_t(std::bitset<3>(4)), | |
direction_t(std::bitset<3>(5)) | |
}}; | |
return directions; | |
} | |
CUBE_INLINE | |
boost::int8_t direction_t::x() const | |
{ | |
return (bits[0] ? 1 : -1) * (bits[2] && !bits[1] ? 1 : 0); | |
} | |
CUBE_INLINE | |
boost::int8_t direction_t::y() const | |
{ | |
return (bits[0] ? 1 : -1) * (!bits[2] && bits[1] ? 1 : 0); | |
} | |
CUBE_INLINE | |
boost::int8_t direction_t::z() const | |
{ | |
return (bits[0] ? 1 : -1) * (!bits[2] && !bits[1] ? 1 : 0); | |
} | |
CUBE_INLINE | |
boost::uint8_t direction_t::index() const | |
{ | |
return bits.to_ulong(); | |
} | |
CUBE_INLINE | |
const direction_t& | |
direction_t::index(boost::uint8_t idx) | |
{ | |
BOOST_ASSERT(idx < SIZE); | |
return all()[idx]; | |
} | |
CUBE_INLINE | |
bool direction_t:: | |
operator<(const direction_t& other) const | |
{ | |
return bits.to_ulong() < other.bits.to_ulong(); | |
} | |
CUBE_INLINE bool direction_t::operator==(const direction_t& other) const | |
{ | |
return bits == other.bits; | |
} | |
CUBE_INLINE bool direction_t::operator!=(const direction_t& other) const | |
{ | |
return bits != other.bits; | |
} | |
CUBE_INLINE | |
const face_t& direction_t::face() const | |
{ | |
return face_t::get(*this); | |
} | |
CUBE_INLINE | |
const direction_t& direction_t::opposite() const | |
{ | |
std::bitset<3> result_bits = bits; | |
result_bits.flip(0); | |
BOOST_ASSERT(result_bits.to_ulong() < SIZE); | |
return all()[ result_bits.to_ulong() ]; | |
} | |
CUBE_INLINE | |
bool direction_t::positive() const | |
{ | |
return bits.test(0); | |
} | |
CUBE_INLINE | |
boost::array<direction_t, 4> | |
direction_t::adjacent() const | |
{ | |
boost::array<direction_t, 4> result = {{ direction_t(), direction_t(), direction_t(), direction_t()}}; | |
std::size_t ri = 0; | |
BOOST_FOREACH(const direction_t& d, direction_t::all()) | |
{ | |
if (d != *this && d != opposite()) | |
{ | |
BOOST_ASSERT(ri < result.size()); | |
result[ri++] = d; | |
} | |
} | |
BOOST_ASSERT(ri == 4); | |
return result; | |
} | |
//################################################################### | |
//################################################################### | |
//#### Corners | |
//################################################################### | |
CUBE_INLINE | |
corner_t:: | |
corner_t() | |
{ | |
} | |
CUBE_INLINE | |
corner_t:: | |
corner_t(const std::bitset< 3 >& bits) | |
: bits(bits) | |
{ | |
#ifndef NDEBUG | |
mx = bits.test(0); | |
my = bits.test(1); | |
mz = bits.test(2); | |
#endif | |
} | |
CUBE_INLINE | |
corner_t:: | |
corner_t(bool x, bool y, bool z) | |
: bits( (x ? 1 : 0) + (y ? 2 : 0) + (z ? 4 : 0)) | |
{ | |
#ifndef NDEBUG | |
mx = bits.test(0); | |
my = bits.test(1); | |
mz = bits.test(2); | |
#endif | |
//bits.set(0, x); | |
//bits.set(1, y); | |
//bits.set(2, z); | |
} | |
CUBE_INLINE | |
const corner_t& | |
corner_t:: | |
get(bool x, bool y, bool z) | |
{ | |
std::bitset<3> bits; | |
bits.set(0,x); | |
bits.set(1,y); | |
bits.set(2,z); | |
return all()[bits.to_ulong()]; | |
} | |
CUBE_INLINE | |
const boost::array< corner_t, 8 >& | |
corner_t:: | |
all() | |
{ | |
static const boost::array<corner_t, 8> corners = | |
{{ | |
corner_t(std::bitset<3>(0)), | |
corner_t(std::bitset<3>(1)), | |
corner_t(std::bitset<3>(2)), | |
corner_t(std::bitset<3>(3)), | |
corner_t(std::bitset<3>(4)), | |
corner_t(std::bitset<3>(5)), | |
corner_t(std::bitset<3>(6)), | |
corner_t(std::bitset<3>(7)) | |
}}; | |
return corners; | |
} | |
CUBE_INLINE | |
boost::uint8_t | |
corner_t:: | |
index() const | |
{ | |
return bits.to_ulong(); | |
} | |
CUBE_INLINE | |
const corner_t& | |
corner_t:: | |
get(boost::uint8_t i) | |
{ | |
BOOST_ASSERT(i < SIZE); | |
return all()[i]; | |
} | |
CUBE_INLINE | |
boost::array< corner_t, 3 > | |
corner_t:: | |
adjacent() const | |
{ | |
boost::array<corner_t,3> result = | |
{{ | |
corner_t(!x(), y(), z() ), | |
corner_t( x(),!y(), z() ), | |
corner_t( x(), y(),!z() ) | |
}}; | |
return result; | |
} | |
CUBE_INLINE | |
corner_set_t | |
corner_t::adjacent_set() const | |
{ | |
return corner_set_t(adjacent()); | |
} | |
CUBE_INLINE | |
bool | |
corner_t:: | |
x() const | |
{ | |
return bits[0]; | |
} | |
CUBE_INLINE | |
bool | |
corner_t:: | |
y() const | |
{ | |
return bits[1]; | |
} | |
CUBE_INLINE | |
bool | |
corner_t:: | |
z() const | |
{ | |
return bits[2]; | |
} | |
CUBE_INLINE | |
unsigned short int | |
corner_t:: | |
x_i() const | |
{ | |
return bits[0] ? 1 : 0; | |
} | |
CUBE_INLINE | |
unsigned short int | |
corner_t:: | |
y_i() const | |
{ | |
return bits[1] ? 1 : 0; | |
} | |
CUBE_INLINE | |
unsigned short int | |
corner_t:: | |
z_i() const | |
{ | |
return bits[2] ? 1 : 0; | |
} | |
CUBE_INLINE | |
bool corner_t::operator<(const corner_t& other) const | |
{ | |
return bits.to_ulong() < other.bits.to_ulong(); | |
} | |
CUBE_INLINE | |
boost::array< face_t, 3 > | |
corner_t::faces() const | |
{ | |
boost::array< face_t, 3 > result = | |
{{ | |
direction_t::get( x() ? 1 : -1, 0, 0).face(), | |
direction_t::get( 0, y() ? 1 : -1, 0).face(), | |
direction_t::get( 0, 0, z() ? 1 : -1).face() | |
}}; | |
return result; | |
} | |
CUBE_INLINE | |
face_set_t | |
corner_t::face_set() const | |
{ | |
return face_set_t(faces()); | |
} | |
CUBE_INLINE | |
const corner_t& | |
corner_t::get(const corner_t& corner) | |
{ | |
BOOST_ASSERT(corner.index() < SIZE); | |
return all()[corner.index()]; | |
} | |
CUBE_INLINE | |
const corner_t& | |
corner_t::opposite() const | |
{ | |
std::size_t idx = std::bitset<3>(bits).flip().to_ulong(); | |
BOOST_ASSERT(idx < SIZE); | |
return all()[idx]; | |
} | |
CUBE_INLINE | |
bool corner_t::operator!=(const corner_t& other) const | |
{ | |
return bits != other.bits; | |
} | |
CUBE_INLINE | |
bool corner_t::operator==(const corner_t& other) const | |
{ | |
return bits == other.bits; | |
} | |
CUBE_INLINE | |
const corner_t& | |
corner_t::index(boost::uint8_t idx) | |
{ | |
return corner_t::get(idx); | |
} | |
CUBE_INLINE | |
const corner_t& | |
corner_t:: | |
adjacent(const direction_t& direction) const | |
{ | |
return corner_t::get(lxor(x(), (direction.x() != 0)), | |
lxor(y(), (direction.y() != 0)), | |
lxor(z(), (direction.z() != 0))); | |
} | |
//################################################################### | |
//################################################################### | |
//#### edge_t | |
//################################################################### | |
namespace detail{ | |
CUBE_INLINE | |
boost::array<corner_t, 2> | |
make_edge_corners(const corner_t& a, const corner_t& b) | |
{ | |
boost::array<corner_t, 2> result = | |
{{ | |
(a.index() < b.index() ? a : b), | |
(a.index() < b.index() ? b : a) | |
}}; | |
return result; | |
} | |
} // namespace detail | |
CUBE_INLINE | |
edge_t:: | |
edge_t(const corner_t& a, const corner_t& b) | |
: mcorners(detail::make_edge_corners(a,b)) | |
{ | |
BOOST_ASSERT(mcorners.front().index() < mcorners.back().index()); | |
BOOST_ASSERT(mcorners.front() != mcorners.back()); | |
BOOST_ASSERT(mcorners.front().adjacent_set().contains(mcorners.back())); | |
BOOST_ASSERT(mcorners.back().adjacent_set().contains(mcorners.front())); | |
} | |
CUBE_INLINE | |
const boost::array<corner_t, 2>& | |
edge_t:: | |
corners() const | |
{ | |
return mcorners; | |
} | |
CUBE_INLINE | |
const boost::array<edge_t, 12>& | |
edge_t:: | |
all() | |
{ | |
///right top far | |
static const corner_t& rtf = corner_t::get( true, true, true); | |
///right bottom near | |
static const corner_t& rbn = corner_t::get( true,false,false); | |
///left bottom, far | |
static const corner_t& lbf = corner_t::get(false,false, true); | |
///left top near | |
static const corner_t& lbn = corner_t::get(false, true,false); | |
static const boost::array<edge_t, 12> result = | |
{{ | |
edge_t(rtf, rtf.adjacent()[0]), | |
edge_t(rtf, rtf.adjacent()[1]), | |
edge_t(rtf, rtf.adjacent()[2]), | |
edge_t(rbn, rbn.adjacent()[0]), | |
edge_t(rbn, rbn.adjacent()[1]), | |
edge_t(rbn, rbn.adjacent()[2]), | |
edge_t(lbf, lbf.adjacent()[0]), | |
edge_t(lbf, lbf.adjacent()[1]), | |
edge_t(lbf, lbf.adjacent()[2]), | |
edge_t(lbn, lbn.adjacent()[0]), | |
edge_t(lbn, lbn.adjacent()[1]), | |
edge_t(lbn, lbn.adjacent()[2]) | |
}}; | |
return result; | |
} | |
//################################################################### | |
CUBE_INLINE | |
box_t:: | |
box_t() | |
{ | |
} | |
CUBE_INLINE | |
const box_t& | |
box_t:: | |
identity() | |
{ | |
static const box_t box; | |
return box; | |
} | |
CUBE_INLINE | |
const boost::array< corner_t, 8 >& | |
box_t::corners() const | |
{ | |
return corner_t::all(); | |
} | |
//################################################################### | |
//#### set_base_t | |
//################################################################### | |
template<typename derived_t, typename element_t, std::size_t N> | |
CUBE_INLINE | |
set_base_t<derived_t, element_t, N>:: | |
set_base_t() | |
: bits(0) | |
{ | |
} | |
template<typename derived_t, typename element_t, std::size_t N> | |
template<typename Sequence> | |
CUBE_INLINE | |
set_base_t<derived_t, element_t, N>:: | |
set_base_t(const Sequence& sequence) | |
: bits(0) | |
{ | |
*this |= sequence; | |
} | |
template<typename derived_t, typename element_t, std::size_t N> | |
CUBE_INLINE | |
bool | |
set_base_t<derived_t, element_t, N>:: | |
contains(const element_t& element) const | |
{ | |
BOOST_ASSERT(element.index() < N); | |
return bits.test(element.index()); | |
} | |
template<typename derived_t, typename element_t, std::size_t N> | |
CUBE_INLINE | |
derived_t& | |
set_base_t<derived_t, element_t, N>:: | |
operator=(const element_t& element) | |
{ | |
BOOST_ASSERT(element.index() < N); | |
bits.reset(); | |
bits.set(element.index(), true); | |
return self(); | |
} | |
template<typename derived_t, typename element_t, std::size_t N> | |
CUBE_INLINE | |
derived_t& | |
set_base_t<derived_t, element_t, N>:: | |
operator=(const derived_t& set) | |
{ | |
bits = set.bits; | |
return self(); | |
} | |
template<typename derived_t, typename element_t, std::size_t N> | |
CUBE_INLINE | |
derived_t& | |
set_base_t<derived_t, element_t, N>:: | |
operator|=(const derived_t& set) | |
{ | |
bits |= set.bits; | |
return self(); | |
} | |
template<typename derived_t, typename element_t, std::size_t N> | |
CUBE_INLINE | |
derived_t& | |
set_base_t<derived_t, element_t, N>:: | |
operator|=(const element_t& element) | |
{ | |
BOOST_ASSERT(element.index() < N); | |
bits.set(element.index(), true); | |
return self(); | |
} | |
template<typename derived_t, typename element_t, std::size_t N> | |
template<typename Sequence> | |
CUBE_INLINE | |
derived_t& | |
set_base_t<derived_t, element_t, N>:: | |
operator|=(const Sequence& sequence) | |
{ | |
BOOST_FOREACH(const element_t& element, sequence) | |
{ | |
*this |= element; | |
} | |
return self(); | |
} | |
template<typename derived_t, typename element_t, std::size_t N> | |
CUBE_INLINE | |
derived_t& | |
set_base_t<derived_t, element_t, N>:: | |
self() | |
{ | |
typedef boost::is_base_of< set_base_t<derived_t, element_t, N>, derived_t > derives_correctly; | |
BOOST_STATIC_ASSERT( derives_correctly::value ); | |
return static_cast<derived_t&>(*this); | |
} | |
template<typename derived_t, typename element_t, std::size_t N> | |
CUBE_INLINE | |
typename set_base_t<derived_t, element_t, N>::const_iterator | |
set_base_t<derived_t, element_t, N>:: | |
begin() const | |
{ | |
BOOST_ASSERT(false && "set_base_t::begin() is broken"); | |
return const_iterator(*this); | |
} | |
template<typename derived_t, typename element_t, std::size_t N> | |
CUBE_INLINE | |
typename set_base_t<derived_t, element_t, N>::const_iterator | |
set_base_t<derived_t, element_t, N>:: | |
end() const | |
{ | |
BOOST_ASSERT(false && "set_base_t::end() is broken"); | |
return const_iterator(*this, N); | |
} | |
template<typename derived_t, typename element_t, std::size_t N> | |
CUBE_INLINE | |
std::size_t | |
set_base_t<derived_t, element_t, N>:: | |
size() const | |
{ | |
return bits.count(); | |
} | |
template<typename derived_t, typename element_t, std::size_t N> | |
CUBE_INLINE | |
void | |
set_base_t<derived_t, element_t, N>:: | |
clear() | |
{ | |
bits.reset(); | |
} | |
template<typename derived_t, typename element_t, std::size_t N> | |
CUBE_INLINE | |
bool | |
set_base_t<derived_t, element_t, N>:: | |
operator==(const derived_t& other) const | |
{ | |
return bits == other.bits; | |
} | |
template<typename derived_t, typename element_t, std::size_t N> | |
CUBE_INLINE | |
bool | |
set_base_t<derived_t, element_t, N>:: | |
contains(const std::size_t& idx) const | |
{ | |
BOOST_ASSERT(idx < N); | |
return bits.test(idx); | |
} | |
CUBE_INLINE | |
direction_set_t::direction_set_t() | |
: base_t() | |
{ | |
} | |
template<typename T> | |
CUBE_INLINE | |
direction_set_t::direction_set_t(const T& v) | |
: base_t(v) | |
{ | |
} | |
CUBE_INLINE | |
face_set_t::face_set_t() | |
: base_t() | |
{ | |
} | |
template<typename T> | |
CUBE_INLINE | |
face_set_t::face_set_t(const T& v) | |
: base_t(v) | |
{ | |
} | |
CUBE_INLINE | |
corner_set_t::corner_set_t() | |
: base_t() | |
{ | |
} | |
template<typename T> | |
CUBE_INLINE | |
corner_set_t::corner_set_t(const T& v) | |
: base_t(v) | |
{ | |
} | |
//################################################################### | |
} // namespace cube |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Copyright (c) 2012 Azriel Fasten azriel.fasten@gmail.com | |
Permission is hereby granted, free of charge, to any person | |
obtaining a copy of this software and associated documentation | |
files (the "Software"), to deal in the Software without | |
restriction, including without limitation the rights to use, | |
copy, modify, merge, publish, distribute, sublicense, and/or sell | |
copies of the Software, and to permit persons to whom the | |
Software is furnished to do so, subject to the following | |
conditions: | |
The above copyright notice and this permission notice shall be | |
included in all copies or substantial portions of the Software. | |
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES | |
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | |
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | |
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
OTHER DEALINGS IN THE SOFTWARE. | |
*/ | |
#ifndef CUBE_LOGIC_UTILITY_H | |
#define CUBE_LOGIC_UTILITY_H | |
inline | |
bool lxor(const bool& a, const bool& b) | |
{ | |
return !a != !b; | |
} | |
inline | |
bool liff(const bool& a, const bool& b) | |
{ | |
return ( (a && b) || (!a && !b) ); | |
} | |
inline | |
bool lif(const bool& a, const bool& b) | |
{ | |
return (!a || b); | |
} | |
inline | |
bool lnand(const bool& a, const bool& b) | |
{ | |
return !(a && b); | |
} | |
#endif // CUBE_LOGIC_UTILITY_H |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment