Commit 667904a5 authored by Volker Krause's avatar Volker Krause
Browse files

Interpolate vehicle section positions from platform section names

This is far from perfect yet (coaches can get widely varying lengths
for example), but this starts to produce something useful for SBB Hafas
data.
parent 83b44639
......@@ -106,6 +106,11 @@ QVariantList VehicleSection::featureList() const
return l;
}
bool VehicleSection::hasPlatformPosition() const
{
return d->platformPositionBegin >= 0.0 && d->platformPositionEnd >= 0.0;
}
KPUBLICTRANSPORT_MAKE_GADGET(Vehicle)
KPUBLICTRANSPORT_MAKE_PROPERTY(Vehicle, QString, name, setName)
KPUBLICTRANSPORT_MAKE_PROPERTY(Vehicle, Vehicle::Direction, direction, setDirection)
......@@ -221,4 +226,14 @@ std::vector<Vehicle> Vehicle::fromJson(const QJsonArray &array)
return Json::fromJson<Vehicle>(array);
}
bool Vehicle::hasPlatformPositions() const
{
return std::all_of(d->sections.begin(), d->sections.end(), [](const auto &p) { return p.hasPlatformPosition(); });
}
bool Vehicle::hasPlatformSectionNames() const
{
return std::none_of(d->sections.begin(), d->sections.end(), [](const auto &p) { return p.platformSectionName().isEmpty(); });
}
#include "moc_vehicle.cpp"
......@@ -109,6 +109,9 @@ class KPUBLICTRANSPORT_EXPORT VehicleSection
*/
KPUBLICTRANSPORT_PROPERTY(QString, platformSectionName, setPlatformSectionName)
/** Returns @c true if this vehicle section has a valid platform position set. */
bool hasPlatformPosition() const;
/** Merge two VehicleSection instances. */
static VehicleSection merge(const VehicleSection &lhs, const VehicleSection &rhs);
......@@ -183,6 +186,11 @@ public:
*/
Q_INVOKABLE float platformPositionForSection(const QString &sectionName) const;
/** Checks whether all vehicle sections have platform positions set. */
bool hasPlatformPositions() const;
/** Check whether all vehicle sections have platform section names set. */
bool hasPlatformSectionNames() const;
/** Merge two Vehicle instances. */
static Vehicle merge(const Vehicle &lhs, const Vehicle &rhs);
......
......@@ -23,6 +23,10 @@ public:
void doQuery() override;
void doClearResults() override;
void interpolatePlatformPositionsFromSectionName();
template <typename Iter>
void interpolatePlatformPositionsFromSectionName(Iter begin, Iter end);
VehicleLayoutRequest m_request;
Stopover m_stopover;
......@@ -50,6 +54,10 @@ void VehicleLayoutQueryModelPrivate::doQuery()
Q_Q(VehicleLayoutQueryModel);
q->beginResetModel();
m_stopover = reply->stopover();
if (!m_stopover.platformLayout().isEmpty() && !m_stopover.vehicleLayout().isEmpty()
&& !m_stopover.vehicleLayout().hasPlatformPositions() && m_stopover.vehicleLayout().hasPlatformSectionNames()) {
interpolatePlatformPositionsFromSectionName();
}
q->endResetModel();
emit q->contentChanged();
});
......@@ -62,6 +70,57 @@ void VehicleLayoutQueryModelPrivate::doClearResults()
emit q->contentChanged();
}
void VehicleLayoutQueryModelPrivate::interpolatePlatformPositionsFromSectionName()
{
auto vehicle = m_stopover.vehicleLayout();
auto vehicleSections = vehicle.takeSections();
const auto startSection = vehicleSections.front().platformSectionName();
const auto endSection = vehicleSections.back().platformSectionName();
for (const auto &sec : m_stopover.platformLayout().sections()) {
if (sec.name() == startSection) {
interpolatePlatformPositionsFromSectionName(vehicleSections.begin(), vehicleSections.end());
break;
} else if (sec.name() == endSection) {
interpolatePlatformPositionsFromSectionName(vehicleSections.rbegin(), vehicleSections.rend());
break;
}
}
vehicle.setSections(std::move(vehicleSections));
m_stopover.setVehicleLayout(std::move(vehicle));
}
template<typename Iter>
void VehicleLayoutQueryModelPrivate::interpolatePlatformPositionsFromSectionName(Iter begin, Iter end)
{
auto rangeBegin = begin, rangeEnd = begin;
while (rangeBegin != end) {
while (rangeEnd != end && (*rangeBegin).platformSectionName() == (*rangeEnd).platformSectionName()) {
++rangeEnd;
}
const auto platformIt = std::find_if(m_stopover.platformLayout().sections().begin(), m_stopover.platformLayout().sections().end(), [&rangeBegin](const auto &p) {
return p.name() == (*rangeBegin).platformSectionName();
});
if (platformIt == m_stopover.platformLayout().sections().end()) {
qWarning() << "Failed to find platform section" << (*rangeBegin).platformSectionName();
return;
}
const auto l = ((*platformIt).end() - (*platformIt).begin()) / std::distance(rangeBegin, rangeEnd);
auto pos = (*platformIt).begin();
for (auto it = rangeBegin; it != rangeEnd; ++it) {
(*it).setPlatformPositionBegin(pos);
(*it).setPlatformPositionEnd(pos + l);
pos += l;
}
rangeBegin = rangeEnd;
}
}
VehicleLayoutQueryModel::VehicleLayoutQueryModel(QObject* parent)
: AbstractQueryModel(new VehicleLayoutQueryModelPrivate, parent)
{
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment