/** @brief グラフィック用数学ライブラリ&フィルタ @file gmt.c @version 3.0 @author Fumi.Iseki (C) */ #include "gmt.h" #include "jbxl_state.h" /** WSGraph Laplacian(WSGraph vp, int mode) 2Dグラフィックデータのラプラシアンを計算する. @param vp 計算対象となるグラフィックデータ構造体. @param mode モード. @b 4: 4近傍ラプラシアン @param mode @b 8: 8近傍ラプラシアン @param mode その他: Sobelのラプラシアン(24近傍) @return 処理されたグラフィックデータ. */ WSGraph Laplacian(WSGraph vp, int mode) { int i, j; int da, db, dc, dd, de, df, dg, dh; WSGraph lp; lp = make_WSGraph(vp.xs, vp.ys, 1); if (lp.gp==NULL) return lp; if (vp.gp==NULL) { lp.state = JBXL_GRAPH_NODATA_ERROR; return lp; } if (mode==4) { for (j=1; j1) { //fprintf(stderr,"CURVATURE: z dimension is > 1.\n"); pp.state = JBXL_GRAPH_IVDARG_ERROR; return pp; } pp = make_VSGraph(vp.xs, vp.ys, vp.zs); if (pp.gp==NULL) return pp; px = fxSobel(vp); py = fySobel(vp); pxy = fySobel(px); pxx = fxxSobel(vp); pyy = fyySobel(vp); if (px.gp==NULL||py.gp==NULL||pxy.gp==NULL||pxx.gp==NULL||pyy.gp==NULL) { freeNull(px.gp); freeNull(py.gp); freeNull(pxy.gp); freeNull(pxx.gp); freeNull(pyy.gp); free_VSGraph(&pp); pp.state = JBXL_GRAPH_ERROR; return pp; } for (i=0; i0 && H<0) vp.gp[i] = PEAK; else if (K>0 && H>0) vp.gp[i] = PIT; else if (K<0 && H<0) vp.gp[i] = SADDLE_RIDGE; else if (K<0 && H>0) vp.gp[i] = SADDLE_VALLEY; else if (K>0 && H==0) vp.gp[i] = NONE_SHAPE; else if (K<0 && H==0) vp.gp[i] = MINIMAL; else if (K==0 && H<0) vp.gp[i] = RIDGE; else if (K==0 && H>0) vp.gp[i] = VALLEY; else if (K==0 && H==0) vp.gp[i] = FLAT; } return vp; } /** WSGraph WSCurve(WSGraph gx, int mode, int cc) 曲面の形状をグラフィックデータ(輝度値)に変換する. @param gx 操作対象となる曲面形状情報3の入ったグラフィックデータ. @param mode 輝度値に変換する曲面の形状.指定できる形状は @b ALL, @b FLAT, @b PIT, @b SADDLE_RIDGE, @b SADDLE_VALLEY, @b NONE_SHAPE, @b MINIMAL, @b RIDGE, @b VALLEY, @b PEAK. @n ALLを指定した場合,形状は違った輝度値に変換される. @param cc modeに ALLを指定しなかった場合,指定された曲面をこの輝度値に変換する. @return 曲面の形状情報を代入した sWord型グラフィックデータ. @note FLAT=500, PIT=1000, SADDLE_RIDGE=1500, SADDLE_VALLEY=2000, NONE_SHAPE=2500, MINIMAL=3000, RIDGE=3500, VALLEY=4000, PEAK=4500 */ WSGraph WSCurve(WSGraph gx, int mode, int cc) { int i; FSGraph wp; VSGraph xp; WSGraph vp; memset(&vp, 0, sizeof(WSGraph)); if (gx.gp==NULL) { vp.state = JBXL_GRAPH_NODATA_ERROR; return vp; } wp = W2FSGraph(gx); if (gx.zs<5) xp = curvature(wp); else xp = curvature3D(wp); vp = curv2WSGraph(xp); freeNull(wp.gp); freeNull(xp.gp); if (vp.gp==NULL) return vp; if (mode==ALL) { for (i=0; i2) { //fprintf(stderr, "IMASK: mismach mask dimension %d %d\n", xp.zs, mask.mode); vp.state = JBXL_GRAPH_IVDARG_ERROR; return vp; } nf = mask.nfact; ms = mask.msize; if (mask.mode==2) { sw = 0; pm = ms*ms; } else { sw = 1; pm = ms*ms*ms; } mz = Min(ms, xp.zs); kc = pm/2; zc = mz/2; xc = ms/2; xs = xp.xs; ps = xp.xs*xp.ys; min = SINTMAX; for (i=0; i=bc) pp.gp[i] = 1; else pp.gp[i] = 0; } for (k=1; k<=vp.zs; k++) { for (j=1; j<=vp.ys; j++) { df = vp.xs; for (i=1; i<=vp.xs; i++) { if (Vxt(pp, i, j, k)!=0) df = df + 1; else df = 0; Vxt(pp, i, j, k) = df*df; } } } for (k=1; k<=vp.zs; k++) { for (j=1; j<=vp.ys; j++) { db = vp.xs; for (i=vp.xs; i>=1; i--) { if (Vxt(pp, i, j, k)!=0) db = db + 1; else db = 0; Vxt(pp, i, j, k) = Min(Vxt(pp, i, j, k), db*db); } } } buff = make_ISGraph(vp.ys, 1, 1); for (k=1; k<=vp.zs; k++) { for (i=1; i<=vp.xs; i++) { for (j=1; j<=vp.ys; j++) { Lxt(buff, j) = Vxt(pp, i, j, k); } for (j=1; j<=vp.ys; j++) { d = Lxt(buff, j); if (d!=0) { rmax = (int)sqrt((double)d) + 1; rstart = Min(rmax, j-1); rend = Min(rmax, vp.ys-j); for (l=-rstart; l<=rend; l++) { w = Lxt(buff, j+l) + l*l; if (w32767) { fprintf(stderr,"EUCLID_DISTANCE: WARNING: distance is too long = %d!\n",pp.gp[i]); } } free(pp.gp); return wp; } /** int out_round(WSGraph vp, int x, int y, IRBound* rb, int mode) 2Dグラフィックデータ構造体vpの(x,y)にあるオブジェクトの周囲長を得る. @param vp 操作対象となる 2D グラフィックデータ構造体. @param x, y 情報を得たいオブジェクトの左上縁の座標. この座標の左横に情報を得たいオブジェクトの一部が在ってはいけない. @param[out] rb オブジェクトの情報を格納する境界構造体.@n rb->xmin: オブジェクトの x座標の最小値.@n rb->xmax: オブジェクトの x座標の最大値.@n rb->ymin: オブジェクトの y座標の最小値.@n rb->ymax: オブジェクトの y座標の最大値.@n rb->misc: 8近傍モード時の斜めの距離の回数. 周囲長を 戻り値 + rb->misc*{sqrt(2.)-1} で計算する場合もある. @param mode モード.@b 8: 8近傍探索.@b その他: 4近傍探索. @return オブジェクトの周囲長.ただし,8近傍モードの場合,斜めの距離も1と数える.rb->misc 参照. @attention 注: 1ドットの長さは1と数える.プログラム中で EGMAX+1 を使用. */ int out_round(WSGraph vp, int x, int y, IRBound* rb, int mode) { int i, j, sp, cp, w, ll, ss; int xx, yy, vx, vy, ix, eflg=OFF; int r8[8]={-1, 1, -1, -1, 1, -1, 1, 1}; int r4[8]={ 0, 1, -1, 0, 0, -1, 1, 0}; int* cc; if (vp.gp==NULL) return JBXL_GRAPH_IVDARG_ERROR; i = y*vp.xs + x; rb->xmax = rb->xmin = x; rb->ymax = rb->ymin = y; sp = cp = i; ss = 0; ll = 0; vx = 1; vy = 0; if (vp.gp[sp]==0 || sp==0) { //fprintf(stderr,"OUT_ROUND: irregular start point!! sp = %d\n",sp); return JBXL_GRAPH_IVDPARAM_ERROR; } if (mode==8){ ix = 8; cc = r8; } else if (mode==4) { ix = 4; cc = r4; } else { //fprintf(stderr,"OUT_ROUND: invalid mode = %d!!\n",mode); return JBXL_GRAPH_IVDMODE_ERROR; } 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]!=0) { 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==0) { eflg = ON; 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==OFF); if (mode==4) ss = 0; (rb->xmax)++; (rb->ymax)++; (rb->xmin)--; (rb->ymin)--; rb->misc = ss; return ll; }