function [triout, xout, yout, zout] = triage(tri, x, y, z) % triage -- Triangle repair. % [triout, xout, yout, zout] = triage(tri, x, y, z) performs % triage on the triangles "tri", whose vertices lie at (x, y, z), % so that the Matlab "tsearch" function can be applied, despite % concavities. The algorithm is: % 1. Cast existing "tri" to counter-clockwise sense. % 2. Fill all concavities and holes with clockwise % triangles that have at least one NaN vertex. % If a "z" vector is given, it will be made compatible % with the (xout, yout) values. Added boundary points % will be interpolated from the original z, and all % supplemental interior points will be set to NaN. % The output consists of the original triangles and % data at the top, followed by the supplemental items % at the bottom. % triage(N) demonstrates itself with N vertices (default = 32). % Copyright (C) 1999 Dr. Charles R. Denham, ZYDECO. % All Rights Reserved. % Disclosure without explicit written consent from the % copyright owner does not constitute publication. % Version of 09-Jul-1999 04:43:15. % Updated 23-Jul-1999 16:22:12. if nargin < 1, tri = 'demo'; end if isequal(tri, 'demo'), tri = 32; end if ischar(tri), tri = eval(tri); end if length(tri) == 1 nvertices = tri; scale = nvertices^(1/4); rad = 1 + rand(nvertices, 1) / scale; ang = sort(rand(size(rad)) * 2 * pi); xy = rad .* exp(ang*sqrt(-1)); x = real(xy); y = imag(xy); [tt, xx, yy, ii] = tripoly(x, y); new = ones(size(x)); new(ii) = 0; new = find(new); xnew = xx(new); ynew = yy(new); s = trisense(tt, xx, yy); ccw = find(s > 0); cw = find(s < 0); if any(cw), tt(cw, :) = []; end [to, xo, yo] = feval(mfilename, tt, xx, yy); delete(get(gca, 'Children')) hold off h = tripatch(to, xo, yo); theBDF = [mfilename ' ' int2str(nvertices)]; set(h, 'ButtonDownFcn', theBDF) title(theBDF) hold on, plot(x, y, 'o', xnew, ynew, '+'), hold off set(gca, 'XLim', [-2 2], 'YLim', [-2 2]) figure(gcf) zoomsafe return end if nargin < 3, help(mfilename), return, end if nargin < 4, z = zeros(size(x)); end x = x(:); y = y(:); z = z(:); trinew = []; s = trisense(tri, x, y); cw = (s < 0); ccw = (s > 0); tri(cw, :) = fliplr(tri(cw, :)); % disp(' ## trihull...') [h, overlapping] = trihull(tri); if ~overlapping % disp(' ## tripoly...') h = [NaN; h(:); NaN]; f = find(isnan(h)); kstart = 2; kstop = length(f); for k = kstart:kstop remaining = length(f)-k+1; if 0 & k == 2 | rem(remaining, 10) == 0 disp([' ## Remaining: ' int2str(remaining) ' segments.']) end hi = h(f(k-1)+1:f(k)-1); xhi = x(hi); yhi = y(hi); [ti, xi, yi, ind] = tripoly(xhi(:), yhi(:)); % Renumber and rearrange with old on top and new below. inserted = length(xi) - length(xhi); if any(inserted) disp([' ## "tripoly" has inserted ' int2str(inserted) ' points.']) old = ind; new = ones(size(xi)); new(old) = 0; new = find(new); htemp = [old(:); new(:)]; xi = xi(htemp); yi = yi(htemp); [ignore, hinv] = sort(htemp); ti = hinv(ti); old = 1:length(old); new = length(old) + (1:length(new)); old = old(:); new = new(:); hi_old = hi; hi_new = length(x) + [1:length(new)]; hi = [hi_old(:); hi_new(:)]; xi_new = xi(new); yi_new = yi(new); x = [x; xi_new(:)]; y = [y; yi_new(:)]; end ti = hi(ti); % Map to original indices. [m, n] = size(ti); if n == 1, ti = ti.'; end s = trisense(ti, x, y); cw = (s < 0); ccw = (s > 0); a(k-1) = areaxy(xi, yi); if a < 0 % cw ti = ti(ccw, :); else % ccw. ti = ti(cw, :); end trinew = [trinew; ti]; end end % Interpolate z for any new (x, y) points. if nargin > 3 & length(z) < length(x) inserted = (length(z)+1):length(x); z(length(x)) = 0; z(inserted) = triterp(trinew, x, y, z, x(inserted), y(inserted)); end xnew = []; ynew = []; znew = []; if ~isempty(trinew) [m, n] = size(trinew); if n == 1, trinew = trinew.'; end xnew = x(trinew); ynew = y(trinew); [m, n] = size(xnew); if n == 1, xnew = xnew.'; ynew = ynew.'; end xnew = xnew * [1;1;1] / 3; ynew = ynew * [1;1;1] / 3; znew = zeros(size(xnew)) + NaN; end xout = [x; xnew]; yout = [y; ynew]; if nargin > 3, zout = [z; znew]; end if ~isempty(trinew) k = (length(x) + (1:length(xnew))).'; trinew = [[trinew(:, [1 2]); trinew(:, [2 3]); trinew(:, [3 1])] [k; k; k]]; s = trisense(trinew, xout, yout); ccw = (s > 0); if any(ccw) trinew(ccw, :) = fliplr(trinew(ccw, :)); end end if nargout > 0 triout = [tri; trinew]; end