From 2d7e7b3df6967a86d85edcbb186be818f7474eef Mon Sep 17 00:00:00 2001
From: James Turner <zakalawe@mac.com>
Date: Tue, 10 Nov 2020 11:40:12 +0000
Subject: [PATCH] Waypoints: use bool returns for load errors

Avoid using exception throws for malformed input, makes error
reporting very noisy when user-generated flight plans are loaded.
---
 src/Navaids/FlightPlan.cxx |   4 +
 src/Navaids/route.cxx      |  38 ++++----
 src/Navaids/route.hxx      |  16 ++--
 src/Navaids/waypoint.cxx   | 174 ++++++++++++++++++++++---------------
 src/Navaids/waypoint.hxx   |  75 ++++++++--------
 5 files changed, 172 insertions(+), 135 deletions(-)

diff --git a/src/Navaids/FlightPlan.cxx b/src/Navaids/FlightPlan.cxx
index 840e8616b..421494c90 100644
--- a/src/Navaids/FlightPlan.cxx
+++ b/src/Navaids/FlightPlan.cxx
@@ -1198,6 +1198,10 @@ void FlightPlan::loadVersion2XMLRoute(SGPropertyNode_ptr routeData)
   if (routeNode.valid()) {
     for (auto wpNode : routeNode->getChildren("wp")) {
         auto wp = Waypt::createFromProperties(this, wpNode);
+        if (!wp) {
+            continue;
+        }
+
       LegRef l = new Leg{this, wp};
       // sync leg restrictions with waypoint ones
         if (wp->speedRestriction() != RESTRICT_NONE) {
diff --git a/src/Navaids/route.cxx b/src/Navaids/route.cxx
index 2990f0b3a..fa77b2c0c 100644
--- a/src/Navaids/route.cxx
+++ b/src/Navaids/route.cxx
@@ -236,8 +236,8 @@ WayptRef Waypt::createInstance(RouteBase* aOwner, const std::string& aTypeName)
 WayptRef Waypt::createFromProperties(RouteBase* aOwner, SGPropertyNode_ptr aProp)
 {
   if (!aProp->hasChild("type")) {
-    throw sg_io_exception("bad props node, no type provided",
-      "Waypt::createFromProperties");
+      SG_LOG(SG_GENERAL, SG_WARN, "Bad waypoint node: missing type");
+      return {};
   }
 
   flightgear::AirwayRef via;
@@ -250,22 +250,24 @@ WayptRef Waypt::createFromProperties(RouteBase* aOwner, SGPropertyNode_ptr aProp
       }
   }
 
-  try {
     WayptRef nd(createInstance(aOwner, aProp->getStringValue("type")));
-    nd->initFromProperties(aProp);
-    return nd;
-  } catch (sg_exception& e) {
-    SG_LOG(SG_GENERAL, SG_WARN, "failed to create waypoint, trying basic:" << e.getMessage());
-  }
+    if (nd->initFromProperties(aProp)) {
+        return nd;
+    }
+    SG_LOG(SG_GENERAL, SG_WARN, "failed to create waypoint, trying basic");
 
-// if we failed to make the waypoint, try again making a basic waypoint.
-// this handles the case where a navaid waypoint is missing, for example
-// we also reject navaids that don't look correct (too far form the specified
-// lat-lon, eg see https://sourceforge.net/p/flightgear/codetickets/1814/ )
-// and again fallback to here.
-  WayptRef nd(new BasicWaypt(aOwner));
-  nd->initFromProperties(aProp);
-  return nd;
+
+    // if we failed to make the waypoint, try again making a basic waypoint.
+    // this handles the case where a navaid waypoint is missing, for example
+    // we also reject navaids that don't look correct (too far form the specified
+    // lat-lon, eg see https://sourceforge.net/p/flightgear/codetickets/1814/ )
+    // and again fallback to here.
+    WayptRef bw(new BasicWaypt(aOwner));
+    if (bw->initFromProperties(aProp)) {
+        return bw;
+    }
+
+    return {}; // total failure
 }
 
 void Waypt::saveAsNode(SGPropertyNode* n) const
@@ -274,7 +276,7 @@ void Waypt::saveAsNode(SGPropertyNode* n) const
   writeToProperties(n);
 }
 
-void Waypt::initFromProperties(SGPropertyNode_ptr aProp)
+bool Waypt::initFromProperties(SGPropertyNode_ptr aProp)
 {
   if (aProp->hasChild("generated")) {
     setFlag(WPT_GENERATED, aProp->getBoolValue("generated"));
@@ -314,7 +316,7 @@ void Waypt::initFromProperties(SGPropertyNode_ptr aProp)
     _speed = aProp->getDoubleValue("speed");
   }
 
-
+  return true;
 }
 
 void Waypt::writeToProperties(SGPropertyNode_ptr aProp) const
diff --git a/src/Navaids/route.hxx b/src/Navaids/route.hxx
index 283456f5d..41a384ac3 100644
--- a/src/Navaids/route.hxx
+++ b/src/Navaids/route.hxx
@@ -208,16 +208,16 @@ protected:
   /**
    * Persistence helper - read node properties from a file
    */
-  virtual void initFromProperties(SGPropertyNode_ptr aProp);
-  
-  /**
+    virtual bool initFromProperties(SGPropertyNode_ptr aProp);
+
+    /**
    * Persistence helper - save this element to a node
    */
-  virtual void writeToProperties(SGPropertyNode_ptr aProp) const;
-  
-  typedef Waypt* (FactoryFunction)(RouteBase* aOwner) ;
-  static void registerFactory(const std::string aNodeType, FactoryFunction* aFactory);
-  
+    virtual void writeToProperties(SGPropertyNode_ptr aProp) const;
+
+    typedef Waypt*(FactoryFunction)(RouteBase* aOwner);
+    static void registerFactory(const std::string aNodeType, FactoryFunction* aFactory);
+
     double _altitudeFt = 0.0;
 	double _speed = 0.0; // knots IAS or mach
 	RouteRestriction _altRestrict = RESTRICT_NONE;
diff --git a/src/Navaids/waypoint.cxx b/src/Navaids/waypoint.cxx
index 9f8d0fa17..03ee819a6 100644
--- a/src/Navaids/waypoint.cxx
+++ b/src/Navaids/waypoint.cxx
@@ -47,18 +47,20 @@ BasicWaypt::BasicWaypt(RouteBase* aOwner) :
 {
 }
 
-void BasicWaypt::initFromProperties(SGPropertyNode_ptr aProp)
+bool BasicWaypt::initFromProperties(SGPropertyNode_ptr aProp)
 {
   if (!aProp->hasChild("lon") || !aProp->hasChild("lat")) {
-    throw sg_io_exception("missing lon/lat properties", 
-      "BasicWaypt::initFromProperties");
+      SG_LOG(SG_AUTOPILOT, SG_WARN, "missing lon/lat properties");
+      return false;
   }
 
-  Waypt::initFromProperties(aProp);
+  if (!Waypt::initFromProperties(aProp))
+      return false;
 
   _pos = SGGeod::fromDeg(aProp->getDoubleValue("lon"), 
     aProp->getDoubleValue("lat"));
   _ident = aProp->getStringValue("ident");
+  return true;
 }
 
 void BasicWaypt::writeToProperties(SGPropertyNode_ptr aProp) const
@@ -102,15 +104,16 @@ std::string NavaidWaypoint::ident() const
   return _navaid->ident();
 }
 
