function savesurfpoly(v,f,holelist,regionlist,p0,p1,fname,forcebox)
%
% savesurfpoly(v,f,holelist,regionlist,p0,p1,fname)
%
% save a set of surfaces into poly format (for tetgen)
%
% author: Qianqian Fang, <q.fang at neu.edu>
% date: 2007/11/21
%
% input:
% v: input, surface node list, dimension (nn,3)
% if v has 4 columns, the last column specifies mesh density near each node
% f: input, surface face element list, dimension (be,3)
% holelist: list of holes, each hole is represented by an internal point
% regionlist: list of regions, similar to holelist
% p0: coordinate of one of the end of the bounding box
% p1: coordinate for the other end of the bounding box
% fname: output file name
% forcebox: non-empty: add bounding box, []: automatic
% if forcebox is a 8x1 vector, it will be used to
% specify max-edge size near the bounding box corners
%
% -- this function is part of iso2mesh toolbox (http://iso2mesh.sf.net)
%
dobbx=0;
if(nargin>=8)
dobbx=~isempty(forcebox) && all(forcebox);
end
if(~iscell(f) && size(f,2)==4)
faceid=f(:,4);
f=f(:,1:3);
end
if(~iscell(f))
edges=surfedge(f);
else
edges=[];
end
bbxnum=0;
nodesize=[];
if(size(v,2)==4)
nodesize=v(:,4);
v=v(:,1:3);
end
node=v;
loopid=[];
loopvert={};
loopnum=1;
if(~isempty(edges))
loops=extractloops(edges);
if(length(loops)<3)
error('degenerated loops detected');
end
seg=[0,find(isnan(loops))];
segnum=length(seg)-1;
newloops=[];
for i=1:segnum
if(seg(i+1)-(seg(i)+1)==0)
continue;
end
oneloop=loops(seg(i)+1:seg(i+1)-1);
if(oneloop(1)==oneloop(end)) oneloop(end)=[]; end
newloops=[newloops nan bbxflatsegment(node,oneloop)];
end
loops=[newloops nan];
seg=[0,find(isnan(loops))];
segnum=length(seg)-1;
bbxnum=6;
loopcount=zeros(bbxnum,1);
loopid=zeros(segnum,1);
for i=1:segnum % walk through the edge loops
subloop=loops(seg(i)+1:seg(i+1)-1);
if(isempty(subloop))
continue;
end
loopvert{loopnum}=subloop;
loopnum=loopnum+1;
boxfacet=find(sum(abs(diff(v(subloop,:))))<1e-8); % find a flat loop
if(length(boxfacet)==1) % if the loop is flat along x/y/z dir
bf=boxfacet(1); % no degeneracy allowed
if(sum(abs(v(subloop(1),bf)-p0(bf)))<1e-2)
loopcount(bf)=loopcount(bf)+1;
v(subloop,bf)=p0(bf);
loopid(i)=bf;
elseif(sum(abs(v(subloop(1),bf)-p1(bf)))<1e-2)
loopcount(bf+3)=loopcount(bf+3)+1;
v(subloop,bf)=p1(bf);
loopid(i)=bf+3;
end
end
end
end
if(dobbx && isempty(edges))
bbxnum=6;
loopcount=zeros(bbxnum,1);
end
if(dobbx || ~isempty(edges))
nn=size(v,1);
boxnode=[p0;p1(1),p0(2:3);p1(1:2),p0(3);p0(1),p1(2),p0(3);
p0(1:2),p1(3);p1(1),p0(2),p1(3);p1;p0(1),p1(2:3)];
boxelem=[
4 nn nn+3 nn+7 nn+4; % x=xmin
4 nn nn+1 nn+5 nn+4; % y=ymin
4 nn nn+1 nn+2 nn+3; % z=zmin
4 nn+1 nn+2 nn+6 nn+5; % x=xmax
4 nn+2 nn+3 nn+7 nn+6; % y=ymax
4 nn+4 nn+5 nn+6 nn+7];% z=zmax
node=[v;boxnode];
end
node=[(0:size(node,1)-1)',node];
fp=fopen(fname,'wt');
fprintf(fp,'#node list\n%d 3 0 0\n',length(node));
fprintf(fp,'%d %.16f %.16f %.16f\n',node');
if(~iscell(f))
fprintf(fp,'#facet list\n%d 1\n',length(f)+bbxnum+length(loopvert));
elem=[3*ones(length(f),1),f-1];
if(~isempty(elem))
if(exist('faceid','var') && length(faceid)==size(elem,1))
fprintf(fp,'1 0 %d\n%d %d %d %d\n',[faceid(:) elem]');
else
fprintf(fp,'1 0\n%d %d %d %d\n',elem');
end
end
if(~isempty(loopvert))
for i=1:length(loopvert) % walk through the edge loops
subloop=loopvert{i}-1;
fprintf(fp,'1 0 %d\n%d',i,length(subloop));
fprintf(fp,'\t%d',subloop);
fprintf(fp,'\n');
end
end
else % if the surface is recorded as a cell array
totalplc=0;
for i=1:length(f)
if(~iscell(f{i}))
totalplc=totalplc+size(f{i},1);
else
totalplc=totalplc+size(f{i}{1},1);
end
end
fprintf(fp,'#facet list\n%d 1\n',totalplc+bbxnum);
for i=1:length(f)
plcs=f{i};
faceid=-1;
if(iscell(plcs)) % if each face is a cell, use plc{2} for face id
if(length(plcs)>1)
faceid=plcs{2};
end
plcs=plcs{1};
end
for row=1:size(plcs,1);
plc=plcs(row,:);
if(any(isnan(plc))) % we use nan to separate outter contours and holes
holeid=find(isnan(plc));
if(faceid>0)
fprintf(fp,'%d %d %d\n%d',length(holeid)+1,length(holeid),faceid,holeid(1)-1);
else
fprintf(fp,'%d %d\n%d',length(holeid)+1,length(holeid),holeid(1)-1);
end
fprintf(fp,'\t%d',plc(1:holeid(1)-1)-1);
fprintf(fp,'\t1\n');
for j=1:length(holeid)
if(j==length(holeid))
fprintf(fp,'%d',length(plc(holeid(j)+1:end)));
fprintf(fp,'\t%d',plc(holeid(j)+1:end)-1);
else
fprintf(fp,'%d',length(plc(holeid(j)+1:holeid(j+1)-1)));
fprintf(fp,'\t%d',plc(holeid(j)+1:holeid(j+1)-1)-1);
end
fprintf(fp,'\t1\n');
end
for j=1:length(holeid)
if(j==length(holeid))
fprintf(fp,'%d %.16f %.16f %.16f\n',j,mean(node(plc(holeid(j)+1:end),2:4)));
else
fprintf(fp,'%d %.16f %.16f %.16f\n',j,mean(node(plc(holeid(j)+1:holeid(j+1)-1),2:4)));
end
end
else
if(faceid>0)
fprintf(fp,'1 0 %d\n%d',faceid,length(plc));
else
fprintf(fp,'1 0\n%d',length(plc));
end
fprintf(fp,'\t%d',plc-1);
fprintf(fp,'\t1\n');
end
end
end
end
if(dobbx || ~isempty(edges))
for i=1:bbxnum
fprintf(fp,'%d %d 1\n',1+loopcount(i),loopcount(i));
fprintf(fp,'%d %d %d %d %d\n',boxelem(i,:));
if(~isempty(edges) && loopcount(i) &&~isempty(find(loopid==i, 1)))
endid=find(loopid==i);
for k=1:length(endid)
j=endid(k);
subloop=loops(seg(j)+1:seg(j+1)-1);
fprintf(fp,'%d ',length(subloop));
fprintf(fp,'%d ',subloop-1);
fprintf(fp,'\n');
end
for k=1:length(endid)
j=endid(k);
subloop=loops(seg(j)+1:seg(j+1)-1);
fprintf(fp,'%d %.16f %.16f %.16f\n',k,internalpoint(v,subloop)); %mean(v(subloop,:)));
end
end
end
end
if(size(holelist,1))
fprintf(fp,'#hole list\n%d\n',size(holelist,1));
for i=1:size(holelist,1)
fprintf(fp,'%d %.16f %.16f %.16f\n', i, holelist(i,:));
end
else
fprintf(fp,'#hole list\n0\n');
end
if(size(regionlist,1))
fprintf(fp,'#region list\n%d\n',size(regionlist,1));
if(size(regionlist,2)==3)
for i=1:size(regionlist,1)
fprintf(fp,'%d %.16f %.16f %.16f %d\n', i, regionlist(i,:),i);
end
elseif(size(regionlist,2)==4)
for i=1:size(regionlist,1)
fprintf(fp,'%d %.16f %.16f %.16f %d %.16f\n', i, regionlist(i,1:3),i,regionlist(i,4));
end
end
end
fclose(fp);
if(~isempty(nodesize))
if(size(nodesize,1)+size(forcebox(:),1)==size(node,1))
nodesize=[nodesize;forcebox(:)];
end
fid=fopen(regexprep(fname,'\.poly$','.mtr'),'wt');
fprintf(fid,'%d 1\n',size(nodesize,1));
fprintf(fid,'%.16f\n',nodesize);
fclose(fid);
end