ALIBVector Ver 2.0 ユーザーズマニュアル

目次
  1. 概要
  2. CAlibVectorクラスの概要
  3. 新機能2007年
  4. 自動トレースオプション
マニュアルホームページ

概要

ALIBVECTOR Ver1.0は、ラスタベクタ変換ライブラリALVECTOR(1999年12月にリリース)を元に作られた簡易版のライブラリです。

ALVECTORの変換後のベクタ編集機能の一部(簡易CAD機能)と、ベクタデータ構造体への直接アクセス機能がありませんが、ラスタベクタ変換の主要な全ての機能はより使いやすい形で使えます。


  1. 面図形の輪郭線を抽出
    輪郭線(OutLine)を抽出し多角形近似します。線分、円弧あるいはスプライン曲線による近似が可能で、近似の精度と多角形の頂点の数は、パラメータによってコントロールすることができます。
    微小なノイズベクタの自動除去を自動的に行うことができます。
  2. 線図形の芯線を抽出
    線図形の中心線をベクタ化します。線分、円弧あるいはスプライン曲線による近似が可能で、近似の精度と多角形の頂点の数は、パラメータによってコントロールすることができます。
    途切れの自動接続、近接する交点の自動統合、余分な近似線分の生成を抑制します。
    十字路やT字路補正や交差点での線分の自動接続によって、生成されるラインの数を抑制します。
  3. 後処理機能
     ベクタ変換によって生成された全てのポリラインに対して、同じパラメータで一括して処理する機能。
     
    といった後処理機能を提供しています。
     

OS対応

Windows 95、Windows 98、Windows NT、Windows2000、WindowsXp、WindowsVista対応。
Windows 7、Windows 8、Windows 10、Windows11対応(2023年追記)
ライブラリは全てANSI標準のC、C++で記述。
開発環境はVC++が必要。(VS6.0以降、VS.NET2003/2005など)
C言語で開発するためのC言語インターフェイスを持つ動的リンクライブラリやC#、VB、VBScript、JAVA、JavaScript、Perl等から呼び出すことのできるCOM/ActiveXインターフェイスでの提供もしますので、お問い合わせください。

目次


ライブラリのファイル構成

  1. DLL
    DLL 概要
    alibvector.dll ベクタライブラリAPI(C++)
    その他複数のDLL 弊社共通ライブラリ(APIは非公開)

  2. VC++向けインポートライブラリ
    alibvector.dllに対応するalibvector.libが必要です。

  3. ヘッダファイル
    ヘッダファイル 概要
    alibvector.h ラスタベクタ変換ライブラリ
    errcode.h エラーコードの定義

その他、キーファイルが必要となります。契約内容によっては、利用機能制限、利用期間制限、利用機械制限設定されます。
また、契約内容(特に低価格版)によって、マニュアルの供給範囲が異なることがあります。
ヘッダファイルには存在していても、マニュアルに無いAPIは、サポート対象外となります。
目次


クラスライブラリの構成

ラスタベクタ変換のためのクラスは、CALibVectorだけです。インスタンスを作成し、キーファイルあるいはキー文字列を指定後に、 ベクタ変換や後処理のメンバ関数をコールし、 辺や頂点の情報を取得します。

目次


CALibVectorクラスの概要


インスタンスの作成

CALibVectorインスタンスが処理する画像は、モノクロ2値でなければなりません。
画像の背景はbit0/前景(面図形や線図形)はbit1でなければなりません。
座標系はXY座標系で、原点は
のいずれかです。終了時はインスタンスをdeleteするだけです。

リファレンス

// コンストラクタ
// 入力
//  char*   code;           キーコードの入ったキーファイルのフルパス
//                          あるいはキーコード文字列そのもの
//                          初期化の成功/不成功はmisinitrastervectorconversion();による問い合わせで調べる
CALibVector(char* code);
// デストラクタ
~CALibVector();
// 初期化が成功したかどうかの問い合わせ
// 戻り値
//   1....成功
//   0....失敗(キーファイルが見つからない、期限切れ等パーミッションが無い)
int     misinitrastervectorconversion();
// ポリラインを消去する(変換後に別の画像をロードしたときなど)
// インスタンスをdeleteして再度newしてもコストは、あまり変わらない
void                mclearpolyline();

サンプル

CALibVector* plib = new CALibVector("c:\\Program Files\\Foo/vector.kcd");
if(plib->misinitrastervectorconversion() == 0) {
   ;  // パーミッションが無い
}
delete plib;
目次


ノードとポリライン

ラスタベクタ変換の結果は、ポリラインというデータ形式で返されます。
ポリラインは、複数の線分で構成され、各線分の端点(多角形の場合は頂点に相当)をノードとします。
ポリラインに対する編集操作は、簡易版のCAlibVectorライブラリには一部だけしか含まれていません。編集操作は、ノードを起点に以下の操作がサポートされています。
  1. 長方形内のノードを選択状態にする。
  2. 選択状態のノードを削除する。
  3. 選択状態のノードを含むポリラインを削除する。
  4. 選択状態のノードを含むポリラインを円弧近似、スプライン近似する。

オリジナルのライブラリ(CALVectorクラスライブラリ)には、指定座標に近いノードの探索、ノードの移動、ノードの挿入、ポリラインや円等の描画、ポリラインのコピーなどの簡易CAD機能が含まれていますが、CALibVectorライブラリではサポートしていません。APIの簡略化のために省いているので、将来的に要望があればサポートする可能性はあります。


目次


近似パラメータ

近似パラメータを用いて、ベクタ変換の精度とノード(頂点)の数のバランスを調整することができます。

近似パラメータを小さくすると、ベクタ変換の精度が上がりますが、ノードの数が増えます。
近似パラメータを大きくすると、ベクタ変換の精度が下がりますが、ノードの数が減ります。
近似パラメータ
近似パラメータは、分母に輪郭上の3点が作る三角形の面積F、 分子に輪郭上の3点の始点と終点との距離Lとした場合の、 aΣF/L(aは定数)の値で、輪郭上をスキャンしていった時 の合計値が近似パラメータを越えた場合に、一つの線分ベクタを確定します。 面積には進行方向右側が左側かに応じた符号がついているため、上図中央 のように、小さなぎざぎざがあっても、全体がほぼ直線状になっていれば、 直線として近似されます。
2007年のバージョンアップにおける最適化変換は、「無数の頂点の組み合わせの中から、最適な頂点の組み合わせを選択する」という全く別のアルゴリズムを使っています。
目次


輪郭の抽出

近似パラメータと、後処理パラメータを引数として面図形の輪郭をポリラインに変換します。
後処理パラメータとして、
  1. 自動的に取り除くヒゲ(微小ベクタ)の長さの上限
  2. ヒゲ(微小ベクタ)を構成する線分の数の上限
  3. 別のポリラインに属する同じ座標の頂点を、複数の頂点に分けるか、一つの頂点として統合するかどうか
を指定します。
ヒゲ
多角形の輪郭抽出の再に、輪郭部分にヒゲが生じて閉曲線以外のベクタが生成されることがあります。そうした ヒゲを除いて、閉曲線として輪郭を抽出します。
(2007年のバージョンアップでサポート)thresholdを0より大きく0.8未満の値で指定すると「最適化輪郭抽出」を実行します。
最適化輪郭抽出では後処理パラメータは全て無視される。アルゴリズム上ヒゲが生じないので後処理は無くても問題ありません。

リファレンス

// ドキュメントの設定
// 入力
//   int            width;           画像の幅(単位ピクセル)
//   int            height;          画像の高さ(単位ピクセル)
//   int            scanlinesize;    画像のスキャンラインサイズ(単位バイト)
//   int            dpi;             画像の解像度(単位dpi)
//   unsigned char* pdata;           画像の先頭アドレスの取得
void                msetdocument(int width,int scanlinesize,int height,int dpi,unsigned char* pdata)
// 輪郭抽出トップレベル
// 簡易版では、3線分までの長さのひげを自動除去
// 簡易版では、自動的に以下の後処理を実行する
//  始終点が0.3mm以内の始終点は一致させる
// (2007年のバージョンアップでサポート)後処理における円弧近似の有無をarcflagでコントロールできるようになった。
// 注意:上記のパラメータをコントロールする場合は、mabstractcenterline/mabstractoutineを用いる // 入力 // double threshold; L2近似しきい値(マニュアル参照) // (0より大きく10.0より小さい値、推奨値0.8~2.0) // int postprocessflag; 1...追加後処理をする // 0...追加後処理はしない // int arcflag; 1...自動円弧近似する(半径1~1000mm) // 0...自動円弧近似しない // 戻り値 // 0....正常終了 // 負...エラー(errcode.h参照) // 追加後処理の内容 // 1...自動近接ノード除去(頂点間距離1mm,角度偏差15度) // 2...直線上の不要ポイント除去(角度偏差3度) // 3...自動コーナー鮮鋭化(コーナー下に画像有り、5頂点までを対象、長辺&短辺ともに2.0mm、対象角度45度まで) // 4...自動T字路十字路補正(頂点移動距離2.5ピクセルまで、直角からの偏差18度まで) // 5...自動円変換(閉曲線上の頂点が推定半径の0.85~1.15の間に100%並んでいるときに頂点の位置を推定半径上に移動する。 // ただし移動先の頂点の下から半径2.5ピクセル以内に画素があることが必要) // 注意:追加後処理のパラメータを操作する場合は、ここでは後処理なしにして、後処理用のAPIのパラメータを指定して呼び出せば良い int mabstractoutlinesimple(double threshold,int postprocessflag,int arcflag = 1); // 前処理パラメータを全て指定するAPI、 // 後処理は後処理用のAPIをコール int mabstractoutline(double threshold, // (0より大きく10.0より小さい値、推奨値0.8~2.0) int higelength, // 除去対象のヒゲの長さ(単位ピクセル、0の場合は除去しない) int higelinenum, // 開曲線で、線分が最大higelinenum個つながっている部分を除去対象とする // 輪郭抽出では、ほとんどが閉曲線となるが、1ピクセル幅の線がある場合にヒゲが発生する double integratedist); // ポリラインの始終点間の距離がintegratedist以下の場合は始終点を一致させる // 閉曲線で近似していくと、始点から周回して終点近くに頂点が発生することがあるため // 通常は、始終点間の距離は十分大きいため、一種の保険のようなものである。 // integratedistには3ピクセル程度の値を指定しておけばよい

