classdef App_AQUISICAO_IMAGEM_testes < matlab.apps.AppBase

    % Properties that correspond to app components
    properties (Access = public)
        UIFigure                        matlab.ui.Figure
        ExitButton                      matlab.ui.control.Button
        TabGroup                        matlab.ui.container.TabGroup
        IMAGEACQUISITIONTab             matlab.ui.container.Tab
        OBJECTDETECTIONPanel            matlab.ui.container.Panel
        ViewFullPointCloudButton        matlab.ui.control.Button
        SELECTROIFORCONTOURSPanel       matlab.ui.container.Panel
        DropDownSelectROIForContour     matlab.ui.control.DropDown
        Label                           matlab.ui.control.Label
        CONTOURSPanel                   matlab.ui.container.Panel
        ShowContoursButton              matlab.ui.control.Button
        StructuringElementRadiusSlider  matlab.ui.control.Slider
        StructuringElementRadiusSliderLabel  matlab.ui.control.Label
        UIAxesObjectContours            matlab.ui.control.UIAxes
        REGIONOFINTERESTPanel           matlab.ui.container.Panel
        SelectROIButton                 matlab.ui.control.Button
        SelectFullObjectButton          matlab.ui.control.Button
        TARGETAREAPanel                 matlab.ui.container.Panel
        GetTargetAreaButton             matlab.ui.control.Button
        ROICoordinatesLabel             matlab.ui.control.Label
        Image                           matlab.ui.control.Image
        ZLabel                          matlab.ui.control.Label
        YLabel                          matlab.ui.control.Label
        XLabel                          matlab.ui.control.Label
        EditField_Zmax                  matlab.ui.control.NumericEditField
        EditField_Zmin                  matlab.ui.control.NumericEditField
        EditField_Xmax                  matlab.ui.control.NumericEditField
        EditField_Ymax                  matlab.ui.control.NumericEditField
        EditField_Ymin                  matlab.ui.control.NumericEditField
        EditField_Xmin                  matlab.ui.control.NumericEditField
        GetFullPointCloudButton         matlab.ui.control.Button
        VIDEOSTREAMSPanel               matlab.ui.container.Panel
        DepthVideoStreamLabel           matlab.ui.control.Label
        RGBVideoStreamLabel             matlab.ui.control.Label
        StartStreamsButton              matlab.ui.control.Button
        UIAxesDEPTHStream               matlab.ui.control.UIAxes
        UIAxesRGBStream                 matlab.ui.control.UIAxes
        POINTCLOUDEDITORTab             matlab.ui.container.Tab
        EditorBrowserLabel              matlab.ui.control.Label
        POINTCLOUDEDITORPanel           matlab.ui.container.Panel
        SpinnerUncompress               matlab.ui.control.Spinner
        SpinnerDensity                  matlab.ui.control.Spinner
        RemovePointsButton              matlab.ui.control.Button
        ResetButton_Uncompress          matlab.ui.control.Button
        SelectUncompressAreaButton      matlab.ui.control.Button
        ResetPointsButton_Density       matlab.ui.control.Button
        SelectDensifyAreaButton         matlab.ui.control.Button
        CropCloudButton                 matlab.ui.control.Button
        SELECTROIFORPOINTCLOUDPROCESSINGPanel  matlab.ui.container.Panel
        PCDownsamplingSpinner           matlab.ui.control.Spinner
        PCDownsamplingSpinner_2Label    matlab.ui.control.Label
        GetPointCloudButton             matlab.ui.control.Button
        DropDownSelectROIForPCProcessing  matlab.ui.control.DropDown
        Label_3                         matlab.ui.control.Label
        UIAxesEditorBrowser             matlab.ui.control.UIAxes
        UIAxesPCDown                    matlab.ui.control.UIAxes
    end

    
    properties (Access = public)
        DEPTHDisp
        RGBDisp
        imgRGB
        RGBFrame
        DEPTHFrame
        ptCloudRot
        PointCloudBrowser
        ptcloudB
        PC_Object
        ptcloudB3
        ImgEdge
        ptGridAvgDownS
        xnuvem_down
        ynuvem_down
        znuvem_down
        CroppedPoints
        PC_PointsRemoved
        RemovedPoints
        PC_PointsDensity
        DensityPoints
        UncomPoints_aRemover
        RemovedPoints_aRemover
        DensityPoints_ARremover
        PC_PointsUncom
        UncomPoints
        ButtonCropCloud = 0;
        ButtonRemovePoints = 0;
        ButtonSelectDensity = 0;
        ButtonSelectUncompress = 0;
    end



    % Callbacks that handle component events
    methods (Access = private)

        % Code that executes after component creation
        function startupFcn(app)
            % FAZER RESET À CAMARA
            imaqreset

            app.ButtonCropCloud = 0;

            % DESATIVAR TODOS OS BOTÕES AO INICIAR A APP
            set(app.GetFullPointCloudButton,'Enable','off')
            set(app.EditField_Xmax,'Enable','off')
            set(app.EditField_Xmin,'Enable','off')
            set(app.EditField_Ymax,'Enable','off')
            set(app.EditField_Ymin,'Enable','off')
            set(app.EditField_Zmax,'Enable','off')
            set(app.EditField_Zmin,'Enable','off')
            set(app.GetTargetAreaButton,'Enable','off')
            set(app.SelectFullObjectButton,'Enable','off')
            set(app.ShowContoursButton,'Enable','off')
            set(app.SelectROIButton,'Enable','off')
            set(app.DropDownSelectROIForContour,'Enable','off')
            set(app.ViewFullPointCloudButton,'Enable','off')
        end

        % Button pushed function: StartStreamsButton
        function StartStreamsButtonPushed(app, event)
            %% FECHAR JANELA ABERTA
            close(figure(1))

            % ATIVAR O BOTAO PARA OBTER NUVEM COMPLETA, DEPOIS DO BOTÃO PARA OBTER AS STREAMS SER CLICKADO
            if app.StartStreamsButton.Enable
                set(app.GetFullPointCloudButton,'Enable','on')
            end

            % AVISAR O USER QUE É NECESSÁRIO ESPERAR PELA DEPTH CAM ESTABILIZAR PARA SE OBTER A NUVEM DE PONTOS
            if app.StartStreamsButton.Enable
                uialert(app.UIFigure,'Depth camera must be stabilised before proceeding to further steps.','Depth camera stabilization.','Icon','warning')
            end

            %% RGB
            % LIGAR CAMARA RGB
            app.RGBDisp = videoinput('kinect',1,'RGB_640x480');

            app.RGBFrame = flip(getsnapshot(app.RGBDisp),2);
            app.imgRGB = image(app.UIAxesRGBStream,zeros(size(app.RGBFrame),'uint8'));

            % MOSTRAR RGB STREAM
            axis(app.UIAxesRGBStream,'image');
            preview(app.RGBDisp,app.imgRGB);

            % RESOLUÇAO DA STREAM VIDEO RGB
            app.UIAxesRGBStream.XLim = [0,640];
            app.UIAxesRGBStream.YLim = [0,480];
            pbaspect(app.UIAxesRGBStream,[640,480,1]);

            %% DEPTH
            % LIGAR CAMARA DEPTH
            app.DEPTHDisp = videoinput('kinect',2,'Depth_640x480');

            app.DEPTHFrame = flip(getsnapshot(app.DEPTHDisp),2);
            imgDEPTH = image(app.UIAxesDEPTHStream,zeros(size(app.DEPTHFrame),'uint8'));

            % MOSTRAR DEPTH STREAM
            axis(app.UIAxesDEPTHStream)
            preview(app.DEPTHDisp,imgDEPTH)

            % RESOLUÇAO DA STREAM VIDEO DEPTH
            app.UIAxesDEPTHStream.XLim = [0,640];
            app.UIAxesDEPTHStream.YLim = [0,480];
            pbaspect(app.UIAxesDEPTHStream,[640,480,1]);
            colormap(app.UIAxesDEPTHStream,'jet')

        end

        % Button pushed function: GetFullPointCloudButton
        function GetFullPointCloudButtonPushed(app, event)
            % ATIVAR O BOTAO PARA OBTER NUVEM COMPLETA, DEPOIS DO BOTÃO PARA OBTER AS STREAMS SER CLICKADO
            if app.GetFullPointCloudButton.Enable
                set(app.GetTargetAreaButton,'Enable','on')
                set(app.EditField_Xmax,'Enable','on')
                set(app.EditField_Xmin,'Enable','on')
                set(app.EditField_Ymax,'Enable','on')
                set(app.EditField_Ymin,'Enable','on')
                set(app.EditField_Zmax,'Enable','on')
                set(app.EditField_Zmin,'Enable','on')
                set(app.ViewFullPointCloudButton,'Enable','on')
            end

            % MUDAR O NOME DO BOTAO DEPOIS DESTE SER CLICKADO
            if app.GetFullPointCloudButton.Enable
                app.GetFullPointCloudButton.Text = "Update Full Point Cloud";
            end

            %% FECHAR JANELA ABERTA
            close(gcf)

            %% NUVEM DE PONTOS COMPLETA
            % EXTRAIR A NUVEM DE PONTOS
            RGBFrame1 = getsnapshot(app.RGBDisp);
            DEPTHFrame1 = getsnapshot(app.DEPTHDisp);

            ptCloudOriginal = pcfromkinect(app.DEPTHDisp, DEPTHFrame1, RGBFrame1);

            %% RODAR A NUVEM DE PONTOS PARA FICAR PARALELA COM EIXO DOS XX
            %ANGULO DE ROTAÇAO
            theta = -0.04;

            % MATRIZ DE ROTAÇAO EM X
            Rx = [1 0 0; 0 cos(theta) -sin(theta); 0 sin(theta) cos(theta)];
            trans = [0, 0, 0];
            tform = rigid3d(Rx,trans);

            % NOVA NUVEM DE PONTOS RODADA
            app.ptCloudRot = pctransform(ptCloudOriginal,tform);

            % MOSTAR NUVEM DE PONTOS
            app.PointCloudBrowser = figure("Name",'Point Cloud Browser','NumberTitle','off');
            pcshow(app.ptCloudRot,"VerticalAxis","Y",VerticalAxisDir="Down");
            title('Full Point Cloud')
            xlabel('X(m)')
            ylabel('Y(m)')
            zlabel('Z(m)')
            whitebg(gcf,'white')
            set(gcf,'Color','w')

        end

        % Button pushed function: ViewFullPointCloudButton
        function ViewFullPointCloudButtonPushed(app, event)
            % MOSTAR NUVEM DE PONTOS
            figure("Name",'Point Cloud Browser','NumberTitle','off')
            pcshow(app.ptCloudRot,"VerticalAxis","Y",VerticalAxisDir="Down");
            title('Full Point Cloud')
            xlabel('X(m)')
            ylabel('Y(m)')
            zlabel('Z(m)')
            whitebg(gcf,'white')
            set(gcf,'Color','w')

        end

        % Button pushed function: GetTargetAreaButton
        function GetTargetAreaButtonPushed(app, event)
            % ATIVAR O BOTAO PARA OBTER NUVEM COMPLETA, DEPOIS DO BOTÃO PARA OBTER AS STREAMS SER CLICKADO
            if app.GetTargetAreaButton.Enable
                set(app.SelectFullObjectButton,'Enable','on')
            end

            % MUDAR O NOME DO BOTAO DEPOIS DESTE SER CLICKADO
            if app.GetTargetAreaButton.Enable
                app.GetTargetAreaButton.Text = "Update Target Area";
            end

            %% DEFINIR UMA ROI CUBICA PARA ASSUMIR A TARGET AREA
            % ESPECIFICAR O STEP SIZE
            stepSize = 100;

            % AMOSTRA A NUVEM DE PONTOS DE ENTRADA E ARMAZENA AS COORDENADAS DE PONTOS COMO UM OBJETO DE NUVEM DE PONTOS
            indices = 1:stepSize:app.ptCloudRot.Count;
            tempPtCloud = select(app.ptCloudRot,indices);

            % REMOVER OS PONTOS INVALIDOS DENTRO DA AMOSTRA ANTERIOR
            [tempPtCloud,validIndices] = removeInvalidPoints(tempPtCloud);

            % OBTER AS COORDENADAS DE LOCALIZAÇAO 3D DOS PONTOS DA NUVEM DE PONTOS
            worldPoints = tempPtCloud.Location;

            % CONVERTER E ENCONTRAR AS COORDENADAS DOS PONTOS 2D CORRESPONDENTES AOS PONTOS 3D DA NUVEM
            [Y,X] = ind2sub([size(app.ptCloudRot.Location,1),size(app.ptCloudRot.Location,2)],indices);
            imagePoints = [X(validIndices)' Y(validIndices)'];

            % ESTIMATIVA DA MATRIZ DE PROJEÇAO DA CAMARA A PARTIR DA IMAGEM E DAS COORDENADAS DOS PONTOS DE LOCALIZAÇAO 3D
            camMatrix = estimateCameraMatrix(imagePoints,worldPoints);

            % DEFINIR A ROI CUBICA PARA A TARGET AREA
            roi = [app.EditField_Xmin.Value app.EditField_Xmax.Value app.EditField_Ymin.Value app.EditField_Ymax.Value app.EditField_Zmin.Value app.EditField_Zmax.Value];

            % ENCONTRAR OS INDICES DOS PONTOS DA NUVEM QUE ESTAO DENTRO DA ROI CUBICA
            indices = findPointsInROI(app.ptCloudRot,roi,camMatrix);

            % SELECIONAR OS PONTOS DA NUVEM QUE SE ENCONTRAM DENTRO DA ROI
            app.ptcloudB = select(app.ptCloudRot,indices);

            % MOSTRAR A NUVEM DE PONTOS COM A TARGER AREA
            figure(app.PointCloudBrowser);
            pcshow(app.ptCloudRot,"VerticalAxis","Y",VerticalAxisDir="Down")
            hold on
            pcshow(app.ptcloudB.Location,'r',"VerticalAxis","Y",VerticalAxisDir="Down")
            title('Full Point Cloud with Target Area')
            xlabel('X(m)')
            ylabel('Y(m)')
            zlabel('Z(m)')
            whitebg(gcf,'white')
            set(gcf,'Color','w')

            % DEFINIÇÃO DOS PONTOS DOS VERTICES DO CUBO DA ROI
            p1 = [roi(1) roi(4) roi(6)]';
            p2 = [roi(1) roi(4) roi(5)]';
            p3 = [roi(2) roi(4) roi(5)]';
            p4 = [roi(2) roi(4) roi(6)]';
            p5 = [roi(1) roi(3) roi(6)]';
            p6 = [roi(1) roi(3) roi(5)]';
            p7 = [roi(2) roi(3) roi(5)]';
            p8 = [roi(2) roi(3) roi(6)]';

            % DEFINIR AS FACES DO CUBO ATRAVES DOS VERTICES ANTERIORES
            A1=[p1 p2 p3 p4;p4 p3 p7 p8;p7 p8 p5 p6;p7 p6 p2 p3;p6 p5 p1 p2;p8 p5 p1 p4];

            % CORES DAS FACES
            p=fill3(A1(1,:),A1(2,:),A1(3,:),'--w');
            p.FaceAlpha = 0.3;
            p=fill3(A1(4,:),A1(5,:),A1(6,:),'--w');
            p.FaceAlpha = 0.3;
            p=fill3(A1(7,:),A1(8,:),A1(9,:),'--w');
            p.FaceAlpha = 0.3;
            p=fill3(A1(10,:),A1(11,:),A1(12,:),'--w');
            p.FaceAlpha = 0.3;
            p=fill3(A1(13,:),A1(14,:),A1(15,:),'--w');
            p.FaceAlpha = 0.3;
            p=fill3(A1(16,:),A1(17,:),A1(18,:),'--w');
            p.FaceAlpha = 0.3;

            hold off

        end

        % Button pushed function: SelectFullObjectButton
        function SelectFullObjectButtonPushed(app, event)
            % ATIVAR O BOTAO PARA OBTER NUVEM COMPLETA, DEPOIS DO BOTÃO PARA OBTER AS STREAMS SER CLICKADO
            if app.SelectFullObjectButton.Enable
                set(app.ShowContoursButton,'Enable','on')
                set(app.SelectROIButton,'Enable','on')
                set(app.DropDownSelectROIForContour,'Enable','on')
            end

            %% FECHAR JANELA ABERTA
            close(figure(2))

            %% REMOVER O PLANO DO CHAO
            % DEFINIR A DISTANCIA MAXIMA PONTO-PLANO PARA A MONTAGEM DO PLANO
            maxDistance = 0.0005;     % (m)

            % DEFINIR O VETOR NORMAL AO PLANO A DEFINIR (NESTE CASO VETOR PREPENDICULAR AO PLANO Y)
            referenceVector = [0,1,0];

            % DETETAR O PLANO E EXTRAI-LO DA NUVEM DE PONTOS
            [~,~,outlierIndices] = pcfitplane(app.ptcloudB,maxDistance,referenceVector);
            remainPtCloud = select(app.ptcloudB,outlierIndices);

            % REMOVER O BARULHO DA NUVEM DE PONTOS (ELIMINAR "IMPUREZAS")
