
| DLL | 概要 |
|---|---|
| alibraster.dll | ラスタ編集ライブラリAPI(C++) |
| ngkocr4.dll | プリミティブ編集ライブラリAPI(C++) |
| その他複数のDLL | 弊社共通ライブラリ(APIは非公開) |
| ヘッダファイル | 概要 |
|---|---|
| alibraster.h | ラスタ編集変換ライブラリ |
| cjocrprim.h | プリミティブ編集ライブラリ |
| errcode.h | エラーコードの定義 |
リファレンス
// 入力 // char* permission; パーミッションファイルのあるパス // あるいはパーミッション文字列(パーミッションファイルの3行目) // char* amodulepath; exeファイルのあるパス // char* apppath; 一時ファイルを作成可能なパス(ログインユーザーの権限で書き込める場所) CALibRaster(char* permission,char* amodulepath,char* apppath); ~CALibRaster(); // 初期化が成功したかどうかの問い合わせ // 戻り値 // 1....成功 // 0....失敗(キーファイルが見つからない、期限切れ等パーミッションが無い) int misinitsuccess();
サンプル
下記は、一時ファイル作成可能なパスが実行ファイルのある場所なので、管理者権限でないと使えないケース
CALibRaster* plib = new CALibRaster("c:\\Program Files\\Foo/rasteredit.kcd","c:\\Program Files\\Foo\\","c:\\Program Files\\Foo\\");
if(plib->misinitsuccess() == 0) {
; // パーミッションが無い
}
delete plib;