サンプル

// 画像の幅(mwidth)、スキャンラインサイズ(mscanlinesize)、高さ(mheight)、解像度(mdpi)、先頭アドレス(mdata)を通知
// CALibVector::plib
#include "alibvector.h"
#include "errcode.h"
plib->msetdocument(mwidth,mscanlinesize,mheight,mdpi,mdata);
// デフォルト前処理、後処理なしで輪郭抽出
int i1 = plib->mabstractoutlinesimple(2.0,0);
if(i1 < 0) {
    // エラー;
}
...

目次


芯線の抽出

近似パラメータと、後処理パラメータを引数として線図形の芯線をポリラインに変換します。
後処理パラメータとして、
  1. 途切れたポリラインを自動的に接続する場合の端点間の最大距離
  2. 接続する途切れた辺同士の角度偏差
  3. 近接する交点を統合する場合の交点間の最大距離

を指定します。
(2007年のバージョンアップでサポート)thresholdを0より大きく0.8未満の値で指定すると「最適化芯線抽出」を実行します。thresholdが0.8の場合よりも、精度の高い変換をします。

リファレンス

// ドキュメントの設定輪郭の抽出参照
void                msetdocument(int width,int scanlinesize,int height,int dpi,unsigned char* pdata)
// 芯線抽出トップレベル
// 簡易版では、自動的に以下の前処理を実行する。
//  2ピクセル以下の長さのひげを自動除去
// 簡易版では、自動的に以下の後処理を実行する
//  1mm以内の端点(角度偏差90度まで)を自動接続
//  3mm以内の端点(角度偏差40度まで)を自動接続
//  近接交差点は統合しない
// 注意:上記のパラメータをコントロールする場合は、mabstractcenterline/mabstractoutineを用いる
// (2007年のバージョンアップでサポート)後処理におけるジョイントの有無をjointflagでコントロールできるようになった。
// 入力 // double threshold; L2近似しきい値(マニュアル参照) // (0より大きく10.0より小さい値、推奨値0.8~2.0) // int postprocessflag; 1...追加後処理をする // 0...追加後処理はしない // int jointflag; 1...自動ジョイント(一直線上の接近した端点を接続する) // 0...自動ジョイントしない // 戻り値 // 0....正常終了 // 負...エラー(errcode.h参照) // 追加後処理の内容 // 1...自動近接ノード除去(頂点間距離1mm,角度偏差15度) // 2...直線上の不要ポイント除去(角度偏差3度) // 3...自動コーナー鮮鋭化(コーナー下に画像有り、5頂点までを対象、長辺&短辺ともに2.0mm、対象角度45度まで) // 4...自動T字路十字路補正(頂点移動距離2.5ピクセルまで、直角からの偏差18度まで) // 5...アイソレート処理(+を↑→↓←の4つのラインではなく→↑の2つの交差するラインとする処理) // 注意:追加後処理のパラメータを操作する場合は、ここでは後処理なしにして、後処理用のAPIのパラメータを指定して呼び出せば良い int mabstractcenterlinesimple(double threshold,int postprocessflag,int jointflag = 1); // 前処理パラメータを全て指定するAPI、 // 後処理は後処理用のAPIをコール int mabstractcenterline(double threshold, // (0より大きく10.0より小さい値、推奨値0.8~2.0) int higelength, // 除去対象のヒゲの長さ(単位ピクセル、0の場合は除去しない) double autojointshort, // 角度偏差90度までの自動接続可能距離の最大値(単位mm、0.0の場合は接続しない) double autojointlong, // 角度偏差autojointangleまでの自動接続可能距離の最大値(単位mm、0.0の場合は接続しない) double autojointangle, // 自動接続可能な2辺の角度偏差(単位ラジアン) double integratedist); // 近接交差点の統合対象距離の最大値(単位mm)

サンプル

// 画像の幅(mwidth)、スキャンラインサイズ(mscanlinesize)、高さ(mheight)、解像度(mdpi)、先頭アドレス(mdata)を通知
// CALibVector::plib
#include "alibvector.h"
#include "errcode.h"
plib->msetdocument(mwidth,mscanlinesize,mheight,mdpi,mdata);
// デフォルト前処理、後処理なしで芯線抽出
int i1 = plib->mabstractcenterlinesimple(2.0,0);
if(i1 < 0) {
    // エラー;
}
...
目次


後処理-傾き補正

ラスタベクタ変換の結果に基づいて傾き補正します。
傾きに対する対処方法として、傾きだけ取得して表示・出力時のみ補正する、傾きを取得して元画像を逆方向に回転して再度ベクタ変換する、といったものが考えられます。
傾き補正のパラメータとして、
  1. 辺の最小長さ
  2. 最小長さより長い辺の最少数

を指定します。
最小長さよりも長い辺が最小数以上ある場合でなおかつ、それらの辺の角度の水平・垂直からの角度偏差の分散が小さい場合に、角度偏差を出力します。
回転したラスタをもとに再度ラスタベクタ変換する場合は、ラスタの回転で画質が若干低下する点に留意が必要です。
バイリニア法やバイキュービック法など画質の低下の少ないアルゴリズムを使うようにしましょう。

傾き補正
たとえば辺の最少数を4として、上図のようにほぼ水平垂直に近い辺が4本あって、全てほぼ同じ角度の水平・垂直からの傾きを持つ場合に、それらの平均を傾きとします。

リファレンス

// 傾き検出と補正
// 入力
//  double      angle1;         0°,90°,180°,270°に近い(±angle1ラジアン)辺を収集
//  double      angle2;         収集した辺の傾きの標準偏差(単位ラジアン)
//  double      threshold;      収集する辺の長さ(単位ピクセル)
//  int         leastnum;       収集する辺の数(leastnum以上収集できたら傾き計算)
// 出力
//  double&     angle;          傾き
// 戻り値
//  1....正常終了
//  0....条件に合わずに傾きを取得できなかった
int                 mhorizontalize(double angle1,double angle2,double threshold,int leastnum,double& angle);

サンプル

// 傾き補正
// 垂直・水平から±5度の範囲にある長さ12.7mm以上の辺の数が2以上で標準偏差が0.5度以下の場合に傾きを推定、取得
// PAIは円周率(3.14159265358979...)
// dpiは解像度(mm→ピクセル単位変換のため)
// CALibVector::plib
double angle;    // 取得する傾き
int i1 = plib->mhorizontalize(5 * PAI / 180,0.5 * PAI / 180,12.7 * dpi / 25.4,2,angle);
if(i1 == 1) {
    ;   // 画像の回転などの処理
}
目次


後処理-近接頂点の除去

全てのポリラインを対象に、近接する頂点を除去します。この操作では、パラメータとして、
  1. 頂点間の距離
  2. 頂点における辺のなす角度の上限

を指定します。 0度から上限角度までの間の近接頂点が除去対象となります。
近接頂点の除去
上図において、ベクタ12とベクタ23のなす角度が角度の上限以下で23間の距離が頂点間の 距離パラメータ以下であるため、頂点2が除去されます。

リファレンス

// 近接頂点除去(芯線輪郭共通)
// 入力
//  double    dnear;        近接ノードとみなす頂点間の最大距離(単位ピクセル)
//  double    radian;        □------□--□------□  1→2と2→3の最大角度偏差(鋭角部分は距離が近くても残すようにするため)
//                           1      2↓3      4
//                                     ↓
//                           □--------□--------□
void                mdeletenearpointall(double dnear,double radian);

サンプル

// 近接頂点の除去、1mm以下15度以下
// CALibVector::plib
plib->mdeletenearpointall(1 * dpi / 25.4,15 * PAI / 180);
目次


後処理-同一直線上の不要頂点の除去

全てのポリラインを対象に、同一直線上の不要な頂点を除去します。この操作では、パラメータとして
  1. 頂点における角度偏差

を指定します。
同一直線上の不要頂点の除去
上図において、ベクタ12とベクタ23のなす角度がパラメータで指定した角度偏差以下で あるため、頂点2が除去されます。

リファレンス

// 直線上の余分な点の除去(芯線輪郭共通)
// □------□------□
// 1      2      3
//         ↓
// □--------------□
// 入力
//    double    angle;       1→2、2→3のなす角度(単位ラジアン)
//    double    probelen;    2から1→3におろした垂線の足の座標値が、ラスタの前景色上にあるかどうかチェック
//                           垂線の足からprobelenピクセル以内にbit1が存在すればOK
void                mdeletewastepointall(double angle,double probelen);

サンプル

// 直線上の余分な点の除去、3度以下1.5ピクセル以内にbit1
// CALibVector::plib
plib->mdeletenearpointall(3 * PAI / 180,1.5);
目次


後処理-コーナー鮮鋭化

全てのポリラインを対象に、コーナーを鮮鋭化します。近似パラメータを精度重視とする場合に、 コーナー部分に複数のノードが生成される場合があります。 そうしたコーナーのノードを一つに統合する操作です。この操作では、パラメータとして、
  1. コーナー部分のノードの数
  2. コーナー部分のノード間距離の合計値の上限
  3. コーナー前後の直線部の辺の長さの下限
  4. コーナー前後の直線部のなす角度の下限
  5. コーナーのノードを一つに統合するときの画素チェックの有無

が指定できます。
別途、指定したノードを含むコーナーのみの鮮鋭化が可能です。
コーナー鮮鋭化
上図において、コーナー部分のノードの数は2,3,4の3つです。 ベクタ12とベクタ45のなす角度がコーナー前後の直線部のなす角度の下限パラメータ から180度の範囲内にあります。ベクタ12とベクタ45の長さがいずれもコーナー前後の直線部の辺の長さの下限以上で、ベクタ23とベクタ34の長さの和がコーナー部分の ノード間距離の合計値の上限パラメータ以下とします。そこでコーナーの2,3,4の3頂点 を除去して、ベクタ12とベクタ54の延長線上の交点に新しい頂点6を設けることがで きます。画素チェックが無い場合、頂点6の近辺に輪郭画像あるいは芯線画像が無くても可。
第1引数forceflagは0か1かの引数でしたが、2007年のバージョンアップにおいて第1引数に2と3を指定できるようになりました。 従来からある1では、新設するノードの下に画素が存在している必要ですが、2では芯線・輪郭画像において半径1の円で 画素チェックを行い、3では元画像で半径1の円で画素の存在チェックを行います。1→2→3の順に画素チェックの条件が緩んで コーナー鮮鋭化がされやすくなります。0では画素チェックはされません。

