搭建一個和CC一樣的點雲編輯器


本文代碼CSDN鏈接:

http://download.csdn.net/download/qq_30547073/10112583

對應的百度網盤鏈接:

鏈接:https://pan.baidu.com/s/1i5MRSbF 密碼:ku8f


好嘞。

這一次手把手教大家搭建一個和CC一模一樣的點雲精簡器

老規矩,我們先上效果



所有源碼按照規矩分享到百度網盤中供大家測試。release下的exe也是可以直接運行的。

希望大家發現問題後及時聯繫我,QQ 4987710226  希望共同學習。
鏈接:https://pan.baidu.com/s/1i5MRSbF 密碼:ku8f

廢話不多說,上核心代碼

enum SimplifyModel
{
    Random_Simplify,
    Space_Simplify,
    Octree_Simplify,
};

class qScarlet_CloudSimplifyFrm : public QWidget
{
    Q_OBJECT
public:
    explicit qScarlet_CloudSimplifyFrm(QWidget *parent = 0);
    qScarlet_CloudSimplifyFrm(int CloudIndex ,int PtNum,QWidget *parent = 0);
    //qScarlet_CloudSimplifyFrm(int in,QWidget *parent = 0);

    void SetCloudIndex(int);
    void SetCloudNum(int);
    int GetCloudIndex();
    int GetOrigionCloudNum();
    int GetAfterRandomCloudNum();
    SimplifyModel GetSimplifyMode();
signals:
    void signal_OnOkBTClick_Random();
    void signal_OnOkBTClick_Space();
    void signal_OnOkBTClick_Octree();
public slots:
    void slot_CurrentMethodChanged(int);
    void slot_ThisCancel();
    void slot_ThisApply();
    void slot_SetRandomSimplifyPtNum(int);
private:
    void start();
    void CreateUpperPartWidget();
    void CreateRandomPartWidget();
    void CreateSpacePartWidget();
    void CreateOctreePartWidget();
    void CreateGroupPartLayOut();
    void CreateOkCancelPartWidget();

    QGroupBox*m_Sampling_parametersGroup;

    QWidget *m_UppterPartWidget;
    QLabel*m_Method_Label;
    QComboBox*m_MethodSelector_Combobox;

    QWidget *m_extent_RandomSimplifyWidget;
    QLabel*m_None_Label;
    QLabel*m_All_Label;
    QSlider*m_NoneAll_Slider;
    QLabel*m_RemainingPoints_Label;
    QSpinBox*m_RemainingPoints_SpinBox;

    QWidget *m_extent_SpaceSimplifyWidget;
    QLabel*m_Large_Label;
    QLabel*m_Small_Label;
    QSlider*m_LargeSmall_Slider;
    QLabel*m_MinSpaceBetweenPoints_Label;
    QSpinBox*m_MinSpaceBetweenPoints_SpinBox;

    QWidget *m_extent_OctreeSimplifyWidget;
    QLabel*m_Min_Label;
    QLabel*m_Max_Label;
    QSlider*m_MinMax_Slider;
    QLabel*m_Subdivision_Label;
    QSpinBox*m_Subdivision_SpinBox;

    QStringListModel *typeModel;

    QWidget *m_OkCancelWidget;
    QPushButton*m_ApplyBT;//Apply the method to cloud Simplify
    QPushButton*m_CancelBT;//Cancel and not do anything on cloud

    int m_CloudIndex;
    int m_PtNum;
    int m_PtNum_SimplifyRandom;
    SimplifyModel m_SimplifyMode;
};
//下面是CPP文件,其實代碼有很多是重複的,同學可以先看一下Layout部分的基本原理再來看代碼:
qScarlet_CloudSimplifyFrm::qScarlet_CloudSimplifyFrm(QWidget *parent):
    QWidget(parent)
{
    start();
}

qScarlet_CloudSimplifyFrm::qScarlet_CloudSimplifyFrm(int CloudIndex ,int PtNum,QWidget *parent )
    :m_CloudIndex(CloudIndex),m_PtNum(PtNum),QWidget(parent)
{
    start();
}

void qScarlet_CloudSimplifyFrm::SetCloudIndex(int in_CloudIndex)
{
    m_CloudIndex = in_CloudIndex;
}
void qScarlet_CloudSimplifyFrm::SetCloudNum(int in_CloudNum)
{
    m_PtNum = in_CloudNum;
}
void qScarlet_CloudSimplifyFrm::slot_SetRandomSimplifyPtNum(int PtNumAfterSimplify)
{
    m_PtNum_SimplifyRandom = PtNumAfterSimplify;
}