-void NavaidWaypoint::initFromProperties(SGPropertyNode_ptr aProp)
+bool NavaidWaypoint::initFromProperties(SGPropertyNode_ptr aProp)
 {
   if (!aProp->hasChild("ident")) {
-    throw sg_io_exception("missing navaid value", 
-      "NavaidWaypoint::initFromProperties");
+      SG_LOG(SG_AUTOPILOT, SG_WARN, "missing navaid ident");
+      return false;
   }
-  
-  Waypt::initFromProperties(aProp);
-  
+
+  if (!Waypt::initFromProperties(aProp))
+      return false;
+
   std::string idn(aProp->getStringValue("ident"));
   SGGeod p;
   if (aProp->hasChild("lon")) {
@@ -121,8 +124,8 @@ void NavaidWaypoint::initFromProperties(SGPropertyNode_ptr aProp)
   // is it sufficent just to ignore DMEs, actually?
   FGPositionedRef nav = FGPositioned::findClosestWithIdent(idn, p, nullptr);
   if (!nav) {
-    throw sg_io_exception("unknown navaid ident:" + idn, 
-      "NavaidWaypoint::initFromProperties");
+      SG_LOG(SG_AUTOPILOT, SG_WARN, "unknown navdaid ident:" << idn);
+      return false;
   }
 
   if (p.isValid() && (SGGeodesy::distanceM(nav->geod(), p) > 4000)) {
@@ -130,12 +133,12 @@ void NavaidWaypoint::initFromProperties(SGPropertyNode_ptr aProp)
       // in this case, throw an exception here so we fall back to using
       // a basic waypoint
       // see https://sourceforge.net/p/flightgear/codetickets/1814/
-      throw sg_io_exception("Waypoint navaid for ident:" + idn +
-                            " is too far from specified lat/lon in flight-plan",
-                            "NavaidWaypoint::initFromProperties");
+      SG_LOG(SG_AUTOPILOT, SG_WARN, "Waypoint navaid for ident:" << idn << " is too far from the specified lat/lon");
+      return false;
   }
   
   _navaid = nav;
+  return true;
 }
 
 void NavaidWaypoint::writeToProperties(SGPropertyNode_ptr aProp) const
@@ -170,17 +173,20 @@ void OffsetNavaidWaypoint::init()
   _geod = SGGeod::fromGeodFt(offset, _altitudeFt);
 }
 