リファレンス
// 入力 // int width; // ラスタの幅(単位ピクセル) // int scanlinesize; // ラスタのスキャンラインサイズ(1行のバイト数) // int height; // ラスタの高さ(単位ピクセル) // int dpi; // ラスタの解像度 // unsigned char* pdatamono; // ラスタデータ(モノクロ1bit深度) // テキスト、線図形、面図形に分けて初期化する。オリジナルデータは // テキスト+線図形+面図形=pdatamonoであることが望ましい // 将来的に"記号"レイヤが増える予定 void msetdocument(int width,int scanlinesize,int height,int dpi,unsigned char* pdatamono); // プリミティブに対してダイレクトにアクセスしたい時はCJocrPrimクラスを経由してアクセスする // CJocrPrimインスタンスのfeatureのcyフィールドがラスタ編集用に予約されているので変更しないこと void msetpjocrprim(CJocrPrim* pjocrprim);
リファレンス
// ポリラインに対しては、CLightPolylineのインスタンスを取得してアクセスする // CLightPolylineインスタンスの数の取得 // 戻り値 // CLightPolylineインスタンスの数 int mgetlightpolylinenum(); // CLightPolylineインスタンスの取得 // 入力 // int polylineoffset; ポリラインオフセット(0〜mgetlightpolylinenum()-1) // 範囲外のオフセットを指定するとMemory Protection fault // 戻り値 // CLightPolylineインスタンスアドレス CLightPolyline* mgetlightpolyline(int polylineoffset); // ポリラインと対応するプリミティブのアドレスの取得 // CLightPolylineクラスのAPIを間接的に呼び出すだけ // 入力 // int polylineno; ポリライン番号(オフセット) // 戻り値 // NULL以外....プリミティブのアドレス // NULL........対応するプリミティブが無かった struct _PRIMITIVE* mgetprimitive(int polylineno); // プリミティブに対応するCLightPolylineインスタンスのアドレスの取得 // 入力 // struct _PRIMITIVE* prim; プリミティブアドレス // 戻り値 // NULL以外....CLightPolylineインスタンスのアドレス // NULL........対応するCLightPolylineインスタンスが無かった CLightPolyline* mgetlightpolylinefromprim(struct _PRIMITIVE* prim); // 平均ポリライン線幅の取得 // 戻り値 // 平均のポリライン線幅を返す double mgetmeanpolylinewidth();
リファレンス
CALibRasterライブラリでは、元の図面の画像を文字列図形、線図形、面図形に分離して初期化時に指定する必要があります。
この分離は、ライブラリ外で行っても構いませんが、ライブラリでも分離機能を提供しています。
また、線図形の最大線幅も初期化のAPIの入力として必要ですが、ライブラリでも最大線幅を取得することができます。
最大線幅は、たとえばライブラリが推定した値を使わずに、ユーザーが指定した値を用いることも可能です。
画像の分離は、文字列図形、線図形、面図形に分離するmalibseplineandtextと、線図形と面図形に分離するmalibseplineがあります。
// テキスト版、線図形、面図形分離
// 入力
// int amincharnum; 文字列図形内の最少プリミティブ数
// double amaxcharsize; 最大文字サイズ
// unsigned char* pdatatext; テキストレイヤ
// unsigned char* pdataline; 線図形レイヤ
// unsigned char* pdatapolygon; 面図形レイヤ
// 出力
// double& linewidth; 最大線幅
// 平均線幅+標準偏差×3×1.5+2.5
// 統計的に99.7%の線図形が入る線幅
// 100本の線の中に1本だけ太い線が混ざっているなどというケースでは
// 太い線は面図形となることもある。
// 戻り値
// 0....正常終了
// 負...エラー
int malibseplineandtext(double& linewidth,int amincharnum,double amaxcharsize,
unsigned char* pdatatext,unsigned char* pdataline,unsigned char* pdatapolygon);
// 線図形、面図形分離
// malibseplineandtextと同様に分離した後に、pdatatextとpdatapolygonを合成する。文字をあらかじめ分離しないと、
// ストローク幅によって文字が線図形になったり、面図形になったりして編集しにくくなるため。
// 入力
// int amincharnum; 文字列図形内の最少プリミティブ数
// double amaxcharsize; 最大文字サイズ
// unsigned char* pdataline; 線図形レイヤ
// unsigned char* pdatapolygon; 面図形レイヤ
// 出力
// double& linewidth; 最大線幅
// 戻り値
// 0....正常終了
// 負...エラー
int malibsepline(double& linewidth,int amincharnum,double amaxcharsize,unsigned char* pdataline,unsigned char* pdatapolygon);
テキスト画像、線図形、面図形の画像バッファと振り分け先のレイヤ番号、最大線幅を引数として、画像のレイヤ設定を
実行します。ライブラリでレイヤは256個使えますが、ライブラリで数個のレイヤ(特に250以上)を作業領域に使うため、
動作保証レイヤを0〜215の216個(6の3乗個)とします。
// CJocrPrimインスタンスをセット後に画像バッファを指定して
// プリミティブを、一般図形/テキスト/線図形にレイヤ分割しつつ読み込む
// pdatatext+pdataline+pdatapolygonがmsetdocumentのpdatamonoになっていることが条件
// バッファは、msetdocumentで指定したサイズのものを2〜3つ確保する。
// 1....ポリライン認識のためのラスタベクタ変換をライブラリに任せる
// 入力
// int layertext; テキストを配置するレイヤ(0〜215、0以外を推奨)
// int layerline; 線図形を配置するレイヤ(0〜215、0以外を推奨)
// int layerpolygon; 面図形を配置するレイヤ(0〜215、0以外を推奨)
// int linewidth; 線図形の線幅を与える
// malibseplineandtextあるいはmalibseplineから出力される線幅を引数とする
// 入出力
// unsigned char* pdatatext; テキストレイヤ(msetdocumentで指定したサイズ)
// unsigned char* pdataline; 線図形レイヤ(msetdocumentで指定したサイズ)
// unsigned char* pdatapolygon; 面図形レイヤ(msetdocumentで指定したサイズ)
// 戻り値
// 0....正常終了
// 負...エラー
int makeprim3layer(int layertext,int layerline,int layerpolygon,int linewidth,
unsigned char* pdatatext,unsigned char* pdataline,unsigned char* pdatapolygon);
int makeprim2layer(int layerline,int layerpolygon,int linewidth,
unsigned char* pdataline,unsigned char* pdatapolygon);
// 2....ポリライン認識のためのラスタベクタ変換をアプリケーション側で行う場合makeprim3layerの前に実行する。
// 注意1:必ず、msetdocument/msetpjocrprimの後に呼び出すこと。
// 注意2:線図形レイヤの全線分に対応したポリラインを設定すること(線図形全てをラスベク変換)
// 1本でもmregistpolylineで登録していると、内蔵のラスタベクタ変換は呼び出されない。
// 2-1...ポリラインの登録
// 線、テキスト、面図形に分離後、線図形レイヤをライブラリ外でポリラインに変換する
// idの仕様には注意が必要で、1以上の正数かつポリラインごとにユニークな値を与えることが必要
// たとえば最初のポリラインのidは1で2番目は2とする。0や負の数はidとして使えない(内部で別の意味を持つため)。
// 入力
// int id; 1以上ポリラインid(ユニークな数値を1以上の値で与える)
// int vertexnum; ポリライン頂点数
// int* px; ポリライン頂点座標x
// int* py; ポリライン頂点座標y
// 戻り値
// 負 エラー
// 0 正常終了
int mregistpolyline(int id,int vertexnum,int* px,int* py);
サンプル
// 3レイヤ分離のコード
{
// monodata..............モノクロ画像バッファ
// monowidth..........モノクロ画像バッファの幅(単位ピクセル)
// monoscanlinesize...モノクロ画像バッファのスキャンラインサイズ(単位バイト)
// monoheight.........モノクロ画像バッファの高さ(単位ピクセル)
// mdpi...............解像度
unsigned char* pdatatext = (unsigned char*)malloc(monoscanlinesize * monoheight * 3);
if(pdatatext == NULL) return(MEMORY_SHORTAGE);
unsigned char* pdataline = pdatatext + monoscanlinesize * monoheight;
unsigned char* pdatapolygon = pdataline + monoscanlinesize * monoheight;
double dlinewidth = maliblinewidth; // maliblinewidthにはデフォルト値が入っている
mplibraster->msetdocument(monowidth,monoscanlinesize,monoheight,mdpi,monodata);
// 一般図形/テキスト/線図形にレイヤ分割
int linewidth = (int)(dlinewidth + 0.5);
int i1 = mplibraster->malibseplineandtext(linewidth,amincharnum,amaxcharsize,pdatatext,pdataline,pdatapolygon);
if(i1 < 0) {
free(pdatatext);
return(i1);
}
// LAYER_TEXTはテキストレイヤ/LAYER_BETAは面画像レイヤ/0は線図形レイヤ
i1 = mplibraster->makeprim3layer(LAYER_TEXT,0,LAYER_BETA,linewidth,pdatatext,pdataline,pdatapolygon);
if(i1 < 0) {
free(pdatatext);
return(i1);
}
free(pdatatext);
if(i1 < 0) return(-1);
// 全図形のレイヤをバックアップ
mplibraster->mbackuplayerinfo(-1);
}
// 2レイヤ分離のコード
{
// monodata..............モノクロ画像バッファ
// monowidth..........モノクロ画像バッファの幅(単位ピクセル)
// monoscanlinesize...モノクロ画像バッファのスキャンラインサイズ(単位バイト)
// monoheight.........モノクロ画像バッファの高さ(単位ピクセル)
// mdpi...............解像度
unsigned char* pdataline = (unsigned char*)malloc(monoscanlinesize * monoheight * 2);
if(pdataline == NULL) return(MEMORY_SHORTAGE);
unsigned char* pdatapolygon = pdataline + monoscanlinesize * monoheight;
double dlinewidth = maliblinewidth; // maliblinewidthにはデフォルト値(十分大きな線幅1mm〜1.5mm程度)が入っている
mplibraster->msetdocument(monowidth,monoscanlinesize,monoheight,mdpi,monodata);
// 一般図形/線図形にレイヤ分割
int linewidth = (int)(dlinewidth + 0.5);
int i1 = mplibraster->malibsepline(linewidth,amincharnum,amaxcharsize,pdataline,pdatapolygon);
if(i1 < 0) {
free(pdataline);
return(i1);
}
// LAYER_BETAは一般画像レイヤ/0は線図形レイヤ
i1 = mplibraster->makeprim2layer(0,LAYER_BETA,linewidth,pdataline,pdatapolygon);
if(i1 < 0) {
free(pdataline);
return(i1);
}
free(pdataline);
if(i1 < 0) return(-1);
// 全図形のレイヤをバックアップ
mplibraster->mbackuplayerinfo(-1);
}



