casa
$Rev:20696$
|
00001 //# RSUtils.qo.h: Common utilities/constants for region shapes. 00002 //# Copyright (C) 2008 00003 //# Associated Universities, Inc. Washington DC, USA. 00004 //# 00005 //# This library is free software; you can redistribute it and/or modify it 00006 //# under the terms of the GNU Library General Public License as published by 00007 //# the Free Software Foundation; either version 2 of the License, or (at your 00008 //# option) any later version. 00009 //# 00010 //# This library is distributed in the hope that it will be useful, but WITHOUT 00011 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00012 //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public 00013 //# License for more details. 00014 //# 00015 //# You should have received a copy of the GNU Library General Public License 00016 //# along with this library; if not, write to the Free Software Foundation, 00017 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA. 00018 //# 00019 //# Correspondence concerning AIPS++ should be addressed as follows: 00020 //# Internet email: aips2-request@nrao.edu. 00021 //# Postal address: AIPS++ Project Office 00022 //# National Radio Astronomy Observatory 00023 //# 520 Edgemont Road 00024 //# Charlottesville, VA 22903-2475 USA 00025 //# 00026 //# $Id$ 00027 #ifndef RSUTILS_QO_H_ 00028 #define RSUTILS_QO_H_ 00029 00030 #include <QtGui> 00031 00032 #include <casa/BasicSL/String.h> 00033 #include <display/Display/WorldCanvasHolder.h> 00034 #include <display/Display/WorldCanvas.h> 00035 #include <measures/Measures/MCDirection.h> 00036 #include <measures/Measures/MDirection.h> 00037 00038 #include <casa/namespace.h> 00039 00040 namespace casa { 00041 00042 class QtColorWidget; 00043 00044 // Common utilities/constants for region shapes. 00045 class RSUtils { 00046 public: 00047 // Returns a new layout with the given parent, and calls setupLayout 00048 // on it; 00049 // <group> 00050 static QHBoxLayout* hlayout(QWidget* parent = NULL); 00051 static QVBoxLayout* vlayout(QWidget* parent = NULL); 00052 // </group> 00053 00054 // Sets up the given layout by setting: 00055 // 1) margins to 0, 00056 // 2) spacing to 3. 00057 static void setupLayout(QLayout* layout); 00058 00059 // Returns a horizontal or vertical line (QFrame). 00060 // <group> 00061 static QWidget* hline(); 00062 static QWidget* vline(); 00063 // </group> 00064 00065 // Returns a new color widget. If margins and spacing are given, they are 00066 // applied to the widget. If a frame is given, the widget is inserted into 00067 // the frame. 00068 static QtColorWidget* colorWidget(bool showButton = false, 00069 String setColor = "", 00070 QWidget* parent = NULL); 00071 00072 00073 // Pixel coordinate system. Used for converting between different 00074 // systems, etc. 00075 static const String PIXEL; 00076 00077 00078 // Returns whether or not the given coordinate system has a direction 00079 // coordinate or not. 00080 // <group> 00081 static bool hasDirectionCoordinate(const CoordinateSystem& cs); 00082 static bool hasDirectionCoordinate(const WorldCanvas* wc) { 00083 return wc != NULL && hasDirectionCoordinate(wc->coordinateSystem()); 00084 } 00085 static bool hasDirectionCoordinate(const WorldCanvasHolder& wch) { 00086 return hasDirectionCoordinate(wch.worldCanvas()->coordinateSystem()); 00087 } 00088 // </group> 00089 00090 // Returns the world system type for the given coordinate system. 00091 static MDirection::Types worldSystem(const CoordinateSystem& cs); 00092 00093 // Returns the world system type for the given WorldCanvas. 00094 static MDirection::Types worldSystem(const WorldCanvas* wc) { 00095 return worldSystem(wc->coordinateSystem()); 00096 } 00097 00098 // Returns the world system type for the given WorldCanvasHolder. 00099 static MDirection::Types worldSystem(const WorldCanvasHolder& wch) { 00100 return worldSystem(wch.worldCanvas()->coordinateSystem()); 00101 } 00102 00103 // Converts between coordinate systems. The result has unit 00104 // RegionShape::UNIT. 00105 static bool convertWCS(const Quantum<Vector<Double> >& from, 00106 MDirection::Types fromSys, 00107 Quantum<Vector<Double> >& to, 00108 MDirection::Types toSys); 00109 00110 // Converts the given coordinates between different systems, using the 00111 // given WorldCanvas and world system (if applicable). Input world values 00112 // are expected to have unit RegionShape::UNIT; output world values always 00113 // have unit RegionShape::UNIT. Methods that have a "wrap" flag will check 00114 // the sign of the values when converting between different world 00115 // coordinate systems, and wrap the values to have the same sign. If 00116 // a String is given, it will be used to record errors when the method 00117 // returns false. 00118 // <group> 00119 static bool worldToPixel(const Quantum<Vector<double> >& worldX, 00120 const Quantum<Vector<double> >& worldY, 00121 Vector<double>& pixelX, Vector<double>& pixelY, 00122 WorldCanvasHolder& wch, MDirection::Types fromSys, 00123 bool wrap = true, String* error = NULL); 00124 00125 static bool pixelToWorld(const Vector<double>& pixelX, 00126 const Vector<double>& pixelY, 00127 Quantum<Vector<double> >& worldX, 00128 Quantum<Vector<double> >& worldY, 00129 WorldCanvasHolder& wch, MDirection::Types toSys, 00130 bool wrap = true, String* error = NULL); 00131 00132 static bool worldToLinear(const Quantum<Vector<double> >& worldX, 00133 const Quantum<Vector<double> >& worldY, 00134 Vector<double>& linearX, Vector<double>& linearY, 00135 WorldCanvasHolder& wch, MDirection::Types fromSys, 00136 bool wrap = true, String* error = NULL); 00137 00138 static bool pixelToLinear(const Vector<double>& pixelX, 00139 const Vector<double>& pixelY, 00140 Vector<double>& linearX, Vector<double>& linearY, 00141 WorldCanvasHolder& wch, String* error = NULL); 00142 00143 static bool linearToScreen(const Vector<double>& linearX, 00144 const Vector<double>& linearY, 00145 Vector<double>& screenX, Vector<double>& screenY, 00146 WorldCanvasHolder& wch, String* error = NULL); 00147 00148 static bool worldToScreen(const Quantum<Vector<double> >& worldX, 00149 const Quantum<Vector<double> >& worldY, 00150 Vector<double>& screenX, Vector<double>& screenY, 00151 WorldCanvasHolder& wch, MDirection::Types fromSys, 00152 bool wrap = true, String* error = NULL) { 00153 Vector<double> linX(worldX.getValue().size()), 00154 linY(worldY.getValue().size()); 00155 return worldToLinear(worldX, worldY, linX, linY, wch, fromSys, wrap, 00156 error) && linearToScreen(linX,linY,screenX,screenY,wch,error); 00157 } 00158 00159 static bool pixelToScreen(const Vector<double>& pixelX, 00160 const Vector<double>& pixelY, 00161 Vector<double>& screenX, Vector<double>& screenY, 00162 WorldCanvasHolder& wch, String* error = NULL) { 00163 Vector<double> linX(pixelX.size()), linY(pixelY.size()); 00164 return pixelToLinear(pixelX, pixelY, linX, linY, wch, error) && 00165 linearToScreen(linX, linY, screenX, screenY, wch, error); 00166 } 00167 00168 static bool screenToLinear(const Vector<double>& screenX, 00169 const Vector<double>& screenY, 00170 Vector<double>& linearX, Vector<double>& linearY, 00171 WorldCanvasHolder& wch, String* error = NULL); 00172 00173 static bool linearToWorld(const Vector<double>& linearX, 00174 const Vector<double>& linearY, 00175 Quantum<Vector<double> >& worldX, 00176 Quantum<Vector<double> >& worldY, 00177 WorldCanvasHolder& wch, MDirection::Types toSys, 00178 const vector<int>& xSign,const vector<int>& ySign, 00179 bool wrap = true, String* error = NULL); 00180 00181 static bool linearToWorld(const Vector<double>& linearX, 00182 const Vector<double>& linearY, 00183 Quantum<Vector<double> >& worldX, 00184 Quantum<Vector<double> >& worldY, 00185 WorldCanvasHolder& wch, MDirection::Types toSys, 00186 String* error = NULL) { 00187 return linearToWorld(linearX, linearY, worldX, worldY, wch, toSys, 00188 vector<int>(), vector<int>(), false, error); 00189 } 00190 00191 static bool linearToPixel(const Vector<double>& linearX, 00192 const Vector<double>& linearY, 00193 Vector<double>& pixelX, Vector<double>& pixelY, 00194 WorldCanvasHolder& wch, String* error = NULL); 00195 00196 static bool screenToWorld(const Vector<double>& screenX, 00197 const Vector<double>& screenY, 00198 Quantum<Vector<double> >& worldX, 00199 Quantum<Vector<double> >& worldY, 00200 WorldCanvasHolder& wch, MDirection::Types toSys, 00201 String* error = NULL) { 00202 Vector<double> linX(screenX.size()), linY(screenY.size()); 00203 return screenToLinear(screenX, screenY, linX, linY, wch) && 00204 linearToWorld(linX, linY, worldX, worldY, wch, toSys, 00205 vector<int>(), vector<int>(), false, error); 00206 } 00207 00208 static bool screenToWorld(const Vector<double>& screenX, 00209 const Vector<double>& screenY, 00210 Quantum<Vector<double> >& worldX, 00211 Quantum<Vector<double> >& worldY, 00212 WorldCanvasHolder& wch, MDirection::Types toSys, 00213 const vector<int>& xSign, const vector<int>& ySign, 00214 String* error = NULL) { 00215 Vector<double> linX(screenX.size()), linY(screenY.size()); 00216 return screenToLinear(screenX, screenY, linX, linY, wch) && 00217 linearToWorld(linX, linY, worldX, worldY, wch, toSys, 00218 xSign, ySign, true, error); 00219 } 00220 00221 static bool screenToPixel(const Vector<double>& screenX, 00222 const Vector<double>& screenY, 00223 Vector<double>& pixelX, Vector<double>& pixelY, 00224 WorldCanvasHolder& wch, String* error = NULL) { 00225 Vector<double> linX(screenX.size()), linY(screenY.size()); 00226 return screenToLinear(screenX, screenY, linX, linY, wch, error) && 00227 linearToPixel(linX, linY, pixelX, pixelY, wch, error); 00228 } 00229 // </group> 00230 00231 00232 // Appends the given message to the given stream, if the stream does not 00233 // already contain an identical message. Messages are newline-separated. 00234 // <group> 00235 static void appendUniqueMessage(stringstream& ss, const String& message); 00236 static void appendUniqueMessage(stringstream* ss, const String& message) { 00237 if(ss != NULL) appendUniqueMessage(*ss, message); 00238 } 00239 static void appendUniqueMessage(String& ss, const String& message); 00240 static void appendUniqueMessage(String* ss, const String& message) { 00241 if(ss != NULL) appendUniqueMessage(*ss, message); 00242 } 00243 // </group> 00244 }; 00245 00246 00247 // A widget that lets the user select a color: either one from a list, or a 00248 // custom color. 00249 class QtColorWidget : public QHBoxLayout { 00250 Q_OBJECT 00251 00252 public: 00253 // Constructor that uses default colors. If setText is nonempty, the 00254 // chooser is set to the given. If showButton is true, a "pick" button 00255 // is shown for picking colors. 00256 QtColorWidget(bool showButton = false, String setText = "", 00257 QWidget* parent = NULL); 00258 00259 // Constructor that uses the given colors. If setText is nonempty, the 00260 // chooser is set to the given. If showButton is true, a "pick" button 00261 // is shown for picking colors. 00262 QtColorWidget(const vector<String>& colors, bool showButton = false, 00263 String setText = "", QWidget* parent = NULL); 00264 00265 // Destructor. 00266 ~QtColorWidget(); 00267 00268 // Returns the color that the user has chosen. This will either be from 00269 // the initial list, or in "#000000" form (see QColor::name()). 00270 String getColor() const; 00271 00272 // Sets the displayed color to the given. If the color is in the colors 00273 // list, that index will be selected -- otherwise it will be entered in 00274 // the custom color box. 00275 void setColor(const String& color); 00276 00277 00278 // Returns default colors. 00279 static vector<String> defaultColors() { 00280 static vector<String> v(9); 00281 v[0] = "white"; v[1] = "black"; 00282 v[2] = "red"; v[3] = "green"; 00283 v[4] = "blue"; v[5] = "cyan"; 00284 v[6] = "magenta"; v[7] = "yellow"; 00285 v[8] = "gray"; 00286 return v; 00287 } 00288 00289 private: 00290 // Color chooser. 00291 QComboBox* m_chooser; 00292 00293 // Custom color. 00294 QLineEdit* m_edit; 00295 00296 // Picker button. 00297 QPushButton* m_button; 00298 00299 // Initializes GUI members. 00300 void init(const vector<String>& colors, const String& setText, 00301 bool showButton); 00302 00303 private slots: 00304 // For when the user picks a different color in the chooser. 00305 void colorChanged(int index); 00306 00307 // For when the user clicks the "pick" button. 00308 void colorPick(); 00309 }; 00310 00311 00312 // Convenience class for the different units available for coordinates/sizes. 00313 // Two modes: quantum and HMS/DMS (distinguished by the "isQuantum" flag). 00314 // <ol><li>Quantum: consists of a value and a unit, stored in "val".</li> 00315 // <li>HMS/DMS: consists of three values and two flags. Hours/degrees 00316 // are stored in "hOrD", minutes are stored in "min", and seconds are 00317 // stored in "sec". The "isHMS" flag distinguishes between HMS and 00318 // DMS. The "isMinusZero" flag is used when "hOrD" is zero, but the 00319 // whole value is negative.</li></ol> 00320 class RSValue { 00321 public: 00322 RSValue(double d = 0) : isQuantum(true), isHMS(false), isMinusZero(false), 00323 val(d, DEG), hOrD(0), min(0), sec(0) { } 00324 00325 RSValue(double d, Unit u) : isQuantum(true), isHMS(false), 00326 isMinusZero(false), val(d, u), hOrD(0), min(0), sec(0) { } 00327 00328 RSValue(bool hms, long hd, long m, double s, bool minus = false) : 00329 isQuantum(false), isHMS(hms), isMinusZero(minus), val(0, "_"), 00330 hOrD(hd), min(m), sec(s) { } 00331 00332 ~RSValue() { } 00333 00334 bool isQuantum; 00335 bool isHMS; 00336 bool isMinusZero; 00337 00338 Quantum<double> val; 00339 long hOrD; 00340 long min; 00341 double sec; 00342 00343 00344 // Conversion methods/constants // 00345 00346 // Units constants. 00347 // <group> 00348 static const String DEG; 00349 static const String RAD; 00350 static const String ARCSEC; 00351 static const String ARCMIN; 00352 static const String HMS; 00353 static const String DMS; 00354 // </group> 00355 00356 // Converts the value in the given QString in the given units to the given 00357 // RSValue. The output RSValue is in degrees. fromUnits should either be: 00358 // 1) HMS or DMS constants, 00359 // 2) a relevant Unit. 00360 static bool convertBetween(const QString& from, const String& fromUnits, 00361 RSValue& to); 00362 00363 // Converts the value in the given RSValue to the given QString, using the 00364 // given precision for the doubles. 00365 static bool convertBetween(const RSValue& from, QString& to, 00366 int precision = -1); 00367 00368 // Converts the value in the given RSValue to the give RSValue which uses 00369 // the given units. toUnits should either be: 00370 // 1) HMS or DMS constants, 00371 // 2) a relevant Unit. 00372 static bool convertBetween(const RSValue& from, RSValue& to, 00373 const String& toUnits); 00374 }; 00375 00376 00377 // Convenience class for a String, bool, or double. 00378 class RSOption { 00379 public: 00380 // String constructor. 00381 RSOption(const String& str); 00382 00383 // Bool constructor. 00384 RSOption(bool b = false); 00385 00386 // Double constructor. 00387 RSOption(double d); 00388 00389 // String vector constructor. 00390 RSOption(const vector<String>& v); 00391 00392 // Destructor. 00393 ~RSOption(); 00394 00395 // Type methods. 00396 // <group> 00397 bool isString() const; 00398 bool isBool() const; 00399 bool isDouble() const; 00400 bool isStringArray() const; 00401 // </group> 00402 00403 // Value methods. 00404 // <group> 00405 const String& asString() const; 00406 bool asBool() const; 00407 double asDouble() const; 00408 const vector<String>& asStringArray() const; 00409 // </group> 00410 00411 // Operators. 00412 // <group> 00413 bool operator==(const RSOption& other); 00414 bool operator!=(const RSOption& other); 00415 RSOption& operator=(const String& str); 00416 RSOption& operator=(bool b); 00417 RSOption& operator=(double d); 00418 RSOption& operator=(const vector<String>& v); 00419 // </group> 00420 00421 private: 00422 bool m_isString; 00423 String m_string; 00424 bool m_isBool; 00425 bool m_bool; 00426 bool m_isDouble; 00427 double m_double; 00428 bool m_isStringArray; 00429 vector<String> m_stringArray; 00430 }; 00431 00432 00433 // A "handle" is a four-point structure (usually a rectangle) that describes 00434 // the boundaries in screen pixels that a RegionShape takes on a canvas. In 00435 // the future, this will be used for selecting/editing/moving/resizing shapes 00436 // on the canvas using the mouse. 00437 class RSHandle { 00438 public: 00439 // Defaults. 00440 // <group> 00441 static const int DEFAULT_MARKER_HEIGHT; 00442 static const String DEFAULT_MARKER_COLOR; 00443 static const Display::Marker DEFAULT_MARKER_TYPE; 00444 // </group> 00445 00446 // Constructor which makes an invalid handle. 00447 RSHandle(); 00448 00449 // Constructor which takes x and y vectors. x and y MUST be length 4 or 00450 // the handle is invalid. 00451 RSHandle(const vector<double>& x, const vector<double>& y, 00452 int markerHeight = DEFAULT_MARKER_HEIGHT, 00453 const String& markerColor = DEFAULT_MARKER_COLOR, 00454 Display::Marker markerType = DEFAULT_MARKER_TYPE); 00455 00456 // Constructor which takes x and y Vectors. x and y MUST be length 4 or 00457 // the handle is invalid. 00458 RSHandle(const Vector<double>& x, const Vector<double>& y, 00459 int markerHeight = DEFAULT_MARKER_HEIGHT, 00460 const String& markerColor = DEFAULT_MARKER_COLOR, 00461 Display::Marker markerType = DEFAULT_MARKER_TYPE); 00462 00463 // Destructor. 00464 ~RSHandle(); 00465 00466 // Gets/sets the marker height/color/type. 00467 // <group> 00468 int getMarkerHeight() const { return m_markerHeight; } 00469 void setMarkerHeight(int height); 00470 String getMarkerColor() const { return m_markerColor; } 00471 void setMarkerColor(const String& color); 00472 Display::Marker getMarkerType() const { return m_markerType; } 00473 void setMarkerType(Display::Marker type); 00474 // </group> 00475 00476 // Returns whether the handle is valid (has four valid points) or not. 00477 bool isValid() const { return m_isValid; } 00478 00479 // Returns true if the handle is valid and the given point is inside. 00480 bool containsPoint(double x, double y) const; 00481 00482 // Gets the handle vertices coordinates and returns whether the operation 00483 // succeeded or not (i.e. if the handle is valid). If it succeeded, x and 00484 // y will be resize to be size 4 if necessary. 00485 bool getVertices(vector<double>& x, vector<double>& y) const; 00486 00487 // Draws the handles on the given canvas and returns whether the operation 00488 // succeeded or not (i.e. if the handle is valid). If valid, each of the 00489 // four points is drawn as a marker. 00490 bool draw(PixelCanvas* canvas) const; 00491 00492 private: 00493 bool m_isValid; 00494 vector<double> m_x, m_y; 00495 int m_markerHeight; 00496 String m_markerColor; 00497 Display::Marker m_markerType; 00498 }; 00499 00500 } 00501 00502 #endif /* RSUTILS_H_ */