PageRenderTime 30ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/model/fitness/fitness_torsion/Mesh2d v23/private/quadtree.m

http://bohreroptimierung.googlecode.com/
MATLAB | 701 lines | 462 code | 104 blank | 135 comment | 75 complexity | 28ff041c77bae2b430a2f8e855185400 MD5 | raw file
Possible License(s): BSD-3-Clause, BSD-2-Clause, LGPL-2.1
  1. function [p,t,h] = quadtree(node,edge,hdata,dhmax,wbar)
  2. % QUADTREE: 2D quadtree decomposition of polygonal geometry.
  3. %
  4. % The polygon is first rotated so that the minimal enclosing rectangle is
  5. % aligned with the Cartesian XY axes. The long axis is aligned with Y. This
  6. % ensures that the quadtree generated for a geometry input that has
  7. % undergone arbitrary rotations in the XY plane is always the same.
  8. %
  9. % The bounding box is recursively subdivided until the dimension of each
  10. % box matches the local geometry feature size. The geometry feature size is
  11. % based on the minimum distance between linear geometry segments.
  12. %
  13. % A size function is obtained at the quadtree vertices based on the minimum
  14. % neighbouring box dimension at each vertex. This size function is gradient
  15. % limited to produce a smooth function.
  16. %
  17. % The quadtree is triangulated to form a background mesh, such that the
  18. % size function may be obtained at any XY position within the domain via
  19. % triangle based linear interpolation. The triangulation is done based on
  20. % the quadtree data structures directly (i.e. NOT using Qhull) which is
  21. % more reliable and produces a consistently oriented triangulation.
  22. %
  23. % The initial rotations are undone.
  24. %
  25. % node : [x1,y1; x2,y2; etc] geometry vertices
  26. % edge : [n11,n12; n21,n22; etc] geometry edges as connections in NODE
  27. % hdata : User defined size function structure
  28. % dhmax : Maximum allowalble relative gradient in the size function
  29. % wbar : Handle to progress bar from MESH2D
  30. %
  31. % p : Background mesh nodes
  32. % t : Background mesh triangles
  33. % h : Size function value at p
  34. % Darren Engwirda : 2007
  35. % Email : d_engwirda@hotmail.com
  36. % Last updated : 18/11/2007 with MATLAB 7.0
  37. % Bounding box
  38. XYmax = max(node,[],1);
  39. XYmin = min(node,[],1);
  40. % Rotate NODE so that the long axis of the minimum bounding rectangle is
  41. % aligned with the Y axis.
  42. theta = minrectangle(node);
  43. node = rotate(node,theta);
  44. % Rotated XY edge endpoints
  45. edgexy = [node(edge(:,1),:), node(edge(:,2),:)];
  46. % LOCAL FEATURE SIZE
  47. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  48. %waitbar(0,wbar,'Estimating local geometric feature size');
  49. % Get size function data
  50. [hmax,edgeh,fun,args] = gethdata(hdata);
  51. % Insert test points along the boundaries at which the LFS can be
  52. % approximated.
  53. wm = 0.5*(edgexy(:,[1,2])+edgexy(:,[3,4])); % Use the edge midpoints as a first pass
  54. len = sqrt(sum((edgexy(:,[3,4])-edgexy(:,[1,2])).^2,2)); % Edge length
  55. L = 2.0*dist2poly(wm,edgexy,2.0*len); % Estimate the LFS at these points by calculating
  56. % the distance to the closest edge segment
  57. % In cases where edges are separated by less than their length
  58. % we will need to add more points to capture the LFS in these
  59. % regions. This allows us to pick up "long and skinny" geometry
  60. % features
  61. r = 2.0*len./L; % Compare L (LFS approximation at wm) to the edge lengths
  62. r = round((r-2.0)/2.0); % Amount of points that need to be added
  63. add = find(r); % at each edge
  64. if ~isempty(add)
  65. num = 2*sum(r(add)); % Total number of points to be added
  66. start = size(wm,1)+1;
  67. wm = [wm; zeros(num,2)]; % Alloc space
  68. L = [L; zeros(num,1)];
  69. next = start;
  70. for j = 1:length(add) % Loop through edges to be subdivided
  71. ce = add(j); % Current edge
  72. num = r(ce);
  73. tmp = (1:num)'/(num+1); % Subdivision increments
  74. num = next+2*num-1;
  75. x1 = edgexy(ce,1); x2 = edgexy(ce,3); xm = wm(ce,1); % Edge values
  76. y1 = edgexy(ce,2); y2 = edgexy(ce,4); ym = wm(ce,2);
  77. wm(next:num,:) = [x1+tmp*(xm-x1), y1+tmp*(ym-y1) % Add to list
  78. xm+tmp*(x2-xm), ym+tmp*(y2-ym)];
  79. L(next:num) = L(ce); % Upper bound on LFS
  80. next = num+1;
  81. end
  82. L(start:end) = dist2poly(wm(start:end,:),edgexy,L(start:end)); % Estimate LFS at the new points
  83. end
  84. % Compute the required size along the edges for any boundary layer size
  85. % functions and add additional points where necessary.
  86. if ~isempty(edgeh)
  87. for j = 1:size(edgeh,1)
  88. if L(edgeh(j,1))>=edgeh(j,2)
  89. cw = edgeh(j,1);
  90. r = 2.0*len(cw)/edgeh(j,2);
  91. r = ceil((r)/2.0); % Number of points to be added
  92. tmp = (1:r-1)'/r;
  93. x1 = edgexy(cw,1); x2 = edgexy(cw,3); xm = wm(cw,1); % Edge values
  94. y1 = edgexy(cw,2); y2 = edgexy(cw,4); ym = wm(cw,2);
  95. wm = [wm; x1+tmp*(xm-x1), y1+tmp*(ym-y1); % Add to list
  96. xm+tmp*(x2-xm), ym+tmp*(y2-ym)];
  97. L(cw) = edgeh(j,2); % Update LFS
  98. L = [L; edgeh(j,2)*ones(2*length(tmp),1)];
  99. end
  100. end
  101. end
  102. % To speed the point location in the quadtree decomposition
  103. % sort the LFS points based on y-value
  104. [i,i] = sort(wm(:,2));
  105. wm = wm(i,:);
  106. L = L(i);
  107. nw = size(wm,1);
  108. % UNBALANCED QUADTREE DECOMPOSITION
  109. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  110. %waitbar(0.2,wbar,'Quadtree decomposition');
  111. xymin = min([edgexy(:,[1,2]); edgexy(:,[3,4])]); % Bounding box
  112. xymax = max([edgexy(:,[1,2]); edgexy(:,[3,4])]);
  113. dim = 2.0*max(xymax-xymin); % Bbox dimensions
  114. xm = 0.5*(xymin(1)+xymax(1));
  115. ym = 0.5*(xymin(2)+xymax(2));
  116. % Setup boxes with a consistent CCW node order
  117. % b(k,1) = n1 : bottom left
  118. % b(k,2) = n2 : bottom right
  119. % b(k,3) = n3 : top right
  120. % b(k,4) = n4 : top left
  121. % Start with bbox
  122. p = [xm-0.5*dim, ym-0.5*dim
  123. xm+0.5*dim, ym-0.5*dim
  124. xm+0.5*dim, ym+0.5*dim
  125. xm-0.5*dim, ym+0.5*dim];
  126. b = [1,2,3,4];
  127. % User defined size functions
  128. pr = rotate(p,-theta);
  129. h = userhfun(pr(:,1),pr(:,2),fun,args,hmax,XYmin,XYmax);
  130. pblock = 5*nw; % Alloc memory in blocks
  131. bblock = pblock;
  132. np = size(p,1);
  133. nb = size(b,1);
  134. test = true(nb,1);
  135. while true
  136. vec = find(test(1:nb)); % Boxes to be checked at this step
  137. if isempty(vec)
  138. break
  139. end
  140. N = np;
  141. for k = 1:length(vec) % Loop through boxes to be checked for subdivision
  142. m = vec(k); % Current box
  143. n1 = b(m,1); n2 = b(m,2); % Corner nodes
  144. n3 = b(m,3); n4 = b(m,4);
  145. x1 = p(n1,1); y1 = p(n1,2); % Corner xy
  146. x2 = p(n2,1); y4 = p(n4,2);
  147. % Binary search to find first wm with y>=ymin for current box
  148. if wm(1,2)>=y1
  149. start = 1;
  150. elseif wm(nw,2)<y1
  151. start = nw+1;
  152. else
  153. lower = 1;
  154. upper = nw;
  155. for i = 1:nw
  156. start = round(0.5*(lower+upper));
  157. if wm(start,2)<y1
  158. lower = start;
  159. elseif wm(start-1,2)<y1
  160. break;
  161. else
  162. upper = start;
  163. end
  164. end
  165. end
  166. % Init LFS as the min of corner user defined size function values
  167. LFS = 1.5*h(n1);
  168. if 1.5*h(n2)<LFS, LFS = 1.5*h(n2); end
  169. if 1.5*h(n3)<LFS, LFS = 1.5*h(n3); end
  170. if 1.5*h(n4)<LFS, LFS = 1.5*h(n4); end
  171. % Loop through all WM in box and take min LFS
  172. for i = start:nw % Loop through points (acending y-value order)
  173. if (wm(i,2)<=y4) % Check box bounds and current min
  174. if (wm(i,1)>=x1) && (wm(i,1)<=x2) && (L(i)<LFS)
  175. LFS = L(i); % New min found - reset
  176. end
  177. else % Due to the sorting
  178. break;
  179. end
  180. end
  181. % Split box into 4
  182. if (x2-x1)>=LFS
  183. if (np+5)>=size(p,1) % Alloc memory on demand
  184. p = [p; zeros(pblock,2)];
  185. pblock = 2*pblock;
  186. end
  187. if (nb+3)>=size(b,1)
  188. b = [b; zeros(bblock,4)];
  189. test = [test; true(bblock,1)];
  190. bblock = 2*bblock;
  191. end
  192. xm = x1+0.5*(x2-x1); % Current midpoints
  193. ym = y1+0.5*(y4-y1);
  194. % New nodes
  195. p(np+1,1) = xm; p(np+1,2) = ym;
  196. p(np+2,1) = xm; p(np+2,2) = y1;
  197. p(np+3,1) = x2; p(np+3,2) = ym;
  198. p(np+4,1) = xm; p(np+4,2) = y4;
  199. p(np+5,1) = x1; p(np+5,2) = ym;
  200. % New boxes
  201. b(m,1) = n1; % Box 1
  202. b(m,2) = np+2;
  203. b(m,3) = np+1;
  204. b(m,4) = np+5;
  205. b(nb+1,1) = np+2; % Box 2
  206. b(nb+1,2) = n2;
  207. b(nb+1,3) = np+3;
  208. b(nb+1,4) = np+1;
  209. b(nb+2,1) = np+1; % Box 3
  210. b(nb+2,2) = np+3;
  211. b(nb+2,3) = n3;
  212. b(nb+2,4) = np+4;
  213. b(nb+3,1) = np+5; % Box 4
  214. b(nb+3,2) = np+1;
  215. b(nb+3,3) = np+4;
  216. b(nb+3,4) = n4;
  217. nb = nb+3;
  218. np = np+5;
  219. else
  220. test(m) = false;
  221. end
  222. end
  223. % User defined size function at new nodes
  224. pr = rotate(p(N+1:np,:),-theta);
  225. h = [h; userhfun(pr(:,1),pr(:,2),fun,args,hmax,XYmin,XYmax)];
  226. end
  227. p = p(1:np,:);
  228. b = b(1:nb,:);
  229. % Remove duplicate nodes
  230. [p,i,j] = unique(p,'rows');
  231. h = h(i);
  232. b = reshape(j(b),size(b));
  233. % FORM SIZE FUNCTION
  234. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  235. %waitbar(0.4,wbar,'Forming element size function')
  236. % Unique edges
  237. e = unique(sort([b(:,[1,2]); b(:,[2,3]); b(:,[3,4]); b(:,[4,1])],2),'rows');
  238. L = sqrt(sum((p(e(:,1),:)-p(e(:,2),:)).^2,2)); % Edge length
  239. ne = size(e,1);
  240. for k = 1:ne % Initial h - minimum neighbouring edge length
  241. Lk = L(k);
  242. if Lk<h(e(k,1)), h(e(k,1)) = Lk; end
  243. if Lk<h(e(k,2)), h(e(k,2)) = Lk; end
  244. end
  245. h = min(h,hmax);
  246. % Gradient limiting
  247. tol = 1.0e-06;
  248. while true % Loop over the edges of the background mesh ensuring
  249. h_old = h; % that dh satisfies the dhmax tolerance
  250. for k = 1:ne % Loop over edges
  251. n1 = e(k,1);
  252. n2 = e(k,2);
  253. Lk = L(k);
  254. if h(n1)>h(n2) % Ensure grad(h)<=dhmax
  255. dh = (h(n1)-h(n2))/Lk;
  256. if dh>dhmax
  257. h(n1) = h(n2) + dhmax*Lk;
  258. end
  259. else
  260. dh = (h(n2)-h(n1))/Lk;
  261. if dh>dhmax
  262. h(n2) = h(n1) + dhmax*Lk;
  263. end
  264. end
  265. end
  266. if norm((h-h_old)./h,'inf')<tol % Test convergence
  267. break
  268. end
  269. end
  270. % TRIANGULATE QUADTREE
  271. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  272. %waitbar(0.6,wbar,'Triangulating quadtree');
  273. if size(b,1)==1
  274. % Split box diagonally into 2 tri's
  275. t = [b(1),b(2),b(3); b(1),b(3),b(4)];
  276. else
  277. % Get node-to-node connectivity
  278. % First column is column count per row
  279. % Max neighbours is 8 due to quadtree setup
  280. n2n = zeros(size(p,1),9);
  281. for k = 1:size(e,1)
  282. % Nodes in kth edge
  283. n1 = e(k,1);
  284. n2 = e(k,2);
  285. % Indexing
  286. n2n(n1,1) = n2n(n1,1)+1; % Node 1
  287. n2n(n1,n2n(n1,1)+1) = n2;
  288. n2n(n2,1) = n2n(n2,1)+1; % Node 2
  289. n2n(n2,n2n(n2,1)+1) = n1;
  290. end
  291. % Check for regular boxes with no mid-side nodes
  292. num = n2n(:,1)<=4;
  293. reg = all(num(b),2);
  294. % Split regular boxes diagonally into 2 tri's
  295. t = [b(reg,[1,2,3]); b(reg,[1,3,4])];
  296. if ~all(reg)
  297. % Use the N2N connectivity to directly triangulate the quadtree
  298. % nodes. Some additional nodes may be added at the centroids of some
  299. % boxes to facilitate triangulation. The triangluation is not
  300. % necessarily Delaunay, but should always be high quality and
  301. % symmetric where possible.
  302. b = b(~reg,:); % Boxes that still need to be dealt with
  303. nb = size(b,1);
  304. nt = size(t,1);
  305. % Alloc space
  306. t = [t; zeros(5*nb,3)]; % Has to be a least 5 times as many tri's as boxes
  307. nlist = zeros(512,1); % Shouldn't ever be exceeded!
  308. lim = 0.5*nb;
  309. for k = 1:nb
  310. if k>lim % Halfway!
  311. %waitbar(0.8,wbar,'Triangulating quadtree');
  312. lim = nb+1;
  313. end
  314. % Corner nodes
  315. n1 = b(k,1); n2 = b(k,2);
  316. n3 = b(k,3); n4 = b(k,4);
  317. % Assemble node list for kth box in CCW order
  318. nlist(1) = n1;
  319. count = 1;
  320. next = 2;
  321. while true
  322. cn = nlist(next-1);
  323. % Find the closest node to CN travelling CCW around box
  324. old = inf;
  325. for j = 1:n2n(cn,1)
  326. nn = n2n(cn,j+1);
  327. dx = p(nn,1)-p(cn,1);
  328. dy = p(nn,2)-p(cn,2);
  329. if count==1 % Edge 12
  330. if (dx>0.0) && (dx<old)
  331. old = dx;
  332. tmp = nn;
  333. end
  334. elseif count==2 % Edge 23
  335. if (dy>0.0) && (dy<old)
  336. old = dy;
  337. tmp = nn;
  338. end
  339. elseif count==3 % Edge 34
  340. if (dx<0.0) && (abs(dx)<old)
  341. old = abs(dx);
  342. tmp = nn;
  343. end
  344. else % Edge 41
  345. if (dy<0.0) && (abs(dy)<old)
  346. old = abs(dy);
  347. tmp = nn;
  348. end
  349. end
  350. end
  351. if tmp==n1 % Back to start - Done!
  352. break
  353. elseif (count<4) && (tmp==b(k,count+1)) % New edge
  354. count = count+1;
  355. end
  356. nlist(next) = tmp;
  357. next = next+1;
  358. end
  359. nnode = next-1;
  360. if (nt+nnode)>=size(t,1) % Realloc memory on demand
  361. t = [t; zeros(nb,3)];
  362. end
  363. if (np+1)>=size(p,1)
  364. p = [p; zeros(nb,2)];
  365. h = [h; zeros(nb,1)];
  366. end
  367. % Triangulate box
  368. if nnode==4 % Special treatment if no mid-side nodes
  369. % Split box diagonally into 2 tri's
  370. % New tri's
  371. t(nt+1,1) = n1; % t1
  372. t(nt+1,2) = n2;
  373. t(nt+1,3) = n3;
  374. t(nt+2,1) = n1; % t2
  375. t(nt+2,2) = n3;
  376. t(nt+2,3) = n4;
  377. % Update count
  378. nt = nt+2;
  379. elseif nnode==5 % Special treatment if only 1 mid-side node
  380. % Split box into 3 tri's centred at mid-side node
  381. % Find the mid-side node
  382. j = 2;
  383. while j<=4
  384. if nlist(j)~=b(k,j)
  385. break
  386. end
  387. j = j+1;
  388. end
  389. % Permute indexing so that the split is always between n1,n2
  390. if j==3
  391. n1 = b(k,2); n2 = b(k,3);
  392. n3 = b(k,4); n4 = b(k,1);
  393. elseif j==4
  394. n1 = b(k,3); n2 = b(k,4);
  395. n3 = b(k,1); n4 = b(k,2);
  396. elseif j==5
  397. n1 = b(k,4); n2 = b(k,1);
  398. n3 = b(k,2); n4 = b(k,3);
  399. end
  400. % New tri's
  401. t(nt+1,1) = n1; % t1
  402. t(nt+1,2) = nlist(j);
  403. t(nt+1,3) = n4;
  404. t(nt+2,1) = nlist(j); % t2
  405. t(nt+2,2) = n2;
  406. t(nt+2,3) = n3;
  407. t(nt+3,1) = n4; % t3
  408. t(nt+3,2) = nlist(j);
  409. t(nt+3,3) = n3;
  410. % Update count
  411. nt = nt+3;
  412. else % Connect all mid-side nodes to an additional node
  413. % introduced at the centroid
  414. % New tri's
  415. xave = 0.0;
  416. yave = 0.0;
  417. have = 0.0;
  418. for j = 1:nnode-1
  419. jj = nlist(j);
  420. % New tri's
  421. t(nt+j,1) = jj;
  422. t(nt+j,2) = np+1;
  423. t(nt+j,3) = nlist(j+1);
  424. % Averaging
  425. xave = xave+p(jj,1);
  426. yave = yave+p(jj,2);
  427. have = have+h(jj);
  428. end
  429. jj = nlist(nnode);
  430. % Last tri
  431. t(nt+nnode,1) = jj;
  432. t(nt+nnode,2) = np+1;
  433. t(nt+nnode,3) = nlist(1);
  434. % New node
  435. p(np+1,1) = (xave+p(jj,1)) /nnode;
  436. p(np+1,2) = (yave+p(jj,2)) /nnode;
  437. h(np+1) = (have+h(jj)) /nnode;
  438. % Update count
  439. nt = nt+nnode;
  440. np = np+1;
  441. end
  442. end
  443. p = p(1:np,:);
  444. h = h(1:np);
  445. t = t(1:nt,:);
  446. end
  447. end
  448. % Undo rotation
  449. p = rotate(p,-theta);
  450. end % quadtree()
  451. %% SUB-FUNCTIONS
  452. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  453. function theta = minrectangle(p)
  454. % Find the rotation angle that must be applied to the 2D points in P so
  455. % that the long axis of the minimum bounding rectangle is aligned with the
  456. % Y axis.
  457. n = size(p,1);
  458. if numel(p)~=2*n
  459. error('P must be an Nx2 array');
  460. end
  461. if n>2
  462. % Convex hull edge segments
  463. e = convhulln(p);
  464. % Keep convex points
  465. i = unique(e(:));
  466. p = p(i,:);
  467. % Re-index to keep E consistent
  468. j = zeros(size(p,1),1);
  469. j(i) = 1;
  470. j = cumsum(j);
  471. e = j(e);
  472. % Angles of hull segments
  473. dxy = p(e(:,2),:)-p(e(:,1),:);
  474. ang = atan2(dxy(:,2),dxy(:,1));
  475. % Check all hull edge segments
  476. Aold = inf;
  477. for k = 1:size(e,1)
  478. % Rotate through -ang(k)
  479. pr = rotate(p,-ang(k));
  480. % Compute area of bounding rectangle and save if better
  481. dxy = max(pr,[],1)-min(pr,[],1);
  482. A = dxy(1)*dxy(2);
  483. if A<Aold
  484. Aold = A;
  485. theta = -ang(k);
  486. end
  487. end
  488. % Check result to ensure that the long axis is aligned with Y
  489. pr = rotate(p,theta);
  490. dxy = max(pr,[],1)-min(pr,[],1);
  491. if dxy(1)>dxy(2)
  492. % Need to flip XY
  493. theta = theta+0.5*pi;
  494. end
  495. else
  496. % 1 or 2 points, degenerate bounding rectangle in either case
  497. theta = 0.0;
  498. end
  499. end % minrectangle()
  500. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  501. function p = rotate(p,theta)
  502. % Rotate the 2D points in P through the angle THETA (radians).
  503. stheta = sin(theta);
  504. ctheta = cos(theta);
  505. p = p*[ctheta, stheta; -stheta, ctheta];
  506. end % rotate()
  507. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  508. function h = userhfun(x,y,fun,args,hmax,xymin,xymax)
  509. % Evaluate user defined size function.
  510. if ~isempty(fun)
  511. h = feval(fun,x,y,args{:});
  512. if size(h)~=size(x)
  513. error('Incorrect user defined size function. SIZE(H) must equal SIZE(X).');
  514. end
  515. else
  516. h = inf*ones(size(x));
  517. end
  518. h = min(h,hmax);
  519. % Limit to domain
  520. out = (x>xymax(1))|(x<xymin(1))|(y>xymax(2))|(y<xymin(2));
  521. h(out) = inf;
  522. if any(h<=0.0)
  523. error('Incorrect user defined size function. H must be positive.');
  524. end
  525. end % userhfun()
  526. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  527. function [hmax,edgeh,fun,args] = gethdata(hdata)
  528. % Check the user defined size functions
  529. d_hmax = inf;
  530. d_edgeh = [];
  531. d_fun = '';
  532. d_args = {};
  533. if ~isempty(hdata)
  534. if ~isstruct(hdata)
  535. error('HDATA must be a structure');
  536. end
  537. if numel(hdata)~=1
  538. error('HDATA cannot be an array of structures');
  539. end
  540. fields = fieldnames(hdata);
  541. names = {'hmax','edgeh','fun','args'};
  542. for k = 1:length(fields)
  543. if ~any(strcmp(fields{k},names))
  544. error('Invalid field in HDATA');
  545. end
  546. end
  547. if isfield(hdata,'hmax')
  548. if (numel(hdata.hmax)~=1) || (hdata.hmax<=0)
  549. error('HDATA.HMAX must be a positive scalar');
  550. else
  551. hmax = hdata.hmax;
  552. end
  553. else
  554. hmax = d_hmax;
  555. end
  556. if isfield(hdata,'edgeh')
  557. if (numel(hdata.edgeh)~=2*size(hdata.edgeh,1)) || any(hdata.edgeh(:)<0)
  558. error('HDATA.EDGEH must be a positive Kx2 array');
  559. else
  560. edgeh = hdata.edgeh;
  561. end
  562. else
  563. edgeh = d_edgeh;
  564. end
  565. if isfield(hdata,'fun')
  566. if ~ischar(hdata.fun) && ~isa(hdata.fun,'function_handle')
  567. error('HDATA.FUN must be a function name or a function handle');
  568. else
  569. fun = hdata.fun;
  570. end
  571. else
  572. fun = d_fun;
  573. end
  574. if isfield(hdata,'args')
  575. if ~iscell(hdata.args)
  576. error(['HDATA.ARGS must be a cell array of additional' ...
  577. 'inputs for HDATA.FUN']);
  578. else
  579. args = hdata.args;
  580. end
  581. else
  582. args = d_args;
  583. end
  584. else
  585. hmax = d_hmax;
  586. edgeh = d_edgeh;
  587. fun = d_fun;
  588. args = d_args;
  589. end
  590. end % gethdata()