---
# System prepended metadata

title: MapDrawer.cpp

---

# MapDrawer.cpp


### MapDrawer::GetCurrentOpenGLCameraMatrix()
將相機姿態mCameraPose由Mat類型轉化為OpenGlMatrix類型
在[Viewer::Run()](#Viewer::Run())中引用

#### 函式流程
1. 取得相機的姿態
2. 將姿態變成轉換矩陣

#### 流程詳解

1. 取得相機的姿態
```
if(!mCameraPose.empty())
{
    cv::Mat Rwc(3,3,CV_32F);
    cv::Mat twc(3,1,CV_32F);
    {
        unique_lock<mutex> lock(mMutexCamera);
        Rwc = mCameraPose.rowRange(0,3).colRange(0,3).t();
        twc = -Rwc*mCameraPose.rowRange(0,3).col(3);
    }
```

2. 將姿態變成轉換矩陣
```
    M.m[0] = Rwc.at<float>(0,0);
    M.m[1] = Rwc.at<float>(1,0);
    M.m[2] = Rwc.at<float>(2,0);
    M.m[3]  = 0.0;

    M.m[4] = Rwc.at<float>(0,1);
    M.m[5] = Rwc.at<float>(1,1);
    M.m[6] = Rwc.at<float>(2,1);
    M.m[7]  = 0.0;

    M.m[8] = Rwc.at<float>(0,2);
    M.m[9] = Rwc.at<float>(1,2);
    M.m[10] = Rwc.at<float>(2,2);
    M.m[11]  = 0.0;

    M.m[12] = twc.at<float>(0);
    M.m[13] = twc.at<float>(1);
    M.m[14] = twc.at<float>(2);
    M.m[15]  = 1.0;
}
else
    M.SetIdentity();
```

###  MapDrawer::DrawCurrentCamera()
繪製當前相機
在[Viewer::Run()](#Viewer::Run())
#### 定義
```
void MapDrawer::DrawCurrentCamera(pangolin::OpenGlMatrix &Twc) //輸入轉換矩陣
```

#### 函式流程
1. 計算相機在世界座標的位置
2. 根據相機姿態畫出當前相機姿態對應的綠色方框


#### 流程詳解

1. 計算相機在世界座標的位置
```
//相機模型大小：寬度佔總寬度比例為0.08
const float &w = mCameraSize;
const float h = w*0.75;
const float z = w*0.6;

//儲存當前姿態
glPushMatrix();

//將4*4的矩陣Twc.m右乘一個當前矩陣
//（由於使用了glPushMatrix函數，因此當前幀矩陣為世界坐標系下的單位矩陣）
//因為OpenGL中的矩陣為列優先存儲，因此實際為Tcw，即相機在世界坐標下的位姿
#ifdef HAVE_GLES
    glMultMatrixf(Twc.m);
#else
    glMultMatrixd(Twc.m);
#endif
```

2. 根據相機姿態畫出當前相機姿態對應的綠色方框
```
//設置繪製圖形時線的寬度
glLineWidth(mCameraLineWidth);
//設置當前顏色為綠色(相機圖標顯示為綠色)
glColor3f(0.0f,1.0f,0.0f);
//用線將下面的頂點兩兩相連
glBegin(GL_LINES);
glVertex3f(0,0,0);
glVertex3f(w,h,z);
glVertex3f(0,0,0);
glVertex3f(w,-h,z);
glVertex3f(0,0,0);
glVertex3f(-w,-h,z);
glVertex3f(0,0,0);
glVertex3f(-w,h,z);

glVertex3f(w,h,z);
glVertex3f(w,-h,z);

glVertex3f(-w,h,z);
glVertex3f(-w,-h,z);

glVertex3f(-w,h,z);
glVertex3f(w,h,z);

glVertex3f(-w,-h,z);
glVertex3f(w,-h,z);
glEnd();

glPopMatrix();
```


### MapDrawer::DrawKeyFrames()
繪製當前關鍵幀
在[Viewer::Run()](#Viewer::Run())

#### 函式流程
1. 取出所有的關鍵幀
2. 顯示所有關鍵幀
3. 顯示本質圖(Essential Graph)


#### 流程詳解

1. 取出所有的關鍵幀
```
//歷史關鍵幀圖標：寬度佔總寬度比例為0.05
const float &w = mKeyFrameSize;
const float h = w*0.75;
const float z = w*0.6;

//取出 vector<KeyFrame*>(mspKeyFrames.begin(),mspKeyFrames.end());
const vector<KeyFrame*> vpKFs = mpMap->GetAllKeyFrames();
```

2. 顯示所有關鍵幀
```
//通過顯示界面選擇是否顯示歷史關鍵幀圖標
if(bDrawKF)
{
    for(size_t i=0; i<vpKFs.size(); i++)
    {
        KeyFrame* pKF = vpKFs[i];
        //轉置, OpenGL中的矩陣為列優先存儲
        cv::Mat Twc = pKF->GetPoseInverse().t();

        glPushMatrix();

        //（由於使用了glPushMatrix函數，因此當前幀矩陣為世界坐標系下的單位矩陣）
        //因為OpenGL中的矩陣為列優先存儲，因此實際為Tcw，即相機在世界坐標下的位姿
        glMultMatrixf(Twc.ptr<GLfloat>(0));

        //設置繪製圖形時線的寬度
        glLineWidth(mKeyFrameLineWidth);
        //設置當前顏色為藍色(關鍵幀圖標顯示為藍色)
        glColor3f(0.0f,0.0f,1.0f);
        //用線將下面的頂點兩兩相連
        glBegin(GL_LINES);
        glVertex3f(0,0,0);
        glVertex3f(w,h,z);
        glVertex3f(0,0,0);
        glVertex3f(w,-h,z);
        glVertex3f(0,0,0);
        glVertex3f(-w,-h,z);
        glVertex3f(0,0,0);
        glVertex3f(-w,h,z);

        glVertex3f(w,h,z);
        glVertex3f(w,-h,z);

        glVertex3f(-w,h,z);
        glVertex3f(-w,-h,z);

        glVertex3f(-w,h,z);
        glVertex3f(w,h,z);

        glVertex3f(-w,-h,z);
        glVertex3f(w,-h,z);
        glEnd();

        glPopMatrix();
    }
}
```

3. 顯示本質圖(Essential Graph)
```
/**已知共視圖中存儲了所有關鍵幀的共視關係，本徵圖中對邊進行了優化,
保存了所有節點,只存儲了具有較多共視點的邊,用於進行優化，而生成樹則進一步進行了優化,
保存了所有節點,但是值保存具有最多共視地圖點的關鍵幀的邊**/

//通過顯示界面選擇是否顯示關鍵幀連接關係
if(bDrawGraph)
{
    //設置繪製圖形時線的寬度
    glLineWidth(mGraphLineWidth);
    //設置共視圖連接線為綠色，透明度為0.6f
    glColor4f(0.0f,1.0f,0.0f,0.6f);
    glBegin(GL_LINES);

    //遍歷關鍵幀
    for(size_t i=0; i<vpKFs.size(); i++)
    {
        // Covisibility Graph
//3.1. 共視程度比較高的共視關鍵幀用線連接
        //遍歷每一個關鍵幀，得到它們共視程度比較高的關鍵幀
        const vector<KeyFrame*> vCovKFs = vpKFs[i]->GetCovisiblesByWeight(100);
        //遍歷每一個關鍵幀，得到它在世界坐標系下的相機坐標
        cv::Mat Ow = vpKFs[i]->GetCameraCenter();
        if(!vCovKFs.empty())
        {
            for(vector<KeyFrame*>::const_iterator vit=vCovKFs.begin(), vend=vCovKFs.end(); vit!=vend; vit++)
            {
                if((*vit)->mnId<vpKFs[i]->mnId)
                    continue;
                cv::Mat Ow2 = (*vit)->GetCameraCenter();
                glVertex3f(Ow.at<float>(0),Ow.at<float>(1),Ow.at<float>(2));
                glVertex3f(Ow2.at<float>(0),Ow2.at<float>(1),Ow2.at<float>(2));
            }
        }

        // Spanning tree
//3.2. 連接最小生成樹
        KeyFrame* pParent = vpKFs[i]->GetParent();
        if(pParent)
        {
            cv::Mat Owp = pParent->GetCameraCenter();
            glVertex3f(Ow.at<float>(0),Ow.at<float>(1),Ow.at<float>(2));
            glVertex3f(Owp.at<float>(0),Owp.at<float>(1),Owp.at<float>(2));
        }

        // Loops
//3.3 連接閉環時形成的連接關係
        set<KeyFrame*> sLoopKFs = vpKFs[i]->GetLoopEdges();
        for(set<KeyFrame*>::iterator sit=sLoopKFs.begin(), send=sLoopKFs.end(); sit!=send; sit++)
        {
            if((*sit)->mnId<vpKFs[i]->mnId)
                continue;
            cv::Mat Owl = (*sit)->GetCameraCenter();
            glVertex3f(Ow.at<float>(0),Ow.at<float>(1),Ow.at<float>(2));
            glVertex3f(Owl.at<float>(0),Owl.at<float>(1),Owl.at<float>(2));
        }
    }

    glEnd();
}
```


### MapDrawer::DrawMapPoints()
繪製當前地圖點
在[Viewer::Run()](#Viewer::Run())


#### 函式流程
1. 取出所有的地圖點
2. 繪製不包含局部地圖點地圖點(黑色)
3. 繪製局部地圖點(紅色)


#### 流程詳解
1. 取出所有的地圖點
```
const vector<MapPoint*> &vpMPs = mpMap->GetAllMapPoints();
//取出mvpReferenceMapPoints，也即局部地圖d點
const vector<MapPoint*> &vpRefMPs = mpMap->GetReferenceMapPoints();
```
mpMap->GetAllMapPoints(): 跳到[Map::GetAllMapPoints()](#Map::GetAllMapPoints())

mpMap->GetReferenceMapPoints(): 跳到[Map::GetReferenceMapPoints()](#Map::GetReferenceMapPoints())

2. 繪製不包含局部地圖點地圖點(黑色)
```
//將vpRefMPs從vector容器類型轉化為set容器類型，便於使用set::count快速統計
set<MapPoint*> spRefMPs(vpRefMPs.begin(), vpRefMPs.end());

if(vpMPs.empty())
    return;

// for AllMapPoints
//顯示所有的地圖點（不包括局部地圖點），大小為2個像素，黑色
glPointSize(mPointSize);
glBegin(GL_POINTS);
glColor3f(0.0,0.0,0.0);

for(size_t i=0, iend=vpMPs.size(); i<iend;i++)
{
    // 不包括ReferenceMapPoints（局部地圖點）
    if(vpMPs[i]->isBad() || spRefMPs.count(vpMPs[i]))
        continue;
    cv::Mat pos = vpMPs[i]->GetWorldPos();
    glVertex3f(pos.at<float>(0),pos.at<float>(1),pos.at<float>(2));
}
glEnd();
```

3. 繪製局部地圖點(紅色)
```
// for ReferenceMapPoints
//顯示局部地圖點，大小為2個像素，紅色
glPointSize(mPointSize);
glBegin(GL_POINTS);
glColor3f(1.0,0.0,0.0);

for(set<MapPoint*>::iterator sit=spRefMPs.begin(), send=spRefMPs.end(); sit!=send; sit++)
{
    if((*sit)->isBad())
        continue;
    cv::Mat pos = (*sit)->GetWorldPos();
    glVertex3f(pos.at<float>(0),pos.at<float>(1),pos.at<float>(2));

}
glEnd();
```