#ifndef __JBXL_CPP_MEMORY_SIMPLE_GRAPH_H_ #define __JBXL_CPP_MEMORY_SIMPLE_GRAPH_H_ /** グラフィックデータ定義用ヘッダ gdata.h */ #include "tools++.h" #include "Vector.h" #include "Gdata.h" // namespace jbxl { void rotate_point (int& x, int& y, double sxc, double syc, double dxc, double dyc, double cst, double snt); void rotate_point_angle(int& x, int& y, double sxc, double syc, double dxc, double dyc, double th); /* template RBound out_around_MSGraph(MSGraph vp, int x, int y, int mode=8); template Vector dgree_circle_MSGraph(MSGraph vp); template double count_around_MSGraph(MSGraph vp); template int count_area_MSGraph(MSGraph xp); template int count_object_MSGraph(MSGraph xp, int mn, int mx); template RBound get_boundary_MSGraph(MSGraph vp, int mn, int mx); template void cat_MSGraph (MSGraph src, MSGraph& dst); template void copy_MSGraph(MSGraph src, MSGraph& dst); template MSGraph dup_MSGraph(MSGraph src); template void ToPola(Vector nv, double& cst, double& snt, double& csf, double& snf, double pcsf=0.0, double psnf=1.0) template void Local2World(MSGraph gd, MSGraph vp, Vector oq, Vector op, Vector ex); template void MSGraph_chngColor(MSGraph vp, int f, int t); template int MSGraph_Paint (MSGraph vp, int x, int y, int mn, int mx, int cc, int mode=8); template int MSGraph_Paint3D (MSGraph vp, int x, int y, int z, int mn, int mx, int cc, int mode=8); template void MSGraph_Line (MSGraph vp, int x1, int y1, int x2, int y2, int cc); template void MSGraph_Line3D (MSGraph vp, int x1, int y1, int z1, int x2, int y2, int z2, int cc); template void MSGraph_Triangle (MSGraph vp, int x1, int y1, int x2, int y2, int x3, int y3, int cc, int mode=OFF); template void MSGraph_Box (MSGraph vp, int x1, int y1, int x2, int y2, int cc, int mode=OFF); template void MSGraph_Circle (MSGraph vp, int x, int y, int r, int cc, int mode=OFF); template void MSGraph_Circle3D (MSGraph vp, Vector<> ox, Vector<> ex, int rr, int cc, int mode=OFF); template void MSGraph_Pool (MSGraph vp, Vector<> a, Vector<> b, int rr, int cc); template void MSGraph_Torus (MSGraph vp, Vector<> ox, Vector<> ex, int rr, int ra, int cc); template void MSGraph_Sphere (MSGraph vp, Vector<> a, int r, int cc, int mode=1); template MSGraph cut_object_MSGraph(MSGraph vp, int mn, int mx, int blank=BOUNDARY_BLANK, bool ecnt=false); template MSGraph cut_object_MSGraph(MSGraph vp, int mn, int mx, RBound rbound, int blank=BOUNDARY_BLANK, bool ecnt=false); template MSGraph cut_object_MSGraph(MSGraph vp, RBound rbound, bool ecnt=false); template MSGraph zoom_MSGraph (MSGraph vp, float zm, int mode=ON); template MSGraph reduce_MSGraph(MSGraph vp, float rc, int mode=ON) template MSGraph rotate_MSGraph(MSGraph vp, int xs, int ys, double cst, double snt, int mode=ON); template MSGraph rotate_MSGraph(MSGraph vp, double th, int mode=ON); template MSGraph x_reverse_MSGraph(MSGraph vp); template MSGraph grab_MSGraph(MSGraph vp, int x1, int y1, int x2, int y2); template void set_around_MSGraph(MSGraph vp, int cc); template int addPaint_MSGraph(MSGraph xp, int x, int y, int mn, int mx, int add, int mode=8); template MSGraph Density_Filter(MSGraph vp, int size, float rate, int mode=8, int work_color=0); template MSGraph Density_Mask(MSGraph vp, float rate, int mode=8, int work_color=0); template void delete_noise_MSGraph(MSGraph vp, int size, int mode=8, int work_color=0) */ /** template Vector dgree_circle_MSGraph(MSGraph vp) 2D画像において,vp.zero以外の輝度値のオブジェクトの分散度(円形度の逆数) を計算する.穴空きのオブジェクトも計算可能.独自アルゴリズム. Fumi.Iseki(C) バグ:縁にかかる画像にかんしては正確に外周を計算できない.=> 縁をvp.zeroで埋めること. Vector x : 外周 y : 面積 z : 分散度 */ template Vector dgree_circle_MSGraph(MSGraph vp) { Vector vt; double fac = 1.113757; // double fac = 1.182; /* MSGraph pp; pp.set(vp.xs+2, vp.ys+2, 1); for (int j=0; j Vector object_feature_MSGraph(MSGraph vp, int mn, int mx) 2D画像において,vp.zero以外の輝度値のオブジェクトの分散度(円形度の逆数) を計算する.穴空きのオブジェクトも計算可能.独自アルゴリズム. Fumi.Iseki(C) Vector x : 個数 y : 全面積 z : 分散度 */ template Vector object_feature_MSGraph(MSGraph vp, int mn, int mx) { int cnt = 0; int nx, ny; MSGraph pp; Vector vt; pp.mimicry(vp); for (int i=0; i(pp); for (int j=0; j=mn && pp.gp[nx]<=mx) { MSGraph_Paint(pp, i, j, mn, mx, pp.zero, 8); cnt++; } } } pp.free(); vt.x = (double)cnt; return vt; } /* template double count_around_MSGraph(MSGraph vp) 2D画像において,vp.zero以外の輝度値のオブジェクトの周囲長を測る. 穴空きのオブジェクトも計算可能. 面積が4以下では不正確になります. 縁にかかる画像に関しては正確に計算できません.=> 縁をvp.zeroで埋めること. 独自アルゴリズム (C) 2002 */ template double count_around_MSGraph(MSGraph vp) { int i, j, m, n, cc; bool sflg; double cnt; const double qs = 0.70710678118654752440084436210; // sqrt(2.)/2. MSGraph xp; xp = zoom_MSGraph(vp, 2, OFF); if (xp.isNull()) return -1.0; cnt = 0.0; for (j=1; j0) if (xp.point(i+(1-m), j)!=vp.zero) sflg = true; // 対角チェック } } } if (cc==1 || cc==3) cnt += qs; else if (cc==2) { if (sflg==false) cnt += 1; else cnt += 2; } } } xp.free(); return cnt; } /** template int count_area_MSGraph(MSGraph xp) 機能:面積を測る. */ template int count_area_MSGraph(MSGraph xp) { int ss = 0; for (int i=0; i int count_object_MSGraph(MSGraph xp, int mn, int mx) { int cnt = 0; int nx, ny; MSGraph pp; pp.mimicry(xp); for (int i=0; i=mn && pp.gp[nx]<=mx) { MSGraph_Paint(pp, i, j, mn, mx, pp.zero, 8); cnt++; } } } pp.free(); return cnt; } /** template RBound out_around_MSGraph(MSGraph vp, int x, int y, int mode=8) 機能: 2Dグラフィックデータ構造体vpの(x,y)にあるオブジェクトの周囲長を得る. 引数: vp -- 操作対象となる 2D グラフィックデータ構造体. x, y -- 情報を得たいオブジェクト内の左上縁(境界)の座標.  または,左上方向のオブジェクト外の座標(この場合,上記の座標を探す) この座標の左横に情報を得たいオブジェクトの一部が在ってはいけない. mode -- モード.4: 4近傍探索.その他:8近傍探索. 戻り値: 境界構造体rb rb.xmin: オブジェクトの x座標の最小値. rb.xmax: オブジェクトの x座標の最大値. rb.ymin: オブジェクトの y座標の最小値. rb.ymax: オブジェクトの y座標の最大値. rb.zmin: オブジェクトの周囲長.ただし、8近傍モードの場合、斜めの距離も1と数える. rb.zmax: 8近傍モード時の斜めの距離の回数. 周囲長を rb.zmin + rb.zmax*{sqrt(2.)-1} で計算する 場合もある. 注: 1ドットの長さは1と数える. */ template RBound out_around_MSGraph(MSGraph vp, int x, int y, int mode=8) { int i, j, sp, cp, w, ll, ss; int xx, yy, vx, vy, ix; bool eflg=false; int r8[8]={-1, 1, -1, -1, 1, -1, 1, 1}; int r4[8]={ 0, 1, -1, 0, 0, -1, 1, 0}; int* cc; i = x; // オブジェクトを探す for (j=y; j rb(x, x, y, y); i = y*vp.xs + x; sp = cp = i; ss = ll = 0; vx = 1; vy = 0; if (mode==4) { ix = 4; cc = r4; } else { ix = 8; cc = r8; } do { w = abs(vx)+abs(vy); xx = (vx*cc[0]+vy*cc[1])/w; yy = (vx*cc[2]+vy*cc[3])/w; for (j=1; j<=ix; j++) { if (vp.gp[cp+yy*vp.xs+xx]!=vp.zero) { vx = xx; vy = yy; cp = cp + yy*vp.xs + xx; xx = cp%vp.xs; yy = (cp-xx)/vp.xs; rb.xmax = Max(rb.xmax, xx); rb.ymax = Max(rb.ymax, yy); rb.xmin = Min(rb.xmin, xx); rb.ymin = Min(rb.ymin, yy); break; } else { if(sp==cp && xx==-1 && yy==vp.zero) { eflg = true; break; } w = abs(xx)+abs(yy); vx = (xx*cc[4]+yy*cc[5])/w; vy = (xx*cc[6]+yy*cc[7])/w; xx = vx; yy = vy; } } ll++; if (abs(vx)+abs(vy)==2) ss++; } while(!eflg); if (mode==4) ss = 0; (rb.xmax)++; (rb.ymax)++; (rb.xmin)--; (rb.ymin)--; rb.zmax = ss; rb.zmin = ll; return rb; } /** template RBound get_boundary_MSGraph(MSGraph vp, T mn, T mx) 機能:3Dオブジェクト境界を得る. */ template RBound get_boundary_MSGraph(MSGraph vp, T mn, T mx) { int nx, ny, nz, ps; RBound rb; rb.set(vp.xs, 0, vp.ys, 0, vp.zs, 0); ps = vp.xs*vp.ys; for (int k=0; k=mn && vp.gp[nx]<=mx) { rb.fusion((T)i, (T)j, (T)k); } } } } rb.cutdown(vp.rbound); return rb; } /** template void cat_MSGraph(MSGraph src, MSGraph& dst) 機能: MSGraph型データのバッファ部を MSGraph型のバッファ部へ上書き(追加)する. 位置,サイズは自動調整される. 引数: src -- コピー元グラフィックデータ dst -- コピー先グラフィックデータ 戻り値:なし. */ template void cat_MSGraph(MSGraph src, MSGraph& dst) { int i, x, y, z; MSGraph vp; RBound rb; if (src.gp==dst.gp) return; rb.xmin = Min(src.rbound.xmin, dst.rbound.xmin); rb.ymin = Min(src.rbound.ymin, dst.rbound.ymin); rb.zmin = Min(src.rbound.zmin, dst.rbound.zmin); rb.xmax = Max(src.rbound.xmax, dst.rbound.xmax); rb.ymax = Max(src.rbound.ymax, dst.rbound.ymax); rb.zmax = Max(src.rbound.zmax, dst.rbound.zmax); vp.set(rb.xmax-rb.xmin+1, rb.ymax-rb.ymin+1, rb.zmax-rb.zmin+1, dst.zero, dst.base, dst.RZxy); if (vp.gp==NULL) return; vp.rbound = rb; vp.max = Max((T)src.max, dst.max); vp.min = Min((T)src.min, dst.min); for (i=0; i void copy_MSGraph(MSGraph src, MSGraph& dst) 機能: MSGraph型データのバッファ部を MSGraph型のバッファ部へコピーする.  dstのデータ部がある場合は破棄される. 引数: src -- コピー元グラフィックデータ dst -- コピー先グラフィックデータ 戻り値:なし. */ template void copy_MSGraph(MSGraph src, MSGraph& dst) { MSGraph vp; if (src.gp==dst.gp) return; vp = src; vp.getm(src.xs, src.ys, src.zs, src.zero); if (vp.gp==NULL) { dst.free(); dst.gp = NULL; dst.state = ERROR_GRAPH_MEMORY; return; } vp.max = (T)src.max; vp.min = (T)src.min; vp.base = (T)src.base; vp.color = src.color; vp.state = src.state; for (int i=0; i MSGraph dup_MSGraph(MSGraph src) 機能: MSGraph型データのコピーを作成する. 引数: src -- コピー元グラフィックデータ 戻り値:コピーされた MSGraph型のデータ */ template MSGraph dup_MSGraph(MSGraph src) { MSGraph vp; vp.init(); if (src.isNull()) { vp.state = ERROR_GRAPH_NODATA; return vp; } vp = src; vp.getm(src.xs, src.ys, src.zs, src.zero); if (vp.gp==NULL) { vp.init(); vp.state = ERROR_GRAPH_MEMORY; return vp; } for (int i=0; i void ToPola(Vector nv, double& cst, double& snt, double& csf, double& snf, double pcsf=0.0, double psnf=1.0) 機能: ベクトル nvの単位ベクトルを極座標 (1,θ,φ) へ変換する. ただし,θφは sin, cosの値として返される. ベクトル nvのノルムは計算されている必要がある. 引数: nv -- 方向ベクトル. cst -- 指定しない.cosθの値が入る. snt -- 指定しない.sinθの値が入る. csf -- 通常は cosφの値が入る.sinθ≒0 の場合は pcsfの値が代入される. snf -- 通常は sinφの値が入る.sinθ≒0 の場合は psnfの値が代入される. pcsf - sinθ≒0 の場合に csfに代入される.連続計算の場合に直前の cosφの値を指定する. psnf - sinθ≒0 の場合に snfに代入される.連続計算の場合に直前の sinφの値を指定する. */ template void ToPola(Vector nv, double& cst, double& snt, double& csf, double& snf, double pcsf=0.0, double psnf=1.0) { if (nv.n!=1.0) nv.normalize(); if (nv.z<-1.0) nv.z = -1.0; if (nv.z> 1.0) nv.z = 1.0; cst = nv.z; snt = sqrt(1.0-nv.z*nv.z); if (snt void Local2World(MSGraph gd, MSGraph vp, Vector oq, Vector op, Vector ex, double pcsf=0.0, double psnf=1.0) 機能: ローカルな観測座標系のグラフィック vpをグローバル座標系 のグラフィック gd に埋めこむ.    ローカルな極座標系はグローバル座標系から平行移動しただけ. ローカルな観測座標系 → ローカルな極座標系 → グローバル座標系 変換先の点の周りの格子点全てに値を設定する. 引数: gd -- グローバル座標系のグラフィック空間. vp -- 観測座標系のグラフィックデータ(左上が原点). oq -- グローバル座標系から見たローカルな極座標系の原点の座標. op -- 観測座標系から見たローカルな極座標系の原点の座標. ex -- ローカルな極座標系から見た観測座標系のx軸(ローカルな極座標系でのz軸)の向き. *pcsf - sinθ≒0 の場合に *csfに代入される.連続計算の場合に直前の cosφの値を指定する. *psnf - sinθ≒0 の場合に *snfに代入される.連続計算の場合に直前の sinφの値を指定する. */ template void Local2World(MSGraph gd, MSGraph vp, Vector oq, Vector op, Vector ex, double* pcsf=NULL, double* psnf=NULL) { int x, y, z, cx, cy, cz; double px, py, pz, xx, yy, zz; double cst, snt, csf=0.0, snf=1.0; if (pcsf!=NULL && psnf!=NULL) { csf = *pcsf; snf = *psnf; } ToPola(ex, cst, snt, csf, snf, csf, snf); for (z=0; z void MSGraph_changeColor(MSGraph vp, int f, int t) { for (int i=0; i int MSGraph_Paint(MSGraph vp, int x, int y, int mn, int mx, int cc, int mode=8) 機能: 2Dグラフィックの塗りつぶし. 2Dグラフィック vpの点(x,y)から始めて, mn〜mx の輝度値を cc で塗りつぶす. 引数: vp -- グラフィックデータ構造体. x -- 塗りつぶしを始める点の x座標. y -- 塗りつぶしを始める点の y座標. mn -- 塗りつぶされる輝度値の最小値 mx -- 塗りつぶされる輝度値の最大値. c -- 塗りつぶしの輝度値. mode -- モード 8:8近傍の塗りつぶし その他:4近傍の塗りつぶし */ template int MSGraph_Paint(MSGraph vp, int x, int y, int mn, int mx, int cc, int mode=8) { int i, j, k, ss; if (cc<=mx && cc>=mn) { DEBUG_MODE print_messageln("MSGRAPH_PAINT: WARNING: c = %d. Not be %d< c <%d", cc, mn, mx); return 0; } if (x<0 || x>=vp.xs || y<0 || y>=vp.ys) return 0; if (vp.gp[y*vp.xs+x]>(T)mx || vp.gp[y*vp.xs+x]<(T)mn) return 0; while(x>0) { if (vp.gp[y*vp.xs+x-1]>(T)mx || vp.gp[y*vp.xs+x-1]<(T)mn) break; x--; } k = x; ss = 0; while(k(T)mx || vp.gp[y*vp.xs+k]<(T)mn) break; vp.gp[y*vp.xs+k] = (T)cc; ss++; k++; } k--; for (i=x; i<=k; i++){ if (y-1>=0 && y-1=(T)mn) { ss += MSGraph_Paint(vp, i, y-1, mn, mx, cc, mode); } if (Xabs(mode)==8) { // 8-neighborhood if (i-1>=0) { if (vp.gp[j-1]<=(T)mx && vp.gp[j-1]>=(T)mn) { ss += MSGraph_Paint(vp, i-1, y-1, mn, mx, cc, mode); } } if (i+1=(T)mn) { ss += MSGraph_Paint(vp, i+1, y-1, mn, mx, cc, mode); } } } } if (y+1>=0 && y+1=(T)mn) { ss += MSGraph_Paint(vp, i, y+1, mn, mx, cc, mode); } if (Xabs(mode)==8) { // 8-neighborhood if (i-1>=0) { if (vp.gp[j-1]<=(T)mx && vp.gp[j-1]>=(T)mn) { ss += MSGraph_Paint(vp, i-1, y+1, mn, mx, cc, mode); } } if (i+1=(T)mn) { ss += MSGraph_Paint(vp, i+1, y+1, mn, mx, cc, mode); } } } } } return ss; } /** template int MSGraph_Paint3D(MSGraph vp, int x, int y, int z, int mn, int mx, int cc, int mode=8) 機能: 3Dグラフィックの塗りつぶし. 3Dグラフィック vpの点(x,y,z)から始めて, mn〜mx の輝度値を c で塗りつぶす. 引数: vp -- グラフィックデータ構造体. x -- 塗りつぶしを始める点の x座標. y -- 塗りつぶしを始める点の y座標. mn -- 塗りつぶされる輝度値の最小値 mx -- 塗りつぶされる輝度値の最大値. c -- 塗りつぶしの輝度値. mode -- モード.マイナスの場合は途中経過(z)を表示. +-8:平面上で8近傍の塗りつぶし その他:平面上で4近傍の塗りつぶし */ template int MSGraph_Paint3D(MSGraph vp, int x, int y, int z, int mn, int mx, int cc, int mode=8) { int i, j, ps, ss; MSGraph xp; ss = 0; ps = vp.xs*vp.ys; xp = vp; xp.zs = 1; xp.gp = &(vp.gp[z*ps]); if (xp.gp[y*xp.xs+x]>(T)mx || xp.gp[y*xp.xs+x]<(T)mn) return 0; ss += MSGraph_Paint(xp, x, y, mn, mx, cc, mode); if (mode<0) { DEBUG_MODE print_messageln("MSGRAPH_PAINT3D: zz = %d", z); } for (i=0; i=0) { j = (z-1)*ps+y*vp.xs+x; if (vp.gp[j]<=(T)mx && vp.gp[j]>=(T)mn) { ss += MSGraph_Paint3D(vp, x, y, z-1, mn, mx, cc, mode); } } if (z+1=(T)mn) { ss += MSGraph_Paint3D(vp, x, y, z+1, mn, mx, cc, mode); } } } } return ss; } /** template void MSGraph_Line(MSGraph vp, int x1, int y1, int x2, int y2, int cc) 機能: 2Dのラインの描画. 点(x1,y1)から点(x2,y2)へ濃度 ccの線を引く. 引数: vp -- 操作対象となるグラフィックデータ構造体. x1, y1 -- 線の始点の座標. x2, y2 -- 線の終点の座標. cc -- 線の濃度. 使用例 MSGraph_Line(vp, 100, 200, 300, 300, 200); (100,200)から(300,300)へ濃度 200の線を引く */ template void MSGraph_Line(MSGraph vp, int x1, int y1, int x2, int y2, int cc) { int thresh=0, index; int xunit=1; int yunit=1; int xdiff=x2-x1; int ydiff=y2-y1; if (xdiff<0) { xdiff = -xdiff; xunit = -1; } if (ydiff<0) { ydiff = -ydiff; yunit = -1; } if (xdiff>ydiff) { for (index=0; index=0 && x1=0 && y1=xdiff) { thresh = thresh - xdiff; y1 = y1 + yunit; } } } else { for (index=0; index=0 && x1=0 && y1=ydiff) { thresh = thresh - ydiff; x1 = x1 + xunit; } } } } /** template void MSGraph_Triangle(MSGraph vp, int x1, int y1, int x2, int y2, int x3, int y3, int cc, int mode=OFF) 機能: 2Dの三角形の描画. 点(x1,y1),(x2,y2),(x3,y3)の三点を頂点とした三角形を描く. 線の濃度は cc. modeが 1以上なら,三角形の内部を塗りつぶす. 引数: vp -- 操作対象となるグラフィックデータ構造体. (x1,y1),(x2,y2),(x3,y3) -- 三角形の頂点の座標. cc -- 線の濃度. mode -- ON なら三角形の内部の vp.zero〜cc-1 をccで塗りつぶす. 使用例 triangle(vp, 100, 100, 100, 200, 200, 100, 1000, 1); (100,100),(100,200),(200,100)を頂点とした三角形(直角三角形)を描き,内部を塗りつぶす */ template void MSGraph_Triangle(MSGraph vp, int x1, int y1, int x2, int y2, int x3, int y3, int cc, int mode=OFF) { MSGraph_Line(vp, x1, y1, x2, y2, cc); MSGraph_Line(vp, x2, y2, x3, y3, cc); MSGraph_Line(vp, x3, y3, x1, y1, cc); if (mode==ON) { MSGraph_Paint(vp, (x1+x2+x3)/3, (y1+y2+y3)/3, (int)vp.zero, cc-1, cc, 4); } return; } /** template void MSGraph_Box(MSGraph vp, int x1, int y1, int x2, int y2, int cc, int mode=OFF) 機能: 点(x1,y1)-(x2,y2)を対角とした四角形を描く.線の濃度は cc. modeが 1以上なら,四角形の内部を塗りつぶす. 引数: vp -- 操作対象となるグラフィックデータ構造体. (x1,y1)-(x2,y2) -- 四角形の対角の座標. cc -- 線の濃度. mode -- ON なら四角形の内部の vp.zero〜cc-1 をccで塗りつぶす. 使用例 box(vp, 100, 100, 200, 200, 1000, 0); (100,100),(200,200)を対角とした四角形を描く */ template void MSGraph_Box(MSGraph vp, int x1, int y1, int x2, int y2, int cc, int mode=OFF) { MSGraph_Line(vp, x1, y1, x2, y1, cc); MSGraph_Line(vp, x2, y1, x2, y2, cc); MSGraph_Line(vp, x2, y2, x1, y2, cc); MSGraph_Line(vp, x1, y2, x1, y1, cc); if (mode==ON) { MSGraph_Paint(vp, (x1+x2)/2, (y1+y2)/2, (int)vp.zero, cc-1, cc, 4); } return; } /** template void MSGraph_Line3D(MSGraph vp, int x1, int y1, int z1, int x2, int y2, int z2, int cc) 機能:3Dのラインの描画. 点(x1,y1,z1)から点(x2,y2,z2)へ濃度 ccの線を引く. 引数:vp -- 操作対象となるグラフィックデータ構造体. x1, y1, z1 -- 線の始点の座標. x2, y2, z2 -- 線の終点の座標. cc -- 線の濃度. 戻り値:なし */ template void MSGraph_Line3D(MSGraph vp, int x1, int y1, int z1, int x2, int y2, int z2, int cc) { int i; int xx, yy, zz, dx, dy, dz; int ux=1, uy=1, uz=1; int sx=0, sy=0, sz=0; dx = x2 - x1; dy = y2 - y1; dz = z2 - z1; if (dx<0) { dx = -dx; ux = -1; } if (dy<0) { dy = -dy; uy = -1; } if (dz<0) { dz = -dz; uz = -1; } xx = x1; yy = y1; zz = z1; if (xx>=0 && xx=0 && yy=0 && zz=dy && dx>=dz) { for (i=1; i<=dx; i++) { xx = xx + ux; sy = sy + dy; sz = sz + dz; if (sy>dx) { sy = sy - dx; yy = yy + uy; } if (sz>dx) { sz = sz - dx; zz = zz + uz; } if (xx>=0 && xx=0 && yy=0 && zzdx && dy>=dz) { for (i=1; i<=dy; i++) { yy = yy + uy; sx = sx + dx; sz = sz + dz; if (sx>dy) { sx = sx - dy; xx = xx + ux; } if (sz>dy) { sz = sz - dy; zz = zz + uz; } if (xx>=0 && xx=0 && yy=0 && zzdz) { sx = sx - dz; xx = xx + ux; } if (sy>dz) { sy = sy - dz; yy = yy + uy; } if (xx>=0 && xx=0 && yy=0 && zz void MSGraph_Circle(MSGraph vp, int x, int y, int r, int cc, int mode=OFF) 機能:2Dの円の描画. 点(x,y)を中心に半径rで濃度 ccの円を書く. 引数:vp -- 操作対象となるグラフィックデータ構造体. x, y -- 円の中心の座標. r -- 円の半径. cc -- 線の濃度. mode -- ON なら円の内部の vp.zero〜cc-1 をccで塗りつぶす. 戻り値:なし */ template void MSGraph_Circle(MSGraph vp, int x, int y, int r, int cc, int mode=OFF) { double yy, dy, dt; int i, nn, cx; int ix, iy, ux=1; int *px, *py; if (r<=0) return; px = (int*)malloc(sizeof(int)*(r+1)); py = (int*)malloc(sizeof(int)*(r+1)); if (px==NULL || py==NULL) { free(px); free(py); return; } ix = 0; iy = r; yy = r; nn = 0; px[0] = ix; py[0] = iy; cx = (y+iy)*vp.xs + (x+ix); if (x+ix>=0 && x+ix=0 && y+iy=ix) { ix = ix + ux; dt = -ux/yy; dy = ix*dt; yy = yy + dy; iy = (int)yy; if (x+ix>=0 && x+ix=0 && y+iy=0 && x+ix=0 && y+iy=0 && x+ix=0 && y+iy=0 && x+ix=0 && y+iy=0 && x+ix=0 && y+iy=0 && x+ix=0 && y+iy=0 && x+ix=0 && y+iy=0 && x+ix=0 && y+iy void MSGraph_Circle3D(MSGraph vp, Vector<> ox, Vector<> ex, int rr, int cc, int mode=OFF) 機能:3D的な円の描画. 引数:vp -- 操作対象となるグラフィックデータ構造体. ox -- 円の中心の座標ベクトル. ex -- 円の中心の法線ベクトル. rr -- 円の半径. cc -- 線の濃度. mode -- ON なら円の内部の vp.zero〜cc-1 をccで塗りつぶす. 戻り値:なし */ template void MSGraph_Circle3D(MSGraph vp, Vector<> ox, Vector<> ex, int rr, int cc, int mode=OFF) { MSGraph xp(2*rr+3, 2*rr+3); if (xp.gp==NULL) return; Vector<> oz((xp.xs-1)/2., (xp.ys-1)/2., 0.0); MSGraph_Circle(xp, rr+1, rr+1, rr, cc, mode); Local2World(vp, xp, ox, oz, ex); xp.free(); } /** template void MSGraph_Pool(MSGraph vp, Vector<> a, Vector<> b, int rr, int cc) 機能:3D的な円柱の描画.中身はccで塗りつぶされる. 引数:vp -- 操作対象となるグラフィックデータ構造体. a -- 円柱上面の円の中心の座標ベクトル. b -- 円柱底面の円の中心の座標ベクトル. rr -- 円柱の半径. cc -- 線と塗りつぶしの濃度. 戻り値:なし */ template void MSGraph_Pool(MSGraph vp, Vector<> a, Vector<> b, int rr, int cc) { int i, cz; Vector<> ox, oz; MSGraph xp, pp; ox = a - b; ox.norm(); xp.set(2*rr+3, 2*rr+3, (int)(ox.n + 0.5)); if (xp.gp==NULL) return; pp = xp; for (i=0; i void MSGraph_Torus(MSGraph vp, Vector<> ox, Vector<> ex, int rr, int ra, int cc) 機能:3D的なトーラスの描画.中身はccで塗りつぶされる. 引数:vp -- 操作対象となるグラフィックデータ構造体. ox -- トーラスの中心の座標ベクトル. ex -- トーラスの中心の法線ベクトル. rr -- トーラスの半径(トーラスの中心から断面の円の中心まで). ra -- トーラスの断面の円の半径 cc -- 線と塗りつぶしの濃度. 戻り値:なし */ template void MSGraph_Torus(MSGraph vp, Vector<> ox, Vector<> ex, int rr, int ra, int cc) { int i, nn; double dt, th, xx, yy, zz, sn, cs; MSGraph xp; Vector<> ve, vo, vz; xp.set(2*(rr+ra)+3, 2*(rr+ra)+3, 2*ra+3); if (xp.gp==NULL) return; nn = (int)(2.0*PI*(rr+ra)*2 + 0.5); dt = 2.0*PI/nn; zz = (xp.zs-1)/2.0; for (i=0; i void MSGraph_Sphere(MSGraph vp, Vector<> a, int r, int cc, int mode=1) 機能:球の描画.境界チェックあり. 引数:vp -- 操作対象となるグラフィックデータ構造体. a -- 球の中心の座標ベクトル. r -- 球の半径. cc -- 線と塗りつぶしの濃度(mode=1のとき) mode -- モード. 1: 円を重ねて球を作る.中身はccで塗りつぶされる. それぞれの円の中心が,領域(境界)内にないと,塗りつぶしに失敗する. -1: 極座標で球を作る.vpとの境界に壁を作る.set_vPoint()を使用. それ以外: 極座標で球を作る.set_vPoint()を使用. 戻り値:なし */ template void MSGraph_Sphere(MSGraph vp, Vector<> a, int r, int cc, int mode=1) { int i, j, k, rx, nn, s=1; // s: 壁を作る場合の境界からの距離 double th, fi, cs, sn, cf, sf, dt; double xx, yy, zz; MSGraph xp; if (mode==1) { xp = vp; for (k=(int)(a.z-r+0.5); k<=(int)(a.z+r+0.5); k++) { if (k>=0 && kvp.zs-s-1) zz = vp.zs - s - 1; } for (j=0; j<=2*nn; j++) { fi = dt*j; cf = cos(fi); sf = sin(fi); xx = r*sn*cf + a.x; yy = r*sn*sf + a.y; if (mode==-1) { if (xxvp.xs-s-1) xx = vp.xs - s - 1; if (yy>vp.ys-s-1) yy = vp.ys - s - 1; } vp.set_vPoint(xx, yy, zz, (T)cc, ON); } } } return; } /** template MSGraph cut_object_MSGraph(MSGraph vp, int mn, int mx, int blank=BOUNDARY_BLANK, bool ecnt=false) 機能:グラフィックデータから mn〜mx の輝度値を持つ部分を抜き出す. 引数:vp -- 操作対象となるグラフィックデータ構造体. mn -- 抜き出す画像の輝度値の最小値. mx -- 抜き出す画像の輝度値の最大値. blank - 境界の余白.余裕. ecnt -- カウンタを使用するかどうか.デフォルトは false 戻り値:抜き出されたグラフィックデータ. rboundメンバに境界情報が入る. */ template MSGraph cut_object_MSGraph(MSGraph vp, int mn, int mx, int blank=BOUNDARY_BLANK, bool ecnt=false) { int i, j, k, n; int cx, cy, cz, cp; int ax, ay, az, ap; MSGraph xp; // = new MSGraph(); xp.init(); RBound rb(vp.xs-1, 0, vp.ys-1, 0, vp.zs-1, 0); RBound rx(0, vp.xs-1, 0, vp.ys-1, 0, vp.zs-1); CVCounter* counter = NULL; if (ecnt) counter = GetUsableGlobalCounter(); if (counter!=NULL) { if (counter->isCanceled()) { xp.state = ERROR_GRAPH_CANCEL; return xp; } counter->SetMax(vp.zs*2); } ap = vp.xs*vp.ys; n = 0; for (k=0; k=(T)mn && vp.gp[ax]<=(T)mx) { n++; rb.fusion(i, j, k); } } } // Counter if (counter!=NULL) { counter->StepIt(); if (counter->isCanceled()) { xp.state = ERROR_GRAPH_CANCEL; return xp; } } } if (n==0) { xp.state = ERROR_GRAPH_NODATA; return xp; } if (blank>0) rb.enlarge(blank); rb.commonarea(rx); xp.set(rb.xmax-rb.xmin+1, rb.ymax-rb.ymin+1, rb.zmax-rb.zmin+1, vp.zero, vp.base, vp.RZxy); if (xp.isNull()) { xp.state = ERROR_GRAPH_MEMORY; return xp; } xp.rbound = rb; xp.min = (T)mx; xp.max = (T)mn; xp.color = vp.color; cp = xp.xs*xp.ys; for (k=0; k=(T)mn && vp.gp[ax]<=(T)mx) { xp.gp[cx] = vp.gp[ax]; xp.max = Max(xp.max, xp.gp[cx]); xp.min = Min(xp.min, xp.gp[cx]); } } } // Counter if (counter!=NULL) { counter->StepIt(); if (counter->isCanceled()) { xp.state = ERROR_GRAPH_CANCEL; return xp; } } } xp.rbound.cutdown(vp.rbound); return xp; } /** template MSGraph cut_object_MSGraph(MSGraph vp, int mn, int mx, RBound rbound, int blank=BOUNDARY_BLANK, bool ecnt=false) 機能:グラフィックデータから rboundの範囲で mn〜mx の輝度値を持つ部分を抜き出す. 引数:vp ---- 操作対象となるグラフィックデータ構造体. mn ---- 抜き出す画像の輝度値の最小値. mx ---- 抜き出す画像の輝度値の最大値. rbound - 切り抜き対象の範囲 blank -- 境界の余白.余裕. ecnt --- カウンタを使用するかどうか.デフォルトは false 戻り値:抜き出されたグラフィックデータ. rboundメンバに境界情報が入る. */ template MSGraph cut_object_MSGraph(MSGraph vp, int mn, int mx, RBound rbound, int blank=BOUNDARY_BLANK, bool ecnt=false) { int i, j, k, n; int cx, cy, cz, cp; int ax, ay, az, ap; MSGraph xp; // = new MSGraph(); xp.init(); RBound rb(vp.xs-1, 0, vp.ys-1, 0, vp.zs-1, 0); RBound rx(0, vp.xs-1, 0, vp.ys-1, 0, vp.zs-1); CVCounter* counter = NULL; if (ecnt) counter = GetUsableGlobalCounter(); if (counter!=NULL) { if (counter->isCanceled()) { xp.state = ERROR_GRAPH_CANCEL; return xp; } counter->SetMax(vp.zs*2); } rbound.commonarea(rx); ap = vp.xs*vp.ys; n = 0; for (k=rbound.zmin; k<=rbound.zmax; k++) { az = ap*k; for (j=rbound.ymin; j<=rbound.ymax; j++) { ay = az + vp.xs*j; for (i=rbound.xmin; i<=rbound.xmax; i++) { ax = ay + i; if (vp.gp[ax]>=(T)mn && vp.gp[ax]<=(T)mx) { n++; rb.fusion(i, j, k); } } } // Counter if (counter!=NULL) { counter->StepIt(); if (counter->isCanceled()) { xp.state = ERROR_GRAPH_CANCEL; return xp; } } } if (n==0) { xp.state = ERROR_GRAPH_NODATA; return xp; } if (blank>0) rb.enlarge(blank); rb.commonarea(rbound); xp.set(rb.xmax-rb.xmin+1, rb.ymax-rb.ymin+1, rb.zmax-rb.zmin+1, vp.zero, vp.base, vp.RZxy); if (xp.isNull()) { xp.state = ERROR_GRAPH_MEMORY; return xp; } xp.rbound = rb; xp.min = (T)mx; xp.max = (T)mn; xp.color = vp.color; cp = xp.xs*xp.ys; for (k=0; k=(T)mn && vp.gp[ax]<=(T)mx) { xp.gp[cx] = vp.gp[ax]; xp.max = Max(xp.max, xp.gp[cx]); xp.min = Min(xp.min, xp.gp[cx]); } } } // Counter if (counter!=NULL) { counter->StepIt(); if (counter->isCanceled()) { xp.state = ERROR_GRAPH_CANCEL; return xp; } } } xp.rbound.cutdown(vp.rbound); return xp; } /** template MSGraph cut_object_MSGraph(MSGraph vp, RBound rb, bool ecnt=false) 機能:グラフィックデータから rbound の範囲を抜き出す. 引数:vp -- 操作対象となるグラフィックデータ構造体. rb -- 切り抜き対象の範囲 ecnt - カウンタを使用するかどうか.デフォルトは false 戻り値:抜き出されたグラフィックデータ. rboundメンバに境界情報が入る. */ template MSGraph cut_object_MSGraph(MSGraph vp, RBound rb, bool ecnt=false) { int i, j, k; int cx, cy, cz, cp; int ax, ay, az, ap; MSGraph xp; // = new MSGraph(); xp.init(); RBound rx(0, vp.xs-1, 0, vp.ys-1, 0, vp.zs-1); CVCounter* counter = NULL; if (ecnt) counter = GetUsableGlobalCounter(); if (counter!=NULL) { if (counter->isCanceled()) { xp.state = ERROR_GRAPH_CANCEL; return xp; } counter->SetMax(vp.zs*2); } rb.commonarea(rx); xp.set(rb.xmax-rb.xmin+1, rb.ymax-rb.ymin+1, rb.zmax-rb.zmin+1, vp.zero, vp.base, vp.RZxy); if (xp.isNull()) { xp.state = ERROR_GRAPH_MEMORY; return xp; } xp.rbound = rb; xp.color = vp.color; ap = vp.xs*vp.ys; cp = xp.xs*xp.ys; for (k=0; kStepIt(); if (counter->isCanceled()) { xp.state = ERROR_GRAPH_CANCEL; return xp; } } } xp.rbound.cutdown(vp.rbound); return xp; } /** template MSGraph zoom_MSGraph(MSGraph vp, float zm, int mode=ON) 機能: 2Dグラフィックデータ拡大する. 引数: vp -- 変換する Vector型単純グラフィックデータ. zm -- 倍率. mode -- モード. ON: 補間拡大 その他: 単純拡大 戻り値:拡大したグラフィックデータ. */ template MSGraph zoom_MSGraph(MSGraph vp, float zm, int mode=ON) { int xss, yss, ps, pz, py; MSGraph vx; vx.init(); if (vp.gp==NULL) { vx.state = ERROR_GRAPH_NODATA; return vx; } if (zm==0.0) { vx.state = ERROR_GRAPH_IVDARG; return vx; } else if (zm<0.0) zm = -zm; xss = (int)(vp.xs*zm) + 1; yss = (int)(vp.ys*zm) + 1; vx.set(xss, yss, vp.zs); if (vx.isNull()) return vx; vx.color = vp.color; ps = xss*yss; if (mode==ON) { int ii, jj, kk, ll; float xx, yy, al, bt; for(int k=0; k=vp.xs) ii = vp.xs - 1; if (jj>=vp.ys) jj = vp.ys - 1; kk = ii + 1; ll = jj + 1; if (kk>=vp.xs) kk = vp.xs - 1; if (ll>=vp.ys) ll = vp.ys - 1; if (xx>=0.) al = xx - ii; else al = 0.; if (yy>=0.) bt = yy - jj; else bt = 0.; vx.gp[py+i] = (T)((1.-al)*(1.-bt)*vp.point(ii, jj, k) + al*(1.-bt)*vp.point(kk, jj, k) + (1.-al)*bt*vp.point(ii, ll, k) + al*bt*vp.point(kk, ll, k) + 0.5); } } } } else { int ii, jj; for(int k=0; k MSGraph reduce_MSGraph(MSGraph vp, float rc, int mode=ON) { int xss, yss, ps, pz, py; MSGraph vx; vx.init(); if (vp.gp==NULL) { vx.state = ERROR_GRAPH_NODATA; return vx; } if (rc==0.0) { vx.state = ERROR_GRAPH_IVDARG; return vx; } else if (rc<0.0) rc = -rc; xss = (int)(vp.xs/rc); yss = (int)(vp.ys/rc); vx.set(xss, yss, vp.zs); if (vx.isNull()) return vx; vx.color = vp.color; ps = xss*yss; if (mode==ON) { int ii, jj, kk, ll, ss, nn; for(int z=0; z=vp.xs) ii = vp.xs - 1; if (jj>=vp.ys) jj = vp.ys - 1; ss = nn = 0; for(int l=jj; l=vp.ys) ll = vp.ys - 1; for(int k=ii; k=vp.xs) kk = vp.xs - 1; ss += vp.point(kk, ll, z); nn++; } } vx.gp[py+i] = ss/nn; } } } } else { int ii, jj; for(int k=0; k=vp.xs) ii = vp.xs - 1; if (jj>=vp.ys) jj = vp.ys - 1; vx.gp[py+i] = vp.point(ii, jj, k); } } } } return vx; } /** template MSGraph rotate_MSGraph(MSGraph vp, int xs, int ys, double cst, double snt, int mode=ON) 反時計回りに画像を回転させる */ template MSGraph rotate_MSGraph(MSGraph vp, int xs, int ys, double cst, double snt, int mode=ON) { MSGraph vs; T pt; int i, j, m, n; int ps, px, pz; double u, t, x, y, a, b; vs.set(xs, ys, vp.zs, vp.zero, vp.base); if (vs.isNull()) return vs; vs.color = vp.color; ps = vs.xs*vs.ys; for (int k=0; k=vp.xs || j<0 || j>=vp.ys) { pt = vs.zero; } else { if (mode==ON) { if (a>=0.) a = a - i; else a = 0.; if (b>=0.) b = b - j; else b = 0.; m = i + 1; n = j + 1; if (m>=vp.xs) m = vp.xs - 1; if (n>=vp.ys) n = vp.ys - 1; pt = (T)((1.-a)*(1.-b)*vp.point(i, j, k) + (1.-a)*b*vp.point(i, n, k) + a*(1.-b)*vp.point(m, j, k) + a*b*vp.point(m, n, k) + 0.5); } else { pt = vp.point(i, j, k); } } vs.gp[px+ii] = pt; } } } return vs; } /** */ template MSGraph rotate_MSGraph(MSGraph vp, double th, int mode=ON) { MSGraph vs; double cst = cos(th); double snt = cos(th); int xys = (int)sqrt(vp.xs*vp.xs+vp.ys*vp.ys) + 1; vs = rotate_MSGraph(vp, xys, xys, cst, snt, mode); return vs; } /** template MSGraph x_reverse_MSGraph(MSGraph vp) 機能:グラフィックデータの x軸を反転させる. 引数:vp -- 操作対象となるグラフィックデータ構造体. 戻り値:反転したグラフィックデータ. */ template MSGraph x_reverse_MSGraph(MSGraph vp, bool ecnt=false) { int i, j, k, cy, cz; MSGraph wp; CVCounter* counter = NULL; wp.init(); if (ecnt) counter = GetUsableGlobalCounter(); if (counter!=NULL) { if (counter->isCanceled()) { wp.state = ERROR_GRAPH_CANCEL; return wp; } counter->SetMax(vp.zs); } wp.set(vp.xs, vp.ys, vp.zs, vp.zero, vp.base, vp.RZxy); if (wp.isNull()) return wp; wp.color = vp.color; for (k=0; kStepIt(); if (counter->isCanceled()) { wp.state = ERROR_GRAPH_CANCEL; return wp; } } } return wp; } /** template void set_around_MSGraph(MSGraph vp, int cc) 機能:2Dグラフィックデータの縁の部分の輝度値を ccにする. 引数:vp -- 操作対象となるグラフィックデータ構造体. cc -- データの縁に設定する輝度値. 戻り値:なし. */ template void set_around_MSGraph(MSGraph vp, int cc=0, int size=1) { int i, j, px1, px2; /* for (i=0; i MSGraph grab_MSGraph(MSGraph vp, int x1, int y1, int x2, int y2) 機能: MSGraph型データvpの (x1,y1)-(x2,y2)の矩形部分だけを取り出す. (x1,y1)-(x2,y2)が元のデータのサイズを越える場合は,元の データに合わせられる. 引数: vp -- 操作対象グラフィックデータ (x1,y1),(x2,y2) -- 矩形の対角の座標. 戻り値:取り出したグラフィックデータ. bound メンバに切り出した範囲が入る. */ template MSGraph grab_MSGraph(MSGraph vp, int x1, int y1, int x2, int y2, int zs=0, int ze=0) { int i, j, k; int xs, xe, ys, ye; int xsize, ysize, zsize; MSGraph xp; xp.init(); xs = Min(x1, x2); xe = Max(x1, x2); xs = Max(xs, 0); xe = Min(xe, vp.xs-1); ys = Min(y1, y2); ye = Max(y1, y2); ys = Max(ys, 0); ye = Min(ye, vp.ys-1); zs = Max(zs, 0); ze = Min(ze, vp.zs-1); xsize = xe - xs + 1; ysize = ye - ys + 1; zsize = ze - zs + 1; xp.set(xsize, ysize, zsize, vp.zero, vp.base); if (xp.isNull()) return xp; xp.color = vp.color; for (k=0; k int addPaint_MSGraph(MSGraph xp, int x, int y, int mn, int mx, int add, int mode=8) 追加式の 2Dペイント xp の (x, y)座標から,輝度値 mn〜mx の範囲の点に addを加える. 引数: vp -- グラフィックデータ構造体. x -- 塗りつぶしを始める点の X座標. y -- 塗りつぶしを始める点の Y座標. mn -- 塗りつぶされる輝度値の最小値 mx -- 塗りつぶされる輝度値の最大値. add -- 加える輝度値.マイナスでも動作するが,作業領域に注意. mode -- モード.8以上:平面上で 8近傍の塗りつぶし その他:平面上で 4近傍の塗りつぶし 注意:輝度値に,addがプラスの場合はadd以上,または addがマイナスの場合は add+輝度値がプラスになるもの があると誤作動する.作業領域として add〜 を使用する. */ template int addPaint_MSGraph(MSGraph xp, int x, int y, int mn, int mx, int add, int mode=8) { int i, k, cc, cx, st, ed, num=0; if (x<0 || x>=xp.xs || y<0 || y>=xp.ys) return 0; // 左端へ cc = (int)xp.point(x, y); while(x>0) { cx = (int)xp.point(x-1, y); if (cx>mx || cxmx || cx=0 && y-1=mn) { num += addPaint_MSGraph(xp, i, y-1, mn, mx, add, mode); } if (mode>=8) { if (i-1>=0) { cx = (int)xp.point(i-1, y-1); if (cx<=mx && cx>=mn) { num += addPaint_MSGraph(xp, i-1, y-1, mn, mx, add, mode); } } if (i+1=mn) { num += addPaint_MSGraph(xp, i+1, y-1, mn, mx, add, mode); } } } } // 1ライン下へ if (y+1>=0 && y+1=mn) { num += addPaint_MSGraph(xp, i, y+1, mn, mx, add, mode); } if (mode>=8) { if (i-1>=0) { cx = (int)xp.point(i-1, y+1); if (cx<=mx && cx>=mn) { num += addPaint_MSGraph(xp, i-1, y+1, mn, mx, add, mode); } } if (i+1=mn) { num += addPaint_MSGraph(xp, i+1, y+1, mn, mx, add, mode); } } } } } return num; } /** template MSGraph Density_Mask(MSGraph vp, float rate, int mode=8, int work_color=0) 密度マスク 区画の中で縁に接して,かつ zeroでない画素の数を数え,全体の画素の 数に対して rate 以上の比率の場合,その画素パターンを返す. rateに満たない場合は zero で埋められたパターンを返す. work_color -- 作業用輝度値 */ template MSGraph Density_Mask(MSGraph vp, float rate, int mode=8, int work_color=0) { MSGraph pp; int ps = vp.xs*vp.ys; if (work_color==0) { if (vp.max==0 || vp.max==vp.zero) vp.get_minmax(); work_color = vp.max + 1; } pp.mimicry(vp); if ((int)(ps*rate+0.5)==ps) { int eflg = OFF; for (int i=0; i xp; xp.set(vp.xs+2, vp.ys+2, 1, vp.zero, vp.base, vp.RZxy); xp.color = vp.color; for (int j=0; jnn) { pp.state = 0; pp.clear(); } xp.free(); return pp; } /** template MSGraph Density_Filter(MSGraph vp, int size, float rate, int mode=8, int work_color=0) 密度フィルター 画像データの密度マスクを適用して返す. size -- マスクのサイズ rate -- 密度の閾値 mode -- 近傍(4 or 8) work_color -- 作業用輝度値 */ template MSGraph Density_Filter(MSGraph vp, int size, float rate, int mode=8, int work_color=0) { MSGraph pp, xp, wp; int hsize = size/2; if (work_color==0) { if (vp.max==0 || vp.max==vp.zero) vp.get_minmax(); work_color = vp.max + 1; } if (hsize==0) hsize = 1; size = hsize*2 + 1; pp.set(size, size, 1, vp.zero, vp.base); wp.mimicry(vp); for (int j=hsize; j(pp, rate, mode, work_color); if (xp.state!=0) { for (int m=-hsize; m<=hsize; m++) { int wx = (m+j)*wp.xs + i; int xx = (m+hsize)*xp.xs + hsize; for (int n=-hsize; n<=hsize; n++) { if (xp.gp[xx+n]!=vp.zero) { wp.gp[wx+n] = xp.gp[xx+n]; } } } } xp.free(); } } pp.free(); return wp; } /** template void delete_noise_MSGraph(MSGraph vp, int size, int mode=8, int work_color=0) 機能: 背景 vp.zero に浮かぶ孤立ノイズを除去する. -work_color〜-1, work_color〜 を作業領域として使用するので,この区間にデータがある場合は誤作動する. */ template void delete_noise_MSGraph(MSGraph vp, int size, int mode=8, int work_color=0) { int i, j, k; int num, ps ,pp; ps = vp.xs*vp.ys; if (work_color==0) { if (vp.max==0 || vp.max==vp.zero) vp.get_minmax(); work_color = vp.max + 1; } for(j=0; jvp.zero && vp.gp[i+pp]=work_color) { vp.gp[k] = vp.zero; n++; if (n>=num) break; } } } else { int n = 0; for (k=i+pp; k=work_color) { vp.gp[k] = -vp.gp[k]; n++; if (n>=num) break; } } } } } } for (i=0; i