Program Listing for File BaseCurve.hxx

Return to documentation for file (Clothoids/BaseCurve.hxx)

/*--------------------------------------------------------------------------*\
 |                                                                          |
 |  Copyright (C) 2017                                                      |
 |                                                                          |
 |         , __                 , __                                        |
 |        /|/  \               /|/  \                                       |
 |         | __/ _   ,_         | __/ _   ,_                                |
 |         |   \|/  /  |  |   | |   \|/  /  |  |   |                        |
 |         |(__/|__/   |_/ \_/|/|(__/|__/   |_/ \_/|/                       |
 |                           /|                   /|                        |
 |                           \|                   \|                        |
 |                                                                          |
 |      Enrico Bertolazzi                                                   |
 |      Dipartimento di Ingegneria Industriale                              |
 |      Universita` degli Studi di Trento                                   |
 |      email: enrico.bertolazzi@unitn.it                                   |
 |                                                                          |
\*--------------------------------------------------------------------------*/


namespace G2lib {

  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  /*\
   |  ____                  ____
   | | __ )  __ _ ___  ___ / ___|   _ _ ____   _____
   | |  _ \ / _` / __|/ _ \ |  | | | | '__\ \ / / _ \
   | | |_) | (_| \__ \  __/ |__| |_| | |   \ V /  __/
   | |____/ \__,_|___/\___|\____\__,_|_|    \_/ \___|
  \*/

  typedef enum {
    G2LIB_LINE=0,
    G2LIB_POLYLINE,
    G2LIB_CIRCLE,
    G2LIB_BIARC,
    G2LIB_BIARC_LIST,
    G2LIB_CLOTHOID,
    G2LIB_CLOTHOID_LIST
  } CurveType;

  extern char const *CurveType_name[];

  typedef std::pair<real_type,real_type> Ipair;
  typedef std::vector<Ipair>             IntersectList;

  /*\
   |   _       _                          _
   |  (_)_ __ | |_ ___ _ __ ___  ___  ___| |_
   |  | | '_ \| __/ _ \ '__/ __|/ _ \/ __| __|
   |  | | | | | ||  __/ |  \__ \  __/ (__| |_
   |  |_|_| |_|\__\___|_|  |___/\___|\___|\__|
  \*/

  class BaseCurve;

  bool
  collision( BaseCurve const & C1, BaseCurve const & C2 );

  bool
  collision_ISO(
    BaseCurve const & C1,
    real_type         offs_C1,
    BaseCurve const & C2,
    real_type         offs_C2
  );

  inline
  bool
  collision_SAE(
    BaseCurve const & C1,
    real_type         offs_C1,
    BaseCurve const & C2,
    real_type         offs_C2
  ) {
    return collision_ISO( C1, -offs_C1, C2, -offs_C2 );
  }

  #ifdef G2LIB_COMPATIBILITY_MODE
  inline
  bool
  collision(
    BaseCurve const & C1,
    real_type         offs_C1,
    BaseCurve const & C2,
    real_type         offs_C2
  ) {
    if ( G2lib::use_ISO ) return collision_ISO( C1, offs_C1, C2, offs_C2 );
    else                  return collision_SAE( C1, offs_C1, C2, offs_C2 );
  }
  #endif

  void
  intersect(
    BaseCurve const & C1,
    BaseCurve const & C2,
    IntersectList   & ilist,
    bool              swap_s_vals
  );

  void
  intersect_ISO(
    BaseCurve const & C1,
    real_type         offs_C1,
    BaseCurve const & C2,
    real_type         offs_C2,
    IntersectList   & ilist,
    bool              swap_s_vals
  );

  inline
  void
  intersect_SAE(
    BaseCurve const & C1,
    real_type         offs_C1,
    BaseCurve const & C2,
    real_type         offs_C2,
    IntersectList   & ilist,
    bool              swap_s_vals
  ) {
    intersect_ISO( C1, -offs_C1, C2, -offs_C2, ilist, swap_s_vals );
  }

  #ifdef G2LIB_COMPATIBILITY_MODE
  inline
  void
  intersect(
    BaseCurve const & C1,
    real_type         offs_C1,
    BaseCurve const & C2,
    real_type         offs_C2,
    IntersectList   & ilist,
    bool              swap_s_vals
  ) {
    if ( G2lib::use_ISO ) intersect_ISO( C1, offs_C1, C2, offs_C2, ilist, swap_s_vals );
    else                  intersect_SAE( C1, offs_C1, C2, offs_C2, ilist, swap_s_vals );
  }
  #endif

  class BaseCurve {

