#include "PointManagerClass.h"
#include <memory>
#include <QAction>
#include <QCloseEvent>
#include <QColor>
#include <QComboBox>
#include <QDateTime>
#include <QDebug>
#include <QDesktopWidget>
#include <QFileDialog>
#include <QFontComboBox>
#include <QImage>
#include <QLabel>
#include <QMainWindow>
#include <QMenu>
#include <QMenuBar>
#include <QMessageBox>
#include <QProgressDialog>
#include <QRect>
#include <QSettings>
#include <QSpinBox>
#include <QString>
#include <QStringList>
#include <QTextCharFormat>
#include <QTime>
#include <QToolBar>
#include <QToolButton>
#include <QListWidgetItem>

#include <QApplication>
#include <QDateTime> //添加QDateTime头文件
#include <QMovie>
#include <QPixmap>
#include <QSplashScreen>
#include <QTextCodec>

// Point Cloud Library
#include <QColorDialog>
#include <iostream>
#include <pcl/common/common.h>
#include <pcl/console/time.h> // TicToc
#include <pcl/console/time.h>
#include <pcl/filters/convolution_3d.h>
#include <pcl/filters/filter.h>
#include <pcl/filters/radius_outlier_removal.h>
#include <pcl/filters/statistical_outlier_removal.h>
#include <pcl/io/pcd_io.h>
#include <pcl/io/ply_io.h>
#include <pcl/kdtree/kdtree_flann.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/visualization/pcl_visualizer.h>

#include <boost/random.hpp> //随机数
#include <boost/thread/thread.hpp>
#include <iostream>
#include <pcl/console/time.h> // TicToc
#include <pcl/features/normal_3d.h>
#include <pcl/filters/bilateral.h>
#include <pcl/filters/extract_indices.h>
#include <pcl/filters/fast_bilateral.h>
#include <pcl/filters/fast_bilateral_omp.h>
#include <pcl/filters/passthrough.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/io/pcd_io.h>
#include <pcl/io/ply_io.h>
#include <pcl/kdtree/kdtree.h>
#include <pcl/kdtree/kdtree_flann.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/registration/ia_fpcs.h>  // 4PCS算法
#include <pcl/registration/ia_kfpcs.h> //K4PCS算法头文件
#include <pcl/registration/icp.h>
#include <pcl/registration/registration.h>
#include <pcl/search/flann_search.h>
#include <pcl/surface/concave_hull.h>
#include <pcl/surface/gp3.h> //贪婪投影三角化算法类定义的头文件
#include <pcl/surface/marching_cubes_hoppe.h> //移动立方体
#include <pcl/surface/marching_cubes_rbf.h>
#include <pcl/surface/mls.h>     //MLS
#include <pcl/surface/poisson.h> //泊松重建
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <string>
#include <vector>
#include <vtkOutputWindow.h>

#include <pcl/console/time.h>                   // TicToc
#include <pcl/filters/approximate_voxel_grid.h> // 体素滤波
#include <pcl/filters/voxel_grid.h>             // 体素滤波
#include <vtkOutputWindow.h>

#include <boost/thread/thread.hpp>
#include <pcl/ModelCoefficients.h>
#include <pcl/filters/extract_indices.h>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/sample_consensus/method_types.h> //随机参数估计方法
#include <pcl/sample_consensus/model_types.h>  //模型定义
#include <pcl/segmentation/sac_segmentation.h> //RANSAC分割
#include <pcl/visualization/pcl_visualizer.h>
#include <sstream>
#include <stdlib.h> //rand()头文件
#include <vtkMassProperties.h>
#include <vtkPLYReader.h>
#include <vtkSmartPointer.h>
#include <vtkTriangleFilter.h>

#include <Eigen/Core>
#include <iostream>
#include <pcl/common/common.h>
#include <pcl/common/transforms.h>
#include <pcl/features/moment_of_inertia_estimation.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/io/io.h>
#include <pcl/io/pcd_io.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <string>
#include <string>
#include <vector>
#include <vtkAutoInit.h>
#include <pcl/io/vtk_lib_io.h>

//可视化相关头文件
#include <vtkActor.h>
#include <vtkAutoInit.h>
#include <vtkInteractorStyleTrackballCamera.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
// Boost
#include <boost/math/special_functions/round.hpp>

// Visualization Toolkit (VTK)
#include <vtkRenderWindow.h>
#include "inputdialog.h"
#include "BasePCL.h"
#include "ToolDialog.h"




