1 /**
2  * @file   tilings.cpp
3  * @author Sebastien Fourey (GREYC)
4  *
5  * @brief  Sample program that draws a ruler.
6  *
7  * This source code is part of the Board project, a C++ library whose
8  * purpose is to allow simple drawings in EPS, FIG or SVG files.
9  * Copyright (C) 2007 Sebastien Fourey <http://foureys.users.greyc.fr>
10  */
11 #include "Board.h"
12 #include <cstdlib>
13 #include <cmath>
14 #include <limits>
15 #include <vector>
16 #include <cassert>
17 using namespace LibBoard;
18 
19 #include <board/PathBoundaries.h>
20 
strikeOut(const Path & path,double strokeWidth,Shape::LineCap lineCap,Shape::LineJoin lineJoin,double miterLimit=4.0)21 ShapeList strikeOut( const Path & path,
22                      double strokeWidth,
23                      Shape::LineCap lineCap,
24                      Shape::LineJoin lineJoin,
25                      double miterLimit = 4.0 )
26 {
27   const double s = 1.0;
28   ShapeList list;
29   std::vector<Point> e = Tools::pathBoundaryPoints(path,strokeWidth,lineCap, lineJoin, miterLimit );
30   size_t limit = (path.closed()?path.size():(path.size()-1));
31   for ( size_t i = 0; i < limit; ++i ) {
32     Point a = path[i];
33     Point b = path[(i+1)%path.size()];
34     Point v = b-a;
35     Point shift  = 0.5 * strokeWidth * v.rotatedPI2().normalise();
36     list << Line(a+shift,b+shift,Color::Black,strokeWidth*0.01).scale(s);
37     list << Line(a-shift,b-shift,Color::Black,strokeWidth*0.01).scale(s);
38     list << Line(a,b,Color::Red,strokeWidth*0.01);
39     if ( (lineCap == Shape::RoundCap) || (lineJoin == Shape::RoundJoin)) {
40       list << Circle(a,strokeWidth*0.5,Color::Green,Color::Null,strokeWidth*0.01);
41     }
42   }
43   if ( (!path.closed() && lineCap == Shape::RoundCap) || (lineJoin == Shape::RoundJoin) ) {
44     Point a = path[path.size()-1];
45     list << Circle(a,strokeWidth*0.5,Color::Green,Color::Null,strokeWidth*0.01);
46   }
47 
48   for ( size_t i = 0; i < e.size(); ++i ) {
49     Point c = e[i];
50     list << Circle(c,10.0,Color::Blue,Color::Null,strokeWidth*0.01);
51     list << Line(c-Point(10.0,0.0), c+Point(10.0,0),Color::Blue,strokeWidth*0.01);
52     list << Line(c-Point(0.0,10.0), c+Point(0,10.0),Color::Blue,strokeWidth*0.01);
53   }
54   return list;
55 }
56 
main(int,char * [])57 int main( int , char *[] )
58 {
59   Board board;
60   Shape::enableLineWidthScaling();
61   board.clear( Color::White);
62 
63   // http://www.w3.org/TR/SVG/painting.html#StrokeProperties
64 
65   Point p1(30,366);
66   Point p2(200,400);
67   Point p3(0,0);
68   Point p4(-100,20);
69   Point p5(-50,-100);
70 
71   Path pA(true);
72   pA<<p1<<p2<<p3<<p4<<p5;
73   Path pB(true);
74   pB<<Point(0,0)<<Point(180,0)<<Point(180,300)<<Point(0,300);
75   Path pC(true);
76   pC << Point(0,0) << Point(200,0) << Point(500,5) << Point(150,200);
77 
78   Path losange;
79   losange << Point(0,0) << Point(300,-500) << Point(600,0) << Point(300,500);
80 
81   ShapeList l;
82   l.append( strikeOut(pA,50.0,Shape::RoundCap,Shape::MiterJoin, 3.0 ),
83             ShapeList::Right, ShapeList::AlignCenter, 30.0 );
84   l.append( strikeOut(pB,50.0,Shape::RoundCap,Shape::BevelJoin, 3.0 ),
85             ShapeList::Right, ShapeList::AlignCenter, 30.0 );
86   l.append( strikeOut(pC,50.0,Shape::RoundCap,Shape::MiterJoin, 3.0 ),
87             ShapeList::Right, ShapeList::AlignCenter, 30.0 );
88   l.append( strikeOut(pA,50.0,Shape::RoundCap,Shape::RoundJoin, 3.0 ),
89             ShapeList::Right, ShapeList::AlignCenter, 30.0 );
90   l.append(Text(0,0,"Round cap, miter/bevel/miter/round join",Fonts::Courier,14.0),ShapeList::Right,ShapeList::AlignCenter);
91   board.append(l,ShapeList::Bottom,ShapeList::AlignLeft);
92 
93   l.clear();
94   l.append( strikeOut(pA,50.0,Shape::ButtCap,Shape::MiterJoin, 3.0 ),
95             ShapeList::Right, ShapeList::AlignCenter, 30.0 );
96   l.append( strikeOut(pB,50.0,Shape::ButtCap,Shape::BevelJoin, 3.0 ),
97             ShapeList::Right, ShapeList::AlignCenter, 30.0 );
98   l.append( strikeOut(pC,50.0,Shape::ButtCap,Shape::MiterJoin, 3.0 ),
99             ShapeList::Right, ShapeList::AlignCenter, 30.0 );
100   l.append( strikeOut(pA,50.0,Shape::ButtCap,Shape::RoundJoin, 3.0 ),
101             ShapeList::Right, ShapeList::AlignCenter, 30.0 );
102   l.append(Text(0,0,"Butt cap, miter/bevel/miter/round join",Fonts::Courier,14.0),ShapeList::Right,ShapeList::AlignCenter);
103   board.append(l,ShapeList::Bottom,ShapeList::AlignLeft);
104 
105   l.clear();
106   l.append( strikeOut(pA,50.0,Shape::SquareCap,Shape::MiterJoin, 3.0 ),
107             ShapeList::Right, ShapeList::AlignCenter, 30.0 );
108   l.append( strikeOut(pB,50.0,Shape::SquareCap,Shape::BevelJoin, 3.0 ),
109             ShapeList::Right, ShapeList::AlignCenter, 30.0 );
110   l.append( strikeOut(pC,50.0,Shape::SquareCap,Shape::MiterJoin, 3.0 ),
111             ShapeList::Right, ShapeList::AlignCenter, 30.0 );
112   l.append( strikeOut(pA,50.0,Shape::SquareCap,Shape::RoundJoin, 3.0 ),
113             ShapeList::Right, ShapeList::AlignCenter, 30.0 );
114   l.append(Text(0,0,"Square cap, miter/bevel/miter/round join",Fonts::Courier,14.0),ShapeList::Right,ShapeList::AlignCenter);
115   board.append(l,ShapeList::Bottom,ShapeList::AlignLeft);
116 
117   ShapeList list;
118   Polyline poly(true,Color::Blue,Color::Null,1.0,Shape::SolidStyle,Shape::ButtCap,Shape::MiterJoin);
119   poly << Point(0,0) << Point(30,-50) << Point(60,0) << Point(30,50);
120   list.append(poly,ShapeList::Right,ShapeList::AlignCenter);
121   list.append(poly,ShapeList::Right,ShapeList::AlignCenter);
122   board.append(list,ShapeList::Right,ShapeList::AlignCenter);
123   board.append( Rectangle(0,0,100,30).rotateDeg(40).scale(1.5,1.0),
124                 ShapeList::Right,ShapeList::AlignCenter);
125 
126   board.saveEPS( "stroke_path.eps" , Board::A4 );
127 
128   board.scaleToWidth(25,Board::UseLineWidth);
129   board.saveSVG( "stroke_path.svg", Board::BoundingBox, 0.0, Board::UCentimeter );
130 }
131