Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 31 additions & 2 deletions .github/workflows/build_and_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,40 @@ jobs:
uses: actions/checkout@v2

- name: CMake Configure
run: cmake -B ${{github.workspace}}/build -G"Ninja" -DINT_TREE_BUILD_EXAMPLES=on -DINT_TREE_ENABLE_TESTS=on -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_CXX_COMPILER=${{ matrix.compiler.cxx }} -DCMAKE_CXX_STANDARD=${{ matrix.cxx_standard }}
run: cmake -B ${{github.workspace}}/build -G"Ninja" -DINT_TREE_USE_OPTIONAL_POLYFILL=on -DINT_TREE_BUILD_EXAMPLES=on -DINT_TREE_ENABLE_TESTS=on -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_CXX_COMPILER=${{ matrix.compiler.cxx }} -DCMAKE_CXX_STANDARD=${{ matrix.cxx_standard }}

- name: Build
run: cmake --build ${{github.workspace}}/build

- name: Test
working-directory: ${{github.workspace}}/build
run: ./tests/tree-tests
run: ./tests/tree-tests

msvc:
runs-on: windows-latest
steps:
- name: Checkout
uses: actions/checkout@v2

- name: Setup MSVC
uses: microsoft/[email protected]

- name: Install vcpkg and gtest
run: |
git clone https://github.com/microsoft/vcpkg.git
.\vcpkg\bootstrap-vcpkg.bat
.\vcpkg\vcpkg.exe install gtest
shell: pwsh
env:
VCPKG_DEFAULT_TRIPLET: x64-windows

- name: CMake Configure
run: cmake -B ${{github.workspace}}/build -G"Visual Studio 17 2022" -A x64 -DCMAKE_TOOLCHAIN_FILE=${{github.workspace}}/vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_CXX_STANDARD=20 -DINT_TREE_USE_OPTIONAL_POLYFILL=on -DINT_TREE_BUILD_EXAMPLES=on -DINT_TREE_ENABLE_TESTS=on -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}

- name: Build
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}

