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,716 @@
#include "transit/experimental/transit_data.hpp"
#include "transit/transit_entities.hpp"
#include "transit/transit_serdes.hpp"
#include "transit/transit_version.hpp"
#include "base/assert.hpp"
#include "base/file_name_utils.hpp"
#include "base/logging.hpp"
#include <algorithm>
#include <fstream>
#include <tuple>
namespace transit
{
namespace experimental
{
template <class E>
void ReadItems(uint32_t start, uint32_t end, std::string const & entityName, NonOwningReaderSource & src,
std::vector<E> & entities)
{
routing::transit::Deserializer<NonOwningReaderSource> deserializer(src);
CHECK_EQUAL(src.Pos(), start, ("Wrong", TRANSIT_FILE_TAG, "section format for:", entityName));
deserializer(entities);
CHECK_EQUAL(src.Pos(), end, ("Wrong", TRANSIT_FILE_TAG, "section format for", entityName));
}
struct ClearVisitor
{
template <class C>
void operator()(C & container, char const * /* entityName */) const
{
container.clear();
}
};
struct SortVisitor
{
template <class C>
void operator()(C & container, char const * /* entityName */) const
{
std::sort(container.begin(), container.end());
}
};
struct CheckValidVisitor
{
template <class C>
void operator()(C const & container, char const * entityName) const
{
for (auto const & item : container)
CHECK(item.IsValid(), (item, "is not valid in", entityName));
}
};
struct CheckUniqueVisitor
{
template <class C>
void operator()(C const & container, char const * entityName) const
{
auto const it = std::adjacent_find(container.begin(), container.end());
CHECK(it == container.end(), (*it, "is not unique in", entityName));
}
};
struct CheckSortedVisitor
{
template <typename C>
void operator()(C const & container, char const * entityName) const
{
CHECK(std::is_sorted(container.begin(), container.end()), (entityName, "is not sorted."));
}
};
TransitId GetIdFromJson(json_t * obj)
{
TransitId id;
FromJSONObject(obj, "id", id);
return id;
}
std::vector<TimeFromGateToStop> GetWeightsFromJson(json_t * obj)
{
json_t * arr = base::GetJSONObligatoryField(obj, "weights");
CHECK(json_is_array(arr), ());
size_t const count = json_array_size(arr);
std::vector<TimeFromGateToStop> weights;
weights.reserve(count);
for (size_t i = 0; i < count; ++i)
{
json_t * item = json_array_get(arr, i);
TimeFromGateToStop weight;
FromJSONObject(item, "stop_id", weight.m_stopId);
FromJSONObject(item, "time_to_stop", weight.m_timeSeconds);
weights.emplace_back(weight);
}
CHECK(!weights.empty(), ());
return weights;
}
template <class T>
std::vector<T> GetVectorFromJson(json_t * obj, std::string const & field, bool obligatory = true)
{
json_t * arr = base::GetJSONOptionalField(obj, field);
if (!arr)
{
if (obligatory)
CHECK(false, ("Obligatory field", field, "is absent."));
return {};
}
CHECK(json_is_array(arr), ());
size_t const count = json_array_size(arr);
std::vector<T> elements;
elements.reserve(count);
for (size_t i = 0; i < count; ++i)
{
json_t * item = json_array_get(arr, i);
T element = 0;
FromJSON(item, element);
elements.emplace_back(element);
}
return elements;
}
m2::PointD GetPointFromJson(json_t * obj)
{
CHECK(json_is_object(obj), ());
m2::PointD point;
FromJSONObject(obj, "x", point.x);
FromJSONObject(obj, "y", point.y);
return point;
}
std::vector<m2::PointD> GetPointsFromJson(json_t * obj)
{
json_t * arr = base::GetJSONObligatoryField(obj, "points");
CHECK(json_is_array(arr), ());
std::vector<m2::PointD> points;
size_t const count = json_array_size(arr);
points.reserve(count);
for (size_t i = 0; i < count; ++i)
{
json_t * item = json_array_get(arr, i);
points.emplace_back(GetPointFromJson(item));
}
return points;
}
TimeTable GetTimeTableFromJson(json_t * obj)
{
json_t * arr = base::GetJSONOptionalField(obj, "timetable");
if (!arr)
return TimeTable{};
CHECK(json_is_array(arr), ());
TimeTable timetable;
for (size_t i = 0; i < json_array_size(arr); ++i)
{
json_t * item = json_array_get(arr, i);
CHECK(json_is_object(item), ());
TransitId lineId;
FromJSONObject(item, "line_id", lineId);
std::vector<TimeInterval> timeIntervals;
auto const & rawValues = GetVectorFromJson<uint64_t>(item, "intervals");
timeIntervals.reserve(rawValues.size());
for (auto const & rawValue : rawValues)
timeIntervals.push_back(TimeInterval(rawValue));
timetable[lineId] = timeIntervals;
}
return timetable;
}
Translations GetTranslationsFromJson(json_t * obj, std::string const & field)
{
json_t * arr = base::GetJSONObligatoryField(obj, field);
CHECK(json_is_array(arr), ());
Translations translations;
for (size_t i = 0; i < json_array_size(arr); ++i)
{
json_t * item = json_array_get(arr, i);
CHECK(json_is_object(item), ());
std::string lang;
std::string text;
FromJSONObject(item, "lang", lang);
FromJSONObject(item, "text", text);
CHECK(translations.emplace(lang, text).second, ());
}
return translations;
}
ShapeLink GetShapeLinkFromJson(json_t * obj)
{
json_t * shapeLinkObj = base::GetJSONObligatoryField(obj, "shape");
CHECK(json_is_object(shapeLinkObj), ());
ShapeLink shapeLink;
FromJSONObject(shapeLinkObj, "id", shapeLink.m_shapeId);
FromJSONObject(shapeLinkObj, "start_index", shapeLink.m_startIndex);
FromJSONObject(shapeLinkObj, "end_index", shapeLink.m_endIndex);
return shapeLink;
}
FrequencyIntervals GetFrequencyIntervals(json_t * obj, std::string const & field)
{
json_t * arrTimeIntervals = base::GetJSONObligatoryField(obj, field);
size_t const countTimeIntervals = json_array_size(arrTimeIntervals);
FrequencyIntervals frequencyIntervals;
for (size_t i = 0; i < countTimeIntervals; ++i)
{
json_t * itemTimeIterval = json_array_get(arrTimeIntervals, i);
uint64_t rawTime = 0;
FromJSONObject(itemTimeIterval, "time_interval", rawTime);
Frequency frequency = 0;
FromJSONObject(itemTimeIterval, "frequency", frequency);
frequencyIntervals.AddInterval(TimeInterval(rawTime), frequency);
}
return frequencyIntervals;
}
Schedule GetScheduleFromJson(json_t * obj)
{
Schedule schedule;
json_t * scheduleObj = base::GetJSONObligatoryField(obj, "schedule");
Frequency defaultFrequency = 0;
FromJSONObject(scheduleObj, "def_frequency", defaultFrequency);
schedule.SetDefaultFrequency(defaultFrequency);
if (json_t * arrIntervals = base::GetJSONOptionalField(scheduleObj, "intervals"); arrIntervals)
{
for (size_t i = 0; i < json_array_size(arrIntervals); ++i)
{
json_t * item = json_array_get(arrIntervals, i);
uint32_t rawData = 0;
FromJSONObject(item, "dates_interval", rawData);
schedule.AddDatesInterval(DatesInterval(rawData), GetFrequencyIntervals(item, "time_intervals"));
}
}
if (json_t * arrExceptions = base::GetJSONOptionalField(scheduleObj, "exceptions"); arrExceptions)
{
for (size_t i = 0; i < json_array_size(arrExceptions); ++i)
{
json_t * item = json_array_get(arrExceptions, i);
uint32_t rawData = 0;
FromJSONObject(item, "exception", rawData);
schedule.AddDateException(DateException(rawData), GetFrequencyIntervals(item, "time_intervals"));
}
}
return schedule;
}
std::tuple<OsmId, FeatureId, TransitId> CalculateIds(base::Json const & obj, OsmIdToFeatureIdsMap const & mapping)
{
OsmId osmId = kInvalidOsmId;
FeatureId featureId = kInvalidFeatureId;
TransitId id = kInvalidTransitId;
// Osm id is present in subway items and is absent in all other public transport items.
FromJSONObjectOptionalField(obj.get(), "osm_id", osmId);
FromJSONObjectOptionalField(obj.get(), "id", id);
if (osmId == 0)
{
osmId = kInvalidOsmId;
}
else
{
FromJSONObjectOptionalField(obj.get(), "feature_id", featureId);
base::GeoObjectId const geoId(osmId);
auto const it = mapping.find(geoId);
if (it != mapping.cend())
{
CHECK(!it->second.empty(),
("Osm id", osmId, "encoded as", geoId.GetEncodedId(), "from transit does not correspond to any feature."));
if (it->second.size() != 1)
{
// |osmId| corresponds to several feature ids. It may happen in case of stops,
// if a stop is present as a relation. It's a rare case.
LOG(LWARNING,
("Osm id", osmId, "encoded as", geoId.GetEncodedId(), "corresponds to", it->second.size(), "feature ids."));
}
featureId = it->second[0];
}
}
return {osmId, featureId, id};
}
void Read(base::Json const & obj, std::vector<Network> & networks)
{
std::string title;
FromJSONObject(obj.get(), "title", title);
networks.emplace_back(GetIdFromJson(obj.get()), title);
}
void Read(base::Json const & obj, std::vector<Route> & routes)
{
TransitId const id = GetIdFromJson(obj.get());
TransitId networkId;
std::string routeType;
std::string color;
std::string title;
FromJSONObject(obj.get(), "network_id", networkId);
FromJSONObject(obj.get(), "color", color);
FromJSONObject(obj.get(), "type", routeType);
FromJSONObject(obj.get(), "title", title);
routes.emplace_back(id, networkId, routeType, title, color);
}
void Read(base::Json const & obj, std::vector<Line> & lines)
{
TransitId const id = GetIdFromJson(obj.get());
TransitId routeId;
FromJSONObject(obj.get(), "route_id", routeId);
ShapeLink const shapeLink = GetShapeLinkFromJson(obj.get());
std::string title;
FromJSONObject(obj.get(), "title", title);
IdList const & stopIds = GetVectorFromJson<TransitId>(obj.get(), "stops_ids");
Schedule const & schedule = GetScheduleFromJson(obj.get());
lines.emplace_back(id, routeId, shapeLink, title, stopIds, schedule);
}
void Read(base::Json const & obj, std::vector<LineMetadata> & linesMetadata)
{
TransitId const id = GetIdFromJson(obj.get());
json_t * arr = base::GetJSONObligatoryField(obj.get(), "shape_segments");
CHECK(json_is_array(arr), ());
size_t const count = json_array_size(arr);
LineSegmentsOrder segmentsOrder;
segmentsOrder.reserve(count);
for (size_t i = 0; i < count; ++i)
{
json_t * item = json_array_get(arr, i);
LineSegmentOrder lineSegmentOrder;
FromJSONObject(item, "order", lineSegmentOrder.m_order);
FromJSONObject(item, "start_index", lineSegmentOrder.m_segment.m_startIdx);
FromJSONObject(item, "end_index", lineSegmentOrder.m_segment.m_endIdx);
segmentsOrder.emplace_back(lineSegmentOrder);
}
linesMetadata.emplace_back(id, segmentsOrder);
}
void Read(base::Json const & obj, std::vector<Stop> & stops, OsmIdToFeatureIdsMap const & mapping)
{
auto const & [osmId, featureId, id] = CalculateIds(obj, mapping);
std::string title;
FromJSONObject(obj.get(), "title", title);
TimeTable const timetable = GetTimeTableFromJson(obj.get());
m2::PointD const point = GetPointFromJson(base::GetJSONObligatoryField(obj.get(), "point"));
IdList const & transferIds = GetVectorFromJson<TransitId>(obj.get(), "transfer_ids", false /* obligatory */);
stops.emplace_back(id, featureId, osmId, title, timetable, point, transferIds);
}
void Read(base::Json const & obj, std::vector<Shape> & shapes)
{
TransitId const id = GetIdFromJson(obj.get());
std::vector<m2::PointD> const polyline = GetPointsFromJson(obj.get());
shapes.emplace_back(id, polyline);
}
void Read(base::Json const & obj, std::vector<Edge> & edges, EdgeIdToFeatureId & edgeFeatureIds)
{
TransitId stopFrom = kInvalidTransitId;
TransitId stopTo = kInvalidTransitId;
FromJSONObject(obj.get(), "stop_id_from", stopFrom);
FromJSONObject(obj.get(), "stop_id_to", stopTo);
EdgeWeight weight;
FromJSONObject(obj.get(), "weight", weight);
TransitId lineId = 0;
ShapeLink shapeLink;
bool isTransfer = false;
FromJSONObjectOptionalField(obj.get(), "line_id", lineId);
TransitId featureId = kInvalidFeatureId;
FromJSONObject(obj.get(), "feature_id", featureId);
if (lineId == 0)
{
lineId = kInvalidTransitId;
isTransfer = true;
}
else
{
shapeLink = GetShapeLinkFromJson(obj.get());
}
edges.emplace_back(stopFrom, stopTo, weight, lineId, isTransfer, shapeLink);
edgeFeatureIds.emplace(EdgeId(stopFrom, stopTo, lineId), featureId);
}
void Read(base::Json const & obj, std::vector<Transfer> & transfers)
{
TransitId const id = GetIdFromJson(obj.get());
m2::PointD const & point = GetPointFromJson(base::GetJSONObligatoryField(obj.get(), "point"));
IdList const & stopIds = GetVectorFromJson<TransitId>(obj.get(), "stops_ids");
transfers.emplace_back(id, point, stopIds);
}
void Read(base::Json const & obj, std::vector<Gate> & gates, OsmIdToFeatureIdsMap const & mapping)
{
auto const & [osmId, featureId, id] = CalculateIds(obj, mapping);
std::vector<TimeFromGateToStop> const weights = GetWeightsFromJson(obj.get());
bool isEntrance = false;
bool isExit = false;
FromJSONObject(obj.get(), "entrance", isEntrance);
FromJSONObject(obj.get(), "exit", isExit);
m2::PointD const point = GetPointFromJson(base::GetJSONObligatoryField(obj.get(), "point"));
gates.emplace_back(id, featureId, osmId, isEntrance, isExit, weights, point);
}
template <typename... Args>
void ReadData(std::string const & path, Args &&... args)
{
std::ifstream input;
input.exceptions(std::ifstream::badbit);
try
{
input.open(path);
CHECK(input.is_open(), (path));
std::string line;
while (std::getline(input, line))
{
if (line.empty())
continue;
base::Json jsonObject(line);
CHECK(jsonObject.get() != nullptr, ("Error parsing json from line:", line));
Read(jsonObject, std::forward<Args>(args)...);
}
}
catch (std::ifstream::failure const & se)
{
LOG(LERROR, ("Exception reading line-by-line json from file", path, se.what()));
}
catch (base::Json::Exception const & je)
{
LOG(LERROR, ("Exception parsing json", path, je.what()));
}
}
void TransitData::DeserializeFromJson(std::string const & dirWithJsons, OsmIdToFeatureIdsMap const & mapping)
{
ReadData(base::JoinPath(dirWithJsons, kNetworksFile), m_networks);
ReadData(base::JoinPath(dirWithJsons, kRoutesFile), m_routes);
ReadData(base::JoinPath(dirWithJsons, kLinesFile), m_lines);
ReadData(base::JoinPath(dirWithJsons, kLinesMetadataFile), m_linesMetadata);
ReadData(base::JoinPath(dirWithJsons, kStopsFile), m_stops, mapping);
ReadData(base::JoinPath(dirWithJsons, kShapesFile), m_shapes);
ReadData(base::JoinPath(dirWithJsons, kEdgesFile), m_edges, m_edgeFeatureIds);
ReadData(base::JoinPath(dirWithJsons, kEdgesTransferFile), m_edges, m_edgeFeatureIds);
ReadData(base::JoinPath(dirWithJsons, kTransfersFile), m_transfers);
ReadData(base::JoinPath(dirWithJsons, kGatesFile), m_gates, mapping);
}
void TransitData::Serialize(Writer & writer)
{
auto const startOffset = writer.Pos();
routing::transit::Serializer<Writer> serializer(writer);
routing::transit::FixedSizeSerializer<Writer> fixedSizeSerializer(writer);
m_header = TransitHeader();
m_header.m_version = static_cast<uint16_t>(TransitVersion::AllPublicTransport);
fixedSizeSerializer(m_header);
m_header.m_stopsOffset = base::checked_cast<uint32_t>(writer.Pos() - startOffset);
serializer(m_stops);
m_header.m_gatesOffset = base::checked_cast<uint32_t>(writer.Pos() - startOffset);
serializer(m_gates);
m_header.m_edgesOffset = base::checked_cast<uint32_t>(writer.Pos() - startOffset);
serializer(m_edges);
m_header.m_transfersOffset = base::checked_cast<uint32_t>(writer.Pos() - startOffset);
serializer(m_transfers);
m_header.m_linesOffset = base::checked_cast<uint32_t>(writer.Pos() - startOffset);
serializer(m_lines);
m_header.m_linesMetadataOffset = base::checked_cast<uint32_t>(writer.Pos() - startOffset);
serializer(m_linesMetadata);
m_header.m_shapesOffset = base::checked_cast<uint32_t>(writer.Pos() - startOffset);
serializer(m_shapes);
m_header.m_routesOffset = base::checked_cast<uint32_t>(writer.Pos() - startOffset);
serializer(m_routes);
m_header.m_networksOffset = base::checked_cast<uint32_t>(writer.Pos() - startOffset);
serializer(m_networks);
m_header.m_endOffset = base::checked_cast<uint32_t>(writer.Pos() - startOffset);
// Overwriting updated header.
CHECK(m_header.IsValid(), (m_header));
auto const endOffset = writer.Pos();
writer.Seek(startOffset);
fixedSizeSerializer(m_header);
writer.Seek(endOffset);
LOG(LINFO, (TRANSIT_FILE_TAG, "experimental section is ready. Header:", m_header));
}
void TransitData::Deserialize(Reader & reader)
{
DeserializeWith(reader, [this](NonOwningReaderSource & src)
{
ReadStops(src);
ReadGates(src);
ReadEdges(src);
ReadTransfers(src);
ReadLines(src);
ReadLinesMetadata(src);
ReadShapes(src);
ReadRoutes(src);
ReadNetworks(src);
});
}
void TransitData::DeserializeForRouting(Reader & reader)
{
DeserializeWith(reader, [this](NonOwningReaderSource & src)
{
ReadStops(src);
ReadGates(src);
ReadEdges(src);
src.Skip(m_header.m_linesOffset - src.Pos());
ReadLines(src);
});
}
void TransitData::DeserializeForRendering(Reader & reader)
{
DeserializeWith(reader, [this](NonOwningReaderSource & src)
{
ReadStops(src);
src.Skip(m_header.m_edgesOffset - src.Pos());
ReadEdges(src);
src.Skip(m_header.m_transfersOffset - src.Pos());
ReadTransfers(src);
ReadLines(src);
ReadLinesMetadata(src);
ReadShapes(src);
ReadRoutes(src);
});
}
void TransitData::DeserializeForCrossMwm(Reader & reader)
{
DeserializeWith(reader, [this](NonOwningReaderSource & src)
{
ReadStops(src);
src.Skip(m_header.m_edgesOffset - src.Pos());
ReadEdges(src);
});
}
void TransitData::Clear()
{
ClearVisitor const visitor;
Visit(visitor);
}
void TransitData::CheckValid() const
{
CheckValidVisitor const visitor;
Visit(visitor);
}
void TransitData::CheckSorted() const
{
CheckSortedVisitor const visitor;
Visit(visitor);
}
void TransitData::CheckUnique() const
{
CheckUniqueVisitor const visitor;
Visit(visitor);
}
bool TransitData::IsEmpty() const
{
// |m_transfers| and |m_gates| may be empty and it is ok.
return m_networks.empty() || m_routes.empty() || m_lines.empty() || m_shapes.empty() || m_stops.empty() ||
m_edges.empty();
}
void TransitData::Sort()
{
SortVisitor const visitor;
Visit(visitor);
}
void TransitData::SetGatePedestrianSegments(size_t gateIdx, std::vector<SingleMwmSegment> const & seg)
{
CHECK_LESS(gateIdx, m_gates.size(), ());
m_gates[gateIdx].SetBestPedestrianSegments(seg);
}
void TransitData::SetStopPedestrianSegments(size_t stopIdx, std::vector<SingleMwmSegment> const & seg)
{
CHECK_LESS(stopIdx, m_stops.size(), ());
m_stops[stopIdx].SetBestPedestrianSegments(seg);
}
void TransitData::ReadHeader(NonOwningReaderSource & src)
{
routing::transit::FixedSizeDeserializer<NonOwningReaderSource> fixedSizeDeserializer(src);
fixedSizeDeserializer(m_header);
CHECK_EQUAL(src.Pos(), m_header.m_stopsOffset, ("Wrong", TRANSIT_FILE_TAG, "section format."));
CHECK(m_header.IsValid(), ());
}
void TransitData::ReadStops(NonOwningReaderSource & src)
{
ReadItems(m_header.m_stopsOffset, m_header.m_gatesOffset, "stops", src, m_stops);
}
void TransitData::ReadGates(NonOwningReaderSource & src)
{
ReadItems(m_header.m_gatesOffset, m_header.m_edgesOffset, "gates", src, m_gates);
}
void TransitData::ReadEdges(NonOwningReaderSource & src)
{
ReadItems(m_header.m_edgesOffset, m_header.m_transfersOffset, "edges", src, m_edges);
}
void TransitData::ReadTransfers(NonOwningReaderSource & src)
{
ReadItems(m_header.m_transfersOffset, m_header.m_linesOffset, "transfers", src, m_transfers);
}
void TransitData::ReadLines(NonOwningReaderSource & src)
{
ReadItems(m_header.m_linesOffset, m_header.m_linesMetadataOffset, "lines", src, m_lines);
}
void TransitData::ReadLinesMetadata(NonOwningReaderSource & src)
{
ReadItems(m_header.m_linesMetadataOffset, m_header.m_shapesOffset, "linesMetadata", src, m_linesMetadata);
}
void TransitData::ReadShapes(NonOwningReaderSource & src)
{
ReadItems(m_header.m_shapesOffset, m_header.m_routesOffset, "shapes", src, m_shapes);
}
void TransitData::ReadRoutes(NonOwningReaderSource & src)
{
ReadItems(m_header.m_routesOffset, m_header.m_networksOffset, "routes", src, m_routes);
}
void TransitData::ReadNetworks(NonOwningReaderSource & src)
{
ReadItems(m_header.m_networksOffset, m_header.m_endOffset, "networks", src, m_networks);
}
} // namespace experimental
} // namespace transit