-void OffsetNavaidWaypoint::initFromProperties(SGPropertyNode_ptr aProp)
+bool OffsetNavaidWaypoint::initFromProperties(SGPropertyNode_ptr aProp)
 {
   if (!aProp->hasChild("radial-deg") || !aProp->hasChild("distance-nm")) {
-    throw sg_io_exception("missing radial/offset distance",
-      "OffsetNavaidWaypoint::initFromProperties");
+      SG_LOG(SG_AUTOPILOT, SG_WARN, "missing radial/offset distance creating offset waypoint");
+      return false;
   }
-  
-  NavaidWaypoint::initFromProperties(aProp);
+
+  if (!NavaidWaypoint::initFromProperties(aProp))
+      return false;
+
   _radial = aProp->getDoubleValue("radial-deg");
   _distanceNm = aProp->getDoubleValue("distance-nm");
   init();
+  return true;
 }
 
 void OffsetNavaidWaypoint::writeToProperties(SGPropertyNode_ptr aProp) const
@@ -224,17 +230,31 @@ double RunwayWaypt::headingRadialDeg() const
   return _runway->headingDeg();
 }
 
-void RunwayWaypt::initFromProperties(SGPropertyNode_ptr aProp)
+bool RunwayWaypt::initFromProperties(SGPropertyNode_ptr aProp)
 {
   if (!aProp->hasChild("icao") || !aProp->hasChild("ident")) {
-    throw sg_io_exception("missing values: icao or ident", 
-      "RunwayWaypoint::initFromProperties");
+      SG_LOG(SG_AUTOPILOT, SG_WARN, "missing ICAO/ident on runway waypoint");
+      return false;
   }
-  
-  Waypt::initFromProperties(aProp);
+
+  if (!Waypt::initFromProperties(aProp))
+      return false;
+
   std::string idn(aProp->getStringValue("ident"));
   const FGAirport* apt = FGAirport::getByIdent(aProp->getStringValue("icao"));
-  _runway = apt->getRunwayByIdent(aProp->getStringValue("ident"));
+  if (!apt) {
+      SG_LOG(SG_AUTOPILOT, SG_WARN, "Unknown airport:" << aProp->getStringValue("icao"));
+      return false;
+  }
+
+  const std::string ident = aProp->getStringValue("ident");
+  if (!apt->hasRunwayWithIdent(ident)) {
+      SG_LOG(SG_AUTOPILOT, SG_WARN, "Unknown runway " << ident << " at " << aProp->getStringValue("icao"));
+      return false;
+  }
+
+  _runway = apt->getRunwayByIdent(ident);
+  return true;
 }
 
 void RunwayWaypt::writeToProperties(SGPropertyNode_ptr aProp) const