    // block default constructor
    BaseCurve( BaseCurve const & ) = delete;
    BaseCurve const & operator = ( BaseCurve const & ) = delete;

  protected:
    CurveType m_type;

  public:

    BaseCurve( CurveType const & type )
    : m_type(type)
    {}

    virtual
    ~BaseCurve() {}

    CurveType type() const { return m_type; }

    // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

    virtual real_type length() const = 0;

    virtual real_type length_ISO( real_type offs ) const = 0;

    real_type
    length_SAE( real_type offs ) const
    { return this->length_ISO(-offs); }

    #ifdef G2LIB_COMPATIBILITY_MODE
    real_type
    length( real_type offs ) const
    { return G2lib::use_ISO ? this->length_ISO(offs) : this->length_SAE(offs); }
    #endif

    /*\
     |   _     _
     |  | |__ | |__   _____  __
     |  | '_ \| '_ \ / _ \ \/ /
     |  | |_) | |_) | (_) >  <
     |  |_.__/|_.__/ \___/_/\_\
    \*/

    virtual
    void
    bbox(
      real_type & xmin,
      real_type & ymin,
      real_type & xmax,
      real_type & ymax
    ) const = 0;

    virtual
    void
    bbox_ISO(
      real_type   offs,
      real_type & xmin,
      real_type & ymin,
      real_type & xmax,
      real_type & ymax
    ) const = 0;

    void
    bbox_SAE(
      real_type   offs,
      real_type & xmin,
      real_type & ymin,
      real_type & xmax,
      real_type & ymax
    ) const {
      this->bbox_ISO( -offs, xmin, ymin, xmax, ymax );
    }

    #ifdef G2LIB_COMPATIBILITY_MODE
    void
    bbox(
      real_type   offs,
      real_type & xmin,
      real_type & ymin,
      real_type & xmax,
      real_type & ymax
    ) const {
      if ( G2lib::use_ISO ) this->bbox_ISO( offs, xmin, ymin, xmax, ymax );
      else                  this->bbox_SAE( offs, xmin, ymin, xmax, ymax );
    }
    #endif

    /*\
     |   _    _   _____    _                _
     |  | |__| |_|_   _| _(_)__ _ _ _  __ _| |___
     |  | '_ \ '_ \| || '_| / _` | ' \/ _` | / -_)
     |  |_.__/_.__/|_||_| |_\__,_|_||_\__, |_\___|
     |                                |___/
    \*/

    virtual
    void
    bbTriangles(
      std::vector<Triangle2D> & tvec,
      real_type                 max_angle = Utils::m_pi/18,
      real_type                 max_size  = 1e100,
      int_type                  icurve    = 0
    ) const = 0;

    virtual
    void
    bbTriangles_ISO(
      real_type                 offs,
      std::vector<Triangle2D> & tvec,
      real_type                 max_angle = Utils::m_pi/18,
      real_type                 max_size  = 1e100,
      int_type                  icurve    = 0
    ) const = 0;

    virtual
    void
    bbTriangles_SAE(
      real_type                 offs,
      std::vector<Triangle2D> & tvec,
      real_type                 max_angle = Utils::m_pi/18,
      real_type                 max_size  = 1e100,
      int_type                  icurve    = 0
    ) const = 0;

    /*\
     |   ____             _          _______           _
     |  | __ )  ___  __ _(_)_ __    / / ____|_ __   __| |
     |  |  _ \ / _ \/ _` | | '_ \  / /|  _| | '_ \ / _` |
     |  | |_) |  __/ (_| | | | | |/ / | |___| | | | (_| |
     |  |____/ \___|\__, |_|_| |_/_/  |_____|_| |_|\__,_|
     |              |___/
    \*/

    virtual real_type thetaBegin() const { return this->theta(0); }

    virtual real_type thetaEnd() const { return this->theta(this->length()); }

    virtual real_type kappaBegin() const { return this->kappa(0); }

    virtual real_type kappaEnd() const { return this->kappa(this->length()); }

    virtual real_type xBegin() const { return this->X(0); }

    virtual real_type yBegin() const { return this->Y(0); }

    virtual real_type xEnd() const { return this->X(this->length()); }

    virtual real_type yEnd() const { return this->Y(this->length()); }

    virtual real_type xBegin_ISO( real_type offs ) const { return this->X_ISO(0,offs); }

    virtual real_type yBegin_ISO( real_type offs ) const { return this->Y_ISO(0,offs); }

    virtual real_type xEnd_ISO( real_type offs ) const { return this->X_ISO(this->length(),offs); }

    virtual real_type yEnd_ISO( real_type offs ) const { return this->Y_ISO(this->length(),offs); }