View file

@ -0,0 +1,110 @@
#pragma once
#include "transit/experimental/transit_types_experimental.hpp"
#include "coding/reader.hpp"
#include "coding/writer.hpp"
#include "base/geo_object_id.hpp"
#include "base/visitor.hpp"
#include <cstring>
#include <map>
#include <string>
#include <unordered_map>
#include <vector>
#include "cppjansson/cppjansson.hpp"
namespace transit
{
namespace experimental
{
using OsmIdToFeatureIdsMap = std::map<base::GeoObjectId, std::vector<FeatureId>>;
using EdgeIdToFeatureId = std::unordered_map<EdgeId, uint32_t, EdgeIdHasher>;
// Functions for parsing one line of line-by-line json and creating corresponding item in container.
void Read(base::Json const & obj, std::vector<Network> & networks);
void Read(base::Json const & obj, std::vector<Route> & routes);
void Read(base::Json const & obj, std::vector<Line> & lines);
void Read(base::Json const & obj, std::vector<LineMetadata> & linesMetadata);
void Read(base::Json const & obj, std::vector<Stop> & stops, OsmIdToFeatureIdsMap const & mapping);
void Read(base::Json const & obj, std::vector<Shape> & shapes);
void Read(base::Json const & obj, std::vector<Edge> & edges, EdgeIdToFeatureId & edgeFeatureIds);
void Read(base::Json const & obj, std::vector<Transfer> & transfers);
void Read(base::Json const & obj, std::vector<Gate> & gates, OsmIdToFeatureIdsMap const & mapping);
/// \brief The class contains all the information to make TRANSIT_FILE_TAG section.
class TransitData
{
public:
void DeserializeFromJson(std::string const & dirWithJsons, OsmIdToFeatureIdsMap const & mapping);
/// \note This method changes only |m_header| and fills it with correct offsets.
void Serialize(Writer & writer);
void Deserialize(Reader & reader);
void DeserializeForRouting(Reader & reader);
void DeserializeForRendering(Reader & reader);
void DeserializeForCrossMwm(Reader & reader);
void Clear();
void CheckValid() const;
void CheckSorted() const;
void CheckUnique() const;
bool IsEmpty() const;
/// \brief Sorts all class fields by their ids.
void Sort();
void SetGatePedestrianSegments(size_t gateIdx, std::vector<SingleMwmSegment> const & seg);
void SetStopPedestrianSegments(size_t stopIdx, std::vector<SingleMwmSegment> const & seg);
std::vector<Stop> const & GetStops() const { return m_stops; }
std::vector<Gate> const & GetGates() const { return m_gates; }
std::vector<Edge> const & GetEdges() const { return m_edges; }
std::vector<Transfer> const & GetTransfers() const { return m_transfers; }
std::vector<Line> const & GetLines() const { return m_lines; }
std::vector<LineMetadata> const & GetLinesMetadata() const { return m_linesMetadata; }
std::vector<Shape> const & GetShapes() const { return m_shapes; }
std::vector<Route> const & GetRoutes() const { return m_routes; }
std::vector<Network> const & GetNetworks() const { return m_networks; }
EdgeIdToFeatureId const & GetEdgeIdToFeatureId() const { return m_edgeFeatureIds; }
private:
DECLARE_VISITOR_AND_DEBUG_PRINT(TransitData, visitor(m_stops, "stops"), visitor(m_gates, "gates"),
visitor(m_edges, "edges"), visitor(m_transfers, "transfers"),
visitor(m_lines, "lines"), visitor(m_shapes, "shapes"),
visitor(m_networks, "networks"), visitor(m_routes, "routes"))
friend TransitData FillTestTransitData();
/// \brief Reads transit form |src|.
/// \note Before calling any of the method except for ReadHeader() |m_header| has to be filled.
void ReadHeader(NonOwningReaderSource & src);
void ReadStops(NonOwningReaderSource & src);
void ReadGates(NonOwningReaderSource & src);
void ReadEdges(NonOwningReaderSource & src);
void ReadTransfers(NonOwningReaderSource & src);
void ReadLines(NonOwningReaderSource & src);
void ReadLinesMetadata(NonOwningReaderSource & src);
void ReadShapes(NonOwningReaderSource & src);
void ReadRoutes(NonOwningReaderSource & src);
void ReadNetworks(NonOwningReaderSource & src);
template <typename Fn>
void DeserializeWith(Reader & reader, Fn && fn)
{
NonOwningReaderSource src(reader);
ReadHeader(src);
fn(src);
}
TransitHeader m_header;
std::vector<Network> m_networks;
std::vector<Route> m_routes;
std::vector<Stop> m_stops;
std::vector<Gate> m_gates;
std::vector<Edge> m_edges;
std::vector<Transfer> m_transfers;
std::vector<Line> m_lines;
std::vector<LineMetadata> m_linesMetadata;
std::vector<Shape> m_shapes;
EdgeIdToFeatureId m_edgeFeatureIds;
};
} // namespace experimental
} // namespace transit