リファレンス

// コーナー鮮鋭化(cnodenumが4の場合)(芯線輪郭共通)
//                                      O(新設する頂点)
//        短辺                         / \
//        O---O                       /   \
//       /     \                     /     \
//      /       長辺                /       \
//     /         \                 /         \
// ---O           O---   ==>   ---O           O---
// 鋭角前後の辺の長さや角度の状況から判断して鋭角を整形する
// 入力
//    int           forceflag;      probelenを無視して、強制的にコーナー鮮鋭化する
//    int           cnodenum;       最大cnodenum個のノードを一つのノードに統合する
//    double        longpixel;      上図の長辺の長さがlongpixel(単位ピクセル)以上
//    double        shortpixel;     上図の短辺の長さがshortpixel(単位ピクセル)以下
//    double        angle;          2本の長辺のなす角度がangleラジアン以下
//    double        probelen;       新設する頂点の下に図形の画素があるかどうかチェックする範囲(単位ピクセル)
// 戻り値
//    0....正常終了
//    負...エラー(errcode.h参照)
// 全ポリラインについてコーナー鮮鋭化
int                 msharpencornerall(int forceflag,int cnodenum,double longpixel,double shortpixel,double angle,double probelen);

サンプル

// コーナー鮮鋭化、probelenは無視しない、長辺2mm、短辺2mm、角度45度までを鮮鋭化対象とする
// CALibVector::plib
plib->msharpencornerall(0,5,2 * dpi / 25.4,2 * dpi / 25.4,45 * PAI / 180,2);
目次


後処理-正円補正

全てのポリラインをスキャンして、円に近似可能なポリゴン(閉じたポリライン)を円近似します。
最大直径以下の閉曲線が、ほぼ円弧上に並んでいるときに、正円に整形します。この操作では、パラメータとして、
  1. 円変換最大直径
  2. 円とみなす判断基準として、半径の分散や円周上の画素チェックに関連するいくつかの数値

が指定できます

リファレンス

// 閉曲線に円を当てはめる(輪郭向け推奨。芯線にも適用可能)
// 入力
//    double    radius;        最大半径(単位ピクセル)
//    double    varrate;    円弧上のノード(頂点)が円の推定半径*(1.0±varrate)以内にあればOK
//    double    fitrate;    varrate以内にあるノードの数/円弧上のノードの数がfitrate以上ならOK
// 戻り値
//  0....正常終了
//  負...エラー
int                 mfitcircleall(double radius,double varrate,double fitrate);

サンプル

// 正円化、半径5mmまで、推定半径の85%~115%に全ての円弧上の頂点が分布している
// CALibVector::plib
plib->mfitcircleall(5 * dpi / 25.4,0.15,1.0);
目次


後処理-交差点補正

全てのポリラインをスキャンして、が十字路、T字路で交差する部分を一括して補正します。
十字路の場合は、90度から少しずれている場合、より90度に近い角度で交差するように補正します。

T字路の場合も、下図のように90度から少しずれている場合、より90度に近い角度で交差するように補正します。

この操作では、パラメータとして
  1. 交差点、および隣接する頂点の最大移動距離
  2. 補正対象とするラインの交差角度の90度からの最大のずれ

を指定します。
また、アイソレート処理によって、十字路で4本、T字路で3本に分かれたラインをいずれも2本のラインにまとめることができます。

リファレンス

// T字路、十字路補正(芯線向け推奨。輪郭にも適用可能だが意味なし)
// 十字路整形
//   │           │
//  \|/   →  ─┼─
//    │           │
//   │           │
//  ─┤/   →  ─┼─
//    │           │
// 入力
//    double        amaxmove;    // 隣接頂点の最大移動距離
//  double        anglemin;    // 最小交差点を中心とした直線部分の最小角度(PAI - anglemin~PAI + angleminまで)
// 戻り値
//  0....正常終了
//  負...エラー
int                 mcorrectCcross(double amaxmove,double anglemin);
// T字路整形
//  ̄\/ ̄     ─┬─
//    │     →   │
//    │           │
// 入力
//    double        amaxmove;    // 隣接頂点の最大移動距離
//  double        anglemin;    // 最小交差点を中心とした直線部分の最小角度(PAI - anglemin~PAI + angleminまで)
// 戻り値
//  0....正常終了
//  負...エラー
int                 mcorrectTcross(double amaxmove,double anglemin);
// アイソレート処理(芯線向け推奨。輪郭にも適用可能だが意味なし)
//   十字路で、+を↑→↓←の4つのラインではなく→↑の2つの交差するラインとする処理、
//     T字路で、Tを←↓→の3つのラインではなく、→↓の2つのT字交差するラインとする処理
//     接合するラインの角度偏差は30度までとする)
// 戻り値
//  0....正常終了
//  負...エラー
int                 misolatepolyline();

サンプル

// 交差点補正 0.15mmの移動、垂直・水平交差からの偏差は15度まで
// CALibVector::plib
plib->mcorrectTcross(0.15 * dpi / 25.4,15 * PAI / 180);
plib->misolatepolyline();
目次


後処理-スプライン近似

全てのポリラインを一括してスプライン近似します。
スプライン近似は、ポリラインの属性としてのスプライン補間点の配列を求める操作であるため、 元の線分近似や円弧近似の情報は失われません。この操作では、パラメータとして
  1. スプライン近似ステップ数

を指定します。
2つのノード間を、指定したステップ数でスプライン近似します。 近似は、3次Bスプライン近似で行うため、ポリラインの各頂点を通るスプライン曲線が取得できます。
屈曲点の近くでは、ステップ数の指定のいかんに関らず、スプラインのたるみを抑制するための補助点が設けられます。
ただし、たるみを完全に抑制できる保証はありません。もともと、鋭角をスプライン近似することには無理があるのでご注意ください。

元の頂点を通るスプライン曲線では、以下の図のように辺を大きく離れます。


   元のポリライン                          スプライン近似曲線

そこで、ALIBVECTORでは、頂点付近に補助点を追加して、元のポリラインと近接したスプライン曲線が生成されるようにしています。


スプライン近似の情報は、以下の2通りの方法で取得することができます。

もちろん、必要に応じて、元の頂点のままスプライン近似しても問題はありません。

リファレンス

// スプライン近似
// 変換後は、スプライン補間した頂点の座標を取得する専用のAPI(mgetsplinevertexofpolyline)で座標を取得する
// 入力
//    int                splinestep;   1辺をsplinestepとなるように補間する。
//                                     前後との接続が複雑な場合は、splinestepよりも補間点を増やすので注意
// 戻り値
//  0....正常終了
//  負...エラー
int                 mconvertspline(int splinestep);
// 線分変換
// 円弧近似、スプライン近似後に線分変換に戻す(頂点座標取得には影響しない。mgetconvertinfo(int offsetpolyline);の戻り値に影響する)
// 戻り値
//  0....正常終了
//  負...エラー
void                mconvertline();

サンプル

// スプライン近似、頂点間を10ステップで補間する
// CALibVector::plib
plib->mconvertspline(10);
目次


後処理-円弧近似

全てのポリラインを一括して円弧似します。
円弧近似は、2つのノード間を結ぶ辺の属性としての円の中心と半径を求める操作であるため、 元の線分近似やスプライン近似の情報は失われません。この操作では、パラメータとして
  1. 円弧近似最小半径
  2. 円弧近似最大半径

を指定します。最小半径よりも小さい円弧と、最大半径より大きい円弧は、円弧近似されません。

リファレンス

// 円弧近似
// ふくらみ情報つきの辺の始終点座標を取得するAPI(mgetsideofpolyline)で座標を取得する
// 入力
//    double            aminradius;        円弧近似する場合の最小半径(最小半径以下の円弧となるものは対象としない)(単位ピクセル)
//    double            amaxradius;        円弧近似する場合の最大半径(最大半径以上の円弧となるものは対象としない)(単位ピクセル)
//                                         最小半径以下となるのは鋭角に近い部分、最大半径以上となるのは直線に近い部分
//    int               checkflag;         円弧下に輪郭画素があるかどうかチェック
//    double            checkrange;        チェックの際に±checkrangeピクセルに輪郭画素があればOK
// 戻り値
//  0....正常終了
//  負...エラー
int                 mconvertarc(double aminradius,double amaxradius,int checkflag,double checkrange);
// 線分変換
// 円弧近似、スプライン近似後に線分変換に戻す(頂点座標取得には影響しない。mgetconvertinfo(int offsetpolyline);の戻り値に影響する)
// 戻り値
//  0....正常終了
//  負...エラー
void                mconvertline();

サンプル

// 円弧近似、半径1mm~1000mmまでの円弧に近似できる部分を円弧近似する。
// 円弧に近似したときに円弧の中点の下から半径2ピクセル以内にbit1があることを確認する
// CALibVector::plib
plib->mconvertarc(1.0 * dpi / 25.4,1000.0 * dpi / 25.4,1,2);
目次


頂点・辺アクセス

変換後のポリラインの頂点や辺の座標を取得して、表示/ファイル出力することができます(表示/出力はライブラリユーザー側の作業)。
基本的に、ポリライン総数を取得して、各ポリラインについて頂点のリストあるいは辺のリストを取得します。
各頂点間が円弧、線分で結ばれるかは辺の属性として取得できます。円弧近似した場合は、頂点のリストではなく辺のリストを取得する必要があります。
ポリラインをスプライン近似する場合は、頂点リストではなくポリライン補間点リストをポリラインごとに取得します。
ポリラインをスプライン近似した曲線を、逆に線分近似した頂点リストを取得することもできます。

  1. 表示
    多角形近似の場合は、各ノード(頂点)間を線分描画APIを使って描画します。
    円弧近似の場合は、始終点の座標と中心座標と半径情報が取得できるので円弧描画APIを使って描画します。
    スプライン近似の場合は、曲線を逆に線分で細分化した頂点リスト間を線分描画APIを使って描画します。
  2. dxf出力
    多角形近似の場合は、各ノード(頂点)間をLINEエンティティ/POLYLINEエンティティで出力します。
    円弧近似の場合は、始終点の座標と中心座標から、ふくらみ(BULGE)値を再計算して、POLYLINEエンティティで出力します。
    円弧近似の半径が極端に小さいときと極端に大きいときは、円弧ではなく直線となっているので、直線として出力します。
    スプライン近似の場合は、ポリライン補間点リストをSPLINEエンティティとして出力します。
    スプライン頂点リストをLINE/POLYLINEエンティティとして出力するという選択肢もあります。
    用途によっては、頂点をそのままSPLINEエンティティで出力しても構いません。

