casa
$Rev:20696$
|
00001 //# DS9FileReader.h: Implementation for DS9 region file reader etc. 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 DS9FILEREADER_H_ 00028 #define DS9FILEREADER_H_ 00029 00030 #include <QStringList> 00031 00032 #include <display/RegionShapes/RSFileReaderWriter.h> 00033 #include <coordinates/Coordinates/Coordinate.h> 00034 #include <display/DisplayDatas/DrawingDisplayData.h> 00035 00036 #include <casa/namespace.h> 00037 00038 namespace casa { 00039 00040 // Contains common enums, constants, and methods for DS9 files. 00041 class DS9 { 00042 public: 00043 // Units. 00044 // <group> 00045 enum CoordinateUnit { 00046 Degrees, Radians, PhysicalPixels, ImagePixels, HMS, DMS, ArcSec, 00047 ArcMin, UNSET 00048 }; 00049 00050 static const String FILE_ARCMIN; 00051 static const String FILE_ARCSEC; 00052 static const String FILE_DEGREES; 00053 static const String FILE_DELIMITER; 00054 static const String FILE_DMS_D; 00055 static const String FILE_DMS_M; 00056 static const String FILE_DMS_S; 00057 static const String FILE_HMS_H; 00058 static const String FILE_HMS_M; 00059 static const String FILE_HMS_S; 00060 static const String FILE_IMAGE_PIXELS; 00061 static const String FILE_PHYSICAL_PIXELS; 00062 static const String FILE_RADIANS; 00063 00064 static CoordinateUnit coordinateUnit(const String& unit) { 00065 if(unit == FILE_ARCMIN) return ArcMin; 00066 else if(unit == FILE_ARCSEC) return ArcSec; 00067 else if(unit == FILE_DEGREES) return Degrees; 00068 else if(unit == FILE_IMAGE_PIXELS) return ImagePixels; 00069 else if(unit == FILE_PHYSICAL_PIXELS) return PhysicalPixels; 00070 else if(unit == FILE_RADIANS) return Radians; 00071 00072 else return UNSET; 00073 } 00074 00075 static const QRegExp REGEXP_HDMS; 00076 static const QRegExp REGEXP_HMS; 00077 static const QRegExp REGEXP_DMS; 00078 static const QRegExp REGEXP_NUMSYS; 00079 // </group> 00080 00081 00082 // Coordinate systems. 00083 // <group> 00084 enum CoordinateSystem { 00085 Physical, Image, FK4, FK5, Galactic, Ecliptic, Linear, Amplifier, 00086 Detector 00087 }; 00088 00089 static CoordinateSystem defaultCoordinateSystem() { return Physical; } 00090 00091 static const QString FILE_AMPLIFIER; 00092 static const QString FILE_B1950; 00093 static const QString FILE_DETECTOR; 00094 static const QString FILE_ECLIPTIC; 00095 static const QString FILE_FK4; 00096 static const QString FILE_FK5; 00097 static const QString FILE_GALACTIC; 00098 static const QString FILE_ICRS; 00099 static const QString FILE_IMAGE; 00100 static const QString FILE_J2000; 00101 static const QString FILE_LINEAR; 00102 static const QString FILE_PHYSICAL; 00103 00104 static QStringList coordinateSystemFirstWords() { 00105 QStringList list; 00106 list << FILE_AMPLIFIER << FILE_B1950 << FILE_DETECTOR; 00107 list << FILE_ECLIPTIC << FILE_FK4 << FILE_FK5 << FILE_GALACTIC; 00108 list << FILE_ICRS << FILE_IMAGE << FILE_J2000 << FILE_LINEAR; 00109 list << FILE_PHYSICAL; 00110 return list; 00111 } 00112 00113 static CoordinateSystem coordinateSystem(const QString& cs) { 00114 QString c = cs.toLower(); 00115 if(c == FILE_AMPLIFIER) return Amplifier; 00116 else if(c == FILE_B1950 || c == FILE_FK4) return FK4; 00117 else if(c == FILE_DETECTOR) return Detector; 00118 else if(c == FILE_ECLIPTIC) return Ecliptic; 00119 else if(c == FILE_FK5 || c == FILE_J2000 || c == FILE_ICRS) return FK5; 00120 else if(c == FILE_GALACTIC) return Galactic; 00121 else if(c == FILE_IMAGE) return Image; 00122 else if(c == FILE_LINEAR) return Linear; 00123 else if(c == FILE_PHYSICAL) return Physical; 00124 00125 else return defaultCoordinateSystem(); 00126 } 00127 00128 static QString coordinateSystem(CoordinateSystem c) { 00129 switch(c) { 00130 case Physical: return FILE_PHYSICAL; 00131 case Image: return FILE_IMAGE; 00132 case FK4: return FILE_FK4; 00133 case FK5: return FILE_FK5; 00134 case Galactic: return FILE_GALACTIC; 00135 case Ecliptic: return FILE_ECLIPTIC; 00136 case Linear: return FILE_LINEAR; 00137 case Amplifier: return FILE_AMPLIFIER; 00138 case Detector: return FILE_DETECTOR; 00139 00140 default: return ""; 00141 } 00142 } 00143 // </group> 00144 00145 00146 // Regions. 00147 // <group> 00148 enum RegionType { 00149 Circle, Annulus, Ellipse, EllipseAnnulus, Box, BoxAnnulus, Polygon, 00150 Line, Vector, Text, Ruler, CirclePoint, BoxPoint, DiamondPoint, 00151 CrossPoint, XPoint, ArrowPoint, BoxCirclePoint, Compass, Projection, 00152 Panda, EllipticalPanda, BoxPanda, Composite 00153 }; 00154 00155 // region types, first word 00156 static const QString FILE_ANNULUS; 00157 static const QString FILE_ARROW; // only for "arrow point" 00158 static const QString FILE_BOX; 00159 static const QString FILE_BOXCIRCLE; // only for "boxcircle point" 00160 static const QString FILE_BPANDA; 00161 static const QString FILE_CIRCLE; 00162 static const QString FILE_COMPASS; 00163 static const QString FILE_COMPOSITE; 00164 static const QString FILE_CROSS; // only for "cross point" 00165 static const QString FILE_DIAMOND; // only for "diamond point" 00166 static const QString FILE_ELLIPSE; 00167 static const QString FILE_EPANDA; 00168 static const QString FILE_LINE; 00169 static const QString FILE_PANDA; 00170 static const QString FILE_POINT; 00171 static const QString FILE_POLYGON; 00172 static const QString FILE_PROJECTION; 00173 static const QString FILE_RULER; 00174 static const QString FILE_TEXT; 00175 static const QString FILE_VECTOR; 00176 static const QString FILE_X; // only for "x point" 00177 00178 static QStringList regionFirstWords() { 00179 QStringList list; 00180 list << FILE_ANNULUS << FILE_ARROW << FILE_BOX << FILE_BOXCIRCLE; 00181 list << FILE_BPANDA << FILE_CIRCLE << FILE_COMPASS << FILE_COMPOSITE; 00182 list << FILE_CROSS << FILE_DIAMOND << FILE_ELLIPSE << FILE_EPANDA; 00183 list << FILE_LINE << FILE_PANDA << FILE_POINT << FILE_POLYGON; 00184 list << FILE_PROJECTION << FILE_RULER << FILE_TEXT << FILE_VECTOR; 00185 list << FILE_X; 00186 return list; 00187 } 00188 00189 static QString regionType(RegionType type) { 00190 switch(type) { 00191 case Circle: return FILE_CIRCLE; 00192 case Annulus: return FILE_ANNULUS; 00193 case Ellipse: case EllipseAnnulus:return FILE_ELLIPSE; 00194 case Box: case BoxAnnulus: return FILE_BOX; 00195 case Polygon: return FILE_POLYGON; 00196 case Line: return FILE_LINE; 00197 case Vector: return FILE_VECTOR; 00198 case Text: return FILE_TEXT; 00199 case Ruler: return FILE_RULER; 00200 case CirclePoint: return FILE_CIRCLE + " " + FILE_POINT; 00201 case BoxPoint: return FILE_BOX + " " + FILE_POINT; 00202 case DiamondPoint: return FILE_DIAMOND + " " + FILE_POINT; 00203 case CrossPoint: return FILE_CROSS + " " + FILE_POINT; 00204 case XPoint: return FILE_X + " " + FILE_POINT; 00205 case ArrowPoint: return FILE_ARROW + " " + FILE_POINT; 00206 case BoxCirclePoint: return FILE_BOXCIRCLE+ " " +FILE_POINT; 00207 case Compass: return FILE_COMPASS; 00208 case Projection: return FILE_PROJECTION; 00209 case Panda: return FILE_PANDA; 00210 case EllipticalPanda: return FILE_EPANDA; 00211 case BoxPanda: return FILE_BPANDA; 00212 case Composite: return FILE_COMPOSITE; 00213 00214 default: return ""; 00215 } 00216 } 00217 00218 static QString pointType(RegionType type) { 00219 switch(type) { 00220 case CirclePoint: return FILE_CIRCLE; 00221 case BoxPoint: return FILE_BOX; 00222 case DiamondPoint: return FILE_DIAMOND; 00223 case CrossPoint: return FILE_CROSS; 00224 case XPoint: return FILE_X; 00225 case ArrowPoint: return FILE_ARROW; 00226 case BoxCirclePoint: return FILE_BOXCIRCLE; 00227 00228 default: return ""; 00229 } 00230 } 00231 // </group> 00232 00233 // DS9 defaults. 00234 // <group> 00235 static const int MARKER_SIZE; 00236 static const int ARROW_SIZE; 00237 // </group> 00238 00239 // Miscellaneous. 00240 // <group> 00241 static const QString FILE_COMMENT; 00242 static const QString FILE_COMPOSITE_OR; 00243 static const QString FILE_EQUAL; 00244 static const QString FILE_GLOBAL; 00245 static const QString FILE_LINESEP; 00246 static const QString FILE_MINUS; 00247 static const QString FILE_PLUS; 00248 static const QString FILE_TEXT_END1; 00249 static const QString FILE_TEXT_END2; 00250 static const QString FILE_TEXT_END3; 00251 static const QString FILE_TEXT_START1; 00252 static const QString FILE_TEXT_START2; 00253 static const QString FILE_TEXT_START3; 00254 // </group> 00255 }; 00256 00257 00258 // Class to represent a single coordinate (value + unit). 00259 class DS9Coordinate { 00260 public: 00261 // Constructor which takes a system and a unit. 00262 DS9Coordinate(DS9::CoordinateSystem s, DS9::CoordinateUnit u = DS9::UNSET); 00263 00264 // Destructor. 00265 ~DS9Coordinate(); 00266 00267 00268 // Sets the coordinate system to the given. 00269 void set(DS9::CoordinateSystem system); 00270 00271 // Sets the coordinate unit to the given. 00272 void set(DS9::CoordinateUnit unit); 00273 00274 // Sets the single value to the given. 00275 void set(double value); 00276 00277 // Sets the HMS/DMS value to the given. minusZero is used when the first 00278 // value is zero, but the whole value is negative. 00279 void set(double val1, double val2, double val3, bool minusZero = false); 00280 00281 // Returns the coordinate system. 00282 DS9::CoordinateSystem system() const; 00283 00284 // Returns the unit. 00285 DS9::CoordinateUnit unit() const; 00286 00287 // Returns the first value. No conversion is used. 00288 double value() const; 00289 00290 // Returns the value(s). Size will be 1 for normal coordinates, 3 for 00291 // HMS/DMS. No conversion is used. 00292 vector<double> values() const; 00293 00294 // Returns 1 for normal coordinates or 3 for HMS/DMS. 00295 unsigned int size() const; 00296 00297 // Returns true if this coordinate is valid, false otherwise. If the 00298 // coordinate is invalid (such as an unset unit), the method will attempt 00299 // to fix it. 00300 bool isValid() const; 00301 00302 // Returns a String version for use with DS9Region::toPrintString. 00303 String toPrintString() const; 00304 00305 // Returns the value in degrees. 00306 double toDegrees() const; 00307 00308 private: 00309 DS9::CoordinateSystem m_system; // coordinate system 00310 DS9::CoordinateUnit m_unit; // coordinate unit 00311 vector<double> m_values; // values 00312 bool m_minusZero; // minusZero flag for HMS/DMS 00313 }; 00314 00315 00316 // Holds information for read DS9 regions. A DS9Region consists of a type, 00317 // a list of coordinates, a coordinate system, and a set of properties. 00318 // Composite regions also have a list of children regions. For simplicity, 00319 // properties are either bool properties or String properties. All properties 00320 // have defaults which are set during construction. 00321 class DS9Region /*: public RFRegion*/ { 00322 //friend class DS9RegionFileReader; 00323 00324 public: 00325 // Public Static Members/Methods // 00326 00327 // Properties. 00328 // <group> 00329 static const String PROP_BACKGROUND; 00330 static const String PROP_COLOR; 00331 static const String PROP_COMPASS; 00332 static const String PROP_COMPASS_ELABEL; 00333 static const String PROP_COMPASS_NLABEL; 00334 static const String PROP_COMPOSITE; 00335 static const String PROP_DASH; 00336 static const String PROP_DASHLIST; 00337 static const String PROP_DELETE; 00338 static const String PROP_EDIT; 00339 static const String PROP_FIXED; 00340 static const String PROP_FONT; 00341 static const String PROP_HIGHLITE; 00342 static const String PROP_INCLUDE; 00343 static const String PROP_LINE; 00344 static const String PROP_MARKER_SIZE; 00345 static const String PROP_MOVE; 00346 static const String PROP_ROTATE; 00347 static const String PROP_RULER; 00348 static const String PROP_SELECT; 00349 static const String PROP_SOURCE; 00350 static const String PROP_TAG; 00351 static const String PROP_TEXT; 00352 static const String PROP_TEXTANGLE; 00353 static const String PROP_VECTOR; 00354 static const String PROP_WIDTH; 00355 // </group> 00356 00357 // Note: when adding new properties: 00358 // 1) add to properties(), DS9RegionFileWriter::globalProperties() (if 00359 // necessary) 00360 // 2) add to isBoolProperty() 00361 // 3) for strings, add to valueIsValid 00362 // 4) add to defaultBoolValue() or defaultStringValue() 00363 // 5) if special printing is required, edit toPrintString, 00364 // DS9RegionFileWriter::writeGlobals() 00365 // 6) if special input is required, edit 00366 // DS9RegionFileReader::readProperties() 00367 00368 // Returns all valid properties. 00369 static vector<String> properties() { 00370 static vector<String> v(26); 00371 v[0] = PROP_INCLUDE; v[1] = PROP_TEXT; 00372 v[2] = PROP_COLOR; v[3] = PROP_FONT; 00373 v[4] = PROP_SELECT; v[5] = PROP_EDIT; 00374 v[6] = PROP_MOVE; v[7] = PROP_ROTATE; 00375 v[8] = PROP_DELETE; v[9] = PROP_FIXED; 00376 v[10] = PROP_LINE; v[11] = PROP_RULER; 00377 v[12] = PROP_SOURCE; v[13] = PROP_BACKGROUND; 00378 v[14] = PROP_TEXTANGLE; v[15] = PROP_WIDTH; 00379 v[16] = PROP_MARKER_SIZE; v[17] = PROP_HIGHLITE; 00380 v[18] = PROP_TAG; v[19] = PROP_VECTOR; 00381 v[20] = PROP_COMPASS; v[21] = PROP_COMPASS_NLABEL; 00382 v[22] = PROP_COMPASS_ELABEL; v[23] = PROP_COMPOSITE; 00383 v[24] = PROP_DASH; v[25] = PROP_DASHLIST; 00384 return v; 00385 } 00386 00387 // Returns true if the given String is a valid property, false otherwise. 00388 static bool isProperty(const String& prp) { 00389 static vector<String> v = properties(); 00390 for(unsigned int i = 0; i < v.size(); i++) if(v[i] == prp) return true; 00391 return false; 00392 } 00393 00394 // Returns true if the given String is a valid bool property, false 00395 // otherwise. 00396 static bool isBoolProperty(const String& property) { 00397 if(!isProperty(property)) return false; 00398 else return property != PROP_TEXT && property != PROP_COLOR && 00399 property != PROP_FONT && property != PROP_LINE && 00400 property != PROP_RULER && property != PROP_TEXTANGLE && 00401 property != PROP_WIDTH && property != PROP_MARKER_SIZE && 00402 property != PROP_TAG && property != PROP_COMPASS && 00403 property != PROP_COMPASS_NLABEL && 00404 property != PROP_COMPASS_ELABEL && 00405 property != PROP_DASHLIST; 00406 } 00407 00408 // Returns true if the given value is valid for the given String property 00409 // and region type, false otherwise. 00410 static bool valueIsValid(const String& property, const String& value, 00411 DS9::RegionType type) { 00412 if(property == PROP_COLOR) { 00413 if(value == "white" || value == "black" || value == "red" || 00414 value == "green" || value == "blue" || value == "cyan" || 00415 value == "magenta" || value == "yellow" || value == "gray" || 00416 value == "grey") return true; 00417 QString v(value.c_str()); 00418 return (v.size() == 7 && 00419 v.indexOf(QRegExp("#(?:\\d|[A-F]|[a-f]){6}")) == 0) || 00420 (v.size() == 6 && 00421 v.indexOf(QRegExp("(?:\\d|[A-F]|[a-f]){6}")) == 0); 00422 } else if(property == PROP_FONT) { 00423 QStringList split = QString(value.c_str()).split(QRegExp("\\s+")); 00424 if(split.size() < 3) return false; 00425 bool valid; 00426 split[1].toInt(&valid); 00427 if(!valid) return false; 00428 return split[2] == "bold" || split[2] == "normal" || 00429 split[2] == "italic" || split[2] == "italics"; 00430 } else if(property == PROP_LINE) { 00431 QStringList split = QString(value.c_str()).split(QRegExp("\\s+")); 00432 if(split.size() < 2) return false; 00433 return (split[0] == "0" || split[0] == "1") && 00434 (split[1] == "0" || split[1] == "1"); 00435 } else if(property == PROP_DASHLIST) { 00436 QStringList split = QString(value.c_str()).split(QRegExp("\\s+")); 00437 if(split.size() < 2) return false; 00438 bool valid; 00439 split[0].toUInt(&valid); 00440 if(!valid) return false; 00441 split[1].toUInt(&valid); 00442 return valid; 00443 } else if(property == PROP_RULER) { 00444 QStringList split = QString(value.c_str()).split(QRegExp("\\s+")); 00445 if(split.size() < 2) return false; 00446 split[0] = split[0].toLower(); 00447 split[1] = split[1].toLower(); 00448 return DS9::coordinateSystemFirstWords().contains(split[0]) && 00449 (split[1] == "image" || split[1] == "physical" || 00450 split[1] == "degrees" || split[1] == "arcmin" || 00451 split[1] == "arcsec"); 00452 } else if(property == PROP_TEXTANGLE) { 00453 bool valid; 00454 QString(value.c_str()).toDouble(&valid); 00455 return type == DS9::Text && valid; 00456 } else if(property == PROP_WIDTH) { 00457 bool valid; 00458 QString(value.c_str()).toDouble(&valid); 00459 return valid; 00460 } else if(property == PROP_MARKER_SIZE) { 00461 bool valid; 00462 QString(value.c_str()).toInt(&valid); 00463 return valid; 00464 } else if(property == PROP_COMPASS) { 00465 return DS9::coordinateSystemFirstWords().contains(value.c_str(), 00466 Qt::CaseInsensitive); 00467 } else return !isBoolProperty(property); 00468 } 00469 00470 // Returns the default value for the given bool property. 00471 static bool defaultBoolValue(const String& property) { 00472 if(property == PROP_INCLUDE) return true; 00473 else if(property == PROP_SELECT) return true; 00474 else if(property == PROP_EDIT) return true; 00475 else if(property == PROP_MOVE) return true; 00476 else if(property == PROP_ROTATE) return true; 00477 else if(property == PROP_DELETE) return true; 00478 else if(property == PROP_FIXED) return false; 00479 else if(property == PROP_SOURCE) return true; 00480 else if(property == PROP_BACKGROUND) return false; 00481 else if(property == PROP_HIGHLITE) return true; 00482 else if(property == PROP_VECTOR) return true; 00483 else if(property == PROP_COMPOSITE) return false; 00484 else if(property == PROP_DASH) return false; 00485 else return false; 00486 } 00487 00488 // Returns the default value for the given String property. 00489 static String defaultStringValue(const String& property) { 00490 if(property == PROP_TEXT) return ""; 00491 else if(property == PROP_COLOR) return "green"; 00492 else if(property == PROP_FONT) return "helvetica 10 normal"; 00493 else if(property == PROP_LINE) return "0 0"; 00494 else if(property == PROP_RULER) return "pixels"; 00495 else if(property == PROP_TEXTANGLE) return "0"; 00496 else if(property == PROP_WIDTH) return "1"; 00497 else if(property == PROP_MARKER_SIZE) 00498 return String::toString(DS9::MARKER_SIZE); 00499 else if(property == PROP_TAG) return ""; 00500 else if(property == PROP_COMPASS) return "image"; 00501 else if(property == PROP_COMPASS_NLABEL) return "N"; 00502 else if(property == PROP_COMPASS_ELABEL) return "E"; 00503 else if(property == PROP_DASHLIST) return "8 3"; 00504 else return ""; 00505 } 00506 00507 00508 // Non-Static // 00509 00510 // Constructor, which types a type and a coordinate system. 00511 DS9Region(DS9::RegionType type, DS9::CoordinateSystem coordSys); 00512 00513 // Destructor. 00514 ~DS9Region(); 00515 00516 00517 // Returns a human-readable representation of this region. 00518 String toPrintString() const; 00519 00520 // Returns a name. 00521 String name() const; 00522 00523 // Converts this region to a RegionShape. Not all DS9 region types are 00524 // supported and thus this may return NULL. For unsupported regions, see 00525 // cookbook documentation. 00526 RegionShape* toRegionShape() const; 00527 00528 00529 // Returns the region type. 00530 DS9::RegionType type() const; 00531 00532 // Sets/adds the given properties to this region's. Returns false if an 00533 // error occured. 00534 bool setProperties(const RecordInterface& properties); 00535 00536 // Defines the given bool property with the given value. Returns false if 00537 // the given property is invalid. 00538 bool define(const String& property, bool value); 00539 00540 // Defines the given String property with the given value. Returns false 00541 // if the given property or value is invalid. 00542 bool define(const String& property, const String& value); 00543 00544 // Returns true if the given property is defined, false otherwise. 00545 bool isDefined(const String& property); 00546 00547 // Returns the value for the given bool property. 00548 bool boolValue(const String& property); 00549 00550 // Returns the String value for the given String property. 00551 String stringValue(const String& property); 00552 00553 // Adds the given coordinate to the region. 00554 void pushCoordinate(const DS9Coordinate& coord); 00555 00556 // Adds the given region to this composite region (does nothing for non- 00557 // composite regions). 00558 void pushCompositeRegion(const DS9Region& region); 00559 00560 // Returns true if this region's coordinates are valid, false otherwise. 00561 // If the coordinates are invalid, this method will attempt to fix them 00562 // first. 00563 bool checkCoordinates(); 00564 00565 // Returns true if this region's properties are valid, false otherwise. 00566 // If the properties are invalid, this method will attempt to fix them 00567 // first. 00568 bool checkProperties(); 00569 00570 // Returns the last error found during toRegionShape(). This error is only 00571 // valid if toRegionShape() returns NULL which indicates an error was 00572 // encountered. 00573 const RFError& lastError() const; 00574 00575 private: 00576 DS9::RegionType m_type; // Region type. 00577 DS9::CoordinateSystem m_system; // Region coordinate system. 00578 vector<DS9Coordinate> m_coords; // Region coordinates. 00579 Record m_props; // Region properties. 00580 vector<DS9Region> m_compositeRegions; // Composite children. 00581 00582 // Last encountered error during toRegionShape. 00583 RFError m_lastError; 00584 00585 // Convenience method for setting the last error during toRegionShape. 00586 void setError(const String& error, bool isFatal = false) const; 00587 }; 00588 00589 00590 // Implementation of RSFileReader for DS9 regions. 00591 class DS9FileReader : public RSFileReader { 00592 public: 00593 // Constructor. 00594 DS9FileReader(); 00595 00596 // Destructor. 00597 ~DS9FileReader(); 00598 00599 00600 // RSFileReader methods // 00601 00602 // Implements RSFileReader::read. 00603 bool read(vector<RegionShape*>& shapes); 00604 00605 private: 00606 // Whether a coordinate system has been set in the file, and what it is. 00607 pair<DS9::CoordinateSystem, bool> m_nextSystem; 00608 00609 // Read regions. 00610 vector<DS9Region> m_regions; 00611 00612 // Current read global properties. 00613 Record m_globals; 00614 00615 00616 // Processes the given line and returns whether an error occurred or not. 00617 // If an error occurred, the details are appended to invalid. 00618 bool processLine(const QString& line, stringstream& invalid); 00619 00620 // Processes the given region and returns whether an error occurred or not. 00621 // If an error occurred, the details are appended to invalid. line should 00622 // contain the comma-, parentheses-, or whitespace-separated text before 00623 // the comment symbol, while "comment" should contain all text after the 00624 // comment symbol. The include flag is used to set the include property. 00625 bool processRegion(QStringList& line, QString& comment, 00626 stringstream& invalid, bool include = true); 00627 00628 // Processes the given coordinate system and returns whether an error 00629 // occurred or not. If an error occurred, the details are appended to 00630 // invalid. 00631 bool processCoordSys(QString& line, stringstream& invalid); 00632 00633 // Processes the given global line and returns whether an error occurred or 00634 // not. If an error occurred, the details are appended to invalid. 00635 bool processGlobal(QString& line, stringstream& invalid); 00636 00637 // Processes the given comment into properties for the given region, and 00638 // returns whether an error occurred or not. If an error occurred, the 00639 // details are appended to invalid. 00640 bool processComment(DS9Region& region, QString& comment, 00641 stringstream& invalid); 00642 00643 // For "point" regions. Parses the given comment for a point=type property 00644 // and places the correct type into "type". Returns whether the operation 00645 // succeeded or not. 00646 bool readPointType(QString& comment, DS9::RegionType& type); 00647 00648 // Reads properties in the given line into the given record. 00649 bool readProperties(Record& record, QString& line); 00650 }; 00651 00652 } 00653 00654 #endif /*DS9FILEREADER_H_*/