casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
MultiPolyTool.h
Go to the documentation of this file.
00001 //# MultiPolyTool.h: Base class for MultiWorldCanvas event-based polygon tools
00002 //# Copyright (C) 1999,2000,2001,2002
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 
00028 #ifndef DISPLAY_MULTIPOLYTOOL_H
00029 #define DISPLAY_MULTIPOLYTOOL_H
00030 
00031 #include <casa/aips.h>
00032 #include <display/DisplayEvents/RegionTool.h>
00033 #include <display/DisplayEvents/DTVisible.h>
00034 #include <display/region/RegionSourceFactory.h>
00035 
00036 namespace casa { //# NAMESPACE CASA - BEGIN
00037 
00038 // <summary>
00039 // Base class for WorldCanvas event-based polygon tools
00040 // </summary>
00041 //
00042 // <use visibility=export>
00043 //
00044 // <reviewed reviewer="" date="yyyy/mm/dd" tests="" demos="">
00045 // </reviewed>
00046 //
00047 // <prerequisites>
00048 //   <li><linkto>WCTool</linkto>
00049 // </prerequisites>
00050 //
00051 // <etymology>
00052 // MultiPolyTool stands for Multi-WorldCanvas Polygon Tool
00053 // </etymology>
00054 //
00055 // <synopsis>
00056 // This class adds to its base MWCTool to provide a tool for drawing,
00057 // reshaping and moving polygons on a WorldCanvas.  While MultiPolyTool
00058 // is not abstract, it performs no useful function.  The programmer
00059 // should derive from this class and override the functions doubleInside
00060 // and doubleOutside at the very least.  These are called when the user
00061 // double-clicks a particular key or mouse button inside or outside an
00062 // existing polygon respectively.  It is up to the programmer to decide
00063 // what these events mean, but it is recommended that an internal double-
00064 // click correspond to the main action of the tool, eg. emitting the 
00065 // polygon vertices to the application, and that an external double-click
00066 // correspond to a secondary action of the tool, if indeed there are
00067 // additional actions suitable to the tool.
00068 //
00069 // The polygon is drawn by clicking at each of the vertices, and
00070 // clicking again on the last or first vertex to complete the polygon.
00071 // Once drawn, the vertices can be moved by dragging their handles,
00072 // and the entire polygon relocated by dragging inside the polygon.
00073 // The polygon is removed from the display when the Esc key is
00074 // pressed.
00075 // </synopsis>
00076 //
00077 // <example>
00078 // </example>
00079 //
00080 // <motivation>
00081 // Many activities on the WorldCanvas will be based on the user drawing
00082 // a polygon and using the polygon in some operation.
00083 // </motivation>
00084 //
00085 // <todo asof="1999/02/24">
00086 //   <li> Add time constraint to double click detection
00087 // </todo>
00088 
00089     class MultiPolyTool : public RegionTool, public DTVisible, public viewer::RegionCreator {
00090 
00091          public:
00092 
00093             // Constructor
00094             MultiPolyTool( viewer::RegionSourceFactory *rsf, PanelDisplay* pd,
00095                            Display::KeySym keysym = Display::K_Pointer_Button1, const Bool persistent = False );
00096 
00097             // Destructor
00098             virtual ~MultiPolyTool();
00099 
00100             // Switch the tool off - this calls the base class disable,
00101             // and then erases the polygon if it's around
00102             virtual void disable();
00103 
00104             // reset to non-existent, non-active polygon.
00105             // Refreshes if necessary to erase (unless skipRefresh==True).
00106             // (Does not unregister from WCs or disable future event handling).
00107             virtual void reset(Bool skipRefresh=False);
00108   
00109             // Is a polygon currently defined?
00110             virtual Bool polygonDefined() { return itsMode>=Ready;  } 
00111   
00112             viewer::RegionSource *getRegionSource( ) { return rfactory; }
00113   
00114             void checkPoint( WorldCanvas *wc, State &state );
00115 
00116             // called when the user (read GUI user) indicates that a region should be deleted...
00117             void revokeRegion( viewer::Region * );
00118 
00119             // returns a set which indicates regions this creator creates...
00120             const std::set<viewer::region::RegionTypes> &regionsCreated( ) const;
00121 
00122             bool create( viewer::region::RegionTypes /*region_type*/, WorldCanvas */*wc*/, const std::vector<std::pair<double,double> > &/*pts*/,
00123                          const std::string &/*label*/, viewer::region::TextPosition /*label_pos*/, const std::vector<int> &/*label_off*/,
00124                          const std::string &/*font*/, int /*font_size*/, int /*font_style*/, const std::string &/*font_color*/,
00125                          const std::string &/*line_color*/, viewer::region::LineStyle /*line_style*/, unsigned int /*line_width*/,
00126                          bool /*annotation*/, VOID */*region_specific_state*/ );
00127 
00128             RegionToolTypes type( ) const { return POLYTOOL; }
00129 
00130         protected:
00131 
00132             // Functions called by the base class event handling operators--and
00133             // normally only those.  This is the input that controls the polygon's
00134             // appearance and action.  When the polygon is ready and double-click
00135             // is received, the doubleInside/Outside routine is invoked.
00136             // <group>
00137             virtual void keyPressed(const WCPositionEvent &/*ev*/);
00138             virtual void moved(const WCMotionEvent &/*ev*/, const viewer::region::region_list_type & /*selected_regions*/);
00139             virtual void keyReleased(const WCPositionEvent &/*ev*/);
00140             virtual void otherKeyPressed(const WCPositionEvent &/*ev*/);
00141             // </group>
00142 
00143             // draw the polygon (if any) on the object's currently active WC.
00144             // Only to be called by the base class refresh event handler.  Derived
00145             // objects should use refresh() if they need to redraw, but even that
00146             // is normally handled automatically by this class.
00147             virtual void draw(const WCRefreshEvent&/*ev*/, const viewer::region::region_list_type & /*selected_regions*/);
00148 
00149             // Output callback functions--to be overridden in derived class as needed.
00150             // Called when there is a double click inside/outside the polygon
00151             // <group>
00152             virtual void doubleInside() { };
00153             virtual void doubleOutside() { };
00154             // </group>
00155 
00156             // Function called when a polygon is ready and not being 
00157             // edited.  (Unused so far on the glish level (12/01)).
00158             virtual void polygonReady() { };
00159 
00160             // Retrieve polygon vertices, or a single vertex, in screen pixels.
00161             // Valid results during the callback functions; to be used by them,
00162             // as well as internally.
00163             // <group>
00164             virtual void get(Vector<Int> &x, Vector<Int> &y) const;
00165             virtual void get(Int &x, Int &y, const Int pt) const;
00166             // </group>
00167 
00168                 virtual bool checkType( viewer::region::RegionTypes t ) { return t == viewer::region::PolyRegion; }
00169 
00170         private:
00171             typedef std::list<std::tr1::shared_ptr<viewer::Polygon> > polygonlist;
00172 
00173             void start_new_polygon( WorldCanvas *, int x, int y );
00174 
00175             // Set the polygon vertices. itsNPoints should already be set, and
00176             // x and y must contain (at least) this many points.
00177             virtual void set(const Vector<Int> &x, const Vector<Int> &y);
00178 
00179             // replace a single vertex.
00180             virtual void set(const Int x, const Int y, const Int pt);
00181 
00182             std::tr1::shared_ptr<viewer::Polygon> resizing_region;
00183             std::tr1::shared_ptr<viewer::Polygon> creating_region;
00184 
00185             // push/pop last vertex
00186             // <group>
00187             void pushPoint(Int x1, Int y1);
00188             void popPoint();
00189             // </group>
00190 
00191             // are we inside the polygon?
00192             Bool inPolygon(const Int &x, const Int &y) const;
00193 
00194             // are we within the specified handle?
00195             Bool inHandle(const Int &pt, const Int &x, const Int &y) const;
00196 
00197 
00198             // should the polygon remain on screen after double clicks?
00199             Bool itsPolygonPersistent;
00200 
00201             // state of the polyline tool
00202             enum AdjustMode {
00203                 Off,    // Nothing exists yet
00204                 Def,    // defining initial polygon
00205                 Ready,  // polygon finished, no current activity
00206                 Move,   // moving entire polygon
00207                 Resize };       // moving single vertex whose handle was pressed
00208             MultiPolyTool::AdjustMode itsMode;
00209 
00210             // set True on double-click, if the polygon is persistent.
00211             // set False when the polygon is moved, resized or reset.
00212             // If True, a click outside the polygon will erase it and begin
00213             // definition of a new one.
00214             Bool itsEmitted;
00215 
00216             // Number of points
00217             Int itsNPoints;
00218 
00219             // Polygon points (linear).  Not to be used directly.
00220             // use get, set, push, pop instead, which take pixel coordinate arguments.
00221             // It's done this way so that zooms work on the figures.
00222             Vector<Double> itsX, itsY;
00223 
00224             // size in pixels of the handles
00225             Int itsHandleSize;
00226   
00227             // vertex being moved
00228             Int itsSelectedHandle;
00229 
00230             // position that move started from
00231             Int itsBaseMoveX, itsBaseMoveY;
00232 
00233             // may not be needed...
00234             int resizing_region_handle;
00235 
00236             polygonlist moving_regions;
00237             double moving_linx_;
00238             double moving_liny_;
00239 
00240             std::tr1::shared_ptr<viewer::Polygon> building_polygon;
00241             viewer::RegionSource *rfactory;
00242             polygonlist polygons;
00243             PanelDisplay *pd_;
00244         };
00245 
00246 } //# NAMESPACE CASA - END
00247 
00248 #endif
00249 
00250