co-maps/libs/editor/edits_migration.cpp

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

111 lines
3.4 KiB
C++
Raw Permalink Normal View History

2025-11-22 13:58:55 +01:00
#include "editor/edits_migration.hpp"
#include "editor/feature_matcher.hpp"
#include "indexer/feature.hpp"
#include "indexer/feature_source.hpp"
#include "geometry/intersection_score.hpp"
#include "geometry/mercator.hpp"
#include "base/logging.hpp"
#include <optional>
namespace editor
{
FeatureID MigrateNodeFeatureIndex(osm::Editor::ForEachFeaturesNearByFn & forEach, XMLFeature const & xml,
FeatureStatus const featureStatus, GenerateIDFn const & generateID)
{
if (featureStatus == FeatureStatus::Created)
return generateID();
FeatureID fid;
auto count = 0;
forEach([&fid, &count](FeatureType const & ft)
{
if (ft.GetGeomType() != feature::GeomType::Point)
return;
// TODO(mgsergio): Check that ft and xml correspond to the same feature.
fid = ft.GetID();
++count;
}, mercator::FromLatLon(xml.GetCenter()));
if (count == 0)
MYTHROW(MigrationError, ("No pointed features returned."));
if (count > 1)
LOG(LWARNING, (count, "features returned for point", mercator::FromLatLon(xml.GetCenter())));
return fid;
}
FeatureID MigrateWayOrRelatonFeatureIndex(
osm::Editor::ForEachFeaturesNearByFn & forEach, XMLFeature const & xml,
FeatureStatus const /* Unused for now (we don't create/delete area features)*/,
GenerateIDFn const & /*Unused for the same reason*/)
{
std::optional<FeatureID> fid;
auto bestScore = 0.6; // initial score is used as a threshold.
auto geometry = xml.GetGeometry();
auto count = 0;
if (geometry.empty())
MYTHROW(MigrationError, ("Feature has invalid geometry", xml));
// This can be any point on a feature.
auto const someFeaturePoint = geometry[0];
forEach([&fid, &geometry, &count, &bestScore](FeatureType & ft)
{
if (ft.GetGeomType() != feature::GeomType::Area)
return;
++count;
std::vector<m2::PointD> ftGeometry;
assign_range(ftGeometry, ft.GetTrianglesAsPoints(FeatureType::BEST_GEOMETRY));
double score = 0.0;
try
{
score = matcher::ScoreTriangulatedGeometries(geometry, ftGeometry);
}
catch (geometry::NotAPolygonException & ex)
{
LOG(LWARNING, (ex.Msg()));
// Support migration for old application versions.
// TODO(a): To remove it when version 8.0.x will no longer be supported.
base::SortUnique(geometry);
base::SortUnique(ftGeometry);
score = matcher::ScoreTriangulatedGeometriesByPoints(geometry, ftGeometry);
}
if (score > bestScore)
{
bestScore = score;
fid = ft.GetID();
}
}, someFeaturePoint);
if (count == 0)
MYTHROW(MigrationError, ("No ways returned for point", someFeaturePoint));
if (!fid)
MYTHROW(MigrationError, ("None of returned ways suffice. Possibly, the feature has been deleted."));
return *fid;
}
FeatureID MigrateFeatureIndex(osm::Editor::ForEachFeaturesNearByFn & forEach, XMLFeature const & xml,
FeatureStatus const featureStatus, GenerateIDFn const & generateID)
{
switch (xml.GetType())
{
case XMLFeature::Type::Unknown: MYTHROW(MigrationError, ("Migration for XMLFeature::Type::Unknown is not possible"));
case XMLFeature::Type::Node: return MigrateNodeFeatureIndex(forEach, xml, featureStatus, generateID);
case XMLFeature::Type::Way:
case XMLFeature::Type::Relation: return MigrateWayOrRelatonFeatureIndex(forEach, xml, featureStatus, generateID);
}
UNREACHABLE();
}
} // namespace editor