    real_type xBegin_SAE( real_type offs ) const { return this->xBegin_ISO(-offs); }

    real_type yBegin_SAE( real_type offs ) const { return this->yBegin_ISO(-offs); }

    real_type xEnd_SAE( real_type offs ) const { return this->xEnd_ISO(-offs); }

    real_type yEnd_SAE( real_type offs ) const { return this->yEnd_ISO(-offs); }

    #ifdef G2LIB_COMPATIBILITY_MODE
    real_type
    xBegin( real_type offs ) const
    { return G2lib::use_ISO ? this->xBegin_ISO(offs) : this->xBegin_SAE(offs); }

    real_type
    yBegin( real_type offs ) const
    { return G2lib::use_ISO ? this->yBegin_ISO(offs) : this->yBegin_SAE(offs); }

    real_type
    xEnd( real_type offs ) const
    { return G2lib::use_ISO ? this->xEnd_ISO(offs) : this->xEnd_SAE(offs); }

    real_type
    yEnd( real_type offs ) const
    { return G2lib::use_ISO ? this->yEnd_ISO(offs) : this->yEnd_SAE(offs); }
    #endif

    virtual real_type tx_Begin() const { return this->tx(0); }

    virtual real_type ty_Begin() const { return this->ty(0); }

    virtual real_type tx_End() const { return this->tx(this->length()); }

    virtual real_type ty_End() const { return this->ty(this->length()); }

    virtual real_type nx_Begin_ISO() const { return -this->ty(0); }

    virtual real_type ny_Begin_ISO() const { return this->tx(0); }

    virtual real_type nx_End_ISO() const { return -this->ty(this->length()); }

    virtual real_type ny_End_ISO() const { return this->tx(this->length()); }

    real_type nx_Begin_SAE() const { return -nx_Begin_ISO(); }

    real_type ny_Begin_SAE() const { return -ny_Begin_ISO(); }

    real_type nx_End_SAE() const { return -nx_End_ISO(); }

    real_type ny_End_SAE() const { return -ny_End_ISO(); }

    #ifdef G2LIB_COMPATIBILITY_MODE
    real_type
    nx_Begin() const
    { return G2lib::use_ISO ? this->nx_Begin_ISO() : this->nx_Begin_SAE(); }

    real_type
    ny_Begin() const
    { return G2lib::use_ISO ? this->ny_Begin_ISO() : this->ny_Begin_SAE(); }

    real_type
    nx_End() const
    { return G2lib::use_ISO ? this->nx_End_ISO() : this->nx_End_SAE(); }

    real_type
    ny_End() const
    { return G2lib::use_ISO ? this->ny_End_ISO() : this->ny_End_SAE(); }
    #endif

    /*\
     |  _   _          _
     | | |_| |__   ___| |_ __ _
     | | __| '_ \ / _ \ __/ _` |
     | | |_| | | |  __/ || (_| |
     |  \__|_| |_|\___|\__\__,_|
    \*/

    virtual real_type theta( real_type s ) const = 0;

    virtual real_type theta_D( real_type s ) const = 0;

    virtual real_type theta_DD( real_type s ) const = 0;

    virtual real_type theta_DDD( real_type s ) const = 0;

    /*\
     |   _
     |  | | ____ _ _ __  _ __   __ _
     |  | |/ / _` | '_ \| '_ \ / _` |
     |  |   < (_| | |_) | |_) | (_| |
     |  |_|\_\__,_| .__/| .__/ \__,_|
     |            |_|   |_|
    \*/

    real_type kappa( real_type s ) const { return theta_D(s); }

    real_type kappa_D ( real_type s ) const { return theta_DD(s); }

    real_type kappa_DD( real_type s ) const { return theta_DDD(s); }

    /*\
     |  _____                   _   _   _
     | |_   _|   __ _ _ __   __| | | \ | |
     |   | |    / _` | '_ \ / _` | |  \| |
     |   | |   | (_| | | | | (_| | | |\  |
     |   |_|    \__,_|_| |_|\__,_| |_| \_|
    \*/

    virtual real_type tx( real_type s ) const;

    virtual real_type ty( real_type s ) const;

    virtual real_type tx_D( real_type s ) const;

    virtual real_type ty_D( real_type s ) const;

    virtual real_type tx_DD( real_type s ) const;

    virtual real_type ty_DD( real_type s ) const;

    virtual real_type tx_DDD( real_type s ) const;

    virtual real_type ty_DDD( real_type s ) const;

    // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
    real_type nx_ISO( real_type s ) const { return -ty(s); }

    real_type nx_ISO_D( real_type s ) const { return -ty_D(s); }

    real_type nx_ISO_DD( real_type s ) const { return -ty_DD(s); }

