@@ -1347,35 +1347,164 @@ namespace lib_interval_tree
13471347 return punch ({min, max});
13481348 }
13491349
1350+ // TODO: private
13501351 /* *
1351- * Only works with deoverlapped trees.
1352- * Removes all intervals from the given interval and produces a tree that contains the remaining intervals.
1353- * This is basically the other punch overload with ival = [tree_lowest, tree_highest]
1352+ * @brief Finds the first interval that is right of the given value and does not contain it.
1353+ *
1354+ * @param low
1355+ * @return node_type*
13541356 */
1355- interval_tree punch (interval_type const & ival ) const
1357+ node_type* find_first_not_right_of_i (value_type search_value ) const
13561358 {
13571359 if (empty ())
1358- return {};
1360+ return nullptr ;
1361+
1362+ // There can be no interval strictly right of the value, if the value
1363+ // is larger than the max.
1364+ if (search_value > root_->max_ )
1365+ return nullptr ;
1366+
1367+ const auto is_interval_strictly_right_of_value = [search_value](node_type* node) {
1368+ return node->low () > search_value ||
1369+ (node->low () == search_value && !node->interval ()->within (search_value));
1370+ };
1371+
1372+ auto * node = root_;
1373+
1374+ // If the interval is not strictly right of the value, we can only go down right
1375+ // And dont have to check left.
1376+ while (!is_interval_strictly_right_of_value (node) && node->right_ )
1377+ node = node->right_ ;
1378+
1379+ bool go_left = false ;
1380+ bool go_right = false ;
1381+ do
1382+ {
1383+ go_left = node->left_ && is_interval_strictly_right_of_value (node->left_ );
1384+ go_right = node->right_ && is_interval_strictly_right_of_value (node->right_ );
1385+
1386+ if (go_left)
1387+ node = node->left_ ;
1388+ else if (go_right)
1389+ node = node->right_ ;
1390+ } while (go_left || go_right);
1391+
1392+ if (is_interval_strictly_right_of_value (node))
1393+ return node;
1394+
1395+ // We only end up when node == root_, otherwise we never went down the tree to begin with.
1396+ return nullptr ;
1397+ }
13591398
1399+ /* *
1400+ * Only works with deoverlapped trees.
1401+ * Removes all intervals from the given interval and produces a tree that contains the remaining intervals.
1402+ * This is basically the other punch overload with ival = [tree_lowest, tree_highest]
1403+ *
1404+ * @param ival The range in which to punch out the gaps as a new tree
1405+ */
1406+ interval_tree punch (interval_type const & ival) const
1407+ {
13601408 interval_tree result;
1361- auto i = std::begin (*this );
1362- if (ival.low () < i->interval ()->low ())
1363- result.insert ({ival.low (), i->interval ()->low ()});
13641409
1365- for ( auto e = end (); i != e; ++i )
1410+ if ( empty () )
13661411 {
1367- auto next = i;
1368- ++next;
1369- if (next != e)
1370- result.insert ({i->interval ()->high (), next->interval ()->low ()});
1371- else
1372- break ;
1412+ // Nothing to punch, so return the whole interval
1413+ result.insert (ival);
1414+ return result;
13731415 }
13741416
1375- if (i != end () && i->interval ()->high () < ival.high ())
1376- result.insert ({i->interval ()->high (), ival.high ()});
1417+ // These two helper functions help to offset the adjacent interval edge depending on the interval type.
13771418
1378- return result;
1419+ const auto low_with_offset_1 = [](interval_type const & interval) {
1420+ return interval.low () + (interval.within (interval.low ()) ? 1 : 0 );
1421+ };
1422+ const auto low_with_offset_minus_1 = [](interval_type const & interval) {
1423+ INTERVAL_TREE_CONSTEXPR_IF (std::is_unsigned<value_type>::value)
1424+ {
1425+ return static_cast <value_type>(
1426+ static_cast <std::make_signed<value_type>>(interval.low ()) -
1427+ (interval.within (interval.low ()) ? 1 : 0 )
1428+ );
1429+ }
1430+ return interval.low () - (interval.within (interval.low ()) ? 1 : 0 );
1431+ };
1432+ const auto high_with_offset_1 = [](interval_type const & interval) {
1433+ return interval.high () + (interval.within (interval.high ()) ? 1 : 0 );
1434+ };
1435+ const auto high_with_offset_minus_1 = [](interval_type const & interval) {
1436+ INTERVAL_TREE_CONSTEXPR_IF (std::is_unsigned<value_type>::value)
1437+ {
1438+ return static_cast <value_type>(
1439+ static_cast <std::make_signed<value_type>>(interval.high ()) -
1440+ (interval.within (interval.high ()) ? 1 : 0 )
1441+ );
1442+ }
1443+ return interval.high () - (interval.within (interval.high ()) ? 1 : 0 );
1444+ };
1445+ const auto is_empty_interval = [](interval_type const & interval) {
1446+ return !interval.within (interval.low ()) && !interval.within (interval.high ());
1447+ };
1448+ const auto insert_if_not_empty = [&](value_type left, value_type right) {
1449+ if (left <= right)
1450+ {
1451+ const auto interval = interval_type{left, right};
1452+ if (!is_empty_interval (interval))
1453+ result.insert (interval);
1454+ }
1455+ };
1456+
1457+ auto * first_not_right = find_first_not_right_of_i (ival.low );
1458+ if (first_not_right == nullptr )
1459+ {
1460+ // There is no interval not fully right of the interval. So ival is either fully right of the rest of
1461+ // the tree or the last interval overlaps ival.
1462+
1463+ auto last = crbegin ();
1464+ if (!ival.overlaps (*crbegin ()))
1465+ {
1466+ // ival is fully right of the tree, so just return a tree with this interval:
1467+ result.insert (ival);
1468+ return result;
1469+ }
1470+
1471+ if (std::max (ival.high (), last->high ()) == last.high ())
1472+ {
1473+ // The slice is not going beyond the last interval:
1474+ return {};
1475+ }
1476+
1477+ // Slice off the part overlapping over the end of last:
1478+ // TODO:
1479+ // if ()
1480+ }
1481+ else
1482+ {
1483+ // There is an interval left of or inside ival.
1484+
1485+ const auto low = [&]() {
1486+ if (first_not_right->interval ()->overlap (ival))
1487+ {
1488+ const auto joined = ival.join (*first_not_right->interval ()).high ();
1489+ return joined.high () + (joined.within (joined.high ()) ? 1 : 0 );
1490+ }
1491+ else
1492+ {
1493+ return ival.low ();
1494+ }
1495+ }();
1496+
1497+ auto next = increment ({first_not_right});
1498+
1499+ if (next == end ())
1500+ {
1501+ value_type high = next->low () - (next->interval ()->within (next->low () - 1 ));
1502+ }
1503+ else
1504+ {
1505+ // TODO:
1506+ }
1507+ }
13791508 }
13801509
13811510 iterator begin ()
0 commit comments