From b81eab8bc78df828979dc501048a84a293b94266 Mon Sep 17 00:00:00 2001
From: mingf2 <fm140905@gmail.com>
Date: Sat, 15 May 2021 15:35:26 -0500
Subject: [PATCH] dynamic update canvas

---
 Headers/draw.h   |  48 ++++++++++++++++++++++
 Sources/draw.cpp | 105 +++++++++++++++++++++++++++++++++++++++++++++++
 Sources/main.cpp |  38 +++++++++++++----
 3 files changed, 183 insertions(+), 8 deletions(-)

diff --git a/Headers/draw.h b/Headers/draw.h
index 09069d6..fbca630 100644
--- a/Headers/draw.h
+++ b/Headers/draw.h
@@ -11,6 +11,54 @@
 
 #include "../Headers/setup.h"
 
+class Image
+{
+private:
+    /* data */
+public:
+    const Setup& config;
+    TCanvas* canvas;
+    TH2D* histo;
+    void initDrawImage();
+    // gridlines
+    const int Nl = 19; // Number of drawn latitudes
+    const int NL = 19; // Number of drawn longitudes
+    int M  = 30;
+    std::vector<TGraph*> latitudes;
+    std::vector<TGraph*> longitudes;
+    void drawGridlines();
+    // source marker
+    TEllipse* sourceMarker;
+    void drawSource();
+    void addCone(const std::vector<Cone> cones);
+    Image(const Setup& config_): config(config_) {
+        initDrawImage();
+        drawGridlines();
+        drawSource();
+    }
+    ~Image(){
+        if (canvas)
+            delete canvas;
+        if (histo)
+            delete histo;
+        for (int i = 0; i < Nl; i++)
+        {
+            if (latitudes[i])
+                delete latitudes[i];
+        }
+        for (int i = 0; i < NL; i++)
+        {
+            if (longitudes[i])
+                delete longitudes[i];
+        }
+        if (!sourceMarker)
+        {
+            delete sourceMarker;
+        }
+        
+    }
+};
+
 int Backprojection(const Setup& config, const std::vector<Cone>& cones, 
                    std::vector<std::vector<double>>& image);
 
diff --git a/Sources/draw.cpp b/Sources/draw.cpp
index 97a403a..ad27a8a 100644
--- a/Sources/draw.cpp
+++ b/Sources/draw.cpp
@@ -1,5 +1,110 @@
 #include "../Headers/draw.h"
 