    real_type nx_ISO_DDD( real_type s ) const { return -ty_DDD(s); }

    real_type ny_ISO( real_type s ) const { return tx(s); }

    real_type ny_ISO_D( real_type s ) const { return tx_D(s); }

    real_type ny_ISO_DD( real_type s ) const { return tx_DD(s); }

    real_type ny_ISO_DDD( real_type s ) const { return tx_DDD(s); }

    real_type nx_SAE( real_type s ) const { return ty(s); }

    real_type nx_SAE_D( real_type s ) const { return ty_D(s); }

    real_type nx_SAE_DD( real_type s ) const { return ty_DD(s); }

    real_type nx_SAE_DDD( real_type s ) const { return ty_DDD(s); }

    real_type ny_SAE( real_type s ) const { return -tx(s); }

    real_type ny_SAE_D( real_type s ) const { return -tx_D(s); }

    real_type ny_SAE_DD ( real_type s ) const { return -tx_DD(s); }

    real_type ny_SAE_DDD( real_type s ) const { return -tx_DDD(s); }

    #ifdef G2LIB_COMPATIBILITY_MODE
    real_type nx( real_type s ) const
    { return G2lib::use_ISO ? this->nx_ISO(s) : this->nx_SAE(s); }

    real_type nx_D( real_type s ) const
    { return G2lib::use_ISO ? this->nx_ISO_D(s) : this->nx_SAE_D(s); }

    real_type nx_DD( real_type s ) const
    { return G2lib::use_ISO ? this->nx_ISO_DD(s) : this->nx_SAE_DD(s); }

    real_type nx_DDD( real_type s ) const
    { return G2lib::use_ISO ? this->nx_ISO_DDD(s) : this->nx_SAE_DDD(s); }

    real_type ny( real_type s ) const
    { return G2lib::use_ISO ? this->ny_ISO(s) : this->ny_SAE(s); }

    real_type ny_D( real_type s ) const
    { return G2lib::use_ISO ? this->ny_ISO_D(s) : this->ny_SAE_D(s); }

    real_type ny_DD( real_type s ) const
    { return G2lib::use_ISO ? this->ny_ISO_DD(s) : this->ny_SAE_DD(s); }

    real_type ny_DDD( real_type s ) const
    { return G2lib::use_ISO ? this->ny_ISO_DDD(s) : this->ny_SAE_DDD(s); }
    #endif

    // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

    virtual
    void
    tg( real_type s, real_type & tg_x, real_type & tg_y ) const {
      tg_x = this->tx(s);
      tg_y = this->ty(s);
    }

    virtual
    void
    tg_D( real_type s, real_type & tg_x_D, real_type & tg_y_D ) const {
      tg_x_D = this->tx_D(s);
      tg_y_D = this->ty_D(s);
    }

    virtual
    void
    tg_DD( real_type s, real_type & tg_x_DD, real_type & tg_y_DD ) const {
      tg_x_DD = this->tx_DD(s);
      tg_y_DD = this->ty_DD(s);
    }

    virtual
    void
    tg_DDD( real_type s, real_type & tg_x_DDD, real_type & tg_y_DDD ) const {
      tg_x_DDD = this->tx_DDD(s);
      tg_y_DDD = this->ty_DDD(s);
    }

    // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

    void
    nor_ISO( real_type s, real_type & nx, real_type & ny ) const
    { tg( s, ny, nx ); nx = -nx; }

    void
    nor_ISO_D( real_type s, real_type & nx_D, real_type & ny_D ) const
    { tg_D( s, ny_D, nx_D ); nx_D = -nx_D; }

    void
    nor_ISO_DD( real_type s, real_type & nx_DD, real_type & ny_DD ) const
    { tg_DD( s, ny_DD, nx_DD ); nx_DD = -nx_DD; }

    void
    nor_ISO_DDD( real_type s, real_type & nx_DDD, real_type & ny_DDD ) const
    { tg_DDD( s, ny_DDD, nx_DDD ); nx_DDD = -nx_DDD; }

    void
    nor_SAE( real_type s, real_type & nx, real_type & ny ) const
    { tg( s, ny, nx ); ny = -ny; }

    void
    nor_SAE_D( real_type s, real_type & nx_D, real_type & ny_D ) const
    { tg_D( s, ny_D, nx_D ); ny_D = -ny_D; }

    void
    nor_SAE_DD( real_type s, real_type & nx_DD, real_type & ny_DD ) const
    { tg_DD( s, ny_DD, nx_DD ); ny_DD = -ny_DD; }

