function varargout = Dipole2(varargin)
    % DIPOLE M-file for Dipole2.fig
    %      DIPOLE2, by itself, creates a new DIPOLE or raises the existing
    %      singleton*.
    %
    %      H = DIPOLE2 returns the handle to a new DIPOLE2 or the handle to
    %      the existing singleton*.
    %
    %      DIPOLE2('CALLBACK',hObject,eventData,handles,...) calls the local
    %      function named CALLBACK in DIPOLE2.M with the given input arguments.
    %
    %      DIPOLE2('Property','Value',...) creates a new DIPOLE or raises the
    %      existing singleton*.  Starting from the left, property value pairs are
    %      applied to the GUI before Dipole_OpeningFcn gets called.  An
    %      unrecognized property name or invalid value makes property application
    %      stop.  All inputs are passed to Dipole_OpeningFcn via varargin.
    %
    %      *See GUI Options on GUIDE's Tools menu.  Choose "GUI allows only one
    %      instance to run (singleton)".
    %
    % See also: GUIDE, GUIDATA, GUIHANDLES

    % Edit the above text to modify the response to help Dipole

    % Last Modified by GUIDE v2.5 02-Jan-2011 23:03:18

    % Begin initialization code - DO NOT EDIT
    gui_Singleton = 1;
    gui_State = struct('gui_Name',       mfilename, ...
                       'gui_Singleton',  gui_Singleton, ...
                       'gui_OpeningFcn', @Dipole_OpeningFcn, ...
                       'gui_OutputFcn',  @Dipole_OutputFcn, ...
                       'gui_LayoutFcn',  [] , ...
                       'gui_Callback',   []);
    if nargin && ischar(varargin{1})
        gui_State.gui_Callback = str2func(varargin{1});
    end

    if nargout
        [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
    else
        gui_mainfcn(gui_State, varargin{:});
    end
    % End initialization code - DO NOT EDIT
end

% --- Executes just before Dipole is made visible.
function Dipole_OpeningFcn(hObject, eventdata, handles, varargin)
    % This function has no output args, see OutputFcn.
    % hObject    handle to figure
    % eventdata  reserved - to be defined in a future version of MATLAB
    % handles    structure with handles and user data (see GUIDATA)
    % varargin   command line arguments to Dipole (see VARARGIN)

    % Choose default command line output for Dipole
    handles.output = hObject;

    global lim pospt negpt k liney q;
    global flag;

    flag=1;
    liney=0.0;
    lim=2.0;                                  %making simulation scale independent
    handles.flag=1;
    sizeXY=200;                              %number of points to plot

    x=linspace(-lim,lim,sizeXY);             %X-axis
    y=linspace(-lim,lim,sizeXY);             %Y-axis

    chargeDrawData.x=zeros(1,11);           %11 boundary points of circle defined to represent charges
    chargeDrawData.y=zeros(1,11);
    theta=linspace(0,2*pi,11);              %11 angular divisions to calculate 11 boundary points of circle
    chargeDrawData.x=lim*0.03*cos(theta);   %x-coordinates of 11 boundary points and
    chargeDrawData.y=lim*0.03*sin(theta);   %y-coordinates of 11 boundary points calculated and
                                            %saved in a structure, 'chargeDrawData'.
    pospt.x=-lim*0.12;                       %making the simulation, scale independent so that
    pospt.y=-lim*0.12;                       %the visible size of charges remains the same
    negpt.x= lim*0.12;
    negpt.y=-lim*0.12;

    q=1000*1.602e-19;                       %1000 electrons form a single charge
    epsilon0=8.8541878e-12;                 %permittivity of free space
    k=1/(4*pi*epsilon0);                    %constant used in program

    drawModelDipole(x,y,chargeDrawData,handles);   %the functions draws model of dipole with mouse interactivity
    plotDipole(x,handles);                  %Plots graph
    axes(handles.axesDipoleModel);          %model axis as current axis
    text(lim+lim*1.28,-lim-lim*0.15,'\leftarrow Distance \rightarrow',...
                    'FontSize',12,'Fontweight','bold','Color',[0.2 0.2 0.6]);   %for right graph
    text(-lim+0.725*lim,-lim-lim*0.15,'\leftarrow Distance \rightarrow',...     %for left model
                    'FontSize',12,'Fontweight','bold','Color',[0.2 0.2 0.6]);
    %set(handles.radioHorizontal,'Value',1);
    % Update handles structure
    guidata(hObject, handles);
    % UIWAIT makes Dipole wait for user response (see UIRESUME)
    % uiwait(handles.figureDipole);
end

% --- Outputs from this function are returned to the command line.
function varargout = Dipole_OutputFcn(hObject, eventdata, handles)
    % varargout  cell array for returning output args (see VARARGOUT);
    % hObject    handle to figure
    % eventdata  reserved - to be defined in a future version of MATLAB
    % handles    structure with handles and user data (see GUIDATA)

    % Get default command line output from handles structure
    varargout{1} = handles.output;
end

% Calculates magnitude of Electric Field
function E=calculateE(x)
    global k q liney pospt negpt;

    y=zeros(1,length(x));       %initial y-values are zero. number of x and y values must be equal.
    y=liney;                    %for new y-value of horizontal line by moving line up and down
                                %distance is measured from charges to horizontal line
    rp_x=x-pospt.x;             %x-component of distance of +ve charge  from a point on the horizontal line
    rp_y=y-pospt.y;             %y-component of +ve charge is constant for horizontal line
    rn_x=negpt.x-x;             %x-component of distance of -ve charge from a point on the horizontal line
    rn_y=negpt.y-y;             %y-component of distance of -ve charge from a point on the horizontal line

    rp_sqrd=rp_x.^2+rp_y.^2;    %square of distance of +ve charge
    rn_sqrd=rn_x.^2+rn_y.^2;    %square of distance of -ve charge

    rp=sqrt(rp_sqrd);           %magnitude of distance of +ve charge
    rn=sqrt(rn_sqrd);           %magnitude of distance of -ve charge

    Ep_mag=k*q./rp_sqrd;        %magnitude of Electric Field due to +ve charge on horizontal line
    En_mag=k*q./rn_sqrd;        %magnitude of Electric Field due to -ve charge on horizontal line

    rp_unitV_x=rp_x./rp;        %x-component of unit vector along +ve charge Electric Field
    rp_unitV_y=rp_y./rp;        %y-component of unit vector along +ve charge Electric Field

    rn_unitV_x=rn_x./rn;        %x-component of unit vector along -ve charge Electric Field
    rn_unitV_y=rn_y./rn;        %y-component of unit vector along -ve charge Electric Field

    Ep_Vx=Ep_mag.*rp_unitV_x;   %x-component of Electric Field due to +ve charge
    Ep_Vy=Ep_mag.*rp_unitV_y;   %y-component of Electric Field due to +ve charge

    En_Vx=En_mag.*rn_unitV_x;   %x-component of Electric Field due to -ve charge
    En_Vy=En_mag.*rn_unitV_y;   %y-component of Electric Field due to -ve charge

    Ex=Ep_Vx+En_Vx;             %x-component of resultant Electric Field due to +ve charge
    Ey=Ep_Vy+En_Vy;             %y-component of resultant Electric Field due to +ve charge
    E=sqrt(Ex.^2+Ey.^2);        %magnitude of resultant Electric Field
end

% --- Executes during object creation, after setting all properties.
function axesDipoleModel_CreateFcn(hObject, eventdata, handles)
    % hObject    handle to axesDipoleModel (see GCBO)
    % eventdata  reserved - to be defined in a future version of MATLAB
    % handles    empty - handles not created until after all CreateFcns called

    % Hint: place code in OpeningFcn to populate axesDipoleModel
end

% --- Executes during object creation, after setting all properties.
function axesEX_CreateFcn(hObject, eventdata, handles)
    % hObject    handle to axesEX (see GCBO)
    % eventdata  reserved - to be defined in a future version of MATLAB
    % handles    empty - handles not created until after all CreateFcns
    % called

    % Hint: place code in OpeningFcn to populate axesEX
end

function drawModelDipole(x,y,chargeDrawData,handles)
    % -------------------------------------------------------------------------
    % The function draws a blue horizontal line, a red vertical line and two
    % charges and deals with mouse events.
    %
    %   The sequence of mouse events:
    %   a)  for line's vertical movement
    %       1)  'ButtonDownFcn' event of Matlab is activated on horizontal line. This event calls
    %       2)  our event-handler, 'startLineDraggingFcn'.This event-handler sets
    %       3)  Matlab 'WindowButtonMotionFcn' event which keeps calling our event-handler,
    %           'lineDraggingFcn' as long as we do not release the mouse button.
    %       4)  Matlab event, 'WindowButtonUpFcn' is set to our event-handler,'stopDraggingFcn' which
    %           in turn sets 'WindowButtonMotionFcn' event to NULL handler.
    %           Dragging stops.
    %   b)  for +ve (red) and -ve (green) charges' movement:
    %       The above sequences in (a) are separately coded for charges' movement and
    %       are similar to that given in (a).
    %   c)  Matlab's "WindowButtonUpFcn" and "WindowButtonMotionFcn"  are
    %       set for 'figure'  not for axes.
    % -------------------------------------------------------------------------

    global pospt;   %positive charge position structure containing x and y
    global negpt;   %negative charge position structure containing x and y
    global liney;   %horizontal line movement, y coordinate
    global flag;    %the 3 choices horizontal, opposite and independent to move charges with mouse

    axes(handles.axesDipoleModel);      %dipole model axis as current axis
    grid on;
    axis([x(1) x(end) y(1) y(end)]);
    hold on;

    hline=line('XData',[x(1) x(end)],'YData',[0 0],'LineWidth',4,...
        'Color',[0,0,0.7],'ButtonDownFcn',@setLineDraggingFcn);  %horizontal line in blue sets
    line([0 0],[y(1) y(end)],'Color',[0.8,0.1,0.3],'LineWidth',2); %vertical line in red
    hchargep=fill(chargeDrawData.x+pospt.x,chargeDrawData.y+pospt.y,[0.8,0.0,0],...
    'ButtonDownFcn',@setpChargeDraggingFcn);
    hchargen=fill(chargeDrawData.x+negpt.x,chargeDrawData.y+negpt.y,[0.0,0.85,0.0],...
            'ButtonDownFcn',@setnChargeDraggingFcn);
    set(gcf,'WindowButtonUpFcn',@stopDraggingFcn);

    %----------------- for line movement --------------------------------
    function setLineDraggingFcn(src,evnt)
        set(gcf,'WindowButtonMotionFcn',@lineDraggingFcn);
    end

    function lineDraggingFcn(src,evnt)
        %line is dragged vertically
        curpt=get(handles.axesDipoleModel,'CurrentPoint'); %gets current point when line is dragged
        set(hline,'YData',[curpt(3) curpt(3)]);     %line's vertical movement
        liney=curpt(3);                             %constant y value from charges to horizontal line updated
        plotDipole(x,handles);                      %graph is updated

    end

    %-------------------- for charges movement --------------------------
    function setpChargeDraggingFcn(src,evnt)
        set(gcf,'WindowButtonMotionFcn',@pchargeDraggingFcn);
    end

    function pchargeDraggingFcn(src,evnt)
        % +ve charge (red) is dragged.
        curpt=get(handles.axesDipoleModel,'CurrentPoint');  %gets current point when charge is dragged
        switch flag
            case 1              %horizontal opposite movement of charges, +ve(red) charge cabbe dragged only
                set(hchargep,'XData',chargeDrawData.x+curpt(2));%new 11 points of +ve charge are set and charge is drawn
                set(hchargen,'XData',chargeDrawData.x-curpt(2));
                pospt.x=curpt(2);       % y is constant for horizontal movement of charges
                negpt.x=-curpt(2);
            case 2              %opposite movement of charges, +ve(red) charge cabbe dragged only
                set(hchargep,'XData',chargeDrawData.x+curpt(2),...
                'YData',chargeDrawData.y+curpt(3));
                set(hchargen,'XData',chargeDrawData.x-curpt(2),...
                'YData',chargeDrawData.y-curpt(3));
                pospt.x=curpt(2);       % positive(red) charge can olny be dragged by user
                pospt.y=curpt(3);       % position of negative(green) changes in opposite direction
                negpt.x=-curpt(2);
                negpt.y=-curpt(3);
            case 3              %both charges can be dragged  independently
                set(hchargep,'XData',chargeDrawData.x+curpt(2),...
                    'YData',chargeDrawData.y+curpt(3));
                pospt.x=curpt(2);       %new position of positive charge
                pospt.y=curpt(3);
        end
        plotDipole(x,handles);
    end

     %-------------------- for charges movement --------------------------
    function setnChargeDraggingFcn(src,evnt)
        set(gcf,'WindowButtonMotionFcn',@nchargeDraggingFcn);
    end

    function nchargeDraggingFcn(src,evnt)
        % -ve charge (green) is dragged.
        if flag==3
            curpt=get(handles.axesDipoleModel,'CurrentPoint');  %gets current point when charge is dragged
            set(hchargen,'XData',chargeDrawData.x+curpt(2),...
                'YData',chargeDrawData.y+curpt(3));     %new 11 points of -ve charge are set and charge is drawn
            negpt.x=curpt(2);                           %new position of -ve charge
            negpt.y=curpt(3);
            plotDipole(x,handles);
        end
    end
    % ------------------ End of mouse dragging events-----------------------------
    function stopDraggingFcn(src,evnt)
        set(gcf,'WindowButtonMotionFcn',' ');
    end