int CloudPointManagerClass::addMeshSTL(QString filepath)
{


    // 生成点云对象
    std::shared_ptr<MeshItemClass> meshItem(new MeshItemClass);
    QFileInfo fileinfo(filepath);
    meshItem->name = fileinfo.fileName();// 文件名
    meshItem->filepath = filepath;
    meshItem->mesh_ptr.reset(new pcl::PolygonMesh);

    // 加载STL文件
    pcl::PolygonMesh mesh;
    pcl::io::loadPolygonFileSTL(filepath.toUtf8().constData(), *(meshItem->mesh_ptr)); // 加载mesh


    // 绑定item
    this->DataList.insert(meshItem->name, meshItem);
    // 添加到 filelist
    QListWidgetItem* item = new QListWidgetItem;

    item->setBackground(QBrush(QColor(220, 230, 250)));
    item->setData(Qt::DisplayRole, meshItem->name);
    item->setData(Qt::CheckStateRole, Qt::Checked);
    this->filelist->addItem(item);
    // 添加到渲染
    meshItem->ViewerShow(this->viewerPtr);
    meshItem->ZoomOnExtend(this->viewerPtr);
    return 0;
}

int CloudPointManagerClass::RemovePointCloud(QString name)
{
    return 0;
}

int CloudPointManagerClass::ZoomOn(QString cloudname)
{
    std::shared_ptr < FileListManagerAbstractItem>  fileItem = this->DataList.value(cloudname);
    fileItem->ZoomOnExtend(this->viewerPtr);
    return 0;
}

QStringList CloudPointManagerClass::getItemNames()
{
    return this->DataList.keys();
}

std::shared_ptr<FileListManagerAbstractItem> CloudPointManagerClass::getItemFromName(QString Name)
{
    if (!this->DataList.contains(Name)) {
        return nullptr;
    }
    else {
        return this->DataList.value(Name);
    }
}

std::shared_ptr<CloudPointItemClass> CloudPointManagerClass::getCloudPointItemFromName(QString Name)
{
    if (!this->DataList.contains(Name)) {
        return nullptr;
    }
    else {
        return std::dynamic_pointer_cast<CloudPointItemClass>(this->DataList.value(Name));
    }
}


void MeshItemClass::ViewerShow(pcl::visualization::PCLVisualizer::Ptr viewer)
{
    viewer->addPolygonMesh(*(this->mesh_ptr), this->name.toUtf8().constData());
    viewer->getRenderWindow()->Render();
}

void MeshItemClass::ZoomOnExtend(pcl::visualization::PCLVisualizer::Ptr viewer)
{
    pcl::PointXYZ minPt, maxPt;

    // 获取包围盒
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
    pcl::fromPCLPointCloud2(this->mesh_ptr->cloud, *cloud);

    pcl::getMinMax3D(*cloud, minPt, maxPt);
    // 计算点云中心位置和对角线长度
    Eigen::Vector3f center((maxPt.x + minPt.x) / 2, (maxPt.y + minPt.y) / 2, (maxPt.z + minPt.z) / 2);
    Eigen::Vector3f diff = maxPt.getVector3fMap() - minPt.getVector3fMap();
    float distance = diff.norm();

    // 设置相机位置和视角
    // (场景中心点的坐标, 摄像机到场景中心点的距离, 摄像机的方向向量)
    viewer->setCameraPosition(center(0), center(1), center(2) + distance, center(0), center(1), center(2), -0.7, -0.9, 0.2);
    viewer->spin();
    return;

}

void CloudPointItemClass::ViewerShow(pcl::visualization::PCLVisualizer::Ptr viewer)
{
    pcl::visualization::PointCloudColorHandlerRandom<pcl::PointXYZRGBA> RandomColor(this->pointCloud); // 随机给点云生成颜色
    viewer->addPointCloud<pcl::PointXYZRGBA>(this->pointCloud, RandomColor, this->name.toUtf8().constData());  // 添加点云
    viewer->getRenderWindow()->Render();
}

void CloudPointItemClass::ZoomOnExtend(pcl::visualization::PCLVisualizer::Ptr viewer)
{
    pcl::PointXYZRGBA minPt, maxPt;
    pcl::getMinMax3D(*(this->pointCloud), minPt, maxPt);
    // 计算点云中心位置和对角线长度
    Eigen::Vector3f center((maxPt.x + minPt.x) / 2, (maxPt.y + minPt.y) / 2, (maxPt.z + minPt.z) / 2);
    Eigen::Vector3f diff = maxPt.getVector3fMap() - minPt.getVector3fMap();
    float distance = diff.norm();

    // 设置相机位置和视角
    // (场景中心点的坐标, 摄像机到场景中心点的距离, 摄像机的方向向量)
    viewer->setCameraPosition(center(0), center(1), center(2) + distance, center(0), center(1), center(2), -0.7, -0.9, 0.2);
    viewer->spin();
    return;
}


void FileListManagerAbstractItem::ViewerShow(pcl::visualization::PCLVisualizer::Ptr viewer)
{
}

void FileListManagerAbstractItem::ZoomOnExtend(pcl::visualization::PCLVisualizer::Ptr viewer)
{
}

FileListManagerAbstractItemType FileListManagerAbstractItem::getType()
{
    return this->itemtype;
}