- name: Test
working-directory: ${{github.workspace}}/build
run: .\tests\Release\tree-tests.exe
shell: cmd
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,6 @@ tests/obj
tests/*.cbp
tests/*.depend
tests/*build_log.html
tests/cairo-wrap
tests/cairo-wrap

CMakeSettings.json
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ endif()

target_include_directories(interval-tree INTERFACE ./include)

if(${MSVC})
target_compile_options(interval-tree INTERFACE /Zc:__cplusplus)
endif()

if(INT_TREE_DRAW_EXAMPLES)
add_subdirectory(cairo-wrap)
add_subdirectory(drawings)
Expand Down
29 changes: 20 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ Options are:
- [After deoverlap](#after-deoverlap)
- [interval\_tree deoverlap\_copy()](#interval_tree-deoverlap_copy)
- [interval\_tree punch(interval\_type const\& ival)](#interval_tree-punchinterval_type-const-ival)
- [Before punching (closed\_adjacent intervals)](#before-punching-closed_adjacent-intervals)
- [Before punching (closed intervals)](#before-punching-closed-intervals)
- [After punching (with \[-10, 60\])](#after-punching-with--10-60)
- [interval\_tree punch()](#interval_tree-punch)
- [bool empty() const noexcept](#bool-empty-const-noexcept)
Expand All @@ -194,14 +194,16 @@ Options are:
- [reverse\_iterator rend()](#reverse_iterator-rend)
- [reverse\_iterator crbegin()](#reverse_iterator-crbegin)
- [reverse\_iterator crend()](#reverse_iterator-crend)
- [void erase\_range(interval\_type const\& ival)](#void-erase_rangeinterval_type-const-ival)
- [void erase\_range(interval\_type const\& ival, bool retainSlices)](#void-erase_rangeinterval_type-const-ival-bool-retainslices)
- [Members of Interval](#members-of-interval)
- [using value\_type](#using-value_type)
- [using interval\_kind](#using-interval_kind)
- [friend bool operator==(interval const\& lhs, interval const\& other)](#friend-bool-operatorinterval-const-lhs-interval-const-other)
- [friend bool operator!=(interval const\& lhs, interval const\& other)](#friend-bool-operatorinterval-const-lhs-interval-const-other-1)
- [value\_type low() const](#value_type-low-const)
- [value\_type high() const](#value_type-high-const)
- [\[\[deprecated\]\] bool overlaps(value\_type l, value\_type h) const](#deprecated-bool-overlapsvalue_type-l-value_type-h-const)
- [DEPRECATED bool overlaps(value\_type l, value\_type h) const](#deprecated-bool-overlapsvalue_type-l-value_type-h-const)
- [bool overlaps\_exclusive(value\_type l, value\_type h) const](#bool-overlaps_exclusivevalue_type-l-value_type-h-const)
- [bool overlaps(interval const\& other) const](#bool-overlapsinterval-const-other-const)
- [bool overlaps\_exclusive(interval const\& other) const](#bool-overlaps_exclusiveinterval-const-other-const)
Expand Down Expand Up @@ -379,10 +381,10 @@ Open intervals with integral numbers will also not produce the gap (5, 6), becau
`ival` can be any subrange of the tree, including encompassing the whole tree.

**Returns**: A new interval_tree containing the gaps.
### Before punching (closed_adjacent intervals)
![BeforePunch](https://private-user-images.githubusercontent.com/6238896/471147224-5c631e00-dea4-4b75-a3bf-6fdd8ec1440b.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NTM1NjI1MzQsIm5iZiI6MTc1MzU2MjIzNCwicGF0aCI6Ii82MjM4ODk2LzQ3MTE0NzIyNC01YzYzMWUwMC1kZWE0LTRiNzUtYTNiZi02ZmRkOGVjMTQ0MGIucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI1MDcyNiUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTA3MjZUMjAzNzE0WiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9ZDQ0NWIwMTcwMjZhNDA1YmUwNGI1YTIzNTBhZTQ5OTNhMWFiOTU5ZmU0N2E3NDI0NTQ0MzYwODA4N2E2MGFiZiZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.P5zLeXg0-9bd20Thj6pfq_WxriMn4GC_lDSLzzGKMbw)
### Before punching (closed intervals)
![BeforePunch](https://5cript.github.io/readme-images/interval-tree/punch_source.png)
### After punching (with [-10, 60])
![AfterPunch](https://private-user-images.githubusercontent.com/6238896/471147227-5c226d1d-d544-4a43-89a4-b3545145107d.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NTM1NjI1MzQsIm5iZiI6MTc1MzU2MjIzNCwicGF0aCI6Ii82MjM4ODk2LzQ3MTE0NzIyNy01YzIyNmQxZC1kNTQ0LTRhNDMtODlhNC1iMzU0NTE0NTEwN2QucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI1MDcyNiUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTA3MjZUMjAzNzE0WiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9NmE2ZDUzMjU2ZTNjZWQ0Y2QzYjQ3ZGUyYjgyNWM2NDViYTAxMTdlY2RjYmQyMzg4OWFmZDlhMWU5YjY4NjlmZCZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.Infe9i281LDOEC5GeBFuLHVE6Xjqw7KvcUo-gv3hjpk)
![AfterPunch](https://5cript.github.io/readme-images/interval-tree/punch_result.png)

---
### interval_tree punch()
Expand Down Expand Up @@ -444,6 +446,12 @@ Returns a past the end const_iterator in reverse.

**Returns**: past the end const_iterator.

### void erase_range(interval_type const& ival)
Removes all intervals overlapping ival from the tree

### void erase_range(interval_type const& ival, bool retainSlices)
Removes all intervals overlapping ival from the tree, but retains the overlap beyond the erase interval.

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

Expand All @@ -465,7 +473,7 @@ Which can be picked with the second template parameter of interval:
- [friend bool operator!=(interval const& lhs, interval const& other)](#friend-bool-operatorinterval-const-lhs-interval-const-other-1)
- [value_type low() const](#value_type-low-const)
- [value_type high() const](#value_type-high-const)
- [\[\[deprecated\]\] bool overlaps(value_type l, value_type h) const](#bool-overlapsvalue_type-l-value_type-h-const)
- [DEPRECATED bool overlaps(value_type l, value_type h) const](#bool-overlapsvalue_type-l-value_type-h-const)
- [bool overlaps_exclusive(value_type l, value_type h) const](#bool-overlaps_exclusivevalue_type-l-value_type-h-const)
- [bool overlaps(interval const& other) const](#bool-overlapsinterval-const-other-const)
- [bool overlaps_exclusive(interval const& other) const](#bool-overlaps_exclusiveinterval-const-other-const)
Expand All @@ -474,6 +482,7 @@ Which can be picked with the second template parameter of interval:
- [value_type operator-(interval const& other) const](#value_type-operator-interval-const-other-const)
- [value_type size() const](#value_type-size-const)
- [interval join(interval const& other) const](#interval-joininterval-const-other-const)
- [slice\_type slice(interval const\& other) const](#slice_type-sliceinterval-const-other-const)

### using value_type
The underlying interval numerical type
Expand All @@ -487,7 +496,7 @@ Comparison operator.
Lower bound.
### value_type high() const
Upper bound.
### \[\[deprecated\]\] bool overlaps(value_type l, value_type h) const
### DEPRECATED bool overlaps(value_type l, value_type h) const
Overlap these bounds with this interval?
Is deprecated because the overlapping does not work with the dynamic interval type.
### bool overlaps_exclusive(value_type l, value_type h) const
Expand All @@ -507,12 +516,14 @@ Overlapping intervals have 0 distance.
Returns The amount of elements in the interval when integral, or the distance between the 2 bounds when floating point.
### interval join(interval const& other) const
Joins 2 intervals and whatever is inbetween.
### slice_type<interval> slice(interval const& other) const
### slice_type slice(interval const& other) const
Removes other from this interval returning what is remaining.
The range of other going beyond the range of this is ignored.
Returns a struct with 2 members: left_slice and right_slice.
```
[ this interval ]
[left][other][right]
```

When the intervals are closed, adjacent results are differenty by 1.
When the intervals are closed_adjacent, adjacent results are differenty by 1.
[0, 9].slice([5, 19]) => left: [0, 4], right: nullopt
45 changes: 45 additions & 0 deletions include/interval-tree/interval_tree.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1126,6 +1126,7 @@ namespace lib_interval_tree
* inserted with more overlap searches? If the result is a single interval shall it insert_overlap or insert?
* Be careful to not produce overlapping merge sets when doing recursive insertion, or it will recurse
* endlessly.
* @return An iterator to the inserted or merged interval.
*/
iterator insert_overlap(interval_type const& ival, bool exclusive = false, bool recursive = true)
{
Expand Down Expand Up @@ -1204,6 +1205,50 @@ namespace lib_interval_tree
return next;
}

