Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
sbasis-2d.cpp
Go to the documentation of this file.
1#include <2geom/sbasis-2d.h>
3
4namespace Geom{
5
6SBasis extract_u(SBasis2d const &a, double u) {
7 SBasis sb(a.vs, Linear());
8 double s = u*(1-u);
9
10 for(unsigned vi = 0; vi < a.vs; vi++) {
11 double sk = 1;
12 Linear bo(0,0);
13 for(unsigned ui = 0; ui < a.us; ui++) {
14 bo += (extract_u(a.index(ui, vi), u))*sk;
15 sk *= s;
16 }
17 sb[vi] = bo;
18 }
19
20 return sb;
21}
22
23SBasis extract_v(SBasis2d const &a, double v) {
24 SBasis sb(a.us, Linear());
25 double s = v*(1-v);
26
27 for(unsigned ui = 0; ui < a.us; ui++) {
28 double sk = 1;
29 Linear bo(0,0);
30 for(unsigned vi = 0; vi < a.vs; vi++) {
31 bo += (extract_v(a.index(ui, vi), v))*sk;
32 sk *= s;
33 }
34 sb[ui] = bo;
35 }
36
37 return sb;
38}
39
40SBasis compose(Linear2d const &a, D2<SBasis> const &p) {
41 D2<SBasis> omp(-p[X] + 1, -p[Y] + 1);
42 return multiply(omp[0], omp[1])*a[0] +
43 multiply(p[0], omp[1])*a[1] +
44 multiply(omp[0], p[1])*a[2] +
45 multiply(p[0], p[1])*a[3];
46}
47
48SBasis
49compose(SBasis2d const &fg, D2<SBasis> const &p) {
50 SBasis B;
51 SBasis s[2];
52 SBasis ss[2];
53 for(unsigned dim = 0; dim < 2; dim++)
54 s[dim] = p[dim]*(Linear(1) - p[dim]);
55 ss[1] = Linear(1);
56 for(unsigned vi = 0; vi < fg.vs; vi++) {
57 ss[0] = ss[1];
58 for(unsigned ui = 0; ui < fg.us; ui++) {
59 unsigned i = ui + vi*fg.us;
60 B += ss[0]*compose(fg[i], p);
61 ss[0] *= s[0];
62 }
63 ss[1] *= s[1];
64 }
65 return B;
66}
67
68D2<SBasis>
69compose_each(D2<SBasis2d> const &fg, D2<SBasis> const &p) {
70 return D2<SBasis>(compose(fg[X], p), compose(fg[Y], p));
71}
72
75 for(unsigned i = 0; i < f.size(); i++) {
76 result.push_back(Linear2d(0,0,0,0));
77 }
78 result.us = f.us;
79 result.vs = f.vs;
80
81 for(unsigned i = 0; i < f.us; i++) {
82 for(unsigned j = 0; j < f.vs; j++) {
83 Linear2d lin = f.index(i,j);
84 Linear2d dlin(lin[1+dim]-lin[0], lin[1+2*dim]-lin[dim], lin[3-dim]-lin[2*(1-dim)], lin[3]-lin[2-dim]);
85 result[i+j*result.us] += dlin;
86 unsigned di = dim?j:i;
87 if (di>=1){
88 float motpi = dim?-1:1;
89 Linear2d ds_lin_low( lin[0], -motpi*lin[1], motpi*lin[2], -lin[3] );
90 result[(i+dim-1)+(j-dim)*result.us] += di*ds_lin_low;
91
92 Linear2d ds_lin_hi( lin[1+dim]-lin[0], lin[1+2*dim]-lin[dim], lin[3]-lin[2-dim], lin[3-dim]-lin[2-dim] );
93 result[i+j*result.us] += di*ds_lin_hi;
94 }
95 }
96 }
97 return result;
98}
99
106D2<SBasis>
107sb2dsolve(SBasis2d const &f, Geom::Point const &A, Geom::Point const &B, unsigned degmax){
108 //g_warning("check f(A)= %f = f(B) = %f =0!", f.apply(A[X],A[Y]), f.apply(B[X],B[Y]));
109
110 SBasis2d dfdu = partial_derivative(f, 0);
111 SBasis2d dfdv = partial_derivative(f, 1);
112 Geom::Point dfA(dfdu.apply(A[X],A[Y]),dfdv.apply(A[X],A[Y]));
113 Geom::Point dfB(dfdu.apply(B[X],B[Y]),dfdv.apply(B[X],B[Y]));
114 Geom::Point nA = dfA/(dfA[X]*dfA[X]+dfA[Y]*dfA[Y]);
115 Geom::Point nB = dfB/(dfB[X]*dfB[X]+dfB[Y]*dfB[Y]);
116
117 D2<SBasis>result(SBasis(degmax, Linear()), SBasis(degmax, Linear()));
118 double fact_k=1;
119 double sign = 1.;
120 for(int dim = 0; dim < 2; dim++)
121 result[dim][0] = Linear(A[dim],B[dim]);
122 for(unsigned k=1; k<degmax; k++){
123 // these two lines make the solutions worse!
124 //fact_k *= k;
125 //sign = -sign;
126 SBasis f_on_curve = compose(f,result);
127 Linear reste = f_on_curve[k];
128 double ax = -reste[0]/fact_k*nA[X];
129 double ay = -reste[0]/fact_k*nA[Y];
130 double bx = -sign*reste[1]/fact_k*nB[X];
131 double by = -sign*reste[1]/fact_k*nB[Y];
132
133 result[X][k] = Linear(ax,bx);
134 result[Y][k] = Linear(ay,by);
135 //sign *= 3;
136 }
137 return result;
138}
139
144//TODO: handle the case when B is "behind" A for the natural orientation of the level set.
145//TODO: more generally, there might be up to 4 solutions. Choose the best one!
146D2<SBasis>
147sb2d_cubic_solve(SBasis2d const &f, Geom::Point const &A, Geom::Point const &B){
148 D2<SBasis>result;//(Linear(A[X],B[X]),Linear(A[Y],B[Y]));
149 //g_warning("check 0 = %f = %f!", f.apply(A[X],A[Y]), f.apply(B[X],B[Y]));
150
151 SBasis2d f_u = partial_derivative(f , 0);
152 SBasis2d f_v = partial_derivative(f , 1);
153 SBasis2d f_uu = partial_derivative(f_u, 0);
154 SBasis2d f_uv = partial_derivative(f_v, 0);
155 SBasis2d f_vv = partial_derivative(f_v, 1);
156
157 Geom::Point dfA(f_u.apply(A[X],A[Y]),f_v.apply(A[X],A[Y]));
158 Geom::Point dfB(f_u.apply(B[X],B[Y]),f_v.apply(B[X],B[Y]));
159
160 Geom::Point V0 = rot90(dfA);
161 Geom::Point V1 = rot90(dfB);
162
163 double D2fVV0 = f_uu.apply(A[X],A[Y])*V0[X]*V0[X]+
164 2*f_uv.apply(A[X],A[Y])*V0[X]*V0[Y]+
165 f_vv.apply(A[X],A[Y])*V0[Y]*V0[Y];
166 double D2fVV1 = f_uu.apply(B[X],B[Y])*V1[X]*V1[X]+
167 2*f_uv.apply(B[X],B[Y])*V1[X]*V1[Y]+
168 f_vv.apply(B[X],B[Y])*V1[Y]*V1[Y];
169
170 std::vector<D2<SBasis> > candidates = cubics_fitting_curvature(A,B,V0,V1,D2fVV0,D2fVV1);
171 if (candidates.empty()) {
172 return D2<SBasis>(SBasis(Linear(A[X],B[X])), SBasis(Linear(A[Y],B[Y])));
173 }
174 //TODO: I'm sure std algorithm could do that for me...
175 double error = -1;
176 unsigned best = 0;
177 for (unsigned i=0; i<candidates.size(); i++){
178 Interval bounds = *bounds_fast(compose(f,candidates[i]));
179 double new_error = (fabs(bounds.max())>fabs(bounds.min()) ? fabs(bounds.max()) : fabs(bounds.min()) );
180 if ( new_error < error || error < 0 ){
181 error = new_error;
182 best = i;
183 }
184 }
185 return candidates[best];
186}
187
188
189
190
191};
192
193/*
194 Local Variables:
195 mode:c++
196 c-file-style:"stroustrup"
197 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
198 indent-tabs-mode:nil
199 fill-column:99
200 End:
201*/
202// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
Geom::IntRect bounds
Definition canvas.cpp:182
Adaptor that creates 2D functions from 1D ones.
Definition d2.h:55
CPoint min() const
Get the corner of the rectangle with smallest coordinate values.
CPoint max() const
Get the corner of the rectangle with largest coordinate values.
Range of real numbers that is never empty.
Definition interval.h:59
Function that interpolates linearly between two values.
Definition linear.h:55
Two-dimensional point that doubles as a vector.
Definition point.h:66
unsigned us
Definition sbasis-2d.h:154
unsigned vs
Definition sbasis-2d.h:154
Linear2d & index(unsigned ui, unsigned vi)
Definition sbasis-2d.h:163
double apply(double u, double v) const
Definition sbasis-2d.h:177
Polynomial in symmetric power basis.
Definition sbasis.h:70
Css & result
@ Y
Definition coord.h:48
@ X
Definition coord.h:48
Various utility functions.
Definition affine.h:22
Linear extract_v(Linear2d const &a, double v)
Definition sbasis-2d.h:96
Bezier multiply(Bezier const &f, Bezier const &g)
Definition bezier.h:337
static float sign(double number)
Returns +1 for positive numbers, -1 for negative numbers, and 0 otherwise.
D2< SBasis > sb2d_cubic_solve(SBasis2d const &f, Geom::Point const &A, Geom::Point const &B)
Finds a path which traces the 0 contour of f, traversing from A to B as a single cubic d2<sbasis>.
D2< T > compose(D2< T > const &a, T const &b)
Definition d2.h:405
SBasis2d partial_derivative(SBasis2d const &a, int dim)
Definition sbasis-2d.cpp:73
Linear extract_u(Linear2d const &a, double u)
Definition sbasis-2d.h:90
D2< SBasis > sb2dsolve(SBasis2d const &f, Geom::Point const &A, Geom::Point const &B, unsigned degmax=2)
Finds a path which traces the 0 contour of f, traversing from A to B as a single d2<sbasis>.
D2< T > compose_each(D2< T > const &a, D2< T > const &b)
Definition d2.h:414
std::vector< D2< SBasis > > cubics_fitting_curvature(Point const &M0, Point const &M1, Point const &dM0, Point const &dM1, double d2M0xdM0, double d2M1xdM1, int insist_on_speed_signs=1, double epsilon=1e-5)
OptInterval bounds_fast(Bezier const &b)
Definition bezier.cpp:305
D2< T > rot90(D2< T > const &a)
Definition d2.h:397
Obsolete 2D SBasis function class.
two-dimensional geometric operators.