%           app.pclimpa = pcdenoise(remainPtCloud,"NumNeighbors",10);
            app.PC_Object = pcdenoise(remainPtCloud);

            % MOSTRAR A NUVEM DE PONTOS LIMPA E SEM O PLANO DO CHAO
            figure("Name",'Object Cloud Viewer','NumberTitle','off');
            pcshow(app.PC_Object,"VerticalAxis","Y",VerticalAxisDir="Down")
            title('Object Cloud Point')
            xlabel('X(m)')
            ylabel('Y(m)')
            zlabel('Z(m)')
            whitebg(gcf,'white')
            set(gcf,'Color','w')
        end

        % Button pushed function: SelectROIButton
        function SelectROIButtonPushed(app, event)
            % AVISAR O USER QUE É NECESSÁRIO FAZER DOUBLE CLICK PARA ESCOLHER A ROI
            if app.SelectROIButton.Enable
                uialert(app.UIFigure,'Draw a rectangle to mark the Region of Interest. Double click inside the rectangle to select the ROI.','Info','Icon','info')
            end

            % CONVERTER MATRIX FULL EM MATRIX DE 3xCOLUNAS COM AS COORDENADAS X Y E Z RESPECTIVAMENTE
            NovaMatrizNuvemTotal = [reshape(app.ptCloudRot.Location(:,:,1),[],1) reshape(app.ptCloudRot.Location(:,:,2),[],1) reshape(app.ptCloudRot.Location(:,:,3),[],1)];

            % COMPARAR MATRIZ FULL E MATRIX DA TARGET AREA E RETIRAR OS INDICES DOS PONTOS DO SEU INTERIOR
            [RowNova01,~] = find(NovaMatrizNuvemTotal(:,1)<app.EditField_Xmax.Value & NovaMatrizNuvemTotal(:,1)>app.EditField_Xmin.Value & NovaMatrizNuvemTotal(:,2)<app.EditField_Ymax.Value & NovaMatrizNuvemTotal(:,2)>app.EditField_Ymin.Value & NovaMatrizNuvemTotal(:,3)>app.EditField_Zmin.Value & NovaMatrizNuvemTotal(:,3)<app.EditField_Zmax.Value);

            % CONVERTER OS INDICES EM LINHA COLUNA DENTRO DA RESOLUÇAO DO FRAME
            [ROWNOVA1,COLNOVA1] = ind2sub([480 640],RowNova01);

            % ENCONTRAR OS MAX E MIN DE COLUNA E LINHA PARA FORMATAR IMAGEM
            maxrow3 = max(ROWNOVA1);
            minrow3 = min(ROWNOVA1);
            maxcol3 = max(COLNOVA1);
            mincol3 = min(COLNOVA1);

            % RETIRAR UM FRAME DA CAMARA RGB E DEPTH
            RGBFrameFlipped2 = flip(getsnapshot(app.RGBDisp),2);

            % "RECORTAR" IMAGEM RGB E DEPTH PELOS MAX/MIN COLUNA/LINHA
            RGB_ROI = RGBFrameFlipped2(minrow3:maxrow3,mincol3:maxcol3,:);

            % ABRIR PLOT PARA CRIAR A ZONA ROI
            figroi = figure("Name",'Region of Interest Selection','NumberTitle','off');
            imshow(RGB_ROI)

            h1 = drawrectangle;

            % ESPERAR PELO USER DEFINIR A ROI PARA SE OBTER A SUA POSIÇAO
            wait(h1)

            %% RETIRAR DO OBJETO O INTERIOR DA ROI ANTERIORMENTE DEFINIDA
            % ESPECIFICAR O STEP SIZE
            stepSize3 = 100;

            % AMOSTRA A NUVEM DE PONTOS DE ENTRADA E ARMAZENA AS COORDENADAS DE PONTOS COMO UM OBJETO DE NUVEM DE PONTOS
            indices3 = 1:stepSize3:app.ptCloudRot.Count;
            tempPtCloud3 = select(app.ptCloudRot,indices3);

            % REMOVER OS PONTOS INVALIDOS DENTRO DA AMOSTRA ANTERIOR
            [tempPtCloud3,validIndices3] = removeInvalidPoints(tempPtCloud3);

            % OBTER AS COORDENADAS DE LOCALIZAÇAO 3D DOS PONTOS DA NUVEM DE PONTOS
            worldPoints3 = tempPtCloud3.Location;

            % CONVERTER E ENCONTRAR AS COORDENADAS DOS PONTOS 2D CORRESPONDENTES AOS PONTOS 3D DA NUVEM
            [Y,X] = ind2sub([size(app.ptCloudRot.Location,1),size(app.ptCloudRot.Location,2)],indices3);
            imagePoints3 = [X(validIndices3)' Y(validIndices3)'];

            % ESTIMATIVA DA MATRIZ DE PROJEÇAO DA CAMARA A PARTIR DA IMAGEM E DAS COORDENADAS DOS PONTOS DE LOCALIZAÇAO 3D
            camMatrix3 = estimateCameraMatrix(imagePoints3,worldPoints3);

            % DEFINIR A ROI CUBICA PARA A TARGET AREA
            distbetween_x = norm(max(app.PC_Object.Location(:,1))-min(app.PC_Object.Location(:,1)));
            distbetween_y = norm(max(app.PC_Object.Location(:,2))-min(app.PC_Object.Location(:,2)));

            Vertice1xmin = floor(h1.Vertices(1));
            Vertice1xmax = floor(h1.Vertices(4));
            Vertice1ymin = floor(h1.Vertices(5));
            Vertice1ymax = floor(h1.Vertices(7));

            if Vertice1xmin == 0
                Vertice1xmin = 1;
            end

            if Vertice1xmax == 0
                Vertice1xmax = 1;
            end

            if Vertice1ymin == 0
                Vertice1ymin = 1;
            end

            if Vertice1ymax == 0
                Vertice1ymax = 1;
            end

            P_ROI_Xmin = min(min(app.PC_Object.Location(:,1)))+((Vertice1xmin)*distbetween_x)/(size(RGB_ROI,2));
            P_ROI_Xmax = min(min(app.PC_Object.Location(:,1)))+((Vertice1xmax)*distbetween_x)/(size(RGB_ROI,2));
            P_ROI_Ymax = min(min(app.PC_Object.Location(:,2)))+((Vertice1ymax)*distbetween_y)/(size(RGB_ROI,1));
            P_ROI_Ymin = min(min(app.PC_Object.Location(:,2)))+((Vertice1ymin)*distbetween_y)/(size(RGB_ROI,1));

            roi3 = [P_ROI_Xmin P_ROI_Xmax P_ROI_Ymin P_ROI_Ymax app.EditField_Zmin.Value app.EditField_Zmax.Value];

            % ENCONTRAR OS INDICES DOS PONTOS DA NUVEM QUE ESTAO DENTRO DA ROI CUBICA
            indices3 = findPointsInROI(app.ptCloudRot,roi3,camMatrix3);

            % SELECIONAR OS PONTOS DA NUVEM QUE SE ENCONTRAM DENTRO DA ROI
            app.ptcloudB3 = select(app.ptCloudRot,indices3);

            % REMOVER BARULHO DA NUVEM ROI
            app.ptcloudB3 = pcdenoise(app.ptcloudB3,"NumNeighbors",100);

            % FECHAR A JANELA DA ROI DEFINIDA
            close(figure(figroi))