int qScarlet_CloudSimplifyFrm::GetCloudIndex()
{
    return m_CloudIndex;
}
int qScarlet_CloudSimplifyFrm::GetOrigionCloudNum()
{
    return m_PtNum;
}
int qScarlet_CloudSimplifyFrm::GetAfterRandomCloudNum()
{
    return m_PtNum_SimplifyRandom;
}
SimplifyModel qScarlet_CloudSimplifyFrm::GetSimplifyMode()
{
    return m_SimplifyMode;
}

void qScarlet_CloudSimplifyFrm::start()
{
    CreateUpperPartWidget();
    CreateRandomPartWidget();
    CreateSpacePartWidget();
    CreateOctreePartWidget();
    CreateOkCancelPartWidget();

    CreateGroupPartLayOut();
}

void qScarlet_CloudSimplifyFrm::CreateUpperPartWidget()
{
    m_UppterPartWidget =new QWidget();
    m_Method_Label = new QLabel("Method");
    m_MethodSelector_Combobox =new QComboBox();
    QGridLayout *UpperPart_GridLayout = new QGridLayout();
    UpperPart_GridLayout->addWidget(m_Method_Label, 0, 0,1,1);
    UpperPart_GridLayout->addWidget(m_MethodSelector_Combobox, 0, 1,1,3);
    //UpperPart_GridLayout->setHorizontalSpacing(200);
    m_UppterPartWidget->setLayout(UpperPart_GridLayout);     
}

void qScarlet_CloudSimplifyFrm::CreateRandomPartWidget()
{
    m_extent_RandomSimplifyWidget =new QWidget();
    m_None_Label =new QLabel("None");
    m_All_Label = new QLabel("All");
    m_NoneAll_Slider = new QSlider(Qt::Orientation::Horizontal);
    m_RemainingPoints_Label = new QLabel("Remaining Points");
    m_RemainingPoints_SpinBox= new QSpinBox();
    QGridLayout* RandomExtentLayout= new QGridLayout();;
    RandomExtentLayout->addWidget(m_None_Label,0, 0,1,1);
    RandomExtentLayout->addWidget(m_All_Label,0, 3,1,1);
    RandomExtentLayout->addWidget(m_NoneAll_Slider,1, 0,1,4);
    RandomExtentLayout->addWidget(m_RemainingPoints_Label,2, 0,1,1);
    RandomExtentLayout->addWidget(m_RemainingPoints_SpinBox,2, 1,1,1);
    m_extent_RandomSimplifyWidget->setLayout(RandomExtentLayout);

    m_NoneAll_Slider->setRange(1,m_PtNum);
    m_RemainingPoints_SpinBox->setRange(1,m_PtNum);
    connect(m_NoneAll_Slider,SIGNAL(valueChanged(int)),m_RemainingPoints_SpinBox,SLOT(setValue(int )));
    connect(m_NoneAll_Slider,SIGNAL(valueChanged(int)),this,SLOT(slot_SetRandomSimplifyPtNum(int)));
    connect(m_RemainingPoints_SpinBox,SIGNAL(valueChanged(int)),m_NoneAll_Slider,SLOT(setValue(int)));

    m_NoneAll_Slider->setValue(m_PtNum/2);
    m_NoneAll_Slider->setSingleStep(m_PtNum/20);//set space
    m_RemainingPoints_SpinBox->setSingleStep(m_PtNum/20);//set space

}

void qScarlet_CloudSimplifyFrm::CreateSpacePartWidget()
{
    m_extent_SpaceSimplifyWidget =new QWidget();
    m_Large_Label =new QLabel("Large");
    m_Small_Label = new QLabel("Small");
    m_LargeSmall_Slider = new QSlider(Qt::Orientation::Horizontal);
    m_MinSpaceBetweenPoints_Label = new QLabel("Min Space Between Points");
    m_MinSpaceBetweenPoints_SpinBox= new QSpinBox();
    QGridLayout* SpaceExtentLayout= new QGridLayout();;
    SpaceExtentLayout->addWidget(m_Large_Label,0, 0,1,1);
    SpaceExtentLayout->addWidget(m_Small_Label,0, 3,1,1);
    SpaceExtentLayout->addWidget(m_LargeSmall_Slider,1, 0,1,4);
    SpaceExtentLayout->addWidget(m_MinSpaceBetweenPoints_Label,2, 0,1,1);
    SpaceExtentLayout->addWidget(m_MinSpaceBetweenPoints_SpinBox,2, 1,1,1);
    m_extent_SpaceSimplifyWidget->setLayout(SpaceExtentLayout);
}

