classdef OpenBox < shape.Shape3D
%SHAPE.OPENBOX Creates a box on the X-Y-Z plane
% 
%   h = shape.Box returns a box shape centered at the origin
%   in 3D space.
%
%   h = shape.Box('Property1', value1,'Property2', value2,...)
%   returns a box shape, based on the specified properties.
%   Properties you do not specify retain their default values.
%
%   OpenBox properties:
%
%   Name        - Name of the open box shape
%   Center      - Cartesian coordinates of the center of the open box in
%                 meters specified as a 3-element vector. The default value
%                 is [0 0 0].
%   Length      - Length of the open  box shape in meters. The default value is 1.
%   Width       - Width of the open box shape in meters. The default value is 2.
%   Height      - Height of the open box shape in meters. The default value is 2.
%   Metal       - Metal assigned for the shape. The default object is
%                 'PEC' with infinite conductivity and zero
%                 thickness.
%   Dielectric  - Dielectric assigned for the shape. The default object is
%                 'Air'.
%   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'.
%
%   OpenBox 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
%   show        - Visualize the shape as a filled patch
%   mesh        - Compute/visualize the mesh of the shape
%   rotate      - Rotate the shape about an axis and an angle
%   rotateX     - Rotate the shape about the X-axis with an angle
%   rotateY     - Rotate the shape about the Y-axis with an angle
%   rotateZ     - Rotate the shape about the Z-axis with an angle
%   translate   - Translate 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
%   removeFaces  - Remove the selected faces of shape interactively
%   addSubstrate - Add Substrate to the custom shape
%
%   % Examples
%
%   % Example 1: 
%   % Create a open box shape, rotate it by 45 degrees about
%   % the z-axis and visualize it.
%   
%   r = shape.OpenBox;
%   r = rotateZ(r,45);
%   show(r);
%
%   % Example 2: 
%   % Create a 2 cm x 2 cm x 2cm box shape,and mesh it with a maximum
%   % edge length of 5 mm
%
%   r = shape.OpenBox(Length = .02,Width = .02,Height = 0.02);
%   mesh(r,MaxEdgeLength = 5e-3)
%
%   See also shape.Box, shape.Cylinder