+void Image::initDrawImage() {
+    histo = new TH2D("ROI", " ; Azimuth; Elevation", 
+                            config.phiBins, -180, 180, 
+                            config.thetaBins, -90, 90);
+    canvas = new TCanvas("THCanvas","Sinocanvas", 1000, 500);
+    // init image
+    for (int i = 0; i < config.phiBins; i++)
+    {
+        for (int j = 0; j < config.thetaBins; j++)
+        {
+            histo->SetBinContent(i+1, j+1, 0);
+        }
+    }
+    gStyle->SetOptStat(0);
+    histo->GetZaxis()->SetLabelSize(0.02);
+    histo->Draw("z aitoff");
+}
+
+void Image::drawGridlines() {
+    float conv=M_PI/180;
+    float la, lo, x, y, z;
+    for (int j=0;j<Nl;++j) {
+        // latitudes[j]=new TGraph();
+        latitudes.push_back(new TGraph());
+        la = -90+180/(Nl-1)*j;
+        for (int i=0;i<M+1;++i) {
+            lo = -180+360/M*i;
+            z  = sqrt(1+cos(la*conv)*cos(lo*conv/2));
+            x  = 180*cos(la*conv)*sin(lo*conv/2)/z;
+            y  = 90*sin(la*conv)/z;
+            latitudes[j]->SetPoint(i,x,y);
+        }
+    } 
+    
+    for (int j=0;j<NL;++j) {
+        // longitudes[j]=new TGraph();
+        longitudes.push_back(new TGraph());
+        lo = -180+360/(NL-1)*j;
+        for (int i=0;i<M+1;++i) {
+            la = -90+180/M*i;
+            z  = sqrt(1+cos(la*conv)*cos(lo*conv/2));
+            x  = 180*cos(la*conv)*sin(lo*conv/2)/z;
+            y  = 90*sin(la*conv)/z;
+            longitudes[j]->SetPoint(i,x,y);
+        }
+    }
+    // Draw the grid	
+    TPad *pad2 = new TPad("pad2","",0,0,1,1);
+    pad2->SetFillStyle(4000);
+    pad2->SetFillColor(0);
+    pad2->SetBorderSize(0);
+    pad2->SetFrameBorderMode(0);
+    pad2->SetFrameLineColor(0); 
+    pad2->SetFrameBorderMode(0);
+    pad2->Draw();
+    pad2->cd();
+    Double_t ymin = -89.5;
+    Double_t ymax = 89.5;
+    Double_t dy = (ymax-ymin)/0.8; //10 per cent margins top and bottom
+    Double_t xmin = -180;
+    Double_t xmax = 180;
+    Double_t dx = (xmax-xmin)/0.8; //10 per cent margins left and right
+
+    pad2->Range(xmin-0.1*dx,ymin-0.1*dy,xmax+0.1*dx,ymax+0.1*dy);
+
+    for (int j=0;j<Nl;++j) latitudes[j]->Draw("l");
+    for (int j=0;j<NL;++j) longitudes[j]->Draw("l");
+}
+
+void Image::drawSource() {
+    // draw source marker
+    float conv=M_PI/180;
+    double sigma = 1;
+    double Ax, Ay;
+    aitoff2xy(config.truePhi / conv, config.trueTheta / conv, Ax, Ay);
+    sourceMarker = new TEllipse(Ax, Ay, sigma, sigma);
+    sourceMarker->SetFillColor(0);
+    sourceMarker->SetFillStyle(0);
+    sourceMarker->SetLineWidth(2);
+    sourceMarker->SetLineColor(kRed);
+    sourceMarker->Draw("SAME");
+}
+
+void Image::addCone(const std::vector<Cone> cones){
+    // project cones onto the spherical surface
+    // std::cout << "Projecting cones onto the designated spherical surface..."<<std::endl;
+    double alpha(0);
+    double beta(0);
+    for (const Cone& event : cones)
+    {
+        // update the image
+        //TODO: add the uncertainty
+        alpha = event.cosHalfAngle;
+        for (int i = 0; i < config.thetaBins; i++)
+        {
+            for (int j = 0; j < config.phiBins; j++)
+            {
+                beta = getCosAngle(event.apex - config.xbs[i][j], event.axis);
+                histo->SetBinContent(j+1, i+1, histo->GetBinContent(j+1, i+1) + std::exp(-(beta-alpha)*(beta-alpha) / 0.002));
+                // histo->SetBinContent(j+1, i+1, std::exp(-(beta-alpha)*(beta-alpha) / 0.002));
+            }
+        }
+    }
+}
+
 int Backprojection(const Setup& config, const std::vector<Cone>& cones, 
                    std::vector<std::vector<double>>& image){
     // project cones onto the spherical surface
diff --git a/Sources/main.cpp b/Sources/main.cpp
index d3765fd..a98a482 100644
--- a/Sources/main.cpp
+++ b/Sources/main.cpp
@@ -3,6 +3,7 @@
 #include <cstdlib>
 #include <ctime>
 
+#include "TSystem.h"
 #include "TApplication.h"
 
 #include "../Headers/setup.h"
@@ -10,22 +11,43 @@
 #include "../Headers/draw.h"
 
 int main(int argc, char** argv) {
+    TApplication *myapp = new TApplication("myApp", 0, 0);
     // init
     const Setup config(10);
-    // simulate some cones
+    // simulate some cones on worker thread
     std::vector<Cone> cones;
     std::srand(std::time(nullptr));
-    for (int i = 0; i < config.nCones; i++)
+    for (int i = 0; i < 10; i++)
     {
         cones.push_back(createCone(config));
     }
-    // generate a projection image
+    // generate a projection image on master thread
     // init image
-    std::vector<std::vector<double>> image(config.thetaBins, std::vector<double>(config.phiBins, 0));
-    // draw    
-    TApplication *myapp = new TApplication("myApp", 0, 0);
-    Backprojection(config, cones, image);
-    drawImage(config, image);
+    // std::vector<std::vector<double>> image(config.thetaBins, std::vector<double>(config.phiBins, 0));
+    // draw
+    Image image(config);
+    image.canvas->Draw();
+    std::cout << "init draw" << '\n';
+    int counter(1);
+    while (true)
+    {
+        // update image
+        for (int i = 0; i < 5; i++)
+        {
+            cones[i] = createCone(config);
+        }
+        image.addCone(cones);
+        std::cout << "draw " << counter << '\n';
+        counter++;
+        // redraw
+        image.canvas->Modified();
+        image.canvas->Update();
+        gSystem->Sleep(100);
+        gSystem->ProcessEvents();
+    }
+    
+    // Backprojection(config, cones, image);
+    // drawImage(config, image);
     myapp->Run();
     return 0;
 }
\ No newline at end of file
-- 
GitLab