リファレンス

// 1.......ポリライン数を取得する
    // 戻り値
    //   ポリライン数
    int                 mgetpolylinenum();
// 2.......各ポリラインの頂点アクセス関数(頂点をアクセスする場合、円弧表現するための情報は得られない。線分の連続として取得する)
//     閉曲線の場合、始点座標=終点座標となる
// 2.1.....頂点数の取得
// 入力
//    int        offsetpolyline;  ポリラインオフセット(0~mgetpolylinenum() - 1)
//                                範囲外を指定すると例外発生
// 戻り値
// 指定ポリラインの頂点数(0の場合無効ポリライン)
// ex.閉曲線の場合、始点と終点は一致するので、たとえば正方形では5頂点となる
    int                 mgetvertexnumofpolyline(int offsetpolyline);
// 2.2.....頂点座標の取得
// 入力
//    int       offsetpolyline;  ポリラインオフセット(0~mgetpolylinenum() - 1)
//    int       offsetvertex;    頂点オフセット(0~mgetvertexnumofpolyline(offsetpolyline) - 1)
// 出力
//    int&      x;    頂点座標(単位ピクセル)
//    int&      y;  頂点座標(単位ピクセル)
//                    範囲外を指定すると例外発生
    void                mgetvertexofpolyline(int offsetpolyline,int offsetvertex,int& x,int& y);
// mm単位での取得(msetdocumentでのdpi情報を用いて変換)
// 出力
//    double&   x;  頂点座標(単位mm)
//    double&   y;  頂点座標(単位mm)
    void                mgetvertexofpolylinemm(int offsetpolyline,int offsetvertex,double& x,double& y);
// 2.3.....ポリラインの変換情報の取得(スプライン近似、円弧近似の有無、msetlineによってスプライン近似、円弧近似の取り消しが可能)
// 戻り値
//    0....線分変換
//    1....円弧近似
//    2....スプライン近似
//    3....円弧近似+スプライン近似(dxf出力はスプライン優先)
    int                    mgetconvertinfo(int offsetpolyline);
// 3.......各有効ポリラインの辺アクセス関数(辺情報に、円弧表現するための情報もついている)
// 3.1.....辺数の取得
// 入力
//    int        offsetpolyline;  ポリラインオフセット(0~mgetpolylinenum() - 1)
//                                範囲外を指定すると例外発生
// 戻り値
// 指定ポリラインの辺数(0の場合無効ポリライン)
    int                 mgetsidenumofpolyline(int offsetpolyline);
// 2.2.....辺の始終点座標の取得
// 入力
//    int        offsetpolyline;    ポリラインオフセット(0~mgetpolylinenum() - 1)
//    int        offsetside;        辺オフセット(0~mgetsidenumofpolyline(offsetpolyline) - 1)
//                    範囲外を指定すると例外発生
// 出力
//    int&       x1,y1,x2,y2;       始終点の座標(単位ピクセル)
//    double&    radius;            円弧近似したときの半径(単位ピクセル)
//    double&    cx,cy;             円弧近似したときの中心座標(単位ピクセル)
    void                mgetsideofpolyline(int offsetpolyline,int offsetside,int& x1,int& y1,int& x2,int& y2,double& radius,double& cx,double& cy);
// mm単位での取得(msetdocumentでのdpi情報を用いて変換)
// 出力
//    double&    x1,y1,x2,y2;       始終点の座標(単位mm)
//    double&    radius;            円弧近似したときの半径(単位mm)
//    double&    cx,cy;             円弧近似したときの中心座標(単位mm)
    void                mgetsideofpolylinemm(int offsetpolyline,int offsetside,double& x1,double& y1,double& x2,double& y2,double& radius,double& cx,double& cy);
// 3.......各ポリラインの3次スプライン頂点アクセス関数
// ポリラインをスプライン近似していないと頂点数としてマイナスが返る
//     閉曲線の場合、始点座標=終点座標となる
// 2.1.....頂点数の取得
// 入力
//    int        offsetpolyline;        ポリラインオフセット(0~mgetpolylinenum() - 1)
//                                範囲外を指定すると例外発生
// 戻り値
// 指定ポリラインのスプライン頂点数(0の場合は無効ポリライン(出力する必要が無いもの))
    int                 mgetsplinevertexnumofpolyline1(int offsetpolyline);
    int                 mgetsplinevertexnumofpolyline2(int offsetpolyline);
// 2.2.....補助点座標の取得
//     スプラインの場合、double値で返るので注意
// 入力
//    int        offsetpolyline;      ポリラインオフセット(0~mgetpolylinenum() - 1)
//    int        offsetvertex;        頂点オフセット(0~mgetvertexnumofpolyline(offsetpolyline) - 1)
//                    範囲外を指定すると例外発生
// 出力
//    double&    x;     補助点の座標(単位ピクセル)
//    double&    y;     補助点の座標(単位ピクセル)
    void                mgetsplinevertexofpolyline1(int offsetpolyline,int offsetvertex,double& x,double& y);
// mm単位での取得(msetdocumentでのdpi情報を用いて変換)
// 出力
//    double&    x;     補助点の座標(単位mm)
//    double&    y;     補助点の座標(単位mm)
    void                mgetsplinevertexofpolyline1mm(int offsetpolyline,int offsetvertex,double& x,double& y);
// 2.3.....スプライン近似曲線のポリライン化頂点座標の取得
//     スプラインの場合、double値で返るので注意
// 入力
//    int        offsetpolyline;      ポリラインオフセット(0~mgetpolylinenum() - 1)
//    int        offsetvertex;        頂点オフセット(0~mgetvertexnumofpolyline(offsetpolyline) - 1)
//                    範囲外を指定すると例外発生
// 出力
//    double&    x;     頂点の座標(単位ピクセル)
//    double&    y;     頂点の座標(単位ピクセル)
    void                mgetsplinevertexofpolyline2(int offsetpolyline,int offsetvertex,double& x,double& y);
// mm単位での取得(msetdocumentでのdpi情報を用いて変換)
// 出力
//    double&    x;     頂点の座標(単位mm)
//    double&    y;     頂点の座標(単位mm)
    void                mgetsplinevertexofpolyline2mm(int offsetpolyline,int offsetvertex,double& x,double& y);

サンプル

