KerMor  0.9
Model order reduction for nonlinear dynamical systems and nonlinear approximation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
tricontour.m
Go to the documentation of this file.
1 
2 
3 /* (Autoinserted by mtoc++)
4  * This source code has been filtered by the mtoc++ executable,
5  * which generates code that can be processed by the doxygen documentation tool.
6  *
7  * On the other hand, it can neither be interpreted by MATLAB, nor can it be compiled with a C++ compiler.
8  * Except for the comments, the function bodies of your M-file functions are untouched.
9  * Consequently, the FILTER_SOURCE_FILES doxygen switch (default in our Doxyfile.template) will produce
10  * attached source files that are highly readable by humans.
11  *
12  * Additionally, links in the doxygen generated documentation to the source code of functions and class members refer to
13  * the correct locations in the source code browser.
14  * However, the line numbers most likely do not correspond to the line numbers in the original MATLAB source files.
15  */
16 
17 function [cout , hout ] = tricontour(ax,double t,p,Hn,N,varargin) {
18 
19 /* Contouring for functions defined on triangular meshes
20  *
21  * TRICONTOUR(p,t,F,N)
22  *
23  * Draws contours of the surface F, where F is defined on the triangulation
24  * [p,t]. These inputs define the xy co-ordinates of the points and their
25  * connectivity:
26  *
27  * P = [x1,y1; x2,y2; etc], - xy co-ordinates of nodes in the
28  * triangulation
29  * T = [n11,n12,n13; n21,n23,n23; etc] - node numbers in each triangle
30  *
31  * The last input N defines the contouring levels. There are several
32  * options:
33  *
34  * N scalar - N number of equally spaced contours will be drawn
35  * N vector - Draws contours at the levels specified in N
36  *
37  * A special call with a two element N where both elements are equal draws a
38  * single contour at that level.
39  *
40  * [C,H] = TRICONTOUR(...)
41  *
42  * This syntax can be used to pass the contour matrix C and the contour
43  * handels H to clabel by adding clabel(c,h) or clabel(c) after the call to
44  * TRICONTOUR.
45  *
46  * TRICONTOUR can also return 3D contours similar to CONTOUR3 by adding
47  * view(3) after the call to TRICONTOUR.
48  *
49  * Type "contourdemo" for some examples.
50  *
51  * See also, CONTOUR, CLABEL */
52 
53 /* This function does NOT interpolate back onto a Cartesian grid, but
54  * instead uses the triangulation directly.
55  *
56  * If your going to use this inside a loop with the same [p,t] a good
57  * modification is to make the connectivity "mkcon" once outside the loop
58  * because usually about 50% of the time is spent in "mkcon".
59  *
60  * Darren Engwirda - 2005 (d_engwirda@hotmail.com)
61  * Updated 15/05/2006 */
62 
63 
64 /* I/O checking */
65 if nargin<5
66  error(" Incorrect number of inputs ")
67 end
68 if nargout>2
69  error(" Incorrect number of outputs ")
70 end
71 
72 /* Error checking */
73 if (size(p,2)~=2) || (size(t,2)~=3) || (size(Hn,2)~=1)
74  error(" Incorrect input dimensions ")
75 end
76 if size(p,1)~=size(Hn,1)
77  error(" F and p must be the same length ")
78 end
79 if (max(t(:))>size(p,1)) || (min(t(:))<=0)
80  error(" t is not a valid triangulation of p ")
81 end
82 if (size(N,1)>1) && (size(N,2)>1)
83  error(" N cannot be a matrix ")
84 end
85 
86 /* Make mesh connectivity data structures (edge based pointers) */
87 [e,eINt,e2t] = mkcon(p,t);
88 
89 numt = size(t,1); /* Num triangles */
90 
91 nume = size(e,1); /* Num edges */
92 
93 
94 
95 
96 /* ==========================================================================
97  * Quadratic interpolation to centroids
98  *========================================================================== */
99 
100 /* Nodes */
101 t1 = t(:,1); t2 = t(:,2); t3 = t(:,3);
102 
103 /* FORM FEM GRADIENTS
104  * Evaluate centroidal gradients (piecewise-linear interpolants) */
105 x23 = p(t2,1)-p(t3,1); y23 = p(t2,2)-p(t3,2);
106 x21 = p(t2,1)-p(t1,1); y21 = p(t2,2)-p(t1,2);
107 
108 /* Centroidal values */
109 Htx = (y23.*Hn(t1) + (y21-y23).*Hn(t2) - y21.*Hn(t3)) ./ (x23.*y21-x21.*y23);
110 Hty = (x23.*Hn(t1) + (x21-x23).*Hn(t2) - x21.*Hn(t3)) ./ (y23.*x21-y21.*x23);
111 
112 /* Form nodal gradients.
113  * Take the average of the neighbouring centroidal values */
114 Hnx = 0*Hn; Hny = Hnx; count = Hnx;
115 for k = 1:numt
116  /* Nodes */
117  n1 = t1(k); n2 = t2(k); n3 = t3(k);
118  /* Current values */
119  Hx = Htx(k); Hy = Hty(k);
120  /* Average to n1 */
121  Hnx(n1) = Hnx(n1)+Hx;
122  Hny(n1) = Hny(n1)+Hy;
123  count(n1) = count(n1)+1;
124  /* Average to n2 */
125  Hnx(n2) = Hnx(n2)+Hx;
126  Hny(n2) = Hny(n2)+Hy;
127  count(n2) = count(n2)+1;
128  /* Average to n3 */
129  Hnx(n3) = Hnx(n3)+Hx;
130  Hny(n3) = Hny(n3)+Hy;
131  count(n3) = count(n3)+1;
132 end
133 Hnx = Hnx./count;
134 Hny = Hny./count;
135 
136 /* Centroids [x,y] */
137 pt = (p(t1,:)+p(t2,:)+p(t3,:))/3;
138 
139 /* Take unweighted average of the linear extrapolation from nodes to centroids */
140 Ht = ( Hn(t1) + (pt(:,1)-p(t1,1)).*Hnx(t1) + (pt(:,2)-p(t1,2)).*Hny(t1) + ...
141  Hn(t2) + (pt(:,1)-p(t2,1)).*Hnx(t2) + (pt(:,2)-p(t2,2)).*Hny(t2) + ...
142  Hn(t3) + (pt(:,1)-p(t3,1)).*Hnx(t3) + (pt(:,2)-p(t3,2)).*Hny(t3) )/3;
143 
144 
145 
146 /* DEAL WITH CONTOURING LEVELS */
147 if length(N)==1
148  lev = linspace(max(Ht),min(Ht),N+1);
149  num = N;
150 else
151  if (length(N)==2) && (N(1)==N(2))
152  lev = N(1);
153  num = 1;
154  else
155  lev = sort(N);
156  num = length(N);
157  lev = lev(num:-1:1);
158  end
159 end
160 
161 /* MAIN LOOP */
162 c = [];
163 h = [];
164 in = false(numt,1);
165 vec = 1:numt;
166 old = in;
167 for v = 1:num /* Loop over contouring levels */
168 
169 
170  /* Find centroid values >= current level */
171  i = vec(Ht>=lev(v));
172  i = i(~old(i)); /* Don't need to check triangles from higher levels */
173 
174  in(i) = true;
175 
176  /* Locate boundary edges in group */
177  bnd = [i; i; i]; /* Just to alloc */
178 
179  next = 1;
180  for k = 1:length(i)
181  ct = i(k);
182  count = 0;
183  for q = 1:3 /* Loop through edges in ct */
184 
185  ce = eINt(ct,q);
186  if ~in(e2t(ce,1)) || ((e2t(ce,2)>0)&&~in(e2t(ce,2)))
187  bnd(next) = ce; /* Found bnd edge */
188 
189  next = next+1;
190  else
191  count = count+1; /* Count number of non-bnd edges in ct */
192 
193  end
194  end
195  if count==3 /* If 3 non-bnd edges ct must be in middle of group */
196 
197  old(ct) = true; /* & doesn't need to be checked for the next level */
198 
199  end
200  end
201  numb = next-1; bnd(next:end) = [];
202 
203  /* Skip to next lev if empty */
204  if numb==0
205  continue
206  end
207 
208  /* Place nodes approximately on contours by interpolating across bnd
209  * edges */
210  t1 = e2t(bnd,1);
211  t2 = e2t(bnd,2);
212  ok = t2>0;
213 
214  /* Get two points for interpolation. Always use t1 centroid and
215  * use t2 centroid for internal edges and bnd midpoint for boundary
216  * edges */
217 
218  /* 1st point is always t1 centroid */
219  H1 = Ht(t1); /* Centroid value */
220 
221  p1 = ( p(t(t1,1),:)+p(t(t1,2),:)+p(t(t1,3),:) )/3; /* Centroid [x,y] */
222 
223 
224  /* 2nd point is either t2 centroid or bnd edge midpoint */
225  i1 = t2(ok); /* Temp indexing */
226 
227  i2 = bnd(~ok);
228  H2 = H1;
229  H2(ok) = Ht(i1); /* Centroid values internally */
230 
231  H2(~ok) = ( Hn(e(i2,1))+Hn(e(i2,2)) )/2; /* Edge values at boundary */
232 
233  p2 = p1;
234  p2(ok,:) = ( p(t(i1,1),:)+p(t(i1,2),:)+p(t(i1,3),:) )/3; /* Centroid [x,y] internally */
235 
236  p2(~ok,:) = ( p(e(i2,1),:)+p(e(i2,2),:) )/2; /* Edge [x,y] at boundary */
237 
238 
239  /* Linear interpolation */
240  r = (lev(v)-H1)./(H2-H1);
241  penew = p1 + [r,r].*(p2-p1);
242 
243  /* Do a temp connection between adjusted node & endpoint nodes in
244  * ce so that the connectivity between neighbouring adjusted nodes
245  * can be determined */
246  vecb = (1:numb)^t;
247  m = 2*vecb-1;
248  c1 = 0*m;
249  c2 = 0*m;
250  c1(m) = e(bnd,1);
251  c1(m+1) = e(bnd,2);
252  c2(m) = vecb;
253  c2(m+1) = vecb;
254 
255  /* Sort connectivity to place connected edges in sucessive rows */
256  [c1,i] = sort(c1); c2 = c2(i);
257 
258  /* Connect adjacent adjusted nodes */
259  k = 1;
260  next = 1;
261  while k<(2*numb)
262  if c1(k)==c1(k+1)
263  c1(next) = c2(k);
264  c2(next) = c2(k+1);
265  next = next+1;
266  k = k+2; /* Skip over connected edge */
267 
268  else
269  k = k+1; /* Node has only 1 connection - will be picked up above */
270 
271  end
272  end
273  ncc = next-1;
274  c1(next:end) = [];
275  c2(next:end) = [];
276 
277 
278  /* Plot the contours
279  * If an output is required, extra sorting of the
280  * contours is necessary for CLABEL to work. */
281  if nargout > 0 && false
282 
283  /* Form connectivity for the contour, connecting
284  * its edges (rows in cc) with its vertices. */
285  ndx = repmat(1,nume,1);
286  n2e = 0*penew;
287  for k = 1:ncc
288  /* Vertices */
289  n1 = c1(k); n2 = c2(k);
290  /* Connectivity */
291  n2e(n1,ndx(n1)) = k; ndx(n1) = ndx(n1)+1;
292  n2e(n2,ndx(n2)) = k; ndx(n2) = ndx(n2)+1;
293  end
294  bndn = n2e(:,2)==0; /* Boundary nodes */
295 
296  bnde = bndn(c1)|bndn(c2); /* Boundary edges */
297 
298 
299  /* Alloc some space */
300  tmpv = repmat(0,1,ncc);
301 
302  /* Loop through the points at the current contour level (lev(v))
303  * Try to assemble the CS data structure introduced in "contours.m"
304  * so that clabel will work. Assemble CS by "walking" around each
305  * subcontour segment contiguously. */
306  ce = 1;
307  start = ce;
308  next = 2;
309  cn = c2(1);
310  flag = false(ncc,1);
311  x = tmpv; x(1) = penew(c1(ce),1);
312  y = tmpv; y(1) = penew(c1(ce),2);
313  for k = 1:ncc
314 
315  /* Checked this edge */
316  flag(ce) = true;
317 
318  /* Add vertices to patch data */
319  x(next) = penew(cn,1);
320  y(next) = penew(cn,2);
321  next = next+1;
322 
323  /* Find edge (that is not ce) joined to cn */
324  if ce==n2e(cn,1)
325  ce = n2e(cn,2);
326  else
327  ce = n2e(cn,1);
328  end
329 
330  /* Check the new edge */
331  if (ce==0)||(ce==start)||(flag(ce))
332 
333  /* Plot current subcontour as a patch and save handles */
334  x = x(1:next-1);
335  y = y(1:next-1);
336  z = repmat(lev(v),1,next);
337  h = [h; patch(" Xdata ",[x,NaN]," Ydata ",[y,NaN]," Zdata ",z, ...
338  " Cdata ",z," facecolor "," none "," edgecolor "," flat ")]; hold on
339 
340  /* Update the CS data structure as per "contours.m"
341  * so that clabel works */
342  c = horzcat(c,[lev(v), x; next-1, y]);
343 
344  if all(flag) /* No more points at lev(v) */
345 
346  break
347  else /* More points, but need to start a new subcontour */
348 
349 
350  /* Find the unflagged edges */
351  edges = find(~flag);
352  ce = edges(1);
353  /* Try to select a boundary edge so that we are
354  * not repeatedly running into the boundary */
355  for i = 1:length(edges)
356  if bnde(edges(i))
357  ce = edges(i); break
358  end
359  end
360  /* Reset counters */
361  start = ce;
362  next = 2;
363  /* Get the non bnd node in ce */
364  if bndn(c2(ce))
365  cn = c1(ce);
366  /* New patch vectors */
367  x = tmpv; x(1) = penew(c2(ce),1);
368  y = tmpv; y(1) = penew(c2(ce),2);
369  else
370  cn = c2(ce);
371  /* New patch vectors */
372  x = tmpv; x(1) = penew(c1(ce),1);
373  y = tmpv; y(1) = penew(c1(ce),2);
374  end
375 
376  end
377 
378  else
379  /* Find node (that is not cn) in ce */
380  if cn==c1(ce)
381  cn = c2(ce);
382  else
383  cn = c1(ce);
384  end
385  end
386 
387  end
388 
389  else /* Just plot the contours as is, this is faster... */
390 
391 
392  z = repmat(lev(v),2,ncc)+.01*abs(lev(v));
393 
394  h = [h; patch(" Xdata ",[penew(c1,1),penew(c2,1)]^t, ...
395  " Ydata ",[penew(c1,2),penew(c2,2)]^t, ...
396  " Zdata ",z," Cdata ",z," Parent ",ax,varargin[:])];
397 
398  hold on
399 
400  end
401 
402 end
403 
404 /* Assign outputs if needed */
405 if nargout>0
406  cout = c;
407  hout = h;
408 end
409 
410 return
411 
412 
413 /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
414 }
415 
416 function [e , eINt , e2t ] = tricontour>mkcon(p,double t) {
417 
418 numt = size(t,1);
419 vect = 1:numt;
420 
421 /* DETERMINE UNIQUE EDGES IN MESH */
422 
423 e = [t(:,[1,2]); t(:,[2,3]); t(:,[3,1])]; /* Edges - not unique */
424 
425 vec = (1:size(e,1))^t; /* List of edge numbers */
426 
427 [e,j,j] = unique(sort(e,2)," rows "); /* Unique edges */
428 
429 vec = vec(j); /* Unique edge numbers */
430 
431 eINt = [vec(vect), vec(vect+numt), vec(vect+2*numt)]; /* Unique edges in each triangle */
432 
433 
434 /* DETERMINE EDGE TO TRIANGLE CONNECTIVITY */
435 
436 /* Each row has two entries corresponding to the triangle numbers
437  * associated with each edge. Boundary edges have one entry = 0. */
438 nume = size(e,1);
439 e2t = repmat(0,nume,2);
440 ndx = repmat(1,nume,1);
441 for k = 1:numt
442  /* Edge in kth triangle */
443  e1 = eINt(k,1); e2 = eINt(k,2); e3 = eINt(k,3);
444  /* Edge 1 */
445  e2t(e1,ndx(e1)) = k; ndx(e1) = ndx(e1)+1;
446  /* Edge 2 */
447  e2t(e2,ndx(e2)) = k; ndx(e2) = ndx(e2)+1;
448  /* Edge 3 */
449  e2t(e3,ndx(e3)) = k; ndx(e3) = ndx(e3)+1;
450 end
451 
452 return
453 
454 }
455 
function [ cout , hout ] = tricontour(ax,double t, p, Hn, N, varargin)
Definition: tricontour.m:17
function [ e , eINt , e2t ] = tricontour>mkcon(p,double t)
Definition: tricontour.m:416
A variable number of input arguments.
Speed test * all(1:3)