01f83bf5ecf86e26e7320d5a232c488b74c153c5
1 #include <2geom/d2.h>
2 /* One would think that we would include d2-sbasis.h, however,
3 * you cannot actually include it in anything - only d2 may import it.
4 * This is due to the trickinesses of template submatching. */
6 namespace Geom {
8 SBasis L2(D2<SBasis> const & a, unsigned k) { return sqrt(dot(a, a), k); }
10 D2<SBasis> multiply(Linear const & a, D2<SBasis> const & b) {
11 return D2<SBasis>(multiply(a, b[X]), multiply(a, b[Y]));
12 }
14 D2<SBasis> multiply(SBasis const & a, D2<SBasis> const & b) {
15 return D2<SBasis>(multiply(a, b[X]), multiply(a, b[Y]));
16 }
18 D2<SBasis> truncate(D2<SBasis> const & a, unsigned terms) {
19 return D2<SBasis>(truncate(a[X], terms), truncate(a[Y], terms));
20 }
22 unsigned sbasis_size(D2<SBasis> const & a) {
23 return std::max((unsigned) a[0].size(), (unsigned) a[1].size());
24 }
26 //TODO: Is this sensical? shouldn't it be like pythagorean or something?
27 double tail_error(D2<SBasis> const & a, unsigned tail) {
28 return std::max(a[0].tailError(tail), a[1].tailError(tail));
29 }
31 Piecewise<D2<SBasis> > sectionize(D2<Piecewise<SBasis> > const &a) {
32 Piecewise<SBasis> x = partition(a[0], a[1].cuts), y = partition(a[1], a[0].cuts);
33 assert(x.size() == y.size());
34 Piecewise<D2<SBasis> > ret;
35 for(unsigned i = 0; i < x.size(); i++)
36 ret.push_seg(D2<SBasis>(x[i], y[i]));
37 ret.cuts.insert(ret.cuts.end(), x.cuts.begin(), x.cuts.end());
38 return ret;
39 }
41 D2<Piecewise<SBasis> > make_cuts_independent(Piecewise<D2<SBasis> > const &a) {
42 D2<Piecewise<SBasis> > ret;
43 for(unsigned d = 0; d < 2; d++) {
44 for(unsigned i = 0; i < a.size(); i++)
45 ret[d].push_seg(a[i][d]);
46 ret[d].cuts.insert(ret[d].cuts.end(), a.cuts.begin(), a.cuts.end());
47 }
48 return ret;
49 }
51 Piecewise<D2<SBasis> > rot90(Piecewise<D2<SBasis> > const &M){
52 Piecewise<D2<SBasis> > result;
53 if (M.empty()) return M;
54 result.push_cut(M.cuts[0]);
55 for (unsigned i=0; i<M.size(); i++){
56 result.push(rot90(M[i]),M.cuts[i+1]);
57 }
58 return result;
59 }
61 Piecewise<SBasis> dot(Piecewise<D2<SBasis> > const &a,
62 Piecewise<D2<SBasis> > const &b){
63 Piecewise<SBasis > result;
64 if (a.empty() || b.empty()) return result;
65 Piecewise<D2<SBasis> > aa = partition(a,b.cuts);
66 Piecewise<D2<SBasis> > bb = partition(b,a.cuts);
68 result.push_cut(aa.cuts.front());
69 for (unsigned i=0; i<aa.size(); i++){
70 result.push(dot(aa.segs[i],bb.segs[i]),aa.cuts[i+1]);
71 }
72 return result;
73 }
75 Piecewise<SBasis> cross(Piecewise<D2<SBasis> > const &a,
76 Piecewise<D2<SBasis> > const &b){
77 Piecewise<SBasis > result;
78 if (a.empty() || b.empty()) return result;
79 Piecewise<D2<SBasis> > aa = partition(a,b.cuts);
80 Piecewise<D2<SBasis> > bb = partition(b,a.cuts);
82 result.push_cut(aa.cuts.front());
83 for (unsigned i=0; i<a.size(); i++){
84 result.push(cross(aa.segs[i],bb.segs[i]),aa.cuts[i+1]);
85 }
86 return result;
87 }
89 Piecewise<D2<SBasis> > operator*(Piecewise<D2<SBasis> > const &a, Matrix const &m) {
90 Piecewise<D2<SBasis> > result;
91 if(a.empty()) return result;
92 result.push_cut(a.cuts[0]);
93 for (unsigned i = 0; i < a.size(); i++) {
94 result.push(a[i] * m, a.cuts[i+1]);
95 }
96 return result;
97 }
99 //if tol>0, only force continuity where the jump is smaller than tol.
100 Piecewise<D2<SBasis> > force_continuity(Piecewise<D2<SBasis> > const &f, double tol, bool closed)
101 {
102 if (f.size()==0) return f;
103 Piecewise<D2<SBasis> > result=f;
104 unsigned cur = (closed)? 0:1;
105 unsigned prev = (closed)? f.size()-1:0;
106 while(cur<f.size()){
107 Point pt0 = f.segs[prev].at1();
108 Point pt1 = f.segs[cur ].at0();
109 if (tol<=0 || L2sq(pt0-pt1)<tol*tol){
110 pt0 = (pt0+pt1)/2;
111 for (unsigned dim=0; dim<2; dim++){
112 SBasis &prev_sb=result.segs[prev][dim];
113 SBasis &cur_sb =result.segs[cur][dim];
114 Coord const c=pt0[dim];
115 if (prev_sb.empty()) {
116 prev_sb.push_back(Linear(0.0, c));
117 } else {
118 prev_sb[0][1] = c;
119 }
120 if (cur_sb.empty()) {
121 cur_sb.push_back(Linear(c, 0.0));
122 } else {
123 cur_sb[0][0] = c;
124 }
125 }
126 }
127 prev = cur++;
128 }
129 return result;
130 }
132 std::vector<Geom::Piecewise<Geom::D2<Geom::SBasis> > >
133 split_at_discontinuities (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwsbin, double tol)
134 {
135 using namespace Geom;
136 std::vector<Piecewise<D2<SBasis> > > ret;
137 unsigned piece_start = 0;
138 for (unsigned i=0; i<pwsbin.segs.size(); i++){
139 if (i==(pwsbin.segs.size()-1) || L2(pwsbin.segs[i].at1()- pwsbin.segs[i+1].at0()) > tol){
140 Piecewise<D2<SBasis> > piece;
141 piece.cuts.push_back(pwsbin.cuts[piece_start]);
142 for (unsigned j = piece_start; j<i+1; j++){
143 piece.segs.push_back(pwsbin.segs[j]);
144 piece.cuts.push_back(pwsbin.cuts[j+1]);
145 }
146 ret.push_back(piece);
147 piece_start = i+1;
148 }
149 }
150 return ret;
151 }
153 } // namespace Geom
156 /*
157 Local Variables:
158 mode:c++
159 c-file-style:"stroustrup"
160 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
161 indent-tabs-mode:nil
162 fill-column:99
163 End:
164 */
165 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :