/ dashing.cc
dashing.cc
1 #include "parse_numbers.hh" 2 #include "dashing.hh" 3 namespace dashing 4 { 5 std::vector<double> parse_numbers(std::string line) { 6 boost::algorithm::replace_all(line, ",", " "); 7 std::istringstream fi(line); 8 std::vector<double> result; 9 double d; 10 while((fi >> d)) result.push_back(d); 11 return result; 12 } 13 14 PSMatrix PSMatrix::inverse() const { 15 auto i = 1. / determinant(); 16 return PSMatrix{d*i, -b*i, -c*i, a*i, i*(c*f-e*d), i*(b*e-a*f)}; 17 } 18 19 PSMatrix Translation(double x, double y) { 20 PSMatrix r{1.,0.,0.,1.,x,y}; 21 return r; 22 } 23 24 PSMatrix Rotation(double theta) { 25 double c = cos(theta), s = sin(theta); 26 PSMatrix r{c,s,-s,c,0.,0.}; 27 return r; 28 } 29 30 PSMatrix XSkew(double xk) { 31 PSMatrix r{1.,0.,xk,1.,0.,0.}; 32 return r; 33 } 34 35 PSMatrix YScale(double ys) { 36 PSMatrix r{1.,0.,0.,ys,0.,0.}; 37 return r; 38 } 39 40 PSMatrix operator*(const PSMatrix &m1, const PSMatrix m2) { 41 PSMatrix r{ 42 m2.a * m1.a + m2.b * m1.c, 43 m2.a * m1.b + m2.b * m1.d, 44 m2.c * m1.a + m2.d * m1.c, 45 m2.c * m1.b + m2.d * m1.d, 46 m2.e * m1.a + m2.f * m1.c + m1.e, 47 m2.e * m1.b + m2.f * m1.d + m1.f}; 48 return r; 49 } 50 51 static double radians(double degrees) { return degrees * acos(0) / 90.; } 52 53 Dash::Dash(double th, double x0, double y0, double dx, double dy, 54 const std::vector<double>::const_iterator dbegin, 55 const std::vector<double>::const_iterator dend) : dash(dbegin, dend) { 56 auto s = 0.; 57 for(auto d : dash) { sum.push_back(s); s += fabs(d); } 58 sum.push_back(s); 59 60 tr = Translation(x0, y0) * Rotation(th) * XSkew(dx / dy) * YScale(dy); 61 tf = tr.inverse(); 62 } 63 64 Dash Dash::FromString(const std::string &line, double scale) { 65 std::vector<double> words = parse_numbers(line); 66 if(words.size() < 5) 67 throw std::invalid_argument("not a valid dash specification"); 68 for(auto i = words.begin() + 1; i != words.end(); i++) *i *= scale; 69 return Dash(radians(words.at(0)), words.at(1), words.at(2), words.at(3), 70 words.at(4), words.begin() + 5, words.end()); 71 } 72 73 }