void qScarlet_CloudSimplifyFrm::CreateOctreePartWidget()
{
    m_extent_OctreeSimplifyWidget =new QWidget();
    m_Min_Label =new QLabel("Min");
    m_Max_Label = new QLabel("Max");
    m_MinMax_Slider = new QSlider(Qt::Orientation::Horizontal);
    m_Subdivision_Label = new QLabel("Subdivision level");
    m_Subdivision_SpinBox= new QSpinBox();
    QGridLayout* OctreeExtentLayout= new QGridLayout();
    OctreeExtentLayout->addWidget(m_Min_Label,0, 0,1,1);
    OctreeExtentLayout->addWidget(m_Max_Label,0, 3,1,1);
    OctreeExtentLayout->addWidget(m_MinMax_Slider,1, 0,1,4);
    OctreeExtentLayout->addWidget(m_Subdivision_Label,2, 0,1,1);
    OctreeExtentLayout->addWidget(m_Subdivision_SpinBox,2, 1,1,1);
    m_extent_OctreeSimplifyWidget->setLayout(OctreeExtentLayout);
}

void qScarlet_CloudSimplifyFrm::CreateOkCancelPartWidget()
{
    m_OkCancelWidget =new QWidget();
    m_ApplyBT = new QPushButton("Apply");
    m_CancelBT = new QPushButton("Cancel");
    QGridLayout* ApplyCancelLayout= new QGridLayout();
    ApplyCancelLayout->addWidget(m_ApplyBT,0, 2,1,1);
    ApplyCancelLayout->addWidget(m_CancelBT,0, 3,1,1);
    m_OkCancelWidget->setLayout(ApplyCancelLayout);
    connect(m_ApplyBT,SIGNAL(clicked()),this,SLOT(slot_ThisApply()));
    connect(m_CancelBT,SIGNAL(clicked()),this,SLOT(slot_ThisCancel()));
}

void qScarlet_CloudSimplifyFrm::CreateGroupPartLayOut()
{
    m_Sampling_parametersGroup = new QGroupBox("Sampling Parameters");
    QVBoxLayout *AllWidgetLayout = new QVBoxLayout();
    AllWidgetLayout->addWidget(m_UppterPartWidget);
    AllWidgetLayout->addWidget(m_extent_RandomSimplifyWidget);
    AllWidgetLayout->addWidget(m_extent_SpaceSimplifyWidget);
    AllWidgetLayout->addWidget(m_extent_OctreeSimplifyWidget);
    AllWidgetLayout->addWidget(m_OkCancelWidget);
    m_Sampling_parametersGroup->setLayout(AllWidgetLayout);

    //========at Last we set group box in the widget
    QGridLayout* AllGridLayout= new QGridLayout();
    AllGridLayout->addWidget(m_Sampling_parametersGroup);
    this->setLayout(AllGridLayout);

    //=======We add some item in combobx
    QStringList MethodItems;
    MethodItems << tr("Random") << tr("Space") << tr("Octree");
    typeModel = new QStringListModel(MethodItems, this);
    m_MethodSelector_Combobox->setModel(typeModel);
    connect(m_MethodSelector_Combobox,SIGNAL(currentIndexChanged(int)),this,SLOT(slot_CurrentMethodChanged(int)));
    m_MethodSelector_Combobox->setCurrentIndex(1);//=======we Set Another index to Init
    m_MethodSelector_Combobox->setCurrentIndex(0);
    m_NoneAll_Slider->setTickPosition(QSlider::TicksAbove); //draw clock tick above the slider
}

void qScarlet_CloudSimplifyFrm::slot_CurrentMethodChanged(int CurrentMethod)
{
    QString CurrentQString = m_MethodSelector_Combobox->currentText();
    //=====firstly we set all invisible
    m_extent_RandomSimplifyWidget->setVisible(false);
    m_extent_SpaceSimplifyWidget->setVisible(false);
    m_extent_OctreeSimplifyWidget->setVisible(false);

    if(CurrentQString == QString("Random"))
    {
        m_extent_RandomSimplifyWidget->setVisible(true);
        m_SimplifyMode = SimplifyModel::Random_Simplify;
         m_ApplyBT->setEnabled(true);
    }
    //We don't open these two functions for the time being
    else if(CurrentQString == QString("Space"))
    {
        m_extent_SpaceSimplifyWidget->setVisible(true);
        m_SimplifyMode = SimplifyModel::Space_Simplify;
        m_ApplyBT->setEnabled(true);
    }
    else if(CurrentQString == QString("Octree"))
    {
        m_extent_OctreeSimplifyWidget->setVisible(true);
        m_SimplifyMode = SimplifyModel::Octree_Simplify;
        m_ApplyBT->setEnabled(false);
    }
    else
    {

    }
}

