Repo created
This commit is contained in:
parent
4af19165ec
commit
68073add76
12458 changed files with 12350765 additions and 2 deletions
716
libs/transit/experimental/transit_data.cpp
Normal file
716
libs/transit/experimental/transit_data.cpp
Normal 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
|
||||
110
libs/transit/experimental/transit_data.hpp
Normal file
110
libs/transit/experimental/transit_data.hpp
Normal 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
|
||||
567
libs/transit/experimental/transit_types_experimental.cpp
Normal file
567
libs/transit/experimental/transit_types_experimental.cpp
Normal 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
|
||||
410
libs/transit/experimental/transit_types_experimental.hpp
Normal file
410
libs/transit/experimental/transit_types_experimental.hpp
Normal 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
|
||||
Loading…
Add table
Add a link
Reference in a new issue