///////////////////
// ポリラインの描画
// CScancalcDocクラスにCALibVectorクラスを同じメソッド名、同じ引数でコールするメソッドをインプリメントしている
void CScancalcView::mDrawPolyline(CDC* pDC)
{
        CScancalcDoc* pDoc = GetDocument();
        if(pDoc->mgetimagenum() == 0) return;
        if(!pDoc->misinitrastervectorconversion()) return;
        int     polylinenum = pDoc->mgetpolylinenum();
        if(polylinenum == 0) return;
        
        CPen*   pen[12];
        pen[0] = new CPen(PS_SOLID,2,RGB(255,127,127));
        pen[1] = new CPen(PS_SOLID,2,RGB(127,255,127));
        pen[2] = new CPen(PS_SOLID,2,RGB(127,127,255));
        pen[3] = new CPen(PS_SOLID,2,RGB(255,255,127));
        pen[4] = new CPen(PS_SOLID,2,RGB(127,255,255));
        pen[5] = new CPen(PS_SOLID,2,RGB(255,127,255));
        pen[6] = new CPen(PS_SOLID,2,RGB(255,0,0));
        pen[7] = new CPen(PS_SOLID,2,RGB(0,255,0));
        pen[8] = new CPen(PS_SOLID,2,RGB(0,0,255));
        pen[9] = new CPen(PS_SOLID,2,RGB(255,255,0));
        pen[10] = new CPen(PS_SOLID,2,RGB(0,255,255));
        pen[11] = new CPen(PS_SOLID,2,RGB(255,0,255));

        CPen*   oldPen = pDC->SelectObject(pen[0]);
        for(int i = 0 ; i < polylinenum ; i++) {
                pDC->SelectObject(pen[i % 12]);
                if(pDoc->mgetvertexnumofpolyline(i) > 0) {
                        // スプライン優先
                        if(pDoc->mgetconvertinfo(i) & 2) {
                                mDrawSpline1(pDC,i);
                        }
                        else if(pDoc->mgetconvertinfo(i) & 1) {
                                mDrawFitcurve1(pDC,i);
                        }
                        else {
                                mDrawPolyline1(pDC,i);
                        }
                }
        }
        pDC->SelectObject(oldPen);
        for(i = 0 ; i < 12 ; i++) {
                delete pen[i];
        }
}
void CScancalcView::mDrawPolyline1(CDC* pDC,int offset)
{
        CScancalcDoc*   pDoc = GetDocument();

        int     sidenum = pDoc->mgetsidenumofpolyline(offset);
        CRect   crect,vrect;
        GetClientRect(&crect);
        vrect.left = mscrollposx;
        vrect.top = mscrollposy;
        vrect.right = (long)(vrect.left + crect.right / mag);
        vrect.bottom = (long)(vrect.top + crect.bottom / mag);
        for(int i = 0 ; i < sidenum ; i++) {
                int     x1,y1,x2,y2;
                double  cx,cy,radius;
                pDoc->mgetsideofpolyline(offset,i,x1,y1,x2,y2,radius,cx,cy);
                if(mcheckvisible(vrect,x1,y1,x2,y2)) {
                        if(i == 0) mDrawNode(pDC,x1,y1);
                        pDC->MoveTo((long)((x1 - mscrollposx) * mag),(long)((y1 - mscrollposy) * mag));
                        pDC->LineTo((long)((x2 - mscrollposx) * mag),(long)((y2 - mscrollposy) * mag));
                        mDrawNode(pDC,x2,y2);
                }
        }
}
void CScancalcView::mDrawSpline1(CDC* pDC,int offset)
{
        CScancalcDoc*   pDoc = GetDocument();

        int     vertexnum = pDoc->mgetsplinevertexnumofpolyline(offset);
        CRect   crect,vrect;
        GetClientRect(&crect);
        vrect.left = mscrollposx;
        vrect.top = mscrollposy;
        vrect.right = (long)(vrect.left + crect.right / mag);
        vrect.bottom = (long)(vrect.top + crect.bottom / mag);

        for(int i = 0 ; i < vertexnum - 1 ; i++) {
                double  x1,y1,x2,y2;
                pDoc->mgetsplinevertexofpolyline(offset,i,x1,y1);
                pDoc->mgetsplinevertexofpolyline(offset,i + 1,x2,y2);
                if(mcheckvisible(vrect,(int)x1,(int)y1,(int)x2,(int)y2)) {
                        pDC->MoveTo((long)((x1 - mscrollposx) * mag),(long)((y1 - mscrollposy) * mag));
                        pDC->LineTo((long)((x2 - mscrollposx) * mag),(long)((y2 - mscrollposy) * mag));
                }
        }
        vertexnum = pDoc->mgetsidenumofpolyline(offset);
        for(i = 0 ; i < vertexnum ; i++) {
                int             x1,y1;
                pDoc->mgetvertexofpolyline(offset,i,x1,y1);
                if(mcheckvisible(vrect,(int)(x1 - 3 / mag),(int)(y1 - 3 / mag),(int)(x1 + 3 / mag),(int)(y1 + 3 / mag))) {
                        mDrawNode(pDC,x1,y1);
                }
        }
}
void CScancalcView::mDrawFitcurve1(CDC* pDC,int offset)
{
        CScancalcDoc*   pDoc = GetDocument();

        int             sidenum = pDoc->mgetsidenumofpolyline(offset);
        CRect           crect,vrect;
        GetClientRect(&crect);
        vrect.left = mscrollposx;
        vrect.top = mscrollposy;
        vrect.right = (long)(vrect.left + crect.right / mag);
        vrect.bottom = (long)(vrect.top + crect.bottom / mag);
        for(int i = 0 ; i < sidenum ; i++) {
                int             x1,y1,x2,y2;
                double  cx,cy,radius;
                pDoc->mgetsideofpolyline(offset,i,x1,y1,x2,y2,radius,cx,cy);
                if(mcheckvisible(vrect,x1,y1,x2,y2)) {
                        if(i == 0) mDrawNode(pDC,x1,y1);
                        if(radius > 0.0) {
                                int             x3,y3,x4,y4;
                                x3 = (int)(((cx - radius) - mscrollposx) * mag);
                                y3 = (int)(((cy - radius) - mscrollposy) * mag);
                                x4 = (int)(((cx + radius) - mscrollposx) * mag);
                                y4 = (int)(((cy + radius) - mscrollposy) * mag);
                                // 四角形の幅と高さは2~32767の制約がある
                                int             width = x4 - x3;
                                int             height = y4 - y3;
                                if(width < 2 || 32767 < width || height < 2 || 32767 < height) {
                                        pDC->MoveTo((long)((x1 - mscrollposx) * mag),(long)((y1 - mscrollposy) * mag));
                                        pDC->LineTo((long)((x2 - mscrollposx) * mag),(long)((y2 - mscrollposy) * mag));
                                }
                                else {
                                        // CDC::Arcは反時計回り、楕円の中心は進行方向左側に無ければならない
                                        // (cx,cy)が(x1,y1)→(x2,y2)の右側にある場合は始終点を逆転
                                        if(pDoc->mccw(x1,y1,x2,y2,cx,cy,0.0) == 1) {
                                                int i1 = x1;x1 = x2;x2 = i1;
                                                i1 = y1;y1 = y2;y2 = i1;
                                        }
                                        pDC->Arc(x3,y3,x4,y4,
                                                (int)((x1 - mscrollposx) * mag),(int)((y1 - mscrollposy) * mag),
                                                (int)((x2 - mscrollposx) * mag),(int)((y2 - mscrollposy) * mag));
                                }
                        }
                        else {
                                pDC->MoveTo((long)((x1 - mscrollposx) * mag),(long)((y1 - mscrollposy) * mag));
                                pDC->LineTo((long)((x2 - mscrollposx) * mag),(long)((y2 - mscrollposy) * mag));
                        }
                        mDrawNode(pDC,x2,y2);
                }
        }
}
void CScancalcView::mDrawNode(CDC* pDC,int x1,int y1)
{
        CPen    pen1(PS_SOLID,3,RGB(255,127,127));
        CPen*   oldPen = pDC->SelectObject(&pen1);
// 矩形を描画
        x1 = (int)((x1 - mscrollposx) * mag);
        y1 = (int)((y1 - mscrollposy) * mag);
        pDC->Rectangle(x1 - 3,y1 - 3,x1 + 3,y1 + 3);
        pDC->SelectObject(oldPen);
}
// 表示する必要があるかどうか
// 入力
//      RECT    arect;                          ピクセル座標系での表示エリア
//      int     x1,int y1,int x2,int y2;        ピクセル座標系でのリンク
int CScancalcView::mcheckvisible(CRect arect,int x1,int y1,int x2,int y2)
{
        // リンクの外接正方形の座標を求める
        int             cx = (x1 + x2) / 2;
        int             cy = (y1 + y2) / 2;
        int             width = x2 - x1 + 1;
        int             height = y2 - y1 + 1;

        if(width < 0) width = -width;
        if(height < 0) height = -height;
        int             sx1,sy1,sx2,sy2;
        if(width > height) {
                sx1 = cx - width / 2;
                sx2 = cx + width / 2;
                sy1 = cy - width / 2;
                sy2 = cy + width / 2;
        }
        else {
                sx1 = cx - height / 2;
                sx2 = cx + height / 2;
                sy1 = cy - height / 2;
                sy2 = cy + height / 2;
        }
// 外接正方形の一部でも表示エリアに入るかどうかチェック
        if(sx2 < arect.left) return(0);
        if(arect.right < sx1) return(0);
        if(sy2 < arect.top) return(0);
        if(arect.bottom < sy1) return(0);
        return(1);
}
// ドキュメントクラスの親クラス
//- 返り値
//-  -1... 線分(x1,y1)-(x2,y2)の進行方向左側に点(x3,y3)がある
//-  1.. 線分(x1,y1)-(x2,y2)の進行方向右側に点(x3,y3)がある
//-       線分(x1,y1)-(x2,y2)の上に点(x3,y3)がある
//-       -1...線分(x3,y3)-(x1,y1)-(x2,y2)が同一直線上
//-       0....線分(x1,y1)-(x3,y3)-(x2,y2)が同一直線上
//-       1....線分(x1,y1)-(x2,y2)-(x3,y3)が同一直線上
int CALDataVector::mccw(double x1,double y1,double x2,double y2,double x3,double y3,double zero)
{
        double          dx12 = x2 - x1;
        double          dy12 = y2 - y1;
        double          dx13 = x3 - x1;
        double          dy13 = y3 - y1;

        double          f = dx12 * dy13 - dy12 * dx13;
        if(f > zero) return 1;
        else if(f < -zero) return -1;
        else {
                if(dx12 * dx13 < 0.0) return -1;
                if(dy12 * dy13 < 0.0) return -1;
                if(dx12 * dx12 + dy12 * dy12 < dx13 * dx13 + dy13 * dy13) return 1;
                return 0;
        }
}
目次


dxfファイル保存

変換結果をdxfファイルとして保存します。保存オプションとして、
  1. 簡易ヘッダつきのdxf形式で保存するか、R12形式のヘッダつきで保存するか
  2. POLYLINEエンティティとして出力するか、LINE/ARCエンティティとして出力するか

が指定できます。SPLINEエンティティは正式サポートしていません。

リファレンス

// dxfファイル保存
// 入力
//  char*       filename;           dxfファイル名(フルパス)
//  int         width;              画像の幅(単位ピクセル)
//  int         height;             画像の高さ(単位ピクセル)
//  int         dpi;                画像の解像度(dxfではピクセル→mm変換して保存するため)
//  int         r12flag;            0...簡易ヘッダ形式でdxfファイル保存する
//                                  1...R12形式ヘッダをつけたdxfファイル保存をする
//  int         linearcflag;        0...ポリラインをPOLYLINEエンティティとして保存する
//                                  1...ポリラインをLINE/ARCエンティティとして保存する
// 戻り値
//  0....正常終了
//  負...エラー
int                 msavedxf(char* filename,int width,int height,int dpi,int r12flag = 0,int linearcflag = 0);

サンプル

// dxfファイル保存
// 2440×1820ピクセルの400dpi画像をラスタベクタ変換した結果を保存する
// CALibVector::plib
int i1 = plib->msavefxf("c:\\data\\sample.dxf",2440,1820,400);
目次


芯線の抽出(拡張版)

mabstractcenterlineの近似パラメータを拡張したものです。
元からある後処理パラメータとして、
  1. 途切れたポリラインを自動的に接続する場合の端点間の最大距離
  2. 接続する途切れた辺同士の角度偏差
  3. 近接する交点を統合する場合の交点間の最大距離

追加の後処理パラメータとして
  1. 隣接する2点を(ポリ)ラインとするかどうかのフラグ
  2. 2ピクセル以内のノードを無条件で接続するかどうかのフラグ
  3. 削除するショートベクタの最大長

が指定できます。

リファレンス

    int                 mabstractcenterlineEX(double threshold,
        int     flag,              // 0x00000000...特に何もしない
                                   // 0x00000020...超至近点の統合を行う(デフォルトはONで統合を行う)
                                   // 0x00000040...2点ショートベクタの生成(デフォルトはOFFでショートベクタの生成は行わない)
        int     higelength,        // 除去対象のヒゲの長さ(単位ピクセル、0の場合は除去しない)
        double  shortvectormax,    // 除去対象のショートベクタの最大長
        double  autojointshort,    // 角度偏差90度までの自動接続可能距離の最大値(単位ピクセル、0.0の場合は接続しない)
        double  autojointlong,     // 角度偏差autojointangleまでの自動接続可能距離の最大値(単位ピクセル、0.0の場合は接続しない)
        double  autojointangle,    // 自動接続可能な2辺の角度偏差(単位ラジアン)
        double  integratedist);    // 近接交差点の統合対象距離の最大値(単位ピクセル)

サンプル

