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