Repo created

This commit is contained in:
Fr4nz D13trich 2025-11-22 13:58:55 +01:00
parent 4af19165ec
commit 68073add76
12458 changed files with 12350765 additions and 2 deletions

View file

@ -0,0 +1,214 @@
#include "generator/altitude_generator.hpp"
#include "generator/srtm_parser.hpp"
#include "routing/routing_helpers.hpp"
#include "indexer/feature.hpp"
#include "indexer/feature_altitude.hpp"
#include "indexer/feature_data.hpp"
#include "indexer/feature_processor.hpp"
#include "coding/files_container.hpp"
#include "coding/succinct_mapper.hpp"
#include "base/assert.hpp"
#include "base/checked_cast.hpp"
#include "base/logging.hpp"
#include "base/scope_guard.hpp"
#include "base/stl_helpers.hpp"
#include "defines.hpp"
#include "3party/succinct/elias_fano.hpp"
#include "3party/succinct/rs_bit_vector.hpp"
namespace routing
{
using namespace feature;
using namespace geometry;
namespace
{
class SrtmGetter : public AltitudeGetter
{
public:
explicit SrtmGetter(std::string const & srtmDir) : m_srtmManager(srtmDir) {}
// AltitudeGetter overrides:
Altitude GetAltitude(m2::PointD const & p) override { return m_srtmManager.GetAltitude(mercator::ToLatLon(p)); }
void PrintStatsAndPurge() override
{
LOG(LINFO, ("Srtm tiles number (x26Mb):", m_srtmManager.GeTilesNumber()));
m_srtmManager.Purge();
}
private:
generator::SrtmTileManager m_srtmManager;
};
class Processor
{
public:
struct FeatureAltitude
{
FeatureAltitude(uint32_t featureId, geometry::Altitudes && altitudes)
: m_featureId(featureId)
, m_altitudes(std::move(altitudes))
{}
uint32_t m_featureId;
feature::Altitudes m_altitudes;
};
explicit Processor(AltitudeGetter & altitudeGetter)
: m_minAltitude(geometry::kInvalidAltitude)
, m_altitudeGetter(altitudeGetter)
{}
void operator()(FeatureType & f, uint32_t id)
{
CHECK_EQUAL(f.GetID().m_index, id, ());
CHECK_EQUAL(id, m_altitudeAvailabilityBuilder.size(), ());
bool hasAltitude = false;
SCOPE_GUARD(altitudeAvailabilityBuilding, [&]() { m_altitudeAvailabilityBuilder.push_back(hasAltitude); });
if (!routing::IsRoad(feature::TypesHolder(f)))
return;
f.ParseGeometry(FeatureType::BEST_GEOMETRY);
size_t const pointsCount = f.GetPointsCount();
if (pointsCount == 0)
return;
geometry::Altitudes altitudes;
altitudes.reserve(pointsCount);
Altitude minFeatureAltitude = geometry::kInvalidAltitude;
for (size_t i = 0; i < pointsCount; ++i)
{
auto const & pt = f.GetPoint(i);
Altitude const a = m_altitudeGetter.GetAltitude(pt);
if (a == geometry::kInvalidAltitude)
{
// Print warning for missing altitude point (if not a ferry or so).
auto const type = CarModel::AllLimitsInstance().GetHighwayType(feature::TypesHolder(f));
if (type && *type != HighwayType::RouteFerry && *type != HighwayType::RouteShuttleTrain)
LOG(LWARNING, ("Invalid altitude at:", mercator::ToLatLon(pt)));
// One invalid point invalidates the whole feature.
return;
}
if (minFeatureAltitude == geometry::kInvalidAltitude)
minFeatureAltitude = a;
else
minFeatureAltitude = std::min(minFeatureAltitude, a);
altitudes.push_back(a);
}
hasAltitude = true;
m_featureAltitudes.emplace_back(id, std::move(altitudes));
if (m_minAltitude == geometry::kInvalidAltitude)
m_minAltitude = minFeatureAltitude;
else
m_minAltitude = std::min(minFeatureAltitude, m_minAltitude);
}
bool HasAltitudeInfo() const { return !m_featureAltitudes.empty(); }
public:
std::vector<FeatureAltitude> m_featureAltitudes;
succinct::bit_vector_builder m_altitudeAvailabilityBuilder;
Altitude m_minAltitude;
AltitudeGetter & m_altitudeGetter;
};
} // namespace
void BuildRoadAltitudes(std::string const & mwmPath, AltitudeGetter & altitudeGetter)
{
try
{
// Preparing altitude information.
Processor processor(altitudeGetter);
feature::ForEachFeature(mwmPath, processor);
processor.m_altitudeGetter.PrintStatsAndPurge();
if (!processor.HasAltitudeInfo())
{
// Possible for small islands like Bouvet or Willis.
LOG(LWARNING, ("No altitude information for road features of mwm:", mwmPath));
return;
}
FilesContainerW cont(mwmPath, FileWriter::OP_WRITE_EXISTING);
auto w = cont.GetWriter(ALTITUDES_FILE_TAG);
AltitudeHeader header;
header.m_minAltitude = processor.m_minAltitude;
auto const startOffset = w->Pos();
header.Serialize(*w);
{
// Altitude availability serialization.
coding::FreezeVisitor<Writer> visitor(*w);
succinct::rs_bit_vector(&processor.m_altitudeAvailabilityBuilder).map(visitor);
}
header.m_featureTableOffset = base::checked_cast<uint32_t>(w->Pos() - startOffset);
std::vector<uint32_t> offsets;
std::vector<uint8_t> deltas;
{
// Altitude info serialization to memory.
MemWriter<std::vector<uint8_t>> writer(deltas);
for (auto const & a : processor.m_featureAltitudes)
{
offsets.push_back(base::checked_cast<uint32_t>(writer.Pos()));
a.m_altitudes.Serialize(header.m_minAltitude, writer);
}
}
{
// Altitude offsets serialization.
CHECK(base::IsSortedAndUnique(offsets), ());
succinct::elias_fano::elias_fano_builder builder(offsets.back(), offsets.size());
for (uint32_t offset : offsets)
builder.push_back(offset);
coding::FreezeVisitor<Writer> visitor(*w);
succinct::elias_fano(&builder).map(visitor);
}
// Writing altitude info.
header.m_altitudesOffset = base::checked_cast<uint32_t>(w->Pos() - startOffset);
w->Write(deltas.data(), deltas.size());
w->WritePaddingByEnd(8);
header.m_endOffset = base::checked_cast<uint32_t>(w->Pos() - startOffset);
// Rewriting header info.
auto const endOffset = w->Pos();
w->Seek(startOffset);
header.Serialize(w);
w->Seek(endOffset);
LOG(LINFO, (ALTITUDES_FILE_TAG, "section is ready. The size is", header.m_endOffset));
if (processor.HasAltitudeInfo())
LOG(LINFO, ("Min altitude is", processor.m_minAltitude));
else
LOG(LINFO, ("Min altitude isn't defined."));
}
catch (RootException const & e)
{
LOG(LERROR, ("An exception happened while creating", ALTITUDES_FILE_TAG, "section:", e.what()));
}
}
void BuildRoadAltitudes(std::string const & mwmPath, std::string const & srtmDir)
{
LOG(LINFO, ("mwmPath =", mwmPath, "srtmDir =", srtmDir));
SrtmGetter srtmGetter(srtmDir);
BuildRoadAltitudes(mwmPath, srtmGetter);
}
} // namespace routing