    void
    nor_SAE_DDD( real_type s, real_type & nx_DDD, real_type & ny_DDD ) const
    { tg_DDD( s, ny_DDD, nx_DDD ); ny_DDD = -ny_DDD; }

    #ifdef G2LIB_COMPATIBILITY_MODE
    void
    nor( real_type s, real_type & nx, real_type & ny ) const {
      if ( G2lib::use_ISO ) this->nor_ISO(s,nx,ny);
      else                  this->nor_SAE(s,nx,ny);
    }

    void
    nor_D( real_type s, real_type & nx_D, real_type & ny_D ) const {
      if ( G2lib::use_ISO ) this->nor_ISO_D(s,nx_D,ny_D);
      else                  this->nor_SAE_D(s,nx_D,ny_D);
    }

    void
    nor_DD( real_type s, real_type & nx_DD, real_type & ny_DD ) const {
      if ( G2lib::use_ISO ) this->nor_ISO_DD(s,nx_DD,ny_DD);
      else                  this->nor_SAE_DD(s,nx_DD,ny_DD);
    }

    void
    nor_DDD( real_type s, real_type & nx_DDD, real_type & ny_DDD ) const {
      if ( G2lib::use_ISO ) this->nor_ISO_DDD(s,nx_DDD,ny_DDD);
      else                  this->nor_SAE_DDD(s,nx_DDD,ny_DDD);
    }
    #endif

    // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

    virtual
    void
    evaluate(
      real_type   s,
      real_type & th,
      real_type & k,
      real_type & x,
      real_type & y
    ) const {
      eval( s, x, y );
      th = theta( s );
      k  = theta_D( s );
    }

    virtual
    void
    evaluate_ISO(
      real_type   s,
      real_type   offs,
      real_type & th,
      real_type & k,
      real_type & x,
      real_type & y
    ) const {
      eval_ISO( s, offs, x, y );
      th = theta( s );
      k  = theta_D( s );
      k /= 1+offs*k; // scale curvature
    }

    virtual
    void
    evaluate_SAE(
      real_type   s,
      real_type   offs,
      real_type & th,
      real_type & k,
      real_type & x,
      real_type & y
    ) const {
      eval_SAE( s, offs, x, y );
      th = theta( s );
      k  = theta_D( s );
      k /= 1-offs*k; // scale curvature
    }

    #ifdef G2LIB_COMPATIBILITY_MODE
    void
    evaluate(
      real_type   s,
      real_type   offs,
      real_type & th,
      real_type & k,
      real_type & x,
      real_type & y
    ) const {
      if ( G2lib::use_ISO ) this->evaluate_ISO( s, offs, th, k, x, y );
      else                  this->evaluate_SAE( s, offs, th, k, x, y );
    }
    #endif

    // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

    virtual real_type X( real_type s ) const = 0;

    virtual real_type Y( real_type s ) const = 0;

    virtual real_type X_D( real_type s ) const = 0;

    virtual real_type Y_D( real_type s ) const = 0;

    virtual real_type X_DD( real_type s ) const = 0;

    virtual real_type Y_DD( real_type s ) const = 0;

    virtual real_type X_DDD( real_type s ) const = 0;

    virtual real_type Y_DDD( real_type s ) const = 0;

    // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

    virtual
    void
    eval( real_type s, real_type & x, real_type & y ) const = 0;

    virtual
    void
    eval_D( real_type s, real_type & x_D, real_type & y_D ) const = 0;

    virtual
    void
    eval_DD( real_type s, real_type & x_DD, real_type & y_DD ) const = 0;

    virtual
    void
    eval_DDD( real_type s, real_type & x_DDD, real_type & y_DDD ) const = 0;

    /*\
     |         __  __          _
     |   ___  / _|/ _|___  ___| |_
     |  / _ \| |_| |_/ __|/ _ \ __|
     | | (_) |  _|  _\__ \  __/ |_
     |  \___/|_| |_| |___/\___|\__|
    \*/

    virtual real_type X_ISO( real_type s, real_type offs ) const;

    virtual real_type Y_ISO( real_type s, real_type offs ) const;

    virtual real_type X_ISO_D( real_type s, real_type offs ) const;

    virtual real_type Y_ISO_D( real_type s, real_type offs ) const;

    virtual real_type X_ISO_DD( real_type s, real_type offs ) const;

    virtual real_type Y_ISO_DD( real_type s, real_type offs ) const;

    virtual real_type X_ISO_DDD( real_type s, real_type offs ) const;

    virtual real_type Y_ISO_DDD( real_type s, real_type offs ) const;

    real_type X_SAE( real_type s, real_type offs ) const { return this->X_ISO(s,-offs); }