end

%The function plots graph between magnitude of E (Electric Field) and
%distance
function plotDipole(x,handles)
    axes(handles.axesEX);               %sets axesEX as current axes for plotting |E| vs Distance
    E=calculateE(x);                    %calculates |E| for all x-values and returns row matrix
    plot(handles.axesEX,x,E,'color',[0.8,0,0],'LineWidth',2.5);
    ylabel('Magnitude of Electric Field \rightarrow',...
        'FontSize',12,'Fontweight','bold','color',[0.2,0.2,0.6]);
    grid on;
end

function editElectrons_Callback(hObject, eventdata, handles)
    % hObject    handle to editElectrons (see GCBO)
    % eventdata  reserved - to be defined in a future version of MATLAB
    % handles    structure with handles and user data (see GUIDATA)

    % Hints: get(hObject,'String') returns contents of editElectrons as text
    %        str2double(get(hObject,'String')) returns contents of editElectrons as a double
    global q;
    n=str2double(get(hObject,'String'));  %reads number of electrons from edit control
    q=n*1.602e-19;                                      %total charge
end

% --- Executes during object creation, after setting all properties.
function editElectrons_CreateFcn(hObject, eventdata, handles)
    % hObject    handle to editElectrons (see GCBO)
    % eventdata  reserved - to be defined in a future version of MATLAB
    % handles    empty - handles not created until after all CreateFcns called

    % Hint: edit controls usually have a white background on Windows.
    %       See ISPC and COMPUTER.
    if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
        set(hObject,'BackgroundColor','white');
    end
end

% --- Executes when selected object is changed in uipanel2.
function uipanel2_SelectionChangeFcn(hObject, eventdata, handles)
    % hObject    handle to the selected object in uipanel2
    % eventdata  structure with the following fields (see UIBUTTONGROUP)
    %	EventName: string 'SelectionChanged' (read only)
    %	OldValue: handle of the previously selected object or empty if none was selected
    %	NewValue: handle of the currently selected object
    % handles    structure with handles and user data (see GUIDATA)
    global flag;
    switch get(eventdata.NewValue,'Tag')
        case 'radioHorizontal'
            flag=1;
        case 'radioOpposite'
            flag=2;
        case 'radioIndependent'
            flag=3;
        otherwise
            flag=1;
    end
end