function V = pdeviz(varargin)
%PDEVIZ Create and plot PDEVisualization object containing nodal data, mesh
%, and visualization options as its properties 
% 
%  PDEVIZ(MeshData,NodalData) creates a PDEVisualization object and plots 
%  data at mesh nodes as a surface plot.
% 
%  PDEVIZ(MeshData) plots the mesh.
% 
%  PDEVIZ(___ ,Name,Value) plots the mesh, the data at nodal locations, or
%  both the mesh and data, depending on the Name,Value pair arguments. Use 
%  any arguments from the previous syntaxes.
% 
%  PDEVIZ(figure, ___) specifies the graphics container for the 
%  PDEVisualization object. For example, you can plot the object in Figure 
%  3 by specifying PDEVIZ(figure(3), ___).
% 
%  V = PDEVIZ(___ ) returns a handle to the PDEVisualization object, using 
%  any of the previous syntaxes.
% 
% The name-value arguments enable you to specify visualization options, such as:
% 
%   Name                    Value/{Default}       Description
%   -----------------------------------------------------------------------
%   Transparency            number in [0,1] {1}   Controls the transparency
%                                                 of the surface. 0 is
%                                                 fully transparent, and 1
%                                                 is fully opaque.
%   MeshVisible             {off} | on            Controls mesh visibility.
%   DeformationData         data                  Changes the position of
%                                                 the mesh nodes according 
%                                                 to the data provided.
%   DeformationScaleFactor  nonnegative number    Scaling factor for 
%                                                 plotting the deformed 
%                                                 shape and used together 
%                                                 with DeformationData. The 
%                                                 default value is computed
%                                                 automatically based on 
%                                                 the mesh and 
%                                                 DeformationData.
%
% For the complete list of available name-value arguments, see documentation for <a
% href="matlab:doc pdeviz">pdeviz</a>.

%   Copyright 2020-2022 The MathWorks, Inc.

narginchk(1,Inf);

args = varargin;
positionalArgs = {};


% Check for parent
if numel(args) >= 1 && isa(args{1},'matlab.graphics.Graphics')
    positionalArgs = {'Parent', args{1}};
    args(1) = [];
end

% Check for mesh data
if numel(args) >= 1 && isa(args{1},'pde.FEMesh')
    positionalArgs = [positionalArgs, {'MeshData', args{1}}];
    args(1) = [];
else
    error(message('pde:pdeviz:nomesh'));
end

% Check for (optional) nodal data
if numel(args) >= 1 && isnumeric(args{1})
    positionalArgs = [positionalArgs, {'NodalData', args{1}}];
    args(1) = [];
else
    % If no nodal data present, turn on mesh by default
    positionalArgs = [positionalArgs, {'MeshVisible', 'on'}];
end

args = [positionalArgs, args];

% build the internal DataStorage to validate all properties before calling
% PDEVisualization
try
    DS = pde.graphics.PDEVisualization.verifyOptions(args{:});
catch ME
    throwAsCaller(ME);
end

% Verify PDEVisualization specific errors
% Verify Mesh and Nodal Data match size
if ~isempty(DS.NodalData)
    if (~pde.graphics.PDEVisualization.verifyMeshAndNodalDataMatch(DS.MeshData,DS.NodalData))
        error(message('pde:pdeviz:incompatibleNodalData'));
    end
end

% Verify Mesh and Deformation Data match size
if ~isempty(DS.DeformationData)
    if (~pde.graphics.PDEVisualization.verifyMeshAndDeformationDataNodalMatch(DS.MeshData,DS.DeformationData))
        error(message('pde:pdeviz:incompatibleDeformationData'));
    end
    
    if (~pde.graphics.PDEVisualization.verifyMeshAndDeformationDataDimensionMatch(DS.MeshData,DS.DeformationData))
        error(message('pde:pdeviz:incompatibleDeformationDataDimensionality',size(DS.MeshData.Nodes,1)));
    end
end
    
% If all previous calls succeded can create chart without errors
V = pde.graphics.PDEVisualization(args{:});
