Some initial tests for route discontinuities.
Probably many more to add, but this is some basic testing at least of inserting, querying and removing discontinuities.
This commit is contained in:
parent
fa898e7cd6
commit
4c0965e3c1
4 changed files with 98 additions and 15 deletions
|
@ -287,7 +287,8 @@ public:
|
|||
// compute leg courses for all static legs (both ends are fixed)
|
||||
void initPass1(const WayptData& previous, WayptData* next)
|
||||
{
|
||||
if (wpt->type() == "vectors") {
|
||||
const auto ty = wpt->type();
|
||||
if ((ty == "vectors") || (ty == "discontinuity")) {
|
||||
// relying on the fact vectors will be followed by a static fix/wpt
|
||||
if (next && next->posValid) {
|
||||
posValid = true;
|
||||
|
@ -295,7 +296,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
if (wpt->type() == "via") {
|
||||
if (ty == "via") {
|
||||
// even though both ends may be known, we don't
|
||||
// want to compute a leg course for a VIA
|
||||
} else if (posValid && !legCourseValid && previous.posValid) {
|
||||
|
@ -309,7 +310,11 @@ public:
|
|||
// use the runway departure end pos
|
||||
FGRunway* rwy = static_cast<RunwayWaypt*>(previous.wpt.get())->runway();
|
||||
legCourseTrue = SGGeodesy::courseDeg(rwy->end(), pos);
|
||||
} else if (wpt->type() != "runway") {
|
||||
} else if (ty == "discontinuity") {
|
||||
// we want to keep the path across DISCONs sharp (no turn entry/exit)
|
||||
// so we keep the leg course invalid, even though we actually
|
||||
// could compute it
|
||||
} else if (ty != "runway") {
|
||||
// need to wait to compute runway leg course
|
||||
legCourseTrue = SGGeodesy::courseDeg(previous.pos, pos);
|
||||
legCourseValid = true;
|
||||
|
@ -323,7 +328,7 @@ public:
|
|||
return;
|
||||
}
|
||||
|
||||
if ((wpt->type() == "discontinuity") || (wpt->type() == "via"))
|
||||
if ((wpt->type() == "via") || (wpt->type() == "discontinuty"))
|
||||
{
|
||||
// do nothing, we can't compute a valid leg course for these types
|
||||
// we'll generate sharp turns in the path but that's no problem.
|
||||
|
@ -792,14 +797,13 @@ public:
|
|||
|
||||
WayptDataVec::iterator previousValidWaypoint(unsigned int index)
|
||||
{
|
||||
if (index == 0) {
|
||||
return waypoints.end();
|
||||
}
|
||||
|
||||
while (waypoints[--index].skipped) {
|
||||
// waypoint zero should be unskippable, this assert verified that
|
||||
assert(index > 0);
|
||||
}
|
||||
do {
|
||||
if (index == 0) {
|
||||
return waypoints.end();
|
||||
}
|
||||
|
||||
--index;
|
||||
} while (waypoints.at(index).skipped || (waypoints.at(index).wpt->type() == "discontinuity"));
|
||||
|
||||
return waypoints.begin() + index;
|
||||
}
|
||||
|
@ -822,7 +826,7 @@ public:
|
|||
}
|
||||
|
||||
++it;
|
||||
while ((it != waypoints.end()) && it->skipped) {
|
||||
while ((it != waypoints.end()) && (it->skipped || (it->wpt->type() == "discontinuity"))) {
|
||||
++it;
|
||||
}
|
||||
return it;
|
||||
|
@ -870,7 +874,8 @@ void RoutePath::commonInit()
|
|||
|
||||
for (unsigned int i=1; i<d->waypoints.size(); ++i) {
|
||||
WayptData* nextPtr = ((i + 1) < d->waypoints.size()) ? &d->waypoints[i+1] : nullptr;
|
||||
d->waypoints[i].initPass1(d->waypoints[i-1], nextPtr);
|
||||
auto prev = d->previousValidWaypoint(i);
|
||||
d->waypoints[i].initPass1(*prev, nextPtr);
|
||||
}
|
||||
|
||||
for (unsigned int i=0; i<d->waypoints.size(); ++i) {
|
||||
|
@ -1073,9 +1078,14 @@ double RoutePath::computeDistanceForIndex(int index) const
|
|||
return 0.0;
|
||||
}
|
||||
|
||||
if (it->wpt->type() == "via") {
|
||||
const auto ty = it->wpt->type();
|
||||
if (ty == "via") {
|
||||
return distanceForVia(static_cast<Via*>(it->wpt.get()), index);
|
||||
}
|
||||
|
||||
if (ty == "discontinuity") {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
auto prevIt = d->previousValidWaypoint(index);
|
||||
assert(prevIt != d->waypoints.end());
|
||||
|
|
|
@ -156,6 +156,10 @@ void populateFPWithoutNasal(flightgear::FlightPlanRef f,
|
|||
|
||||
for (auto ws : simgear::strutils::split(waypoints)) {
|
||||
WayptRef wpt = f->waypointFromString(ws);
|
||||
if (!wpt) {
|
||||
SG_LOG(SG_NAVAID, SG_ALERT, "No waypoint created for:" << ws);
|
||||
continue;
|
||||
}
|
||||
f->insertWayptAtIndex(wpt, -1);
|
||||
}
|
||||
|
||||
|
|
|
@ -394,3 +394,68 @@ void FlightplanTests::testLoadSaveMachRestriction()
|
|||
|
||||
CPPUNIT_ASSERT_EQUAL(8, f2->legAtIndex(2)->holdCount());
|
||||
}
|
||||
|
||||
void FlightplanTests::testBasicDiscontinuity()
|
||||
{
|
||||
FlightPlanRef fp1 = makeTestFP("LIRF", "34L", "LEBL", "25R",
|
||||
"ESINO GITRI BALEN MUREN TOSNU");
|
||||
|
||||
const auto tdBefore = fp1->totalDistanceNm();
|
||||
|
||||
|
||||
const SGGeod balenPos = fp1->legAtIndex(3)->waypoint()->position();
|
||||
const SGGeod murenPos = fp1->legAtIndex(4)->waypoint()->position();
|
||||
|
||||
// total distance should not change
|
||||
fp1->insertWayptAtIndex(new Discontinuity(fp1), 4); // betwee BALEN and MUREN
|
||||
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL(tdBefore, fp1->totalDistanceNm(), 1.0);
|
||||
|
||||
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL(fp1->legAtIndex(4)->courseDeg(),
|
||||
SGGeodesy::courseDeg(balenPos, murenPos), 0.1);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL(fp1->legAtIndex(4)->distanceNm(), 0.0, 0.1);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL(fp1->legAtIndex(5)->courseDeg(),
|
||||
SGGeodesy::courseDeg(balenPos, murenPos), 0.1);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL(fp1->legAtIndex(5)->distanceNm(),
|
||||
SGGeodesy::distanceNm(balenPos, murenPos), 0.1);
|
||||
|
||||
// remove the discontinuity
|
||||
fp1->deleteIndex(4);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL(fp1->legAtIndex(4)->courseDeg(),
|
||||
SGGeodesy::courseDeg(balenPos, murenPos), 0.1);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL(fp1->legAtIndex(4)->distanceNm(),
|
||||
SGGeodesy::distanceNm(balenPos, murenPos), 0.1);
|
||||
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL(tdBefore, fp1->totalDistanceNm(), 1.0);
|
||||
|
||||
}
|
||||
|
||||
void FlightplanTests::testOnlyDiscontinuityRoute()
|
||||
{
|
||||
FlightPlanRef f = new FlightPlan;
|
||||
FGAirportRef depApt = FGAirport::getByIdent("LFBD");
|
||||
f->setDeparture(depApt);
|
||||
|
||||
|
||||
FGAirportRef destApt = FGAirport::getByIdent("EHAM");
|
||||
f->setDestination(destApt);
|
||||
|
||||
f->insertWayptAtIndex(new Discontinuity(f), 0);
|
||||
|
||||
RoutePath rp1(f);
|
||||
|
||||
// discontinuity should act like a straight segment between preceeding and following
|
||||
const double d = SGGeodesy::distanceNm(depApt->geod(), destApt->geod());
|
||||
// CPPUNIT_ASSERT_DOUBLES_EQUAL(rp1.distanceForIndex(0), d, 0.5);
|
||||
|
||||
// start inserting waypoints ahead of the DISCON, Boeing FPL style
|
||||
WayptRef wpt = f->waypointFromString("LMG");
|
||||
f->insertWayptAtIndex(wpt, 0);
|
||||
|
||||
wpt = f->waypointFromString("KUKOR");
|
||||
f->insertWayptAtIndex(wpt, 1);
|
||||
|
||||
wpt = f->waypointFromString("EPL");
|
||||
f->insertWayptAtIndex(wpt, 2);
|
||||
}
|
||||
|
|
|
@ -41,6 +41,8 @@ class FlightplanTests : public CppUnit::TestFixture
|
|||
CPPUNIT_TEST(testRoutPathWpt0Midflight);
|
||||
CPPUNIT_TEST(testRoutePathVec);
|
||||
CPPUNIT_TEST(testLoadSaveMachRestriction);
|
||||
CPPUNIT_TEST(testOnlyDiscontinuityRoute);
|
||||
CPPUNIT_TEST(testBasicDiscontinuity);
|
||||
|
||||
// CPPUNIT_TEST(testParseICAORoute);
|
||||
// CPPUNIT_TEST(testParseICANLowLevelRoute);
|
||||
|
@ -66,6 +68,8 @@ public:
|
|||
void testRoutPathWpt0Midflight();
|
||||
void testRoutePathVec();
|
||||
void testLoadSaveMachRestriction();
|
||||
void testBasicDiscontinuity();
|
||||
void testOnlyDiscontinuityRoute();
|
||||
};
|
||||
|
||||
#endif // FG_FLIGHTPLAN_UNIT_TESTS_HXX
|
||||
|
|
Loading…
Reference in a new issue