co-maps/generator/generator_tests/cluster_finder_tests.cpp
2025-11-22 13:58:55 +01:00

153 lines
3.6 KiB
C++

#include "testing/testing.hpp"
#include "generator/cluster_finder.hpp"
#include "geometry/mercator.hpp"
#include "geometry/point2d.hpp"
#include "geometry/rect2d.hpp"
#include "base/assert.hpp"
#include <cmath>
#include <list>
#include <string>
#include <vector>
namespace cluster_finder_tests
{
enum class Type
{
T1 = 1,
T2,
T3
};
std::string DebugPrint(Type const & t)
{
return "T" + std::to_string(static_cast<int>(t));
}
struct NamedPoint
{
NamedPoint(m2::PointD const & point, Type const & type, std::string const & name)
: m_point(point)
, m_type(type)
, m_name(name)
{}
size_t m_id = m_counter++;
m2::PointD m_point;
Type m_type;
std::string m_name;
private:
static size_t m_counter;
};
size_t NamedPoint::m_counter = 0;
m2::RectD GetLimitRect(NamedPoint const & p)
{
return m2::RectD(p.m_point, p.m_point);
}
bool operator==(NamedPoint const & left, NamedPoint const & right)
{
return left.m_id == right.m_id;
}
std::string DebugPrint(NamedPoint const & t)
{
return DebugPrint(t.m_point) + " " + DebugPrint(t.m_type) + " " + t.m_name;
}
auto const getRadiusMFunction = [](NamedPoint const & p)
{
switch (p.m_type)
{
case Type::T1: return 4000;
case Type::T2: return 8000;
case Type::T3: return 16000;
};
UNREACHABLE();
};
auto const isSameFunction = [](NamedPoint const & left, NamedPoint const & right)
{ return left.m_name == right.m_name && left.m_type == right.m_type; };
using ClusterT = std::vector<NamedPoint const *>;
void Sort(std::vector<ClusterT> & data)
{
for (auto & d : data)
std::sort(std::begin(d), std::end(d), [](NamedPoint const * l, NamedPoint const * r) { return l->m_id < r->m_id; });
std::sort(std::begin(data), std::end(data), [](ClusterT const & l, ClusterT const & r)
{
TEST(!l.empty(), ());
TEST(!r.empty(), ());
return l.front()->m_id < r.front()->m_id;
});
}
void Test(std::vector<NamedPoint> const & input, std::vector<ClusterT> & expected)
{
auto result = generator::GetClusters(input, getRadiusMFunction, isSameFunction);
Sort(result);
Sort(expected);
TEST_EQUAL(result, expected, ());
}
UNIT_TEST(ClustersFinder_Empty)
{
std::vector<ClusterT> expected;
Test({}, expected);
}
UNIT_TEST(ClustersFinder_OneElement)
{
std::vector<NamedPoint> in{NamedPoint({0.0, 0.0}, Type::T1, "name")};
std::vector<ClusterT> expected{{&in[0]}};
Test(in, expected);
}
UNIT_TEST(ClustersFinder_TwoElements)
{
std::vector<NamedPoint> in{NamedPoint({0.0, 0.0}, Type::T1, "name"), NamedPoint({0.0001, 0.0001}, Type::T1, "name")};
std::vector<ClusterT> expected{{&in[0], &in[1]}};
Test(in, expected);
}
UNIT_TEST(ClustersFinder_TwoClusters)
{
{
std::vector<NamedPoint> in{NamedPoint({0.0, 0.0}, Type::T1, "name1"),
NamedPoint({0.0001, 0.0001}, Type::T1, "name2")};
std::vector<ClusterT> expected{{&in[1]}, {&in[0]}};
Test(in, expected);
}
{
std::vector<NamedPoint> in{NamedPoint({0.0, 0.0}, Type::T1, "name"), NamedPoint({0.1, 0.1}, Type::T1, "name")};
std::vector<ClusterT> expected{{&in[0]}, {&in[1]}};
Test(in, expected);
}
}
UNIT_TEST(ClustersFinder_ThreeClusters)
{
std::vector<NamedPoint> in{
NamedPoint({0.0, 0.0}, Type::T1, "name"), NamedPoint({0.0, 0.00001}, Type::T1, "name"),
NamedPoint({0.0001, 0.0000}, Type::T1, "name"),
NamedPoint({0.0, 0.0}, Type::T2, "name"), NamedPoint({0.0, 0.001}, Type::T2, "name"),
NamedPoint({0.001, 0.0000}, Type::T2, "name"),
NamedPoint({0.0, 0.0}, Type::T1, "name21")};
std::vector<ClusterT> expected{{&in[1], &in[0], &in[2]}, {&in[3], &in[5], &in[4]}, {&in[6]}};
Test(in, expected);
}
} // namespace cluster_finder_tests