@@ -1347,35 +1347,164 @@ namespace lib_interval_tree
1347
1347
return punch ({min, max});
1348
1348
}
1349
1349
1350
+ // TODO: private
1350
1351
/* *
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*
1354
1356
*/
1355
- interval_tree punch (interval_type const & ival ) const
1357
+ node_type* find_first_not_right_of_i (value_type search_value ) const
1356
1358
{
1357
1359
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
+ }
1359
1398
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
+ {
1360
1408
interval_tree result;
1361
- auto i = std::begin (*this );
1362
- if (ival.low () < i->interval ()->low ())
1363
- result.insert ({ival.low (), i->interval ()->low ()});
1364
1409
1365
- for ( auto e = end (); i != e; ++i )
1410
+ if ( empty () )
1366
1411
{
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;
1373
1415
}
1374
1416
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.
1377
1418
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
+ }
1379
1508
}
1380
1509
1381
1510
iterator begin ()
0 commit comments