Mercurial > repos > public > sbplib
changeset 86:3c39dd714fb6
In Curve: Added numerical FD differentiation if derivative is not supplied. Added arc length computation based on the derivative. Added arc length parameterization (but this function is very slow.). In +util: Added fzero_vec.m and integral_vec.m, which call fzero and integral but take vector arguments.
author | Martin Almquist <martin.almquist@it.uu.se> |
---|---|
date | Sun, 29 Nov 2015 14:28:53 +0100 |
parents | 14bf01b7a068 |
children | 0a29a60e0b21 |
files | +grid/Curve.m +util/fzero_vec.m +util/integral_vec.m |
diffstat | 3 files changed, 118 insertions(+), 5 deletions(-) [+] |
line wrap: on
line diff
--- a/+grid/Curve.m Wed Nov 25 18:33:49 2015 +0100 +++ b/+grid/Curve.m Sun Nov 29 14:28:53 2015 +0100 @@ -7,19 +7,29 @@ methods %TODO: % Errors or FD if there is no derivative function added. + % -semi-done % Concatenation of curves % Subsections of curves - % Stretching of curve paramter + % Stretching of curve paramter - semi-done % Curve to cell array of linesegments - % Should accept derivative of curve. - function obj = Curve(g,gp,transformation) + % Should supply either derivative or a difference operator D1 + function obj = Curve(g,gp,transformation,D1) default_arg('gp',[]); default_arg('transformation',[]); + default_arg('D1',[]); p_test = g(0); assert(all(size(p_test) == [2,1]), 'A curve parametrization must return a 2x1 vector.'); + if(isempty(gp) && isempty(D1)); + % Should be error instead of disp. + disp(['You really should supply either the exact derivative ',... + 'or a suitable difference operator to compute it.']); + elseif(isempty(gp)) + gp = grid.Curve.numerical_derivative(g,D1); + end + if ~isempty(transformation) transformation.base_g = g; transformation.base_gp = gp; @@ -30,6 +40,18 @@ obj.gp = gp; obj.transformation = transformation; end + + % Length of arc from parameter t0 to t1 (which may be vectors). + % Computed using derivative. + function L = arc_length(obj,t0,t1) + deriv = obj.gp; + speed = @(t) sp(deriv(t)); + + function s = sp(deriv) + s = sqrt(sum(deriv.^2,1)); + end + L = util.integral_vec(speed,t0,t1); + end % Made up length calculation!! Science this before actual use!! % Calculates the length of the curve. Makes sure the longet segment used is shorter than h_max. @@ -125,7 +147,27 @@ end % Shows curve with name and arrow for direction. - + + % Should this be in the transformation method? + function curve = stretch_parameter(obj,type) + default_arg('type','arc_length'); + switch type + % Arc length parameterization. WARNING: slow. + case 'arc_length' + arcLength = @(t) obj.arc_length(0,t); + arcPar = @(t) util.fzero_vec(@(s)arcLength(s) - t*arcLength(1),0); + g_new = @(t)obj.g(arcPar(t)); + gp_old = obj.gp; + gp_new = @(t) normalize(gp_old(arcPar(t))); + + curve = grid.Curve(g_new,gp_new); + + otherwise + error('That stretching is not implemented.'); + end + + end + % how to make it work for methods without returns function p = subsref(obj,S) %Should i add error checking here? @@ -265,6 +307,28 @@ end methods (Static) + + function gp_out = numerical_derivative(g,D1) + m = length(D1); L = 1; % Assume curve parameter from 0 to 1. + dt = L/(m-1); + t = linspace(0,L,m); + g = g(t)'; + gp = (D1*g)'; + + % Make vectors longer to make sure splines are + % reasonable at 1+eps. + t_l = linspace(0,L+dt,m+1); + gp_l = [gp,gp(:,end)+gp(:,end)-gp(:,end-1)]; + + % 4:th order splines. + spline_order = 4; + gp1 = spapi( optknt(t_l,spline_order), t_l, gp_l(1,:) ); + gp2 = spapi( optknt(t_l,spline_order), t_l, gp_l(2,:) ); + gp1_fun = @(t) fnval(gp1,t); gp2_fun = @(t) fnval(gp2,t); + gp_out = @(t) [gp1_fun(t);gp2_fun(t)]; + + end + function obj = line(p1, p2) function v = g_fun(t) @@ -343,5 +407,14 @@ end end - end + end end + +function g_norm = normalize(g0) + g1 = g0(1,:); g2 = g0(2,:); + normalization = sqrt(sum(g0.^2,1)); + g_norm = [g1./normalization; g2./normalization]; +end + + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/+util/fzero_vec.m Sun Nov 29 14:28:53 2015 +0100 @@ -0,0 +1,14 @@ +function I = fzero_vec(f,lim) +% Wrapper around the built-in function fzero that +% handles multiple functions (vector-valued f). + + fval = f(lim(1)); + I = zeros(size(fval)); + + for i = 1:length(fval) + e = zeros(size(fval)); + e(i) = 1; + I(i) = fzero(@(t) sum(e.*f(t)),lim); + end + +end \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/+util/integral_vec.m Sun Nov 29 14:28:53 2015 +0100 @@ -0,0 +1,26 @@ +function I = integral_vec(f,a,b) +% Wrapper around the built-in function integral that +% handles multiple limits. + + Na = length(a); + Nb = length(b); + assert(Na == 1 || Nb == 1 || Na==Nb,... + 'a and b must have same length, unless one is a scalar.'); + + if(Na>Nb); + I = zeros(size(a)); + for i = 1:Na + I(i) = integral(f,a(i),b); + end + elseif(Nb>Na) + I = zeros(size(b)); + for i = 1:Nb + I(i) = integral(f,a,b(i)); + end + else + I = zeros(size(b)); + for i = 1:Nb + I(i) = integral(f,a(i),b(i)); + end + end +end \ No newline at end of file