// 画像の幅(mwidth)、スキャンラインサイズ(mscanlinesize)、高さ(mheight)、解像度(mdpi)、先頭アドレス(mdata)を通知
// CALibVector::plib
#include "alibvector.h"
#include "errcode.h"
plib->msetdocument(mwidth,mscanlinesize,mheight,mdpi,mdata);
int i1 = plib->mabstractcenterlineEX(mapploxthreshold,0x00000040,       // 2点ショートベクタも生成する
                                                                           // 2ピクセル以内のノードの接続をしない
                             2,                                            // 長さ2ピクセルまでのヒゲを除去
                             0,                                            // ショートベクタの削除をしない
                             (0.25 * mdpi) / 25.4,                         // 間隔0.25mmまでの破線をつなげる(角度は90度まで、直角に曲がっていても接続される)、ピクセル変換している
                             (1.25 * mdpi) / 25.4,                         // 間隔1.25mmまでの破線をつなげる(角度は40度まで、水平に近いものが接続される)、ピクセル変換している
                             40.0 * PAI / 180.0,                           // 上記の角度をラジアンで指定する
                             (0.5 * mdpi) / 25.4);                         // 0.5mm以内の交点2つを統合する
if(i1 < 0) {
    // エラー;
}
...
詳しい説明


上記の引数で破線をつなげた場合以下のようになる


目次

1.25を0.75にすると以下のようになる。破線の間隔が1mm程度あるためこのようになる。

2点ショートベクタを生成すると以下のように極端に短いラインが生成される。

2点ショートベクタを生成しない0x00000040→0x00000000場合、以下のように極端に短いラインは生成されない。

2ピクセルより長いショートベクタもshortvectormax引数で削除することができる。

第4引数を0→(2.00 * mdpi) / 25.4と変えると、2mm以下のショートベクタが消え以下のようになる

ジョイント以外に、2ピクセル以内にある2つのノードを無条件で統合するためのフラグもある。上記のサンプルではフラグがオフとなっているので、以下のようになる。

フラグ0x00000040を0x00000060とすると以下のように変わる。



新機能2007年

従来比5倍以上の高速化(Pentium-M 1.5GHz A0超で2分30秒→27秒)と、不要頂点の大幅減少、座標精度の向上という3つの性能面の改良に加えて、孤立点変換・破線認識機能を新たに追加した。
高速化、不要頂点の減少、座標精度の向上に関連する性能面の改良は、mabstractcenterlinesimple/mabsrtaceoutlinesimpeを使っている場合、従来と全く同じ変換APIで反映される。つまり、ライブラリを差し替えるだけである。
mabstractcenterlinesimple/mabsrtaceoutlinesimpeを使っている場合は、高速化と座標精度向上は、従来と同じAPIで反映されるが、T字路、十字路補正API直線上の不要頂点の除去APIについては、別途後処理APIを呼び出す必要がある。また、近接平行線補正APIについては、別途前処理として呼び出す必要がある。
フラグによって前処理と後処理を指定するmabstracecenterlineEXでは、該当するフラグを変更しないと、高速化以外は従来の変換と同じ性能となる。座標精度向上なども、フラグでしていすることで有効となる。
最初の項目で、フラグの変更点を解説する。
つぎに性能向上に関連するAPIについて解説し、最後に破線認識機能について解説する。
目次


変換フラグの拡張

mabstracecenterlineEXのフラグは以下のような意味を持つ
int         flag,           // 0x0000031f...左記7bitはalibvector.dllでは未公開
                            // 0x00000020...超至近点の統合(前バージョン)
                            // 0x00000040...ショートベクタの生成(前バージョン)
                            // 以下は、2007年のバージョンアップで利用するフラグ
                            // 0x00000080...孤立点ベクタ化
                            // 0x00000400...端点延長処理
                            // 0x00000800...1ピクセル対角線
                            // 0x00010000...※ 直線上の不要頂点の除去
                            // 0x00020000...※ 鋭角ヒゲの除去
                            // 0x00040000...※ 改良版T字路十字路補正
                            // 0x00080000...※ 座標補正処理
                            // 0x01000000...acute angle emphasis
                            // 0x02000000...acute angle emphasisのスムージングつき
                            // 0x10000000...※ 近接平行線補正
  1. 孤立点変換フラグ
    0x00000080...孤立点ベクタ化
    孤立点をベクタとして取得します。孤立点は始終点が同じ座標の1辺として、他の辺と同様にアクセスすることができます。
  2. 座標補正処理フラグ
    0x00080000...座標補正処理
    座標補正処理を行います。後処理APIをmtunevertex(0,0x0000000f,1,1)として呼び出します。
  3. T字路、十字路補正フラグ
    0x00040000...改良版T字路十字路補正
    T字路、十字路補正を行います。後処理APIをmtunecrossrepeat(3,(1.0 * mdpi) / 25.4,(2.0 * mdpi) / 25.4)として呼び出します。
  4. 直線上の不要頂点の除去フラグ
    0x00010000...直線上の不要頂点の除去
    直線上の不要頂点を除去します。後処理APIをmwastepointrepeat(mwastepointangle * PAI / 180.0,1.0)と、mwastepointsimrepeat(1.5,0.75)として呼び出します。
  5. 鋭角ヒゲの除去フラグ
    0x00020000...鋭角ヒゲの除去
      鋭角ヒゲを除去します。

  6. 近接平行線補正処理フラグ
    0x10000000...近接平行線補正
    前処理用APIをmparallelfilter()として呼び出します。
  7. 端点延長処理フラグ
    0x00000400...端点延長処理
    端点延長処理をします。ただし、端点延長しないほうが元の作図の意図に忠実な場合もあるので、フラグを軽率に立てるのは考え物である。

目次

前処理・後処理API

  1. T字路、十字路補正
    下記の仕様でT字路、十字路補正を行います。「3」はT字路、「4」は十字路、「2」は中継点を示しています。
    各ケースは下図の様になっています。T字路同士には対応していますが、T字路と十字路、十字路同士には対応していません(要望があれば対応可能)。

    // T字路十字路処理改良版
    // int          flag22;             デフォルトで3-2ケース/4-2ケース対応
    //                                  bit0...3-2-2/4-2-2ケース対応
    //                                  bit1...3-2ケース対応の拡張
    //                                  bit2...3-2-2ケース対応の拡張
    //                                  bit3...3-3ケース対応
    //                                  2は、線分の中継点・--中継点--・
    //                                  3は、T字路
    //                                  4は、十字路
    // double       tunecrossmax1;	    3-2/3-3/4-2ケース対応のノード間最大距離(単位ピクセル)
    // double       tunecrossmax2;	    3-2-2/4-2-2ケース対応のノード間最大距離(単位ピクセル)
    // 戻り値
    //  0以上       統合したノード数
    //  負          エラー
    int             mtunecrossrepeat(int flag22,double tunecrossmax1,double tunecrossmax2);
  2. 直線上の不要頂点の除去API
    下記の仕様で直線上の不要頂点の除去を行います。
    mdeletepointrepeatでは、従来のAPIであるmdeletewastepointを削除するノードがなくなるまで繰り返し適用します。
    mdeletewastepointsimrepeatでは、ノード「2」を「1」と「3」の中点に移動できるかチェックして、移動できる場合に点を削除します。
    ノード「2」と中点との距離がamaxmode以下で、中点の下に芯線あるいは輪郭線の画素がある場合に「移動できる」と判定します。
    移動距離は、1.5ピクセルくらいが限度で0.75ピクセル程度を推奨します。
    amindensは、大きいほど移動が発生しにくくなります。0.75くらいが上限で、通常は0.25くらいを推奨します。
    // 直線上の不要頂点の除去
    // □------□------□
    // 1      2      3
    //         ↓
    // □--------------□
    //  double      angle;              1→2、2→3のなす角度(単位ラジアン)
    //  double      probelen;           2から1→3におろした垂線の足の座標値が、ラスタの前景色上にあるかどうかチェック
    //                                  垂線の足からprobelenピクセル以内にbit1が存在すればOK
    // 戻り値
    //  0以上       削除したノード数
    //  負          エラー
    int 				mdeletewastepointrepeat(double angle,double probelen);
    // 最大ポイント移動距離で画素密度がamindens以上の場合に除去
    //  double      amaxmode;           2の最大移動距離(単位ピクセル)
    //  double      amindens;           2の移動先での輝度値(0.0~1.0)
    // 戻り値
    //  0以上       削除したノード数
    //  負          エラー
    int 				mdeletewastepointsimrepeat(double amaxmove,double amindens);
  3. 近接平行線補正API
    近接平行線補正は、変換フラグの拡張のフラグを指定することでもできますが、後処理APIで明示的に 補正することもできます。この場合、msetdocumentで指定した元画像を直接変換して平行線整形を行います。平行線整形した画像を ユーザーに表示する場合に用いると良いでしょう。

    // 近接平行線整形フィルタ
    // 戻り値
    //  0           正常終了
    //  負          エラー
    int					mparallelfilter();
    
  4. コーナー鮮鋭化フラグの拡張
    コーナー先鋭化の第1引数forceflagは0か1かの引数でしたが、第1引数に2と3を指定できるようになりました。 1→2→3の順に画素チェックの条件が緩んでコーナー鮮鋭化がされやすくなります。0と1は従来と同じ動作をします。 2では芯線・輪郭画像において半径1の円で画素チェックを行い、3では元画像で半径1の円で画素の存在チェックを行います。
目次


最適化変換API

従来mabstractcenterlineEX/mabstractoutlineEXの精度パラメータthresholdは、最高精度(最も小さい値)で0.8であったが、0より大きく0.8より小さい値を指定することもできるようになった。
その場合、従来とは全く異なるアルゴリズムによりラスタベクタ変換を行う。アルゴリズム適用の結果、近似線分上の全ての点が芯線あるいは輪郭線から1画素以内の距離にあるように頂点が生成される。
ただし、後処理の内容によっては、1画素以上外れることもあるので注意が必要である。
0~0.8(0と0.8は含まない)の間の値では処理内容は変わらない。
"0"をthresholdに指定した場合は、エラーが返るようになった。"0"は将来的に利用できるように予約されている。
目次


破線認識API

連続して線状に並んだ"-"形状、"──"形状、"・"形状、"└ ┌ ┐ ┘"形状の"破線素"が一定個数以上ある場合に、 それらを破線属性のついたひとつの破線ポリラインにまとめる処理。"・"形状の破線素が入る場合は、 変換フラグの拡張において、孤立点変換フラグを立てておく必要がある。
// 破線認識
//  int         aminnum;            aminnum個以上破線素がある
//  double      amaxlen;            破線素の最大長
//  double      amaxgap;            破線素間隔の最大値
//  double      amaxangle;          破線素、gapの最大偏角
// 戻り値
//  0以上       生成した破線数
//  負          エラー
int                 mconvertdotline(int aminnum,double amaxlen,double amaxgap,double amaxangle);
破線の個々の線素にアクセスするには、mgetsideofpolylineと同じようなAPIである、mgetsideofdotlineでアクセスする。
注意:破線では、通常の辺と異なり円弧近似やスプライン近似はできない。