@@ -286,20 +306,18 @@ void Hold::setLeftHanded()
 {
   _righthanded = false;
 }
-  
-void Hold::initFromProperties(SGPropertyNode_ptr aProp)
-{
-  BasicWaypt::initFromProperties(aProp);
-  
-  if (!aProp->hasChild("lon") || !aProp->hasChild("lat")) {
-    throw sg_io_exception("missing lon/lat properties", 
-      "Hold::initFromProperties");
-  }
 
-  _righthanded = aProp->getBoolValue("right-handed");
-  _isDistance = aProp->getBoolValue("is-distance");
-  _bearing = aProp->getDoubleValue("inbound-radial-deg");
-  _holdTD = aProp->getDoubleValue("td");
+bool Hold::initFromProperties(SGPropertyNode_ptr aProp)
+{
+    if (!BasicWaypt::initFromProperties(aProp))
+        return false;
+
+    _righthanded = aProp->getBoolValue("right-handed");
+    _isDistance = aProp->getBoolValue("is-distance");
+    _bearing = aProp->getDoubleValue("inbound-radial-deg");
+    _holdTD = aProp->getDoubleValue("td");
+
+    return true;
 }
 
 void Hold::writeToProperties(SGPropertyNode_ptr aProp) const
@@ -328,16 +346,19 @@ HeadingToAltitude::HeadingToAltitude(RouteBase* aOwner) :
 {
 }
 
-void HeadingToAltitude::initFromProperties(SGPropertyNode_ptr aProp)
+bool HeadingToAltitude::initFromProperties(SGPropertyNode_ptr aProp)
 {
   if (!aProp->hasChild("heading-deg")) {
-    throw sg_io_exception("missing heading/alt properties", 
-      "HeadingToAltitude::initFromProperties");
+      SG_LOG(SG_AUTOPILOT, SG_WARN, "Missing heading property creating HdgToAlt waypoint");
+      return false;
   }
 
-  Waypt::initFromProperties(aProp);
+  if (!Waypt::initFromProperties(aProp))
+      return false;
+
   _magHeading = aProp->getDoubleValue("heading-deg");
   _ident = aProp->getStringValue("ident");
+  return true;
 }
 
 void HeadingToAltitude::writeToProperties(SGPropertyNode_ptr aProp) const
@@ -365,20 +386,23 @@ DMEIntercept::DMEIntercept(RouteBase* aOwner) :
 {
 }
 
-void DMEIntercept::initFromProperties(SGPropertyNode_ptr aProp)
+bool DMEIntercept::initFromProperties(SGPropertyNode_ptr aProp)
 {
   if (!aProp->hasChild("lon") || !aProp->hasChild("lat")) {
-    throw sg_io_exception("missing lon/lat properties", 
-      "DMEIntercept::initFromProperties");
+      SG_LOG(SG_AUTOPILOT, SG_WARN, "Missing lat/lom properties creating DMEIntc waypoint");
+      return false;
   }
 
-  Waypt::initFromProperties(aProp);
+  if (!Waypt::initFromProperties(aProp))
+      return false;
+
   _pos = SGGeod::fromDeg(aProp->getDoubleValue("lon"), aProp->getDoubleValue("lat"));
   _ident = aProp->getStringValue("ident");
 // check it's a real DME?
   _magCourse = aProp->getDoubleValue("course-deg");
   _dmeDistanceNm = aProp->getDoubleValue("dme-distance-nm");
-  
+
+  return true;
 }
 
 void DMEIntercept::writeToProperties(SGPropertyNode_ptr aProp) const
@@ -409,21 +433,24 @@ RadialIntercept::RadialIntercept(RouteBase* aOwner) :
   Waypt(aOwner)
 {
 }
-  
-void RadialIntercept::initFromProperties(SGPropertyNode_ptr aProp)
+
+bool RadialIntercept::initFromProperties(SGPropertyNode_ptr aProp)
 {
   if (!aProp->hasChild("lon") || !aProp->hasChild("lat")) {
-    throw sg_io_exception("missing lon/lat properties", 
-      "RadialIntercept::initFromProperties");
+      SG_LOG(SG_AUTOPILOT, SG_WARN, "Missing lat/lom properties creating RadialIntercept waypoint");
+      return false;
   }
 
-  Waypt::initFromProperties(aProp);
+  if (!Waypt::initFromProperties(aProp))
+      return false;
+
   _pos = SGGeod::fromDeg(aProp->getDoubleValue("lon"), aProp->getDoubleValue("lat"));
   _ident = aProp->getStringValue("ident");
 // check it's a real VOR?
   _magCourse = aProp->getDoubleValue("course-deg");
   _radial = aProp->getDoubleValue("radial-deg");
-  
+
+  return true;
 }
 
 void RadialIntercept::writeToProperties(SGPropertyNode_ptr aProp) const
@@ -465,21 +492,21 @@ string ATCVectors::ident() const
   return "VECTORS-" + _facility->ident();
 }
 
