casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
RegionShapes.h
Go to the documentation of this file.
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&lt;double&gt;</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&lt;double&gt;</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_*/