    real_type Y_SAE( real_type s, real_type offs ) const { return this->Y_ISO(s,-offs); }

    real_type X_SAE_D( real_type s, real_type offs ) const { return this->X_ISO_D(s,-offs); }

    real_type Y_SAE_D( real_type s, real_type offs ) const { return this->Y_ISO_D(s,-offs); }

    real_type X_SAE_DD( real_type s, real_type offs ) const { return this->X_ISO_DD(s,-offs); }

    real_type Y_SAE_DD( real_type s, real_type offs ) const { return this->Y_ISO_DD(s,-offs); }

    real_type X_SAE_DDD( real_type s, real_type offs ) const { return this->X_ISO_DDD(s,-offs); }

    real_type Y_SAE_DDD( real_type s, real_type offs ) const { return this->Y_ISO_DDD(s,-offs); }

    #ifdef G2LIB_COMPATIBILITY_MODE
    real_type
    X( real_type s, real_type offs ) const
    { return G2lib::use_ISO ? this->X_ISO( s, offs ) : this->X_SAE( s, offs ); }

    real_type
    Y( real_type s, real_type offs ) const
    { return G2lib::use_ISO ? this->Y_ISO( s, offs ) : this->Y_SAE( s, offs ); }

    real_type
    X_D( real_type s, real_type offs ) const
    { return G2lib::use_ISO ? this->X_ISO_D( s, offs ) : this->X_SAE_D( s, offs ); }

    real_type
    Y_D( real_type s, real_type offs ) const
    { return G2lib::use_ISO ? this->Y_ISO_D( s, offs ) : this->Y_SAE_D( s, offs ); }

    real_type
    X_DD( real_type s, real_type offs ) const
    { return G2lib::use_ISO ? this->X_ISO_DD( s, offs ) : this->X_SAE_DD( s, offs ); }

    real_type
    Y_DD( real_type s, real_type offs ) const
    { return G2lib::use_ISO ? this->Y_ISO_DD( s, offs ) : this->Y_SAE_DD( s, offs ); }

    real_type
    X_DDD( real_type s, real_type offs ) const
    { return G2lib::use_ISO ? this->X_ISO_DDD( s, offs ) : this->X_SAE_DDD( s, offs ); }

    real_type
    Y_DDD( real_type s, real_type offs ) const
    { return G2lib::use_ISO ? this->Y_ISO_DDD( s, offs ) : this->Y_SAE_DDD( s, offs ); }
    #endif

    // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

    virtual
    void
    eval_ISO(
      real_type   s,
      real_type   offs,
      real_type & x,
      real_type & y
    ) const;

    void
    eval_SAE(
      real_type   s,
      real_type   offs,
      real_type & x,
      real_type & y
    ) const {
      this->eval_ISO( s, -offs, x, y );
    }

    #ifdef G2LIB_COMPATIBILITY_MODE
    void
    eval(
      real_type   s,
      real_type   offs,
      real_type & x,
      real_type & y
    ) const {
      if ( G2lib::use_ISO ) this->eval_ISO( s, offs, x, y );
      else                  this->eval_SAE( s, offs, x, y );
    }
    #endif

    virtual
    void
    eval_ISO_D(
      real_type   s,
      real_type   offs,
      real_type & x_D,
      real_type & y_D
    ) const;

    void
    eval_SAE_D(
      real_type   s,
      real_type   offs,
      real_type & x_D,
      real_type & y_D
    ) const {
      this->eval_ISO_D( s, -offs, x_D, y_D );
    }

    #ifdef G2LIB_COMPATIBILITY_MODE
    void
    eval_D(
      real_type   s,
      real_type   offs,
      real_type & x_D,
      real_type & y_D
    ) const {
      if ( G2lib::use_ISO ) this->eval_ISO_D( s, offs, x_D, y_D );
      else                  this->eval_SAE_D( s, offs, x_D, y_D );
    }
    #endif

    virtual
    void
    eval_ISO_DD(
      real_type   s,
      real_type   offs,
      real_type & x_DD,
      real_type & y_DD
    ) const;

    void
    eval_SAE_DD(
      real_type   s,
      real_type   offs,
      real_type & x_DD,
      real_type & y_DD
    ) const {
      this->eval_ISO_DD( s, -offs, x_DD, y_DD );
    }

    #ifdef G2LIB_COMPATIBILITY_MODE
    void
    eval_DD(
      real_type   s,
      real_type   offs,
      real_type & x_DD,
      real_type & y_DD
    ) const {
      if ( G2lib::use_ISO ) this->eval_ISO_DD( s, offs, x_DD, y_DD );
      else                  this->eval_SAE_DD( s, offs, x_DD, y_DD );
    }
    #endif

