classdef traces < handle & matlab.mixin.SetGet & matlab.mixin.Copyable & matlab.mixin.CustomDisplay
% traces creates the trace object w.r.t the InputType in the board.
%
% t = traces(pobj) creates the trace object which takes pcbFileRead as 
% input and returns the traces w.r.t the InputType in the board. 
% 
% t = traces(pobj,'Cadnet','Cadnetname') takes pcbFileRead as input and 
% creates the traces object w.r.t. the Cadnetname.
%
% t = traces(pobj,'Layer',1) takes pcbFileRead as an input and creates the
% traces object for the 1st metal layer.
%
% traces properties:
%
%   pcBoard         - pcbFileRead object.
%   InputType       - Type of the input to get the vias. The choices
%                     are 'Layer' or 'Cadnet'. 
%                     The default InputType is 'layer'. 
%   NumTracePath    - Number of trace paths w.r.t the InputType.
%   TracePoints     - Coordinate points of the trace path. It is nx2 
%                     elements.
%   TracePathWidth  - Width of the trace in inch.
%   TracePathInfo   - Info table of the trace w.r.t the InputType.
%
%   If InputType = 'Layer'
%   LayerNumber  - Index/Position of the layer number in the stack. It 
%                  accepts the scalar value. 
%   or
%   LayerName        - Name of the layer in the stack. It accepts the string.   
%   TracePathInfo    - Info table of the pins in a respective layer. 
%                      Returns the table with below fields. 
%     TraceIndex     : The index of each trace path in a cadnet.
%                      Max(TraceIndex) is the count of trace path in a 
%                      layer.
%     CadnetName     : Name of the cadnet the trace is associated with.