void qScarlet_CloudSimplifyFrm::slot_ThisApply()
{
    switch(m_SimplifyMode)
    {
    case Random_Simplify:emit(signal_OnOkBTClick_Random()); break;
    case Space_Simplify:emit(signal_OnOkBTClick_Space());break;
    case Octree_Simplify:emit(signal_OnOkBTClick_Octree());break;
    default:
        break;
    }

}

void qScarlet_CloudSimplifyFrm::slot_ThisCancel()
{
    this->close();
}

界面和CC可以說毫無差別。
單擊apply的時候要進行精簡處理,那麼連接的代碼以及show窗體的代碼如下: 
void qscarlet_opencvMaster::on_actionCloudSimplification_triggered()
{

    QModelIndex SelectedModelindex = treeView3D_GLES2->selectionModel()->currentIndex();
    if(SelectedModelindex.column() == 0&&SelectedModelindex.parent().data().toString() == "Ninja")
    {
        std::vector<qScarlet_GLCloudEngin_ES2*> myCloudEnginVec = m_GLWidget_ES2->GetAllEngin();
        int SelectedCloudIndex = SelectedModelindex.row();
        qScarlet_GLCloudEngin_ES2* CurrentEngin =  myCloudEnginVec[SelectedCloudIndex];
        int PtNum = CurrentEngin->Get_PointNum();
        m_CloudSimplifyFrm = new qScarlet_CloudSimplifyFrm(SelectedCloudIndex,PtNum);
        connect(m_CloudSimplifyFrm,SIGNAL(signal_OnOkBTClick_Random()),this,SLOT(slot_ApplyCloudSimplification_Random()));
        connect(m_CloudSimplifyFrm,SIGNAL(signal_OnOkBTClick_Space()),this,SLOT(slot_ApplyCloudSimplification_Space()));
        connect(m_CloudSimplifyFrm,SIGNAL(signal_OnOkBTClick_Octree()),this,SLOT(slot_ApplyCloudSimplification_Octree()));
        //and we hanve other signal to emit
        m_CloudSimplifyFrm->setAttribute(Qt::WA_DeleteOnClose);//關閉立刻釋放
        m_CloudSimplifyFrm->show();
    }
    else
    {

    }
}

精簡的原理很簡單,主要是產生一定數量的隨機數,然後將隨機數對應的點雲刪除就行了。
對於具體精簡,每個人的接口都不一樣。。。。我這裏就只放隨機數產生器的代碼:
爲什麼這樣呢?因爲rand()函數產生的最大隨機數爲32767,而點雲可達上億,如果想獲得正確的精簡效果就必須產生任意大小的隨機數,普通的做法當然不行。下面就分享給大家任意數字大小的隨機數產生器


//==超級隨機數產生器
const double MinProb = 1.0 / (RAND_MAX + 1);
bool happened(double probability)//probability 0~1
{
    if (probability <= 0)
    {
        return false;
    }
    if (probability<MinProb)
    {
        return rand() == 0 && happened(probability*(RAND_MAX + 1));
    }
    if (rand() <= probability*(RAND_MAX + 1))
    {
        return true;
    }
    return false;
}
//產生0~n-1之間的等概率隨機數
long RandomEngin(long n)
{

    int t = 0;
    if (n <= RAND_MAX)
    {
        long r = RAND_MAX - (RAND_MAX + 1) % n;//尾數
        t = rand();
        while (t > r)
        {
            t = rand();
        }
        return t % n;
    }
    else
    {
        long r = n % (RAND_MAX + 1);//餘數
        if (happened((double)r / n))//取到餘數的概率
        {
            return n - r + RandomEngin(r);
        }
        else
        {
            return rand() + RandomEngin(n / (RAND_MAX + 1))*(RAND_MAX + 1);
        }
    }
}






發佈了41 篇原創文章 · 獲贊 62 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章