001 /*
002 * This file is part of McIDAS-V
003 *
004 * Copyright 2007-2013
005 * Space Science and Engineering Center (SSEC)
006 * University of Wisconsin - Madison
007 * 1225 W. Dayton Street, Madison, WI 53706, USA
008 * https://www.ssec.wisc.edu/mcidas
009 *
010 * All Rights Reserved
011 *
012 * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and
013 * some McIDAS-V source code is based on IDV and VisAD source code.
014 *
015 * McIDAS-V is free software; you can redistribute it and/or modify
016 * it under the terms of the GNU Lesser Public License as published by
017 * the Free Software Foundation; either version 3 of the License, or
018 * (at your option) any later version.
019 *
020 * McIDAS-V is distributed in the hope that it will be useful,
021 * but WITHOUT ANY WARRANTY; without even the implied warranty of
022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
023 * GNU Lesser Public License for more details.
024 *
025 * You should have received a copy of the GNU Lesser Public License
026 * along with this program. If not, see http://www.gnu.org/licenses.
027 */
028
029 package edu.wisc.ssec.mcidasv.data.hydra;
030
031 import java.rmi.RemoteException;
032
033 import java.util.Iterator;
034
035 import java.awt.Color;
036
037 import ucar.unidata.beans.*;
038
039 import visad.*;
040
041 import ucar.visad.display.DisplayMaster;
042 import ucar.visad.display.Displayable;
043 import ucar.visad.display.DisplayableData;
044 import ucar.visad.display.ScalarMapSet;
045 import ucar.unidata.util.Range;
046
047 import visad.RealType;
048 import visad.ScalarMap;
049 import visad.BadMappingException;
050 import visad.LocalDisplay;
051 import visad.DataReference;
052 import visad.VisADException;
053 import visad.UnimplementedException;
054 import visad.bom.ImageRendererJ3D;
055 import visad.java3d.DefaultRendererJ3D;
056 import java.rmi.RemoteException;
057
058 import java.util.ArrayList;
059 import java.util.Hashtable;
060 import java.util.List;
061 import java.util.Iterator;
062
063 import edu.wisc.ssec.mcidasv.control.HydraControl;
064 import edu.wisc.ssec.mcidasv.control.MultiSpectralControl;
065
066
067 public class HydraRGBDisplayable extends DisplayableData {
068
069 /**
070 * The name of the "color palette" property.
071 */
072 public static final String COLOR_PALETTE = "colorPalette";
073
074 /**
075 * The name of the "RGB real-type" property.
076 */
077 public static final String RGB_REAL_TYPE = "rgbRealType";
078
079 /**
080 * The polygon fill style
081 */
082 public static final int POLYGON_FILL = 0;
083
084 /**
085 * The polygon line style
086 */
087 public static final int POLYGON_LINE = 1;
088
089 /**
090 * The polygon point style
091 */
092 public static final int POLYGON_POINT = 2;
093
094 /**
095 * Color Palette
096 */
097 private float[][] colorPalette = null;
098
099 private String colorPaletteName = null;
100
101 /** color ScalarMap */
102 private volatile ScalarMap colorMap;
103
104 /** field index to Animation ScalarMap */
105 private volatile ScalarMap animMap;
106
107 /** control for ScalarMap */
108 private volatile BaseColorControl colorControl;
109
110 /** RealType for the ScalarMap */
111 private volatile RealType rgbRealType;
112
113 /** RealType for the SelectRange ScalarMap */
114 private ScalarMap selectMap = null;
115
116 /** RealType for the Animation ScalarMap */
117 private RealType indexRealType;
118
119 /** Control for select range */
120 private RangeControl selectControl;
121
122 /** RealType for the SelectRange ScalarMap */
123 private RealType selectRealType = null;
124
125 /** flag for whether alpha is used or not */
126 private boolean alphaflag;
127
128 /** local point size */
129 private float myPointSize;
130
131 /** low range for colors */
132 //private double lowRange = 315; // low range for scalarmap
133 private double lowRange = Double.NaN; // low range for scalarmap
134
135 /** high range for colors */
136 //private double highRange = 230; // high range for scalarmap
137 private double highRange = Double.NaN; // high range for scalarmap
138
139 /** default polygonMode */
140 private int polygonMode = POLYGON_FILL;
141
142 /** default curvedSize */
143 private int curvedSize = 10;
144
145 /** low range for select */
146 private double lowSelectedRange = Double.NaN; // low range for scalarmap
147
148 /** high range for select */
149 private double highSelectedRange = Double.NaN; // high range for scalarmap
150
151 /** low range for select map */
152 private double minSelect = Double.NaN; // low range for scalarmap
153
154 /** high range for select map */
155 private double maxSelect = Double.NaN; // high range for scalarmap
156
157 private HydraControl multiSpecCntrl;
158
159 private boolean useDefaultRenderer = false;
160
161 /**
162 * Constructs from a name for the Displayable and the type of the
163 * RGB parameter.
164 *
165 * @param name The name for the displayable.
166 * @param rgbRealType The type of the RGB parameter. May be
167 * <code>null</code>.
168 * @param alphaflag boolean - will use Display.RBGA if true
169 * otherwise only Display.RGB
170 * @throws VisADException VisAD failure.
171 * @throws RemoteException Java RMI failure.
172 */
173 public HydraRGBDisplayable(String name, RealType rgbRealType, RealType indexRealType, boolean alphaflag,
174 HydraControl multiSpecCntrl)
175 throws VisADException, RemoteException {
176 this(name, rgbRealType, indexRealType, null, alphaflag, null, multiSpecCntrl);
177 }
178
179 public HydraRGBDisplayable(String name, RealType rgbRealType, RealType indexRealType, float[][] colorPalette, boolean alphaflag, Range initRange,
180 HydraControl multiSpecCntrl)
181 throws VisADException, RemoteException {
182 this(name, rgbRealType, indexRealType, colorPalette, null, alphaflag, initRange, multiSpecCntrl);
183 }
184
185 /**
186 * Constructs from a name for the Displayable and the type of the
187 * RGB parameter.
188 *
189 * @param name The name for the displayable.
190 * @param rgbRealType The type of the RGB parameter. May be
191 * <code>null</code>.
192 * @param colorPalette The initial colorPalette to use. May be
193 * <code>null</code> (Vis5D palette used
194 * as default).
195 * @param alphaflag boolean - use Display.RBGA if true
196 * @param initRange Range to use as initial or first min,max
197 * @throws VisADException VisAD failure.
198 * @throws RemoteException Java RMI failure.
199 */
200 public HydraRGBDisplayable(String name, RealType rgbRealType, RealType indexRealType, float[][] colorPalette, String colorPaletteName, boolean alphaflag, Range initRange,
201 HydraControl multiSpecCntrl)
202 throws VisADException, RemoteException {
203
204 super(name);
205
206 this.rgbRealType = rgbRealType;
207 this.selectRealType = rgbRealType;
208 this.indexRealType = indexRealType;
209 this.colorPalette = colorPalette;
210 this.colorPaletteName = colorPaletteName;
211 this.alphaflag = alphaflag;
212 this.multiSpecCntrl = multiSpecCntrl;
213
214 if (initRange != null) {
215 this.lowRange = initRange.getMin();
216 this.highRange = initRange.getMax();
217 }
218
219 if (rgbRealType != null) {
220 setColorMaps();
221 if (useDisplayUnitForColor()) {
222 setDisplayUnit(rgbRealType.getDefaultUnit());
223 } else {
224 setColorUnit(rgbRealType.getDefaultUnit());
225 }
226 }
227
228 if (indexRealType != null) {
229 //-setAnimationMap();
230 setSelectMap();
231 }
232
233 if (selectRealType != null) {
234 //setSelectMaps();
235 }
236 }
237
238 /**
239 * Does this object use the displayUnit (or the colorUnit) for its
240 * display unit. The default is true. This allows derived classes
241 * to have this class use the colorUnit.
242 * @return true if the display unit is the same as the color unit
243 */
244 protected boolean useDisplayUnitForColor() {
245 return true;
246 }
247
248
249 /**
250 * Constructs from another instance. The following attributes are set from
251 * the other instance: color palette, the color RealType.
252 * @param that The other instance.
253 * @throws VisADException VisAD failure.
254 * @throws RemoteException Java RMI failure.
255 */
256 protected HydraRGBDisplayable(HydraRGBDisplayable that)
257 throws VisADException, RemoteException {
258
259 super(that);
260 colorPalette = that.colorPalette;
261 rgbRealType = that.rgbRealType; // immutable object
262 alphaflag = that.alphaflag;
263
264 if (rgbRealType != null) {
265 setColorMaps();
266 }
267 }
268
269 /**
270 * Sets the RealType of the RGB parameter.
271 * @param realType The RealType of the RGB parameter. May
272 * not be <code>null</code>.
273 * @throws VisADException VisAD failure.
274 * @throws RemoteException Java RMI failure.
275 */
276 public void setRGBRealType(RealType realType)
277 throws RemoteException, VisADException {
278
279 if ( !realType.equals(rgbRealType)) {
280 RealType oldValue = rgbRealType;
281 rgbRealType = realType;
282 setColorMaps();
283 if (useDisplayUnitForColor()) {
284 if ( !isUnitCompatible(rgbRealType, getDisplayUnit())) {
285 setDisplayUnit(null);
286 }
287 } else {
288 if ( !isUnitCompatible(rgbRealType, getColorUnit())) {
289 setColorUnit(null);
290 }
291 }
292 firePropertyChange(RGB_REAL_TYPE, oldValue, rgbRealType);
293 }
294 }
295
296 public ScalarMap getColorMap() {
297 return colorMap;
298 }
299
300 public ScalarMap getAnimationMap() {
301 return animMap;
302 }
303
304
305 /**
306 * Returns the RealType of the RGB parameter.
307 * @return The RealType of the color parameter. May
308 * be <code>null</code>.
309 */
310 public RealType getRGBRealType() {
311 return rgbRealType;
312 }
313
314 /**
315 * Returns the RealType of the SelectRange parameter.
316 * @return The RealType of the select range parameter. May
317 * be <code>null</code>.
318 */
319 public RealType getSelectRealType() {
320 return selectRealType;
321 }
322
323 protected DataRenderer getDataRenderer() throws VisADException {
324 if (useDefaultRenderer) {
325 return new DefaultRendererJ3D();
326 }
327 else {
328 return new ImageRendererJ3D();
329 }
330 }
331
332 public void setDefaultRenderer() {
333 useDefaultRenderer = true;
334 }
335
336 public void setImageRenderer() {
337 useDefaultRenderer = false;
338 }
339
340 /**
341 * Sets the set of ScalarMap-s of this instance. The ScalarMap-s of
342 * this instance will be added to the set before the SCALAR_MAP_SET
343 * property is set. This method fires a PropertyChangeEvent for
344 * SCALAR_MAP_SET with <code>null</code> for the old value and the new
345 * set of ScalarMap-s for the new Value. Intermediate subclasses that
346 * have their own ScalarMap-s should override this method and invoke
347 * <code>super.setScalarMaps(ScalarMapSet)</code>.
348 * @param maps The set of ScalarMap-s to be added.
349 * @throws BadMappingException The RealType of the color parameter
350 * has not been set or its ScalarMap is alread in
351 * the set.
352 */
353 protected void setScalarMaps(ScalarMapSet maps)
354 throws BadMappingException {
355
356 if (colorMap == null) {
357 throw new BadMappingException(getClass().getName()
358 + ".setScalarMaps(ScalarMapSet): "
359 + "Color not yet set");
360 }
361
362 maps.add(colorMap);
363
364 if (selectMap != null) {
365
366 maps.add(selectMap);
367 }
368
369 super.setScalarMapSet(maps);
370 }
371
372 /**
373 * This method sets the color palette
374 * according to the color table in argument;
375 * pair this method with setRange(lo,high) to get
376 * a fixed association of color table and range of values.
377 *
378 * @param colorPalette the color table or color-alpha table desired
379 * @param colorPaletteName name for the color table (can be null)
380 * @throws VisADException if a core VisAD failure occurs.
381 * @throws RemoteException if a Java RMI failure occurs.
382 */
383 public void setColorPalette(float[][] colorPalette, String name)
384 throws RemoteException, VisADException {
385 if (colorControl != null) {
386 colorControl.setTable(colorPalette);
387 }
388
389 this.colorPalette = colorPalette;
390 this.colorPaletteName = name;
391 }
392
393 /**
394 * This method sets the color palette
395 * according to the color table in argument;
396 * pair this method with setRange(lo,high) to get
397 * a fixed association of color table and range of values;
398 * asigns null (doesn't have a name) for the name.
399 *
400 * @param colorPalette the color table or color-alpha table desired
401 * @throws VisADException if a core VisAD failure occurs.
402 * @throws RemoteException if a Java RMI failure occurs.
403 */
404 public void setColorPalette(float[][] colorPalette)
405 throws VisADException, RemoteException {
406 setColorPalette(colorPalette, null);
407 }
408
409 /**
410 * Return the current color palette in this Displayable
411 *
412 * @return a color table float[3][len] or color-alpha table float[4][len]
413 */
414 public float[][] getColorPalette() {
415 return colorPalette;
416 }
417
418 public String getColorPaletteName() {
419 return colorPaletteName;
420 }
421
422 /**
423 * Make a color palette representing this color and set it as the
424 * color pallete.
425 *
426 * @param color color to use
427 * @throws VisADException VisAD failure.
428 * @throws RemoteException Java RMI failure.
429 */
430 public void setColor(Color color) throws RemoteException, VisADException {
431 int len = 5;
432 float[][] table = new float[(alphaflag == true)
433 ? 4
434 : 3][len];
435 for (int m = 0; m < len; m++) {
436 table[0][m] = color.getRed() / 255.f; // Red amount
437 table[1][m] = color.getGreen() / 255.f; // Green
438 table[2][m] = color.getBlue() / 255.f; // Blue
439 }
440 setColorPalette(table);
441 }
442
443 /**
444 * This method sets the color palette to shades of grey.
445 *
446 * @throws VisADException if a core VisAD failure occurs.
447 * @throws RemoteException if a Java RMI failure occurs.
448 */
449 public final void setGreyPalette()
450 throws RemoteException, VisADException {
451
452 if (colorControl != null) {
453 colorControl.initGreyWedge();
454 setColorPalette(colorControl.getTable());
455 }
456 }
457
458 /**
459 * This method with no argument sets the default Vis5D color spectrum.
460 *
461 * @throws VisADException if a core VisAD failure occurs.
462 * @throws RemoteException if a Java RMI failure occurs.
463 */
464 public final void setVisADPalette()
465 throws RemoteException, VisADException {
466
467 if (colorControl != null) {
468 colorControl.initVis5D();
469 setColorPalette(colorControl.getTable());
470 }
471 }
472
473 /**
474 * Set the upper and lower limit of the range values associated
475 * with a color table.
476 *
477 * @param low the minimun value
478 * @param hi the maximum value
479 * @deprecated use setRangeForColor
480 *
481 * @throws RemoteException Java RMI error
482 * @throws VisADException problem creating VisAD object
483 */
484 public void setRange(double low, double hi)
485 throws VisADException, RemoteException {
486
487 setRangeForColor(low, hi);
488 }
489
490 /**
491 * Set the upper and lower limit of the range values associated
492 * with a color table.
493 *
494 * Matches method name in Contour2DDisplayable
495 *
496 * @param low The minimum value of the parameter matched to
497 * the low end of the color table.
498 * @param hi The maximum value of the parameter matched to
499 * the high end of the color table.
500 *
501 * @exception VisADException VisAD failure.
502 * @exception RemoteException Java RMI failure.
503 */
504 public void setRangeForColor(double low, double hi)
505 throws VisADException, RemoteException {
506 lowRange = low;
507 highRange = hi;
508 if ((colorMap != null) && hasRange()) {
509 colorMap.setRange(low, hi);
510 }
511 }
512
513 /**
514 * Get the color range
515 *
516 * @return an array of the low and high values for the range
517 * @deprecated use #getRangeForColor()
518 */
519 public double[] getRangeforColor() {
520 return getRangeForColor();
521 }
522
523 /**
524 * Get the color range
525 *
526 * @return an array of the low and high values for the range
527 */
528 public double[] getRangeForColor() {
529 return new double[]{ lowRange, highRange };
530 }
531
532 /**
533 * Apply the correct unit (either the displayUnit or the colorUnit)
534 * to the scalar map
535 *
536 * @param colorMap ScalarMap to apply to
537 * @param rgbRealType RealType for default Unit
538 *
539 * @throws RemoteException Java RMI error
540 * @throws VisADException problem creating VisAD object
541 */
542 private void applyUnit(ScalarMap colorMap, RealType rgbRealType)
543 throws VisADException, RemoteException {
544 if (useDisplayUnitForColor()) {
545 applyDisplayUnit(colorMap, rgbRealType);
546 } else {
547 applyColorUnit(colorMap, rgbRealType);
548 }
549 }
550
551
552 /**
553 * Set the units for the displayed range
554 *
555 * @param unit Unit for display
556 *
557 * @throws RemoteException Java RMI error
558 * @throws VisADException problem creating VisAD object
559 */
560 public void setDisplayUnit(Unit unit)
561 throws VisADException, RemoteException {
562 if (useDisplayUnitForColor()) {
563 //Make sure this unit is ok
564 checkUnit(rgbRealType, unit);
565 }
566 super.setDisplayUnit(unit);
567 if (useDisplayUnitForColor()) {
568 applyUnit(colorMap, rgbRealType);
569 }
570 }
571
572
573 /**
574 * Set the units for the displayed range
575 *
576 * @param unit Unit for display
577 *
578 * @throws RemoteException Java RMI error
579 * @throws VisADException problem creating VisAD object
580 */
581 public void setColorUnit(Unit unit)
582 throws VisADException, RemoteException {
583 if ( !useDisplayUnitForColor()) {
584 //Make sure this unit is ok
585 checkUnit(rgbRealType, unit);
586 }
587 super.setColorUnit(unit);
588 if ( !useDisplayUnitForColor()) {
589 applyUnit(colorMap, rgbRealType);
590 }
591 }
592
593
594 /**
595 * Returns whether this Displayable has a valid range (i.e., lowRange and
596 * highRange are both not NaN's
597 *
598 * @return true if range has been set
599 */
600 public boolean hasRange() {
601 return ( !Double.isNaN(lowRange) && !Double.isNaN(highRange));
602 }
603
604
605 /**
606 * Sets the size of points in this Displayable.
607 *
608 * @param pointSize Size of points (2 = normal)
609 *
610 * @throws VisADException VisAD failure.
611 * @throws RemoteException Java RMI failure.
612 */
613 public void setPointSize(float pointSize)
614 throws VisADException, RemoteException {
615
616 float oldValue;
617
618 synchronized (this) {
619 oldValue = myPointSize;
620
621 addConstantMap(new ConstantMap(pointSize, Display.PointSize));
622
623 myPointSize = pointSize;
624 }
625
626 }
627
628 /**
629 * Gets the point size associated with this LineDrawing
630 *
631 * @return point size
632 */
633 public float getPointSize() {
634 return myPointSize;
635 }
636
637 /**
638 * Set the type of polygon display that should be used
639 *
640 * @param polygonMode polygon mode
641 *
642 * @throws RemoteException Java RMI error
643 * @throws VisADException problem creating VisAD object
644 */
645 public void setPolygonMode(int polygonMode)
646 throws VisADException, RemoteException {
647 this.polygonMode = polygonMode;
648 addConstantMap(new ConstantMap(convertToVisADPolygonMode(polygonMode),
649 Display.PolygonMode));
650 }
651
652 /**
653 * Converts an RGBDisplayable Polygon mode to the appropriate
654 * (or default) VisAD mode
655 *
656 * @param myMode polygon mode
657 * @return Java3D mode
658 */
659 private int convertToVisADPolygonMode(int myMode) {
660 if (visad.util.Util.canDoJava3D()) {
661 switch (myMode) {
662
663 case POLYGON_FILL :
664 return visad.java3d.DisplayImplJ3D.POLYGON_FILL;
665
666 case POLYGON_LINE :
667 return visad.java3d.DisplayImplJ3D.POLYGON_LINE;
668
669 case POLYGON_POINT :
670 return visad.java3d.DisplayImplJ3D.POLYGON_POINT;
671
672 default :
673 return visad.java3d.DisplayImplJ3D.POLYGON_FILL;
674 }
675 } else {
676 return 0;
677 }
678 }
679
680 /**
681 * Return the type of polygon mode being used
682 *
683 * @return polygon mode
684 */
685 public int getPolygonMode() {
686 return polygonMode;
687 }
688
689 /**
690 * Set the curved size for textured displays
691 *
692 * @param curvedSize size to use (> 0)
693 *
694 * @throws RemoteException Java RMI error
695 * @throws VisADException problem creating VisAD object
696 */
697 public void setCurvedSize(int curvedSize)
698 throws VisADException, RemoteException {
699 this.curvedSize = curvedSize;
700 addConstantMap(makeCurvedSizeMap(curvedSize));
701 }
702
703 /**
704 * Create the ConstantMap for the texture curve size
705 *
706 * @param curvedSize size for texture curve
707 * @return ConstantMap
708 *
709 * @throws RemoteException Java RMI error
710 * @throws VisADException problem creating VisAD object
711 */
712 protected ConstantMap makeCurvedSizeMap(int curvedSize)
713 throws VisADException, RemoteException {
714 return new ConstantMap(curvedSize, Display.CurvedSize);
715 }
716
717 /**
718 * Return the size of a curved texture
719 * @return curved size
720 */
721 public int getCurvedSize() {
722 return curvedSize;
723 }
724
725 /**
726 * creates the ScalarMap for color and ColorControl for this Displayable.
727 *
728 * @throws VisADException VisAD failure.
729 * @throws RemoteException Java RMI failure.
730 */
731 private void setColorMaps() throws RemoteException, VisADException {
732
733 // ScalarMap is either mapping to Display.RGB (color only)
734 // or to Display.RGBA color plus transparency.
735 if ( !alphaflag) {
736 colorMap = new ScalarMap(rgbRealType, Display.RGB);
737 } else {
738 colorMap = new ScalarMap(rgbRealType, Display.RGBA);
739 }
740
741 applyUnit(colorMap, rgbRealType);
742
743 if (hasRange()) {
744 colorMap.setRange(lowRange, highRange);
745 }
746
747 colorMap.addScalarMapListener(new ScalarMapListener() {
748
749 public void controlChanged(ScalarMapControlEvent event)
750 throws RemoteException, VisADException {
751
752 int id = event.getId();
753
754 if ((id == event.CONTROL_ADDED)
755 || (id == event.CONTROL_REPLACED)) {
756 colorControl = (BaseColorControl) colorMap.getControl();
757
758 if (colorControl != null) {
759 if (colorPalette != null) {
760 colorControl.setTable(colorPalette);
761 } else {
762 colorPalette = colorControl.getTable();
763 }
764 }
765 }
766 }
767
768 public void mapChanged(ScalarMapEvent event)
769 throws RemoteException, VisADException {
770 if ((event.getId() == event.AUTO_SCALE) && hasRange()) {
771 double[] rng = colorMap.getRange();
772 if (multiSpecCntrl != null) {
773 multiSpecCntrl.updateRange(new Range(rng));
774 }
775 }
776 }
777 });
778 ScalarMapSet maps = getScalarMapSet(); //new ScalarMapSet();
779 maps.add(colorMap);
780 setScalarMapSet(maps);
781 }
782
783 private void setAnimationMap() throws RemoteException, VisADException {
784 animMap = new ScalarMap(indexRealType, Display.Animation);
785 ScalarMapSet maps = getScalarMapSet();
786 maps.add(animMap);
787 setScalarMapSet(maps);
788 }
789
790 private void setSelectMap() throws RemoteException, VisADException {
791 animMap = new ScalarMap(indexRealType, Display.SelectValue);
792 ScalarMapSet maps = getScalarMapSet();
793 maps.add(animMap);
794 setScalarMapSet(maps);
795 }
796
797 /**
798 * Sets the RealType of the select parameter.
799 * @param realType The RealType of the RGB parameter. May
800 * not be <code>null</code>.
801 * @throws VisADException VisAD failure.
802 * @throws RemoteException Java RMI failure.
803 */
804 protected void setSelectRealType(RealType realType)
805 throws RemoteException, VisADException {
806
807 if ( !realType.equals(selectRealType)) {
808 RealType oldValue = selectRealType;
809 selectRealType = realType;
810 setSelectMaps();
811 if (useDisplayUnitForColor()) {
812 if ( !isUnitCompatible(selectRealType, getDisplayUnit())) {
813 setDisplayUnit(null);
814 }
815 } else {
816 if ( !isUnitCompatible(selectRealType, getColorUnit())) {
817 setColorUnit(null);
818 }
819 }
820 }
821 }
822
823 /**
824 * Returns whether this Displayable has a valid range
825 * (i.e., lowSelectedRange and highSelectedRange are both not NaN's
826 *
827 * @return true if range has been set
828 */
829 public boolean hasSelectedRange() {
830 return ( !Double.isNaN(lowSelectedRange)
831 && !Double.isNaN(highSelectedRange));
832 }
833
834 /**
835 * Set selected range with the range for select
836 *
837 * @param low low select value
838 * @param hi hi select value
839 *
840 * @throws RemoteException Java RMI error
841 * @throws VisADException problem creating VisAD object
842 */
843 public void setSelectedRange(double low, double hi)
844 throws VisADException, RemoteException {
845
846 lowSelectedRange = low;
847 highSelectedRange = hi;
848 if ((selectControl != null) && hasSelectedRange()) {
849 selectControl.setRange(new double[]{ low, hi });
850 }
851
852 }
853
854 /**
855 * Set the upper and lower limit of the range values associated
856 * with a color table.
857 *
858 * @param low the minimun value
859 * @param hi the maximum value
860 *
861 * @throws RemoteException Java RMI error
862 * @throws VisADException problem creating VisAD object
863 */
864 public void setRangeForSelect(double low, double hi)
865 throws VisADException, RemoteException {
866
867 minSelect = low;
868 maxSelect = hi;
869 if ((selectMap != null) && hasSelectMinMax()) {
870 selectMap.setRange(low, hi);
871 }
872 }
873
874 /**
875 * Check to see if the range has been set for the select
876 *
877 * @return true if it has
878 */
879 private boolean hasSelectMinMax() {
880 return ( !Double.isNaN(minSelect) && !Double.isNaN(maxSelect));
881 }
882
883 /**
884 * creates the ScalarMap for SelectRange and control for this Displayable.
885 *
886 * @throws VisADException VisAD failure.
887 * @throws RemoteException Java RMI failure.
888 */
889 private void setSelectMaps() throws RemoteException, VisADException {
890
891 selectMap = new ScalarMap(selectRealType, Display.SelectRange);
892
893 if (selectRealType.equals(rgbRealType)) {
894 applyUnit(selectMap, selectRealType);
895 }
896
897 if (hasSelectMinMax()) {
898 selectMap.setRange(minSelect, maxSelect);
899 }
900
901 selectMap.addScalarMapListener(new ScalarMapListener() {
902
903 public void controlChanged(ScalarMapControlEvent event)
904 throws RemoteException, VisADException {
905
906 int id = event.getId();
907
908 if ((id == event.CONTROL_ADDED)
909 || (id == event.CONTROL_REPLACED)) {
910 selectControl = (RangeControl) selectMap.getControl();
911 if (hasSelectedRange()) {
912 selectControl.setRange(new double[]{ lowSelectedRange,
913 highSelectedRange });
914 }
915 }
916 }
917
918 public void mapChanged(ScalarMapEvent event)
919 throws RemoteException, VisADException {
920 if ((event.getId() == event.AUTO_SCALE)
921 && hasSelectMinMax()) {
922 selectMap.setRange(minSelect, maxSelect);
923 }
924 }
925 });
926 ScalarMapSet maps = getScalarMapSet(); //new ScalarMapSet();
927 maps.add(selectMap);
928 setScalarMapSet(maps);
929 }
930
931 }