%
%   If InputType = 'Cadnet'
%   CadnetName         - Name of the cadnet. 
%   TracePathInfo      - Info table of the vias of a respective cadnet. 
%                        Returns the table with below fields.
%     TraceIndex     : The index of each trace path in a cadnet.
%                      Max(TraceIndex) is the count of trace path in a 
%                      cadnet.
%     LayerName      : Name of the layer the trace is associated with.
%     LayerNumber    : Layer number the trace is associated with.
%
%
% traces methods:
%   
%   shapes       - Returns the shape of the trace path w.r.t the InputType
%
%   Copyright 2023 The MathWorks, Inc.
    
    properties(SetObservable)
        % pcbFileRead object.
        pcBoard
        % Type of the input to return the traces.
        InputType
        % Layer Number.
        LayerNumber
        % Layer Name.
        LayerName
        % Cadnet Name.
        CadnetName
    end

    properties(SetAccess=protected, GetAccess = public)
        % Number of trace segments w.r.t the InputType.
        NumTraces
        % Start Point of the trace segment.
        StartPoint
        % End Point of the trace segment.
        EndPoint
        % Width of the trace in meter.
        TraceWidth
        % Number of trace path w.r.t the InputType.
        NumTracePath
        % X and Y Points of trace in meter.
        TracePoints
        % Width of the trace path in meter.
        TracePathWidth
    end

    % properties (Access=private)
    %     hUiTable
    %     hUiTableFig
    %     hTab
    %     hTable
    %     SearchCompName
    %     SearchPartName
    %     SearchTable
    % end

    properties(SetAccess = private, GetAccess = public)
        % Info of the surfaces in a respective layer
        TracePathInfo
        TraceInfo
    end

    properties(Access=private)
        LayerNumFlag
    end

    methods
        function obj = traces(pcBoard,InputType,value)
            parserObj = inputParser;

            % add parameters
            addRequired(parserObj,'pcBoard');
            addRequired(parserObj,'InputType');

            if strcmpi(InputType,'Layer')
                if isstring(value) || ischar(value)
                    addOptional(parserObj,'LayerName',value);
                else
                    addOptional(parserObj,'LayerNumber',value);
                end
            elseif strcmpi(InputType,'Cadnet')
                addOptional(parserObj,'CadnetName',value);
            end

            % parse the input
            parse(parserObj,pcBoard,InputType);
            obj.pcBoard        = pcBoard;
            if strcmpi(InputType,'Layer')
                if isstring(value) || ischar(value)
                    obj.LayerName     = parserObj.Results.LayerName;
                    getLayerNumber(obj,value);
                else
                    obj.LayerNumber     = parserObj.Results.LayerNumber;
                    getLayerName(obj,value);
                    obj.LayerNumFlag = 1;
                end
            elseif strcmpi(InputType,'Cadnet')
                obj.CadnetName         = parserObj.Results.CadnetName;
            end
            obj.InputType = InputType;
        end


        function set.pcBoard(obj,propval)
            if ~isa(propval,'pcbFileRead')
                error(message('rfpcb:rfpcberrors:Unsupported','This input',...
                    'pcBoard. Supported input is pcbFileRead object'));
            end
            if isPropertyChanged(obj,obj.pcBoard,propval)
                obj.pcBoard =  propval;
            end
        end

        function set.InputType(obj,propval)
            if ~isempty(propval)
                validatestring(propval,{'Layer','Cadnet'}, ...
                    class(obj),'InputType');
                if isPropertyChanged(obj,obj.InputType,propval)
                    if isstring(propval)
                        propval = char(propval);
                    end
                    obj.InputType =  propval;
                    getTracePathInfo(obj);
                    getTraceInfo(obj)
                end
            end
        end

        function set.LayerName(obj,propval)
            mustBeNonempty(propval);
            if ~isempty(propval)   
                validateLayerName(obj,propval);
                if isPropertyChanged(obj,obj.LayerName,propval)
                    if isstring(propval)
                        propval = char(propval);
                    end
                    obj.LayerName =  propval;
                    getLayerNumber(obj,obj.LayerName);
                    UpdateTraceProp(obj);
                end
            end
        end

        function set.LayerNumber(obj,propval)
            mustBeNonempty(propval);
            if ~isempty(propval)
                % validate the input Layer number
                validateLayerNumber(obj,propval);
                if isPropertyChanged(obj,obj.LayerNumber,propval)
                    obj.LayerNumber =  propval;
                    getLayerName(obj,obj.LayerNumber);
                    UpdateTraceProp(obj);
                end
            end
        end

        function set.CadnetName(obj,propval)
            mustBeNonempty(propval);
            if ~isempty(propval)
                if ~((ischar(propval) || isStringScalar(propval)) && strlength(propval) > 0)
                    error(message('rfpcb:rfpcberrors:PCBNameNotString','CadnetName'));
                end
                validateCadnetName(obj,propval)
                if isPropertyChanged(obj,obj.CadnetName,propval)
                    if isstring(propval)
                        propval = char(propval);
                    end
                    obj.CadnetName =  propval;
                    UpdateTraceProp(obj);
                end
            end
        end


        function tracePathCount = get.NumTracePath(obj)
            if strcmpi(obj.InputType,'Cadnet')
                CName = obj.CadnetName;
                tracePathCount = getCadnetTracePathsCount(CName);
            elseif strcmpi(obj.InputType,'Layer')
                LayerN = obj.LayerNumber;
                tracePathCount = [];
            end
            obj.NumTracePath =  tracePathCount;
        end


        function traceCount = get.NumTraces(obj)
            if strcmpi(obj.InputType,'Cadnet')
                CName = obj.CadnetName;
                traceCount = getCadnetTracesCount(CName);
            elseif strcmpi(obj.InputType,'Layer')
                LayerN = obj.LayerNumber;
                traceCount = getLayerTracesCount(int32(LayerN));
            end
            obj.NumTraces =  traceCount;
        end

        function tracept = get.TracePoints(obj)
            if strcmpi(obj.InputType,'Cadnet')
                [tp,~] = getCadnetTracePoint(obj);
            else
                tp = [];
            end
            tracept = tp;
            obj.TracePoints = tracept;
        end

        function traceW = get.TracePathWidth(obj)
            if strcmpi(obj.InputType,'Cadnet')
                [~,traceW,~] = getCadnetTracePoint(obj);
            else
                traceW = [];
            end
            obj.TracePathWidth = traceW;
        end

        function startPt = get.StartPoint(obj)
            if strcmpi(obj.InputType,'Cadnet')
                traceIdx = 1: obj.NumTraces;
                startx = cell2mat(arrayfun(@(x) getCadnetTraceData(obj.CadnetName, int32(x)).xStart,traceIdx,'UniformOutput',false));
                starty = cell2mat(arrayfun(@(x) getCadnetTraceData(obj.CadnetName, int32(x)).yStart,traceIdx,'UniformOutput',false));
                startPt = [startx',starty'];
            else
                traceIdx = 1: obj.NumTraces;
                startx = cell2mat(arrayfun(@(x) getLayerTraceData(int32(obj.LayerNumber), int32(x)).xStart,traceIdx,'UniformOutput',false));
                starty = cell2mat(arrayfun(@(x) getLayerTraceData(int32(obj.LayerNumber), int32(x)).yStart,traceIdx,'UniformOutput',false));
                startPt = [startx',starty'];
            end
            obj.StartPoint = startPt;
        end

        function stopPt = get.EndPoint(obj)
            if strcmpi(obj.InputType,'Cadnet')
                traceIdx = 1: obj.NumTraces;
                endx = cell2mat(arrayfun(@(x) getCadnetTraceData(obj.CadnetName, int32(x)).xEnd,traceIdx,'UniformOutput',false));
                endy = cell2mat(arrayfun(@(x) getCadnetTraceData(obj.CadnetName, int32(x)).yEnd,traceIdx,'UniformOutput',false));
                stopPt = [endx',endy'];
            else
                traceIdx = 1: obj.NumTraces;
                endx = cell2mat(arrayfun(@(x) getLayerTraceData(int32(obj.LayerNumber), int32(x)).xEnd,traceIdx,'UniformOutput',false));
                endy = cell2mat(arrayfun(@(x) getLayerTraceData(int32(obj.LayerNumber), int32(x)).yEnd,traceIdx,'UniformOutput',false));
                stopPt = [endx',endy'];
            end
            obj.EndPoint = stopPt;
        end

        function tw = get.TraceWidth(obj)
            if strcmpi(obj.InputType,'Cadnet')
                traceIdx = 1: obj.NumTraces;
                tw = cell2mat(arrayfun(@(x) getCadnetTraceData(obj.CadnetName, int32(x)).width,traceIdx,'UniformOutput',false));
                tw = tw';
            else
                traceIdx = 1: obj.NumTraces;
                tw = cell2mat(arrayfun(@(x) getLayerTraceData(int32(obj.LayerNumber), int32(x)).width,traceIdx,'UniformOutput',false));
                tw = tw';
            end
            obj.TraceWidth = tw;
        end
    end
    methods (Hidden)
        function UpdateTraceProp(obj)
            if ~isempty(obj.InputType)
                prop = get(obj);
                getTracePathInfo(obj);
                getTraceInfo(obj)
            end
        end

        function validateLayerName(obj,propval)
            mLnum = obj.pcBoard.MetalLayer;
            mLname = stackUp(obj.pcBoard,mLnum).LayerName;
            mustBeMember(propval,mLname);
        end

        function validateCadnetName(obj,propval)
            mCnetName = cadnetList(obj.pcBoard).CadnetList;
            mustBeMember(propval,mCnetName);
        end

        function validateLayerNumber(obj,propval)
            mLnum = obj.pcBoard.MetalLayer;
            mustBeMember(propval,mLnum);
        end

        function LNum = getLayerNumber(obj,LName)
            stack = stackUp(obj.pcBoard,obj.pcBoard.MetalLayer);
            Lind = strcmpi(stack.LayerName,LName);
            LNum = stack.LayerNumber(Lind);
            obj.LayerNumber = LNum;
        end

        function LName = getLayerName(obj,LNum)
            stack = stackUp(obj.pcBoard,obj.pcBoard.MetalLayer);
            Lind = find(stack.LayerNumber(:,1)==LNum);
            LName = stack.LayerName(Lind);
            LName = LName{1};
            obj.LayerName = LName;
        end
        function getTracePathInfo(obj)
            if strcmpi(obj.InputType,'Layer')

                obj.TracePathInfo = [];

            elseif strcmpi(obj.InputType,'Cadnet')
                traceCount = obj.NumTracePath;
                % Trace Index
                traceIdx = 1:traceCount;
                [~,~,LayerN] = getCadnetTracePoint(obj);
                % Layer Name
                Layername = LayerN;
                % Layer Number
                Layernum = LayerN;
                % Variable names.
                varNames = {'TraceIndex','Layer name','Layer number'} ;
                obj.TracePathInfo = table(traceIdx',Layername,Layernum);
               obj.TracePathInfo.Properties.VariableNames = varNames;

            end
        end

        function getTraceInfo(obj)
            if strcmpi(obj.InputType,'Layer')
                traceCount = obj.NumTraces;
                % Trace Index
                traceIdx = 1:traceCount;
                % LayerNum = cell2mat(arrayfun(@(x) getLayerTraceData(obj.CadnetName, int32(x)),traceIdx,'UniformOutput',false));
                % % Layer Name
                % % LayerName = LayerN;
                % % % Layer Number
                % LayerName = (arrayfun(@(x) getLayerTraceData(obj.CadnetName, int32(x)),traceIdx,'UniformOutput',false));

                % Variable names.
                varNames = {'TraceIndex'} ;
                obj.TraceInfo = table(traceIdx');
                obj.TraceInfo.Properties.VariableNames = varNames;
                obj.TraceInfo = [];

            elseif strcmpi(obj.InputType,'Cadnet')
                traceCount = obj.NumTraces;
                % Trace Index
                traceIdx = 1:traceCount;
                LayerNum = cell2mat(arrayfun(@(x) getCadnetTraceData(obj.CadnetName, int32(x)).layerNumber,traceIdx,'UniformOutput',false));
                % Layer Name
                % LayerName = LayerN;
                % % Layer Number
                LayerName = (arrayfun(@(x) getCadnetTraceData(obj.CadnetName, int32(x)).layerName,traceIdx,'UniformOutput',false));

                % Variable names.
                varNames = {'TraceIndex','LayerName','LayerNumber'} ;
                obj.TraceInfo = table(traceIdx',LayerName',LayerNum');
                obj.TraceInfo.Properties.VariableNames = varNames;

            end
        end

        function PcbTraces = createGeometry(obj,varargin)
            if strcmpi(obj.InputType,'Layer')
                PcbTraces = [];
            elseif strcmpi(obj.InputType,'Cadnet')
                %tracecnt = obj.NumTracePath;
                traceCnt = obj.NumTracePath;
                if(traceCnt > 0)
                    tIdx = 1:traceCnt;
                    PcbTraces = arrayfun(@(x) drawTraces(obj,x),tIdx,'UniformOutput',false);
                end
            end
        end

        function  polyObj = convertLineToPolygon(~,lineXs,lineYs, thickness)
            angle = atan2((lineYs(2)-lineYs(1)),(lineXs(2)-lineXs(1)));
            polyXVals = [];
            thickness = 0.5*thickness;
            polyXVals(1) = lineXs(1) + thickness*cos(angle+pi/2);
            polyXVals(2) = lineXs(1) + thickness*cos(angle-pi/2);
            polyXVals(3) = lineXs(2) + thickness*cos(angle-pi/2);
            polyXVals(4) = lineXs(2) + thickness*cos(angle+pi/2);
            polyYVals(1) = lineYs(1) + thickness*sin(angle+pi/2);
            polyYVals(2) = lineYs(1) + thickness*sin(angle-pi/2);
            polyYVals(3) = lineYs(2) + thickness*sin(angle-pi/2);
            polyYVals(4) = lineYs(2) + thickness*sin(angle+pi/2);

            zValues = zeros(4,1);
            polyVertices = [polyXVals(:), polyYVals(:), zValues(:)];
            polyObj = antenna.Polygon("Vertices", polyVertices);
        end 
    end

    methods(Hidden)

        function [tracePt,traceW,LayerN] = getCadnetTracePoint(obj)
            if strcmp(obj.InputType,'Cadnet')
                Tcount = obj.NumTracePath;
                tracePathIdx = 1:Tcount;
                [xValues, yValues, pathWidth, layern] = arrayfun(@(x) getCadnetTracePathData(obj.CadnetName, int32(x)),tracePathIdx,'UniformOutput',false);
                Tpts = cell(length(xValues),1);
                for i = 1:length(xValues)
                     Tpts{i} = [xValues{i},yValues{i}];
                end
                tracePt = Tpts;
                traceW = cell2mat(pathWidth)';
                LayerN = cell2mat(layern)';
            end
        end

        % function [tracePt,traceW,CadnetN] = getLayerTracePoint(obj)
        %     if strcmp(obj.InputType,'Layer')
        %         Tcount = obj.NumTracePath;
        %         tracePathIdx = 1:Tcount;
        %         [xValues, yValues, pathWidth, layern] = arrayfun(@(x) getLayerTracePathData(int32(obj.LayerNumber), int32(x)),tracePathIdx,'UniformOutput',false);
        %         Tpts = cell(length(xValues),1);
        %         for i = 1:length(xValues)
        %             Tpts{i} = [xValues{i},yValues{i}];
        %         end
        %         tracePt = Tpts;
        %         traceW = cell2mat(pathWidth)';
        %         CadnetN = cell2mat(layern)';
        %     end
        % end
       
        function TracePoly = drawTraces(obj,tind)

            tracept = obj.TracePoints; 
            traceW = obj.TracePathWidth;
               
            if length(tracept{tind}(:,1))==2
                lineX = tracept{tind}(:,1);
                lineY = tracept{tind}(:,2);
                lineXs = [lineX(1),lineX(end)]';
                lineYs = [lineY(1),lineY(end)]';
                % x1 = lineX(1);
                % y1 = lineY(1);
                % x2 = lineX(end);
                % y2 = lineY(end);
                thickness = traceW(tind);
                % numVertices = 2;
                % [xVertices, yVertices] = getRoundedLineVertices(obj,x1, y1, x2, y2, thickness, numVertices);
                tracepoly = convertLineToPolygon(obj,lineXs,lineYs,thickness);
                Tpoly= tracepoly;
            else     
                Tp = removeMiddlePoints(obj,tracept{tind});
                t = tracePoint("TracePoints",Tp,'Width',traceW(tind),EnableRoundedEnds=1);
                Tpoly= t;
            end
           
            % % % If trace point
            % tracept = [obj.StartPoint(tind,:);obj.EndPoint(tind,:)];
            % traceW = obj.TraceWidth;
            % lineX = tracept(:,1);
            % lineY = tracept(:,2);
            % lineXs = [lineX(1),lineX(end)]';
            % lineYs = [lineY(1),lineY(end)]';
            % % x1 = lineX(1);
            % % y1 = lineY(1);
            % % x2 = lineX(end);
            % % y2 = lineY(end);
            % thickness = traceW(tind);
            % % numVertices = 2;
            % % [xVertices, yVertices] = getRoundedLineVertices(obj,x1, y1, x2, y2, thickness, numVertices);
            % tracepoly = convertLineToPolygon(obj,lineXs,lineYs,thickness);
            % Tpoly= tracepoly;

            TracePoly = Tpoly;
        end

        function endPoints = removeMiddlePoints(obj,points)
            % Initialize the output variable
            endPoints = [];

            % Loop through each point
            for i = 1:length(points)
                % Get the current point
                currentPoint = points(i,:);

                % Check if the current point is collinear with the previous and next points
                if i > 1 && i < length(points)
                    previousPoint = points(i-1,:);
                    nextPoint = points(i+1,:);

                    % Calculate the cross product of the vectors formed by the points
                    crossProduct = (currentPoint(1)-previousPoint(1))*(nextPoint(2)-previousPoint(2)) - (currentPoint(2)-previousPoint(2))*(nextPoint(1)-previousPoint(1));

                    % If the cross product is zero, the points are collinear
                    if crossProduct == 0
                        % If the current point is collinear, skip adding it to the output
                        continue;
                    end
                end

                % Add the current point to the output
                endPoints = [endPoints; currentPoint];
            end
        end

        function tf = isPropertyChanged(~,val1,val2)
            % Check if property values are different
            if isempty(val1)        % During constructor call
                tf = true;
            else
                tf = ~isequal(val1,val2);
            end
        end

    end

    methods(Hidden)
        % function out = search(obj,options)
        % 
        %     arguments
        %         obj
        %         options.Component
        %         options.Part
        %         %options.PartName (1,:) {mustBeA(Name,{'char','string'}), mustBeValidSearchName(obj,Name)
        %         options.Layer
        %         options.ComponentType (1,:) string
        %         options.Value (1,1) double
        %     end
        %     obj.SearchTable = obj.PinInfo;
        %     Pindata = obj.SearchTable;
        %     % if obj.SearchCompName
        %     %     idxComp = matches(Pindata.ComponentName,SearchName);
        %     %     obj.SearchTable = Pindata(idxComp,:);
        %     % elseif obj.SearchPartName
        %     %     idxComp = matches(Pindata.PartName,SearchName);
        %     %     obj.SearchTable = Pindata(idxComp,:);
        %     % end
        % 
        %     if isfield(options,'Layer')
        %         pcbL = upper(options.Layer);
        %         if isa(pcbL,"string") ||  isa(pcbL,"char")
        %             mustBeMember(cellstr(upper(pcbL)),Pindata.LayerName)
        %             idxLayer = matches(Pindata.LayerName,pcbL);
        %         elseif isa(pcbL,"double")
        %             mustBeMember(options.Layer,Pindata.LayerName)
        %             idxLayer = matches(Pindata.LayerNumber,pcbL);
        %         end
        %         searchL = Pindata;
        %         obj.SearchTable = searchL(idxLayer,:);
        %     end
        % 
        %     if isfield(options,'Part')
        %         Pname = options.Part;
        %         mustBeMember(Pname,Pindata.PartName)
        %         searchTp = obj.SearchTable;
        %         idxPart = matches(searchTp.PartName,Pname);
        %         obj.SearchTable = searchTp(idxPart,:);
        %         % Search for the respective component
        %     end
        % 
        %     if isfield(options,'Component')
        %         Cname = options.Component;
        %         mustBeMember(Cname,Pindata.ComponentName)
        %         searchTc = obj.SearchTable;
        %         idxComp = matches(searchTc.ComponentName,Cname);
        %         obj.SearchTable = searchTc(idxComp,:);
        %         % Search for the respective component
        %     end
        % 
        %     % if isfield(options,'LayerNumber')
        %     %     mustBeMember(options.Vendor,obj.Vendor)
        %     %     vendors = options.Vendor;
        %     %     idxVendor = matches(obj.Vendor,options.Vendor,IgnoreCase=true);
        %     %     vendorXMLs = obj.xmlVendor(idxVendor);
        %     % else
        %     %     vendors = obj.Vendor;
        %     %     vendorXMLs = obj.xmlVendor;
        %     % end
        % 
        %     % if isfield(options,'Value')
        %     %     mustBeMember(options.Type,obj.Type)
        %     %     idx = find(obj.Availability(matches(obj.Vendor,vendors),...
        %     %         matches(obj.Type,options.Type)));
        %     %     vendors = obj.Vendor(idx);
        %     %     vendorXMLs = obj.xmlVendor(idx);
        %     % else
        %     %     options.Type = obj.Type;
        %     % end
        %     if nargout ==0
        %         pinD = obj.SearchTable;
        %         createUITable(obj,pinD)
        %     else
        %         out = obj.SearchTable;
        %     end
        % end
        % 
        % function createUITable(obj,pinD)
        %     pos = get(0,'defaultFigurePosition');
        %     fig = figure( ...
        %         'Name', 'Pins', ...
        %         'MenuBar', 'none', ...
        %         'Position', pos, ...
        %         'Tag', 'pinSearchTable', ...
        %         'NumberTitle', 'off');
        %     obj.hUiTableFig = fig;
        %     createFigureTab(obj,pinD);
        % end
        % 
        % function createFigureTab(obj,pinD)
        %     % Create Tabbed panel
        %     % pos = obj.hUiTableFig.Position;
        %     % First table
        %     tg = uitabgroup(obj.hUiTableFig);
        %     obj.hTab = uitab(tg,'Title','Search Results');
        %     obj.hTable = pinD;
        %     createTabTable(obj);
        % 
        %     % Second table
        %     obj.hTab = uitab(tg,'Title','PinInfo');
        %     obj.hTable = obj.PinInfo;
        %     createTabTable(obj);
        % end
        % 
        % function createTabTable(obj)
        %     pos = get(0,'defaultFigurePosition');
        %     pos(1:2) = [20 20];
        %     pos(3) = pos(3)-50;
        %     pos(4) = pos(4)-50;
        %     data = table2cell(obj.hTable);
        %     name = obj.hTable.Properties.VariableNames;
        % 
        %     obj.hUiTable = uitable( ...
        %         'Parent', obj.hTab, ...
        %         'Data', data, ...
        %         'ColumnName', name, ...
        %         'ColumnEditable', false, ...
        %         'Position', pos);
        % end
        % 
    end

    methods
        function S = shapes(obj)
            %shapes returns all the shapes of the trace paths w.r.t 
            % InputType.
            %
            % S = shapes(obj) returns the shapes of trace paths w.r.t 
            % InputType.
            %

            % Copyright 2023 The MathWorks, Inc.

            poly = createGeometry(obj);
            %npoly = numel(poly);
            S = poly';
        end    
    end

    methods(Access=protected)
        function group = getPropertyGroups(obj)
            title = '';
            if strcmpi(obj.InputType,'Layer')
                 if obj.LayerNumFlag==1
                    plist = {'pcBoard','InputType','LayerNumber'};
                 else
                    plist = {'pcBoard','InputType','LayerName'};
                 end
                 group = matlab.mixin.util.PropertyGroup(plist,title);
                 plist = {'NumTracePath','TracePoints','TracePathWidth','TracePathInfo'};
                 title1 = 'If TracePath data required: ';
                 title1 = "<strong>" + title1 + "</strong>";
                %  if matlab.internal.display.isHot
                %     title1 = 'If TracePath data required: ';
                %     title1 = "<strong>" + title1 + "</strong>";
                % end
                group(end+1) = matlab.mixin.util.PropertyGroup(plist,title1);
                title2 = 'If Trace data required: ';
                title2 = "<strong>" + title2 + "</strong>";
                % if matlab.internal.display.isHot
                %     title2 = 'If Trace data required: ';
                %     title2 = "<strong>" + title2 + "</strong>";
                % end
                % Trace Count data
                plist = {'NumTraces','StartPoint','EndPoint','TraceWidth','TraceInfo'};
                group(end+1) = matlab.mixin.util.PropertyGroup(plist,title2);
            elseif strcmpi(obj.InputType,'Cadnet')
                plist = {'pcBoard','InputType','CadnetName'};
                group = matlab.mixin.util.PropertyGroup(plist,title);
                % Trace Path Data
                plist = {'NumTracePath','TracePoints','TracePathWidth','TracePathInfo'};
                title1 = 'If TracePath data required: ';
                title1 = "<strong>" + title1 + "</strong>";
                % if matlab.internal.display.isHot
                %     title1 = 'If TracePath data required: ';
                %     title1 = "<strong>" + title1 + "</strong>";
                % end
                group(end+1) = matlab.mixin.util.PropertyGroup(plist,title1);
                title2 = 'If Trace data required: ';
                title2 = "<strong>" + title2 + "</strong>";
                % if matlab.internal.display.isHot
                %     title2 = 'If Trace data required: ';
                %     title2 = "<strong>" + title2 + "</strong>";
                % end
                % Trace Count data
                plist = {'NumTraces','StartPoint','EndPoint','TraceWidth','TraceInfo'};
                group(end+1) = matlab.mixin.util.PropertyGroup(plist,title2);
            end
        end

        function group = objectProps(obj, propertyDisplayList,title)
            propList    = properties(obj);
            numProps    = max(size(propertyDisplayList));
            for i = 1:numProps
                if(strcmpi(propertyDisplayList{i},propList(strcmpi(propertyDisplayList{i},propList))))
                    antennaProps.(char(propertyDisplayList{i})) = get(obj,propertyDisplayList{i});
                else
                    % Error message ??
                end
            end
            group = matlab.mixin.util.PropertyGroup(antennaProps,title);
        end

    end

end



