001/* 002 * $Id: ScatterDisplay.java,v 1.40 2011/03/24 16:06:32 davep Exp $ 003 * 004 * This file is part of McIDAS-V 005 * 006 * Copyright 2007-2011 007 * Space Science and Engineering Center (SSEC) 008 * University of Wisconsin - Madison 009 * 1225 W. Dayton Street, Madison, WI 53706, USA 010 * https://www.ssec.wisc.edu/mcidas 011 * 012 * All Rights Reserved 013 * 014 * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and 015 * some McIDAS-V source code is based on IDV and VisAD source code. 016 * 017 * McIDAS-V is free software; you can redistribute it and/or modify 018 * it under the terms of the GNU Lesser Public License as published by 019 * the Free Software Foundation; either version 3 of the License, or 020 * (at your option) any later version. 021 * 022 * McIDAS-V is distributed in the hope that it will be useful, 023 * but WITHOUT ANY WARRANTY; without even the implied warranty of 024 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 025 * GNU Lesser Public License for more details. 026 * 027 * You should have received a copy of the GNU Lesser Public License 028 * along with this program. If not, see http://www.gnu.org/licenses. 029 */ 030 031 032package edu.wisc.ssec.mcidasv.control; 033 034import java.awt.BorderLayout; 035import java.awt.Color; 036import java.awt.Component; 037import java.awt.Container; 038import java.awt.FlowLayout; 039import java.awt.GridLayout; 040import java.awt.event.ActionEvent; 041import java.awt.event.ActionListener; 042import java.awt.geom.Rectangle2D; 043import java.net.URL; 044import java.rmi.RemoteException; 045import java.util.ArrayList; 046import java.util.List; 047 048import javax.swing.ButtonGroup; 049import javax.swing.ImageIcon; 050import javax.swing.JComponent; 051import javax.swing.JPanel; 052import javax.swing.JRadioButton; 053import javax.swing.JToggleButton; 054import javax.swing.border.CompoundBorder; 055import javax.swing.border.EmptyBorder; 056import javax.swing.border.LineBorder; 057 058import visad.AxisScale; 059import visad.BaseColorControl; 060import visad.CellImpl; 061import visad.CoordinateSystem; 062import visad.Data; 063import visad.DelaunayCustom; 064import visad.DisplayEvent; 065import visad.DisplayListener; 066import visad.FieldImpl; 067import visad.FlatField; 068import visad.FunctionType; 069import visad.Gridded2DSet; 070import visad.Gridded3DSet; 071import visad.Integer1DSet; 072import visad.Linear2DSet; 073import visad.LinearLatLonSet; 074import visad.RealTupleType; 075import visad.MathType; 076import visad.RealType; 077import visad.SampledSet; 078import visad.ScalarMap; 079import visad.Set; 080import visad.SetType; 081import visad.UnionSet; 082import visad.VisADException; 083import visad.data.mcidas.BaseMapAdapter; 084import visad.georef.MapProjection; 085import visad.georef.TrivialMapProjection; 086 087import ucar.unidata.data.DataAlias; 088import ucar.unidata.data.DataChoice; 089import ucar.unidata.data.DataSelection; 090import ucar.unidata.data.grid.GridUtil; 091import ucar.unidata.idv.DisplayConventions; 092import ucar.unidata.idv.control.ColorTableWidget; 093import ucar.unidata.idv.control.DisplayControlImpl; 094import ucar.unidata.ui.colortable.ColorTableManager; 095import ucar.unidata.util.ColorTable; 096import ucar.unidata.util.LogUtil; 097import ucar.unidata.util.Range; 098import ucar.unidata.view.geoloc.MapProjectionDisplay; 099import ucar.unidata.view.geoloc.MapProjectionDisplayJ3D; 100import ucar.visad.display.DisplayMaster; 101import ucar.visad.display.LineDrawing; 102import ucar.visad.display.MapLines; 103import ucar.visad.display.RGBDisplayable; 104import ucar.visad.display.RubberBandBox; 105import ucar.visad.display.XYDisplay; 106 107import edu.wisc.ssec.mcidasv.data.hydra.CurveDrawer; 108import edu.wisc.ssec.mcidasv.data.hydra.HistogramField; 109import edu.wisc.ssec.mcidasv.data.hydra.HydraRGBDisplayable; 110import edu.wisc.ssec.mcidasv.data.hydra.MultiSpectralData; 111import edu.wisc.ssec.mcidasv.data.hydra.SubsetRubberBandBox; 112import edu.wisc.ssec.mcidasv.data.hydra.LongitudeLatitudeCoordinateSystem; 113 114public class ScatterDisplay extends DisplayControlImpl { 115 116 private Container container; 117 private FlatField X_field; 118 private FlatField Y_field; 119 private DisplayMaster scatterMaster = null; 120 121 private DisplayMaster dspMasterX; 122 private DisplayMaster dspMasterY; 123 124 private HistogramField histoField; 125 126 private FlatField mask_field; 127 private float[][] mask_range; 128 private float[][] scatterFieldRange; 129 private Data X_data; 130 private Data Y_data; 131 private String X_name; 132 private String Y_name; 133 134 private ScatterDisplayable scatterMarkDsp; 135 136 private RGBDisplayable maskX; 137 138 private RGBDisplayable maskY; 139 140 private BoxCurveSwitch boxCurveSwitch; 141 142 public DataChoice dataChoiceX = null; 143 144 public DataChoice dataChoiceY = null; 145 146 public DataSelection dataSelectionX = null; 147 148 public DataSelection dataSelectionY = null; 149 150 JComponent ctwCompX; 151 152 JComponent ctwCompY; 153 154 ColorTableWidget ctw; 155 156 int n_selectors = 3; 157 158 List<ScatterBoxSelector> scatterBoxSelectors = new ArrayList<ScatterBoxSelector>(); 159 160 List<ScatterCurveSelector> scatterCurveSelectors = new ArrayList<ScatterCurveSelector>(); 161 162 List<ImageBoxSelector> imageXBoxSelectors = new ArrayList<ImageBoxSelector>(); 163 164 List<ImageBoxSelector> imageYBoxSelectors = new ArrayList<ImageBoxSelector>(); 165 166 List<ImageCurveSelector> imageXCurveSelectors = new ArrayList<ImageCurveSelector>(); 167 168 List<ImageCurveSelector> imageYCurveSelectors = new ArrayList<ImageCurveSelector>(); 169 170 JToggleButton[] selectorToggleButtons = new JToggleButton[n_selectors]; 171 Color[] selectorColors = new Color[] {Color.magenta, Color.green, Color.blue}; 172 float[][] maskColorPalette = new float[][] {{0.8f,0f,0f},{0f,0.8f,0f},{0.8f,0f,0.8f}}; 173 float[][] markColorPalette = new float[][] {{1f,0.8f,0f,0f},{1f,0f,0.8f,0f},{1f,0.8f,0f,0.8f}}; 174 175 boolean selectByCurve = false; 176 177 public ScatterDisplay() { 178 super(); 179 setHelpUrl("idv.controls.misc.scatteranalysiscontrol"); 180 } 181 182 183 @Override public boolean init(List choices) throws VisADException, RemoteException { 184 if ((dataChoiceX != null) && (dataChoiceY != null)) { 185 setupFromUnpersistence(); 186 } 187 else { 188 setup(); 189 } 190 191 mask_field = new FlatField( 192 new FunctionType(((FunctionType)X_field.getType()).getDomain(), RealType.Generic), 193 X_field.getDomainSet()); 194 195 int len = X_field.getDomainSet().getLength(); 196 mask_range = new float[1][len]; 197 for (int t=0; t<len; t++) { 198 mask_range[0][t] = Float.NaN; 199 } 200 mask_range[0][0] = 0; //- field should not be all missing 201 mask_field.setSamples(mask_range, false); 202 203 try { 204 histoField = new HistogramField(X_field, Y_field, mask_field, 100, 10); 205 } 206 catch (Exception e) { 207 e.printStackTrace(); 208 } 209 210 Range rangeX = getImageRange(X_field); 211 Range rangeY = getImageRange(Y_field); 212 ColorTable clrTableX = getColorTable(X_field); 213 ColorTable clrTableY = getColorTable(Y_field); 214 215 dspMasterX = makeImageDisplay(getDataProjection(X_field), X_field, mask_field, 216 rangeX, clrTableX); 217 218 dspMasterY = makeImageDisplay(getDataProjection(Y_field), Y_field, mask_field, 219 rangeY, clrTableY); 220 221 dspMasterX.addDisplayListener(new DisplayListener() { 222 @Override public void displayChanged(final DisplayEvent e) { 223 double[] xProjection = dspMasterX.getProjectionMatrix(); 224 double[] yProjection = dspMasterY.getProjectionMatrix(); 225 if (xProjection.equals(yProjection)) 226 return; 227 228 try { 229 dspMasterY.setProjectionMatrix(xProjection); 230 } catch (Exception ex) { 231 LogUtil.logException("dspMasterX.displayChanged", ex); 232 } 233 } 234 }); 235 236 dspMasterY.addDisplayListener(new DisplayListener() { 237 @Override public void displayChanged(final DisplayEvent e) { 238 double[] xProjection = dspMasterX.getProjectionMatrix(); 239 double[] yProjection = dspMasterY.getProjectionMatrix(); 240 if (yProjection.equals(xProjection)) 241 return; 242 243 try { 244 dspMasterX.setProjectionMatrix(yProjection); 245 } catch (Exception ex) { 246 LogUtil.logException("dspMasterX.displayChanged", ex); 247 } 248 } 249 }); 250 251 X_name = ((((FunctionType)X_field.getType()).getFlatRange().getRealComponents())[0]).getName(); 252 Y_name = ((((FunctionType)Y_field.getType()).getFlatRange().getRealComponents())[0]).getName(); 253 254 Grid2DReadoutProbe probeX = new Grid2DReadoutProbe(X_field, dspMasterX); 255 Grid2DReadoutProbe probeY = new Grid2DReadoutProbe(Y_field, dspMasterY); 256 probeX.doMakeProbe(Color.red, dspMasterX); 257 probeY.doMakeProbe(Color.red, dspMasterY); 258 259 ImageControl dCntrl = new ImageControl((HydraRGBDisplayable)dspMasterX.getDisplayables(0), getDisplayConventions()); 260 ctw = new ColorTableWidget(dCntrl, 261 ColorTableManager.getManager(), clrTableX, rangeX); 262 ctwCompX = ctw.getLegendPanel(BOTTOM_LEGEND); 263 dCntrl.ctw = ctw; 264 265 dCntrl = new ImageControl((HydraRGBDisplayable)dspMasterY.getDisplayables(0), getDisplayConventions()); 266 ctw = new ColorTableWidget(dCntrl, 267 ColorTableManager.getManager(), clrTableY, rangeY); 268 ctwCompY = ctw.getLegendPanel(BOTTOM_LEGEND); 269 dCntrl.ctw = ctw; 270 271 return true; 272 } 273 274 public void setup() throws VisADException, RemoteException { 275 dataSelectionX = getDataSelection(); 276 dataChoiceX = getDataChoice(); 277 X_data = dataChoiceX.getData(dataSelectionX); 278 279 if (X_data instanceof FlatField) { 280 X_field = (FlatField) X_data; 281 } else if (X_data instanceof FieldImpl) { 282 X_field = (FlatField) ((FieldImpl)X_data).getSample(0); 283 } 284 285 this.popupDataDialog("select Y Axis field", container, false, null); 286 287 288 dataSelectionY = getDataSelection(); 289 dataChoiceY = getDataChoice(); 290 291 dataSelectionY.setGeoSelection(dataSelectionX.getGeoSelection()); 292 293 Y_data = dataChoiceY.getData(dataSelectionY); 294 295 if (Y_data instanceof FlatField) { 296 Y_field = (FlatField) Y_data; 297 } else if (X_data instanceof FieldImpl) { 298 Y_field = (FlatField) ((FieldImpl)Y_data).getSample(0); 299 } 300 301 int[] Xlens = ((Gridded2DSet) X_field.getDomainSet()).getLengths(); 302 int[] Ylens = ((Gridded2DSet) Y_field.getDomainSet()).getLengths(); 303 304 if ( (X_field.getLength() != Y_field.getLength()) || 305 (Xlens[0] != Ylens[0]) || (Xlens[1] != Ylens[1]) ) 306 { 307 Y_field = (FlatField) Y_field.resample(X_field.getDomainSet()); 308 } 309 } 310 311 public void setupFromUnpersistence() throws VisADException, RemoteException { 312 X_data = dataChoiceX.getData(dataSelectionX); 313 if (X_data instanceof FlatField) { 314 X_field = (FlatField) X_data; 315 } else if (X_data instanceof FieldImpl) { 316 X_field = (FlatField) ((FieldImpl)X_data).getSample(0); 317 } 318 319 Y_data = dataChoiceY.getData(dataSelectionY); 320 if (Y_data instanceof FlatField) { 321 Y_field = (FlatField) Y_data; 322 } else if (X_data instanceof FieldImpl) { 323 Y_field = (FlatField) ((FieldImpl)Y_data).getSample(0); 324 } 325 } 326 327 @Override protected void popupDataDialog(final String dialogMessage, 328 Component from, boolean multiples, 329 List categories) { 330 331 List<DataChoice> choices = selectDataChoices(dialogMessage, from, 332 multiples, categories); 333 if ((choices == null) || (choices.size() == 0)) { 334 return; 335 } 336 final List clonedList = 337 DataChoice.cloneDataChoices((List)choices.get(0)); 338 dataSelection = ((DataChoice) clonedList.get(0)).getDataSelection(); 339 //- don't do this in a separate thread like the IDV does. 340 //- We want the dataChoice list updated before return. 341 try { 342 addNewData(clonedList); 343 } catch (Exception exc) { 344 logException("Selecting new data", exc); 345 } 346 } 347 348 349 @Override public void initDone() { 350 try { 351 DisplayMaster master = makeScatterDisplay(); 352 for (int k=0; k<n_selectors; k++) { 353 scatterBoxSelectors.add(new ScatterBoxSelector(master, selectorColors[k], (float)k)); 354 scatterCurveSelectors.add(new ScatterCurveSelector(master, selectorColors[k], (float)k)); 355 } 356 master.draw(); 357 358 for (int k=0; k<n_selectors; k++) { 359 SubsetRubberBandBox X_subsetBox = 360 new SubsetRubberBandBox(getIsLatLon(X_field), X_field, 361 ((MapProjectionDisplayJ3D)dspMasterX).getDisplayCoordinateSystem(), 1, false); 362 X_subsetBox.setColor(selectorColors[k]); 363 ImageBoxSelector markX = new ImageBoxSelector(X_subsetBox, X_field.getDomainSet(), dspMasterX, 364 selectorColors[k], (float)k+1); 365 366 SubsetRubberBandBox Y_subsetBox = 367 new SubsetRubberBandBox(getIsLatLon(Y_field), Y_field, 368 ((MapProjectionDisplayJ3D)dspMasterY).getDisplayCoordinateSystem(), 1, false); 369 Y_subsetBox.setColor(selectorColors[k]); 370 ImageBoxSelector markY = new ImageBoxSelector(Y_subsetBox, Y_field.getDomainSet(), dspMasterY, 371 selectorColors[k], (float)k+1); 372 373 markX.setOther(markY); 374 markY.setOther(markX); 375 imageXBoxSelectors.add(markX); 376 imageYBoxSelectors.add(markY); 377 } 378 379 for (int k=0; k<n_selectors; k++) { 380 CurveDrawer curveDraw = new CurveDrawer(RealType.Longitude, RealType.Latitude, 1); 381 curveDraw.setColor(selectorColors[k]); 382 curveDraw.setLineWidth(2); 383 ImageCurveSelector curveX = new ImageCurveSelector(curveDraw, X_field, dspMasterX, selectorColors[k], (float) k+1); 384 curveX.setActive(false); 385 curveDraw.addAction(curveX); 386 curveX.setVisible(false); 387 dspMasterX.addDisplayable(curveDraw); 388 389 curveDraw = new CurveDrawer(RealType.Longitude, RealType.Latitude, 1); 390 curveDraw.setColor(selectorColors[k]); 391 curveDraw.setLineWidth(2); 392 ImageCurveSelector curveY = new ImageCurveSelector(curveDraw, Y_field, dspMasterY, selectorColors[k], (float) k+1); 393 curveY.setActive(false); 394 curveDraw.addAction(curveY); 395 curveY.setVisible(false); 396 dspMasterY.addDisplayable(curveDraw); 397 398 curveX.setOther(curveY); 399 curveY.setOther(curveX); 400 imageXCurveSelectors.add(curveX); 401 imageYCurveSelectors.add(curveY); 402 } 403 404 for (int k=0; k<n_selectors; k++) { 405 JToggleButton jtog = selectorToggleButtons[k]; 406 407 jtog.addActionListener(new ActionListener() { 408 @Override public void actionPerformed(ActionEvent e) { 409 int idx = Integer.valueOf(e.getActionCommand()); 410 try { 411 for (int i=0; i<n_selectors; i++) { 412 ScatterBoxSelector boxSel = (ScatterBoxSelector) scatterBoxSelectors.get(i); 413 ImageBoxSelector imageXbox = (ImageBoxSelector) imageXBoxSelectors.get(i); 414 ImageBoxSelector imageYbox = (ImageBoxSelector) imageYBoxSelectors.get(i); 415 ScatterCurveSelector curveSel = (ScatterCurveSelector) scatterCurveSelectors.get(i); 416 ImageCurveSelector imageXcurve = (ImageCurveSelector) imageXCurveSelectors.get(i); 417 ImageCurveSelector imageYcurve = (ImageCurveSelector) imageYCurveSelectors.get(i); 418 419 if (i == idx) { 420 if (!selectorToggleButtons[i].isSelected()) { 421 boxSel.setActive(false); 422 boxSel.setVisible(false); 423 boxSel.reset(); 424 imageXbox.setActive(false); 425 imageXbox.setVisible(false); 426 imageXbox.reset(); 427 imageYbox.setActive(false); 428 imageYbox.setVisible(false); 429 imageYbox.reset(); 430 431 curveSel.setActive(false); 432 curveSel.setVisible(false); 433 curveSel.reset(); 434 imageXcurve.setActive(false); 435 imageXcurve.setVisible(false); 436 imageXcurve.reset(); 437 imageYcurve.setActive(false); 438 imageYcurve.setVisible(false); 439 imageYcurve.reset(); 440 } 441 boxSel.setActive(!getSelectByCurve()); 442 boxSel.setVisible(!getSelectByCurve()); 443 imageXbox.setActive(!getSelectByCurve()); 444 imageXbox.setVisible(!getSelectByCurve()); 445 imageYbox.setActive(!getSelectByCurve()); 446 imageYbox.setVisible(!getSelectByCurve()); 447 448 curveSel.setActive(getSelectByCurve()); 449 curveSel.setVisible(getSelectByCurve()); 450 imageXcurve.setActive(getSelectByCurve()); 451 imageXcurve.setVisible(getSelectByCurve()); 452 imageYcurve.setActive(getSelectByCurve()); 453 imageYcurve.setVisible(getSelectByCurve()); 454 } 455 else { 456 selectorToggleButtons[i].setSelected(false); 457 boxSel.setActive(false); 458 boxSel.setVisible(false); 459 imageXbox.setActive(false); 460 imageXbox.setVisible(false); 461 imageYbox.setActive(false); 462 imageYbox.setVisible(false); 463 curveSel.setActive(false); 464 curveSel.setVisible(false); 465 imageXcurve.setActive(false); 466 imageXcurve.setVisible(false); 467 imageYcurve.setActive(false); 468 imageYcurve.setVisible(false); 469 } 470 } 471 } 472 catch (Exception exc) { 473 System.out.println(exc); 474 } 475 }}); 476 477 ScatterBoxSelector boxSel = (ScatterBoxSelector) scatterBoxSelectors.get(k); 478 ImageBoxSelector imageXbox = (ImageBoxSelector) imageXBoxSelectors.get(k); 479 ImageBoxSelector imageYbox = (ImageBoxSelector) imageYBoxSelectors.get(k); 480 ScatterCurveSelector curveSel = (ScatterCurveSelector) scatterCurveSelectors.get(k); 481 ImageCurveSelector imageXcurve = (ImageCurveSelector) imageXCurveSelectors.get(k); 482 ImageCurveSelector imageYcurve = (ImageCurveSelector) imageYCurveSelectors.get(k); 483 484 if (k == 0) { 485 jtog.setSelected(true); 486 boxSel.setActive(!getSelectByCurve()); 487 boxSel.setVisible(!getSelectByCurve()); 488 imageXbox.setActive(!getSelectByCurve()); 489 imageXbox.setVisible(!getSelectByCurve()); 490 imageYbox.setActive(!getSelectByCurve()); 491 imageYbox.setVisible(!getSelectByCurve()); 492 493 curveSel.setActive(getSelectByCurve()); 494 curveSel.setVisible(getSelectByCurve()); 495 imageXcurve.setActive(getSelectByCurve()); 496 imageXcurve.setVisible(getSelectByCurve()); 497 imageYcurve.setActive(getSelectByCurve()); 498 imageYcurve.setVisible(getSelectByCurve()); 499 } 500 else { 501 boxSel.setActive(false); 502 boxSel.setVisible(false); 503 imageXbox.setActive(false); 504 imageXbox.setVisible(false); 505 imageYbox.setActive(false); 506 imageYbox.setVisible(false); 507 curveSel.setActive(false); 508 curveSel.setVisible(false); 509 imageXcurve.setActive(false); 510 imageXcurve.setVisible(false); 511 imageYcurve.setActive(false); 512 imageYcurve.setVisible(false); 513 } 514 } 515 } 516 catch (Exception e) { 517 e.printStackTrace(); 518 } 519 } 520 521 public DisplayMaster makeScatterDisplay() throws VisADException, RemoteException { 522 523 ScatterDisplayable scatterDsp = new ScatterDisplayable("scatter", 524 RealType.getRealType("mask"), markColorPalette, false); 525 float[] valsX = X_field.getFloats(false)[0]; 526 float[] valsY = Y_field.getFloats(false)[0]; 527 Integer1DSet set = new Integer1DSet(valsX.length); 528 FlatField scatter = new FlatField( 529 new FunctionType(RealType.Generic, 530 new RealTupleType(RealType.XAxis, RealType.YAxis, RealType.getRealType("mask"))), set); 531 float[] mask = new float[valsX.length]; 532 for (int k=0; k<mask.length; k++) mask[k] = 0; 533 scatterFieldRange = new float[][] {valsX, valsY, mask}; 534 scatter.setSamples(scatterFieldRange); 535 scatterDsp.setPointSize(2f); 536 scatterDsp.setRangeForColor(0,n_selectors); 537 538 float[] xRange = minmax(valsX); 539 float[] yRange = minmax(valsY); 540 541 scatterDsp.setData(scatter); 542 543 scatterMarkDsp = new ScatterDisplayable("scatter", 544 RealType.getRealType("mask"), markColorPalette, false); 545 set = new Integer1DSet(2); 546 scatter = new FlatField( 547 new FunctionType(RealType.Generic, 548 new RealTupleType(RealType.XAxis, RealType.YAxis, RealType.getRealType("mask"))), set); 549 scatterMarkDsp.setData(scatter); 550 scatterMarkDsp.setPointSize(2f); 551 scatterMarkDsp.setRangeForColor(0,n_selectors); 552 553 DisplayMaster master = scatterMaster; 554 ((XYDisplay)master).showAxisScales(true); 555 AxisScale scaleX = ((XYDisplay)master).getXAxisScale(); 556 scaleX.setTitle(X_name); 557 AxisScale scaleY = ((XYDisplay)master).getYAxisScale(); 558 scaleY.setTitle(Y_name); 559 560 ((XYDisplay)master).setXRange((double)xRange[0], (double)xRange[1]); 561 ((XYDisplay)master).setYRange((double)yRange[0], (double)yRange[1]); 562 master.addDisplayable(scatterDsp); 563 master.addDisplayable(scatterMarkDsp); 564 565 return master; 566 } 567 568 569 @Override public Container doMakeContents() { 570 JPanel pane = new JPanel(new GridLayout(1,3)); 571 572 Component[] comps = new Component[] {null, null, null}; 573 comps[0] = dspMasterX.getComponent(); 574 comps[1] = dspMasterY.getComponent(); 575 comps[2] = getScatterTabComponent(); 576 577 JPanel panelX = new JPanel(new BorderLayout()); 578 panelX.setBorder(new EmptyBorder(4,4,4,4)); 579 panelX.add(comps[0], BorderLayout.CENTER); 580 panelX.add(ctwCompX, BorderLayout.SOUTH); 581 582 JPanel panelY = new JPanel(new BorderLayout()); 583 panelY.setBorder(new EmptyBorder(4,4,4,4)); 584 panelY.add(comps[1], BorderLayout.CENTER); 585 panelY.add(ctwCompY, BorderLayout.SOUTH); 586 587 JPanel panelS = new JPanel(new BorderLayout()); 588 panelS.setBorder(new EmptyBorder(4,4,4,4)); 589 panelS.add(comps[2], BorderLayout.CENTER); 590 591 pane.add(panelX); 592 pane.add(panelY); 593 pane.add(panelS); 594 595 596 JPanel buttonPanel = new JPanel(); 597 buttonPanel.setLayout(new FlowLayout()); 598 JRadioButton boxSelect = new JRadioButton("Box"); 599 boxSelect.setSelected(true); 600 JRadioButton curveSelect = new JRadioButton("Curve"); 601 ButtonGroup buttonGroup = new ButtonGroup(); 602 buttonGroup.add(boxSelect); 603 buttonGroup.add(curveSelect); 604 buttonPanel.add(boxSelect); 605 buttonPanel.add(curveSelect); 606 607 boxCurveSwitch = new BoxCurveSwitch(); 608 boxSelect.addActionListener(boxCurveSwitch); 609 curveSelect.addActionListener(boxCurveSwitch); 610 611 612 JPanel toggleButtonPanel = new JPanel(new FlowLayout()); 613 for (int k=0; k<n_selectors; k++) { 614 JToggleButton jtog = 615 new JToggleButton( 616 new ImageIcon(getClass().getResource("/edu/wisc/ssec/mcidasv/resources/icons/buttons/subset12.jpg"))); 617 jtog.setBorder(new CompoundBorder(new LineBorder(selectorColors[k],2), new EmptyBorder(4,4,4,4))); 618 jtog.setActionCommand(String.valueOf(k)); 619 toggleButtonPanel.add(jtog); 620 selectorToggleButtons[k] = jtog; 621 } 622 623 buttonPanel.add(toggleButtonPanel); 624 625 //-container = pane; 626 JPanel new_pane = new JPanel(new BorderLayout()); 627 new_pane.add(pane, BorderLayout.CENTER); 628 new_pane.add(buttonPanel, BorderLayout.SOUTH); 629 container = new_pane; 630 return container; 631 } 632 633 634// @Override public void doRemove() throws VisADException, RemoteException { 635// super.doRemove(); 636// } 637 638 639 protected Component getScatterTabComponent() { 640 try { 641 scatterMaster = new XYDisplay("Scatter", RealType.XAxis, RealType.YAxis); 642 } catch (Exception e) { 643 e.printStackTrace(); 644 } 645 return scatterMaster.getComponent(); 646 } 647 648 public DisplayMaster makeImageDisplay(MapProjection mapProj, FlatField image, 649 FlatField mask_image, Range imageRange, ColorTable colorTable) 650 throws VisADException, RemoteException { 651 MapProjectionDisplayJ3D mapProjDsp; 652 DisplayMaster dspMaster; 653 654 mapProjDsp = new MapProjectionDisplayJ3D(MapProjectionDisplay.MODE_2Din3D); 655 mapProjDsp.enableRubberBanding(false); 656 dspMaster = mapProjDsp; 657 mapProjDsp.setMapProjection(mapProj); 658 659 RealType imageRangeType = 660 (((FunctionType)image.getType()).getFlatRange().getRealComponents())[0]; 661 662 boolean alphaflag = false; 663 HydraRGBDisplayable imageDsp = new HydraRGBDisplayable("image", imageRangeType, null, alphaflag, null); 664 665 imageDsp.setData(image); 666 dspMaster.addDisplayable(imageDsp); 667 addMapDisplayables(mapProjDsp); 668 669 if (mask_image != null) { 670 RGBDisplayable maskDsp = 671 new ScatterDisplayable("mask", RealType.Generic, maskColorPalette, false); 672 maskDsp.setData(mask_image); 673 maskDsp.setRangeForColor(0, n_selectors-1); 674 dspMaster.addDisplayable(maskDsp); 675 } 676 677 dspMaster.draw(); 678 679 ScalarMap colorMap = imageDsp.getColorMap(); 680 colorMap.setRange(imageRange.getMin(), imageRange.getMax()); 681 BaseColorControl clrCntrl = (BaseColorControl) colorMap.getControl(); 682 float[][] ct = colorTable.getColorTable(); 683 684 if ( !(alphaflag) && (ct.length == 4) ) { 685 float[][] new_ct = new float[3][]; 686 new_ct[0] = ct[0]; 687 new_ct[1] = ct[1]; 688 new_ct[2] = ct[2]; 689 ct = new_ct; 690 } 691 692 clrCntrl.setTable(ct); 693 694 return dspMaster; 695 } 696 697 public Range getImageRange(FlatField image) 698 throws VisADException, RemoteException { 699 DisplayConventions dc = getDisplayConventions(); 700 Range[] range = GridUtil.fieldMinMax(image); 701 Range imageRange = range[0]; 702 RealType imageRangeType = 703 (((FunctionType)image.getType()).getFlatRange().getRealComponents())[0]; 704 String canonicalName = DataAlias.aliasToCanonical(imageRangeType.getName()); 705 Range dfltRange = dc.getParamRange(canonicalName, null); 706 707 if (dfltRange == null) { 708 imageRange = range[0]; 709 } 710 else if ((imageRange.getMax() - imageRange.getMin()) < (dfltRange.getMax() - dfltRange.getMin())) { 711 } 712 else { 713 imageRange = dfltRange; 714 } 715 return imageRange; 716 } 717 718 public ColorTable getColorTable(FlatField image) 719 throws VisADException, RemoteException { 720 RealType imageRangeType = 721 (((FunctionType)image.getType()).getFlatRange().getRealComponents())[0]; 722 DisplayConventions dc = getDisplayConventions(); 723 return dc.getParamColorTable(imageRangeType.getName()); 724 } 725 726 727 public MapProjection getDataProjection(FlatField image) 728 throws VisADException, RemoteException { 729 MapProjection mp = null; 730 //- get MapProjection from incoming image. If none, use default method 731 FunctionType fnc_type = (FunctionType) image.getType(); 732 RealTupleType rtt = fnc_type.getDomain(); 733 CoordinateSystem cs = rtt.getCoordinateSystem(); 734 Set domainSet = image.getDomainSet(); 735 736 if (cs instanceof visad.CachingCoordinateSystem) { 737 cs = ((visad.CachingCoordinateSystem)cs).getCachedCoordinateSystem(); 738 } 739 740 if (cs instanceof MapProjection) { 741 return (MapProjection) cs; 742 } 743 else if (cs instanceof LongitudeLatitudeCoordinateSystem) { 744 Rectangle2D rect = MultiSpectralData.getLonLatBoundingBox(image); 745 try { 746 mp = new LambertAEA(rect); 747 } catch (Exception e) { 748 System.out.println(" getDataProjection"+e); 749 } 750 return mp; 751 } 752 753 float minLon = Float.NaN; 754 float minLat = Float.NaN; 755 float delLon = Float.NaN; 756 float delLat = Float.NaN; 757 758 if (domainSet instanceof LinearLatLonSet) { 759 MathType type0 = ((SetType)domainSet.getType()).getDomain().getComponent(0); 760 int latI = RealType.Latitude.equals(type0) ? 0 : 1; 761 int lonI = (latI == 1) ? 0 : 1; 762 763 float[] min = ((LinearLatLonSet)domainSet).getLow(); 764 float[] max = ((LinearLatLonSet)domainSet).getHi(); 765 minLon = min[lonI]; 766 minLat = min[latI]; 767 delLon = max[lonI] - min[lonI]; 768 delLat = max[latI] - min[latI]; 769 770 try { 771 mp = new TrivialMapProjection(RealTupleType.SpatialEarth2DTuple, 772 new Rectangle2D.Float(minLon, minLat, delLon, delLat)); 773 } catch (Exception e) { 774 logException("MultiSpectralControl.getDataProjection", e); 775 } 776 777 return mp; 778 } 779 else if (domainSet instanceof Gridded2DSet) { 780 rtt = ((SetType)domainSet.getType()).getDomain(); 781 rtt = RealTupleType.SpatialEarth2DTuple; 782 if (!(rtt.equals(RealTupleType.SpatialEarth2DTuple) || rtt.equals(RealTupleType.LatitudeLongitudeTuple))) { 783 minLon = -180f; 784 minLat = -90f; 785 delLon = 360f; 786 delLat = 180f; 787 } 788 else { 789 int latI = rtt.equals(RealTupleType.SpatialEarth2DTuple) ? 1 : 0; 790 int lonI = (latI == 1) ? 0 : 1; 791 792 float[] min = ((Gridded2DSet)domainSet).getLow(); 793 float[] max = ((Gridded2DSet)domainSet).getHi(); 794 minLon = min[lonI]; 795 minLat = min[latI]; 796 delLon = max[lonI] - min[lonI]; 797 delLat = max[latI] - min[latI]; 798 } 799 } 800 801 try { 802 mp = new TrivialMapProjection(RealTupleType.SpatialEarth2DTuple, 803 new Rectangle2D.Float(minLon, minLat, delLon, delLat)); 804 } catch (Exception e) { 805 logException("MultiSpectralControl.getDataProjection", e); 806 } 807 808 return mp; 809 } 810 811 public void addMapDisplayables(MapProjectionDisplayJ3D mapProjDsp) 812 throws VisADException, RemoteException { 813 MapLines mapLines = new MapLines("maplines"); 814 URL mapSource = 815 mapProjDsp.getClass().getResource("/auxdata/maps/OUTLSUPU"); 816 try { 817 BaseMapAdapter mapAdapter = new BaseMapAdapter(mapSource); 818 mapLines.setMapLines(mapAdapter.getData()); 819 mapLines.setColor(java.awt.Color.cyan); 820 mapProjDsp.addDisplayable(mapLines); 821 } catch (Exception excp) { 822 System.out.println("Can't open map file " + mapSource); 823 System.out.println(excp); 824 } 825 826 mapLines = new MapLines("maplines"); 827 mapSource = 828 mapProjDsp.getClass().getResource("/auxdata/maps/OUTLSUPW"); 829 try { 830 BaseMapAdapter mapAdapter = new BaseMapAdapter(mapSource); 831 mapLines.setMapLines(mapAdapter.getData()); 832 mapLines.setColor(java.awt.Color.cyan); 833 mapProjDsp.addDisplayable(mapLines); 834 } catch (Exception excp) { 835 System.out.println("Can't open map file " + mapSource); 836 System.out.println(excp); 837 } 838 839 mapLines = new MapLines("maplines"); 840 mapSource = 841 mapProjDsp.getClass().getResource("/auxdata/maps/OUTLHPOL"); 842 try { 843 BaseMapAdapter mapAdapter = new BaseMapAdapter(mapSource); 844 mapLines.setMapLines(mapAdapter.getData()); 845 mapLines.setColor(java.awt.Color.cyan); 846 mapProjDsp.addDisplayable(mapLines); 847 } catch (Exception excp) { 848 System.out.println("Can't open map file " + mapSource); 849 System.out.println(excp); 850 } 851 } 852 853 public boolean getSelectByCurve() { 854 return selectByCurve; 855 } 856 857 private class ScatterDisplayable extends RGBDisplayable { 858 ScatterDisplayable(String name, RealType rgbRealType, float[][] colorPalette, boolean alphaflag) 859 throws VisADException, RemoteException { 860 super(name, rgbRealType, colorPalette, alphaflag); 861 } 862 } 863 864 private class ImageControl extends DisplayControlImpl { 865 HydraRGBDisplayable rgbDisp; 866 DisplayConventions dc; 867 ColorTableWidget ctw; 868 869 ImageControl(HydraRGBDisplayable rgbDisp, DisplayConventions dc) { 870 super(); 871 this.rgbDisp = rgbDisp; 872 this.dc = dc; 873 } 874 875 @Override public void setRange(Range r) throws VisADException, RemoteException { 876 if (r != null) { 877 rgbDisp.setRangeForColor(r.getMin(), r.getMax()); 878 } 879 } 880 881 @Override public DisplayConventions getDisplayConventions() { 882 return dc; 883 } 884 885 @Override public void setColorTable(ColorTable ct) { 886 try { 887 ctw.setColorTable(ct); 888 ScalarMap colorMap = rgbDisp.getColorMap(); 889 BaseColorControl clrCntrl = (BaseColorControl) colorMap.getControl(); 890 891 // Force incoming color dimension to that of the colorMap 892 // 893 int numComps = clrCntrl.getNumberOfComponents(); 894 float[][] clrTable = ct.getColorTable(); 895 float[][] newTable = null; 896 if (numComps != clrTable.length) { 897 if (numComps < clrTable.length) { 898 newTable = new float[numComps][clrTable[0].length]; 899 for (int k=0; k<numComps; k++) { 900 System.arraycopy(clrTable[k], 0, newTable[k], 0, newTable[0].length); 901 } 902 } 903 else if (numComps > clrTable.length) { 904 newTable = new float[numComps][clrTable[0].length]; 905 for (int k=0; k<clrTable.length; k++) { 906 System.arraycopy(clrTable[k], 0, newTable[k], 0, newTable[0].length); 907 } 908 newTable[3] = new float[clrTable[0].length]; 909 } 910 } 911 clrCntrl.setTable(newTable); 912 } 913 catch (Exception e) { 914 LogUtil.logException("Problem changing color table", e); 915 } 916 } 917 } 918 919 private class ImageCurveSelector extends CellImpl implements DisplayListener { 920 boolean init = false; 921 CurveDrawer curveDraw; 922 DisplayMaster dspMaster; 923 FlatField image; 924 Gridded2DSet domainSet; 925 CoordinateSystem cs; 926 int domainLen_0; 927 int domainLen_1; 928 ImageCurveSelector other; 929 UnionSet last_uSet = null; 930 boolean imageLatLon = false; 931 boolean active = true; 932 float maskVal; 933 LineDrawing lastCurve; 934 935 ImageCurveSelector(CurveDrawer curveDraw, FlatField image, DisplayMaster master) 936 throws VisADException, RemoteException { 937 this(curveDraw, image, master, Color.magenta, 1f); 938 } 939 940 ImageCurveSelector(CurveDrawer curveDraw, FlatField image, DisplayMaster master, Color color, float maskVal) 941 throws VisADException, RemoteException { 942 this.curveDraw = curveDraw; 943 this.maskVal = maskVal; 944 dspMaster = master; 945 dspMaster.addDisplayListener(this); 946 this.image = image; 947 domainSet = (Gridded2DSet) image.getDomainSet(); 948 int[] lens = domainSet.getLengths(); 949 domainLen_0 = lens[0]; 950 domainLen_1 = lens[1]; 951 cs = ((FunctionType)image.getType()).getDomain().getCoordinateSystem(); 952 RealTupleType reference = null; 953 if (cs != null) { 954 reference = cs.getReference(); 955 } 956 else { 957 reference = ((SetType)domainSet.getType()).getDomain(); 958 } 959 RealType[] rtypes = reference.getRealComponents(); 960 if (rtypes[0].equals(RealType.Latitude)) imageLatLon = true; 961 lastCurve = new LineDrawing("lastCurve"); 962 lastCurve.setColor(color); 963 lastCurve.setLineWidth(2); 964 master.addDisplayable(lastCurve); 965 } 966 967 @Override public void displayChanged(DisplayEvent de) 968 throws VisADException, RemoteException { 969 if ((de.getId() == DisplayEvent.MOUSE_RELEASED) && (active)) { 970 UnionSet uSet = curveDraw.getCurves(); 971 if (uSet == last_uSet) return; 972 SampledSet[] sets = uSet.getSets(); 973 int s_idx = sets.length-1; 974 float[][] crv; 975 976 if (cs != null) { 977 crv = sets[s_idx].getSamples(); 978 if (imageLatLon) { 979 float[] tmp = crv[0]; 980 crv[0] = crv[1]; 981 crv[1] = tmp; 982 } 983 crv = cs.fromReference(crv); 984 crv = domainSet.valueToGrid(crv); 985 } 986 else { 987 crv = sets[s_idx].getSamples(); 988 crv = domainSet.valueToGrid(crv); 989 } 990 991 float[][] onImage = new float[2][crv[0].length]; 992 int cnt = 0; 993 for (int i=0; i<crv[0].length; i++) { 994 if ( ((crv[0][i] >= 0)&&(crv[0][i] <= domainLen_0)) && 995 ((crv[1][i] >= 0)&&(crv[1][i] <= domainLen_1)) ) { 996 onImage[0][cnt] = crv[0][i]; 997 onImage[1][cnt] = crv[1][i]; 998 cnt++; 999 } 1000 } 1001 uSet = new UnionSet(new SampledSet[] {sets[s_idx]}); 1002 last_uSet = uSet; 1003 lastCurve.setData(last_uSet); 1004 curveDraw.setCurves(uSet); 1005 other.updateCurve(sets[s_idx]); 1006 1007 if (cnt == 0) { 1008 return; 1009 } 1010 1011 float[][] tmp = new float[2][cnt]; 1012 System.arraycopy(onImage[0], 0, tmp[0], 0, cnt); 1013 System.arraycopy(onImage[1], 0, tmp[1], 0, cnt); 1014 onImage = tmp; 1015 1016 float[] minmaxvals = minmax(onImage[0]); 1017 int low_0 = Math.round(minmaxvals[0]); 1018 int hi_0 = Math.round(minmaxvals[1]); 1019 minmaxvals = minmax(onImage[1]); 1020 int low_1 = Math.round(minmaxvals[0]); 1021 int hi_1 = Math.round(minmaxvals[1]); 1022 1023 int len_0 = (hi_0 - low_0) + 1; 1024 int len_1 = (hi_1 - low_1) + 1; 1025 int len = len_0*len_1; 1026 1027 tmp = new float[3][len]; 1028 1029 int num_inside = 0; 1030 for (int j=0; j<len_1; j++) { 1031 for (int i=0; i<len_0; i++) { 1032 int idx = (j+low_1)*domainLen_0 + (i+low_0); 1033 int k = j*len_0 + i; 1034 float x = (float) (i + low_0); 1035 float y = (float) (j + low_1); 1036 if (DelaunayCustom.inside(crv, x, y)) { 1037 tmp[0][k] = scatterFieldRange[0][idx]; 1038 tmp[1][k] = scatterFieldRange[1][idx]; 1039 tmp[2][k] = maskVal; 1040 num_inside++; 1041 } 1042 } 1043 } 1044 len = num_inside; 1045 float[][] markScatter = new float[3][len]; 1046 System.arraycopy(tmp[0], 0, markScatter[0], 0, len); 1047 System.arraycopy(tmp[1], 0, markScatter[1], 0, len); 1048 System.arraycopy(tmp[2], 0, markScatter[2], 0, len); 1049 1050 1051 int last_len = 0; 1052 float[][] lastMark = ((FlatField)scatterMarkDsp.getData()).getFloats(false); 1053 tmp = new float[3][lastMark[0].length]; 1054 for (int k=0; k<lastMark[0].length; k++) { 1055 if (lastMark[2][k] != maskVal) { 1056 tmp[0][last_len] = lastMark[0][k]; 1057 tmp[1][last_len] = lastMark[1][k]; 1058 tmp[2][last_len] = lastMark[2][k]; 1059 last_len++; 1060 } 1061 } 1062 1063 float[][] newMarkScatter = new float[3][len+last_len]; 1064 System.arraycopy(tmp[0], 0, newMarkScatter[0], 0, last_len); 1065 System.arraycopy(tmp[1], 0, newMarkScatter[1], 0, last_len); 1066 System.arraycopy(tmp[2], 0, newMarkScatter[2], 0, last_len); 1067 System.arraycopy(markScatter[0], 0, newMarkScatter[0], last_len, len); 1068 System.arraycopy(markScatter[1], 0, newMarkScatter[1], last_len, len); 1069 System.arraycopy(markScatter[2], 0, newMarkScatter[2], last_len, len); 1070 1071 Integer1DSet dset = new Integer1DSet(len+last_len); 1072 FlatField scatterFieldMark = new FlatField( 1073 new FunctionType(RealType.Generic, 1074 new RealTupleType(RealType.XAxis, RealType.YAxis, RealType.getRealType("mask"))), dset); 1075 1076 scatterFieldMark.setSamples(newMarkScatter, false); 1077 scatterMarkDsp.setData(scatterFieldMark); 1078 } 1079 } 1080 1081 public void setActive(boolean active) { 1082 this.active = active; 1083 } 1084 1085 public void reset() throws VisADException, RemoteException { 1086 1087 float[][] lastMark = ((FlatField)scatterMarkDsp.getData()).getFloats(false); 1088 float[][] tmp = new float[3][lastMark[0].length]; 1089 int cnt = 0; 1090 for (int k=0; k<lastMark[0].length; k++) { 1091 if (lastMark[2][k] != maskVal) { 1092 tmp[0][cnt] = lastMark[0][k]; 1093 tmp[1][cnt] = lastMark[1][k]; 1094 tmp[2][cnt] = lastMark[2][k]; 1095 cnt++; 1096 } 1097 } 1098 1099 RealTupleType type = ((SetType)curveDraw.getCurves().getType()).getDomain(); 1100 curveDraw.setCurves(new UnionSet(new Gridded2DSet[]{ 1101 new Gridded2DSet(type, new float[][] { 1102 { 0.0f }, { 0.0f }}, 1) })); 1103 1104 lastCurve.setData(new UnionSet(new Gridded2DSet[]{ 1105 new Gridded2DSet(type, new float[][] { 1106 { 0.0f }, { 0.0f }}, 1) })); 1107 1108 FlatField scatterFieldMark = null; 1109 if (cnt == 0) { 1110 Integer1DSet dset = new Integer1DSet(2); 1111 scatterFieldMark = new FlatField( 1112 new FunctionType(RealType.Generic, 1113 new RealTupleType(RealType.XAxis, RealType.YAxis, RealType.getRealType("mask"))), dset); 1114 float[][] markScatter = new float[3][2]; 1115 for (int k=0; k<2; k++) { 1116 markScatter[0][k] = scatterFieldRange[0][k]; 1117 markScatter[1][k] = scatterFieldRange[1][k]; 1118 markScatter[2][k] = 0; 1119 } 1120 scatterFieldMark.setSamples(markScatter, false); 1121 } 1122 else { 1123 Integer1DSet dset = new Integer1DSet(cnt); 1124 scatterFieldMark = new FlatField( 1125 new FunctionType(RealType.Generic, 1126 new RealTupleType(RealType.XAxis, RealType.YAxis, RealType.getRealType("mask"))), dset); 1127 float[][] markScatter = new float[3][cnt]; 1128 for (int k=0; k<cnt; k++) { 1129 markScatter[0][k] = tmp[0][k]; 1130 markScatter[1][k] = tmp[1][k]; 1131 markScatter[2][k] = tmp[2][k]; 1132 } 1133 scatterFieldMark.setSamples(markScatter, false); 1134 } 1135 1136 scatterMarkDsp.setData(scatterFieldMark); 1137 } 1138 1139 public void updateCurve(SampledSet set) throws VisADException, RemoteException { 1140 last_uSet = new UnionSet(new SampledSet[] {set}); 1141 curveDraw.setCurves(last_uSet); 1142 lastCurve.setData(last_uSet); 1143 } 1144 1145 public void setOther(ImageCurveSelector other) { 1146 this.other = other; 1147 } 1148 1149 @Override public void doAction() 1150 throws VisADException, RemoteException { 1151 if (!init) { 1152 init = true; 1153 return; 1154 } 1155 } 1156 1157 public void setVisible(boolean visible) throws VisADException, RemoteException { 1158 curveDraw.setVisible(visible); 1159 } 1160 1161 } 1162 1163 private class ImageBoxSelector extends CellImpl { 1164 boolean init = false; 1165 boolean active = true; 1166 SubsetRubberBandBox subsetBox; 1167 Set imageDomain; 1168 int domainLen_0; 1169 int domainLen_1; 1170 float[][] scatter; 1171 LineDrawing lastBox; 1172 ImageBoxSelector other; 1173 float maskVal; 1174 boolean earthCoordDomain = false; 1175 1176 ImageBoxSelector(SubsetRubberBandBox subsetBox, Set imageDomain, DisplayMaster master) 1177 throws VisADException, RemoteException { 1178 this(subsetBox, imageDomain, master, Color.magenta, 0f); 1179 } 1180 1181 ImageBoxSelector(SubsetRubberBandBox subsetBox, Set imageDomain, DisplayMaster master, Color color, float maskVal) 1182 throws VisADException, RemoteException { 1183 super(); 1184 this.subsetBox = subsetBox; 1185 this.imageDomain = imageDomain; 1186 int[] lens = ((Gridded2DSet)imageDomain).getLengths(); 1187 this.maskVal = maskVal; 1188 domainLen_0 = lens[0]; 1189 domainLen_1 = lens[1]; 1190 lastBox = new LineDrawing("last_box"); 1191 lastBox.setColor(color); 1192 master.addDisplayable(lastBox); 1193 subsetBox.addAction(this); 1194 master.addDisplayable(subsetBox); 1195 RealTupleType rtt = ((SetType)imageDomain.getType()).getDomain(); 1196 if (rtt.equals(RealTupleType.SpatialEarth2DTuple) || 1197 rtt.equals(RealTupleType.LatitudeLongitudeTuple)) { 1198 earthCoordDomain = true; 1199 } 1200 } 1201 1202 @Override public void doAction() 1203 throws VisADException, RemoteException 1204 { 1205 if (!init) { 1206 init = true; 1207 return; 1208 } 1209 1210 if (!active) { 1211 return; 1212 } 1213 1214 Gridded2DSet set = subsetBox.getBounds(); 1215 float[][] corners = set.getSamples(false); 1216 float[][] coords = corners; 1217 1218 if ((imageDomain instanceof Linear2DSet) || !earthCoordDomain) { 1219 coords = ((Gridded2DSet)imageDomain).valueToGrid(corners); 1220 } 1221 1222 float[] coords_0 = coords[0]; 1223 float[] coords_1 = coords[1]; 1224 1225 int low_0 = Math.round(Math.min(coords_0[0], coords_0[1])); 1226 int low_1 = Math.round(Math.min(coords_1[0], coords_1[1])); 1227 int hi_0 = Math.round(Math.max(coords_0[0], coords_0[1])); 1228 int hi_1 = Math.round(Math.max(coords_1[0], coords_1[1])); 1229 1230 int len_0 = (hi_0 - low_0) + 1; 1231 int len_1 = (hi_1 - low_1) + 1; 1232 int len = len_0*len_1; 1233 1234 float[][] markScatter = new float[3][len]; 1235 1236 for (int j=0; j<len_1; j++) { 1237 for (int i=0; i<len_0; i++) { 1238 int idx = (j+low_1)*domainLen_0 + (i+low_0); 1239 int k = j*len_0 + i; 1240 markScatter[0][k] = scatterFieldRange[0][idx]; 1241 markScatter[1][k] = scatterFieldRange[1][idx]; 1242 markScatter[2][k] = maskVal; 1243 } 1244 } 1245 1246 int last_len = 0; 1247 float[][] lastMark = ((FlatField)scatterMarkDsp.getData()).getFloats(false); 1248 float[][] tmp = new float[3][lastMark[0].length]; 1249 for (int k=0; k<lastMark[0].length; k++) { 1250 if (lastMark[2][k] != maskVal) { 1251 tmp[0][last_len] = lastMark[0][k]; 1252 tmp[1][last_len] = lastMark[1][k]; 1253 tmp[2][last_len] = lastMark[2][k]; 1254 last_len++; 1255 } 1256 } 1257 1258 float[][] newMarkScatter = new float[3][len+last_len]; 1259 System.arraycopy(tmp[0], 0, newMarkScatter[0], 0, last_len); 1260 System.arraycopy(tmp[1], 0, newMarkScatter[1], 0, last_len); 1261 System.arraycopy(tmp[2], 0, newMarkScatter[2], 0, last_len); 1262 System.arraycopy(markScatter[0], 0, newMarkScatter[0], last_len, len); 1263 System.arraycopy(markScatter[1], 0, newMarkScatter[1], last_len, len); 1264 System.arraycopy(markScatter[2], 0, newMarkScatter[2], last_len, len); 1265 1266 Integer1DSet dset = new Integer1DSet(len+last_len); 1267 FlatField scatterFieldMark = new FlatField( 1268 new FunctionType(RealType.Generic, 1269 new RealTupleType(RealType.XAxis, RealType.YAxis, RealType.getRealType("mask"))), dset); 1270 1271 scatterFieldMark.setSamples(newMarkScatter, false); 1272 scatterMarkDsp.setData(scatterFieldMark); 1273 updateBox(); 1274 } 1275 1276 public void setActive(boolean active) { 1277 this.active = active; 1278 } 1279 1280 public void setVisible(boolean visible) throws VisADException, RemoteException { 1281 subsetBox.setVisible(visible); 1282 if (visible) { 1283 lastBox.setVisible(visible); 1284 } 1285 } 1286 1287 public void reset() throws VisADException, RemoteException { 1288 Gridded2DSet set2D = 1289 new Gridded2DSet(RealTupleType.SpatialCartesian2DTuple, 1290 new float[][] {{0},{0}}, 1); 1291 lastBox.setVisible(false); 1292 lastBox.setData(set2D); 1293 1294 float[][] lastMark = ((FlatField)scatterMarkDsp.getData()).getFloats(false); 1295 float[][] tmp = new float[3][lastMark[0].length]; 1296 int cnt = 0; 1297 for (int k=0; k<lastMark[0].length; k++) { 1298 if (lastMark[2][k] != maskVal) { 1299 tmp[0][cnt] = lastMark[0][k]; 1300 tmp[1][cnt] = lastMark[1][k]; 1301 tmp[2][cnt] = lastMark[2][k]; 1302 cnt++; 1303 } 1304 } 1305 1306 FlatField scatterFieldMark; 1307 if (cnt == 2) { 1308 Integer1DSet dset = new Integer1DSet(2); 1309 scatterFieldMark = new FlatField( 1310 new FunctionType(RealType.Generic, 1311 new RealTupleType(RealType.XAxis, RealType.YAxis, RealType.getRealType("mask"))), dset); 1312 float[][] markScatter = new float[3][2]; 1313 for (int k=0; k<2; k++) { 1314 markScatter[0][k] = scatterFieldRange[0][k]; 1315 markScatter[1][k] = scatterFieldRange[1][k]; 1316 markScatter[2][k] = 0; 1317 } 1318 scatterFieldMark.setSamples(markScatter, false); 1319 } 1320 else { 1321 Integer1DSet dset = new Integer1DSet(cnt); 1322 scatterFieldMark = new FlatField( 1323 new FunctionType(RealType.Generic, 1324 new RealTupleType(RealType.XAxis, RealType.YAxis, RealType.getRealType("mask"))), dset); 1325 float[][] markScatter = new float[3][cnt]; 1326 for (int k=0; k<cnt; k++) { 1327 markScatter[0][k] = tmp[0][k]; 1328 markScatter[1][k] = tmp[1][k]; 1329 markScatter[2][k] = tmp[2][k]; 1330 } 1331 scatterFieldMark.setSamples(markScatter, false); 1332 } 1333 1334 scatterMarkDsp.setData(scatterFieldMark); 1335 } 1336 1337 public void setOther(ImageBoxSelector other) { 1338 this.other = other; 1339 } 1340 1341 public void updateBox() throws VisADException, RemoteException { 1342 Gridded3DSet set3D = subsetBox.getLastBox(); 1343 float[][] samples = set3D.getSamples(false); 1344 Gridded2DSet set2D = 1345 new Gridded2DSet(RealTupleType.SpatialCartesian2DTuple, 1346 new float[][] {samples[0], samples[1]}, samples[0].length); 1347 lastBox.setData(set2D); 1348 other.updateBox(set2D); 1349 } 1350 1351 public void updateBox(Gridded2DSet set2D) throws VisADException, RemoteException { 1352 lastBox.setData(set2D); 1353 } 1354 1355 public SubsetRubberBandBox getSelector() { 1356 return subsetBox; 1357 } 1358 } 1359 1360 private class ScatterBoxSelector extends CellImpl { 1361 boolean init = false; 1362 double[] x_coords = new double[2]; 1363 double[] y_coords = new double[2]; 1364 RubberBandBox rbb; 1365 LineDrawing selectBox; 1366 boolean active = true; 1367 float maskVal = 0; 1368 1369 ScatterBoxSelector(DisplayMaster master) throws VisADException, RemoteException { 1370 this(master, Color.green, 0f); 1371 } 1372 1373 ScatterBoxSelector(DisplayMaster master, Color color, float maskVal) throws VisADException, RemoteException { 1374 selectBox = new LineDrawing("select"); 1375 selectBox.setColor(color); 1376 1377 rbb = new RubberBandBox(RealType.XAxis, RealType.YAxis, 1); 1378 rbb.setColor(color); 1379 rbb.addAction(this); 1380 1381 master.addDisplayable(rbb); 1382 master.addDisplayable(selectBox); 1383 this.maskVal = maskVal; 1384 } 1385 1386 1387 @Override public void doAction() throws VisADException, RemoteException { 1388 if (!init) { 1389 init = true; 1390 return; 1391 } 1392 1393 if (!active) { 1394 return; 1395 } 1396 1397 Gridded2DSet set = rbb.getBounds(); 1398 float[] low = set.getLow(); 1399 float[] hi = set.getHi(); 1400 x_coords[0] = low[0]; 1401 x_coords[1] = hi[0]; 1402 y_coords[0] = low[1]; 1403 y_coords[1] = hi[1]; 1404 1405 SampledSet[] sets = new SampledSet[4]; 1406 sets[0] = new Gridded2DSet(RealTupleType.SpatialCartesian2DTuple, new float[][] {{low[0], hi[0]}, {low[1], low[1]}}, 2); 1407 sets[1] = new Gridded2DSet(RealTupleType.SpatialCartesian2DTuple, new float[][] {{hi[0], hi[0]}, {low[1], hi[1]}}, 2); 1408 sets[2] = new Gridded2DSet(RealTupleType.SpatialCartesian2DTuple, new float[][] {{hi[0], low[0]}, {hi[1], hi[1]}}, 2); 1409 sets[3] = new Gridded2DSet(RealTupleType.SpatialCartesian2DTuple, new float[][] {{low[0], low[0]}, {hi[1], low[1]}}, 2); 1410 UnionSet uset = new UnionSet(sets); 1411 selectBox.setData(uset); 1412 1413 try { 1414 FlatField updateMask = histoField.markMaskFieldByRange(x_coords, y_coords, maskVal); 1415 } catch (Exception e) { 1416 e.printStackTrace(); 1417 } 1418 } 1419 1420 public void setVisible(boolean visible) throws VisADException, RemoteException { 1421 rbb.setVisible(visible); 1422 if (visible) { 1423 selectBox.setVisible(visible); 1424 } 1425 } 1426 1427 public void setActive(boolean active) { 1428 this.active = active; 1429 } 1430 1431 public void reset() throws Exception { 1432 selectBox.setVisible(false); 1433 selectBox.setData(new Gridded2DSet(RealTupleType.SpatialCartesian2DTuple, new float[][] {{0f, 0f}, {0f, 0f}}, 2)); 1434 histoField.resetMaskField(maskVal); 1435 } 1436 } 1437 1438 private class ScatterCurveSelector extends CellImpl implements DisplayListener { 1439 CurveDrawer curveDraw; 1440 boolean init = false; 1441 UnionSet last_uSet = null; 1442 boolean active = true; 1443 float maskVal = 0; 1444 LineDrawing selectCurve; 1445 1446 ScatterCurveSelector(DisplayMaster master) throws VisADException, RemoteException { 1447 this(master, Color.green, 0f); 1448 } 1449 1450 ScatterCurveSelector(DisplayMaster master, Color color, float maskVal) throws VisADException, RemoteException { 1451 curveDraw = new CurveDrawer(RealType.XAxis, RealType.YAxis, 1); 1452 curveDraw.setColor(color); 1453 curveDraw.setLineWidth(2); 1454 curveDraw.setData(new UnionSet(new Gridded2DSet[]{ 1455 new Gridded2DSet(RealTupleType.SpatialCartesian2DTuple, new float[][] { 1456 { scatterFieldRange[0][0] }, { scatterFieldRange[1][0]} 1457 }, 1) })); 1458 1459 selectCurve = new LineDrawing("select"); 1460 selectCurve.setColor(color); 1461 selectCurve.setLineWidth(2); 1462 master.addDisplayable(curveDraw); 1463 master.addDisplayable(selectCurve); 1464 this.maskVal = maskVal; 1465 1466 curveDraw.addAction(this); 1467 master.addDisplayListener(this); 1468 } 1469 1470 @Override public void displayChanged(DisplayEvent de) 1471 throws VisADException, RemoteException { 1472 if ((de.getId() == DisplayEvent.MOUSE_RELEASED) && (active)) { 1473 UnionSet uSet = curveDraw.getCurves(); 1474 if (uSet == last_uSet) return; 1475 SampledSet[] sets = uSet.getSets(); 1476 int s_idx = sets.length-1; 1477 float[][] crv; 1478 1479 crv = sets[s_idx].getSamples(); 1480 last_uSet = new UnionSet(new SampledSet[] {sets[s_idx]}); 1481 curveDraw.setCurves(last_uSet); 1482 selectCurve.setData(last_uSet); 1483 1484 try { 1485 histoField.clearMaskField(maskVal); 1486 FlatField updateMask = histoField.markMaskFieldByCurve(crv, maskVal); 1487 } catch (Exception e) { 1488 e.printStackTrace(); 1489 } 1490 } 1491 } 1492 1493 @Override public void doAction() throws VisADException, RemoteException { 1494 if (!init) { 1495 init = true; 1496 return; 1497 } 1498 } 1499 1500 public void setVisible(boolean visible) throws VisADException, RemoteException { 1501 curveDraw.setVisible(visible); 1502 } 1503 1504 public void setActive(boolean active) { 1505 this.active = active; 1506 } 1507 1508 public void reset() throws Exception { 1509 curveDraw.setData(new UnionSet(new Gridded2DSet[]{ 1510 new Gridded2DSet(RealTupleType.SpatialCartesian2DTuple, new float[][] { 1511 { scatterFieldRange[0][0] }, { scatterFieldRange[1][0]} 1512 }, 1) })); 1513 selectCurve.setData(new UnionSet(new Gridded2DSet[]{ 1514 new Gridded2DSet(RealTupleType.SpatialCartesian2DTuple, new float[][] { 1515 { scatterFieldRange[0][0] }, { scatterFieldRange[1][0]} 1516 }, 1) })); 1517 histoField.resetMaskField(maskVal); 1518 } 1519 } 1520 1521 private class BoxCurveSwitch implements ActionListener { 1522 1523 public BoxCurveSwitch() { 1524 } 1525 1526 @Override public void actionPerformed(ActionEvent ae) { 1527 String cmd = ae.getActionCommand(); 1528 try { 1529 if (cmd.equals("Box")) { 1530 selectByCurve = false; 1531 } else if (cmd.equals("Curve")) { 1532 selectByCurve = true; 1533 } 1534 } 1535 catch (Exception e) { 1536 e.printStackTrace(); 1537 } 1538 } 1539 } 1540 1541 public static float[] minmax(float[] values) { 1542 float min = Float.MAX_VALUE; 1543 float max = -Float.MAX_VALUE; 1544 for (int k = 0; k < values.length; k++) { 1545 float val = values[k]; 1546 if ((val == val) && (val < Float.POSITIVE_INFINITY) && (val > Float.NEGATIVE_INFINITY)) { 1547 if (val < min) min = val; 1548 if (val > max) max = val; 1549 } 1550 } 1551 return new float[] {min, max}; 1552 } 1553 1554 public boolean getIsLatLon(FlatField field) throws VisADException, RemoteException { 1555 boolean isLL = false; 1556 FunctionType fnc_type = (FunctionType) field.getType(); 1557 RealTupleType rtt = fnc_type.getDomain(); 1558 if (rtt.equals(RealTupleType.LatitudeLongitudeTuple)) { 1559 isLL = true; 1560 } 1561 else if (!rtt.equals(RealTupleType.SpatialEarth2DTuple)) { 1562 rtt = fnc_type.getDomain().getCoordinateSystem().getReference(); 1563 if ( rtt.equals(RealTupleType.LatitudeLongitudeTuple)) { 1564 isLL = true; 1565 } 1566 } 1567 return isLL; 1568 } 1569}