
function print_geom_objects (GOBJ, taglist)
% function print_geom_objects (GOBJ, taglist)
%    (cell array, taglist, is optional)
%
% Prints construction info for all (or selected, on option) objects in a 
% geometry object's GOBJ.objects field, traversing and printing info for
% its children, and so recursively.
%
% examples: 
%   print_geom_objects (fea.geom)
%	print_geom_objects (fea.geom, {'B1', 'S3'})

% place constant array for names of transformation fields
% (turns out not to be such a great idea in general, but I will leave it
% for now...)
global trans_param_names;
trans_param_names = ...
    {'disp' 'scale' 'rotnAng' 'rotnCntr' 'rotnAxis' '0=rad/1=deg' };

% place constant array for names of cutplane fields
% (Second attempt at this technique ... not really going to work...probably
% should remove this one and perhals the "trans_param_names" one also.)
global brep_param_names;
brep_param_names = {'cutplane pt' 'cutplane norm'};

% crudely deal with the optional argument
if( nargin ~= 1 )
    if ~iscell(taglist)
        fprintf ("INFO: Optional 'objtags' must be cell array.");
        fprintf ("    print_geom_objects (GOBJ, {'S1' 'B1' 'SP2'});");
        return;
    end
end

% print summary (implent later as option)
% for q=1:1:length(GOBJ.objects)
%     fprintf (" %2d:  '%s', '%s'\n", ...
%         q, GOBJ.objects{q}.tag, GOBJ.objects{q}.type);
% end

