Mercurial > repos > public > sbplib
comparison +grid/Curve.m @ 109:142974097efc
Merged in feature/arclen-param (pull request #1)
Feature/arclen param
author | Martin Almquist <martin.almquist@it.uu.se> |
---|---|
date | Tue, 08 Dec 2015 10:42:20 +0100 |
parents | 06c3034966b7 |
children |
comparison
equal
deleted
inserted
replaced
101:9933169d2651 | 109:142974097efc |
---|---|
2 properties | 2 properties |
3 g | 3 g |
4 gp | 4 gp |
5 transformation | 5 transformation |
6 end | 6 end |
7 | |
7 methods | 8 methods |
8 %TODO: | 9 %TODO: |
9 % Errors or FD if there is no derivative function added. | |
10 | |
11 % Concatenation of curves | 10 % Concatenation of curves |
12 % Subsections of curves | 11 % Subsections of curves |
13 % Stretching of curve paramter | 12 % Stretching of curve parameter - done for arc length. |
14 % Curve to cell array of linesegments | 13 % Curve to cell array of linesegments |
15 | 14 |
16 % Should accept derivative of curve. | 15 % Returns a curve object. |
16 % g -- curve parametrization for parameter between 0 and 1 | |
17 % gp -- parametrization of curve derivative | |
17 function obj = Curve(g,gp,transformation) | 18 function obj = Curve(g,gp,transformation) |
18 default_arg('gp',[]); | 19 default_arg('gp',[]); |
19 default_arg('transformation',[]); | 20 default_arg('transformation',[]); |
20 p_test = g(0); | 21 p_test = g(0); |
21 assert(all(size(p_test) == [2,1]), 'A curve parametrization must return a 2x1 vector.'); | 22 assert(all(size(p_test) == [2,1]), 'A curve parametrization must return a 2x1 vector.'); |
27 end | 28 end |
28 | 29 |
29 obj.g = g; | 30 obj.g = g; |
30 obj.gp = gp; | 31 obj.gp = gp; |
31 obj.transformation = transformation; | 32 obj.transformation = transformation; |
32 end | 33 |
33 | |
34 % Made up length calculation!! Science this before actual use!! | |
35 % Calculates the length of the curve. Makes sure the longet segment used is shorter than h_max. | |
36 function [L,t] = curve_length(C,h_max) | |
37 default_arg('h_max',0.001); | |
38 g = C.g; | |
39 h = 0.1; | |
40 m = 1/h+1; | |
41 t = linspace(0,1,m); | |
42 | |
43 [p,d] = get_d(t,g); | |
44 | |
45 while any(d>h_max) | |
46 I = find(d>h_max); | |
47 | |
48 % plot(p(1,:),p(2,:),'.') | |
49 % waitforbuttonpress | |
50 | |
51 new_t = []; | |
52 for i = I | |
53 new_t(end +1) = (t(i)+t(i+1))/2; | |
54 end | |
55 t = [t new_t]; | |
56 t = sort(t); | |
57 | |
58 [p,d] = get_d(t,g); | |
59 end | |
60 | |
61 L = sum(d); | |
62 | |
63 function [p,d] = get_d(t,g) | |
64 n = length(t); | |
65 | |
66 p = zeros(2,n); | |
67 for i = 1:n | |
68 p(:,i) = g(t(i)); | |
69 end | |
70 | |
71 d = zeros(1,n-1); | |
72 for i = 1:n-1 | |
73 d(i) = norm(p(:,i) - p(:,i+1)); | |
74 end | |
75 end | |
76 end | 34 end |
77 | 35 |
78 function n = normal(obj,t) | 36 function n = normal(obj,t) |
37 assert(~isempty(obj.gp),'Curve has no derivative!'); | |
79 deriv = obj.gp(t); | 38 deriv = obj.gp(t); |
80 normalization = sqrt(sum(deriv.^2,1)); | 39 normalization = sqrt(sum(deriv.^2,1)); |
81 n = [-deriv(2,:)./normalization; deriv(1,:)./normalization]; | 40 n = [-deriv(2,:)./normalization; deriv(1,:)./normalization]; |
82 end | 41 end |
83 | 42 |
84 | 43 |
85 % Plots a curve g(t) for 0<t<1, using n points. Retruns a handle h to the plotted curve. | 44 % Plots a curve g(t) for 0<t<1, using n points. Returns a handle h to the plotted curve. |
86 % h = plot_curve(g,n) | 45 % h = plot_curve(g,n) |
87 function h = plot(obj,n) | 46 function h = plot(obj,n) |
88 default_arg('n',100); | 47 default_arg('n',100); |
89 | 48 |
90 t = linspace(0,1,n); | 49 t = linspace(0,1,n); |
91 | |
92 p = obj.g(t); | 50 p = obj.g(t); |
93 | |
94 h = line(p(1,:),p(2,:)); | 51 h = line(p(1,:),p(2,:)); |
95 end | 52 end |
96 | 53 |
97 function h= plot_normals(obj,l,n,m) | 54 function h= plot_normals(obj,l,n,m) |
98 default_arg('l',0.1); | 55 default_arg('l',0.1); |
123 | 80 |
124 obj.plot(); | 81 obj.plot(); |
125 end | 82 end |
126 % Shows curve with name and arrow for direction. | 83 % Shows curve with name and arrow for direction. |
127 | 84 |
85 % Length of arc from parameter t0 to t1 (which may be vectors). | |
86 % Computed using derivative. | |
87 function L = arcLength(obj,t0,t1) | |
88 assert(~isempty(obj.gp),'Curve has no derivative!'); | |
89 speed = @(t) sqrt(sum(obj.gp(t).^2,1)); | |
90 L = integral_vec(speed,t0,t1); | |
91 end | |
92 | |
93 % Creates the arc length parameterization of a curve. | |
94 % N -- number of points used to approximate the arclength function | |
95 function curve = arcLengthParametrization(obj,N) | |
96 default_arg('N',100); | |
97 assert(~isempty(obj.gp),'Curve has no derivative!'); | |
98 | |
99 % Construct arcLength function using splines | |
100 tvec = linspace(0,1,N); | |
101 arcVec = obj.arcLength(0,tvec); | |
102 tFunc = spline(arcVec,tvec); % t as a function of arcLength | |
103 L = obj.arcLength(0,1); | |
104 arcPar = @(s) tFunc(s*L); | |
105 | |
106 % New function and derivative | |
107 g_new = @(t)obj.g(arcPar(t)); | |
108 gp_new = @(t) normalize(obj.gp(arcPar(t))); | |
109 curve = grid.Curve(g_new,gp_new); | |
110 | |
111 end | |
128 | 112 |
129 % how to make it work for methods without returns | 113 % how to make it work for methods without returns |
130 function p = subsref(obj,S) | 114 function p = subsref(obj,S) |
131 %Should i add error checking here? | 115 %Should i add error checking here? |
132 %Maybe if you want performance you fetch obj.g and then use that | 116 %Maybe if you want performance you fetch obj.g and then use that |
139 otherwise | 123 otherwise |
140 p = builtin('subsref',obj,S); | 124 p = builtin('subsref',obj,S); |
141 % error() | 125 % error() |
142 end | 126 end |
143 end | 127 end |
144 | |
145 | |
146 | 128 |
147 | 129 |
148 %% TRANSFORMATION OF A CURVE | 130 %% TRANSFORMATION OF A CURVE |
149 function D = reverse(C) | 131 function D = reverse(C) |
150 % g = C.g; | 132 % g = C.g; |
263 D = C.transform(A,b); | 245 D = C.transform(A,b); |
264 end | 246 end |
265 end | 247 end |
266 | 248 |
267 methods (Static) | 249 methods (Static) |
250 | |
251 % Computes the derivative of g: R -> R^2 using an operator D1 | |
252 function gp_out = numericalDerivative(g,D1) | |
253 m = length(D1); | |
254 t = linspace(0,1,m); | |
255 gVec = g(t)'; | |
256 gpVec = (D1*gVec)'; | |
257 | |
258 gp1_fun = spline(t,gpVec(1,:)); | |
259 gp2_fun = spline(t,gpVec(2,:)); | |
260 gp_out = @(t) [gp1_fun(t);gp2_fun(t)]; | |
261 end | |
262 | |
268 function obj = line(p1, p2) | 263 function obj = line(p1, p2) |
269 | 264 |
270 function v = g_fun(t) | 265 function v = g_fun(t) |
271 v(1,:) = p1(1) + t.*(p2(1)-p1(1)); | 266 v(1,:) = p1(1) + t.*(p2(1)-p1(1)); |
272 v(2,:) = p1(2) + t.*(p2(2)-p1(2)); | 267 v(2,:) = p1(2) + t.*(p2(2)-p1(2)); |
343 end | 338 end |
344 end | 339 end |
345 | 340 |
346 end | 341 end |
347 end | 342 end |
343 | |
344 | |
345 | |
346 function g_norm = normalize(g0) | |
347 g1 = g0(1,:); | |
348 g2 = g0(2,:); | |
349 normalization = sqrt(sum(g0.^2,1)); | |
350 g_norm = [g1./normalization; g2./normalization]; | |
351 end | |
352 | |
353 function I = integral_vec(f,a,b) | |
354 % Wrapper around the built-in function integral that | |
355 % handles multiple limits. | |
356 | |
357 Na = length(a); | |
358 Nb = length(b); | |
359 assert(Na == 1 || Nb == 1 || Na==Nb,... | |
360 'a and b must have same length, unless one is a scalar.'); | |
361 | |
362 if(Na>Nb); | |
363 I = zeros(size(a)); | |
364 for i = 1:Na | |
365 I(i) = integral(f,a(i),b); | |
366 end | |
367 elseif(Nb>Na) | |
368 I = zeros(size(b)); | |
369 for i = 1:Nb | |
370 I(i) = integral(f,a,b(i)); | |
371 end | |
372 else | |
373 I = zeros(size(b)); | |
374 for i = 1:Nb | |
375 I(i) = integral(f,a(i),b(i)); | |
376 end | |
377 end | |
378 end | |
379 | |
380 % Returns a function handle to the spline. | |
381 function f = spline(tval,fval,spline_order) | |
382 default_arg('spline_order',4); | |
383 [m,~] = size(tval); | |
384 assert(m==1,'Need row vectors.'); | |
385 | |
386 f_spline = spapi( optknt(tval,spline_order), tval, fval ); | |
387 f = @(t) fnval(f_spline,t); | |
388 end |