View file

@ -0,0 +1,567 @@
#include "transit/experimental/transit_types_experimental.hpp"
#include <tuple>
namespace transit
{
namespace experimental
{
std::string GetTranslation(Translations const & titles)
{
CHECK(!titles.empty(), ());
// If there is only one language we return title in this only translation.
if (titles.size() == 1)
return titles.begin()->second;
// Otherwise we try to extract default language for this region.
auto it = titles.find("default");
if (it != titles.end())
return it->second;
// If there is no default language we return one of the represented translations.
return titles.begin()->second;
}
// TransitHeader ----------------------------------------------------------------------------------
bool TransitHeader::IsValid() const
{
return m_stopsOffset <= m_gatesOffset && m_gatesOffset <= m_transfersOffset && m_transfersOffset <= m_linesOffset &&
m_linesOffset <= m_linesMetadataOffset && m_linesMetadataOffset <= m_shapesOffset &&
m_shapesOffset <= m_routesOffset && m_routesOffset <= m_networksOffset && m_networksOffset <= m_endOffset;
}
// SingleMwmSegment --------------------------------------------------------------------------------
SingleMwmSegment::SingleMwmSegment(FeatureId featureId, uint32_t segmentIdx, bool forward)
: m_featureId(featureId)
, m_segmentIdx(segmentIdx)
, m_forward(forward)
{}
bool SingleMwmSegment::operator==(SingleMwmSegment const & rhs) const
{
return std::tie(m_featureId, m_segmentIdx, m_forward) == std::tie(rhs.m_featureId, rhs.m_segmentIdx, rhs.m_forward);
}
// IdBundle ----------------------------------------------------------------------------------------
IdBundle::IdBundle(bool serializeFeatureIdOnly) : m_serializeFeatureIdOnly(serializeFeatureIdOnly) {}
IdBundle::IdBundle(FeatureId featureId, OsmId osmId, bool serializeFeatureIdOnly)
: m_featureId(featureId)
, m_osmId(osmId)
, m_serializeFeatureIdOnly(serializeFeatureIdOnly)
{}
bool IdBundle::operator<(IdBundle const & rhs) const
{
CHECK_EQUAL(m_serializeFeatureIdOnly, rhs.m_serializeFeatureIdOnly, ());
if (m_serializeFeatureIdOnly)
return m_featureId < rhs.m_featureId;
return std::tie(m_featureId, m_osmId) < std::tie(rhs.m_featureId, rhs.m_osmId);
}
bool IdBundle::operator==(IdBundle const & rhs) const
{
CHECK_EQUAL(m_serializeFeatureIdOnly, rhs.m_serializeFeatureIdOnly, ());
return m_serializeFeatureIdOnly ? m_featureId == rhs.m_featureId
: m_featureId == rhs.m_featureId && m_osmId == rhs.m_osmId;
}
bool IdBundle::operator!=(IdBundle const & rhs) const
{
return !(*this == rhs);
}
bool IdBundle::IsValid() const
{
return m_serializeFeatureIdOnly ? m_featureId != kInvalidFeatureId
: m_featureId != kInvalidFeatureId && m_osmId != kInvalidOsmId;
}
void IdBundle::SetOsmId(OsmId osmId)
{
m_osmId = osmId;
}
void IdBundle::SetFeatureId(FeatureId featureId)
{
m_featureId = featureId;
}
OsmId IdBundle::GetOsmId() const
{
return m_osmId;
}
FeatureId IdBundle::GetFeatureId() const
{
return m_featureId;
}
bool IdBundle::SerializeFeatureIdOnly() const
{
return m_serializeFeatureIdOnly;
}
// Network -----------------------------------------------------------------------------------------
Network::Network(TransitId id, std::string const & title) : m_id(id), m_title(title) {}
Network::Network(TransitId id) : m_id(id), m_title{} {}
bool Network::operator<(Network const & rhs) const
{
return m_id < rhs.m_id;
}
bool Network::operator==(Network const & rhs) const
{
return m_id == rhs.m_id;
}
bool Network::IsValid() const
{
return m_id != kInvalidTransitId;
}
TransitId Network::GetId() const
{
return m_id;
}
std::string const & Network::GetTitle() const
{
return m_title;
}
// Route -------------------------------------------------------------------------------------------
Route::Route(TransitId id, TransitId networkId, std::string const & routeType, std::string const & title,
std::string const & color)
: m_id(id)
, m_networkId(networkId)
, m_routeType(routeType)
, m_title(title)
, m_color(color)
{}
bool Route::operator<(Route const & rhs) const
{
return m_id < rhs.m_id;
}
bool Route::operator==(Route const & rhs) const
{
return m_id == rhs.m_id;
}
bool Route::IsValid() const
{
return m_id != kInvalidTransitId && m_networkId != kInvalidTransitId && !m_routeType.empty();
}
TransitId Route::GetId() const
{
return m_id;
}
std::string const & Route::GetTitle() const
{
return m_title;
}
std::string const & Route::GetType() const
{
return m_routeType;
}
std::string const & Route::GetColor() const
{
return m_color;
}
TransitId Route::GetNetworkId() const
{
return m_networkId;
}
// Line --------------------------------------------------------------------------------------------
Line::Line(TransitId id, TransitId routeId, ShapeLink const & shapeLink, std::string const & title,
IdList const & stopIds, Schedule const & schedule)
: m_id(id)
, m_routeId(routeId)
, m_shapeLink(shapeLink)
, m_title(title)
, m_stopIds(stopIds)
, m_schedule(schedule)
{}
bool Line::operator<(Line const & rhs) const
{
return m_id < rhs.m_id;
}
bool Line::operator==(Line const & rhs) const
{
return m_id == rhs.m_id;
}
bool Line::IsValid() const
{
return m_id != kInvalidTransitId && m_routeId != kInvalidTransitId && m_shapeLink.m_shapeId != kInvalidTransitId &&
!m_stopIds.empty();
}
TransitId Line::GetId() const
{
return m_id;
}
std::string const & Line::GetTitle() const
{
return m_title;
}
TransitId Line::GetRouteId() const
{
return m_routeId;
}
ShapeLink const & Line::GetShapeLink() const
{
return m_shapeLink;
}
IdList const & Line::GetStopIds() const
{
return m_stopIds;
}
Schedule const & Line::GetSchedule() const
{
return m_schedule;
}
// LineMetadata ------------------------------------------------------------------------------------
LineMetadata::LineMetadata(TransitId id, LineSegmentsOrder const & segmentsOrder)
: m_id(id)
, m_segmentsOrder(segmentsOrder)
{}
bool LineMetadata::operator<(LineMetadata const & rhs) const
{
return m_id < rhs.GetId();
}
bool LineMetadata::operator==(LineMetadata const & rhs) const
{
return m_id == rhs.GetId();
}
bool LineMetadata::IsValid() const
{
return m_id != kInvalidTransitId;
}
TransitId LineMetadata::GetId() const
{
return m_id;
}
LineSegmentsOrder const & LineMetadata::GetLineSegmentsOrder() const
{
return m_segmentsOrder;
}
// Stop --------------------------------------------------------------------------------------------
Stop::Stop() : m_ids(true /* serializeFeatureIdOnly */) {}
Stop::Stop(TransitId id, FeatureId featureId, OsmId osmId, std::string const & title, TimeTable const & timetable,
m2::PointD const & point, IdList const & transferIds)
: m_id(id)
, m_ids(featureId, osmId, true /* serializeFeatureIdOnly */)
, m_title(title)
, m_timetable(timetable)
, m_point(point)
, m_transferIds(transferIds)
{}
Stop::Stop(TransitId id) : m_id(id), m_ids(true /* serializeFeatureIdOnly */) {}
bool Stop::operator<(Stop const & rhs) const
{
if (m_id != kInvalidTransitId || rhs.m_id != kInvalidTransitId)
return m_id < rhs.m_id;
return m_ids.GetFeatureId() < rhs.m_ids.GetFeatureId();
}
bool Stop::operator==(Stop const & rhs) const
{
if (m_id != kInvalidTransitId || rhs.m_id != kInvalidTransitId)
return m_id == rhs.m_id;
return m_ids.GetFeatureId() == rhs.m_ids.GetFeatureId() && m_ids.GetOsmId() == rhs.m_ids.GetOsmId();
}
bool Stop::IsValid() const
{
return ((m_id != kInvalidTransitId) || (m_ids.GetOsmId() != kInvalidOsmId) ||
(m_ids.GetFeatureId() != kInvalidFeatureId));
}
FeatureId Stop::GetId() const
{
return m_id;
}
FeatureId Stop::GetFeatureId() const
{
return m_ids.GetFeatureId();
}
OsmId Stop::GetOsmId() const
{
return m_ids.GetOsmId();
}
std::string const & Stop::GetTitle() const
{
return m_title;
}
TimeTable const & Stop::GetTimeTable() const
{
return m_timetable;
}
m2::PointD const & Stop::GetPoint() const
{
return m_point;
}
IdList const & Stop::GetTransferIds() const
{
return m_transferIds;
}
void Stop::SetBestPedestrianSegments(std::vector<SingleMwmSegment> const & seg)
{
m_bestPedestrianSegments = seg;
}
std::vector<SingleMwmSegment> const & Stop::GetBestPedestrianSegments() const
{
return m_bestPedestrianSegments;
}
// Gate --------------------------------------------------------------------------------------------
Gate::Gate() : m_ids(false /* serializeFeatureIdOnly */) {}
Gate::Gate(TransitId id, FeatureId featureId, OsmId osmId, bool entrance, bool exit,
std::vector<TimeFromGateToStop> const & weights, m2::PointD const & point)
: m_id(id)
, m_ids(featureId, osmId, false /* serializeFeatureIdOnly */)
, m_entrance(entrance)
, m_exit(exit)
, m_weights(weights)
, m_point(point)
{}
bool Gate::operator<(Gate const & rhs) const
{
return std::tie(m_id, m_ids, m_entrance, m_exit) < std::tie(rhs.m_id, rhs.m_ids, rhs.m_entrance, rhs.m_exit);
}
bool Gate::operator==(Gate const & rhs) const
{
return std::tie(m_id, m_ids, m_entrance, m_exit) == std::tie(rhs.m_id, rhs.m_ids, rhs.m_entrance, rhs.m_exit);
}
bool Gate::IsValid() const
{
return ((m_id != kInvalidTransitId) || (m_ids.GetOsmId() != kInvalidOsmId)) && (m_entrance || m_exit) &&
!m_weights.empty();
}
void Gate::SetBestPedestrianSegments(std::vector<SingleMwmSegment> const & seg)
{
m_bestPedestrianSegments = seg;
}
FeatureId Gate::GetFeatureId() const
{
return m_ids.GetFeatureId();
}
OsmId Gate::GetOsmId() const
{
return m_ids.GetOsmId();
}
TransitId Gate::GetId() const
{
return m_id;
}
std::vector<SingleMwmSegment> const & Gate::GetBestPedestrianSegments() const
{
return m_bestPedestrianSegments;
}
bool Gate::IsEntrance() const
{
return m_entrance;
}
bool Gate::IsExit() const
{
return m_exit;
}
std::vector<TimeFromGateToStop> const & Gate::GetStopsWithWeight() const
{
return m_weights;
}
m2::PointD const & Gate::GetPoint() const
{
return m_point;
}
// Edge --------------------------------------------------------------------------------------------
Edge::Edge(TransitId stop1Id, TransitId stop2Id, EdgeWeight weight, TransitId lineId, bool transfer,
ShapeLink const & shapeLink)
: m_stop1Id(stop1Id)
, m_stop2Id(stop2Id)
, m_weight(weight)
, m_isTransfer(transfer)
, m_lineId(lineId)
, m_shapeLink(shapeLink)
{}
bool Edge::operator<(Edge const & rhs) const
{
return std::tie(m_stop1Id, m_stop2Id, m_lineId) < std::tie(rhs.m_stop1Id, rhs.m_stop2Id, rhs.m_lineId);
}
bool Edge::operator==(Edge const & rhs) const
{
return std::tie(m_stop1Id, m_stop2Id, m_lineId) == std::tie(rhs.m_stop1Id, rhs.m_stop2Id, rhs.m_lineId);
}
bool Edge::operator!=(Edge const & rhs) const
{
return !(*this == rhs);
}
bool Edge::IsValid() const
{
if (m_isTransfer && (m_lineId != kInvalidTransitId || m_shapeLink.m_shapeId != kInvalidTransitId))
return false;
if (!m_isTransfer && m_lineId == kInvalidTransitId)
return false;
return m_stop1Id != kInvalidTransitId && m_stop2Id != kInvalidTransitId;
}
void Edge::SetWeight(EdgeWeight weight)
{
m_weight = weight;
}
TransitId Edge::GetStop1Id() const
{
return m_stop1Id;
}
TransitId Edge::GetStop2Id() const
{
return m_stop2Id;
}
EdgeWeight Edge::GetWeight() const
{
return m_weight;
}
TransitId Edge::GetLineId() const
{
return m_lineId;
}
bool Edge::IsTransfer() const
{
return m_isTransfer;
}
ShapeLink const & Edge::GetShapeLink() const
{
return m_shapeLink;
}
// Transfer ----------------------------------------------------------------------------------------
Transfer::Transfer(TransitId id, m2::PointD const & point, IdList const & stopIds)
: m_id(id)
, m_point(point)
, m_stopIds(stopIds)
{}
bool Transfer::operator<(Transfer const & rhs) const
{
return m_id < rhs.m_id;
}
bool Transfer::operator==(Transfer const & rhs) const
{
return m_id == rhs.m_id;
}
bool Transfer::IsValid() const
{
return m_id != kInvalidTransitId && m_stopIds.size() > 1;
}
TransitId Transfer::GetId() const
{
return m_id;
}
m2::PointD const & Transfer::GetPoint() const
{
return m_point;
}
IdList const & Transfer::GetStopIds() const
{
return m_stopIds;
}
// Shape -------------------------------------------------------------------------------------------
Shape::Shape(TransitId id, std::vector<m2::PointD> const & polyline) : m_id(id), m_polyline(polyline) {}
bool Shape::operator<(Shape const & rhs) const
{
return m_id < rhs.m_id;
}
bool Shape::operator==(Shape const & rhs) const
{
return m_id == rhs.m_id;
}
bool Shape::IsValid() const
{
return m_id != kInvalidTransitId && m_polyline.size() > 1;
}
TransitId Shape::GetId() const
{
return m_id;
}
std::vector<m2::PointD> const & Shape::GetPolyline() const
{
return m_polyline;
}
} // namespace experimental
} // namespace transit

