mirror of
https://codeberg.org/comaps/comaps
synced 2025-12-19 04:53:36 +00:00
To expand with full Organic Maps and Maps.ME commits history run: git remote add om-historic [om-historic.git repo url] git fetch --tags om-historic git replace squashed-history historic-commits
505 lines
18 KiB
C++
505 lines
18 KiB
C++
#pragma once
|
|
|
|
#include "indexer/feature_decl.hpp"
|
|
#include "indexer/scales.hpp"
|
|
|
|
#include "geometry/point2d.hpp"
|
|
|
|
#include "base/newtype.hpp"
|
|
#include "base/visitor.hpp"
|
|
|
|
#include <algorithm>
|
|
#include <limits>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
namespace routing
|
|
{
|
|
namespace transit
|
|
{
|
|
using Anchor = uint8_t;
|
|
using FeatureId = uint32_t;
|
|
using LineId = uint32_t;
|
|
using NetworkId = uint32_t;
|
|
using OsmId = uint64_t;
|
|
using StopId = uint64_t;
|
|
using TransferId = uint64_t;
|
|
using Weight = int32_t;
|
|
using Ranges = std::vector<std::vector<StopId>>;
|
|
|
|
Anchor constexpr kInvalidAnchor = std::numeric_limits<Anchor>::max();
|
|
std::string const kInvalidColor = std::string("");
|
|
LineId constexpr kInvalidLineId = std::numeric_limits<LineId>::max();
|
|
NetworkId constexpr kInvalidNetworkId = std::numeric_limits<NetworkId>::max();
|
|
OsmId constexpr kInvalidOsmId = std::numeric_limits<OsmId>::max();
|
|
StopId constexpr kInvalidStopId = std::numeric_limits<StopId>::max();
|
|
TransferId constexpr kInvalidTransferId = std::numeric_limits<TransferId>::max();
|
|
Weight constexpr kInvalidWeight = std::numeric_limits<Weight>::max();
|
|
|
|
#define DECLARE_TRANSIT_TYPE_FRIENDS \
|
|
template <class Sink> friend class Serializer; \
|
|
template <class Source> friend class Deserializer; \
|
|
friend class DeserializerFromJson; \
|
|
template <typename Sink> friend class FixedSizeSerializer; \
|
|
template <typename Sink> friend class FixedSizeDeserializer; \
|
|
|
|
struct TransitHeader
|
|
{
|
|
TransitHeader() { Reset(); }
|
|
TransitHeader(uint16_t version, uint32_t stopsOffset, uint32_t gatesOffset, uint32_t edgesOffset,
|
|
uint32_t transfersOffset, uint32_t linesOffset, uint32_t shapesOffset,
|
|
uint32_t networksOffset, uint32_t endOffset);
|
|
|
|
void Reset();
|
|
bool IsEqualForTesting(TransitHeader const & header) const;
|
|
bool IsValid() const;
|
|
|
|
private:
|
|
DECLARE_TRANSIT_TYPE_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_shapesOffset, "shapesOffset"),
|
|
visitor(m_networksOffset, "networksOffset"), visitor(m_endOffset, "endOffset"))
|
|
|
|
public:
|
|
uint16_t m_version;
|
|
uint16_t m_reserve;
|
|
uint32_t m_stopsOffset;
|
|
uint32_t m_gatesOffset;
|
|
uint32_t m_edgesOffset;
|
|
uint32_t m_transfersOffset;
|
|
uint32_t m_linesOffset;
|
|
uint32_t m_shapesOffset;
|
|
uint32_t m_networksOffset;
|
|
uint32_t m_endOffset;
|
|
};
|
|
|
|
static_assert(sizeof(TransitHeader) == 36, "Wrong header size of transit section.");
|
|
|
|
/// \brief This class represents osm id and feature id of the same feature.
|
|
class FeatureIdentifiers
|
|
{
|
|
public:
|
|
explicit FeatureIdentifiers(bool serializeFeatureIdOnly);
|
|
FeatureIdentifiers(OsmId osmId, FeatureId const & featureId, bool serializeFeatureIdOnly);
|
|
|
|
bool operator<(FeatureIdentifiers const & rhs) const;
|
|
bool operator==(FeatureIdentifiers const & rhs) const;
|
|
bool operator!=(FeatureIdentifiers const & rhs) const { return !(*this == rhs); }
|
|
bool IsValid() const;
|
|
void SetOsmId(OsmId osmId) { m_osmId = osmId; }
|
|
void SetFeatureId(FeatureId featureId) { m_featureId = featureId; }
|
|
|
|
OsmId GetOsmId() const { return m_osmId; }
|
|
FeatureId GetFeatureId() const { return m_featureId; }
|
|
bool IsSerializeFeatureIdOnly() const { return m_serializeFeatureIdOnly; }
|
|
|
|
private:
|
|
DECLARE_TRANSIT_TYPE_FRIENDS
|
|
DECLARE_VISITOR_AND_DEBUG_PRINT(FeatureIdentifiers, visitor(m_osmId, "osm_id"),
|
|
visitor(m_featureId, "feature_id"))
|
|
|
|
OsmId m_osmId = kInvalidOsmId;
|
|
FeatureId m_featureId = kInvalidFeatureId;
|
|
bool m_serializeFeatureIdOnly = true;
|
|
};
|
|
|
|
class TitleAnchor
|
|
{
|
|
public:
|
|
TitleAnchor() = default;
|
|
TitleAnchor(uint8_t minZoom, Anchor anchor);
|
|
|
|
bool operator==(TitleAnchor const & titleAnchor) const;
|
|
bool IsEqualForTesting(TitleAnchor const & titleAnchor) const;
|
|
bool IsValid() const;
|
|
|
|
uint8_t GetMinZoom() const { return m_minZoom; }
|
|
Anchor const & GetAnchor() const { return m_anchor; }
|
|
|
|
private:
|
|
DECLARE_TRANSIT_TYPE_FRIENDS
|
|
DECLARE_VISITOR_AND_DEBUG_PRINT(TitleAnchor, visitor(m_minZoom, "min_zoom"),
|
|
visitor(m_anchor, "anchor"))
|
|
|
|
uint8_t m_minZoom = scales::UPPER_STYLE_SCALE;
|
|
Anchor m_anchor = kInvalidAnchor;
|
|
};
|
|
|
|
class Stop
|
|
{
|
|
public:
|
|
NEWTYPE(StopId, WrappedStopId);
|
|
|
|
Stop() : m_featureIdentifiers(true /* serializeFeatureIdOnly */){};
|
|
Stop(StopId id, OsmId osmId, FeatureId featureId, TransferId transferId,
|
|
std::vector<LineId> const & lineIds, m2::PointD const & point,
|
|
std::vector<TitleAnchor> const & titleAnchors);
|
|
explicit Stop(StopId id) : m_id(id), m_featureIdentifiers(true /* serializeFeatureIdOnly */) {}
|
|
|
|
bool operator<(Stop const & rhs) const { return m_id < rhs.m_id; }
|
|
bool operator==(Stop const & rhs) const { return m_id == rhs.m_id; }
|
|
bool IsEqualForTesting(Stop const & stop) const;
|
|
bool IsValid() const;
|
|
|
|
StopId GetId() const { return m_id.Get(); }
|
|
FeatureId GetFeatureId() const { return m_featureIdentifiers.GetFeatureId(); }
|
|
OsmId GetOsmId() const { return m_featureIdentifiers.GetOsmId(); }
|
|
TransferId GetTransferId() const { return m_transferId; }
|
|
std::vector<LineId> const & GetLineIds() const { return m_lineIds; }
|
|
m2::PointD const & GetPoint() const { return m_point; }
|
|
std::vector<TitleAnchor> const & GetTitleAnchors() const { return m_titleAnchors; }
|
|
|
|
private:
|
|
DECLARE_TRANSIT_TYPE_FRIENDS
|
|
DECLARE_VISITOR_AND_DEBUG_PRINT(Stop, visitor(m_id, "id"),
|
|
visitor(m_featureIdentifiers, "osm_id"),
|
|
visitor(m_transferId, "transfer_id"),
|
|
visitor(m_lineIds, "line_ids"), visitor(m_point, "point"),
|
|
visitor(m_titleAnchors, "title_anchors"))
|
|
|
|
WrappedStopId m_id = WrappedStopId(kInvalidStopId);
|
|
FeatureIdentifiers m_featureIdentifiers;
|
|
TransferId m_transferId = kInvalidTransferId;
|
|
std::vector<LineId> m_lineIds;
|
|
m2::PointD m_point {0.0, 0.0};
|
|
std::vector<TitleAnchor> m_titleAnchors;
|
|
};
|
|
NEWTYPE_SIMPLE_OUTPUT(Stop::WrappedStopId)
|
|
|
|
class SingleMwmSegment
|
|
{
|
|
public:
|
|
SingleMwmSegment() = default;
|
|
SingleMwmSegment(FeatureId featureId, uint32_t segmentIdx, bool forward);
|
|
bool IsEqualForTesting(SingleMwmSegment const & s) const;
|
|
bool IsValid() const;
|
|
|
|
FeatureId GetFeatureId() const { return m_featureId; }
|
|
uint32_t GetSegmentIdx() const { return m_segmentIdx; }
|
|
bool GetForward() const { return m_forward; }
|
|
|
|
private:
|
|
DECLARE_TRANSIT_TYPE_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;
|
|
};
|
|
|
|
class Gate
|
|
{
|
|
public:
|
|
Gate() : m_featureIdentifiers(false /* serializeFeatureIdOnly */){};
|
|
Gate(OsmId osmId, FeatureId featureId, bool entrance, bool exit, Weight weight,
|
|
std::vector<StopId> const & stopIds, m2::PointD const & point);
|
|
|
|
bool operator<(Gate const & rhs) const;
|
|
bool operator==(Gate const & rhs) const;
|
|
bool IsEqualForTesting(Gate const & gate) const;
|
|
bool IsValid() const;
|
|
void SetBestPedestrianSegment(SingleMwmSegment const & s) { m_bestPedestrianSegment = s; };
|
|
|
|
FeatureId GetFeatureId() const { return m_featureIdentifiers.GetFeatureId(); }
|
|
OsmId GetOsmId() const { return m_featureIdentifiers.GetOsmId(); }
|
|
SingleMwmSegment const & GetBestPedestrianSegment() const { return m_bestPedestrianSegment; }
|
|
bool GetEntrance() const { return m_entrance; }
|
|
bool GetExit() const { return m_exit; }
|
|
Weight GetWeight() const { return m_weight; }
|
|
std::vector<StopId> const & GetStopIds() const { return m_stopIds; }
|
|
m2::PointD const & GetPoint() const { return m_point; }
|
|
|
|
private:
|
|
DECLARE_TRANSIT_TYPE_FRIENDS
|
|
DECLARE_VISITOR_AND_DEBUG_PRINT(Gate, visitor(m_featureIdentifiers, "osm_id"),
|
|
visitor(m_bestPedestrianSegment, "best_pedestrian_segment"),
|
|
visitor(m_entrance, "entrance"), visitor(m_exit, "exit"),
|
|
visitor(m_weight, "weight"), visitor(m_stopIds, "stop_ids"),
|
|
visitor(m_point, "point"))
|
|
|
|
// |m_featureIdentifiers| contains feature id of a feature which represents gates. Usually it's a
|
|
// point feature.
|
|
FeatureIdentifiers m_featureIdentifiers;
|
|
// |m_bestPedestrianSegment| is a segment which can be used for pedestrian routing to leave and
|
|
// enter the gate. The segment may be invalid because of map date. If so there's no pedestrian
|
|
// segment which can be used to reach the gate.
|
|
SingleMwmSegment m_bestPedestrianSegment;
|
|
bool m_entrance = true;
|
|
bool m_exit = true;
|
|
Weight m_weight = kInvalidWeight;
|
|
std::vector<StopId> m_stopIds;
|
|
m2::PointD m_point;
|
|
};
|
|
|
|
class ShapeId
|
|
{
|
|
public:
|
|
ShapeId() = default;
|
|
ShapeId(StopId stop1Id, StopId stop2Id) : m_stop1Id(stop1Id), m_stop2Id(stop2Id) {}
|
|
|
|
bool operator<(ShapeId const & rhs) const;
|
|
bool operator==(ShapeId const & rhs) const;
|
|
bool IsEqualForTesting(ShapeId const & rhs) const { return *this == rhs; }
|
|
|
|
bool IsValid() const;
|
|
StopId GetStop1Id() const { return m_stop1Id; }
|
|
StopId GetStop2Id() const { return m_stop2Id; }
|
|
|
|
private:
|
|
DECLARE_TRANSIT_TYPE_FRIENDS
|
|
DECLARE_VISITOR_AND_DEBUG_PRINT(ShapeId, visitor(m_stop1Id, "stop1_id"),
|
|
visitor(m_stop2Id, "stop2_id"))
|
|
|
|
StopId m_stop1Id = kInvalidStopId;
|
|
StopId m_stop2Id = kInvalidStopId;
|
|
};
|
|
|
|
class EdgeFlags
|
|
{
|
|
public:
|
|
DECLARE_TRANSIT_TYPE_FRIENDS
|
|
friend std::string DebugPrint(EdgeFlags const & f);
|
|
|
|
uint8_t GetFlags() const;
|
|
void SetFlags(uint8_t flags);
|
|
|
|
// |m_transfer == true| if |Edge::m_shapeIds| is empty.
|
|
bool m_transfer = false;
|
|
/// |m_isShapeIdsEmpty == true| if |Edge::m_shapeIds| is empty.
|
|
bool m_isShapeIdsEmpty = false;
|
|
// |m_isShapeIdsSingle == true| if |Edge::m_shapeIds| contains only one item.
|
|
bool m_isShapeIdsSingle = false;
|
|
// Note. If |m_isShapeIdsSingle == true| |m_isShapeIdsSame| is set to
|
|
// |Edge::m_stop1Id == m_shapeIds[0].m_stop1Id && Edge::m_stop2Id == m_shapeIds[0].m_stop2Id|.
|
|
// |m_isShapeIdsSingle| is invalid otherwise.
|
|
bool m_isShapeIdsSame = false;
|
|
// Note. If |m_isShapeIdsSingle == true| |m_isShapeIdsReversed| is set to
|
|
// |Edge::m_stop1Id == m_shapeIds[0].m_stop2Id && Edge::m_stop2Id == m_shapeIds[0].m_stop1Id|.
|
|
// |m_isShapeIdsReversed| is invalid otherwise.
|
|
bool m_isShapeIdsReversed = false;
|
|
|
|
private:
|
|
uint8_t BoolToUint(bool b) const { return static_cast<uint8_t>(b ? 1 : 0); }
|
|
uint8_t GetBit(uint8_t flags, uint8_t mask) const { return BoolToUint((flags & mask) != 0); }
|
|
|
|
static uint8_t constexpr kTransferMask = 1;
|
|
static uint8_t constexpr kEmptyShapeIdsMask = (1 << 1);
|
|
static uint8_t constexpr kSingleShapeIdMask = (1 << 2);
|
|
static uint8_t constexpr kShapeIdIsSameMask = (1 << 3);
|
|
static uint8_t constexpr kShapeIdIsReversedMask = (1 << 4);
|
|
};
|
|
|
|
std::string DebugPrint(EdgeFlags const & f);
|
|
|
|
class Edge
|
|
{
|
|
public:
|
|
NEWTYPE(StopId, WrappedEdgeId);
|
|
|
|
Edge() = default;
|
|
Edge(StopId stop1Id, StopId stop2Id, Weight weight, LineId lineId, bool transfer,
|
|
std::vector<ShapeId> const & shapeIds);
|
|
|
|
bool operator<(Edge const & rhs) const;
|
|
bool operator==(Edge const & rhs) const;
|
|
bool operator!=(Edge const & rhs) const { return !(*this == rhs); }
|
|
bool IsEqualForTesting(Edge const & edge) const;
|
|
bool IsValid() const;
|
|
void SetWeight(Weight weight) { m_weight = weight; }
|
|
|
|
StopId GetStop1Id() const { return m_stop1Id.Get(); }
|
|
StopId GetStop2Id() const { return m_stop2Id; }
|
|
Weight GetWeight() const { return m_weight; }
|
|
LineId GetLineId() const { return m_lineId; }
|
|
bool GetTransfer() const { return m_flags.m_transfer; }
|
|
std::vector<ShapeId> const & GetShapeIds() const { return m_shapeIds; }
|
|
|
|
private:
|
|
DECLARE_TRANSIT_TYPE_FRIENDS
|
|
DECLARE_VISITOR_AND_DEBUG_PRINT(Edge, visitor(m_stop1Id, "stop1_id"),
|
|
visitor(m_stop2Id, "stop2_id"), visitor(m_weight, "weight"),
|
|
visitor(m_lineId, "line_id"), visitor(m_flags, "transfer"),
|
|
visitor(m_shapeIds, "shape_ids"))
|
|
|
|
WrappedEdgeId m_stop1Id = WrappedEdgeId(kInvalidStopId);
|
|
StopId m_stop2Id = kInvalidStopId;
|
|
Weight m_weight = kInvalidWeight; // in seconds
|
|
LineId m_lineId = kInvalidLineId;
|
|
EdgeFlags m_flags;
|
|
std::vector<ShapeId> m_shapeIds;
|
|
};
|
|
NEWTYPE_SIMPLE_OUTPUT(Edge::WrappedEdgeId)
|
|
|
|
class Transfer
|
|
{
|
|
public:
|
|
Transfer() = default;
|
|
Transfer(StopId id, m2::PointD const & point, std::vector<StopId> const & stopIds,
|
|
std::vector<TitleAnchor> const & titleAnchors);
|
|
|
|
bool operator<(Transfer const & rhs) const { return m_id < rhs.m_id; }
|
|
bool operator==(Transfer const & rhs) const { return m_id == rhs.m_id; }
|
|
bool IsEqualForTesting(Transfer const & transfer) const;
|
|
bool IsValid() const;
|
|
|
|
StopId GetId() const { return m_id; }
|
|
m2::PointD const & GetPoint() const { return m_point; }
|
|
std::vector<StopId> const & GetStopIds() const { return m_stopIds; }
|
|
std::vector<TitleAnchor> const & GetTitleAnchors() const { return m_titleAnchors; }
|
|
|
|
private:
|
|
DECLARE_TRANSIT_TYPE_FRIENDS
|
|
DECLARE_VISITOR_AND_DEBUG_PRINT(Transfer, visitor(m_id, "id"), visitor(m_point, "point"),
|
|
visitor(m_stopIds, "stop_ids"),
|
|
visitor(m_titleAnchors, "title_anchors"))
|
|
|
|
StopId m_id = kInvalidStopId;
|
|
m2::PointD m_point;
|
|
std::vector<StopId> m_stopIds;
|
|
std::vector<TitleAnchor> m_titleAnchors;
|
|
};
|
|
|
|
class StopIdRanges
|
|
{
|
|
public:
|
|
StopIdRanges() = default;
|
|
explicit StopIdRanges(Ranges const & ids) : m_ids(ids) {}
|
|
|
|
bool operator==(StopIdRanges const & rhs) const { return m_ids == rhs.m_ids; }
|
|
bool IsValid() const { return !m_ids.empty(); }
|
|
|
|
Ranges const & GetIds() const { return m_ids; }
|
|
|
|
private:
|
|
DECLARE_TRANSIT_TYPE_FRIENDS
|
|
DECLARE_VISITOR_AND_DEBUG_PRINT(StopIdRanges, visitor(m_ids, "ids"))
|
|
|
|
Ranges m_ids;
|
|
};
|
|
|
|
class Line
|
|
{
|
|
public:
|
|
Line() = default;
|
|
Line(LineId id, std::string const & number, std::string const & title, std::string const & type,
|
|
std::string const & color, NetworkId networkId, Ranges const & stopIds, Weight interval);
|
|
|
|
bool operator<(Line const & rhs) const { return m_id < rhs.m_id; }
|
|
bool operator==(Line const & rhs) const { return m_id == rhs.m_id; }
|
|
bool IsEqualForTesting(Line const & line) const;
|
|
bool IsValid() const;
|
|
|
|
LineId GetId() const { return m_id; }
|
|
std::string const & GetNumber() const { return m_number; }
|
|
std::string const & GetTitle() const { return m_title; }
|
|
std::string const & GetType() const { return m_type; }
|
|
std::string const & GetColor() const { return m_color; }
|
|
NetworkId GetNetworkId() const { return m_networkId; }
|
|
Ranges const & GetStopIds() const { return m_stopIds.GetIds(); }
|
|
Weight GetInterval() const { return m_interval; }
|
|
|
|
private:
|
|
DECLARE_TRANSIT_TYPE_FRIENDS
|
|
DECLARE_VISITOR_AND_DEBUG_PRINT(Line, visitor(m_id, "id"), visitor(m_number, "number"),
|
|
visitor(m_title, "title"), visitor(m_type, "type"),
|
|
visitor(m_color, "color"), visitor(m_networkId, "network_id"),
|
|
visitor(m_stopIds, "stop_ids"), visitor(m_interval, "interval"))
|
|
|
|
LineId m_id = kInvalidLineId;
|
|
std::string m_number;
|
|
std::string m_title;
|
|
std::string m_type;
|
|
std::string m_color = kInvalidColor;
|
|
NetworkId m_networkId = kInvalidNetworkId;
|
|
StopIdRanges m_stopIds;
|
|
Weight m_interval = kInvalidWeight;
|
|
};
|
|
|
|
class Shape
|
|
{
|
|
public:
|
|
Shape() = default;
|
|
Shape(ShapeId const & id, std::vector<m2::PointD> const & polyline)
|
|
: m_id(id), m_polyline(polyline)
|
|
{
|
|
}
|
|
|
|
bool operator<(Shape const & rhs) const { return m_id < rhs.m_id; }
|
|
bool operator==(Shape const & rhs) const { return m_id == rhs.m_id; }
|
|
bool IsEqualForTesting(Shape const & shape) const;
|
|
bool IsValid() const { return m_id.IsValid() && m_polyline.size() > 1; }
|
|
|
|
ShapeId GetId() const { return m_id; }
|
|
std::vector<m2::PointD> const & GetPolyline() const { return m_polyline; }
|
|
|
|
private:
|
|
DECLARE_TRANSIT_TYPE_FRIENDS
|
|
DECLARE_VISITOR_AND_DEBUG_PRINT(Shape, visitor(m_id, "id"), visitor(m_polyline, "polyline"))
|
|
|
|
ShapeId m_id;
|
|
std::vector<m2::PointD> m_polyline;
|
|
};
|
|
|
|
class Network
|
|
{
|
|
public:
|
|
Network() = default;
|
|
Network(NetworkId id, std::string const & title);
|
|
explicit Network(NetworkId id) : m_id(id), m_title("") {}
|
|
|
|
bool operator<(Network const & rhs) const { return m_id < rhs.m_id; }
|
|
bool operator==(Network const & rhs) const { return m_id == rhs.m_id; }
|
|
bool IsEqualForTesting(Network const & shape) const;
|
|
bool IsValid() const;
|
|
|
|
NetworkId GetId() const { return m_id; }
|
|
std::string const & GetTitle() const { return m_title; }
|
|
|
|
private:
|
|
DECLARE_TRANSIT_TYPE_FRIENDS
|
|
DECLARE_VISITOR_AND_DEBUG_PRINT(Network, visitor(m_id, "id"), visitor(m_title, "title"))
|
|
|
|
NetworkId m_id = kInvalidNetworkId;
|
|
std::string m_title;
|
|
};
|
|
|
|
template <class Item>
|
|
void CheckValid(std::vector<Item> const & items, std::string const & name)
|
|
{
|
|
for (auto const & i : items)
|
|
CHECK(i.IsValid(), (i, "is not valid. Table name:", name));
|
|
}
|
|
|
|
template <class Item>
|
|
void CheckSorted(std::vector<Item> const & items, std::string const & name)
|
|
{
|
|
CHECK(std::is_sorted(items.cbegin(), items.cend()), ("Table is not sorted. Table name:", name));
|
|
}
|
|
|
|
template <class Item>
|
|
void CheckUnique(std::vector<Item> const & items, std::string const & name)
|
|
{
|
|
auto const it = std::adjacent_find(items.cbegin(), items.cend());
|
|
CHECK(it == items.cend(), (*it, "is not unique. Table name:", name));
|
|
}
|
|
|
|
template <class Item>
|
|
void CheckValidSortedUnique(std::vector<Item> const & items, std::string const & name)
|
|
{
|
|
CheckValid(items, name);
|
|
CheckSorted(items, name);
|
|
CheckUnique(items, name);
|
|
}
|
|
|
|
EdgeFlags GetEdgeFlags(bool transfer, StopId stopId1, StopId stopId2,
|
|
std::vector<ShapeId> const & shapeIds);
|
|
|
|
#undef DECLARE_TRANSIT_TYPE_FRIENDS
|
|
} // namespace transit
|
|
} // namespace routing
|