%   Copyright 2022-2023 The MathWorks, Inc.


    properties
        % Name of the rectangle shape specified as a character array
        Name
        % Cartesian coordinates of the center of the rectangle specified
        % as a 2-element vector (meter).
        Center
        % Length of the rectangle (meter).
        Length
        % Width of the rectangle (meter).
        Width
        % Height of the OpenBox (meter).
        Height
    end

    properties(Hidden)
        PointDistribution
    end

    methods
        function obj = OpenBox(varargin)
            parserObj = inputParser;
            addParameter(parserObj,'Name','myOpenBox');
            addParameter(parserObj,'Length',1);
            addParameter(parserObj,'Width',2);
            addParameter(parserObj,'Center',[0,0,0]);
            addParameter(parserObj,'Height',2);
            % addParameter(parserObj,'Material',shape.Material);
            addParameter(parserObj,'Metal','PEC');
            addParameter(parserObj,'Dielectric','Air');
            addParameter(parserObj,'Color','y');
            addParameter(parserObj,'Transparency',1);
            addParameter(parserObj,'EdgeColor','k');
            parse(parserObj,varargin{:});
            obj = obj@shape.Shape3D();
            obj.Name      = parserObj.Results.Name;
            obj.Length    = parserObj.Results.Length;
            obj.Width     = parserObj.Results.Width;
            obj.Center    = parserObj.Results.Center;
            obj.Height = parserObj.Results.Height;
            % obj.Material = parserObj.Results.Material;
            obj.Metal = parserObj.Results.Metal;
            obj.Dielectric = parserObj.Results.Dielectric;
            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.Length(obj,propVal)
            validateattributes(propVal,{'double'},{'nonempty','scalar', 'real',     ...
                'nonnan','finite','positive'},class(obj),'Length') ;
            if isPropertyChanged(obj,obj.Length,propVal)
                obj.Length = propVal;
            end
        end

        function set.Width(obj,propVal)
            validateattributes(propVal,{'double'},{'nonempty','scalar', 'real',     ...
                'nonnan','finite','positive'},class(obj),'Width') ;
            if isPropertyChanged(obj,obj.Width,propVal)
                obj.Width = propVal;
            end
        end

        function set.Center(obj,propVal)
            validateattributes(propVal,{'double'},{'nonempty', 'real',     ...
                'nonnan','finite','numel',3},class(obj),'Center');
            if isPropertyChanged(obj,obj.Center,propVal)
                if ~isrow(propVal)
                    propVal = propVal';
                end
                obj.Center = propVal;
            end
        end

        function set.Height(obj,propVal)
            validateattributes(propVal,{'numeric'},{'nonempty',...
                'scalar','real','nonnan', 'finite','positive'},class(obj),'Height');
            if isPropertyChanged(obj,obj.Height,propVal)
                obj.Height = propVal;
            end
        end

    end

    methods(Hidden)
        function createGeometry(obj,varargin)
            if ~isrow(obj.Center)
                obj.Center = obj.Center';
            end
           % Create a open box by using the closed box
            box = shape.Box('Length',obj.Length,'Width',obj.Width,'Height',obj.Height,'Center',obj.Center);
            box = deleteFaces(box,1);
            p = box.Points;
            % Orient the geometry
            p=orientGeom(obj,p');
            obj.Points=p';
            [~]=em.internal.authoring.getMultiplier(obj,[obj.Length,obj.Width,obj.Height,obj.Center],1);
            obj.Triangles=box.Triangles;
            % Generate the triangulation
            trnorm=triangulation(obj.Triangles(:,1:3),obj.Points);
            if ~isempty(obj.Thickness)
                trnorm=em.internal.authoring.thicken(trnorm,obj.Thickness);
                obj.Points=trnorm.Points;obj.Triangles=trnorm.ConnectivityList;
            end
            % Boundary Edges
            be=featureEdges(trnorm,pi/2);
            obj.MesherStruct.Geometry.BorderVertices = obj.Points;
            geom = getGeometry(obj);
            % Save geometry
            saveGeometry(obj,geom.BorderVertices,geom.polygons, ...
                geom.MaxFeatureSize,...
                be);
            resetHasStructureChanged(obj);
        end

        function rObj = superLoad(obj,s)
            if nargin>1
                obj.Name            = s.Name;
                obj.Length          = s.Length;
                obj.Width           = s.Width;
                obj.Center          = s.Center;
                obj.Height       = s.Height;
                rObj = superLoadShape(obj,s);
            end
        end
    end

    methods(Access=protected)
        function group = getPropertyGroups(obj) %#ok<MANU>
            title = '';
            propertyList = {'Name'; 'Center'; 'Length';'Width';'Height';...
                                 'Metal';'Dielectric';...
                           'Color';'Transparency';'EdgeColor'};
            group = matlab.mixin.util.PropertyGroup(propertyList,title);
        end
        function updateShapeDimension(obj, scalingFactor)
            tmpValue = [obj.Length obj.Width obj.Height].*scalingFactor;
            obj.Length = tmpValue(1);
            obj.Width = tmpValue(2);
                       obj.Height = tmpValue(3);

        end
        function tri= getmeshforshape(~,p)
            % Get the mesh for given points
            sv1=p;
            % If all x-points are equal
            if all(sv1(:,1)==sv1(1,1))
                psh=polyshape(sv1(:,2:3),'Simplify',false);
                tr1i=triangulation(psh);
                tri=triangulation(tr1i.ConnectivityList,[sv1(:,1) tr1i.Points(:,1) tr1i.Points(:,2)]);
                % If all y-points are equal
            elseif all(sv1(:,2)==sv1(1,2))
                psh=polyshape([sv1(:,1) sv1(:,3)] ,'Simplify',false);
                tr1i=triangulation(psh);
                tri=triangulation(tr1i.ConnectivityList,[ tr1i.Points(:,1) sv1(:,2) tr1i.Points(:,2)]);
                % If all z-points are equal
            elseif all(sv1(:,3)==sv1(1,3))
                psh=polyshape(sv1(:,1:2),'Simplify',false);
                tr1i=triangulation(psh);
                tri=triangulation(tr1i.ConnectivityList,[ tr1i.Points(:,1)  tr1i.Points(:,2) sv1(:,3)]);
            end
        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
                newrectangle = shape.OpenBox;
                % Populate the properties
                r = superLoad(newrectangle,obj);
            end
            r = loadobj@shape.Shape3D(r);
        end
    end
end