%             close()

            % MOSTRAR A NUVEM DE PONTOS DA ROI
            figure("Name",'ROI Point Cloud Viewer','NumberTitle','off')
            pcshow(app.ptcloudB3,"VerticalAxis","Y",VerticalAxisDir="Down")
            title('ROI Point Cloud')
            xlabel('X(m)')
            ylabel('Y(m)')
            zlabel('Z(m)')
            whitebg(gcf,'white')
            set(gcf,'Color','w')

        end

        % Button pushed function: ShowContoursButton
        function ShowContoursButtonPushed(app, event)
            % LIMPAR O AXIS DOS CONTORNOS
            cla(app.UIAxesObjectContours,"reset")

            switch app.DropDownSelectROIForContour.Value
                case 'Full Object'

                    % DEFINIR O VALOR DO INICIAL DO SLIDER PARA 1
                    raio_strel = 1;

                    % EXTRAIR COORDENADAS X E Y DO OBJETO (RETIRAR Z)
                    xnuvem = app.PC_Object.Location(:,1);
                    ynuvem = app.PC_Object.Location(:,2);

                case 'ROI'
                    % DEFINIR O VALOR DO INICIAL DO SLIDER PARA 1
                    raio_strel = 5;

                    % EXTRAIR COORDENADAS X E Y DO OBJETO (RETIRAR Z)
                    xnuvem = app.ptcloudB3.Location(:,1);
                    ynuvem = app.ptcloudB3.Location(:,2);
            end

            % FAZER PLOT DOS PONTOS X E Y DO OBJETO E RODAR O PLOT
            plot(app.UIAxesObjectContours,xnuvem,ynuvem,'.k')
            set(app.UIAxesObjectContours,'ydir','reverse')
            axis(app.UIAxesObjectContours,'off')

            % RETIRAR FRAME DO PLOT ANTERIOR
            FramePlot = frame2im(getframe(app.UIAxesObjectContours));

            % BINARIZAR IMG E INVERTER COR
            ImgBin = imbinarize(im2gray(FramePlot));
            InverseImg = uint8(255) - im2uint8(ImgBin);

            % PREENCHER ESPAÇOS ABERTOS NO OBJETO
            raio_strel = round(app.StructuringElementRadiusSlider.Value);
            se = strel('disk',raio_strel);
            ImgClosed = imclose(InverseImg,se);

            % FAZER CONTORNOS DO OBJETO
            app.ImgEdge = edge(ImgClosed,"canny");

            % ENCONTRAR LINHAS E COLUNAS DOS PONTOS BRANCOS ( AKA CONTORNOS)
            [rowbw1,colbw1] = find(app.ImgEdge==1);

            % LIMITAR IMAGEM SEGUNDO OS CONTORNOS
            rowmax12 = max(rowbw1)+10;
            rowmin12 = min(rowbw1)-10;
            colmax12 = max(colbw1)+10;
            colmin12 = min(colbw1)-10;

            % NAO DEIXAR QUE A IMAGEM RECORTADA NAO ULTRAPASSE A RESOLUÇAO DA IMAGEM
            if rowmin12 < 0
                rowmin12 = 1;
            end

            if rowmax12 > size(app.ImgEdge,1)
                rowmax12 = size(app.ImgEdge,1);
            end

            if colmin12 < 0
                colmin12 = 1;
            end

            if colmax12 > size(app.ImgEdge,2)
                colmax12 = size(app.ImgEdge,2);
            end

            % RECORTAR E MOSTRAR IMAGEM DOS CONTORNOS
%           novaimagembw1 = ImgEdge(rowmin12:rowmax12,colmin12:colmax12,:);
%           imshow(novaimagembw1,'Parent',app.UIAxesObjectContours)
            imshow(app.ImgEdge,'Parent',app.UIAxesObjectContours)


        end

        % Button pushed function: GetPointCloudButton
        function GetPointCloudButtonPushed2(app, event)
            cla(app.UIAxesEditorBrowser, 'reset')

            gridStep = app.PCDownsamplingSpinner.Value;

            % DROPDOWN PARA ESCOLHER QUAL NUVEM PARA O FAZER O DOWNSAMPLE
            switch app.DropDownSelectROIForPCProcessing.Value
                case 'Full Object'
                    app.ptGridAvgDownS = pcdownsample(app.PC_Object,'gridAverage',gridStep);
                    app.xnuvem_down = app.ptGridAvgDownS.Location(:,1);
                    app.ynuvem_down = app.ptGridAvgDownS.Location(:,2);
                    app.znuvem_down = app.ptGridAvgDownS.Location(:,3);

                case 'ROI'
                    app.ptGridAvgDownS = pcdownsample(app.ptcloudB3,'gridAverage',gridStep);
                    app.xnuvem_down = app.ptGridAvgDownS.Location(:,1);
                    app.ynuvem_down = app.ptGridAvgDownS.Location(:,2);
                    app.znuvem_down = app.ptGridAvgDownS.Location(:,3);
            end


            % FAZER PLOT DA NUVEM ESCOLHIDA
            plot3(app.UIAxesPCDown,app.xnuvem_down,app.znuvem_down,-app.ynuvem_down,'.k')

            title(app.UIAxesPCDown,'Point Cloud Downsampled')
            xlabel(app.UIAxesPCDown,'X(m)')
            ylabel(app.UIAxesPCDown,'Y(m)')
            zlabel(app.UIAxesPCDown,'Z(m)')

            axis(app.UIAxesPCDown,"equal")
            grid(app.UIAxesPCDown,"on")

            % FAZER PLOT DA NUVEM NO NAVEGADOR
            plot3(app.UIAxesEditorBrowser,app.xnuvem_down,app.znuvem_down,-app.ynuvem_down,'.k')

            xlabel(app.UIAxesEditorBrowser,'X(m)')
            ylabel(app.UIAxesEditorBrowser,'Y(m)')
            zlabel(app.UIAxesEditorBrowser,'Z(m)')

            grid(app.UIAxesEditorBrowser,"on")
            axis(app.UIAxesEditorBrowser,"equal")
