手順 2:新しい投影図法の定義
この手順では、投影図法へのパラメーターの追加方法と、それら追加パラメーターに対応する入出力関数の書き方について説明します。また、特定エラー・コードの作成方法にも触れます。
この投影図法のコード一式は、proj_step2.h ファイルと proj_step2.cpp ファイルに入っています。
新規パラメーターの定義
メルカトル図法では、距離は保持されません。メルカトル図法の場合、倍率が緯度によって変化します。さらに、ポイントが赤道から離れれば離れるほど倍率は大きくなります。ただし、実縮尺の緯度を指定できます。すなわち、その緯度を基準として投影したポイント間の距離が維持されます。
以下の例によって、この新規パラメーターを紹介するとともに、その永続性の管理方法を示します。
新規エラー・コードの定義
メルカトル図法の前記手順で見たとおり、ポイントの順投影では、ポイントが極に近付きすぎるとエラーが発生する場合があります。汎用エラー・コードの IlvProjection::ToleranceConditionError() を返す代わりに、この場合に返される特定のエラー・コードを作成します。
新規クラスの宣言
メルカトル・クラスの第 2 版を、ファイル proj_step2.h で宣言します。
サンプル・コードで追加したのは、次のものです。
実縮尺の緯度を設定するメソッド
実縮尺の緯度を取得するメソッド
メルカトル図法の特定エラー・コードを取得するための、
PolarZoneError スタティック・メソッド
デフォルトの
IlvProjection::write メソッドをオーバーライドする仮想
write メソッド
新規エラー・コードの割り当てに使用する、
InitClass プライベート・スタティック・メソッド
実縮尺の緯度を格納するプライベート・フィールド
エラー・コードを格納するプライベート・スタティック・フィールド
class Mercator :public IlvProjection
{
public:
Mercator();
void setLatitudeOfTrueScale(IlvDouble latitudeOfTrueScale)
{_latitudeOfTrueScale = latitudeOfTrueScale;}
IlvDouble getLatitudeOfTrueScale() const
{return _latitudeOfTrueScale;}
static IlvMapsError PolarZoneError() {return _polarZoneError;}
virtual void write(IlvOutputFile&) const;
protected:
virtual IlvMapsError sForward(IlvCoordinate &) const;
virtual IlvMapsError sInverse(IlvCoordinate &) const;
virtual IlvMapsError eForward(IlvCoordinate &) const;
virtual IlvMapsError eInverse(IlvCoordinate &) const;
private:
static void InitClass();
private:
IlvDouble _latitudeOfTrueScale;
static IlvMapsError _polarZoneError;
IlvMapsDeclareProjectionIO(Mercator);
};
投影図法の定義
投影図法は、proj_step2.cpp ファイルで定義されます。
クラスを定義するためには、IlvMapsDefineProjectionIO マクロを使用します。このマクロは、追加パラメーターの保存が必要な投影図法用の IlvMapsDefineBasicProjectionIO マクロの代わりに使用する必要があります。
この手順では、エラー・コードを初期化する Mercator::InitClass() スタティック・プライベート関数に、マクロの初期化ステートメントを設定します。この場所でメルカトル・クラスのスタティック・プライベート関数を呼び出すことができます。Mercator クラスの friend として、IlvMapsDeclareProjectionIO マクロによって宣言された用途で、IlvMapsDefineProjectionIO マクロが初期化ステートメントを生成するからです。
IlvMapsDefineProjectionIO(Mercator,
IlvProjection,
"My Mercator Implementation",
new Mercator(),
Mercator::InitClass());
エラー・コードの初期化
新規エラー・コードは InitClass メソッドによって呼び出されます。このメソッドは静的初期化の段階で、自動的に呼び出されます。
void
Mercator::InitClass()
{
_polarZoneError =
IlvMaps::CreateError("&MercatorPolarZoneError");
}
新規パラメーターと新規エラー・コードの使用
実縮尺の緯度と新規エラー・コードは、順関数および逆関数で使用されます。次の例では、投影図法関数におけるそれらの使用法を示します。
IlvMapsError
Mercator::sForward(IlvCoordinate& ll) const
{
if (fabs(fabs(ll.y()) - IlvMaps::Pi() / 2.)<= 1e-10)
// Returning the specific error code.
return PolarZoneError();
IlvDouble k = cos(_latitudeOfTrueScale);
ll.setY(k * log(tan(IlvMaps::Pi() / 4. + 0.5 * ll.y())));
ll.setX(k * ll.x());
return IlvMaps::NoError();
}
新規パラメーターの入出力関数を書く
新規パラメーターの完全な IO サポートを提供するためには、write メソッドを実装して、この追加パラメーターを保存する必要があります。この write メソッドでは、何らかのデータを書き込む前に、スーパークラスの write メソッドを呼び出す必要があります。
void Mercator::write(IlvOutputFile &file) const
{
IlvProjection::write(file);
file.getStream() << _latitudeOfTrueScale << IlvSpc();
}
読み込みコンストラクターの実装も必要です。このコンストラクターは、そのスーパークラスの読み込みコンストラクターを呼び出してから、実縮尺の緯度を読み込みます。
Mercator::Mercator(IlvInputFile& file)
:IlvProjection(file)
{
file.getStream() >> _latitudeOfTrueScale;
}
最後に、この新規パラメーターのコピーを実装するために、コピー・コンストラクターを更新する必要があります。
Mercator::Mercator(const Mercator& source)
:IlvProjection(source),
_latitudeOfTrueScale(source._latitudeOfTrueScale)
{
}
Version 6.0
Copyright © 2015, Rogue Wave Software, Inc. All Rights Reserved.