破線アクセスAPI

ポリラインが破線かどうかを判定するには、mgetconvertinfo(int offsetpolyline)の戻り値が拡張されているのでそれを用いる。具体的には戻り値が4の場合が破線である。
破線ポリラインでは、破線素(図形のある部分)、破線素の空隙(図形の無い部分)も同じように辺として返される。
破線素か空隙かはmgetsideofdotline/mgetsideofdotlinemmの戻り値で判定することができる。
個々の破線素の頂点数は1~4の範囲である。破線素の頂点数が1は、破線素が点であることを示している。ほとんどの破線素は2頂点で、屈曲した破線素や他の線分と交差している破線素には3~4頂点のものがある。
// 辺の始終点座標の取得
// 入力
//    int        offsetpolyline;    ポリラインオフセット(0~mgetpolylinenum() - 1)
//    int        offsetside;        辺オフセット(0~mgetsidenumofpolyline(offsetpolyline) - 1)
//                    範囲外を指定すると例外発生
// 出力
//    int&       x1,y1,x2,y2;       始終点の座標(単位ピクセル)
// 戻り値
//  1....破線の線素
//  0....破線の線素の空隙
    int                 mgetsideofdotline(int offsetpolyline,int offsetside,int& x1,int& y1,int& x2,int& y2);
// mm単位での取得(msetdocumentでのdpi情報を用いて変換)
// 出力
//    double&    x1,y1,x2,y2;       始終点の座標(単位mm)
// 戻り値
//  1....破線の線素
//  0....破線の線素の空隙
    int                 mgetsideofdotlinemm(int offsetpolyline,int offsetside,double& x1,double& y1,double& x2,double& y2);
目次


簡易編集API

ユーザーからの要望に基づいてCALVectorクラスライブラリにある簡易CAD機能の一部をCALibVectorライブラリでもサポートした。
サポートした機能は頂点(ノード)の選択と削除、選択したノードを含むポリラインの削除と円弧近似、スプライン近似である。
頂点挿入や描画等の機能はサポートしていないが、要望次第では将来的にはサポートする可能性もある。
malibselectnodeによって、長方形内の頂点を選択することができ、選択状態はmalibisselectnodeによって調べることができる。
選択状態のクリアは、malibclearselectnodeによって行う。
選択状態のノードに対して削除を実行することができる。
選択状態のノードを含むポリラインに対して削除、円弧近似、スプライン近似、直線近似を実行することができる。

// ノード(頂点)選択クリア
// 全てのノードの選択状態をクリアする
void				malibclearselectnode();
// ノード(頂点)選択
// 長方形(left,top)-(right,bottom)内部のノード(頂点)を選択状態にする
// 戻り値
//  選択したノード(頂点)数
int					malibselectnode(int left,int top,int right,int bottom);
// ノード選択状態の参照
// 入力
//    int       offsetpolyline;     ポリラインオフセット(0~mgetpolylinenum() - 1)
//    int       offsetvertex;       頂点オフセット(0~mgetvertexnumofpolyline(offsetpolyline) - 1)
// 1....そのノードは選択状態にある
// 0....そのノードは選択状態にない
int					malibisselectnode(int offsetpolyline,int offsetvertex);
// 選択ノードの数を返す
int					mgetselectednodenum();
// ノードの数を返す
int					mgetnodenum();
// 選択ノードを削除する
// 戻り値...削除したノードの数
int					mdeleteselectednode();
// 選択ノードを含むポリラインを削除する
// 選択ノードを削除する
// 戻り値...削除したポリラインの数
int					mdeleteselectedpolyline();
// 全ポリラインを削除する
// 戻り値...削除したポリラインの数
int					mdeleteallpolyline();
// 円弧近似
// ふくらみ情報つきの辺の始終点座標を取得するAPI(mgetsideofpolyline)で座標を取得する
// 入力
//  int             offsetpolyline;     ポリラインオフセット(0~mgetpolylinenum() - 1)
//  double          aminradius;         円弧近似する場合の最小半径(最小半径以下の円弧となるものは対象としない)(単位ピクセル)
//  double          amaxradius;         円弧近似する場合の最大半径(最大半径以上の円弧となるものは対象としない)(単位ピクセル)
//                                      最小半径以下となるのは鋭角に近い部分、最大半径以上となるのは直線に近い部分
//  int             checkflag;          円弧下に輪郭画素があるかどうかチェック
//  double          checkrange;         チェックの際に±checkrangeピクセルに輪郭画素があればOK
// 戻り値
//  0....正常終了
//  負...エラー
int                 mconvertarc(int offsetpolyline,double aminradius,double amaxradius,int checkflag,double checkrange);
// スプライン近似
// 変換後は、スプライン補間した頂点の座標を取得する専用のAPI(mgetsplinevertexofpolyline)で座標を取得する
// 入力
//  int             offsetpolyline;     ポリラインオフセット(0~mgetpolylinenum() - 1)
//  int             splinestep;         1辺をsplinestepとなるように補間する。
//                                      前後との接続が複雑な場合は、splinestepよりも補間点を増やすので注意
// 戻り値
//  0....正常終了
//  負...エラー
int                 mconvertspline(int offsetpolyline,int splinestep);
// 線分近似
// 円弧近似、スプライン近似後に線分近似に戻す(頂点座標取得には影響しない。辺属性とmsavedxfに影響する)
// 入力
//  int             offsetpolyline;     ポリラインオフセット(0~mgetpolylinenum() - 1)
// 戻り値
//  0....正常終了
//  負...エラー
void                mconvertline(int offsetpolyline);
目次

2008年追加予定

  1. 文字図形、線図形、面図形分離機能(時期:自動トレースオプション前)
    ラスタ編集ライブラリと同じ、文字図形、線図形、面図形の分離機能を追加する。
  2. 一部図形変換機能(自動トレースオプション後)
    指定長方形にフックされる(枠+内部)図形か指定長方形の内部にある図形のみを変換対象とする機能を追加する。
  3. アンドゥ・リドゥサポート
    現在のライブラリの状態をバッファに取得するAPIと、バッファの状態をライブラリに反映させるAPIを新設して、 アプリケーションのアンドゥ、リドゥのサポートをする。バッファ内容は、アドレス情報などが含まれないリロ ケータブル形式になっているため、、ファイルを使ったアンドゥ・リドゥや固有形式でのファイル保存に利用し ても問題はない。

リファレンス1(予定仕様:文字図形、線図形、面図形分離機能)
図面を、線図形、面図形、文字列図形に分離して線図形は芯線ベクタ変換、面図形は輪郭ベクタ変換する。
最初に文字列図形を、amincharnum/amaxcharsizeパラメータを使って分離する。amincharnumが10000以上の場合は 文字列図形の分離は行わない。破線がある場合、破線と文字列は誤認されやすいので文字列図形の分離は避ける。
次に線図形と面図形を、最大線幅linewidthmaxパラメータを用いて分離する。
線図形は、threshold以下の引数をそのまま使ってmabstractcenterlineEXと同じ処理で変換する。
面図形は、moptimizeoutlineで変換する。moptimizeoutlineの引数は1ピクセル孤立点(8連結)/孤立穴(4連結)除去が onの場合は2でoffの場合は1とする。

// 面図形、線図形、文字列図形自動認識ベクタ変換
int CALibVector::mabstractbothline(
	double  linewidthmax,       // 最大線幅linewidthmaxを越える図形は面図形と判定
	int     amincharnum,        // 文字列内の最少プリミティブ数(10000以上の場合は文字列分離しない)
	double  amaxcharsize,       // 最大文字サイズ
	double  threshold,          // 近似パラメータ(0より大きく10.0より小さい値、推奨値0.8~2.0)
	int		flag,				// 0x00000001...至近点のジョイント;
								// 0x00000002...近点のジョイント
								// 0x00000004...交差点のジョイント
								// 0x00000008...ヒゲ除去
								// 0x00000010...近接交差点の統合
								// 0x00000020...超至近点の統合
								// 0x00000040...ショートベクタの生成
								// 0x00000080...孤立点ベクタ化
								// 0x00000100...TandT交差の補正
								// 0x00000200...ストレートジョイント
								// 0x00000400...端点延長処理
								// 0x00000800...1ピクセル対角線
								// 0x00010000...※ 直線上の不要頂点の除去(弱)
								// 0x00020000...※ 鋭角ヒゲの除去
								// 0x00040000...※ 改良版T字路十字路補正
								// 0x01000000...acute angle emphasis
								// 0x02000000...acute angle emphasisのスムージングつき
								// 0x10000000...※ 近接平行線補正
								// 0x20000000...※ 1ピクセル孤立点(8連結)/孤立穴(4連結)除去
    int     higelength,        // 除去対象のヒゲの長さ(単位ピクセル、0の場合は除去しない)
    double  shortvectormax,    // 除去対象のショートベクタの最大長
    double  autojointshort,    // 角度偏差90度までの自動接続可能距離の最大値(単位ピクセル、0.0の場合は接続しない)
    double  autojointlong,     // 角度偏差autojointangleまでの自動接続可能距離の最大値(単位ピクセル、0.0の場合は接続しない)
    double  autojointangle,    // 自動接続可能な2辺の角度偏差(単位ラジアン)
    double  integratedist);    // 近接交差点の統合対象距離の最大値(単位ピクセル)

リファレンス2(予定仕様:一部図形変換機能)
面図形、線図形、文字列図形自動認識ベクタ変換を、一部の図形に対して適用する。
図形の選択は、長方形フックと長方形インナーの2通りが提供される。長方形フックでは、長方形内部+長方形枠にかかる 図形を変換対象とする。長方形インナーでは、長方形内部の図形を変換対象として、長方形枠にかかる図形は変換対象から 除外される。