-void ATCVectors::initFromProperties(SGPropertyNode_ptr aProp)
-{  
-  if (!aProp->hasChild("icao")) {
-    throw sg_io_exception("missing icao propertie", 
-      "ATCVectors::initFromProperties");
-  }
+bool ATCVectors::initFromProperties(SGPropertyNode_ptr aProp)
+{
+    if (!Waypt::initFromProperties(aProp))
+        return false;
 
-  Waypt::initFromProperties(aProp);
-  _facility = FGAirport::getByIdent(aProp->getStringValue("icao"));
+    _facility = FGAirport::getByIdent(aProp->getStringValue("icao"));
+    return true;
 }
 
 void ATCVectors::writeToProperties(SGPropertyNode_ptr aProp) const
 {
   Waypt::writeToProperties(aProp);
-  aProp->setStringValue("icao", _facility->ident());
+  if (_facility) {
+      aProp->setStringValue("icao", _facility->ident());
+  }
 }
 
 /////////////////////////////////////////////////////////////////////////////
@@ -505,8 +532,9 @@ string Discontinuity::ident() const
     return "DISCONTINUITY";
 }
 
-void Discontinuity::initFromProperties(SGPropertyNode_ptr aProp)
+bool Discontinuity::initFromProperties(SGPropertyNode_ptr aProp)
 {
+    return true;
 }
 
 void Discontinuity::writeToProperties(SGPropertyNode_ptr aProp) const
@@ -542,21 +570,22 @@ Via::~Via()
 {
 }
 
