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