for i=1:1:length(GOBJ.objects)
    if( nargin == 1 )  
        %% || ismember (GOBJ.objects{i}.tag, objtags)
        %% (if I could count on short circuit processing of 'if A || B'
        %% but for now just make two tests and duplicate calls :(
        print_children ("", GOBJ.objects{i}, i, 0);
    elseif  ismember (GOBJ.objects{i}.tag, taglist)
        print_children ("", GOBJ.objects{i}, i, 0);
    end
end

end

function print_param (par, n)
% print triad, typically a 3D point or Vector
% Used in conjunction with trans_param_names and brep_param_names.
for j=1:1:length(par{n})
    if (isinteger(par{n}(j)))
        %  integer or logical
        fprintf (" %2d", par{n}(j));
    else
        %  floating point
        fprintf (" %9f", par{n}(j));
    end
end
end


function print_info (ndent, obj, n)
% Print selected fields from objects of the specific object type

    global trans_param_names;
    global brep_param_names;
    
    % first print the info contained in all objects
    fprintf ("%s%2d:  '%s', '%s'\n", ndent, n, obj.tag, obj.type);
    
    % then 'case/switch' on each type of interest and print its info
    if isequal(obj.type,'transformed')
        for i=1:1:length(obj.param)
            fprintf ("%s   %12s: ", ndent, trans_param_names{i});
            print_param (obj.param, i);
            fprintf ("\n");
        end
        
    elseif  isequal(obj.type,'point')
        fprintf ("   %scenter: %9f  %9f  %9f\n", ndent, obj.center(1:3));
        fprintf ("   %s     v: %9f  %9f  %9f  (?)\n", ndent, obj.v(1:3));
        
    elseif  isequal(obj.type,'block')
        fprintf ("   %s        min        max\n", ndent);
        fprintf ("   %s x: %9f  %9f\n", ndent, obj.x_min, obj.x_max);
        fprintf ("   %s y: %9f  %9f\n", ndent, obj.y_min, obj.y_max);
        fprintf ("   %s z: %9f  %9f\n", ndent, obj.z_min, obj.z_max);
        
    elseif  isequal(obj.type,'sphere')
        fprintf ("   %s  center: %9f  %9f  %9f\n", ndent, obj.center(1:3));
        fprintf ("   %s  radius: %9f\n", ndent, obj.radius);
        fprintf ("   %s    axis: %2d     (1/2/3 ==> x/y/z axis direction)\n", ...
            ndent, obj.axis);
              
    elseif  isequal(obj.type,'ellipsoid')
        fprintf ("   %scenter: %9f  %9f  %9f\n", ndent, obj.center(1:3));
        fprintf ("   %s radii: %9f  %9f  %9f\n", ndent, obj.radius_x, ...
            obj.radius_y, obj.radius_z);
        fprintf ("   %s  axis: %9f  %9f  %9f\n", ndent, obj.axis(1:3));

    elseif  isequal(obj.type,'cylinder')
        fprintf ("   %scenter: %9f  %9f  %9f\n", ndent, obj.center(1:3));
        fprintf ("   %sradius: %9f\n", ndent, obj.radius);
        fprintf ("   %slength: %9f\n", ndent, obj.length);
        fprintf ("   %s  axis: %9f  %9f  %9f\n", ndent, obj.axis(1:3));

    elseif  isequal(obj.type,'cone')
        fprintf ("   %scenter: %9f  %9f  %9f\n", ndent, obj.center(1:3));
        fprintf ("   %s rad_1: %9f\n", ndent, obj.radius_1);
        fprintf ("   %s rad_2: %9f\n", ndent, obj.radius_2);
        fprintf ("   %slength: %9f\n", ndent, obj.length);
        fprintf ("   %s  axis: %9f  %9f  %9f\n", ndent, obj.axis(1:3));
        
    elseif  isequal(obj.type,'polyhedron')
        for i=1:1:length(obj.points)
            fprintf ("%s   pt%2d: %9f  %9f %9f\n", ...
                ndent, i, obj.points(i,1:3));
        end
        
    elseif  isequal(obj.type,'torus')
        fprintf ("   %scenter: %9f  %9f  %9f\n", ndent, obj.center(1:3));
        fprintf ("   %s rad_c: %9f\n", ndent, obj.radius_c);
        fprintf ("   %s rad_t: %9f\n", ndent, obj.radius_t);
        fprintf ("   %s  axis: %9f  %9f  %9f\n", ndent, obj.axis(1:3));

    elseif  isequal(obj.type,'join') || ...
            isequal(obj.type,'subtract') || ...
            isequal(obj.type,'intersect')        
        fprintf ("   %sformula: (%s)\n", ndent, obj.formula); 

    elseif  isequal(obj.type,'brep')  % result of a split
        for i=1:1:length(obj.param)
            fprintf ("%s   %13s: ", ndent, brep_param_names{i});
            print_param (obj.param, i);
            fprintf ("\n");
        end
        
    elseif  isequal(obj.type,'fillet')
        fprintf ("   %sradius: %9f\n", ndent, obj.param{1});
        
     elseif  isequal(obj.type,'chamfer')
         fprintf ("   %sdistance: %9f\n", ndent, obj.param{1});
                
    elseif  isequal(obj.type,'extrusion')
        fprintf ("   %sdistance: %9f\n", ndent, obj.param{1});
        fprintf ("   %s  vector: %9f  %9f  %9f\n", ndent, obj.param{2});
        
        % param{3} for this type either conatins Workplane data or
        % an object (unspecified) face number.
        if isstruct(obj.param{3}) && ...
           isequal(fieldnames(obj.param{3}),[{'p'}; {'n'}; {'t'}])
            %  extrusion from 2D Workplane at: 
            fprintf ("   %sWkPpoint: %9f  %9f  %9f\n", ndent, obj.param{3}.p);
            fprintf ("   %sWkPVnorm: %9f  %9f  %9f\n", ndent, obj.param{3}.n);
            fprintf ("   %sWkPVtang: %9f  %9f  %9f\n", ndent, obj.param{3}.t);
            
        else  % if isinteger(obj.param{3}) but it is a FLOAT?
            
            fprintf ("   %sextrFace:  %d\n", ndent, obj.param{3});
        end
        
    elseif  isequal(obj.type,'revolution')
        fprintf ("   %s   revAng:  %9f\n", ndent, obj.param{1});
        fprintf ("   %s revPoint: %9f  %9f  %9f\n", ndent, obj.param{2});
        fprintf ("   %srevVector: %9f  %9f  %9f\n", ndent, obj.param{3});
        fprintf ("   %s  revFace:  %d\n", ndent, obj.param{4});
        fprintf ("   %s revPitch:  %9f   (TBD)\n", ndent, 99.999);
        
    else
        fprintf ("   %s*****************\n", ndent);
        fprintf ("   %s** DETAILS TBD **\n", ndent);
        fprintf ("   %s*****************\n", ndent);
    end
    fprintf ("\n");
end

function print_children (indent_str, obj, m, gen)

if (m == 1)
    %  Print a header for each generation
    fprintf ("%s --> Gen %d", indent_str, gen);
    if (gen == 0)
        fprintf (" (Active Objects)");
    end
    fprintf ("\n");
end

% print the selected info for this object
print_info(indent_str, obj, m);

if (isfield(obj,'children') && ~isempty(obj.children))
    % if there are children, print its info and traverse its descendents
    for k=1:1:length(obj.children) 
        print_children(indent_str+"   ", obj.children{k}, k, gen+1);
    end
end

end



