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 java.io.*; 9 import java.text.*; 10 import javax.swing.*; 11 import javax.swing.event.*; 12 import javax.swing.border.*; 13 14 15 public class PTCroquette extends ImageFilterAdapter implements ParticleTracker, ROI { 16 17 18 public static int CROSS_L=32; 19 20 public static int CROSS_H=3; 21 22 public static double CALIBR_STEP=0.5; 23 24 public static int CALIBR_AVR=3; 25 26 public String getName() { return "PT 3D symmetric"; }; 27 28 private PTCroquetteCross cross1,cross2; 29 private PositionControl pc = null; 30 31 private ParticleTrackerListener ptl = null; 32 public void setListener(ParticleTrackerListener ptl) { 33 this.ptl=ptl; 34 } 35 36 38 public PTCroquette(PositionControl p) { 39 cross1 = new PTCroquetteCross(CROSS_L,CROSS_H,new Point(50,50),Color.MAGENTA); 40 cross2 = new PTCroquetteCross(CROSS_L,CROSS_H,new Point(50,120),Color.CYAN); 41 pc = p; 42 controlComponent = new PTControlComponent( new Control[] {pc,cross1,cross2} ); 43 pc.addChangeListener((ChangeListener)cross1.getControlComponent()); 44 pc.addChangeListener((ChangeListener)cross2.getControlComponent()); 45 controlComponent = new PTControlComponent( new Control[] {pc,cross1,cross2} ); 46 } 47 48 51 public void filter(Image f) { 52 cross1.setBBox(new Rectangle(new Point(0,0),getSize())); 53 cross2.setBBox(new Rectangle(new Point(0,0),getSize())); 54 cross1.findXY(f); 55 cross2.findXY(f); 56 if (!calibrating) { 57 cross1.findZ(f); 58 cross2.findZ(f); 59 } 60 else { 61 cross1.calibrationSendImage(f); 62 cross2.calibrationSendImage(f); 63 } 64 if (ptl!=null) 65 ptl.receivePosition(f.getTimeStamp(), 66 new int[] {0,1}, 67 new double[] {cross1.getLocation().getX(),cross2.getLocation().getX()}, 68 new double[] {cross1.getLocation().getY(),cross2.getLocation().getY()}, 69 new double[] {cross1.getZ()-pc.getPosition(),cross2.getZ()-pc.getPosition()} 70 ); 71 } 72 73 74 75 76 77 78 public Shape getShape() { return cross2; } 79 80 public void paint(java.awt.Graphics g) { 81 Graphics2D g2= (Graphics2D)g; 82 g2.setColor(cross1.getColor()); 83 g2.draw(cross1); 84 Point2D p = cross1.getLocation(); 85 g2.drawString("Ref",(int)p.getX()+CROSS_H,(int)p.getY()+CROSS_L); 86 g2.setColor(cross2.getColor()); 87 g2.draw(cross2); 88 } 89 90 private Component mouseComponent; 91 92 96 public void setComponent(Component c) { 97 mouseComponent=c; 98 c.addMouseListener(new MouseHandler()); 99 c.addMouseMotionListener(new MouseMotionHandler()); 100 c.addMouseWheelListener(new MouseWheelHandler()); 101 } 102 103 104 105 106 107 108 109 private boolean calibrating = false; 110 111 private void doCalibration(int zNum,int lNum,double minZ,double maxZ) { 112 calibrating=true; 113 cross1.calibrationStart(zNum,minZ,maxZ); 114 cross2.calibrationStart(zNum,minZ,maxZ); 115 for (int j=0;j<zNum;j++) { 116 pc.setPosition(j*(maxZ-minZ)/zNum+minZ); 117 pc.sleep(); 118 for (int k=0;k<lNum;k++) { 119 cross1.calibrationRequest(j); 120 cross2.calibrationRequest(j); 121 cross1.calibrationWait(); 122 cross2.calibrationWait(); 123 } 124 } 125 cross1.calibrationEnd(); 126 cross2.calibrationEnd(); 127 calibrating=false; 128 } 129 130 131 132 133 134 135 136 private PTControlComponent controlComponent; 137 138 141 public Component getFilterControlComponent() { return controlComponent; } 142 143 private class PTControlComponent extends JPanel { 144 145 private JButton calibrButton = new JButton("Calibrate"); 146 147 private JButton setMin = new JButton("Set min"); 148 private JButton setMax = new JButton("Set max"); 149 private JSpinner calibrMin = 150 new JSpinner(new SpinnerNumberModel(0.0,pc.getMinimum(),pc.getMaximum(),0.1)); 151 private JSpinner calibrMax = 152 new JSpinner(new SpinnerNumberModel(0.0,pc.getMinimum(),pc.getMaximum(),0.1)); 153 154 public PTControlComponent(Control [] cc) { 155 super(); 156 for (int j=0;j<cc.length;j++) add(cc[j].getControlComponent()); 157 add(calibrButton); 158 159 calibrButton.addActionListener(new ActionListener() { 160 public void actionPerformed(ActionEvent e) { 161 Thread calibrThrd = new Thread (new Runnable () { 162 public void run() { 163 calibrButton.setEnabled(false); 164 pc.getControlComponent().setEnabled(false); 165 double min = ((Double )calibrMin.getValue()).doubleValue(); 166 double max = ((Double )calibrMax.getValue()).doubleValue(); 167 doCalibration((int)Math.round((max-min)/CALIBR_STEP),CALIBR_AVR,min,max); 168 pc.getControlComponent().setEnabled(true); 169 calibrButton.setEnabled(true); 170 } 171 }); 172 calibrThrd.start(); 173 } 174 }); 175 176 setMin.addActionListener(new ActionListener() { 177 public void actionPerformed(ActionEvent e) { 178 calibrMin.setValue(new Double (pc.getPosition())); 179 } 180 }); 181 setMax.addActionListener(new ActionListener() { 182 public void actionPerformed(ActionEvent e) { 183 calibrMax.setValue(new Double (pc.getPosition())); 184 } 185 }); 186 JPanel calibrPanel1 = new JPanel(); 187 calibrPanel1.setLayout( new BorderLayout()); 188 JPanel calibrPanel2 = new JPanel(); 189 calibrPanel2.setLayout( new BorderLayout()); 190 calibrPanel1.add("North",setMax); 191 calibrPanel2.add("North",calibrMax); 192 calibrPanel1.add("South",setMin); 193 calibrPanel2.add("South",calibrMin); 194 add(calibrPanel1); 195 add(calibrPanel2); 196 } 197 } 198 199 200 201 202 203 204 205 206 private Point refPos = new Point(); 207 208 209 private class MouseHandler extends MouseAdapter { 210 public void mousePressed(MouseEvent event) { 211 if (cross1.getBounds().contains(event.getPoint())) { 212 cross1.setDragging(true); 213 refPos=new Point((int)cross1.getLocation().getX(),(int)cross1.getLocation().getY()); 214 } 215 else if (cross2.getBounds().contains(event.getPoint())) { 216 cross2.setDragging(true); 217 refPos=new Point((int)cross2.getLocation().getX(),(int)cross2.getLocation().getY()); 218 } 219 refPos.translate(-event.getPoint().x,-event.getPoint().y); 220 } 221 public void mouseReleased(MouseEvent event) { 222 cross1.setDragging(false); 223 cross2.setDragging(false); 224 } 225 } 226 227 private class MouseMotionHandler extends MouseMotionAdapter { 228 public void mouseMoved(MouseEvent event) { 229 if ( 230 cross1.getBounds().contains(event.getPoint()) || 231 cross2.getBounds().contains(event.getPoint()) 232 ) 233 mouseComponent.setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR)); 234 else 235 mouseComponent.setCursor(Cursor.getDefaultCursor()); 236 } 237 public void mouseDragged(MouseEvent event) { 238 if (cross1.isDragging()) cross1.setLocation(new Point(event.getPoint().x+refPos.x,event.getPoint().y+refPos.y)); 239 if (cross2.isDragging()) cross2.setLocation(new Point(event.getPoint().x+refPos.x,event.getPoint().y+refPos.y)); 240 } 241 } 242 243 private class MouseWheelHandler implements MouseWheelListener { 244 public void mouseWheelMoved(MouseWheelEvent e) { 245 if (calibrating) return; 246 double p=pc.getPosition(); 247 p-=e.getWheelRotation()*0.1; 248 pc.setPosition(p); 249 } 250 } 251 252 253 254 257 public static void main(String args[]) { 258 PositionControl pc = new DummyPositionControl() { 259 protected void doSetPosition(double p) { 260 Simulated.z=p; 261 super.doSetPosition(p); 262 } 263 }; 264 Simulated.z=pc.getPosition(); 265 PTCroquette filter = new PTCroquette(pc); 266 ImageSource source = new Simulated(); 267 Player player = new Player(); 268 player.addROI(filter); 269 source.setSink(filter); 270 filter.setSink(player); 271 player.start(); 272 273 final NumberFormat formatter = NumberFormat.getNumberInstance(); 274 { formatter.setMaximumFractionDigits(3); 275 formatter.setMinimumFractionDigits(1); 276 formatter.setMinimumIntegerDigits(1); 277 formatter.setMaximumIntegerDigits(4); 278 } 279 ParticleTrackerListener ptl = new ParticleTrackerListener() { 280 public void receivePosition(long time,int[] n,double[] x,double[] y,double[] z) { 281 System.out.println(time+" "+x[0]+" "+y[0]+" "+z[0]+" "+x[1]+" "+y[1]+" "+z[1]); 282 } 283 }; 284 filter.setListener(ptl); 285 286 287 288 } 289 290 291 } 292 293 294 295 296 297 298 301 302 303 306 class Simulated implements ImageSource,Runnable { 307 308 309 310 private Dimension dim = new Dimension(600,500); 311 312 public Simulated() { 313 Thread t = new Thread (this); 314 t.setDaemon(true); 315 t.start(); 316 } 317 318 private ImageSink sink; 319 322 public void setSink(ImageSink fs) { 323 if (sink!=fs) { 324 sink=fs; 325 sink.setSource(this); 326 } 327 } 328 329 public void run() { 330 int num = 0; 331 while (true) { 332 Image f = getImage(); 333 if (sink!=null) sink.receive(f); 334 try { Thread.sleep(100); } 335 catch (InterruptedException e) {} 336 } 337 } 338 339 340 public int getWidth() { return dim.width; } 341 342 343 public int getHeight() { return dim.height; } 344 345 346 public Dimension getSize() { return dim; } 347 348 350 public Component getControlComponent() { 351 JPanel p = new JPanel(); 352 p.setLayout(new BorderLayout()); 353 final JButton oscillButton = new JButton("Oscillate"); 354 oscillButton.addActionListener(new ActionListener() { 355 public void actionPerformed(ActionEvent e) { 356 boolean state = ! Simulated.getOscillating(); 357 Simulated.setOscillating(state); 358 if (state) oscillButton.setText("Stop"); 359 else oscillButton.setText("Oscillate"); 360 } 361 }); 362 p.add(BorderLayout.NORTH,new JLabel("Test")); 363 p.add(BorderLayout.SOUTH,oscillButton); 364 Border etched = BorderFactory.createEtchedBorder(); 365 Border titled = BorderFactory.createTitledBorder(etched,"source"); 366 p.setBorder(titled); 367 return p; 368 } 369 370 371 373 public static double z; 374 private long num=0; 375 376 private double theta = 0.0, vs,vc,dh; 377 private final double R=100.0; 378 private double f(double x) { 379 return 1.0/(1.0-Math.pow(x,2)+Math.pow(x,4)); 380 } 381 private double g(double x,double y) { 382 return f(Math.sqrt(Math.pow(x-vc,2)+Math.pow(y-vs,2))/(5.0+(z+dh)/4.0)); 383 } 384 385 private Image getImage() { 386 double x1,y1,z1,x2,y2,z2; 387 vs=0.0; 388 theta+=0.04; 389 final byte[] ba = new byte[600*500]; 390 for (int j=0;j<500*600;j++) ba[j]=0; 391 vc=R*Math.cos(theta); 392 if (oscillate) dh=Math.sin(theta*1.3); 393 else dh=0.0; 394 for (int j=170;j<430;j++) 395 for (int k=320;k<380;k++) 396 ba[j+k*600]=(byte)(160.0*g(j-300.0,k-350.0)); 397 x1=300.0+vc;y1=350;z1=dh; 398 theta+=2.0; 399 vc=R*Math.cos(theta); 400 theta-=2.0; 401 if (oscillate) dh=Math.cos(theta*1.3); 402 else dh=0.0; 403 for (int j=170;j<430;j++) 404 for (int k=120;k<180;k++) 405 ba[j+k*600]=(byte)(100.0*g(j-300.0,k-150.0)); 406 x2=300.0+vc;y2=150;z2=dh; 407 408 final long t = System.currentTimeMillis(); 409 final Dimension dim = new Dimension(getWidth(),getHeight()); 410 Image f = new Image() { 411 public byte[] getData() { return ba; } 412 public Dimension getSize() { return dim; } 413 public long getTimeStamp() { return t; } 414 }; 415 416 System.out.println("#Simulated: "+num+" "+ 417 +x1+" "+y1+" "+z1+" "+ 418 x2+" "+y2+" "+z2 419 ); 420 421 return f; 422 } 423 424 static private boolean oscillate; 425 static public void setOscillating(boolean o) {oscillate=o;} 426 static public boolean getOscillating() {return oscillate;} 427 428 } 429 | Popular Tags |