Skip to content

Commit 40bc0f8

Browse files
committed
Renamed extrude to slice and added docs.
1 parent dafb5c2 commit 40bc0f8

File tree

4 files changed

+147
-10
lines changed

4 files changed

+147
-10
lines changed

README.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ Options are:
210210
- [value\_type operator-(interval const\& other) const](#value_type-operator-interval-const-other-const)
211211
- [value\_type size() const](#value_type-size-const)
212212
- [interval join(interval const\& other) const](#interval-joininterval-const-other-const)
213+
- [slice\_type slice(interval const\& other) const](#slice_type-sliceinterval-const-other-const)
213214

214215
### iterator insert(interval_type const& ival)
215216
Adds an interval into the tree.
@@ -443,7 +444,7 @@ Returns a past the end const_iterator in reverse.
443444
**Returns**: past the end const_iterator.
444445

445446
## Members of Interval
446-
___You can implement your own interval if you provide the same functions, except (operator-, size, operator!=).___
447+
___You can implement your own interval if you provide the same functions, except (slice, operator-, size, operator!=).___
447448

448449
There are 6 types of intervals:
449450
- open: (a, b)
@@ -505,3 +506,12 @@ Overlapping intervals have 0 distance.
505506
Returns The amount of elements in the interval when integral, or the distance between the 2 bounds when floating point.
506507
### interval join(interval const& other) const
507508
Joins 2 intervals and whatever is inbetween.
509+
### slice_type<interval> slice(interval const& other) const
510+
Removes other from this interval returning what is remaining.
511+
The range of other going beyond the range of this is ignored.
512+
Returns a struct with 2 members: left_slice and right_slice.
513+
[ this interval ]
514+
[left][other][right]
515+
516+
When the intervals are closed, adjacent results are differenty by 1.
517+
[0, 9].slice([5, 19]) => left: [0, 4], right: nullopt

include/interval-tree/interval_tree.hpp

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,30 @@ namespace lib_interval_tree
3232
// ############################################################################################################
3333
using default_interval_value_type = int;
3434
// ############################################################################################################
35+
namespace detail
36+
{
37+
template <class...>
38+
using void_t = void;
39+
40+
template <typename interval_t, typename = void>
41+
struct has_slice_impl : std::false_type
42+
{};
43+
44+
template <typename interval_t>
45+
struct has_slice_impl<
46+
interval_t,
47+
void_t<decltype(std::declval<interval_t>().slice(std::declval<interval_t>()))>> : std::true_type
48+
{};
49+
50+
#if __cplusplus >= 202002L
51+
template <typename interval_t>
52+
concept has_slice = has_slice_impl<interval_t>::value;
53+
#else
54+
template <typename interval_t>
55+
constexpr bool has_slice = has_slice_impl<interval_t>::value;
56+
#endif
57+
}
58+
// ############################################################################################################
3559
template <typename numerical_type, typename interval_kind_>
3660
struct interval_base
3761
{
@@ -212,12 +236,14 @@ namespace lib_interval_tree
212236
}
213237

214238
/**
215-
* @brief Extrudes other from this interval returning what is remaining.
239+
* @brief Removes other from this interval returning what is remaining.
240+
*
241+
* The range of other going beyond the range of this is ignored.
216242
*
217243
* @param other
218244
* @return slice_type<interval>
219245
*/
220-
slice_type<interval> extrude(interval const& other) const
246+
slice_type<interval> slice(interval const& other) const
221247
{
222248
slice_type<interval> slices{};
223249
if (low_ < other.low_)
@@ -362,12 +388,12 @@ namespace lib_interval_tree
362388
}
363389

364390
/**
365-
* @brief Extrudes other from this interval returning what is remaining.
391+
* @brief Removes other from this interval returning what is remaining.
366392
*
367393
* @param other
368394
* @return slice_type<interval>
369395
*/
370-
slice_type<interval> extrude(interval const& other) const
396+
slice_type<interval> slice(interval const& other) const
371397
{
372398
if (!overlaps(other))
373399
return {};
@@ -1417,9 +1443,7 @@ namespace lib_interval_tree
14171443
{
14181444
if (empty())
14191445
return {};
1420-
auto min = std::begin(*this)->interval()->low();
1421-
auto max = root_->max_;
1422-
return punch({min, max});
1446+
return punch({begin()->low(), root_->max_});
14231447
}
14241448

14251449
/**
@@ -1429,7 +1453,14 @@ namespace lib_interval_tree
14291453
*
14301454
* @param ival The range in which to punch out the gaps as a new tree
14311455
*/
1432-
interval_tree punch(interval_type ival) const
1456+
template <typename interval_t = interval_type>
1457+
#ifdef LIB_INTERVAL_TREE_CONCEPTS
1458+
requires detail::has_slice<interval_t>
1459+
interval_tree
1460+
#else
1461+
typename std::enable_if<detail::has_slice<interval_t>, interval_tree>::type
1462+
#endif
1463+
punch(interval_type ival) const
14331464
{
14341465
interval_tree result;
14351466

@@ -1462,7 +1493,7 @@ namespace lib_interval_tree
14621493
bool insert_remaining = false;
14631494
for (; iter != cend(); ++iter)
14641495
{
1465-
ex = ival.extrude(*iter);
1496+
ex = ival.slice(*iter);
14661497
if (ex.left_slice)
14671498
result.insert(*ex.left_slice);
14681499

tests/interval_tests.hpp

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -899,4 +899,77 @@ TEST_F(IntervalTests, CanFindDynamicIntervalUsingComparisonFunction)
899899
EXPECT_EQ(iter->high(), 5);
900900
EXPECT_EQ(iter->left_border(), interval_border::closed);
901901
EXPECT_EQ(iter->right_border(), interval_border::closed);
902+
}
903+
904+
TEST_F(IntervalTests, ClosedSliceLeftOverlap)
905+
{
906+
// [ this ]
907+
// [ls][param]
908+
const auto result = i<closed>(1, 8).slice(i<closed>(5, 100));
909+
ASSERT_TRUE(result.left_slice);
910+
EXPECT_EQ(result.left_slice->low(), 1);
911+
EXPECT_EQ(result.left_slice->high(), 4);
912+
EXPECT_FALSE(result.right_slice);
913+
}
914+
915+
TEST_F(IntervalTests, OpenSliceLeftOverlap)
916+
{
917+
// [ this ]
918+
// [ls][param]
919+
using lib_interval_tree::open;
920+
const auto result = i<open>(1, 8).slice(i<open>(5, 10));
921+
ASSERT_TRUE(result.left_slice);
922+
EXPECT_EQ(result.left_slice->low(), 1);
923+
EXPECT_EQ(result.left_slice->high(), 5);
924+
EXPECT_FALSE(result.right_slice);
925+
}
926+
927+
TEST_F(IntervalTests, ClosedRightRemains)
928+
{
929+
// [ this ]
930+
// [param][rs]
931+
const auto result = i<closed>(8, 15).slice(i<closed>(8, 12));
932+
ASSERT_TRUE(result.right_slice);
933+
EXPECT_EQ(result.right_slice->low(), 13);
934+
EXPECT_EQ(result.right_slice->high(), 15);
935+
EXPECT_FALSE(result.left_slice);
936+
}
937+
938+
TEST_F(IntervalTests, OpenRightRemains)
939+
{
940+
// [ this ]
941+
// [param][rs]
942+
using lib_interval_tree::open;
943+
const auto result = i<open>(8, 15).slice(i<open>(8, 12));
944+
ASSERT_TRUE(result.right_slice);
945+
EXPECT_EQ(result.right_slice->low(), 12);
946+
EXPECT_EQ(result.right_slice->high(), 15);
947+
EXPECT_FALSE(result.left_slice);
948+
}
949+
950+
TEST_F(IntervalTests, ClosedMiddleExtrusion)
951+
{
952+
// [ this ]
953+
// [ls][param][rs]
954+
const auto result = i<closed>(0, 10).slice(i<closed>(5, 8));
955+
ASSERT_TRUE(result.left_slice);
956+
EXPECT_EQ(result.left_slice->low(), 0);
957+
EXPECT_EQ(result.left_slice->high(), 4);
958+
ASSERT_TRUE(result.right_slice);
959+
EXPECT_EQ(result.right_slice->low(), 9);
960+
EXPECT_EQ(result.right_slice->high(), 10);
961+
}
962+
963+
TEST_F(IntervalTests, OpenMiddleExtrusion)
964+
{
965+
// [ this ]
966+
// [ls][param][rs]
967+
using lib_interval_tree::open;
968+
const auto result = i<open>(0, 10).slice(i<open>(5, 8));
969+
ASSERT_TRUE(result.left_slice);
970+
EXPECT_EQ(result.left_slice->low(), 0);
971+
EXPECT_EQ(result.left_slice->high(), 5);
972+
ASSERT_TRUE(result.right_slice);
973+
EXPECT_EQ(result.right_slice->low(), 8);
974+
EXPECT_EQ(result.right_slice->high(), 10);
902975
}

tests/punch_tests.hpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -668,4 +668,27 @@ TEST_F(PunchTests, ClosedFloatGap)
668668
EXPECT_NEAR(iter->high(), 6.0f, 0.001f);
669669
EXPECT_NEAR((++iter)->low(), 10.0f, 0.001f);
670670
EXPECT_FLOAT_EQ(iter->high(), 12.0f);
671+
}
672+
673+
TEST_F(PunchTests, PunchWithoutArgsEncompassesTree)
674+
{
675+
using types = closed<int>;
676+
677+
auto tree = types::tree_type{};
678+
tree.insert(types::interval_type{0, 5});
679+
tree.insert(types::interval_type{10, 15});
680+
tree.insert(types::interval_type{20, 25});
681+
tree.insert(types::interval_type{30, 35});
682+
auto result = tree.punch();
683+
684+
ASSERT_EQ(result.size(), 3);
685+
auto iter = result.begin();
686+
EXPECT_EQ(iter->low(), 6);
687+
EXPECT_EQ(iter->high(), 9);
688+
689+
EXPECT_EQ((++iter)->low(), 16);
690+
EXPECT_EQ(iter->high(), 19);
691+
692+
EXPECT_EQ((++iter)->low(), 26);
693+
EXPECT_EQ(iter->high(), 29);
671694
}

0 commit comments

Comments
 (0)