    virtual
    void
    eval_ISO_DDD(
      real_type   s,
      real_type   offs,
      real_type & x_DDD,
      real_type & y_DDD
    ) const;

    void
    eval_SAE_DDD(
      real_type   s,
      real_type   offs,
      real_type & x_DDD,
      real_type & y_DDD
    ) const {
      this->eval_ISO_DDD( s, -offs, x_DDD, y_DDD );
    }

    #ifdef G2LIB_COMPATIBILITY_MODE
    void
    eval_DDD(
      real_type   s,
      real_type   offs,
      real_type & x_DDD,
      real_type & y_DDD
    ) const {
      if ( G2lib::use_ISO ) this->eval_ISO_DDD( s, offs, x_DDD, y_DDD );
      else                  this->eval_SAE_DDD( s, offs, x_DDD, y_DDD );
    }
    #endif

    /*\
     |  _                        __
     | | |_ _ __ __ _ _ __  ___ / _| ___  _ __ _ __ ___
     | | __| '__/ _` | '_ \/ __| |_ / _ \| '__| '_ ` _ \
     | | |_| | | (_| | | | \__ \  _| (_) | |  | | | | | |
     |  \__|_|  \__,_|_| |_|___/_|  \___/|_|  |_| |_| |_|
    \*/

    virtual
    void
    translate( real_type tx, real_type ty ) = 0;

    virtual
    void
    rotate( real_type angle, real_type cx, real_type cy ) = 0;

    virtual
    void
    scale( real_type sc ) = 0;

    virtual
    void
    reverse() = 0;

    virtual
    void
    changeOrigin( real_type newx0, real_type newy0 ) = 0;

    virtual
    void
    trim( real_type s_begin, real_type s_end ) = 0;

    /*\
     |   _       _                          _
     |  (_)_ __ | |_ ___ _ __ ___  ___  ___| |_
     |  | | '_ \| __/ _ \ '__/ __|/ _ \/ __| __|
     |  | | | | | ||  __/ |  \__ \  __/ (__| |_
     |  |_|_| |_|\__\___|_|  |___/\___|\___|\__|
    \*/

    bool
    collision( BaseCurve const & C ) const
    { return G2lib::collision( *this, C ); }

    bool
    collision_ISO(
      real_type         offs,
      BaseCurve const & C,
      real_type         offs_C
    ) const {
      return G2lib::collision_ISO( *this, offs, C, offs_C );
    }

    bool
    collision_SAE(
      real_type         offs,
      BaseCurve const & C,
      real_type         offs_C
    ) const {
      return G2lib::collision_SAE( *this, offs, C, offs_C );
    }

    #ifdef G2LIB_COMPATIBILITY_MODE
    bool
    collision(
      real_type         offs,
      BaseCurve const & C,
      real_type         offs_C
    ) const {
      if ( G2lib::use_ISO )
        return G2lib::collision_ISO( *this, offs, C, offs_C );
      else
        return G2lib::collision_SAE( *this, offs, C, offs_C );
    }
    #endif

    void
    intersect(
      BaseCurve const & C,
      IntersectList   & ilist,
      bool              swap_s_vals
    ) const {
      G2lib::intersect( *this, C, ilist, swap_s_vals );
    }

    void
    intersect_ISO(
      real_type         offs,
      BaseCurve const & C,
      real_type         offs_C,
      IntersectList   & ilist,
      bool              swap_s_vals
    ) const {
      G2lib::intersect_ISO( *this, offs, C, offs_C, ilist, swap_s_vals );
    }

    void
    intersect_SAE(
      real_type         offs,
      BaseCurve const & C,
      real_type         offs_C,
      IntersectList   & ilist,
      bool              swap_s_vals
    ) const {
      G2lib::intersect_SAE( *this, offs, C, offs_C, ilist, swap_s_vals );
    }

    #ifdef G2LIB_COMPATIBILITY_MODE
    void
    intersect(
      real_type         offs,
      BaseCurve const & C,
      real_type         offs_C,
      IntersectList   & ilist,
      bool              swap_s_vals
    ) const {
      if ( G2lib::use_ISO )
        G2lib::intersect_ISO( *this, offs, C, offs_C, ilist, swap_s_vals );
      else
        G2lib::intersect_SAE( *this, offs, C, offs_C, ilist, swap_s_vals );
    }
    #endif

    /*\
     |      _ _     _
     |   __| (_)___| |_ __ _ _ __   ___ ___
     |  / _` | / __| __/ _` | '_ \ / __/ _ \
     | | (_| | \__ \ || (_| | | | | (_|  __/
     |  \__,_|_|___/\__\__,_|_| |_|\___\___|
    \*/

