00001
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 }
00608
00609
00610
00611 #endif
00612