リファレンス
// レイヤ別のパレットを設定する // レイヤ0〜255に対してレイヤ別のパレットが割り当てられ、表示用のAPIで参照される // 入力 // void* palette; sizeof(RGBQUAD) * 256の配列 void makedefaultpalette(void* palette); // いずれのAPIも指定したパレットの256色と、256のレイヤを対応付けてカラー表示する // makedispdatafast:Nearest Neighbor法によって表示領域の画素に対応するプリミティブの色を取得する // 高速だが、低倍率の縮小画像では細い線などがかすれたりする // makedispdataNN :表示領域よりが入るサイズの2^nあるいは1/2^nの画像を面積平均法で取得したあとに // Nearest Neighbor法で目的のサイズにする。makedispdatafastよりも遅いが画質は改善される。 // 倍率0.5以下の場合に推奨 // makedispdatabilinear:makedispdataNNと面積平均法までは一緒で、その後bilinear法で拡大・縮小する。 // 3つのAPIの中では、最も遅いが高品質の表示画像が得られる。 // 倍率0.25以下の場合に推奨 // いずれも画像データは24ビットフルカラー画像で返される // 入力 // int width; 表示領域のサイズ(クライアントウィンドウのサイズ、単位ピクセル) // int height; 表示領域のサイズ(クライアントウィンドウのサイズ、単位ピクセル) // int scrollposx; 表示するデータの左上の座標(スクロール開始座標、実画像データでの座標、単位ピクセル) // int scrollposy; // int scanlinesize; 表示する24ビットデータのスキャンラインサイズ(DIBとして表示するため4バイトバウンダリにしたりする) // double amag; 表示倍率 // unsigned char* pdispdata; 表示データバッファ(呼ぶ側で確保する) void makedispdatalayerbilinear(int width,int height,int scrollposx,int scrollposy,int scanlinesize,double amag,unsigned char* pdispdata); void makedispdatalayerNN(int width,int height,int scrollposx,int scrollposy,int scanlinesize,double amag,unsigned char* pdispdata); void makedispdatalayerfast(int width,int height,int scrollposx,int scrollposy,int scanlinesize,double amag,unsigned char* pdispdata);
サンプル
// レイヤパレットカラーの設定
// RGBQUAD mdefaultpalette[256];で定義されている
void CALData::makedefaultpalette()
{
// とりあえずmdefaultpalette[215]まで6^3色のパレットを設定する
// R/G/Bそれぞれ(0,51,102,153,204,255)の値を取る
for(int i = 0 ; i < 216 ; i++) {
mdefaultpalette[i].rgbBlue = (i % 6) * 51;
mdefaultpalette[i].rgbGreen = ((i / 6) % 6) * 51;
mdefaultpalette[i].rgbRed = (i / 36) * 51;
mdefaultpalette[i].rgbReserved = 0;
}
// mdefaultpalette[216]〜mdefaultpalette[255]は白
for(; i < 256 ; i++) {
mdefaultpalette[i].rgbBlue = 0xff;
mdefaultpalette[i].rgbGreen = 0xff;
mdefaultpalette[i].rgbRed = 0xff;
mdefaultpalette[i].rgbReserved = 0;
}
// 予約レイヤ
// 下記3つは、デモアプリ専用のレイヤ処理のため、特にまねする必要は無い
// LAYER_SELECTNOISE0...ノイズ選択0レイヤ(緑)
// LAYER_SELECTNOISE1...ノイズ選択1レイヤ(グレイ)
// LAYER_WHITE...削除レイヤ
mdefaultpalette[LAYER_SELECTNOISE0].rgbBlue = 0;
mdefaultpalette[LAYER_SELECTNOISE0].rgbGreen = 255;
mdefaultpalette[LAYER_SELECTNOISE0].rgbRed = 0;
mdefaultpalette[LAYER_SELECTNOISE1].rgbBlue = 128;
mdefaultpalette[LAYER_SELECTNOISE1].rgbGreen = 128;
mdefaultpalette[LAYER_SELECTNOISE1].rgbRed = 128;
mdefaultpalette[LAYER_WHITE].rgbBlue = 255;
mdefaultpalette[LAYER_WHITE].rgbGreen = 255;
mdefaultpalette[LAYER_WHITE].rgbRed = 255;
// 選択された図形のレイヤ、テキストレイヤ、面図形レイヤの色を設定
// LAYER_SELECT...通常選択レイヤは明るい緑
// LAYER_TEXT...テキストレイヤは明るい水色
// LAYER_BETA...面図形レイヤは黄色
mdefaultpalette[LAYER_SELECT].rgbBlue = 102;
mdefaultpalette[LAYER_SELECT].rgbGreen = 255;
mdefaultpalette[LAYER_SELECT].rgbRed = 102;
mdefaultpalette[LAYER_TEXT].rgbBlue = 255;
mdefaultpalette[LAYER_TEXT].rgbGreen = 255;
mdefaultpalette[LAYER_TEXT].rgbRed = 0;
mdefaultpalette[LAYER_BETA].rgbBlue = 0;
mdefaultpalette[LAYER_BETA].rgbGreen = 255;
mdefaultpalette[LAYER_BETA].rgbRed = 255;
// パレット設定APIの呼び出し
mplibraster->makedefaultpalette(mdefaultpalette);
}
// 入力
// int quality; 0...高品質・低速
// 1...中品質・中速
// 2...低品質・高速
// int width; クライアント領域の幅(単位ピクセル)
// int height; クライアント領域の高さ(単位ピクセル)
// CRect crect;GetClientRect(&crect);で取得したもの
// int scrollposx; スクロール原点x
// int scrollposy; スクロール原点y
// double amag; 表示倍率
// 出力
// BITMAPINFO*& pbi; BITMAPINFO
// unsigned char*& pdispdata; 表示画像データバッファ
///////
// mplibraster....CALibRasterクラスのインスタンス
// 表示クラスではmakedispdatalayertopコール後に以下のようになる
// void CScancalcView::OnDraw(CDC* pDC)
// {
// int ret = SetDIBitsToDevice(pDC->m_hDC,
// 0, // XDest
// 0, // YDest
// (WORD)pbi->bmiHeader.biWidth, // Source Rect width
// (WORD)pbi->bmiHeader.biHeight, // Source Rect height
// 0, // XSrc
// 0, // YSrc
// 0, // Scanstart
// (WORD)pbi->bmiHeader.biHeight, // ScanEnd
// (LPSTR)pdispdata,
// (LPBITMAPINFO)pbi,DIB_RGB_COLORS);
// .....
void CScancalcDoc::makedispdatalayertop(int quality,int width,int height,int scrollposx,int scrollposy,
double amag,BITMAPINFO*& pbi,unsigned char*& pdispdata)
{
if(pbi) {
free(pbi);
pbi = NULL;
}
if(pdispdata) {
free(pdispdata);
pdispdata = NULL;
}
if(pbi == NULL) {
pbi = (BITMAPINFO *)malloc(sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256);
}
pbi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pbi->bmiHeader.biPlanes = 1;
pbi->bmiHeader.biBitCount = 24; // 24ビットフルカラー画像
pbi->bmiHeader.biWidth = width;
pbi->bmiHeader.biHeight = height;
pbi->bmiHeader.biCompression = 0;
pbi->bmiHeader.biClrUsed = 0;
// 4バイトバウンダリ
int scanlinesize = ((pbi->bmiHeader.biWidth * 3) / 4 + ((pbi->bmiHeader.biWidth * 3) % 4 > 0)) * 4;
// すべての画像をDIBとする
pbi->bmiHeader.biSizeImage = scanlinesize * pbi->bmiHeader.biHeight;
pbi->bmiHeader.biXPelsPerMeter = 0;
pbi->bmiHeader.biYPelsPerMeter = 0;
pbi->bmiHeader.biClrImportant = 0;
if(pdispdata == NULL) {
pdispdata = (unsigned char*)malloc(scanlinesize * pbi->bmiHeader.biHeight);
}
// 薄いグレイで背景(画像の無い部分)を埋める
memset(pdispdata,192,scanlinesize * pbi->bmiHeader.biHeight);
if(mimagenum > 0) {
switch(quality) {
case 0:
mplibraster->makedispdatalayerbilinear(width,height,scrollposx,scrollposy,scanlinesize,amag,pdispdata);
break;
case 1:
mplibraster->makedispdatalayerNN(width,height,scrollposx,scrollposy,scanlinesize,amag,pdispdata);
break;
case 2:
mplibraster->makedispdatalayerfast(width,height,scrollposx,scrollposy,scanlinesize,amag,pdispdata);
break;
}
}
}



