1 package JSci.instruments; 2 3 import JSci.swing.*; 4 5 import java.awt.*; 6 import java.awt.event.*; 7 import java.awt.geom.*; 8 import javax.swing.*; 9 import javax.swing.text.*; 10 import javax.swing.event.*; 11 import java.util.*; 12 import java.text.*; 13 import java.awt.image.*; 14 15 18 public class PTCroquetteCross extends Polygon implements Control { 19 20 private int crossHW=3; 21 private int crossL=32; 22 private Point2D position = new Point2D.Double(); 23 private Point intPosition = new Point(); 24 private double z = 0.0; 25 private boolean dragging = true; 26 private Rectangle bbox = null; 27 private Color color; 28 29 35 public PTCroquetteCross(int l, int hw, Point p, Color col) { 36 super(new int[] {-hw,hw,hw,l,l,hw,hw,-hw,-hw,-l,-l,-hw}, 37 new int[] {-l,-l,-hw,-hw,hw,hw,l,l,hw,hw,-hw,-hw}, 38 12 39 ); 40 crossHW=hw; 41 crossL=l; 42 intPosition.setLocation(p); 43 translate(intPosition.x,intPosition.y); 44 position.setLocation(p); 45 color=col; 46 z = 0.0; 47 dragging = false; 48 calibrating=false; 49 } 50 51 52 53 54 55 private void FFT(double []x,double []y,int d) 56 { 57 int n,m,l,le,le1,i,j,ip,nv2,nm1,k; 58 double ur,ui,wr,wi,tr,ti,sr,si; 59 60 n=x.length; 61 m=2; 62 switch (n) { 63 case 4:m=2;break; 64 case 8:m=3;break; 65 case 16:m=4;break; 66 case 32:m=5;break; 67 case 64:m=6;break; 68 case 128:m=7;break; 69 case 256:m=8;break; 70 case 512:m=9;break; 71 case 1024:m=10;break; 72 case 2048:m=11;break; 73 } 74 le1=n; 75 for (l=1;l<=m;l++) 76 { 77 le=le1; 78 le1=le/2; 79 ur=1.0;ui=0.0; 80 wr=Math.cos(Math.PI/le1);wi=d*Math.sin(Math.PI/le1); 81 for (j=0;j<le1;j++) 82 { 83 for (i=j;i<n;i+=le) 84 { 85 ip=i+le1; 86 tr=x[i]+x[ip];ti=y[i]+y[ip]; 87 sr=x[i]-x[ip];si=y[i]-y[ip]; 88 x[ip]=sr*ur-si*ui;y[ip]=sr*ui+si*ur; 89 x[i]=tr;y[i]=ti; 90 } 91 tr=ur*wr-ui*wi; 92 ui=ur*wi+ui*wr; 93 ur=tr; 94 } 95 96 } 97 98 nv2=n/2; 99 nm1=n-1; 100 j=0; 101 for (i=0;i<nm1;i++) 102 { 103 if (i<j) 104 { 105 tr=x[j];ti=y[j]; 106 x[j]=x[i];y[j]=y[i]; 107 x[i]=tr;y[i]=ti; 108 } 109 k=nv2; 110 while (k<j+1) {j=j-k;k/=2;} 111 j+=k; 112 } 113 114 } 115 116 117 int fromImg(byte c) { if (c>=0) return (int)c; else return (int)(256+c); } 118 119 private Point2D findJNIXY(Image f,int x0,int y0,int l,int w) { 120 double t,tx,ty,frp,fip,frm,fim,tr,ti; 121 double h[],v[]; 122 int j,k,mx,my; 123 124 h=new double[2*l]; 125 v=new double[2*l]; 126 127 for (j=0;j<2*l;j++) h[j]=v[j]=0.0; 128 for (k=-w;k<w;k++) for (j=0;j<2*l;j++) h[j]+=fromImg(f.getData()[f.getOffset()+x0-l+j+(y0+k)*f.getScansize()]); 129 for (k=0;k<2*l;k++) for (j=-w;j<w;j++) v[k]+=fromImg(f.getData()[f.getOffset()+x0+j+(y0-l+k)*f.getScansize()]); 130 131 FFT(h,v,1); 132 for (j=0;j<=l;j++) { 133 if (j==0) k=0; else k=2*l-j; 134 135 frp=h[j]; fip=v[j]; frm=h[k]; fim=v[k]; 136 137 h[j]=v[j]=h[k]=v[k]=0.0; 138 139 tr=(frp+frm)/2.0; ti=(fip-fim)/2.0; 140 141 t=Math.pow(tr,2)-Math.pow(ti,2); ti=2.0*tr*ti; tr=t; 142 143 h[j]+=tr; v[j]+=ti; 144 h[k]+=tr; v[k]+=-ti; 145 146 tr=(fip+fim)/2.0; ti=-(frp-frm)/2.0; 147 148 t=Math.pow(tr,2)-Math.pow(ti,2); ti=2.0*tr*ti; tr=t; 149 150 h[j]+=-ti; v[j]+=tr; 151 h[k]+=ti; v[k]+=tr; 152 } 153 FFT(h,v,-1); 154 155 tx=h[0];ty=v[0];mx=my=0; 156 for (j=0;j<2*l;j++) { 157 if (h[j]>tx) { tx=h[j]; mx=j; } 158 if (v[j]>ty) { ty=v[j]; my=j; } 159 } 160 161 if (mx>=l) mx-=2*l; 162 if (my>=l) my-=2*l; 163 return new Point2D.Double(mx/2.0+x0,my/2.0+y0); 164 165 } 166 167 168 private double findJNIZ(Image f,int x0,int y0,int l,int w,int n,double []templ) { 169 int j,k; 170 double msd[],s[],mv,c1,c2; 171 int mp; 172 s=new double[l]; 173 for (j=0;j<l;j++) s[j]=0.0; 174 for (k=-w;k<w;k++) for (j=0;j<l;j++) 175 s[j]+= 176 fromImg(f.getData()[f.getOffset()+x0+j+(y0+k)*f.getScansize()])+ 177 fromImg(f.getData()[f.getOffset()+x0-j+(y0+k)*f.getScansize()])+ 178 fromImg(f.getData()[f.getOffset()+x0+k+(y0+j)*f.getScansize()])+ 179 fromImg(f.getData()[f.getOffset()+x0+k+(y0-j)*f.getScansize()]); 180 mv=0.0; 181 for (j=0;j<l;j++) mv+=s[j]; 182 for (j=0;j<l;j++) s[j]/=mv; 183 msd=new double[n]; 184 for (k=0;k<n;k++) { 185 msd[k]=0.0; 186 for (j=0;j<l;j++) msd[k]+=Math.pow(templ[k*l+j]-s[j],2); 187 } 188 mv=msd[4];mp=4; 189 for (k=0;k<n;k++) if (msd[k]<mv) {mv=msd[k];mp=k;} 190 if (mp==0) mp=1; 191 if (mp==n-1) mp=n-2; 192 c1 = (msd[mp+1]-msd[mp-1])/2.0; 193 c2 = msd[mp+1]+msd[mp-1]-2.0*msd[mp]; 194 return mp-c1/c2; 195 } 196 197 void addJNIToTemplate(Image f,int x0,int y0,int l,int w,double []templ,int z) { 198 int j,k; 199 double s[],mv; 200 s=new double[l]; 201 for (j=0;j<l;j++) s[j]=0.0; 202 for (k=-w;k<w;k++) for (j=0;j<l;j++) 203 s[j]+= 204 fromImg(f.getData()[f.getOffset()+x0+j+(y0+k)*f.getScansize()])+ 205 fromImg(f.getData()[f.getOffset()+x0-j+(y0+k)*f.getScansize()])+ 206 fromImg(f.getData()[f.getOffset()+x0+k+(y0+j)*f.getScansize()])+ 207 fromImg(f.getData()[f.getOffset()+x0+k+(y0-j)*f.getScansize()]); 208 mv=0.0; 209 for (j=0;j<l;j++) mv+=s[j]; 210 for (j=0;j<l;j++) s[j]/=mv; 211 for (j=0;j<l;j++) templ[j+l*z]+=s[j]; 212 } 213 214 215 216 217 220 public synchronized void findXY(Image f) { 221 if (dragging) return; 222 setLocation(findJNIXY(f,intPosition.x,intPosition.y,crossL,crossHW)); 223 } 224 225 226 229 public void findZ(Image f) { 230 if (calibrating || dragging || calibration==null) return; 231 z=findJNIZ(f, 232 intPosition.x,intPosition.y, 233 crossL,crossHW, 234 zNum,calibration 235 )*(maxZ-minZ)/zNum+minZ; 236 component.setValue(z); 237 } 238 239 240 243 public synchronized void setDragging(boolean v) { 244 dragging = v; 245 } 246 247 248 251 public boolean isDragging() { 252 return dragging; 253 } 254 255 256 259 public void setBBox(Rectangle r) { 260 bbox=r; 261 } 262 263 264 267 public void setLocation(Point2D p) { 268 Point ip = new Point((int)p.getX(),(int)p.getY()); 269 if (!bbox.contains(getBounds(ip))) return; 270 position.setLocation(p); 271 translate(-intPosition.x+ip.x,-intPosition.y+ip.y); 272 intPosition.setLocation(ip); 273 } 274 275 276 279 public Point2D getLocation() { 280 Point2D r = new Point2D.Double(); 281 r.setLocation(position); 282 return r; 283 } 284 285 288 public double getZ() { 289 return z; 290 } 291 292 293 private Rectangle getBounds(Point p) { 294 return new Rectangle(p.x-crossL,p.y-crossL,2*crossL,2*crossL); 295 } 296 297 298 301 public Rectangle getBounds() { 302 return getBounds(intPosition); 303 } 304 305 306 309 public Color getColor() { 310 return color; 311 } 312 313 314 private CComponent component = new CComponent(); 315 private class CComponent extends JPanel implements ChangeListener { 316 JPointer sliderZero = new JPointer(JPointer.SLIDER_SIMPLE_STOP); 317 JPointer sliderFound = new JPointer(JPointer.SLIDER_SIMPLE_QUADRANGLE); 318 JSliderPlus sliderHolder = new JSliderPlus(JSliderPlus.VERTICAL,0.0,100.0); 319 JLabel calibrImg = new JLabel(); 320 public CComponent() { 321 add(calibrImg); 322 sliderZero.setColor(Color.MAGENTA); 323 sliderFound.setColor(Color.CYAN); 324 sliderHolder.addJPointer(sliderZero); 325 sliderHolder.addJPointer(sliderFound); 326 add(sliderHolder); 327 sliderZero.setEnabled(false); 328 sliderFound.setEnabled(false); 329 } 330 public void setValue(double p) { 331 sliderFound.setValue(p); 332 } 333 public void setMinMax(double a,double b) { 334 sliderHolder.setLimits(a,b); 335 if (Math.abs(b-a)<5.0) { 336 sliderHolder.setMinorTickSpacing(0.5); 337 sliderHolder.setMajorTickSpacing(1.0); 338 } 339 else { 340 sliderHolder.setMinorTickSpacing(5.0); 341 sliderHolder.setMajorTickSpacing(10.0); 342 } 343 } 344 public void stateChanged(ChangeEvent e) { 345 double p=((PositionControl)e.getSource()).getPosition(); 346 sliderZero.setValue(p); 347 } 348 public void updateCalibrationImageLabel() { 349 java.awt.Image img=calibrImg.createImage(createCalibrationImage()); 350 calibrImg.setIcon(new ImageIcon(img)); 351 } 352 } 353 358 public Component getControlComponent() { 359 return component; 360 } 361 362 365 private double [] calibration = null; 366 private boolean calibrating = true; 367 private int zNum,zLevel=-1; 368 private double minZ,maxZ; 369 370 375 public void calibrationStart(int zNum, double minZ, double maxZ) { 376 calibrating = true; 377 this.zNum=zNum; 378 this.minZ=minZ; 379 this.maxZ=maxZ; 380 zLevel=-1; 381 calibration = new double[zNum*crossL]; 382 component.setMinMax(minZ,maxZ); 383 } 384 385 389 synchronized public void calibrationSendImage(Image f) { 390 if (zLevel<0 || zLevel>=zNum) return; 391 addJNIToTemplate(f, 392 intPosition.x,intPosition.y, 393 crossL,crossHW, 394 calibration,zLevel); 395 zLevel=-1; 396 notify(); 397 } 398 399 400 410 synchronized public void calibrationRequest(int zLevel) { 411 this.zLevel = zLevel; 412 } 413 414 415 418 synchronized public void calibrationWait() { 419 while (zLevel>=0) { 420 try { wait(); } catch (InterruptedException e) {} 421 } 422 } 423 424 425 427 public void calibrationEnd() { 428 double s; 429 for (int j=0;j<zNum;j++) { 430 s=0.0; 431 for (int k=0;k<crossL;k++) s+=calibration[j*crossL+k]; 432 for (int k=0;k<crossL;k++) calibration[j*crossL+k]/=s; 433 } 434 calibrating=false; 435 component.updateCalibrationImageLabel(); 436 } 437 438 private ImageProducer createCalibrationImage() { 439 int width=crossL; 440 int height=zNum; 441 byte [] ima = new byte[width*height]; 442 for (int j=0;j<width;j++) for (int k=0;k<height;k++) 443 ima[j+k*width]=(byte)(int)(calibration[j+(height-1-k)*width]*crossL*128.0); 444 byte [] reds = new byte[256]; 445 byte [] greens = new byte[256]; 446 byte [] blues = new byte[256]; 447 for (int j=0;j<256;j++) { reds[j]=greens[j]=blues[j]=(byte)j; } 448 ColorModel icm = new IndexColorModel(8,256,reds,greens,blues); 449 ImageProducer imgsrc=new MemoryImageSource(width,height,icm,ima,0,width); 450 return imgsrc; 451 } 452 453 } 454 | Popular Tags |