View file

@ -0,0 +1,410 @@
#pragma once
#include "transit/transit_entities.hpp"
#include "indexer/feature_decl.hpp"
#include "geometry/point2d.hpp"
#include "base/visitor.hpp"
#include <limits>
#include <string>
#include <vector>
// This is the implementation of the new transit classes which support not only subway, but also
// public transport types from GTFS. Since it is experimental it exists at one time with
// subway classes for handling networks, stops and other transit entities. When the time comes this
// transit implementation will completely replace the subway classes, they will be removed, and the
// experimental namespace will be also removed.
namespace routing
{
namespace transit
{
template <class Sink>
class Serializer;
template <class Source>
class Deserializer;
template <typename Sink>
class FixedSizeSerializer;
template <typename Sink>
class FixedSizeDeserializer;
} // namespace transit
} // namespace routing
namespace transit
{
namespace experimental
{
#define DECLARE_TRANSIT_TYPES_FRIENDS \
template <class Sink> \
friend class routing::transit::Serializer; \
template <class Source> \
friend class routing::transit::Deserializer; \
template <typename Sink> \
friend class routing::transit::FixedSizeSerializer; \
template <typename Sink> \
friend class routing::transit::FixedSizeDeserializer;
using FeatureId = uint32_t;
using OsmId = uint64_t;
OsmId constexpr kInvalidOsmId = std::numeric_limits<OsmId>::max();
class SingleMwmSegment
{
public:
SingleMwmSegment() = default;
SingleMwmSegment(FeatureId featureId, uint32_t segmentIdx, bool forward);
FeatureId GetFeatureId() const { return m_featureId; }
uint32_t GetSegmentIdx() const { return m_segmentIdx; }
bool IsForward() const { return m_forward; }
bool operator==(SingleMwmSegment const & rhs) const;
private:
DECLARE_TRANSIT_TYPES_FRIENDS
DECLARE_VISITOR_AND_DEBUG_PRINT(SingleMwmSegment, visitor(m_featureId, "feature_id"),
visitor(m_segmentIdx, "segment_idx"), visitor(m_forward, "forward"))
FeatureId m_featureId = kInvalidFeatureId;
uint32_t m_segmentIdx = 0;
bool m_forward = false;
};
/// \brief This class represents osm id and feature id of the same feature.
class IdBundle
{
public:
explicit IdBundle(bool serializeFeatureIdOnly);
IdBundle(FeatureId featureId, OsmId osmId, bool serializeFeatureIdOnly);
bool operator<(IdBundle const & rhs) const;
bool operator==(IdBundle const & rhs) const;
bool operator!=(IdBundle const & rhs) const;
bool IsValid() const;
void SetFeatureId(FeatureId featureId);
void SetOsmId(OsmId osmId);
FeatureId GetFeatureId() const;
OsmId GetOsmId() const;
bool SerializeFeatureIdOnly() const;
private:
DECLARE_TRANSIT_TYPES_FRIENDS
DECLARE_VISITOR_AND_DEBUG_PRINT(IdBundle, visitor(m_featureId, "feature_id"), visitor(m_osmId, "osm_id"))
FeatureId m_featureId = kInvalidFeatureId;
OsmId m_osmId = kInvalidOsmId;
bool m_serializeFeatureIdOnly = true;
};
struct TransitHeader
{
TransitHeader() = default;
bool IsValid() const;
DECLARE_TRANSIT_TYPES_FRIENDS
DECLARE_VISITOR_AND_DEBUG_PRINT(TransitHeader, visitor(m_version, "version"), visitor(m_reserve, "reserve"),
visitor(m_stopsOffset, "stops"), visitor(m_gatesOffset, "gatesOffset"),
visitor(m_edgesOffset, "edgesOffset"), visitor(m_transfersOffset, "transfersOffset"),
visitor(m_linesOffset, "linesOffset"),
visitor(m_linesMetadataOffset, "linesMetadataOffset"),
visitor(m_shapesOffset, "shapesOffset"), visitor(m_routesOffset, "routesOffset"),
visitor(m_networksOffset, "networksOffset"), visitor(m_endOffset, "endOffset"))
uint16_t m_version = 0;
uint16_t m_reserve = 0;
uint32_t m_stopsOffset = 0;
uint32_t m_gatesOffset = 0;
uint32_t m_edgesOffset = 0;
uint32_t m_transfersOffset = 0;
uint32_t m_linesOffset = 0;
uint32_t m_linesMetadataOffset = 0;
uint32_t m_shapesOffset = 0;
uint32_t m_routesOffset = 0;
uint32_t m_networksOffset = 0;
uint32_t m_endOffset = 0;
};
static_assert(sizeof(TransitHeader) == 44, "Wrong header size of transit section.");
class Network
{
public:
Network() = default;
Network(TransitId id, std::string const & title);
explicit Network(TransitId id);
bool operator<(Network const & rhs) const;
bool operator==(Network const & rhs) const;
bool IsValid() const;
TransitId GetId() const;
std::string const & GetTitle() const;
private:
DECLARE_TRANSIT_TYPES_FRIENDS
DECLARE_VISITOR_AND_DEBUG_PRINT(Network, visitor(m_id, "id"), visitor(m_title, "title"))
TransitId m_id = kInvalidTransitId;
std::string m_title;
};
class Route
{
public:
Route() = default;
Route(TransitId id, TransitId networkId, std::string const & routeType, std::string const & title,
std::string const & color);
bool operator<(Route const & rhs) const;
bool operator==(Route const & rhs) const;
bool IsValid() const;
TransitId GetId() const;
std::string const & GetTitle() const;
std::string const & GetType() const;
std::string const & GetColor() const;
TransitId GetNetworkId() const;
private:
DECLARE_TRANSIT_TYPES_FRIENDS
DECLARE_VISITOR_AND_DEBUG_PRINT(Route, visitor(m_id, "id"), visitor(m_networkId, "network_id"),
visitor(m_routeType, "type"), visitor(m_title, "title"), visitor(m_color, "color"))
TransitId m_id = kInvalidTransitId;
TransitId m_networkId = kInvalidTransitId;
std::string m_routeType;
std::string m_title;
std::string m_color;
};
class Line
{
public:
Line() = default;
Line(TransitId id, TransitId routeId, ShapeLink const & shapeLink, std::string const & title, IdList const & stopIds,
Schedule const & schedule);
bool operator<(Line const & rhs) const;
bool operator==(Line const & rhs) const;
bool IsValid() const;
TransitId GetId() const;
std::string const & GetTitle() const;
TransitId GetRouteId() const;
ShapeLink const & GetShapeLink() const;
IdList const & GetStopIds() const;
Schedule const & GetSchedule() const;
private:
DECLARE_TRANSIT_TYPES_FRIENDS
DECLARE_VISITOR_AND_DEBUG_PRINT(Line, visitor(m_id, "id"), visitor(m_routeId, "route_id"),
visitor(m_shapeLink, "shape_link"), visitor(m_title, "title"),
visitor(m_stopIds, "stop_ids"), visitor(m_schedule, "schedule"))
TransitId m_id = kInvalidTransitId;
TransitId m_routeId = kInvalidTransitId;
ShapeLink m_shapeLink;
std::string m_title;
IdList m_stopIds;
Schedule m_schedule;
};
class LineMetadata
{
public:
LineMetadata() = default;
LineMetadata(TransitId id, LineSegmentsOrder const & segmentsOrder);
bool operator<(LineMetadata const & rhs) const;
bool operator==(LineMetadata const & rhs) const;
bool IsValid() const;
TransitId GetId() const;
LineSegmentsOrder const & GetLineSegmentsOrder() const;
private:
DECLARE_TRANSIT_TYPES_FRIENDS
DECLARE_VISITOR_AND_DEBUG_PRINT(LineMetadata, visitor(m_id, "id"), visitor(m_segmentsOrder, "segments_order"))
TransitId m_id = kInvalidTransitId;
LineSegmentsOrder m_segmentsOrder;
};
class Stop
{
public:
Stop();
Stop(TransitId id, FeatureId featureId, OsmId osmId, std::string const & title, TimeTable const & timetable,
m2::PointD const & point, IdList const & transferIds);
explicit Stop(TransitId id);
bool operator<(Stop const & rhs) const;
bool operator==(Stop const & rhs) const;
bool IsValid() const;
void SetBestPedestrianSegments(std::vector<SingleMwmSegment> const & seg);
std::vector<SingleMwmSegment> const & GetBestPedestrianSegments() const;
FeatureId GetId() const;
FeatureId GetFeatureId() const;
OsmId GetOsmId() const;
std::string const & GetTitle() const;
TimeTable const & GetTimeTable() const;
m2::PointD const & GetPoint() const;
IdList const & GetTransferIds() const;
private:
DECLARE_TRANSIT_TYPES_FRIENDS
DECLARE_VISITOR_AND_DEBUG_PRINT(Stop, visitor(m_id, "id"), visitor(m_ids, "id_bundle"),
visitor(m_bestPedestrianSegments, "best_pedestrian_segments"),
visitor(m_title, "title"), visitor(m_timetable, "timetable"),
visitor(m_point, "point"), visitor(m_transferIds, "transfer_ids"))
TransitId m_id = kInvalidTransitId;
IdBundle m_ids;
// |m_bestPedestrianSegments| are segments which can be used for pedestrian routing to leave and
// enter the gate. The segments may be invalid because of map date. If so there's no pedestrian
// segment which can be used to reach the stop.
std::vector<SingleMwmSegment> m_bestPedestrianSegments;
std::string m_title;
TimeTable m_timetable;
m2::PointD m_point;
IdList m_transferIds;
};
class Gate
{
public:
Gate();
Gate(TransitId id, FeatureId featureId, OsmId osmId, bool entrance, bool exit,
std::vector<TimeFromGateToStop> const & weights, m2::PointD const & point);
bool operator<(Gate const & rhs) const;
bool operator==(Gate const & rhs) const;
bool IsValid() const;
TransitId GetId() const;
FeatureId GetFeatureId() const;
OsmId GetOsmId() const;
std::vector<SingleMwmSegment> const & GetBestPedestrianSegments() const;
void SetBestPedestrianSegments(std::vector<SingleMwmSegment> const & seg);
bool IsEntrance() const;
bool IsExit() const;
std::vector<TimeFromGateToStop> const & GetStopsWithWeight() const;
m2::PointD const & GetPoint() const;
private:
DECLARE_TRANSIT_TYPES_FRIENDS
DECLARE_VISITOR_AND_DEBUG_PRINT(Gate, visitor(m_id, "id"), visitor(m_ids, "id_bundle"),
visitor(m_bestPedestrianSegments, "best_pedestrian_segments"),
visitor(m_entrance, "entrance"), visitor(m_exit, "exit"),
visitor(m_weights, "weights"), visitor(m_point, "point"))
TransitId m_id = kInvalidTransitId;
// |m_ids| contains feature id of a feature which represents gates. Usually it's a
// point feature.
IdBundle m_ids;
// |m_bestPedestrianSegments| are segments which can be used for pedestrian routing to leave and
// enter the gate. The segments may be invalid because of map date. If so there's no pedestrian
// segment which can be used to reach the gate.
std::vector<SingleMwmSegment> m_bestPedestrianSegments;
bool m_entrance = true;
bool m_exit = true;
std::vector<TimeFromGateToStop> m_weights;
m2::PointD m_point;
};
class Edge
{
public:
Edge() = default;
Edge(TransitId stop1Id, TransitId stop2Id, EdgeWeight weight, TransitId lineId, bool transfer,
ShapeLink const & shapeLink);
bool operator<(Edge const & rhs) const;
bool operator==(Edge const & rhs) const;
bool operator!=(Edge const & rhs) const;
bool IsValid() const;
void SetWeight(EdgeWeight weight);
TransitId GetStop1Id() const;
TransitId GetStop2Id() const;
EdgeWeight GetWeight() const;
TransitId GetLineId() const;
bool IsTransfer() const;
ShapeLink const & GetShapeLink() const;
private:
DECLARE_TRANSIT_TYPES_FRIENDS
DECLARE_VISITOR_AND_DEBUG_PRINT(Edge, visitor(m_stop1Id, "stop1_id"), visitor(m_stop2Id, "stop2_id"),
visitor(m_weight, "weight"), visitor(m_isTransfer, "is_transfer"),
visitor(m_lineId, "line_id"), visitor(m_shapeLink, "shape_link"))
TransitId m_stop1Id = kInvalidTransitId;
TransitId m_stop2Id = kInvalidTransitId;
EdgeWeight m_weight = 0;
bool m_isTransfer = false;
TransitId m_lineId = kInvalidTransitId;
ShapeLink m_shapeLink;
};
class Transfer
{
public:
Transfer() = default;
Transfer(TransitId id, m2::PointD const & point, IdList const & stopIds);
bool operator<(Transfer const & rhs) const;
bool operator==(Transfer const & rhs) const;
bool IsValid() const;
TransitId GetId() const;
m2::PointD const & GetPoint() const;
IdList const & GetStopIds() const;
private:
DECLARE_TRANSIT_TYPES_FRIENDS
DECLARE_VISITOR_AND_DEBUG_PRINT(Transfer, visitor(m_id, "id"), visitor(m_point, "point"),
visitor(m_stopIds, "stop_ids"))
TransitId m_id = kInvalidTransitId;
m2::PointD m_point;
IdList m_stopIds;
};
class Shape
{
public:
Shape() = default;
Shape(TransitId id, std::vector<m2::PointD> const & polyline);
bool operator<(Shape const & rhs) const;
bool operator==(Shape const & rhs) const;
bool IsValid() const;
TransitId GetId() const;
std::vector<m2::PointD> const & GetPolyline() const;
private:
DECLARE_TRANSIT_TYPES_FRIENDS
DECLARE_VISITOR_AND_DEBUG_PRINT(Shape, visitor(m_id, "id"), visitor(m_polyline, "polyline"))
TransitId m_id;
std::vector<m2::PointD> m_polyline;
};
#undef DECLARE_TRANSIT_TYPES_FRIENDS
} // namespace experimental
} // namespace transit