include/board/Shapes.h

00001 /* -*- mode: c++ -*- */
00010 #ifndef _BOARD_SHAPES_H_
00011 #define _BOARD_SHAPES_H_
00012 
00013 #include "board/Point.h"
00014 #include "board/Rect.h"
00015 #include "board/Color.h"
00016 #include "board/Transforms.h"
00017 #include <string>
00018 #include <vector>
00019 #include <iostream>
00020 #include <map>
00021 #include <cmath>
00022 
00023 #ifndef M_PI
00024 #define M_PI           3.14159265358979323846
00025 #endif
00026 
00027 #ifndef M_PI_2
00028 #define M_PI_2         1.57079632679489661923
00029 #endif
00030 
00031 namespace BoardLib {
00032 
00037 struct Shape {
00038 
00039   enum LineCap { ButtCap = 0, RoundCap, SquareCap };
00040   enum LineJoin { MiterJoin = 0, RoundJoin, BevelJoin };
00041 
00050   Shape( Color penColor, Color fillColor,
00051          float lineWidth, const LineCap cap, const LineJoin join,
00052          int depth )
00053     : _depth( depth ), _penColor( penColor ), _fillColor( fillColor ), 
00054       _lineWidth( lineWidth ), _lineCap( cap ), _lineJoin( join ) { }
00055 
00059   virtual ~Shape() { }
00060 
00066   virtual Shape * clone() const = 0;
00067   
00073   inline bool filled() const { return _fillColor != Color::none; }
00074   
00080   virtual Point center() const = 0;
00081   
00090   virtual Shape & rotate( double angle, const Point & center ) = 0;
00091 
00099   virtual Shape & rotate( double angle ) = 0;
00100 
00109   inline Shape & rotateDeg( double angle, const Point & center );
00110   
00119   inline Shape & rotateDeg( double angle );
00120 
00129   virtual Shape & translate( double dx, double dy ) = 0;
00130 
00139   virtual Shape & scale( double sx, double sy ) = 0;
00140 
00148   virtual void flushPostscript( std::ostream & stream,
00149                                 const TransformEPS & transform ) const = 0;
00150 
00158   virtual void flushFIG( std::ostream & stream,
00159                          const TransformFIG & transform,
00160                          std::map<Color,int> & colormap ) const = 0;
00161 
00169   virtual void flushSVG( std::ostream & stream,
00170                          const TransformSVG & transform ) const = 0;
00171   
00177   virtual Rect boundingBox() const = 0;
00178 
00179 
00180   inline int depth() const;
00181   virtual void depth( int );
00182   inline const Color & penColor() const;
00183   inline const Color & fillColor() const;
00184   
00185 protected:
00186 
00187   int _depth;                   
00188   Color _penColor;              
00189   Color _fillColor;             
00190   float _lineWidth;             
00191   LineCap _lineCap;             
00192   LineJoin _lineJoin;           
00200   std::string svgProperties( const TransformSVG & transform ) const;
00201 
00202   
00208   std::string postscriptProperties() const;
00209 
00210 };
00211 
00212 inline int
00213 Shape::depth() const
00214 {
00215   return _depth;
00216 }
00217 
00218 inline const Color &
00219 Shape::penColor() const
00220 {
00221   return _penColor;
00222 }
00223 
00224 const Color &
00225 Shape::fillColor() const
00226 {
00227   return _fillColor;
00228 }
00229 
00230 Shape &
00231 Shape::rotateDeg( double angle, const Point & center )
00232 {
00233   return rotate( angle * ( M_PI / 180.0 ), center ); 
00234 }
00235 
00236 Shape &
00237 Shape::rotateDeg( double angle )
00238 {
00239   return rotate( angle * ( M_PI / 180.0 ), center() ); 
00240 }
00241 
00246 struct Line : public Shape { 
00247   
00259   Line( double x1, double y1, double x2, double y2, 
00260         Color color, 
00261         float lineWidth, const LineCap cap = ButtCap, const LineJoin join = MiterJoin,
00262         int depth = -1 )
00263     : Shape( color, Color::none, lineWidth, cap, join, depth ),
00264       _x1( x1 ), _y1( y1 ), _x2( x2 ), _y2( y2 ) { }
00265 
00266   Point center() const;
00267 
00268   Shape & rotate( double angle, const Point & center );
00269 
00270   Shape & rotate( double angle );
00271 
00272   Shape & translate( double dx, double dy );
00273 
00274   Shape & scale( double sx, double sy );
00275   
00276   void flushPostscript( std::ostream & stream,
00277                         const TransformEPS & transform ) const;
00278   
00279   void flushFIG( std::ostream & stream,
00280                  const TransformFIG & transform,
00281                  std::map<Color,int> & colormap ) const;
00282 
00283   void flushSVG( std::ostream & stream,
00284                  const TransformSVG & transform ) const;
00285 
00286   Rect boundingBox() const;
00287 
00288   Shape * clone() const { return new Line(*this); }
00289 
00290 protected:
00291   double _x1;                   
00292   double _y1;                   
00293   double _x2;                   
00294   double _y2;                   
00295 };
00296 
00301 struct Arrow : public Line { 
00302 
00315   Arrow( double x1, double y1, double x2, double y2,
00316          Color penColor, Color fillColor,
00317          float lineWidth, const LineCap cap = ButtCap, const LineJoin join = MiterJoin,
00318          int depth = -1 )
00319     : Line( x1, y1, x2, y2, penColor, lineWidth, cap, join, depth ) {
00320     Shape::_fillColor = fillColor;
00321   }
00322   
00323   void flushPostscript( std::ostream & stream,
00324                         const TransformEPS & transform ) const;
00325   
00326   void flushFIG( std::ostream & stream,
00327                  const TransformFIG & transform,
00328                  std::map<Color,int> & colormap ) const;
00329   void flushSVG( std::ostream & stream,
00330                  const TransformSVG & transform ) const;
00331 
00332   Shape * clone() const { return new Arrow(*this); }
00333 };
00334 
00339 struct Polyline : public Shape { 
00340   Polyline( const std::vector<Point> & points, 
00341             bool closed,
00342             Color penColor, Color fillColor,
00343             float lineWidth, const LineCap cap = ButtCap, const LineJoin join = MiterJoin,
00344             int depth = -1 )
00345     : Shape( penColor, fillColor, lineWidth, cap, join, depth ),
00346       _points( points ), _closed( closed ) { }
00347             
00348   Point center() const;
00349 
00350   Shape & rotate( double angle, const Point & center );
00351 
00352   Shape & rotate( double angle );
00353 
00354   Shape & translate( double dx, double dy );
00355 
00356   Shape & scale( double sx, double sy );
00357 
00358   void flushPostscript( std::ostream & stream,
00359                         const TransformEPS & transform ) const;
00360 
00361   void flushFIG( std::ostream & stream,
00362                  const TransformFIG & transform,
00363                  std::map<Color,int> & colormap ) const;
00364 
00365   void flushSVG( std::ostream & stream,
00366                  const TransformSVG & transform ) const;
00367 
00368   Rect boundingBox() const;
00369 
00370   Shape * clone() const { return new Polyline(*this); }
00371 
00372 protected:
00373   std::vector<Point> _points;
00374   bool _closed;
00375 };
00376 
00381 struct Rectangle : public Polyline {
00382 
00383   Rectangle( double x, double y, double width, double height,
00384              Color penColor, Color fillColor,
00385              float lineWidth, const LineCap cap = ButtCap, const LineJoin join = MiterJoin,
00386              int depth = -1 )
00387     : Polyline( std::vector<Point>(), true, penColor, fillColor, lineWidth, cap, join, depth ) {
00388     _points.push_back( Point( x, y ) );
00389     _points.push_back( Point( x + width, y ) );
00390     _points.push_back( Point( x + width, y - height ) );
00391     _points.push_back( Point( x, y - height ) );
00392   }
00393   
00394   Rectangle( const Rect & rect,
00395              Color penColor, Color fillColor,
00396              float lineWidth, const LineCap cap = ButtCap, const LineJoin join = MiterJoin,
00397              int depth = -1 )
00398     : Polyline( std::vector<Point>(), true, penColor, fillColor, lineWidth, cap, join, depth ) {
00399     _points.push_back( Point( rect.left, rect.top ) );
00400     _points.push_back( Point( rect.left + rect.width, rect.top ) );
00401     _points.push_back( Point( rect.left + rect.width, rect.top - rect.height ) );
00402     _points.push_back( Point( rect.left, rect.top - rect.height ) );
00403   }
00404 
00405   double x() const { return _points[0].x; }
00406   double y() const { return _points[0].y; }
00407   double width() { return (_points[1] - _points[0]).norm(); }
00408   double height() { return (_points[0] - _points[3]).norm(); }
00409   
00410   void flushFIG( std::ostream & stream,
00411                  const TransformFIG & transform,
00412                  std::map<Color,int> & colormap ) const;
00413 
00414   void flushSVG( std::ostream & stream,
00415                  const TransformSVG & transform ) const;
00416 
00417   Shape * clone() const { return new Rectangle(*this); }
00418 };
00419 
00424 struct GouraudTriangle : public Polyline {
00425 
00426   GouraudTriangle( const Point & p0, const Color & color0,
00427                    const Point & p1, const Color & color1,
00428                    const Point & p2, const Color & color2,
00429                    int subdivisions,
00430                    int depth = -1 );
00431 
00432   GouraudTriangle( const Point & p0, float brightness0,
00433                    const Point & p1, float brightness1,
00434                    const Point & p2, float brightness2,
00435                    const Color & fillColor,
00436                    int subdivisions,
00437                    int depth = -1 );
00438 
00439   Point center() const;
00440 
00441   Shape & rotate( double angle, const Point & center );  
00442   Shape & rotate( double angle );
00443 
00444   void flushPostscript( std::ostream & stream,
00445                         const TransformEPS & transform ) const;
00446 
00459   void flushFIG( std::ostream & stream,
00460                  const TransformFIG & transform,
00461                  std::map<Color,int> & colormap ) const;
00462 
00463   void flushSVG( std::ostream & stream,
00464                  const TransformSVG & transform ) const;
00465 
00466   Shape * clone() const { return new GouraudTriangle(*this); }
00467 protected:
00468   Color _color0;
00469   Color _color1;
00470   Color _color2;
00471   int _subdivisions;
00472 };
00473 
00478 struct Ellipse : public Shape {
00479   
00480   Ellipse( double x, double y, 
00481            double xRadius, double yRadius, 
00482            Color penColor, Color fillColor,
00483            float lineWidth, int depth = -1 )
00484     : Shape( penColor, fillColor, lineWidth,  ButtCap, MiterJoin, depth ),
00485       _center( x, y ), _xRadius( xRadius ), _yRadius( yRadius ), _angle( 0.0 ),
00486       _circle( false ) {
00487     while ( _angle > M_PI_2 ) _angle -= M_PI;
00488     while ( _angle < -M_PI_2 ) _angle += M_PI;
00489   }
00490 
00491   Point center() const;
00492 
00493   Shape & rotate( double angle, const Point & center );
00494   Shape & rotate( double angle );
00495   
00496   Shape & translate( double dx, double dy );
00497 
00498   Shape & scale( double sx, double sy );
00499   
00500   void flushPostscript( std::ostream & stream,
00501                         const TransformEPS & transform ) const;
00502 
00503   void flushFIG( std::ostream & stream,
00504                  const TransformFIG & transform,
00505                  std::map<Color,int> & colormap ) const;
00506 
00507   void flushSVG( std::ostream & stream,
00508                  const TransformSVG & transform ) const;
00509 
00510   Rect boundingBox() const;
00511 
00512   Shape * clone() const { return new Ellipse(*this); }
00513  
00514 protected:
00515   Point _center;
00516   double _xRadius; 
00517   double _yRadius;
00518   double _angle;
00519   bool _circle;
00520 };
00521 
00526 struct Circle : public Ellipse {
00527 
00528   Circle( double x, double y, double radius, 
00529           Color penColor, Color fillColor,
00530           float lineWidth,
00531           int depth = -1 )
00532     : Ellipse( x, y, radius, radius, penColor, fillColor, lineWidth, depth )
00533   { _circle = true; }
00534 
00535   Point center() const;
00536 
00537   Shape & rotate( double angle, const Point & center );
00538 
00539   Shape & rotate( double angle );
00540   
00541   Shape & translate( double dx, double dy );
00542 
00543   Shape & scale( double sx, double sy );
00544 
00545   void flushSVG( std::ostream & stream,
00546                  const TransformSVG & transform ) const;
00547 
00548   Shape * clone() const { return new Circle(*this); }
00549 };
00550 
00555 struct Text : public Shape {
00556   
00557   Text( double x, double y,
00558         const std::string & text, const std::string & font, float size,
00559         Color color, int depth = -1 )
00560     : Shape( color, Color::none, 1.0, ButtCap, MiterJoin, depth ),
00561       _position( x, y ), _text( text ), _font( font ), _size( size ),
00562       _xScale( 1.0 ), _yScale( 1.0 ) { }
00563   
00564   Point center() const;
00565 
00566   Shape & rotate( double angle, const Point & center );
00567 
00568   Shape & rotate( double angle );
00569   
00570   Shape & translate( double dx, double dy );
00571 
00572   Shape & scale( double sx, double sy );
00573   
00574   void flushPostscript( std::ostream & stream,
00575                         const TransformEPS & transform ) const;
00576 
00577   void flushFIG( std::ostream & stream,
00578                  const TransformFIG & transform,
00579                  std::map<Color,int> & colormap ) const;
00580 
00581   void flushSVG( std::ostream & stream,
00582                  const TransformSVG & transform ) const;
00583 
00584   Rect boundingBox() const;
00585 
00586   Shape * clone() const { return new Text(*this); }
00587 
00588 protected:
00589   Point _position;
00590   std::string _text;
00591   std::string _font;
00592   float _size;
00593   double _xScale;
00594   double _yScale;
00595 };
00596 
00605 bool shapeGreaterDepth( const Shape *s1, const Shape *s2 );
00606 
00607 } // namespace BoardLib 
00608 
00609 
00610 
00611 #endif /* _SHAPE_H_ */
00612 

Generated on Mon Dec 17 11:15:51 2007 for Board by  doxygen 1.5.3-20071008