/**
* @brief Erases all elements that overlap with ival, if retainSlices is true, the left and right overhanging
* parts are reinserted.
*
* ( i1 )
* ( i2 )
* ( erase )
* yields for retainSlices = true:
* (i1rest) (i2rest)
*
* Edge behavior depends on the interval type, or rather the slice implementation.
*
* @param ival The interval to erase.
* @param retainSlice If true, retains the non-overlapping parts of the intervals.
*/
template <typename interval_t = interval_type>
#ifdef LIB_INTERVAL_TREE_CONCEPTS
requires detail::has_slice<interval_t>
void
#else
typename std::enable_if<detail::has_slice<interval_t>, void>::type
#endif
erase_range(interval_t const& ival, bool retainSlices)
{
const auto iter = insert_overlap(ival, false, true);
if (!retainSlices)
{
erase(iter);
return;
}

const auto slices = iter->slice(ival);
erase(iter);
if (slices.left_slice)
insert(slices.left_slice.value());
if (slices.right_slice)
insert(slices.right_slice.value());
}

void erase_range(interval_type const& ival)
{
erase(insert_overlap(ival, false, true));
}

/**
* Returns the size of the object.
*/
Expand Down
2 changes: 1 addition & 1 deletion include/interval-tree/optional.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ namespace lib_interval_tree
template < \
typename U, \
typename... Args, \
std::enable_if_t<std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value, int>...> \
std::enable_if_t<std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value, int> = 0> \
constexpr explicit optional_base(in_place_t, std::initializer_list<U> il, Args&&... args) \
: value_(il, std::forward<Args>(args)...) \
, engaged_{true} \
Expand Down
14 changes: 11 additions & 3 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,25 @@ file(GLOB sources "*.cpp")
# Add Executable
add_executable(tree-tests ${sources})

target_link_libraries(tree-tests PRIVATE gtest gmock interval-tree)
find_package(GTest REQUIRED)

target_link_libraries(tree-tests PRIVATE interval-tree GTest::gtest GTest::gmock GTest::gmock_main)

# Compiler Options
set(DEBUG_OPTIONS -fexceptions -g -Wall -pedantic-errors -pedantic)
target_compile_options(tree-tests PUBLIC "$<$<CONFIG:DEBUG>:${DEBUG_OPTIONS}>")

set(RELEASE_OPTIONS -fexceptions -O3 -Wall -pedantic)
if (${MSVC})
set(WARNING_FLAGS -W4)
else()
set(WARNING_FLAGS -Wall)
list(APPEND WARNING_FLAGS -Wextra)
endif()
set(RELEASE_OPTIONS -fexceptions -O3 ${WARNING_FLAGS} -pedantic)
target_compile_options(tree-tests PUBLIC "$<$<CONFIG:RELEASE>:${RELEASE_OPTIONS}>")

if (INT_TREE_DRAW_EXAMPLES)
target_link_libraries(tree-tests PRIVATE cairo cairo-wrap)
target_link_libraries(tree-tests PRIVATE cairo-wrap cairo)
endif()

# If msys2, copy dynamic libraries to executable directory, visual studio does this automatically.
Expand Down
Loading
Loading