function [bonds,components] = rbg2abg(name,rbonds,rstrokes,rcomponents,port_coord,port_name,infofile) % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % %% Version control history % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % %% $Id$ % %% $Log$ % %% Revision 1.15 1997/08/06 21:43:19 peterg % %% Corrected error in creating component list: the kth component of the % %% list is given by the jth component of the original list NOT vice % %% versa. % %% % %% Revision 1.14 1997/08/04 14:18:55 peterg % %% If no ports labels at all, just use the default component list. % %% % %% Revision 1.13 1997/08/04 12:50:39 peterg % %% Many bug fixes to the named port version + tied up the logic and % %% supporting comments. % %% % %% Revision 1.12 1997/08/02 19:37:53 peterg % %% Now uses named ports. % %% % %% Revision 1.11 1997/04/29 09:12:37 peterg % %% Added error message if port label near to >1 bond. % %% % %% Revision 1.10 1997/03/17 13:45:42 peterg % %% Added more error info. % %% % %% Revision 1.9 1996/12/31 11:25:57 peterg % %% Clearer error messages for incorrect ports. % %% % %% Revision 1.8 1996/12/04 21:52:39 peterg % %% Now uses fopen. % %% % %% Revision 1.7 1996/11/01 18:01:57 peterg % %% Rationalised port ordering. % %% Fixed port bug. % %% % %% Revision 1.6 1996/08/25 08:27:14 peter % %% Now checks ports correctely - I hope. % %% % %% Revision 1.5 1996/08/24 19:21:26 peter % %% More specific error messages. % %% % %% Revision 1.4 1996/08/24 18:00:33 peter % %% Fixed bug with finding ports. % %% % %% Revision 1.3 1996/08/09 08:26:35 peter % %% Cosmetic tidy up. % %% % %% Revision 1.2 1996/08/04 18:37:57 peter % %% Fixed no causal strokes bug. % %% % %% Revision 1.1 1996/08/04 18:30:14 peter % %% Initial revision % %% % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% if nargin<5 infofile='stdout'; else fnum = fopen(infofile, 'w'); end; %Default to no components components = [0]; % Xfig scaling factor scale = 1200.0/2.54546; % Rotation matrix rot = [0 -1; 1 0]; % Find number of strokes [n_strokes,columns] = size(rstrokes); if (columns ~= 4)&(n_strokes>0) error('Incorrect rstrokes matrix: must have 4 columns'); end; % Find number of bonds [n_bonds,columns] = size(rbonds); if (columns ~= 6)&(n_bonds>0) error('Incorrect rbonds matrix: must have 6 columns'); end; % Find number of components [n_components,columns] = size(rcomponents); % Find the number of ports refered to within the component [n_ports,columns] = size(port_coord) % Determine coordinates of the arrow end of the bond and the other end other_end_1 = rbonds(:,1:2); arrow_end = rbonds(:,3:4); other_end_2 = rbonds(:,5:6); distance_1 = length2d(other_end_1 - arrow_end); distance_2 = length2d(other_end_2 - arrow_end); which_end = (distance_1>distance_2)*[1 1]; one = ones(size(which_end)); other_end = which_end.*other_end_1 + (one-which_end).*other_end_2; arrow_vector = ( which_end.*other_end_2 + (one-which_end).*other_end_1 ) - ... arrow_end; % Locate the bond end nearest to each port % col 1 of port_near_bond contains a signed bond number (+ for arrow end) % col 2 of port_near_bond contains the corresponding port index for i = 1:n_ports near_bond = adjbond(port_coord(i,1:2),arrow_end,other_end); [rows,cols]=size(near_bond); if rows>1 error(sprintf ... ("A port is near to more than one bond at coordinates %g,%g\n", ... port_coord(i,1)/scale, port_coord(i,2)/scale)); end; %The (signed) bond corresponding to the ith port label port_bond(i) = near_bond(1)*sign(1.5-near_bond(2)); end; %We now have the (signed) bond (port_bond(i)) correponding to the % ith port label within the component % Locate the components at the ends of each bond % col 1 of comp_near_bond contain the component nearest to the arrow end % col 2 of comp_near_bond contain the component nearest to the other end for i = 1:n_bonds comp_near_bond(i,:) = adjcomp(arrow_end(i,:),other_end(i,:),rcomponents); end; %We now have a list (comp_near_bond) of the component(s) at each end %of each bond % Produce a list of bonds on each component (within this component) % - sorted if explicit port numbers for i = 1:n_components %Get component type eval(['[comp_type, comp_name] = ', name, '_cmp(i)']); %Convert junction names if comp_type=='0' comp_type = 'zero'; end if comp_type=='1' comp_type = 'one'; end %Find the port list for this component if exist([comp_type, '_cause'])==0 eval(['[junk1,junk2,junk3,junk4,junk5,port_list]=', comp_type, '_rbg;']); else port_list=comp_ports(comp_type); end; % There are n_comp_bonds bonds on this component with corresponding index [index,n_comp_ports] = getindex(comp_near_bond,i); % Error message in case we need it! port_error = sprintf(... 'Component at (%1.3f,%1.3f) has inconsistent port numbers', ... rcomponents(i,1)/scale, rcomponents(i,2)/scale); if index(1,1) ~= 0 % Then its a genuine component % Create the signed list of bonds on this component one = ones(n_comp_ports,1); bond_list = index(:,1); % bond at component bond_end = index(:,2); % which end of bond at component? direction = -sign(bond_end-1.5*one); signed_bond_list = bond_list.*direction; unsorted_port_list=""; if n_ports>0 % then there are some numbered ports % so find those associated with the bonds on this component. k=0; for j = 1:n_comp_ports b = signed_bond_list(j); % Find the port label on component end of bond (if any) [port_index,m] = getindex(port_bond,b); if m==1 k=k+1; unsorted_port_list(k,:) = port_name(port_index,:); end; end; else % just use that provided by the component unsorted_port_list = port_list; k = n_comp_ports; end; %Either all ports or no ports should be labelled - write error %message if this is not so if (k~=0)&(k~=n_comp_ports) mtt_info(['Component ', comp_name, ' (', comp_type, ') has wrong number of labels'], infofile); mtt_info(sprintf("\tit has %1.0f labels but should have 0 or %1.0f",k,n_comp_ports), infofile); end; %Compute the number of labeled ports [n_unsorted_ports,m_unsorted_ports] = size(unsorted_port_list); if m_unsorted_ports<2 n_unsorted_ports = 0; end; % One port defaults: if (n_comp_ports==1)&(n_unsorted_ports==0) if (direction(1)<0) & ~strcmp(comp_type,'SS') % Wrong way for default mtt_info(['One-port ', comp_name, ' (', comp_type, ') has the sign pointing the wrong way '], infofile); end; unsorted_port_list = port_list; end; %Two port defaults if (n_comp_ports==2)&(n_unsorted_ports==0) if direction(1)==direction(2) % Wrong way for default mtt_info(['Two-port ', comp_name, ' (', comp_type, ') does not have though-pointing arrows'], infofile); end; if direction(1)==1 %in unsorted_port_list = port_list; else %reverse the order unsorted_port_list = port_list(2:1); end; end; % Recompute the number of unsorted ports [n_unsorted_ports,m_unsorted_ports] = size(unsorted_port_list); if m_unsorted_ports<2 n_unsorted_ports = 0; end; % Junctions or no lables(order of ports unimportant) if strcmp(comp_type,'zero')|strcmp(comp_type,'one') for j = 1:n_comp_ports components(i,j) = signed_bond_list(j); end else %Order of ports is important unsorted_port_list, port_list if n_unsorted_ports==0 mtt_info(['Component ', comp_name, ' (', comp_type, ') has no labeled ports: '], infofile); end; %Write out the signed bond list in the correct order for j = 1:n_comp_ports name_k = unsorted_port_list(j,:); k = name_in_list(name_k, port_list); % Check that it only appears once in port list if length(k)>1 mtt_info(['Component ', comp_name, ' (', comp_type, ') has ports with the same name: ', name_k], infofile); end; %Check that it only appears one in the label list kk = name_in_list(name_k,unsorted_port_list); if length(kk)>1 mtt_info(['Component ', comp_name, ' (', comp_type, ') has multiple port labels: ', name_k], infofile); end; if k==0 mtt_info(['Component ', comp_name, ' (', comp_type, ') has an unrecognised port: ', name_k], infofile); else components(i,k) = signed_bond_list(j); end; end; end; end; end; % Deduce causality from the strokes (if any). causality = zeros(n_bonds,2); if n_strokes>0 % Find out location of centre and ends of stroke. stroke_end_1 = [rstrokes(:,1) rstrokes(:,2)]; stroke_end_2 = [rstrokes(:,3) rstrokes(:,4)]; stroke_centre = (stroke_end_1 + stroke_end_2)/2; stroke_vector = (stroke_end_1 - stroke_end_2); stroke_length = length2d(stroke_vector); % Deduce bond causality from the strokes for i = 1:n_strokes stroke = [stroke_centre(i,:) stroke_end_1(i,:) stroke_end_2(i,:)]; % Find the nearest bond end. [index,distance] = adjbond(stroke(1,:),arrow_end,other_end); if (distance>2*stroke_length(i)) info = sprintf('Stroke at (%4.3f,%4.3f) is %4.3f away from the nearest bond\n', ... stroke(1,1)/scale, stroke(1,2)/scale, distance/scale); end; % Bond end coordinates j = index(1,1); which_end = index(1,2)==1; bond_end = arrow_end(j,:)*which_end + other_end(j,:)*(1-which_end); % Now decide which bit of the stroke is nearest stroke_index = adjbond(bond_end,stroke,zeros(size(stroke))); if stroke_index(1)==1 % uni-causal stroke causality(j,1:2) = (2*which_end-1)*[1 1]; else % bicausal stroke % Find out whether stroke is on flow side of bond stroke_direction = stroke(1,:) - stroke(stroke_index(1),:); flow_side = stroke_direction*arrow_vector(j,:)'>0; causality(j,1+flow_side) = 2*which_end-1; end; end; end; bonds = causality; fclose(fnum);