%             hold on

        end

        % Button pushed function: CropCloudButton
        function CropCloudButtonPushed2(app, event)
            % BOTAO CROP CLOUD FOI CARREGADO
            app.ButtonCropCloud = 1;
            
            figure(13)
            plot(app.ptGridAvgDownS.Location(:,1),app.ptGridAvgDownS.Location(:,2),'.k')
            set(gca,'ydir','reverse')

            % DESENHAR QUADRADO
            h2 = drawrectangle;
            wait(h2)

            % RETIRAR COORDENADAS DOS PONTOS DENTRO DO QUADRADO
            squareCropped_xmin = min(h2.Vertices(:,1));
            squareCropped_xmax = max(h2.Vertices(:,1));
            squareCropped_ymin = min(h2.Vertices(:,2));
            squareCropped_ymax = max(h2.Vertices(:,2));

            % PONTOS DENTRO DO QUADRADO
            app.CroppedPoints = find(app.ptGridAvgDownS.Location(:,1)>squareCropped_xmin & app.ptGridAvgDownS.Location(:,1)<squareCropped_xmax & ...
                app.ptGridAvgDownS.Location(:,2)>squareCropped_ymin & app.ptGridAvgDownS.Location(:,2)<squareCropped_ymax );

            app.CroppedPoints = app.ptGridAvgDownS.Location(app.CroppedPoints,:);

            close(figure(13))

            % NUVEM RECORTADA
            plot3(app.UIAxesPCDown,app.CroppedPoints(:,1),app.CroppedPoints(:,3),-app.CroppedPoints(:,2),'k.')
            axis(app.UIAxesPCDown,"equal")
            grid(app.UIAxesPCDown,"on")
            xlabel('X')
            ylabel('Y')
            zlabel('Z')

            % LIMPAR O NAVEGADOR
            cla(app.UIAxesEditorBrowser, 'reset')

            % FAZER PLOT DA PARTE RECORTADA NO NAVEGADOR
            plot3(app.UIAxesEditorBrowser,app.xnuvem_down,app.znuvem_down,-app.ynuvem_down,'.k')

            xlabel(app.UIAxesEditorBrowser,'X(m)')
            ylabel(app.UIAxesEditorBrowser,'Y(m)')
            zlabel(app.UIAxesEditorBrowser,'Z(m)')

            axis(app.UIAxesEditorBrowser,"equal")
            grid(app.UIAxesEditorBrowser,"on")
            hold(app.UIAxesEditorBrowser,"on")

            CroppedArea = plot3(app.UIAxesEditorBrowser,app.CroppedPoints(:,1),app.CroppedPoints(:,3),-app.CroppedPoints(:,2),'g.');
            legend(app.UIAxesEditorBrowser,CroppedArea,"Cropped Points",Location="southeastoutside")


        end

        % Button pushed function: RemovePointsButton
        function RemovePointsButtonPushed(app, event)
            % BOTAO REMOVE POINTS FOI CARREGADO
            app.ButtonRemovePoints.Value = 1;

            if app.ButtonCropCloud == 1
                figure(14)
                plot(app.CroppedPoints(:,1),app.CroppedPoints(:,2),'.k')
                set(gca,'ydir','reverse')

                % DESENHAR QUADRADO
                h3 = drawrectangle;
                wait(h3)

                % RETIRAR COORDENADAS DOS PONTOS DENTRO DO QUADRADO
                squareRemovePoints_xmin = min(h3.Vertices(:,1));
                squareRemovePoints_xmax = max(h3.Vertices(:,1));
                squareRemovePoints_ymin = min(h3.Vertices(:,2));
                squareRemovePoints_ymax = max(h3.Vertices(:,2));

                % PONTOS DENTRO DO QUADRADO
                app.RemovedPoints = find(app.CroppedPoints(:,1)>squareRemovePoints_xmin & app.CroppedPoints(:,1)<squareRemovePoints_xmax & ...
                    app.CroppedPoints(:,2)>squareRemovePoints_ymin & app.CroppedPoints(:,2)<squareRemovePoints_ymax );

                % PONTOS A RETIRAR
                app.RemovedPoints_aRemover = app.CroppedPoints(app.RemovedPoints,:);

                close(figure(14))

                % REMOVER OS PONTOS A RETIRAR DA NUVEM
                NPontosRemov = size(app.CroppedPoints,1);
                app.PC_PointsRemoved = zeros(size(app.CroppedPoints,1),3);
                for i=1:NPontosRemov
                    if i ~= app.RemovedPoints
                        app.PC_PointsRemoved(i,:) = app.CroppedPoints(i,:);
                    end
                end
                
            else
                figure(14)
                plot(app.xnuvem_down,app.ynuvem_down,'.k')
                set(gca,'ydir','reverse')

                % DESENHAR QUADRADO
                h3 = drawrectangle;
                wait(h3)

                % RETIRAR COORDENADAS DOS PONTOS DENTRO DO QUADRADO
                squareRemovePoints_xmin = min(h3.Vertices(:,1));
                squareRemovePoints_xmax = max(h3.Vertices(:,1));
                squareRemovePoints_ymin = min(h3.Vertices(:,2));
                squareRemovePoints_ymax = max(h3.Vertices(:,2));

                % PONTOS DENTRO DO QUADRADO
                app.RemovedPoints = find(app.xnuvem_down>squareRemovePoints_xmin & app.xnuvem_down<squareRemovePoints_xmax & ...
                                         app.ynuvem_down>squareRemovePoints_ymin & app.ynuvem_down<squareRemovePoints_ymax );
                
                % PONTOS A RETIRAR
                app.RemovedPoints_aRemover = app.ptGridAvgDownS.Location(app.RemovedPoints,:);

                close(figure(14))

                % REMOVER OS PONTOS A RETIRAR DA NUVEM
                NPontosRemov = size(app.ptGridAvgDownS.Location,1);
                app.PC_PointsRemoved = zeros(size(app.ptGridAvgDownS.Location,1),3);
                for i=1:NPontosRemov
                    if i ~= app.RemovedPoints
                        app.PC_PointsRemoved(i,:) = app.ptGridAvgDownS.Location(i,:);
                    end
                end
                
            end

            app.PC_PointsRemoved(~any(app.PC_PointsRemoved,2),:) = [];

            % FAZER PLOT DA NUVEM COM PONTOS REMOVIDOS
            plot3(app.UIAxesPCDown,app.PC_PointsRemoved(:,1),app.PC_PointsRemoved(:,3),-app.PC_PointsRemoved(:,2),'k.')

            xlabel(app.UIAxesPCDown,'X(m)')
            ylabel(app.UIAxesPCDown,'Y(m)')
            zlabel(app.UIAxesPCDown,'Z(m)')

            axis(app.UIAxesPCDown,"equal")
            grid(app.UIAxesPCDown,"on")

            % LIMPAR NAVEGADOR
            cla(app.UIAxesEditorBrowser, 'reset')

            if app.ButtonCropCloud == 1
                % FAZER PLOT DO NAVEGADOR COM AS PARTES CROPPED E OS PONTOS REMOVIDOS
                plot3(app.UIAxesEditorBrowser,app.xnuvem_down,app.znuvem_down,-app.ynuvem_down,'.k')

                xlabel(app.UIAxesEditorBrowser,'X(m)')
                ylabel(app.UIAxesEditorBrowser,'Y(m)')
                zlabel(app.UIAxesEditorBrowser,'Z(m)')

                axis(app.UIAxesEditorBrowser,"equal")
                grid(app.UIAxesEditorBrowser,"on")
                hold(app.UIAxesEditorBrowser,"on")

                CroppedAreaPlot = plot3(app.UIAxesEditorBrowser,app.CroppedPoints(:,1),app.CroppedPoints(:,3),-app.CroppedPoints(:,2),'g.');
                PointsRemovedPlot = plot3(app.UIAxesEditorBrowser,app.RemovedPoints_aRemover(:,1),app.RemovedPoints_aRemover(:,3),-app.RemovedPoints_aRemover(:,2),'r.');
                legend(app.UIAxesEditorBrowser,[CroppedAreaPlot PointsRemovedPlot],{'Cropped Part' 'Removed Points'},Location="southeastoutside")

            else
                % FAZER PLOT DO NAVEGADOR COM AS PARTES CROPPED E OS PONTOS REMOVIDOS
                plot3(app.UIAxesEditorBrowser,app.xnuvem_down,app.znuvem_down,-app.ynuvem_down,'.k')

                xlabel(app.UIAxesEditorBrowser,'X(m)')
                ylabel(app.UIAxesEditorBrowser,'Y(m)')
                zlabel(app.UIAxesEditorBrowser,'Z(m)')

                axis(app.UIAxesEditorBrowser,"equal")
                grid(app.UIAxesEditorBrowser,"on")
                hold(app.UIAxesEditorBrowser,"on")

                PointsRemovedPlot = plot3(app.UIAxesEditorBrowser,app.RemovedPoints_aRemover(:,1),app.RemovedPoints_aRemover(:,3),-app.RemovedPoints_aRemover(:,2),'r.');
                legend(app.UIAxesEditorBrowser,PointsRemovedPlot,{'Removed Points'},Location="southeastoutside")
            end

        end

        % Button pushed function: ResetPointsButton_Density
        function ResetPointsButton_DensityPushed(app, event)
            % LIMPAR O NAVEGADOR E O PLOT DA NUVEM DO DOWNSAMPLE
            cla(app.UIAxesEditorBrowser, 'reset')
            cla(app.UIAxesPCDown, 'reset')

            % FAZER PLOT DA NUVEM ORIGINAL DOWNSAMPLED
            plot3(app.UIAxesPCDown,app.xnuvem_down,app.znuvem_down,-app.ynuvem_down,'.k')

            title(app.UIAxesPCDown,'Point Cloud Downsampled')
            xlabel(app.UIAxesPCDown,'X(m)')
            ylabel(app.UIAxesPCDown,'Y(m)')
            zlabel(app.UIAxesPCDown,'Z(m)')

            axis(app.UIAxesPCDown,"equal")
            grid(app.UIAxesPCDown,"on")

            % FAZER PLOT DA NUVEM ORIGINAL NO NAVEGADOR
            plot3(app.UIAxesEditorBrowser,app.xnuvem_down,app.znuvem_down,-app.ynuvem_down,'.k')

            xlabel(app.UIAxesEditorBrowser,'X(m)')
            ylabel(app.UIAxesEditorBrowser,'Y(m)')
            zlabel(app.UIAxesEditorBrowser,'Z(m)')
            
            axis(app.UIAxesEditorBrowser,"equal")
            grid(app.UIAxesEditorBrowser,"on")

        end

        % Button pushed function: SelectDensifyAreaButton
        function SelectDensifyAreaButtonPushed(app, event)
            % BOTAO SELECT DENSIFY AREA CARREGADO
            app.ButtonSelectDensity = 1;

