classdef surfaceCutout < handle
% surfaceCutout creates a surfaceCutout object that returns the data of  
% cutouts in a surface.
%
% S = surfaceCutout(sobj,SurfInd) creates cutout object of metalSurface
% w.r.t the surface index.
%
% surfaceCutout input argument:
%   sobj     - metalSurface object.
%   SurfInd  - Index of the surface in a metalSurface. It accepts the
%              scalar value.
%
% surfaceCutout properties:
%   NumCutouts  - Number of cutouts in a surface.
%   Vertices    - Vertices of the cutout polygons.
%
% surfaceIslandPolygon methods:   
%   shapes  - Returns the shape of the cutout polygon w.r.t a surface

% Copyright 2023 The MathWorks, Inc.


    properties(SetAccess = private, GetAccess = public)
        % Number of cutouts in a surface.
        NumCutouts
        % Vertices of the cutouts
        Vertices
        %Shape
    end

    properties(Access=private)
        PrivateSurfaceInd
        PrivateLayerNumber
        PrivateCadnetName
        PrivateInputType
    end

    properties(Hidden)
        CutoutData
    end

    methods
        function obj = surfaceCutout(Sobj,SurfInd)
            arguments
                Sobj(1,1)  metalSurface
                SurfInd(1,1) {mustBeNumeric,...
                    mustBeNonNan,mustBeFinite,mustBeInteger,...
                    mustBePositive,mustBeValidNumber(Sobj,SurfInd)};
            end
            obj.PrivateInputType = Sobj.InputType;
            if strcmpi( obj.PrivateInputType,'Layer')
                obj.PrivateLayerNumber = Sobj.LayerNumber;
            elseif strcmpi( obj.PrivateInputType,'Cadnet')
                obj.PrivateCadnetName = Sobj.CadnetName;
            end
            obj.PrivateSurfaceInd = SurfInd;
        end
    end
    methods %-------Set/Get-------- %
        function HoleCnt = get.NumCutouts(obj)
           [HoleCnt,~] = SurfaceDataPolyHole(obj,obj.PrivateSurfaceInd);
            obj.NumCutouts =  HoleCnt;
        end

        function HData = get.Vertices(obj)
            [~,HoleData] = SurfaceDataPolyHole(obj,obj.PrivateSurfaceInd);
            HData = HoleData';
            % Remove the NANs from the data
            for i = 1: size(HData,1)       
                idx  =isnan(HData{i}(:,1));
                HData{i}(idx,:) = [];
            end
            obj.Vertices =  HData;
        end

        % function HPoly = get.Shape(obj)
        %     HPoly = CreatePolyHole(obj,obj.PrivateSurfaceInd);
        %     obj.Shape =  HPoly;
        % end        
    end

    methods (Hidden)
        function [polyCount,SPolyData] = SurfaceDataPolyHole(obj,SurfaceIndex)

            Sidx = SurfaceIndex;
            if ~isempty(obj.PrivateLayerNumber)
                Lid = obj.PrivateLayerNumber;
                Surf_LayerId = getLayerSurfaceId(int32(Lid));
            else
                Surf_LayerId = getCadnetSurfaceIndexList(obj.PrivateCadnetName)';
            end

            % polyhole data
            polyHCount = getSurfaceHolePolygonCount(int32(Surf_LayerId(Sidx)));
            % RoundAntipad
            RoundHCount = getSurfaceRoundHoleCount(int32(Surf_LayerId(Sidx)));
            % Antipad type rectangle data
            RecHCount =  getSurfaceRectHoleCount(int32(Surf_LayerId(Sidx)));
            polyCount = polyHCount+RoundHCount+RecHCount;
            if polyHCount~=0
                holeIdx = 1 : polyHCount;
                HoleVertices = arrayfun(@(x) CreateCutoutVertices(obj,Sidx,x),holeIdx,'UniformOutput',false);
                HData = HoleVertices;
            else
                HData = [];
            end
            if RoundHCount~=0
                rhIdx = 1: RoundHCount;
                RHVertices = arrayfun(@(x) CreateRHVertices(obj,Sidx,x),rhIdx,'UniformOutput',false);
                RPolyV =  RHVertices;
            else
                RPolyV = [];
            end
            if RecHCount~=0
                rechIdx = 1: RecHCount;
                RecHVertices = arrayfun(@(x) CreateRecHVertices(obj,Sidx,x),rechIdx,'UniformOutput',false);
                RecPolyV =  RecHVertices;
            else
                RecPolyV = [];
            end
            SPolyData = [HData,RPolyV,RecPolyV];
        end

        % function HoleVertices = getHoleVertices(obj,surfIdx,holeIdx)
        %     Lid = obj.PrivateLayerNumber;
        %     Surf_LayerId = getLayerSurfaceId(int32(Lid));
        %     % Return the vertices with nan seperator
        %     [HolexValues,HoleyValues] = getSurfaceHolePolygonData(int32(Surf_LayerId(surfIdx)), int32(holeIdx));
        %     HoleVertices = [HolexValues(:), HoleyValues(:)];
        % end

        function RHolePoly = CreateRHVertices(obj,surfIdx,rhIdx)
            if ~isempty(obj.PrivateLayerNumber)
                Lid = obj.PrivateLayerNumber;
                Surf_LayerId = getLayerSurfaceId(int32(Lid));
            else
                Surf_LayerId = getCadnetSurfaceIndexList(obj.PrivateCadnetName)';
            end
             RHseparator = [nan,nan];
            
             % Return the vertices with nan seperator
             [RHxValues,RHyValues] = getSurfaceRoundHolePolygonData(int32(Surf_LayerId(surfIdx)), int32(rhIdx));
             RHVertices = [RHxValues(:), RHyValues(:)];
             RHVertices = [RHVertices; RHseparator];
             RHolePoly = RHVertices;
        end

        function RecHolePoly = CreateRecHVertices(obj,surfIdx,rechIdx)
            if ~isempty(obj.PrivateLayerNumber)
                Lid = obj.PrivateLayerNumber;
                Surf_LayerId = getLayerSurfaceId(int32(Lid));
            else
                Surf_LayerId = getCadnetSurfaceIndexList(obj.PrivateCadnetName)';
            end
             RecHseparator = [nan,nan];
             % Return the vertices with nan seperator
             [RecHxValues,RecHyValues] =  getSurfaceRectHolePolygonData(int32(Surf_LayerId(surfIdx)), int32(rechIdx));
             RecHVertices = [RecHxValues(:), RecHyValues(:)];
             RecHVertices = [RecHVertices; RecHseparator];
             RecHolePoly = RecHVertices;
        end

        function SurfHolePoly = CreatePolyHole(obj,surfInd)
            % This function is used to create the poly hole

            % Get Poly Hole Data
            [~,PolyHoleData] = SurfaceDataPolyHole(obj,surfInd);
            orig_state = warning;
            warning('off','MATLAB:polyshape:repairedBySimplify');
            % Create the shape of hole polygon using polyshape
            if ~isempty(PolyHoleData)
                PolyHoleCount = length(PolyHoleData);
                if ~(PolyHoleCount == 0) 
                    %CutOutVertices = arrayfun(@(x) CreateCutoutVertices(obj,surfInd,x),polyIdx,'UniformOutput',false);
                    CutoutPolyV =  cell2mat(PolyHoleData');
                    CutoutPolyV(:,3) = zeros(length(CutoutPolyV(:,1)),1);
                    SurfHolePoly = antenna.Polygon('Vertices',CutoutPolyV);
                    warning(orig_state);
                end
            else
                SurfHolePoly = [];
            end
        end

        function HolePoly = CreateCutoutVertices(obj,surfIdx,polyIdx)
           
            if ~isempty(obj.PrivateLayerNumber)
                Lid = obj.PrivateLayerNumber;
                Surf_LayerId = getLayerSurfaceId(int32(Lid));
            else
                Surf_LayerId = getCadnetSurfaceIndexList(obj.PrivateCadnetName)';
            end
            
            Cutoutseparator = [nan,nan];
            % Return the vertices with nan seperator
            [HolexValues,HoleyValues] = getSurfaceHolePolygonData(int32(Surf_LayerId(surfIdx)), int32(polyIdx));
            HoleVertices = [HolexValues(:), HoleyValues(:)];
            HoleVertices = [HoleVertices; Cutoutseparator];
            HolePoly = HoleVertices;


            % [ViaxValues,ViayValues] = getSurfaceViaPolygonData(int32(surfIdx), int32(viaIdx));
            % fillViashape = polyshape(ViaxValues(:,1),ViayValues(:,1));
            % ViaHolePoly = fillViashape;%union(RHolePoly,fillRHshape);
        end
    end

    methods
        function S = shapes(obj)
            %shapes returns the shape of the cutouts in a surfaces
            %
            % S = shapes(obj) returns the shapes of cutouts in a surfaces

            % Copyright 2023 The MathWorks, Inc.

            surfInd = obj.PrivateSurfaceInd;
            HoleShape = CreatePolyHole(obj,surfInd);

            if ~isempty(HoleShape)
                S = HoleShape;
            else
                S = [];
            end
        end
    end
end
function mustBeValidNumber(SurfObj,value)
SurfaceInd = value;
SurfaceIndExp = SurfObj.SurfaceInfo.SurfaceIndex;
if any(SurfaceInd==SurfaceIndExp)
    value = value;  %#ok<ASGSL>
else
    eid = 'Value:notValid';
    msg = getString(message('rfpcb:rfpcberrors:SurfaceIndex',num2str(SurfaceIndExp')));
    throwAsCaller(MException(eid,msg));
end
end