classdef Ellipse < shape.Shape2D
 %SHAPE.ELLIPSE Create an ellipse centered at the origin on the X-Y plane
 %
 %   h = shape.Ellipse returns a ellipse shape on the X-Y plane
 %   centered at the origin.
 %
 %   h = shape.Ellipse(Name1=Value1,...,NameN=ValueN) creates a ellipse shape
 %   with specified properties. Name is the property name and
 %   Value is the corresponding value. Properties that you do
 %   not specify retain their default values.
 %
 %   Ellipse properties:
 %
 %   Name       - Name of the ellipse shape. The default name is myEllipse.
 %   Center     - Cartesian coordinates of the center of the ellipse in
 %                units of meters specified as a 2-element vector. The
 %                default value is [0 0].
 %   MajorAxis  - Longest diameter of the ellipse shape in meters. The 
 %                default value is 1.
 %   MinorAxis  - Shortest diameter of the ellipse shape in meters. The
 %                default value is 0.5
 %   NumPoints  - Number of discretization points on the circumference. The
 %                default value is 30.
 %   Metal       - Metal assigned for the shape. The default object is
 %                 'PEC' with infinite conductivity and zero
 %                 thickness.
 %   Color       - Face Color of the shape. The default value is 'y'.
 %   Transparency - Transparency of the shape. The default value is 1.
 %   EdgeColor   - Edge Color of the shape. The default value is 'k'.
 %
 %   Ellipse methods:
 %
 %   add           - Boolean unite operation on two shapes
 %   subtract      - Boolean subtraction operation on two shapes
 %   intersect     - Boolean intersection operation on two shapes
 %   plus          - r1 + r2, boolean unite, equivalent to add
 %   minus         - r1 - r2, boolean subtraction, equivalent to subtract
 %   and           - r1&r2, boolean intersection, equivalent to intersect
 %   area          - Area of shape in units of sq.m
 %   show          - Visualize the shape as a filled patch
 %   plot          - Visualize the shape boundary
 %   mesh          - Compute/visualize the mesh of the shape
 %   rotate        - Rotate the shape about an axis and an angle
 %   rotateX       - Rotate the shape about X-axis with an angle
 %   rotateY       - Rotate the shape about Y-axis with an angle
 %   rotateZ       - Rotate the shape about Z-axis with an angle
 %   translate     - Move the shape to a new location
 %   scale         - Scale the size of the shape
 %   imprintShape  - Imprint a 2-D shape onto a custom 2-D or 3-D shape
 %   createHole    - Create a hole of 2-D shape on custom 2-D or 3-D shape
 %   extrude       - Extrude a 2D shape on custom shape
 %   extrudeLinear - Extrude a 2D shape linearly
 %   extrudeRotate - Extrude a 2D shape by rotation
 %   removeFaces   - Remove the selected faces of shape interactively
 %
 %   % Examples
 %
 %   % Example 1:
 %   % Create an ellipse shape with major axis of length 1 m and 
 %   % the minor axis of length 0.5 m, make a square hole of side 10 cm at the
 %   % center and mesh it at a wavelength of 1 m.
 %
 %   e = shape.Ellipse;
 %   r = shape.Rectangle(Length = 0.1,Width = 0.1);
 %   s = e-r;
 %   mesh(s,1)
 %
 %   % Example 2:
 %   % Create an ellipse shape with major axis of length 1 m and the 
 %   % minor axis of length 0.5 m, make a circular hole of radius 10 cm at the 
 %   % center and mesh it with a maximum edge length of 20 cm.
 %
 %   e = shape.Ellipse;
 %   r = shape.Circle(Radius = 0.1);
 %   s = e-r;
 %   mesh(s,MaxEdgeLength = 2e-1)
 %
 %   %Example 3:
 %   % Create an ellipse shape with major axis of length 1 m and the 
 %   % minor axis of length 0.5 m. Compute the focal points.
 %
 %   e = shape.Ellipse;
 %   e.Foci
 %
 %   See also shape.Rectangle, shape.Polygon, shape.Circle
    
 %   Copyright 2019-2023 The MathWorks, Inc.
    
    properties
        % Name of the ellipse shape specified as a character array
        Name
        % Cartesian coordinates of the center of the ellipse specified
        % as a 2-element vector (meter).
        Center
        % Longest diameter of the ellipse (meters)
        MajorAxis
        MinorAxis
        % Shortest diameter of the ellipse (meters)
        % Number of discretization points on the circumference
        NumPoints        
    end


    properties(Dependent,SetAccess=protected,GetAccess = public)
        % Focal points of the ellipse
        Foci
    end
    
    
    methods
        function obj = Ellipse(varargin)
            parserObj = inputParser;
            addParameter(parserObj,'Name','myEllipse');
            addParameter(parserObj,'Center',[0,0]);
            addParameter(parserObj,'MajorAxis',1);
            addParameter(parserObj,'MinorAxis',0.5);
            addParameter(parserObj,'NumPoints',30);  
            addParameter(parserObj,'Metal','PEC');
            addParameter(parserObj,'Color','y');
            addParameter(parserObj,'Transparency',1);
            addParameter(parserObj,'EdgeColor','k');
            parse(parserObj,varargin{:});
            p = [0.5 0  0;...
                0.2500 0.2165   0;...
                -0.2500  0.2165  0;...
                -0.5000 0  0;...
                -0.2500 -0.2165  0;...
                0.2500  -0.2165 0]';
            
            obj             = obj@shape.Shape2D(p');
            obj.Name        = parserObj.Results.Name;
            obj.Center      = parserObj.Results.Center;
            obj.MajorAxis      = parserObj.Results.MajorAxis;
            obj.MinorAxis      = parserObj.Results.MinorAxis;
            obj.NumPoints   = parserObj.Results.NumPoints;  
            obj.Metal = parserObj.Results.Metal;
            obj.Color = parserObj.Results.Color;
            obj.Transparency = parserObj.Results.Transparency;
            obj.EdgeColor = parserObj.Results.EdgeColor;
        end
        
    end
    
    methods
        function set.Name(obj,propVal)
            validateattributes(propVal,{'char','string'},{'nonempty',     ...
                },class(obj),'Name') ;
            if isPropertyChanged(obj,obj.Name,propVal)
                obj.Name = propVal;
            end
        end
        
        function set.MajorAxis(obj,propVal)
            validateattributes(propVal,{'double'},{'nonempty','scalar',...
                'nonnan','finite','real','positive'},class(obj),'MajorAxis') ;
            if isPropertyChanged(obj,obj.MajorAxis,propVal)
                obj.MajorAxis = propVal;
            end
        end

        function set.MinorAxis(obj,propVal)
            validateattributes(propVal,{'double'},{'nonempty','scalar',...
                'nonnan','finite','real','positive'},class(obj),'MinorAxis') ;
            if isPropertyChanged(obj,obj.MinorAxis,propVal)
                obj.MinorAxis = propVal;
            end
        end
        
        function set.Center(obj,propVal)
            validateattributes(propVal,{'numeric'},{'nonempty',...
                'nonnan','finite', 'real','numel',2},class(obj),'Center');            
            if isPropertyChanged(obj,obj.Center,propVal)                
                if iscolumn(propVal)
                    obj.Center= propVal';
                else
                   obj.Center = propVal;
                end
            end
        end
        
        function propVal = get.Center(obj)
            propVal = obj.Center;
        end
       
        
        function set.NumPoints(obj,propVal)
            validateattributes(propVal,{'numeric'},{'nonempty','scalar',...
                'nonnan','finite','real','integer','positive','>=',20},class(obj),'NumPoints');
            if isPropertyChanged(obj,obj.NumPoints,propVal)
                obj.NumPoints = propVal;
            end
        end
        
        function propVal = get.Foci(obj)
            validateattributes(obj.MinorAxis,{'numeric'},{'scalar','<', ... 
                obj.MajorAxis},'Ellipse','MinorAxis')            
            foci = sqrt((obj.MajorAxis/2)^2-(obj.MinorAxis/2)^2);
            Focii = [-foci 0 0; foci 0 0];
            propVal    =em.internal.translateshape(Focii',[obj.Center 0])';           
        end
    end
    
    methods(Hidden)
        function createGeometry(obj)
          
            p = obj.generateEllipsePoints(obj.Center,obj.MajorAxis,   ...
                obj.MinorAxis,obj.NumPoints); 
            [~]=em.internal.authoring.getMultiplier(obj,[obj.MajorAxis,obj.MinorAxis,obj.Center],1);
            p = orientGeom(obj,p);
            updateShape(obj,p')
            obj.MesherStruct.Geometry.BorderVertices = p';
            resetHasStructureChanged(obj);
            
        end
        
        function rObj = superLoad(obj,s)
            if nargin>1
                obj.Name            = s.Name;
                obj.Center          = s.Center;
                obj.MajorAxis       = s.MajorAxis;
                obj.MinorAxis       = s.MinorAxis;
                obj.NumPoints       = s.NumPoints;
                rObj = superLoadShape(obj,s);
            end
        end
    end
    
    methods(Static=true, Access = private)
        
        function pt = generateEllipsePoints(c,MajorAxis,MinorAxis,n)
            
            nameOfFunction = 'generateEllipsePoints';
            validateattributes(c,{'numeric'},{'nonempty',    ...
                'nonnan','finite','real','numel',2},   ...
                nameOfFunction,'Center');            

            validateattributes(MajorAxis,{'numeric'},{'nonempty','scalar',   ...
                'nonnan','finite','real','positive'},   ...
                nameOfFunction,'MajorAxis');
            
            validateattributes(MinorAxis,{'numeric'},{'nonempty','scalar',      ...
                'nonnan','finite','real','positive','<',MajorAxis},   ...
                nameOfFunction,'MinorAxis');
            
            validateattributes(n,{'numeric'},{'nonempty','scalar',      ...
                'nonnan','finite','real','integer','positive',...
                '>=',6},   ...
                nameOfFunction,'NumPoints');
            
            del_phi     = 360/n;
            phi_start   = 0;
            phi_end     = 360 - del_phi;
            phi         = linspace(phi_start,phi_end,n);
            
            x = (MajorAxis/2).*cosd(phi);
            y = (MinorAxis/2).*sind(phi);
            z = zeros(size(x));
            
            p = [x;y;z];
            
            pt(1,:)     = p(1,:) + c(1);
            pt(2,:)     = p(2,:) + c(2);
            pt(3,:)     = p(3,:);
        end
    end
    
    methods(Access=protected)
        function group = getPropertyGroups(obj)      %#ok<MANU>
            title = '';
            propertyList = {'Name'; 'Center'; 'MajorAxis';'MinorAxis';...
                'NumPoints';
                 'Metal';...
               'Color';'Transparency';'EdgeColor'};
            group = matlab.mixin.util.PropertyGroup(propertyList,title);
        end 
        function updateShapeDimension(obj, scalingFactor)
            tmpValue = [obj.MajorAxis obj.MinorAxis].*scalingFactor;
            obj.MajorAxis = tmpValue(1);
            obj.MinorAxis = tmpValue(2);
        end
    end
    
    methods (Static = true,Hidden) % ----LOADOBJ only IMPLEMENTATION ---%
        function r = loadobj(obj)
            if isobject(obj)&& isObjectFromCurrentVersion(obj)
                r = obj;
            else
                % Create default microstrip patch
                newEllipse = shape.Ellipse;
                % Populate the properties
                r = superLoad(newEllipse,obj);
            end
            r = loadobj@shape.Shape2D(r);
        end
    end
    
end