-void Via::initFromProperties(SGPropertyNode_ptr aProp)
+bool Via::initFromProperties(SGPropertyNode_ptr aProp)
 {
     if (!aProp->hasChild("airway") || !aProp->hasChild("to")) {
-        throw sg_io_exception("missing airway/to properties",
-                              "Via::initFromProperties");
+        SG_LOG(SG_AUTOPILOT, SG_WARN, "Missingairway/to properties on Via wp");
+        return false;
     }
 
-    Waypt::initFromProperties(aProp);
+    if (!Waypt::initFromProperties(aProp))
+        return false;
 
     const std::string ident = aProp->getStringValue("airway");
     const Airway::Level level = static_cast<Airway::Level>(aProp->getIntValue("level", Airway::Both));
     _airway = Airway::findByIdent(ident, level);
     if (!_airway) {
-        throw sg_io_exception("unknown airway ident: '" + ident + "'",
-                              "Via::initFromProperties");
+        SG_LOG(SG_AUTOPILOT, SG_WARN, "VIA: unknown airway:" << ident);
+        return false;
     }
 
     std::string idn(aProp->getStringValue("to"));
@@ -568,8 +597,8 @@ void Via::initFromProperties(SGPropertyNode_ptr aProp)
 
     FGPositionedRef nav = FGPositioned::findClosestWithIdent(idn, p, nullptr);
     if (!nav) {
-        throw sg_io_exception("unknown navaid ident:" + idn,
-                              "Via::initFromProperties");
+        SG_LOG(SG_AUTOPILOT, SG_WARN, "VIA TO navaid: " << idn << " not found");
+        return false;
     }
     
     if (!_airway->containsNavaid(nav)) {
@@ -578,6 +607,7 @@ void Via::initFromProperties(SGPropertyNode_ptr aProp)
     }
 
     _to = nav;
+    return true;
 }
 
 void Via::writeToProperties(SGPropertyNode_ptr aProp) const
diff --git a/src/Navaids/waypoint.hxx b/src/Navaids/waypoint.hxx
index cb67bd147..2aefae9e4 100644
--- a/src/Navaids/waypoint.hxx
+++ b/src/Navaids/waypoint.hxx
@@ -44,10 +44,10 @@ public:
 
     std::string icaoDescription() const override;
 protected:
-  virtual void initFromProperties(SGPropertyNode_ptr aProp);
-  virtual void writeToProperties(SGPropertyNode_ptr aProp) const;
+    bool initFromProperties(SGPropertyNode_ptr aProp) override;
+    void writeToProperties(SGPropertyNode_ptr aProp) const override;
 
-  virtual std::string type() const
+    virtual std::string type() const
     { return "basic"; } 
 
   SGGeod _pos;
@@ -72,12 +72,13 @@ public:
     { return _navaid; }
     
   virtual std::string ident() const;
-protected:	
-  virtual void initFromProperties(SGPropertyNode_ptr aProp);
-  virtual void writeToProperties(SGPropertyNode_ptr aProp) const;
+
+  protected:
+  bool initFromProperties(SGPropertyNode_ptr aProp) override;
+  void writeToProperties(SGPropertyNode_ptr aProp) const override;
 
   virtual std::string type() const
-    { return "navaid"; }
+  { return "navaid"; }
     
   FGPositionedRef _navaid;
 };
@@ -93,10 +94,10 @@ public:
     { return _geod; }
 
 protected:
-  virtual void initFromProperties(SGPropertyNode_ptr aProp);
-  virtual void writeToProperties(SGPropertyNode_ptr aProp) const;
-  
-  virtual std::string type() const
+    bool initFromProperties(SGPropertyNode_ptr aProp) override;
+    void writeToProperties(SGPropertyNode_ptr aProp) const override;
+
+    virtual std::string type() const
     { return "offset-navaid"; }
     
 private:
@@ -132,9 +133,9 @@ public:
 protected:	
   virtual std::string type() const
     { return "runway"; }
-  
-  virtual void initFromProperties(SGPropertyNode_ptr aProp);
-  virtual void writeToProperties(SGPropertyNode_ptr aProp) const;
+
+    bool initFromProperties(SGPropertyNode_ptr aProp) override;
+    void writeToProperties(SGPropertyNode_ptr aProp) const override;
 
 private:
   FGRunway* _runway;