%             if app.ButtonCropCloud == 0 && app.ButtonRemovePoints == 0
% 
%             elseif app.ButtonCropCloud == 1 && app.ButtonRemovePoints == 0
% 
%             elseif app.ButtonCropCloud == 1 && app.ButtonRemovePoints == 1
% 
%                 figure(40)
%                 plot(app.PC_PointsRemoved(:,1),app.PC_PointsRemoved(:,2),'.k')
%                 set(gca,'ydir','reverse')
% 
%                 % DESENHAR QUADRADO
%                 h4 = drawrectangle;
%                 wait(h4)
% 
%                 % RETIRAR COORDENADAS DOS PONTOS DENTRO DO QUADRADO
%                 squareDensityPoints_xmin = min(h4.Vertices(:,1));
%                 squareDensityPoints_xmax = max(h4.Vertices(:,1));
%                 squareDensityPoints_ymin = min(h4.Vertices(:,2));
%                 squareDensityPoints_ymax = max(h4.Vertices(:,2));
% 
%                 % PONTOS DENTRO DO QUADRADO
%                 app.DensityPoints = find(app.PC_PointsRemoved(:,1)>squareDensityPoints_xmin & app.PC_PointsRemoved(:,1)<squareDensityPoints_xmax & ...
%                     app.PC_PointsRemoved(:,2)>squareDensityPoints_ymin & app.PC_PointsRemoved(:,2)<squareDensityPoints_ymax );
%                 % PONTOS A RETIRAR
%                 app.DensityPoints_ARremover = app.PC_PointsRemoved(app.DensityPoints,:);
% 
%                 close(figure(40))
% 
%                 % LIMPAR O PLOT DA NUVEM DOWNSAMPLED PARA INSERIR NOVA NUVEM
%                 cla(app.UIAxesPCDown,"reset")
% 
%                 % REMOVER OS PONTOS OS PONTOS DENTRO DO QUADRADO h4
%                 NPontosDensity = size(app.PC_PointsRemoved,1);
%                 app.PC_PointsDensity = zeros(size(app.PC_PointsRemoved,1),3);
%                 for i=1:NPontosDensity
%                     if i ~= app.DensityPoints
%                         app.PC_PointsDensity(i,:) = app.PC_PointsRemoved(i,:);
%                     end
%                 end
%                 
%             end            
            
            figure(40)
            plot(app.PC_PointsRemoved(:,1),app.PC_PointsRemoved(:,2),'.k')
            set(gca,'ydir','reverse')

            % DESENHAR QUADRADO
            h4 = drawrectangle;
            wait(h4)

            % RETIRAR COORDENADAS DOS PONTOS DENTRO DO QUADRADO
            squareDensityPoints_xmin = min(h4.Vertices(:,1));
            squareDensityPoints_xmax = max(h4.Vertices(:,1));
            squareDensityPoints_ymin = min(h4.Vertices(:,2));
            squareDensityPoints_ymax = max(h4.Vertices(:,2));

            % PONTOS DENTRO DO QUADRADO
            app.DensityPoints = find(app.PC_PointsRemoved(:,1)>squareDensityPoints_xmin & app.PC_PointsRemoved(:,1)<squareDensityPoints_xmax & ...
                                     app.PC_PointsRemoved(:,2)>squareDensityPoints_ymin & app.PC_PointsRemoved(:,2)<squareDensityPoints_ymax );
            % PONTOS A RETIRAR
            app.DensityPoints_ARremover = app.PC_PointsRemoved(app.DensityPoints,:);

            close(figure(40))

            % LIMPAR O PLOT DA NUVEM DOWNSAMPLED PARA INSERIR NOVA NUVEM
            cla(app.UIAxesPCDown,"reset")
            
            % REMOVER OS PONTOS OS PONTOS DENTRO DO QUADRADO h4
            NPontosDensity = size(app.PC_PointsRemoved,1);
            app.PC_PointsDensity = zeros(size(app.PC_PointsRemoved,1),3);
            for i=1:NPontosDensity
                if i ~= app.DensityPoints
                    app.PC_PointsDensity(i,:) = app.PC_PointsRemoved(i,:);
                end
            end

            app.PC_PointsDensity(~any(app.PC_PointsDensity,2),:) = [];

            % FAZER PLOT DA NUVEM DA NUVEM SEM OS PONTOS DE DENSITY
            plot3(app.UIAxesPCDown,app.PC_PointsDensity(:,1),app.PC_PointsDensity(:,3),-app.PC_PointsDensity(:,2),'k.')

            axis(app.UIAxesPCDown,"equal")
            grid(app.UIAxesPCDown,"on")


            % BUSCAR OS PONTOS INICIAIS DA NUVEM ANTES DO DOWNSAMPLE PARA DAR MAIOR DENSIDADE AOS PONTOS
            app.DensityPoints = find(app.PC_Object.Location(:,1)>squareDensityPoints_xmin & app.PC_Object.Location(:,1)<squareDensityPoints_xmax & ...
                                     app.PC_Object.Location(:,2)>squareDensityPoints_ymin & app.PC_Object.Location(:,2)<squareDensityPoints_ymax );

            % PONTOS COM DENSIDADE MAXIMA
            app.DensityPoints = app.PC_Object.Location(app.DensityPoints,:);

            % FAZER PLOT DOS PONTOS COM DENSIDADE MAX NO PLOT DA NUVEM DOWNSAMPLE
            hold(app.UIAxesPCDown,"on")
            plot3(app.UIAxesPCDown,app.DensityPoints(:,1),app.DensityPoints(:,3),-app.DensityPoints(:,2),'k.')

            xlabel(app.UIAxesPCDown,'X(m)')
            ylabel(app.UIAxesPCDown,'Y(m)')
            zlabel(app.UIAxesPCDown,'Z(m)')

            grid(app.UIAxesPCDown,"on")
            axis(app.UIAxesPCDown,"equal")

            % LIMPAR O NAVEDOR
            cla(app.UIAxesEditorBrowser, 'reset')

            % FAZER PLOT NO NAVEGADOR COM AS LEGENDAS DE TODOS OS PONTOS ANTERIORES
            plot3(app.UIAxesEditorBrowser,app.xnuvem_down,app.znuvem_down,-app.ynuvem_down,'.k')

            xlabel(app.UIAxesEditorBrowser,'X(m)')
            ylabel(app.UIAxesEditorBrowser,'Y(m)')
            zlabel(app.UIAxesEditorBrowser,'Z(m)')

            axis(app.UIAxesEditorBrowser,"equal")
            grid(app.UIAxesEditorBrowser,"on")
            hold(app.UIAxesEditorBrowser,"on")

            CroppedArea = plot3(app.UIAxesEditorBrowser,app.CroppedPoints(:,1),app.CroppedPoints(:,3),-app.CroppedPoints(:,2),'g.');
            PointsRemovedPlot = plot3(app.UIAxesEditorBrowser,app.RemovedPoints_aRemover(:,1),app.RemovedPoints_aRemover(:,3),-app.RemovedPoints_aRemover(:,2),'r.');
            DensifyArea = plot3(app.UIAxesEditorBrowser,app.DensityPoints_ARremover(:,1),app.DensityPoints_ARremover(:,3),-app.DensityPoints_ARremover(:,2),'b.');
            legend(app.UIAxesEditorBrowser,[CroppedArea PointsRemovedPlot DensifyArea],{'Cropped Part' 'Removed Points' 'Densified Area'},Location="southeastoutside")
      
        end

        % Callback function
        function Slider_densValueChanging(app, event)