リファレンス
// レイヤ情報のバックアップ // レイヤ情報は、PRIMFEATURE::lengthフィールドにバックアップされる // 他のフィールドを使うときはCJocrPrimクラスのAPIを使って自前で記述する // 入力 // int layer; バックアップする対象レイヤ(0〜215、-1は全レイヤ) // struct _PRIMITIVE* prim; 対象プリミティブのみバックアップ void mbackuplayerinfo(int layer); void mbackuplayerinfo(int layer,struct _PRIMITIVE* prim); // レイヤ情報のリストア // レイヤ情報は、PRIMFEATURE::lengthフィールドにバックアップされる // 他のフィールドを使うときはCJocrPrimクラスのAPIを使って自前で記述する // 入力 // int layer; バックアップする対象レイヤ(0〜215、-1は全レイヤ) // struct _PRIMITIVE* prim; 対象プリミティブのみリストア void mrestorelayerinfo(int layer); void mrestorelayerinfo(int layer,struct _PRIMITIVE* prim); // 指定した面積のプリミティブの移動 // CJocrPrim::mpveprimpixel(amin,amax,from,to);をコールするだけ int moveprimpixel(int amin,int amax,int from,int to); // 矩形内にかかるオブジェクトをfromからtoへ移動 // CJocrPrim::mpveprimrecthook(x1,y1,x2,y2,from,to,0);をコールするだけ int moveprimrecthook(int x1,int y1,int x2,int y2,int from,int to); // 矩形内に完全に含まれるオブジェクトをfromからtoへ移動 // CJocrPrim::mpveprimrect(x1,y1,x2,y2,from,to,0);をコールするだけ int moveprimrect(int x1,int y1,int x2,int y2,int from,int to);
リファレンス
// ポリラインの有効無効の指定
// 入力
// int unused; 1の場合無効に、0の場合有効に
void msetunused(int unused = 1) {munused = unused;}
// 戻り値
// 1....ポリラインが無効の場合
// 0....ポリラインが有効の場合
int misunused() {return (munused == 1);}
// 戻り値
// ポリラインの外接矩形の左上x、左上y、右下x、右下y座標(単位ピクセル)を返す
int mgetleft() {return mleft;}
int mgettop() {return mtop;}
int mgetright() {return mright;}
int mgetbottom() {return mbottom;}
// 戻り値
// ポリラインに結びついたプリミティブのオフセットを返す
// CAlibRaster::mpjocrprimにおけるプリミティブとなっている
int mgetprimoffset() {return mprimoffset;}
// ポリラインに結びついたプリミティブオフセットの設定
// 入力
// int offset; CAlibRaster::mpjocrprimにおけるプリミティブオフセット
void msetprimoffset(int offset) {mprimoffset = offset;}
// ポリラインの線幅の計算
// mcalclwidth()後にmgetlwidthで線幅にアクセスできる
// msetlwidthによってアプリケーション側から別途線幅を設定することも可能
void mcalclwidth();
// 戻り値
// 線幅
inline double mgetlwidth() {return mlwidth;}
// 入力
// double lwidth; 線幅
void msetlwidth(double lwidth) {mlwidth = lwidth;}
// ポリラインの頂点数・頂点座標アクセス
// 戻り値
// ポリラインの頂点数
inline int mgetvertexnum() {return mvertexnum;}
// 戻り値
// ポリラインの頂点座標配列の先頭アドレス
inline int* mgetx() {return mpx;}
inline int* mgety() {return mpy;}
// 戻り値
// ポリラインの頂点座標mgetx(n)はmgetx()[n]と同じ
// 入力
// int n; 頂点オフセット
inline int mgetx(int n) {return mpx[n];}
inline int mgety(int n) {return mpy[n];}
// ポリラインの頂点の座標設定
// 入力
// int n; 頂点オフセット
// int x,y; 頂点座標
inline void msetx(int n,int x);
inline void msety(int n,int y);
// CLightPolyline構築用
// 頂点配列の登録
// 入力
// int vertenum; 頂点数
// int* px; 頂点座標配列
// int* py;
// 戻り値
// 0....正常終了
// 負...エラー
int mregistvertex(int vertexnum,int* px,int* py);
// 頂点の削除
// 入力
// int n; 削除する頂点オフセット
void mdeletevertex(int n);
// インスタンスの回転
// 入力
// double cx; 回転中心座標
// double cy;
// double angle; 回転角度
void mrotate(double cx,double cy,double angle);
// 頂点の挿入
// 入力
// int n; n番目の頂点として挿入する
// int x,y; 挿入する頂点座標
// 戻り値
// 0....正常終了
// 負...エラー
int minsertvertex(int n,int x,int y);
// ポリラインの移動
// 入力
// int sx,sy; 相対的移動量=移動ベクトル
void moverel(int sx,int sy);
リファレンス
// 指定座標に最も近い頂点のポリライン番号と座標番号を得る // 入力 // double x; 指定座標(x,y) // double y; // double th; 座標からthピクセル以下の距離の頂点を探す // int layer; ポリラインの存在するレイヤ(0〜215、-1は全てのレイヤ) // 出力 // int& polylineno; ポリライン番号(オフセット) // int& vertexno; 頂点番号(始点が0) // 戻り値 // 0 見つからなかった // 1 見つかった int mgetnearestvertex(double x,double y,double th,int layer,int& polylineno,int& vertexno);
サンプル
// OnLButtonDown/OnMouseMove/OnKeyDownなどのハンドラの先頭で呼び出す
// マウスカーソルの位置により
// 1...マウス形状の設定
// 2...コントロールポイントのサーチ
// を行う
// int lbuttondownflag; 1...OnLButtonDownからの呼び出し、
// コントロールポイント制御開始
void CScancalcView::msetmousecursor(int lbuttondownflag,UINT nFlags,CPoint point)
{
CScancalcDoc* pDoc = GetDocument();
// mscrollposx,mscrollposyは実データピクセル座標でのスクロールポジション
CPoint sp(mscrollposx,mscrollposy);
if(pDoc->mgetimagenum() == 0) {
SetCursor(m_cursor_normal);
}
else {
// modeは動作モード
switch(mode) {
// 起動時は、図形選択モード
case MODE_SELECTPRIM:
{
// マウスポインタの座標を実データピクセル座標に変換している
double x = (point.x / mag) + mscrollposx;
double y = (point.y / mag) + mscrollposy;
double th = 16.0 / mag; // 画面上で16.0ピクセル離れている場合は頂点付近と見なさない
if(th < 10.0) th = 10.0;
int i1 = pDoc->mgetnearestvertex(x,y,th,LAYER_SELECT,mcontrolpolylineno,mcontrolvertexno);
// int i1 = mplibraster->mgetnearestvertex(x,y,th,layer,polylineno,vertexno);
// OnLbuttonDownハンドラ
if(lbuttondownflag) {
if(i1 == 1) {
mchangemode(MODE_MOVEVERTEX); // 頂点移動モード
}
else {
mcontrolpolylineno = mcontrolvertexno = -1; // 付近に頂点が無い
}
}
// OnMouseMove/OnLbuttonUp/OnRbuttonUp/OnRbuttonDown...ハンドラ
else {
if(i1 == 1) {
SetCursor(m_cursor_dragscroll); // 付近に頂点がある
// 手のひら形状にする
}
else {
mcontrolpolylineno = mcontrolvertexno = -1; // 付近に頂点が無い
SetCursor(m_cursor_normal); // 通常のマウスカーソルにする
}
}
}
break;
............

リファレンス
// ポリラインの頂点移動 // 入力 // int tolayer; 移動したポリラインの移動先レイヤ // (通常選択レイヤに移動するか、何もしないか) // int polylineno; ポリライン番号(オフセット) // int vertexno; 頂点番号(始点が0のオフセット) // int x,y; 頂点の移動先(単位ピクセル) // 戻り値 // 0 該当頂点が無い // 1 移動した // 負 エラー int movevertex(int tolayer,int polylineno,int vertexno,int x,int y);

リファレンス
// ポリラインの頂点削除 // mgetnearestvertexで取得したポリライン番号と頂点番号で削除する頂点を指示する // 端点を削除する場合は、削除した頂点を含む辺を削除 // 端点以外を削除する場合は、削除した頂点の前後の頂点をつなぐように補間 // 入力 // int tolayer; 頂点を削除したポリラインの移動先 // (通常選択レイヤに移動するか、何もしないか) // int polylineno; ポリライン番号(オフセット) // int vertexno; 頂点番号(始点が0) // 戻り値 // 0 該当頂点が無い // 1 削除した // 負 エラー int mdeletevertex(int tolayer,int polylineno,int vertexno);

リファレンス
// ポリラインの頂点切断 // 入力 // int tolayer; 切断したポリラインの移動先 // (元のレイヤのままでもいいし、選択レイヤに移動しても良い) // int polylineno; ポリライン番号(オフセット) // int vertexno; 頂点番号(始点が0) // 戻り値 // 0 該当頂点が無い // 1 切断した // 負 エラー int mseparatevertex(int tolayer,int polylineno,int vertexno);

リファレンス
// 指定レイヤのポリラインに頂点挿入 // 入力 // int layer; レイヤ(0〜215,-1は全レイヤ) // int x,y; 指定座標(x,y)からthピクセル以内にある辺に挿入 // double th; // 注意:挿入位置が前後の頂点から線幅×10ピクセル未満の場合は頂点挿入をしない // 戻り値 // 負 エラー // 0 頂点を挿入しなかった // 1 頂点を挿入した int minsertvertex(int layer,int x,int y,double th);


リファレンス
// 指定レイヤのポリラインの太線化 // 指定レイヤのポリラインの細線化 // 入力 // int layer; ポリラインの存在するレイヤ(0〜215、-1は全てのレイヤ) // int tolayer; 太線化、細線化したポリラインの移動先レイヤ // (元のレイヤのままでもいいし、選択レイヤに移動しても良い) // 戻り値 // 負 エラー // 0以上 太線化、細線化ポリライン数 int mfatpolyline(int layer,int tolayer); int mthinpolyline(int layer,int tolayer); // 指定レイヤのポリラインのレンダリング // 入力 // int layer; ポリラインの存在するレイヤ(0〜215、-1は全てのレイヤ) // int tolayer; レンダリングしたポリラインの移動先レイヤ // (元のレイヤのままでもいいし、選択レイヤに移動しても良い) // 戻り値 // 負 エラー // 0以上 レンダリングしたポリライン数 int mrenderpolyline(int layer,int tolayer);

リファレンス
// 指定レイヤのプリミティブ(ポリライン含む)削除 // 入力 // int layer; 削除対象のレイヤ(0〜215、このAPIでは全レイヤを表す-1は引数として使えない) // 戻り値 // 負 エラー // 0以上 削除プリミティブ数 int mdeleteprimitive(int layer);


リファレンス
// プリミティブ(ポリライン含む)移動(長方形内部+枠上) // 入力 // int copyflag; 1....コピー/0....移動 // int tolayer; レンダリングしたプリミティブの移動先レイヤ // (元のレイヤのままでもいいし、選択レイヤに移動しても良い) // int x1,y1,x2,y2; (x1,y1)-(x2,y2)で指定される長方形にフックされるプリミティブを移動する // int vx,vy; 移動ベクトル(方向と移動量) // 戻り値 // 負 エラー // 0以上 移動プリミティブ数 int moveprimitivehook(int copyflag,int tolayer,int x1,int y1,int x2,int y2,int vx,int vy); // プリミティブ(ポリライン含む)移動(長方形内部) // 入力 // int copyflag; 1....コピー/0....移動 // int tolayer; レンダリングしたプリミティブの移動先レイヤ // (元のレイヤのままでもいいし、選択レイヤに移動しても良い) // int x1,y1,x2,y2; (x1,y1)-(x2,y2)で指定される長方形に完全に囲まれるプリミティブを移動する // int vx,vy; 移動ベクトル(方向と移動量) // 戻り値 // 負 エラー // 0以上 移動プリミティブ数 int moveprimitiveinner(int copyflag,int tolayer,int x1,int y1,int x2,int y2,int vx,int vy); // プリミティブ(ポリライン含む)移動(指定レイヤ) // 入力 // int copyflag; 1....コピー/0....移動 // int layer; 移動するプリミティブのあるlayer(0〜215,-1は全レイヤ) // int tolayer; レンダリングしたプリミティブの移動先レイヤ // (元のレイヤのままでもいいし、選択レイヤに移動しても良い) // int vx,vy; 移動ベクトル(方向と移動量) // 戻り値 // 負 エラー // 0以上 移動プリミティブ数 int moveprimitivelayer(int copyflag,int layer,int tolayer,int vx,int vy);

リファレンス
// 図形プリミティブの回転(長方形内部+枠上) // 入力 // int copyflag; 1....コピー/0....移動 // int tolayer; レンダリングしたプリミティブの移動先レイヤ // (元のレイヤのままでもいいし、選択レイヤに移動しても良い) // int x1,y1,x2,y2; (x1,y1)-(x2,y2)で指定される長方形にフックされるプリミティブを移動する // double cx,cy; 回転中心 // double angle; 回転角度ラジアン(原点-----0) // ↓方向が正 // 戻り値 // 負 エラー // 0以上 回転プリミティブ数 int mrotateprimitivehook(int copyflag,int tolayer,int x1,int y1,int x2,int y2,double cx,double cy,double angle); // 図形プリミティブの回転(長方形内部) // 入力 // int copyflag; 1....コピー/0....移動 // int tolayer; レンダリングしたプリミティブの移動先レイヤ // (元のレイヤのままでもいいし、選択レイヤに移動しても良い) // int x1,y1,x2,y2; (x1,y1)-(x2,y2)で指定される長方形内部のプリミティブを移動する // double cx,cy; 回転中心 // double angle; 回転角度ラジアン(原点-----0) // ↓方向が正 // 戻り値 // 負 エラー // 0以上 回転プリミティブ数 int mrotateprimitiveinner(int copyflag,int tolayer,int x1,int y1,int x2,int y2,double cx,double cy,double angle); // 指定レイヤの図形プリミティブの回転 // 入力 // int copyflag; 1....コピー/0....移動 // int layer; プリミティブの存在するレイヤ(0〜215、-1は全てのレイヤ) // int tolayer; レンダリングしたポリラインの移動先レイヤ // (元のレイヤのままでもいいし、選択レイヤに移動しても良い) // double cx,cy; 回転中心 // double angle; 回転角度ラジアン(原点-----0) // ↓方向が正 // 戻り値 // 負 エラー // 0以上 回転プリミティブ数 int mrotateprimitivelayer(int copyflag,int layer,int tolayer,double cx,double cy,double angle);


リファレンス
// プリミティブの拡大縮小(長方形内部+枠上) // 入力 // int copyflag; 1....コピー/0....移動 // int tolayer; 拡大縮小後のレイヤ // (元のレイヤのままでもいいし、選択レイヤに移動しても良い) // int x1,y1,x2,y2; (x1,y1)-(x2,y2)で指定される長方形内部+枠上のプリミティブを移動する // double cx,cy; 拡大縮小中心 // double amagx; x軸方向の拡大率 // double amagy; y軸方向の拡大率 // 戻り値 // 負 エラー // 0 正常終了 int mexpandprimitivehook(int copyflag,int tolayer,int x1,int y1,int x2,int y2,double cx,double cy,double amagx,double amagy); // プリミティブの拡大縮小(長方形内部) // 入力 // int copyflag; 1....コピー/0....移動 // int tolayer; 拡大縮小後のレイヤ // (元のレイヤのままでもいいし、選択レイヤに移動しても良い) // int x1,y1,x2,y2; (x1,y1)-(x2,y2)で指定される長方形内部のプリミティブを移動する // double cx,cy; 拡大縮小中心 // double amagx; x軸方向の拡大率 // double amagy; y軸方向の拡大率 // 戻り値 // 負 エラー // 0 正常終了 int mexpandprimitiveinner(int copyflag,int tolayer,int x1,int y1,int x2,int y2,double cx,double cy,double amagx,double amagy); // 指定レイヤのプリミティブの拡大縮小 // 入力 // int copyflag; 1....コピー/0....移動 // int layer; 指定レイヤ // int tolayer; 拡大縮小後のレイヤ // (元のレイヤのままでもいいし、選択レイヤに移動しても良い) // double cx,cy; 拡大縮小中心 // double amagx; x軸方向の拡大率 // double amagy; y軸方向の拡大率 // 戻り値 // 負 エラー // 0 正常終了 int mexpandprimitivelayer(int copyflag,int layer,int tolayer,double cx,double cy,double amagx,double amagy);
目次



リファレンス
// ポリラインの描画 // 入力 // int tolayer; 描画したポリラインを置くレイヤ // (線図形レイヤ、選択図形レイヤに移動しても良い) // int vertexnum; ポリラインの頂点数(注意:2以上必要) // int* px; ポリラインの頂点 // int* py; // double lwidth; ポリラインの線幅 // 戻り値 // 0 正常終了 // 負 エラー int mdrawpolyline(int tolayer,int vertexnum,int* px,int* py,double lwidth); // int tolayer; 描画したポリラインを置くレイヤ // (線図形レイヤ、選択図形レイヤに移動しても良い) // int polylinenum; ポリライン数 // int* pvertexnum; ポリラインの頂点数配列(0〜polylinenum-1)(注意:全て2以上必要) // int** ppx; ポリラインの頂点配列の配列(0〜polylinenum-1) // int** ppy; // double* plwidth; ポリラインの線幅(0〜polylinenum-1) // 戻り値 // 0 正常終了 // 負 エラー int mdrawpolylineset(int tolayer,int polylinenum,int* pvertexnum,int** px,int** py,double* plwidth); // 長方形枠の描画(ポリラインとして) // 入力 // int tolayer; 描画したポリラインを置くレイヤ // int x1,y1,x2,y2; 長方形の対角線の座標(順不同、マウスでどのように指定した座標でも渡せる) // double lwidth; ポリラインの線幅 // 戻り値 // 0 正常終了 // 負 エラー int mdrawframerect(int tolayer,int x1,int y1,int x2,int y2,double lwidth); // 楕円枠の描画(ポリラインとして) // 入力 // int tolayer; 描画したポリラインを置くレイヤ // int x1,y1,x2,y2; 楕円外接長方形の対角線の座標(順不同、マウスでどのように指定した座標でも渡せる) // double lwidth; ポリラインの線幅 // 戻り値 // 0 正常終了 // 負 エラー int mdrawframeellipse(int tolayer,int x1,int y1,int x2,int y2,double lwidth); // 塗りつぶし長方形の描画(面図形として) // 入力 // int tolayer; 描画した塗りつぶし長方形を置くレイヤ // int x1,y1,x2,y2; 長方形の対角線の座標(順不同、マウスでどのように指定した座標でも渡せる) // 戻り値 // 0 正常終了 // 負 エラー int mdrawfillrect(int tolayer,int x1,int y1,int x2,int y2); // 塗りつぶし楕円の描画(面図形として) // 入力 // int tolayer; 描画した塗りつぶし楕円を置くレイヤ // int x1,y1,x2,y2; 楕円外接長方形の対角線の座標(順不同、マウスでどのように指定した座標でも渡せる) // 戻り値 // 0 正常終了 // 負 エラー int mdrawfillellipse(int tolayer,int x1,int y1,int x2,int y2); // 任意面図形の挿入(面図形として:任意数プリミティブを一度に挿入可能) // 入力 // int tolayer; 描画した面図形を置くレイヤ // int left; 面図形バッファの左上座標(msetdocumentの左上を原点として) // int top; // int width; 面図形バッファの幅(単位ピクセル) // int scanlinesize; 面図形バッファのスキャンラインサイズ(単位バイト) // int height; 面図形バッファの高さ(単位ピクセル) // unsigned char* pdata; 面図形バッファ // 戻り値 // 0以上 挿入した面図形の数 // 負 エラー int minsertprimitive(int tolayer,int left,int top,int width,int scanlinesize,int height,unsigned char* pdata);
リファレンス
// ライブラリの現在の状態を取得するバッファサイズを得る // 戻り値 // バッファサイズ(アプリケーション側で確保する) size_t mgetsaveLPbuffersize(); size_t mgetsaveLPPbuffersize(); // ライブラリの現在の状態を取得する // 利用目的1;undo/redo機能を実現する // 2;独自形式のファイルで現在の作業状態をファイル保存/読込する // 取得前にmgetsaveLPbuffersize()で取得したバッファサイズ分の領域を確保する // 入力 // char*& ps1; 状態を取得するバッファの先頭アドレス(アプリケーション側で確保) void msaveLPbuffer(char*& ps1); void msaveLPPbuffer(char*& ps1); // ライブラリの現在の状態をバッファで指定する // 入力 // size_t len; バッファサイズ // char*& ps1; 状態バッファの先頭アドレス // 戻り値 // 負 エラー // 0 正常終了 int mloadLPbuffer(size_t& len,char*& ps1); int mloadLPPbuffer(size_t& len,char*& ps1);
サンプル
/////////////////////////////////////////
// 0....ライブラリの状態を保存する領域をリングバッファで管理するものとする。
// リングバッファがいっぱいになったときは古いものから除外する
// 1....画像入力時にOSからメモリの状況を取得して、リングバッファのサイズ(=アンドゥ回数+1/+1はアンドゥのリドゥ分)
// を設定する。
// 2....オペレーションの直前に現在の状態を保存するために、mregistoperationをコール
// バッファをリングバッファに登録する
// 3....アンドゥコマンド処理時には、mprocessundoをコール
// リングバッファのトップの場合は、mregistoperationをコールする(最初のアンドゥの前までリドゥするため)。
// 4....リドゥコマンド処理時には、mprocessredoをコール
///////////////////////////////////////////
// 操作をヒストリ(リングバッファ)に登録する
// typedef struct _HISTORYBUFFER_RASTER {
// int mflag; // 1....ライトポリライン情報のみ
// // 2....画像+ライトポリライン情報
// // 4....最初のundo時に最新のステータスを保存したもの
// size_t mundosize;
// ....以下にはアプリケーション固有の情報があれば、それを保存する
// } HISTORYBUFFER_RASTER;
// 入力
// int lastflag; undo直前から呼び出した時は1
// そのほかは0
// int prsaveflag; レイヤ情報だけ保存するときは0
// primitive情報全てを保存するときは1
void CScancalcDoc::mregistoperation(int lastflag,int prsaveflag)
{
HISTORYBUFFER_RASTER* ph;
size_t buffersize = sizeof(HISTORYBUFFER_RASTER);
// CJocrPrim情報(レイヤ情報だけ)
// CJocrPrim情報
size_t undoprimsize = mgetsaveLPPbuffersize((prsaveflag==0));
buffersize += undoprimsize;
// undoバッファ確保
ph = (HISTORYBUFFER_RASTER *)malloc(buffersize);
if(ph) {
// prsaveflagが0か1かを保存
if(prsaveflag)
ph->mflag = 3; // プリミティブ構造を保存する
else
ph->mflag = 1; // プリミティブ構造を保存しない
// lastflagを保存
if(lastflag == 1)
ph->mflag |= 4; // 最新の状態を保存したもの(redo用)
// ライブラリの保存
ph->mundosize = undoprimsize;
// CJocrPrim情報
// ヘッダの次から保存されている
char* ps1 = (char *)(ph + 1);
// ライブラリの状態をps1に取り出す
msaveLPPbuffer(prsaveflag==0,ps1);
// リングバッファに登録するためのアプリケーション固有の関数
mundoregist(lastflag,buffersize,(void*)ph);
free(ph);
}
}
// アンドゥ処理
int CScancalcDoc::mprocessundo()
{
int buffersize;
void* ph;
// リングバッファのトップの場合は、アンドゥ直前の状態を登録して、そこまでリドゥ可能とする
if(mistoregistoperationbyundo()) { // リングバッファのトップ判定
mregistoperation(1,mlastprsaveflag);
}
int i1 = mexecundo(buffersize,ph);
if(i1 == 0) {
mrecoveroperation(ph);
return((((HISTORYBUFFER_RASTER*)ph)->mflag & 2) != 0); // 画像が変わると1を返す
// 画像が変わったら何か特別なことをしたい場合
}
return(0); // レイヤ情報だけが変わった場合
}
// リドゥ処理
int CScancalcDoc::mprocessredo()
{
int buffersize;
void* ph;
int i1 = mexecredo(buffersize,ph);
if(i1 == 0) {
mrecoveroperation(ph);
return((((HISTORYBUFFER_RASTER*)ph)->mflag & 2) != 0);
}
return(0);
}
// アンドゥ・リドゥ共通処理
void CScancalcDoc::mrecoveroperation(void* p1)
{
HISTORYBUFFER_RASTER* ph = (HISTORYBUFFER_RASTER *)p1;
// CJocrPrim情報の復帰
// 画像情報が保存されている
size_t len = ph->mundosize;
char* ps1 = (char*)(ph + 1);
// バッファps1の状態にライブラリを設定する
mloadLPPbuffer((ph->mflag & 2) == 0,len,ps1);
}
リファレンス
// プリミティブ→ビットマップ逆変換 // 幅と高さ、スキャンラインは元のドキュメントと同じ(msetdocumentで設定したもの) // コールする側でバッファを確保、管理、解放する // 入力 // int layer; -1,0〜255...逆変換するレイヤ、-1は全レイヤ void makebitmap(int layer,unsigned char* pdata);
サンプル
///////////////////
// レイヤ画像の保存
// レイヤを指定して、モノクロ画像として保存する
// 全レイヤを保存する場合は、layernumに1、player[0]に-1を設定する。
// 入力
// char* filename; 保存ファイル名
// int layernum; レイヤ数
// int* player; player[0]〜player[layernum-1]までのレイヤ配列
// 戻り値
// 負...エラー
// 0....正常終了
int CALData::msavelayerimage(char* filename,int layernum,int* player)
{
// 各レイヤの画像を加算するため、画像サイズ×2のバッファを取得
unsigned char* pdata = (unsigned char*)malloc(mscanlinesize * mheight * 2);
if(pdata == NULL) return(MEMORY_SHORTAGE);
// 0で埋める(保存時のphotometric設定で白)
memset(pdata,0,mscanlinesize * mheight * 2);
unsigned char* pdata1 = pdata + mscanlinesize * mheight;
if(layernum > 0) {
// player[0]が-1の時は、全レイヤ保存
if(player[0] == -1) {
mplibraster->makebitmap(player[0],pdata);
}
else {
// 指定レイヤの画像を合成する
for(int i = 0 ; i < layernum ; i++) {
mplibraster->makebitmap(player[i],pdata1);
for(int j = 0 ; j < mheight ; j++) {
unsigned char* ps1 = pdata1 + mscanlinesize * j;
unsigned char* ps2 = pdata + mscanlinesize * j;
for(int k = 0 ; k < mscanlinesize ; k++,ps1++,ps2++) {
*ps2 = *ps2 | *ps1;
}
}
}
}
}
// アプリケーション固有の画像保存呼び出し
// alibrasterライブラリには含まれません
int i1 = mplibimage->msaveimage(0,0,filename,mwidth,mheight,1,mscanlinesize,0,mdpi,pdata);
free(pdata);
if(i1 < 0) {
return(i1);
}
return(0);
}