// 長方形内部+長方形枠にかかるオブジェクトを輪郭・芯線自動認識変換
// 入力
//  double          linewidthmax;       最大線幅linewidthmaxを越える図形は面図形と判定
//  int             x1,y1,x2,y2;        長方形の対角線座標
//  double          threshold;...       mabstractbothline参照
// 戻り値
//  0.....正常終了
//  負....エラー
int                 mabstractbothlinerecthook(
	double linewidthmax,       // 最大線幅
	int    x1,
	int    y1,
	int    x2,
	int    y2,                 // 長方形の対角線座標
	double threshold,int flag,int higelength,double shortvectormax,
    double autojointshort,double autojointlong,double autojointangle,double integratedist);
// 長方形に完全に含まれるオブジェクトを輪郭・芯線自動認識変換
int                 mabstractbothlinerectinner(
	double linewidthmax,       // 最大線幅
	int    x1,
	int    y1,
	int    x2,
	int    y2,                 // 長方形の対角線座標
	double threshold,int flag,int higelength,double shortvectormax,
    double autojointshort,double autojointlong,double autojointangle,double integratedist);

リファレンス3(確定仕様:アンドゥ・リドゥサポート)

// ライブラリの現在の状態を取得するバッファサイズを得る
// 戻り値
//  バッファサイズ(アプリケーション側で確保する)
size_t              mgetsavebuffersize();
// ライブラリの現在の状態を取得する
// 利用目的1;undo/redo機能を実現する
//         2;独自形式のファイルで現在の作業状態をファイル保存/読込する
// 取得前にmgetsavebuffersize()で取得したバッファサイズ分の領域を確保する
// 入力
//  char*&          ps1;                状態を取得するバッファの先頭アドレス(アプリケーション側で確保)
void                msavebuffer(char*& ps1);
// ライブラリの現在の状態をバッファで指定する
// 入力
//  size_t          len;                バッファサイズ
//  char*&          ps1;                状態バッファの先頭アドレス
// 戻り値
//  負              エラー
//  0               正常終了
int                 mloadbuffer(size_t& len,char*& ps1);
目次


自動トレースオプション

トレースオプションは、ユーザーが指定した2点の座標に沿って、端点と交差点、交差点と交差点を自動的に結びつ けたポリライン(線分が結合したもの)を生成する機能です。トレースの動作をコントロールするパラメータは、輪郭 ベクタ変換、芯線ベクタ変換と、ほぼ同じものを使います。トレースAPIでは入力パラメータとして、始点と終点の 2点の座標を与えます。下図左において
  

上図右のように始点を(X0,Y0)、終点を(X1,Y1)として自動トレースAPIを呼び出すと

下図左のように自動トレースしたポリラインが返されます。次は、(x1,y1)を始点(X0,Y0)としてトレースする方向に向けて終点を指定します。
  
自動トレースしたポリラインの頂点数は上図のように2つとは限りません。
  
上図のように、3つ以上の頂点を持つポリラインが返ることもあります。
目次


自動トレースAPI

自動トレースAPIでの変換パラメータを、毎回APIを呼ぶたびに与えるのは面倒なので、自動トレースAPIでは、あらかじめ変換パラメータを与えておきます。
自動トレースAPI本体は、始点と終点の2点の座標を入力として、ポリラインの頂点数と座標を出力とする仕様となっています。
戻り値によって、自動トレースが交差点で終わっているか、端点で終わっているかが分かるので、交差点で終わっている場合は、 前回の出力ポリラインの最後の点を始点として、終点をユーザーのマウス操作などから取得すれば、トレースを継続していくことが できます。
出力バッファpx,pyは、ライブラリ内のバッファなので、APIコール後はアプリケーション側でpx,pyをバックアップしてください。

// 自動トレースAPI
// 入力
//  double          x1;                 開始点x(ユーザー指定)
//  double          y1;                 開始点y
//  double          x2;                 終了点x(ユーザー指定)
//  double          y2;                 終了点y
// 出力
//  int&            vertexnum;          頂点数
//  double*         px;                 頂点座標配列x
//  double*         py;                 頂点座標配列y
// 戻り値
//  0....成功、終了点は端点、次の自動トレースは別の始点を指定する
//  1....成功、終了点は交差点、次の自動トレースは(px[vertexnum-1]、py[vertexnum-1]を始点として指定する
//  負...エラー
int                 mautotrace(double x1,double y1,double x2,double y2,int& vertexnum,double* px,double* py);
目次


自動トレースのパラメータ設定

自動トレースのパラメータ設定は、以下の2つのAPIに分かれています。
  1. 自動トレースパラメータの設定1
      芯線ベクタ変換と共通
  2. 自動トレースパラメータの設定2
      自動トレース固有
自動トレースパラメータの設定1
自動トレースでは、一部芯線ベクタ変換と共通のパラメータを使っています。
後処理パラメータは、芯線ベクタ変換と同じ後処理をするかどうかを指定するパラメータです。 詳しくは変換フラグの拡張をご覧ください。有効なパラメータは4つだけです。
近似パラメータは、この節で解説しているように、線画像が多少蛇行していても 直線として判定する程度をコントロールするパラメータです。大きいほど直線から大きなずれを許容するように 近似します。
自動端点接続パラメータは、端点同士を自動的に接続するかどうかを制御するためのパラメータです。
下図のように自動トレースの始終点を指定した場合

自動端点接続をしない場合、下左図のようにトレースされ、
  
自動端点接続する場合は、上右図のようにトレースされます。
  
また、端点同士の距離が自動端点接続の距離のパラメータ超えている場合、自動端点接続ありとしていても上図のように端点は接続されません。

その他の芯線ベクタ変換パラメータについては、適当な初期値がシステム側で設定されています。

// 自動トレースパラメータの設定1
// 芯線ベクタ変換に準拠するパラメータの設定
// 入力
// 後処理パラメータ
//  int             postprocessflag;    // 0x00010000...※ 直線上の不要頂点の除去
                                        // 0x00020000...※ 鋭角ヒゲの除去
                                        // 0x00040000...※ 改良版T字路十字路補正
                                        // 0x10000000...※ 近接平行線補正
// 近似パラメータ
//  double          threshold;          // 近似パラメータ(小さいほど近似精度が高くなり、頂点数が多くなる)
//                                         (0より大きく10.0より小さい値、推奨値0.8~2.0)
// 自動端点接続パラメータ
//  double          autojointshort;     // とても近い端点同士を自動接続する。
//                                         角度偏差90度までの自動接続可能距離の最大値(単位ピクセル、0.0の場合は接続しない)
//  double          autojointlong;      // やや近い端点同士を自動接続する。
//                                         角度偏差autojointangleまでの自動接続可能距離の最大値(単位ピクセル、0.0の場合は接続しない)
//  double          autojointangle;     // 自動接続可能な2辺の角度偏差(単位ラジアン)
void                msetautotraceparameter1(int postprocessflag,double threshold,
	double autojointshort,double autojointlong,double autojointangle);

自動トレースパラメータの設定2
このAPIでは、自動トレース固有のパラメータについて設定します。ヒゲの処理は芯線ベクタ変換にもありますが、自動トレースでは独自に指定する ようになっています。
  1. ヒゲの処理
    交差点の先が端点までのベクタとなっていて、その長さがignorelengthピクセル以下の場合には、そのベクタは無視して自動トレース処理をします。
  2. 交差点突き抜け処理
    あるていど一直線上に接続したベクタは、交差点を突き抜けてトレースする。


  3. トレースショートカット
    自動トレースAPIで次の交差点の先を指定した場合、通常は、下右図のように新しいトレースが始まる
      
    トレースショートカットフラグを立てている場合、下図のように次の交差点の先まで自動トレースする。

  4. 円弧近似
    この節でやっているものと同じ処理です。引数の意味も一緒です。
  5. 円当てはめ
    この節でやっているものと同じ処理です。引数の意味も一緒です。
  6. コーナー鮮鋭化
    この節でやっているものと同じ処理です。 第1引数は2007年のバージョンアップで新設された3に固定されています。 第2引数は5で固定されています。 他の引数の意味は一緒です。

// 自動トレースパラメータの設定2
// 自動トレース固有のパラメータの設定
// 入力
//  int             flag;               0x00000001...交差点突き抜け処理をする
//                                      0x00000002...トレースショートカット
//                                      マニュアル解説参照
//                                      0x00000004...円弧近似
//                                      0x00000008...円当てはめ
//                                      0x00000010...コーナー鮮鋭化
//  double          penetrateangle;     交差点突き抜け角度(単位ラジアン)
//                                      交差点の手前と先のベクタの偏角(0度の場合一直線)
//  自動トレース固有のヒゲ処理
//  double          ignorelength;       分岐点から発生するignorelength以下のショートベクタは無視する
//  円弧近似関連
//  double          aminradius;         円弧近似する場合の最小半径(最小半径以下の円弧となるものは対象としない)(単位ピクセル)
//  double          amaxradius;         円弧近似する場合の最大半径(最大半径以上の円弧となるものは対象としない)(単位ピクセル)
//                                      最小半径以下となるのは鋭角に近い部分、最大半径以上となるのは直線に近い部分
//  double          checkrange;         円弧近似での円弧下の画素の有無をチェックする。
//                                      チェックの際に±checkrangeピクセルに輪郭画素があればOK
//                                      0の場合チェックなし
//  円近似関連
//  double          radius;             円近似の最大半径(単位ピクセル)
//  double          varrate;            円弧上のノード(頂点)が円の推定半径*(1.0±varrate)以内にあればOK
//  double          fitrate;            varrate以内にあるノードの数/円弧上のノードの数がfitrate以上ならOK
//  鮮鋭化パラメータ
//                                      O(新設する頂点)
//        短辺                         / \
//        O---O                       /   \
//       /     \                     /     \
//      /       長辺                /       \
//     /         \                 /         \
// ---O           O---   ==>   ---O           O---
//    double        longpixel;          上図の長辺の長さがlongpixel(単位ピクセル)以上
//    double        shortpixel;         上図の短辺の長さがshortpixel(単位ピクセル)以下
//    double        sharpenangle;       2本の長辺のなす角度がangleラジアン以下
//    double        probelen;           新設する頂点の下に図形の画素があるかどうかチェックする範囲(単位ピクセル)
void                msetautotraceparameter2(int flag,double penetrateangle,
	double ignorelength,
	double aminradius,double amaxradius,double checkrange,
	double radius,double varrate,double fitrate,
	double longpixel,double shortpixel,double sharpenangle,double probelen);

目次


マニュアルホームページ