casa
$Rev:20696$
|
00001 //# RegionShapes.h: Classes for displaying region shapes on the viewer. 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 REGIONSHAPES_H_ 00028 #define REGIONSHAPES_H_ 00029 00030 #include <display/RegionShapes/RegionShape.h> 00031 00032 #include <cctype> 00033 00034 #include <casa/namespace.h> 00035 00036 namespace casa { 00037 00038 // Subclass of RegionShape used for drawing ellipses. An ellipse has the 00039 // following properties in addition to those listed for RegionShape: 00040 // <ul><li>x and y coordinate</li> 00041 // <li>x-radius and y-radius</li> 00042 // <li>angle of rotation</li></ul> 00043 class RSEllipse : public RegionShape { 00044 public: 00045 // World Constructor. x, y, xRadius, yRadius, and angle must all be 00046 // 1) using the same world system as defined by worldSystem, and 2) in 00047 // unit RegionShape::UNIT. Angle is counterclockwise, and angle 0 is the 00048 // east vector. 00049 RSEllipse(double x, double y, double xRadius, double yRadius, 00050 MDirection::Types worldSystem, double angle = 0); 00051 00052 // Pixel Constructor. Angle in counterclockwise degrees. 00053 RSEllipse(double x, double y, double xRadius, double yRadius, 00054 double angle = 0); 00055 00056 // Record Constructor. 00057 RSEllipse(const RecordInterface& properties); 00058 00059 // Destructor. 00060 virtual ~RSEllipse(); 00061 00062 // Implements RegionShape::drawAndUpdateBoundingBox. 00063 virtual bool drawAndUpdateBoundingBox(WorldCanvasHolder& wch, 00064 String* error = NULL); 00065 00066 // Implements RegionShape::type. 00067 virtual String type() const { return "ellipse"; } 00068 00069 // Gets ellipse-specific coordinates, to avoid dependence on 00070 // coordParameterValues() when the shape type is known. 00071 // If toSystem is empty, no conversion is done; otherwise see the 00072 // constraints listed in RegionShape::coordParameterValues(String). 00073 void getEllipseCoordinates(double& x, double& y, double& xRadius, 00074 double& yRadius, double& angle, 00075 String toSystem = "") const; 00076 00077 // Implements RegionShape::coordParameterValues. 00078 virtual vector<double> coordParameterValues() const; 00079 00080 // Implements RegionShape::coordParameterValues. 00081 virtual vector<double> coordParameterValues(String toSystem) const; 00082 00083 // Implements RegionShape::coordParameterNames. 00084 virtual vector<String> coordParameterNames() const; 00085 00086 // Implements RegionShape::coordParameterPositions. 00087 virtual vector<CoordinateParameterType> coordParameterTypes() const; 00088 00089 // Implements RegionShape::setCoordParameters. 00090 virtual void setCoordParameters(const vector<double>& vals); 00091 00092 // Implements RegionShape::setCoordParameters. 00093 virtual void setCoordParameters(const vector<double>& vals, String system); 00094 00095 // Implements RegionShape::move. 00096 virtual void move(double dx, double dy, String system = ""); 00097 00098 // Implements RegionShape::getHandle. 00099 virtual RSHandle getHandle() const; 00100 00101 // Implements RegionShape option methods. Note: ellipses do not have 00102 // additonal options. 00103 // <group> 00104 virtual vector<String> optionNames() const { return vector<String>(); } 00105 virtual vector<OptionType> optionTypes() const { 00106 return vector<OptionType>(); } 00107 virtual vector<RSOption> optionValues() const { return vector<RSOption>();} 00108 virtual void setOptionValues(const vector<RSOption>& /*options*/) { } 00109 // </group> 00110 00111 protected: 00112 vector<double> m_spec; // order: [x, y, x-radius, y-radius, angle] 00113 // either world or pixel coords 00114 vector<double> m_screenSpec; // same order, screen coords 00115 00116 00117 // Implements RegionShape::getShapeSpecificProperties. 00118 virtual void getShapeSpecificProperties(Record& properties) const { 00119 properties.define(PROPTYPE, PROPTYPE_ELLIPSE); 00120 } 00121 00122 // Implements RegionShape::setShapeSpecificProperties. 00123 virtual void setShapeSpecificProperties(const RecordInterface& /*props*/) { } 00124 00125 // Updates screen coords using world/pixel coords and the given WorldCanvas 00126 virtual bool updateScreenCoordinates(WorldCanvasHolder& wch, String* err); 00127 00128 // Update m_xMin, m_xMax, m_yMin, and m_yMax. 00129 virtual void updateMinMax(); 00130 }; 00131 00132 00133 // Subclass of RSEllipse used for drawing circles. Only one radius (x) is 00134 // taken and no angle. 00135 class RSCircle : public RSEllipse { 00136 public: 00137 // World constructor. x, y, and xRadius must be of the type defined by 00138 // worldSys and in units of RegionShape::UNIT. 00139 RSCircle(double x, double y, double xRadius, MDirection::Types worldSys); 00140 00141 // Pixel constructor. 00142 RSCircle(double x, double y, double xRadius); 00143 00144 // Record Constructor. 00145 RSCircle(const RecordInterface& properties); 00146 00147 // Destructor. 00148 ~RSCircle(); 00149 00150 // Overrides RSEllipse::type. 00151 String type() const { return "circle"; } 00152 00153 // Gets circle-specific coordinates, to avoid dependence on 00154 // coordParameterValues() when the shape type is known. 00155 // If toSystem is empty, no conversion is done; otherwise see the 00156 // constraints listed in RegionShape::coordParameterValues(String). 00157 void getCircleCoordinates(double& x, double& y, double& xRadius, 00158 String toSystem = "") const; 00159 00160 // Overrides RSEllipse::coordParameterValues. 00161 vector<double> coordParameterValues() const; 00162 00163 // Overrides RSEllipse::coordParameterValues. 00164 vector<double> coordParameterValues(String toSystem) const; 00165 00166 // Overrides RSEllipse::coordParameterNames. 00167 vector<String> coordParameterNames() const; 00168 00169 // Overrides RSEllipse::coordParameterPositions. 00170 vector<CoordinateParameterType> coordParameterTypes() const; 00171 00172 // Overrides RSEllipse::setCoordParameters. 00173 void setCoordParameters(const vector<double>& vals); 00174 00175 // Overrides RSEllipse::setCoordParameters. 00176 void setCoordParameters(const vector<double>& vals, String valSystem); 00177 00178 protected: 00179 // Overrides RSEllipse::getShapeSpecificProperties. 00180 void getShapeSpecificProperties(Record& properties) const { 00181 properties.define(PROPTYPE, PROPTYPE_CIRCLE); 00182 } 00183 00184 // Overrides RSEllipse::updateScreenCoordinates. 00185 bool updateScreenCoordinates(WorldCanvasHolder& wch, String* err); 00186 }; 00187 00188 00189 // Subclass of RegionShape used for drawing rectangles. A rectangle has the 00190 // following properties in addition to those listed for RegionShape: 00191 // <ul><li>x and y coordinate of center</li> 00192 // <li>width and height</li></ul> 00193 class RSRectangle : public RegionShape { 00194 public: 00195 // Static Members // 00196 00197 // Gets the four rectangle points for the given center, radii, and angle 00198 // and puts them in the given vectors. Returns whether or not the 00199 // operation succeeded. Angle is in counterclockwise degrees. The point 00200 // order is [top right, top left, bottom left, bottom right] in the 00201 // coordinate system of the given points. 00202 static bool getRectanglePoints(double centerX, double centerY, 00203 double radiusX, double radiusY, 00204 double angle, Vector<double>& xPoints, 00205 Vector<double>& yPoints); 00206 00207 00208 // Non-Static Members // 00209 00210 // World Constructor. x, y, width, and height must all be 1) using the 00211 // same world system as defined by worldSystem, and 2) in unit 00212 // RegionShape::UNIT. (x, y) specifies the center of the rectangle. 00213 // Angle is in counterclockwise degrees starting at the east vector. 00214 RSRectangle(double x, double y, double width, double height, 00215 MDirection::Types worldSystem, double angle = 0); 00216 00217 // Pixel Constructor. (x, y) specifies the center of the rectangle. 00218 RSRectangle(double x, double y, double width, double height, 00219 double angle = 0); 00220 00221 // Record Constructor. 00222 RSRectangle(const RecordInterface& properties); 00223 00224 // Destructor. 00225 ~RSRectangle(); 00226 00227 // Implements RegionShape::drawAndUpdateBoundingBox. 00228 bool drawAndUpdateBoundingBox(WorldCanvasHolder& wch, String* err = NULL); 00229 00230 // Implements RegionShape::type. 00231 String type() const { return "rectangle"; } 00232 00233 // Gets rectangle-specific coordinates, to avoid dependence on 00234 // coordParameterValues() when the shape type is known. 00235 // If toSystem is empty, no conversion is done; otherwise see the 00236 // constraints listed in RegionShape::coordParameterValues(String). 00237 void getRectangleCoordinates(double& x, double& y, double& width, 00238 double& height, double& angle, 00239 String toSystem = "") const; 00240 00241 // Implements RegionShape::coordParameterValues. 00242 vector<double> coordParameterValues() const; 00243 00244 // Implements RegionShape::coordParameterValues. 00245 vector<double> coordParameterValues(String toSystem) const; 00246 00247 // Implements RegionShape::coordParameterNames. 00248 vector<String> coordParameterNames() const; 00249 00250 // Implements RegionShape::coordParameterPositions. 00251 vector<CoordinateParameterType> coordParameterTypes() const; 00252 00253 // Implements RegionShape::setCoordParameters. 00254 void setCoordParameters(const vector<double>& vals); 00255 00256 // Implements RegionShape::setCoordParameters. 00257 void setCoordParameters(const vector<double>& vals, String valSystem); 00258 00259 // Implements RegionShape::move. 00260 void move(double dx, double dy, String system = ""); 00261 00262 // Implements RegionShape::getHandle. 00263 RSHandle getHandle() const; 00264 00265 // Implements RegionShape option methods. Note: rectangles do not have 00266 // additonal options. 00267 // <group> 00268 vector<String> optionNames() const { return vector<String>(); } 00269 vector<OptionType> optionTypes() const { return vector<OptionType>(); } 00270 vector<RSOption> optionValues() const { return vector<RSOption>();} 00271 void setOptionValues(const vector<RSOption>& /*options*/) { } 00272 // </group> 00273 00274 protected: 00275 vector<double> m_spec; // order: [x, y, width, height, angle] 00276 // either world or pixel coords 00277 Vector<double> m_x, m_y; // pixel/world coords for four points 00278 // in order: [upL, boL, boR, upR] 00279 Vector<double> m_screenX, m_screenY; // screen coords for four points 00280 // same order 00281 00282 // Implements RegionShape::getShapeSpecificProperties. 00283 void getShapeSpecificProperties(Record& properties) const { 00284 properties.define(PROPTYPE, PROPTYPE_RECTANGLE); 00285 } 00286 00287 // Implements RegionShape::setShapeSpecificProperties. 00288 void setShapeSpecificProperties(const RecordInterface& /*properties*/) { } 00289 00290 // Updates screen coords using world/pixel coords and the given WorldCanvas 00291 bool updateScreenCoordinates(WorldCanvasHolder& wch, String* err); 00292 00293 // Translates m_spec into m_x and m_y. 00294 void updatePoints(); 00295 00296 // Update m_xMin, m_xMax, m_yMin, and m_yMax. 00297 void updateMinMax(); 00298 }; 00299 00300 00301 // Subclass of RegionShape used for drawing polygons. A polygon has the 00302 // following properties in addition to those listed for RegionShape: 00303 // <ul><li>list of x and y coordinates</li> 00304 // <li>optional custom name</li></ul> 00305 // The following properties are also available: 00306 // <ul><li><b>RSPolygon::PROPXCOORDINATES</b> (<i>Array<double></i>): 00307 // vertices x values. <b>NOT STRICTLY REQUIRED, BUT A VALID POLYGON 00308 // HAS AT LEAST TWO VERTICES.</b></li> 00309 // <li><b>RSPolygon::PROPYCOORDINATES</b> (<i>Array<double></li>): 00310 // vertices y values. <b>NOT STRICTLY REQUIRED, BUT A VALID POLYGON 00311 // HAS AT LEAST TWO VERTICES.</b></li></ul> 00312 class RSPolygon : public RegionShape { 00313 public: 00314 // Static Members // 00315 00316 // Properties. (See class descriptions of RegionShape and RSPolygon.) 00317 // <group> 00318 static const String PROPXCOORDINATES; 00319 static const String PROPYCOORDINATES; 00320 // </group> 00321 00322 00323 // Non-Static Members // 00324 00325 // World Constructor. x and y must both be 1) using the same world system 00326 // as defined by worldSystem, and 2) in unit RegionShape::UNIT. A custom 00327 // name can be provided to be returned with RSPolygon::type(). 00328 RSPolygon(const Vector<double>& x, const Vector<double>& y, 00329 MDirection::Types worldSystem, String custName = ""); 00330 00331 // Pixel Constructor. 00332 RSPolygon(const Vector<double>& x, const Vector<double>& y, 00333 String custName = ""); 00334 00335 // Record Constructor. 00336 RSPolygon(const RecordInterface& properties); 00337 00338 // Destructor. 00339 ~RSPolygon(); 00340 00341 // Sets the polygon coordinates to the given. 00342 void setPolygonCoordinates(const Vector<double>& x, 00343 const Vector<double>& y); 00344 00345 // Implements RegionShape::drawAndUpdateBoundingBox. 00346 bool drawAndUpdateBoundingBox(WorldCanvasHolder& wch, String* err = NULL); 00347 00348 // Implements RegionShape::type. 00349 String type() const { 00350 if(!m_custName.empty()) return m_custName; 00351 else return "polygon"; 00352 } 00353 00354 // Overrides RegionShape::oneWordType. 00355 String oneWordType() const { return "polygon"; } 00356 00357 // Gets polygon-specific coordinates, to avoid dependence on 00358 // coordParameterValues() when the shape type is known. 00359 // If toSystem is empty, no conversion is done; otherwise see the 00360 // constraints listed in RegionShape::coordParameterValues(String). 00361 void getPolygonCoordinates(double& centerX, double& centerY, 00362 String toSystem = "") const; 00363 00364 // Gets actual polygon coordinates. 00365 // If toSystem is empty, no conversion is done; otherwise see the 00366 // constraints listed in RegionShape::coordParameterValues(String). 00367 void getPolygonCoordinates(vector<double>& x, vector<double>& y, 00368 String toSystem = "") const; 00369 00370 // Implements RegionShape::coordParameterValues. 00371 vector<double> coordParameterValues() const; 00372 00373 // Implements RegionShape::coordParameterValues. 00374 vector<double> coordParameterValues(String toSystem) const; 00375 00376 // Implements RegionShape::coordParameterNames. 00377 vector<String> coordParameterNames() const; 00378 00379 // Implements RegionShape::coordParameterPositions. 00380 vector<CoordinateParameterType> coordParameterTypes() const; 00381 00382 // Implements RegionShape::setCoordParameters. 00383 void setCoordParameters(const vector<double>& vals); 00384 00385 // Implements RegionShape::setCoordParameters. 00386 void setCoordParameters(const vector<double>& vals, String valSystem); 00387 00388 // Implements RegionShape::move. 00389 void move(double dx, double dy, String system = ""); 00390 00391 // Implements RegionShape::getHandle. 00392 RSHandle getHandle() const; 00393 00394 // Implements RegionShape::optionNames. 00395 vector<String> optionNames() const; 00396 00397 // Implements RegionShape::optionTypes. 00398 vector<OptionType> optionTypes() const; 00399 00400 // Implements RegionShape::optionValues. 00401 vector<RSOption> optionValues() const; 00402 00403 // Implements RegionShape::setOptions. 00404 void setOptionValues(const vector<RSOption>& options); 00405 00406 protected: 00407 Vector<Double> m_x, m_y; // coordinates, world or pixel 00408 double m_centerX, m_centerY; // center of polygon, world or pixel 00409 Vector<Double> m_screenX, m_screenY; // coordinates, screen 00410 unsigned int m_n; // number of points 00411 String m_custName; // optional custom name 00412 00413 // Implements RegionShape::getShapeSpecificProperties. 00414 void getShapeSpecificProperties(Record& properties) const; 00415 00416 // Implements RegionShape::setShapeSpecificProperties. 00417 void setShapeSpecificProperties(const RecordInterface& properties); 00418 00419 // Updates screen coords using world/pixel coords and the given WorldCanvas 00420 bool updateScreenCoordinates(WorldCanvasHolder& wch, String* err); 00421 00422 // Update m_xMin, m_xMax, m_yMin, and m_yMax. 00423 void updateMinMax(); 00424 }; 00425 00426 00427 // Subclass of RegionShape used for drawing lines. A line has the 00428 // following properties in addition to those listed for RegionShape: 00429 // <ul><li>x1, y1 and x2, y2 coordinates</li> 00430 // <li>whether to draw an arrow on either of the endpoints</li> 00431 // <li>arrow length</li></ul> 00432 class RSLine : public RegionShape { 00433 public: 00434 // Static Members // 00435 00436 // Different ways to draw the arrow(s) at the end of the line. 00437 enum ArrowType { 00438 FilledTriangle, Triangle, V, FilledDoubleV 00439 }; 00440 00441 // Returns all possible arrow types. 00442 // <group> 00443 static vector<ArrowType> allArrowTypes() { 00444 static vector<ArrowType> v(4); 00445 v[0] = FilledTriangle; v[1] = Triangle; 00446 v[2] = V; v[3] = FilledDoubleV; 00447 return v; 00448 } 00449 00450 static vector<String> allArrowTypesStrings() { 00451 vector<ArrowType> types = allArrowTypes(); 00452 vector<String> v(types.size()); 00453 for(unsigned int i = 0; i < v.size(); i++) v[i] = arrowType(types[i]); 00454 return v; 00455 } 00456 // </group> 00457 00458 // Converts to/from the String representation of arrow types. 00459 // <group> 00460 static String arrowType(ArrowType type) { 00461 switch(type) { 00462 case FilledTriangle: return "filled triangle"; 00463 case Triangle: return "triangle"; 00464 case V: return "v"; 00465 case FilledDoubleV: return "filled double v"; 00466 00467 default: return ""; 00468 } 00469 } 00470 00471 static ArrowType arrowType(const String& type) { 00472 String t = type; 00473 for(unsigned int i = 0; i < t.size(); i++) t[i] = tolower(t[i]); 00474 if(t == "filled triangle") return FilledTriangle; 00475 else if(t == "triangle") return Triangle; 00476 else if(t == "v") return V; 00477 else if(t == "filled double v") return FilledDoubleV; 00478 00479 else return FilledTriangle; 00480 } 00481 // </group> 00482 00483 00484 // Non-Static Members // 00485 00486 // World Constructor. x1, y1, x2, and y2 must all be 1) using the 00487 // same world system as defined by worldSystem, and 2) in unit 00488 // RegionShape::UNIT. arrowLength is in screen pixels. arrow1 defines 00489 // whether (x1, y1) has an arrow; arrow2 for (x2, y2). 00490 RSLine(double x1, double y1, double x2, double y2, 00491 MDirection::Types worldSystem, int arrowLength, bool arrow1 = false, 00492 bool arrow2 = false, ArrowType type1 = FilledDoubleV, 00493 ArrowType type2 = FilledDoubleV); 00494 00495 // Pixel Constructor. arrowLength is in screen pixels. arrow1 defines 00496 // whether (x1, y1) has an arrow; arrow2 for (x2, y2). 00497 RSLine(double x1, double y1, double x2, double y2, int arrowLength, 00498 bool arrow1 = false, bool arrow2 = false, 00499 ArrowType type1 = FilledDoubleV, ArrowType type2 = FilledDoubleV); 00500 00501 // Record Constructor. 00502 RSLine(const RecordInterface& properties); 00503 00504 // Destructor. 00505 virtual ~RSLine(); 00506 00507 // Returns whether the two endpoints have arrows or not. 00508 // </group> 00509 bool p1Arrow() const { return m_arrow1; } 00510 bool p2Arrow() const { return m_arrow2; } 00511 // </group> 00512 00513 // Implements RegionShape::drawAndUpdateBoundingBox. 00514 virtual bool drawAndUpdateBoundingBox(WorldCanvasHolder& wch, 00515 String* error = NULL); 00516 00517 // Implements RegionShape::type. 00518 virtual String type() const { return "line"; } 00519 00520 // Gets line-specific coordinates, to avoid dependence on 00521 // coordParameterValues() when the shape type is known. 00522 // If toSystem is empty, no conversion is done; otherwise see the 00523 // constraints listed in RegionShape::coordParameterValues(String). 00524 void getLineCoordinates(double& x1, double& y1, double& x2, double& y2, 00525 int& arrowLength, String toSystem = "") const; 00526 00527 // Implements RegionShape::coordParameterVales. 00528 virtual vector<double> coordParameterValues() const; 00529 00530 // Implements RegionShape::coordParameterValues. 00531 vector<double> coordParameterValues(String toSystem) const; 00532 00533 // Implements RegionShape::coordParameterNames. 00534 virtual vector<String> coordParameterNames() const; 00535 00536 // Implements RegionShape::coordParameterPositions. 00537 virtual vector<CoordinateParameterType> coordParameterTypes() const; 00538 00539 // Implements RegionShape::setCoordParameters. 00540 virtual void setCoordParameters(const vector<double>& vals); 00541 00542 // Implements RegionShape::setCoordParameters. 00543 virtual void setCoordParameters(const vector<double>& vals, String System); 00544 00545 // Implements RegionShape::move. 00546 virtual void move(double dx, double dy, String system = ""); 00547 00548 // Implements RegionShape::getHandle. 00549 virtual RSHandle getHandle() const; 00550 00551 // Implements RegionShape::optionNames. 00552 virtual vector<String> optionNames() const; 00553 00554 // Implements RegionShape::optionTypes. 00555 virtual vector<OptionType> optionTypes() const; 00556 00557 // Implements RegionShape::optionChoices. 00558 virtual vector<vector<String> > optionChoices() const; 00559 00560 // Implements RegionShape::optionValues. 00561 virtual vector<RSOption> optionValues() const; 00562 00563 // Implements RegionShape::setOptions. 00564 virtual void setOptionValues(const vector<RSOption>& options); 00565 00566 protected: 00567 vector<double> m_spec; // order: [x1 y1 x2 y2], either world or pixel 00568 vector<double> m_screenSpec; // same order, screen coords 00569 int m_arrowLength; // arrow length, screen coords 00570 bool m_arrow1, m_arrow2; // whether to draw the arrows 00571 ArrowType m_aType1, m_aType2; // arrow types 00572 00573 // Implements RegionShape::getShapeSpecificProperties. 00574 virtual void getShapeSpecificProperties(Record& properties) const { 00575 properties.define(PROPTYPE, PROPTYPE_LINE); 00576 } 00577 00578 // Implements RegionShape::setShapeSpecificProperties. 00579 virtual void setShapeSpecificProperties(const RecordInterface& /*props*/) { } 00580 00581 // Updates screen coords using world/pixel coords and the given WorldCanvas 00582 virtual bool updateScreenCoordinates(WorldCanvasHolder& wch, String* err); 00583 00584 // Update m_xMin, m_xMax, m_yMin, and m_yMax. 00585 void updateMinMax(); 00586 00587 // Generates arrow points based on the given (x1, y1) (x2, y2) points. 00588 // NOTE: Duplicated code from casaqt/QwtPlotter/QPShape (QPArrow class). 00589 static bool arrowPoints(double x1, double y1, double x2, double y2, 00590 double length, double& resX1, double& resY1, 00591 double& resX2, double& resY2); 00592 00593 // Helper for arrowPoints. NOTE: Duplicated code. 00594 static bool arrowPointsHelper(double x1, double y1, double x2, double y2, 00595 double length, double& resX1, double& resY1, 00596 double& resX2, double& resY2); 00597 }; 00598 00599 00600 // Subclass of RSLine that takes a length and angle instead of a second point. 00601 class RSVector : public RSLine { 00602 public: 00603 // World Constructor. x, y, length, and angle must all be 1) using the 00604 // same world system as defined by worldSystem, and 2) in unit 00605 // RegionShape::UNIT. Angle is counterclockwise, and the base is the east 00606 // vector. arrowLength is in screen pixels. arrow defines whether the 00607 // second point has an arrow. 00608 RSVector(double x, double y, double length, double angle, 00609 MDirection::Types worldSystem, int arrowLength, 00610 bool arrow = true, ArrowType arrowType = FilledDoubleV); 00611 00612 // Pixel Constructor. Angle is counterclockwise. arrowLength is in screen 00613 // pixels. arrow defines whether the second point has an arrow. 00614 RSVector(double x, double y, double length, double angle, int arrowLength, 00615 bool arrow = true, ArrowType arrowType = FilledDoubleV); 00616 00617 // Record Constructor. 00618 RSVector(const RecordInterface& properties); 00619 00620 // Destructor. 00621 ~RSVector(); 00622 00623 // Returns whether the vector has an arrow at the end or not. 00624 bool arrow() const { return p2Arrow(); } 00625 00626 // Overrides RSLine::type. 00627 String type() const { return "vector"; } 00628 00629 // Gets vector-specific coordinates, to avoid dependence on 00630 // coordParameterValues() when the shape type is known. 00631 // If toSystem is empty, no conversion is done; otherwise see the 00632 // constraints listed in RegionShape::coordParameterValues(String). 00633 void getVectorCoordinates(double& x, double& y, double& angle, 00634 double& length, int& arrowLength, 00635 String toSystem = "") const; 00636 00637 // Overrides RSLine::coordParameterValues. 00638 vector<double> coordParameterValues() const; 00639 00640 // Implements RegionShape::coordParameterValues. 00641 vector<double> coordParameterValues(String toSystem) const; 00642 00643 // Overrides RSLine::coordParameterNames. 00644 vector<String> coordParameterNames() const; 00645 00646 // Overrides RSLine::coordParameterPositions. 00647 vector<CoordinateParameterType> coordParameterTypes() const; 00648 00649 // Overrides RSLine::setCoordParameters. 00650 void setCoordParameters(const vector<double>& vals); 00651 00652 // Overrides RSLine::setCoordParameters. 00653 void setCoordParameters(const vector<double>& vals, String valSystem); 00654 00655 // Overrides RSLine::optionNames. 00656 vector<String> optionNames() const; 00657 00658 // Overrides RSLine::optionTypes. 00659 vector<OptionType> optionTypes() const; 00660 00661 // Overrides RSLine::optionChoices. 00662 vector<vector<String> > optionChoices() const; 00663 00664 // Overrides RSLine::optionValues. 00665 vector<RSOption> optionValues() const; 00666 00667 // Overrides RSLine::setOptions. 00668 void setOptionValues(const vector<RSOption>& options); 00669 00670 protected: 00671 double m_length; // length, world or pixel 00672 double m_angle; // angle, world or pixel 00673 00674 // Overrides RSLine::getShapeSpecificProperties. 00675 void getShapeSpecificProperties(Record& properties) const { 00676 properties.define(PROPTYPE, PROPTYPE_VECTOR); 00677 } 00678 }; 00679 00680 00681 // Subclass of RegionShape used for drawing markers. A marker has the 00682 // following properties in addition to those listed for RegionShape: 00683 // <ul><li>x and y coordinates</li> 00684 // <li>marker type, or list of marker types</li> 00685 // <li>pixel height</li></ul> 00686 class RSMarker : public RegionShape { 00687 public: 00688 // World Constructor for a single marker type. x and y must all be 00689 // 1) using the same world system as defined by worldSystem, and 00690 // 2) in the unit RegionShape::UNIT. pixelHeight is in screen pixels. 00691 RSMarker(double x, double y, Display::Marker marker, int pixelHeight, 00692 MDirection::Types worldSystem); 00693 00694 // World Constructor for a compound marker type. x and y must all be 00695 // 1) using the same world system as defined by worldSystem, and 00696 // 2) in the unit RegionShape::UNIT. pixelHeight is in screen pixels. 00697 RSMarker(double x, double y, const vector<Display::Marker>& markers, 00698 int pixelHeight, MDirection::Types worldSystem); 00699 00700 // Pixel Constructor for a single marker type. pixelHeight is in screen 00701 // pixels. 00702 RSMarker(double x, double y, Display::Marker marker, int pixelHeight); 00703 00704 // Pixel Constructor for a compound marker type. pixelHeight is in screen 00705 // pixels. 00706 RSMarker(double x, double y, const vector<Display::Marker>& markers, 00707 int pixelHeight); 00708 00709 // Record Constructor. 00710 RSMarker(const RecordInterface& properties); 00711 00712 // Destructor. 00713 ~RSMarker(); 00714 00715 // Gets/sets the markers used for this shape. 00716 // <group> 00717 vector<Display::Marker> markers() const; 00718 void setMarker(Display::Marker marker); 00719 void setMarkers(const vector<Display::Marker>& markers); 00720 // </group> 00721 00722 00723 // Implements RegionShape::drawAndUpdateBoundingBox. 00724 bool drawAndUpdateBoundingBox(WorldCanvasHolder& wch, String* err = NULL); 00725 00726 // Implements RegionShape::type. 00727 String type() const; 00728 00729 // Overrides RegionShape::oneWordType. 00730 String oneWordType() const { return "marker"; } 00731 00732 // Gets marker-specific coordinates, to avoid dependence on 00733 // coordParameterValues() when the shape type is known. 00734 // If toSystem is empty, no conversion is done; otherwise see the 00735 // constraints listed in RegionShape::coordParameterValues(String). 00736 void getMarkerCoordinates(double& x, double& y, int& pixelHeight, 00737 String toSystem = "") const; 00738 00739 // Implements RegionShape::coordParameterValues. 00740 vector<double> coordParameterValues() const; 00741 00742 // Implements RegionShape::coordParameterValues. 00743 vector<double> coordParameterValues(String toSystem) const; 00744 00745 // Implements RegionShape::coordParameterNames. 00746 vector<String> coordParameterNames() const; 00747 00748 // Implements RegionShape::coordParameterPositions. 00749 vector<CoordinateParameterType> coordParameterTypes() const; 00750 00751 // Implements RegionShape::setCoordParameters. 00752 void setCoordParameters(const vector<double>& vals); 00753 00754 // Implements RegionShape::setCoordParameters. 00755 void setCoordParameters(const vector<double>& vals, String valSystem); 00756 00757 // Implements RegionShape::move. 00758 void move(double dx, double dy, String system = ""); 00759 00760 // Implements RegionShape::getHandle. 00761 RSHandle getHandle() const; 00762 00763 // Implements RegionShape::optionNames. 00764 vector<String> optionNames() const; 00765 00766 // Implements RegionShape::optionTypes. 00767 vector<OptionType> optionTypes() const; 00768 00769 // Overrides RegionShape::optionChoices. 00770 vector<vector<String> > optionChoices() const; 00771 00772 // Implements RegionShape::optionValues. 00773 vector<RSOption> optionValues() const; 00774 00775 // Implements RegionShape::setOptions. 00776 void setOptionValues(const vector<RSOption>& options); 00777 00778 protected: 00779 double m_x, m_y; // location, world or pixel 00780 double m_screenX, m_screenY; // location, screen 00781 vector<Display::Marker> m_markers; // marker(s) to be drawn 00782 int m_pixelHeight; // pixel height for marker(s) 00783 00784 // Implements RegionShape::getShapeSpecificProperties. 00785 void getShapeSpecificProperties(Record& properties) const { 00786 properties.define(PROPTYPE, PROPTYPE_MARKER); 00787 } 00788 00789 // Implements RegionShape::setShapeSpecificProperties. 00790 void setShapeSpecificProperties(const RecordInterface& /*properties*/) { } 00791 00792 // Updates screen coords using world/pixel coords and the given WorldCanvas 00793 bool updateScreenCoordinates(WorldCanvasHolder& wch, String* err); 00794 00795 // Update m_xMin, m_xMax, m_yMin, and m_yMax. 00796 void updateMinMax(); 00797 00798 00799 static String markerToString(Display::Marker marker) { 00800 switch(marker) { 00801 case Display::Cross: return "cross"; 00802 case Display::X: return "x"; 00803 case Display::Diamond: return "diamond"; 00804 case Display::Circle: return "circle"; 00805 case Display::Square: return "square"; 00806 case Display::Triangle: return "triangle"; 00807 case Display::InvertedTriangle: return "inverted triangle"; 00808 case Display::FilledCircle: return "filled circle"; 00809 case Display::FilledSquare: return "filled square"; 00810 case Display::FilledDiamond: return "filled diamond"; 00811 case Display::FilledTriangle: return "filled triangle"; 00812 case Display::FilledInvertedTriangle:return "filled inverted triangle"; 00813 case Display::CircleAndCross: return "circle and cross"; 00814 case Display::CircleAndX: return "circle and x"; 00815 case Display::CircleAndDot: return "circle and dot"; 00816 00817 default: return ""; 00818 } 00819 } 00820 00821 static bool stringToMarker(const String& str, Display::Marker& marker) { 00822 String m = str; 00823 for(unsigned int i = 0; i < m.size(); i++) m[i] = tolower(str[i]); 00824 00825 if(m == "cross") marker = Display::Cross; 00826 else if(m == "x") marker = Display::X; 00827 else if(m == "diamond") marker = Display::Diamond; 00828 else if(m == "circle") marker = Display::Circle; 00829 else if(m == "square") marker = Display::Square; 00830 else if(m == "triangle") marker = Display::Triangle; 00831 else if(m == "inverted triangle") marker = Display::InvertedTriangle; 00832 else if(m == "filled circle") marker = Display::FilledCircle; 00833 else if(m == "filled square") marker = Display::FilledSquare ; 00834 else if(m == "filled diamond") marker = Display::FilledDiamond; 00835 else if(m == "filled triangle") marker = Display::FilledTriangle; 00836 else if(m == "filled inverted triangle") 00837 marker = Display::FilledInvertedTriangle; 00838 else if(m == "circle and cross") marker = Display::CircleAndCross; 00839 else if(m == "circle and x") marker = Display::CircleAndX; 00840 else if(m == "circle and dot") marker = Display::CircleAndDot; 00841 else return false; 00842 return true; 00843 } 00844 00845 static vector<Display::Marker> allMarkers() { 00846 static vector<Display::Marker> v(15); 00847 v[0] = Display::Cross; v[1] = Display::X; 00848 v[2] = Display::Diamond; v[3] = Display::Circle; 00849 v[4] = Display::Square; v[5] = Display::Triangle; 00850 v[6] = Display::InvertedTriangle; v[7] = Display::FilledCircle; 00851 v[8] = Display::FilledSquare; v[9] = Display::FilledDiamond; 00852 v[10] = Display::FilledTriangle; v[11]=Display::FilledInvertedTriangle; 00853 v[12] = Display::CircleAndCross; v[13] = Display::CircleAndX; 00854 v[14] = Display::CircleAndDot; 00855 return v; 00856 } 00857 }; 00858 00859 00860 // Subclass of RegionShape used for drawing text. Text uses RegionShape's 00861 // label property. 00862 class RSText : public RegionShape { 00863 public: 00864 // World Constructor. x, y, and angle must both be 1) using the same world 00865 // system as defined by worldSystem, and 2) in unit RegionShape::UNIT. 00866 // Angle is counterclockwise, and the base is the east vector. 00867 RSText(double x, double y, const String& text, MDirection::Types worldSys, 00868 double angle = 0); 00869 00870 // Pixel Constructor. Angle is counterclockwise. 00871 RSText(double x, double y, const String& text, double angle = 0); 00872 00873 // Record Constructor. 00874 RSText(const RecordInterface& properties); 00875 00876 // Destructor. 00877 ~RSText(); 00878 00879 // Implements RegionShape::drawAndUpdateBoundingBox. 00880 bool drawAndUpdateBoundingBox(WorldCanvasHolder& wch, String* err = NULL); 00881 00882 // Implements RegionShape::type. 00883 String type() const { return "text"; } 00884 00885 // Gets text-specific coordinates, to avoid dependence on 00886 // coordParameterValues() when the shape type is known. 00887 // If toSystem is empty, no conversion is done; otherwise see the 00888 // constraints listed in RegionShape::coordParameterValues(String). 00889 void getTextCoordinates(double& x, double& y, double& angle, 00890 String toSystem = "") const; 00891 00892 // Implements RegionShape::coordParameterValues. 00893 vector<double> coordParameterValues() const; 00894 00895 // Implements RegionShape::coordParameterValues. 00896 vector<double> coordParameterValues(String toSystem) const; 00897 00898 // Implements RegionShape::coordParameterNames. 00899 vector<String> coordParameterNames() const; 00900 00901 // Implements RegionShape::coordParameterPositions. 00902 vector<CoordinateParameterType> coordParameterTypes() const; 00903 00904 // Implements RegionShape::setCoordParameters. 00905 void setCoordParameters(const vector<double>& vals); 00906 00907 // Implements RegionShape::setCoordParameters. 00908 void setCoordParameters(const vector<double>& vals, String valSystem); 00909 00910 // Implements RegionShape::move. 00911 void move(double dx, double dy, String system = ""); 00912 00913 // Implements RegionShape::getHandle. 00914 RSHandle getHandle() const; 00915 00916 // Implements RegionShape option methods. Note: text do not have 00917 // additonal options. 00918 // <group> 00919 vector<String> optionNames() const { return vector<String>(); } 00920 vector<OptionType> optionTypes() const { return vector<OptionType>(); } 00921 vector<RSOption> optionValues() const { return vector<RSOption>();} 00922 void setOptionValues(const vector<RSOption>& /*options*/) { } 00923 // </group> 00924 00925 protected: 00926 double m_x, m_y; // location, pixel or world 00927 double m_angle; // angle, pixel or world 00928 double m_wWidth; // width in pixel/world 00929 // updated during updateScreenCoordinates 00930 double m_screenX, m_screenY; // location, screen 00931 00932 // Implements RegionShape::getShapeSpecificProperties. 00933 void getShapeSpecificProperties(Record& properties) const { 00934 properties.define(PROPTYPE, PROPTYPE_TEXT); 00935 } 00936 00937 // Implements RegionShape::setShapeSpecificProperties. 00938 void setShapeSpecificProperties(const RecordInterface& /*properties*/) { } 00939 00940 // Updates screen coords using world/pixel coords and the given WorldCanvas 00941 bool updateScreenCoordinates(WorldCanvasHolder& wch, String* err); 00942 00943 // Update m_xMin, m_xMax, m_yMin, and m_yMax. Note that this is only valid 00944 // the screen coordinates have been updated. 00945 void updateMinMax(); 00946 }; 00947 00948 00949 // Subclass of RegionShape used for drawing composite regions. A composite 00950 // region consists of zero or more children RegionShapes. A RSComposite can 00951 // either see its children as dependent, in which the parent controls the 00952 // properties for each shape, or independent in which each child's properties 00953 // must be set individually. An RSComposite can have a custom name/type. 00954 // NOTE: xMin, xMax, yMin, and yMax values are ONLY valid if all children 00955 // shapes have the same coordinate system as the parent composite. 00956 // The following properties are also available: 00957 // <ul><li><b>RSComposite::PROPDEPENDENTCHILDREN</b> (<i>bool</i>): 00958 // whether the composite's children are dependent (true) or independent 00959 // (false). <b>OPTIONAL</b>.</li> 00960 // <li><b>RSComposite::PROPCHILDREN</b> (<i>Record of Records</li>): 00961 // ordered list of children records. Each field must have a unique 00962 // name (the specifics are irrelevant because it's the order that 00963 // matters) and the value must be a record that can be used to create a 00964 // RegionShape child. <b>NOT STRICTLY REQUIRED, BUT A VALID COMPOSITE 00965 // HAS AT LEAST ONE CHILD.</b></li></ul> 00966 class RSComposite : public RegionShape { 00967 public: 00968 // Static Members // 00969 00970 // Properties. (See class descriptions of RegionShape and RSComposite.) 00971 // <group> 00972 static const String PROPDEPENDENTCHILDREN; 00973 static const String PROPCHILDREN; 00974 // </group> 00975 00976 00977 // Non-Static Members // 00978 00979 // World constructor. Initially empty composite. The dependent flag 00980 // controls whether the children are dependent or independent. If 00981 // customName is set, it will be returned on type(). The given world 00982 // system is only used for displaying/setting the center of the composite 00983 // and does not affect the coordinate systems of the children. 00984 RSComposite(MDirection::Types worldSys, bool dependent = true, 00985 String customName = ""); 00986 00987 // Pixel constructor. Initially empty composite. The dependent flag 00988 // controls whether the children are dependent or independent. If 00989 // custonName is set, it will be returned on type(). 00990 RSComposite(bool dependent = true, String customName = ""); 00991 00992 // Record Constructor. 00993 RSComposite(const RecordInterface& properties); 00994 00995 // Destructor. 00996 ~RSComposite(); 00997 00998 // Adds the given shape(s) to this composite. Note that in the case of 00999 // depdendent children, line properties, linethrough properties, and label 01000 // properties of the individual shapes are discarded in favor of those of 01001 // the parent RSComposite. 01002 // <group> 01003 void addShape(RegionShape* shape); 01004 void addShapes(const vector<RegionShape*> shapes); 01005 // </group> 01006 01007 // Returns true if the children are dependent, false otherwise. 01008 bool childrenAreDependent() const; 01009 01010 // Sets whether children are dependent or not. NOTE: This should never be 01011 // called AFTER the composite has already been added to the 01012 // QtRegionShapeManager. Preferably it should be done before adding any 01013 // children either. 01014 void setChildrenAreDependent(bool dependent = true); 01015 01016 // Returns the composite's children. 01017 // <group> 01018 vector<RegionShape*> children(); 01019 vector<const RegionShape*> children() const; 01020 // </group> 01021 01022 01023 // Overrides RegionShape methods in the case of dependent children. 01024 // <group> 01025 void setLineColor(const String& newColor, bool alsoSetLabel = true); 01026 void setLineWidth(double width); 01027 void setLineStyle(LineStyle style); 01028 void setLabel(const RegionShapeLabel& label); 01029 // </group> 01030 01031 // Implements RegionShape::drawAndUpdateBoundingBox. 01032 bool drawAndUpdateBoundingBox(WorldCanvasHolder& wch, String* err = NULL); 01033 01034 // Implements RegionShape::type. 01035 String type() const; 01036 01037 // Overrides RegionShape::oneWordType. 01038 String oneWordType() const { return "composite"; } 01039 01040 // Returns 0 degrees pixel/screen in the given coordinate system (own 01041 // system if toSystem is empty, otherwise see the constraints listed in 01042 // RegionShape::coordParameterValues(String). 01043 double getAngle(String toSystem = "") const; 01044 01045 // Gets composite-specific coordinates, to avoid dependence on 01046 // coordParameterValues() when the shape type is known. 01047 // If toSystem is empty, no conversion is done; otherwise see the 01048 // constraints listed in RegionShape::coordParameterValues(String). 01049 void getCompositeCoordinates(double& centerX, double& centerY, 01050 String toSystem = "") const; 01051 01052 // Implements RegionShape::coordParameterValues. 01053 vector<double> coordParameterValues() const; 01054 01055 // Implements RegionShape::coordParameterValues. 01056 vector<double> coordParameterValues(String toSystem) const; 01057 01058 // Implements RegionShape::coordParameterNames. 01059 vector<String> coordParameterNames() const; 01060 01061 // Implements RegionShape::coordParameterPositions. 01062 vector<CoordinateParameterType> coordParameterTypes() const; 01063 01064 // Implements RegionShape::setCoordParameters. 01065 void setCoordParameters(const vector<double>& vals); 01066 01067 // Implements RegionShape::setCoordParameters. 01068 void setCoordParameters(const vector<double>& vals, String valSystem); 01069 01070 // Implements RegionShape::move. 01071 void move(double dx, double dy, String system = ""); 01072 01073 // Implements RegionShape::getHandle. 01074 RSHandle getHandle() const; 01075 01076 // Implements RegionShape::optionNames. 01077 vector<String> optionNames() const; 01078 01079 // Implements RegionShape::optionTypes. 01080 vector<OptionType> optionTypes() const; 01081 01082 // Implements RegionShape::optionValues. 01083 vector<RSOption> optionValues() const; 01084 01085 // Implements RegionShape::setOptions. 01086 void setOptionValues(const vector<RSOption>& options); 01087 01088 protected: 01089 String m_custName; // optional custom name 01090 bool m_dependentChildren; // whether children are dependent 01091 vector<RegionShape*> m_shapes; // children 01092 double m_centerX, m_centerY; // center 01093 bool m_syncAngleDepChildren; // flag for whether all children: 01094 // 1) are dependent 01095 // 2) have angles (rectangle, ellipse, 01096 // vector, text) 01097 // 3) all have synched (same) angle 01098 double m_syncAngle; // Sync angle (if applicable). 01099 bool m_applyChangesToChildren; // Whether or not to apply options changes 01100 // to children or not. 01101 01102 // Implements RegionShape::getShapeSpecificProperties. 01103 void getShapeSpecificProperties(Record& properties) const; 01104 01105 // Implements RegionShape::setShapeSpecificProperties. 01106 void setShapeSpecificProperties(const RecordInterface& properties); 01107 01108 // Update m_xMin, m_xMax, m_yMin, and m_yMax. 01109 void updateMinMax(); 01110 01111 private: 01112 // Adds the given child but does not perform upkeep. Returns true if the 01113 // shape was added, false otherwise. 01114 bool addShapeHelper(RegionShape* shape); 01115 01116 // Does upkeep after adding shapes. 01117 void addShapeUpkeep(); 01118 01119 // Gets the min/max of the child at the given index, in the composite's 01120 // coordinate system. 01121 void convertMinMax(double& xmin, double& xmax, double& ymin, double& ymax, 01122 unsigned int index) const; 01123 }; 01124 01125 } 01126 01127 #endif /*REGIONSHAPES_H_*/