    virtual
    int_type
    closestPoint_ISO(
      real_type   qx,
      real_type   qy,
      real_type & x,
      real_type & y,
      real_type & s,
      real_type & t,
      real_type & dst
    ) const = 0;

    int_type
    closestPoint_SAE(
      real_type   qx,
      real_type   qy,
      real_type & x,
      real_type & y,
      real_type & s,
      real_type & t,
      real_type & dst
    ) const {
      int_type res = this->closestPoint_ISO( qx, qy, x, y, s, t, dst );
      t = -t;
      return res;
    }

    #ifdef G2LIB_COMPATIBILITY_MODE
    int_type
    closestPoint(
      real_type   qx,
      real_type   qy,
      real_type & x,
      real_type & y,
      real_type & s,
      real_type & t,
      real_type & dst
    ) const {
      if ( G2lib::use_ISO )
        return this->closestPoint_ISO( qx, qy, x, y, s, t, dst );
      else
        return this->closestPoint_SAE( qx, qy, x, y, s, t, dst );
    }
    #endif

    virtual
    int_type // true if projection is unique and orthogonal
    closestPoint_ISO(
      real_type   qx,
      real_type   qy,
      real_type   offs,
      real_type & x,
      real_type & y,
      real_type & s,
      real_type & t,
      real_type & dst
    ) const = 0;

    int_type
    closestPoint_SAE(
      real_type   qx,
      real_type   qy,
      real_type   offs,
      real_type & x,
      real_type & y,
      real_type & s,
      real_type & t,
      real_type & dst
    ) const {
      int_type res = this->closestPoint_ISO( qx, qy, -offs, x, y, s, t, dst );
      t = -t;
      return res;
    }

    #ifdef G2LIB_COMPATIBILITY_MODE
    int_type
    closestPoint(
      real_type   qx,
      real_type   qy,
      real_type   offs,
      real_type & x,
      real_type & y,
      real_type & s,
      real_type & t,
      real_type & dst
    ) const {
      if ( G2lib::use_ISO )
        return this->closestPoint_ISO( qx, qy, offs, x, y, s, t, dst );
      else
        return this->closestPoint_SAE( qx, qy, offs, x, y, s, t, dst );
    }
    #endif

    virtual
    real_type
    distance( real_type qx, real_type qy ) const {
      real_type x, y, s, t, dst;
      closestPoint_ISO( qx, qy, x, y, s, t, dst );
      return dst;
    }

    real_type
    distance_ISO(
      real_type qx,
      real_type qy,
      real_type offs
    ) const {
      real_type x, y, s, t, dst;
      this->closestPoint_ISO( qx, qy, offs, x, y, s, t, dst );
      return dst;
    }

    real_type
    distance_SAE(
      real_type qx,
      real_type qy,
      real_type offs
    ) const {
      real_type x, y, s, t, dst;
      this->closestPoint_SAE( qx, qy, offs, x, y, s, t, dst );
      return dst;
    }

    #ifdef G2LIB_COMPATIBILITY_MODE
    virtual
    real_type
    distance(
      real_type qx,
      real_type qy,
      real_type offs
    ) const {
      real_type x, y, s, t, dst;
      this->closestPoint( qx, qy, offs, x, y, s, t, dst );
      return dst;
    }
    #endif

    /*\
     |    __ _           _ ____ _____
     |   / _(_)_ __   __| / ___|_   _|
     |  | |_| | '_ \ / _` \___ \ | |
     |  |  _| | | | | (_| |___) || |
     |  |_| |_|_| |_|\__,_|____/ |_|
    \*/

    bool
    findST_ISO(
      real_type   x,
      real_type   y,
      real_type & s,
      real_type & t
    ) const {
      real_type X, Y, dst;
      int_type icode = this->closestPoint_ISO( x, y, X, Y, s, t, dst );
      return icode >= 0;
    }

    bool
    findST_SAE(
      real_type   x,
      real_type   y,
      real_type & s,
      real_type & t
    ) const {
      real_type X, Y, dst;
      int_type icode = this->closestPoint_SAE( x, y, X, Y, s, t, dst );
      return icode >= 0;
    }

    #ifdef G2LIB_COMPATIBILITY_MODE
    bool
    findST(
      real_type   x,
      real_type   y,
      real_type & s,
      real_type & t
    ) const {
      real_type X, Y, dst;
      int_type icode = this->closestPoint( x, y, X, Y, s, t, dst );
      return icode >= 0;
    }
    #endif

    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    virtual
    void
    info( ostream_type & stream ) const = 0;

  };

}