%             gridStep4 = event.Value;
% 
%             % LIMPAR PLOT DA NUVEM DOWNSAMPLED
%             cla(app.UIAxesPCDown,"reset")
% 
%             % VALOR E LIMITES DO SLIDER PARA A DENSIDADE
%             app.Slider_dens.Limits = [0.000001 app.PCDownsamplingSpinner.Value];
%             app.Slider_dens.MajorTicks = (0.000001:0.005:app.PCDownsamplingSpinner.Value);
% 
%             % CRIAR NUVEM NOVA PARA FAZER NOVO DOWNSAMPLE
%             PCdens = pointCloud(app.DensityPoints);
% 
%             % FAZER DOWNSAMPLE COM O VALOR INTRODUZIDO NO SLIDER
%             PCdens_down = pcdownsample(PCdens,"gridAverage",gridStep4);
% 
%             % PLOT DA NUVEM NO PLOT DA NUVEM DOWNSAMPLE
%             plot3(app.UIAxesPCDown,app.PC_PointsDensity(:,1),app.PC_PointsDensity(:,3),-app.PC_PointsDensity(:,2),'k.')
% 
%             xlabel(app.UIAxesPCDown,'X(m)')
%             ylabel(app.UIAxesPCDown,'Y(m)')
%             zlabel(app.UIAxesPCDown,'Z(m)')
% 
%             axis(app.UIAxesPCDown,"equal")
%             grid(app.UIAxesPCDown,"on")
%             hold(app.UIAxesPCDown,"on")
% 
%             % FAZER PLOT DA NUVEM CRIADA ANTERIOR MENTE
%             plot3(app.UIAxesPCDown,PCdens_down.Location(:,1),PCdens_down.Location(:,3),-PCdens_down.Location(:,2),'.k')
            
        end

        % Value changing function: SpinnerDensity
        function SpinnerDensityValueChanging(app, event)
            app.SpinnerDensity.Value = app.PCDownsamplingSpinner.Value;
            app.SpinnerDensity.Limits = [10^-5 app.PCDownsamplingSpinner.Value];

            gridStep4 = event.Value;

            % LIMPAR PLOT DA NUVEM DOWNSAMPLED
            cla(app.UIAxesPCDown,"reset")

            % CRIAR NUVEM NOVA PARA FAZER NOVO DOWNSAMPLE
            PCdens = pointCloud(app.DensityPoints);

            % FAZER DOWNSAMPLE COM O VALOR INTRODUZIDO NO SLIDER
            PCdens_down = pcdownsample(PCdens,"gridAverage",gridStep4);

            % PLOT DA NUVEM NO PLOT DA NUVEM DOWNSAMPLE
            plot3(app.UIAxesPCDown,app.PC_PointsDensity(:,1),app.PC_PointsDensity(:,3),-app.PC_PointsDensity(:,2),'k.')

            xlabel(app.UIAxesPCDown,'X(m)')
            ylabel(app.UIAxesPCDown,'Y(m)')
            zlabel(app.UIAxesPCDown,'Z(m)')

            axis(app.UIAxesPCDown,"equal")
            grid(app.UIAxesPCDown,"on")
            hold(app.UIAxesPCDown,"on")

            % FAZER PLOT DA NUVEM CRIADA ANTERIOR MENTE
            plot3(app.UIAxesPCDown,PCdens_down.Location(:,1),PCdens_down.Location(:,3),-PCdens_down.Location(:,2),'.k')
            
        end

        % Button pushed function: SelectUncompressAreaButton
        function SelectUncompressAreaButtonPushed(app, event)
            figure(60)
            plot(app.PC_PointsRemoved(:,1),app.PC_PointsRemoved(:,2),'.k')
            set(gca,'ydir','reverse')

            % DESENHAR QUADRADO
            h5 = drawrectangle;
            wait(h5)

            % RETIRAR COORDENADAS DOS PONTOS DENTRO DO QUADRADO
            squareUncomPoints_xmin = min(h5.Vertices(:,1));
            squareUncomPoints_xmax = max(h5.Vertices(:,1));
            squareUncomPoints_ymin = min(h5.Vertices(:,2));
            squareUncomPoints_ymax = max(h5.Vertices(:,2));

            % PONTOS DENTRO DO QUADRADO
            app.UncomPoints = find(app.PC_PointsRemoved(:,1)>squareUncomPoints_xmin & app.PC_PointsRemoved(:,1)<squareUncomPoints_xmax & ...
                               app.PC_PointsRemoved(:,2)>squareUncomPoints_ymin & app.PC_PointsRemoved(:,2)<squareUncomPoints_ymax );
            % PONTOS A RETIRAR
            app.UncomPoints_aRemover = app.PC_PointsRemoved(app.UncomPoints,:);

            close(figure(60))

            cla(app.UIAxesPCDown,"reset")
            
            % REMOVER OS PONTOS DENTRO DO QUADRADO h5
            NPontosRemov = size(app.PC_PointsRemoved,1);
            app.PC_PointsUncom = zeros(size(app.PC_PointsRemoved,1),3);
            for i=1:NPontosRemov
                if i ~= app.UncomPoints
                    app.PC_PointsUncom(i,:) = app.PC_PointsRemoved(i,:);
                end
            end

            app.PC_PointsUncom(~any(app.PC_PointsUncom,2),:) = [];

            % FAZAER PLOT DA NUVEM SEM OS PONTOS UNCOMPRESSED
            plot3(app.UIAxesPCDown,app.PC_PointsUncom(:,1),app.PC_PointsUncom(:,3),-app.PC_PointsUncom(:,2),'k.')
            
            xlabel(app.UIAxesPCDown,'X(m)')
            ylabel(app.UIAxesPCDown,'Y(m)')
            zlabel(app.UIAxesPCDown,'Z(m)')
            
            axis(app.UIAxesPCDown,"equal")
            grid(app.UIAxesPCDown,"on")

            % ENCONTRAR OS PONTOS DENTRO DO QUADRADO h5 DA NUVEM ORIGINAL DOWNSAMPLE
            UncomPoints_PontosIniciais = find(app.ptGridAvgDownS.Location(:,1)>squareUncomPoints_xmin & app.ptGridAvgDownS.Location(:,1)<squareUncomPoints_xmax & ...
                               app.ptGridAvgDownS.Location(:,2)>squareUncomPoints_ymin & app.ptGridAvgDownS.Location(:,2)<squareUncomPoints_ymax );

            UncomPoints_PontosIniciais = app.ptGridAvgDownS.Location(UncomPoints_PontosIniciais,:);


            % FAZER PLOT DOS PONTOS
            hold(app.UIAxesPCDown,"on")
            plot3(app.UIAxesPCDown,UncomPoints_PontosIniciais(:,1),UncomPoints_PontosIniciais(:,3),-UncomPoints_PontosIniciais(:,2),'k.')

            xlabel(app.UIAxesPCDown,'X(m)')
            ylabel(app.UIAxesPCDown,'Y(m)')
            zlabel(app.UIAxesPCDown,'Z(m)')

            grid(app.UIAxesPCDown,"on")
            axis(app.UIAxesPCDown,"equal")


            % LIMPAR O NAVEGADOR
            cla(app.UIAxesEditorBrowser, 'reset')

            % FAZER PLOT DOS PONTOS UNCOMPRESS NO NAVEGADOR
            plot3(app.UIAxesEditorBrowser,app.xnuvem_down,app.znuvem_down,-app.ynuvem_down,'.k')

            xlabel(app.UIAxesEditorBrowser,'X(m)')
            ylabel(app.UIAxesEditorBrowser,'Y(m)')
            zlabel(app.UIAxesEditorBrowser,'Z(m)')

            axis(app.UIAxesEditorBrowser,"equal")
            grid(app.UIAxesEditorBrowser,"on")
            hold(app.UIAxesEditorBrowser,"on")

            CroppedArea = plot3(app.UIAxesEditorBrowser,app.CroppedPoints(:,1),app.CroppedPoints(:,3),-app.CroppedPoints(:,2),'g.');
            PointsRemovedPlot = plot3(app.UIAxesEditorBrowser,app.RemovedPoints_aRemover(:,1),app.RemovedPoints_aRemover(:,3),-app.RemovedPoints_aRemover(:,2),'r.');
            DensifyArea = plot3(app.UIAxesEditorBrowser,app.DensityPoints_ARremover(:,1),app.DensityPoints_ARremover(:,3),-app.DensityPoints_ARremover(:,2),'b.');
            UncomArea = plot3(app.UIAxesEditorBrowser,app.UncomPoints_aRemover(:,1),app.UncomPoints_aRemover(:,3),-app.UncomPoints_aRemover(:,2),'m.');
            legend(app.UIAxesEditorBrowser,[CroppedArea PointsRemovedPlot DensifyArea UncomArea],{'Cropped Part' 'Removed Points' 'Densified Area' 'Uncompressed Area'},Location="southeastoutside")
      
        end

        % Value changing function: SpinnerUncompress
        function SpinnerUncompressValueChanging(app, event)
            % LIMPAR O PLOT DA NUVEM DOWNSAMPLED
            cla(app.UIAxesPCDown,"reset")

            % LIMITES E VALOR DO SLIDER
            app.SpinnerUncompress.Limits = [app.PCDownsamplingSpinner.Value inf];
            gridStep8 = event.Value;

            % CRIAR NOVA NUVEM PARA FAZER NOVO DOWNSAMPLE
            PCuncomp = pointCloud(app.UncomPoints_aRemover);

            PCuncomp_down = pcdownsample(PCuncomp,"gridAverage",gridStep8);

            plot3(app.UIAxesPCDown,app.PC_PointsUncom(:,1),app.PC_PointsUncom(:,3),-app.PC_PointsUncom(:,2),'k.')

            xlabel(app.UIAxesPCDown,'X(m)')
            ylabel(app.UIAxesPCDown,'Y(m)')
            zlabel(app.UIAxesPCDown,'Z(m)')

            axis(app.UIAxesPCDown,"equal")
            grid(app.UIAxesPCDown,"on")
            hold(app.UIAxesPCDown,"on")

            plot3(app.UIAxesPCDown,PCuncomp_down.Location(:,1),PCuncomp_down.Location(:,3),-PCuncomp_down.Location(:,2),'.k')
            
        end

        % Callback function
        function Slider_uncompressValueChanging(app, event)