@@ -169,10 +170,10 @@ public:
   virtual double headingRadialDeg() const
   { return inboundRadial(); }
 protected:
-  virtual void initFromProperties(SGPropertyNode_ptr aProp);
-  virtual void writeToProperties(SGPropertyNode_ptr aProp) const;
-  
-  virtual std::string type() const
+    bool initFromProperties(SGPropertyNode_ptr aProp) override;
+    void writeToProperties(SGPropertyNode_ptr aProp) const override;
+
+    virtual std::string type() const
     { return "hold"; }
     
 private:
@@ -188,10 +189,10 @@ public:
   HeadingToAltitude(RouteBase* aOwner, const std::string& aIdent, double aMagHdg);
   
   HeadingToAltitude(RouteBase* aOwner);
-  
-  virtual void initFromProperties(SGPropertyNode_ptr aProp);
-  virtual void writeToProperties(SGPropertyNode_ptr aProp) const;
-  
+
+  bool initFromProperties(SGPropertyNode_ptr aProp) override;
+  void writeToProperties(SGPropertyNode_ptr aProp) const override;
+
   virtual std::string type() const
     { return "hdgToAlt"; }
 
@@ -221,10 +222,10 @@ public:
     double aCourseDeg, double aDistanceNm);
   
   DMEIntercept(RouteBase* aOwner);
-  
-  virtual void initFromProperties(SGPropertyNode_ptr aProp);
-  virtual void writeToProperties(SGPropertyNode_ptr aProp) const;
-  
+
+  bool initFromProperties(SGPropertyNode_ptr aProp) override;
+  void writeToProperties(SGPropertyNode_ptr aProp) const override;
+
   virtual std::string type() const
     { return "dmeIntercept"; }
 
@@ -256,10 +257,10 @@ public:
     double aCourseDeg, double aRadialDeg);
   
   RadialIntercept(RouteBase* aOwner);
-  
-  virtual void initFromProperties(SGPropertyNode_ptr aProp);
-  virtual void writeToProperties(SGPropertyNode_ptr aProp) const;
-  
+
+  bool initFromProperties(SGPropertyNode_ptr aProp) override;
+  void writeToProperties(SGPropertyNode_ptr aProp) const override;
+
   virtual std::string type() const
     { return "radialIntercept"; }
 
@@ -296,10 +297,10 @@ public:
   virtual ~ATCVectors();
   
   ATCVectors(RouteBase* aOwner);
-  
-  virtual void initFromProperties(SGPropertyNode_ptr aProp);
-  virtual void writeToProperties(SGPropertyNode_ptr aProp) const;
-  
+
+  bool initFromProperties(SGPropertyNode_ptr aProp) override;
+  void writeToProperties(SGPropertyNode_ptr aProp) const override;
+
   virtual std::string type() const
     { return "vectors"; }
 
@@ -326,8 +327,8 @@ public:
     virtual ~Discontinuity();
     Discontinuity(RouteBase* aOwner);
 
-    virtual void initFromProperties(SGPropertyNode_ptr aProp);
-    virtual void writeToProperties(SGPropertyNode_ptr aProp) const;
+    bool initFromProperties(SGPropertyNode_ptr aProp) override;
+    void writeToProperties(SGPropertyNode_ptr aProp) const override;
 
     virtual std::string type() const
     { return "discontinuity"; }
@@ -348,7 +349,7 @@ public:
     Via(RouteBase* aOwner, AirwayRef airway, FGPositionedRef to);
     virtual ~Via();
 
-    void initFromProperties(SGPropertyNode_ptr aProp) override;
+    bool initFromProperties(SGPropertyNode_ptr aProp) override;
     void writeToProperties(SGPropertyNode_ptr aProp) const override;
 
     std::string type() const override