function [bonds,components] = rbg2abg(rbonds,rstrokes,rcomponents,rports,infofile)
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %% Version control history
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %% $Id$
% %% $Log$
% %% 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;
% Xfig scaling factor
scale = 1200.0;
% 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 number of ports
[n_ports,columns] = size(rports);
% 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
for i = 1:n_ports
near_bond = adjbond(rports(i,1:2),arrow_end,other_end);
port_near_bond(i,:) = [near_bond, rports(i,3)];
end;
% Locate the components at the ends of each bond
for i = 1:n_bonds
comp_near_bond(i,:) = adjcomp(arrow_end(i,:),other_end(i,:),rcomponents);
end;
% Produce a list of bonds on each component - sorted if explicit port numbers
for i = 1:n_components
[index,n] = 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
one = ones(n,1);
bond_list = index(:,1); % bond at component
bond_end = index(:,2); % which end of bond at component?
% Default sort of bonds (ie no change)
sort_index = [1:n]';
if n_ports>0
% Are the component ports numbered? (either they all are or none are)
k=0;
for j = 1:n
b = bond_list(j); e = bond_end(j);
% Find all ports on this bond
[port_indices,m] = getindex(port_near_bond(:,1),b);
% Now find the one at this end - if any
port_index = 0;
for l=1:m
if port_near_bond(port_indices(l),2)==e
port_index = port_indices(l);
break;
end;
end;
if port_index>0
% and put the corresponding number in the list
k=k+1;
port_number(k,1) = port_near_bond(port_index,3);
end;
end;
% Must have a lable for each port or non at all
if k==n
[sorted,sort_index]=sort(port_number);
if sum(sorted==[1:n]')~=n % The there is something wrong
mtt_info(port_error,fnum);
mtt_info(sprintf('\t it must have ports from 1:%1.0f\n', n), fnum);
end;
elseif k~=0
mtt_info(port_error,fnum);
mtt_info(sprintf('\t it must have 0 or %1.0f ports\n', n), fnum);
end;
end;
end;
% direction is 1 if arrow at component else -1
direction = -sign(index(:,2)-1.5*one);
signed_bond_list = bond_list.*direction;
% Write out bond list sorted by port number (if any)
for j = 1:length(sort_index)
jj = sort_index(j);
components(i,j) = signed_bond_list(jj);
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);