%             % LIMPAR O PLOT DA NUVEM DOWNSAMPLED
%             cla(app.UIAxesPCDown,"reset")
% 
%             % LIMITES E VALOR DO SLIDER
%             app.Slider_uncompress.Limits = [app.PCDownsamplingSpinner.Value (app.PCDownsamplingSpinner.Value)*10];
%             app.Slider_uncompress.MajorTicks = (app.PCDownsamplingSpinner.Value:0.001:((app.PCDownsamplingSpinner.Value)*10));
%             gridStep8 = event.Value;
% 
%             % CRIAR NOVA NUVEM PARA FAZER NOVO DOWNSAMPLE
%             PCuncomp = pointCloud(app.UncomPoints_aRemover);
% 
%             PCuncomp_down = pcdownsample(PCuncomp,"gridAverage",gridStep8);
% 
%             plot3(app.UIAxesPCDown,app.PC_PointsUncom(:,1),app.PC_PointsUncom(:,3),-app.PC_PointsUncom(:,2),'k.')
% 
%             xlabel(app.UIAxesPCDown,'X(m)')
%             ylabel(app.UIAxesPCDown,'Y(m)')
%             zlabel(app.UIAxesPCDown,'Z(m)')
% 
%             axis(app.UIAxesPCDown,"equal")
%             grid(app.UIAxesPCDown,"on")
%             hold(app.UIAxesPCDown,"on")
% 
%             plot3(app.UIAxesPCDown,PCuncomp_down.Location(:,1),PCuncomp_down.Location(:,3),-PCuncomp_down.Location(:,2),'.k')
%         
        end

        % Button pushed function: ResetButton_Uncompress
        function ResetButton_UncompressPushed(app, event)

        end

        % Button pushed function: ExitButton
        function ExitButtonPushed(app, event)
            % FECHAR APLICAÇAO E TODAS AS JANELAS ABERTAS
            app.delete
            close all
        end
    end

    % Component initialization
    methods (Access = private)

        % Create UIFigure and components
        function createComponents(app)

            % Create UIFigure and hide until all components are created
            app.UIFigure = uifigure('Visible', 'off');
            app.UIFigure.Position = [100 100 1134 737];
            app.UIFigure.Name = 'MATLAB App';
            app.UIFigure.Scrollable = 'on';

            % Create TabGroup
            app.TabGroup = uitabgroup(app.UIFigure);
            app.TabGroup.Position = [1 38 1134 700];

            % Create IMAGEACQUISITIONTab
            app.IMAGEACQUISITIONTab = uitab(app.TabGroup);
            app.IMAGEACQUISITIONTab.Title = 'IMAGE ACQUISITION';

            % Create VIDEOSTREAMSPanel
            app.VIDEOSTREAMSPanel = uipanel(app.IMAGEACQUISITIONTab);
            app.VIDEOSTREAMSPanel.Title = 'VIDEO STREAMS';
            app.VIDEOSTREAMSPanel.Position = [9 12 354 648];

            % Create UIAxesRGBStream
            app.UIAxesRGBStream = uiaxes(app.VIDEOSTREAMSPanel);
            app.UIAxesRGBStream.Box = 'on';
            app.UIAxesRGBStream.Position = [21 421 312 185];

            % Create UIAxesDEPTHStream
            app.UIAxesDEPTHStream = uiaxes(app.VIDEOSTREAMSPanel);
            app.UIAxesDEPTHStream.Box = 'on';
            app.UIAxesDEPTHStream.Position = [21 181 313 185];

            % Create StartStreamsButton
            app.StartStreamsButton = uibutton(app.VIDEOSTREAMSPanel, 'push');
            app.StartStreamsButton.ButtonPushedFcn = createCallbackFcn(app, @StartStreamsButtonPushed, true);
            app.StartStreamsButton.Position = [102 108 150 39];
            app.StartStreamsButton.Text = 'Start Streams';

            % Create RGBVideoStreamLabel
            app.RGBVideoStreamLabel = uilabel(app.VIDEOSTREAMSPanel);
            app.RGBVideoStreamLabel.Position = [124 597 107 22];
            app.RGBVideoStreamLabel.Text = 'RGB Video Stream';

            % Create DepthVideoStreamLabel
            app.DepthVideoStreamLabel = uilabel(app.VIDEOSTREAMSPanel);
            app.DepthVideoStreamLabel.Position = [121 357 113 22];
            app.DepthVideoStreamLabel.Text = 'Depth Video Stream';

            % Create OBJECTDETECTIONPanel
            app.OBJECTDETECTIONPanel = uipanel(app.IMAGEACQUISITIONTab);
            app.OBJECTDETECTIONPanel.Title = 'OBJECT DETECTION';
            app.OBJECTDETECTIONPanel.Position = [382 12 740 648];

            % Create GetFullPointCloudButton
            app.GetFullPointCloudButton = uibutton(app.OBJECTDETECTIONPanel, 'push');
            app.GetFullPointCloudButton.ButtonPushedFcn = createCallbackFcn(app, @GetFullPointCloudButtonPushed, true);
            app.GetFullPointCloudButton.Position = [18 587 328 32];
            app.GetFullPointCloudButton.Text = 'Get Full Point Cloud';

            % Create TARGETAREAPanel
            app.TARGETAREAPanel = uipanel(app.OBJECTDETECTIONPanel);
            app.TARGETAREAPanel.TitlePosition = 'centertop';
            app.TARGETAREAPanel.Title = 'TARGET AREA';
            app.TARGETAREAPanel.Position = [18 333 697 244];

            % Create EditField_Xmin
            app.EditField_Xmin = uieditfield(app.TARGETAREAPanel, 'numeric');
            app.EditField_Xmin.HorizontalAlignment = 'left';
            app.EditField_Xmin.Position = [41 158 52 22];
            app.EditField_Xmin.Value = -0.5;

            % Create EditField_Ymin
            app.EditField_Ymin = uieditfield(app.TARGETAREAPanel, 'numeric');
            app.EditField_Ymin.HorizontalAlignment = 'left';
            app.EditField_Ymin.Position = [42 126 52 22];

            % Create EditField_Ymax
            app.EditField_Ymax = uieditfield(app.TARGETAREAPanel, 'numeric');
            app.EditField_Ymax.Position = [132 126 52 22];
            app.EditField_Ymax.Value = 0.4;

            % Create EditField_Xmax
            app.EditField_Xmax = uieditfield(app.TARGETAREAPanel, 'numeric');
            app.EditField_Xmax.Position = [132 158 52 22];
            app.EditField_Xmax.Value = 0.5;

            % Create EditField_Zmin
            app.EditField_Zmin = uieditfield(app.TARGETAREAPanel, 'numeric');
            app.EditField_Zmin.HorizontalAlignment = 'left';
            app.EditField_Zmin.Position = [42 93 52 22];
            app.EditField_Zmin.Value = 1.2;

            % Create EditField_Zmax
            app.EditField_Zmax = uieditfield(app.TARGETAREAPanel, 'numeric');
            app.EditField_Zmax.Position = [132 92 52 22];
            app.EditField_Zmax.Value = 1.7;

            % Create XLabel
            app.XLabel = uilabel(app.TARGETAREAPanel);
            app.XLabel.HorizontalAlignment = 'center';
            app.XLabel.Position = [95 158 34 22];
            app.XLabel.Text = '< X <';

            % Create YLabel
            app.YLabel = uilabel(app.TARGETAREAPanel);
            app.YLabel.HorizontalAlignment = 'center';
            app.YLabel.Position = [95 126 34 22];
            app.YLabel.Text = '< Y <';

            % Create ZLabel
            app.ZLabel = uilabel(app.TARGETAREAPanel);
            app.ZLabel.HorizontalAlignment = 'center';
            app.ZLabel.Position = [95 93 34 22];
            app.ZLabel.Text = '< Z <';

            % Create Image
            app.Image = uiimage(app.TARGETAREAPanel);
            app.Image.Position = [236 1 442 235];
            app.Image.ImageSource = 'App Designer Kinect Diagram.png';

            % Create ROICoordinatesLabel
            app.ROICoordinatesLabel = uilabel(app.TARGETAREAPanel);
            app.ROICoordinatesLabel.Position = [65 190 95 22];
            app.ROICoordinatesLabel.Text = 'ROI Coordinates';

            % Create GetTargetAreaButton
            app.GetTargetAreaButton = uibutton(app.TARGETAREAPanel, 'push');
            app.GetTargetAreaButton.ButtonPushedFcn = createCallbackFcn(app, @GetTargetAreaButtonPushed, true);
            app.GetTargetAreaButton.Position = [37 33 150 39];
            app.GetTargetAreaButton.Text = 'Get Target Area';

            % Create REGIONOFINTERESTPanel
            app.REGIONOFINTERESTPanel = uipanel(app.OBJECTDETECTIONPanel);
            app.REGIONOFINTERESTPanel.Title = 'REGION OF INTEREST';
            app.REGIONOFINTERESTPanel.Position = [18 109 247 207];

            % Create SelectFullObjectButton
            app.SelectFullObjectButton = uibutton(app.REGIONOFINTERESTPanel, 'push');
            app.SelectFullObjectButton.ButtonPushedFcn = createCallbackFcn(app, @SelectFullObjectButtonPushed, true);
            app.SelectFullObjectButton.Position = [18 107 203 61];
            app.SelectFullObjectButton.Text = 'Select Full Object';

            % Create SelectROIButton
            app.SelectROIButton = uibutton(app.REGIONOFINTERESTPanel, 'push');
            app.SelectROIButton.ButtonPushedFcn = createCallbackFcn(app, @SelectROIButtonPushed, true);
            app.SelectROIButton.Position = [18 20 203 61];
            app.SelectROIButton.Text = 'Select ROI';

            % Create CONTOURSPanel
            app.CONTOURSPanel = uipanel(app.OBJECTDETECTIONPanel);
            app.CONTOURSPanel.Title = 'CONTOURS';
            app.CONTOURSPanel.Position = [280 21 435 295];

            % Create UIAxesObjectContours
            app.UIAxesObjectContours = uiaxes(app.CONTOURSPanel);
            app.UIAxesObjectContours.Box = 'on';
            app.UIAxesObjectContours.Position = [6 51 324 218];

            % Create StructuringElementRadiusSliderLabel
            app.StructuringElementRadiusSliderLabel = uilabel(app.CONTOURSPanel);
            app.StructuringElementRadiusSliderLabel.HorizontalAlignment = 'center';
            app.StructuringElementRadiusSliderLabel.WordWrap = 'on';
            app.StructuringElementRadiusSliderLabel.Position = [336 3 91 62];
            app.StructuringElementRadiusSliderLabel.Text = 'Structuring Element Radius';

            % Create StructuringElementRadiusSlider
            app.StructuringElementRadiusSlider = uislider(app.CONTOURSPanel);
            app.StructuringElementRadiusSlider.Limits = [0 16];
            app.StructuringElementRadiusSlider.MajorTicks = [0 2 4 6 8 10 12 14 16];
            app.StructuringElementRadiusSlider.MajorTickLabels = {'0', '2', '4', '6', '8', '10', '12', '14', '16'};
            app.StructuringElementRadiusSlider.Orientation = 'vertical';
            app.StructuringElementRadiusSlider.MinorTicks = [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16];
            app.StructuringElementRadiusSlider.Position = [376 62 3 194];
            app.StructuringElementRadiusSlider.Value = 5;

            % Create ShowContoursButton
            app.ShowContoursButton = uibutton(app.CONTOURSPanel, 'push');
            app.ShowContoursButton.ButtonPushedFcn = createCallbackFcn(app, @ShowContoursButtonPushed, true);
            app.ShowContoursButton.Position = [93 20 150 39];
            app.ShowContoursButton.Text = 'Show Contours';

            % Create SELECTROIFORCONTOURSPanel
            app.SELECTROIFORCONTOURSPanel = uipanel(app.OBJECTDETECTIONPanel);
            app.SELECTROIFORCONTOURSPanel.TitlePosition = 'centertop';
            app.SELECTROIFORCONTOURSPanel.Title = 'SELECT ROI FOR CONTOURS';
            app.SELECTROIFORCONTOURSPanel.Position = [18 21 247 89];

            % Create Label
            app.Label = uilabel(app.SELECTROIFORCONTOURSPanel);
            app.Label.HorizontalAlignment = 'right';
            app.Label.Position = [18 27 25 22];
            app.Label.Text = '';

            % Create DropDownSelectROIForContour
            app.DropDownSelectROIForContour = uidropdown(app.SELECTROIFORCONTOURSPanel);
            app.DropDownSelectROIForContour.Items = {' ', 'Full Object', 'ROI'};
            app.DropDownSelectROIForContour.Position = [18 27 203 22];
            app.DropDownSelectROIForContour.Value = ' ';

            % Create ViewFullPointCloudButton
            app.ViewFullPointCloudButton = uibutton(app.OBJECTDETECTIONPanel, 'push');
            app.ViewFullPointCloudButton.ButtonPushedFcn = createCallbackFcn(app, @ViewFullPointCloudButtonPushed, true);
            app.ViewFullPointCloudButton.Position = [387 587 328 32];
            app.ViewFullPointCloudButton.Text = 'View Full Point Cloud';

            % Create POINTCLOUDEDITORTab
            app.POINTCLOUDEDITORTab = uitab(app.TabGroup);
            app.POINTCLOUDEDITORTab.Title = 'POINT CLOUD EDITOR';

            % Create UIAxesPCDown
            app.UIAxesPCDown = uiaxes(app.POINTCLOUDEDITORTab);
            title(app.UIAxesPCDown, 'Point Cloud Downsampled')
            app.UIAxesPCDown.XGrid = 'on';
            app.UIAxesPCDown.YGrid = 'on';
            app.UIAxesPCDown.ZGrid = 'on';
            app.UIAxesPCDown.Position = [372 12 752 651];

            % Create UIAxesEditorBrowser
            app.UIAxesEditorBrowser = uiaxes(app.POINTCLOUDEDITORTab);
            app.UIAxesEditorBrowser.XGrid = 'on';
            app.UIAxesEditorBrowser.YGrid = 'on';
            app.UIAxesEditorBrowser.ZGrid = 'on';
            app.UIAxesEditorBrowser.Box = 'on';
            app.UIAxesEditorBrowser.Position = [11 295 353 223];

            % Create SELECTROIFORPOINTCLOUDPROCESSINGPanel
            app.SELECTROIFORPOINTCLOUDPROCESSINGPanel = uipanel(app.POINTCLOUDEDITORTab);
            app.SELECTROIFORPOINTCLOUDPROCESSINGPanel.TitlePosition = 'centertop';
            app.SELECTROIFORPOINTCLOUDPROCESSINGPanel.Title = 'SELECT ROI FOR POINT CLOUD PROCESSING';
            app.SELECTROIFORPOINTCLOUDPROCESSINGPanel.Position = [12 523 352 136];

            % Create Label_3
            app.Label_3 = uilabel(app.SELECTROIFORPOINTCLOUDPROCESSINGPanel);
            app.Label_3.HorizontalAlignment = 'right';
            app.Label_3.Position = [19 75 25 22];
            app.Label_3.Text = '';

            % Create DropDownSelectROIForPCProcessing
            app.DropDownSelectROIForPCProcessing = uidropdown(app.SELECTROIFORPOINTCLOUDPROCESSINGPanel);
            app.DropDownSelectROIForPCProcessing.Items = {' ', 'Full Object', 'ROI'};
            app.DropDownSelectROIForPCProcessing.Position = [19 75 194 22];
            app.DropDownSelectROIForPCProcessing.Value = ' ';

            % Create GetPointCloudButton
            app.GetPointCloudButton = uibutton(app.SELECTROIFORPOINTCLOUDPROCESSINGPanel, 'push');
            app.GetPointCloudButton.ButtonPushedFcn = createCallbackFcn(app, @GetPointCloudButtonPushed2, true);
            app.GetPointCloudButton.WordWrap = 'on';
            app.GetPointCloudButton.Position = [239 29 77 58];
            app.GetPointCloudButton.Text = 'Get Point Cloud';

            % Create PCDownsamplingSpinner_2Label
            app.PCDownsamplingSpinner_2Label = uilabel(app.SELECTROIFORPOINTCLOUDPROCESSINGPanel);
            app.PCDownsamplingSpinner_2Label.HorizontalAlignment = 'right';
            app.PCDownsamplingSpinner_2Label.WordWrap = 'on';
            app.PCDownsamplingSpinner_2Label.Position = [12 23 86 35];
            app.PCDownsamplingSpinner_2Label.Text = 'PC Downsampling';

            % Create PCDownsamplingSpinner
            app.PCDownsamplingSpinner = uispinner(app.SELECTROIFORPOINTCLOUDPROCESSINGPanel);
            app.PCDownsamplingSpinner.Step = 0.001;
            app.PCDownsamplingSpinner.Limits = [0 Inf];
            app.PCDownsamplingSpinner.Position = [113 30 100 22];
            app.PCDownsamplingSpinner.Value = 0.01;

            % Create POINTCLOUDEDITORPanel
            app.POINTCLOUDEDITORPanel = uipanel(app.POINTCLOUDEDITORTab);
            app.POINTCLOUDEDITORPanel.TitlePosition = 'centertop';
            app.POINTCLOUDEDITORPanel.Title = 'POINT CLOUD EDITOR';
            app.POINTCLOUDEDITORPanel.Position = [9 12 355 271];

            % Create CropCloudButton
            app.CropCloudButton = uibutton(app.POINTCLOUDEDITORPanel, 'push');
            app.CropCloudButton.ButtonPushedFcn = createCallbackFcn(app, @CropCloudButtonPushed2, true);
            app.CropCloudButton.Position = [15 195 201 39];
            app.CropCloudButton.Text = 'Crop Cloud';

            % Create SelectDensifyAreaButton
            app.SelectDensifyAreaButton = uibutton(app.POINTCLOUDEDITORPanel, 'push');
            app.SelectDensifyAreaButton.ButtonPushedFcn = createCallbackFcn(app, @SelectDensifyAreaButtonPushed, true);
            app.SelectDensifyAreaButton.WordWrap = 'on';
            app.SelectDensifyAreaButton.Position = [15 78 110 36];
            app.SelectDensifyAreaButton.Text = 'Select Densify Area';

            % Create ResetPointsButton_Density
            app.ResetPointsButton_Density = uibutton(app.POINTCLOUDEDITORPanel, 'push');
            app.ResetPointsButton_Density.ButtonPushedFcn = createCallbackFcn(app, @ResetPointsButton_DensityPushed, true);
            app.ResetPointsButton_Density.WordWrap = 'on';
            app.ResetPointsButton_Density.Position = [225 149 118 85];
            app.ResetPointsButton_Density.Text = 'Reset Cloud   Points';

            % Create SelectUncompressAreaButton
            app.SelectUncompressAreaButton = uibutton(app.POINTCLOUDEDITORPanel, 'push');
            app.SelectUncompressAreaButton.ButtonPushedFcn = createCallbackFcn(app, @SelectUncompressAreaButtonPushed, true);
            app.SelectUncompressAreaButton.WordWrap = 'on';
            app.SelectUncompressAreaButton.Position = [15 26 110 36];
            app.SelectUncompressAreaButton.Text = 'Select Uncompress Area';

            % Create ResetButton_Uncompress
            app.ResetButton_Uncompress = uibutton(app.POINTCLOUDEDITORPanel, 'push');
            app.ResetButton_Uncompress.ButtonPushedFcn = createCallbackFcn(app, @ResetButton_UncompressPushed, true);
            app.ResetButton_Uncompress.WordWrap = 'on';
            app.ResetButton_Uncompress.Position = [225 29 118 85];
            app.ResetButton_Uncompress.Text = 'Reset Cloud Densification';

            % Create RemovePointsButton
            app.RemovePointsButton = uibutton(app.POINTCLOUDEDITORPanel, 'push');
            app.RemovePointsButton.ButtonPushedFcn = createCallbackFcn(app, @RemovePointsButtonPushed, true);
            app.RemovePointsButton.Position = [15 149 201 39];
            app.RemovePointsButton.Text = 'Remove Points';

            % Create SpinnerDensity
            app.SpinnerDensity = uispinner(app.POINTCLOUDEDITORPanel);
            app.SpinnerDensity.Step = 0.0001;
            app.SpinnerDensity.ValueChangingFcn = createCallbackFcn(app, @SpinnerDensityValueChanging, true);
            app.SpinnerDensity.Limits = [0 Inf];
            app.SpinnerDensity.Position = [133 78 83 36];

            % Create SpinnerUncompress
            app.SpinnerUncompress = uispinner(app.POINTCLOUDEDITORPanel);
            app.SpinnerUncompress.Step = 0.001;
            app.SpinnerUncompress.ValueChangingFcn = createCallbackFcn(app, @SpinnerUncompressValueChanging, true);
            app.SpinnerUncompress.Limits = [0 Inf];
            app.SpinnerUncompress.Position = [133 26 83 36];

            % Create EditorBrowserLabel
            app.EditorBrowserLabel = uilabel(app.POINTCLOUDEDITORTab);
            app.EditorBrowserLabel.Position = [144 496 84 22];
            app.EditorBrowserLabel.Text = 'Editor Browser';

            % Create ExitButton
            app.ExitButton = uibutton(app.UIFigure, 'push');
            app.ExitButton.ButtonPushedFcn = createCallbackFcn(app, @ExitButtonPushed, true);
            app.ExitButton.Position = [1023 9 100 22];
            app.ExitButton.Text = 'Exit';

            % Show the figure after all components are created
            app.UIFigure.Visible = 'on';
        end
    end

    % App creation and deletion
    methods (Access = public)

        % Construct app
        function app = App_AQUISICAO_IMAGEM_testes

            % Create UIFigure and components
            createComponents(app)

            % Register the app with App Designer
            registerApp(app, app.UIFigure)

            % Execute the startup function
            runStartupFcn(app, @startupFcn)

            if nargout == 0
                clear app
            end
        end

        % Code that executes before app deletion
        function delete(app)

            % Delete UIFigure when app is deleted
            delete(app.UIFigure)
        end
    end
end