diff --git a/cpp/dbscan.cpp b/cpp/dbscan.cpp index 0f43514..6011473 100644 --- a/cpp/dbscan.cpp +++ b/cpp/dbscan.cpp @@ -44,8 +44,9 @@ auto Dbscan::fit_predict(std::vector const& points) -> std::vecto // derive num_bins out of it float const range_x{max[0] - min[0]}; float const range_y{max[1] - min[1]}; - auto const num_bins_x{static_cast(std::ceil(range_x / eps_))}; - auto const num_bins_y{static_cast(std::ceil(range_y / eps_))}; + // add 1e-7 to handle the case where range is exactly divisible by eps_ + auto const num_bins_x{static_cast(std::ceil((range_x + 1e-7f) / eps_))}; + auto const num_bins_y{static_cast(std::ceil((range_y + 1e-7f) / eps_))}; // count number of points in every bin counts_.assign(num_bins_x * num_bins_y, 0); diff --git a/python/dbscan_test.py b/python/dbscan_test.py index 52d49d3..634792b 100644 --- a/python/dbscan_test.py +++ b/python/dbscan_test.py @@ -61,5 +61,16 @@ def test_blobs(): assert all(np.count_nonzero(y_pred == label) == 500 for label in range(n_blobs)) +def test_points_on_border(): + """Test using two points on the border with an eps which divides (point - min_point) without remainder.""" + X = np.array([[0, 0], [1, 1]]) + + dbscan = py_dbscan.DBSCAN(0.5, 2) + y_pred = dbscan.fit_predict(X) + + assert y_pred.shape[0] == 2 + np.testing.assert_equal(y_pred, np.array([-1, -1])) + + if __name__ == "__main__": sys.exit(pytest.main([__file__, "-rP"]))